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

171 lines
6.1 KiB
C#

using System;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Reactive;
using System.Reactive.Linq;
using System.Threading.Tasks;
using Intromat.PersistentModel;
using Intromat.ViewModels.Nodes;
using Intromat.ViewModels.Previews;
using NodeNetwork.Toolkit.Group;
using NodeNetwork.Toolkit.NodeList;
using ReactiveUI;
namespace Intromat.ViewModels
{
public class MainViewModel : ReactiveObject
{
private ProjectViewModel _project;
private FileViewModel? _activeFile;
private object? _propertiesContext;
private DxTexturePreviewViewModel? _preview2dContext;
private DxMeshPreviewViewModel? _preview3dContext;
public MainViewModel()
{
AppState = ((AppStateViewModel)RxApp.SuspensionHost.AppState!)!;
Explorer = new(this);
var desktopPath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
var initialProjectPath = Path.Combine(desktopPath, "Project1", "Project1.iproj");
if (File.Exists(initialProjectPath))
{
_project = Task.Run(() => ProjectSerializer.LoadProject(this, initialProjectPath)).GetAwaiter().GetResult()!;
}
else
{
_project = ProjectViewModel.CreateDefault(this, initialProjectPath, "Project1");
}
foreach (var nodeType in typeof(CodeGenNodeViewModel).Assembly.ExportedTypes.Where(t => typeof(CodeGenNodeViewModel).IsAssignableFrom(t) && !t.IsAbstract))
{
if (nodeType.Namespace == $"{nameof(Intromat)}.{nameof(Nodes)}")
continue;
NodeList.AddNodeType(() => (CodeGenNodeViewModel)Activator.CreateInstance(nodeType)!);
}
Grouper = new NodeGrouper
{
GroupNodeFactory = subnet => new GroupNodeViewModel
{
Name = "Group",
Subnet = (CodeGenNetworkViewModel)subnet
},
EntranceNodeFactory = () => new GroupSubnetIONodeViewModel
{
IsEntranceNode = true
},
ExitNodeFactory = () => new GroupSubnetIONodeViewModel
{
IsEntranceNode = false
},
SubNetworkFactory = parentNet =>
{
var subNetwork = new CodeGenNetworkViewModel(((CodeGenNetworkViewModel)parentNet).Document, "Group") { ParentNetwork = (CodeGenNetworkViewModel)parentNet };
return subNetwork;
},
IOBindingFactory = (groupNode, entranceNode, exitNode) =>
new CodeNodeGroupIOBinding(groupNode, entranceNode, exitNode)
};
LoadProject = ReactiveCommand.CreateFromTask(async () =>
{
var file = await OpenProjectFile.Handle(true);
if (file == null)
return null;
var activeFile = ActiveFile;
if (activeFile != null)
UndoRedo.Purge(activeFile);
UndoRedo.Recording = false;
try
{
return await ProjectSerializer.LoadProject(this, file);
}
catch (Exception)
{
// ignored, TODO
}
finally
{
ActiveFile = null;
Files.Clear();
UndoRedo.Recording = true;
}
return null;
});
LoadProject.Where(n => n != null).Subscribe(project => Project = project!);
SaveProject = ReactiveCommand.CreateFromTask(async () =>
{
await ProjectSerializer.SaveModel(Project);
});
SaveProjectAs = ReactiveCommand.CreateFromTask(() => throw new NotImplementedException());
this.WhenAnyValue(vm => vm.Project).Subscribe(_ =>
{
if (Explorer.TreeRoot.Count == 0)
Explorer.TreeRoot.Add(Project);
else
{
Explorer.TreeRoot[0] = Project;
}
});
this.WhenAnyValue(vm => vm.ActiveFile!.CurrentViewModel).Subscribe(n => PropertiesContext = n);
UndoRedo.Recording = true;
}
public NodeListViewModel NodeList { get; } = new();
public UndoRedoViewModel UndoRedo { get; } = new();
public AppStateViewModel AppState { get; }
public ExplorerViewModel Explorer { get; }
public ReactiveCommand<Unit, ProjectViewModel?> LoadProject { get; }
public ReactiveCommand<Unit, Unit> SaveProject { get; }
public ReactiveCommand<Unit, Unit> SaveProjectAs { get; }
public Interaction<bool, string?> OpenProjectFile { get; } = new();
public Interaction<Unit, Func<FileViewModel>?> SelectTypeAndFileName { get; } = new();
public Interaction<string?, string?> SelectName { get; } = new();
public NodeGrouper Grouper { get; }
public ProjectViewModel Project
{
get => _project;
set => this.RaiseAndSetIfChanged(ref _project, value);
}
public ObservableCollection<FileViewModel> Files { get; } = new();
public FileViewModel? ActiveFile
{
get => _activeFile;
set => this.RaiseAndSetIfChanged(ref _activeFile, value);
}
public object? PropertiesContext
{
get => _propertiesContext;
set => this.RaiseAndSetIfChanged(ref _propertiesContext, value);
}
public DxTexturePreviewViewModel? Preview2dContext
{
get => _preview2dContext;
set => this.RaiseAndSetIfChanged(ref _preview2dContext, value);
}
public DxMeshPreviewViewModel? Preview3dContext
{
get => _preview3dContext;
set => this.RaiseAndSetIfChanged(ref _preview3dContext, value);
}
}
}