Пример #1
0
 /// <summary>
 /// Initializes a new instance of the <see cref="CustomNodeWorkspaceModel"/> class
 /// by given information about it and node factory
 /// </summary>
 /// <param name="info">Information for creating custom node workspace</param>
 /// <param name="factory">Node factory to create nodes</param>
 public CustomNodeWorkspaceModel(WorkspaceInfo info, NodeFactory factory)
     : this(factory,
         Enumerable.Empty<NodeModel>(),
         Enumerable.Empty<NoteModel>(),
         Enumerable.Empty<AnnotationModel>(),
         Enumerable.Empty<PresetModel>(),
         new ElementResolver(),
         info) { }
        public CustomNodeWorkspaceModel( 
            NodeFactory factory,
            IEnumerable<NodeModel> nodes, 
            IEnumerable<NoteModel> notes, 
            IEnumerable<AnnotationModel> annotations,
            IEnumerable<PresetModel> presets,
            ElementResolver elementResolver, 
            WorkspaceInfo info)
            : base(nodes, notes,annotations, info, factory,presets, elementResolver)
        {
            HasUnsavedChanges = false;

            CustomNodeId = Guid.Parse(info.ID);
            Category = info.Category;
            Description = info.Description;
            IsVisibleInDynamoLibrary = info.IsVisibleInDynamoLibrary;
            PropertyChanged += OnPropertyChanged;
        }
Пример #3
0
        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            var obj = JObject.Load(reader);

            var isCustomNode = obj["IsCustomNode"].Value<bool>();
            var lastModifiedStr = obj["LastModified"].Value<string>();
            var lastModified = DateTime.ParseExact(lastModifiedStr,"yyyy-MM-dd",CultureInfo.InvariantCulture);
            var author = obj["LastModifiedBy"].Value<string>();
            var description = obj["Description"].Value<string>();
            var guidStr = obj["Uuid"].Value<string>();
            var guid = Guid.Parse(guidStr);
            var name = obj["Name"].Value<string>();

            var elementResolver = obj["ElementResolver"].ToObject<ElementResolver>(serializer);
            var nmc = (NodeModelConverter)serializer.Converters.First(c => c is NodeModelConverter);
            nmc.ElementResolver = elementResolver;

            // nodes
            var nodes = obj["Nodes"].ToObject<IEnumerable<NodeModel>>(serializer);
            
            // notes
            var notes = obj["Notes"].ToObject<IEnumerable<NoteModel>>(serializer);
            if (notes.Any())
            {
                foreach(var n in notes)
                {
                    serializer.ReferenceResolver.AddReference(serializer.Context, n.GUID.ToString(), n);
                }
            }

            // connectors
            // Although connectors are not used in the construction of the workspace
            // we need to deserialize this collection, so that they connect to their
            // relevant ports.
            var connectors = obj["Connectors"].ToObject<IEnumerable<ConnectorModel>>(serializer);

            // annotations
            var annotations = obj["Annotations"].ToObject<IEnumerable<AnnotationModel>>(serializer);

            var info = new WorkspaceInfo(guid.ToString(), name, description, Dynamo.Models.RunType.Automatic);

            WorkspaceModel ws;
            if (isCustomNode)
            {
                ws = new CustomNodeWorkspaceModel(factory, nodes, notes, annotations, 
                    Enumerable.Empty<PresetModel>(), elementResolver, info);
            }
            else
            {
                ws = new HomeWorkspaceModel(guid, engine, scheduler, factory, 
                    Enumerable.Empty<KeyValuePair<Guid, List<CallSite.RawTraceData>>>(), nodes, notes, annotations, 
                    Enumerable.Empty<PresetModel>(), elementResolver, 
                    info, verboseLogging, isTestMode);
            }

            return ws;
        }
