merge the formfield patch from ooo-build
[ooovba.git] / svtools / source / contnr / treelist.cxx
blob4889d719ba205c3c4da3b0402c24f03fc5fe555f
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: treelist.cxx,v $
10 * $Revision: 1.13 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_svtools.hxx"
34 #define _TREELIST_CXX
36 #ifndef GCC
37 #endif
39 #include <svtools/treelist.hxx>
41 #ifndef PRODUCT
42 // Prueft Integritaet der Liste nach jeder Operation
43 //#define CHECK_INTEGRITY
44 #endif
47 DBG_NAME(SvListEntry);
49 SvListEntry::SvListEntry()
51 DBG_CTOR(SvListEntry,0);
52 pChilds = 0;
53 pParent = 0;
54 nListPos = 0;
55 nAbsPos = 0;
58 SvListEntry::SvListEntry( const SvListEntry& rEntry )
60 DBG_CTOR(SvListEntry,0);
61 pChilds = 0;
62 pParent = 0;
63 nListPos &= 0x80000000;
64 nListPos |= ( rEntry.nListPos & 0x7fffffff);
65 nAbsPos = rEntry.nAbsPos;
68 SvListEntry::~SvListEntry()
70 DBG_DTOR(SvListEntry,0);
71 if ( pChilds )
73 pChilds->DestroyAll();
74 delete pChilds;
76 #ifdef DBG_UTIL
77 pChilds = 0;
78 pParent = 0;
79 #endif
82 void SvListEntry::Clone( SvListEntry* pSource)
84 DBG_CHKTHIS(SvListEntry,0);
85 nListPos &= 0x80000000;
86 nListPos |= ( pSource->nListPos & 0x7fffffff);
87 nAbsPos = pSource->nAbsPos;
90 void SvListEntry::SetListPositions()
92 if( pChilds )
94 SvListEntry *pEntry = (SvListEntry*)pChilds->First();
95 ULONG nCur = 0;
96 while ( pEntry )
98 pEntry->nListPos &= 0x80000000;
99 pEntry->nListPos |= nCur;
100 nCur++;
101 pEntry = (SvListEntry*)pChilds->Next();
104 nListPos &= (~0x80000000);
108 DBG_NAME(SvViewData);
110 SvViewData::SvViewData()
112 DBG_CTOR(SvViewData,0);
113 nFlags = 0;
114 nVisPos = 0;
117 SvViewData::SvViewData( const SvViewData& rData )
119 DBG_CTOR(SvViewData,0);
120 nFlags = rData.nFlags;
121 nFlags &= ~( SVLISTENTRYFLAG_SELECTED | SVLISTENTRYFLAG_FOCUSED );
122 nVisPos = rData.nVisPos;
125 SvViewData::~SvViewData()
127 DBG_DTOR(SvViewData,0);
128 #ifdef DBG_UTIL
129 nVisPos = 0x12345678;
130 nFlags = 0x1234;
131 #endif
134 void SvTreeEntryList::DestroyAll()
136 SvListEntry* pPtr = (SvListEntry*)First();
137 while( pPtr )
139 delete pPtr;
140 pPtr = (SvListEntry*)Next();
147 #if defined (WIN) && defined (MSC)
148 // siehe BugId 42896: Die Funktionen Prev, PrevVisible, Next, NextVisible
149 // (andere?) funktionieren nicht mit Optimierung.
150 #pragma optimize ("", off)
151 #endif
155 /*************************************************************************
157 |* SvTreeList::
159 |* Beschreibung
160 |* Ersterstellung 17.08.94
161 |* Letzte Aenderung 17.08.94
163 *************************************************************************/
165 SvTreeList::SvTreeList()
167 nEntryCount = 0;
168 bAbsPositionsValid = FALSE;
169 nRefCount = 1;
170 pRootItem = new SvListEntry;
171 eSortMode = SortNone;
175 /*************************************************************************
177 |* SvTreeList::~SvTreeList
179 |* Beschreibung
180 |* Ersterstellung 17.08.94
181 |* Letzte Aenderung 17.08.94
183 *************************************************************************/
185 SvTreeList::~SvTreeList()
187 Clear();
188 delete pRootItem;
189 #ifdef DBG_UTIL
190 pRootItem = 0;
191 #endif
194 /*************************************************************************
196 |* SvTreeList::Broadcast
198 |* Beschreibung
199 |* Ersterstellung 17.08.94
200 |* Letzte Aenderung 17.08.94
202 *************************************************************************/
204 void SvTreeList::Broadcast( USHORT nActionId, SvListEntry* pEntry1,
205 SvListEntry* pEntry2, ULONG nPos )
207 ULONG nViewCount = aViewList.Count();
208 for( ULONG nCurView = 0; nCurView < nViewCount; nCurView++ )
210 SvListView* pView = (SvListView*)aViewList.GetObject( nCurView );
211 if( pView )
212 pView->ModelNotification( nActionId, pEntry1, pEntry2, nPos );
216 void SvTreeList::InsertView( SvListView* pView)
218 ULONG nPos = aViewList.GetPos( pView );
219 if ( nPos == LIST_ENTRY_NOTFOUND )
221 aViewList.Insert( pView, LIST_APPEND );
222 nRefCount++;
226 void SvTreeList::RemoveView( SvListView* pView )
228 ULONG nPos = aViewList.GetPos( pView );
229 if ( nPos != LIST_ENTRY_NOTFOUND )
231 aViewList.Remove( pView );
232 nRefCount--;
237 // Ein Entry ist sichtbar, wenn alle Parents expandiert sind
238 BOOL SvTreeList::IsEntryVisible( const SvListView* pView, SvListEntry* pEntry ) const
240 DBG_ASSERT(pView&&pEntry,"IsVisible:Invalid Params");
241 BOOL bRetVal=FALSE;
244 if ( pEntry == pRootItem )
246 bRetVal=TRUE;
247 break;
249 pEntry = pEntry->pParent;
250 } while( pView->IsExpanded( pEntry ) );
251 return bRetVal;
254 USHORT SvTreeList::GetDepth( SvListEntry* pEntry ) const
256 DBG_ASSERT(pEntry&&pEntry!=pRootItem,"GetDepth:Bad Entry");
257 USHORT nDepth = 0;
258 while( pEntry->pParent != pRootItem )
260 nDepth++;
261 pEntry = pEntry->pParent;
263 return nDepth;
266 /*************************************************************************
268 |* SvTreeList::
270 |* Beschreibung
271 |* Ersterstellung 17.08.94
272 |* Letzte Aenderung 17.08.94
274 *************************************************************************/
276 void SvTreeList::Clear()
278 Broadcast( LISTACTION_CLEARING );
279 SvTreeEntryList* pRootList = pRootItem->pChilds;
280 if ( pRootList )
282 SvListEntry* pEntry = (SvListEntry*)(pRootList->First());
283 while( pEntry )
285 delete pEntry;
286 pEntry = (SvListEntry*)(pRootList->Next());
288 delete pRootItem->pChilds;
289 pRootItem->pChilds = 0;
291 nEntryCount = 0;
292 Broadcast( LISTACTION_CLEARED );
296 /*************************************************************************
298 |* SvTreeList::
300 |* Beschreibung
301 |* Ersterstellung 17.08.94
302 |* Letzte Aenderung 17.08.94
304 *************************************************************************/
306 BOOL SvTreeList::IsChild( SvListEntry* pParent, SvListEntry* pChild ) const
308 if ( !pParent )
309 pParent = pRootItem;
311 BOOL bIsChild = FALSE;
312 SvTreeEntryList* pList = pParent->pChilds;
313 if ( !pList )
314 return FALSE;
315 SvListEntry* pActualChild = (SvListEntry*)(pList->First());
316 while( !bIsChild && pActualChild )
318 if ( pActualChild == pChild )
319 bIsChild = TRUE;
320 else
322 if ( pActualChild->pChilds )
323 bIsChild = IsChild( pActualChild, pChild );
324 pActualChild = (SvListEntry*)(pList->Next());
327 return bIsChild;
330 ULONG SvTreeList::Move(SvListEntry* pSrcEntry,SvListEntry* pTargetParent,ULONG nListPos)
332 // pDest darf Null sein!
333 DBG_ASSERT(pSrcEntry,"Entry?");
334 if ( !pTargetParent )
335 pTargetParent = pRootItem;
336 DBG_ASSERT(pSrcEntry!=pTargetParent,"Move:Source=Target");
338 Broadcast( LISTACTION_MOVING, pSrcEntry, pTargetParent, nListPos );
340 if ( !pTargetParent->pChilds )
341 pTargetParent->pChilds = new SvTreeEntryList;
342 if ( pSrcEntry == pTargetParent )
343 return pSrcEntry->GetChildListPos();
345 bAbsPositionsValid = FALSE;
347 SvTreeEntryList* pDstList = pTargetParent->pChilds;
348 SvTreeEntryList* pSrcList = pSrcEntry->pParent->pChilds;
350 // Dummy-Ptr einfuegen, weil nListPos durch das
351 // folgende Remove ungueltig werden koennte
352 SvListEntry* pDummy = 0; pDstList->Insert( pDummy, nListPos );
354 // loeschen
355 pSrcList->Remove( pSrcEntry );
356 // Hat Parent noch Childs ?
357 if ( pSrcList->Count() == 0 )
359 // Keine Childs, deshalb Child-List loeschen
360 SvListEntry* pParent = pSrcEntry->pParent;
361 pParent->pChilds = 0;
362 delete pSrcList;
363 pSrcList = 0;
366 // Parent umsetzen (erst hier, weil wir zum Loeschen
367 // der ChildList den alten Parent noch benoetigen!)
368 pSrcEntry->pParent = pTargetParent;
370 pDstList->Replace( pSrcEntry, pDummy );
372 // Listenpositionen in Zielliste korrigieren
373 SetListPositions( pDstList );
374 if ( pSrcList && (ULONG)pSrcList != (ULONG)pDstList )
375 SetListPositions( pSrcList );
377 #ifdef CHECK_INTEGRITY
378 CheckIntegrity();
379 #endif
381 ULONG nRetVal = pDstList->GetPos( pSrcEntry );
382 DBG_ASSERT(nRetVal==pSrcEntry->GetChildListPos(),"ListPos not valid");
383 Broadcast( LISTACTION_MOVED,pSrcEntry,pTargetParent,nRetVal);
384 return nRetVal;
387 ULONG SvTreeList::Copy(SvListEntry* pSrcEntry,SvListEntry* pTargetParent,ULONG nListPos)
389 // pDest darf Null sein!
390 DBG_ASSERT(pSrcEntry,"Entry?");
391 if ( !pTargetParent )
392 pTargetParent = pRootItem;
393 if ( !pTargetParent->pChilds )
394 pTargetParent->pChilds = new SvTreeEntryList;
396 bAbsPositionsValid = FALSE;
398 ULONG nCloneCount = 0;
399 SvListEntry* pClonedEntry = Clone( pSrcEntry, nCloneCount );
400 nEntryCount += nCloneCount;
402 SvTreeEntryList* pDstList = pTargetParent->pChilds;
403 pClonedEntry->pParent = pTargetParent; // Parent umsetzen
404 pDstList->Insert( pClonedEntry, nListPos ); // Einfuegen
405 SetListPositions( pDstList ); // Listenpositionen in Zielliste korrigieren
407 #ifdef CHECK_INTEGRITY
408 CheckIntegrity();
409 #endif
410 Broadcast( LISTACTION_INSERTED_TREE, pClonedEntry );
411 ULONG nRetVal = pDstList->GetPos( pClonedEntry );
412 return nRetVal;
417 /*************************************************************************
419 |* SvTreeList::
421 |* Beschreibung
422 |* Ersterstellung 17.08.94
423 |* Letzte Aenderung 17.08.94
425 *************************************************************************/
427 void SvTreeList::Move( SvListEntry* pSrcEntry, SvListEntry* pDstEntry )
429 SvListEntry* pParent;
430 ULONG nPos;
432 if ( !pDstEntry )
434 pParent = pRootItem;
435 nPos = 0UL;
437 else
439 pParent = pDstEntry->pParent;
440 nPos = pDstEntry->GetChildListPos();
441 nPos++; // UNTER (Bildschirm) pDstEntry einfuegen
443 Move( pSrcEntry, pParent, nPos );
446 /*************************************************************************
448 |* SvTreeList::
450 |* Beschreibung
451 |* Ersterstellung 17.08.94
452 |* Letzte Aenderung 17.08.94
454 *************************************************************************/
456 void SvTreeList::Copy( SvListEntry* pSrcEntry, SvListEntry* pDstEntry )
458 SvListEntry* pParent;
459 ULONG nPos;
461 if ( !pDstEntry )
463 pParent = pRootItem;
464 nPos = 0UL;
466 else
468 pParent = pDstEntry->pParent;
469 nPos = pDstEntry->GetChildListPos()+1;
471 Copy( pSrcEntry, pParent, nPos );
474 /*************************************************************************
476 |* SvTreeList::
478 |* Beschreibung
479 |* Ersterstellung 17.08.94
480 |* Letzte Aenderung 17.08.94
482 *************************************************************************/
483 void SvTreeList::InsertTree( SvListEntry* pSrcEntry, SvListEntry* pDstEntry)
485 SvListEntry* pParent;
486 ULONG nPos;
488 if ( !pDstEntry )
490 pParent = pRootItem;
491 nPos = 0UL;
493 else
495 pParent = pDstEntry->pParent;
496 nPos = pDstEntry->GetChildListPos()+1;
498 InsertTree( pSrcEntry, pParent, nPos );
502 void SvTreeList::InsertTree(SvListEntry* pSrcEntry,
503 SvListEntry* pTargetParent,ULONG nListPos)
505 DBG_ASSERT(pSrcEntry,"InsertTree:Entry?");
506 if ( !pSrcEntry )
507 return;
509 if ( !pTargetParent )
510 pTargetParent = pRootItem;
511 if ( !pTargetParent->pChilds )
512 pTargetParent->pChilds = new SvTreeEntryList;
514 // Sortierung beruecksichtigen
515 GetInsertionPos( pSrcEntry, pTargetParent, nListPos );
517 bAbsPositionsValid = FALSE;
519 pSrcEntry->pParent = pTargetParent; // Parent umsetzen
520 SvTreeEntryList* pDstList = pTargetParent->pChilds;
521 pDstList->Insert( pSrcEntry, nListPos ); // einfuegen
522 SetListPositions(pDstList); // Listenpositionen in Zielliste korrigieren
523 nEntryCount += GetChildCount( pSrcEntry );
524 nEntryCount++; // der Parent ist ja auch neu
526 #ifdef CHECK_INTEGRITY
527 CheckIntegrity();
528 #endif
529 Broadcast(LISTACTION_INSERTED_TREE, pSrcEntry );
532 SvListEntry* SvTreeList::CloneEntry( SvListEntry* pSource ) const
534 if( aCloneLink.IsSet() )
535 return (SvListEntry*)aCloneLink.Call( pSource );
536 SvListEntry* pEntry = CreateEntry();
537 pSource->Clone( pEntry );
538 return pSource;
541 SvListEntry* SvTreeList::CreateEntry() const
543 return new SvListEntry;
546 /*************************************************************************
548 |* SvTreeList::
550 |* Beschreibung
551 |* Ersterstellung 17.08.94
552 |* Letzte Aenderung 17.08.94
554 *************************************************************************/
556 SvListEntry* SvTreeList::Clone( SvListEntry* pEntry, ULONG& nCloneCount ) const
558 SvListEntry* pClonedEntry = CloneEntry( pEntry );
559 nCloneCount = 1;
560 SvTreeEntryList* pChilds = pEntry->pChilds;
561 if ( pChilds )
562 pClonedEntry->pChilds=CloneChilds(pChilds,pClonedEntry,nCloneCount);
563 return pClonedEntry;
566 /*************************************************************************
568 |* SvTreeList::
570 |* Beschreibung
571 |* Ersterstellung 17.08.94
572 |* Letzte Aenderung 17.08.94
574 *************************************************************************/
576 SvTreeEntryList* SvTreeList::CloneChilds( SvTreeEntryList* pChilds,
577 SvListEntry* pNewParent,
578 ULONG& nCloneCount ) const
580 DBG_ASSERT(pChilds->Count(),"Childs?");
581 SvTreeEntryList* pClonedChilds = new SvTreeEntryList;
582 SvListEntry* pChild = (SvListEntry*)pChilds->First();
583 while ( pChild )
585 SvListEntry* pNewChild = CloneEntry( pChild );
586 nCloneCount++;
587 pNewChild->pParent = pNewParent;
588 SvTreeEntryList* pSubChilds = pChild->pChilds;
589 if ( pSubChilds )
591 pSubChilds = CloneChilds( pSubChilds, pNewChild, nCloneCount );
592 pNewChild->pChilds = pSubChilds;
595 pClonedChilds->Insert( pNewChild, LIST_APPEND );
596 pChild = (SvListEntry*)pChilds->Next();
598 return pClonedChilds;
602 /*************************************************************************
604 |* SvTreeList::GetChildCount
606 |* Beschreibung
607 |* Ersterstellung 17.08.94
608 |* Letzte Aenderung 17.08.94
610 *************************************************************************/
612 ULONG SvTreeList::GetChildCount( SvListEntry* pParent ) const
614 if ( !pParent )
615 return GetEntryCount();
617 if ( !pParent || !pParent->pChilds)
618 return 0;
619 ULONG nCount = 0;
620 USHORT nRefDepth = GetDepth( pParent );
621 USHORT nActDepth = nRefDepth;
624 pParent = Next( pParent, &nActDepth );
625 nCount++;
626 } while( pParent && nRefDepth < nActDepth );
627 nCount--;
628 return nCount;
631 /*************************************************************************
633 |* SvTreeList::
635 |* Beschreibung
636 |* Ersterstellung 17.08.94
637 |* Letzte Aenderung 17.08.94
639 *************************************************************************/
641 ULONG SvTreeList::GetVisibleChildCount(const SvListView* pView, SvListEntry* pParent) const
643 DBG_ASSERT(pView,"GetVisChildCount:No View");
644 if ( !pParent )
645 pParent = pRootItem;
646 if ( !pParent || !pView->IsExpanded(pParent) || !pParent->pChilds )
647 return 0;
648 ULONG nCount = 0;
649 USHORT nRefDepth = GetDepth( pParent );
650 USHORT nActDepth = nRefDepth;
653 pParent = NextVisible( pView, pParent, &nActDepth );
654 nCount++;
655 } while( pParent && nRefDepth < nActDepth );
656 nCount--;
657 return nCount;
660 ULONG SvTreeList::GetChildSelectionCount(const SvListView* pView,SvListEntry* pParent) const
662 DBG_ASSERT(pView,"GetChildSelCount:No View");
663 if ( !pParent )
664 pParent = pRootItem;
665 if ( !pParent || !pParent->pChilds)
666 return 0;
667 ULONG nCount = 0;
668 USHORT nRefDepth = GetDepth( pParent );
669 USHORT nActDepth = nRefDepth;
672 pParent = Next( pParent, &nActDepth );
673 if( pParent && pView->IsSelected( pParent ) && nRefDepth < nActDepth)
674 nCount++;
675 } while( pParent && nRefDepth < nActDepth );
676 // nCount--;
677 return nCount;
681 /*************************************************************************
683 |* SvTreeList::
685 |* Beschreibung
686 |* Ersterstellung 17.08.94
687 |* Letzte Aenderung 17.08.94
689 *************************************************************************/
691 SvListEntry* SvTreeList::First() const
693 if ( nEntryCount )
694 return (SvListEntry*)(pRootItem->pChilds->GetObject(0));
695 else
696 return 0;
699 /*************************************************************************
701 |* SvTreeList::Next
703 |* Beschreibung
704 |* Ersterstellung 17.08.94
705 |* Letzte Aenderung 17.08.94
707 *************************************************************************/
708 SvListEntry* SvTreeList::Next( SvListEntry* pActEntry, USHORT* pDepth ) const
710 DBG_ASSERT( pActEntry && pActEntry->pParent, "SvTreeList::Next: invalid entry/parent!" );
711 if ( !pActEntry || !pActEntry->pParent )
712 return NULL;
714 USHORT nDepth = 0;
715 int bWithDepth = FALSE;
716 if ( pDepth )
718 nDepth = *pDepth;
719 bWithDepth = TRUE;
722 SvTreeEntryList* pActualList = pActEntry->pParent->pChilds;
723 ULONG nActualPos = pActEntry->GetChildListPos();
725 if ( pActEntry->pChilds /* && pActEntry->pChilds->Count() */ )
727 nDepth++;
728 pActEntry = (SvListEntry*)(pActEntry->pChilds->GetObject(0));
729 if ( bWithDepth )
730 *pDepth = nDepth;
731 return pActEntry;
734 if ( pActualList->Count() > ( nActualPos + 1 ) )
736 pActEntry = (SvListEntry*)(pActualList->GetObject( nActualPos + 1 ));
737 if ( bWithDepth )
738 *pDepth = nDepth;
739 return pActEntry;
742 SvListEntry* pParent = pActEntry->pParent;
743 nDepth--;
744 while( pParent != pRootItem && pParent != 0 )
746 DBG_ASSERT(pParent!=0,"TreeData corrupt!");
747 pActualList = pParent->pParent->pChilds;
748 DBG_ASSERT(pActualList,"TreeData corrupt!");
749 nActualPos = pParent->GetChildListPos();
750 if ( pActualList->Count() > ( nActualPos + 1 ) )
752 pActEntry = (SvListEntry*)(pActualList->GetObject( nActualPos + 1 ));
753 if ( bWithDepth )
754 *pDepth = nDepth;
755 return pActEntry;
757 pParent = pParent->pParent;
758 nDepth--;
760 return 0;
763 /*************************************************************************
765 |* SvTreeList::Prev
767 |* Beschreibung
768 |* Ersterstellung 17.08.94
769 |* Letzte Aenderung 17.08.94
771 *************************************************************************/
772 SvListEntry* SvTreeList::Prev( SvListEntry* pActEntry, USHORT* pDepth ) const
774 DBG_ASSERT(pActEntry!=0,"Entry?");
776 USHORT nDepth = 0;
777 int bWithDepth = FALSE;
778 if ( pDepth )
780 nDepth = *pDepth;
781 bWithDepth = TRUE;
784 SvTreeEntryList* pActualList = pActEntry->pParent->pChilds;
785 ULONG nActualPos = pActEntry->GetChildListPos();
787 if ( nActualPos > 0 )
789 pActEntry = (SvListEntry*)(pActualList->GetObject( nActualPos - 1 ));
790 while( pActEntry->pChilds /* && pActEntry->pChilds->Count() */ )
792 pActualList = pActEntry->pChilds;
793 nDepth++;
794 pActEntry = (SvListEntry*)(pActualList->Last());
796 if ( bWithDepth )
797 *pDepth = nDepth;
798 return pActEntry;
800 if ( pActEntry->pParent == pRootItem )
801 return 0;
803 pActEntry = pActEntry->pParent;
805 if ( pActEntry )
807 nDepth--;
808 if ( bWithDepth )
809 *pDepth = nDepth;
810 return pActEntry;
812 return 0;
815 /*************************************************************************
817 |* SvTreeList::
819 |* Beschreibung
820 |* Ersterstellung 17.08.94
821 |* Letzte Aenderung 17.08.94
823 *************************************************************************/
825 SvListEntry* SvTreeList::Last( USHORT* /* nDepth */ ) const
827 SvTreeEntryList* pActList = pRootItem->pChilds;
828 // if ( pActList->Count() == 0 )
829 // return 0;
830 SvListEntry* pEntry = 0;
831 while( pActList )
833 pEntry = (SvListEntry*)(pActList->Last());
834 pActList = pEntry->pChilds;
835 // if ( pActList->Count() == 0 )
836 // pActList = 0;
838 return pEntry;
841 /*************************************************************************
843 |* SvTreeList::
845 |* Beschreibung
846 |* Ersterstellung 17.08.94
847 |* Letzte Aenderung 17.08.94
849 *************************************************************************/
851 ULONG SvTreeList::GetVisiblePos( const SvListView* pView, SvListEntry* pEntry ) const
853 DBG_ASSERT(pView&&pEntry,"View/Entry?");
855 if ( !pView->bVisPositionsValid )
857 // damit GetVisibleCount die Positionen aktualisiert
858 ((SvListView*)pView)->nVisibleCount = 0;
859 GetVisibleCount( pView );
861 SvViewData* pViewData = pView->GetViewData( pEntry );
862 return pViewData->nVisPos;
865 /*************************************************************************
867 |* SvTreeList::
869 |* Beschreibung
870 |* Ersterstellung 17.08.94
871 |* Letzte Aenderung 17.08.94
873 *************************************************************************/
875 ULONG SvTreeList::GetVisibleCount( const SvListView* pView ) const
877 DBG_ASSERT(pView,"GetVisCount:No View");
878 if( !pView->HasViewData() )
879 return 0;
880 if ( pView->nVisibleCount )
881 return pView->nVisibleCount;
883 ULONG nPos = 0;
884 SvListEntry* pEntry = First(); // erster Eintrag immer sichtbar
885 while ( pEntry )
887 SvViewData* pViewData = pView->GetViewData( pEntry );
888 pViewData->nVisPos = nPos;
889 nPos++;
890 pEntry = NextVisible( pView, pEntry );
892 #ifdef DBG_UTIL
893 if( nPos > 10000000 )
895 DBG_ERROR("nVisibleCount bad");
897 #endif
898 ((SvListView*)pView)->nVisibleCount = nPos;
899 ((SvListView*)pView)->bVisPositionsValid = TRUE;
900 return nPos;
904 /*************************************************************************
906 |* SvTreeList::
908 |* Beschreibung
909 |* Ersterstellung 17.08.94
910 |* Letzte Aenderung 17.08.94
912 *************************************************************************/
914 // Funktion geht aus Geschwindigkeitsgruenden davon aus,
915 // das der uebergebene Eintrag bereits sichtbar ist
917 SvListEntry* SvTreeList::NextVisible(const SvListView* pView,SvListEntry* pActEntry,USHORT* pActDepth) const
919 DBG_ASSERT(pView,"NextVisible:No View");
920 if ( !pActEntry )
921 return 0;
923 USHORT nDepth = 0;
924 int bWithDepth = FALSE;
925 if ( pActDepth )
927 nDepth = *pActDepth;
928 bWithDepth = TRUE;
931 SvTreeEntryList* pActualList = pActEntry->pParent->pChilds;
932 ULONG nActualPos = pActEntry->GetChildListPos();
934 if ( pView->IsExpanded(pActEntry) )
936 DBG_ASSERT(pActEntry->pChilds,"Childs?");
937 nDepth++;
938 pActEntry = (SvListEntry*)(pActEntry->pChilds->GetObject(0));
939 if ( bWithDepth )
940 *pActDepth = nDepth;
941 return pActEntry;
944 nActualPos++;
945 if ( pActualList->Count() > nActualPos )
947 pActEntry = (SvListEntry*)(pActualList->GetObject( nActualPos ));
948 if ( bWithDepth )
949 *pActDepth = nDepth;
950 return pActEntry;
953 SvListEntry* pParent = pActEntry->pParent;
954 nDepth--;
955 while( pParent != pRootItem )
957 pActualList = pParent->pParent->pChilds;
958 nActualPos = pParent->GetChildListPos();
959 nActualPos++;
960 if ( pActualList->Count() > nActualPos )
962 pActEntry = (SvListEntry*)(pActualList->GetObject( nActualPos ));
963 if ( bWithDepth )
964 *pActDepth = nDepth;
965 return pActEntry;
967 pParent = pParent->pParent;
968 nDepth--;
970 return 0;
974 /*************************************************************************
976 |* SvTreeList::
978 |* Beschreibung
979 |* Ersterstellung 17.08.94
980 |* Letzte Aenderung 17.08.94
982 *************************************************************************/
984 // Funktion geht aus Geschwindigkeitsgruenden davon aus,
985 // das der uebergebene Eintrag bereits sichtbar ist
987 SvListEntry* SvTreeList::PrevVisible(const SvListView* pView, SvListEntry* pActEntry, USHORT* pActDepth) const
989 DBG_ASSERT(pView&&pActEntry,"PrevVis:View/Entry?");
991 USHORT nDepth = 0;
992 int bWithDepth = FALSE;
993 if ( pActDepth )
995 nDepth = *pActDepth;
996 bWithDepth = TRUE;
999 SvTreeEntryList* pActualList = pActEntry->pParent->pChilds;
1000 ULONG nActualPos = pActEntry->GetChildListPos();
1002 if ( nActualPos > 0 )
1004 pActEntry = (SvListEntry*)(pActualList->GetObject( nActualPos - 1 ));
1005 while( pView->IsExpanded(pActEntry) )
1007 pActualList = pActEntry->pChilds;
1008 nDepth++;
1009 pActEntry = (SvListEntry*)(pActualList->Last());
1011 if ( bWithDepth )
1012 *pActDepth = nDepth;
1013 return pActEntry;
1016 if ( pActEntry->pParent == pRootItem )
1017 return 0;
1019 pActEntry = pActEntry->pParent;
1020 if ( pActEntry )
1022 nDepth--;
1023 if ( bWithDepth )
1024 *pActDepth = nDepth;
1025 return pActEntry;
1027 return 0;
1030 /*************************************************************************
1032 |* SvTreeList::
1034 |* Beschreibung
1035 |* Ersterstellung 17.08.94
1036 |* Letzte Aenderung 17.08.94
1038 *************************************************************************/
1040 SvListEntry* SvTreeList::LastVisible( const SvListView* pView, USHORT* pDepth) const
1042 DBG_ASSERT(pView,"LastVis:No View");
1043 SvListEntry* pEntry = Last();
1044 while( pEntry && !IsEntryVisible( pView, pEntry ) )
1045 pEntry = PrevVisible( pView, pEntry );
1046 if ( pEntry && pDepth )
1047 *pDepth = GetDepth( pEntry );
1048 return pEntry;
1051 /*************************************************************************
1053 |* SvTreeList::
1055 |* Beschreibung
1056 |* Ersterstellung 17.08.94
1057 |* Letzte Aenderung 17.08.94
1059 *************************************************************************/
1061 SvListEntry* SvTreeList::NextVisible(const SvListView* pView,SvListEntry* pEntry,USHORT& nDelta) const
1063 DBG_ASSERT(pView&&pEntry&&IsEntryVisible(pView,pEntry),"NextVis:Wrong Prms/!Vis");
1065 ULONG nVisPos = GetVisiblePos( pView, pEntry );
1066 // nDelta Eintraege vorhanden ?
1067 // Beispiel: 0,1,2,3,4,5,6,7,8,9 nVisPos=5 nDelta=7
1068 // nNewDelta = 10-nVisPos-1 == 4
1069 if ( nVisPos+nDelta >= pView->nVisibleCount )
1071 nDelta = (USHORT)(pView->nVisibleCount-nVisPos);
1072 nDelta--;
1074 USHORT nDeltaTmp = nDelta;
1075 while( nDeltaTmp )
1077 pEntry = NextVisible( pView, pEntry );
1078 nDeltaTmp--;
1079 DBG_ASSERT(pEntry,"Entry?");
1081 return pEntry;
1084 /*************************************************************************
1086 |* SvTreeList::
1088 |* Beschreibung
1089 |* Ersterstellung 17.08.94
1090 |* Letzte Aenderung 17.08.94
1092 *************************************************************************/
1094 SvListEntry* SvTreeList::PrevVisible( const SvListView* pView, SvListEntry* pEntry, USHORT& nDelta ) const
1096 DBG_ASSERT(pView&&pEntry&&IsEntryVisible(pView,pEntry),"PrevVis:Parms/!Vis");
1098 ULONG nVisPos = GetVisiblePos( pView, pEntry );
1099 // nDelta Eintraege vorhanden ?
1100 // Beispiel: 0,1,2,3,4,5,6,7,8,9 nVisPos=8 nDelta=20
1101 // nNewDelta = nNewVisPos
1102 if ( nDelta > nVisPos )
1103 nDelta = (USHORT)nVisPos;
1104 USHORT nDeltaTmp = nDelta;
1105 while( nDeltaTmp )
1107 pEntry = PrevVisible( pView, pEntry );
1108 nDeltaTmp--;
1109 DBG_ASSERT(pEntry,"Entry?");
1111 return pEntry;
1114 /*************************************************************************
1116 |* SvTreeList::
1118 |* Beschreibung
1119 |* Ersterstellung 17.08.94
1120 |* Letzte Aenderung 17.08.94
1122 *************************************************************************/
1124 SvListEntry* SvTreeList::FirstSelected( const SvListView* pView) const
1126 DBG_ASSERT(pView,"FirstSel:No View");
1127 if( !pView )
1128 return 0;
1129 SvListEntry* pActSelEntry = First();
1130 while( pActSelEntry && !pView->IsSelected(pActSelEntry) )
1131 pActSelEntry = NextVisible( pView, pActSelEntry );
1132 return pActSelEntry;
1136 SvListEntry* SvTreeList::FirstChild( SvListEntry* pParent ) const
1138 if ( !pParent )
1139 pParent = pRootItem;
1140 SvListEntry* pResult;
1141 if ( pParent->pChilds )
1142 pResult = (SvListEntry*)(pParent->pChilds->GetObject( 0 ));
1143 else
1144 pResult = 0;
1145 return pResult;
1148 SvListEntry* SvTreeList::NextSibling( SvListEntry* pEntry ) const
1150 DBG_ASSERT(pEntry,"Entry?");
1151 if( !pEntry )
1152 return 0;
1153 SvTreeEntryList* pList = pEntry->pParent->pChilds;
1154 // ULONG nPos = pList->GetPos( pEntry );
1155 ULONG nPos = pEntry->GetChildListPos();
1156 nPos++;
1157 pEntry = (SvListEntry*)(pList->GetObject( nPos ));
1158 return pEntry;
1161 SvListEntry* SvTreeList::PrevSibling( SvListEntry* pEntry ) const
1163 DBG_ASSERT(pEntry,"Entry?");
1164 if( !pEntry )
1165 return 0;
1167 SvTreeEntryList* pList = pEntry->pParent->pChilds;
1168 // ULONG nPos = pList->GetPos( pEntry );
1169 ULONG nPos = pEntry->GetChildListPos();
1170 if ( nPos == 0 )
1171 return 0;
1172 nPos--;
1173 pEntry = (SvListEntry*)(pList->GetObject( nPos ));
1174 return pEntry;
1178 SvListEntry* SvTreeList::LastSibling( SvListEntry* pEntry ) const
1180 DBG_ASSERT(pEntry,"LastSibling:Entry?");
1181 if( !pEntry )
1182 return 0;
1183 SvListEntry* pSib = 0;
1184 SvTreeEntryList* pSibs = pEntry->pParent->pChilds;
1185 if ( pSibs )
1186 pSib = (SvListEntry*)(pSibs->Last());
1187 return pSib;
1192 /*************************************************************************
1194 |* SvTreeList::
1196 |* Beschreibung
1197 |* Ersterstellung 17.08.94
1198 |* Letzte Aenderung 17.08.94
1200 *************************************************************************/
1202 SvListEntry* SvTreeList::NextSelected( const SvListView* pView, SvListEntry* pEntry ) const
1204 DBG_ASSERT(pView&&pEntry,"NextSel:View/Entry?");
1205 pEntry = Next( pEntry );
1206 while( pEntry && !pView->IsSelected(pEntry) )
1207 pEntry = Next( pEntry );
1208 return pEntry;
1211 /*************************************************************************
1213 |* SvTreeList::
1215 |* Beschreibung
1216 |* Ersterstellung 17.08.94
1217 |* Letzte Aenderung 17.08.94
1219 *************************************************************************/
1221 SvListEntry* SvTreeList::PrevSelected( const SvListView* pView, SvListEntry* pEntry) const
1223 DBG_ASSERT(pView&&pEntry,"PrevSel:View/Entry?");
1224 pEntry = Prev( pEntry );
1225 while( pEntry && !pView->IsSelected(pEntry) )
1226 pEntry = Prev( pEntry );
1228 return pEntry;
1231 /*************************************************************************
1233 |* SvTreeList::
1235 |* Beschreibung
1236 |* Ersterstellung 17.08.94
1237 |* Letzte Aenderung 17.08.94
1239 *************************************************************************/
1241 SvListEntry* SvTreeList::LastSelected( const SvListView* pView ) const
1243 DBG_ASSERT(pView,"LastSel:No View");
1244 SvListEntry* pEntry = Last();
1245 while( pEntry && !pView->IsSelected(pEntry) )
1246 pEntry = Prev( pEntry );
1247 return pEntry;
1250 /*************************************************************************
1252 |* SvTreeList::Insert
1254 |* Beschreibung
1255 |* Ersterstellung 17.08.94
1256 |* Letzte Aenderung 17.08.94
1258 *************************************************************************/
1259 ULONG SvTreeList::Insert( SvListEntry* pEntry,SvListEntry* pParent,ULONG nPos )
1261 DBG_ASSERT( pEntry,"Entry?");
1263 if ( !pParent )
1264 pParent = pRootItem;
1267 SvTreeEntryList* pList = pParent->pChilds;
1268 if ( !pList )
1270 // Parent bekommt zum erstenmal ein Kind
1271 pList = new SvTreeEntryList;
1272 pParent->pChilds = pList;
1275 // Sortierung beruecksichtigen
1276 GetInsertionPos( pEntry, pParent, nPos );
1278 bAbsPositionsValid = FALSE;
1279 pEntry->pParent = pParent;
1281 pList->Insert( pEntry, nPos );
1282 nEntryCount++;
1283 if( nPos != LIST_APPEND && (nPos != (pList->Count()-1)) )
1284 SetListPositions( pList );
1285 else
1286 pEntry->nListPos = pList->Count()-1;
1288 #ifdef CHECK_INTEGRITY
1289 CheckIntegrity();
1290 #endif
1291 Broadcast( LISTACTION_INSERTED, pEntry );
1292 return nPos; // pEntry->nListPos;
1295 /*************************************************************************
1297 |* SvTreeList::
1299 |* Beschreibung
1300 |* Ersterstellung 17.08.94
1301 |* Letzte Aenderung 17.08.94
1303 *************************************************************************/
1305 ULONG SvTreeList::GetAbsPos( SvListEntry* pEntry) const
1307 if ( !bAbsPositionsValid )
1308 ((SvTreeList*)this)->SetAbsolutePositions();
1309 return pEntry->nAbsPos;
1312 /*************************************************************************
1314 |* SvTreeList::
1316 |* Beschreibung
1317 |* Ersterstellung 17.08.94
1318 |* Letzte Aenderung 17.08.94
1320 *************************************************************************/
1322 void SvTreeList::SetAbsolutePositions()
1324 ULONG nPos = 0;
1325 SvListEntry* pEntry = First();
1326 while ( pEntry )
1328 pEntry->nAbsPos = nPos;
1329 nPos++;
1330 pEntry = Next( pEntry );
1332 bAbsPositionsValid = TRUE;
1333 #ifdef CHECK_INTEGRITY
1334 CheckIntegrity();
1335 #endif
1339 /*************************************************************************
1341 |* SvTreeList::Expand
1343 |* Beschreibung
1344 |* Ersterstellung 17.08.94
1345 |* Letzte Aenderung 17.08.94
1347 *************************************************************************/
1349 void SvTreeList::Expand( SvListView* pView, SvListEntry* pEntry )
1351 DBG_ASSERT(pEntry&&pView,"Expand:View/Entry?");
1352 if ( pView->IsExpanded(pEntry) )
1353 return;
1355 DBG_ASSERT(pEntry->pChilds,"Expand:No Childs!");
1357 SvViewData* pViewData = pView->GetViewData(pEntry);
1358 pViewData->nFlags |= SVLISTENTRYFLAG_EXPANDED;
1359 SvListEntry* pParent = pEntry->pParent;
1360 // wenn Parent sichtbar dann Statusdaten invalidieren
1361 if ( pView->IsExpanded( pParent ) )
1363 pView->bVisPositionsValid = FALSE;
1364 pView->nVisibleCount = 0;
1366 #ifdef CHECK_INTEGRITY
1367 CheckIntegrity();
1368 #endif
1371 /*************************************************************************
1373 |* SvTreeList::Collapse
1375 |* Beschreibung
1376 |* Ersterstellung 17.08.94
1377 |* Letzte Aenderung 17.08.94
1379 *************************************************************************/
1381 void SvTreeList::Collapse( SvListView* pView, SvListEntry* pEntry )
1383 DBG_ASSERT(pView&&pEntry,"Collapse:View/Entry?");
1384 if ( !pView->IsExpanded(pEntry) )
1385 return;
1387 DBG_ASSERT(pEntry->pChilds,"Collapse:No Childs!");
1389 SvViewData* pViewData = pView->GetViewData( pEntry );
1390 pViewData->nFlags &=(~SVLISTENTRYFLAG_EXPANDED);
1392 SvListEntry* pParent = pEntry->pParent;
1393 if ( pView->IsExpanded(pParent) )
1395 pView->nVisibleCount = 0;
1396 pView->bVisPositionsValid = FALSE;
1398 #ifdef CHECK_INTEGRITY
1399 CheckIntegrity();
1400 #endif
1404 /*************************************************************************
1406 |* SvTreeList::
1408 |* Beschreibung
1409 |* Ersterstellung 17.08.94
1410 |* Letzte Aenderung 17.08.94
1412 *************************************************************************/
1414 BOOL SvTreeList::Select( SvListView* pView, SvListEntry* pEntry, BOOL bSelect )
1416 DBG_ASSERT(pView&&pEntry,"Select:View/Entry?");
1417 SvViewData* pViewData = pView->GetViewData( pEntry );
1418 if ( bSelect )
1420 if ( pViewData->IsSelected() || !pViewData->IsSelectable() )
1421 return FALSE;
1422 else
1424 pViewData->nFlags |= SVLISTENTRYFLAG_SELECTED;
1425 pView->nSelectionCount++;
1428 else
1430 if ( !pViewData->IsSelected() )
1431 return FALSE;
1432 else
1434 pViewData->nFlags &= ~( SVLISTENTRYFLAG_SELECTED );
1435 pView->nSelectionCount--;
1438 #ifdef CHECK_INTEGRITY
1439 CheckIntegrity();
1440 #endif
1441 return TRUE;
1444 /*************************************************************************
1446 |* SvTreeList::Remove
1448 |* Beschreibung
1449 |* Ersterstellung 17.08.94
1450 |* Letzte Aenderung 05.04.01
1452 *************************************************************************/
1453 BOOL SvTreeList::Remove( SvListEntry* pEntry )
1455 DBG_ASSERT(pEntry,"Cannot remove root, use clear");
1457 if( !pEntry->pParent )
1459 DBG_ERROR("Removing entry not in model!");
1460 // unter gewissen Umstaenden (welche?) loescht der
1461 // Explorer aus der View Eintraege, die er nicht in die View
1462 // eingefuegt hat. Da sich der Kunde fuer ein platzendes
1463 // Office nichts kaufen kann, fange ich diesen Fall ab.
1464 return FALSE;
1467 Broadcast( LISTACTION_REMOVING, pEntry );
1468 ULONG nRemoved = 1 + GetChildCount(pEntry);
1469 bAbsPositionsValid = FALSE;
1471 SvListEntry* pParent = pEntry->pParent;
1472 SvTreeEntryList* pList = pParent->pChilds;
1473 DBG_ASSERT(pList,"Remove:No Childlist");
1474 BOOL bLastEntry = FALSE;
1476 if ( pEntry->HasChildListPos() )
1478 ULONG nListPos = pEntry->GetChildListPos();
1479 bLastEntry = (nListPos == (pList->Count()-1) ) ? TRUE : FALSE;
1480 pList->Remove( nListPos );
1482 else
1484 pList->Remove( (void*) pEntry );
1488 // moved to end of method because it is used later with Broadcast
1489 // delete pEntry; // loescht auch alle Childs
1491 if ( pList->Count() == 0 )
1493 pParent->pChilds = 0;
1494 delete pList;
1496 else
1498 if( !bLastEntry )
1499 SetListPositions( pList );
1501 nEntryCount -= nRemoved;
1503 #ifdef CHECK_INTEGRITY
1504 CheckIntegrity();
1505 #endif
1506 Broadcast( LISTACTION_REMOVED, pEntry );
1508 delete pEntry; // loescht auch alle Childs
1509 return TRUE;
1512 /*************************************************************************
1514 |* SvTreeList::
1516 |* Beschreibung
1517 |* Ersterstellung 17.08.94
1518 |* Letzte Aenderung 17.08.94
1520 *************************************************************************/
1522 ULONG SvTreeList::SelectChilds(SvListView* pView, SvListEntry* pParent,BOOL bSelect )
1524 DBG_ASSERT(pView&&pParent,"SelChilds:View/Parent?");
1525 if ( !pParent->pChilds )
1526 return 0;
1527 if ( pParent->pChilds->Count() == 0 )
1528 return 0;
1530 USHORT nRefDepth = GetDepth( pParent );
1531 USHORT nDepth = nRefDepth;
1532 ULONG nCount = 0;
1533 pParent = Next( pParent );
1536 if ( Select( pView, pParent, bSelect ) )
1537 nCount++; // nur die tatsaechlichen Selektierungen zaehlen
1538 pParent = Next( pParent, &nDepth );
1540 while( pParent && nDepth > nRefDepth );
1541 #ifdef CHECK_INTEGRITY
1542 CheckIntegrity();
1543 #endif
1544 return nCount;
1547 void SvTreeList::SelectAll( SvListView* pView, BOOL bSelect )
1549 DBG_ASSERT(pView,"SelectAll:NoView");
1550 SvListEntry* pEntry = First();
1551 while ( pEntry )
1553 SvViewData* pViewData = pView->GetViewData( pEntry );
1554 if ( bSelect )
1555 pViewData->nFlags |= SVLISTENTRYFLAG_SELECTED;
1556 else
1557 pViewData->nFlags &= (~SVLISTENTRYFLAG_SELECTED);
1559 pEntry = Next( pEntry );
1561 if ( bSelect )
1562 pView->nSelectionCount = nEntryCount;
1563 else
1564 pView->nSelectionCount = 0;
1565 #ifdef CHECK_INTEGRITY
1566 CheckIntegrity();
1567 #endif
1571 SvListEntry* SvTreeList::GetEntryAtAbsPos( ULONG nAbsPos ) const
1573 SvListEntry* pEntry = First();
1574 while ( nAbsPos && pEntry )
1576 pEntry = Next( pEntry );
1577 nAbsPos--;
1579 return pEntry;
1582 SvListEntry* SvTreeList::GetEntryAtVisPos( const SvListView* pView, ULONG nVisPos ) const
1584 DBG_ASSERT(pView,"GetEntryAtVisPos:No View");
1585 SvListEntry* pEntry = First();
1586 while ( nVisPos && pEntry )
1588 pEntry = NextVisible( pView, pEntry );
1589 nVisPos--;
1591 return pEntry;
1594 void SvTreeList::SetListPositions( SvTreeEntryList* pList )
1596 if( pList->Count() )
1598 SvListEntry* pEntry = (SvListEntry*)(pList->GetObject(0));
1599 if( pEntry->pParent )
1600 pEntry->pParent->InvalidateChildrensListPositions();
1603 ULONG nListPos = 0;
1604 SvListEntry* pEntry = (SvListEntry*)(pList->First());
1605 while( pEntry )
1607 pEntry->nListPos = nListPos;
1608 nListPos++;
1609 pEntry = (SvListEntry*)(pList->Next());
1615 void SvTreeList::InvalidateEntry( SvListEntry* pEntry )
1617 Broadcast( LISTACTION_INVALIDATE_ENTRY, pEntry );
1620 BOOL SvTreeList::IsInChildList( SvListEntry* pParent, SvListEntry* pChild) const
1622 if ( !pParent )
1623 pParent = pRootItem;
1624 BOOL bIsChild = FALSE;
1625 if ( pParent->pChilds )
1626 bIsChild = (BOOL)(pParent->pChilds->GetPos(pChild) != LIST_ENTRY_NOTFOUND);
1627 return bIsChild;
1631 void lcl_CheckList( SvTreeEntryList* pList )
1633 SvListEntry* pEntry = (SvListEntry*)(pList->First());
1634 ULONG nPos = 0;
1635 while ( pEntry )
1637 DBG_ASSERT(pEntry->GetChildListPos()==nPos,"Wrong ListPos");
1638 pEntry = (SvListEntry*)(pList->Next());
1639 nPos++;
1643 void SvTreeList::CheckIntegrity() const
1645 ULONG nMyEntryCount = 0;
1646 if ( pRootItem->pChilds )
1648 lcl_CheckList( pRootItem->pChilds );
1649 SvListEntry* pEntry = First();
1650 while( pEntry )
1652 nMyEntryCount++;
1653 if ( pEntry->pChilds )
1654 lcl_CheckList( pEntry->pChilds );
1655 pEntry = Next( pEntry );
1658 DBG_ASSERT(nMyEntryCount==GetEntryCount(),"Entry count invalid");
1661 SvListEntry* SvTreeList::GetRootLevelParent( SvListEntry* pEntry ) const
1663 DBG_ASSERT(pEntry,"GetRootLevelParent:No Entry");
1664 SvListEntry* pCurParent = 0;
1665 if ( pEntry )
1667 pCurParent = pEntry->pParent;
1668 if ( pCurParent == pRootItem )
1669 return pEntry; // ist sein eigener Parent
1670 while( pCurParent && pCurParent->pParent != pRootItem )
1671 pCurParent = pCurParent->pParent;
1673 return pCurParent;
1679 //*************************************************************************
1680 //*************************************************************************
1681 //*************************************************************************
1682 //*************************************************************************
1683 //*************************************************************************
1684 //*************************************************************************
1685 //*************************************************************************
1686 //*************************************************************************
1688 DBG_NAME(SvListView);
1690 SvListView::SvListView( SvTreeList* pModell )
1692 DBG_CTOR(SvListView,0);
1693 pModel = 0;
1694 nSelectionCount = 0;
1695 nVisibleCount = 0;
1696 bVisPositionsValid = FALSE;
1697 SetModel( pModell );
1700 SvListView::SvListView()
1702 DBG_CTOR(SvListView,0);
1703 pModel = 0;
1704 nSelectionCount = 0;
1705 nVisibleCount = 0;
1706 bVisPositionsValid = FALSE;
1710 SvListView::~SvListView()
1712 DBG_DTOR(SvListView,0);
1713 ClearTable();
1716 void SvListView::InitTable()
1718 DBG_CHKTHIS(SvListView,0);
1719 DBG_ASSERT(pModel,"InitTable:No Model");
1720 DBG_ASSERT(!nSelectionCount&&!nVisibleCount&&!bVisPositionsValid,"InitTable: Not cleared!");
1722 if( aDataTable.Count() )
1724 DBG_ASSERT(aDataTable.Count()==1,"InitTable: TableCount != 1");
1725 // die im Clear fuer die Root allozierten View-Daten loeschen
1726 // Achtung: Das zu dem RootEntry (und damit auch der Entry)
1727 // gehoerende Model kann bereits geloescht sein!
1728 SvViewData* pViewData = (SvViewData*)aDataTable.GetObject( 0 );
1729 delete pViewData;
1730 aDataTable.Clear();
1733 SvListEntry* pEntry;
1734 SvViewData* pViewData;
1736 // RootEntry einfuegen
1737 pEntry = pModel->pRootItem;
1738 pViewData = new SvViewData;
1739 pViewData->nFlags = SVLISTENTRYFLAG_EXPANDED;
1740 aDataTable.Insert( (ULONG)pEntry, pViewData );
1741 // Jetzt alle anderen Entries
1742 pEntry = pModel->First();
1743 while( pEntry )
1745 pViewData = CreateViewData( pEntry );
1746 DBG_ASSERT(pViewData,"InitTable:No ViewData");
1747 InitViewData( pViewData, pEntry );
1748 aDataTable.Insert( (ULONG)pEntry, pViewData );
1749 pEntry = pModel->Next( pEntry );
1753 SvViewData* SvListView::CreateViewData( SvListEntry* )
1755 DBG_CHKTHIS(SvListView,0);
1756 return new SvViewData;
1759 void SvListView::ClearTable()
1761 DBG_CHKTHIS(SvListView,0);
1762 SvViewData* pViewData = (SvViewData*)aDataTable.First();
1763 while( pViewData )
1765 delete pViewData;
1766 pViewData = (SvViewData*)aDataTable.Next();
1768 aDataTable.Clear();
1771 void SvListView::Clear()
1773 ClearTable();
1774 nSelectionCount = 0;
1775 nVisibleCount = 0;
1776 bVisPositionsValid = FALSE;
1777 if( pModel )
1779 // RootEntry einfuegen
1780 SvListEntry* pEntry = pModel->pRootItem;
1781 SvViewData* pViewData = new SvViewData;
1782 pViewData->nFlags = SVLISTENTRYFLAG_EXPANDED;
1783 aDataTable.Insert( (ULONG)pEntry, pViewData );
1787 void SvListView::SetModel( SvTreeList* pNewModel )
1789 DBG_CHKTHIS(SvListView,0);
1790 BOOL bBroadcastCleared = FALSE;
1791 if ( pModel )
1793 pModel->RemoveView( this );
1794 bBroadcastCleared = TRUE;
1795 ModelNotification( LISTACTION_CLEARING,0,0,0 );
1796 if ( pModel->GetRefCount() == 0 )
1797 delete pModel;
1799 pModel = pNewModel;
1800 InitTable();
1801 pNewModel->InsertView( this );
1802 if( bBroadcastCleared )
1803 ModelNotification( LISTACTION_CLEARED,0,0,0 );
1807 void SvListView::ModelHasCleared()
1809 DBG_CHKTHIS(SvListView,0);
1812 void SvListView::ModelHasInserted( SvListEntry* )
1814 DBG_CHKTHIS(SvListView,0);
1817 void SvListView::ModelHasInsertedTree( SvListEntry* )
1819 DBG_CHKTHIS(SvListView,0);
1822 void SvListView::ModelIsMoving( SvListEntry* /* pSource */ ,
1823 SvListEntry* /* pTargetParent */ , ULONG /* nPos */ )
1825 DBG_CHKTHIS(SvListView,0);
1829 void SvListView::ModelHasMoved( SvListEntry* )
1831 DBG_CHKTHIS(SvListView,0);
1834 void SvListView::ModelIsRemoving( SvListEntry* )
1836 DBG_CHKTHIS(SvListView,0);
1839 void SvListView::ModelHasRemoved( SvListEntry* )
1841 DBG_CHKTHIS(SvListView,0);
1844 void SvListView::ModelHasEntryInvalidated( SvListEntry*)
1846 DBG_CHKTHIS(SvListView,0);
1849 void SvListView::ActionMoving( SvListEntry* pEntry,SvListEntry*,ULONG)
1851 DBG_CHKTHIS(SvListView,0);
1852 SvListEntry* pParent = pEntry->pParent;
1853 DBG_ASSERT(pParent,"Model not consistent");
1854 if( pParent != pModel->pRootItem && pParent->pChilds->Count() == 1 )
1856 SvViewData* pViewData = (SvViewData*)aDataTable.Get( (ULONG)pParent );
1857 pViewData->nFlags &= (~SVLISTENTRYFLAG_EXPANDED);
1859 // vorlaeufig
1860 nVisibleCount = 0;
1861 bVisPositionsValid = FALSE;
1864 void SvListView::ActionMoved( SvListEntry* /* pEntry */ ,
1865 SvListEntry* /* pTargetPrnt */ ,
1866 ULONG /* nChildPos */ )
1868 DBG_CHKTHIS(SvListView,0);
1869 nVisibleCount = 0;
1870 bVisPositionsValid = FALSE;
1873 void SvListView::ActionInserted( SvListEntry* pEntry )
1875 DBG_CHKTHIS(SvListView,0);
1876 DBG_ASSERT(pEntry,"Insert:No Entry");
1877 SvViewData* pData = CreateViewData( pEntry );
1878 InitViewData( pData, pEntry );
1879 #ifdef DBG_UTIL
1880 BOOL bSuccess =
1881 #endif
1882 aDataTable.Insert( (ULONG)pEntry, pData );
1883 DBG_ASSERT(bSuccess,"Entry already in View");
1884 if ( nVisibleCount && pModel->IsEntryVisible( this, pEntry ))
1886 nVisibleCount = 0;
1887 bVisPositionsValid = FALSE;
1891 void SvListView::ActionInsertedTree( SvListEntry* pEntry )
1893 DBG_CHKTHIS(SvListView,0);
1894 if ( pModel->IsEntryVisible( this, pEntry ))
1896 nVisibleCount = 0;
1897 bVisPositionsValid = FALSE;
1899 // ueber Entry und seine Childs iterieren
1900 SvListEntry* pCurEntry = pEntry;
1901 USHORT nRefDepth = pModel->GetDepth( pCurEntry );
1902 while( pCurEntry )
1904 DBG_ASSERT(aDataTable.Get((ULONG)pCurEntry)==0,"Entry already in Table");
1905 SvViewData* pViewData = CreateViewData( pCurEntry );
1906 DBG_ASSERT(pViewData,"No ViewData");
1907 InitViewData( pViewData, pEntry );
1908 aDataTable.Insert( (ULONG)pCurEntry, pViewData );
1909 pCurEntry = pModel->Next( pCurEntry );
1910 if ( pCurEntry && pModel->GetDepth(pCurEntry) <= nRefDepth)
1911 pCurEntry = 0;
1915 void SvListView::RemoveViewData( SvListEntry* pParent )
1917 SvTreeEntryList* pChilds = pParent->pChilds;
1918 if( pChilds )
1920 SvListEntry* pCur = (SvListEntry*)pChilds->First();
1921 while( pCur )
1923 SvViewData* pViewData = (SvViewData*)aDataTable.Get((ULONG)pCur);
1924 delete pViewData;
1925 aDataTable.Remove( (ULONG)pCur );
1926 if( pCur->HasChilds())
1927 RemoveViewData( pCur );
1928 pCur = (SvListEntry*)pChilds->Next();
1935 void SvListView::ActionRemoving( SvListEntry* pEntry )
1937 DBG_CHKTHIS(SvListView,0);
1938 DBG_ASSERT(pEntry,"Remove:No Entry");
1940 SvViewData* pViewData = (SvViewData*)aDataTable.Get( (ULONG)pEntry );
1941 ULONG nSelRemoved = 0;
1942 if ( pViewData->IsSelected() )
1943 nSelRemoved = 1 + pModel->GetChildSelectionCount( this, pEntry );
1944 nSelectionCount -= nSelRemoved;
1945 ULONG nVisibleRemoved = 0;
1946 if ( pModel->IsEntryVisible( this, pEntry ) )
1947 nVisibleRemoved = 1 + pModel->GetVisibleChildCount( this, pEntry );
1948 if( nVisibleCount )
1950 #ifdef DBG_UTIL
1951 if( nVisibleCount < nVisibleRemoved )
1953 DBG_ERROR("nVisibleRemoved bad");
1955 #endif
1956 nVisibleCount -= nVisibleRemoved;
1958 bVisPositionsValid = FALSE;
1960 pViewData = (SvViewData*)aDataTable.Get((ULONG)pEntry);
1961 delete pViewData;
1962 aDataTable.Remove( (ULONG)pEntry );
1963 RemoveViewData( pEntry );
1965 SvListEntry* pCurEntry = pEntry->pParent;
1966 if ( pCurEntry && pCurEntry != pModel->pRootItem &&
1967 pCurEntry->pChilds->Count() == 1 )
1969 pViewData = (SvViewData*)aDataTable.Get((ULONG)pCurEntry);
1970 pViewData->nFlags &= (~SVLISTENTRYFLAG_EXPANDED);
1974 void SvListView::ActionRemoved( SvListEntry* /* pEntry */ )
1976 DBG_CHKTHIS(SvListView,0);
1979 void SvListView::ActionClear()
1981 DBG_CHKTHIS(SvListView,0);
1982 Clear();
1985 void SvListView::ModelNotification( USHORT nActionId, SvListEntry* pEntry1,
1986 SvListEntry* pEntry2, ULONG nPos )
1988 DBG_CHKTHIS(SvListView,0);
1989 switch( nActionId )
1991 case LISTACTION_INSERTED:
1992 ActionInserted( pEntry1 );
1993 ModelHasInserted( pEntry1 );
1994 break;
1995 case LISTACTION_INSERTED_TREE:
1996 ActionInsertedTree( pEntry1 );
1997 ModelHasInsertedTree( pEntry1 );
1998 break;
1999 case LISTACTION_REMOVING:
2000 ModelIsRemoving( pEntry1 );
2001 ActionRemoving( pEntry1 );
2002 break;
2003 case LISTACTION_REMOVED:
2004 ActionRemoved( pEntry1 );
2005 ModelHasRemoved( pEntry1 );
2006 break;
2007 case LISTACTION_MOVING:
2008 ModelIsMoving( pEntry1, pEntry2, nPos );
2009 ActionMoving( pEntry1, pEntry2, nPos );
2010 break;
2011 case LISTACTION_MOVED:
2012 ActionMoved( pEntry1, pEntry2, nPos );
2013 ModelHasMoved( pEntry1 );
2014 break;
2015 case LISTACTION_CLEARING:
2016 ActionClear();
2017 ModelHasCleared(); //sic! wg. Kompatibilitaet!
2018 break;
2019 case LISTACTION_CLEARED:
2020 break;
2021 case LISTACTION_INVALIDATE_ENTRY:
2022 // keine Action fuer die Basisklasse
2023 ModelHasEntryInvalidated( pEntry1 );
2024 break;
2025 case LISTACTION_RESORTED:
2026 bVisPositionsValid = FALSE;
2027 break;
2028 case LISTACTION_RESORTING:
2029 break;
2030 default:
2031 DBG_ERROR("unknown ActionId");
2035 void SvListView::InitViewData( SvViewData*, SvListEntry* )
2039 StringCompare SvTreeList::Compare( SvListEntry* pLeft, SvListEntry* pRight) const
2041 if( aCompareLink.IsSet())
2043 SvSortData aSortData;
2044 aSortData.pLeft = pLeft;
2045 aSortData.pRight = pRight;
2046 return (StringCompare)aCompareLink.Call( &aSortData );
2048 return COMPARE_EQUAL;
2051 void SvTreeList::Resort()
2053 Broadcast( LISTACTION_RESORTING );
2054 bAbsPositionsValid = FALSE;
2055 ResortChilds( pRootItem );
2056 Broadcast( LISTACTION_RESORTED );
2059 void SvTreeList::ResortChilds( SvListEntry* pParent )
2061 DBG_ASSERT(pParent,"Parent not set");
2062 List* pChildList = pParent->pChilds;
2063 if( !pChildList )
2064 return;
2065 List aList( *pChildList );
2066 pChildList->Clear();
2068 ULONG nCount = aList.Count();
2069 for( ULONG nCur = 0; nCur < nCount; nCur++ )
2071 SvListEntry* pCurEntry = (SvListEntry*)aList.GetObject( nCur );
2072 ULONG nListPos = LIST_APPEND;
2073 GetInsertionPos( pCurEntry, pParent, nListPos );
2074 pChildList->Insert( pCurEntry, nListPos );
2075 if( pCurEntry->pChilds )
2076 ResortChilds( pCurEntry );
2078 SetListPositions( (SvTreeEntryList*)pChildList );
2081 void SvTreeList::GetInsertionPos( SvListEntry* pEntry, SvListEntry* pParent,
2082 ULONG& rPos )
2084 DBG_ASSERT(pEntry,"No Entry");
2086 if( eSortMode == SortNone )
2087 return;
2089 rPos = LIST_APPEND;
2090 SvTreeEntryList* pChildList = GetChildList( pParent );
2092 if( pChildList && pChildList->Count() )
2094 long i = 0;
2095 long j = pChildList->Count()-1;
2096 long k;
2097 StringCompare eCompare = COMPARE_GREATER;
2101 k = (i+j)/2;
2102 SvListEntry* pTempEntry = (SvListEntry*)(pChildList->GetObject(k));
2103 eCompare = Compare( pEntry, pTempEntry );
2104 if( eSortMode == SortDescending && eCompare != COMPARE_EQUAL )
2106 if( eCompare == COMPARE_LESS )
2107 eCompare = COMPARE_GREATER;
2108 else
2109 eCompare = COMPARE_LESS;
2111 if( eCompare == COMPARE_GREATER )
2112 i = k + 1;
2113 else
2114 j = k - 1;
2115 } while( (eCompare != COMPARE_EQUAL) && (i <= j) );
2117 if( eCompare != COMPARE_EQUAL )
2119 if(i > ((long)pChildList->Count() - 1)) // nicht gefunden, Ende der Liste
2120 rPos = LIST_APPEND;
2121 else
2122 rPos = i; // nicht gefunden, Mitte
2124 else
2125 rPos = k;