using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using Avalonia.Controls; using Avalonia.Interactivity; namespace Inspectron.Settings.Avalonia.Configuration; public partial class OptionsWindow : Window { private readonly Dictionary> _settingsByCategory; private readonly IControlFactory _controlFactory; public OptionsWindow(IControlFactory controlFactory) { _controlFactory = controlFactory; _settingsByCategory = new Dictionary>(); InitializeComponent(); TreeViewCategories.SelectionChanged += TreeViewCategories_SelectionChanged; BtnOK.Click += BtnOK_Click; BtnCancel.Click += BtnCancel_Click; } public void LoadFromSettings(InspectronSettings inspectronSettings) { void Traverse(object nodeObj, string path) { var node = nodeObj as dynamic; object value = node.Value; if (value is string folderName) { string newPath = string.IsNullOrEmpty(path) ? folderName : $"{path}/{folderName}"; foreach (var child in node.Children) Traverse(child, newPath); } else if (value is InspectronSettings.UserSettingsInfo info) { string groupName = info.Name; string groupPath = string.IsNullOrEmpty(path) ? groupName : $"{path}/{groupName}"; foreach (var pd in info.Settings) { object owner = null; string description = pd.Description; if (pd is BoundPropertyDescriptor bpd) { owner = bpd.Owner; if (string.IsNullOrEmpty(description)) description = bpd.DisplayName; } else { continue; } RegisterUserSetting(owner, bpd.PropertyInfo.Name, groupPath, description); } } } Traverse(inspectronSettings.UserSettings.Root, ""); } public void RegisterUserSetting(object owner, string propertyName, string treePath, string? description = null) { var property = owner.GetType().GetProperty(propertyName, BindingFlags.Public | BindingFlags.Instance); if (property == null) throw new ArgumentException($"Property '{propertyName}' not found on owner type."); if (string.IsNullOrEmpty(description)) description = propertyName; var setting = new OptionSetting { Owner = owner, Property = property, Description = description, TreePath = treePath, Value = property.GetValue(owner) }; if (!_settingsByCategory.TryGetValue(treePath, out var settingsList)) { settingsList = new List(); _settingsByCategory[treePath] = settingsList; } settingsList.Add(setting); AddTreeNodes(treePath); } private void AddTreeNodes(string treePath) { var parts = treePath.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries); var items = TreeViewCategories.Items; string currentPath = ""; foreach (var part in parts) { currentPath = string.IsNullOrEmpty(currentPath) ? part : $"{currentPath}/{part}"; var existing = items.OfType().FirstOrDefault(n => (string)n.Header == part); if (existing == null) { existing = new TreeViewItem { Header = part, Tag = currentPath, IsExpanded = false }; items.Add(existing); } items = existing.Items; } } private void TreeViewCategories_SelectionChanged(object? sender, SelectionChangedEventArgs e) { if (TreeViewCategories.SelectedItem is TreeViewItem selectedItem) { var path = selectedItem.Tag as string; if (path != null) DisplaySettings(path); } } private void DisplaySettings(string treePath) { SettingsPanel.Children.Clear(); if (_settingsByCategory.TryGetValue(treePath, out var settingsList)) { foreach (var setting in settingsList) { var control = _controlFactory.CreateControl( setting.Property.Name, setting.Description, setting.Property, setting.Value, (newValue) => { setting.Value = newValue; }, this); SettingsPanel.Children.Add(control); } } } private void BtnOK_Click(object? sender, RoutedEventArgs e) { foreach (var settingsList in _settingsByCategory.Values) { foreach (var setting in settingsList) { setting.Property.SetValue(setting.Owner, setting.Value); } } Close(true); } private void BtnCancel_Click(object? sender, RoutedEventArgs e) { Close(false); } }