Example #1
0
        /// <summary>
        /// Construct a view and respond to property changes on the model.
        /// </summary>
        /// <param name="model"></param>
        public ConnectorViewModel(WorkspaceViewModel workspace, ConnectorModel model)
        {
            this.workspaceViewModel = workspace;
            _model = model;

            _model.PropertyChanged             += Model_PropertyChanged;
            _model.Start.Owner.PropertyChanged += StartOwner_PropertyChanged;
            _model.End.Owner.PropertyChanged   += EndOwner_PropertyChanged;

            workspaceViewModel.DynamoViewModel.PropertyChanged += DynamoViewModel_PropertyChanged;
            Nodevm.PropertyChanged += nodeViewModel_PropertyChanged;
            Redraw();
        }
Example #2
0
        public void TestSingleOutputNode()
        {
            // TODO pratapa: Test goes into infinite loop after Dictionary changes
            RunModel(@"core\multiout\singleoutput.dyn");
            AssertPreviewValue("060e57e1-b889-4b94-a440-8adb0067ae79", null);

            var instanceNode = CurrentDynamoModel.CurrentWorkspace.Nodes.First(n => n.GUID.ToString().Equals("306c8777-ecff-4106-bfdd-dd331e61cf2b"));
            var dictNode     = CurrentDynamoModel.CurrentWorkspace.Nodes.First(n => n.GUID.ToString().Equals("41271769-11b8-46fc-bb16-fffd022dc9bc"));
            var connector    = ConnectorModel.Make(instanceNode, dictNode, 0, 0);

            RunCurrentModel();
            AssertPreviewValue("060e57e1-b889-4b94-a440-8adb0067ae79", "green");
        }
Example #3
0
        /// <summary>
        /// Deletes all connectors attached to this PortModel.
        /// </summary>
        public void DestroyConnectors()
        {
            if (Owner == null)
            {
                return;
            }

            while (Connectors.Any())
            {
                ConnectorModel connector = Connectors[0];
                connector.Delete();
            }
        }
Example #4
0
        private void OnPortConnected(PortModel port, ConnectorModel connectorModel)
        {
            Tuple <int, NodeModel> input;

            if (watch.TryGetInput(watch.InPorts.IndexOf(connectorModel.End), out input))
            {
                var oldId = astBeingWatched;
                astBeingWatched = input.Item2.GetAstIdentifierForOutputIndex(input.Item1);
                if (oldId != null && astBeingWatched.Value != oldId.Value)
                {
                    // the input node has changed, we clear preview
                    rootWatchViewModel.Children.Clear();
                }
            }
        }
        public ActionResult Create(ConnectorModel connectorModel)
        {
            try
            {
                if (connectorModel.CK_Id > 0)
                {
                    return(StatusCode(StatusCodes.Status400BadRequest, "Providing custom CK_Id is not allowed, Connector.CK_Id is Auto-Generated !"));
                }



                var connector = _Mapper.Map <Connector>(connectorModel);
                connector = _ConnectorService.CreateConnector(connector);
                return(Ok(_Mapper.Map <ConnectorModel>(connector)));
            }
            catch (ConnectorMaxCurrentExceedGroupCapacityException ex)
            {
                return(StatusCode(StatusCodes.Status400BadRequest, ex.Message));
            }
            catch (ConnectorsMaxCurrentExceedGroupCapacityException ex)
            {
                //get chargeStation
                var chargeStation = _ChargeStationService.GetChargeStation(connectorModel.ChargeStationId);
                //get connectors of group
                var connectorsOFGroup = _ConnectorService.GetConnectorsByGroup(chargeStation.GroupId);
                //get suggestions
                var suggestions = _Suggester.GetSuggestions(connectorsOFGroup, connectorModel.MaxCurrent);
                //Create suggestionResponse
                var response = new SuggestionResponse {
                    ErrorMessage = ex.Message
                };
                response.Suggestions = _Mapper.Map <List <SuggestionModel> >(suggestions);

                return(BadRequest(response));
            }
            catch (DataException ex)
            {
                return(StatusCode(StatusCodes.Status400BadRequest, ex.Message));
            }
            catch (DomainValidationException ex)
            {
                return(StatusCode(StatusCodes.Status400BadRequest, ex.Message));
            }
            catch (Exception)
            {
                return(StatusCode(StatusCodes.Status500InternalServerError));
            }
        }
Example #6
0
        public void TestOnDeletionStarted()
        {
            //Arrange
            //This will subscribe our local method to the DeletionStarted event
            CurrentDynamoModel.DeletionStarted += CurrentDynamoModel_DeletionStarted;

            //This create a new Code Block node and update the content
            var codeBlockNode0 = CreateCodeBlockNode();

            UpdateCodeBlockNodeContent(codeBlockNode0, @"true;");

            // Create the watch node.
            var watch   = new Watch();
            var command = new DynCmd.CreateNodeCommand(
                watch, 0, 0, true, false);

            CurrentDynamoModel.ExecuteCommand(command);

            // Connect the two nodes
            ConnectorModel.Make(codeBlockNode0, watch, 0, 0);

            // Run
            Assert.DoesNotThrow(BeginRun);

            // Check that we have two nodes in the current workspace, the Watch node and the CodeBlock
            Assert.AreEqual(2, CurrentDynamoModel.CurrentWorkspace.Nodes.Count());

            // Delete the code block node, internally this will call the OnDeletionStarted() method
            var nodeCodeBlock = new List <ModelBase> {
                codeBlockNode0
            };

            CurrentDynamoModel.DeleteModelInternal(nodeCodeBlock);

            // Check that we have only the watch in the current workspace
            Assert.AreEqual(1, CurrentDynamoModel.CurrentWorkspace.Nodes.Count());
            Assert.AreEqual("Watch", CurrentDynamoModel.CurrentWorkspace.Nodes.FirstOrDefault().GetType().Name);

            // Try to delete the Watch node
            var nodeWatch = new List <ModelBase> {
                watch
            };

            CurrentDynamoModel.DeleteModelInternal(nodeWatch);

            CurrentDynamoModel.DeletionStarted -= CurrentDynamoModel_DeletionStarted;
            Assert.IsTrue(deletionStarted);
        }
