/// <summary>
        /// This method pushes changes from the GraphLayout.Graph objects
        /// back to the workspace models, but only for nodes placed by NodeAutocomplete.
        /// </summary>
        private static void SaveLayoutGraphForNodeAutoComplete(this WorkspaceModel workspace, List <GraphLayout.Graph> layoutSubgraphs, Guid?originalNodeGUID)
        {
            // Assign coordinates to nodes outside groups
            foreach (var node in workspace.Nodes)
            {
                GraphLayout.Graph graph = layoutSubgraphs
                                          .FirstOrDefault(g => g.FindNode(node.GUID) != null);

                if (graph != null)
                {
                    GraphLayout.Node n       = graph.FindNode(node.GUID);
                    double           offsetY = graph.OffsetY;
                    //skipping the original node to avoid jumping of node
                    if (node.GUID != originalNodeGUID)
                    {
                        node.X = n.X;
                        node.Y = n.Y + n.NotesHeight + offsetY;
                    }
                    node.ReportPosition();
                    workspace.HasUnsavedChanges = true;

                    double noteOffset = -n.NotesHeight;
                    foreach (NoteModel note in n.LinkedNotes)
                    {
                        if (note.IsSelected || DynamoSelection.Instance.Selection.Count == 0)
                        {
                            note.X      = node.X;
                            note.Y      = node.Y + noteOffset;
                            noteOffset += note.Height + GraphLayout.Graph.VerticalNoteDistance;
                            note.ReportPosition();
                        }
                    }
                }
            }
        }
        /// <summary>
        /// <param name="workspace">A <see cref="WorkspaceModel"/>.</param>
        /// This method extracts all models from the workspace and puts them
        /// into the combined graph object, LayoutSubgraphs.First()
        /// <param name="isGroupLayout">True if all the selected models are groups.</param>
        /// <param name="layoutSubgraphs"></param>
        /// <param name="subgraphClusters"></param>
        /// </summary>
        private static void GenerateCombinedGraph(this WorkspaceModel workspace, bool isGroupLayout,
                                                  out List <GraphLayout.Graph> layoutSubgraphs, out List <List <GraphLayout.Node> > subgraphClusters)
        {
            layoutSubgraphs = new List <GraphLayout.Graph>
            {
                new GraphLayout.Graph()
            };
            var combinedGraph = layoutSubgraphs.First();

            subgraphClusters = new List <List <GraphLayout.Node> >();

            if (!isGroupLayout)
            {
                foreach (AnnotationModel group in workspace.Annotations)
                {
                    // Treat a group as a graph layout node/vertex
                    combinedGraph.AddNode(group.GUID, group.Width, group.Height, group.X, group.Y,
                                          group.IsSelected || DynamoSelection.Instance.Selection.Count == 0);
                }
            }

            foreach (NodeModel node in workspace.Nodes)
            {
                if (!isGroupLayout)
                {
                    AnnotationModel group = workspace.Annotations.Where(
                        g => g.Nodes.Contains(node)).ToList().FirstOrDefault();

                    // Do not process nodes within groups
                    if (group == null)
                    {
                        combinedGraph.AddNode(node.GUID, node.Width, node.Height, node.X, node.Y,
                                              node.IsSelected || DynamoSelection.Instance.Selection.Count == 0);
                    }
                }
                else
                {
                    // Process all nodes inside the selection
                    combinedGraph.AddNode(node.GUID, node.Width, node.Height, node.X, node.Y,
                                          node.IsSelected || DynamoSelection.Instance.Selection.Count == 0);
                }
            }

            foreach (ConnectorModel edge in workspace.Connectors)
            {
                if (!isGroupLayout)
                {
                    AnnotationModel startGroup = null, endGroup = null;
                    startGroup = workspace.Annotations.Where(
                        g => g.Nodes.Contains(edge.Start.Owner)).ToList().FirstOrDefault();
                    endGroup = workspace.Annotations.Where(
                        g => g.Nodes.Contains(edge.End.Owner)).ToList().FirstOrDefault();

                    // Treat a group as a node, but do not process edges within a group
                    if (startGroup == null || endGroup == null || startGroup != endGroup)
                    {
                        combinedGraph.AddEdge(
                            startGroup == null ? edge.Start.Owner.GUID : startGroup.GUID,
                            endGroup == null ? edge.End.Owner.GUID : endGroup.GUID,
                            edge.Start.Center.X, edge.Start.Center.Y, edge.End.Center.X, edge.End.Center.Y);
                    }
                }
                else
                {
                    // Edges within a group are also processed
                    combinedGraph.AddEdge(edge.Start.Owner.GUID, edge.End.Owner.GUID,
                                          edge.Start.Center.X, edge.Start.Center.Y, edge.End.Center.X, edge.End.Center.Y);
                }
            }

            foreach (NoteModel note in workspace.Notes)
            {
                AnnotationModel group = workspace.Annotations.Where(
                    g => g.Nodes.Contains(note)).ToList().FirstOrDefault();

                GraphLayout.Node nd = null;

                if (!isGroupLayout || group == null)
                {
                    // If note is not part of a group, link to the nearest node in the graph
                    nd = combinedGraph.Nodes.OrderBy(node =>
                                                     Math.Pow(node.X + node.Width / 2 - note.X - note.Width / 2, 2) +
                                                     Math.Pow(node.Y + node.Height / 2 - note.Y - note.Height / 2, 2)).FirstOrDefault();
                }
                else
                {
                    // If note is part of a group, link to the nearest node in the group
                    NodeModel ndm = group.Nodes.OfType <NodeModel>().OrderBy(node =>
                                                                             Math.Pow(node.X + node.Width / 2 - note.X - note.Width / 2, 2) +
                                                                             Math.Pow(node.Y + node.Height / 2 - note.Y - note.Height / 2, 2)).FirstOrDefault();

                    // Skip processing the group if there is no node in the group
                    if (ndm == null)
                    {
                        continue;
                    }

                    // If the nearest point is a node model
                    nd = combinedGraph.FindNode(ndm.GUID);

                    // If the nearest point is a group model
                    nd = nd ?? combinedGraph.FindNode(group.GUID);
                }

                // Otherwise, leave the note unchanged
                if (nd != null)
                {
                    nd.LinkNote(note, note.Width, note.Height);
                }
            }

            if (!isGroupLayout)
            {
                // Add all nodes to one big cluster
                List <GraphLayout.Node> bigcluster = new List <GraphLayout.Node>();
                bigcluster.AddRange(combinedGraph.Nodes);
                subgraphClusters.Add(bigcluster);
            }
            else
            {
                // Each group becomes one cluster
                foreach (AnnotationModel group in DynamoSelection.Instance.Selection.OfType <AnnotationModel>())
                {
                    List <GraphLayout.Node> cluster = new List <GraphLayout.Node>();
                    cluster.AddRange(group.Nodes.OfType <NodeModel>().Select(x => combinedGraph.FindNode(x.GUID)));
                    subgraphClusters.Add(cluster);
                }
            }
        }
        /// <summary>
        /// This method pushes changes from the GraphLayout.Graph objects
        /// back to the workspace models.
        /// </summary>
        private static void SaveLayoutGraph(this WorkspaceModel workspace, List <GraphLayout.Graph> layoutSubgraphs)
        {
            // Assign coordinates to nodes inside groups
            foreach (var group in workspace.Annotations)
            {
                GraphLayout.Graph graph = layoutSubgraphs
                                          .FirstOrDefault(g => g.FindNode(group.GUID) != null);

                if (graph != null)
                {
                    GraphLayout.Node n = graph.FindNode(group.GUID);

                    double deltaX = n.X - group.X;
                    double deltaY = n.Y - group.Y + graph.OffsetY;
                    foreach (var node in group.Nodes.OfType <NodeModel>())
                    {
                        node.X += deltaX;
                        node.Y += deltaY;
                        node.ReportPosition();
                    }

                    foreach (NoteModel note in n.LinkedNotes)
                    {
                        if (note.IsSelected || DynamoSelection.Instance.Selection.Count == 0)
                        {
                            note.X += deltaX;
                            note.Y += deltaY;
                            note.ReportPosition();
                        }
                    }
                }
            }

            // Assign coordinates to nodes outside groups
            foreach (var node in workspace.Nodes)
            {
                GraphLayout.Graph graph = layoutSubgraphs
                                          .FirstOrDefault(g => g.FindNode(node.GUID) != null);

                if (graph != null)
                {
                    GraphLayout.Node n       = graph.FindNode(node.GUID);
                    double           offsetY = graph.OffsetY;

                    node.X = n.X;
                    node.Y = n.Y + n.NotesHeight + offsetY;
                    node.ReportPosition();
                    workspace.HasUnsavedChanges = true;

                    double noteOffset = -n.NotesHeight;
                    foreach (NoteModel note in n.LinkedNotes)
                    {
                        if (note.IsSelected || DynamoSelection.Instance.Selection.Count == 0)
                        {
                            note.X      = node.X;
                            note.Y      = node.Y + noteOffset;
                            noteOffset += note.Height + GraphLayout.Graph.VerticalNoteDistance;
                            note.ReportPosition();
                        }
                    }
                }
            }
        }
