private GraphElement CreateStackNode(MathStackNode mathStackNode, Vector2 pos)
        {
            SimpleStackNode graphStackNode = new SimpleStackNode(mathStackNode);

            graphStackNode.SetPosition(new Rect(pos.x, pos.y, 100, 100));

            return(graphStackNode);
        }
        public SimpleStackNode(MathStackNode node)
        {
            var visualTree = Resources.Load("SimpleStackNodeHeader") as VisualTreeAsset;

            m_Header = visualTree.Instantiate();

            m_TitleItem = m_Header.Q <Label>(name: "titleLabel");
            m_TitleItem.AddToClassList("label");

            m_TitleEditor = m_Header.Q(name: "titleField") as TextField;

            m_TitleEditor.AddToClassList("textfield");
            m_TitleEditor.visible = false;

            m_TitleEditor.RegisterCallback <FocusOutEvent>(e => { OnEditTitleFinished(); });
            m_TitleEditor.Q("unity-text-input").RegisterCallback <KeyDownEvent>(OnKeyPressed);


            headerContainer.Add(m_Header);

            m_OperationControl = m_Header.Q <EnumField>(name: "operationField");
            m_OperationControl.Init(MathStackNode.Operation.Addition);
            m_OperationControl.value = node.currentOperation;
            m_OperationControl.RegisterCallback <ChangeEvent <Enum> >(v =>
            {
                node.currentOperation = (MathStackNode.Operation)v.newValue;

                MathNode mathNode = userData as MathNode;

                if (mathNode != null && mathNode.mathBook != null)
                {
                    mathNode.mathBook.inputOutputs.ComputeOutputs();
                }
            });

            var inputPort  = InstantiatePort(Orientation.Vertical, Direction.Input, Port.Capacity.Single, typeof(float));
            var outputPort = InstantiatePort(Orientation.Vertical, Direction.Output, Port.Capacity.Single, typeof(float));

            inputPort.portName  = "";
            outputPort.portName = "";

            inputContainer.Add(inputPort);
            outputContainer.Add(outputPort);

            RegisterCallback <MouseDownEvent>(OnMouseUpEvent);

            userData            = node;
            viewDataKey         = node.nodeID.ToString();
            title               = node.name;
            inputPort.userData  = node;
            outputPort.userData = node;
        }
        public bool OnSelectEntry(SearchTreeEntry entry, SearchWindowContext context)
        {
            if (!(entry is SearchTreeGroupEntry))
            {
                if (!GraphViewStaticBridge.HasGUIView(graphView))
                {
                    return(false);
                }

                MathNode node = ScriptableObject.CreateInstance(entry.userData as Type) as MathNode;

                AddNode(node);
                Node nodeUI = CreateNode(node) as Node;
                if (nodeUI != null)
                {
                    if (m_InsertStack != null)
                    {
                        MathStackNode stackNode = m_InsertStack.userData as MathStackNode;

                        stackNode.InsertNode(m_InsertIndex, node);
                        m_InsertStack.InsertElement(m_InsertIndex, nodeUI);
                    }
                    else
                    {
                        graphView.AddElement(nodeUI);

                        Vector2 pointInWindow = context.screenMousePosition - position.position;
                        Vector2 pointInGraph  = nodeUI.parent.WorldToLocal(pointInWindow);

                        nodeUI.SetPosition(new Rect(pointInGraph, Vector2.zero)); // it's ok to pass zero here because width/height is dynamic
                    }
                    nodeUI.Select(graphView, false);
                }
                else
                {
                    Debug.LogError("Failed to create element for " + node);
                    return(false);
                }

                return(true);
            }
            return(false);
        }
        public GraphElement CreateNode(MathNode mathNode)
        {
            if (mathNode is MathOperator)
            {
                MathOperator add = mathNode as MathOperator;

                return(CreateMathNode(mathNode, mathNode.name, add.m_Position, 2, 1));
            }
            else if (mathNode is MathStackNode)
            {
                MathStackNode mathStackNode = mathNode as MathStackNode;

                return(CreateStackNode(mathStackNode, mathStackNode.m_Position));
            }
            else if (mathNode is MathFunction)
            {
                MathFunction fn = mathNode as MathFunction;

                Debug.Assert(fn.parameterCount == fn.parameterNames.Length);

                Node nodeUI = CreateMathNode(mathNode, mathNode.name, mathNode.m_Position, fn.parameterNames.Length, 1);

                for (int i = 0; i < fn.parameterNames.Length; ++i)
                {
                    (nodeUI.inputContainer.ElementAt(i) as Port).portName = fn.parameterNames[i];
                }

                return(nodeUI);
            }
            else if (mathNode is IMathBookFieldNode)
            {
                IMathBookFieldNode mathBookFieldNode = mathNode as IMathBookFieldNode;
                SimpleTokenNode    tokenNode         = new SimpleTokenNode(mathBookFieldNode);

                tokenNode.SetPosition(new Rect(mathNode.m_Position, Vector2.zero));
                tokenNode.RefreshPorts();
                tokenNode.visible = true;

                return(tokenNode);
            }
            else if (mathNode is MathConstant)
            {
                MathConstant mathConstant = mathNode as MathConstant;

                Node nodeUI = CreateMathNode(
                    mathNode,
                    mathConstant.name,
                    mathConstant.m_Position, 0, 1);

                var field = new DoubleField()
                {
                    value = mathConstant.m_Value
                };
                field.SetEnabled(!(mathConstant is PIConstant));
                field.RegisterValueChangedCallback(evt => mathConstant.m_Value = (float)evt.newValue);
                nodeUI.inputContainer.Add(field);
                nodeUI.RefreshExpandedState();
                return(nodeUI);
            }
            else if (mathNode is MathResult)
            {
                MathResult mathResult = mathNode as MathResult;

                Node nodeUI = CreateMathNode(
                    mathNode,
                    "Result",
                    mathResult.m_Position, 1, 0);

                nodeUI.inputContainer.Add(new Button(() => Debug.Log(mathResult.Evaluate()))
                {
                    text = "Print result"
                });

                return(nodeUI);
            }
            else if (mathNode is MathGroupNode)
            {
                MathGroupNode mathGroupNode = mathNode as MathGroupNode;

                if (mathGroupNode.m_IsScope)
                {
                    return(CreateScope(mathGroupNode,
                                       mathGroupNode.m_Position));
                }
                else
                {
                    return(CreateGroupNode(mathGroupNode,
                                           mathGroupNode.m_Title,
                                           mathGroupNode.m_Position));
                }
            }

            return(null);
        }
        public void Reload(IEnumerable <MathNode> nodesToReload, IEnumerable <MathPlacemat> placemats, IEnumerable <MathStickyNote> stickies, Dictionary <string, string> oldToNewIdMapping = null)
        {
            string oldId;
            var    nodes          = new Dictionary <MathNode, GraphElement>();
            var    oldIdToNewNode = new Dictionary <string, ISelectable>();

            var newToOldIdMapping = new Dictionary <string, string>();

            if (oldToNewIdMapping != null)
            {
                foreach (var oldIdKV in oldToNewIdMapping)
                {
                    newToOldIdMapping[oldIdKV.Value] = oldIdKV.Key;
                }
            }

            // Create the nodes.
            foreach (MathNode mathNode in nodesToReload)
            {
                GraphElement node = m_SimpleGraphViewWindow.CreateNode(mathNode);

                if (node is Group)
                {
                    node.name = "SimpleGroup";
                }
                else if (node is Scope)
                {
                    node.name = "SimpleScope";
                }
                else
                {
                    node.name = "SimpleNode";
                }

                if (node == null)
                {
                    Debug.LogError("Could not create node " + mathNode);
                    continue;
                }

                nodes[mathNode] = node;

                if (mathNode.groupNode == null)
                {
                    if (newToOldIdMapping.TryGetValue(mathNode.nodeID.ToString(), out oldId))
                    {
                        oldIdToNewNode.Add(oldId, node);
                    }
                }

                AddElement(node);
            }

            // Assign scopes
            foreach (MathNode mathNode in nodesToReload)
            {
                if (mathNode.groupNode == null)
                {
                    continue;
                }

                Scope graphScope = nodes[mathNode.groupNode] as Scope;

                graphScope.AddElement(nodes[mathNode]);
            }

            // Add to stacks
            foreach (MathNode mathNode in nodesToReload)
            {
                MathStackNode stack = mathNode as MathStackNode;

                if (stack == null)
                {
                    continue;
                }

                StackNode graphStackNode = nodes[stack] as StackNode;

                for (int i = 0; i < stack.nodeCount; ++i)
                {
                    MathNode stackMember = stack.GetNode(i);
                    if (stackMember == null)
                    {
                        Debug.LogWarning("null stack member! Item " + i + " of stack " + stack.name + " is null. Possibly a leftover from bad previous manips.");
                    }

                    graphStackNode.AddElement(nodes[stackMember]);
                }
            }

            // Connect the presenters.
            foreach (var mathNode in nodesToReload)
            {
                if (mathNode is MathOperator)
                {
                    MathOperator mathOperator = mathNode as MathOperator;

                    if (!nodes.ContainsKey(mathNode))
                    {
                        Debug.LogError("No element found for " + mathNode);
                        continue;
                    }

                    var graphNode = nodes[mathNode] as Node;

                    if (mathOperator.left != null && nodes.ContainsKey(mathOperator.left))
                    {
                        var outputPort = (nodes[mathOperator.left] as Node).outputContainer[0] as Port;
                        var inputPort  = graphNode.inputContainer[0] as Port;

                        Edge edge = inputPort.ConnectTo(outputPort);
                        edge.viewDataKey = mathOperator.left.nodeID + "_edge";
                        AddElement(edge);
                    }
                    else if (mathOperator.left != null)
                    {
                        //add.m_Left = null;
                        Debug.LogWarning("Invalid left operand for operator " + mathOperator + " , " + mathOperator.left);
                    }

                    if (mathOperator.right != null && nodes.ContainsKey(mathOperator.right))
                    {
                        var outputPort = (nodes[mathOperator.right] as Node).outputContainer[0] as Port;
                        var inputPort  = graphNode.inputContainer[1] as Port;

                        Edge edge = inputPort.ConnectTo(outputPort);
                        edge.viewDataKey = mathOperator.right.nodeID + "_edge";
                        AddElement(edge);
                    }
                    else if (mathOperator.right != null)
                    {
                        Debug.LogWarning("Invalid right operand for operator " + mathOperator + " , " + mathOperator.right);
                    }
                }
                else if (mathNode is MathFunction)
                {
                    MathFunction mathFunction = mathNode as MathFunction;

                    if (!nodes.ContainsKey(mathNode))
                    {
                        Debug.LogError("No element found for " + mathNode);
                        continue;
                    }

                    var graphNode = nodes[mathNode] as Node;

                    for (int i = 0; i < mathFunction.parameterCount; ++i)
                    {
                        MathNode param = mathFunction.GetParameter(i);

                        if (param != null && nodes.ContainsKey(param))
                        {
                            var outputPort = (nodes[param] as Node).outputContainer[0] as Port;
                            var inputPort  = graphNode.inputContainer[i] as Port;

                            Edge edge = inputPort.ConnectTo(outputPort);
                            edge.viewDataKey = param.nodeID + "_edge";
                            AddElement(edge);
                        }
                        else if (param != null)
                        {
                            Debug.LogWarning("Invalid parameter for function" + mathFunction + " , " +
                                             param);
                        }
                    }
                }
                else if (mathNode is MathResult)
                {
                    MathResult mathResult = mathNode as MathResult;
                    var        graphNode  = nodes[mathNode] as Node;

                    if (mathResult.root != null)
                    {
                        var outputPort = (nodes[mathResult.root] as Node).outputContainer[0] as Port;
                        var inputPort  = graphNode.inputContainer[0] as Port;

                        Edge edge = inputPort.ConnectTo(outputPort);
                        edge.viewDataKey = mathResult.root.nodeID + "_edge";
                        AddElement(edge);
                    }
                }
            }

            foreach (var matModel in placemats.OrderBy(p => p.zOrder))
            {
                var newPlacemat = placematContainer.CreatePlacemat <SimplePlacemat>(matModel.position, matModel.zOrder, matModel.title);
                newPlacemat.userData    = matModel;
                newPlacemat.viewDataKey = matModel.identification;
                newPlacemat.Model       = matModel;

                if (newToOldIdMapping.TryGetValue(matModel.identification, out oldId))
                {
                    oldIdToNewNode.Add(oldId, newPlacemat);
                }
            }

            if (stickies != null)
            {
                var existingStickies = this.Query <SimpleStickyNote>().ToList();

                foreach (var sticky in existingStickies.Where(t => !stickies.Contains(t.model)))
                {
                    RemoveElement(sticky);
                }

                foreach (var stickyModel in stickies.Except(existingStickies.Select(t => t.model)))
                {
                    var newSticky = new SimpleStickyNote();
                    newSticky.model    = stickyModel;
                    newSticky.userData = stickyModel;
                    AddElement(newSticky);

                    if (newToOldIdMapping.TryGetValue(stickyModel.id, out oldId))
                    {
                        oldIdToNewNode.Add(oldId, newSticky);
                    }
                }
            }

            // Now that all graph elements have been created, init the collapsed elements of each placemat.
            foreach (var p in this.Query <SimplePlacemat>().ToList())
            {
                p.InitCollapsedElementsFromModel();
            }

            // Make sure collapsed edges are hidden.
            placematContainer.HideCollapsedEdges();

            UpdateSelection(oldIdToNewNode);

            RebuildBlackboard();
        }