using System; using System.Reactive; using System.Reactive.Linq; using DynamicData; using Intromat.Model.Compiler; using Intromat.PersistentModel; using Intromat.ViewModels; using Intromat.ViewModels.Editors; using Intromat.ViewModels.Previews; using Intromat.Views; using NodeNetwork.Toolkit.ValueNode; using NodeNetwork.ViewModels; using ReactiveUI; using Splat; namespace Intromat.Nodes.Code { public class ForLoopNode : ExecutionNodeBase { static ForLoopNode() { Locator.CurrentMutable.Register(() => new CodeGenNodeView(), typeof(IViewFor)); } public ForLoopNode() : base(NodeType.Code) { var boundsGroup = new EndpointGroup("Bounds"); Name = "For Loop"; LoopBodyFlow = new CodeGenInputViewModel(EPortType.Execution) { Name = "Loop Body", Group = _executionFlowGroup }; Inputs.Add(LoopBodyFlow); FirstIndex = new CodeGenInputViewModel>(EPortType.Integer) { Name = "First Index", Group = boundsGroup, Editor = FirstIndexEditor }; Inputs.Add(FirstIndex); LastIndex = new CodeGenInputViewModel>(EPortType.Integer) { Name = "Last Index", Group = boundsGroup, Editor = LastIndexEditor }; Inputs.Add(LastIndex); var loopBodyChanged = LoopBodyFlow.ValueChanged.Select(_ => Unit.Default).StartWith(Unit.Default); FlowIn.Value = loopBodyChanged .CombineLatest(FlowOutChanged, FirstIndex.ValueChanged, LastIndex.ValueChanged, (bodyChange, endChange, firstI, lastI) => (BodyChange: bodyChange, EndChange: endChange, FirstI: firstI, LastI: lastI)) .Select(v => new ForLoopValue { LoopBody = LoopBodyFlow.Value, FlowOut = FlowOut.Value, LowerBound = v.FirstI, UpperBound = v.LastI }); CurrentIndex = new CodeGenOutputViewModel>(EPortType.Integer) { Name = "Current Index", Value = FlowIn.Value.Select(v => new VariableReference { LocalVariable = ((ForLoopValue)v).CurrentIndex }) }; Outputs.Add(CurrentIndex); var stringPreview = new StringPreviewViewModel(); Preview = stringPreview; FlowIn.Value.Subscribe(v => { var forLoop = (ForLoopValue)v; stringPreview.Value = $"[{forLoop.LowerBound?.PreviewValue ?? "0"}..{forLoop.UpperBound?.PreviewValue ?? "0"}]"; }); } public ValueNodeInputViewModel LoopBodyFlow { get; } public IntegerExpressionEditorViewModel FirstIndexEditor { get; } = new(); public ValueNodeInputViewModel> FirstIndex { get; } public IntegerExpressionEditorViewModel LastIndexEditor { get; } = new(); public ValueNodeInputViewModel> LastIndex { get; } public ValueNodeOutputViewModel> CurrentIndex { get; } public override NodeModelBase CreateModel() { return new ForLoopModel(); } public override void SaveModel(NodeModelBase model) { base.SaveModel(model); var forLoop = (ForLoopModel)model; forLoop.FirstIndex = FirstIndexEditor.CreateModel(); forLoop.LastIndex = LastIndexEditor.CreateModel(); } public override void LoadModel(NodeModelBase model) { base.LoadModel(model); var forLoop = (ForLoopModel)model; FirstIndexEditor.LoadModel(forLoop.FirstIndex); LastIndexEditor.LoadModel(forLoop.LastIndex); } } }