SettingForm Invalid value error icon

This commit is contained in:
ChsBuffer
2021-11-14 00:58:54 +08:00
parent 65b204a21a
commit 07045b2e71
4 changed files with 93 additions and 38 deletions

View File

@@ -5,6 +5,7 @@ namespace Netch.Forms;
[Fody.ConfigureAwait(true)]
public class BindingForm : Form
{
// validation actions
private readonly Dictionary<Control, Func<string, bool>> _checkActions = new();
private readonly Dictionary<Control, Action<Control>> _saveActions = new();
@@ -13,7 +14,7 @@ public class BindingForm : Form
BindTextBox<string>(control, check, save, value);
}
protected void BindTextBox<T>(TextBoxBase control, Func<T, bool> check, Action<T> save, object value)
protected virtual void BindTextBox<T>(TextBoxBase control, Func<T, bool> check, Action<T> save, object value)
{
control.Text = value.ToString();
_checkActions.Add(control,
@@ -21,7 +22,7 @@ public class BindingForm : Form
{
try
{
return check.Invoke((T)Convert.ChangeType(s, typeof(T)));
return check((T)Convert.ChangeType(s, typeof(T)));
}
catch
{
@@ -29,7 +30,7 @@ public class BindingForm : Form
}
});
_saveActions.Add(control, c => save.Invoke((T)Convert.ChangeType(((TextBoxBase)c).Text, typeof(T))));
_saveActions.Add(control, c => save((T)Convert.ChangeType(((TextBoxBase)c).Text, typeof(T))));
}
protected void BindCheckBox(CheckBox control, Action<bool> save, bool value)
@@ -48,7 +49,7 @@ public class BindingForm : Form
protected void BindRadioBox(RadioButton control, Action<bool> save, bool value)
{
control.Checked = value;
_saveActions.Add(control, c => save.Invoke(((RadioButton)c).Checked));
_saveActions.Add(control, c => save(((RadioButton)c).Checked));
}
protected void BindListComboBox<T>(ComboBox comboBox, Action<T> save, IEnumerable<T> values, T value) where T : notnull
@@ -62,7 +63,7 @@ public class BindingForm : Form
comboBox.ValueMember = nameof(TagItem<T>.Value);
comboBox.DisplayMember = nameof(TagItem<T>.Text);
_saveActions.Add(comboBox, c => save.Invoke(((TagItem<T>)((ComboBox)c).SelectedItem).Value));
_saveActions.Add(comboBox, c => save(((TagItem<T>)((ComboBox)c).SelectedItem).Value));
Load += (_, _) => { comboBox.SelectedItem = tagItems.SingleOrDefault(t => t.Value.Equals(value)); };
}
@@ -71,20 +72,28 @@ public class BindingForm : Form
if (values != null)
control.Items.AddRange(values);
_saveActions.Add(control, c => save.Invoke(((ComboBox)c).Text));
_checkActions.Add(control, check.Invoke);
_checkActions.Add(control, check);
_saveActions.Add(control, c => save(((ComboBox)c).Text));
Load += (_, _) => { control.Text = value; };
}
protected List<Control> GetCheckFailedControls()
protected List<Control> GetInvalidateValueControls()
{
return _checkActions.Where(pair => !pair.Value.Invoke(pair.Key.Text)).Select(pair => pair.Key).ToList();
return _checkActions.Keys.Where(c => !Validate(c)).ToList();
}
protected bool Validate(Control c)
{
if (!_checkActions.ContainsKey(c))
throw new ArgumentException();
return _checkActions[c](c.Text);
}
protected void SaveBinds()
{
foreach (var pair in _saveActions)
pair.Value.Invoke(pair.Key);
pair.Value(pair.Key);
}
}

View File