Example #7
0
        internal void EndConnection(Guid nodeId, int portIndex, PortType portType)
        {
            int  index    = portIndex;
            bool isInPort = portType == PortType.INPUT;

            NodeModel      node              = Model.GetModelInternal(nodeId) as NodeModel;
            PortModel      portModel         = isInPort ? node.InPorts[index] : node.OutPorts[index];
            ConnectorModel connectorToRemove = null;

            // Remove connector if one already exists
            if (portModel.Connectors.Count > 0 && portModel.PortType == PortType.INPUT)
            {
                connectorToRemove = portModel.Connectors[0];
                Model.Connectors.Remove(connectorToRemove);
                portModel.Disconnect(connectorToRemove);
                var startPort = connectorToRemove.Start;
                startPort.Disconnect(connectorToRemove);
            }

            // Create the new connector model
            var start = this.activeConnector.ActiveStartPort;
            var end   = portModel;

            // We could either connect from an input port to an output port, or
            // another way around (in which case we swap first and second ports).
            PortModel firstPort = start, second = end;

            if (portModel.PortType != PortType.INPUT)
            {
                firstPort = end;
                second    = start;
            }

            ConnectorModel newConnectorModel = this.Model.AddConnection(firstPort.Owner,
                                                                        second.Owner, firstPort.Index, second.Index, PortType.INPUT);

            // Record the creation of connector in the undo recorder.
            var models = new Dictionary <ModelBase, UndoRedoRecorder.UserAction>();

            if (connectorToRemove != null)
            {
                models.Add(connectorToRemove, UndoRedoRecorder.UserAction.Deletion);
            }
            models.Add(newConnectorModel, UndoRedoRecorder.UserAction.Creation);
            Model.RecordModelsForUndo(models);
            this.SetActiveConnector(null);
        }
Example #8
0
        private void Model_PortConnected(PortModel portModel, ConnectorModel connector)
        {
            switch (portModel.PortType)
            {
            case PortType.Input:
                var ifcModels = NodeModel.GetCachedInput <IfcModel>(portModel.Index, ModelEngineController);
                // Autofix extension if unique
                if (1 == ifcModels.Length)
                {
                    NodeModel.Selected = ifcModels.FirstOrDefault()?.FormatExtension;
                }
                break;

            case PortType.Output:
                break;
            }
        }
Example #9
0
        private static void OnSelectedTypeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            Slot      slot = (Slot)d;
            SlaveType type;
            PluginChangedEventArgs args;

            ConnectorModel model = slot.element.ConnectorModel;

            if (slot.loading)
            {
                return;
            }

            if ((e.OldValue != null || e.NewValue == null) && slot.ActiveModel != null)
            {
                model.WorkspaceModel.ModifyModel(new DeletePluginModelOperation(slot.ActiveModel));
                model.WorkspaceModel.ModifyModel(new DeleteConnectionModelOperation(slot.activeConnectionModel));
                args = new PluginChangedEventArgs(slot.ActiveModel.Plugin, slot.ActiveModel.GetName(), DisplayPluginMode.Normal);
                slot.MyEditor.onSelectedPluginChanged(args);
                slot.ActiveModel = null;
            }

            if (e.OldValue != null && e.NewValue != null)
            {
                if (((SlaveType)e.OldValue).Type.IsAssignableFrom(((SlaveType)e.NewValue).Type))
                {
                    return;
                }
            }

            if (e.NewValue == null)
            {
                return;
            }

            type = e.NewValue as SlaveType;
            var v = (PluginModel)model.WorkspaceModel.ModifyModel(new NewPluginModelOperation(new Point(0, 0), (double)0, (double)0, type.Type));

            slot.ActiveModel = v;
            var f = v.GetInputConnectors().Single(a => a.ConnectorType.IsAssignableFrom(slot.element.ConnectorModel.ConnectorType));

            slot.activeConnectionModel = (ConnectionModel)model.WorkspaceModel.ModifyModel(new NewConnectionModelOperation(model, f, f.ConnectorType));

            args = new PluginChangedEventArgs(slot.ActiveModel.Plugin, slot.ActiveModel.GetName(), DisplayPluginMode.Normal);
            slot.MyEditor.onSelectedPluginChanged(args);
        }
    /// <summary>
    /// Disconnect the specified connector from this port.
    /// </summary>
    /// <param name="connector">Connector.</param>
    public virtual void Disconnect(ConnectorModel connector)
    {
        if (connectors.Remove(connector) == false)
        {
            Debug.Log("could not disconnect connect, could not find it in connector list");
            return;
        }
        if (connectors.Count == 0)
        {
            IsConnected = false;
        }
        //throw the event for a connection
        OnPortDisconnected(EventArgs.Empty);



        //Owner.ValidateConnections ();
    }
Example #11
0
        /// <summary>
        /// Handler for the model's ConnectorDeleted event.
        /// </summary>
        /// <param name="connector"></param>
        private void DynamoModel_ConnectorDeleted(ConnectorModel connector)
        {
            // TODO: Ian should remove this when the CBN reconnection bug is solved.

            /*if (connector.Start.Owner.GetType() == typeof(CodeBlockNodeModel))
             * {
             *  return;
             * }
             *
             * //we are given the connector that was deleted
             * //if it's end node still exists, clear the package for
             * //the node and trigger an update.
             * if (connector.End != null)
             *  connector.End.Owner.ClearRenderPackages();
             *
             * //tell the watches that they require re-binding.
             * QueueRenderTask();*/
        }
Example #12
0
        internal void EndConnection(Guid nodeId, int portIndex, PortType portType)
        {
            int  index    = portIndex;
            bool isInPort = portType == PortType.INPUT;

            NodeModel node      = _model.GetModelInternal(nodeId) as NodeModel;
            PortModel portModel = isInPort ? node.InPorts[index] : node.OutPorts[index];

            // Remove connector if one already exists
            if (portModel.Connectors.Count > 0 && portModel.PortType == PortType.INPUT)
            {
                var connToRemove = portModel.Connectors[0];
                _model.Connectors.Remove(connToRemove);
                portModel.Disconnect(connToRemove);
                var startPort = connToRemove.Start;
                startPort.Disconnect(connToRemove);
            }

            // Create the new connector model
            var start = this.activeConnector.ActiveStartPort;
            var end   = portModel;

            // We could either connect from an input port to an output port, or
            // another way around (in which case we swap first and second ports).
            PortModel firstPort = start, second = end;

            if (portModel.PortType != PortType.INPUT)
            {
                firstPort = end;
                second    = start;
            }

            ConnectorModel newConnectorModel = ConnectorModel.Make(firstPort.Owner,
                                                                   second.Owner, firstPort.Index, second.Index, PortType.INPUT);

            if (newConnectorModel != null) // Add to the current workspace
            {
                _model.Connectors.Add(newConnectorModel);
            }

            // Record the creation of connector in the undo recorder.
            _model.RecordCreatedModel(newConnectorModel);
            this.SetActiveConnector(null);
        }
