Example #1
0
        public void CanAddANote()
        {
            // Create some test note data
            Guid id = Guid.NewGuid();
            DynCmd.CreateNoteCommand command = new DynCmd.CreateNoteCommand(
                id, "This is a test note.", 200.0, 200.0, false);

            var ws = Controller.DynamoViewModel.CurrentSpace;
            dynSettings.Controller.DynamoModel.AddNoteInternal(command, ws);
            Assert.AreEqual(Controller.DynamoViewModel.CurrentSpace.Notes.Count, 1);
        }
Example #2
0
        public void CanAddANote()
        {
            // Create some test note data
            Guid id = Guid.NewGuid();
            DynCmd.CreateNoteCommand command = new DynCmd.CreateNoteCommand(
                id, "This is a test note.", 200.0, 200.0, false);

            var ws = Controller.DynamoViewModel.CurrentSpace;
            dynSettings.Controller.DynamoModel.AddNoteInternal(command, ws);
            Assert.AreEqual(Controller.DynamoViewModel.CurrentSpace.Notes.Count, 1);
        }
Example #3
0
        public void TestCreateNoteCommand()
        {
            // Create the command in completely unpredictable states. These
            // states should properly be serialized and deserialized across
            // two instances of the same command.
            //
            Guid   nodeId     = Guid.NewGuid();
            string text       = randomizer.Next().ToString();
            double x          = randomizer.NextDouble() * 1000;
            double y          = randomizer.NextDouble() * 1000;
            bool   defaultPos = randomizer.Next(2) == 0;

            var cmdOne = new DynCmd.CreateNoteCommand(nodeId, text, x, y, defaultPos);
            var cmdTwo = DuplicateAndCompare(cmdOne);

            Assert.AreEqual(cmdOne.NodeId, cmdTwo.NodeId);
            Assert.AreEqual(cmdOne.NoteText, cmdTwo.NoteText);
            Assert.AreEqual(cmdOne.X, cmdTwo.X, 0.000001);
            Assert.AreEqual(cmdOne.Y, cmdTwo.Y, 0.000001);
            Assert.AreEqual(cmdOne.DefaultPosition, cmdTwo.DefaultPosition);
        }
Example #4
0
        /// <summary>
        /// After command framework is implemented, this method should now be only 
        /// called from a menu item (i.e. Ctrl + W). It should not be used as a way
        /// for any other code paths to create a note programmatically. For that we
        /// now have AddNoteInternal which takes in more configurable arguments.
        /// </summary>
        /// <param name="parameters">This is not used and should always be null,
        /// otherwise an ArgumentException will be thrown.</param>
        /// 
        public void AddNote(object parameters)
        {
            if (null != parameters) // See above for details of this exception.
            {
                var message = "Internal error, argument must be null";
                throw new ArgumentException(message, "parameters");
            }

            var command = new DynCmd.CreateNoteCommand(Guid.NewGuid(), null, 0, 0, true);
            this.ExecuteCommand(command);
        }