Exemple #4
0
        /// <summary>
        /// <param name="workspace">A <see cref="WorkspaceModel"/>.</param>
        /// This method extracts all models from the workspace and puts them
        /// into the combined graph object, LayoutSubgraphs.First()
        /// <param name="isGroupLayout">True if all the selected models are groups.</param>
        /// <param name="layoutSubgraphs"></param>
        /// <param name="subgraphClusters"></param>
        /// </summary>
        private static void GenerateCombinedGraph(this WorkspaceModel workspace, bool isGroupLayout,
                                                  out List <GraphLayout.Graph> layoutSubgraphs, out List <List <GraphLayout.Node> > subgraphClusters)
        {
            layoutSubgraphs = new List <GraphLayout.Graph>
            {
                new GraphLayout.Graph()
            };
            var combinedGraph = layoutSubgraphs.First();

            subgraphClusters = new List <List <GraphLayout.Node> >();

            if (!isGroupLayout)
            {
                foreach (AnnotationModel group in workspace.Annotations)
                {
                    // Treat a group as a graph layout node/vertex
                    combinedGraph.AddNode(group.GUID, group.Width, group.Height, group.X, group.Y,
                                          group.IsSelected || DynamoSelection.Instance.Selection.Count == 0);
                }
            }

            foreach (NodeModel node in workspace.Nodes)
            {
                if (!isGroupLayout)
                {
                    AnnotationModel group = workspace.Annotations.Where(
                        g => g.Nodes.Contains(node)).ToList().FirstOrDefault();

                    // Do not process nodes within groups
                    if (group == null)
                    {
                        combinedGraph.AddNode(node.GUID, node.Width, node.Height, node.X, node.Y,
                                              node.IsSelected || DynamoSelection.Instance.Selection.Count == 0);
                    }
                }
                else
                {
                    // Process all nodes inside the selection
                    combinedGraph.AddNode(node.GUID, node.Width, node.Height, node.X, node.Y,
                                          node.IsSelected || DynamoSelection.Instance.Selection.Count == 0);
                }
            }

            ///Adding all connectorPins (belonging to all connectors) as graph.nodes to the combined graph.
            foreach (ConnectorModel edge in workspace.Connectors)
            {
                foreach (var pin in edge.ConnectorPinModels)
                {
                    combinedGraph.AddNode(pin.GUID,
                                          pin.Width,
                                          pin.Height,
                                          pin.CenterX,
                                          pin.CenterY,
                                          pin.IsSelected || DynamoSelection.Instance.Selection.Count == 0);
                }
            }

            foreach (ConnectorModel edge in workspace.Connectors)
            {
                if (!isGroupLayout)
                {
                    AnnotationModel startGroup = null, endGroup = null;
                    startGroup = workspace.Annotations.Where(
                        g => g.Nodes.Contains(edge.Start.Owner)).ToList().FirstOrDefault();
                    endGroup = workspace.Annotations.Where(
                        g => g.Nodes.Contains(edge.End.Owner)).ToList().FirstOrDefault();

                    // Treat a group as a node, but do not process edges within a group
                    if (startGroup == null || endGroup == null || startGroup != endGroup)
                    {
                        var startGuid = startGroup == null ? edge.Start.Owner.GUID : startGroup.GUID;
                        var endGuid   = endGroup == null ? edge.End.Owner.GUID : endGroup.GUID;

                        AddConnectorEdgesIncludingPinEdges(combinedGraph, edge, startGuid, endGuid);
                    }
                }
                else
                {
                    AddConnectorEdgesIncludingPinEdges(combinedGraph, edge);
                }
            }

            var sortedNotes = workspace.Notes.OrderBy(x => x.PinnedNode is null);

            foreach (NoteModel note in sortedNotes)
            {
                // If the note is pinned to a node we dont want to
                // modify its posistion as it is tied to the node.
                if (note.PinnedNode != null)
                {
                    // We add this note to the LinkedNotes on the
                    // pinned node.
                    var graphNode = combinedGraph.FindNode(note.PinnedNode.GUID);
                    var height    = note.PinnedNode.Rect.Top - note.Rect.Top;
                    graphNode.LinkNote(note, note.Width, height);
                    continue;
                }

                AnnotationModel group = workspace.Annotations.Where(
                    g => g.Nodes.Contains(note)).ToList().FirstOrDefault();

                GraphLayout.Node nd = null;

                if (!isGroupLayout || group == null)
                {
                    // If note is not part of a group, link to the nearest node in the graph
                    nd = combinedGraph.Nodes.OrderBy(node =>
                                                     Math.Pow(node.X + node.Width / 2 - note.X - note.Width / 2, 2) +
                                                     Math.Pow(node.Y + node.Height / 2 - note.Y - note.Height / 2, 2)).FirstOrDefault();
                }
                else
                {
                    // If note is part of a group, link to the nearest node in the group
                    NodeModel ndm = group.Nodes.OfType <NodeModel>().OrderBy(node =>
                                                                             Math.Pow(node.X + node.Width / 2 - note.X - note.Width / 2, 2) +
                                                                             Math.Pow(node.Y + node.Height / 2 - note.Y - note.Height / 2, 2)).FirstOrDefault();

                    // Skip processing the group if there is no node in the group
                    if (ndm == null)
                    {
                        continue;
                    }

                    // If the nearest point is a node model
                    nd = combinedGraph.FindNode(ndm.GUID);

                    // If the nearest point is a group model
                    nd = nd ?? combinedGraph.FindNode(group.GUID);
                }

                // Otherwise, leave the note unchanged
                if (nd != null)
                {
                    nd.LinkNote(note, note.Width, note.Height);
                }
            }

            if (!isGroupLayout)
            {
                // Add all nodes to one big cluster
                List <GraphLayout.Node> bigcluster = new List <GraphLayout.Node>();
                bigcluster.AddRange(combinedGraph.Nodes);
                subgraphClusters.Add(bigcluster);
            }
            else
            {
                // Each group becomes one cluster
                foreach (AnnotationModel group in DynamoSelection.Instance.Selection.OfType <AnnotationModel>())
                {
                    List <GraphLayout.Node> cluster = new List <GraphLayout.Node>();
                    cluster.AddRange(group.Nodes.OfType <NodeModel>().Select(x => combinedGraph.FindNode(x.GUID)));
                    subgraphClusters.Add(cluster);
                }
            }
        }