Example #13
0
        /// <summary>
        /// Handler for the model's ConnectorDeleted event.
        /// </summary>
        /// <param name="connector"></param>
        void DynamoModel_ConnectorDeleted(ConnectorModel connector)
        {
            // TODO: Ian should remove this when the CBN reconnection bug is solved.
            if (connector.Start.Owner.GetType() == typeof(CodeBlockNodeModel))
            {
                return;
            }

            //we are given the connector that was deleted
            //if it's end node still exists, clear the package for
            //the node and trigger an update.
            if (connector.End != null)
            {
                connector.End.Owner.ClearRenderPackages();
            }

            //tell the watches that they require re-binding.
            OnVisualizationUpdateComplete(this, EventArgs.Empty);
        }
        /// <summary>
        /// Places watch node at the midpoint of the connector
        /// </summary>
        internal List <ModelBase> PlaceWatchNode(ConnectorModel connector, IEnumerable <Point> connectorPinLocations, List <ModelBase> allDeletedModels)
        {
            var createdModels = new List <ModelBase>();

            NodeModel startNode = ViewModel.ConnectorModel.Start.Owner;
            NodeModel endNode   = ViewModel.ConnectorModel.End.Owner;

            this.Dispatcher.Invoke(() =>
            {
                var watchNode = new Watch();
                var nodeX     = CurrentPosition.X - (watchNode.Width / 2);
                var nodeY     = CurrentPosition.Y - (watchNode.Height / 2);
                DynamoModel.ExecuteCommand(new DynamoModel.CreateNodeCommand(watchNode, nodeX, nodeY, false, false));
                createdModels.Add(watchNode);
                WireNewNode(DynamoModel, startNode, endNode, watchNode, connector, connectorPinLocations, createdModels, allDeletedModels);
            });

            return(createdModels);
        }
Example #15
0
        internal void BeginConnection(Guid nodeId, int portIndex, PortType portType)
        {
            int  index    = portIndex;
            bool isInPort = portType == PortType.INPUT;

            NodeModel node      = _model.GetModelInternal(nodeId) as NodeModel;
            PortModel portModel = isInPort ? node.InPorts[index] : node.OutPorts[index];

            // Test if port already has a connection, if so grab it and begin connecting
            // to somewhere else (we don't allow the grabbing of the start connector).
            if (portModel.Connectors.Count > 0 && portModel.Connectors[0].Start != portModel)
            {
                // Define the new active connector
                var c = new ConnectorViewModel(portModel.Connectors[0].Start);
                this.SetActiveConnector(c);

                // Disconnect the connector model from its start and end ports
                // and remove it from the connectors collection. This will also
                // remove the view model.
                ConnectorModel connector = portModel.Connectors[0];
                if (_model.Connectors.Contains(connector))
                {
                    List <ModelBase> models = new List <ModelBase>();
                    models.Add(connector);
                    _model.RecordAndDeleteModels(models);
                    connector.NotifyConnectedPortsOfDeletion();
                }
            }
            else
            {
                try
                {
                    // Create a connector view model to begin drawing
                    var connector = new ConnectorViewModel(portModel);
                    this.SetActiveConnector(connector);
                }
                catch (Exception ex)
                {
                    System.Diagnostics.Debug.WriteLine(ex.Message);
                }
            }
        }
Example #16
0
        public void TestKeepReferenceThisAttribute()
        {
            // Test KeepReferenceThisAttribute could avoid a C# object from
            // being disposed even it is out function scope.
            //
            // The .dyn file uses ReferenceThis from FFITarget.dll. Note the
            // return value of GetItems() has reference to "this" object:
            //
            // class ReferenceThis {
            //  ....
            //  public IEnumerable<ReferenceThisItem> GetItems() {
            //      return new [] { new ReferenceThisItem(this), ... };
            //  }
            // }
            //
            // So if we call GetItems() in a function, refThis object will be
            // disposed and returned object has reference to disposed
            // ReferenceThis.
            //
            // def foo() {
            //   refThis = ReferenceThis();
            //   return = refThis.GetItems();
            // }
            //
            // But if applying KeepReferenceThisAttribute, refThis will be
            // referenced in the returned object and won't be disposed. This
            // test case is to verify ReferenceThis.Disposed is false when
            // returns from a function.
            var dynFilePath = Path.Combine(TestDirectory, @"core\dsevaluation\referenceThis.dyn");

            OpenModel(dynFilePath);
            var node1 = CurrentDynamoModel.CurrentWorkspace.Nodes.OfType <Graph.Nodes.CustomNodes.Function>().FirstOrDefault();
            var node2 = CurrentDynamoModel.CurrentWorkspace.Nodes.OfType <DSFunction>().FirstOrDefault();

            // Not connect at the beginning to ensure GC() is invoked.
            ConnectorModel.Make(node1, node2, 0, 0);
            RunCurrentModel();
            AssertPreviewValue("763c4e98-dbe0-4bb7-b00f-69e5b79b09b0", new object[] { false, false });
        }
        /// <summary>
        /// Rewires nodes and newly placed watch node between them.
        /// </summary>
        /// <param name="dynamoModel"></param>
        /// <param name="startNode"></param>
        /// <param name="endNode"></param>
        /// <param name="watchNodeModel"></param>
        private void WireNewNode(
            DynamoModel dynamoModel,
            NodeModel startNode,
            NodeModel endNode,
            NodeModel watchNodeModel,
            ConnectorModel connector,
            IEnumerable <Point> connectorPinLocations,
            List <ModelBase> allCreatedModels,
            List <ModelBase> allDeletedModels)
        {
            (int startIndex, int endIndex) = GetPortIndex(connector);

            // Connect startNode and watch node
            dynamoModel.ExecuteCommand(new DynamoModel.MakeConnectionCommand(startNode.GUID, startIndex, PortType.Output, DynamoModel.MakeConnectionCommand.Mode.Begin));
            dynamoModel.ExecuteCommand(new DynamoModel.MakeConnectionCommand(watchNodeModel.GUID, 0, PortType.Input, DynamoModel.MakeConnectionCommand.Mode.End));

            // Connect watch node and endNode
            dynamoModel.ExecuteCommand(new DynamoModel.MakeConnectionCommand(watchNodeModel.GUID, 0, PortType.Output, DynamoModel.MakeConnectionCommand.Mode.Begin));
            dynamoModel.ExecuteCommand(new DynamoModel.MakeConnectionCommand(endNode.GUID, endIndex, PortType.Input, DynamoModel.MakeConnectionCommand.Mode.End));

            PlacePinsOnWires(startNode, watchNodeModel, connector, connectorPinLocations, allCreatedModels, allDeletedModels);
        }
Example #18
0
        public void Disconnect(ConnectorModel connector, bool silent = false)
        {
            if (!connectors.Contains(connector))
            {
                return;
            }

            //throw the event for a disconnection
            if (!silent)
            {
                OnPortDisconnected();
            }

            connectors.Remove(connector);

            if (connectors.Count == 0)
            {
                IsConnected = false;
            }

            Owner.ValidateConnections();
        }
Example #19
0
        private void OnPortConnected(PortModel port, ConnectorModel connectorModel)
        {
            Tuple <int, NodeModel> input;

            if (!watch.TryGetInput(watch.InPorts.IndexOf(connectorModel.End), out input) ||
                astBeingComputed == null)
            {
                return;
            }

            var astBeingWatched = input.Item2.GetAstIdentifierForOutputIndex(input.Item1);

            if (astBeingComputed.Value != astBeingWatched.Value)
            {
                // the input node has changed, we clear preview
                rootWatchViewModel.Children.Clear();
            }
            else
            {
                ResetWatch();
            }
        }
        private void PlacePinsOnWires(NodeModel startNode,
                                      NodeModel watchNodeModel,
                                      ConnectorModel connector,
                                      IEnumerable <Point> connectorPinLocations,
                                      List <ModelBase> allCreatedModels,
                                      List <ModelBase> allDeletedModels)
        {
            // Collect ports & connectors of newly connected nodes
            // so that old pins (that need to remain) can be transferred over correctly.
            PortModel startNodePort = startNode.OutPorts.FirstOrDefault(p => p.GUID == connector.Start.GUID);
            PortModel watchNodePort = watchNodeModel.OutPorts[0];

            Graph.Connectors.ConnectorModel[] connectors = new Graph.Connectors.ConnectorModel[2];

            connectors[0] = startNodePort.Connectors.FirstOrDefault(c => c.End.Owner.GUID == watchNodeModel.GUID && c.GUID != connector.GUID);
            connectors[1] = watchNodePort.Connectors.FirstOrDefault(c => c.Start.Owner.GUID == watchNodeModel.GUID && c.GUID != connector.GUID);

            if (connectors.Any(c => c is null))
            {
                return;
            }

            allCreatedModels.AddRange(connectors);
            allDeletedModels.Add(connector);

            if (connectorPinLocations.Count() < 1)
            {
                return;
            }

            // Place each pin where required on the newly connected connectors.
            foreach (var connectorPinLocation in connectorPinLocations)
            {
                int wireIndex = ConnectorSegmentIndex(CurrentPosition, connectorPinLocation);
                ViewModel.PinConnectorPlacementFromWatchNode(connectors, wireIndex, connectorPinLocation, allCreatedModels);
            }
        }
Example #21
0
        /// <summary>
        ///     Creates and initializes a ConnectorModel from its Xml representation.
        /// </summary>
        /// <param name="connEl">XmlElement for a ConnectorModel.</param>
        /// <param name="nodes">Dictionary to be used for looking up a NodeModel by it's Guid.</param>
        /// <returns>Returns the new instance of ConnectorModel loaded from XmlElement.</returns>
        public static ConnectorModel LoadConnectorFromXml(XmlElement connEl, IDictionary <Guid, NodeModel> nodes)
        {
            var helper = new XmlElementHelper(connEl);

            var guid       = helper.ReadGuid("guid", Guid.NewGuid());
            var guidStart  = helper.ReadGuid("start");
            var guidEnd    = helper.ReadGuid("end");
            int startIndex = helper.ReadInteger("start_index");
            int endIndex   = helper.ReadInteger("end_index");

            //find the elements to connect
            NodeModel start;

            if (nodes.TryGetValue(guidStart, out start))
            {
                NodeModel end;
                if (nodes.TryGetValue(guidEnd, out end))
                {
                    return(ConnectorModel.Make(start, end, startIndex, endIndex, guid));
                }
            }

            return(null);
        }
Example #22
0
        public RewireConnectorOperation(ISketchItemDisplay pad, ConnectorModel model, Point p)
        {
            _connector = model;
            _pad       = pad;

            IBoundedSketchItemModel ending = model.To;

            if (ending == null)
            {
                ending = model.From;
            }
            var start = ConnectorUtilities.ComputeCenter(ending.Bounds);

            _selector = new ConnectablePairSelector(start, p);
            _pad.Canvas.Children.Add(_selector);
            _selector.Visibility = Visibility.Visible;
            foreach (var ch in _pad.Canvas.Children.OfType <ISketchItemUI>())
            {
                ch.Disable();
            }
            _pad.Canvas.MouseMove += HandleMouseMove;
            _pad.Canvas.MouseDown += HandleMouseDown;
            _pad.Canvas.KeyDown   += HandleKeyDown;
        }
Example #23
0
        public void ConnectorModelConnectTest()
        {
            //Arrange
            var outnode1 = new Output();

            outnode1.Symbol = "out1";

            var outnode2 = new Output();

            outnode2.Symbol = "out2";

            var numberNode = new DoubleInput();

            numberNode.Value = "5";

            //Act
            //It passes as parameters the same out port (start and end the same port) to the Connect(PortModel p) method then it won't create the connection to end.
            var connector1 = new ConnectorModel(numberNode.OutPorts.FirstOrDefault(), numberNode.OutPorts.FirstOrDefault(), Guid.NewGuid());

            //It passes the second parameter (End) the output port then the Connect(PortModel p) method will try to connect an End port and it will fail
            var connector2 = new ConnectorModel(outnode2.InPorts.FirstOrDefault(), numberNode.OutPorts.FirstOrDefault(), Guid.NewGuid());

            //The outnode2.InPorts has already nodes connected then when calling the Connect(PortModel p) method will remove the port connected
            var connector3 = new ConnectorModel(numberNode.OutPorts.FirstOrDefault(), outnode2.InPorts.FirstOrDefault(), Guid.NewGuid());

            //Assert
            //The End will be null due that the connection from Start to End was not created (out port was passed to both parameters)
            Assert.IsNull(connector1.End);

            //The End will be null due that the connection from Start to End was not created (in port was passed to both parameters)
            Assert.IsNull(connector2.End);

            //It will create the connector from Start to End (removing the previous connected InPort).
            Assert.IsNotNull(connector3.Start);
            Assert.IsNotNull(connector3.End);
        }
Example #24
0
 private void RegisterConnector(ConnectorModel connector)
 {
     connector.Deleted += () => OnConnectorDeleted(connector);
 }
Example #25
0
 protected virtual void OnConnectorAdded(ConnectorModel obj)
 {
     RegisterConnector(obj);
     var handler = ConnectorAdded;
     if (handler != null) handler(obj);
 }
