Added source code.

This commit is contained in:
2018-02-06 01:24:46 +02:00
parent 1d9f2990c8
commit 8b28da5b80
367 changed files with 22964 additions and 0 deletions

View File

@ -0,0 +1,8 @@
<Application x:Class="GraphingCalculator.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="MainWindow.xaml">
<Application.Resources>
</Application.Resources>
</Application>

View File

@ -0,0 +1,42 @@
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Windows;
namespace GraphingCalculator
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
Log.LogEvent("Session started!");
}
protected override void OnExit(ExitEventArgs e)
{
base.OnExit(e);
Log.LogEvent("Session finished! Exit code: {0}", e.ApplicationExitCode);
Log.LogEvent("-----------------");
try {
if (!System.IO.Directory.Exists("logs")) System.IO.Directory.CreateDirectory("logs");
if (System.IO.File.Exists("logs\\graphingcalc.log"))
System.IO.File.AppendAllLines("logs\\graphingcalc.log", Log.Entries.ToArray());
else System.IO.File.WriteAllLines("logs\\graphingcalc.log", Log.Entries.ToArray());
}
catch { }
// Save settings
GraphingCalculator.Properties.Settings.Default.Save();
}
}
}

View File

@ -0,0 +1,77 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace GraphingCalculator
{
public class Bounds
{
private double left, right, top, bottom;
#region Public properties
public double Left
{
get { return left; }
set { left = value; if (BoundsChanged != null) BoundsChanged(this, new EventArgs()); }
}
public double Right
{
get { return right; }
set { right = value; if (BoundsChanged != null) BoundsChanged(this, new EventArgs()); }
}
public double Top
{
get { return top; }
set { top = value; if (BoundsChanged != null) BoundsChanged(this, new EventArgs()); }
}
public double Bottom
{
get { return bottom; }
set { bottom = value; if (BoundsChanged != null) BoundsChanged(this, new EventArgs()); }
}
public double Width
{
get { return Right - Left; }
set { Right = Left + value; }
}
public double Height
{
get { return Top - Bottom; }
set { Top = Bottom + Height; }
}
#endregion
public event EventHandler BoundsChanged;
#region Constructors
public Bounds()
{
Left = Right = Top = Bottom = 0;
}
public Bounds(double w, double h)
{
Left = Bottom = 0;
Width = w; Height = h;
}
public Bounds(double l, double t, double r, double b)
{
Left = l; Top = t; Right = r; Bottom = b;
}
#endregion
#region IsInBounds
public bool IsInBounds(double x, double y)
{
return (x >= Math.Min(Left, Right) && x <= Math.Max(Left, Right) &&
y >= Math.Min(Top, Bottom) && y <= Math.Max(Top, Bottom));
}
public bool IsInBounds(System.Windows.Point point)
{
return IsInBounds(point.X, point.Y);
}
#endregion
}
}

View File

@ -0,0 +1,101 @@
<Window x:Class="GraphingCalculator.EvaluateWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Evaluate expression" Height="251" Width="471" WindowStartupLocation="CenterScreen"
WindowStyle="ToolWindow" SnapsToDevicePixels="True"
KeyUp="Window_KeyUp">
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/Styles/GroupBoxStyle.xaml" />
<ResourceDictionary Source="/Styles/ButtonStyle.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
<Window.Background>
<LinearGradientBrush StartPoint="0,0" EndPoint=".5,1">
<GradientStop Color="#EEE" Offset="0" />
<GradientStop Color="#BBB" Offset="1" />
</LinearGradientBrush>
</Window.Background>
<Grid Margin="3">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="5"/>
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<GridSplitter Grid.Column="1" Grid.Row="0" Background="Transparent"
VerticalAlignment="Stretch" HorizontalAlignment="Stretch"/>
<GroupBox Header="Input expression" Margin="0,0,-3,0">
<TextBox Name="inputExpression" TextWrapping="Wrap"/>
</GroupBox>
<GroupBox Grid.Column="2" Header="Variables" Margin="-3,0,0,0">
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition />
<ColumnDefinition Width="Auto" />
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<ListBox Name="listVars" Grid.ColumnSpan="100" Margin="0,0,0,2">
<ListBox.ContextMenu>
<ContextMenu>
<MenuItem Header="Edit" Click="contextEdit_Click"/>
<MenuItem Header="Delete" Click="contextDelete_Click" />
<MenuItem Header="Clear list" Click="contextClear_Click" />
</ContextMenu>
</ListBox.ContextMenu>
</ListBox>
<TextBlock Grid.Row="1" Grid.Column="0" VerticalAlignment="Center">Name:</TextBlock>
<TextBox Name="inputVarName" Grid.Row="1" Grid.Column="1" />
<TextBlock Grid.Row="1" Grid.Column="2" VerticalAlignment="Center" Margin="3,0,0,0">Value:</TextBlock>
<TextBox Name="inputVarValue" Grid.Row="1" Grid.Column="3" />
<Button VerticalAlignment="Center" Name="buttonAdd"
Grid.Row="1" Grid.Column="4" Margin="3,0,0,0"
Click="buttonAdd_Click">Add</Button>
</Grid>
</GroupBox>
<GroupBox Grid.Row="1" Grid.ColumnSpan="3" Header="Result">
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<TextBox Name="outputResult" Grid.ColumnSpan="2" IsReadOnly="True" Background="White"
Margin="0,0,0,2"/>
<Button Name="buttonClose" Grid.Row="1" Grid.Column="1" Width="80" Margin="2"
HorizontalAlignment="Left" Click="buttonClose_Click">Close</Button>
<Button Name="buttonEval" Grid.Row="1" Width="80" Margin="2"
HorizontalAlignment="Right" Click="buttonEval_Click">Evaluate</Button>
</Grid>
</GroupBox>
</Grid>
</Window>

View File

@ -0,0 +1,216 @@
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
}
}

View File

@ -0,0 +1,137 @@
<Canvas x:Class="GraphingCalculator.GraphingCanvas"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d" d:DesignHeight="234" d:DesignWidth="348"
ClipToBounds="True"
SizeChanged="Canvas_SizeChanged"
MouseWheel="Canvas_MouseWheel"
>
<Canvas.Resources>
<Style TargetType="Button">
<Setter Property="OverridesDefaultStyle" Value="True" />
<Setter Property="SnapsToDevicePixels" Value="True" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid Name="grid">
<Border Name="border" CornerRadius="4" Visibility="Collapsed"
VerticalAlignment="Stretch"
HorizontalAlignment="Stretch"
BorderBrush="Orange"
BorderThickness="1">
<Border.Background>
<RadialGradientBrush Center=".5, .5" GradientOrigin=".5,1" RadiusX="1" RadiusY=".7">
<GradientStop Color="#FFBF6A" Offset="0" />
<GradientStop Color="#FFF6E2" Offset="1" />
</RadialGradientBrush>
</Border.Background>
</Border>
<Border Name="blackness" CornerRadius="4" Background="Brown" Opacity="0" />
<ContentPresenter VerticalAlignment="Center" Margin="3"
HorizontalAlignment="Center" />
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="border" Property="Visibility" Value="Visible" />
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter TargetName="blackness" Property="Opacity" Value=".3" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="RepeatButton">
<Setter Property="OverridesDefaultStyle" Value="True" />
<Setter Property="SnapsToDevicePixels" Value="True" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="RepeatButton">
<Grid Name="grid">
<Border Name="border" CornerRadius="4" Visibility="Collapsed"
VerticalAlignment="Stretch"
HorizontalAlignment="Stretch"
BorderBrush="Orange"
BorderThickness="1">
<Border.Background>
<RadialGradientBrush Center=".5, .5" GradientOrigin=".5,1" RadiusX="1" RadiusY=".7">
<GradientStop Color="#FFBF6A" Offset="0" />
<GradientStop Color="#FFF6E2" Offset="1" />
</RadialGradientBrush>
</Border.Background>
</Border>
<Border Name="blackness" CornerRadius="4" Background="Brown" Opacity="0" />
<ContentPresenter VerticalAlignment="Center" Margin="3"
HorizontalAlignment="Center" />
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="border" Property="Visibility" Value="Visible" />
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter TargetName="blackness" Property="Opacity" Value=".3" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Canvas.Resources>
<RepeatButton Name="buttonUp" Canvas.Right="25" Canvas.Top="5"
Width="20" Height="20" Click="buttonUp_Click">
<Path Height="12" Stretch="Fill" Fill="Gray"
Data="F1 M 190.792,238.149L 182.688,252.184L 198.895,252.184L 190.792,238.149 Z "/>
</RepeatButton>
<RepeatButton Name="buttonLeft" Canvas.Right="45" Canvas.Top="25"
Width="20" Height="20" Click="buttonLeft_Click" >
<Path Width="12" Stretch="Fill" Fill="Gray" Data="F1 M 204.774,246.729L 218.809,254.833L 218.809,238.626L 204.774,246.729 Z "/>
</RepeatButton>
<Button Name="buttonReset"
Canvas.Right="25" Canvas.Top="25"
Width="20" Height="20"
Click="buttonReset_Click"
ToolTip="Reset" >
<Ellipse Width="12" Height="12" Fill="Gray"/>
</Button>
<RepeatButton Name="buttonRight"
Canvas.Right="5" Canvas.Top="25"
Width="20" Height="20" Click="buttonRight_Click" >
<Path Width="12" Stretch="Fill" Fill="Gray" Data="F1 M 214.722,227.667L 200.686,219.563L 200.686,235.77L 214.722,227.667 Z "/>
</RepeatButton>
<RepeatButton Name="buttonBottom" Canvas.Right="25" Canvas.Top="45"
Width="20" Height="20" Click="buttonBottom_Click" >
<Path Height="12" Stretch="Fill" Fill="Gray" Data="F1 M 188.333,235.024L 196.437,220.988L 180.23,220.988L 188.333,235.024 Z "/>
</RepeatButton>
<!-- Zoom buttons -->
<RepeatButton Name="buttonZoomIn" Canvas.Right="5" Canvas.Bottom="5"
Width="25" Height="20" Click="buttonZoomIn_Click">
<Path Width="12" Height="12" Stretch="Fill" Fill="Gray" Data="M 139.292,225.542L 147.292,225.542L 147.292,233.542L 155.292,233.542L 155.292,241.542L 147.292,241.542L 147.292,249.542L 139.292,249.542L 139.292,241.542L 131.292,241.542L 131.292,233.542L 139.292,233.542L 139.292,225.542 Z "/>
</RepeatButton>
<RepeatButton Name="buttonZoomOut" Canvas.Right="30" Canvas.Bottom="5"
Width="25" Height="20" Click="buttonZoomOut_Click">
<Rectangle Width="12" Height="4.32" Stretch="Fill" Fill="Gray"/>
</RepeatButton>
</Canvas>

View File

@ -0,0 +1,466 @@
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 GraphingCalculator
{
/// <summary>
/// Interaction logic for GraphingCanvas.xaml
/// </summary>
public partial class GraphingCanvas : Canvas
{
#region Settings
private double PlotPrecision
{
get { return GraphingCalculator.Properties.Settings.Default.PlotPrecision; }
set { GraphingCalculator.Properties.Settings.Default.PlotPrecision = value; }
}
private double GridDensity
{
get { return GraphingCalculator.Properties.Settings.Default.GridDensity; }
set { GraphingCalculator.Properties.Settings.Default.GridDensity = value; }
}
private int RoundDoublesGraph
{
get { return GraphingCalculator.Properties.Settings.Default.RoundDoublesGraph; }
set { GraphingCalculator.Properties.Settings.Default.RoundDoublesGraph = value; }
}
private double NavigationSens
{
get { return GraphingCalculator.Properties.Settings.Default.NavigationSensitivity; }
set { GraphingCalculator.Properties.Settings.Default.NavigationSensitivity = value; }
}
private double ZoomSens
{
get { return GraphingCalculator.Properties.Settings.Default.ZoomSensitivity; }
set { GraphingCalculator.Properties.Settings.Default.ZoomSensitivity = value; }
}
#endregion
#region Constants
private Point specialSeparator = new Point(double.MaxValue, double.MaxValue);
private Point specialVisibleTrue = new Point(0, double.MaxValue);
private Point specialVisibleFalse = new Point(0, double.MinValue);
#endregion
#region Expressions
private List<VisualExpression> expressions = new List<VisualExpression>();
public List<VisualExpression> Expressions { get { return expressions; } }
/// <summary>
/// Adds an expression to be plotted
/// </summary>
public void AddExpression(VisualExpression ex)
{
this.Expressions.Add(ex);
EvaluateExpression(ex);
Redraw();
#region Log
Log.LogEvent("Plotted expression '{0}'", ex.ExpressionString);
#endregion
}
public void SetExpressionVisibility(int index, bool visibility)
{
if (Expressions[index].IsVisible == visibility) return;
if (queuedPoints.Count != 0) {
int i, ci;
for (i = 0, ci = -1; i < queuedPoints.Count && ci < index; i++)
if (queuedPoints[i] == specialSeparator) ci++;
queuedPoints[i] = (visibility) ? specialVisibleTrue : specialVisibleFalse;
}
Expressions[index].IsVisible = visibility;
Redraw();
}
#endregion
#region Canvas and screen bounds
public Bounds CanvasBounds { get; set; }
public Bounds ScreenBounds { get; set; }
public double CoordXToCanvas(double x)
{
double scrX = x - ScreenBounds.Left;
return CanvasBounds.Left + (CanvasBounds.Width * (scrX / ScreenBounds.Width));
}
public double CoordXToScreen(double x)
{
double canX = x - CanvasBounds.Left;
return ScreenBounds.Left + (ScreenBounds.Width * (canX / CanvasBounds.Width));
}
public double CoordYToCanvas(double y)
{
double scrY = y - ScreenBounds.Bottom;
return CanvasBounds.Bottom + (CanvasBounds.Height * (scrY / ScreenBounds.Height));
}
public double CoordYToScreen(double y)
{
double canY = y - CanvasBounds.Bottom;
return ScreenBounds.Bottom + (ScreenBounds.Height * (canY / CanvasBounds.Height));
}
public Point CoordToCanvas(double x, double y)
{
return new Point(CoordXToCanvas(x), CoordYToCanvas(y));
}
public Point CoordToCanvas(Point p)
{
return new Point(CoordXToCanvas(p.X), CoordYToCanvas(p.Y));
}
public Point CoordToScreen(double x, double y)
{
return new Point(CoordXToScreen(x), CoordYToScreen(y));
}
public Point CoordToScreen(Point p)
{
return new Point(CoordXToScreen(p.X), CoordYToScreen(p.Y));
}
public void SetCanvasBounds(Bounds b)
{
if (b.Width <= 0 || b.Height <= 0) return;
CanvasBounds.Top = b.Top;
CanvasBounds.Bottom = b.Bottom;
CanvasBounds.Left = b.Left;
CanvasBounds.Right = b.Right;
EvaluateExpressions();
Redraw();
}
#endregion
#region Constructor
public GraphingCanvas()
{
InitializeComponent();
CanvasBounds = new Bounds(-5, 5, 5, -5);
ScreenBounds = new Bounds(0, 0, this.ActualWidth, this.ActualHeight);
}
#endregion
#region UI Events
private void Canvas_SizeChanged(object sender, SizeChangedEventArgs e)
{
ScreenBounds.Right = e.NewSize.Width;
ScreenBounds.Bottom = e.NewSize.Height;
Redraw();
}
private void buttonReset_Click(object sender, RoutedEventArgs e)
{
CanvasBounds.Left = -5;
CanvasBounds.Right = 5;
CanvasBounds.Bottom = -5;
CanvasBounds.Top = 5;
EvaluateExpressions();
Redraw();
}
private void buttonUp_Click(object sender, RoutedEventArgs e)
{
double h = CanvasBounds.Height * NavigationSens;
CanvasBounds.Top += h;
CanvasBounds.Bottom += h;
EvaluateExpressions();
Redraw();
}
private void buttonLeft_Click(object sender, RoutedEventArgs e)
{
double w = CanvasBounds.Width * NavigationSens;
CanvasBounds.Left -= w;
CanvasBounds.Right -= w;
EvaluateExpressions();
Redraw();
}
private void buttonRight_Click(object sender, RoutedEventArgs e)
{
double w = CanvasBounds.Width * NavigationSens;
CanvasBounds.Left += w;
CanvasBounds.Right += w;
EvaluateExpressions();
Redraw();
}
private void buttonBottom_Click(object sender, RoutedEventArgs e)
{
double h = CanvasBounds.Height * NavigationSens;
CanvasBounds.Top -= h;
CanvasBounds.Bottom -= h;
EvaluateExpressions();
Redraw();
}
private void buttonZoomIn_Click(object sender, RoutedEventArgs e)
{
double new_w = CanvasBounds.Width / ZoomSens;
double new_h = CanvasBounds.Height / ZoomSens;
double diff_w = (CanvasBounds.Width - new_w) / 2 ;
double diff_h = (CanvasBounds.Height - new_h) / 2;
CanvasBounds.Left += diff_w;
CanvasBounds.Right -= diff_w;
CanvasBounds.Bottom += diff_h;
CanvasBounds.Top -= diff_h;
EvaluateExpressions();
Redraw();
}
private void buttonZoomOut_Click(object sender, RoutedEventArgs e)
{
double new_w = CanvasBounds.Width * ZoomSens;
double new_h = CanvasBounds.Height * ZoomSens;
double diff_w = (CanvasBounds.Width - new_w) / 2;
double diff_h = (CanvasBounds.Height - new_h) / 2;
CanvasBounds.Left += diff_w;
CanvasBounds.Right -= diff_w;
CanvasBounds.Bottom += diff_h;
CanvasBounds.Top -= diff_h;
EvaluateExpressions();
Redraw();
}
#endregion
#region Expression evaluation
List<Point> queuedPoints = new List<Point>();
public void EvaluateExpression(VisualExpression expr)
{
queuedPoints.Add(specialSeparator);
queuedPoints.Add((expr.IsVisible) ? specialVisibleTrue : specialVisibleFalse);
for (double x = CanvasBounds.Left; x <= CanvasBounds.Right; x += CanvasBounds.Width / PlotPrecision)
{
expr.Variables["x"] = expr.Variables["X"] = x;
queuedPoints.Add(new Point(x, expr.Evaluate()));
}
}
public void EvaluateExpressions()
{
queuedPoints.Clear();
foreach (var expr in Expressions)
EvaluateExpression(expr);
}
#endregion
#region Rendering
public void Redraw()
{
this.InvalidateVisual();
}
private void RenderDouble(DrawingContext dc, double n, Point pos, bool center)
{
FormattedText text = new FormattedText(Math.Round(n, RoundDoublesGraph).ToString(),
new System.Globalization.CultureInfo("en-US"), FlowDirection.LeftToRight,
new Typeface("Arial"), 8.0, Brushes.Black);
if (center) dc.DrawText(text, new Point(pos.X - (text.Width / 2), pos.Y + 10));
else dc.DrawText(text, new Point(pos.X + 2, pos.Y));
}
private void RenderGridVertical(DrawingContext dc, Pen pen, double from, double to, double interv)
{
if (from > to) interv *= -1;
// Draw vertical grid
for (double i = from; (from < to && i < to) || (from > to && i > to); i += interv)
{
Point text = CoordToScreen(i, 0);
Point f = CoordToScreen(i, CanvasBounds.Bottom);
Point t = CoordToScreen(i, CanvasBounds.Top);
dc.DrawLine(pen, f, t);
RenderDouble(dc, i, text, true);
}
}
private void RenderGridHorizontal(DrawingContext dc, Pen pen, double from, double to, double interv)
{
if (from > to) interv *= -1;
// Draw vertical grid
for (double i = from; (from < to && i < to) || (from > to && i > to); i += interv)
{
Point text = CoordToScreen(0, i);
Point f = CoordToScreen(CanvasBounds.Left, i);
Point t = CoordToScreen(CanvasBounds.Right, i);
dc.DrawLine(pen, f, t);
RenderDouble(dc, i, text, false);
}
}
private void RenderGrid(DrawingContext dc)
{
Pen pen = new Pen(new SolidColorBrush(Color.FromRgb(0xa6, 0xdd, 0xe2)), 1);
pen.DashStyle = DashStyles.Dash;
double w_div = Math.Truncate(this.ActualWidth / GridDensity);
double h_div = Math.Truncate(this.ActualHeight / GridDensity);
if (Convert.ToInt32(w_div) % 2 == 1) w_div += 1;
if (Convert.ToInt32(h_div) % 2 == 1) h_div += 1;
double w_int = CanvasBounds.Width / w_div;
double h_int = CanvasBounds.Height / h_div;
RenderGridVertical(dc, pen, 0, CanvasBounds.Right, w_int);
RenderGridVertical(dc, pen, 0, CanvasBounds.Left, w_int);
RenderGridHorizontal(dc, pen, 0, CanvasBounds.Top, h_int);
RenderGridHorizontal(dc, pen, 0, CanvasBounds.Bottom, h_int);
}
private void RenderAxis(DrawingContext dc)
{
Point dst;
Pen lines = new Pen(Brushes.Coral, 1.5);
// Draw X axis
dst = CoordToScreen(CanvasBounds.Right, 0);
dc.DrawLine(lines, CoordToScreen(CanvasBounds.Left, 0), dst);
dc.DrawLine(lines, dst, new Point(dst.X - 5, dst.Y + 2));
dc.DrawLine(lines, dst, new Point(dst.X - 5, dst.Y - 2));
// Draw Y axis
dst = CoordToScreen(0, CanvasBounds.Top);
dc.DrawLine(lines, CoordToScreen(0, CanvasBounds.Bottom), dst);
dc.DrawLine(lines, dst, new Point(dst.X - 2, dst.Y + 5));
dc.DrawLine(lines, dst, new Point(dst.X + 2, dst.Y + 5));
}
private void RenderFunctions(DrawingContext dc)
{
if (Expressions.Count == 0) return;
int exprIndex = -1;
bool visible = true;
Pen pen = new Pen();
for (int i = 0; i < queuedPoints.Count - 1; i++)
{
if (queuedPoints[i] == specialSeparator)
{
exprIndex++; i++;
pen = new Pen(new SolidColorBrush(Expressions[exprIndex].Color), Expressions[exprIndex].Thickness);
visible = (queuedPoints[i] == specialVisibleTrue);
}
else if (visible && queuedPoints[i + 1] != specialSeparator)
{
Point src = CoordToScreen(queuedPoints[i]);
Point dst = CoordToScreen(queuedPoints[i + 1]);
if (ScreenBounds.IsInBounds(src) || ScreenBounds.IsInBounds(dst))
dc.DrawLine(pen, src, dst);
}
}
}
protected override void OnRender(DrawingContext dc)
{
// Reduce garbage collector intrusions
var latency = System.Runtime.GCSettings.LatencyMode;
System.Runtime.GCSettings.LatencyMode = System.Runtime.GCLatencyMode.LowLatency;
// Draw grid
RenderGrid(dc);
RenderAxis(dc);
// Render functions
RenderFunctions(dc);
// Base render
base.OnRender(dc);
// Restore previous garbage collector setting
System.Runtime.GCSettings.LatencyMode = latency;
}
#endregion
private void Canvas_MouseWheel(object sender, MouseWheelEventArgs e)
{
if (e.Delta > 0) buttonZoomIn_Click(this, new RoutedEventArgs());
else buttonZoomOut_Click(this, new RoutedEventArgs());
}
#region Navigation control
public void PeformMouseWheelChange(MouseWheelEventArgs e)
{
Canvas_MouseWheel(this, e);
}
public void PerformMoveLeft()
{
buttonLeft_Click(this, new RoutedEventArgs());
}
public void PerformMoveRight()
{
buttonRight_Click(this, new RoutedEventArgs());
}
public void PerformMoveUp()
{
buttonUp_Click(this, new RoutedEventArgs());
}
public void PerformMoveDown()
{
buttonBottom_Click(this, new RoutedEventArgs());
}
public void PerformReset()
{
buttonReset_Click(this, new RoutedEventArgs());
}
public void PerformZoomIn()
{
buttonZoomIn_Click(this, new RoutedEventArgs());
}
public void PerformZoomOut()
{
buttonZoomOut_Click(this, new RoutedEventArgs());
}
#endregion
}
}