Example #5
0
        /// <summary>
        ///     Deserialize a function definition from a given path.  A side effect of this function is that
        ///     the node is added to the dictionary of loadedNodes.  
        /// </summary>
        /// <param name="funcDefGuid">The function guid we're currently loading</param>
        /// <param name="controller">Reference to the calling controller</param>
        /// <param name="def">The resultant function definition</param>
        /// <returns></returns>
        private bool GetDefinitionFromPath(Guid funcDefGuid, out FunctionDefinition def)
        {
            var controller = dynSettings.Controller;

            try
            {
                var xmlPath = GetNodePath(funcDefGuid);

                #region read xml file

                var xmlDoc = new XmlDocument();
                xmlDoc.Load(xmlPath);

                string funName = null;
                string category = "";
                double cx = 0;
                double cy = 0;
                string description = "";
                string version = "";

                double zoom = 1.0;
                string id = "";

                // load the header

                // handle legacy workspace nodes called dynWorkspace
                // and new workspaces without the dyn prefix
                XmlNodeList workspaceNodes = xmlDoc.GetElementsByTagName("Workspace");
                if(workspaceNodes.Count == 0)
                    workspaceNodes = xmlDoc.GetElementsByTagName("dynWorkspace");

                foreach (XmlNode node in workspaceNodes)
                {
                    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("Category"))
                            category = att.Value;
                        else if (att.Name.Equals("Description"))
                            description = att.Value;
                        else if (att.Name.Equals("ID"))
                            id = att.Value;
                        else if (att.Name.Equals("Version"))
                            version = 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))
                {
                    id = GuidUtility.Create(GuidUtility.UrlNamespace, funName).ToString();
                }

                #endregion

                //DynamoCommands.WriteToLogCmd.Execute("Loading node definition for \"" + funName + "\" from: " + xmlPath);
                dynSettings.Controller.DynamoModel.WriteToLog("Loading node definition for \"" + funName + "\" from: " + xmlPath);

                var ws = new CustomNodeWorkspaceModel(
                    funName, category.Length > 0
                    ? category
                    : "Custom Nodes", description, cx, cy)
                {
                    WatchChanges = false,
                    FileName = xmlPath,
                    Zoom = zoom
                };

                def = new FunctionDefinition(Guid.Parse(id))
                {
                    WorkspaceModel = ws
                };

                // load a dummy version, so any nodes depending on this node
                // will find an (empty) identifier on compilation
                FScheme.Expression dummyExpression = FScheme.Expression.NewNumber_E(0);
                controller.FSchemeEnvironment.DefineSymbol(def.FunctionId.ToString(), dummyExpression);

                // set the node as loaded
                this.LoadedCustomNodes.Add(def.FunctionId, def);

                XmlNodeList elNodes = xmlDoc.GetElementsByTagName("Elements");
                XmlNodeList cNodes = xmlDoc.GetElementsByTagName("Connectors");
                XmlNodeList nNodes = xmlDoc.GetElementsByTagName("Notes");

                if (elNodes.Count == 0)
                    elNodes = xmlDoc.GetElementsByTagName("dynElements");
                if (cNodes.Count == 0)
                    cNodes = xmlDoc.GetElementsByTagName("dynConnectors");
                if (nNodes.Count == 0)
                    nNodes = xmlDoc.GetElementsByTagName("dynNotes");

                XmlNode elNodesList = elNodes[0];
                XmlNode cNodesList = cNodes[0];
                XmlNode nNodesList = nNodes[0];

                #region instantiate nodes

                var badNodes = new List<Guid>();

                foreach (XmlNode elNode in elNodesList.ChildNodes)
                {
                    XmlAttribute typeAttrib = elNode.Attributes["type"];
                    XmlAttribute guidAttrib = elNode.Attributes["guid"];
                    XmlAttribute nicknameAttrib = elNode.Attributes["nickname"];
                    XmlAttribute xAttrib = elNode.Attributes["x"];
                    XmlAttribute yAttrib = elNode.Attributes["y"];
                    XmlAttribute lacingAttrib = elNode.Attributes["lacing"];
                    XmlAttribute isVisAttrib = elNode.Attributes["isVisible"];
                    XmlAttribute isUpstreamVisAttrib = elNode.Attributes["isUpstreamVisible"];

                    string typeName = typeAttrib.Value;

                    //test the GUID to confirm that it is non-zero
                    //if it is zero, then we have to fix it
                    //this will break the connectors, but it won't keep
                    //propagating bad GUIDs
                    var guid = new Guid(guidAttrib.Value);
                    if (guid == Guid.Empty)
                    {
                        guid = Guid.NewGuid();
                    }

                    string nickname = nicknameAttrib.Value;

                    double x = double.Parse(xAttrib.Value, CultureInfo.InvariantCulture);
                    double y = double.Parse(yAttrib.Value, CultureInfo.InvariantCulture);

                    bool isVisible = true;
                    if (isVisAttrib != null)
                        isVisible = isVisAttrib.Value == "true" ? true : false;

                    bool isUpstreamVisible = true;
                    if (isUpstreamVisAttrib != null)
                        isUpstreamVisible = isUpstreamVisAttrib.Value == "true" ? true : false;

                    typeName = Dynamo.Nodes.Utilities.PreprocessTypeName(typeName);
                    System.Type type = Dynamo.Nodes.Utilities.ResolveType(typeName);
                    if (null == type)
                    {
                        badNodes.Add(guid);
                        continue;
                    }

                    NodeModel el = dynSettings.Controller.DynamoModel.CreateNodeInstance(type, nickname, guid);

                    if (lacingAttrib != null)
                    {
                        LacingStrategy lacing = LacingStrategy.First;
                        Enum.TryParse(lacingAttrib.Value, out lacing);
                        el.ArgumentLacing = lacing;
                    }

                    el.IsVisible = isVisible;
                    el.IsUpstreamVisible = isUpstreamVisible;

                    ws.Nodes.Add(el);
                    el.WorkSpace = ws;
                    var node = el;

                    node.X = x;
                    node.Y = y;

                    if (el == null)
                        return false;

                    el.DisableReporting();

                    el.Load(
                        elNode,
                        string.IsNullOrEmpty(version)
                            ? new Version(0, 0, 0, 0)
                            : new Version(version));
                }

                #endregion

                #region instantiate connectors

                foreach (XmlNode connector in cNodesList.ChildNodes)
                {
                    XmlAttribute guidStartAttrib = connector.Attributes[0];
                    XmlAttribute intStartAttrib = connector.Attributes[1];
                    XmlAttribute guidEndAttrib = connector.Attributes[2];
                    XmlAttribute intEndAttrib = connector.Attributes[3];
                    XmlAttribute portTypeAttrib = connector.Attributes[4];

                    var guidStart = new Guid(guidStartAttrib.Value);
                    var guidEnd = new Guid(guidEndAttrib.Value);
                    int startIndex = Convert.ToInt16(intStartAttrib.Value);
                    int endIndex = Convert.ToInt16(intEndAttrib.Value);
                    PortType portType = ((PortType)Convert.ToInt16(portTypeAttrib.Value));

                    //find the elements to connect
                    NodeModel start = null;
                    NodeModel end = null;

                    if (badNodes.Contains(guidStart) || badNodes.Contains(guidEnd))
                        continue;

                    foreach (NodeModel e in ws.Nodes)
                    {
                        if (e.GUID == guidStart)
                        {
                            start = e;
                        }
                        else if (e.GUID == guidEnd)
                        {
                            end = e;
                        }
                        if (start != null && end != null)
                        {
                            break;
                        }
                    }

                    try
                    {
                        var newConnector = ConnectorModel.Make(
                            start, end,
                            startIndex, endIndex,
                            portType);
                        if (newConnector != null)
                            ws.Connectors.Add(newConnector);
                    }
                    catch
                    {
                        //DynamoCommands.WriteToLogCmd.Execute(string.Format("ERROR : Could not create connector between {0} and {1}.", start.NickName, end.NickName));
                        dynSettings.Controller.DynamoModel.WriteToLog(string.Format("ERROR : Could not create connector between {0} and {1}.", start.NickName, end.NickName));
                    }
                }

                #endregion

                #region instantiate notes

                if (nNodesList != null)
                {
                    foreach (XmlNode note in nNodesList.ChildNodes)
                    {
                        XmlAttribute textAttrib = note.Attributes[0];
                        XmlAttribute xAttrib = note.Attributes[1];
                        XmlAttribute yAttrib = note.Attributes[2];

                        string text = textAttrib.Value;
                        double x = Convert.ToDouble(xAttrib.Value, CultureInfo.InvariantCulture);
                        double y = Convert.ToDouble(yAttrib.Value, CultureInfo.InvariantCulture);

                        Guid guid = Guid.NewGuid();
                        var command = new DynCmd.CreateNoteCommand(guid, text, x, y, false);
                        dynSettings.Controller.DynamoModel.AddNoteInternal(command, ws);
                    }
                }

                #endregion

                foreach (var e in ws.Nodes)
                    e.EnableReporting();

                def.CompileAndAddToEnvironment(controller.FSchemeEnvironment);

                ws.WatchChanges = true;

                this.OnGetDefinitionFromPath(def);

            }
            catch (Exception ex)
            {
                dynSettings.Controller.DynamoModel.WriteToLog("There was an error opening the workbench.");
                dynSettings.Controller.DynamoModel.WriteToLog(ex);

                if (DynamoController.IsTestMode)
                    Assert.Fail(ex.Message);

                def = null;
                return false;
            }

            return true;
        }