Пример #4
0
        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            var obj = JObject.Load(reader);

            var isCustomNode = obj["IsCustomNode"].Value <bool>();
            var description  = obj["Description"].Value <string>();
            var guidStr      = obj["Uuid"].Value <string>();
            var guid         = Guid.Parse(guidStr);
            var name         = obj["Name"].Value <string>();

            var elementResolver = obj["ElementResolver"].ToObject <ElementResolver>(serializer);
            var nmc             = (NodeReadConverter)serializer.Converters.First(c => c is NodeReadConverter);

            nmc.ElementResolver = elementResolver;

            // nodes
            var nodes = obj["Nodes"].ToObject <IEnumerable <NodeModel> >(serializer);

            // notes
            //TODO: Check this when implementing ReadJSON in ViewModel.
            //var notes = obj["Notes"].ToObject<IEnumerable<NoteModel>>(serializer);
            //if (notes.Any())
            //{
            //    foreach(var n in notes)
            //    {
            //        serializer.ReferenceResolver.AddReference(serializer.Context, n.GUID.ToString(), n);
            //    }
            //}

            // connectors
            // Although connectors are not used in the construction of the workspace
            // we need to deserialize this collection, so that they connect to their
            // relevant ports.
            var connectors = obj["Connectors"].ToObject <IEnumerable <ConnectorModel> >(serializer);

            var info = new WorkspaceInfo(guid.ToString(), name, description, Dynamo.Models.RunType.Automatic);

            //Build an empty annotations. Annotations are defined in the view block. If the file has View block
            //serialize view block first and build the annotations.
            var annotations = new List <AnnotationModel>();

            //Build an empty notes. Notes are defined in the view block. If the file has View block
            //serialize view block first and build the notes.
            var notes = new List <NoteModel>();

            WorkspaceModel ws;

            if (isCustomNode)
            {
                ws = new CustomNodeWorkspaceModel(factory, nodes, notes, annotations,
                                                  Enumerable.Empty <PresetModel>(), elementResolver, info);
            }
            else
            {
                ws = new HomeWorkspaceModel(guid, engine, scheduler, factory,
                                            Enumerable.Empty <KeyValuePair <Guid, List <CallSite.RawTraceData> > >(), nodes, notes, annotations,
                                            Enumerable.Empty <PresetModel>(), elementResolver,
                                            info, verboseLogging, isTestMode);
            }

            return(ws);
        }
Пример #5
0
        internal static bool FromXmlDocument(XmlDocument xmlDoc, string path, bool isTestMode,
                                             bool forceManualExecutionMode, ILogger logger, out WorkspaceInfo workspaceInfo)
        {
            try
            {
                string funName                  = null;
                double cx                       = 0;
                double cy                       = 0;
                double zoom                     = 1.0;
                string id                       = "";
                string category                 = "";
                string description              = "";
                string version                  = "";
                var    runType                  = RunType.Manual;
                int    runPeriod                = RunSettings.DefaultRunPeriod;
                bool   hasRunWithoutCrash       = false;
                bool   isVisibleInDynamoLibrary = true;

                var topNode = xmlDoc.GetElementsByTagName("Workspace");

                // legacy support
                if (topNode.Count == 0)
                {
                    topNode = xmlDoc.GetElementsByTagName("dynWorkspace");
                }

                // load the header
                foreach (XmlNode node in topNode)
                {
                    foreach (XmlAttribute att in node.Attributes)
                    {
                        if (att.Name.Equals("X"))
                        {
                            cx = double.Parse(att.Value, CultureInfo.InvariantCulture);
                        }
                        else if (att.Name.Equals("Y"))
                        {
                            cy = double.Parse(att.Value, CultureInfo.InvariantCulture);
                        }
                        else if (att.Name.Equals("zoom"))
                        {
                            zoom = double.Parse(att.Value, CultureInfo.InvariantCulture);
                        }
                        else if (att.Name.Equals("Name"))
                        {
                            funName = att.Value;
                        }
                        else if (att.Name.Equals("ID"))
                        {
                            id = att.Value;
                        }
                        else if (att.Name.Equals("Category"))
                        {
                            category = att.Value;
                        }
                        else if (att.Name.Equals("Description"))
                        {
                            description = att.Value;
                        }
                        else if (att.Name.Equals("HasRunWithoutCrash"))
                        {
                            hasRunWithoutCrash = bool.Parse(att.Value);
                        }
                        else if (att.Name.Equals("IsVisibleInDynamoLibrary"))
                        {
                            isVisibleInDynamoLibrary = bool.Parse(att.Value);
                        }
                        else if (att.Name.Equals("Version"))
                        {
                            version = att.Value;
                        }
                        else if (att.Name.Equals("RunType"))
                        {
                            if (forceManualExecutionMode || !Enum.TryParse(att.Value, false, out runType))
                            {
                                runType = RunType.Manual;
                            }
                        }
                        else if (att.Name.Equals("RunPeriod"))
                        {
                            runPeriod = Int32.Parse(att.Value);
                        }
                    }
                }

                // we have a dyf and it lacks an ID field, we need to assign it
                // a deterministic guid based on its name.  By doing it deterministically,
                // files remain compatible
                if (string.IsNullOrEmpty(id) && !string.IsNullOrEmpty(funName) && funName != "Home")
                {
                    id = GuidUtility.Create(GuidUtility.UrlNamespace, funName).ToString();
                }

                workspaceInfo = new WorkspaceInfo
                {
                    ID                       = id,
                    Name                     = funName,
                    X                        = cx,
                    Y                        = cy,
                    Zoom                     = zoom,
                    FileName                 = path,
                    Category                 = category,
                    Description              = description,
                    Version                  = version,
                    RunType                  = runType,
                    RunPeriod                = runPeriod,
                    HasRunWithoutCrash       = hasRunWithoutCrash,
                    IsVisibleInDynamoLibrary = isVisibleInDynamoLibrary
                };
                return(true);
            }
            catch (Exception ex)
            {
                logger.Log(Properties.Resources.OpenWorkbenchError);
                logger.Log(ex);
                Debug.WriteLine(ex.Message + ":" + ex.StackTrace);

                //TODO(Steve): Need a better way to handle this kind of thing. -- MAGN-5712
                if (isTestMode)
                {
                    throw; // Rethrow for NUnit.
                }
                workspaceInfo = null;
                return(false);
            }
        }
