Represents base class for all kind of workspaces which contains general data such as Name, collections of nodes, notes, annotations, etc.
Inheritance: Dynamo.Core.NotificationObject, ILocatable, IUndoRedoRecorderClient, ILogSource, IDisposable, IWorkspaceModel
Example #1
0
        /// <summary>
        /// This method is called by code that intends to start a graph update.
        /// This method is called on the main thread where node collection in a 
        /// WorkspaceModel can be safely accessed.
        /// </summary>
        /// <param name="controller">Reference to an instance of EngineController 
        /// to assist in generating GraphSyncData object for the given set of nodes.
        /// </param>
        /// <param name="workspace">Reference to the WorkspaceModel from which a 
        /// set of updated nodes is computed. The EngineController generates the 
        /// resulting GraphSyncData from this list of updated nodes.</param>
        /// <returns>Returns true if there is any GraphSyncData, or false otherwise
        /// (in which case there will be no need to schedule UpdateGraphAsyncTask 
        /// for execution).</returns>
        /// 
        internal bool Initialize(EngineController controller, WorkspaceModel workspace)
        {
            try
            {
                engineController = controller;
                TargetedWorkspace = workspace;

                ModifiedNodes = ComputeModifiedNodes(workspace);
                graphSyncData = engineController.ComputeSyncData(workspace.Nodes, ModifiedNodes, verboseLogging);
                if (graphSyncData == null)
                    return false;

                // We clear dirty flags before executing the task. If we clear
                // flags after the execution of task, for example in
                // AsyncTask.Completed or in HandleTaskCompletionCore(), as both
                // are executed in the other thread, although some nodes are
                // modified and we request graph execution, but just before
                // computing sync data, the task completion handler jumps in
                // and clear dirty flags. Now graph sync data will be null and
                // graph is in wrong state.
                foreach (var nodeGuid in graphSyncData.NodeIDs)
                {
                    var node = workspace.Nodes.FirstOrDefault(n => n.GUID.Equals(nodeGuid));
                    if (node != null)
                        node.ClearDirtyFlag();
                }

                return true;
            }
            catch (Exception e)
            {
                System.Diagnostics.Debug.WriteLine("UpgradeGraphAsyncTask saw: " + e.ToString());
                return false;
            }
        }
 /// <summary>
 /// This method is called by codes that intent to start a graph update.
 /// This method is called on the main thread where node collection in a 
 /// WorkspaceModel can be safely accessed.
 /// </summary>
 /// <param name="controller">Reference to an instance of EngineController 
 /// to assist in generating GraphSyncData object for the given set of nodes.
 /// </param>
 /// <param name="workspace">Reference to the WorkspaceModel from which a 
 /// set of updated nodes is computed. The EngineController generates the 
 /// resulting GraphSyncData from this list of updated nodes.</param>
 /// <returns>Returns the list of node id's that will be executed in the next run
 /// for execution).</returns>
 internal List<Guid> Initialize(EngineController controller, WorkspaceModel workspace)
 {
     try
     {
         engineController = controller;
         TargetedWorkspace = workspace;                
         modifiedNodes = ComputeModifiedNodes(workspace);                
         previewGraphData = engineController.PreviewGraphSyncData(modifiedNodes,verboseLogging);
         return previewGraphData;
     }
     catch (Exception e)
     {             
         return null;
     }
 }
        private void listBoxErrorNodes_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (sender == null)
            {
                return;
            }
            ListBox lb = sender as ListBox;

            if (lb.SelectedItem == null)
            {
                return;
            }

            var              selection        = lb.SelectedItem;
            ModelBase        modelBase        = selection.GetType().GetProperty("theNode").GetValue(selection) as ModelBase;
            ViewLoadedParams viewLoadedParams = selection.GetType().GetProperty("theWSModel").GetValue(selection) as ViewLoadedParams;
            string           guid             = selection.GetType().GetProperty("guid").GetValue(selection) as string;

            foreach (NodeModel node in viewLoadedParams.CurrentWorkspaceModel.Nodes)
            {
                node.Deselect();
                node.IsSelected = false;
            }

            Dynamo.Graph.Workspaces.WorkspaceModel ws = viewLoadedParams.CurrentWorkspaceModel as WorkspaceModel;
            foreach (AnnotationModel group in ws.Annotations)
            {
                group.Deselect();
                group.IsSelected = false;
            }

            foreach (NoteModel note in ws.Notes)
            {
                note.Deselect();
                note.IsSelected = false;
            }

            var VM = viewLoadedParams.DynamoWindow.DataContext as DynamoViewModel;

            VM.CurrentSpaceViewModel.ResetFitViewToggleCommand.Execute(null);
            VM.AddToSelectionCommand.Execute(modelBase);
            VM.FitViewCommand.Execute(null);
        }
        // Helper function that builds string of error nodes
        public List <groupData> getGroupTypes()
        {
            List <groupData> output = new List <groupData>();
            List <groupData> groups = new List <groupData>();

            Dynamo.Graph.Workspaces.WorkspaceModel ws = readyParams.CurrentWorkspaceModel as WorkspaceModel;

            foreach (AnnotationModel group in ws.Annotations)
            {
                if (group.AnnotationText == "")
                {
                    groups.Add(new groupData()
                    {
                        name       = "*Group has no Title*",
                        guid       = group.GUID.ToString(),
                        theGroup   = group,
                        theWSModel = readyParams
                    });
                }
                else
                {
                    groups.Add(new groupData()
                    {
                        name       = group.AnnotationText,
                        guid       = group.GUID.ToString(),
                        theGroup   = group,
                        theWSModel = readyParams
                    });
                }
            }
            foreach (groupData group in groups.OrderByDescending(x => x.name))
            {
                output.Add(group);
            }
            output.Reverse();
            return(output);
        }
 private static IEnumerable<NodeModel> ComputeModifiedNodes(WorkspaceModel workspace)
 {
     return workspace.Nodes; // TODO(Ben): Implement dirty node subsetting.
 }
Example #6
0
        /// <summary>
        /// This method is called to gather all the nodes whose cached values 
        /// should be updated after graph update is done. This set of nodes 
        /// includes nodes that are explicitly marked as requiring update, as 
        /// well as all its downstream nodes.
        /// </summary>
        /// <param name="workspace">The WorkspaceModel from which nodes are to
        /// be retrieved.</param>
        /// <returns>Returns a list of NodeModel whose cached values are to be 
        /// updated after the evaluation.</returns>
        /// 
        private static IEnumerable<NodeModel> ComputeModifiedNodes(WorkspaceModel workspace)
        {
            var nodesToUpdate = new List<NodeModel>();
            //Get those modified nodes that are not frozen
            foreach (var node in workspace.Nodes.Where(n => n.IsModified && !n.IsFrozen))
            {
                GetDownstreamNodes(node, nodesToUpdate);
            }

            return nodesToUpdate;
        }
Example #7
0
        /// <summary>
        /// Save a Workspace to json.
        /// </summary>
        /// <returns>A string representing the serialized WorkspaceModel.</returns>
        public static string SaveWorkspaceToJson(WorkspaceModel workspace, LibraryServices libraryServices, 
            EngineController engineController, DynamoScheduler scheduler, NodeFactory factory,
            bool isTestMode, bool verboseLogging, CustomNodeManager manager)
        {
            var settings = new JsonSerializerSettings
            {
                Error = (sender, args) =>
                {
                    args.ErrorContext.Handled = true;
                    Console.WriteLine(args.ErrorContext.Error);
                },
                ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
                TypeNameHandling = TypeNameHandling.Auto,
                Formatting = Formatting.Indented,
                Converters = new List<JsonConverter>{
                        new ConnectorConverter(),
                        new AnnotationConverter(),
                        new WorkspaceConverter(engineController, scheduler, factory,
                        isTestMode, verboseLogging),
                        new NodeModelConverter(manager, libraryServices),
                    },
                ReferenceResolverProvider = () => { return new IdReferenceResolver(); }
            };

            var json = JsonConvert.SerializeObject(workspace, settings);
            var result = ReplaceTypeDeclarations(json);

            return result;
        }
Example #8
0
        /// <summary>
        /// Returns the backup file path for a workspace
        /// </summary>
        /// <param name="workspace"></param>
        /// <returns></returns>
        internal string GetBackupFilePath(WorkspaceModel workspace)
        {
            string fileName;
            if (string.IsNullOrEmpty(workspace.FileName))
            {
                if (workspace is HomeWorkspaceModel)
                {
                    fileName = Configurations.BackupFileNamePrefix + ".DYN";
                }
                else
                {
                    fileName = workspace.Name + ".DYF";
                }
            }
            else
            {
                fileName = Path.GetFileName(workspace.FileName);
            }

            return Path.Combine(BackupDirectory, fileName);
        }
Example #9
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);
                }
            }

            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);
                }
            }
        }
Example #10
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;
                    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();
                        }
                    }
                }
            }
            // 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;
                    }
                }
            }
        }