Example #6
0
        /// <summary>
        ///     Deserialize a function definition from a given path.  A side effect of this function is that
        ///     the node is added to the dictionary of loadedNodes.
        /// </summary>
        /// <param name="funcDefGuid">The function guid we're currently loading</param>
        /// <param name="controller">Reference to the calling controller</param>
        /// <param name="def">The resultant function definition</param>
        /// <returns></returns>
        private bool GetDefinitionFromPath(Guid funcDefGuid, out FunctionDefinition def)
        {
            var controller = dynSettings.Controller;

            try
            {
                var xmlPath = GetNodePath(funcDefGuid);

                #region read xml file

                var xmlDoc = new XmlDocument();
                xmlDoc.Load(xmlPath);

                string funName     = null;
                string category    = "";
                double cx          = 0;
                double cy          = 0;
                string description = "";
                string version     = "";

                double zoom = 1.0;
                string id   = "";

                // load the header

                // handle legacy workspace nodes called dynWorkspace
                // and new workspaces without the dyn prefix
                XmlNodeList workspaceNodes = xmlDoc.GetElementsByTagName("Workspace");
                if (workspaceNodes.Count == 0)
                {
                    workspaceNodes = xmlDoc.GetElementsByTagName("dynWorkspace");
                }

                foreach (XmlNode node in workspaceNodes)
                {
                    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("Category"))
                        {
                            category = att.Value;
                        }
                        else if (att.Name.Equals("Description"))
                        {
                            description = att.Value;
                        }
                        else if (att.Name.Equals("ID"))
                        {
                            id = att.Value;
                        }
                        else if (att.Name.Equals("Version"))
                        {
                            version = 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))
                {
                    id = GuidUtility.Create(GuidUtility.UrlNamespace, funName).ToString();
                }

                #endregion

                //DynamoCommands.WriteToLogCmd.Execute("Loading node definition for \"" + funName + "\" from: " + xmlPath);
                dynSettings.Controller.DynamoModel.WriteToLog("Loading node definition for \"" + funName + "\" from: " + xmlPath);

                var ws = new CustomNodeWorkspaceModel(
                    funName, category.Length > 0
                    ? category
                    : "Custom Nodes", description, cx, cy)
                {
                    WatchChanges = false,
                    FileName     = xmlPath,
                    Zoom         = zoom
                };

                def = new FunctionDefinition(Guid.Parse(id))
                {
                    WorkspaceModel = ws
                };

                // load a dummy version, so any nodes depending on this node
                // will find an (empty) identifier on compilation
                FScheme.Expression dummyExpression = FScheme.Expression.NewNumber_E(0);
                controller.FSchemeEnvironment.DefineSymbol(def.FunctionId.ToString(), dummyExpression);

                // set the node as loaded
                this.LoadedCustomNodes.Add(def.FunctionId, def);

                XmlNodeList elNodes = xmlDoc.GetElementsByTagName("Elements");
                XmlNodeList cNodes  = xmlDoc.GetElementsByTagName("Connectors");
                XmlNodeList nNodes  = xmlDoc.GetElementsByTagName("Notes");

                if (elNodes.Count == 0)
                {
                    elNodes = xmlDoc.GetElementsByTagName("dynElements");
                }
                if (cNodes.Count == 0)
                {
                    cNodes = xmlDoc.GetElementsByTagName("dynConnectors");
                }
                if (nNodes.Count == 0)
                {
                    nNodes = xmlDoc.GetElementsByTagName("dynNotes");
                }

                XmlNode elNodesList = elNodes[0];
                XmlNode cNodesList  = cNodes[0];
                XmlNode nNodesList  = nNodes[0];

                #region instantiate nodes

                var badNodes = new List <Guid>();

                foreach (XmlNode elNode in elNodesList.ChildNodes)
                {
                    XmlAttribute typeAttrib          = elNode.Attributes["type"];
                    XmlAttribute guidAttrib          = elNode.Attributes["guid"];
                    XmlAttribute nicknameAttrib      = elNode.Attributes["nickname"];
                    XmlAttribute xAttrib             = elNode.Attributes["x"];
                    XmlAttribute yAttrib             = elNode.Attributes["y"];
                    XmlAttribute lacingAttrib        = elNode.Attributes["lacing"];
                    XmlAttribute isVisAttrib         = elNode.Attributes["isVisible"];
                    XmlAttribute isUpstreamVisAttrib = elNode.Attributes["isUpstreamVisible"];

                    string typeName = typeAttrib.Value;

                    //test the GUID to confirm that it is non-zero
                    //if it is zero, then we have to fix it
                    //this will break the connectors, but it won't keep
                    //propagating bad GUIDs
                    var guid = new Guid(guidAttrib.Value);
                    if (guid == Guid.Empty)
                    {
                        guid = Guid.NewGuid();
                    }

                    string nickname = nicknameAttrib.Value;

                    double x = double.Parse(xAttrib.Value, CultureInfo.InvariantCulture);
                    double y = double.Parse(yAttrib.Value, CultureInfo.InvariantCulture);

                    bool isVisible = true;
                    if (isVisAttrib != null)
                    {
                        isVisible = isVisAttrib.Value == "true" ? true : false;
                    }

                    bool isUpstreamVisible = true;
                    if (isUpstreamVisAttrib != null)
                    {
                        isUpstreamVisible = isUpstreamVisAttrib.Value == "true" ? true : false;
                    }

                    typeName = Dynamo.Nodes.Utilities.PreprocessTypeName(typeName);
                    System.Type type = Dynamo.Nodes.Utilities.ResolveType(typeName);
                    if (null == type)
                    {
                        badNodes.Add(guid);
                        continue;
                    }

                    NodeModel el = dynSettings.Controller.DynamoModel.CreateNodeInstance(type, nickname, guid);

                    if (lacingAttrib != null)
                    {
                        LacingStrategy lacing = LacingStrategy.First;
                        Enum.TryParse(lacingAttrib.Value, out lacing);
                        el.ArgumentLacing = lacing;
                    }

                    el.IsVisible         = isVisible;
                    el.IsUpstreamVisible = isUpstreamVisible;

                    ws.Nodes.Add(el);
                    el.WorkSpace = ws;
                    var node = el;

                    node.X = x;
                    node.Y = y;

                    if (el == null)
                    {
                        return(false);
                    }

                    el.DisableReporting();

                    el.Load(
                        elNode,
                        string.IsNullOrEmpty(version)
                            ? new Version(0, 0, 0, 0)
                            : new Version(version));
                }

                #endregion

                #region instantiate connectors

                foreach (XmlNode connector in cNodesList.ChildNodes)
                {
                    XmlAttribute guidStartAttrib = connector.Attributes[0];
                    XmlAttribute intStartAttrib  = connector.Attributes[1];
                    XmlAttribute guidEndAttrib   = connector.Attributes[2];
                    XmlAttribute intEndAttrib    = connector.Attributes[3];
                    XmlAttribute portTypeAttrib  = connector.Attributes[4];

                    var      guidStart  = new Guid(guidStartAttrib.Value);
                    var      guidEnd    = new Guid(guidEndAttrib.Value);
                    int      startIndex = Convert.ToInt16(intStartAttrib.Value);
                    int      endIndex   = Convert.ToInt16(intEndAttrib.Value);
                    PortType portType   = ((PortType)Convert.ToInt16(portTypeAttrib.Value));

                    //find the elements to connect
                    NodeModel start = null;
                    NodeModel end   = null;

                    if (badNodes.Contains(guidStart) || badNodes.Contains(guidEnd))
                    {
                        continue;
                    }

                    foreach (NodeModel e in ws.Nodes)
                    {
                        if (e.GUID == guidStart)
                        {
                            start = e;
                        }
                        else if (e.GUID == guidEnd)
                        {
                            end = e;
                        }
                        if (start != null && end != null)
                        {
                            break;
                        }
                    }

                    try
                    {
                        var newConnector = ConnectorModel.Make(
                            start, end,
                            startIndex, endIndex,
                            portType);
                        if (newConnector != null)
                        {
                            ws.Connectors.Add(newConnector);
                        }
                    }
                    catch
                    {
                        //DynamoCommands.WriteToLogCmd.Execute(string.Format("ERROR : Could not create connector between {0} and {1}.", start.NickName, end.NickName));
                        dynSettings.Controller.DynamoModel.WriteToLog(string.Format("ERROR : Could not create connector between {0} and {1}.", start.NickName, end.NickName));
                    }
                }

                #endregion

                #region instantiate notes

                if (nNodesList != null)
                {
                    foreach (XmlNode note in nNodesList.ChildNodes)
                    {
                        XmlAttribute textAttrib = note.Attributes[0];
                        XmlAttribute xAttrib    = note.Attributes[1];
                        XmlAttribute yAttrib    = note.Attributes[2];

                        string text = textAttrib.Value;
                        double x    = Convert.ToDouble(xAttrib.Value, CultureInfo.InvariantCulture);
                        double y    = Convert.ToDouble(yAttrib.Value, CultureInfo.InvariantCulture);

                        Guid guid    = Guid.NewGuid();
                        var  command = new DynCmd.CreateNoteCommand(guid, text, x, y, false);
                        dynSettings.Controller.DynamoModel.AddNoteInternal(command, ws);
                    }
                }

                #endregion

                foreach (var e in ws.Nodes)
                {
                    e.EnableReporting();
                }

                def.CompileAndAddToEnvironment(controller.FSchemeEnvironment);

                ws.WatchChanges = true;

                this.OnGetDefinitionFromPath(def);
            }
            catch (Exception ex)
            {
                dynSettings.Controller.DynamoModel.WriteToLog("There was an error opening the workbench.");
                dynSettings.Controller.DynamoModel.WriteToLog(ex);

                if (DynamoController.IsTestMode)
                {
                    Assert.Fail(ex.Message);
                }

                def = null;
                return(false);
            }

            return(true);
        }
Example #7
0
        /// <summary>
        /// Paste ISelectable objects from the clipboard to the workspace.
        /// </summary>
        /// <param name="parameters"></param>
        public void Paste(object parameters)
        {
            //make a lookup table to store the guids of the
            //old nodes and the guids of their pasted versions
            var nodeLookup = new Dictionary<Guid, Guid>();

            //make a list of all newly created models so that their
            //creations can be recorded in the undo recorder.
            var createdModels = new List<ModelBase>();

            //clear the selection so we can put the
            //paste contents in
            DynamoSelection.Instance.ClearSelection();

            var nodes = dynSettings.Controller.ClipBoard.OfType<NodeModel>();

            var connectors = dynSettings.Controller.ClipBoard.OfType<ConnectorModel>();

            foreach (NodeModel node in nodes)
            {
                //create a new guid for us to use
                Guid newGuid = Guid.NewGuid();
                nodeLookup.Add(node.GUID, newGuid);

                string nodeName = node.GetType().ToString();
                if (node is Function)
                    nodeName = ((node as Function).Definition.FunctionId).ToString();
#if USE_DSENGINE
                else if (node is DSFunction)
                    nodeName = ((node as DSFunction).Definition.MangledName);
                else if (node is DSVarArgFunction)
                    nodeName = ((node as DSVarArgFunction).Definition.MangledName);
#endif

                var xmlDoc = new XmlDocument();
                var dynEl = xmlDoc.CreateElement(node.GetType().ToString());
                xmlDoc.AppendChild(dynEl);
                node.Save(xmlDoc, dynEl, SaveContext.Copy);

                createdModels.Add(CreateNode(newGuid, node.X, node.Y + 100, nodeName, dynEl));
            }

            OnRequestLayoutUpdate(this, EventArgs.Empty);

            foreach (ConnectorModel c in connectors)
            {
                var connectionData = new Dictionary<string, object>();

                // if in nodeLookup, the node is paste.  otherwise, use the existing node guid
                Guid startGuid = Guid.Empty;
                Guid endGuid = Guid.Empty;

                startGuid = nodeLookup.TryGetValue(c.Start.Owner.GUID, out startGuid) ? startGuid : c.Start.Owner.GUID;
                endGuid = nodeLookup.TryGetValue(c.End.Owner.GUID, out endGuid) ? endGuid : c.End.Owner.GUID;

                var startNode = CurrentWorkspace.Nodes.FirstOrDefault(x => x.GUID == startGuid);
                var endNode = CurrentWorkspace.Nodes.FirstOrDefault(x => x.GUID == endGuid);

                // do not form connector if the end nodes are null
                if (startNode == null || endNode == null)
                {
                    continue;
                }

                //don't let users paste connectors between workspaces
                if (startNode.WorkSpace != CurrentWorkspace)
                {
                    continue;
                }

                connectionData.Add("start", startNode);
                connectionData.Add("end", endNode);

                connectionData.Add("port_start", c.Start.Index);
                connectionData.Add("port_end", c.End.Index);

                createdModels.Add(CreateConnectionInternal(connectionData));
            }

            //process the queue again to create the connectors
            //DynamoCommands.ProcessCommandQueue();

            var notes = dynSettings.Controller.ClipBoard.OfType<NoteModel>();

            foreach (NoteModel note in notes)
            {
                var newGUID = Guid.NewGuid();

                var sameSpace = CurrentWorkspace.Notes.Any(x => x.GUID == note.GUID);
                var newX = sameSpace ? note.X + 20 : note.X;
                var newY = sameSpace ? note.Y + 20 : note.Y;

                DynCmd.CreateNoteCommand command = new DynCmd.CreateNoteCommand(
                    newGUID, note.Text, newX, newY, false);

                createdModels.Add(AddNoteInternal(command, null));

                // TODO: Why can't we just add "noteData" instead of doing a look-up?
                AddToSelection(CurrentWorkspace.Notes.FirstOrDefault(x => x.GUID == newGUID));
            }

            foreach (var de in nodeLookup)
            {
                AddToSelection(CurrentWorkspace.Nodes.FirstOrDefault(x => x.GUID == de.Value));
            }

            // Record models that are created as part of the command.
            CurrentWorkspace.RecordCreatedModels(createdModels);
        }
Example #8
0
        /// <summary>
        /// Open a workspace from a path.
        /// </summary>
        /// <param name="xmlPath">The path to the workspace.</param>
        /// <returns></returns>
        public bool OpenWorkspace(string xmlPath)
        {
            dynSettings.DynamoLogger.Log("Opening home workspace " + xmlPath + "...");

            CleanWorkbench();
            MigrationManager.ResetIdentifierIndex();

            var sw = new Stopwatch();

            try
            {
                #region read xml file

                sw.Start();

                var xmlDoc = new XmlDocument();
                xmlDoc.Load(xmlPath);

                TimeSpan previousElapsed = sw.Elapsed;
                dynSettings.DynamoLogger.Log(string.Format("{0} elapsed for loading xml.", sw.Elapsed));

                double cx = 0;
                double cy = 0;
                double zoom = 1.0;
                string version = "";

                // handle legacy workspace nodes called dynWorkspace
                // and new workspaces without the dyn prefix
                XmlNodeList workspaceNodes = xmlDoc.GetElementsByTagName("Workspace");
                if (workspaceNodes.Count == 0)
                    workspaceNodes = xmlDoc.GetElementsByTagName("dynWorkspace");

                foreach (XmlNode node in workspaceNodes)
                {
                    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("Version"))
                        {
                            version = att.Value;
                        }
                    }
                }

                Version fileVersion = MigrationManager.VersionFromString(version);

                var dynamoModel = dynSettings.Controller.DynamoModel;
                var currentVersion = MigrationManager.VersionFromWorkspace(dynamoModel.HomeSpace);

                if (fileVersion > currentVersion)
                {
                    bool resume = Utils.DisplayFutureFileMessage(xmlPath, fileVersion, currentVersion);
                    if (!resume)
                        return false;                    
                }

                var decision = MigrationManager.ShouldMigrateFile(fileVersion, currentVersion);
                if (decision == MigrationManager.Decision.Abort)
                {
                    Utils.DisplayObsoleteFileMessage(xmlPath, fileVersion, currentVersion);
                    return false;
                }
                else if (decision == MigrationManager.Decision.Migrate)
                {
                    string backupPath = string.Empty;
                    bool isTesting = DynamoController.IsTestMode; // No backup during test.
                    if (!isTesting && MigrationManager.BackupOriginalFile(xmlPath, ref backupPath))
                    {
                        string message = string.Format(
                            "Original file '{0}' gets backed up at '{1}'",
                            Path.GetFileName(xmlPath), backupPath);

                        dynSettings.DynamoLogger.Log(message);
                    }

                    //Hardcode the file version to 0.6.0.0. The file whose version is 0.7.0.x
                    //needs to be forced to be migrated. The version number needs to be changed from
                    //0.7.0.x to 0.6.0.0.
                    if (fileVersion == new Version(0, 7, 0, 0))
                        fileVersion = new Version(0, 6, 0, 0);

                    MigrationManager.Instance.ProcessWorkspaceMigrations(xmlDoc, fileVersion);
                    MigrationManager.Instance.ProcessNodesInWorkspace(xmlDoc, fileVersion);
                }

                //set the zoom and offsets and trigger events
                //to get the view to position iteself
                CurrentWorkspace.X = cx;
                CurrentWorkspace.Y = cy;
                CurrentWorkspace.Zoom = zoom;

                var vm = dynSettings.Controller.DynamoViewModel.Workspaces.First(x => x.Model == CurrentWorkspace);
                vm.OnCurrentOffsetChanged(this, new PointEventArgs(new Point(cx, cy)));

                XmlNodeList elNodes = xmlDoc.GetElementsByTagName("Elements");
                XmlNodeList cNodes = xmlDoc.GetElementsByTagName("Connectors");
                XmlNodeList nNodes = xmlDoc.GetElementsByTagName("Notes");

                if (elNodes.Count == 0)
                    elNodes = xmlDoc.GetElementsByTagName("dynElements");
                if (cNodes.Count == 0)
                    cNodes = xmlDoc.GetElementsByTagName("dynConnectors");
                if (nNodes.Count == 0)
                    nNodes = xmlDoc.GetElementsByTagName("dynNotes");

                XmlNode elNodesList = elNodes[0];
                XmlNode cNodesList = cNodes[0];
                XmlNode nNodesList = nNodes[0];

                foreach (XmlNode elNode in elNodesList.ChildNodes)
                {
                    XmlAttribute typeAttrib = elNode.Attributes["type"];
                    XmlAttribute guidAttrib = elNode.Attributes["guid"];
                    XmlAttribute nicknameAttrib = elNode.Attributes["nickname"];
                    XmlAttribute xAttrib = elNode.Attributes["x"];
                    XmlAttribute yAttrib = elNode.Attributes["y"];
                    XmlAttribute isVisAttrib = elNode.Attributes["isVisible"];
                    XmlAttribute isUpstreamVisAttrib = elNode.Attributes["isUpstreamVisible"];
                    XmlAttribute lacingAttrib = elNode.Attributes["lacing"];

                    string typeName = typeAttrib.Value;

                    //test the GUID to confirm that it is non-zero
                    //if it is zero, then we have to fix it
                    //this will break the connectors, but it won't keep
                    //propagating bad GUIDs
                    var guid = new Guid(guidAttrib.Value);
                    if (guid == Guid.Empty)
                    {
                        guid = Guid.NewGuid();
                    }

                    string nickname = nicknameAttrib.Value;

                    double x = double.Parse(xAttrib.Value, CultureInfo.InvariantCulture);
                    double y = double.Parse(yAttrib.Value, CultureInfo.InvariantCulture);

                    bool isVisible = true;
                    if (isVisAttrib != null)
                        isVisible = isVisAttrib.Value == "true" ? true : false;

                    bool isUpstreamVisible = true;
                    if (isUpstreamVisAttrib != null)
                        isUpstreamVisible = isUpstreamVisAttrib.Value == "true" ? true : false;

                    // Retrieve optional 'function' attribute (only for DSFunction).
                    XmlAttribute signatureAttrib = elNode.Attributes["function"];
                    var signature = signatureAttrib == null ? null : signatureAttrib.Value;

                    NodeModel el = null;
                    XmlElement dummyElement = null;

                    try
                    {
                        // The attempt to create node instance may fail due to "type" being
                        // something else other than "NodeModel" derived object type. This 
                        // is possible since some legacy nodes have been made to derive from
                        // "MigrationNode" object type that is not derived from "NodeModel".
                        // 
                        typeName = Dynamo.Nodes.Utilities.PreprocessTypeName(typeName);
                        System.Type type = Dynamo.Nodes.Utilities.ResolveType(typeName);
                        if (type != null)
                            el = CreateNodeInstance(type, nickname, signature, guid);

                        if (el != null)
                        {
                            el.WorkSpace = CurrentWorkspace;
                            el.Load(elNode);
                        }
                        else
                        {
                            var e = elNode as XmlElement;
                            dummyElement = MigrationManager.CreateMissingNode(e, 1, 1);
                        }
                    }
                    catch (UnresolvedFunctionException)
                    {
                        // If a given function is not found during file load, then convert the 
                        // function node into a dummy node (instead of crashing the workflow).
                        // 
                        var e = elNode as XmlElement;
                        dummyElement = MigrationManager.CreateUnresolvedFunctionNode(e);
                    }

                    // If a custom node fails to load its definition, convert it into a dummy node.
                    var function = el as Dynamo.Nodes.Function;
                    if ((function != null) && (function.Definition == null))
                    {
                        var e = elNode as XmlElement;
                        dummyElement = MigrationManager.CreateMissingNode(
                            e, el.InPortData.Count, el.OutPortData.Count);
                    }

                    if (dummyElement != null) // If a dummy node placement is desired.
                    {
                        // The new type representing the dummy node.
                        typeName = dummyElement.GetAttribute("type");
                        System.Type type = Dynamo.Nodes.Utilities.ResolveType(typeName);

                        el = CreateNodeInstance(type, nickname, string.Empty, guid);
                        el.WorkSpace = CurrentWorkspace;
                        el.Load(dummyElement);
                    }

                    CurrentWorkspace.Nodes.Add(el);

                    OnNodeAdded(el);

                    el.X = x;
                    el.Y = y;

                    if (lacingAttrib != null)
                    {
                        if (el.ArgumentLacing != LacingStrategy.Disabled)
                        {
                            LacingStrategy lacing = LacingStrategy.Disabled;
                            Enum.TryParse(lacingAttrib.Value, out lacing);
                            el.ArgumentLacing = lacing;
                        }
                    }

                    el.DisableReporting();

                    // This is to fix MAGN-3648. Method reference in CBN that gets 
                    // loaded before method definition causes a CBN to be left in 
                    // a warning state. This is to clear such warnings and set the 
                    // node to "Dead" state (correct value of which will be set 
                    // later on with a call to "EnableReporting" below). Please 
                    // refer to the defect for details and other possible fixes.
                    // 
                    if (el.State == ElementState.Warning && (el is CodeBlockNodeModel))
                        el.State = ElementState.Dead; // Condition to fix MAGN-3648

                    el.IsVisible = isVisible;
                    el.IsUpstreamVisible = isUpstreamVisible;

                    if (CurrentWorkspace == HomeSpace)
                        el.SaveResult = true;
                }

                dynSettings.DynamoLogger.Log(string.Format("{0} ellapsed for loading nodes.", sw.Elapsed - previousElapsed));
                previousElapsed = sw.Elapsed;

                //OnRequestLayoutUpdate(this, EventArgs.Empty);

                //dynSettings.DynamoLogger.Log(string.Format("{0} ellapsed for updating layout.", sw.Elapsed - previousElapsed));
                //previousElapsed = sw.Elapsed;

                foreach (XmlNode connector in cNodesList.ChildNodes)
                {
                    XmlAttribute guidStartAttrib = connector.Attributes[0];
                    XmlAttribute intStartAttrib = connector.Attributes[1];
                    XmlAttribute guidEndAttrib = connector.Attributes[2];
                    XmlAttribute intEndAttrib = connector.Attributes[3];
                    XmlAttribute portTypeAttrib = connector.Attributes[4];

                    var guidStart = new Guid(guidStartAttrib.Value);
                    var guidEnd = new Guid(guidEndAttrib.Value);
                    int startIndex = Convert.ToInt16(intStartAttrib.Value);
                    int endIndex = Convert.ToInt16(intEndAttrib.Value);
                    PortType portType = ((PortType) Convert.ToInt16(portTypeAttrib.Value));

                    //find the elements to connect
                    NodeModel start = null;
                    NodeModel end = null;

                    foreach (NodeModel e in Nodes)
                    {
                        if (e.GUID == guidStart)
                        {
                            start = e;
                        }
                        else if (e.GUID == guidEnd)
                        {
                            end = e;
                        }
                        if (start != null && end != null)
                        {
                            break;
                        }
                    }

                    var newConnector = ConnectorModel.Make(start, end,
                        startIndex, endIndex, portType);

                    if (newConnector != null)
                        CurrentWorkspace.Connectors.Add(newConnector);

                    OnConnectorAdded(newConnector);
                }

                dynSettings.DynamoLogger.Log(string.Format("{0} ellapsed for loading connectors.",
                    sw.Elapsed - previousElapsed));
                previousElapsed = sw.Elapsed;

                #region instantiate notes

                if (nNodesList != null)
                {
                    foreach (XmlNode note in nNodesList.ChildNodes)
                    {
                        XmlAttribute textAttrib = note.Attributes[0];
                        XmlAttribute xAttrib = note.Attributes[1];
                        XmlAttribute yAttrib = note.Attributes[2];

                        string text = textAttrib.Value;
                        double x = double.Parse(xAttrib.Value, CultureInfo.InvariantCulture);
                        double y = double.Parse(yAttrib.Value, CultureInfo.InvariantCulture);

                        // TODO(Ben): Shouldn't we be reading in the Guid 
                        // from file instead of generating a new one here?
                        Guid id = Guid.NewGuid();
                        var command = new DynCmd.CreateNoteCommand(id, text, x, y, false);
                        AddNoteInternal(command, CurrentWorkspace);
                    }
                }

                #endregion

                dynSettings.DynamoLogger.Log(string.Format("{0} ellapsed for loading notes.", sw.Elapsed - previousElapsed));

                foreach (NodeModel e in CurrentWorkspace.Nodes)
                    e.EnableReporting();

                // http://www.japf.fr/2009/10/measure-rendering-time-in-a-wpf-application/comment-page-1/#comment-2892
                Dispatcher.CurrentDispatcher.BeginInvoke(
                    DispatcherPriority.Background,
                    new Action(() =>
                    {
                        sw.Stop();
                        dynSettings.DynamoLogger.Log(string.Format("{0} ellapsed for loading workspace.", sw.Elapsed));
                    }));

                #endregion

                HomeSpace.FileName = xmlPath;

                // Allow live runner a chance to preload trace data from XML.
                var engine = dynSettings.Controller.EngineController;
                if (engine != null && (engine.LiveRunnerCore != null))
                {
                    var data = Utils.LoadTraceDataFromXmlDocument(xmlDoc);
                    CurrentWorkspace.PreloadedTraceData = data;
                }
            }
            catch (Exception ex)
            {
                dynSettings.DynamoLogger.Log("There was an error opening the workbench.");
                dynSettings.DynamoLogger.Log(ex);
                Debug.WriteLine(ex.Message + ":" + ex.StackTrace);
                CleanWorkbench();
                return false;
            }

            CurrentWorkspace.HasUnsavedChanges = false;

            return true;
        }
Example #9
0
        /// <summary>
        /// Open a workspace from a path.
        /// </summary>
        /// <param name="xmlPath">The path to the workspace.</param>
        /// <returns></returns>
        public bool OpenWorkspace(string xmlPath)
        {
            DynamoLogger.Instance.Log("Opening home workspace " + xmlPath + "...");

            CleanWorkbench();

            //clear the renderables
            dynSettings.Controller.VisualizationManager.ClearRenderables();

            var sw = new Stopwatch();

            try
            {
                #region read xml file

                sw.Start();

                var xmlDoc = new XmlDocument();
                xmlDoc.Load(xmlPath);

                TimeSpan previousElapsed = sw.Elapsed;
                DynamoLogger.Instance.Log(string.Format("{0} elapsed for loading xml.", sw.Elapsed));

                double cx = 0;
                double cy = 0;
                double zoom = 1.0;
                string version = "";

                // handle legacy workspace nodes called dynWorkspace
                // and new workspaces without the dyn prefix
                XmlNodeList workspaceNodes = xmlDoc.GetElementsByTagName("Workspace");
                if (workspaceNodes.Count == 0)
                    workspaceNodes = xmlDoc.GetElementsByTagName("dynWorkspace");

                foreach (XmlNode node in workspaceNodes)
                {
                    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("Version"))
                        {
                            version = att.Value;
                        }
                    }
                }

                MigrationManager.Instance.ProcessWorkspaceMigrations(xmlDoc, version);

                //set the zoom and offsets and trigger events
                //to get the view to position iteself
                CurrentWorkspace.X = cx;
                CurrentWorkspace.Y = cy;
                CurrentWorkspace.Zoom = zoom;

                var vm = dynSettings.Controller.DynamoViewModel.Workspaces.First(x => x.Model == CurrentWorkspace);
                vm.OnCurrentOffsetChanged(this, new PointEventArgs(new Point(cx, cy)));

                XmlNodeList elNodes = xmlDoc.GetElementsByTagName("Elements");
                XmlNodeList cNodes = xmlDoc.GetElementsByTagName("Connectors");
                XmlNodeList nNodes = xmlDoc.GetElementsByTagName("Notes");

                if (elNodes.Count == 0)
                    elNodes = xmlDoc.GetElementsByTagName("dynElements");
                if (cNodes.Count == 0)
                    cNodes = xmlDoc.GetElementsByTagName("dynConnectors");
                if (nNodes.Count == 0)
                    nNodes = xmlDoc.GetElementsByTagName("dynNotes");

                XmlNode elNodesList = elNodes[0];
                XmlNode cNodesList = cNodes[0];
                XmlNode nNodesList = nNodes[0];

                //if there is any problem loading a node, then
                //add the node's guid to the bad nodes collection
                //so we can avoid attempting to make connections to it
                List<Guid> badNodes = new List<Guid>();

                foreach (XmlNode elNode in elNodesList.ChildNodes)
                {
                    XmlAttribute typeAttrib = elNode.Attributes["type"];
                    XmlAttribute guidAttrib = elNode.Attributes["guid"];
                    XmlAttribute nicknameAttrib = elNode.Attributes["nickname"];
                    XmlAttribute xAttrib = elNode.Attributes["x"];
                    XmlAttribute yAttrib = elNode.Attributes["y"];
                    XmlAttribute isVisAttrib = elNode.Attributes["isVisible"];
                    XmlAttribute isUpstreamVisAttrib = elNode.Attributes["isUpstreamVisible"];
                    XmlAttribute lacingAttrib = elNode.Attributes["lacing"];

                    string typeName = typeAttrib.Value;

                    //test the GUID to confirm that it is non-zero
                    //if it is zero, then we have to fix it
                    //this will break the connectors, but it won't keep
                    //propagating bad GUIDs
                    var guid = new Guid(guidAttrib.Value);
                    if (guid == Guid.Empty)
                    {
                        guid = Guid.NewGuid();
                    }

                    string nickname = nicknameAttrib.Value;

                    double x = double.Parse(xAttrib.Value, CultureInfo.InvariantCulture);
                    double y = double.Parse(yAttrib.Value, CultureInfo.InvariantCulture);

                    typeName = Dynamo.Nodes.Utilities.PreprocessTypeName(typeName);
                    System.Type type = Dynamo.Nodes.Utilities.ResolveType(typeName);
                    if (null == type)
                    {
                        badNodes.Add(guid);
                        continue;
                    }

                    bool isVisible = true;
                    if (isVisAttrib != null)
                        isVisible = isVisAttrib.Value == "true" ? true : false;

                    bool isUpstreamVisible = true;
                    if (isUpstreamVisAttrib != null)
                        isUpstreamVisible = isUpstreamVisAttrib.Value == "true" ? true : false;

                    NodeModel el = CreateNodeInstance(type, nickname, guid);
                    el.WorkSpace = CurrentWorkspace;

                    el.Load(
                        elNode,
                        string.IsNullOrEmpty(version)
                            ? new Version(0, 0, 0, 0)
                            : new Version(version));

                    CurrentWorkspace.Nodes.Add(el);

                    OnNodeAdded(el);

                    el.X = x;
                    el.Y = y;

                    el.isVisible = isVisible;
                    el.isUpstreamVisible = isUpstreamVisible;

                    if (lacingAttrib != null)
                    {
                        if (el.ArgumentLacing != LacingStrategy.Disabled)
                        {
                            LacingStrategy lacing = LacingStrategy.Disabled;
                            Enum.TryParse(lacingAttrib.Value, out lacing);
                            el.ArgumentLacing = lacing;
                        }
                    }

                    el.DisableReporting();

                    if (CurrentWorkspace == HomeSpace)
                        el.SaveResult = true;
                }

                DynamoLogger.Instance.Log(string.Format("{0} ellapsed for loading nodes.", sw.Elapsed - previousElapsed));
                previousElapsed = sw.Elapsed;

                //OnRequestLayoutUpdate(this, EventArgs.Empty);

                //DynamoLogger.Instance.Log(string.Format("{0} ellapsed for updating layout.", sw.Elapsed - previousElapsed));
                //previousElapsed = sw.Elapsed;

                foreach (XmlNode connector in cNodesList.ChildNodes)
                {
                    XmlAttribute guidStartAttrib = connector.Attributes[0];
                    XmlAttribute intStartAttrib = connector.Attributes[1];
                    XmlAttribute guidEndAttrib = connector.Attributes[2];
                    XmlAttribute intEndAttrib = connector.Attributes[3];
                    XmlAttribute portTypeAttrib = connector.Attributes[4];

                    var guidStart = new Guid(guidStartAttrib.Value);
                    var guidEnd = new Guid(guidEndAttrib.Value);
                    int startIndex = Convert.ToInt16(intStartAttrib.Value);
                    int endIndex = Convert.ToInt16(intEndAttrib.Value);
                    PortType portType = ((PortType)Convert.ToInt16(portTypeAttrib.Value));

                    //find the elements to connect
                    NodeModel start = null;
                    NodeModel end = null;

                    if (badNodes.Contains(guidStart) || badNodes.Contains(guidEnd))
                        continue;

                    foreach (NodeModel e in Nodes)
                    {
                        if (e.GUID == guidStart)
                        {
                            start = e;
                        }
                        else if (e.GUID == guidEnd)
                        {
                            end = e;
                        }
                        if (start != null && end != null)
                        {
                            break;
                        }
                    }

                    var newConnector = ConnectorModel.Make(start, end,
                        startIndex, endIndex, portType);

                    if (newConnector != null)
                        CurrentWorkspace.Connectors.Add(newConnector);

                    OnConnectorAdded(newConnector);
                }

                DynamoLogger.Instance.Log(string.Format("{0} ellapsed for loading connectors.", sw.Elapsed - previousElapsed));
                previousElapsed = sw.Elapsed;

                #region instantiate notes

                if (nNodesList != null)
                {
                    foreach (XmlNode note in nNodesList.ChildNodes)
                    {
                        XmlAttribute textAttrib = note.Attributes[0];
                        XmlAttribute xAttrib = note.Attributes[1];
                        XmlAttribute yAttrib = note.Attributes[2];

                        string text = textAttrib.Value;
                        double x = double.Parse(xAttrib.Value, CultureInfo.InvariantCulture);
                        double y = double.Parse(yAttrib.Value, CultureInfo.InvariantCulture);

                        // TODO(Ben): Shouldn't we be reading in the Guid
                        // from file instead of generating a new one here?
                        Guid id = Guid.NewGuid();
                        var command = new DynCmd.CreateNoteCommand(id, text, x, y, false);
                        AddNoteInternal(command, CurrentWorkspace);
                    }
                }

                #endregion

                DynamoLogger.Instance.Log(string.Format("{0} ellapsed for loading notes.", sw.Elapsed - previousElapsed));

                foreach (NodeModel e in CurrentWorkspace.Nodes)
                    e.EnableReporting();

                // http://www.japf.fr/2009/10/measure-rendering-time-in-a-wpf-application/comment-page-1/#comment-2892
                Dispatcher.CurrentDispatcher.BeginInvoke(
                    DispatcherPriority.Background,
                    new Action(() =>
                    {
                        sw.Stop();
                        DynamoLogger.Instance.Log(string.Format("{0} ellapsed for loading workspace.", sw.Elapsed));
                    }));

                #endregion

                HomeSpace.FileName = xmlPath;
            }
            catch (Exception ex)
            {
                DynamoLogger.Instance.Log("There was an error opening the workbench.");
                DynamoLogger.Instance.Log(ex);
                Debug.WriteLine(ex.Message + ":" + ex.StackTrace);
                CleanWorkbench();
                return false;
            }
            CurrentWorkspace.HasUnsavedChanges = false;
            return true;
        }