217 lines
7.0 KiB
C#
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
|
|||
|
}
|
|||
|
}
|