Skip to content

Commit

Permalink
ScientificNumericUpDown - make it great, make it bugless, use it ever…
Browse files Browse the repository at this point in the history
…ywhere (resolved issue #34)
  • Loading branch information
PawelTroka committed Mar 18, 2017
1 parent ff56b69 commit e98cf71
Show file tree
Hide file tree
Showing 6 changed files with 133 additions and 171 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ private void _view_ComputeClicked(object sender, EventArgs e)
_errorHandler.DisplayError(Strings.GivenΕIsNotValid, Strings.Error);
return;
}
if (!(eps > 0.0) || !(eps < 1))
if (!(eps > 0.0) || !(eps <= 1))
{
_errorHandler.DisplayError(
Strings.GivenΕIsNotValidΕShouldBeSmallPositiveNumber, Strings.Error);
Expand Down
158 changes: 103 additions & 55 deletions Computator.NET/Controls/ScientificNumericUpDown.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
using System.Drawing;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using Computator.NET.Core.Evaluation;
Expand All @@ -17,7 +16,25 @@ namespace Computator.NET.Controls
{
public sealed partial class ScientificNumericUpDown : NumericUpDown
{
private readonly int _multiplyFactor = 10;
public enum UpDownBehavior
{
/// <summary>
/// Depending on <see cref="Value"/> essentially uses scaling <see cref="Increment"/> property for small values and <see cref="Multiplication"/> mode for larger ones.
/// </summary>
Adaptive,
/// <summary>
/// Simplest mode known from basic NumericUpDown. Uses <see cref="Increment"/> property to increase or decrease by adding or subtracting it from <see cref="Value"/>.
/// </summary>
Addition,
/// <summary>
/// Common mode for values in exponential notation. Uses <see cref="MultiplyFactor"/> property to multiply or divide <see cref="Value"/>.
/// </summary>
Multiplication,
}

public UpDownBehavior UpDownMode { get; set; }

public decimal MultiplyFactor { get; set; } = 10;

private const string Exponents = "⁰¹²³⁴⁵⁶⁷⁸⁹⁻";
private const string ToReplace = "0123456789-";
Expand All @@ -28,25 +45,26 @@ public ScientificNumericUpDown()

if (!DesignMode)
{
Minimum = decimal.MinValue / 10;
Maximum = decimal.MaxValue / 10;
Minimum = -(decimal)(1e28);
Maximum = (decimal)(1e28);


TextAlign = HorizontalAlignment.Center;
Font = base.Font;

ValueChanged += (o, e) =>
{
if (!ExponentialMode)
if (UpDownMode==UpDownBehavior.Adaptive && !IsExponent)
Increment = Math.Max(Epsilon,
Math.Abs((0.3m * Value).RoundToSignificantDigits(1)));
//if (Increment == 0)
//Increment = 1;
};
}
}



/// <summary>
/// Closest to 0 value allowed. Anything closer to 0 than this value will become 0.
/// </summary>
public decimal Epsilon { get; set; } = 0.001m;

public new decimal Value
Expand All @@ -72,8 +90,8 @@ public ScientificNumericUpDown()
set { base.Font = !DesignMode ? CustomFonts.GetMathFont(value.Size) : value; }
}

public bool ExponentialMode => ((double)Value).ToString(CultureInfo.InvariantCulture).Contains('E') ||
((double)Value).ToString(CultureInfo.InvariantCulture).Contains('e');
private bool IsExponent => ((double) Value).ToString(CultureInfo.InvariantCulture).Contains('E') ||
((double) Value).ToString(CultureInfo.InvariantCulture).Contains('e');


[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
Expand Down Expand Up @@ -113,34 +131,43 @@ protected override void OnTextBoxKeyPress(object source, KeyPressEventArgs e)
else if (e.KeyChar == '-' &&
!((IsCharOnLeftOfCaret('E') || IsCharOnLeftOfCaret('e')) && !IsCharOnRightOfCaret('-')) &&
!(CaretPosition == 0 && !Text.StartsWith("-")))
{
e.Handled = true;
}

else if (e.KeyChar == '*' && !Text.Contains(SpecialSymbols.DotSymbol))
{
e.KeyChar = SpecialSymbols.DotSymbol;
}
else if (!Text.Contains("e") && !Text.Contains("E") && (e.KeyChar == 'E' || e.KeyChar == 'e'))
{
// Text += dotSymbol + "10";
// e.Handled = true;
}
else if (!Text.Contains(".") && (e.KeyChar == ',' || e.KeyChar == '.' ||
e.KeyChar == Thread.CurrentThread.CurrentCulture.NumberFormat.NumberDecimalSeparator[0] ||
e.KeyChar == Thread.CurrentThread.CurrentUICulture.NumberFormat.NumberDecimalSeparator[0]))
e.KeyChar ==
Thread.CurrentThread.CurrentCulture.NumberFormat.NumberDecimalSeparator[0] ||
e.KeyChar ==
Thread.CurrentThread.CurrentUICulture.NumberFormat.NumberDecimalSeparator[0
]))
{
e.KeyChar = '.';
// //Text += '.';
// //e.Handled = true;
}
else if (Text.Contains(".") && (e.KeyChar == ',' || e.KeyChar == '.' ||
e.KeyChar ==
Thread.CurrentThread.CurrentCulture.NumberFormat.NumberDecimalSeparator[0] ||
e.KeyChar ==
Thread.CurrentThread.CurrentUICulture.NumberFormat.NumberDecimalSeparator[0
]))
e.KeyChar ==
Thread.CurrentThread.CurrentCulture.NumberFormat.NumberDecimalSeparator[0] ||
e.KeyChar ==
Thread.CurrentThread.CurrentUICulture.NumberFormat.NumberDecimalSeparator[0
]))
{
e.Handled = true;
}
else
{
base.OnTextBoxKeyPress(source, e);
}
}

