Files
Nitrox/Nitrox.Launcher/ViewModels/ObjectPropertyEditorViewModel.cs
2025-07-06 00:23:46 +02:00

84 lines
2.7 KiB
C#

using System;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using Avalonia.Collections;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using HanumanInstitute.MvvmDialogs;
using Nitrox.Launcher.Models.Design;
using Nitrox.Launcher.ViewModels.Abstract;
namespace Nitrox.Launcher.ViewModels;
public partial class ObjectPropertyEditorViewModel : ModalViewModelBase
{
private readonly IDialogService dialogService;
[ObservableProperty]
private AvaloniaList<EditorField> editorFields = [];
[ObservableProperty]
private object ownerObject;
private string title;
public string Title
{
get => title ?? $"{OwnerObject.GetType().Name} editor";
set => title = value;
}
/// <summary>
/// Gets or sets the field filter to use. If filter returns false, it will omit the field.
/// </summary>
public Func<PropertyInfo, bool> FieldAcceptFilter { get; set; } = _ => true;
public ObjectPropertyEditorViewModel() : this(null)
{
}
protected override void OnPropertyChanged(PropertyChangedEventArgs e)
{
if (e.PropertyName == nameof(OwnerObject))
{
EditorFields.Clear();
EditorFields.AddRange(OwnerObject
.GetType()
.GetProperties()
.Where(FieldAcceptFilter)
.Select(p => new EditorField(p, p.GetValue(OwnerObject), GetPossibleValues(p)))
.Where(editorField => editorField.Value is string or bool or int or float || editorField.PossibleValues != null));
}
base.OnPropertyChanged(e);
}
public ObjectPropertyEditorViewModel(IDialogService dialogService)
{
this.dialogService = dialogService;
}
[RelayCommand(CanExecute = nameof(CanSave))]
public async Task Save()
{
foreach (EditorField field in EditorFields)
{
try
{
field.PropertyInfo.SetValue(OwnerObject, Convert.ChangeType(field.Value, field.PropertyInfo.PropertyType));
}
catch (Exception ex)
{
await dialogService.ShowErrorAsync(ex, description: field.ToString());
}
}
Close(ButtonOptions.Ok);
}
public bool CanSave() => !HasErrors;
private static AvaloniaList<object> GetPossibleValues(PropertyInfo propertyInfo) =>
propertyInfo.PropertyType.IsEnum ? new AvaloniaList<object>(propertyInfo.PropertyType.GetFields(BindingFlags.Static | BindingFlags.Public).Select(f => f.GetValue(propertyInfo.PropertyType))) : null;
}