public void RouteEdges(PositionedGraph posGraph) { Dictionary<PositionedEdge, RoutedEdge> routedEdges = router.RouteEdges(posGraph.Nodes, posGraph.Edges); foreach (var edgePair in routedEdges) { SetEdgeSplinePoints(edgePair.Key, edgePair.Value); } }
// Expanded is passed so that the correct ContentNodes are expanded in the PositionedNode PositionedGraph BuildPositionedGraph(ObjectGraph objectGraph, Expanded expanded) { var positionedNodeFor = new Dictionary <ObjectGraphNode, PositionedNode>(); var positionedGraph = new PositionedGraph(); // create empty PositionedNodes foreach (ObjectGraphNode objectNode in objectGraph.ReachableNodes) { var posNode = new PositionedNode(objectNode, expanded); posNode.MeasureVisualControl(); positionedGraph.AddNode(posNode); positionedNodeFor[objectNode] = posNode; } // create edges foreach (PositionedNode posNode in positionedGraph.Nodes) { foreach (PositionedNodeProperty property in posNode.Properties) { if (property.ObjectGraphProperty.TargetNode != null) { ObjectGraphNode targetObjectNode = property.ObjectGraphProperty.TargetNode; PositionedNode edgeTarget = positionedNodeFor[targetObjectNode]; property.Edge = new PositionedEdge { Name = property.Name, Source = property, Target = edgeTarget }; } } } positionedGraph.Root = positionedNodeFor[objectGraph.Root]; return(positionedGraph); }
// Expanded is passed so that the correct ContentNodes are expanded in the PositionedNode PositionedGraph BuildPositionedGraph(ObjectGraph objectGraph, Expanded expanded) { var positionedNodeFor = new Dictionary<ObjectGraphNode, PositionedNode>(); var positionedGraph = new PositionedGraph(); // create empty PositionedNodes foreach (ObjectGraphNode objectNode in objectGraph.ReachableNodes) { var posNode = new PositionedNode(objectNode, expanded); posNode.MeasureVisualControl(); positionedGraph.AddNode(posNode); positionedNodeFor[objectNode] = posNode; } // create edges foreach (PositionedNode posNode in positionedGraph.Nodes) { foreach (PositionedNodeProperty property in posNode.Properties) { if (property.ObjectGraphProperty.TargetNode != null) { ObjectGraphNode targetObjectNode = property.ObjectGraphProperty.TargetNode; PositionedNode edgeTarget = positionedNodeFor[targetObjectNode]; property.Edge = new PositionedEdge { Name = property.Name, Source = property, Target = edgeTarget }; } } } positionedGraph.Root = positionedNodeFor[objectGraph.Root]; return positionedGraph; }
private PositionedGraph buildTreeGraph(ObjectGraph objectGraph, Expanded expanded) { var resultGraph = new PositionedGraph(); // create empty PosNodes foreach (ObjectGraphNode objectGraphNode in objectGraph.ReachableNodes) { TreeGraphNode posNode = createNewTreeGraphNode(objectGraphNode); resultGraph.AddNode(posNode); treeNodeFor[objectGraphNode] = posNode; posNode.InitContentFromObjectNode(expanded); } // create edges foreach (PositionedGraphNode posNode in resultGraph.Nodes) { // create edges outgoing from this posNode foreach (PositionedNodeProperty property in posNode.Properties) { //property.IsPropertyExpanded = expanded.Expressions.IsExpanded(property.Expression); if (property.ObjectGraphProperty.TargetNode != null) { ObjectGraphNode targetObjectNode = property.ObjectGraphProperty.TargetNode; PositionedGraphNode edgeTarget = treeNodeFor[targetObjectNode]; property.Edge = new TreeGraphEdge { IsTreeEdge = false, Name = property.Name, Source = property, Target = edgeTarget }; } } } resultGraph.Root = treeNodeFor[objectGraph.Root]; return resultGraph; }
Dictionary<int, PositionedNode> BuildHashToNodeMap(PositionedGraph graph) { var hashToNodeMap = new Dictionary<int, PositionedNode>(); foreach (PositionedNode node in graph.Nodes) { hashToNodeMap[node.ObjectNode.HashCode] = node; } return hashToNodeMap; }
/// <summary> /// Calculates diff between 2 <see cref="PositionedGraph"/>s. /// The <see cref="GraphDiff"/> describes a matching between nodes in the graphs, added and removed nodes. /// </summary> public GraphDiff MatchGraphs(PositionedGraph oldGraph, PositionedGraph newGraph) { if (oldGraph == null) { if (newGraph == null) { return(new GraphDiff()); } else { GraphDiff addAllDiff = new GraphDiff(); foreach (PositionedNode newNode in newGraph.Nodes) { addAllDiff.SetAdded(newNode); } return(addAllDiff); } } else if (newGraph == null) { GraphDiff removeAllDiff = new GraphDiff(); foreach (PositionedNode oldNode in oldGraph.Nodes) { removeAllDiff.SetRemoved(oldNode); } return(removeAllDiff); } // none of the graphs is null GraphDiff diff = new GraphDiff(); Dictionary <int, PositionedNode> newNodeForHashCode = BuildHashToNodeMap(newGraph); Dictionary <PositionedNode, bool> newNodeMatched = new Dictionary <PositionedNode, bool>(); foreach (PositionedNode oldNode in oldGraph.Nodes) { PositionedNode matchingNode = MatchNode(oldNode, newNodeForHashCode); if (matchingNode != null) { diff.SetMatching(oldNode, matchingNode); newNodeMatched[matchingNode] = true; } else { diff.SetRemoved(oldNode); } } foreach (PositionedNode newNode in newGraph.Nodes) { if (!newNodeMatched.ContainsKey(newNode)) { diff.SetAdded(newNode); } } return(diff); }
public void RouteEdges(PositionedGraph posGraph) { Dictionary <PositionedEdge, RoutedEdge> routedEdges = router.RouteEdges(posGraph.Nodes, posGraph.Edges); foreach (var edgePair in routedEdges) { SetEdgeSplinePoints(edgePair.Key, edgePair.Value); } }
void CalculateLayout(PositionedGraph positionedGraph) { // impose a tree structure on the graph HashSet <PositionedEdge> treeEdges = DetermineTreeEdges(positionedGraph.Root); // first layout pass CalculateSubtreeSizesRecursive(positionedGraph.Root, treeEdges); // second layout pass CalculateNodePosRecursive(positionedGraph.Root, treeEdges, MarginTop, MarginBottom); }
Dictionary <int, PositionedNode> BuildHashToNodeMap(PositionedGraph graph) { var hashToNodeMap = new Dictionary <int, PositionedNode>(); foreach (PositionedNode node in graph.Nodes) { hashToNodeMap[node.ObjectNode.HashCode] = node; } return(hashToNodeMap); }
public PositionedGraph RouteEdges(PositionedGraph posGraph) { List<RoutedEdge> routedEdges = router.RouteEdges(posGraph.Nodes, posGraph.Edges); int i = 0; // assume routedEdges come in the same order as posGraph.Edges foreach (var edge in posGraph.Edges) { SetEdgeSplinePoints(edge, routedEdges[i]); i++; } return posGraph; }
public GraphDiff MatchGraphs(PositionedGraph oldGraph, PositionedGraph newGraph) { if (oldGraph == null) { if (newGraph == null) { return new GraphDiff(); } else { GraphDiff addAllDiff = new GraphDiff(); foreach (PositionedGraphNode newNode in newGraph.Nodes) addAllDiff.SetAdded(newNode); return addAllDiff; } } else if (newGraph == null) { GraphDiff removeAllDiff = new GraphDiff(); foreach (PositionedGraphNode oldNode in oldGraph.Nodes) removeAllDiff.SetRemoved(oldNode); return removeAllDiff; } // none of the graphs is null GraphDiff diff = new GraphDiff(); Dictionary<int, PositionedGraphNode> newNodeForHashCode = buildHashToNodeMap(newGraph); Dictionary<PositionedGraphNode, bool> newNodeMatched = new Dictionary<PositionedGraphNode, bool>(); foreach (PositionedGraphNode oldNode in oldGraph.Nodes) { PositionedGraphNode matchingNode = matchNode(oldNode, newNodeForHashCode); if (matchingNode != null) { diff.SetMatching(oldNode, matchingNode); newNodeMatched[matchingNode] = true; } else { diff.SetRemoved(oldNode); } } foreach (PositionedGraphNode newNode in newGraph.Nodes) { if (!newNodeMatched.ContainsKey(newNode)) { diff.SetAdded(newNode); } } return diff; }
public PositionedGraph RouteEdges(PositionedGraph posGraph) { List <RoutedEdge> routedEdges = router.RouteEdges(posGraph.Nodes, posGraph.Edges); int i = 0; // assume routedEdges come in the same order as posGraph.Edges foreach (var edge in posGraph.Edges) { SetEdgeSplinePoints(edge, routedEdges[i]); i++; } return(posGraph); }
private PositionedGraph buildTreeGraph(ObjectGraph objectGraph, Expanded expanded) { var resultGraph = new PositionedGraph(); // create empty PosNodes foreach (ObjectGraphNode objectGraphNode in objectGraph.ReachableNodes) { TreeGraphNode posNode = createNewTreeGraphNode(objectGraphNode); resultGraph.AddNode(posNode); treeNodeFor[objectGraphNode] = posNode; posNode.InitContentFromObjectNode(expanded); } // create edges foreach (PositionedGraphNode posNode in resultGraph.Nodes) { // create edges outgoing from this posNode foreach (PositionedNodeProperty property in posNode.Properties) { //property.IsPropertyExpanded = expanded.Expressions.IsExpanded(property.Expression); if (property.ObjectGraphProperty.TargetNode != null) { ObjectGraphNode targetObjectNode = property.ObjectGraphProperty.TargetNode; PositionedGraphNode edgeTarget = treeNodeFor[targetObjectNode]; property.Edge = new TreeGraphEdge { IsTreeEdge = false, Name = property.Name, Source = property, Target = edgeTarget }; } } } resultGraph.Root = treeNodeFor[objectGraph.Root]; return(resultGraph); }
void LayoutGraph(ObjectGraph graph) { this.oldPosGraph = this.currentPosGraph; Log.Debug("Debugger visualizer: Calculating graph layout"); var layoutDirection = layoutViewModel.SelectedEnumValue; this.currentPosGraph = new TreeLayout(layoutDirection).CalculateLayout(graph, expanded); Log.Debug("Debugger visualizer: Graph layout done"); RegisterExpandCollapseEvents(this.currentPosGraph); var graphDiff = new GraphMatcher().MatchGraphs(oldPosGraph, currentPosGraph); Log.Debug("Debugger visualizer: starting graph animation"); this.graphDrawer.StartAnimation(oldPosGraph, currentPosGraph, graphDiff); }
/// <summary> /// Starts animation from oldGraph to newGraph. /// </summary> /// <param name="oldGraph"></param> /// <param name="newGraph"></param> /// <param name="diff"></param> public void StartAnimation(PositionedGraph oldGraph, PositionedGraph newGraph, GraphDiff diff) { // account for that the visual controls could have been reused (we are not reusing controls now - NodeControlCache does nothing) this.canvas.Width = newGraph.BoundingRect.Width; this.canvas.Height = newGraph.BoundingRect.Height; if (oldGraph == null) { Draw(newGraph); return; } var durationMove = new Duration(TimeSpan.FromSeconds(animationDurationSeconds)); var durationFade = durationMove; DoubleAnimation fadeOutAnim = new DoubleAnimation(1.0, 0.0, durationFade); DoubleAnimation fadeInAnim = new DoubleAnimation(0.0, 1.0, durationFade); foreach (UIElement drawing in canvas.Children) { var arrow = drawing as Path; if (arrow != null) { arrow.BeginAnimation(UIElement.OpacityProperty, fadeOutAnim); } } foreach (PositionedEdge edge in newGraph.Edges) { AddEdgeToCanvas(edge).BeginAnimation(UIElement.OpacityProperty, fadeInAnim); } foreach (PositionedNode removedNode in diff.RemovedNodes) { removedNode.NodeVisualControl.BeginAnimation(UIElement.OpacityProperty, fadeOutAnim); } foreach (PositionedNode addedNode in diff.AddedNodes) { AddNodeToCanvas(addedNode).BeginAnimation(UIElement.OpacityProperty, fadeInAnim); } bool first = true; foreach (PositionedNode node in diff.ChangedNodes) { var newNode = diff.GetMatchingNewNode(node); PointAnimation anim = new PointAnimation(); if (first) { anim.Completed += (o, e) => { Draw(newGraph); if (oldGraph != null) { foreach (var oldNode in oldGraph.Nodes) { oldNode.ReleaseNodeVisualControl(); } } }; first = false; } anim.From = node.LeftTop; anim.To = newNode.LeftTop; anim.DecelerationRatio = 0.3; anim.AccelerationRatio = 0.3; anim.Duration = durationMove; node.NodeVisualControl.BeginAnimation(CanvasLocationAdapter.LocationProperty, anim); } }
/// <summary> /// Draws <see cref="PositionedGraph"></see> on Canvas. /// </summary> /// <param name="posGraph">Graph to draw.</param> /// <param name="canvas">Destination Canvas.</param> public void Draw(PositionedGraph posGraph) { canvas.Children.Clear(); // draw nodes foreach (PositionedNode node in posGraph.Nodes) { AddNodeToCanvas(node); } // draw edges foreach (PositionedEdge edge in posGraph.Edges) { AddEdgeToCanvas(edge); } edgeTooltip.Visibility = Visibility.Hidden; edgeTooltip.Background = Brushes.White; canvas.Children.Add(edgeTooltip); }
void CalculateLayout(PositionedGraph positionedGraph) { // impose a tree structure on the graph HashSet<PositionedEdge> treeEdges = DetermineTreeEdges(positionedGraph.Root); // first layout pass CalculateSubtreeSizesRecursive(positionedGraph.Root, treeEdges); // second layout pass CalculateNodePosRecursive(positionedGraph.Root, treeEdges, MarginTop, MarginBottom); }
void LayoutGraph(ObjectGraph graph) { if (this.oldPosGraph != null) { foreach (var oldNode in this.oldPosGraph.Nodes) { // controls from old graph would be garbage collected, reuse them NodeControlCache.Instance.ReturnForReuse(oldNode.NodeVisualControl); } } this.oldPosGraph = this.currentPosGraph; Log.Debug("Debugger visualizer: Calculating graph layout"); var layoutDirection = layoutViewModel.SelectedEnumValue; this.currentPosGraph = new TreeLayout(layoutDirection).CalculateLayout(graph, expanded); Log.Debug("Debugger visualizer: Graph layout done"); RegisterExpandCollapseEvents(this.currentPosGraph); var graphDiff = new GraphMatcher().MatchGraphs(oldPosGraph, currentPosGraph); Log.Debug("Debugger visualizer: starting graph animation"); this.graphDrawer.StartAnimation(oldPosGraph, currentPosGraph, graphDiff); }
/// <summary> /// Starts animation from oldGraph to newGraph. /// </summary> /// <param name="oldGraph"></param> /// <param name="newGraph"></param> /// <param name="diff"></param> public void StartAnimation(PositionedGraph oldGraph, PositionedGraph newGraph, GraphDiff diff) { if (oldGraph != null) { foreach (var oldNode in oldGraph.Nodes) { foreach (var newNode in newGraph.Nodes) { if (oldNode.NodeVisualControl == newNode.NodeVisualControl) { ClearCanvas(); } } } } this.canvas.Width = newGraph.BoundingRect.Width; this.canvas.Height = newGraph.BoundingRect.Height; if (oldGraph == null) { Draw(newGraph); return; } double seconds = 0.5; var durationMove = new Duration(TimeSpan.FromSeconds(seconds)); var durationFade = durationMove; DoubleAnimation fadeOutAnim = new DoubleAnimation(1.0, 0.0, durationFade); DoubleAnimation fadeInAnim = new DoubleAnimation(0.0, 1.0, durationFade); foreach (UIElement drawing in canvas.Children) { var arrow = drawing as Path; if (arrow != null) { arrow.BeginAnimation(UIElement.OpacityProperty, fadeOutAnim); } } foreach (PositionedEdge edge in newGraph.Edges) { addEdgeToCanvas(edge).BeginAnimation(UIElement.OpacityProperty, fadeInAnim); } foreach (PositionedGraphNode removedNode in diff.RemovedNodes) { removedNode.NodeVisualControl.BeginAnimation(UIElement.OpacityProperty, fadeOutAnim); } foreach (PositionedGraphNode addedNode in diff.AddedNodes) { addNodeToCanvas(addedNode).BeginAnimation(UIElement.OpacityProperty, fadeInAnim); } bool first = true; foreach (PositionedGraphNode node in diff.ChangedNodes) { var newNode = diff.GetMatchingNewNode(node); PointAnimation anim = new PointAnimation(); if (first) { anim.Completed += new EventHandler((o, e) => { Draw(newGraph); }); first = false; } anim.From = node.LeftTop; anim.To = newNode.LeftTop; anim.DecelerationRatio = 0.3; anim.AccelerationRatio = 0.3; anim.Duration = durationMove; node.NodeVisualControl.BeginAnimation(CanvasLocationAdapter.LocationProperty, anim); } }
/// <summary> /// Draws <see cref="PositionedGraph"></see> on Canvas. /// </summary> /// <param name="posGraph">Graph to draw.</param> /// <param name="canvas">Destination Canvas.</param> public void Draw(PositionedGraph posGraph) { canvas.Children.Clear(); /*try { // why do the controls disappear? var n1 = posGraph.Nodes.First().NodeVisualControl; var n2 = posGraph.Nodes.Skip(1).First().NodeVisualControl; var n3 = posGraph.Nodes.Skip(2).First().NodeVisualControl; if (n1 == n2 || n1 == n3 || n2 == n3) { ClearCanvas(); } } catch{}*/ // draw nodes foreach (PositionedGraphNode node in posGraph.Nodes) { addNodeToCanvas(node); } // draw edges foreach (PositionedEdge edge in posGraph.Edges) { addEdgeToCanvas(edge); } edgeTooltip.Visibility = Visibility.Hidden; edgeTooltip.Background = Brushes.White; canvas.Children.Add(edgeTooltip); }
void layoutGraph(ObjectGraph graph) { if (this.oldPosGraph != null) { foreach (var oldNode in this.oldPosGraph.Nodes) { // controls from old graph would be garbage collected, reuse them NodeControlCache.Instance.ReturnForReuse(oldNode.NodeVisualControl); } } this.oldPosGraph = this.currentPosGraph; ICSharpCode.Core.LoggingService.Debug("Debugger visualizer: Calculating graph layout"); this.currentPosGraph = this.layouter.CalculateLayout(graph, layoutViewModel.SelectedEnumValue, this.expanded); ICSharpCode.Core.LoggingService.Debug("Debugger visualizer: Graph layout done"); registerExpandCollapseEvents(this.currentPosGraph); var graphDiff = new GraphMatcher().MatchGraphs(oldPosGraph, currentPosGraph); ICSharpCode.Core.LoggingService.Debug("Debugger visualizer: starting graph animation"); this.graphDrawer.StartAnimation(oldPosGraph, currentPosGraph, graphDiff); //this.graphDrawer.Draw(this.currentPosGraph); // buggy layout with NodeControlCache }
void RegisterExpandCollapseEvents(PositionedGraph posGraph) { foreach (var node in posGraph.Nodes) { node.PropertyExpanded += new EventHandler<PositionedPropertyEventArgs>(node_PropertyExpanded); node.PropertyCollapsed += new EventHandler<PositionedPropertyEventArgs>(node_PropertyCollapsed); node.ContentNodeExpanded += new EventHandler<ContentNodeEventArgs>(node_ContentNodeExpanded); node.ContentNodeCollapsed += new EventHandler<ContentNodeEventArgs>(node_ContentNodeCollapsed); } }