-
Notifications
You must be signed in to change notification settings - Fork 0
/
AdvancedNumericBox.cs
199 lines (177 loc) · 7.37 KB
/
AdvancedNumericBox.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using static System.Windows.Forms.VisualStyles.VisualStyleElement;
namespace UserControlTesterProject
{
public partial class AdvancedNumericBox : UserControl
{
private double ActualValue;
/// <summary>
/// Use the required format specifier string. The default is "G":
/// https://learn.microsoft.com/en-us/dotnet/standard/base-types/standard-numeric-format-strings#GFormatString.
/// Use Precision specifier if required, for example scientific notation "E" has a default of 6 precision.
/// If you need less or more, you can change this like "E3" for example (in this case the 3rd digit will be rounded).
/// </summary>
[Description("Use the required format specifier string.")]
public string NumberFormatSpecifier { get; set; } = "G";
public double MinimumValue { get; private set; } = double.MinValue;
public double MaximumValue { get; private set; } = double.MaxValue;
/// <summary>
/// If false, out of range values will be ignored. If true, value will be coerced to actual min or max limit.
/// Default is false.
/// </summary>
[Description("If false, out of range values will be ignored. If true, value will be coerced to actual MinimumValue or MaximumValue limit.")]
public bool CoerceOutOfRange { get; set; } = false;
/// <summary>
/// Color used to indicate edit mode of the control. Default is Color.LightBlue.
/// </summary>
public Color ValidatingColor { get; set; } = Color.LightBlue;
[Browsable(true)]
[Category("Action")]
[Description("Invoked when Enter key is released")]
public event EventHandler EnterKeyUpCustom;
[Browsable(true)]
[Category("Action")]
[Description("Invoked when the focus is lost")]
public event EventHandler FocusLostCustom;
[Browsable(true)]
[Category("Action")]
[Description("Invoked when input was not parsable as a number")]
public event EventHandler InvalidInput;
[Browsable(true)]
[Category("Action")]
[Description("Invoked when input is out of range")]
public event EventHandler OutOfRange;
public AdvancedNumericBox()
{
InitializeComponent();
SetValue(0);
textBox.BackColor = SystemColors.Window;
}
/// <summary>
/// Sets the minimum limit of the accepted input range. If actual value is below the new limit, we set it to the new limit.
/// </summary>
/// <param name="minLimit">Requested new minimum limit.</param>
public void SetMinimum(double minLimit)
{
if (ActualValue < minLimit)
{
ActualValue = minLimit;
textBox.Text = ActualValue.ToString(NumberFormatSpecifier, CultureInfo.InvariantCulture);
textBox.BackColor = SystemColors.Window;
}
MinimumValue = minLimit;
}
/// <summary>
/// Sets the maximum limit of the accepted input range. If actual value is above the new limit, we set it to the new limit.
/// </summary>
/// <param name="maxLimit">Requested new minimum limit.</param>
public void SetMaximum(double maxLimit)
{
if (ActualValue > maxLimit)
{
ActualValue = maxLimit;
textBox.Text = ActualValue.ToString(NumberFormatSpecifier, CultureInfo.InvariantCulture);
textBox.BackColor = SystemColors.Window;
}
MaximumValue = maxLimit;
}
/// <summary>
/// Use this to programmatically set the value of the user control.
/// </summary>
/// <param name="newVal"></param>
public void SetValue(double newVal)
{
if (newVal > MaximumValue)
{
if (CoerceOutOfRange) ActualValue = MaximumValue;
OutOfRange?.Invoke(this, null);
}
else if (newVal < MinimumValue)
{
if (CoerceOutOfRange) ActualValue = MinimumValue;
OutOfRange?.Invoke(this, null);
}
else ActualValue = newVal;
textBox.Text = ActualValue.ToString(NumberFormatSpecifier, CultureInfo.InvariantCulture);
textBox.BackColor = SystemColors.Window;
}
/// <summary>
/// Get the double value the user control currently holds.
/// </summary>
/// <returns></returns>
public double GetValue()
{
return ActualValue;
}
public void EnableToolTip(string text)
{
toolTip1.SetToolTip(textBox, text);
}
public void DisableToolTip()
{
toolTip1.RemoveAll();
}
private void textBox_KeyUp(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
if (double.TryParse(textBox.Text, NumberStyles.Any, CultureInfo.InvariantCulture, out double newVal))
{
if (newVal > MaximumValue)
{
if (CoerceOutOfRange) ActualValue = MaximumValue;
OutOfRange?.Invoke(this, null);
}
else if (newVal < MinimumValue)
{
if (CoerceOutOfRange) ActualValue = MinimumValue;
OutOfRange?.Invoke(this, null);
}
else ActualValue = newVal;
}
else InvalidInput?.Invoke(this, e);
EnterKeyUpCustom?.Invoke(this, e);
textBox.Text = ActualValue.ToString(NumberFormatSpecifier, CultureInfo.InvariantCulture);
textBox.BackColor = SystemColors.Window;
}
}
private void textBox_Leave(object sender, EventArgs e)
{
if (double.TryParse(textBox.Text, NumberStyles.Any, CultureInfo.InvariantCulture, out double newVal))
{
if (newVal > MaximumValue)
{
if (CoerceOutOfRange) ActualValue = MaximumValue;
OutOfRange?.Invoke(this, null);
}
else if (newVal < MinimumValue)
{
if (CoerceOutOfRange) ActualValue = MinimumValue;
OutOfRange?.Invoke(this, null);
}
else ActualValue = newVal;
}
else InvalidInput?.Invoke(this, e);
FocusLostCustom?.Invoke(this, e);
textBox.Text = ActualValue.ToString(NumberFormatSpecifier, CultureInfo.InvariantCulture);
textBox.BackColor = SystemColors.Window;
}
private void textBox_Enter(object sender, EventArgs e)
{
textBox.BackColor = ValidatingColor;
}
private void textBox_TextChanged(object sender, EventArgs e)
{
textBox.BackColor = ValidatingColor;
}
}
}