From facc68b78d8de4b562e4841a91a16c46570fc814 Mon Sep 17 00:00:00 2001 From: Tom Wendel Date: Tue, 22 Sep 2020 21:11:59 +0200 Subject: [PATCH 01/84] Show up existing wires in tree --- .../Models/NodeModel.cs | 9 ++++ .../Models/WireNodeModel.cs | 13 +++++ .../TreeTemplateSelector.cs | 4 ++ .../ViewModels/RuntimeViewModel.cs | 48 +++++++++++++++++-- .../Views/RuntimeView.xaml | 8 ++++ 5 files changed, 77 insertions(+), 5 deletions(-) create mode 100644 src/Applications/OctoPatch.DesktopClient/Models/WireNodeModel.cs diff --git a/src/Applications/OctoPatch.DesktopClient/Models/NodeModel.cs b/src/Applications/OctoPatch.DesktopClient/Models/NodeModel.cs index bd80124..6afbc29 100644 --- a/src/Applications/OctoPatch.DesktopClient/Models/NodeModel.cs +++ b/src/Applications/OctoPatch.DesktopClient/Models/NodeModel.cs @@ -59,5 +59,14 @@ protected NodeModel(ConnectorDescription description) : this(description.Key) { Name = description.DisplayName; } + + protected NodeModel(Guid wireId) + { + this.Name = "Wire"; + Items = new ObservableCollection(); + Key = wireId.ToString(); + State = NodeState.Uninitialized; + + } } } diff --git a/src/Applications/OctoPatch.DesktopClient/Models/WireNodeModel.cs b/src/Applications/OctoPatch.DesktopClient/Models/WireNodeModel.cs new file mode 100644 index 0000000..7869b60 --- /dev/null +++ b/src/Applications/OctoPatch.DesktopClient/Models/WireNodeModel.cs @@ -0,0 +1,13 @@ +using System; +using OctoPatch.Descriptions; + +namespace OctoPatch.DesktopClient.Models +{ + public sealed class WireNodeModel : NodeModel + { + public WireNodeModel(Guid wireId, string name) : base(wireId) + { + Name = name; + } + } +} diff --git a/src/Applications/OctoPatch.DesktopClient/TreeTemplateSelector.cs b/src/Applications/OctoPatch.DesktopClient/TreeTemplateSelector.cs index ca004d4..d732ede 100644 --- a/src/Applications/OctoPatch.DesktopClient/TreeTemplateSelector.cs +++ b/src/Applications/OctoPatch.DesktopClient/TreeTemplateSelector.cs @@ -18,6 +18,8 @@ public sealed class TreeTemplateSelector : DataTemplateSelector public DataTemplate InputTemplate { get; set; } + public DataTemplate WireTemplate { get; set; } + public override DataTemplate SelectTemplate(object item, DependencyObject container) { switch (item) @@ -34,6 +36,8 @@ public override DataTemplate SelectTemplate(object item, DependencyObject contai return OutputTemplate; case InputNodeModel _: return InputTemplate; + case WireNodeModel _: + return WireTemplate; } return base.SelectTemplate(item, container); diff --git a/src/Applications/OctoPatch.DesktopClient/ViewModels/RuntimeViewModel.cs b/src/Applications/OctoPatch.DesktopClient/ViewModels/RuntimeViewModel.cs index ec63c74..e7cf67a 100644 --- a/src/Applications/OctoPatch.DesktopClient/ViewModels/RuntimeViewModel.cs +++ b/src/Applications/OctoPatch.DesktopClient/ViewModels/RuntimeViewModel.cs @@ -19,9 +19,11 @@ public sealed class RuntimeViewModel : IRuntimeViewModel { private readonly IRuntime _runtime; - private List _nodes; + private readonly List _nodes; - private List _descriptions; + private readonly List _wires; + + private readonly List _descriptions; public ObservableCollection NodeDescriptions { get; } @@ -165,7 +167,7 @@ public NodeModel SelectedNode _startSelectedNode.Enabled = item != null; _stopSelectedNode.Enabled = item != null; _saveNodeDescription.Enabled = item != null; - _takeConnector.Enabled = (SelectedWireConnector != null && value is InputNodeModel) || value is OutputNodeModel; + _takeConnector.Enabled = SelectedWireConnector != null && value is InputNodeModel || value is OutputNodeModel; //// TODO: Lookup model by Attribute if (item?.Setup.Key == "12ea0035-45af-4da8-8b5d-e1b9d9484ba4:MidiDeviceNode") @@ -250,6 +252,7 @@ private set public RuntimeViewModel() { _nodes = new List(); + _wires = new List(); _descriptions = new List(); NodeDescriptions = new ObservableCollection(); @@ -295,7 +298,7 @@ private async void TakeConnectorCallback(object obj) if (SelectedWireConnector != null && node is InputNodeModel inputNode) { await _runtime.AddWire( - SelectedWireConnector.ParentId, SelectedWireConnector.Key, + SelectedWireConnector.ParentId, SelectedWireConnector.Key, inputNode.ParentId, inputNode.Key, CancellationToken.None); SelectedWireConnector = null; _takeConnector.Enabled = false; @@ -479,8 +482,30 @@ private void RuntimeOnOnWireRemoved(Guid obj) { } - private void RuntimeOnOnWireAdded(WireSetup obj) + private void RuntimeOnOnWireAdded(WireSetup wire) { + var inputNode = _nodes.First(n => n.Setup.NodeId == wire.InputNodeId); + var inputConnector = inputNode.Model.Items.OfType() + .First(m => m.Key == wire.InputConnectorKey); + + var outputNode = _nodes.First(n => n.Setup.NodeId == wire.OutputNodeId); + var outputConnector = outputNode.Model.Items.OfType() + .First(m => m.Key == wire.OutputConnectorKey); + + var inputWire = new WireNodeModel(wire.WireId, $"Wire to {outputNode.Model.Name} ({outputConnector.Name})"); + inputConnector.Items.Add(inputWire); + + var outputWire = new WireNodeModel(wire.WireId, $"Wire to {inputNode.Model.Name} ({inputConnector.Name})"); + outputConnector.Items.Add(outputWire); + + _wires.Add(new WireItem + { + InputConnector = inputConnector, + InputWire = inputWire, + OutputConnector = outputConnector, + OutputWire = outputWire, + Setup = wire + }); } private void RuntimeOnOnNodeRemoved(Guid obj) @@ -617,5 +642,18 @@ private sealed class NodeItem public NodeModel Model { get; set; } } + + private sealed class WireItem + { + public InputNodeModel InputConnector { get; set; } + + public OutputNodeModel OutputConnector { get; set; } + + public WireNodeModel InputWire { get; set; } + + public WireNodeModel OutputWire { get; set; } + + public WireSetup Setup { get; set; } + } } } diff --git a/src/Applications/OctoPatch.DesktopClient/Views/RuntimeView.xaml b/src/Applications/OctoPatch.DesktopClient/Views/RuntimeView.xaml index f53743f..c3b1f0c 100644 --- a/src/Applications/OctoPatch.DesktopClient/Views/RuntimeView.xaml +++ b/src/Applications/OctoPatch.DesktopClient/Views/RuntimeView.xaml @@ -87,6 +87,14 @@ + + + + + + + + From 661730e7e08bed1d67861cb4e249224b5d8c49a1 Mon Sep 17 00:00:00 2001 From: Tom Wendel Date: Tue, 22 Sep 2020 21:13:30 +0200 Subject: [PATCH 02/84] Add more methods and events to the IRuntime interface - SetNodePosition - (On)WireUpdated --- src/Core/OctoPatch.Client/RuntimeClient.cs | 43 +++++++++++----------- src/Core/OctoPatch.Server/Runtime.cs | 29 ++++++++------- src/Core/OctoPatch.Server/RuntimeHub.cs | 5 +++ src/Core/OctoPatch/IRuntimeCallbacks.cs | 6 +++ src/Core/OctoPatch/IRuntimeEvents.cs | 5 +++ src/Core/OctoPatch/IRuntimeMethods.cs | 10 +++++ src/Core/OctoPatch/Setup/WireSetup.cs | 10 +++++ 7 files changed, 72 insertions(+), 36 deletions(-) diff --git a/src/Core/OctoPatch.Client/RuntimeClient.cs b/src/Core/OctoPatch.Client/RuntimeClient.cs index 07dece6..ef85078 100644 --- a/src/Core/OctoPatch.Client/RuntimeClient.cs +++ b/src/Core/OctoPatch.Client/RuntimeClient.cs @@ -125,6 +125,11 @@ public Task SetNodeConfiguration(Guid nodeGuid, string configuration, Cancellati return _hubConnection.InvokeAsync(nameof(SetNodeConfiguration), nodeGuid, configuration, cancellationToken, cancellationToken); } + public Task SetNodePosition(Guid nodeId, int x, int y, CancellationToken cancellationToken) + { + return _hubConnection.InvokeAsync(nameof(SetNodePosition), nodeId, x, y, cancellationToken); + } + public Task StartNode(Guid nodeId, CancellationToken cancellationToken) { throw new NotImplementedException(); @@ -165,9 +170,9 @@ public Task RemoveWire(Guid wireId, CancellationToken cancellationToken) /// /// /// - public void OnNodeAdded(NodeSetup instance, NodeState state, string environment) + public void OnNodeAdded(NodeSetup setup, NodeState state, string environment) { - NodeAdded?.Invoke(instance, state, environment); + NodeAdded?.Invoke(setup, state, environment); } /// @@ -197,62 +202,56 @@ public void OnNodeRemoved(Guid instanceGuid) /// /// /// - public void OnNodeUpdated(NodeSetup nodeSetup) + public void OnNodeUpdated(NodeSetup setup) { - NodeUpdated?.Invoke(nodeSetup); + NodeUpdated?.Invoke(setup); } /// /// /// - public void OnWireAdded(WireSetup instance) + public void OnWireAdded(WireSetup setup) { - WireAdded?.Invoke(instance); + WireAdded?.Invoke(setup); } /// /// /// - public void OnWireRemoved(Guid instanceGuid) + public void OnWireRemoved(Guid wireId) + { + WireRemoved?.Invoke(wireId); + } + + public void OnWireUpdated(WireSetup setup) { - WireRemoved?.Invoke(instanceGuid); + WireUpdated?.Invoke(setup); } #endregion - /// /// - /// public event Action NodeAdded; - /// /// - /// public event Action NodeRemoved; - /// /// - /// public event Action NodeUpdated; - /// /// - /// public event Action NodeStateChanged; - /// /// - /// public event Action NodeEnvironmentChanged; - /// /// - /// public event Action WireAdded; - /// /// - /// public event Action WireRemoved; + + /// + public event Action WireUpdated; } } diff --git a/src/Core/OctoPatch.Server/Runtime.cs b/src/Core/OctoPatch.Server/Runtime.cs index beba15f..43817eb 100644 --- a/src/Core/OctoPatch.Server/Runtime.cs +++ b/src/Core/OctoPatch.Server/Runtime.cs @@ -281,6 +281,18 @@ public Task SetNodeDescription(Guid nodeId, string name, string description, Can return Task.CompletedTask; } + public Task SetNodePosition(Guid nodeId, int x, int y, CancellationToken cancellationToken) + { + if (_nodeMapping.TryGetValue(nodeId, out var nodeSetup)) + { + nodeSetup.setup.PositionX = x; + nodeSetup.setup.PositionY = y; + NodeUpdated?.Invoke(nodeSetup.setup); + } + + return Task.CompletedTask; + } + public Task SetConfiguration(GridSetup grid, CancellationToken cancellationToken) { //var description = _descriptions.First(d => d.Guid == nodeInstance.NodeDescription); @@ -334,39 +346,28 @@ public async Task StopNode(Guid nodeId, CancellationToken cancellationToken) } } - /// /// - /// public event Action NodeAdded; - /// /// - /// public event Action NodeRemoved; - /// /// - /// public event Action WireAdded; - /// /// - /// public event Action WireRemoved; + + /// + public event Action WireUpdated; - /// /// - /// public event Action NodeUpdated; - /// /// - /// public event Action NodeStateChanged; - /// /// - /// public event Action NodeEnvironmentChanged; } } diff --git a/src/Core/OctoPatch.Server/RuntimeHub.cs b/src/Core/OctoPatch.Server/RuntimeHub.cs index 620ba9f..349aae4 100644 --- a/src/Core/OctoPatch.Server/RuntimeHub.cs +++ b/src/Core/OctoPatch.Server/RuntimeHub.cs @@ -170,6 +170,11 @@ public Task SetNodeConfiguration(Guid nodeGuid, string configuration, Cancellati //// TODO: Apply configuration to the node } + public Task SetNodePosition(Guid nodeId, int x, int y, CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } + public Task StartNode(Guid nodeId, CancellationToken cancellationToken) { throw new NotImplementedException(); diff --git a/src/Core/OctoPatch/IRuntimeCallbacks.cs b/src/Core/OctoPatch/IRuntimeCallbacks.cs index 0486c46..f153d1f 100644 --- a/src/Core/OctoPatch/IRuntimeCallbacks.cs +++ b/src/Core/OctoPatch/IRuntimeCallbacks.cs @@ -53,5 +53,11 @@ public interface IRuntimeCallbacks /// /// wire guid void OnWireRemoved(Guid instanceGuid); + + /// + /// Gets a call when a wire was updated + /// + /// updated setup + void OnWireUpdated(WireSetup setup); } } diff --git a/src/Core/OctoPatch/IRuntimeEvents.cs b/src/Core/OctoPatch/IRuntimeEvents.cs index 5f2beb6..259eddc 100644 --- a/src/Core/OctoPatch/IRuntimeEvents.cs +++ b/src/Core/OctoPatch/IRuntimeEvents.cs @@ -42,5 +42,10 @@ public interface IRuntimeEvents /// Gets a call when an existing wire instance was removed /// event Action WireRemoved; + + /// + /// Gets a call when an existing wire changed setup + /// + event Action WireUpdated; } } diff --git a/src/Core/OctoPatch/IRuntimeMethods.cs b/src/Core/OctoPatch/IRuntimeMethods.cs index 6bb2b0d..ed5832a 100644 --- a/src/Core/OctoPatch/IRuntimeMethods.cs +++ b/src/Core/OctoPatch/IRuntimeMethods.cs @@ -109,6 +109,16 @@ Task AddWire(Guid outputNodeId, string outputConnectorKey, Guid input /// cancellation token Task SetNodeDescription(Guid nodeId, string name, string description, CancellationToken cancellationToken); + /// + /// Sets the new position of the given node + /// + /// node id + /// x position + /// y position + /// cancellation token + /// + Task SetNodePosition(Guid nodeId, int x, int y, CancellationToken cancellationToken); + /// /// Gets the current environment information of the requested node /// diff --git a/src/Core/OctoPatch/Setup/WireSetup.cs b/src/Core/OctoPatch/Setup/WireSetup.cs index 3411009..ae7e846 100644 --- a/src/Core/OctoPatch/Setup/WireSetup.cs +++ b/src/Core/OctoPatch/Setup/WireSetup.cs @@ -31,5 +31,15 @@ public sealed class WireSetup /// connector key of the input connector /// public string InputConnectorKey { get; set; } + + /// + /// key of the adapter of this wire or null, if no adapter was set + /// + public string AdapterKey { get; set; } + + /// + /// Adapter configuration + /// + public string AdapterConfiguration { get; set; } } } From f535f0ba21a6003ac20bdf29a87afdb451f4ef2e Mon Sep 17 00:00:00 2001 From: Tom Wendel Date: Tue, 22 Sep 2020 21:16:00 +0200 Subject: [PATCH 03/84] Make connectors typed (not ready yet) --- src/Core/OctoPatch/Connector.cs | 47 ++++++++++++--- .../OctoPatch/ContentTypes/AllContentType.cs | 6 +- src/Core/OctoPatch/InputConnector.cs | 58 ++++++++++++++++++- src/Core/OctoPatch/Node.cs | 33 +++++++++-- src/Core/OctoPatch/OutputConnector.cs | 31 +++++++++- .../OctoPatch.Plugin.Midi/MidiDeviceNode.cs | 2 +- 6 files changed, 154 insertions(+), 23 deletions(-) diff --git a/src/Core/OctoPatch/Connector.cs b/src/Core/OctoPatch/Connector.cs index ab5254a..ff3edda 100644 --- a/src/Core/OctoPatch/Connector.cs +++ b/src/Core/OctoPatch/Connector.cs @@ -1,4 +1,5 @@ using System; +using OctoPatch.ContentTypes; using OctoPatch.Descriptions; namespace OctoPatch @@ -6,30 +7,60 @@ namespace OctoPatch /// /// Base class for all kind of connectors /// - internal abstract class Connector : IConnector + public abstract class Connector : IConnector { /// - /// + /// Returns the supported type /// + protected Type SupportedType { get; } + + /// public Guid NodeId { get; } - /// /// - /// public string Key { get; } - /// /// - /// public ConnectorDescription Description { get; } - protected Connector(Guid nodeId, ConnectorDescription description) + protected Connector(Guid nodeId, Type supportedType, ConnectorDescription description) { - if (description == null) + if (description is null) { throw new ArgumentNullException(nameof(description)); } + // Compare supported type with description type + switch (description.ContentType) + { + case AllContentType _: + break; + case BinaryContentType _: + if (supportedType != typeof(byte[])) throw new ArgumentException("types do not match", nameof(description)); + break; + case BoolContentType _: + if (supportedType != typeof(bool)) throw new ArgumentException("types do not match", nameof(description)); + break; + case ComplexContentType _: + break; + case EmptyContentType _: + if (supportedType != typeof(void)) throw new ArgumentException("types do not match", nameof(description)); + break; + case EnumContentType _: + break; + case FloatContentType _: + if (supportedType != typeof(float)) throw new ArgumentException("types do not match", nameof(description)); + break; + case IntegerContentType _: + if (supportedType != typeof(int)) throw new ArgumentException("types do not match", nameof(description)); + break; + case StringContentType _: + if (supportedType != typeof(string)) throw new ArgumentException("types do not match", nameof(description)); + break; + } + + SupportedType = supportedType; + NodeId = nodeId; Key = description.Key; Description = description; diff --git a/src/Core/OctoPatch/ContentTypes/AllContentType.cs b/src/Core/OctoPatch/ContentTypes/AllContentType.cs index 3497f63..57c25fa 100644 --- a/src/Core/OctoPatch/ContentTypes/AllContentType.cs +++ b/src/Core/OctoPatch/ContentTypes/AllContentType.cs @@ -1,8 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace OctoPatch.ContentTypes +namespace OctoPatch.ContentTypes { /// /// Content type for all kind of types. This is only used as a no-matter-what input diff --git a/src/Core/OctoPatch/InputConnector.cs b/src/Core/OctoPatch/InputConnector.cs index f994290..6b86eb2 100644 --- a/src/Core/OctoPatch/InputConnector.cs +++ b/src/Core/OctoPatch/InputConnector.cs @@ -7,21 +7,26 @@ namespace OctoPatch /// /// Connector implementation for incoming messages /// - internal sealed class InputConnector : Connector, IInputConnector, IInputConnectorHandler + public sealed class InputConnector : Connector, IInputConnector, IInputConnectorHandler { /// /// List of handlers /// private readonly List _handlers; - public InputConnector(Guid nodeId, ConnectorDescription description) - : base(nodeId, description) + private InputConnector(Guid nodeId, Type supportedType, ConnectorDescription description) + : base(nodeId, supportedType, description) { _handlers = new List(); } public IInputConnectorHandler HandleRaw(Action handler) { + if (handler == null) + { + throw new ArgumentNullException(nameof(handler)); + } + _handlers.Add(new RawHandler(handler)); return this; } @@ -31,6 +36,16 @@ public IInputConnectorHandler HandleRaw(Action handler) /// public IInputConnectorHandler Handle(Action handler) { + if (handler == null) + { + throw new ArgumentNullException(nameof(handler)); + } + + if (SupportedType != typeof(void)) + { + throw new NotSupportedException("connector is not a trigger connector"); + } + _handlers.Add(new Handler(handler)); return this; } @@ -40,6 +55,16 @@ public IInputConnectorHandler Handle(Action handler) /// public IInputConnectorHandler Handle(Action handler) where T : struct { + if (handler == null) + { + throw new ArgumentNullException(nameof(handler)); + } + + if (SupportedType != typeof(T)) + { + throw new NotSupportedException("connector does not handle the requested type"); + } + _handlers.Add(new Handler(handler)); return this; } @@ -60,6 +85,33 @@ public void OnNext(Message value) } } + #region static fabric + + /// + /// Creates a new input connector for trigger messages + /// + /// parent node id + /// connector description + /// new connector + public static InputConnector Create(Guid nodeId, ConnectorDescription description) + { + return new InputConnector(nodeId, typeof(void), description); + } + + /// + /// Creates a new input connector with the given message type + /// + /// type of message + /// parent node id + /// connector description + /// new connector + public static InputConnector Create(Guid nodeId, ConnectorDescription description) + { + return new InputConnector(nodeId, typeof(T), description); + } + + #endregion + /// /// Common interface for a handler /// diff --git a/src/Core/OctoPatch/Node.cs b/src/Core/OctoPatch/Node.cs index 58c212a..3e3b1e6 100644 --- a/src/Core/OctoPatch/Node.cs +++ b/src/Core/OctoPatch/Node.cs @@ -565,25 +565,50 @@ protected virtual void OnDispose() { } #region Connector Management /// - /// Registers a new output connector to the node + /// Registers a new trigger output connector to the node /// /// output connector description /// new connector protected IOutputConnectorHandler RegisterOutputConnector(ConnectorDescription description) { - var outputConnector = new OutputConnector(Id, description); + var outputConnector = OutputConnector.Create(Id, description); _outputs.Add(outputConnector); return outputConnector; } /// - /// Registers a new input connector to the node + /// Registers a new output connector to the node + /// + /// output connector description + /// new connector + protected IOutputConnectorHandler RegisterOutputConnector(ConnectorDescription description) + { + var outputConnector = OutputConnector.Create(Id, description); + _outputs.Add(outputConnector); + return outputConnector; + } + + /// + /// Registers a new trigger input connector to the node /// /// input connector description /// new connector protected IInputConnectorHandler RegisterInputConnector(ConnectorDescription description) { - var inputConnector = new InputConnector(Id, description); + var inputConnector = InputConnector.Create(Id, description); + _inputs.Add(inputConnector); + return inputConnector; + } + + /// + /// Registers a new input connector to the node + /// + /// message type + /// input connector description + /// new connector + protected IInputConnectorHandler RegisterInputConnector(ConnectorDescription description) + { + var inputConnector = InputConnector.Create(Id, description); _inputs.Add(inputConnector); return inputConnector; } diff --git a/src/Core/OctoPatch/OutputConnector.cs b/src/Core/OctoPatch/OutputConnector.cs index 32b7861..537864d 100644 --- a/src/Core/OctoPatch/OutputConnector.cs +++ b/src/Core/OctoPatch/OutputConnector.cs @@ -11,8 +11,8 @@ internal sealed class OutputConnector : Connector, IOutputConnector, IOutputConn { private readonly HashSet _subscriptions; - public OutputConnector(Guid nodeId, ConnectorDescription description) - : base(nodeId, description) + private OutputConnector(Guid nodeId, Type supportedType, ConnectorDescription description) + : base(nodeId, supportedType, description) { // TODO: Make subscriptions threadsafe @@ -84,6 +84,33 @@ public IDisposable Subscribe(Action messageHandler) where T : struct }); } + #region static fabrics + + /// + /// Creates a new output connector for trigger type + /// + /// parent node id + /// connector description + /// new connector + public static OutputConnector Create(Guid nodeId, ConnectorDescription description) + { + return new OutputConnector(nodeId, typeof(void), description); + } + + /// + /// Creates a new output connector for the given type + /// + /// message type + /// parent node id + /// connector description + /// new connector + public static OutputConnector Create(Guid nodeId, ConnectorDescription description) + { + return new OutputConnector(nodeId, typeof(T), description); + } + + #endregion + private sealed class Subscription : IDisposable { private readonly IObserver _observer; diff --git a/src/Plugins/OctoPatch.Plugin.Midi/MidiDeviceNode.cs b/src/Plugins/OctoPatch.Plugin.Midi/MidiDeviceNode.cs index e59d0bf..49f39a8 100644 --- a/src/Plugins/OctoPatch.Plugin.Midi/MidiDeviceNode.cs +++ b/src/Plugins/OctoPatch.Plugin.Midi/MidiDeviceNode.cs @@ -55,7 +55,7 @@ public sealed class MidiDeviceNode : Node(HandleMessage); + RegisterInputConnector(MidiInputDescription).Handle(HandleMessage); // Build environment UpdateEnvironment(new MidiDeviceEnvironment From 94e4a5ee6ddfed9e27a68a085791e55a922e40be Mon Sep 17 00:00:00 2001 From: Tom Wendel Date: Tue, 22 Sep 2020 21:16:13 +0200 Subject: [PATCH 04/84] Start tests for InputConnector --- test/OctoPatch.Test/InputConnectorTest.cs | 87 +++++++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 test/OctoPatch.Test/InputConnectorTest.cs diff --git a/test/OctoPatch.Test/InputConnectorTest.cs b/test/OctoPatch.Test/InputConnectorTest.cs new file mode 100644 index 0000000..64470cb --- /dev/null +++ b/test/OctoPatch.Test/InputConnectorTest.cs @@ -0,0 +1,87 @@ +using System; +using OctoPatch.ContentTypes; +using OctoPatch.Descriptions; +using Xunit; + +namespace OctoPatch.Test +{ + /// + /// Collection of tests around the input connector + /// + public sealed class InputConnectorTest + { + /// + /// default node guid + /// + private static readonly Guid DefaultNodeGuid = Guid.Parse("{C7929EB6-DBFF-4683-B85F-5E6753AFBA50}"); + + /// + /// default connector setup + /// + private static ConnectorDescription DefaultDescription => new ConnectorDescription( + "test", "Test connection","Test connection description", new BoolContentType()); + + /// + /// Tests the behavior of a properly created input connector + /// + [Fact] + public void ProperlyCreated() + { + var connector = InputConnector.Create(DefaultNodeGuid, DefaultDescription); + Assert.Equal(DefaultNodeGuid, connector.NodeId); + Assert.Equal(DefaultDescription.Key, connector.Key); + Assert.Equal(DefaultDescription.DisplayName, connector.Description.DisplayName); + Assert.Equal(DefaultDescription.DisplayDescription, connector.Description.DisplayDescription); + Assert.Equal(DefaultDescription.ContentType.Type, connector.Description.ContentType.Type); + } + + #region Wrong parameter + + /// + /// Test behavior on empty description + /// + [Fact] + public void EmptyFabricParameter() + { + Assert.Throws(() => InputConnector.Create(DefaultNodeGuid, null)); + Assert.Throws(() => InputConnector.Create(DefaultNodeGuid, null)); + } + + /// + /// Test the behavior when using a wrong type within create + /// + [Fact] + public void WrongCreateType() + { + // Description is of type bool + Assert.Throws(() => InputConnector.Create(DefaultNodeGuid, DefaultDescription)); + Assert.Throws(() => InputConnector.Create(DefaultNodeGuid, DefaultDescription)); + } + + /// + /// Test behavior of handler methods with null parameter + /// + [Fact] + public void EmptyHandler() + { + var connector = InputConnector.Create(DefaultNodeGuid, DefaultDescription); + Assert.Throws(() => connector.Handle(null)); + Assert.Throws(() => connector.Handle(null)); + Assert.Throws(() => connector.HandleRaw(null)); + } + + /// + /// Test the behavior when register for the wrong type (match against description) + /// + [Fact] + public void WrongHandlerType() + { + var connector = InputConnector.Create(DefaultNodeGuid, DefaultDescription); + Assert.Throws(() => connector.Handle((i) => { })); + } + + #endregion + + + } +} From 905c7a82513f860a6c60f1f42169fe51b8984dfc Mon Sep 17 00:00:00 2001 From: Tom Wendel Date: Tue, 22 Sep 2020 22:12:39 +0200 Subject: [PATCH 05/84] WPF Cleanup --- .../Models/AdapterConfigurationModel.cs | 6 + .../ViewModels/IRuntimeViewModel.cs | 130 +++++++++++++- .../ViewModels/RuntimeViewModel.cs | 170 ++++++++++++++---- .../Views/CommonNodeSetupView.xaml | 32 ---- .../Views/CommonNodeSetupView.xaml.cs | 15 -- .../Views/NodeDescriptionView.xaml | 25 --- .../Views/NodeDescriptionView.xaml.cs | 26 --- .../Views/RuntimeView.xaml | 52 +++++- .../Views/ToolboxView.xaml | 18 -- .../Views/ToolboxView.xaml.cs | 26 --- 10 files changed, 316 insertions(+), 184 deletions(-) create mode 100644 src/Applications/OctoPatch.DesktopClient/Models/AdapterConfigurationModel.cs delete mode 100644 src/Applications/OctoPatch.DesktopClient/Views/CommonNodeSetupView.xaml delete mode 100644 src/Applications/OctoPatch.DesktopClient/Views/CommonNodeSetupView.xaml.cs delete mode 100644 src/Applications/OctoPatch.DesktopClient/Views/NodeDescriptionView.xaml delete mode 100644 src/Applications/OctoPatch.DesktopClient/Views/NodeDescriptionView.xaml.cs delete mode 100644 src/Applications/OctoPatch.DesktopClient/Views/ToolboxView.xaml delete mode 100644 src/Applications/OctoPatch.DesktopClient/Views/ToolboxView.xaml.cs diff --git a/src/Applications/OctoPatch.DesktopClient/Models/AdapterConfigurationModel.cs b/src/Applications/OctoPatch.DesktopClient/Models/AdapterConfigurationModel.cs new file mode 100644 index 0000000..c75e7a3 --- /dev/null +++ b/src/Applications/OctoPatch.DesktopClient/Models/AdapterConfigurationModel.cs @@ -0,0 +1,6 @@ +namespace OctoPatch.DesktopClient.Models +{ + public abstract class AdapterConfigurationModel : Model + { + } +} diff --git a/src/Applications/OctoPatch.DesktopClient/ViewModels/IRuntimeViewModel.cs b/src/Applications/OctoPatch.DesktopClient/ViewModels/IRuntimeViewModel.cs index 3f7439b..34e2a3a 100644 --- a/src/Applications/OctoPatch.DesktopClient/ViewModels/IRuntimeViewModel.cs +++ b/src/Applications/OctoPatch.DesktopClient/ViewModels/IRuntimeViewModel.cs @@ -3,46 +3,166 @@ using System.Windows.Input; using OctoPatch.Descriptions; using OctoPatch.DesktopClient.Models; -using OctoPatch.Setup; namespace OctoPatch.DesktopClient.ViewModels { public interface IRuntimeViewModel : INotifyPropertyChanged { + #region Toolbox + + /// + /// List of available nodes to drag into tree + /// ObservableCollection NodeDescriptions { get; } + /// + /// Gets or sets the current selected node description in toolbox + /// NodeDescription SelectedNodeDescription { get; set; } + /// + /// Command to add the selected node description to the tree + /// ICommand AddSelectedNodeDescription { get; } + #endregion + + #region Patch + + /// + /// Hierarchical tree structure + /// + ObservableCollection NodeTree { get; } + + /// + /// Gets or sets the current selected node within the tree + /// + NodeModel SelectedNode { get; set; } + + /// + /// Command to delete the current selected tree node + /// + ICommand RemoveSelectedNode { get; } + + /// + /// Command to delete the current selected wire + /// + ICommand RemoveSelectedWire { get; } + + #endregion + + #region Context Toolbox + + /// + /// List of available nodes for the current selected tree node + /// ObservableCollection ContextNodeDescriptions { get; } + /// + /// Gets or sets the current selected node description of context toolbox + /// NodeDescription SelectedContextNodeDescription { get; set; } + /// + /// Command to add the current selected context node description + /// to the current selected tree node + /// ICommand AddSelectedContextNodeDescription { get; } - ObservableCollection NodeTree { get; } + #endregion - ICommand RemoveSelectedNode { get; } + #region Property bar + + #region Node lifecycle management + /// + /// Command to start the current selected node + /// ICommand StartSelectedNode { get; } + /// + /// Command to stop the current selected node + /// ICommand StopSelectedNode { get; } - NodeModel SelectedNode { get; set; } + #endregion + + #region Common node configuration + /// + /// Gets the common configuration (name and description) of the current selected tree node + /// NodeDescriptionModel NodeDescription { get; } + /// + /// Command to store all the changed made in the NodeDescription property + /// ICommand SaveNodeDescription { get; } + #endregion + + #region Node specific configuration + + /// + /// Holds the specific configuration model for the current selected tree node + /// NodeConfigurationModel NodeConfiguration { get; } + /// + /// Command to store all the changes made in the node configuration + /// ICommand SaveNodeConfiguration { get; } + #endregion + + #region Wire wizard + + /// + /// gets the current selected ouptut connector (if available) + /// OutputNodeModel SelectedWireConnector { get; } + /// + /// Command to take the selected output / input connector to wire them up + /// ICommand TakeConnector { get; } - ObservableCollection Wires { get; } + #endregion + + #region Wire configuration + + /// + /// List of all available adapters for the selected wire context + /// + ObservableCollection AdapterDescriptions { get; } + + /// + /// Gets or sets the current selected adapter + /// + AdapterDescription SelectedAdapterDescription { get; set; } + + /// + /// Command to apply current adapter selection to the selected wire + /// + ICommand SaveAdapter { get; } + + #endregion + + #region Adapter configuration + + /// + /// Gets the configuration for the adapter of the current selected wire + /// + AdapterConfigurationModel AdapterConfiguration { get; } + + /// + /// Command to store all the changes in the adapter configuration + /// + ICommand SaveAdapterConfiguration { get; } + + #endregion + + #endregion + } } diff --git a/src/Applications/OctoPatch.DesktopClient/ViewModels/RuntimeViewModel.cs b/src/Applications/OctoPatch.DesktopClient/ViewModels/RuntimeViewModel.cs index e7cf67a..d1be8ee 100644 --- a/src/Applications/OctoPatch.DesktopClient/ViewModels/RuntimeViewModel.cs +++ b/src/Applications/OctoPatch.DesktopClient/ViewModels/RuntimeViewModel.cs @@ -25,10 +25,14 @@ public sealed class RuntimeViewModel : IRuntimeViewModel private readonly List _descriptions; + #region Toolbox + + /// public ObservableCollection NodeDescriptions { get; } private NodeDescription _selectedNodeDescription; + /// public NodeDescription SelectedNodeDescription { get => _selectedNodeDescription; @@ -43,44 +47,16 @@ public NodeDescription SelectedNodeDescription private readonly ActionCommand _addSelectedNodeDescription; + /// public ICommand AddSelectedNodeDescription => _addSelectedNodeDescription; - public ObservableCollection ContextNodeDescriptions { get; } - - private NodeDescription _selectedContextNodeDescription; - - public NodeDescription SelectedContextNodeDescription - { - get => _selectedContextNodeDescription; - set - { - _selectedContextNodeDescription = value; - OnPropertyChanged(); - - _addSelectedContextNodeDescription.Enabled = value != null; - } - } - - private readonly ActionCommand _addSelectedContextNodeDescription; - - public ICommand AddSelectedContextNodeDescription => _addSelectedContextNodeDescription; + #endregion + #region Patch public ObservableCollection NodeTree { get; } - private readonly ActionCommand _removeSelectedNode; - - public ICommand RemoveSelectedNode => _removeSelectedNode; - - private readonly ActionCommand _startSelectedNode; - - public ICommand StartSelectedNode => _startSelectedNode; - - private readonly ActionCommand _stopSelectedNode; - - public ICommand StopSelectedNode => _stopSelectedNode; - - private NodeModel _selectedNode; + private NodeModel _selectedNode; public NodeModel SelectedNode { @@ -199,6 +175,56 @@ public NodeModel SelectedNode } } + private readonly ActionCommand _removeSelectedNode; + + public ICommand RemoveSelectedNode => _removeSelectedNode; + + private readonly ActionCommand _removeSelectedWire; + + public ICommand RemoveSelectedWire => _removeSelectedWire; + + #endregion + + #region Context Toolbox + + public ObservableCollection ContextNodeDescriptions { get; } + + private NodeDescription _selectedContextNodeDescription; + + public NodeDescription SelectedContextNodeDescription + { + get => _selectedContextNodeDescription; + set + { + _selectedContextNodeDescription = value; + OnPropertyChanged(); + + _addSelectedContextNodeDescription.Enabled = value != null; + } + } + + private readonly ActionCommand _addSelectedContextNodeDescription; + + public ICommand AddSelectedContextNodeDescription => _addSelectedContextNodeDescription; + + #endregion + + #region Property bar + + #region Node lifecycle management + + private readonly ActionCommand _startSelectedNode; + + public ICommand StartSelectedNode => _startSelectedNode; + + private readonly ActionCommand _stopSelectedNode; + + public ICommand StopSelectedNode => _stopSelectedNode; + + #endregion + + #region Common node configuration + private NodeDescriptionModel _nodeDescription; public NodeDescriptionModel NodeDescription @@ -215,6 +241,10 @@ private set public ICommand SaveNodeDescription => _saveNodeDescription; + #endregion + + #region Node specific configuration + private NodeConfigurationModel _nodeConfiguration; public NodeConfigurationModel NodeConfiguration @@ -231,6 +261,10 @@ private set public ICommand SaveNodeConfiguration => _saveNodeConfiguration; + #endregion + + #region Wire wizard + private OutputNodeModel _selectedWireConnector; public OutputNodeModel SelectedWireConnector @@ -247,7 +281,51 @@ private set public ICommand TakeConnector => _takeConnector; - public ObservableCollection Wires { get; } + #endregion + + #region Wire configuration + + public ObservableCollection AdapterDescriptions { get; } + + private AdapterDescription _selectedAdapterDescription; + + public AdapterDescription SelectedAdapterDescription + { + get => _selectedAdapterDescription; + set + { + _selectedAdapterDescription = value; + OnPropertyChanged(); + } + } + + private readonly ActionCommand _saveAdapter; + + public ICommand SaveAdapter => _saveAdapter; + + #endregion + + #region Adapter configuration + + private AdapterConfigurationModel _adapterConfiguration; + + public AdapterConfigurationModel AdapterConfiguration + { + get => _adapterConfiguration; + private set + { + _adapterConfiguration = value; + OnPropertyChanged(); + } + } + + private readonly ActionCommand _saveAdapterConfiguration; + + public ICommand SaveAdapterConfiguration => _saveAdapterConfiguration; + + #endregion + + #endregion public RuntimeViewModel() { @@ -258,16 +336,19 @@ public RuntimeViewModel() NodeDescriptions = new ObservableCollection(); ContextNodeDescriptions = new ObservableCollection(); NodeTree = new ObservableCollection(); - Wires = new ObservableCollection(); + AdapterDescriptions = new ObservableCollection(); _addSelectedNodeDescription = new ActionCommand(AddNodeDescriptionCallback, false); _addSelectedContextNodeDescription = new ActionCommand(AddContextNodeDescriptionCallback, false); _removeSelectedNode = new ActionCommand(RemoveSelectedNodeCallback, false); + _removeSelectedWire = new ActionCommand(RemoveSelectedWireCallback, false); _startSelectedNode = new ActionCommand(StartSelectedNodeCallback, false); _stopSelectedNode = new ActionCommand(StopSelectedNodeCallback, false); _saveNodeDescription = new ActionCommand(SaveNodeDescriptionCallback, false); _saveNodeConfiguration = new ActionCommand(SaveNodeConfigurationCallback, false); _takeConnector = new ActionCommand(TakeConnectorCallback, false); + _saveAdapter = new ActionCommand(SaveAdapterCallback, false); + _saveAdapterConfiguration = new ActionCommand(SaveAdapterConfigurationCallback, false); var repository = new Repository(); _runtime = new Runtime(repository); @@ -279,10 +360,31 @@ public RuntimeViewModel() _runtime.NodeEnvironmentChanged += RuntimeOnOnNodeEnvironmentChanged; _runtime.WireAdded += RuntimeOnOnWireAdded; _runtime.WireRemoved += RuntimeOnOnWireRemoved; + _runtime.WireUpdated += RuntimeOnWireUpdated; Task.Run(() => Setup(CancellationToken.None)); } + private void RuntimeOnWireUpdated(WireSetup obj) + { + + } + + private void SaveAdapterConfigurationCallback(object obj) + { + throw new NotImplementedException(); + } + + private void SaveAdapterCallback(object obj) + { + throw new NotImplementedException(); + } + + private void RemoveSelectedWireCallback(object obj) + { + throw new NotImplementedException(); + } + private async void TakeConnectorCallback(object obj) { var node = SelectedNode; diff --git a/src/Applications/OctoPatch.DesktopClient/Views/CommonNodeSetupView.xaml b/src/Applications/OctoPatch.DesktopClient/Views/CommonNodeSetupView.xaml deleted file mode 100644 index b6dcc42..0000000 --- a/src/Applications/OctoPatch.DesktopClient/Views/CommonNodeSetupView.xaml +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - -