297 lines
12 KiB
Plaintext
297 lines
12 KiB
Plaintext
@using MudBlazor
|
|
@using System.Collections
|
|
@using System.ComponentModel
|
|
@using System.Reflection
|
|
@using Inspectron.Settings
|
|
@using Inspectron.Settings.Attributes
|
|
|
|
<MudDialog>
|
|
<DialogContent>
|
|
<div class="settings-layout">
|
|
<div class="settings-tree">
|
|
<MudTreeView T="string" SelectedValueChanged="OnCategorySelected" Dense="true">
|
|
<SettingsTreeNode Nodes="_treeRoot" />
|
|
</MudTreeView>
|
|
</div>
|
|
<div class="settings-content">
|
|
@if (_selectedCategory != null && GetSettingsForCategory(_selectedCategory) is { Count: > 0 } settings)
|
|
{
|
|
@foreach (var setting in settings)
|
|
{
|
|
<div class="settings-field">
|
|
@if (!string.IsNullOrEmpty(setting.SettingDescription))
|
|
{
|
|
<MudText Typo="Typo.caption" Class="mb-1" Style="font-style: italic;">@setting.SettingDescription</MudText>
|
|
}
|
|
|
|
@if (setting.Property.PropertyType == typeof(bool))
|
|
{
|
|
var boolVal = (bool)(setting.Value ?? false);
|
|
<MudSwitch T="bool" Value="boolVal"
|
|
ValueChanged="@(v => setting.Value = v)"
|
|
Label="@setting.Description" Color="Color.Primary" />
|
|
}
|
|
else if (setting.Property.PropertyType == typeof(int))
|
|
{
|
|
var intVal = (int)(setting.Value ?? 0);
|
|
<MudNumericField T="int" Value="intVal"
|
|
ValueChanged="@(v => setting.Value = v)"
|
|
Label="@setting.Description" Variant="Variant.Outlined" />
|
|
}
|
|
else if (setting.Property.PropertyType == typeof(double))
|
|
{
|
|
var dblVal = (double)(setting.Value ?? 0.0);
|
|
<MudNumericField T="double" Value="dblVal"
|
|
ValueChanged="@(v => setting.Value = v)"
|
|
Label="@setting.Description" Variant="Variant.Outlined" />
|
|
}
|
|
else if (setting.Property.PropertyType.IsEnum)
|
|
{
|
|
<MudSelect T="object" Value="setting.Value"
|
|
ValueChanged="@(v => setting.Value = v)"
|
|
Label="@setting.Description" Variant="Variant.Outlined">
|
|
@foreach (var enumVal in Enum.GetValues(setting.Property.PropertyType))
|
|
{
|
|
<MudSelectItem T="object" Value="@enumVal">@enumVal.ToString()</MudSelectItem>
|
|
}
|
|
</MudSelect>
|
|
}
|
|
else if (IsListType(setting.Property.PropertyType))
|
|
{
|
|
var s = setting;
|
|
<MudText Typo="Typo.subtitle2" Class="mb-1">@setting.Description</MudText>
|
|
<MudTextField T="string" Value="@GetListDisplayText(setting.Value as IList)"
|
|
ReadOnly="true" Lines="3" Variant="Variant.Outlined" />
|
|
<MudButton Variant="Variant.Outlined" Color="Color.Primary" Class="mt-1"
|
|
OnClick="@(() => EditList(s))">Edit</MudButton>
|
|
}
|
|
else
|
|
{
|
|
var strVal = setting.Value?.ToString() ?? "";
|
|
<MudTextField T="string" Value="strVal"
|
|
ValueChanged="@(v => setting.Value = v)"
|
|
Label="@setting.Description" Variant="Variant.Outlined" />
|
|
}
|
|
</div>
|
|
}
|
|
}
|
|
else
|
|
{
|
|
<MudText Typo="Typo.body2" Class="pa-4">Select a category to view settings.</MudText>
|
|
}
|
|
</div>
|
|
</div>
|
|
</DialogContent>
|
|
<DialogActions>
|
|
<MudButton OnClick="Cancel">Cancel</MudButton>
|
|
<MudButton Color="Color.Primary" OnClick="Save">Save</MudButton>
|
|
</DialogActions>
|
|
</MudDialog>
|
|
|
|
@code {
|
|
[CascadingParameter] private IMudDialogInstance MudDialog { get; set; } = null!;
|
|
[Parameter] public InspectronSettings? Settings { get; set; }
|
|
|
|
[Microsoft.AspNetCore.Components.Inject] private IDialogService DialogService { get; set; } = null!;
|
|
|
|
private Dictionary<string, List<SettingEntry>> _categories = new();
|
|
private string? _selectedCategory;
|
|
private List<CategoryNode> _treeRoot = new();
|
|
|
|
protected override void OnParametersSet()
|
|
{
|
|
if (Settings == null) return;
|
|
LoadSettings();
|
|
}
|
|
|
|
private void LoadSettings()
|
|
{
|
|
_categories.Clear();
|
|
_treeRoot = new List<CategoryNode>();
|
|
var treeView = Settings!.UserSettings;
|
|
var root = treeView.Root as Tree<object>;
|
|
if (root != null)
|
|
Traverse(root, "");
|
|
|
|
foreach (var categoryPath in _categories.Keys)
|
|
{
|
|
var parts = categoryPath.Split('/');
|
|
var currentList = _treeRoot;
|
|
for (int i = 0; i < parts.Length; i++)
|
|
{
|
|
var existing = currentList.FirstOrDefault(n => n.Label == parts[i]);
|
|
if (existing == null)
|
|
{
|
|
existing = new CategoryNode
|
|
{
|
|
Label = parts[i],
|
|
FullPath = string.Join("/", parts.Take(i + 1))
|
|
};
|
|
currentList.Add(existing);
|
|
}
|
|
currentList = existing.ChildNodes;
|
|
}
|
|
}
|
|
}
|
|
|
|
private void Traverse(Tree<object> node, string path)
|
|
{
|
|
object value = node.Value;
|
|
|
|
if (value is string folderName)
|
|
{
|
|
string newPath = string.IsNullOrEmpty(path) ? folderName : $"{path}/{folderName}";
|
|
foreach (Tree<object> 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 (PropertyDescriptor pd in info.Settings)
|
|
{
|
|
if (pd is BoundPropertyDescriptor bpd)
|
|
{
|
|
var owner = bpd.Owner;
|
|
var description = string.IsNullOrEmpty(pd.Description) ? bpd.DisplayName : pd.Description;
|
|
|
|
string? settingDesc = null;
|
|
var descAttr = bpd.PropertyInfo.GetCustomAttribute<SettingDescriptionAttribute>();
|
|
if (descAttr != null)
|
|
settingDesc = descAttr.Description;
|
|
|
|
var entry = new SettingEntry
|
|
{
|
|
Owner = owner,
|
|
Property = bpd.PropertyInfo,
|
|
Description = description,
|
|
SettingDescription = settingDesc,
|
|
Value = bpd.PropertyInfo.GetValue(owner)
|
|
};
|
|
|
|
if (!_categories.TryGetValue(groupPath, out var list))
|
|
{
|
|
list = new List<SettingEntry>();
|
|
_categories[groupPath] = list;
|
|
}
|
|
list.Add(entry);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private void OnCategorySelected(string? category)
|
|
{
|
|
_selectedCategory = category;
|
|
}
|
|
|
|
private List<SettingEntry> GetSettingsForCategory(string category)
|
|
{
|
|
if (_categories.TryGetValue(category, out var exact))
|
|
return exact;
|
|
|
|
var prefix = category + "/";
|
|
return _categories
|
|
.Where(kvp => kvp.Key.StartsWith(prefix))
|
|
.SelectMany(kvp => kvp.Value)
|
|
.ToList();
|
|
}
|
|
|
|
private static bool IsListType(Type type)
|
|
{
|
|
return type.IsGenericType && type.GetGenericTypeDefinition() == typeof(List<>);
|
|
}
|
|
|
|
private static string GetListDisplayText(IList? list)
|
|
{
|
|
if (list == null || list.Count == 0)
|
|
return "(empty list)";
|
|
var items = new List<string>();
|
|
foreach (var item in list)
|
|
items.Add(item?.ToString() ?? "(null)");
|
|
return string.Join(Environment.NewLine, items);
|
|
}
|
|
|
|
private async Task EditList(SettingEntry setting)
|
|
{
|
|
var elementType = setting.Property.PropertyType.GetGenericArguments()[0];
|
|
var parameters = new DialogParameters<ListEditorDialog>
|
|
{
|
|
{ x => x.ElementType, elementType },
|
|
{ x => x.InitialList, setting.Value as IList }
|
|
};
|
|
var options = new DialogOptions { MaxWidth = MaxWidth.Medium, FullWidth = true };
|
|
var dialog = await DialogService.ShowAsync<ListEditorDialog>($"Edit {setting.Description}", parameters, options);
|
|
var result = await dialog.Result;
|
|
if (result != null && !result.Canceled && result.Data is IList newList)
|
|
{
|
|
setting.Value = newList;
|
|
StateHasChanged();
|
|
}
|
|
}
|
|
|
|
private void Save()
|
|
{
|
|
foreach (var list in _categories.Values)
|
|
{
|
|
foreach (var setting in list)
|
|
{
|
|
var currentValue = setting.Property.GetValue(setting.Owner);
|
|
if (!Equals(currentValue, setting.Value))
|
|
{
|
|
try
|
|
{
|
|
if (IsListType(setting.Property.PropertyType) && setting.Value is IList listVal)
|
|
{
|
|
// For list types, clear and repopulate the original list
|
|
var originalList = setting.Property.GetValue(setting.Owner) as IList;
|
|
if (originalList != null)
|
|
{
|
|
originalList.Clear();
|
|
foreach (var item in listVal)
|
|
originalList.Add(item);
|
|
}
|
|
else
|
|
{
|
|
setting.Property.SetValue(setting.Owner, setting.Value);
|
|
}
|
|
}
|
|
else if (setting.Value != null && setting.Value.GetType() != setting.Property.PropertyType)
|
|
{
|
|
var converted = Convert.ChangeType(setting.Value, setting.Property.PropertyType);
|
|
setting.Property.SetValue(setting.Owner, converted);
|
|
}
|
|
else
|
|
{
|
|
setting.Property.SetValue(setting.Owner, setting.Value);
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
}
|
|
}
|
|
}
|
|
Settings?.SaveSettings();
|
|
MudDialog.Close(DialogResult.Ok(true));
|
|
}
|
|
|
|
private void Cancel() => MudDialog.Cancel();
|
|
|
|
private class SettingEntry
|
|
{
|
|
public object Owner { get; set; } = null!;
|
|
public PropertyInfo Property { get; set; } = null!;
|
|
public string Description { get; set; } = "";
|
|
public string? SettingDescription { get; set; }
|
|
public object? Value { get; set; }
|
|
}
|
|
|
|
public class CategoryNode
|
|
{
|
|
public string Label { get; set; } = "";
|
|
public string FullPath { get; set; } = "";
|
|
public List<CategoryNode> ChildNodes { get; set; } = new();
|
|
}
|
|
}
|