Esempio n. 1
0
        private void GetUpstreamIDrawable(List <IDrawable> drawables, Dictionary <int, Tuple <int, dynNodeModel> > inputs)
        {
            foreach (KeyValuePair <int, Tuple <int, dynNodeModel> > pair in inputs)
            {
                if (pair.Value == null)
                {
                    continue;
                }

                dynNodeModel node     = pair.Value.Item2;
                IDrawable    drawable = node as IDrawable;

                if (node.IsVisible && drawable != null)
                {
                    drawables.Add(drawable);
                }

                if (node.IsUpstreamVisible)
                {
                    GetUpstreamIDrawable(drawables, node.Inputs);
                }
                else
                {
                    continue; // don't bother checking if function
                }
                //if the node is function then get all the
                //drawables inside that node. only do this if the
                //node's workspace is the home space to avoid infinite
                //recursion in the case of custom nodes in custom nodes
                if (node is dynFunction && node.WorkSpace == dynSettings.Controller.DynamoModel.HomeSpace)
                {
                    dynFunction func = (dynFunction)node;
                    IEnumerable <dynNodeModel> topElements = func.Definition.Workspace.GetTopMostNodes();
                    foreach (dynNodeModel innerNode in topElements)
                    {
                        GetUpstreamIDrawable(drawables, innerNode.Inputs);
                    }
                }
            }
        }
Esempio n. 2
0
        /// <summary>
        ///     Get a dynFunction from a guid, also stores type internally info for future instantiation.
        ///     And add the compiled node to the enviro
        ///     As a side effect, any of its dependent nodes are also initialized.
        /// </summary>
        /// <param name="environment">The environment from which to get the </param>
        /// <param name="guid">Open a definition from a path, without instantiating the nodes or dependents</param>
        public bool GetNodeInstance(DynamoController controller, Guid guid, out dynFunction result)
        {
            if ( !this.Contains(guid) ) {
                result = null;
                return false;
            }

            FunctionDefinition def = null;
            if (!this.IsInitialized(guid))
            {
                if (!GetDefinitionFromPath(guid, controller, out def))
                {
                    result = null;
                    return false;
                }
            } else {
                def = this.loadedNodes[guid];
            }

            dynWorkspace ws = def.Workspace;

            //TODO: Update to base off of Definition

                IEnumerable<string> inputs =
                    ws.Nodes.Where(e => e is dynSymbol)
                        .Select(s => (s as dynSymbol).Symbol);

                IEnumerable<string> outputs =
                    ws.Nodes.Where(e => e is dynOutput)
                        .Select(o => (o as dynOutput).Symbol);

                if (!outputs.Any())
                {
                    var topMost = new List<Tuple<int, dynNode>>();

                    IEnumerable<dynNode> topMostNodes = ws.GetTopMostNodes();

                    foreach (dynNode topNode in topMostNodes)
                    {
                        foreach (int output in Enumerable.Range(0, topNode.OutPortData.Count))
                        {
                            if (!topNode.HasOutput(output))
                                topMost.Add(Tuple.Create(output, topNode));
                        }
                    }

                    outputs = topMost.Select(x => x.Item2.OutPortData[x.Item1].NickName);
                }

            result = new dynFunction(inputs, outputs, def);
            result.NodeUI.NickName = ws.Name;

            return true;
        }
Esempio n. 3
0
        /// <summary>
        ///     Get a guid from the name of a node.  If it doesn't exist, returns Guid.Empty.
        /// </summary>
        /// <param name="guid">Open a definition from a path, without instantiating the nodes or dependents</param>
        public bool GetNodeInstance(DynamoController controller, string name, out dynFunction result)
        {
            if (!this.Contains(name))
            {
                result = null;
                return false;
            }

            return this.GetNodeInstance(controller, GetGuidFromName(name), out result);
        }
