using System; using System.Linq; using System.Reflection; using Avalonia.Controls; using Avalonia.Interactivity; namespace Inspectron.Settings.Avalonia.Configuration; public partial class ItemEditorDialog : Window { private readonly Type _itemType; private object? _workingValue; private readonly DefaultControlFactory _controlFactory; private readonly OptionsWindow _parentOptionsWindow; public ItemEditorDialog(Type itemType, object? initialValue, DefaultControlFactory controlFactory, OptionsWindow parentOptionsWindow) { _itemType = itemType; _workingValue = CloneObject(initialValue); _controlFactory = controlFactory; _parentOptionsWindow = parentOptionsWindow; InitializeComponent(); Title = $"Edit {_itemType.Name}"; CreatePropertyControls(); BtnOK.Click += BtnOK_Click; BtnCancel.Click += BtnCancel_Click; } private void CreatePropertyControls() { if (_itemType.IsValueType || _itemType == typeof(string)) { CreateSimpleValueControl(); } else { CreateComplexObjectControls(); } } private void CreateSimpleValueControl() { var dummyProperty = new SimplePropertyInfo(_itemType, "Value"); var control = _controlFactory.CreateControl("Value", "Value", dummyProperty, _workingValue!, newValue => _workingValue = newValue, _parentOptionsWindow); PropertyPanel.Children.Add(control); } private void CreateComplexObjectControls() { var properties = _itemType.GetProperties(BindingFlags.Public | BindingFlags.Instance) .Where(p => p.CanRead && p.CanWrite) .ToArray(); foreach (var property in properties) { var currentValue = property.GetValue(_workingValue); var control = _controlFactory.CreateControl(property.Name, property.Name, property, currentValue!, newValue => property.SetValue(_workingValue, newValue), _parentOptionsWindow); PropertyPanel.Children.Add(control); } } private void BtnOK_Click(object? sender, RoutedEventArgs e) { Close(_workingValue); } private void BtnCancel_Click(object? sender, RoutedEventArgs e) { Close(null); } private object? CloneObject(object? obj) { if (obj == null) return GetDefaultValue(_itemType); var type = obj.GetType(); if (type.IsValueType || type == typeof(string)) { return obj; } try { var clone = Activator.CreateInstance(type); foreach (var prop in type.GetProperties(BindingFlags.Public | BindingFlags.Instance)) { if (prop.CanRead && prop.CanWrite) { prop.SetValue(clone, prop.GetValue(obj)); } } return clone; } catch { return GetDefaultValue(type); } } private object? GetDefaultValue(Type type) { if (type.IsValueType) { return Activator.CreateInstance(type); } else if (type == typeof(string)) { return ""; } else { try { return Activator.CreateInstance(type); } catch { return null; } } } }