Example #26
0
 /// <summary>
 /// Checks whether the given connection is inside the node to code set or outside it. 
 /// This determines if it should be redrawn(if it is external) or if it should be 
 /// deleted (if it is internal)
 /// </summary>
 private static bool IsInternalNodeToCodeConnection(IEnumerable<NodeModel> nodes, ConnectorModel connector)
 {
     return nodes.Contains(connector.Start.Owner) && nodes.Contains(connector.End.Owner);
 }
Example #27
0
 protected virtual void PortConnectedHandler(PortModel arg1, ConnectorModel arg2)
 {
     // Do nothing for a standard node.
 }
Example #28
0
        /// <summary>
        ///     Now that the portData has been set for the new ports, we recreate the connections we
        ///     so mercilessly destroyed, restoring peace and balance to the world once again.
        /// </summary>
        /// <param name="inportConnections"></param>
        /// <param name="outportConnections"> List of the connections that were killed</param>
        private void LoadAndCreateConnectors(OrderedDictionary inportConnections, OrderedDictionary outportConnections)
        {
            //----------------------------Inputs---------------------------------
            /* Input Port connections are matched only if the name is the same */
            for (int i = 0; i < InPortData.Count; i++)
            {
                string varName = InPortData[i].ToolTipString;
                if (inportConnections.Contains(varName))
                {
                    if (inportConnections[varName] != null)
                    {
                        foreach (var startPortModel in (inportConnections[varName] as List <PortModel>))
                        {
                            NodeModel startNode = startPortModel.Owner;
                            var       connector = ConnectorModel.Make(
                                startNode,
                                this,
                                startPortModel.Index,
                                i);
                        }
                        outportConnections[varName] = null;
                    }
                }
            }

            //----------------------------Outputs--------------------------------

            /*The matching is done in three parts:
             * Step 1:
             *   First, it tries to match the connectors wrt to the defined
             *   variable name. Hence it first checks to see if any of the old
             *   variable names are present. If so, if there were any connectors
             *   presnt then it makes the new connectors. As it iterates through
             *   the new ports, it also finds the ports that didnt exist before
             */
            List <int> undefinedIndices = new List <int>();

            for (int i = 0; i < OutPortData.Count; i++)
            {
                string varName = OutPortData[i].ToolTipString;
                if (outportConnections.Contains(varName))
                {
                    if (outportConnections[varName] != null)
                    {
                        foreach (var endPortModel in (outportConnections[varName] as List <PortModel>))
                        {
                            NodeModel endNode   = endPortModel.Owner;
                            var       connector = ConnectorModel.Make(this, endNode, i, endPortModel.Index);
                        }
                        outportConnections[varName] = null;
                    }
                }
                else
                {
                    undefinedIndices.Add(i);
                }
            }

            /*
             * Step 2:
             *   The second priority is to match the connections to the previous
             *   indices. For all the ports that were not previously defined, it
             *   now checks if that "numbered" port had any connections
             *   previously, ie, if the old third port had 2 connections, then
             *   these would go to the new 3rd port (if it is not a variable that
             *   was defined before)
             */
            for (int i = 0; i < undefinedIndices.Count; i++)
            {
                int index = undefinedIndices[i];
                if (index < outportConnections.Count && outportConnections[index] != null)
                {
                    foreach (PortModel endPortModel in (outportConnections[index] as List <PortModel>))
                    {
                        NodeModel endNode   = endPortModel.Owner;
                        var       connector = ConnectorModel.Make(this, endNode, index, endPortModel.Index);
                    }
                    outportConnections[index] = null;
                    undefinedIndices.Remove(index);
                    i--;
                }
            }

            /*
             * Step 2:
             *   The final step. Now that the priorties are finished, the
             *   function tries to reuse any existing connections by attaching
             *   them to any ports that have not already been given connections
             */
            List <List <PortModel> > unusedConnections =
                outportConnections.Values.Cast <List <PortModel> >()
                .Where(portModelList => portModelList != null)
                .ToList();

            while (undefinedIndices.Count > 0 && unusedConnections.Count != 0)
            {
                foreach (PortModel endPortModel in unusedConnections[0])
                {
                    NodeModel      endNode   = endPortModel.Owner;
                    ConnectorModel connector = ConnectorModel.Make(
                        this,
                        endNode,
                        undefinedIndices[0],
                        endPortModel.Index);
                }
                undefinedIndices.RemoveAt(0);
                unusedConnections.RemoveAt(0);
            }
        }
Example #29
0
 void Connectors_ConnectorDeleted(ConnectorModel c)
 {
     var connector = _connectors.FirstOrDefault(x => x.ConnectorModel == c);
     if (connector != null)
         _connectors.Remove(connector);
 }
 protected virtual void PortConnectedHandler(PortModel arg1, ConnectorModel arg2)
 {
     // Do nothing for a standard node.
 }
Example #31
0
        protected virtual void OnConnectorDeleted(ConnectorModel obj)
        {
            if (hasNodeInSyncWithDefinition)
            {
                undoRecorder.RecordModelAsOffTrack(obj.GUID);
            }

            var handler = ConnectorDeleted;
            if (handler != null) handler(obj);
        }
