using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Data; using System.Diagnostics; using System.Globalization; using System.Linq; using System.Security.Principal; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; namespace MaterialSkin.Controls { public partial class MaterialUpDown : UserControl,INotifyPropertyChanged { private double _value; private bool _mouseDown; private int _direction; public MaterialUpDown() { InitializeComponent(); textBox1.BackColor = SkinManager.GetApplicationBackgroundColor(); AllowDecimal = false; AllowKeyboard=true; } [Browsable(false)] public MaterialSkinManager SkinManager => MaterialSkinManager.Instance; public bool AllowDecimal { get; set; } public bool AllowKeyboard { get { return _allowKeyboard; } set { _allowKeyboard = value; textBox1.ReadOnly = !_allowKeyboard || _readOnly; } } public bool HideControls { get { return _hideControls; } set { _hideControls = value; materialIcon1.Visible = !value; materialIcon2.Visible = !value; } } public double Value { get { return _value; } set { _value = value; if (_value>Max) { _value = Max; } if (_value < Min) { _value = Min; } if (!AllowDecimal) { _value = Math.Floor(_value); } Action a = ()=> textBox1.Text = _value.ToString(); if (textBox1.InvokeRequired) textBox1.Invoke(a); else a(); } } public bool ReadOnly { get { return _readOnly; } set { _readOnly = value; materialIcon1.Enabled = !value; materialIcon2.Enabled = !value; textBox1.ReadOnly = !_allowKeyboard || _readOnly; } } public event PropertyChangedEventHandler PropertyChanged= delegate { }; public double Max { get; set; } public double Min { get; set; } public double Step { get; set; } protected override void OnPaintBackground(PaintEventArgs e) { e.Graphics.Clear(SkinManager.GetApplicationBackgroundColor()); } private void materialIcon2_Click(object sender, EventArgs e) { } private void materialIcon1_Click(object sender, EventArgs e) { } private async void HoldCountDown(CancellationToken cancellationSourceToken) { await Task.Delay(500); var startTime = DateTime.Now; while (_mouseDown&&!cancellationSourceToken.IsCancellationRequested) { Value += Step*_direction; await Task.Delay(100/(int)Math.Max(1,Math.Min(5,(DateTime.Now-startTime).TotalSeconds))); } } private CancellationTokenSource _cancellationSource; private bool _readOnly; private bool _allowKeyboard; private void materialIcon2_MouseDown(object sender, MouseEventArgs e) { _cancellationSource =new CancellationTokenSource(); Value += Step; _mouseDown = true; _direction = 1; Task.Run(()=> HoldCountDown(_cancellationSource.Token)); } private void materialIcon2_MouseUp(object sender, MouseEventArgs e) { if (_cancellationSource != null) { _cancellationSource.Cancel(); _cancellationSource = null; } _mouseDown = false; PropertyChanged(this,new PropertyChangedEventArgs(nameof(Value))); } private void materialIcon1_MouseDown(object sender, MouseEventArgs e) { _cancellationSource = new CancellationTokenSource(); Value -= Step; _mouseDown = true; _direction = -1; Task.Run(() => HoldCountDown(_cancellationSource.Token)); } private void materialIcon1_MouseUp(object sender, MouseEventArgs e) { if (_cancellationSource != null) { _cancellationSource.Cancel(); _cancellationSource = null; } _mouseDown = false; PropertyChanged(this, new PropertyChangedEventArgs(nameof(Value))); } private void materialIcon2_MouseLeave(object sender, EventArgs e) { materialIcon2_MouseUp(null,null); } private void materialIcon1_MouseLeave(object sender, EventArgs e) { materialIcon1_MouseUp(null, null); } private void textBox1_KeyPress(object sender, KeyPressEventArgs e) { if (!char.IsControl(e.KeyChar) && !char.IsDigit(e.KeyChar) && (e.KeyChar != '.')) { e.Handled = true; return; } // only allow one decimal point if ((e.KeyChar == '.') && ((sender as TextBox).Text.IndexOf('.') > -1)) { e.Handled = true; return; } _validate = true; } private CancellationTokenSource _cancellationTokenSource = null; private bool _validate; private bool _hideControls; private void textBox1_Click(object sender, EventArgs e) { if (textBox1.ReadOnly) return; textBox1.SelectAll(); } private void textBox1_TextChanged(object sender, EventArgs e) { } private void textBox1_Leave(object sender, EventArgs e) { if (double.TryParse((sender as TextBox).Text, NumberStyles.AllowDecimalPoint, CultureInfo.GetCultureInfo("en-us"), out var value)) { if (_cancellationTokenSource != null) _cancellationTokenSource.Cancel(); _cancellationTokenSource = new CancellationTokenSource(); Task.Run(async () => { var newValue = value; var token = _cancellationTokenSource.Token; if (token.IsCancellationRequested) throw new OperationCanceledException(); Value = newValue; PropertyChanged(this, new PropertyChangedEventArgs(nameof(Value))); }); } } private void textBox1_KeyDown(object sender, KeyEventArgs e) { if (e.KeyCode == Keys.Enter) { textBox1_Leave(textBox1,null); e.Handled = true; } } } }