1 // Permission is hereby granted, free of charge, to any person obtaining
2 // a copy of this software and associated documentation files (the
3 // "Software"), to deal in the Software without restriction, including
4 // without limitation the rights to use, copy, modify, merge, publish,
5 // distribute, sublicense, and/or sell copies of the Software, and to
6 // permit persons to whom the Software is furnished to do so, subject to
7 // the following conditions:
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
12 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
14 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
16 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
17 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
18 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 // Copyright (c) 2005 Novell, Inc.
23 // Jonathan Gilbert <logic@deltaq.org>
25 // Integration into MWF:
26 // Peter Bartok <pbartok@novell.com>
30 using System
.Collections
;
31 using System
.ComponentModel
;
33 using System
.Globalization
;
34 using System
.Runtime
.InteropServices
;
36 using System
.Windows
.Forms
;
38 namespace System
.Windows
.Forms
{
39 [DefaultEvent("ValueChanged")]
40 [DefaultProperty("Value")]
41 [DefaultBindingProperty ("Value")]
42 [ClassInterface (ClassInterfaceType
.AutoDispatch
)]
44 public class NumericUpDown
: UpDownBase
, ISupportInitialize
{
45 #region Local Variables
46 private bool suppress_validation
;
47 private int decimal_places
;
48 private bool hexadecimal
;
49 private decimal increment
;
50 private decimal maximum
;
51 private decimal minimum
;
52 private bool thousands_separator
;
53 private decimal dvalue
;
56 NumericUpDownAccelerationCollection accelerations
;
57 // private long buttonPressedTicks;
58 //private bool isSpinning;
59 #endregion // Local Variables
61 #region UIA FrameWork Events
62 static object UIAMinimumChangedEvent
= new object ();
64 internal event EventHandler UIAMinimumChanged
{
65 add { Events.AddHandler (UIAMinimumChangedEvent, value); }
66 remove { Events.RemoveHandler (UIAMinimumChangedEvent, value); }
69 internal void OnUIAMinimumChanged (EventArgs e
)
71 EventHandler eh
= (EventHandler
) Events
[UIAMinimumChangedEvent
];
76 static object UIAMaximumChangedEvent
= new object ();
78 internal event EventHandler UIAMaximumChanged
{
79 add { Events.AddHandler (UIAMaximumChangedEvent, value); }
80 remove { Events.RemoveHandler (UIAMaximumChangedEvent, value); }
83 internal void OnUIAMaximumChanged (EventArgs e
)
85 EventHandler eh
= (EventHandler
) Events
[UIAMaximumChangedEvent
];
90 static object UIASmallChangeChangedEvent
= new object ();
92 internal event EventHandler UIASmallChangeChanged
{
93 add { Events.AddHandler (UIASmallChangeChangedEvent, value); }
94 remove { Events.RemoveHandler (UIASmallChangeChangedEvent, value); }
97 internal void OnUIASmallChangeChanged (EventArgs e
)
99 EventHandler eh
= (EventHandler
) Events
[UIASmallChangeChangedEvent
];
105 #region Public Constructors
106 public NumericUpDown() {
107 suppress_validation
= false;
113 thousands_separator
= false;
117 #endregion // Public Constructors
119 #region Public Instance Properties
122 [DesignerSerializationVisibility (DesignerSerializationVisibility
.Hidden
)]
123 public NumericUpDownAccelerationCollection Accelerations
{
125 if (accelerations
== null)
126 accelerations
= new NumericUpDownAccelerationCollection ();
127 return accelerations
;
132 public int DecimalPlaces
{
134 return decimal_places
;
138 decimal_places
= value;
143 [DefaultValue(false)]
144 public bool Hexadecimal
{
155 public decimal Increment
{
163 throw new ArgumentOutOfRangeException("value", value, "NumericUpDown increment cannot be negative");
168 // UIA Framework Event: SmallChange Changed
169 OnUIASmallChangeChanged (EventArgs
.Empty
);
173 [RefreshProperties(RefreshProperties
.All
)]
174 public decimal Maximum
{
182 if (minimum
> maximum
)
185 if (dvalue
> maximum
)
188 // UIA Framework Event: Maximum Changed
189 OnUIAMaximumChanged (EventArgs
.Empty
);
193 [RefreshProperties(RefreshProperties
.All
)]
194 public decimal Minimum
{
202 if (maximum
< minimum
)
205 if (dvalue
< minimum
)
208 // UIA Framework Event: Minimum Changed
209 OnUIAMinimumChanged (EventArgs
.Empty
);
214 [EditorBrowsable (EditorBrowsableState
.Never
)]
215 [DesignerSerializationVisibility (DesignerSerializationVisibility
.Hidden
)]
216 public new Padding Padding
{
217 get { return Padding.Empty; }
223 [DesignerSerializationVisibility(DesignerSerializationVisibility
.Hidden
)]
224 [EditorBrowsable(EditorBrowsableState
.Never
)]
225 public override string Text
{
235 [DefaultValue(false)]
237 public bool ThousandsSeparator
{
239 return thousands_separator
;
243 thousands_separator
= value;
249 public decimal Value
{
257 if (value != dvalue
) {
258 if (!suppress_validation
&& ((value < minimum
) || (value > maximum
))) {
259 throw new ArgumentOutOfRangeException ("value", "NumericUpDown.Value must be within the specified Minimum and Maximum values");
263 OnValueChanged (EventArgs
.Empty
);
268 #endregion // Public Instance Properties
270 #region Public Instance Methods
271 public void BeginInit() {
272 suppress_validation
= true;
275 public void EndInit() {
276 suppress_validation
= false;
277 Value
= Check (dvalue
);
281 public override string ToString() {
282 return string.Format("{0}, Minimum = {1}, Maximum = {2}", base.ToString(), minimum
, maximum
);
285 public override void DownButton() {
290 Value
= Math
.Max (minimum
, unchecked (dvalue
- increment
));
292 // UIA Framework Event: DownButton Click
293 OnUIADownButtonClick (EventArgs
.Empty
);
296 public override void UpButton() {
301 Value
= Math
.Min (maximum
, unchecked (dvalue
+ increment
));
303 // UIA Framework Event: UpButton Click
304 OnUIAUpButtonClick (EventArgs
.Empty
);
306 #endregion // Public Instance Methods
308 #region Protected Instance Methods
309 protected override AccessibleObject
CreateAccessibilityInstance() {
310 AccessibleObject acc
;
312 acc
= new AccessibleObject(this);
313 acc
.role
= AccessibleRole
.SpinButton
;
318 protected override void OnTextBoxKeyPress(object source
, KeyPressEventArgs e
) {
319 if ((ModifierKeys
& ~Keys
.Shift
) != Keys
.None
) {
323 NumberFormatInfo nfi
= CultureInfo
.CurrentCulture
.NumberFormat
;
324 string pressedKey
= e
.KeyChar
.ToString ();
326 if ((pressedKey
!= nfi
.NegativeSign
) && (pressedKey
!= nfi
.NumberDecimalSeparator
) &&
327 (pressedKey
!= nfi
.NumberGroupSeparator
)) {
328 string acceptable
= hexadecimal
? "\b0123456789abcdefABCDEF" : "\b0123456789";
329 if (acceptable
.IndexOf (e
.KeyChar
) == -1) {
330 // FIXME: produce beep to signal that "invalid" key was pressed
331 // prevent the key from reaching the text box
336 base.OnTextBoxKeyPress(source
, e
);
339 protected virtual void OnValueChanged(EventArgs e
) {
340 EventHandler eh
= (EventHandler
)(Events
[ValueChangedEvent
]);
345 protected void ParseEditText () {
348 Value
= Check (decimal.Parse (Text
, CultureInfo
.CurrentCulture
));
350 Value
= Check (Convert
.ToDecimal (Convert
.ToInt32 (Text
, 16)));
359 private decimal Check (decimal val
)
373 protected override void UpdateEditText () {
374 if (suppress_validation
)
382 // "N" and "F" differ only in that "N" includes commas
383 // every 3 digits to the left of the decimal and "F"
386 string format_string
;
388 if (thousands_separator
) {
394 format_string
+= decimal_places
;
396 Text
= dvalue
.ToString (format_string
, CultureInfo
.CurrentCulture
);
399 // Cast to Int64 to be able to use the "X" formatter.
400 // If the value is below Int64.MinValue or above Int64.MaxValue,
401 // then an OverflowException will be thrown, as with .NET.
402 Text
= ((Int64
)dvalue
).ToString("X", CultureInfo
.CurrentCulture
);
407 protected override void ValidateEditText() {
412 protected override void OnLostFocus(EventArgs e
) {
418 protected override void OnKeyUp (KeyEventArgs e
)
420 // isSpinning = false;
424 protected override void OnKeyDown (KeyEventArgs e
)
426 // buttonPressedTicks = DateTime.Now.Ticks;
427 // isSpinning = true;
430 #endregion // Protected Instance Methods
434 [EditorBrowsable (EditorBrowsableState
.Never
)]
435 public new event EventHandler PaddingChanged
{
436 add { base.PaddingChanged += value; }
437 remove { base.PaddingChanged -= value; }
440 static object ValueChangedEvent
= new object ();
442 public event EventHandler ValueChanged
{
443 add { Events.AddHandler (ValueChangedEvent, value); }
444 remove { Events.RemoveHandler (ValueChangedEvent, value); }
448 [EditorBrowsable(EditorBrowsableState
.Never
)]
449 public new event EventHandler TextChanged
{
450 add { base.TextChanged += value; }
451 remove { base.TextChanged -= value; }