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 DrawTheadline() { if (DoRevalue) { RecalcCover(InternalRoot); RecalcCover(ExternalRoot); DoRevalue = false; RevalueCount++; DoResize = true; } // set what nodes are allowed in the threadline based on the current root if (CurrentThreadlineZoom != CurrentRoot) { CenterMap.Clear(); CenterMap.Add(CurrentRoot.ID); Utilities.RecurseTree <NodeModel>( tree: CurrentRoot.Nodes, evaluate: n => CenterMap.Add(n.ID), recurse: n => n.Nodes); CurrentThreadlineZoom = CurrentRoot; } long currentTick = XRay.Watch.ElapsedTicks; if (!Paused) { CalcThreadline(currentTick); } LayoutThreadlines(currentTick); }
private bool AddToTimeline(ThreadFlow flow, StackItem item) { // do stuff with item Threadline timeline; if (!Threadlines.TryGetValue(flow.ThreadID, out timeline)) { timeline = new Threadline(flow, ThreadOrder++); Threadlines[flow.ThreadID] = timeline; } timeline.IsAlive = flow.IsAlive; // update var node = NodeModels[item.NodeID]; if (node.Show && (CenterMap.Contains(node.ID) || (ShowOutside && !node.XNode.External) || (ShowExternal && node.XNode.External))) { timeline.Sequence.Add(item); if (item.Depth > timeline.Deepest) { timeline.Deepest = item.Depth; } timeline.DepthSet.Add(item.Depth); return(true); } else { return(false); } }
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++; } }
public static void CenterMapOn(Mapsui.Geometries.Point position) { CenterMap?.Invoke(position); }
private void SizeNode(IRenderer Renderer, NodeModel root, NodeModel exclude, bool center) { if (!root.Show) { return; } RectangleF insideArea = root.AreaF; if (ShowLabels) { // check if enough room in root box for label var labelSpace = root.AreaF; labelSpace.Width -= LabelPadding * 2.0f; labelSpace.Height -= LabelPadding * 2.0f; var labelSize = new RectangleF(root.AreaF.Location, Renderer.MeasureString(root.Name, TextFont)); float minHeight = (root.Nodes.Count > 0) ? labelSize.Height * 2.0f : labelSize.Height; if (minHeight < labelSpace.Height && labelSize.Width / 3f < labelSpace.Width) { labelSize.X += LabelPadding; labelSize.Y += LabelPadding; if (labelSpace.Width < labelSize.Width) { root.LabelClipped = true; labelSize.Width = labelSpace.Width; } insideArea.Y += labelSize.Height; insideArea.Height -= labelSize.Height; root.RoomForLabel = true; root.LabelRect = labelSize; } } List <Sector> sectors = new TreeMap(root, exclude, insideArea.Size).Results; foreach (Sector sector in sectors) { var node = sector.OriginalValue; sector.Rect = RectangleExtensions.Contract(sector.Rect, NodeBorderWidth); if (sector.Rect.X < NodeBorderWidth) { sector.Rect.X = NodeBorderWidth; } if (sector.Rect.Y < NodeBorderWidth) { sector.Rect.Y = NodeBorderWidth; } if (sector.Rect.X > insideArea.Width - NodeBorderWidth) { sector.Rect.X = insideArea.Width - NodeBorderWidth; } if (sector.Rect.Y > insideArea.Height - NodeBorderWidth) { sector.Rect.Y = insideArea.Height - NodeBorderWidth; } sector.Rect.X += insideArea.X; sector.Rect.Y += insideArea.Y; node.SetArea(sector.Rect); PositionMap[node.ID] = node; node.RoomForLabel = false; // cant do above without graphic artifacts node.LabelClipped = false; if (center) { CenterMap.Add(node.ID); } if (sector.Rect.Width > 1.0f && sector.Rect.Height > 1.0f) { SizeNode(Renderer, node, exclude, center); } } }
private void DrawNode(NodeModel node, RectangleF area, RectangleF labelArea, int depth, bool drawChildren, bool showHit) { if (!node.Show) { return; } var xNode = node.XNode; // set background of node base color Color background = XColors.EmptyColor; // if selcted if (node.Hovered && ViewLayout == LayoutType.TreeMap) { if (depth > XColors.OverColors.Length - 1) { depth = XColors.OverColors.Length - 1; } background = XColors.OverColors[depth]; } else if (ViewLayout != LayoutType.TreeMap && !CenterMap.Contains(node.ID)) { background = XColors.OutsideColor; } // if no overlay, draw the border color as the entire node cause its very small bool noBorder = area.Width < 3.0f || area.Height < 3.0f; if (noBorder) { background = XColors.ObjColors[(int)node.ObjType]; } Color overlay = XColors.EmptyColor; if (showHit) { // check if function is an entry point or holding if (XRay.FlowTracking && xNode.StillInside > 0) { GLUtils.BlendColors((xNode.EntryPoint > 0) ? XColors.EntryColor : XColors.HoldingColor, ref overlay); } // not an else if, draw over holding or entry if (xNode.ExceptionHit > 0) { GLUtils.BlendColors(XColors.ExceptionColors[xNode.ExceptionHit], ref overlay); } else if (xNode.FunctionHit > 0) { if (node.ObjType == XObjType.Field) { if (xNode.LastFieldOp == FieldOp.Set) { GLUtils.BlendColors(XColors.FieldSetColors[xNode.FunctionHit], ref overlay); } else { GLUtils.BlendColors(XColors.FieldGetColors[xNode.FunctionHit], ref overlay); } } else { GLUtils.BlendColors(XColors.HitColors[xNode.FunctionHit], ref overlay); } } else if (xNode.ConstructedHit > 0) { GLUtils.BlendColors(XColors.ConstructedColors[xNode.ConstructedHit], ref overlay); } else if (xNode.DisposeHit > 0) { GLUtils.BlendColors(XColors.DisposedColors[xNode.DisposeHit], ref overlay); } } if (FocusedNodes.Count > 0 && node.ObjType == XObjType.Class) { bool dependent = DependentClasses.Contains(node.ID); bool independent = IndependentClasses.Contains(node.ID); if (dependent && independent) { GLUtils.BlendColors(XColors.InterdependentColor, ref overlay); } else if (dependent) { GLUtils.BlendColors(XColors.DependentColor, ref overlay); } else if (independent) { GLUtils.BlendColors(XColors.IndependentColor, ref overlay); } } if (node.SearchMatch && !SearchStrobe) { GLUtils.BlendColors(XColors.SearchMatchColor, ref overlay); } if (FilteredNodes.Contains(node.ID)) { GLUtils.BlendColors(XColors.FilteredColor, ref overlay); } else if (IgnoredNodes.Contains(node.ID)) { GLUtils.BlendColors(XColors.IgnoredColor, ref overlay); } // mix background with overlay if (overlay != XColors.EmptyColor) { GLUtils.BlendColors(overlay, ref background); } // use a circle for external/outside nodes in the call map bool outside = (ViewLayout == LayoutType.CallGraph && node.XNode.External); // if just a point, drawing a border messes up pixels if (noBorder && !DrawSubpixel) { Renderer.DrawNode(background, area, outside, node, depth); } else { Color pen = XColors.ObjColors[(int)node.ObjType]; if (FilteredNodes.Contains(node.ID)) { pen = XColors.FilteredColor; } else if (IgnoredNodes.Contains(node.ID)) { pen = XColors.IgnoredColor; } int penWidth = 1; if (FocusedNodes.Contains(node)) { penWidth = 2; } Renderer.DrawNode(background, area, outside, node, depth); Renderer.DrawNodeOutline(pen, penWidth, area, outside, node, depth); } // draw label //buffer.FillRectangle(SearchMatchBrush, node.DebugRect); if (ShowLabels && node.RoomForLabel) { Renderer.DrawTextBackground(XColors.LabelBgColor, labelArea.X, labelArea.Y, labelArea.Width, labelArea.Height); Renderer.DrawNodeLabel(node.Name, TextFont, XColors.ObjColors[(int)node.ObjType], labelArea, node, depth); // draw code inside node if (ShowCode && node.AreaF.Width > 50 && node.AreaF.Height > 50) { if (node.ObjType == XObjType.Method) { string code = node.XNode.GetMethodCode(); Renderer.DrawString(code, TextFont, XColors.CodeColor, node.AreaF.X + 5, node.AreaF.Y + labelArea.Height + 5, node.AreaF.Width - 10, node.AreaF.Height - 10 - labelArea.Height); } // draw field values inside node else if (node.ObjType == XObjType.Field) { var summary = ""; foreach (var value in node.GetFieldValues()) { summary += value + "\r\n"; } Renderer.DrawString(summary, TextFont, XColors.CodeColor, node.AreaF.X + 5, node.AreaF.Y + labelArea.Height + 5, node.AreaF.Width - 10, node.AreaF.Height - 10 - labelArea.Height); } } } if (MapMode == TreeMapMode.Dependencies && node.ObjType == XObjType.Class) { drawChildren = false; } if (drawChildren && ((area.Width > 1 && area.Height > 1) || DrawSubpixel)) { foreach (var sub in node.Nodes) { DrawNode(sub, depth + 1, drawChildren); } } // after drawing children, draw instance tracking on top of it all /*if (XRay.InstanceTracking && node.ObjType == XObjType.Class) * { * if (XRay.InstanceCount[node.ID] > 0) * { * string count = XRay.InstanceCount[node.ID].ToString(); * Rectangle x = new Rectangle(node.Area.Location, buffer.MeasureString(count, InstanceFont).ToSize()); * * if (node.Area.Contains(x)) * { * buffer.FillRectangle(NothingBrush, x); * buffer.DrawString(count, InstanceFont, InstanceBrush, node.Area.Location.X + 2, node.Area.Location.Y + 2); * } * } * }*/ }