예제 #1
0
 public static bool Add(
     TREENODE parentNode, PositionTracker[] positions, int positionIndex, int relativeRow, int relativeColumn,
     ref NODEPOSITIONTRACKER lastTracker)
 {
     Debug.Assert((lastTracker == null) || (lastTracker.myNext == null));
     Debug.Assert(!parentNode.NoTracking);
     var retVal = false;
     NODEPOSITIONTRACKER newTracker = null;
     if (parentNode.DefaultTracking)
     {
         newTracker = new NODEPOSITIONTRACKER_Default(parentNode, positions, positionIndex, relativeRow, relativeColumn);
     }
     else
     {
         object trackerObject;
         var dummyOptions = 0;
         trackerObject = parentNode.Branch.GetObject(relativeRow, relativeColumn, ObjectStyle.TrackingObject, ref dummyOptions);
         if (trackerObject != null)
         {
             newTracker = new NODEPOSITIONTRACKER_Dynamic(parentNode, positions, positionIndex, trackerObject);
         }
     }
     if (newTracker != null)
     {
         if (lastTracker != null)
         {
             lastTracker.myNext = newTracker;
         }
         lastTracker = newTracker;
         retVal = true;
     }
     return retVal;
 }
예제 #2
0
        // Helper function for RealignTreeNodeLevelShift. Collects sub branches into a single
        // list, detaches them from the parent nodes, and adjusts the Expanded setting on each.
        private void CollectChildBranches(
            ref TREENODE tnParent, ILevelShiftAdjuster branchTester, ref TREENODE tnAttach, ref TREENODE tnDummyHead,
            ref TREENODE tnAttachInKillZone, ref TREENODE tnDummyHeadInKillZone, ref NODEPOSITIONTRACKER_Dynamic detachedTrackers,
            int levelShift, bool parentExpanded)
        {
            // The ILevelShiftAdjuster mechanism allows us to keep this expansion for later attachment,
            // essentially making it a potential sibling of branches originally below this level.
            var tnProcessParent = tnParent;
            if (branchTester != null)
            {
                var testResult = branchTester.TestReattachBranch(tnParent.Branch);
                if (testResult != TestReattachBranchResult.Discard)
                {
                    tnParent.Expanded = tnParent.Expanded && parentExpanded;
                    if (tnAttachInKillZone == null)
                    {
                        if (tnDummyHeadInKillZone == null)
                        {
                            tnDummyHeadInKillZone = new TREENODE();
                        }
                        // Create a dummy head to attach to
                        tnAttachInKillZone = tnDummyHeadInKillZone;
                    }
                    tnAttachInKillZone.NextSibling = tnParent;
                    tnAttachInKillZone = tnParent;
                    tnParent.NextSibling = null;
                    tnParent = null;
                    switch (testResult)
                    {
                        case TestReattachBranchResult.ReattachIntact:
                            return;
                        case TestReattachBranchResult.Realign:
                            tnProcessParent.ImmedCount = tnProcessParent.Branch.VisibleItemCount;
                            if ((tnProcessParent.FirstPositionTracker != null)
                                && !tnProcessParent.DefaultTracking)
                            {
                                NODEPOSITIONTRACKER_Dynamic.DetachTrackers(ref tnProcessParent.FirstPositionTracker, ref detachedTrackers);
                            }
                            goto case TestReattachBranchResult.ReattachChildren;
                        case TestReattachBranchResult.ReattachChildren: // Allow processing to continue below
                            tnProcessParent.FullCount = tnProcessParent.ImmedCount;
                            tnProcessParent.ImmedSubItemGain = 0;
                            tnProcessParent.FullSubItemGain = 0;
                            break;
                    }
                }
            }

            var tnChild = tnProcessParent.FirstChild;
            if (tnChild == null)
            {
                // Not checked before calling CollectChildBranches so that TestReattachBranch has a chance
                return;
            }
            Debug.Assert((tnAttach == null) || (tnAttach.NextSibling == null)); // Bad attach point
            parentExpanded = parentExpanded && tnProcessParent.Expanded;
            if (levelShift <= 1)
            {
                // Walk the children to adjust the Expanded states and locate
                // the last child (for our next attach point).
                TREENODE tnPrev = null;
                while (tnChild != null)
                {
                    tnPrev = tnChild;
                    tnChild.Expanded = tnChild.Expanded && parentExpanded;
                    tnChild = tnChild.NextSibling;
                }

                // Detach the child list from the parent node and reattach it. Note
                // that this thrashes the FullCount of the parent node, but this is
                // harmless because we're about to blow the immediate parents away anyway.
                if (tnAttach == null)
                {
                    if (tnDummyHead == null)
                    {
                        tnDummyHead = new TREENODE();
                    }
                    // Create a dummy head to attach to
                    tnAttach = tnDummyHead;
                }
                tnAttach.NextSibling = tnProcessParent.FirstChild;
                tnProcessParent.FirstChild = null;
                tnAttach = tnPrev;
            }
            else
            {
                --levelShift;
                var tnNext = tnChild;
                while ((tnChild = tnNext) != null)
                {
                    // tnChild can come back null, get NextSibling first
                    tnNext = tnChild.NextSibling;
                    CollectChildBranches(
                        ref tnChild, branchTester, ref tnAttach, ref tnDummyHead, ref tnAttachInKillZone, ref tnDummyHeadInKillZone,
                        ref detachedTrackers, levelShift, parentExpanded);
                }
            }
        }
예제 #3
0
        private void FreeRecursive(ref TREENODE pStart, ref NODEPOSITIONTRACKER_Dynamic ntDetached)
        {
            if (pStart != null)
            {
                if (myPositionManager == null
                    || pStart.NoTracking
                    || pStart.DefaultTracking)
                {
                    FreeRecursive(ref pStart);
                    return;
                }
                var tn1 = pStart;
                TREENODE tn2;
                SUBITEMNODE sn;

                //Stop the recursion from walking above the node
                tn1.Parent = null;
                while (tn1 != null)
                {
                    tn2 = tn1.FirstChild;
                    if (tn2 != null)
                    {
                        tn1.FirstChild = tn2.NextSibling;
                        tn1 = tn2;
                    }
                    else if (tn1.FirstSubItem != null)
                    {
                        sn = tn1.FirstSubItem;
                        tn1.FirstSubItem = sn.NextSibling;
                        tn1 = sn.RootNode;
                    }
                    else
                    {
                        tn2 = tn1;
                        tn1 = tn2.Parent;
                        if (tn2.FirstPositionTracker != null)
                        {
                            NODEPOSITIONTRACKER_Dynamic.DetachTrackers(ref tn2.FirstPositionTracker, ref ntDetached);
                            Debug.Assert(tn2.FirstPositionTracker == null);
                        }
                        DestroyTreeNode(ref tn2);
                    }
                }
                pStart = null;
            }
        }
예제 #4
0
 public static void DetachTrackers(ref NODEPOSITIONTRACKER ntFirst, ref NODEPOSITIONTRACKER_Dynamic ntDetached)
 {
     Debug.Assert(ntFirst != null); // Precondition, check before calling
     var ntHead = (NODEPOSITIONTRACKER_Dynamic)ntFirst;
     var ntNext = ntHead;
     NODEPOSITIONTRACKER_Dynamic ntCur = null;
     while (ntNext != null)
     {
         ntCur = ntNext;
         ntCur.myParentNode = null;
         ntNext = (NODEPOSITIONTRACKER_Dynamic)ntCur.myNextSibling;
     }
     // Link all of the detached objects together
     ntCur.myNextSibling = ntDetached;
     ntDetached = ntHead;
     ntFirst = null;
 }