Пример #6
0
        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            var obj = JObject.Load(reader);

            var isCustomNode = obj["IsCustomNode"].Value <bool>();
            var description  = obj["Description"].Value <string>();
            var guidStr      = obj["Uuid"].Value <string>();
            var guid         = Guid.Parse(guidStr);
            var name         = obj["Name"].Value <string>();

            var elementResolver = obj["ElementResolver"].ToObject <ElementResolver>(serializer);
            var nmc             = (NodeReadConverter)serializer.Converters.First(c => c is NodeReadConverter);

            nmc.ElementResolver = elementResolver;

            // nodes
            var nodes = obj["Nodes"].ToObject <IEnumerable <NodeModel> >(serializer);

            // Setting Inputs
            // Required in headless mode by Dynamo Player that NodeModel.Name and NodeModel.IsSetAsInput are set
            var inputsToken = obj["Inputs"];

            if (inputsToken != null)
            {
                var inputs = inputsToken.ToArray().Select(x => x.ToObject <NodeInputData>()).ToList();
                //using the inputs lets set the correct properties on the nodes.
                foreach (var inputData in inputs)
                {
                    var matchingNode = nodes.Where(x => x.GUID == inputData.Id).FirstOrDefault();
                    if (matchingNode != null)
                    {
                        matchingNode.IsSetAsInput = true;
                        matchingNode.Name         = inputData.Name;
                    }
                }
            }

            // Setting Outputs
            var outputsToken = obj["Outputs"];

            if (outputsToken != null)
            {
                var outputs = outputsToken.ToArray().Select(x => x.ToObject <NodeOutputData>()).ToList();
                //using the inputs lets set the correct properties on the nodes.
                foreach (var outputData in outputs)
                {
                    var matchingNode = nodes.Where(x => x.GUID == outputData.Id).FirstOrDefault();
                    if (matchingNode != null)
                    {
                        matchingNode.IsSetAsOutput = true;
                        matchingNode.Name          = outputData.Name;
                    }
                }
            }

            #region Setting Inputs based on view layer info
            // TODO: It is currently duplicating the effort with Input Block parsing which should be cleaned up once
            // Dynamo supports both selection and drop down nodes in Inputs block
            var view = obj["View"];
            if (view != null)
            {
                var nodesView = view["NodeViews"];
                if (nodesView != null)
                {
                    var inputsView = nodesView.ToArray().Select(x => x.ToObject <Dictionary <string, string> >()).ToList();
                    foreach (var inputViewData in inputsView)
                    {
                        string isSetAsInput = "";
                        if (!inputViewData.TryGetValue("IsSetAsInput", out isSetAsInput) || isSetAsInput == bool.FalseString)
                        {
                            continue;
                        }

                        string inputId = "";
                        if (inputViewData.TryGetValue("Id", out inputId))
                        {
                            Guid inputGuid;
                            try
                            {
                                inputGuid = Guid.Parse(inputId);
                            }
                            catch
                            {
                                continue;
                            }

                            var matchingNode = nodes.Where(x => x.GUID == inputGuid).FirstOrDefault();
                            if (matchingNode != null)
                            {
                                matchingNode.IsSetAsInput = true;
                                string inputName = "";
                                if (inputViewData.TryGetValue("Name", out inputName))
                                {
                                    matchingNode.Name = inputName;
                                }
                            }
                        }
                    }
                }
            }
            #endregion

            // notes
            //TODO: Check this when implementing ReadJSON in ViewModel.
            //var notes = obj["Notes"].ToObject<IEnumerable<NoteModel>>(serializer);
            //if (notes.Any())
            //{
            //    foreach(var n in notes)
            //    {
            //        serializer.ReferenceResolver.AddReference(serializer.Context, n.GUID.ToString(), n);
            //    }
            //}

            // connectors
            // Although connectors are not used in the construction of the workspace
            // we need to deserialize this collection, so that they connect to their
            // relevant ports.
            var connectors = obj["Connectors"].ToObject <IEnumerable <ConnectorModel> >(serializer);

            var info = new WorkspaceInfo(guid.ToString(), name, description, Dynamo.Models.RunType.Automatic);

            // IsVisibleInDynamoLibrary and Category should be set explicitly for custom node workspace
            if (obj["View"] != null && obj["View"]["Dynamo"] != null && obj["View"]["Dynamo"]["IsVisibleInDynamoLibrary"] != null)
            {
                info.IsVisibleInDynamoLibrary = obj["View"]["Dynamo"]["IsVisibleInDynamoLibrary"].Value <bool>();
            }
            if (obj["Category"] != null)
            {
                info.Category = obj["Category"].Value <string>();
            }

            //Build an empty annotations. Annotations are defined in the view block. If the file has View block
            //serialize view block first and build the annotations.
            var annotations = new List <AnnotationModel>();

            //Build an empty notes. Notes are defined in the view block. If the file has View block
            //serialize view block first and build the notes.
            var notes = new List <NoteModel>();

            #region Restore trace data
            // Trace Data
            Dictionary <Guid, List <CallSite.RawTraceData> > loadedTraceData = new Dictionary <Guid, List <CallSite.RawTraceData> >();
            // Restore trace data if bindings are present in json
            if (obj["Bindings"] != null && obj["Bindings"].Children().Count() > 0)
            {
                JEnumerable <JToken> bindings = obj["Bindings"].Children();

                // Iterate through bindings to extract nodeID's and bindingData (callsiteId & traceData)
                foreach (JToken entity in bindings)
                {
                    Guid   nodeId        = Guid.Parse(entity["NodeId"].ToString());
                    string bindingString = entity["Binding"].ToString();

                    // Key(callsiteId) : Value(traceData)
                    Dictionary <string, string>  bindingData       = JsonConvert.DeserializeObject <Dictionary <string, string> >(bindingString);
                    List <CallSite.RawTraceData> callsiteTraceData = new List <CallSite.RawTraceData>();

                    foreach (KeyValuePair <string, string> pair in bindingData)
                    {
                        callsiteTraceData.Add(new CallSite.RawTraceData(pair.Key, pair.Value));
                    }

                    loadedTraceData.Add(nodeId, callsiteTraceData);
                }
            }
            #endregion

            WorkspaceModel ws;
            if (isCustomNode)
            {
                ws = new CustomNodeWorkspaceModel(factory, nodes, notes, annotations,
                                                  Enumerable.Empty <PresetModel>(), elementResolver, info);
            }
            else
            {
                ws = new HomeWorkspaceModel(guid, engine, scheduler, factory,
                                            loadedTraceData, nodes, notes, annotations,
                                            Enumerable.Empty <PresetModel>(), elementResolver,
                                            info, verboseLogging, isTestMode);
            }

            return(ws);
        }
Пример #7
0
        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            var obj = JObject.Load(reader);

            var isCustomNode = obj["IsCustomNode"].Value <bool>();
            var description  = obj["Description"].Value <string>();
            var guidStr      = obj["Uuid"].Value <string>();
            var guid         = Guid.Parse(guidStr);
            var name         = obj["Name"].Value <string>();

            var elementResolver = obj["ElementResolver"].ToObject <ElementResolver>(serializer);
            var nmc             = (NodeReadConverter)serializer.Converters.First(c => c is NodeReadConverter);

            nmc.ElementResolver = elementResolver;

            // nodes
            var nodes = obj["Nodes"].ToObject <IEnumerable <NodeModel> >(serializer);

            // nodes
            var inputsToken = obj["Inputs"];

            if (inputsToken != null)
            {
                var inputs = inputsToken.ToArray().Select(x => x.ToObject <NodeInputData>()).ToList();
                //using the inputs lets set the correct properties on the nodes.
                foreach (var inputData in inputs)
                {
                    var matchingNode = nodes.Where(x => x.GUID == inputData.Id).FirstOrDefault();
                    if (matchingNode != null)
                    {
                        matchingNode.IsSetAsInput = true;
                    }
                }
            }

            var outputsToken = obj["Outputs"];

            if (outputsToken != null)
            {
                var outputs = outputsToken.ToArray().Select(x => x.ToObject <NodeOutputData>()).ToList();
                //using the inputs lets set the correct properties on the nodes.
                foreach (var outputData in outputs)
                {
                    var matchingNode = nodes.Where(x => x.GUID == outputData.Id).FirstOrDefault();
                    if (matchingNode != null)
                    {
                        matchingNode.IsSetAsOutput = true;
                    }
                }
            }

            // notes
            //TODO: Check this when implementing ReadJSON in ViewModel.
            //var notes = obj["Notes"].ToObject<IEnumerable<NoteModel>>(serializer);
            //if (notes.Any())
            //{
            //    foreach(var n in notes)
            //    {
            //        serializer.ReferenceResolver.AddReference(serializer.Context, n.GUID.ToString(), n);
            //    }
            //}

            // connectors
            // Although connectors are not used in the construction of the workspace
            // we need to deserialize this collection, so that they connect to their
            // relevant ports.
            var connectors = obj["Connectors"].ToObject <IEnumerable <ConnectorModel> >(serializer);

            var info = new WorkspaceInfo(guid.ToString(), name, description, Dynamo.Models.RunType.Automatic);

            //Build an empty annotations. Annotations are defined in the view block. If the file has View block
            //serialize view block first and build the annotations.
            var annotations = new List <AnnotationModel>();

            //Build an empty notes. Notes are defined in the view block. If the file has View block
            //serialize view block first and build the notes.
            var notes = new List <NoteModel>();

            // Trace Data
            Dictionary <Guid, List <CallSite.RawTraceData> > loadedTraceData = new Dictionary <Guid, List <CallSite.RawTraceData> >();

            // Restore trace data if bindings are present in json
            if (obj["Bindings"] != null && obj["Bindings"].Children().Count() > 0)
            {
                JEnumerable <JToken> bindings = obj["Bindings"].Children();

                // Iterate through bindings to extract nodeID's and bindingData (callsiteId & traceData)
                foreach (JToken entity in bindings)
                {
                    Guid   nodeId        = Guid.Parse(entity["NodeId"].ToString());
                    string bindingString = entity["Binding"].ToString();

                    // Key(callsiteId) : Value(traceData)
                    Dictionary <string, string>  bindingData       = JsonConvert.DeserializeObject <Dictionary <string, string> >(bindingString);
                    List <CallSite.RawTraceData> callsiteTraceData = new List <CallSite.RawTraceData>();

                    foreach (KeyValuePair <string, string> pair in bindingData)
                    {
                        callsiteTraceData.Add(new CallSite.RawTraceData(pair.Key, pair.Value));
                    }

                    loadedTraceData.Add(nodeId, callsiteTraceData);
                }
            }

            WorkspaceModel ws;

            if (isCustomNode)
            {
                ws = new CustomNodeWorkspaceModel(factory, nodes, notes, annotations,
                                                  Enumerable.Empty <PresetModel>(), elementResolver, info);
            }
            else
            {
                ws = new HomeWorkspaceModel(guid, engine, scheduler, factory,
                                            loadedTraceData, nodes, notes, annotations,
                                            Enumerable.Empty <PresetModel>(), elementResolver,
                                            info, verboseLogging, isTestMode);
            }

            return(ws);
        }
