private void LayoutThreadlines(long currentTick) { PositionMap.Clear(); ThreadlineNodes.Clear(); // go through each thread object and position nodes float xOffset = 0; float nodeHeight = 18; float nodeWidth = 18; foreach (var timeline in Threadlines.Values.OrderBy(t => t.ThreadID)) { // do depth correction so we dont have empty columns int fixedDepth = 0; timeline.FixedDepths = new int[timeline.Deepest + 1]; foreach (var depth in timeline.DepthSet) { timeline.FixedDepths[depth] = fixedDepth; fixedDepth++; } timeline.NodeDepths = new ThreadlineNode[timeline.Deepest + 2]; // an extra level to prevent outside bounds exc when checking lower level float yPos = ScreenSize.Height - nodeHeight - 16; float colWidth = timeline.Deepest * nodeWidth + 100; string label = "#" + timeline.ThreadID.ToString() + ": " + timeline.Name; float x = ScreenOffset.X + xOffset + 2; float y = ScreenOffset.Y + yPos + nodeHeight + 2; Renderer.DrawString(label, TextFont, timeline.IsAlive ? Color.Black : Color.Gray, x, y, colWidth, 18); foreach (var item in timeline.Sequence) { var node = NodeModels[item.NodeID]; PositionMap[node.ID] = node; int depth = timeline.FixedDepths[item.Depth]; float xPos = xOffset + nodeWidth * depth; var area = new RectangleF(ScreenOffset.X + xPos, ScreenOffset.Y + yPos, nodeHeight, nodeWidth); // only light up the latest node if (!AddedNodes.Contains(node.ID)) { node.RoomForLabel = true; node.SetArea(area); } // extend this node down to the previous nodes (future node) depth bool foundPrev = false; for (int i = depth + 1; i < timeline.NodeDepths.Length; i++) { if (!foundPrev && timeline.NodeDepths[i] != null) { area.Height = timeline.NodeDepths[i].Area.Bottom - area.Top; foundPrev = true; } timeline.NodeDepths[i] = null; } bool showHit = false; if (item.EndTick == 0 || Utilities.TicksToSeconds(currentTick - item.StartTick) < 1.0) // of started in last second { showHit = true; } float labelX = ScreenOffset.X + xPos + nodeWidth + 3; float labelWidth = colWidth - nodeWidth * (depth + 1) - 3; var labelArea = new RectangleF(labelX, ScreenOffset.Y + yPos + 1, labelWidth, nodeHeight); var entry = new ThreadlineNode() { Node = node, Area = area, LabelArea = labelArea, ShowHit = showHit }; if (timeline.NodeDepths[depth] == null) { timeline.NodeDepths[depth] = entry; } ThreadlineNodes.Add(entry); yPos -= nodeHeight; } xOffset += colWidth; } }
private void LayoutThreadlines(long currentTick) { PositionMap.Clear(); ThreadlineNodes.Clear(); // go through each thread object and position nodes float xOffset = 0; float nodeHeight = 18; float nodeWidth = 18; foreach (var timeline in Threadlines.Values.OrderBy(t => t.ThreadID)) { // do depth correction so we dont have empty columns int fixedDepth = 0; timeline.FixedDepths = new int[timeline.Deepest + 1]; foreach (var depth in timeline.DepthSet) { timeline.FixedDepths[depth] = fixedDepth; fixedDepth++; } timeline.NodeDepths = new ThreadlineNode[timeline.Deepest + 2]; // an extra level to prevent outside bounds exc when checking lower level float yPos = ScreenSize.Height - nodeHeight - 16; float colWidth = timeline.Deepest * nodeWidth + 100; string label = "#" + timeline.ThreadID.ToString() + ": " + timeline.Name; float x = ScreenOffset.X + xOffset + 2; float y = ScreenOffset.Y + yPos + nodeHeight + 2; Renderer.DrawString(label, TextFont, timeline.IsAlive ? Color.Black : Color.Gray, x, y, colWidth, 18); foreach (var item in timeline.Sequence) { var node = NodeModels[item.NodeID]; PositionMap[node.ID] = node; int depth = timeline.FixedDepths[item.Depth]; float xPos = xOffset + nodeWidth * depth; var area = new RectangleF(ScreenOffset.X + xPos, ScreenOffset.Y + yPos, nodeHeight, nodeWidth); // only light up the latest node if (!AddedNodes.Contains(node.ID)) { node.RoomForLabel = true; node.SetArea(area); } // extend this node down to the previous nodes (future node) depth bool foundPrev = false; for (int i = depth + 1; i < timeline.NodeDepths.Length; i++) { if (!foundPrev && timeline.NodeDepths[i] != null) { area.Height = timeline.NodeDepths[i].Area.Bottom - area.Top; foundPrev = true; } timeline.NodeDepths[i] = null; } bool showHit = false; if (item.EndTick == 0 || Utilities.TicksToSeconds(currentTick - item.StartTick) < 1.0) // of started in last second showHit = true; float labelX = ScreenOffset.X + xPos + nodeWidth + 3; float labelWidth = colWidth - nodeWidth * (depth + 1) - 3; var labelArea = new RectangleF(labelX, ScreenOffset.Y + yPos + 1, labelWidth, nodeHeight); var entry = new ThreadlineNode() { Node = node, Area = area, LabelArea = labelArea, ShowHit = showHit }; if (timeline.NodeDepths[depth] == null) timeline.NodeDepths[depth] = entry; ThreadlineNodes.Add(entry); yPos -= nodeHeight; } xOffset += colWidth; } }