From 0d2fefb8c4a5c5ba784439c7b3511dc5eecf8421 Mon Sep 17 00:00:00 2001 From: Serge <5920850+seerge@users.noreply.github.com> Date: Mon, 2 Sep 2024 10:47:03 +0200 Subject: [PATCH] Added units to backlight timeout inputs https://github.com/seerge/g-helper/pull/3037 --- app/Extra.Designer.cs | 15 ++-- app/UI/NumericUpDownWithUnit.cs | 141 ++++++++++++++++++++++++++++++++ 2 files changed, 150 insertions(+), 6 deletions(-) create mode 100644 app/UI/NumericUpDownWithUnit.cs diff --git a/app/Extra.Designer.cs b/app/Extra.Designer.cs index cd8677ce..8deb7a78 100644 --- a/app/Extra.Designer.cs +++ b/app/Extra.Designer.cs @@ -73,8 +73,8 @@ namespace GHelper labelBacklightTitle = new Label(); panelBacklight = new Panel(); panelBacklightExtra = new Panel(); - numericBacklightPluggedTime = new NumericUpDown(); - numericBacklightTime = new NumericUpDown(); + numericBacklightPluggedTime = new NumericUpDownWithUnit(); + numericBacklightTime = new NumericUpDownWithUnit(); labelBacklightTimeout = new Label(); labelSpeed = new Label(); comboKeyboardSpeed = new RComboBox(); @@ -119,7 +119,7 @@ namespace GHelper checkStatusLed = new CheckBox(); checkPerKeyRGB = new CheckBox(); panelPower = new Panel(); - numericHibernateAfter = new NumericUpDown(); + numericHibernateAfter = new NumericUpDownWithUnit(); labelHibernateAfter = new Label(); pictureHibernate = new PictureBox(); toolTip = new ToolTip(components); @@ -715,6 +715,7 @@ namespace GHelper numericBacklightPluggedTime.Name = "numericBacklightPluggedTime"; numericBacklightPluggedTime.Size = new Size(140, 39); numericBacklightPluggedTime.TabIndex = 1; + numericBacklightPluggedTime.Unit = "sec"; // // numericBacklightTime // @@ -725,6 +726,7 @@ namespace GHelper numericBacklightTime.Name = "numericBacklightTime"; numericBacklightTime.Size = new Size(140, 39); numericBacklightTime.TabIndex = 2; + numericBacklightTime.Unit = "sec"; // // labelBacklightTimeout // @@ -1323,6 +1325,7 @@ namespace GHelper numericHibernateAfter.Maximum = new decimal(new int[] { 3000000, 0, 0, 0 }); numericHibernateAfter.Name = "numericHibernateAfter"; numericHibernateAfter.Size = new Size(152, 39); + numericHibernateAfter.Unit = "min"; numericHibernateAfter.TabIndex = 1; // // labelHibernateAfter @@ -1714,8 +1717,8 @@ namespace GHelper private Panel panelBacklightHeader; private Panel panelBacklight; private Panel panelBacklightExtra; - private NumericUpDown numericBacklightPluggedTime; - private NumericUpDown numericBacklightTime; + private NumericUpDownWithUnit numericBacklightPluggedTime; + private NumericUpDownWithUnit numericBacklightTime; private Label labelBacklightTimeout; private Label labelSpeed; private RComboBox comboKeyboardSpeed; @@ -1764,7 +1767,7 @@ namespace GHelper private Panel panelPower; private PictureBox pictureHibernate; private Label labelHibernateAfter; - private NumericUpDown numericHibernateAfter; + private NumericUpDownWithUnit numericHibernateAfter; private CheckBox checkGPUFix; private ToolTip toolTip; private CheckBox checkBootSound; diff --git a/app/UI/NumericUpDownWithUnit.cs b/app/UI/NumericUpDownWithUnit.cs new file mode 100644 index 00000000..a521937f --- /dev/null +++ b/app/UI/NumericUpDownWithUnit.cs @@ -0,0 +1,141 @@ +using System.Globalization; +using System.Text.RegularExpressions; + +public class NumericUpDownWithUnit : NumericUpDown +{ + #region| Fields | + + private string unit = null; + private bool unitFirst = false; + + #endregion + + #region| Properties | + + public string Unit + { + get => unit; + set + { + unit = value; + + UpdateEditText(); + } + } + + public bool UnitFirst + { + get => unitFirst; + set + { + unitFirst = value; + + UpdateEditText(); + } + } + + #endregion + + #region| Methods | + + /// + /// Method called when updating the numeric updown text. + /// + protected override void UpdateEditText() + { + // If there is a unit we handle it ourselfs, if there is not we leave it to the base class. + if (Unit != null && Unit != string.Empty) + { + if (UnitFirst) + { + Text = $"({Unit}) {Value}"; + } + else + { + Text = $"{Value} ({Unit})"; + } + } + else + { + base.UpdateEditText(); + } + } + + /// + /// Validate method called before actually updating the text. + /// This is exactly the same as the base class but it will use the new ParseEditText from this class instead. + /// + protected override void ValidateEditText() + { + // See if the edit text parses to a valid decimal considering the label unit + ParseEditText(); + UpdateEditText(); + } + + /// + /// Converts the text displayed in the up-down control to a numeric value and evaluates it. + /// + protected new void ParseEditText() + { + try + { + // The only difference of this methods to the base one is that text is replaced directly + // with the property Text instead of using the regex. + // We now that the only characters that may be on the textbox are from the unit we provide. + // because the NumericUpDown handles invalid input from user for us. + // This is where the magic happens. This regex will match all characters from the unit + // (so your unit cannot have numbers). You can change this regex to fill your needs + var regex = new Regex($@"[^(?!{Unit} )]+"); + var match = regex.Match(Text); + + if (match.Success) + { + var text = match.Value; + + // VSWhidbey 173332: Verify that the user is not starting the string with a "-" + // before attempting to set the Value property since a "-" is a valid character with + // which to start a string representing a negative number. + if (!string.IsNullOrEmpty(text) && !(text.Length == 1 && text == "-")) + { + if (Hexadecimal) + { + Value = Constrain(Convert.ToDecimal(Convert.ToInt32(Text, 16))); + } + else + { + Value = Constrain(Decimal.Parse(text, CultureInfo.CurrentCulture)); + } + } + } + } + catch + { + // Leave value as it is + } + finally + { + UserEdit = false; + } + } + + /// + /// Returns the provided value constrained to be within the min and max. + /// This is exactly the same as the one in base class (which is private so we can't directly use it). + /// + private decimal Constrain(decimal value) + { + if (value < Minimum) + { + value = Minimum; + } + + if (value > Maximum) + { + value = Maximum; + } + + return value; + } + + #endregion +} \ No newline at end of file