示例#1
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, DynamoController controller, out FunctionDefinition def)
        {
            try
            {
                var xmlPath = GetNodePath(funcDefGuid);

                #region read xml file

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

                string funName     = null;
                string category    = "";
                string description = "";
                double cx          = DynamoView.CANVAS_OFFSET_X;
                double cy          = DynamoView.CANVAS_OFFSET_Y;
                double zoom        = 1.0;
                string id          = "";

                // load the header
                foreach (XmlNode node in xmlDoc.GetElementsByTagName("dynWorkspace"))
                {
                    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;
                        }
                    }
                }

                // 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);

                var ws = new FuncWorkspace(
                    funName, category.Length > 0
                    ? category
                    : BuiltinNodeCategories.SCRIPTING_CUSTOMNODES, description, cx, cy)
                {
                    WatchChanges = false
                };

                ws.Zoom = zoom;

                def = new FunctionDefinition(Guid.Parse(id))
                {
                    Workspace = 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);
                this.loadedNodes.Add(def.FunctionId, def);

                XmlNodeList elNodes = xmlDoc.GetElementsByTagName("dynElements");
                XmlNodeList cNodes  = xmlDoc.GetElementsByTagName("dynConnectors");
                XmlNodeList 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;

                    const string oldNamespace = "Dynamo.Elements.";
                    if (typeName.StartsWith(oldNamespace))
                    {
                        typeName = "Dynamo.Nodes." + typeName.Remove(0, oldNamespace.Length);
                    }

                    //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;
                    }

                    //Type t = Type.GetType(typeName);
                    TypeLoadData tData;
                    Type         t;

                    if (!controller.BuiltInTypesByName.TryGetValue(typeName, out tData))
                    {
                        //try and get a system type by this name
                        t = Type.GetType(typeName);

                        //if we still can't find the type, try the also known as attributes
                        if (t == null)
                        {
                            //try to get the also known as values
                            foreach (KeyValuePair <string, TypeLoadData> kvp in controller.BuiltInTypesByName)
                            {
                                var akaAttribs = kvp.Value.Type.GetCustomAttributes(typeof(AlsoKnownAsAttribute), false);
                                if (akaAttribs.Any())
                                {
                                    if ((akaAttribs[0] as AlsoKnownAsAttribute).Values.Contains(typeName))
                                    {
                                        controller.DynamoViewModel.Log(string.Format("Found matching node for {0} also known as {1}", kvp.Key, typeName));
                                        t = kvp.Value.Type;
                                    }
                                }
                            }
                        }

                        if (t == null)
                        {
                            controller.DynamoViewModel.Log("Could not load node of type: " + typeName);
                            controller.DynamoViewModel.Log("Loading will continue but nodes might be missing from your workflow.");

                            //return false;
                            badNodes.Add(guid);
                            continue;
                        }
                    }
                    else
                    {
                        t = tData.Type;
                    }

                    dynNodeModel el = dynSettings.Controller.DynamoViewModel.CreateNodeInstance(t, nickname, guid);

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

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

                    // note - this is because the connectors fail to be created if there's not added
                    // to the canvas
                    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); // inject the node properties from the xml

                    // moved this logic to LoadNode in dynFunction --SJE

                    //if (el is dynFunction)
                    //{
                    //    var fun = el as dynFunction;

                    //    // we've found a custom node, we need to attempt to load its guid.
                    //    // if it doesn't exist (i.e. its a legacy node), we need to assign it one,
                    //    // deterministically
                    //    Guid funId;
                    //    try
                    //    {
                    //        funId = Guid.Parse(fun.Symbol);
                    //    }
                    //    catch
                    //    {
                    //        funId = GuidUtility.Create(GuidUtility.UrlNamespace, nicknameAttrib.Value);
                    //        fun.Symbol = funId.ToString();
                    //    }

                    //    // if it's not a recurisve node and it's not yet loaded, load it
                    //    if (funcDefGuid != funId && !this.loadedNodes.ContainsKey(funId))
                    //    {
                    //        dynSettings.Controller.CustomNodeLoader.GetFunctionDefinition(funId);
                    //        fun.Definition = this.loadedNodes[funId];
                    //    }
                    //    else if ( this.loadedNodes.ContainsKey(funId ))
                    //    {
                    //        fun.Definition = this.loadedNodes[funId];
                    //    }

                    //}
                }

                #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);
                    int portType   = Convert.ToInt16(portTypeAttrib.Value);

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

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

                    foreach (dynNodeModel 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 = dynConnectorModel.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));
                    }
                }

                #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);
                        double y    = Convert.ToDouble(yAttrib.Value);

                        //dynNoteView n = Bench.AddNote(text, x, y, ws);
                        //Bench.AddNote(text, x, y, ws);

                        var paramDict = new Dictionary <string, object>();
                        paramDict.Add("x", x);
                        paramDict.Add("y", y);
                        paramDict.Add("text", text);
                        paramDict.Add("workspace", ws);
                        dynSettings.Controller.DynamoViewModel.AddNoteCommand.Execute(paramDict);
                    }
                }

                #endregion

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

                ws.FilePath = xmlPath;

                var expression = CompileFunction(def);
                controller.FSchemeEnvironment.DefineSymbol(def.FunctionId.ToString(), expression);

                ws.WatchChanges = true;
            }
            catch (Exception ex)
            {
                DynamoCommands.WriteToLogCmd.Execute("There was an error opening the workbench.");
                DynamoCommands.WriteToLogCmd.Execute(ex);

                if (controller.Testing)
                {
                    Assert.Fail(ex.Message);
                }

                def = null;
                return(false);
            }

            return(true);
        }
