math-suite/Source/GraphingCalculator/Controls/EvaluateWindow.xaml.cs

217 lines
7.0 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.Shapes;
namespace GraphingCalculator
{
/// <summary>
/// Interaction logic for EvaluateWindow.xaml
/// </summary>
public partial class EvaluateWindow : Window
{
private Dictionary<string, double> variables = new Dictionary<string, double>();
#region Properties
public string InputExpression
{
get { return inputExpression.Text; }
set { inputExpression.Text = value; }
}
#endregion
#region Constructors
public EvaluateWindow()
{
InitializeComponent();
}
public EvaluateWindow(string txt)
{
InitializeComponent();
InputExpression = txt;
// Convenience: evaluate already
buttonEval_Click(this, new RoutedEventArgs());
}
#endregion
#region User input
private void buttonAdd_Click(object sender, RoutedEventArgs e)
{
string errorMessage = "";
double val = 0;
outputResult.Clear();
// Verify boxes are not empty
if (inputVarName.Text == "" || inputVarValue.Text == "")
errorMessage = "Name or value cannot be empty!";
// Get number
if (errorMessage == "" && !double.TryParse(inputVarValue.Text, out val))
{
try {
Expression expr = new Expression(inputVarValue.Text);
val = expr.Evaluate();
}
catch { errorMessage = "Value must be a number!"; }
}
// Verify name is unique
if (errorMessage == "" && variables.ContainsKey(inputVarName.Text))
{
var res = MessageBox.Show("A variable with the same name already exists. Replace it with the new value?", "Warning", MessageBoxButton.YesNo);
if (res != MessageBoxResult.Yes) errorMessage = "A variable with the same name already exists!";
}
// Verify name doesn't contain forbidden characters
if (errorMessage == "")
{
bool ok = char.IsLetter (inputVarName.Text.First());
foreach (var i in inputVarName.Text)
if (!char.IsLetterOrDigit(i)) ok = false;
if (!ok) errorMessage = "Forbidden variable name, it can only contain letters or digits!";
}
// Add variable
if (errorMessage == "")
{
variables[inputVarName.Text] = val;
// Remove if it exists already
for (int i = 0; i < listVars.Items.Count; i++)
{
string str = listVars.Items[i] as string;
if (str != null && str.StartsWith(inputVarName.Text + " = ")) listVars.Items.RemoveAt(i);
}
// Add variable
listVars.Items.Add(inputVarName.Text + " = " + inputVarValue.Text);
// Clear text boxes
inputVarName.Clear();
inputVarValue.Clear();
}
else
{
outputResult.Foreground = Brushes.DarkRed;
outputResult.Text = "Error adding variable: " + errorMessage;
}
}
private void buttonEval_Click(object sender, RoutedEventArgs e)
{
// Create expression
Expression expression = new Expression(inputExpression.Text);
double result = 0;
// Add variables
foreach (var i in variables)
expression.Variables.Add(i.Key, i.Value);
// Try to evaluate
try {
result = expression.Evaluate();
}
catch (Exception ex) {
outputResult.Text = "Error evaluating: " + ex.Message;
outputResult.Foreground = Brushes.DarkRed;
#region Log
Log.LogEvent("Failed to evaluate expression '{0}'. Message: {1}", inputExpression.Text, ex.Message);
Log.LogEvent("> Stack trace: {0}", ex.StackTrace);
if (listVars.Items.Count > 0) Log.LogEvent("> Variables: ");
foreach (var i in listVars.Items)
Log.LogEvent(">> {0}", i.ToString());
#endregion
return;
}
// Output results
outputResult.Text = Math.Round(result, 15).ToString();
outputResult.Foreground = Brushes.Black;
#region Log
// Log what happened here
Log.LogEvent("Evaluated expression '{0}' result={1}", inputExpression.Text, outputResult.Text);
if (listVars.Items.Count > 0) Log.LogEvent("> WHERE: ");
foreach (var i in listVars.Items)
Log.LogEvent(">> {0}", i.ToString());
#endregion
}
private void buttonClose_Click(object sender, RoutedEventArgs e)
{
this.Close();
}
private void contextEdit_Click(object sender, RoutedEventArgs e)
{
// Make sure we have 1 selected item
if (listVars.SelectedItems.Count != 1) return;
// Get key
var item = listVars.SelectedItem as string;
if (item == null) return;
string key = item.Substring(0, item.IndexOf(" = "));
// Place in input boxes
inputVarName.Text = key;
inputVarValue.Text = variables[key].ToString();
// Remove item
listVars.Items.Remove(listVars.SelectedItem);
variables.Remove(key);
}
private void contextDelete_Click(object sender, RoutedEventArgs e)
{
// Make sure we have 1 selected item
if (listVars.SelectedItems.Count != 1) return;
// Get key
var item = listVars.SelectedItem as string;
if (item == null) return;
string key = item.Substring(0, item.IndexOf(" = "));
// Remove
listVars.Items.Remove(listVars.SelectedItem);
variables.Remove(key);
}
private void contextClear_Click(object sender, RoutedEventArgs e)
{
listVars.Items.Clear();
variables.Clear();
}
private void Window_KeyUp(object sender, KeyEventArgs e)
{
e.Handled = true;
if (e.Key == Key.Escape) buttonClose_Click(this, new RoutedEventArgs());
else if (e.Key == Key.Enter) buttonEval_Click(this, new RoutedEventArgs());
else if (e.Key == Key.Insert) buttonAdd_Click(this, new RoutedEventArgs());
else e.Handled = false;
}
#endregion
}
}