View File

@ -0,0 +1,80 @@
<Window x:Class="GraphingCalculator.Controls.IntegralWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Integral" Height="331" Width="261" WindowStyle="ToolWindow" WindowStartupLocation="CenterScreen">
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/Styles/ButtonStyle.xaml" />
<ResourceDictionary Source="/Styles/RadioButtonStyle.xaml" />
<ResourceDictionary Source="/Styles/GroupBoxStyle.xaml" />
<ResourceDictionary Source="/Styles/WarningGroupBoxStyle.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
<Window.Background>
<LinearGradientBrush StartPoint="0,0" EndPoint=".5,1">
<GradientStop Color="#EEE" Offset="0" />
<GradientStop Color="#999" Offset="1" />
</LinearGradientBrush>
</Window.Background>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition />
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<GroupBox Style="{StaticResource WarningGroupBox}"
Grid.Row="0" Grid.ColumnSpan="2" Margin="8,5,8,2"
HorizontalContentAlignment="Stretch"
Header="Warning" TextBlock.TextAlignment="Center" >
<TextBlock TextWrapping="Wrap">This feature is experimental, so the given results may not fully be accurate.</TextBlock>
</GroupBox>
<GroupBox Header="Expression" Grid.Row="1">
<TextBox Name="inputExpression" TextWrapping="Wrap" />
</GroupBox>
<GroupBox Header="Interval" Grid.Row="2">
<StackPanel>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="32" />
<ColumnDefinition />
<ColumnDefinition Width="5" />
<ColumnDefinition Width="32" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" VerticalAlignment="Center">From:</TextBlock>
<TextBox Name="inputIntervalBeg" Grid.Column="1" VerticalAlignment="Center">-1</TextBox>
<TextBlock Grid.Column="3" VerticalAlignment="Center">To:</TextBlock>
<TextBox Name="inputIntervalEnd" Grid.Column="4" VerticalAlignment="Center">1</TextBox>
</Grid>
</StackPanel>
</GroupBox>
<GroupBox Header="Result" Grid.Row="3">
<TextBox Name="outputResult" IsReadOnly="True" Background="White"/>
</GroupBox>
<Grid Grid.Row="4">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Button Name="buttonCalculate" Grid.Column="0" HorizontalAlignment="Right" Width="80" Click="buttonCalculate_Click">Calculate</Button>
<Button Name="buttonClose" Grid.Column="1" HorizontalAlignment="Left" Width="80" Click="buttonClose_Click">Close</Button>
</Grid>
</Grid>
</Window>

View File

@ -0,0 +1,93 @@
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.Controls
{
/// <summary>
/// Interaction logic for LimitWindow.xaml
/// </summary>
public partial class IntegralWindow : Window
{
#region Properties
public string ExpressionString
{
get { return inputExpression.Text; }
set { inputExpression.Text = value; }
}
#endregion
#region Constructors
public IntegralWindow()
{
InitializeComponent();
ExpressionString = "";
}
public IntegralWindow(string expression)
{
InitializeComponent();
ExpressionString = expression;
}
#endregion
#region Other routines
private void Result (string result, bool error = false)
{
outputResult.Text = result;
if (error) outputResult.Foreground = Brushes.DarkRed;
else outputResult.Foreground = Brushes.Black;
}
#endregion
#region Button handlers
private void buttonClose_Click(object sender, RoutedEventArgs e)
{
this.Close();
}
private void buttonCalculate_Click(object sender, RoutedEventArgs e)
{
double val_beg, val_end, integr_res;
Expression beg, end, expr;
beg = new Expression(inputIntervalBeg.Text);
end = new Expression(inputIntervalEnd.Text);
expr = new Expression(inputExpression.Text);
// Try to evaluate interval ends
try { val_beg = beg.Evaluate(); }
catch { Result("Failed to evaluate interval start.", true); return; }
try { val_end = end.Evaluate(); }
catch { Result("Failed to evaluate interval end.", true); return; }
// Try to calculate the integral
try { integr_res = Integrator.Integrate(expr, val_beg, val_end, "x"); }
catch (Exception ex)
{
Result("Failed to evaluate expression. Message: " + ex.Message, true);
Log.LogEvent("Failed to integrate expression: {0}", expr.ExpressionString);
Log.LogEvent("> Interval: [{0}, {1}] = [{2}, {3}]", beg.ExpressionString, end.ExpressionString, val_beg, val_end);
Log.LogEvent("> Message: {0}", ex.Message);
Log.LogEvent("> Stack trace: {0}", ex.StackTrace);
return;
}
// Show result
Result(Math.Round(integr_res, 14).ToString());
Log.LogEvent("Integrated expression: {0}", expr.ExpressionString);
Log.LogEvent("> Interval: [{0}, {1}] = [{2}, {3}]", beg.ExpressionString, end.ExpressionString, val_beg, val_end);
Log.LogEvent("> Result: {0}", integr_res);
}
#endregion
}
}

View File

@ -0,0 +1,44 @@
<Window x:Class="GraphingCalculator.LogWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Log" Height="379" Width="543" WindowStartupLocation="CenterScreen" ShowInTaskbar="True">
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/Styles/ButtonStyle.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<ListBox Name="listEntries" Grid.Row="0" Grid.ColumnSpan="10"
ScrollViewer.HorizontalScrollBarVisibility="Disabled" >
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock TextWrapping="Wrap" Text="{Binding}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<Button Name="buttonCopy" Grid.Row="1" Grid.Column="1" Width="60" Click="buttonCopy_Click">Copy</Button>
<Button Name="buttonSave" Grid.Row="1" Grid.Column="2" Width="60" Click="buttonSave_Click">Save...</Button>
<Button Name="buttonClear" Grid.Row="1" Grid.Column="3" Width="60" Click="buttonClear_Click">Clear</Button>
<Button Name="buttonRefresh" Grid.Row="1" Grid.Column="0" Width="60" Click="buttonRefresh_Click">Refresh</Button>
<Button Name="buttonClose" Grid.Row="1" Grid.Column="5" Width="60" Click="buttonClose_Click">Close</Button>
</Grid>
</Window>

View File

@ -0,0 +1,74 @@
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 LogWindow.xaml
/// </summary>
public partial class LogWindow : Window
{
public LogWindow()
{
InitializeComponent();
buttonRefresh_Click(this, new RoutedEventArgs());
}
private void buttonCopy_Click(object sender, RoutedEventArgs e)
{
if (listEntries.SelectedIndex != -1)
Clipboard.SetText(listEntries.SelectedItem.ToString());
}
private void buttonClear_Click(object sender, RoutedEventArgs e)
{
listEntries.Items.Clear();
Log.Entries.Clear();
}
private void buttonRefresh_Click(object sender, RoutedEventArgs e)
{
listEntries.Items.Clear();
foreach (var i in Log.Entries)
listEntries.Items.Add(i);
}
private void buttonClose_Click(object sender, RoutedEventArgs e)
{
this.Close();
}
private void buttonSave_Click(object sender, RoutedEventArgs e)
{
Microsoft.Win32.SaveFileDialog dialog = new Microsoft.Win32.SaveFileDialog();
dialog.Title = "Save log...";
dialog.Filter = "Text file|*.txt|Log file|*.log|All files|*.*";
bool? res = dialog.ShowDialog();
if (!res.HasValue && !res.Value) return;
try
{
System.IO.File.WriteAllLines(dialog.FileName, Log.Entries.ToArray());
}
catch (Exception ex)
{
Log.LogEvent("Failed to save log to file {0}: {1}", dialog.FileName, ex.Message);
MessageBox.Show("Error: " + ex.Message, "Failed to save log file!");
}
}
}
}

View File

@ -0,0 +1,165 @@
<Window x:Class="GraphingCalculator.SettingsWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Settings" Height="320" Width="562"
ShowInTaskbar="False" WindowStartupLocation="CenterScreen"
WindowStyle="ToolWindow">
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/Styles/GroupBoxStyle.xaml" />
<ResourceDictionary Source="/Styles/ButtonStyle.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
<Window.Background>
<LinearGradientBrush StartPoint="0,0" EndPoint=".5,1">
<GradientStop Color="#EEE" Offset="0" />
<GradientStop Color="#BBB" Offset="1" />
</LinearGradientBrush>
</Window.Background>
<Grid Margin="2">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto" />
<RowDefinition />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<GroupBox Header="Graph precision" Grid.Row="0">
<StackPanel>
<Slider Name="sliderGraphPrecision"
Minimum="50" Maximum="2000" TickFrequency="150"
SmallChange="10" LargeChange="50"
TickPlacement="BottomRight"/>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition />
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock>Minimum</TextBlock>
<TextBlock Grid.Column="2">Maximum</TextBlock>
</Grid>
<TextBlock TextWrapping="Wrap" FontSize="11"
Foreground="#444" Margin="2,4,2,2">
A higher precision means that drawing takes longer to render, making the application slower.</TextBlock>
</StackPanel>
</GroupBox>
<GroupBox Header="Grid density" Grid.Column="1" Grid.Row="0">
<StackPanel>
<Slider Name="sliderGridDensity"
Minimum="10" Maximum="100" TickFrequency="5"
SmallChange="2" LargeChange="5"
TickPlacement="BottomRight"/>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition />
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock>Higher</TextBlock>
<TextBlock Grid.Column="2">Lower</TextBlock>
</Grid>
<TextBlock TextWrapping="Wrap" FontSize="11"
Foreground="#444" Margin="2,4,2,2">
A higher density means that more grid lines are drawn.</TextBlock>
</StackPanel>
</GroupBox>
<GroupBox Header="Grid numbers precision" Grid.Row="2" Grid.RowSpan="2">
<StackPanel>
<Slider Name="sliderDoublePrecision"
Minimum="0" Maximum="15" TickFrequency="1"
SmallChange="1" LargeChange="1" ValueChanged="sliderDoublePrecision_ValueChanged"
TickPlacement="BottomRight" IsSnapToTickEnabled="True"/>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition />
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock>0</TextBlock>
<TextBlock Name="outputDoublePrecision" Grid.Column="1" HorizontalAlignment="Center">? decimals</TextBlock>
<TextBlock Grid.Column="2">15</TextBlock>
</Grid>
<TextBlock TextWrapping="Wrap" FontSize="11"
Foreground="#444" Margin="2,4,2,2">
A higher precision means that more decimals appear in the graph. If the value is too high, values may overlap each other.</TextBlock>
</StackPanel>
</GroupBox>
<GroupBox Header="Navigation sensitivity"
Grid.Column="1" Grid.Row="2">
<StackPanel>
<Slider Name="sliderNavigationSensitivity"
Minimum=".01" Maximum="1.5" TickFrequency=".1"
SmallChange=".01" LargeChange=".05" ValueChanged="sliderNavigationSensitivity_ValueChanged"
TickPlacement="BottomRight"/>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition />
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock>1%</TextBlock>
<TextBlock Name="outputNavigationSensitivity" Grid.Column="1" HorizontalAlignment="Center">?% of screen</TextBlock>
<TextBlock Grid.Column="2">150%</TextBlock>
</Grid>
</StackPanel>
</GroupBox>
<GroupBox Header="Zoom sensitivity"
Grid.Column="1" Grid.Row="3">
<StackPanel>
<Slider Name="sliderZoomSensitivity"
Minimum="1.01" Maximum="2.5" TickFrequency=".1"
SmallChange=".01" LargeChange=".05" ValueChanged="sliderZoomSensitivity_ValueChanged"
TickPlacement="BottomRight"/>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition />
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock>1%</TextBlock>
<TextBlock Name="outputZoomSensitivity" Grid.Column="1" HorizontalAlignment="Center">?% of screen</TextBlock>
<TextBlock Grid.Column="2">150%</TextBlock>
</Grid>
</StackPanel>
</GroupBox>
<Grid Grid.Row="5" Grid.ColumnSpan="2">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Button Name="buttonDefaults" Width="80" Click="buttonDefaults_Click">Defaults</Button>
<Button Name="buttonCancel" Width="80" Grid.Column="2" Click="buttonCancel_Click">Cancel</Button>
<Button Name="buttonAccept" Width="80" Grid.Column="3" Click="buttonAccept_Click">Accept</Button>
</Grid>
</Grid>
</Window>

View File

@ -0,0 +1,94 @@
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 SettingsWindow.xaml
/// </summary>
public partial class SettingsWindow : Window
{
public SettingsWindow()
{
InitializeComponent();
this.Loaded += new RoutedEventHandler(SettingsWindow_Loaded);
}
void SettingsWindow_Loaded(object sender, RoutedEventArgs e)
{
Update();
}
private void Update()
{
sliderGraphPrecision.Value = GraphingCalculator.Properties.Settings.Default.PlotPrecision;
sliderGridDensity.Value = GraphingCalculator.Properties.Settings.Default.GridDensity;
sliderDoublePrecision.Value = GraphingCalculator.Properties.Settings.Default.RoundDoublesGraph;
sliderNavigationSensitivity.Value = GraphingCalculator.Properties.Settings.Default.NavigationSensitivity;
sliderZoomSensitivity.Value = GraphingCalculator.Properties.Settings.Default.ZoomSensitivity;
}
private void Save()
{
GraphingCalculator.Properties.Settings.Default.PlotPrecision = sliderGraphPrecision.Value;
GraphingCalculator.Properties.Settings.Default.GridDensity = sliderGridDensity.Value;
GraphingCalculator.Properties.Settings.Default.RoundDoublesGraph = Convert.ToInt32(sliderDoublePrecision.Value);
GraphingCalculator.Properties.Settings.Default.NavigationSensitivity = sliderNavigationSensitivity.Value;
GraphingCalculator.Properties.Settings.Default.ZoomSensitivity = sliderZoomSensitivity.Value;
}
private void buttonDefaults_Click(object sender, RoutedEventArgs e)
{
sliderGraphPrecision.Value = 600;
sliderGridDensity.Value = 41;
sliderDoublePrecision.Value = 4;
sliderNavigationSensitivity.Value = 0.1;
sliderZoomSensitivity.Value = 1.075;
}
private void buttonCancel_Click(object sender, RoutedEventArgs e)
{
this.Close();
}
private void buttonAccept_Click(object sender, RoutedEventArgs e)
{
Save();
this.Close();
}
private void sliderDoublePrecision_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
if (outputDoublePrecision != null)
outputDoublePrecision.Text = e.NewValue.ToString() + " decimals";
}
private void sliderNavigationSensitivity_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
if (outputNavigationSensitivity != null)
outputNavigationSensitivity.Text = Math.Round(e.NewValue * 100, 0).ToString() + "% of screen";
}
private void sliderZoomSensitivity_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
if (outputZoomSensitivity != null)
outputZoomSensitivity.Text = Math.Round((e.NewValue-1) * 100, 0).ToString() + "% of screen";
}
}
}

View File

@ -0,0 +1,361 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace GraphingCalculator
{
public class Expression
{
#region Token type
public enum Token
{
None, Literal, Variable, Operator, Function, FunctionArgumentSeparator,
LeftParanthesis, RightParanthesis
};
#endregion
#region Variables, properties
private string expressionString;
private bool isProcessed = false;
private List<KeyValuePair<Token, string>> tokens = new List<KeyValuePair<Token, string>>();
private List<KeyValuePair<Token, string>> output = new List<KeyValuePair<Token, string>>();
private Dictionary<string, double> variables = new Dictionary<string, double>();
protected List<KeyValuePair<Token, string>> Tokens { get { return tokens; } }
protected List<KeyValuePair<Token, string>> Output { get { return output; } }
public Dictionary<string, double> Variables { get { return variables; } }
public string ExpressionString
{
get { return expressionString; }
set
{
expressionString = value;
isProcessed = false;
}
}
#endregion
#region Other stuff
public void AddVariable(string name, double value)
{
variables[name] = value;
}
#endregion
#region Constructor
public Expression()
{
Variables.Add("pi", Math.PI);
Variables.Add("e", Math.E);
}
public Expression(string expr)
: this()
{
expressionString = expr;
}
#endregion
#region Processor
private void Tokenize()
{
tokens.Clear();
for (int i = 0; i < ExpressionString.Length; i++)
{
if (char.IsWhiteSpace(ExpressionString[i])) continue;
if (IsOperator(ExpressionString[i]))
{
// Unary minus
if (ExpressionString[i] == '-' && (tokens.Count == 0 || tokens.Last().Key == Token.LeftParanthesis || tokens.Last().Key == Token.Operator || tokens.Last().Key == Token.FunctionArgumentSeparator))
tokens.Add(new KeyValuePair<Token, string>(Token.Operator, "!-"));
// Any other operator
else tokens.Add(new KeyValuePair<Token, string>(Token.Operator, ExpressionString[i].ToString()));
}
else if (ExpressionString[i] == '(')
tokens.Add(new KeyValuePair<Token, string>(Token.LeftParanthesis, ExpressionString[i].ToString()));
else if (ExpressionString[i] == ')')
tokens.Add(new KeyValuePair<Token, string>(Token.RightParanthesis, ExpressionString[i].ToString()));
else if (ExpressionString[i] == ',')
tokens.Add(new KeyValuePair<Token, string>(Token.FunctionArgumentSeparator, ExpressionString[i].ToString()));
else if (Char.IsDigit(ExpressionString[i]))
tokens.Add(new KeyValuePair<Token, string>(Token.Literal, GetLiteral(ExpressionString, ref i)));
else if (Char.IsLetter(ExpressionString[i]))
{
if (IsFunction(ExpressionString, i)) tokens.Add(new KeyValuePair<Token, string>(Token.Function, GetVariable(ExpressionString, ref i)));
else tokens.Add(new KeyValuePair<Token, string>(Token.Variable, GetVariable(ExpressionString, ref i)));
}
else throw new Exception("Unrecognized character found!");
}
}
private void ShuntingYard()
{
Stack<KeyValuePair<Token, string>> stack = new Stack<KeyValuePair<Token, string>>();
foreach (var i in Tokens) switch (i.Key)
{
case Token.Variable:
case Token.Literal: output.Add(i); break;
case Token.Function: stack.Push(i); break;
case Token.FunctionArgumentSeparator:
while (stack.Peek().Key != Token.LeftParanthesis)
{
output.Add(stack.Pop());
if (stack.Count == 0) throw new Exception("Syntax error!");
}
break;
case Token.Operator:
if (IsLeftAssociative(i.Value))
{
while (stack.Count != 0 && Precedence(i.Value) <= Precedence(stack.Peek().Value))
output.Add(stack.Pop());
}
else
{
while (stack.Count != 0 && Precedence(i.Value) < Precedence(stack.Peek().Value))
output.Add(stack.Pop());
}
stack.Push(i);
break;
case Token.LeftParanthesis: stack.Push(i); break;
case Token.RightParanthesis:
while (stack.Peek().Key != Token.LeftParanthesis)
{
output.Add(stack.Pop());
if (stack.Count == 0) throw new Exception("Mismatched parantheses!");
}
stack.Pop(); // Pop paranthesis
if (stack.Count > 0 && stack.Peek().Key == Token.Function) output.Add(stack.Pop()); // Pop function
break;
}
while (stack.Count > 0)
{
if (stack.Peek().Key == Token.LeftParanthesis) throw new Exception("Mismatched parantheses!");
output.Add(stack.Pop());
}
}
public void Process()
{
if (!isProcessed)
{
tokens.Clear();
output.Clear();
Tokenize();
ShuntingYard();
}
}
public double Evaluate()
{
Process();
if (Output.Count == 0) return 0;
Stack<double> stack = new Stack<double>();
foreach (var i in Output)
switch (i.Key)
{
case Token.Variable:
if (!Variables.ContainsKey(i.Value)) throw new Exception("Undefined variable '" + i.Value + "'.");
stack.Push(Variables[i.Value]);
break;
case Token.Literal: stack.Push(double.Parse(i.Value)); break;
case Token.Operator:
switch (i.Value)
{
case "!-": stack.Push(stack.Pop() * -1); break;
case "+": stack.Push(stack.Pop() + stack.Pop()); break;
case "-":
{
double b = stack.Pop();
double a = stack.Pop();
stack.Push(a - b);
} break;
case "*": stack.Push(stack.Pop() * stack.Pop()); break;
case "/":
{
double b = stack.Pop();
double a = stack.Pop();
stack.Push(a / b);
} break;
case "%":
{
double b = stack.Pop();
double a = stack.Pop();
stack.Push(a % b);
} break;
case "^":
{
double b = stack.Pop();
double a = stack.Pop();
stack.Push(Math.Pow(a, b));
} break;
}
break;
case Token.Function:
EvaluateFunction(i.Value, ref stack);
break;
}
return stack.Pop();
}
#endregion
#region Helper routines
private void EvaluateFunction(string func, ref Stack<double> stack)
{
switch (func)
{
case "sin": stack.Push(Math.Sin(stack.Pop())); break;
case "sinh": stack.Push(Math.Sinh(stack.Pop())); break;
case "cos": stack.Push(Math.Cos(stack.Pop())); break;
case "cosh": stack.Push(Math.Cosh(stack.Pop())); break;
case "tan": stack.Push(Math.Tan(stack.Pop())); break;
case "tanh": stack.Push(Math.Tanh(stack.Pop())); break;
case "ctan": stack.Push(1 / Math.Tan(stack.Pop())); break;
case "arcsin": stack.Push(Math.Asin(stack.Pop())); break;
case "asin": stack.Push(Math.Asin(stack.Pop())); break;
case "arccos": stack.Push(Math.Acos(stack.Pop())); break;
case "acos": stack.Push(Math.Acos(stack.Pop())); break;
case "arctan": stack.Push(Math.Atan(stack.Pop())); break;
case "atan": stack.Push(Math.Atan(stack.Pop())); break;
case "truncate":
case "int": stack.Push(Math.Truncate(stack.Pop())); break;
case "floor": stack.Push(Math.Floor(stack.Pop())); break;
case "ceil":
case "ceiling": stack.Push(Math.Ceiling(stack.Pop())); break;
case "sqrt": stack.Push(Math.Sqrt(stack.Pop())); break;
case "cbrt": stack.Push(Math.Pow(stack.Pop(), 1.0 / 3.0)); break;
case "root": stack.Push(Math.Pow(stack.Pop(), 1 / stack.Pop())); break;
case "abs": stack.Push(Math.Abs(stack.Pop())); break;
case "max": stack.Push(Math.Max(stack.Pop(), stack.Pop())); break;
case "min": stack.Push(Math.Min(stack.Pop(), stack.Pop())); break;
case "round": {
double dec = stack.Pop(), val = stack.Pop();
dec = Math.Max(0, dec);
dec = Math.Min(15, dec);
stack.Push(Math.Round(val, Convert.ToInt32(dec)));
break;
}
case "lg": stack.Push(Math.Log10(stack.Pop())); break;
case "log": stack.Push(Math.Log(stack.Pop(), stack.Pop())); break;
case "ln": stack.Push(Math.Log(stack.Pop(), Math.E)); break;
default: throw new Exception("Undefined function '" + func + "'.");
}
}
private static bool IsLeftAssociative(string op)
{
return (op != "^");
}
private static int Precedence(string op)
{
switch (op)
{
case "+":
case "-": return 1;
case "*":
case "/":
case "%": return 2;
case "^": return 3;
case "!-": return 10;
default: return 0;
}
}
private static bool IsOperator(char c)
{
const string operators = "+-*/%^";
return operators.Contains(c);
}
private static bool IsFunction(string s, int index)
{
// Skip function/variable name
while (index < s.Length && char.IsLetterOrDigit(s[index])) index++;
while (index < s.Length && char.IsWhiteSpace(s[index])) index++;
// End of string? Than it's a variable
if (index >= s.Length) return false;
// If an operator, function separator, or ), variable
if (s[index] == '(') return true;
return false;
}
private static string GetVariable(string s, ref int index)
{
StringBuilder str = new StringBuilder();
while (index < s.Length && (char.IsLetterOrDigit(s[index])))
str.Append(s[index++]);
index -= 1;
return str.ToString();
}
private static string GetLiteral(string s, ref int index)
{
StringBuilder str = new StringBuilder();
while (index < s.Length && (char.IsDigit(s[index]) || s[index] == '.'))
str.Append(s[index++]);
index -= 1;
return str.ToString();
}
#endregion
}
}

View File

@ -0,0 +1,116 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace GraphingCalculator
{
public static class Integrator
{
#region Settings
private static int maximumRecursionDepth = 16;
public static int MaximumRecursionDepth
{
get { return maximumRecursionDepth; }
set { maximumRecursionDepth = value; }
}
private static double initialEpsilon = 1e-10;
public static double InitialEpsilon
{
get { return initialEpsilon; }
set { initialEpsilon = value; }
}
#endregion
#region Some variables
private static string variable = "x";
private static Expression expression;
private static Dictionary<double, double> results = new Dictionary<double, double>();
#endregion
#region Swap function
private static void Swap(ref double a, ref double b)
{
double c = a;
a = b;
b = c;
}
#endregion
private static double EvaluateCache(double x)
{
if (!results.ContainsKey(x))
{
expression.Variables[variable] = x;
results[x] = expression.Evaluate();
}
return results[x];
}
private static double CalculateIntegralAux(double xA, double xB, double epsilon, double S, double yA, double yB, double yC, int depth)
{
double xC = (xA + xB) / 2;
double width = (xB - xA);
double xD = (xA + xC) / 2;
double xE = (xC + xB) / 2;
double yD = EvaluateCache(xD);
double yE = EvaluateCache(xE);
double Sleft = (width / 12) * (yA + 4 * yD + yC);
double Sright = (width / 12) * (yC + 4 * yE + yB);
double S2 = Sleft + Sright;
if (depth <= 0 || Math.Abs(S2 - S) <= 15 * epsilon)
return S2 + (S2 - S) / 15;
return CalculateIntegralAux(xA, xC, epsilon / 2, Sleft, yA, yC, yD, depth - 1) +
CalculateIntegralAux(xC, xB, epsilon / 2, Sright, yC, yB, yE, depth - 1);
}
private static double CalculateIntegral(double xA, double xB, double epsilon, int maxDepth)
{
double xC = (xA + xB) / 2;
double width = xB - xA;
double yA = EvaluateCache(xA);
double yC = EvaluateCache(xC);
double yB = EvaluateCache(xB);
double S = (width / 6) * (yA + 4 * yC + yB);
return CalculateIntegralAux(xA, xB, epsilon, S, yA, yB, yC, maxDepth);
}
/// <summary>
/// Calculates a definite integral (the area between the function graph and the X axis, where x ranges between beg and end.
/// </summary>
/// <param name="expr">An expression to integrate.</param>
/// <param name="beg">Beginning of the interval</param>
/// <param name="end">End of the interval</param>
/// <param name="var">The name of the variable, by default is 'x'</param>
public static double Integrate(Expression expr, double beg, double end, string var = "x")
{
double result = 0;
bool changeSign = false;
// Make sure beg < end
if (beg > end)
{
Swap(ref beg, ref end);
changeSign = true;
}
// Initialization
results.Clear();
variable = var;
expression = expr;
// Calculation
result = CalculateIntegral(beg, end, initialEpsilon, maximumRecursionDepth);
if (changeSign) return -result;
return result;
}
}
}

View File

@ -0,0 +1,64 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Media;
namespace GraphingCalculator
{
public class VisualExpression : Expression
{
private static int rand_seed = 0x250D;
#region Variables
private Color color = Colors.Blue;
public Color Color { get { return color; } set { color = value; } }
private double thickness = 2;
public double Thickness { get { return thickness; } set { thickness = value; } }
public bool IsVisible { get; set; }
#endregion
#region Constructors
public VisualExpression() : base()
{
SetRandomColor();
IsVisible = true;
}
public VisualExpression(string expr) : base(expr)
{
SetRandomColor();
IsVisible = true;
}
public VisualExpression(string expr, Color color, double thickness = 2) : base(expr)
{
this.Color = color;
this.Thickness = thickness;
IsVisible = true;
}
#endregion
public void SetRandomColor()
{
Random random = new Random(rand_seed);
rand_seed = 0x51 * (random.Next() - 0xA82F90) * random.Next() - 0x513511;
int r, g, b;
r = random.Next(256);
g = random.Next(256);
b = random.Next(256);
int avg = (r + g + b) / 3;
int min = Math.Min(r, Math.Min(g, b));
if (avg >= 182) {
r -= min; g -= min; b -= min;
}
this.Color = Color.FromRgb(Convert.ToByte(r), Convert.ToByte(g), Convert.ToByte(b));
}
}
}

View File

@ -0,0 +1,187 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{A1B63EB2-82CF-4589-8AE2-18FAAF51B662}</ProjectGuid>
<OutputType>WinExe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>GraphingCalculator</RootNamespace>
<AssemblyName>GraphingCalculator</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<TargetFrameworkProfile>Client</TargetFrameworkProfile>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<PlatformTarget>x86</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<PlatformTarget>x86</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup>
<NoWin32Manifest>true</NoWin32Manifest>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release - Publish|x86'">
<OutputPath>..\..\TibisMathematicsSuite - Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisIgnoreBuiltInRuleSets>true</CodeAnalysisIgnoreBuiltInRuleSets>
<CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules>
<CodeAnalysisFailOnMissingRules>false</CodeAnalysisFailOnMissingRules>
</PropertyGroup>
<PropertyGroup>
<ApplicationIcon>graphing-logo.ico</ApplicationIcon>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="System.Xaml">
<RequiredTargetFramework>4.0</RequiredTargetFramework>
</Reference>
<Reference Include="WindowsBase" />
<Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" />
</ItemGroup>
<ItemGroup>
<ApplicationDefinition Include="App.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</ApplicationDefinition>
<Compile Include="Controls\IntegralWindow.xaml.cs">
<DependentUpon>IntegralWindow.xaml</DependentUpon>
</Compile>
<Compile Include="Controls\EvaluateWindow.xaml.cs">
<DependentUpon>EvaluateWindow.xaml</DependentUpon>
</Compile>
<Compile Include="Expression\Integrator.cs" />
<Compile Include="Expression\VisualExpression.cs" />
<Compile Include="Controls\SettingsWindow.xaml.cs">
<DependentUpon>SettingsWindow.xaml</DependentUpon>
</Compile>
<Page Include="Controls\IntegralWindow.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Controls\EvaluateWindow.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Controls\GraphingCanvas.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Controls\LogWindow.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="MainWindow.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Compile Include="App.xaml.cs">
<DependentUpon>App.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Compile Include="Bounds.cs" />
<Compile Include="Expression\Expression.cs" />
<Compile Include="Controls\GraphingCanvas.xaml.cs">
<DependentUpon>GraphingCanvas.xaml</DependentUpon>
</Compile>
<Compile Include="IO\ExpressionFile.cs" />
<Compile Include="Log.cs" />
<Compile Include="Controls\LogWindow.xaml.cs">
<DependentUpon>LogWindow.xaml</DependentUpon>
</Compile>
<Compile Include="MainWindow.xaml.cs">
<DependentUpon>MainWindow.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Page Include="Controls\SettingsWindow.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Styles\ButtonStyle.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Styles\GroupBoxStyle.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Styles\RadioButtonStyle.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Styles\WarningGroupBoxStyle.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
</ItemGroup>
<ItemGroup>
<Compile Include="Properties\AssemblyInfo.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<Compile Include="Properties\Settings.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
<None Include="app.config" />
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
<AppDesigner Include="Properties\" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Launcher\DynamicLink.csproj">
<Project>{A04B247B-6A95-462B-9E07-3337A1C158F1}</Project>
<Name>Launcher</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Resource Include="graphing-logo.ico" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@ -0,0 +1,88 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace GraphingCalculator.IO
{
public class ExpressionFile
{
private List<VisualExpression> expressions = new List<VisualExpression>();
public List<VisualExpression> Expressions { get { return expressions; } }
public void SaveToFile(string filename)
{
System.Xml.XmlWriter writer = System.Xml.XmlWriter.Create(filename, new System.Xml.XmlWriterSettings() { Indent = true });
writer.WriteStartDocument();
writer.WriteStartElement("Document");
// Write expressions
writer.WriteStartElement("ExpressionList");
foreach (var i in Expressions)
{
writer.WriteStartElement("Expression");
writer.WriteAttributeString("String", i.ExpressionString);
writer.WriteAttributeString("IsVisible", i.IsVisible.ToString());
writer.WriteAttributeString("Color", i.Color.ToString());
foreach (var j in i.Variables)
{
writer.WriteStartElement("Variable");
writer.WriteAttributeString("Key", j.Key);
writer.WriteAttributeString("Value", j.Value.ToString());
writer.WriteEndElement();
}
writer.WriteEndElement();
}
writer.WriteEndElement();
// Finish
writer.WriteEndElement();
writer.WriteEndDocument();
writer.Close();
}
public void LoadFromFile(string filename)
{
System.Xml.XmlReader reader = System.Xml.XmlReader.Create(filename);
string varKey = "", varVal = "";
VisualExpression expr;
while (reader.Read())
switch (reader.NodeType)
{
case System.Xml.XmlNodeType.Element:
// Read an expression
if (reader.Name == "Expression")
{
expr = new VisualExpression();
while (reader.MoveToNextAttribute()) {
if (reader.Name == "String") expr.ExpressionString = reader.Value;
else if (reader.Name == "IsVisible") expr.IsVisible = bool.Parse(reader.Value);
else if (reader.Name == "Color") expr.Color = (System.Windows.Media.Color) System.Windows.Media.ColorConverter.ConvertFromString(reader.Value);
}
this.Expressions.Add(expr);
}
// A variable
else if (reader.Name == "Variable")
{
while (reader.MoveToNextAttribute()) {
if (reader.Name == "Key") varKey = reader.Value;
else if (reader.Name == "Value") varVal = reader.Value;
}
if (varKey != "")
this.Expressions.Last().Variables[varKey] = double.Parse(varVal);
}
break;
}
reader.Close();
}
}
}

View File

@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace GraphingCalculator
{
public static class Log
{
private static List<string> entries = new List<string>();
public static List<string> Entries { get { return entries; } }
public static void LogEvent (string format, params object[] p)
{
entries.Add(DateTime.Now + ": " + String.Format(format, p));
}
}
}

View File

@ -0,0 +1,163 @@
<Window x:Class="GraphingCalculator.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:my="clr-namespace:GraphingCalculator"
Title="Graphing Calculator" Height="526" Width="891"
MouseWheel="Window_MouseWheel"
KeyDown="Window_KeyDown" Icon="/GraphingCalculator;component/graphing-logo.ico">
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Styles\GroupBoxStyle.xaml" />
<ResourceDictionary Source="Styles\ButtonStyle.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="200px" />
<ColumnDefinition Width="5px" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Menu Grid.ColumnSpan="100">
<MenuItem Header="_File">
<MenuItem Name="menuFileSave" Header="Save plotted expressions..."
Click="menuFileSave_Click" InputGestureText="Ctrl+S"/>
<MenuItem Name="menuFileImport" Header="Import..."
Click="menuFileImport_Click" InputGestureText="Ctrl+O"/>
<Separator />
<MenuItem Name="menuFileExit" Header="Exit" Click="menuFileExit_Click"
InputGestureText="Ctrl+Q"/>
</MenuItem>
<MenuItem Header="_Application">
<MenuItem Name="menuAppLog" Header="View log..." Click="menuAppLog_Click"/>
<MenuItem Name="menuAppPref" Header="Preferences" Click="menuAppPref_Click" />
</MenuItem>
<MenuItem Header="_Help">
<MenuItem Name="menuAbout" Header="_About" Click="menuAbout_Click"
InputGestureText="Ctrl+F1"/>
<MenuItem Name="menuHelp" Header="_Help" Click="menuHelp_Click"
InputGestureText="F1"/>
</MenuItem>
</Menu>
<Border Grid.Row="2" Grid.Column="0">
<Border.Background>
<LinearGradientBrush StartPoint="0,0" EndPoint=".5,1">
<GradientStop Color="#EEE" Offset="0" />
<GradientStop Color="#BBB" Offset="1" />
</LinearGradientBrush>
</Border.Background>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<!-- Input box -->
<GroupBox Header="Input" Grid.Row="0">
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<TextBox Name="inputExpression"
TextWrapping="Wrap" Height="50px"
Grid.ColumnSpan="10" Margin="0,0,0,1" />
<Button Name="buttonPlot" Grid.Row="1" Grid.Column="0" Click="buttonPlot_Click">Plot</Button>
<Button Name="buttonEvaluate" Grid.Row="1" Grid.Column="1" Click="buttonEvaluate_Click">Evaluate</Button>
<Button Name="buttonIntegrate" Grid.Row="1" Grid.Column="2" Click="buttonIntegrate_Click">Integrate</Button>
</Grid>
</GroupBox>
<!-- Plotted functions list -->
<GroupBox Header="Plotted expressions" Grid.Row="1">
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<ListBox Name="listExpressions" Grid.ColumnSpan="10" Margin="0,0,0,1"/>
<Button Name="buttonDelete" Grid.Row="1" Grid.Column="0" Click="buttonDelete_Click">Delete</Button>
<Button Name="buttonClear" Grid.Row="1" Grid.Column="1" Click="buttonClear_Click">Clear</Button>
<Button Name="buttonHideAll" Grid.Row="1" Grid.Column="2" Click="buttonHideAll_Click">Hide all</Button>
</Grid>
</GroupBox>
<!-- Range box -->
<GroupBox Header="Range" Grid.Row="2">
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="2*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Row="0" VerticalAlignment="Center">Bottom:</TextBlock>
<TextBlock Grid.Row="1" VerticalAlignment="Center">Left:</TextBlock>
<TextBlock Grid.Row="2" VerticalAlignment="Center">Top:</TextBlock>
<TextBlock Grid.Row="3" VerticalAlignment="Center">Right:</TextBlock>
<TextBox Name="inputBoundsBottom" Grid.Column="1" Grid.Row="0" />
<TextBox Name="inputBoundsLeft" Grid.Column="1" Grid.Row="1" />
<TextBox Name="inputBoundsTop" Grid.Column="1" Grid.Row="2" />
<TextBox Name="inputBoundsRight" Grid.Column="1" Grid.Row="3" />
<Button Name="buttonChangeBounds" Margin="1,2,1,1"
Grid.Row="4" Grid.ColumnSpan="10"
Click="buttonChangeBounds_Click">Change</Button>
</Grid>
</GroupBox>
</Grid>
</Border>
<GridSplitter Grid.Column="1" Grid.Row="2" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"/>
<my:GraphingCanvas x:Name="graphingCanvas" Grid.Column="2" Grid.Row="2" />
</Grid>
</Window>

View File

@ -0,0 +1,389 @@
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 GraphingCalculator
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
#region Constructor
public MainWindow()
{
InitializeComponent();
// Update textboxes
graphingCanvas.CanvasBounds.BoundsChanged += new EventHandler(CanvasBounds_BoundsChanged);
graphingCanvas.CanvasBounds.Right = graphingCanvas.CanvasBounds.Right;
}
#endregion
#region Function list
private void updateList()
{
listExpressions.Items.Clear();
foreach (var i in graphingCanvas.Expressions)
{
CheckBox chk = new CheckBox();
chk.Content = i.ExpressionString;
chk.IsChecked = i.IsVisible;
chk.Foreground = new SolidColorBrush(i.Color);
chk.FontWeight = FontWeights.Bold;
chk.Click += new RoutedEventHandler(Visibility_Checked);
listExpressions.Items.Add(chk);
}
}
void Visibility_Checked(object sender, RoutedEventArgs e)
{
int index = listExpressions.Items.IndexOf(sender);
CheckBox c = sender as CheckBox;
if (index < 0 || c == null || !c.IsChecked.HasValue) return;
graphingCanvas.SetExpressionVisibility(index, c.IsChecked.Value);
}
private void buttonDelete_Click(object sender, RoutedEventArgs e)
{
int index = listExpressions.SelectedIndex;
if (index == -1) return;
listExpressions.Items.RemoveAt(index);
graphingCanvas.Expressions.RemoveAt(index);
graphingCanvas.EvaluateExpressions();
graphingCanvas.Redraw();
}
private void buttonClear_Click(object sender, RoutedEventArgs e)
{
listExpressions.Items.Clear();
graphingCanvas.Expressions.Clear();
graphingCanvas.EvaluateExpressions();
graphingCanvas.Redraw();
}
private void buttonHideAll_Click(object sender, RoutedEventArgs e)
{
for (int i = 0; i < listExpressions.Items.Count; i++)
{
CheckBox c = listExpressions.Items[i] as CheckBox;
if (c != null) c.IsChecked = false;
graphingCanvas.SetExpressionVisibility(i, false);
}
}
#endregion
#region Keyboard/mouse input
private void Window_MouseWheel(object sender, MouseWheelEventArgs e)
{
graphingCanvas.PeformMouseWheelChange(e);
}
private bool EditingTextbox()
{
TextBox box = Keyboard.FocusedElement as TextBox;
return (box != null);
}
private void Window_KeyDown(object sender, KeyEventArgs e)
{
e.Handled = true;
if (e.KeyboardDevice.Modifiers == ModifierKeys.None)
{
switch (e.Key)
{
case Key.F1: menuHelp_Click(this, new RoutedEventArgs()); break;
case Key.NumPad8:
case Key.Up:
if (!EditingTextbox()) graphingCanvas.PerformMoveUp();
else e.Handled = false;
break;
case Key.NumPad4:
case Key.Left:
if (!EditingTextbox()) graphingCanvas.PerformMoveLeft();
else e.Handled = false;
break;
case Key.NumPad6:
case Key.Right:
if (!EditingTextbox()) graphingCanvas.PerformMoveRight();
else e.Handled = false;
break;
case Key.NumPad2:
case Key.Down:
if (!EditingTextbox()) graphingCanvas.PerformMoveDown();
else e.Handled = false;
break;
case Key.NumPad5:
if (!EditingTextbox()) graphingCanvas.PerformReset();
else e.Handled = false;
break;
case Key.Add:
if (!EditingTextbox()) graphingCanvas.PerformZoomIn();
else e.Handled = false;
break;
case Key.Subtract:
if (!EditingTextbox()) graphingCanvas.PerformZoomOut();
else e.Handled = false;
break;
case Key.Enter: buttonPlot_Click(this, new RoutedEventArgs()); break;
default: e.Handled = false; break;
}
}
else if (Keyboard.Modifiers == ModifierKeys.Control)
{
if (e.Key == Key.F1) menuAbout_Click(this, new RoutedEventArgs());
else if (e.Key == Key.S) menuFileSave_Click(this, new RoutedEventArgs());
else if (e.Key == Key.O) menuFileImport_Click(this, new RoutedEventArgs());
else if (e.Key == Key.Q) menuFileExit_Click(this, new RoutedEventArgs());
else e.Handled = false;
}
else e.Handled = false;
}
#endregion
#region Buttons
private void buttonPlot_Click(object sender, RoutedEventArgs e)
{
if (inputExpression.Text == "") return;
VisualExpression expr = new VisualExpression();
try
{
expr.ExpressionString = inputExpression.Text;
expr.Process();
expr.Variables["x"] = expr.Variables["X"] = 0;
expr.Evaluate();
}
catch (Exception ex)
{
MessageBox.Show("Error: " + ex.Message, "Error!");
#region Log
Log.LogEvent("Failed to plot expression '{0}'. Message: {1}", expr.ExpressionString, ex.Message);
Log.LogEvent("> Stack trace: {0}", ex.StackTrace);
#endregion
return;
}
graphingCanvas.AddExpression(expr);
updateList();
}
private void buttonEvaluate_Click(object sender, RoutedEventArgs e)
{
EvaluateWindow window = new EvaluateWindow(inputExpression.Text);
window.Show();
}
private void buttonIntegrate_Click(object sender, RoutedEventArgs e)
{
Controls.IntegralWindow window = new Controls.IntegralWindow(inputExpression.Text);
window.Show();
}
private bool IsNanInf (params double[] items)
{
bool result = false;
foreach (var i in items)
result = result || double.IsNaN(i) || double.IsInfinity(i);
return result;
}
private void buttonChangeBounds_Click(object sender, RoutedEventArgs e)
{
Expression el, er, et, eb;
double l, r, t, b;
bool ok = true;
// Initialize stuff
el = new Expression(inputBoundsLeft.Text);
er = new Expression(inputBoundsRight.Text);
et = new Expression(inputBoundsTop.Text);
eb = new Expression(inputBoundsBottom.Text);
l = r = t = b = 0;
// Initialize visuals
inputBoundsLeft.Background = SystemColors.WindowBrush;
inputBoundsTop.Background = SystemColors.WindowBrush;
inputBoundsRight.Background = SystemColors.WindowBrush;
inputBoundsBottom.Background = SystemColors.WindowBrush;
// Evaluate left
try { l = el.Evaluate(); }
catch {
if (!double.TryParse(el.ExpressionString, out l)) {
inputBoundsLeft.Background = Brushes.Pink; ok = false;
}
}
// Evaluate top
try { t = et.Evaluate(); }
catch {
if (!double.TryParse(et.ExpressionString, out t)) {
inputBoundsTop.Background = Brushes.Pink; ok = false;
}
}
// Evaluate right
try { r = er.Evaluate(); }
catch {
if (!double.TryParse(er.ExpressionString, out r)) {
inputBoundsRight.Background = Brushes.Pink; ok = false;
}
}
// Evaluate bottom
try { b = eb.Evaluate(); }
catch {
if (!double.TryParse(eb.ExpressionString, out b)) {
inputBoundsBottom.Background = Brushes.Pink; ok = false;
}
}
// Preview results
inputBoundsTop.Text = Math.Round(t, 15).ToString();
inputBoundsLeft.Text = Math.Round(l, 15).ToString();
inputBoundsRight.Text = Math.Round(r, 15).ToString();
inputBoundsBottom.Text = Math.Round(b, 15).ToString();
// Verify
if (ok)
{
if (l >= r || b >= t || IsNanInf(l, r, b, t)) MessageBox.Show("Invalid interval! Make sure left is smaller than right, bottom is smaller than top, and the intervals are finite.", "Error");
else graphingCanvas.SetCanvasBounds(new Bounds(l, t, r, b));
}
}
#endregion
#region Menu items
private void menuFileSave_Click(object sender, RoutedEventArgs e)
{
Microsoft.Win32.SaveFileDialog save = new Microsoft.Win32.SaveFileDialog();
save.Filter = "XML Expression list|*.xml|All files|*.*";
save.Title = "Save expression list...";
bool? result = save.ShowDialog();
if (!result.HasValue || !result.Value) return;
IO.ExpressionFile file = new IO.ExpressionFile();
file.Expressions.AddRange(graphingCanvas.Expressions);
try { file.SaveToFile(save.FileName); }
catch (Exception ex)
{
MessageBox.Show("Error: " + ex.Message, "Error!");
Log.LogEvent("Failed to save to file '{0}': {1}", save.FileName, ex.Message);
Log.LogEvent("> Stack trace: {0}", ex.StackTrace);
}
}
private void menuFileImport_Click(object sender, RoutedEventArgs e)
{
IO.ExpressionFile file = new IO.ExpressionFile();
Microsoft.Win32.OpenFileDialog open = new Microsoft.Win32.OpenFileDialog();
bool? res;
// Show dialog
open.Filter = "XML Expression list|*.xml|All files|*.*";
open.Title = "Import expression list";
res = open.ShowDialog();
if (!res.HasValue || !res.Value) return;
// Try to load data
try {
file.LoadFromFile(open.FileName);
}
catch (Exception ex) {
MessageBox.Show("Error: " + ex.Message, "Error!");
Log.LogEvent("Failed to import from file '{0}': {1}", open.FileName, ex.Message);
Log.LogEvent("> Stack trace: {0}", ex.StackTrace);
}
// Add expressions to our list
foreach (var i in file.Expressions)
this.graphingCanvas.AddExpression(i);
updateList();
}
private void menuFileExit_Click(object sender, RoutedEventArgs e)
{
this.Close();
}
private void menuAppLog_Click(object sender, RoutedEventArgs e)
{
new LogWindow().Show();
}
private void menuAppPref_Click(object sender, RoutedEventArgs e)
{
new SettingsWindow().ShowDialog();
graphingCanvas.SetCanvasBounds(graphingCanvas.CanvasBounds);
}
private void menuHelp_Click(object sender, RoutedEventArgs e)
{
DynamicLink.Launcher.StartModule("Help", "graphingcalc");
}
private void menuAbout_Click(object sender, RoutedEventArgs e)
{
DynamicLink.Launcher.About();
}
#endregion
#region Misc
void CanvasBounds_BoundsChanged(object sender, EventArgs e)
{
int p = GraphingCalculator.Properties.Settings.Default.RoundDoublesGraph;
this.inputBoundsBottom.Text = Math.Round(graphingCanvas.CanvasBounds.Bottom, p).ToString();
this.inputBoundsLeft.Text = Math.Round(graphingCanvas.CanvasBounds.Left, p).ToString();
this.inputBoundsTop.Text = Math.Round(graphingCanvas.CanvasBounds.Top, p).ToString();
this.inputBoundsRight.Text = Math.Round(graphingCanvas.CanvasBounds.Right, p).ToString();
#region Log
Log.LogEvent("Canvas bounds changed: left={0}; top={1}; right={2}; bottom={3}", this.inputBoundsLeft.Text,
this.inputBoundsTop.Text, this.inputBoundsRight.Text, this.inputBoundsBottom.Text);
#endregion
}
#endregion
}
}

View File

@ -0,0 +1,55 @@
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Windows;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Graphing Calculator")]
[assembly: AssemblyDescription("Plots expressions, and calculates integrals and limits.")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Tibi Software")]
[assembly: AssemblyProduct("Tibi's Mathematics Suite")]
[assembly: AssemblyCopyright("Copyright © 2012")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
//In order to begin building localizable applications, set
//<UICulture>CultureYouAreCodingWith</UICulture> in your .csproj file
//inside a <PropertyGroup>. For example, if you are using US english
//in your source files, set the <UICulture> to en-US. Then uncomment
//the NeutralResourceLanguage attribute below. Update the "en-US" in
//the line below to match the UICulture setting in the project file.
//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
[assembly: ThemeInfo(
ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
//(used if a resource is not found in the page,
// or application resource dictionaries)
ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
//(used if a resource is not found in the page,
// app, or any theme specific resource dictionaries)
)]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@ -0,0 +1,71 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.261
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace GraphingCalculator.Properties
{
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources
{
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources()
{
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager
{
get
{
if ((resourceMan == null))
{
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("GraphingCalculator.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture
{
get
{
return resourceCulture;
}
set
{
resourceCulture = value;
}
}
}
}

View File

@ -0,0 +1,117 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@ -0,0 +1,86 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.261
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace GraphingCalculator.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
public static Settings Default {
get {
return defaultInstance;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("600")]
public double PlotPrecision {
get {
return ((double)(this["PlotPrecision"]));
}
set {
this["PlotPrecision"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("41")]
public double GridDensity {
get {
return ((double)(this["GridDensity"]));
}
set {
this["GridDensity"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("4")]
public int RoundDoublesGraph {
get {
return ((int)(this["RoundDoublesGraph"]));
}
set {
this["RoundDoublesGraph"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("0.1")]
public double NavigationSensitivity {
get {
return ((double)(this["NavigationSensitivity"]));
}
set {
this["NavigationSensitivity"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("1.075")]
public double ZoomSensitivity {
get {
return ((double)(this["ZoomSensitivity"]));
}
set {
this["ZoomSensitivity"] = value;
}
}
}
}

View File

@ -0,0 +1,21 @@
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)" GeneratedClassNamespace="GraphingCalculator.Properties" GeneratedClassName="Settings">
<Profiles />
<Settings>
<Setting Name="PlotPrecision" Type="System.Double" Scope="User">
<Value Profile="(Default)">600</Value>
</Setting>
<Setting Name="GridDensity" Type="System.Double" Scope="User">
<Value Profile="(Default)">41</Value>
</Setting>
<Setting Name="RoundDoublesGraph" Type="System.Int32" Scope="User">
<Value Profile="(Default)">4</Value>
</Setting>
<Setting Name="NavigationSensitivity" Type="System.Double" Scope="User">
<Value Profile="(Default)">0.1</Value>
</Setting>
<Setting Name="ZoomSensitivity" Type="System.Double" Scope="User">
<Value Profile="(Default)">1.075</Value>
</Setting>
</Settings>
</SettingsFile>

View File

@ -0,0 +1,55 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style TargetType="Button">
<Setter Property="Margin" Value="1" />
<Setter Property="MinHeight" Value="22" />
<Setter Property="SnapsToDevicePixels" Value="True" />
<Setter Property="OverridesDefaultStyle" Value="True" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border Name="border" Padding="2" CornerRadius="4"
BorderBrush="Gray" BorderThickness="1">
<Border.Background>
<LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
<GradientStop Color="#EEE" Offset="0" />
<GradientStop Color="#BBB" Offset="1" />
</LinearGradientBrush>
</Border.Background>
<ContentPresenter HorizontalAlignment="Center"
VerticalAlignment="Center" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="border" Property="Background">
<Setter.Value>
<LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
<GradientStop Color="#FFF" Offset="0" />
<GradientStop Color="#C8C8C8" Offset="1" />
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter TargetName="border" Property="Background">
<Setter.Value>
<LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
<GradientStop Color="#BBB" Offset="0" />
<GradientStop Color="#DDD" Offset="1" />
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>

View File

@ -0,0 +1,40 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style TargetType="GroupBox">
<Setter Property="SnapsToDevicePixels" Value="True" />
<Setter Property="OverridesDefaultStyle" Value="True" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="GroupBox">
<Border Background="#FAF8F8"
BorderBrush="White"
BorderThickness="1"
CornerRadius="5"
Margin="4">
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch" >
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition />
</Grid.RowDefinitions>
<ContentPresenter Margin="3,0,0,0" ContentSource="Header" >
<ContentPresenter.Resources>
<Style TargetType="TextBlock">
<Setter Property="Foreground" Value="Gray" />
</Style>
</ContentPresenter.Resources>
</ContentPresenter>
<ContentPresenter HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Margin="4" Grid.Row="1" />
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>

View File

@ -0,0 +1,63 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style TargetType="RadioButton">
<Setter Property="SnapsToDevicePixels" Value="True" />
<Setter Property="OverridesDefaultStyle" Value="True" />
<Setter Property="TextBlock.TextAlignment" Value="Center" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="RadioButton">
<Grid>
<Border Name="border" BorderBrush="Gray" BorderThickness="1">
<Border.Background>
<LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
<GradientStop Color="#EEE" Offset="0" />
<GradientStop Color="#BBB" Offset="1" />
</LinearGradientBrush>
</Border.Background>
</Border>
<ContentPresenter Margin="4,1,4,1" />
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="Background" Value="White">
<Setter TargetName="border" Property="CornerRadius" Value="5,0,0,5" />
<Setter TargetName="border" Property="BorderThickness" Value="1,1,0,1" />
</Trigger>
<Trigger Property="Background" Value="Black">
<Setter TargetName="border" Property="CornerRadius" Value="0,5,5,0" />
<Setter TargetName="border" Property="BorderThickness" Value="1,1,1,1" />
</Trigger>
<Trigger Property="Background" Value="Gray">
<Setter TargetName="border" Property="CornerRadius" Value="0" />
<Setter TargetName="border" Property="BorderThickness" Value="1,1,0,1" />
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="border" Property="Background">
<Setter.Value>
<LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
<GradientStop Color="#FFF" Offset="0" />
<GradientStop Color="#C8C8C8" Offset="1" />
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="IsChecked" Value="True">
<Setter TargetName="border" Property="Background">
<Setter.Value>
<LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
<GradientStop Color="#BBB" Offset="0" />
<GradientStop Color="#DDD" Offset="1" />
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>

View File

@ -0,0 +1,58 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style x:Key="WarningGroupBox" TargetType="{x:Type GroupBox}">
<Setter Property="SnapsToDevicePixels" Value="True" />
<Setter Property="OverridesDefaultStyle" Value="True" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GroupBox}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
<Border Grid.RowSpan="2" BorderBrush="Yellow"
BorderThickness="1" CornerRadius="5" >
<Border.Background>
<LinearGradientBrush MappingMode="Absolute"
SpreadMethod="Repeat"
StartPoint="0,0"
EndPoint="5,5">
<GradientStop Color="#fde245" Offset=".5" />
<GradientStop Color="#caae65" Offset=".5" />
</LinearGradientBrush>
</Border.Background>
</Border>
<Border Grid.RowSpan="2" CornerRadius="5">
<Border.Background>
<RadialGradientBrush GradientOrigin=".5,0" Center=".5,.1"
RadiusX=".9" RadiusY=".8" >
<GradientStop Color="#e0FFFFFF" Offset="0" />
<GradientStop Color="#10FFFFFF" Offset="1" />
</RadialGradientBrush>
</Border.Background>
</Border>
<ContentPresenter Margin="7,4,4,0" ContentSource="Header" >
<ContentPresenter.Resources>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="FontWeight" Value="Bold" />
<Setter Property="Foreground" Value="#835f01" />
</Style>
</ContentPresenter.Resources>
</ContentPresenter>
<ContentPresenter HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Margin="5" Grid.Row="1" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>

View File

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
<section name="GraphingCalculator.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
</sectionGroup>
</configSections>
<userSettings>
<GraphingCalculator.Properties.Settings>
<setting name="PlotPrecision" serializeAs="String">
<value>600</value>
</setting>
<setting name="GridDensity" serializeAs="String">
<value>41</value>
</setting>
<setting name="RoundDoublesGraph" serializeAs="String">
<value>4</value>
</setting>
<setting name="NavigationSensitivity" serializeAs="String">
<value>0.1</value>
</setting>
<setting name="ZoomSensitivity" serializeAs="String">
<value>1.075</value>
</setting>
</GraphingCalculator.Properties.Settings>
</userSettings>
</configuration>

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB