Files
2025-07-23 13:25:19 +02:00

291 lines
12 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System.Windows.Forms;
using Inspectron.Settings.Attributes;
using Microsoft.WindowsAPICodePack.Dialogs;
namespace Inspectron.Settings.Windows.Configuration;
public class DefaultControlFactory : IControlFactory
{
public virtual Control CreateControl(string name, string description, PropertyInfo propertyInfo,
object initialValue, Action<object> valueChangedCallback, OptionsWindow optionsWindow)
{
var type = propertyInfo.PropertyType;
// Check for SettingDescriptionAttribute
var settingDescriptionAttribute = propertyInfo.GetCustomAttribute<SettingDescriptionAttribute>();
string settingDescription = settingDescriptionAttribute?.Description;
// Check for SettingPreviewAttribute
var previewAttribute = propertyInfo.GetCustomAttribute<SettingPreviewAttribute>();
Label previewLabel = null;
Func<object, string> getPreview = null;
if (previewAttribute != null)
{
var method = previewAttribute.PreviewClass.GetMethod(previewAttribute.PreviewFunction, BindingFlags.Public | BindingFlags.Static);
getPreview = value => (string)method.Invoke(null, new[] { value });
previewLabel = new Label
{
AutoSize = false,
Size = new System.Drawing.Size(600, 30),
Padding = new Padding(15, 0, 0, 0),
Font = new System.Drawing.Font("Segoe UI", 10, System.Drawing.FontStyle.Italic),
Text = getPreview(initialValue)
};
}
// Check for List<T> types
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(List<>))
{
return CreateListControl(name, description, type, initialValue, valueChangedCallback, optionsWindow, settingDescription, previewLabel, getPreview);
}
else if (type == typeof(string) && propertyInfo.GetCustomAttribute<FileAttribute>()!=null)
{
return CreateFileControl(name, description, initialValue, valueChangedCallback, optionsWindow, settingDescription, previewLabel, getPreview, propertyInfo.GetCustomAttribute<FileAttribute>().Filter);
}
else if (type == typeof(string) && name.EndsWith("Path", StringComparison.OrdinalIgnoreCase))
{
return CreatePathControl(name, description, initialValue, valueChangedCallback, optionsWindow, settingDescription, previewLabel, getPreview);
}
else if (type == typeof(string))
{
return CreateStringControl(description, initialValue, valueChangedCallback, settingDescription, previewLabel, getPreview);
}
else if (type == typeof(int))
{
return CreateIntControl(description, initialValue, valueChangedCallback, settingDescription, previewLabel, getPreview);
}
else if (type == typeof(bool))
{
return CreateBoolControl(description, initialValue, valueChangedCallback, settingDescription, previewLabel, getPreview);
}
else if (type.IsEnum)
{
return CreateEnumControl(description, type, initialValue, valueChangedCallback, settingDescription, previewLabel, getPreview);
}
else
{
return new Label { Text = $"Unsupported type: {type.Name}", AutoSize = true };
}
}
private Control CreateListControl(string name, string description, Type listType, object initialValue,
Action<object> valueChangedCallback, OptionsWindow optionsWindow, string settingDescription,
Label previewLabel, Func<object, string> getPreview)
{
var elementType = listType.GetGenericArguments()[0];
var list = (IList)initialValue ?? (IList)Activator.CreateInstance(listType);
var label = new Label { Text = description, AutoSize = true, Padding = new Padding(0, 5, 0, 0) };
var textBox = new TextBox
{
Text = GetListDisplayText(list),
Width = 500,
Height = 60,
Multiline = true,
ReadOnly = true,
ScrollBars = ScrollBars.Vertical
};
var editButton = new Button { Text = "Edit", AutoSize = true };
editButton.Click += (s, e) =>
{
using (var listEditor = new ListEditorDialog(elementType, list, this, optionsWindow, name))
{
if (listEditor.ShowDialog(optionsWindow) == DialogResult.OK)
{
var newList = listEditor.GetEditedList();
list.Clear();
foreach (object o in newList)
{
list.Add(o);
}
textBox.Text = GetListDisplayText(list);
valueChangedCallback(list);
if (previewLabel != null && getPreview != null)
previewLabel.Text = getPreview(list);
}
}
};
return CreateOuterPanel(settingDescription, previewLabel, label, textBox, editButton);
}
private 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 Control CreatePathControl(string name, string description, object initialValue, Action<object> valueChangedCallback,
OptionsWindow optionsWindow, string settingDescription, Label previewLabel, Func<object, string> getPreview)
{
var textBox = new TextBox { Text = initialValue as string, Width = 400 };
var label = new Label { Text = description, AutoSize = true, Padding = new Padding(0, 5, 0, 0) };
var browseButton = new Button { Text = "Browse", AutoSize = true };
browseButton.Click += (s, e) =>
{
using (var dialog = new CommonOpenFileDialog { IsFolderPicker = true })
{
if (dialog.ShowDialog(optionsWindow.Handle) == CommonFileDialogResult.Ok)
{
textBox.Text = dialog.FileName;
valueChangedCallback(dialog.FileName);
if (previewLabel != null && getPreview != null)
previewLabel.Text = getPreview(dialog.FileName);
}
}
};
textBox.TextChanged += (s, e) =>
{
valueChangedCallback(textBox.Text);
if (previewLabel != null && getPreview != null)
previewLabel.Text = getPreview(textBox.Text);
};
return CreateOuterPanel(settingDescription, previewLabel, label, textBox, browseButton);
}
private Control CreateFileControl(string name, string description, object initialValue, Action<object> valueChangedCallback,
OptionsWindow optionsWindow, string settingDescription, Label previewLabel, Func<object, string> getPreview, string filter)
{
var textBox = new TextBox { Text = initialValue as string, Width = 400 };
var label = new Label { Text = description, AutoSize = true, Padding = new Padding(0, 5, 0, 0) };
var browseButton = new Button { Text = "Browse", AutoSize = true };
browseButton.Click += (s, e) =>
{
using (var dialog = new CommonOpenFileDialog {Filters = { new CommonFileDialogFilter(filter, filter) }})
{
if (dialog.ShowDialog(optionsWindow.Handle) == CommonFileDialogResult.Ok)
{
textBox.Text = dialog.FileName;
valueChangedCallback(dialog.FileName);
if (previewLabel != null && getPreview != null)
previewLabel.Text = getPreview(dialog.FileName);
}
}
};
textBox.TextChanged += (s, e) =>
{
valueChangedCallback(textBox.Text);
if (previewLabel != null && getPreview != null)
previewLabel.Text = getPreview(textBox.Text);
};
return CreateOuterPanel(settingDescription, previewLabel, label, textBox, browseButton);
}
private Control CreateStringControl(string description, object initialValue, Action<object> valueChangedCallback,
string settingDescription, Label previewLabel, Func<object, string> getPreview)
{
var textBox = new TextBox { Text = initialValue as string, Width = 600 };
var label = new Label { Text = description, AutoSize = true, Padding = new Padding(0, 5, 0, 0) };
textBox.TextChanged += (s, e) =>
{
valueChangedCallback(textBox.Text);
if (previewLabel != null && getPreview != null)
previewLabel.Text = getPreview(textBox.Text);
};
return CreateOuterPanel(settingDescription, previewLabel, label, textBox);
}
private Control CreateIntControl(string description, object initialValue, Action<object> valueChangedCallback,
string settingDescription, Label previewLabel, Func<object, string> getPreview)
{
var label = new Label { Text = description, AutoSize = true, Padding = new Padding(0, 5, 0, 0) };
var numericUpDown = new NumericUpDown { Minimum = 0, Maximum = 99999999999, Value = Convert.ToDecimal(initialValue), Width = 200 };
numericUpDown.ValueChanged += (s, e) =>
{
valueChangedCallback(Convert.ToInt32(numericUpDown.Value));
if (previewLabel != null && getPreview != null)
previewLabel.Text = getPreview(Convert.ToInt32(numericUpDown.Value));
};
return CreateOuterPanel(settingDescription, previewLabel, label, numericUpDown);
}
private Control CreateBoolControl(string description, object initialValue, Action<object> valueChangedCallback,
string settingDescription, Label previewLabel, Func<object, string> getPreview)
{
var checkBox = new CheckBox { Text = description, Checked = (bool)initialValue, AutoSize = true };
checkBox.CheckedChanged += (s, e) =>
{
valueChangedCallback(checkBox.Checked);
if (previewLabel != null && getPreview != null)
previewLabel.Text = getPreview(checkBox.Checked);
};
return CreateOuterPanel(settingDescription, previewLabel, checkBox);
}
private Control CreateEnumControl(string description, Type enumType, object initialValue, Action<object> valueChangedCallback,
string settingDescription, Label previewLabel, Func<object, string> getPreview)
{
var label = new Label { Text = description, AutoSize = true, Padding = new Padding(0, 5, 0, 0) };
var comboBox = new ComboBox { DropDownStyle = ComboBoxStyle.DropDownList, Width = 200 };
// Populate ComboBox with enum values
foreach (var value in Enum.GetValues(enumType))
{
comboBox.Items.Add(value);
}
// Set initial value
comboBox.SelectedItem = initialValue;
comboBox.SelectedIndexChanged += (s, e) =>
{
valueChangedCallback(comboBox.SelectedItem);
if (previewLabel != null && getPreview != null)
previewLabel.Text = getPreview(comboBox.SelectedItem);
};
return CreateOuterPanel(settingDescription, previewLabel, label, comboBox);
}
private Control CreateOuterPanel(string settingDescription, Label previewLabel, params Control[] controls)
{
var outerPanel = new FlowLayoutPanel { FlowDirection = FlowDirection.TopDown, AutoSize = true, Margin = new Padding(0, 25, 0, 0) };
if (!string.IsNullOrEmpty(settingDescription))
{
var descriptionLabel = new Label { Text = settingDescription, AutoSize = true, Padding = new Padding(0, 5, 0, 0) };
outerPanel.Controls.Add(descriptionLabel);
}
foreach (var control in controls)
{
outerPanel.Controls.Add(control);
}
if (previewLabel != null)
outerPanel.Controls.Add(previewLabel);
return outerPanel;
}
}
// List Editor Dialog
// Item Editor Dialog
// Helper class for simple property info