Пример #8
0
        /// <summary>
        /// Return a boolean indicating if successfully deserialized workspace info object from Json file
        /// </summary>
        /// <param name="jsonDoc">Target Josn</param>
        /// <param name="path">Target path</param>
        /// <param name="isTestMode">Boolean indicating if Dynamo is running in Test Mode</param>
        /// <param name="forceManualExecutionMode">Boolean indicating if forcing manual mode</param>
        /// <param name="logger">Dynamo logger</param>
        /// <param name="workspaceInfo">Return object</param>
        /// <returns>A boolean indicating success</returns>
        internal static bool FromJsonDocument(String jsonDoc, string path, bool isTestMode,
                                              bool forceManualExecutionMode, ILogger logger, out WorkspaceInfo workspaceInfo)
        {
            var jObject = (JObject)JsonConvert.DeserializeObject(jsonDoc);

            try
            {
                double cx                       = 0;
                double cy                       = 0;
                double zoom                     = 1.0;
                double scaleFactor              = 1.0;
                string version                  = "";
                var    runType                  = RunType.Manual;
                int    runPeriod                = RunSettings.DefaultRunPeriod;
                bool   hasRunWithoutCrash       = false;
                bool   isVisibleInDynamoLibrary = true;

                JToken value;
                string funName     = jObject.TryGetValue("Name", out value)? value.ToString(): "";
                string id          = jObject.TryGetValue("Uuid", out value) ? value.ToString() : "";
                string category    = jObject.TryGetValue("Category", out value) ? value.ToString() : "";
                string description = jObject.TryGetValue("Description", out value) ? value.ToString() : "";
                // we have a dyf and it lacks an ID field, we need to assign it
                // a deterministic guid based on its name.  By doing it deterministically,
                // files remain compatible
                if (string.IsNullOrEmpty(id) && !string.IsNullOrEmpty(funName) && funName != Properties.Resources.DefaultHomeWorkspaceName)
                {
                    id = GuidUtility.Create(GuidUtility.UrlNamespace, funName).ToString();
                }

                // Parse the following info when graph contains a "View" block
                if (jObject.TryGetValue("View", out value))
                {
                    JObject viewObject = value.ToObject <JObject>();
                    Double.TryParse((viewObject.TryGetValue("X", out value) ? value.ToString(): "0"), out cx);
                    Double.TryParse((viewObject.TryGetValue("Y", out value) ? value.ToString() : "0"), out cy);
                    Double.TryParse((viewObject.TryGetValue("Zoom", out value) ? value.ToString() : "1.0"), out zoom);

                    // Parse the following info when "View" block contains a "Dynamo" block
                    if (viewObject.TryGetValue("Dynamo", out value))
                    {
                        JObject dynamoObject = value.ToObject <JObject>();
                        Double.TryParse((dynamoObject.TryGetValue("ScaleFactor", out value) ? value.ToString(): "1.0"), out scaleFactor);
                        Boolean.TryParse((dynamoObject.TryGetValue("HasRunWithoutCrash", out value) ? value.ToString(): "false"), out hasRunWithoutCrash);
                        Boolean.TryParse((dynamoObject.TryGetValue("IsVisibleInDynamoLibrary", out value) ? value.ToString(): "true"), out isVisibleInDynamoLibrary);
                        version = dynamoObject.TryGetValue("Version", out value)? value.ToString() : "";
                        if (forceManualExecutionMode || !Enum.TryParse((dynamoObject.TryGetValue("RunType", out value)? value.ToString(): "false"), false, out runType))
                        {
                            runType = RunType.Manual;
                        }
                        Int32.TryParse((dynamoObject.TryGetValue("RunPeriod", out value)? value.ToString() : RunSettings.DefaultRunPeriod.ToString()), out runPeriod);
                    }
                }

                workspaceInfo = new WorkspaceInfo
                {
                    ID                       = id,
                    Name                     = funName,
                    X                        = cx,
                    Y                        = cy,
                    Zoom                     = zoom,
                    ScaleFactor              = scaleFactor,
                    FileName                 = path,
                    Category                 = category,
                    Description              = description,
                    Version                  = version,
                    RunType                  = runType,
                    RunPeriod                = runPeriod,
                    HasRunWithoutCrash       = hasRunWithoutCrash,
                    IsVisibleInDynamoLibrary = isVisibleInDynamoLibrary
                };
                return(true);
            }
            catch (Exception ex)
            {
                logger.Log(Properties.Resources.OpenWorkbenchError);
                logger.Log(ex);
                Debug.WriteLine(ex.Message + ":" + ex.StackTrace);

                if (isTestMode)
                {
                    throw; // Rethrow for NUnit.
                }
                workspaceInfo = null;
                return(false);
            }
        }