Esempio n. 4
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<dynNode> selectedNodes, dynWorkspace currentWorkspace)
        {
            var selectedNodeSet = new HashSet<dynNode>(selectedNodes);

            // TODO: this code needs refactoring
            #region Prompt

            //First, prompt the user to enter a name
            string newNodeName, newNodeCategory;
            string error = "";

            do
            {
                var dialog = new FunctionNamePrompt(dynSettings.Controller.SearchViewModel.Categories, error);
                if (dialog.ShowDialog() != true)
                {
                    return;
                }

                newNodeName = dialog.Text;
                newNodeCategory = dialog.Category;

                if (dynSettings.Controller.CustomNodeLoader.Contains(newNodeName))
                {
                    error = "A function with this name already exists.";
                }
                else if (newNodeCategory.Equals(""))
                {
                    error = "Please enter a valid category.";
                }
                else
                {
                    error = "";
                }
            } while (!error.Equals(""));

            var newNodeWorkspace = new FuncWorkspace(newNodeName, newNodeCategory, 0, 0);
            var newNodeDefinition = new FunctionDefinition(Guid.NewGuid());
            newNodeDefinition.Workspace = newNodeWorkspace;

            #endregion

            currentWorkspace.DisableReporting();

            #region Determine Inputs and Outputs

            //Step 1: determine which nodes will be inputs to the new node
            var inputs = new HashSet<Tuple<dynNode, int, Tuple<int, dynNode>>>(
                    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<dynNode, int, Tuple<int, dynNode>>>(
                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<dynNode>(
                    inputs
                        .Select(x => x.Item3.Item2)
                        .Intersect(outputs.Select(x => x.Item3.Item2)))
                    .Select(
                        outerNode =>
                        {
                            var node = new dynApply1();

                            dynNodeUI nodeUI = node.NodeUI;

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

                            nodeUI.GUID = Guid.NewGuid();

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

                            node.DisableReporting();

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

                            //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.NodeUI.RegisterAllPorts();

                            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 => Canvas.GetLeft(node.NodeUI));
            double avgY = selectedNodeSet.Average(node => Canvas.GetTop(node.NodeUI));

            double leftMost = selectedNodeSet.Min(node => Canvas.GetLeft(node.NodeUI)) + 24;
            double topMost = selectedNodeSet.Min(node => Canvas.GetTop(node.NodeUI));
            double rightMost = selectedNodeSet.Max(node => Canvas.GetLeft(node.NodeUI) + node.NodeUI.Width);

            #endregion

            #region Move selection to new workspace

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

            //Step 2: move all nodes to new workspace
            //  remove from old
            currentWorkspace.Nodes.RemoveAll(selectedNodeSet.Contains);
            currentWorkspace.Connectors.RemoveAll(connectors.Contains);

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

            double leftShift = leftMost - 250;
            foreach (dynNodeUI node in newNodeWorkspace.Nodes.Select(x => x.NodeUI))
            {
                Canvas.SetLeft(node, Canvas.GetLeft(node) - leftShift);
                Canvas.SetTop(node, Canvas.GetTop(node) - topMost + 120);
            }

            #endregion

            #region Insert new node into the current workspace

            //Step 5: insert new node into original workspace
            var collapsedNode = new dynFunction(
                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.NodeUI.GUID = Guid.NewGuid();

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

            dynSettings.Bench.WorkBench.Children.Add(collapsedNode.NodeUI);

            Canvas.SetLeft(collapsedNode.NodeUI, avgX);
            Canvas.SetTop(collapsedNode.NodeUI, avgY);

            #endregion

            #region Destroy all hanging connectors

            //Step 6: connect inputs and outputs
            foreach (dynConnector connector in currentWorkspace.Connectors
                                                           .Where(
                                                               c =>
                                                               selectedNodeSet.Contains(c.Start.Owner.NodeLogic) &&
                                                               !selectedNodeSet.Contains(c.End.Owner.NodeLogic))
                                                           .ToList())
            {
                connector.Kill();
            }

            foreach (dynConnector connector in currentWorkspace.Connectors
                                                           .Where(
                                                               c =>
                                                               !selectedNodeSet.Contains(c.Start.Owner.NodeLogic) &&
                                                               selectedNodeSet.Contains(c.End.Owner.NodeLogic)).ToList()
                )
            {
                connector.Kill();
            }

            #endregion

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

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

            #region Process inputs

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

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

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

                inConnectors.Add(new Tuple<dynNodeUI, int, int>(inputNode.NodeUI, inputData, inputIndex));

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

                dynNodeUI nodeUI = node.NodeUI;

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

                nodeUI.GUID = Guid.NewGuid();

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

                node.DisableReporting();

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

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

                if (curriedNode == null)
                {
                    //Connect it (new dynConnector)
                    newNodeWorkspace.Connectors.Add(new dynConnector(
                                                        nodeUI,
                                                        inputReceiverNode.NodeUI,
                                                        0,
                                                        inputReceiverData,
                                                        0,
                                                        false));
                }
                else
                {
                    //Connect it to the applier
                    newNodeWorkspace.Connectors.Add(new dynConnector(
                                                        nodeUI,
                                                        curriedNode.InnerNode.NodeUI,
                                                        0,
                                                        0,
                                                        0,
                                                        false));

                    //Connect applier to the inner input receiver
                    newNodeWorkspace.Connectors.Add(new dynConnector(
                                                        curriedNode.InnerNode.NodeUI,
                                                        inputReceiverNode.NodeUI,
                                                        0,
                                                        inputReceiverData,
                                                        0,
                                                        false));
                }
            }

            #endregion

            #region Process outputs

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

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

            int i = 0;
            foreach (var output in outputs)
            {
                if (outportList.All(x => !(x.Item1 == output.Item1 && x.Item2 == output.Item2)))
                {
                    dynNode outputSenderNode = output.Item1;
                    int outputSenderData = output.Item2;
                    dynNode 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
                    };

                    dynNodeUI nodeUI = node.NodeUI;

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

                    nodeUI.GUID = Guid.NewGuid();

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

                    node.DisableReporting();

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

                    newNodeWorkspace.Connectors.Add(new dynConnector(
                                                        outputSenderNode.NodeUI,
                                                        nodeUI,
                                                        outputSenderData,
                                                        0,
                                                        0,
                                                        false));

                    i++;
                }
            }

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

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

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

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

                if (curriedNode == null)
                {
                    // we create the connectors in the current space later
                    outConnectors.Add(new Tuple<dynNodeUI, int, int>(outputReceiverNode.NodeUI,
                                                                     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)
                    newNodeWorkspace.Connectors.Add(new dynConnector(
                                                        outputSenderNode.NodeUI,
                                                        curriedNode.InnerNode.NodeUI,
                                                        outputSenderData,
                                                        targetPortIndex + 1,
                                                        0));
                }
            }

            #endregion

            #region Make new workspace invisible

            //Step 4: make nodes invisible
            // and update positions
            foreach (dynNodeUI node in newNodeWorkspace.Nodes.Select(x => x.NodeUI))
                node.Visibility = Visibility.Hidden;

            foreach (dynConnector connector in newNodeWorkspace.Connectors)
                connector.Visible = false;

            #endregion

            //set the name on the node
            collapsedNode.NodeUI.NickName = newNodeName;

            currentWorkspace.Nodes.Remove(collapsedNode);
            dynSettings.Bench.WorkBench.Children.Remove(collapsedNode.NodeUI);

            // save and load the definition from file
            var path = dynSettings.Controller.SaveFunctionOnly(newNodeDefinition);
            dynSettings.Controller.CustomNodeLoader.SetNodeInfo(newNodeName, newNodeCategory, newNodeDefinition.FunctionId, path);
            dynSettings.Controller.SearchViewModel.Add(newNodeName, newNodeCategory, newNodeDefinition.FunctionId);

            DynamoCommands.CreateNodeCmd.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);

            newlyPlacedCollapsedNode.DisableReporting();

            dynSettings.Bench.WorkBench.UpdateLayout(); // without doing this, connectors fail to be created

            foreach (var nodeTuple in inConnectors)
            {
                currentWorkspace.Connectors.Add(
                    new dynConnector(
                        nodeTuple.Item1,
                        newlyPlacedCollapsedNode.NodeUI,
                        nodeTuple.Item2,
                        nodeTuple.Item3,
                        0,
                        true));
            }

            foreach (var nodeTuple in outConnectors)
            {
                currentWorkspace.Connectors.Add(
                    new dynConnector(
                        newlyPlacedCollapsedNode.NodeUI,
                        nodeTuple.Item1,
                        nodeTuple.Item2,
                        nodeTuple.Item3,
                        0,
                        true));
            }

            newlyPlacedCollapsedNode.EnableReporting();
            currentWorkspace.EnableReporting();
        }
Esempio n. 5
0
        internal void NodeFromSelection(IEnumerable<dynNode> selectedNodes)
        {
            var selectedNodeSet = new HashSet<dynNode>(selectedNodes);

            #region Prompt
            //First, prompt the user to enter a name
            string newNodeName, newNodeCategory;
            string error = "";

            do
            {
                var dialog = new FunctionNamePrompt(Bench.addMenuCategoryDict.Keys, error);
                if (dialog.ShowDialog() != true)
                {
                    return;
                }

                newNodeName = dialog.Text;
                newNodeCategory = dialog.Category;

                if (FunctionDict.ContainsKey(newNodeName))
                {
                    error = "A function with this name already exists.";
                }
                else if (newNodeCategory.Equals(""))
                {
                    error = "Please enter a valid category.";
                }
                else
                {
                    error = "";
                }
            }
            while (!error.Equals(""));

            var newNodeWorkspace = NewFunction(newNodeName, newNodeCategory, false);
            #endregion

            CurrentSpace.DisableReporting();

            #region UI Positioning Calculations
            var avgX = selectedNodeSet.Average(node => Canvas.GetLeft(node.NodeUI));
            var avgY = selectedNodeSet.Average(node => Canvas.GetTop(node.NodeUI));

            var leftMost = selectedNodeSet.Min(node => Canvas.GetLeft(node.NodeUI));
            var topMost = selectedNodeSet.Min(node => Canvas.GetTop(node.NodeUI));
            var rightMost = selectedNodeSet.Max(node => Canvas.GetLeft(node.NodeUI) + node.NodeUI.Width);
            #endregion

            #region Determine Inputs and Outputs
            //Step 1: determine which nodes will be inputs to the new node
            var inputs = new HashSet<Tuple<dynNode, int, Tuple<int, dynNode>>>(
                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<dynNode, int, Tuple<int, dynNode>>>(
                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<dynNode>(
                    inputs
                        .Select(x => x.Item3.Item2)
                        .Intersect(outputs.Select(x => x.Item3.Item2)))
                .Select(
                    outerNode =>
                    {
                        var node = new dynApply1();

                        var nodeUI = node.NodeUI;

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

                        nodeUI.GUID = Guid.NewGuid();

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

                        node.DisableReporting();

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

                        //Fetch all input ports
                        // in order
                        // that have inputs
                        // and whose input comes from an inner node
                        var 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.NodeUI.RegisterAllPorts();

                        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 Move selection to new workspace
            var connectors = new HashSet<dynConnector>(
                CurrentSpace.Connectors.Where(
                    conn => selectedNodeSet.Contains(conn.Start.Owner.NodeLogic)
                        && selectedNodeSet.Contains(conn.End.Owner.NodeLogic)));

            //Step 2: move all nodes to new workspace
            //  remove from old
            CurrentSpace.Nodes.RemoveAll(selectedNodeSet.Contains);
            CurrentSpace.Connectors.RemoveAll(connectors.Contains);
            //  add to new
            newNodeWorkspace.Nodes.AddRange(selectedNodeSet);
            newNodeWorkspace.Connectors.AddRange(connectors);

            var leftShift = leftMost - 250;
            foreach (var node in newNodeWorkspace.Nodes.Select(x => x.NodeUI))
            {
                Canvas.SetLeft(node, Canvas.GetLeft(node) - leftShift);
                Canvas.SetTop(node, Canvas.GetTop(node) - topMost);
            }
            #endregion

            #region Insert new node replacement into the current workspace
            //Step 5: insert new node into original workspace
            var collapsedNode = new dynFunction(
                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),
                newNodeName);

            collapsedNode.NodeUI.GUID = Guid.NewGuid();

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

            Bench.WorkBench.Children.Add(collapsedNode.NodeUI);

            Canvas.SetLeft(collapsedNode.NodeUI, avgX);
            Canvas.SetTop(collapsedNode.NodeUI, avgY);

            Bench.WorkBench.UpdateLayout();
            #endregion

            #region Destroy all hanging connectors
            //Step 6: connect inputs and outputs
            foreach (var connector in CurrentSpace.Connectors
                .Where(c => selectedNodeSet.Contains(c.Start.Owner.NodeLogic) && !selectedNodeSet.Contains(c.End.Owner.NodeLogic)).ToList())
            {
                connector.Kill();
            }

            foreach (var connector in CurrentSpace.Connectors
                .Where(c => !selectedNodeSet.Contains(c.Start.Owner.NodeLogic) && selectedNodeSet.Contains(c.End.Owner.NodeLogic)).ToList())
            {
                connector.Kill();
            }
            #endregion

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

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

                var inputReceiverNode = input.Item2.Item1;
                var inputReceiverData = input.Item2.Item2;

                var inputNode = input.Item2.Item3.Item2;
                var inputData = input.Item2.Item3.Item1;

                //Connect outside input to the node
                CurrentSpace.Connectors.Add(
                    new dynConnector(
                        inputNode.NodeUI,
                        collapsedNode.NodeUI,
                        inputData,
                        inputIndex,
                        0,
                        true));

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

                var nodeUI = node.NodeUI;

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

                nodeUI.GUID = Guid.NewGuid();

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

                node.DisableReporting();

                Bench.WorkBench.Children.Add(nodeUI);

                //Place it in an appropriate spot
                Canvas.SetLeft(nodeUI, 0);
                Canvas.SetTop(nodeUI, inputIndex * (50 + node.NodeUI.Height));

                Bench.WorkBench.UpdateLayout();

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

                if (curriedNode == null)
                {
                    //Connect it (new dynConnector)
                    newNodeWorkspace.Connectors.Add(new dynConnector(
                        nodeUI,
                        inputReceiverNode.NodeUI,
                        0,
                        inputReceiverData,
                        0,
                        false));
                }
                else
                {
                    //Connect it to the applier
                    newNodeWorkspace.Connectors.Add(new dynConnector(
                        nodeUI,
                        curriedNode.InnerNode.NodeUI,
                        0,
                        0,
                        0,
                        false));

                    //Connect applier to the inner input receiver
                    newNodeWorkspace.Connectors.Add(new dynConnector(
                        curriedNode.InnerNode.NodeUI,
                        inputReceiverNode.NodeUI,
                        0,
                        inputReceiverData,
                        0,
                        false));
                }
            }
            #endregion

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

            int i = 0;
            foreach (var output in outputs)
            {
                if (outportList.All(x => !(x.Item1 == output.Item1 && x.Item2 == output.Item2)))
                {
                    var outputSenderNode = output.Item1;
                    var outputSenderData = output.Item2;
                    var 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
                    };

                    var nodeUI = node.NodeUI;

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

                    nodeUI.GUID = Guid.NewGuid();

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

                    node.DisableReporting();

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

                    Bench.WorkBench.UpdateLayout();

                    newNodeWorkspace.Connectors.Add(new dynConnector(
                        outputSenderNode.NodeUI,
                        nodeUI,
                        outputSenderData,
                        0,
                        0,
                        false));

                    i++;
                }
            }

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

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

                var outputReceiverData = output.Item3.Item1;
                var outputReceiverNode = output.Item3.Item2;

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

                if (curriedNode == null)
                {
                    CurrentSpace.Connectors.Add(
                        new dynConnector(
                            collapsedNode.NodeUI,
                            outputReceiverNode.NodeUI,
                            outportList.FindIndex(x => x.Item1 == outputSenderNode && x.Item2 == outputSenderData),
                            outputReceiverData,
                            0,
                            true));
                }
                else
                {
                    var targetPort = curriedNode.Inputs
                        .First(
                            x => x.InnerNodeInputSender == outputSenderNode)
                        .OuterNodeInPortData;

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

                    //Connect it (new dynConnector)
                    newNodeWorkspace.Connectors.Add(new dynConnector(
                        outputSenderNode.NodeUI,
                        curriedNode.InnerNode.NodeUI,
                        outputSenderData,
                        targetPortIndex + 1,
                        0));
                }
            }
            #endregion

            #region Make new workspace invisible
            //Step 4: make nodes invisible
            // and update positions
            foreach (var node in newNodeWorkspace.Nodes.Select(x => x.NodeUI))
                node.Visibility = Visibility.Hidden;

            foreach (var connector in newNodeWorkspace.Connectors)
                connector.Visible = false;
            #endregion

            newNodeWorkspace.Nodes.ForEach(x => { x.EnableReporting(); x.NodeUI.UpdateConnections(); });

            collapsedNode.EnableReporting();
            collapsedNode.NodeUI.UpdateConnections();

            CurrentSpace.EnableReporting();

            SaveFunction(newNodeWorkspace, true);
        }
Esempio n. 6
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;
        }