@@ -31,6 +31,7 @@ namespace Netch.Forms
/// </summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.TabControl = new System.Windows.Forms.TabControl();
this.GeneralTabPage = new System.Windows.Forms.TabPage();
this.PortGroupBox = new System.Windows.Forms.GroupBox();
@@ -112,6 +113,7 @@ namespace Netch.Forms
this.AioDNSListenPortTextBox = new System.Windows.Forms.TextBox();
this.ControlButton = new System.Windows.Forms.Button();
this.flowLayoutPanel1 = new System.Windows.Forms.FlowLayoutPanel();
this.errorProvider = new System.Windows.Forms.ErrorProvider(this.components);
this.TabControl.SuspendLayout();
this.GeneralTabPage.SuspendLayout();
this.PortGroupBox.SuspendLayout();
@@ -123,6 +125,7 @@ namespace Netch.Forms
this.OtherTabPage.SuspendLayout();
this.AioDNSTabPage.SuspendLayout();
this.flowLayoutPanel1.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.errorProvider)).BeginInit();
this.SuspendLayout();
//
// TabControl
@@ -476,7 +479,7 @@ namespace Netch.Forms
this.WinTUNGroupBox.Controls.Add(this.ProxyDNSCheckBox);
this.WinTUNGroupBox.Location = new System.Drawing.Point(6, 6);
this.WinTUNGroupBox.Name = "WinTUNGroupBox";
this.WinTUNGroupBox.Size = new System.Drawing.Size(420, 175);
this.WinTUNGroupBox.Size = new System.Drawing.Size(450, 175);
this.WinTUNGroupBox.TabIndex = 0;
this.WinTUNGroupBox.TabStop = false;
//
@@ -562,8 +565,8 @@ namespace Netch.Forms
//
// ProxyDNSCheckBox
//
this.ProxyDNSCheckBox.DataBindings.Add((new System.Windows.Forms.Binding("Visible", UseCustomDNSCheckBox, "Checked", true)));
this.ProxyDNSCheckBox.AutoSize = true;
this.ProxyDNSCheckBox.DataBindings.Add(new System.Windows.Forms.Binding("Visible", this.UseCustomDNSCheckBox, "Checked", true));
this.ProxyDNSCheckBox.Location = new System.Drawing.Point(175, 139);
this.ProxyDNSCheckBox.Name = "ProxyDNSCheckBox";
this.ProxyDNSCheckBox.Size = new System.Drawing.Size(89, 21);
@@ -642,7 +645,7 @@ namespace Netch.Forms
this.KCPGroupBox.Controls.Add(this.congestionCheckBox);
this.KCPGroupBox.Location = new System.Drawing.Point(9, 75);
this.KCPGroupBox.Name = "KCPGroupBox";
this.KCPGroupBox.Size = new System.Drawing.Size(427, 204);
this.KCPGroupBox.Size = new System.Drawing.Size(447, 204);
this.KCPGroupBox.TabIndex = 3;
this.KCPGroupBox.TabStop = false;
this.KCPGroupBox.Text = "KCP";
@@ -967,6 +970,11 @@ namespace Netch.Forms
this.flowLayoutPanel1.Size = new System.Drawing.Size(480, 400);
this.flowLayoutPanel1.TabIndex = 0;
//
// errorProvider
//
this.errorProvider.BlinkStyle = System.Windows.Forms.ErrorBlinkStyle.NeverBlink;
this.errorProvider.ContainerControl = this;
//
// SettingForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
@@ -1000,6 +1008,7 @@ namespace Netch.Forms
this.AioDNSTabPage.ResumeLayout(false);
this.AioDNSTabPage.PerformLayout();
this.flowLayoutPanel1.ResumeLayout(false);
((System.ComponentModel.ISupportInitialize)(this.errorProvider)).EndInit();
this.ResumeLayout(false);
this.PerformLayout();
@@ -1088,5 +1097,6 @@ namespace Netch.Forms
private System.Windows.Forms.CheckBox FilterTCPCheckBox;
private System.Windows.Forms.CheckBox FilterUDPCheckBox;
private System.Windows.Forms.CheckBox DNSProxyCheckBox;
private ErrorProvider errorProvider;
}
}

View File

