using System; using System.ComponentModel; using System.Linq; using System.Reactive.Linq; using DynamicData; using DynamicData.Alias; using Intromat.Graphics; using Intromat.Interfaces; using Intromat.PersistentModel; using Intromat.ViewModels.Previews; using Intromat.Views; using NodeNetwork.ViewModels; using ReactiveUI; using Splat; namespace Intromat.ViewModels { public enum NodeType { Special, Literal, Code, Group } public abstract class CodeGenNodeViewModel : NodeViewModel, ICustomTypeDescriptor, IRefreshProperties { private bool _isMouseOver; private NodePreviewViewModelBase? _preview; static CodeGenNodeViewModel() { Locator.CurrentMutable.Register(() => new CodeGenNodeView(), typeof(IViewFor)); } protected CodeGenNodeViewModel(NodeType type) { NodeType = type; Guid = Guid.NewGuid(); var dxHost = Locator.Current.GetService()!; var inputs = Inputs.Connect().Cast(e => (Endpoint)e).ObserveOn(dxHost.MainDispatcher); var outputs = Outputs.Connect().Cast(e => (Endpoint)e).ObserveOn(dxHost.MainDispatcher); var leftInputs = inputs.Filter(e => e.PortPosition == PortPosition.Left); var leftOutputs = outputs.Filter(e => e.PortPosition == PortPosition.Left); var rightInputs = inputs.Filter(e => e.PortPosition == PortPosition.Right); var rightOutputs = outputs.Filter(e => e.PortPosition == PortPosition.Right); var leftEndpoints = leftInputs.Merge(leftOutputs); var rightEndpoints = rightInputs.Merge(rightOutputs); LeftEndpoints = leftEndpoints .AutoRefreshOnObservable(e => ((CodeGenPortViewModel)e.Port).IsPortVisibleChanged) .Filter(e => { var port = (CodeGenPortViewModel)e.Port; return port.PortType != EPortType.None && port.IsPortVisible; }).AsObservableList(); RightEndpoints = rightEndpoints .AutoRefreshOnObservable(e => ((CodeGenPortViewModel)e.Port).IsPortVisibleChanged) .Filter(e => { var port = (CodeGenPortViewModel)e.Port; return port.PortType != EPortType.None && port.IsPortVisible; }).AsObservableList(); PropertyDescriptors = inputs.Merge(outputs) .Where(e => e.Visibility != EndpointVisibility.AlwaysHidden && e.Editor != null) .Transform(CreateEndpointPropertyDescriptor) .AsObservableList(); this.WhenAnyValue(vm => vm.IsMouseOver).Subscribe(_ => { foreach (dynamic e in Inputs.Items) { e.IsMouseOver = IsMouseOver; } foreach (dynamic e in Outputs.Items) { e.IsMouseOver = IsMouseOver; } }); ParentChanged = this.WhenAnyValue(vm => vm.Parent); } private PropertyDescriptor CreateEndpointPropertyDescriptor(Endpoint endpoint, int index) { return EndpointPropertyDescriptor.Create(this, endpoint, index); } public NodeType NodeType { get; } public Guid Guid { get; set; } public IObservable ParentChanged { get; } public abstract NodeModelBase CreateModel(); public virtual void SaveModel(NodeModelBase model) { model.Guid = Guid; model.Name = Name; } public virtual void LoadModel(NodeModelBase model) { Guid = model.Guid; Name = model.Name; } /// /// The list of properties available for editing /// public IObservableList? PropertyDescriptors { get; } /// /// The list of visible endpoints that are positioned to the left. /// public IObservableList LeftEndpoints { get; } /// /// The list of visible endpoints that are positioned to the right. /// public IObservableList RightEndpoints { get; } public bool IsMouseOver { get => _isMouseOver; set => this.RaiseAndSetIfChanged(ref _isMouseOver, value); } public NodePreviewViewModelBase? Preview { get => _preview; set => this.RaiseAndSetIfChanged(ref _preview, value); } public AttributeCollection GetAttributes() { return null!; } public string GetClassName() { return GetType().Name; } public string GetComponentName() { return Name; } public TypeConverter GetConverter() { return null!; } public EventDescriptor GetDefaultEvent() { return null!; } public PropertyDescriptor GetDefaultProperty() { return null!; } public object GetEditor(Type editorBaseType) { return null!; } public EventDescriptorCollection GetEvents() { return null!; } public EventDescriptorCollection GetEvents(Attribute[]? attributes) { return null!; } public PropertyDescriptorCollection GetProperties() { return new(PropertyDescriptors!.Items.ToArray()); } public PropertyDescriptorCollection GetProperties(Attribute[]? attributes) { return new(PropertyDescriptors!.Items.ToArray()); } public object GetPropertyOwner(PropertyDescriptor? pd) { return this; } } }