Esempio n. 7
0
        internal dynNode CreateDragNode(string name)
        {
            dynNode result;
            if (FunctionDict.ContainsKey(name))
            {
                dynWorkspace ws = FunctionDict[name];

                var inputs =
                    ws.Nodes.Where(e => e is dynSymbol)
                        .Select(s => (s as dynSymbol).Symbol);

                var outputs =
                    ws.Nodes.Where(e => e is dynOutput)
                        .Select(o => (o as dynOutput).Symbol);

                if (!outputs.Any())
                {
                    var topMost = new List<Tuple<int, dynNode>>();

                    var topMostNodes = ws.GetTopMostNodes();

                    foreach (var topNode in topMostNodes)
                    {
                        foreach (var output in Enumerable.Range(0, topNode.OutPortData.Count))
                        {
                            if (!topNode.HasOutput(output))
                                topMost.Add(Tuple.Create(output, topNode));
                        }
                    }

                    outputs = topMost.Select(x => x.Item2.OutPortData[x.Item1].NickName);
                }

                result = new dynFunction(inputs, outputs, name);
            }
            else
            {
                TypeLoadData tld = builtinTypesByNickname[name];

                var obj = Activator.CreateInstanceFrom(tld.Assembly.Location, tld.Type.FullName);
                var newEl = (dynNode)obj.Unwrap();
                newEl.NodeUI.DisableInteraction();
                result = newEl;
            }

            if (result is dynDouble)
                (result as dynDouble).Value = this.storedSearchNum;
            else if (result is dynStringInput)
                (result as dynStringInput).Value = this.storedSearchStr;
            else if (result is dynBool)
                (result as dynBool).Value = this.storedSearchBool;

            return result;
        }