示例#2
0
        /// <summary>
        ///     Collapse a set of nodes in a given workspace.  Has the side effects of prompting the user
        ///     first in order to obtain the name and category for the new node,
        ///     writes the function to a dyf file, adds it to the FunctionDict, adds it to search, and compiles and
        ///     places the newly created symbol (defining a lambda) in the Controller's FScheme Environment.
        /// </summary>
        /// <param name="selectedNodes"> The function definition for the user-defined node </param>
        /// <param name="currentWorkspace"> The workspace where</param>
        internal static void Collapse(IEnumerable <dynNodeModel> selectedNodes, dynWorkspaceModel currentWorkspace)
        {
            var selectedNodeSet = new HashSet <dynNodeModel>(selectedNodes);

            //First, prompt the user to enter a name
            string newNodeName = "", newNodeCategory = "", newNodeDescription = "A collapsed node";

            if (!dynSettings.Controller.DynamoViewModel.ShowNewFunctionDialog(ref newNodeName, ref newNodeCategory, ref newNodeDescription))
            {
                return;
            }

            var newNodeWorkspace = new FuncWorkspace(newNodeName, newNodeCategory, newNodeDescription, 0, 0)
            {
                WatchChanges = false
            };

            var newNodeDefinition = new FunctionDefinition(Guid.NewGuid())
            {
                Workspace = newNodeWorkspace
            };

            currentWorkspace.DisableReporting();

            #region Determine Inputs and Outputs

            //Step 1: determine which nodes will be inputs to the new node
            var inputs = new HashSet <Tuple <dynNodeModel, int, Tuple <int, dynNodeModel> > >(
                selectedNodeSet.SelectMany(
                    node => Enumerable.Range(0, node.InPortData.Count).Where(node.HasInput)
                    .Select(data => Tuple.Create(node, data, node.Inputs[data]))
                    .Where(input => !selectedNodeSet.Contains(input.Item3.Item2))));

            var outputs = new HashSet <Tuple <dynNodeModel, int, Tuple <int, dynNodeModel> > >(
                selectedNodeSet.SelectMany(
                    node => Enumerable.Range(0, node.OutPortData.Count).Where(node.HasOutput).SelectMany(
                        data => node.Outputs[data]
                        .Where(output => !selectedNodeSet.Contains(output.Item2))
                        .Select(output => Tuple.Create(node, data, output)))));

            #endregion

            #region Detect 1-node holes (higher-order function extraction)

            var curriedNodeArgs =
                new HashSet <dynNodeModel>(
                    inputs
                    .Select(x => x.Item3.Item2)
                    .Intersect(outputs.Select(x => x.Item3.Item2)))
                .Select(
                    outerNode =>
            {
                var node = new dynApply1();

                //MVVM : Don't make direct reference to view here
                //MVVM: no reference to view here
                //dynNodeView nodeUI = node.NodeUI;

                var elNameAttrib =
                    node.GetType().GetCustomAttributes(typeof(NodeNameAttribute), true)[0] as
                    NodeNameAttribute;
                if (elNameAttrib != null)
                {
                    node.NickName = elNameAttrib.Name;
                }

                node.GUID = Guid.NewGuid();

                //store the element in the elements list
                newNodeWorkspace.Nodes.Add(node);
                node.WorkSpace = newNodeWorkspace;

                node.DisableReporting();

                //MVVM : Can't set view location here

                //dynSettings.Bench.WorkBench.Children.Add(nodeUI);

                //Place it in an appropriate spot
                //Canvas.SetLeft(nodeUI, Canvas.GetLeft(outerNode.NodeUI));
                //Canvas.SetTop(nodeUI, Canvas.GetTop(outerNode.NodeUI));
                node.X = outerNode.X;
                node.Y = outerNode.Y;

                //Fetch all input ports
                // in order
                // that have inputs
                // and whose input comes from an inner node
                List <int> inPortsConnected = Enumerable.Range(0, outerNode.InPortData.Count)
                                              .Where(
                    x =>
                    outerNode.HasInput(x) &&
                    selectedNodeSet.Contains(
                        outerNode.Inputs[x].Item2))
                                              .ToList();

                var nodeInputs = outputs
                                 .Where(output => output.Item3.Item2 == outerNode)
                                 .Select(
                    output =>
                    new
                {
                    InnerNodeInputSender = output.Item1,
                    OuterNodeInPortData  = output.Item3.Item1
                }).ToList();

                nodeInputs.ForEach(_ => node.AddInput());

                node.RegisterAllPorts();

                //MVVM: don't call update layout here
                //dynSettings.Bench.WorkBench.UpdateLayout();

                return(new
                {
                    OuterNode = outerNode,
                    InnerNode = node,
                    Outputs = inputs.Where(input => input.Item3.Item2 == outerNode)
                              .Select(input => input.Item3.Item1),
                    Inputs = nodeInputs,
                    OuterNodePortDataList = inPortsConnected
                });
            }).ToList();

            #endregion

            #region UI Positioning Calculations

            double avgX = selectedNodeSet.Average(node => node.X);
            double avgY = selectedNodeSet.Average(node => node.Y);

            double leftMost  = selectedNodeSet.Min(node => node.X);
            double topMost   = selectedNodeSet.Min(node => node.Y);
            double rightMost = selectedNodeSet.Max(node => node.X + node.Width);

            #endregion

            #region Move selection to new workspace

            var connectors = new HashSet <dynConnectorModel>(currentWorkspace.Connectors.Where(
                                                                 conn => selectedNodeSet.Contains(conn.Start.Owner) &&
                                                                 selectedNodeSet.Contains(conn.End.Owner)));

            //Step 2: move all nodes to new workspace
            //  remove from old
            foreach (var ele in selectedNodeSet)
            {
                currentWorkspace.Nodes.Remove(ele);
            }
            foreach (var ele in connectors)
            {
                currentWorkspace.Connectors.Remove(ele);
            }

            //  add to new
            newNodeWorkspace.Nodes.AddRange(selectedNodeSet);
            newNodeWorkspace.Connectors.AddRange(connectors);

            double leftShift = leftMost - 250;
            foreach (dynNodeModel node in newNodeWorkspace.Nodes)
            {
                node.X = node.X - leftShift;
                node.Y = node.Y - topMost;
            }

            #endregion

            #region Insert new node into the current workspace

            //Step 5: insert new node into original workspace
            var collapsedNode = dynSettings.Controller.DynamoViewModel.CreateFunction(
                inputs.Select(x => x.Item1.InPortData[x.Item2].NickName),
                outputs
                .Where(x => !curriedNodeArgs.Any(y => y.OuterNode == x.Item3.Item2))
                .Select(x => x.Item1.OutPortData[x.Item2].NickName),
                newNodeDefinition);

            collapsedNode.GUID = Guid.NewGuid();

            currentWorkspace.Nodes.Add(collapsedNode);
            collapsedNode.WorkSpace = currentWorkspace;

            collapsedNode.X = avgX;
            collapsedNode.Y = avgY;

            #endregion

            #region Destroy all hanging connectors

            //Step 6: connect inputs and outputs

            var removeConnectors = currentWorkspace.Connectors.Where(c =>
                                                                     selectedNodeSet.Contains(c.Start.Owner) ||
                                                                     selectedNodeSet.Contains(c.End.Owner))
                                   .ToList();
            foreach (dynConnectorModel connector in removeConnectors)
            {
                connector.NotifyConnectedPortsOfDeletion();
                currentWorkspace.Connectors.Remove(connector);
            }

            #endregion

            newNodeWorkspace.Nodes.ToList().ForEach(x => x.DisableReporting());

            var inConnectors = new List <Tuple <dynNodeModel, int, int> >();

            #region Process inputs

            var uniqueInputSenders = new Dictionary <Tuple <dynNodeModel, int>, dynSymbol>();

            //Step 3: insert variables (reference step 1)
            foreach (var input in Enumerable.Range(0, inputs.Count).Zip(inputs, Tuple.Create))
            {
                int inputIndex = input.Item1;

                dynNodeModel inputReceiverNode = input.Item2.Item1;
                int          inputReceiverData = input.Item2.Item2;

                dynNodeModel inputNode = input.Item2.Item3.Item2;
                int          inputData = input.Item2.Item3.Item1;

                dynSymbol node;

                var key = Tuple.Create(inputNode, inputData);
                if (uniqueInputSenders.ContainsKey(key))
                {
                    node = uniqueInputSenders[key];
                }
                else
                {
                    //MVVM : replace NodeUI reference with node
                    inConnectors.Add(Tuple.Create(inputNode, inputData, inputIndex));

                    //Create Symbol Node
                    node = new dynSymbol
                    {
                        Symbol = inputReceiverNode.InPortData[inputReceiverData].NickName
                    };

                    //MVVM : Don't make direct reference to view here
                    //dynNodeView nodeUI = node.NodeUI;

                    var elNameAttrib =
                        node.GetType().GetCustomAttributes(typeof(NodeNameAttribute), true)[0] as NodeNameAttribute;
                    if (elNameAttrib != null)
                    {
                        node.NickName = elNameAttrib.Name;
                    }

                    node.GUID = Guid.NewGuid();

                    //store the element in the elements list
                    newNodeWorkspace.Nodes.Add(node);
                    node.WorkSpace = newNodeWorkspace;

                    node.DisableReporting();

                    //MVVM : Do not add view directly to canvas

                    /*dynSettings.Bench.WorkBench.Children.Add(nodeUI);
                     *
                     * //Place it in an appropriate spot
                     * Canvas.SetLeft(nodeUI, 0);
                     * Canvas.SetTop(nodeUI, inputIndex * (50 + node.NodeUI.Height));
                     *
                     * dynSettings.Bench.WorkBench.UpdateLayout();*/
                    node.X = 0;
                    node.Y = inputIndex * (50 + node.Height);

                    uniqueInputSenders[key] = node;
                }

                var curriedNode = curriedNodeArgs.FirstOrDefault(x => x.OuterNode == inputNode);

                if (curriedNode == null)
                {
                    var conn1 = dynConnectorModel.Make(node,
                                                       inputReceiverNode,
                                                       0,
                                                       inputReceiverData,
                                                       0);

                    if (conn1 != null)
                    {
                        newNodeWorkspace.Connectors.Add(conn1);
                    }
                }
                else
                {
                    //Connect it to the applier
                    var conn = dynConnectorModel.Make(node,
                                                      curriedNode.InnerNode,
                                                      0,
                                                      0,
                                                      0);
                    if (conn != null)
                    {
                        newNodeWorkspace.Connectors.Add(conn);
                    }

                    //Connect applier to the inner input receive
                    var conn2 = dynConnectorModel.Make(
                        curriedNode.InnerNode,
                        inputReceiverNode,
                        0,
                        inputReceiverData,
                        0);

                    if (conn2 != null)
                    {
                        newNodeWorkspace.Connectors.Add(conn2);
                    }
                }
            }

            #endregion

            #region Process outputs

            //List of all inner nodes to connect an output. Unique.
            var outportList = new List <Tuple <dynNodeModel, int> >();

            var outConnectors = new List <Tuple <dynNodeModel, int, int> >();

            int i = 0;
            foreach (var output in outputs)
            {
                if (outportList.All(x => !(x.Item1 == output.Item1 && x.Item2 == output.Item2)))
                {
                    dynNodeModel outputSenderNode   = output.Item1;
                    int          outputSenderData   = output.Item2;
                    dynNodeModel outputReceiverNode = output.Item3.Item2;

                    if (curriedNodeArgs.Any(x => x.OuterNode == outputReceiverNode))
                    {
                        continue;
                    }

                    outportList.Add(Tuple.Create(outputSenderNode, outputSenderData));

                    //Create Symbol Node
                    var node = new dynOutput
                    {
                        Symbol = outputSenderNode.OutPortData[outputSenderData].NickName
                    };

                    //dynNodeView nodeUI = node.NodeUI;

                    var elNameAttrib =
                        node.GetType().GetCustomAttributes(typeof(NodeNameAttribute), false)[0] as NodeNameAttribute;
                    if (elNameAttrib != null)
                    {
                        node.NickName = elNameAttrib.Name;
                    }

                    node.GUID = Guid.NewGuid();

                    //store the element in the elements list
                    newNodeWorkspace.Nodes.Add(node);
                    node.WorkSpace = newNodeWorkspace;

                    node.DisableReporting();

                    //MVVM : Do not add view directly to canvas

                    /*dynSettings.Bench.WorkBench.Children.Add(nodeUI);
                     *
                     * //Place it in an appropriate spot
                     * Canvas.SetLeft(nodeUI, rightMost + 75 - leftShift);
                     * Canvas.SetTop(nodeUI, i * (50 + node.NodeUI.Height));
                     *
                     * dynSettings.Bench.WorkBench.UpdateLayout();*/

                    node.X = rightMost + 75 - leftShift;
                    node.Y = i * (50 + node.Height);

                    var conn = dynConnectorModel.Make(
                        outputSenderNode,
                        node,
                        outputSenderData,
                        0,
                        0);

                    if (conn != null)
                    {
                        newNodeWorkspace.Connectors.Add(conn);
                    }

                    i++;
                }
            }

            //Connect outputs to new node
            foreach (var output in outputs)
            {
                //Node to be connected to in CurrentSpace
                dynNodeModel outputSenderNode = output.Item1;

                //Port to be connected to on outPutNode_outer
                int outputSenderData = output.Item2;

                int          outputReceiverData = output.Item3.Item1;
                dynNodeModel outputReceiverNode = output.Item3.Item2;

                var curriedNode = curriedNodeArgs.FirstOrDefault(
                    x => x.OuterNode == outputReceiverNode);

                if (curriedNode == null)
                {
                    // we create the connectors in the current space later
//MVVM : replaced multiple dynNodeView refrences with dynNode
                    outConnectors.Add(
                        Tuple.Create(
                            outputReceiverNode,
                            outportList.FindIndex(
                                x => x.Item1 == outputSenderNode && x.Item2 == outputSenderData),
                            outputReceiverData));
                }
                else
                {
                    int targetPort = curriedNode.Inputs
                                     .First(
                        x => x.InnerNodeInputSender == outputSenderNode)
                                     .OuterNodeInPortData;

                    int targetPortIndex = curriedNode.OuterNodePortDataList.IndexOf(targetPort);

                    //Connect it (new dynConnector)

                    var conn = dynConnectorModel.Make(
                        outputSenderNode,
                        curriedNode.InnerNode,
                        outputSenderData,
                        targetPortIndex + 1,
                        0);

                    if (conn != null)
                    {
                        newNodeWorkspace.Connectors.Add(conn);
                    }
                }
            }

            #endregion

            //set the name on the node
            collapsedNode.NickName = newNodeName;
            currentWorkspace.Nodes.Remove(collapsedNode);

            // save and load the definition from file
            var customNodeInfo = new CustomNodeInfo(newNodeDefinition.FunctionId, newNodeName, newNodeCategory, "", "");
            dynSettings.Controller.CustomNodeManager.SetNodeInfo(customNodeInfo);
            var path = dynSettings.Controller.DynamoViewModel.SaveFunctionOnly(newNodeDefinition);
            dynSettings.Controller.CustomNodeManager.SetNodePath(newNodeDefinition.FunctionId, path);
            dynSettings.Controller.SearchViewModel.Add(newNodeName, newNodeCategory, "No description provided", newNodeDefinition.FunctionId);

            dynSettings.Controller.DynamoViewModel.CreateNodeCommand.Execute(new Dictionary <string, object>()
            {
                { "name", collapsedNode.Definition.FunctionId.ToString() },
                { "x", avgX },
                { "y", avgY }
            });

            var newlyPlacedCollapsedNode = currentWorkspace.Nodes
                                           .Where(node => node is dynFunction)
                                           .First(node => ((dynFunction)node).Definition.FunctionId == newNodeDefinition.FunctionId);

            // place the node as intended, not centered
            newlyPlacedCollapsedNode.X = avgX;
            newlyPlacedCollapsedNode.Y = avgY;

            newlyPlacedCollapsedNode.DisableReporting();

            foreach (var nodeTuple in inConnectors)
            {
                var conn = dynConnectorModel.Make(
                    nodeTuple.Item1,
                    newlyPlacedCollapsedNode,
                    nodeTuple.Item2,
                    nodeTuple.Item3,
                    0);

                if (conn != null)
                {
                    currentWorkspace.Connectors.Add(conn);
                }
            }

            foreach (var nodeTuple in outConnectors)
            {
                var conn = dynConnectorModel.Make(
                    newlyPlacedCollapsedNode,
                    nodeTuple.Item1,
                    nodeTuple.Item2,
                    nodeTuple.Item3,
                    0);

                if (conn != null)
                {
                    currentWorkspace.Connectors.Add(conn);
                }
            }

            newlyPlacedCollapsedNode.EnableReporting();
            currentWorkspace.EnableReporting();

            newNodeWorkspace.WatchChanges = true;
        }
