RemoveNode(ArrayList nodes, int indexToRemove) { #if DEBUG || ASSERTIONS_TRACE ProgressNode nodeToRemove = (ProgressNode)nodes[indexToRemove]; Util.Assert(nodes != null, "can't remove nodes from a null list"); Util.Assert(indexToRemove < nodes.Count, "index is not in list"); Util.Assert(nodes[indexToRemove] != null, "no node at specified index"); Util.Assert(nodeToRemove.Children == null || nodeToRemove.Children.Count == 0, "can't remove a node with children"); #endif nodes.RemoveAt(indexToRemove); --_nodeCount; #if DEBUG || ASSERTIONS_ON Util.Assert(_nodeCount == this.CountNodes(), "We've lost track of the number of nodes in the tree"); #endif }
CompressToFitHelper( PSHostRawUserInterface rawUi, int maxHeight, int maxWidth, out int nodesCompressed, ProgressNode.RenderStyle priorStyle, ProgressNode.RenderStyle newStyle) { nodesCompressed = 0; int age = 0; do { ProgressNode node = FindOldestNodeOfGivenStyle(_topLevelNodes, age, priorStyle); if (node == null) { // We've compressed every node of the prior style already. break; } node.Style = newStyle; ++nodesCompressed; if (TallyHeight(rawUi, maxHeight, maxWidth) <= maxHeight) { return(true); } } while (true); // If we get all the way to here, then we've compressed all the nodes and we still don't fit. #if DEBUG || ASSERTIONS_TRACE Util.Assert( nodesCompressed == CountNodes(), "We should have compressed every node in the tree."); Util.Assert( AllNodesHaveGivenStyle(_topLevelNodes, newStyle), "We should have compressed every node in the tree."); #endif return(false); }
FindOldestNodeOfGivenStyle(ArrayList nodes, int oldestSoFar, ProgressNode.RenderStyle style) { if (nodes == null) { return(null); } ProgressNode found = null; for (int i = 0; i < nodes.Count; ++i) { ProgressNode node = (ProgressNode)nodes[i]; Util.Assert(node != null, "nodes should not contain null elements"); if (node.Age >= oldestSoFar && node.Style == style) { found = node; oldestSoFar = found.Age; } if (node.Children != null) { ProgressNode child = FindOldestNodeOfGivenStyle(node.Children, oldestSoFar, style); if (child != null) { // In this universe, parents can be younger than their children. We found a child older than us. found = child; oldestSoFar = found.Age; } } } #if DEBUG || ASSERTIONS_TRACE if (found != null) { Util.Assert(found.Style == style, "unexpected style"); Util.Assert(found.Age >= oldestSoFar, "unexpected age"); } #endif return(found); }
RemoveNodeAndPromoteChildren(ArrayList nodes, int indexToRemove) { ProgressNode nodeToRemove = (ProgressNode)nodes[indexToRemove]; Util.Assert(nodes != null, "can't remove nodes from a null list"); Util.Assert(indexToRemove < nodes.Count, "index is not in list"); Util.Assert(nodeToRemove != null, "no node at specified index"); if (nodeToRemove == null) { return; } if (nodeToRemove.Children != null) { // promote the children. for (int i = 0; i < nodeToRemove.Children.Count; ++i) { // unparent the children. If the children are ever updated again, they will be reparented. ((ProgressNode)nodeToRemove.Children[i]).ParentActivityId = -1; } // add the children as siblings nodes.RemoveAt(indexToRemove); --_nodeCount; nodes.InsertRange(indexToRemove, nodeToRemove.Children); #if DEBUG || ASSERTIONS_TRACE Util.Assert(_nodeCount == this.CountNodes(), "We've lost track of the number of nodes in the tree"); #endif } else { // nothing to promote RemoveNode(nodes, indexToRemove); return; } }
EvictNode() { ArrayList listWhereFound = null; int indexWhereFound = -1; ProgressNode oldestNode = FindOldestLeafmostNode(out listWhereFound, out indexWhereFound); if (oldestNode == null) { // Well that's a surprise. There's got to be at least one node there that's older than 0. Util.Assert(false, "Must be an old node in the tree somewhere"); // We'll just pick the root node, then. RemoveNode(_topLevelNodes, 0); } else { RemoveNode(listWhereFound, indexWhereFound); } }
FindOldestLeafmostNode(out ArrayList listWhereFound, out int indexWhereFound) { listWhereFound = null; indexWhereFound = -1; ProgressNode result = null; ArrayList treeToSearch = _topLevelNodes; do { result = FindOldestLeafmostNodeHelper(treeToSearch, out listWhereFound, out indexWhereFound); if (result == null || result.Children == null || result.Children.Count == 0) { break; } // search the subtree for the oldest child treeToSearch = result.Children; } while (true); return(result); }
VisitNodes(ArrayList nodes, NodeVisitor v) { if (nodes == null) { return; } for (int i = 0; i < nodes.Count; ++i) { ProgressNode node = (ProgressNode)nodes[i]; Util.Assert(node != null, "nodes should not contain null elements"); if (!v.Visit(node, nodes, i)) { return; } if (node.Children != null) { VisitNodes(node.Children, v); } } }
Visit(ProgressNode unused, ArrayList unusedToo, int unusedThree) { ++Count; return(true); }
Update(Int64 sourceId, ProgressRecord record) { Util.Assert(record != null, "record should not be null"); do { if (record.ParentActivityId == record.ActivityId) { // ignore malformed records. LogManager.Trace("Ignoring malformed record: {0}", record); break; } ArrayList listWhereFound = null; int indexWhereFound = -1; ProgressNode foundNode = FindNodeById(sourceId, record.ActivityId, out listWhereFound, out indexWhereFound); if (foundNode != null) { Util.Assert(listWhereFound != null, "node found, but list not identified"); Util.Assert(indexWhereFound >= 0, "node found, but index not returned"); if (record.RecordType == ProgressRecordType.Completed) { RemoveNodeAndPromoteChildren(listWhereFound, indexWhereFound); break; } if (record.ParentActivityId == foundNode.ParentActivityId) { // record is an update to an existing activity. Copy the record data into the found node, and // reset the age of the node. foundNode.Activity = record.Activity; foundNode.StatusDescription = record.StatusDescription; foundNode.CurrentOperation = record.CurrentOperation; foundNode.PercentComplete = Math.Min(record.PercentComplete, 100); foundNode.SecondsRemaining = record.SecondsRemaining; foundNode.Age = 0; break; } else { // The record's parent Id mismatches with that of the found node's. We interpret // this to mean that the activity represented by the record (and the found node) is // being "re-parented" elsewhere. So we remove the found node and treat the record // as a new activity. RemoveNodeAndPromoteChildren(listWhereFound, indexWhereFound); } } // At this point, the record's activity is not in the tree. So we need to add it. if (record.RecordType == ProgressRecordType.Completed) { // We don't track completion records that don't correspond to activities we're not // already tracking. break; } ProgressNode newNode = new ProgressNode(sourceId, record); // If we're adding a node, and we have no more space, then we need to pick a node to evict. while (_nodeCount >= maxNodeCount) { EvictNode(); } if (newNode.ParentActivityId >= 0) { ProgressNode parentNode = FindNodeById(newNode.SourceId, newNode.ParentActivityId); if (parentNode != null) { if (parentNode.Children == null) { parentNode.Children = new ArrayList(); } AddNode(parentNode.Children, newNode); break; } // The parent node is not in the tree. Make the new node's parent the root, // and add it to the tree. If the parent ever shows up, then the next time // we receive a record for this activity, the parent id's won't match, and the // activity will be properly re-parented. newNode.ParentActivityId = -1; } AddNode(_topLevelNodes, newNode); } while (false); // At this point the tree is up-to-date. Make a pass to age all of the nodes AgeNodesAndResetStyle(); }
Visit(ProgressNode node, ArrayList unused, int unusedToo) { node.Age = Math.Min(node.Age + 1, Int32.MaxValue - 1); node.Style = ProgressNode.RenderStyle.FullPlus; return(true); }
Visit(ProgressNode node, ArrayList listWhereFound, int indexWhereFound);