@@ -31,10 +31,7 @@ public partial class SettingForm : BindingForm
i => Global.Settings.DetectionTick = i,
Global.Settings.DetectionTick);
BindTextBox<int>(StartedPingIntervalTextBox,
_ => true,
i => Global.Settings.StartedPingInterval = i,
Global.Settings.StartedPingInterval);
BindTextBox<int>(StartedPingIntervalTextBox, _ => true, i => Global.Settings.StartedPingInterval = i, Global.Settings.StartedPingInterval);
object[]? stuns;
try
@@ -88,11 +85,10 @@ public partial class SettingForm : BindingForm
BindCheckBox(FilterDNSCheckBox, b => Global.Settings.Redirector.FilterDNS = b, Global.Settings.Redirector.FilterDNS);
// TODO validate Redirector AioDNS DNS
BindTextBox(DNSHijackHostTextBox, s => true, s => Global.Settings.Redirector.DNSHost = s, Global.Settings.Redirector.DNSHost);
BindCheckBox(ChildProcessHandleCheckBox,
s => Global.Settings.Redirector.FilterParent = s,
Global.Settings.Redirector.FilterParent);
BindCheckBox(ChildProcessHandleCheckBox, s => Global.Settings.Redirector.FilterParent = s, Global.Settings.Redirector.FilterParent);
BindCheckBox(DNSProxyCheckBox, b => Global.Settings.Redirector.DNSProxy = b, Global.Settings.Redirector.DNSProxy);
@@ -102,20 +98,11 @@ public partial class SettingForm : BindingForm
#region TUN/TAP
BindTextBox(TUNTAPAddressTextBox,
s => IPAddress.TryParse(s, out _),
s => Global.Settings.TUNTAP.Address = s,
Global.Settings.TUNTAP.Address);
BindTextBox(TUNTAPAddressTextBox, s => IPAddress.TryParse(s, out _), s => Global.Settings.TUNTAP.Address = s, Global.Settings.TUNTAP.Address);
BindTextBox(TUNTAPNetmaskTextBox,
s => IPAddress.TryParse(s, out _),
s => Global.Settings.TUNTAP.Netmask = s,
Global.Settings.TUNTAP.Netmask);
BindTextBox(TUNTAPNetmaskTextBox, s => IPAddress.TryParse(s, out _), s => Global.Settings.TUNTAP.Netmask = s, Global.Settings.TUNTAP.Netmask);
BindTextBox(TUNTAPGatewayTextBox,
s => IPAddress.TryParse(s, out _),
s => Global.Settings.TUNTAP.Gateway = s,
Global.Settings.TUNTAP.Gateway);
BindTextBox(TUNTAPGatewayTextBox, s => IPAddress.TryParse(s, out _), s => Global.Settings.TUNTAP.Gateway = s, Global.Settings.TUNTAP.Gateway);
BindCheckBox(UseCustomDNSCheckBox, b => { Global.Settings.TUNTAP.UseCustomDNS = b; }, Global.Settings.TUNTAP.UseCustomDNS);
@@ -161,9 +148,7 @@ public partial class SettingForm : BindingForm
i => Global.Settings.V2RayConfig.KcpConfig.writeBufferSize = i,
Global.Settings.V2RayConfig.KcpConfig.writeBufferSize);
BindCheckBox(congestionCheckBox,
b => Global.Settings.V2RayConfig.KcpConfig.congestion = b,
Global.Settings.V2RayConfig.KcpConfig.congestion);
BindCheckBox(congestionCheckBox, b => Global.Settings.V2RayConfig.KcpConfig.congestion = b, Global.Settings.V2RayConfig.KcpConfig.congestion);
#endregion
@@ -208,6 +193,39 @@ public partial class SettingForm : BindingForm
TUNTAPUseCustomDNSCheckBox_CheckedChanged(null, null);
}
protected override void BindTextBox<T>(TextBoxBase control, Func<T, bool> check, Action<T> save, object value)
{
base.BindTextBox(control, check, save, value);
control.TextChanged += (_, _) =>
{
if (Validate(control))
{
errorProvider.SetError(control, null);
}
else
{
errorProvider.SetError(control, i18N.Translate("Invalid value"));
}
};
}
protected new void BindComboBox(ComboBox control, Func<string, bool> check, Action<string> save, string value, object[]? values = null)
{
base.BindComboBox(control, check, save, value, values);
control.TextChanged += (_, _) =>
{
if (Validate(control))
{
errorProvider.SetError(control, null);
}
else
{
errorProvider.SetError(control, i18N.Translate("Invalid value"));
}
};
}
private void TUNTAPUseCustomDNSCheckBox_CheckedChanged(object? sender, EventArgs? e)
{
if (UseCustomDNSCheckBox.Checked)
@@ -229,12 +247,27 @@ public partial class SettingForm : BindingForm
#region Check
var checkNotPassControl = GetCheckFailedControls();
foreach (Control control in checkNotPassControl)
Utils.Utils.ChangeControlForeColor(control, Color.Red);
var checkNotPassControl = GetInvalidateValueControls();
if (checkNotPassControl.Any())
{
var failControl = checkNotPassControl.First();
// switch to fail control's tab page
var p = failControl.Parent;
while (p != null)
{
if (p is TabPage tabPage)
{
TabControl.SelectedTab = tabPage;
break;
}
p = p.Parent;
}
return;
}
#endregion

View File

@@ -57,4 +57,7 @@
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="errorProvider.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
</root>