mirror of
https://github.com/netchx/netch.git
synced 2026-03-18 18:13:21 +08:00
SettingForm Invalid value error icon
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
16
Netch/Forms/SettingForm.Designer.cs
generated
16
Netch/Forms/SettingForm.Designer.cs
generated
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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>
|
||||
Reference in New Issue
Block a user