Example #32
0
        /// <summary>
        ///     Collapse a set of nodes in a given workspace.
        /// </summary>
        /// <param name="selectedNodes"> The function definition for the user-defined node </param>
        /// <param name="selectedNotes"> The note models in current selection </param>
        /// <param name="currentWorkspace"> The workspace where</param>
        /// <param name="args"></param>
        internal CustomNodeWorkspaceModel Collapse(
            IEnumerable <NodeModel> selectedNodes,
            IEnumerable <NoteModel> selectedNotes,
            WorkspaceModel currentWorkspace,
            FunctionNamePromptEventArgs args)
        {
            var selectedNodeSet = new HashSet <NodeModel>(selectedNodes);
            // Note that undoable actions are only recorded for the "currentWorkspace",
            // the nodes which get moved into "newNodeWorkspace" are not recorded for undo,
            // even in the new workspace. Their creations will simply be treated as part of
            // the opening of that new workspace (i.e. when a user opens a file, she will
            // not expect the nodes that show up to be undoable).
            //
            // After local nodes are moved into "newNodeWorkspace" as the result of
            // conversion, if user performs an undo, new set of nodes will be created in
            // "currentWorkspace" (not moving those nodes in the "newNodeWorkspace" back
            // into "currentWorkspace"). In another word, undo recording is on a per-
            // workspace basis, it does not work across different workspaces.
            //
            UndoRedoRecorder undoRecorder = currentWorkspace.UndoRecorder;

            CustomNodeWorkspaceModel newWorkspace;

            Debug.WriteLine("Current workspace has {0} nodes and {1} connectors",
                            currentWorkspace.Nodes.Count(), currentWorkspace.Connectors.Count());

            using (undoRecorder.BeginActionGroup())
            {
                #region Determine Inputs and Outputs

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

                var outputs =
                    new HashSet <Tuple <NodeModel, int, Tuple <int, NodeModel> > >(
                        selectedNodeSet.SelectMany(
                            node =>
                            Enumerable.Range(0, node.OutPorts.Count)
                            .Where(index => node.OutPorts[index].Connectors.Any())
                            .SelectMany(
                                data =>
                                node.OutputNodes[data].Where(
                                    output => !selectedNodeSet.Contains(output.Item2))
                                .Select(output => Tuple.Create(node, data, output)))));

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

                double leftShift = leftMost - 250;

                #endregion

                #region Handle full selected connectors

                // Step 2: Determine all the connectors whose start/end owners are
                // both in the selection set, and then move them from the current
                // workspace into the new workspace.

                var fullySelectedConns = new HashSet <ConnectorModel>(
                    currentWorkspace.Connectors.Where(
                        conn =>
                {
                    bool startSelected = selectedNodeSet.Contains(conn.Start.Owner);
                    bool endSelected   = selectedNodeSet.Contains(conn.End.Owner);
                    return(startSelected && endSelected);
                }));

                foreach (var connector in fullySelectedConns)
                {
                    undoRecorder.RecordDeletionForUndo(connector);
                    connector.Delete();
                }

                #endregion

                #region Handle partially selected connectors

                // Step 3: Partially selected connectors (either one of its start
                // and end owners is in the selection) are to be destroyed.

                var partiallySelectedConns =
                    currentWorkspace.Connectors.Where(
                        conn =>
                        selectedNodeSet.Contains(conn.Start.Owner) ||
                        selectedNodeSet.Contains(conn.End.Owner)).ToList();

                foreach (var connector in partiallySelectedConns)
                {
                    undoRecorder.RecordDeletionForUndo(connector);
                    connector.Delete();
                }

                #endregion

                #region Transfer nodes and connectors to new workspace

                var newNodes       = new List <NodeModel>();
                var newNotes       = new List <NoteModel>();
                var newAnnotations = new List <AnnotationModel>();

                // Step 4: move all nodes and notes to new workspace remove from old
                // PB: This could be more efficiently handled by a copy paste, but we
                // are preservering the node
                foreach (var node in selectedNodeSet)
                {
                    undoRecorder.RecordDeletionForUndo(node);
                    currentWorkspace.RemoveAndDisposeNode(node);

                    // Assign a new guid to this node, otherwise when node is
                    // compiled to AST, literally it is still in global scope
                    // instead of in function scope.
                    node.GUID = Guid.NewGuid();

                    // shift nodes
                    node.X = node.X - leftShift;
                    node.Y = node.Y - topMost;

                    newNodes.Add(node);
                }

                foreach (var note in selectedNotes)
                {
                    undoRecorder.RecordDeletionForUndo(note);
                    currentWorkspace.RemoveNote(note);

                    note.GUID = Guid.NewGuid();
                    note.X    = note.X - leftShift;
                    note.Y    = note.Y - topMost;
                    newNotes.Add(note);
                }

                //Copy the group from newNodes
                foreach (var group in DynamoSelection.Instance.Selection.OfType <AnnotationModel>())
                {
                    undoRecorder.RecordDeletionForUndo(group);
                    currentWorkspace.RemoveGroup(group);

                    group.GUID  = Guid.NewGuid();
                    group.Nodes = group.DeletedModelBases;
                    newAnnotations.Add(group);
                }

                // Now all selected nodes already moved to custom workspace,
                // clear the selection.
                DynamoSelection.Instance.ClearSelection();

                foreach (var conn in fullySelectedConns)
                {
                    ConnectorModel.Make(conn.Start.Owner, conn.End.Owner, conn.Start.Index, conn.End.Index);
                }

                #endregion

                #region Process inputs

                var inConnectors       = new List <Tuple <NodeModel, int> >();
                var uniqueInputSenders = new Dictionary <Tuple <NodeModel, int>, Symbol>();

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

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

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

                    Symbol node;

                    var key = Tuple.Create(inputNode, inputData);
                    if (uniqueInputSenders.ContainsKey(key))
                    {
                        node = uniqueInputSenders[key];
                    }
                    else
                    {
                        inConnectors.Add(Tuple.Create(inputNode, inputData));

                        node = new Symbol
                        {
                            InputSymbol = inputReceiverNode.InPorts[inputReceiverData].Name,
                            X           = 0
                        };

                        // Try to figure out the type of input of custom node
                        // from the type of input of selected node. There are
                        // two kinds of nodes whose input type are available:
                        // function node and custom node.
                        List <Library.TypedParameter> parameters = null;

                        if (inputReceiverNode is EFunction)
                        {
                            var func = inputReceiverNode as EFunction;
                            parameters = func.Controller.Definition.Parameters.ToList();
                        }
                        else if (inputReceiverNode is DSFunctionBase)
                        {
                            var dsFunc   = inputReceiverNode as DSFunctionBase;
                            var funcDesc = dsFunc.Controller.Definition;
                            parameters = funcDesc.Parameters.ToList();

                            if (funcDesc.Type == Engine.FunctionType.InstanceMethod ||
                                funcDesc.Type == Engine.FunctionType.InstanceProperty)
                            {
                                var dummyType = new ProtoCore.Type()
                                {
                                    Name = funcDesc.ClassName
                                };
                                var instanceParam = new TypedParameter(funcDesc.ClassName, dummyType);
                                parameters.Insert(0, instanceParam);
                            }
                        }

                        // so the input of custom node has format
                        //    input_var_name : type
                        if (parameters != null && parameters.Count() > inputReceiverData)
                        {
                            var typeName = parameters[inputReceiverData].DisplayTypeName;
                            if (!string.IsNullOrEmpty(typeName))
                            {
                                node.InputSymbol += " : " + typeName;
                            }
                        }

                        node.SetNameFromNodeNameAttribute();
                        node.Y = inputIndex * (50 + node.Height);

                        uniqueInputSenders[key] = node;

                        newNodes.Add(node);
                    }

                    ConnectorModel.Make(node, inputReceiverNode, 0, inputReceiverData);
                }

                #endregion

                #region Process outputs

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

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

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

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

                            //Create Symbol Node
                            var node = new Output
                            {
                                Symbol = outputSenderNode.OutPorts[outputSenderData].Name,
                                X      = rightMost + 75 - leftShift
                            };

                            node.Y = i * (50 + node.Height);

                            node.SetNameFromNodeNameAttribute();

                            newNodes.Add(node);
                            ConnectorModel.Make(outputSenderNode, node, outputSenderData, 0);

                            i++;
                        }
                    }

                    //Connect outputs to new node
                    outConnectors.AddRange(
                        from output in outputs
                        let outputSenderNode = output.Item1
                                               let outputSenderData = output.Item2
                                                                      let outputReceiverData = output.Item3.Item1
                                                                                               let outputReceiverNode = output.Item3.Item2
                                                                                                                        select
                                                                                                                        Tuple.Create(
                            outputReceiverNode,
                            outportList.FindIndex(
                                x => x.Item1 == outputSenderNode && x.Item2 == outputSenderData),
                            outputReceiverData));
                }
                else
                {
                    foreach (var hanging in
                             selectedNodeSet.SelectMany(
                                 node =>
                                 Enumerable.Range(0, node.OutPorts.Count)
                                 .Where(index => !node.OutPorts[index].IsConnected)
                                 .Select(port => new { node, port })).Distinct())
                    {
                        //Create Symbol Node
                        var node = new Output
                        {
                            Symbol = hanging.node.OutPorts[hanging.port].Name,
                            X      = rightMost + 75 - leftShift
                        };
                        node.Y = i * (50 + node.Height);
                        node.SetNameFromNodeNameAttribute();

                        newNodes.Add(node);
                        ConnectorModel.Make(hanging.node, node, hanging.port, 0);

                        i++;
                    }
                }

                #endregion

                var newId = Guid.NewGuid();
                newWorkspace = new CustomNodeWorkspaceModel(
                    nodeFactory,
                    newNodes,
                    newNotes,
                    newAnnotations,
                    Enumerable.Empty <PresetModel>(),
                    currentWorkspace.ElementResolver,
                    new WorkspaceInfo()
                {
                    X           = 0,
                    Y           = 0,
                    Name        = args.Name,
                    Category    = args.Category,
                    Description = args.Description,
                    ID          = newId.ToString(),
                    FileName    = string.Empty,
                    IsVisibleInDynamoLibrary = true
                });

                newWorkspace.HasUnsavedChanges = true;

                RegisterCustomNodeWorkspace(newWorkspace);

                Debug.WriteLine("Collapsed workspace has {0} nodes and {1} connectors",
                                newWorkspace.Nodes.Count(), newWorkspace.Connectors.Count());

                var collapsedNode = CreateCustomNodeInstance(newId);
                collapsedNode.X = avgX;
                collapsedNode.Y = avgY;
                currentWorkspace.AddAndRegisterNode(collapsedNode, centered: false);
                undoRecorder.RecordCreationForUndo(collapsedNode);

                foreach (var connector in
                         inConnectors.Select((x, idx) => new { node = x.Item1, from = x.Item2, to = idx })
                         .Select(
                             nodeTuple =>
                             ConnectorModel.Make(
                                 nodeTuple.node,
                                 collapsedNode,
                                 nodeTuple.@from,
                                 nodeTuple.to))
                         .Where(connector => connector != null))
                {
                    undoRecorder.RecordCreationForUndo(connector);
                }

                foreach (var connector in
                         outConnectors.Select(
                             nodeTuple =>
                             ConnectorModel.Make(
                                 collapsedNode,
                                 nodeTuple.Item1,
                                 nodeTuple.Item2,
                                 nodeTuple.Item3)).Where(connector => connector != null))
                {
                    undoRecorder.RecordCreationForUndo(connector);
                }
            }
            return(newWorkspace);
        }
