public void DrawTreeMap(IRenderer Renderer) { if (DoRevalue || (ShowLayout != ShowNodes.All && XRay.CoverChange) || (ShowLayout == ShowNodes.Instances && XRay.InstanceChange)) { RecalcCover(InternalRoot); RecalcCover(ExternalRoot); XRay.CoverChange = false; XRay.InstanceChange = false; DoRevalue = false; RevalueCount++; DoResize = true; } if (DoResize) { var drawArea = new RectangleF(ScreenOffset.X, ScreenOffset.Y, ScreenSize.Width, ScreenSize.Height); float offset = 0; float centerWidth = drawArea.Width; PositionMap.Clear(); CenterMap.Clear(); if (ShowingOutside) { offset = drawArea.Width * 1.0f / 4.0f; centerWidth -= offset; InternalRoot.SetArea(new RectangleF(ScreenOffset.X, ScreenOffset.Y, offset - PanelBorderWidth, drawArea.Height)); PositionMap[InternalRoot.ID] = InternalRoot; SizeNode(Renderer, InternalRoot, CurrentRoot, false); } if (ShowingExternal) { float extWidth = drawArea.Width * 1.0f / 4.0f; centerWidth -= extWidth; ExternalRoot.SetArea(new RectangleF(ScreenOffset.X + offset + centerWidth + PanelBorderWidth, ScreenOffset.Y, extWidth - PanelBorderWidth, drawArea.Height)); PositionMap[ExternalRoot.ID] = ExternalRoot; SizeNode(Renderer, ExternalRoot, null, false); } CurrentRoot.SetArea(new RectangleF(ScreenOffset.X + offset, ScreenOffset.Y, centerWidth, drawArea.Height)); PositionMap[CurrentRoot.ID] = CurrentRoot; SizeNode(Renderer, CurrentRoot, null, true); DoResize = false; ResizeCount++; } }
public void DrawCallGraph() { if (DoRevalue || XRay.CallChange || (ShowLayout != ShowNodes.All && XRay.CoverChange) || (ShowLayout == ShowNodes.Instances && XRay.InstanceChange)) { RecalcCover(InternalRoot); RecalcCover(ExternalRoot); PositionMap.Clear(); CenterMap.Clear(); var root = CurrentRoot; //causes method graph with ShowExternal on to show nothing //if (root == InternalRoot && ShowExternal) // root = TopRoot; TopGraph = new GraphSet(this, root); // combine position and center maps for graph tree Utilities.RecurseTree( TopGraph, s => { foreach (var kvp in s.PositionMap) { PositionMap[kvp.Key] = kvp.Value; } foreach (var id in s.CenterMap) { CenterMap.Add(id); } }, s => s.Subsets.Values ); XRay.CallChange = false; XRay.CoverChange = false; XRay.InstanceChange = false; DoRevalue = false; RevalueCount++; DoResize = true; } // graph created in relative coords so it doesnt need to be re-computed each resize, only on recalc if (DoResize) { Utilities.RecurseTree( TopGraph, s => { foreach (var graph in s.Graphs) { if (s.GraphContainer == null) { ScaleGraph(graph, new RectangleF(ScreenOffset, ScreenSize)); } else if (s.GraphContainer.XNode.External) { // this is assuming the external node is a triangle var area = s.GraphContainer.AreaF; var inside = new RectangleF(area.X + area.Width / 4f, area.Y + area.Height / 2f, area.Width / 2f, area.Height / 2f); ScaleGraph(graph, inside); } else { ScaleGraph(graph, s.GraphContainer.AreaF); } } }, s => s.Subsets.Values ); DoResize = false; ResizeCount++; } }
protected void ClearMap() { map.Clear(); ClearTags(); }
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; } }