private bool IsCharOnRightOfCaret(char v)
Expand Down Expand Up @@ -168,9 +195,7 @@ protected override void ValidateEditText() //basically it sets Value after Text
// which to start a string representing a negative number.
if (!string.IsNullOrEmpty(Text) &&
!(Text.Length == 1 && Text == "-"))
{
Value = Constrain(Text.FromMathString());
}
}
catch
{
Expand All @@ -185,81 +210,104 @@ protected override void ValidateEditText() //basically it sets Value after Text
}



private decimal Constrain(double value)
{
Debug.Assert(Minimum <= Maximum,
"minimum > maximum");
"minimum > maximum");

if (value < (double)Minimum)
{
if (value < (double) Minimum)
return Minimum;
}

if (value > (double)Maximum)
{
if (value > (double) Maximum)
return Maximum;
}

return (decimal)value;
return (decimal) value;
}

private decimal Constrain(decimal value)
{

Debug.Assert(Minimum <= Maximum,
"minimum > maximum");
"minimum > maximum");

if (value < Minimum)
{
value = Minimum;
}

if (value > Maximum)
{
value = Maximum;
}

return value;
}


public override void UpButton()
{
if (!ExponentialMode)
switch (UpDownMode)
{
base.UpButton();
Value = Value.RoundToSignificantDigits(2);
//beware it's kind of experimental, 1 instead of two would give generally better results but wight have stopped progres in some cases like 0.001
case UpDownBehavior.Addition:
base.UpButton();
break;
case UpDownBehavior.Multiplication:
MultiplyUp();
break;
default:
if (!IsExponent)
{
base.UpButton();
Value = Value.RoundToSignificantDigits(2);
}
else
MultiplyUp();
break;
}
else
{
if (Value > 0)
Value = Constrain(Value * _multiplyFactor);
else if (Value < 0)
Value = Constrain(Value / _multiplyFactor);
}

//UpdateEditText();
private void MultiplyUp()
{
if (Value > 0)
{
if (decimal.MaxValue / MultiplyFactor >= Value)
Value = Constrain(Value * MultiplyFactor);
}
else if (Value < 0)
{
Value = Constrain(Value / MultiplyFactor);
}
}

public override void DownButton()
{
if (!ExponentialMode)
switch (UpDownMode)
{
base.DownButton();
Value = Value.RoundToSignificantDigits(2);
//beware it's kind of experimental, 1 instead of two would give generally better results but wight have stopped progres in some cases like 0.001
case UpDownBehavior.Addition:
base.DownButton();
break;
case UpDownBehavior.Multiplication:
MultiplyDown();
break;
default:
if (!IsExponent)
{
base.DownButton();
Value = Value.RoundToSignificantDigits(2);
//beware it's kind of experimental, 1 instead of two would give generally better results but wight have stopped progress in some cases like 0.001
}
else
MultiplyDown();
break;
}
else
}

private void MultiplyDown()
{
if (Value > 0)
Value = Constrain(Value / MultiplyFactor);
else if (Value < 0)
{
if (Value > 0)
Value = Constrain(Value / _multiplyFactor);
else if (Value < 0)
Value = Constrain(Value * _multiplyFactor);
//UpdateEditText();
if(decimal.MinValue/MultiplyFactor <= Value)
Value = Constrain(Value * MultiplyFactor);
}
}



protected override void UpdateEditText() //basically it sets Text after Value was established
Expand Down
32 changes: 6 additions & 26 deletions Computator.NET/Views/CalculationsView.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit e98cf71

Please sign in to comment.