using System; using System.Linq; using System.Reflection; using System.Windows.Forms; namespace Inspectron.Settings.Windows.Configuration; public partial class ItemEditorDialog : Form { private readonly Type _itemType; private object _workingValue; private readonly DefaultControlFactory _controlFactory; private readonly OptionsWindow _parentOptionsWindow; private FlowLayoutPanel _propertyPanel; private Button _okButton; private Button _cancelButton; public ItemEditorDialog(Type itemType, object initialValue, DefaultControlFactory controlFactory, OptionsWindow parentOptionsWindow) { _itemType = itemType; _workingValue = CloneObject(initialValue); _controlFactory = controlFactory; _parentOptionsWindow = parentOptionsWindow; InitializeComponent(); CreatePropertyControls(); } private void InitializeComponent() { this.Text = $"Edit {_itemType.Name}"; this.Size = new System.Drawing.Size(650, 420); this.StartPosition = FormStartPosition.CenterParent; this.FormBorderStyle = FormBorderStyle.FixedDialog; this.MaximizeBox = false; this.MinimizeBox = false; _propertyPanel = new FlowLayoutPanel { Location = new System.Drawing.Point(12, 12), Size = new System.Drawing.Size(620, 320), Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Bottom, FlowDirection = FlowDirection.TopDown, AutoScroll = true }; _okButton = new Button { Text = "OK", Location = new System.Drawing.Point(470, 340), Size = new System.Drawing.Size(75, 23), Anchor = AnchorStyles.Bottom | AnchorStyles.Right, DialogResult = DialogResult.OK }; _cancelButton = new Button { Text = "Cancel", Location = new System.Drawing.Point(550, 340), Size = new System.Drawing.Size(75, 23), Anchor = AnchorStyles.Bottom | AnchorStyles.Right, DialogResult = DialogResult.Cancel }; this.Controls.AddRange(new Control[] { _propertyPanel, _okButton, _cancelButton }); } private void CreatePropertyControls() { if (_itemType.IsValueType || _itemType == typeof(string)) { // For simple types, create a single control CreateSimpleValueControl(); } else { // For complex types, create controls for each property CreateComplexObjectControls(); } } private void CreateSimpleValueControl() { var dummyProperty = new SimplePropertyInfo(_itemType, "Value"); var control = _controlFactory.CreateControl("Value", "Value", dummyProperty, _workingValue, newValue => _workingValue = newValue, _parentOptionsWindow); _propertyPanel.Controls.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.Controls.Add(control); } } public object GetEditedValue() { return _workingValue; } 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; } } } }