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; }
/// <summary> /// Store positions to track. Generally called from an BeforeListShuffle event /// </summary> /// <param name="positions">An array of PositionTracker structures</param> /// <param name="key">The key for the tracked positions. Usually the instance of the object tracking positions.</param> /// <param name="multiColumnPositions">Specify if the positions use multi or single column indices. Note that this value can be different in the RetrievePositions call.</param> public void StorePositions(PositionTracker[] positions, object key, bool multiColumnPositions) { if (positions != null) { // Translate from single column positions into multicolumn indices when // we store the data, then translate back if needed on the way out. Feeding // the position tracking algorithms in the core engine consistent data is well // worth the up front translation cost. if (myMultiColumnTree != null) { int i; int startRow; var rowBound = (myMultiColumnTree as ITree).VisibleItemCount; var positionsCount = positions.Length; if (multiColumnPositions) { // Find any items with a column of 'I don't care' and // bind it to the first possible column. for (i = 0; i < positionsCount; ++i) { if (positions[i].Column == -1) { startRow = positions[i].StartRow; if (startRow != -1 && startRow < rowBound) { positions[i].Column = myMultiColumnTree.FindFirstNonBlankColumn(startRow); } } } } else { for (i = 0; i < positionsCount; ++i) { startRow = positions[i].StartRow; if (startRow != -1 && startRow < rowBound) { positions[i].StartRow = myMultiColumnTree.TranslateSingleColumnRow(startRow); positions[i].Column = 0; // Ignore NoColumnAffinity setting, this will always bind correctly } } } } myTable[key] = positions; } }
private bool TrackPosition(ref PositionTracker tracker, out TREENODE tnParent, out int relativeRow, out int relativeColumn) { relativeRow = VirtualTreeConstant.NullIndex; relativeColumn = 0; tnParent = null; var startRow = tracker.StartRow; if (startRow != VirtualTreeConstant.NullIndex && startRow < (this as ITree).VisibleItemCount) { var column = tracker.Column; var pos = TrackCell(startRow, ref column); if (!pos.ParentNode.NoTracking) { tnParent = pos.ParentNode; relativeRow = pos.Index; relativeColumn = column; } } return tnParent != null; }
public NODEPOSITIONTRACKER_Dynamic(TREENODE parentNode, PositionTracker[] positions, int positionIndex, object trackerObject) : base(parentNode, positions, positionIndex) { myTrackerObject = trackerObject; }
private static void ClearPositionTracker(ref PositionTracker tracker) { tracker.EndRow = tracker.StartRow = VirtualTreeConstant.NullIndex; }
public NODEPOSITIONTRACKER_Default( TREENODE parentNode, PositionTracker[] positions, int positionIndex, int relativeRow, int relativeColumn) : base(parentNode, positions, positionIndex) { myRelativeRow = relativeRow; myRelativeColumn = relativeColumn; }
protected NODEPOSITIONTRACKER(TREENODE parentNode, PositionTracker[] positions, int positionIndex) { myParentNode = parentNode; myPositions = positions; myPositionIndex = positionIndex; myNextSibling = myParentNode.FirstPositionTracker; myParentNode.FirstPositionTracker = this; }
private void UpdateEndPosition(ref PositionTracker tracker) { if (tracker.StartRow != VirtualTreeConstant.NullIndex) { int relativeRow; int relativeColumn; GetRelativePosition(out relativeRow, out relativeColumn); if (relativeRow == VirtualTreeConstant.NullIndex) { // Can't track the node tracker.EndRow = VirtualTreeConstant.NullIndex; } else { // Have end position, now determine where this node sits in the tree // UNDONE: Should be able to optimize this by walking the sibling lists // off of individual nodes. int singleColumnSubItemAdjust; var coord = FindAbsoluteIndex(myParentNode, relativeRow, out singleColumnSubItemAdjust); if (coord.IsValid) { tracker.EndRow = coord.Row; tracker.Column = coord.Column; } else { tracker.EndRow = -1; } } } }
internal void ApplyPositionTrackerData(PositionTracker[] trackers) { restoreTop = trackers[TRACKINDEX_RestoreTop].EndRow; restoreCaret = trackers[TRACKINDEX_Caret].EndRow; restoreAnchorIndex = trackers[TRACKINDEX_Anchor].EndRow; var count = trackers.Length; if (count > TRACKINDEX_FirstSelection) { var newCount = 0; // Pass 1, figure out how many node selections survived the process. for (var i = TRACKINDEX_FirstSelection; i < count; ++i) { if (trackers[i].EndRow != VirtualTreeConstant.NullIndex) { ++newCount; } } // Pass 2, reset the selection array if (newCount == 0) { restoreSelection = null; } else { if (newCount != restoreSelection.Length) { restoreSelection = new int[newCount]; } var nextSlot = 0; int endPos; for (var i = TRACKINDEX_FirstSelection; i < count; ++i) { endPos = trackers[i].EndRow; if (endPos != VirtualTreeConstant.NullIndex) { restoreSelection[nextSlot] = endPos; if (++nextSlot == newCount) { break; } } } } } }
// Get the tracker items into a PositionTracker array internal PositionTracker[] GetPositionTrackers() { var selCount = (restoreSelection == null) ? 0 : restoreSelection.Length; var retVal = new PositionTracker[TRACKINDEX_FirstSelection + selCount]; var column = restoreColumn; retVal[TRACKINDEX_RestoreTop].Initialize(restoreTop, -1); retVal[TRACKINDEX_Caret].Initialize(restoreCaret, column); retVal[TRACKINDEX_Anchor].Initialize(restoreAnchorIndex, column); //UNDONE: Temporary hack to make it easier to test selection tracking // retVal[TRACKINDEX_RestoreTop].StartPosition = -1; // retVal[TRACKINDEX_Caret].StartPosition = -1; // retVal[TRACKINDEX_Anchor].StartPosition = -1; if (selCount != 0) { for (var i = 0; i < selCount; ++i) { retVal[TRACKINDEX_FirstSelection + i].Initialize(restoreSelection[i], column); } } return retVal; }