Example #33
0
 /// <summary>
 /// Checks whether the given connection is inside the node to code set or outside it.
 /// This determines if it should be redrawn(if it is external) or if it should be
 /// deleted (if it is internal)
 /// </summary>
 private static bool IsInternalNodeToCodeConnection(IEnumerable <NodeModel> nodes, ConnectorModel connector)
 {
     return(nodes.Contains(connector.Start.Owner) && nodes.Contains(connector.End.Owner));
 }
Example #34
0
 void Connectors_ConnectorAdded(ConnectorModel c)
 {
     var viewModel = new ConnectorViewModel(this, c);
     if (_connectors.All(x => x.ConnectorModel != c))
         _connectors.Add(viewModel);
 }
Example #35
0
        protected virtual void OnConnectorDeleted(ConnectorModel obj)
        {
            if (hasNodeInSyncWithDefinition)
            {
                undoRecorder.RecordModelAsOffTrack(obj.GUID);
            }

            var handler = ConnectorDeleted;
            if (handler != null) handler(obj);
            //Check if the workspace is loaded, i.e all the nodes are
            //added to the workspace. In that case, compute the Upstream cache for the
            //given node.
            if (workspaceLoaded)
            {
                obj.End.Owner.ComputeUpstreamOnDownstreamNodes();
            }
        }
Example #36
0
 protected virtual void OnConnectorAdded(ConnectorModel obj)
 {
     RegisterConnector(obj);
     var handler = ConnectorAdded;
     if (handler != null) handler(obj);
     //Check if the workspace is loaded, i.e all the nodes are
     //added to the workspace. In that case, compute the Upstream cache for the
     //given node.
     if (workspaceLoaded)
     {
         obj.End.Owner.ComputeUpstreamOnDownstreamNodes();
     }
 }
