using System; using System.Collections.Generic; using System.Collections.Specialized; using System.Linq; using System.Reactive.Linq; using System.Text; using System.Threading.Tasks; using DynamicData; using NodeNetwork.Utilities; using NodeNetwork.Views; using ReactiveUI; namespace NodeNetwork.ViewModels { /// /// Viewmodel class for outputs on a node. /// Outputs are endpoints that can only be connected to inputs. /// public class NodeOutputViewModel : Endpoint { static NodeOutputViewModel() { NNViewRegistrar.AddRegistration(() => new NodeOutputView(), typeof(IViewFor)); } #region Logger private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); #endregion public NodeOutputViewModel() { MaxConnections = Int32.MaxValue; this.PortPosition = PortPosition.Right; } /// /// Sets the pending connection in the network to a new connection with this endpoint as the output. /// If the connection would be invalid, no pending connection is made. /// Called when the user clicks on this endpoint. /// protected override void CreatePendingConnection() { NetworkViewModel network = Parent?.Parent; if (network == null) { return; } if (Connections.Count >= MaxConnections) { return; } network.PendingConnection = new PendingConnectionViewModel(network) { Output = this, OutputIsLocked = true, LooseEndPoint = Port.CenterPoint }; } /// /// Sets this endpoint as the output of the pending connection and updates its validation. /// Called when the user drags and holds a pending connection over this endpoint. /// /// /// True to set this endpoint as the output of the pending connection. /// To remove this endpoint from the pending connection, set this to false. /// protected override void SetConnectionPreview(bool previewActive) { PendingConnectionViewModel pendingCon = Parent.Parent.PendingConnection; if (pendingCon.Output != null && (pendingCon.Output != this || pendingCon.OutputIsLocked)) { return; } if (previewActive) { pendingCon.Output = this; pendingCon.Validation = pendingCon.Input.ConnectionValidator(pendingCon); } else { pendingCon.Output = null; pendingCon.Validation = null; } } /// /// Tries to create a new connection in the network based on the pending connection and this endpoint as the output. /// If the connection would be invalid, no connection is made. /// The pending connection is deleted. /// Called when the user drags and releases a pending connection over this endpoint. /// protected override void FinishPendingConnection() { NetworkViewModel network = Parent?.Parent; if (network == null) { return; } if (network.PendingConnection.Output == this && !network.PendingConnection.OutputIsLocked) { //Only allow drag from output to input, not input to input if (network.PendingConnection.Input.Parent != network.PendingConnection.Output.Parent) { //Dont allow connections between an input and an output on the same node if (network.PendingConnection.Validation.IsValid) { //Connection is valid if (MaxConnections > Connections.Count) { //MaxConnections hasn't been reached yet. if (!network.Connections.Items.Any(con => con.Output == this && con.Input == network.PendingConnection.Input)) { //Connection does not exist already network.Connections.Add(network.ConnectionFactory(network.PendingConnection.Input, this)); } } } } } network.RemovePendingConnection(); } } }