Mesen-X/GUI.NET/Controls/MesenNumericUpDown.cs
2020-04-13 11:21:34 -04:00

323 lines
9.3 KiB
C#

using Mesen.GUI.Utilities;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Mesen.GUI.Controls
{
class MesenNumericUpDown : BaseControl
{
private TextBox txtValue;
private Button btnUp;
private Button btnDown;
private Panel pnlButtons;
private Timer tmrRepeat;
private int _repeatCount = 0;
private bool _repeatIncrease = false;
private bool _preventClick = false;
public event EventHandler ValueChanged;
public MesenNumericUpDown()
{
InitializeComponent();
if(!IsDesignMode) {
this.BackColor = SystemColors.ControlLightLight;
this.MaximumSize = new Size(10000, 21);
this.MinimumSize = new Size(0, 21);
this.Size = new Size(62, 21);
this.btnDown.Image = ThemeHelper.IsDark ? Properties.Resources.NudDownArrowDarkTheme : Properties.Resources.NudDownArrow;
this.btnUp.Image = ThemeHelper.IsDark ? Properties.Resources.NudUpArrowDarkTheme : Properties.Resources.NudUpArrow;
if(Program.IsMono) {
this.BorderStyle = BorderStyle.None;
this.txtValue.Dock = DockStyle.Fill;
this.txtValue.Multiline = true;
this.btnUp.Location = new Point(-1, 0);
this.btnDown.Location = new Point(-1, 10);
this.MinimumSize = new Size(0, 22);
} else {
this.BorderStyle = BorderStyle.FixedSingle;
}
}
}
private void tmrRepeat_Tick(object sender, EventArgs e)
{
tmrRepeat.Interval = _repeatCount > 5 ? 75 : 200;
if(_repeatIncrease) {
this.Value += this.Increment;
} else {
this.Value -= this.Increment;
}
_repeatCount++;
_preventClick = true;
}
private void btn_MouseDown(object sender, MouseEventArgs e)
{
_repeatCount = 0;
_repeatIncrease = (sender == btnUp);
tmrRepeat.Start();
}
private void btn_MouseUp(object sender, MouseEventArgs e)
{
tmrRepeat.Stop();
}
private void btnDown_Click(object sender, EventArgs e)
{
if(!_preventClick) {
this.Value -= this.Increment;
}
_preventClick = false;
}
private void btnUp_Click(object sender, EventArgs e)
{
if(!_preventClick) {
this.Value += this.Increment;
}
_preventClick = false;
}
private void txtValue_TextChanged(object sender, EventArgs e)
{
decimal val;
int hexVal;
if(string.IsNullOrWhiteSpace(txtValue.Text)) {
SetValue(0, false);
} else if(!IsHex && decimal.TryParse(txtValue.Text, out val)) {
SetValue(val, false);
} else if(IsHex && int.TryParse(txtValue.Text, System.Globalization.NumberStyles.HexNumber, null, out hexVal)) {
SetValue(hexVal, false);
}
}
private void txtValue_Validated(object sender, EventArgs e)
{
decimal val;
int hexVal;
if(string.IsNullOrWhiteSpace(txtValue.Text)) {
SetValue(0, true);
} else if(!IsHex && decimal.TryParse(txtValue.Text, out val)) {
SetValue(val, true);
} else if(IsHex && int.TryParse(txtValue.Text, System.Globalization.NumberStyles.HexNumber, null, out hexVal)) {
SetValue(hexVal, true);
} else {
SetValue(this.Value, true);
}
}
private void SetValue(decimal value, bool updateText)
{
value = decimal.Round(value, this.DecimalPlaces);
if(value > Maximum) {
value = Maximum;
}
if(value < Minimum) {
value = Minimum;
}
if(value != _value) {
_value = value;
ValueChanged?.Invoke(this, EventArgs.Empty);
}
if(updateText) {
txtValue.TextChanged -= txtValue_TextChanged;
if(IsHex) {
txtValue.Text = ((int)_value).ToString("X");
} else {
txtValue.Text = _value.ToString("0" + (this.DecimalPlaces > 0 ? "." : "") + new string('0', this.DecimalPlaces));
}
txtValue.TextChanged += txtValue_TextChanged;
}
}
private decimal _value = 0;
public decimal Value
{
get { return _value; }
set
{
SetValue(value, true);
}
}
public bool IsHex { get; set; } = false;
public new string Text
{
get { return txtValue.Text; }
set { txtValue.Text = value; }
}
private decimal _maximum = 100;
public decimal Maximum
{
get { return _maximum; }
set { _maximum = value; SetValue(this.Value, true); }
}
private decimal _minimum = 0;
public decimal Minimum
{
get { return _minimum; }
set { _minimum = value; SetValue(this.Value, true); }
}
public decimal Increment { get; set; } = 1;
private int _decimalPlaces = 0;
public int DecimalPlaces
{
get { return _decimalPlaces; }
set { _decimalPlaces = value; }
}
protected override void OnSizeChanged(EventArgs e)
{
base.OnSizeChanged(e);
if(this.Height < 21) {
this.Height = 21;
}
double scale = (double)this.Height / 21;
if(scale > 1) {
btnDown.Image = Properties.Resources.NudDownArrow.GetScaledImage(scale);
btnUp.Image = Properties.Resources.NudUpArrow.GetScaledImage(scale);
}
}
private void txtValue_KeyDown(object sender, KeyEventArgs e)
{
if(e.KeyCode == Keys.Up) {
this.Value += this.Increment;
e.SuppressKeyPress = true;
} else if(e.KeyCode == Keys.Down) {
this.Value -= this.Increment;
e.SuppressKeyPress = true;
} else if(
!((e.KeyCode >= Keys.D0 && e.KeyCode <= Keys.D9) ||
(e.KeyCode >= Keys.NumPad0 && e.KeyCode <= Keys.NumPad9) ||
e.KeyCode == Keys.OemPeriod || e.KeyCode == Keys.Oemcomma ||
e.KeyCode == Keys.Delete || e.KeyCode == Keys.Left ||
e.KeyCode == Keys.Right || e.KeyCode == Keys.Home ||
e.KeyCode == Keys.End || e.KeyCode == Keys.Back)
) {
if(IsHex && e.KeyCode >= Keys.A && e.KeyCode <= Keys.F) {
//Allow A-F when in hex mode
return;
}
e.SuppressKeyPress = true;
}
}
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.txtValue = new System.Windows.Forms.TextBox();
this.btnUp = new System.Windows.Forms.Button();
this.btnDown = new System.Windows.Forms.Button();
this.pnlButtons = new System.Windows.Forms.Panel();
this.pnlButtons.SuspendLayout();
this.SuspendLayout();
//
// txtValue
//
this.txtValue.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right)));
this.txtValue.BorderStyle = System.Windows.Forms.BorderStyle.None;
this.txtValue.Location = new System.Drawing.Point(1, 3);
this.txtValue.Margin = new System.Windows.Forms.Padding(0);
this.txtValue.Name = "txtValue";
this.txtValue.Size = new System.Drawing.Size(44, 13);
this.txtValue.TabIndex = 0;
this.txtValue.TextChanged += new System.EventHandler(this.txtValue_TextChanged);
this.txtValue.KeyDown += new System.Windows.Forms.KeyEventHandler(this.txtValue_KeyDown);
this.txtValue.Validated += new System.EventHandler(this.txtValue_Validated);
//
// btnUp
//
this.btnUp.Location = new System.Drawing.Point(1, -1);
this.btnUp.Margin = new System.Windows.Forms.Padding(0);
this.btnUp.Name = "btnUp";
this.btnUp.Size = new System.Drawing.Size(15, 11);
this.btnUp.TabIndex = 2;
this.btnUp.TabStop = false;
this.btnUp.UseVisualStyleBackColor = true;
this.btnUp.Click += new System.EventHandler(this.btnUp_Click);
this.btnUp.MouseDown += new System.Windows.Forms.MouseEventHandler(this.btn_MouseDown);
this.btnUp.MouseUp += new System.Windows.Forms.MouseEventHandler(this.btn_MouseUp);
//
// btnDown
//
this.btnDown.Location = new System.Drawing.Point(1, 9);
this.btnDown.Margin = new System.Windows.Forms.Padding(0);
this.btnDown.Name = "btnDown";
this.btnDown.Size = new System.Drawing.Size(15, 11);
this.btnDown.TabIndex = 3;
this.btnDown.TabStop = false;
this.btnDown.UseVisualStyleBackColor = true;
this.btnDown.Click += new System.EventHandler(this.btnDown_Click);
this.btnDown.MouseDown += new System.Windows.Forms.MouseEventHandler(this.btn_MouseDown);
this.btnDown.MouseUp += new System.Windows.Forms.MouseEventHandler(this.btn_MouseUp);
//
// pnlButtons
//
this.pnlButtons.Controls.Add(this.btnDown);
this.pnlButtons.Controls.Add(this.btnUp);
this.pnlButtons.Dock = System.Windows.Forms.DockStyle.Right;
this.pnlButtons.Location = new System.Drawing.Point(47, 0);
this.pnlButtons.Margin = new System.Windows.Forms.Padding(0);
this.pnlButtons.Name = "pnlButtons";
this.pnlButtons.Size = new System.Drawing.Size(15, 21);
this.pnlButtons.TabIndex = 1;
//
// tmrRepeat
//
this.tmrRepeat = new Timer(components);
this.tmrRepeat.Tick += tmrRepeat_Tick;
//
// MesenNumericUpDown
//
this.Controls.Add(this.txtValue);
this.Controls.Add(this.pnlButtons);
this.MaximumSize = new System.Drawing.Size(10000, 21);
this.MinimumSize = new System.Drawing.Size(0, 21);
this.Name = "MesenNumericUpDown";
this.Size = new System.Drawing.Size(62, 21);
this.pnlButtons.ResumeLayout(false);
this.ResumeLayout(false);
this.PerformLayout();
}
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if(disposing && (components != null)) {
components.Dispose();
}
base.Dispose(disposing);
}
}
}