示例#3
0
        internal FunctionDefinition NewFunction(Guid id, 
                                                string name, 
                                                string category, 
                                                bool display, 
                                                double workspaceOffsetX = dynBench.CANVAS_OFFSET_X, 
                                                double workspaceOffsetY = dynBench.CANVAS_OFFSET_Y )
        {
            //Add an entry to the funcdict
            var workSpace = new FuncWorkspace(
                name, category, workspaceOffsetX, workspaceOffsetY);

            List<dynNode> newElements = workSpace.Nodes;
            List<dynConnector> newConnectors = workSpace.Connectors;

            var functionDefinition = new FunctionDefinition(id)
                {
                    Workspace = workSpace
                };

            this.CustomNodeLoader.AddFunctionDefinition(functionDefinition.FunctionId, functionDefinition);

            // add the element to search
            SearchViewModel.Add(workSpace);

            if (display)
            {
                if (!ViewingHomespace)
                {
                    var def = dynSettings.Controller.CustomNodeLoader.GetDefinitionFromWorkspace(CurrentSpace);
                    if (def != null)
                        SaveFunction( def );
                }

                DynamoController.hideWorkspace(CurrentSpace);
                CurrentSpace = workSpace;

                Bench.homeButton.IsEnabled = true;

                Bench.workspaceLabel.Content = CurrentSpace.Name;

                Bench.editNameButton.Visibility = Visibility.Visible;
                Bench.editNameButton.IsHitTestVisible = true;
                Bench.setFunctionBackground();
                dynSettings.ReturnFocusToSearch();
            }

            return functionDefinition;
        }
示例#4
0
        internal dynWorkspace NewFunction(string name, string category, bool display)
        {
            //Add an entry to the funcdict
            var workSpace = new FuncWorkspace(name, category, dynBench.CANVAS_OFFSET_X, dynBench.CANVAS_OFFSET_Y);

            var newElements = workSpace.Nodes;
            var newConnectors = workSpace.Connectors;

            this.FunctionDict[name] = workSpace;

            //Add an entry to the View menu
            System.Windows.Controls.MenuItem i = new System.Windows.Controls.MenuItem();
            i.Header = name;
            i.Click += new RoutedEventHandler(Bench.ChangeView_Click);
            Bench.viewMenu.Items.Add(i);
            Bench.viewMenuItemsDict[name] = i;

            //Add an entry to the Add menu
            //System.Windows.Controls.MenuItem mi = new System.Windows.Controls.MenuItem();
            //mi.Header = name;
            //mi.Click += new RoutedEventHandler(AddElement_Click);
            //AddMenu.Items.Add(mi);
            //this.addMenuItemsDict[name] = mi;

            dynFunction newEl = new dynFunction(
               workSpace.Nodes.Where(el => el is dynSymbol)
                  .Select(s => ((dynSymbol)s).Symbol),
               new List<String>() { "out" },
               name
            );

            newEl.NodeUI.DisableInteraction();
            newEl.NodeUI.MouseDown += delegate
            {
                Bench.BeginDragElement(newEl.NodeUI, name, Mouse.GetPosition(newEl.NodeUI));

                newEl.NodeUI.Visibility = System.Windows.Visibility.Hidden;
            };
            newEl.NodeUI.GUID = Guid.NewGuid();
            newEl.NodeUI.Margin = new Thickness(5, 30, 5, 5);
            newEl.NodeUI.LayoutTransform = new ScaleTransform(.8, .8);
            newEl.NodeUI.State = ElementState.DEAD;

            Expander expander;

            if (Bench.addMenuCategoryDict.ContainsKey(category))
            {
                expander = Bench.addMenuCategoryDict[category];
            }
            else
            {
                expander = new Expander()
                {
                    Header = category,
                    Height = double.NaN,
                    Margin = new Thickness(0, 5, 0, 0),
                    Content = new WrapPanel()
                    {
                        Height = double.NaN,
                        Width = 240
                    },
                    HorizontalAlignment = System.Windows.HorizontalAlignment.Left,
                    //FontWeight = FontWeights.Bold
                };

                Bench.addMenuCategoryDict[category] = expander;

                var sortedExpanders = new SortedList<string, Expander>();
                foreach (Expander child in Bench.SideStackPanel.Children)
                {
                    sortedExpanders.Add((string)child.Header, child);
                }
                sortedExpanders.Add(category, expander);

                Bench.SideStackPanel.Children.Clear();

                foreach (Expander child in sortedExpanders.Values)
                {
                    Bench.SideStackPanel.Children.Add(child);
                }
            }

            var wp = (WrapPanel)expander.Content;

            var sortedElements = new SortedList<string, dynNodeUI>();
            foreach (dynNodeUI child in wp.Children)
            {
                sortedElements.Add(child.NickName, child);
            }
            sortedElements.Add(name, newEl.NodeUI);

            wp.Children.Clear();

            foreach (dynNodeUI child in sortedElements.Values)
            {
                wp.Children.Add(child);
            }

            Bench.addMenuItemsDictNew[name] = newEl.NodeUI;
            searchDict.Add(newEl.NodeUI, name.Split(' ').Where(x => x.Length > 0));

            if (display)
            {
                //Store old workspace
                //var ws = new dynWorkspace(this.elements, this.connectors, this.CurrentX, this.CurrentY);

                if (!this.ViewingHomespace)
                {
                    //Step 2: Store function workspace in the function dictionary
                    this.FunctionDict[this.CurrentSpace.Name] = this.CurrentSpace;

                    //Step 3: Save function
                    this.SaveFunction(this.CurrentSpace);
                }

                //Make old workspace invisible
                foreach (dynNode dynE in this.Nodes)
                {
                    dynE.NodeUI.Visibility = System.Windows.Visibility.Collapsed;
                }
                foreach (dynConnector dynC in this.CurrentSpace.Connectors)
                {
                    dynC.Visible = false;
                }
                foreach (dynNote note in this.CurrentSpace.Notes)
                {
                    note.Visibility = System.Windows.Visibility.Hidden;
                }

                //this.currentFunctionName = name;

                ////Clear the bench for the new function
                //this.elements = newElements;
                //this.connectors = newConnectors;
                //this.CurrentX = CANVAS_OFFSET_X;
                //this.CurrentY = CANVAS_OFFSET_Y;
                this.CurrentSpace = workSpace;

                //this.saveFuncItem.IsEnabled = true;
                Bench.homeButton.IsEnabled = true;
                //this.varItem.IsEnabled = true;

                Bench.workspaceLabel.Content = this.CurrentSpace.Name;
                Bench.editNameButton.Visibility = System.Windows.Visibility.Visible;
                Bench.editNameButton.IsHitTestVisible = true;
                Bench.setFunctionBackground();
            }

            return workSpace;
        }