math-suite/Source/Calculator/MainWindow.xaml.cs

379 lines
13 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace Calculator
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
enum Operator
{
None, Sum, Subtraction, Multiplication, Division, Mod, Logn, Pown, NRoot, Combinations, Arrangements
};
enum Stages
{
First, FirstDisplay, Second
};
#region Variables
double memory = 0;
bool is2ndOn = false, error = false;
double first = 0, second = 0;
Stages stage = Stages.First;
Operator oper = Operator.None;
Brush IndicatorColor = (Brushes.Orange);
#endregion
#region Properties
public bool Is2ndOn
{
get { return is2ndOn; }
set
{
is2ndOn = value;
Indicator2ndf.Background = (value) ? (IndicatorColor) : (Brushes.Transparent);
}
}
public bool Error
{
get { return error; }
set
{
error = value;
IndicatorError.Background = (value) ? (IndicatorColor) : (Brushes.Transparent);
}
}
public double DisplayValue
{
set { Display.Text = value.ToString(); }
get
{
double val;
string temp = Display.Text;
if (temp.EndsWith(".") || temp.Length == 0) temp += '0';
if (!Double.TryParse(temp, out val))
{
Error = true;
val = 0;
}
return val;
}
}
public string DisplayText
{
get { return Display.Text; }
set { Display.Text = value; }
}
public double Memory
{
get { return memory; }
set
{
memory = value;
IndicatorMem.Background = (value != 0) ? (IndicatorColor) : (Brushes.Transparent);
}
}
#endregion
#region Calculator logics
public MainWindow()
{
InitializeComponent();
}
void BinaryOperatorPressed(bool isEqual = false)
{
if (stage == Stages.First)
{
first = DisplayValue; stage = Stages.FirstDisplay;
}
else if (stage == Stages.Second)
{
second = DisplayValue;
DisplayValue = Calculate();
if (isEqual) stage = Stages.First;
else
{
first = DisplayValue;
stage = Stages.FirstDisplay;
}
}
}
double Calculate()
{
switch (oper)
{
case Operator.Sum: return first + second;
case Operator.Subtraction: return first - second;
case Operator.Multiplication: return first * second;
case Operator.Division: return first / second;
case Operator.Mod: return first % second;
case Operator.Logn: return Math.Log(first, second);
case Operator.Pown: return Math.Pow(first, second);
case Operator.NRoot: return Math.Pow(first, 1.0 / second);
case Operator.Combinations: return MathHelper.Combinations(first, second);
case Operator.Arrangements: return MathHelper.Arrangements(first, second);
}
return 0;
}
void AddDigit(char digit)
{
if (stage == Stages.FirstDisplay) { DisplayText = ""; stage = Stages.Second; }
DisplayText += digit;
}
void SetValue(double value)
{
if (stage == Stages.FirstDisplay) stage = Stages.Second;
DisplayValue = value;
}
private void Handle_Click(object sender, bool is2nd)
{
var s = sender as Button;
if (s == null) return;
is2nd = is2nd || Is2ndOn;
if (s.Name != "B2ndf") Is2ndOn = false;
double val = DisplayValue;
if (DisplayText == "0") DisplayText = "";
switch (s.Name)
{
// Column 1
case "B2ndf": Is2ndOn = !Is2ndOn; break;
case "BInt":
if (!is2nd) SetValue(Math.Floor(val));
else SetValue(val - Math.Floor(val));
break;
case "BSin":
if (!is2nd) SetValue(Math.Sin(val));
else SetValue(Math.Asin(val));
break;
case "BSinh":
if (!is2nd) SetValue(Math.Sinh(val));
else SetValue(Math.Log(val + Math.Sqrt(val * val + 1)));
break;
case "BPi":
if (!is2nd) SetValue(Math.PI);
else SetValue(2 * Math.PI);
break;
// Column 2
case "BLn":
if (!is2nd) SetValue(Math.Log(val));
else SetValue(Math.Exp(val));
break;
case "BAbs":
if (!is2nd) SetValue(Math.Abs(val));
else SetValue(-Math.Abs(val));
break;
case "BCos":
if (!is2nd) SetValue(Math.Cos(val));
else SetValue(Math.Acos(val));
break;
case "BCosh":
if (!is2nd) SetValue(Math.Cosh(val));
else SetValue(Math.Log(val + Math.Sqrt(val * val - 1)));
break;
case "BE": SetValue(Math.E); break;
// Column 3
case "BLog":
if (!is2nd) SetValue(Math.Log10(val));
else SetValue(Math.Pow(10, val));
break;
case "BInverse": SetValue(1 / val);
break;
case "BTan":
if (!is2nd) SetValue(Math.Tan(val));
else SetValue(Math.Atan(val));
break;
case "BTanh":
if (!is2nd) SetValue(Math.Tanh(val));
else SetValue(Math.Log((1+val) * (1-val))/2);
break;
case "BCombinations":
if (!is2nd) oper = Operator.Combinations;
else oper = Operator.Arrangements;
BinaryOperatorPressed();
break;
// Column 4
case "BLogn":
oper = Operator.Logn;
BinaryOperatorPressed();
break;
case "BPown":
if (!is2nd) oper = Operator.Pown;
else oper = Operator.NRoot;
BinaryOperatorPressed();
break;
case "BSquare":
if (!is2nd) SetValue(val * val);
else SetValue(Math.Pow(val, 1.0 / 2.0));
break;
case "BCube":
if (!is2nd) SetValue(val * val * val);
else SetValue(Math.Pow(val, 1.0 / 3.0));
break;
case "BFact":
SetValue(MathHelper.Factorial(val));
break;
// Memory operations
case "BMemAdd": Memory += val; break;
case "BMemSub": Memory -= val; break;
case "BMemClear": Memory = 0; break;
case "BMemSet": Memory = val; break;
case "BMemRecall": SetValue(Memory); break;
// Numbers
case "BNum7": AddDigit('7'); break;
case "BNum4": AddDigit('4'); break;
case "BNum1": AddDigit('1'); break;
case "BNum0": AddDigit('0'); break;
// Numbers
case "BNum8": AddDigit('8'); break;
case "BNum5": AddDigit('5'); break;
case "BNum2": AddDigit('2'); break;
// Numbers
case "BBackspace": if (DisplayText.Length >= 1) DisplayText = DisplayText.Substring(0, DisplayText.Length - 1); break;
case "BNum9": AddDigit('9'); break;
case "BNum6": AddDigit('6'); break;
case "BNum3": AddDigit('3'); break;
case "BPeriod": if (!DisplayText.Contains('.')) AddDigit('.'); break;
// Ops
case "BClear": SetValue(0); break;
case "BOpDivide": oper = Operator.Division; BinaryOperatorPressed(); break;
case "BOpMultiply": oper = Operator.Multiplication; BinaryOperatorPressed(); break;
case "BOpSub": oper = Operator.Subtraction; BinaryOperatorPressed(); break;
case "BOpAdd": oper = Operator.Sum; BinaryOperatorPressed(); break;
// Ops
case "BClearAC": stage = Stages.First; oper = Operator.None; DisplayValue = 0; break;
case "BOpMod": oper = Operator.Mod; BinaryOperatorPressed(); break;
case "BOpSign": SetValue(val * -1); break;
case "BEqual":
if (stage == Stages.Second) BinaryOperatorPressed(true);
break;
}
Error = (DisplayText == "NaN");
if (DisplayText == "") DisplayText = "0";
}
#endregion
#region User input
private void Button_Click(object sender, RoutedEventArgs e)
{
Handle_Click(sender, false);
}
private void Button_MouseUp(object sender, MouseButtonEventArgs e)
{
if (e.ChangedButton == MouseButton.Left) Handle_Click(sender, false);
else if (e.ChangedButton == MouseButton.Right) Handle_Click(sender, true);
}
private void Window_KeyDown(object sender, KeyEventArgs e)
{
e.Handled = true;
if (Keyboard.Modifiers == ModifierKeys.Shift) switch (e.Key)
{
case Key.D6: Handle_Click(BPown, false); break;
case Key.D8: Handle_Click(BOpMultiply, false); break;
case Key.D5: Handle_Click(BOpMod, false); break;
}
if (Keyboard.Modifiers == ModifierKeys.Control && e.Key == Key.Q)
this.Close();
else if (Keyboard.Modifiers == ModifierKeys.None) switch (e.Key)
{
// Numeric keys
case Key.D0:
case Key.NumPad0: Handle_Click(BNum0, false); break;
case Key.D1:
case Key.NumPad1: Handle_Click(BNum1, false); break;
case Key.D2:
case Key.NumPad2: Handle_Click(BNum2, false); break;
case Key.D3:
case Key.NumPad3: Handle_Click(BNum3, false); break;
case Key.D4:
case Key.NumPad4: Handle_Click(BNum4, false); break;
case Key.D5:
case Key.NumPad5: Handle_Click(BNum5, false); break;
case Key.D6:
case Key.NumPad6: Handle_Click(BNum6, false); break;
case Key.D7:
case Key.NumPad7: Handle_Click(BNum7, false); break;
case Key.D8:
case Key.NumPad8: Handle_Click(BNum8, false); break;
case Key.D9:
case Key.NumPad9: Handle_Click(BNum9, false); break;
case Key.OemPeriod:
case Key.Decimal: Handle_Click(BPeriod, false); break;
// Binary Operators
case Key.Add:
case Key.OemPlus: Handle_Click(BOpAdd, false); break;
case Key.Subtract:
case Key.OemMinus: Handle_Click(BOpSub, false); break;
case Key.Multiply: Handle_Click(BOpMultiply, false); break;
case Key.OemBackslash:
case Key.Divide: Handle_Click(BOpDivide, false); break;
// Others
case Key.Return: Handle_Click(BEqual, false); break;
case Key.Escape: Handle_Click(BClearAC, false); break;
case Key.Back: Handle_Click(BBackspace, false); break;
case Key.Delete: Handle_Click(BClear, false); break;
case Key.F1: BHelp_Click(this, new RoutedEventArgs()); break;
}
}
private void BHelp_Click(object sender, RoutedEventArgs e)
{
DynamicLink.Launcher.StartModule("Help", "Calculator");
}
#endregion
}
}