Exemple #5
0
        /// <summary>
        /// This method pushes changes from the GraphLayout.Graph objects
        /// back to the workspace models.
        /// </summary>
        private static void SaveLayoutGraph(this WorkspaceModel workspace, List <GraphLayout.Graph> layoutSubgraphs)
        {
            // Assign coordinates to nodes inside groups
            foreach (var group in workspace.Annotations)
            {
                GraphLayout.Graph graph = layoutSubgraphs
                                          .FirstOrDefault(g => g.FindNode(group.GUID) != null);

                if (graph != null)
                {
                    GraphLayout.Node n = graph.FindNode(group.GUID);

                    double deltaX = n.X - group.X;
                    double deltaY = n.Y - group.Y + graph.OffsetY;

                    // We update the posistion of all nodes in the
                    // parent group + all nodes in any potential
                    // nested groups.
                    foreach (var node in group.Nodes
                             .OfType <NodeModel>()
                             .Union(group.Nodes.OfType <AnnotationModel>().SelectMany(x => x.Nodes.OfType <NodeModel>())))
                    {
                        node.X += deltaX;
                        node.Y += deltaY;
                        node.ReportPosition();
                    }

                    foreach (NoteModel note in n.LinkedNotes)
                    {
                        if (note.PinnedNode != null)
                        {
                            continue;
                        }
                        if (note.IsSelected || DynamoSelection.Instance.Selection.Count == 0)
                        {
                            note.X += deltaX;
                            note.Y += deltaY;
                            note.ReportPosition();
                        }
                    }

                    group.ReportPosition();
                }
            }

            // Assign coordinates to nodes outside groups
            foreach (var node in workspace.Nodes)
            {
                GraphLayout.Graph graph = layoutSubgraphs
                                          .FirstOrDefault(g => g.FindNode(node.GUID) != null);

                if (graph != null)
                {
                    GraphLayout.Node n       = graph.FindNode(node.GUID);
                    double           offsetY = graph.OffsetY;

                    node.X = n.X;
                    node.Y = n.Y + n.NotesHeight + offsetY;
                    node.ReportPosition();
                    workspace.HasUnsavedChanges = true;

                    double noteOffset = -n.NotesHeight;
                    foreach (NoteModel note in n.LinkedNotes)
                    {
                        if (note.PinnedNode != null)
                        {
                            continue;
                        }
                        if (note.IsSelected || DynamoSelection.Instance.Selection.Count == 0)
                        {
                            note.X      = node.X;
                            note.Y      = node.Y + noteOffset;
                            noteOffset += note.Height + GraphLayout.Graph.VerticalNoteDistance;
                            note.ReportPosition();
                        }
                    }
                }
            }
            // Assign coordinates to connectors outside of groups
            foreach (var connector in workspace.Connectors)
            {
                foreach (var pin in connector.ConnectorPinModels)
                {
                    GraphLayout.Graph graph = layoutSubgraphs
                                              .FirstOrDefault(g => g.FindNode(pin.GUID) != null);

                    if (graph != null)
                    {
                        GraphLayout.Node n = graph.FindNode(pin.GUID);

                        pin.CenterX = n.X;
                        pin.CenterY = n.Y;
                        pin.ReportPosition();
                        workspace.HasUnsavedChanges = true;
                    }
                }
            }
        }