174 lines
5.2 KiB
C#
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;
|
|
}
|
|
}
|
|
}
|