Example #37
0
        public void AddPresetShouldSetDirtyFlag()

        {
            var model = CurrentDynamoModel;
            //create some numbers
            var numberNode1 = new DoubleInput();

            numberNode1.Value = "1";
            var numberNode2 = new DoubleInput();

            numberNode2.Value = "2";

            var addNode = new DSFunction(model.LibraryServices.GetFunctionDescriptor("+"));

            //Check for Dirty flag
            Assert.AreEqual(model.CurrentWorkspace.HasUnsavedChanges, false);

            //add the nodes
            model.CurrentWorkspace.AddAndRegisterNode(numberNode1, false);
            model.CurrentWorkspace.AddAndRegisterNode(numberNode2, false);
            model.CurrentWorkspace.AddAndRegisterNode(addNode, false);

            //Check for Dirty flag
            Assert.AreEqual(model.CurrentWorkspace.HasUnsavedChanges, true);

            //Set the dirty flag to false. Mocking the save.
            model.CurrentWorkspace.HasUnsavedChanges = false;
            Assert.AreEqual(model.CurrentWorkspace.HasUnsavedChanges, false);

            //connect them up
            ConnectorModel.Make(numberNode1, addNode, 0, 0);
            ConnectorModel.Make(numberNode2, addNode, 0, 1);

            //Check for Dirty flag - After the connection the dirty flag should be set.
            Assert.AreEqual(model.CurrentWorkspace.HasUnsavedChanges, true);

            //Set the dirty flag to false. Mocking the save.
            model.CurrentWorkspace.HasUnsavedChanges = false;
            Assert.AreEqual(model.CurrentWorkspace.HasUnsavedChanges, false);

            Assert.AreEqual(model.CurrentWorkspace.Nodes.Count(), 3);
            Assert.AreEqual(model.CurrentWorkspace.Connectors.Count(), 2);

            //create the first state with the numbers selected
            DynamoSelection.Instance.Selection.Add(numberNode1);
            DynamoSelection.Instance.Selection.Add(numberNode2);
            var ids = DynamoSelection.Instance.Selection.OfType <NodeModel>().Select(x => x.GUID).ToList();

            //create the preset from 2 nodes
            model.CurrentWorkspace.AddPreset(
                "state1",
                "3", ids);

            Assert.AreEqual(1, model.CurrentWorkspace.Presets.Count());

            //change values
            numberNode1.Value = "2";
            numberNode2.Value = "3";

            DynamoSelection.Instance.ClearSelection();
            DynamoSelection.Instance.Selection.Add(numberNode1);
            DynamoSelection.Instance.Selection.Add(numberNode2);
            ids = DynamoSelection.Instance.Selection.OfType <NodeModel>().Select(x => x.GUID).ToList();

            model.CurrentWorkspace.AddPreset(
                "state2",
                "5", ids);

            //Check for Dirty flag - After the Preset the dirty flag should be set.
            Assert.AreEqual(model.CurrentWorkspace.HasUnsavedChanges, true);
        }
 protected override void PortConnectedHandler(PortModel arg1, ConnectorModel arg2)
 {
     UpdateUpstream();
 }
Example #39
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>
        public static void Collapse(IEnumerable <NodeModel> selectedNodes, WorkspaceModel currentWorkspace, FunctionNamePromptEventArgs args = null)
        {
            var selectedNodeSet = new HashSet <NodeModel>(selectedNodes);

            if (args == null || !args.Success)
            {
                args = new FunctionNamePromptEventArgs();
                dynSettings.Controller.DynamoModel.OnRequestsFunctionNamePrompt(null, args);

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

            var newNodeWorkspace = new CustomNodeWorkspaceModel(args.Name, args.Category, args.Description, 0, 0)
            {
                WatchChanges      = false,
                HasUnsavedChanges = true
            };

            var newNodeDefinition = new FunctionDefinition(Guid.NewGuid())
            {
                WorkspaceModel = 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 <NodeModel, int, Tuple <int, NodeModel> > >(
                selectedNodeSet.SelectMany(
                    node => Enumerable.Range(0, node.InPortData.Count).Where(node.HasConnectedInput)
                    .Select(data => Tuple.Create(node, data, node.Inputs[data]))
                    .Where(input => !selectedNodeSet.Contains(input.Item3.Item2))));

            var outputs = new HashSet <Tuple <NodeModel, int, Tuple <int, NodeModel> > >(
                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 <NodeModel>(
                    inputs
                    .Select(x => x.Item3.Item2)
                    .Intersect(outputs.Select(x => x.Item3.Item2)))
                .Select(
                    outerNode =>
            {
                var node = new Apply1();

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

                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 <ConnectorModel>(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)
            {
                ele.SaveResult = false;
                currentWorkspace.Nodes.Remove(ele);
                ele.WorkSpace = newNodeWorkspace;
            }
            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 (NodeModel 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 (ConnectorModel connector in removeConnectors)
            {
                connector.NotifyConnectedPortsOfDeletion();
                currentWorkspace.Connectors.Remove(connector);
            }

            #endregion

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

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

            #region Process inputs

            var uniqueInputSenders = new Dictionary <Tuple <NodeModel, int>, Symbol>();

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

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

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

                Symbol 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 Symbol
                    {
                        InputSymbol = 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();

                    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 = ConnectorModel.Make(node,
                                                    inputReceiverNode,
                                                    0,
                                                    inputReceiverData,
                                                    PortType.INPUT);

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

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

                    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 <NodeModel, int> >();

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

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

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

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

                    //Create Symbol Node
                    var node = new Output
                    {
                        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();

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

                    var conn = ConnectorModel.Make(
                        outputSenderNode,
                        node,
                        outputSenderData,
                        0,
                        PortType.INPUT);

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

                    i++;
                }
            }

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

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

                int       outputReceiverData = output.Item3.Item1;
                NodeModel 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 = ConnectorModel.Make(
                        outputSenderNode,
                        curriedNode.InnerNode,
                        outputSenderData,
                        targetPortIndex + 1,
                        PortType.INPUT);

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

            #endregion

            // save and load the definition from file
            newNodeDefinition.SyncWithWorkspace(true, true);
            dynSettings.Controller.DynamoModel.Workspaces.Add(newNodeWorkspace);

            string name          = newNodeDefinition.FunctionId.ToString();
            var    collapsedNode = dynSettings.Controller.DynamoModel.CreateNode(avgX, avgY, name);

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

            collapsedNode.DisableReporting();

            foreach (var nodeTuple in inConnectors)
            {
                var conn = ConnectorModel.Make(
                    nodeTuple.Item1,
                    collapsedNode,
                    nodeTuple.Item2,
                    nodeTuple.Item3,
                    PortType.INPUT);

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

            foreach (var nodeTuple in outConnectors)
            {
                var conn = ConnectorModel.Make(
                    collapsedNode,
                    nodeTuple.Item1,
                    nodeTuple.Item2,
                    nodeTuple.Item3,
                    PortType.INPUT);

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

            collapsedNode.EnableReporting();
            currentWorkspace.EnableReporting();

            newNodeWorkspace.WatchChanges = true;
        }
Example #40
0
        /// <summary>
        /// Construct a view and respond to property changes on the model. 
        /// </summary>
        /// <param name="model"></param>
        public ConnectorViewModel(WorkspaceViewModel workspace, ConnectorModel model)
        {
            this.workspaceViewModel = workspace;
            _model = model;

            _model.PropertyChanged += Model_PropertyChanged;
            _model.Start.Owner.PropertyChanged += StartOwner_PropertyChanged;
            _model.End.Owner.PropertyChanged += EndOwner_PropertyChanged;

            workspaceViewModel.DynamoViewModel.PropertyChanged += DynamoViewModel_PropertyChanged;
            Nodevm.PropertyChanged += nodeViewModel_PropertyChanged;
            Redraw();
        }