Files
carmanager-3/CarManagerV3/Forms/SettingsForm.cs
2026-03-10 15:04:27 +01:00

174 lines
5.2 KiB
C#

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace CarManagerV3.Forms
{
public partial class SettingsForm : Form
{
// Settings map (Maps settings to controls and default values + optional change event handler function that takes previous and new value)
private readonly Dictionary<string, ISettingBinding> settingsMap = new();
public SettingsForm()
{
InitializeComponent();
initializeSettingsMap();
}
private void initializeSettingsMap()
{
// Initialize the settings map with setting keys, associated controls, default values, and optional change event handlers
settingsMap["DataLocation"] =
new SettingBinding<string>(
control: tbxDataLocation,
defaultValue: Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\CarManagerV3",
read: () => Properties.Settings.Default.DataLocation, // strongly typed
write: v => Properties.Settings.Default.DataLocation = v, // strongly typed
onChange: (before, after) =>
{
// TODO: handle path change if needed
});
settingsMap["AllowPrerelease"] =
new SettingBinding<bool>(
control: cbxPreRelease,
defaultValue: false,
read: () => Properties.Settings.Default.AllowPrerelease,
write: v => Properties.Settings.Default.AllowPrerelease = v);
}
private void SettingsForm_Load(object sender, EventArgs e)
{
loadSettings();
}
private void loadSettings()
{
foreach (var kvp in settingsMap)
kvp.Value.Load();
}
private void saveSettings()
{
foreach (var kvp in settingsMap)
kvp.Value.Save();
Properties.Settings.Default.Save();
}
private void resetSettings()
{
DialogResult confirmReset = MessageBox.Show(
"Are you sure you want to reset all settings to their default values? This action cannot be undone.",
"Confirm Reset",
MessageBoxButtons.YesNo,
MessageBoxIcon.Warning);
if (confirmReset != DialogResult.Yes)
return;
foreach (var kvp in settingsMap)
kvp.Value.Reset();
Properties.Settings.Default.Save();
loadSettings();
}
private void btnAccept_Click(object sender, EventArgs e)
{
saveSettings();
this.Close();
}
private void btnDiscard_Click(object sender, EventArgs e)
{
this.Close();
}
private void btnReset_Click(object sender, EventArgs e)
{
resetSettings();
}
}
internal interface ISettingBinding
{
void Load();
void Save();
void Reset();
}
internal sealed class SettingBinding<T> : ISettingBinding
{
private readonly Control control;
private readonly T defaultValue;
private readonly Func<T> read;
private readonly Action<T> write;
private readonly Action<T, T>? onChange;
public SettingBinding(Control control, T defaultValue, Func<T> read, Action<T> write, Action<T, T>? onChange = null)
{
this.control = control;
this.defaultValue = defaultValue;
this.read = read;
this.write = write;
this.onChange = onChange;
}
public void Load()
{
T value = read();
ApplyToControl(value);
}
public void Save()
{
T before = read();
T after = ReadFromControl();
write(after);
if (onChange != null && !EqualityComparer<T>.Default.Equals(before, after))
onChange(before, after);
}
public void Reset() => write(defaultValue);
private void ApplyToControl(T value)
{
switch (control)
{
case TextBox tb:
tb.Text = value?.ToString() ?? string.Empty;
break;
case CheckBox cb:
cb.Checked = value is bool b ? b : Convert.ToBoolean(value);
break;
default:
throw new NotSupportedException($"Control type '{control.GetType().Name}' not supported for {typeof(T).Name}.");
}
}
private T ReadFromControl()
{
object result = control switch
{
TextBox tb when typeof(T) == typeof(string) => tb.Text,
CheckBox cb when typeof(T) == typeof(bool) => cb.Checked,
_ => throw new NotSupportedException($"Cannot read {typeof(T).Name} from control type '{control.GetType().Name}'.")
};
return (T)result;
}
}
}