Files
bluflame/intromat/Intromat/ViewModels/CodeGenNodeViewModel.cs
2026-04-18 22:31:51 +02:00

199 lines
5.9 KiB
C#

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<CodeGenNodeViewModel>));
}
protected CodeGenNodeViewModel(NodeType type)
{
NodeType = type;
Guid = Guid.NewGuid();
var dxHost = Locator.Current.GetService<DxHost>()!;
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<NetworkViewModel> 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;
}
/// <summary>
/// The list of properties available for editing
/// </summary>
public IObservableList<PropertyDescriptor>? PropertyDescriptors { get; }
/// <summary>
/// The list of visible endpoints that are positioned to the left.
/// </summary>
public IObservableList<Endpoint> LeftEndpoints { get; }
/// <summary>
/// The list of visible endpoints that are positioned to the right.
/// </summary>
public IObservableList<Endpoint> 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;
}
}
}