diff --git a/Docs/documentation-ro.pdf b/Docs/documentation-ro.pdf new file mode 100644 index 0000000..37091ea Binary files /dev/null and b/Docs/documentation-ro.pdf differ diff --git a/Docs/proiect.doc b/Docs/proiect.doc new file mode 100644 index 0000000..a7c4ea7 Binary files /dev/null and b/Docs/proiect.doc differ diff --git a/Docs/screen0.png b/Docs/screen0.png new file mode 100644 index 0000000..3facc56 Binary files /dev/null and b/Docs/screen0.png differ diff --git a/Docs/screen1.png b/Docs/screen1.png new file mode 100644 index 0000000..3aa8a19 Binary files /dev/null and b/Docs/screen1.png differ diff --git a/Docs/screen2.png b/Docs/screen2.png new file mode 100644 index 0000000..217304f Binary files /dev/null and b/Docs/screen2.png differ diff --git a/Docs/screen3.png b/Docs/screen3.png new file mode 100644 index 0000000..93d8d2f Binary files /dev/null and b/Docs/screen3.png differ diff --git a/Docs/screen4.png b/Docs/screen4.png new file mode 100644 index 0000000..b9821f9 Binary files /dev/null and b/Docs/screen4.png differ diff --git a/Resources/promotional.jpg b/Resources/promotional.jpg new file mode 100644 index 0000000..7e8d847 Binary files /dev/null and b/Resources/promotional.jpg differ diff --git a/Resources/promotional.psd b/Resources/promotional.psd new file mode 100644 index 0000000..099d567 Binary files /dev/null and b/Resources/promotional.psd differ diff --git a/Source/Calculator/ASTRONAU.TTF b/Source/Calculator/ASTRONAU.TTF new file mode 100644 index 0000000..c89f952 Binary files /dev/null and b/Source/Calculator/ASTRONAU.TTF differ diff --git a/Source/Calculator/App.xaml b/Source/Calculator/App.xaml new file mode 100644 index 0000000..b635142 --- /dev/null +++ b/Source/Calculator/App.xaml @@ -0,0 +1,8 @@ + + + + + diff --git a/Source/Calculator/App.xaml.cs b/Source/Calculator/App.xaml.cs new file mode 100644 index 0000000..f57ce38 --- /dev/null +++ b/Source/Calculator/App.xaml.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Configuration; +using System.Data; +using System.Linq; +using System.Windows; + +namespace Calculator +{ + /// + /// Interaction logic for App.xaml + /// + public partial class App : Application + { + + } +} diff --git a/Source/Calculator/Calculator.csproj b/Source/Calculator/Calculator.csproj new file mode 100644 index 0000000..9530c9a --- /dev/null +++ b/Source/Calculator/Calculator.csproj @@ -0,0 +1,144 @@ + + + + Debug + x86 + 8.0.30703 + 2.0 + {D0040DA8-5B61-4B40-AF35-1320C1CC7121} + WinExe + Properties + Calculator + Calculator + v3.5 + 512 + {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + 4 + + + x86 + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + x86 + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + calculator-logo.ico + + + true + + + bin\x86\Release %28Publish%29\ + TRACE + true + pdbonly + x86 + prompt + + + ..\..\TibisMathematicsSuite - Release\ + TRACE + true + pdbonly + x86 + prompt + false + false + + + + + + + + + + + + + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + App.xaml + Code + + + MainWindow.xaml + Code + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + + + + Code + + + True + True + Resources.resx + + + True + Settings.settings + True + + + ResXFileCodeGenerator + Resources.Designer.cs + + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + + + + {A04B247B-6A95-462B-9E07-3337A1C158F1} + DynamicLink + + + + + + + + + + + \ No newline at end of file diff --git a/Source/Calculator/Images/calculator-logo.png b/Source/Calculator/Images/calculator-logo.png new file mode 100644 index 0000000..2d8885f Binary files /dev/null and b/Source/Calculator/Images/calculator-logo.png differ diff --git a/Source/Calculator/MainWindow.xaml b/Source/Calculator/MainWindow.xaml new file mode 100644 index 0000000..67d4843 --- /dev/null +++ b/Source/Calculator/MainWindow.xaml @@ -0,0 +1,298 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2ndf + + + Mem + + + Error + + + + + + + {x} + + + arcsin + + + arcsinh + + + + + + + + eⁿ + + + -Abs + + + arccos + + + arccosh + + + + + + + 10ⁿ + + + + + arctan + + + arctanh + + + xPy + + + + + + + ⁿ√x + + + √x + + + ∛x + + + + + + + Add + + + Subtract + + + Clear + + + Set + + + Recall + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/Calculator/MainWindow.xaml.cs b/Source/Calculator/MainWindow.xaml.cs new file mode 100644 index 0000000..6de0afb --- /dev/null +++ b/Source/Calculator/MainWindow.xaml.cs @@ -0,0 +1,378 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace Calculator +{ + /// + /// Interaction logic for MainWindow.xaml + /// + public partial class MainWindow : Window + { + enum Operator + { + None, Sum, Subtraction, Multiplication, Division, Mod, Logn, Pown, NRoot, Combinations, Arrangements + }; + + enum Stages + { + First, FirstDisplay, Second + }; + + #region Variables + double memory = 0; + bool is2ndOn = false, error = false; + double first = 0, second = 0; + Stages stage = Stages.First; + Operator oper = Operator.None; + + Brush IndicatorColor = (Brushes.Orange); + + #endregion + + #region Properties + public bool Is2ndOn + { + get { return is2ndOn; } + set + { + is2ndOn = value; + Indicator2ndf.Background = (value) ? (IndicatorColor) : (Brushes.Transparent); + } + } + + public bool Error + { + get { return error; } + set + { + error = value; + IndicatorError.Background = (value) ? (IndicatorColor) : (Brushes.Transparent); + } + } + + public double DisplayValue + { + set { Display.Text = value.ToString(); } + get + { + double val; + string temp = Display.Text; + + if (temp.EndsWith(".") || temp.Length == 0) temp += '0'; + if (!Double.TryParse(temp, out val)) + { + Error = true; + val = 0; + } + return val; + } + } + + public string DisplayText + { + get { return Display.Text; } + set { Display.Text = value; } + } + + public double Memory + { + get { return memory; } + set + { + memory = value; + IndicatorMem.Background = (value != 0) ? (IndicatorColor) : (Brushes.Transparent); + } + } + + #endregion + + #region Calculator logics + public MainWindow() + { + InitializeComponent(); + } + + void BinaryOperatorPressed(bool isEqual = false) + { + if (stage == Stages.First) + { + first = DisplayValue; stage = Stages.FirstDisplay; + } + + else if (stage == Stages.Second) + { + second = DisplayValue; + DisplayValue = Calculate(); + + if (isEqual) stage = Stages.First; + else + { + first = DisplayValue; + stage = Stages.FirstDisplay; + } + } + } + + double Calculate() + { + switch (oper) + { + case Operator.Sum: return first + second; + case Operator.Subtraction: return first - second; + case Operator.Multiplication: return first * second; + case Operator.Division: return first / second; + case Operator.Mod: return first % second; + case Operator.Logn: return Math.Log(first, second); + case Operator.Pown: return Math.Pow(first, second); + case Operator.NRoot: return Math.Pow(first, 1.0 / second); + case Operator.Combinations: return MathHelper.Combinations(first, second); + case Operator.Arrangements: return MathHelper.Arrangements(first, second); + } + + return 0; + } + + void AddDigit(char digit) + { + if (stage == Stages.FirstDisplay) { DisplayText = ""; stage = Stages.Second; } + DisplayText += digit; + } + + void SetValue(double value) + { + if (stage == Stages.FirstDisplay) stage = Stages.Second; + DisplayValue = value; + } + + private void Handle_Click(object sender, bool is2nd) + { + var s = sender as Button; + if (s == null) return; + + is2nd = is2nd || Is2ndOn; + if (s.Name != "B2ndf") Is2ndOn = false; + double val = DisplayValue; + + if (DisplayText == "0") DisplayText = ""; + + switch (s.Name) + { + // Column 1 + case "B2ndf": Is2ndOn = !Is2ndOn; break; + case "BInt": + if (!is2nd) SetValue(Math.Floor(val)); + else SetValue(val - Math.Floor(val)); + break; + case "BSin": + if (!is2nd) SetValue(Math.Sin(val)); + else SetValue(Math.Asin(val)); + break; + case "BSinh": + if (!is2nd) SetValue(Math.Sinh(val)); + else SetValue(Math.Log(val + Math.Sqrt(val * val + 1))); + break; + case "BPi": + if (!is2nd) SetValue(Math.PI); + else SetValue(2 * Math.PI); + break; + + // Column 2 + case "BLn": + if (!is2nd) SetValue(Math.Log(val)); + else SetValue(Math.Exp(val)); + break; + case "BAbs": + if (!is2nd) SetValue(Math.Abs(val)); + else SetValue(-Math.Abs(val)); + break; + case "BCos": + if (!is2nd) SetValue(Math.Cos(val)); + else SetValue(Math.Acos(val)); + break; + case "BCosh": + if (!is2nd) SetValue(Math.Cosh(val)); + else SetValue(Math.Log(val + Math.Sqrt(val * val - 1))); + break; + case "BE": SetValue(Math.E); break; + + // Column 3 + case "BLog": + if (!is2nd) SetValue(Math.Log10(val)); + else SetValue(Math.Pow(10, val)); + break; + case "BInverse": SetValue(1 / val); + break; + case "BTan": + if (!is2nd) SetValue(Math.Tan(val)); + else SetValue(Math.Atan(val)); + break; + case "BTanh": + if (!is2nd) SetValue(Math.Tanh(val)); + else SetValue(Math.Log((1+val) * (1-val))/2); + break; + case "BCombinations": + if (!is2nd) oper = Operator.Combinations; + else oper = Operator.Arrangements; + BinaryOperatorPressed(); + break; + + // Column 4 + case "BLogn": + oper = Operator.Logn; + BinaryOperatorPressed(); + break; + case "BPown": + if (!is2nd) oper = Operator.Pown; + else oper = Operator.NRoot; + BinaryOperatorPressed(); + break; + case "BSquare": + if (!is2nd) SetValue(val * val); + else SetValue(Math.Pow(val, 1.0 / 2.0)); + break; + case "BCube": + if (!is2nd) SetValue(val * val * val); + else SetValue(Math.Pow(val, 1.0 / 3.0)); + break; + case "BFact": + SetValue(MathHelper.Factorial(val)); + break; + + // Memory operations + case "BMemAdd": Memory += val; break; + case "BMemSub": Memory -= val; break; + case "BMemClear": Memory = 0; break; + case "BMemSet": Memory = val; break; + case "BMemRecall": SetValue(Memory); break; + + // Numbers + case "BNum7": AddDigit('7'); break; + case "BNum4": AddDigit('4'); break; + case "BNum1": AddDigit('1'); break; + case "BNum0": AddDigit('0'); break; + + // Numbers + case "BNum8": AddDigit('8'); break; + case "BNum5": AddDigit('5'); break; + case "BNum2": AddDigit('2'); break; + + // Numbers + case "BBackspace": if (DisplayText.Length >= 1) DisplayText = DisplayText.Substring(0, DisplayText.Length - 1); break; + case "BNum9": AddDigit('9'); break; + case "BNum6": AddDigit('6'); break; + case "BNum3": AddDigit('3'); break; + case "BPeriod": if (!DisplayText.Contains('.')) AddDigit('.'); break; + + // Ops + case "BClear": SetValue(0); break; + case "BOpDivide": oper = Operator.Division; BinaryOperatorPressed(); break; + case "BOpMultiply": oper = Operator.Multiplication; BinaryOperatorPressed(); break; + case "BOpSub": oper = Operator.Subtraction; BinaryOperatorPressed(); break; + case "BOpAdd": oper = Operator.Sum; BinaryOperatorPressed(); break; + + // Ops + case "BClearAC": stage = Stages.First; oper = Operator.None; DisplayValue = 0; break; + case "BOpMod": oper = Operator.Mod; BinaryOperatorPressed(); break; + case "BOpSign": SetValue(val * -1); break; + case "BEqual": + if (stage == Stages.Second) BinaryOperatorPressed(true); + break; + } + + Error = (DisplayText == "NaN"); + if (DisplayText == "") DisplayText = "0"; + } + #endregion + + #region User input + private void Button_Click(object sender, RoutedEventArgs e) + { + Handle_Click(sender, false); + } + + private void Button_MouseUp(object sender, MouseButtonEventArgs e) + { + if (e.ChangedButton == MouseButton.Left) Handle_Click(sender, false); + else if (e.ChangedButton == MouseButton.Right) Handle_Click(sender, true); + } + + private void Window_KeyDown(object sender, KeyEventArgs e) + { + e.Handled = true; + + if (Keyboard.Modifiers == ModifierKeys.Shift) switch (e.Key) + { + case Key.D6: Handle_Click(BPown, false); break; + case Key.D8: Handle_Click(BOpMultiply, false); break; + case Key.D5: Handle_Click(BOpMod, false); break; + } + + if (Keyboard.Modifiers == ModifierKeys.Control && e.Key == Key.Q) + this.Close(); + + else if (Keyboard.Modifiers == ModifierKeys.None) switch (e.Key) + { + // Numeric keys + case Key.D0: + case Key.NumPad0: Handle_Click(BNum0, false); break; + case Key.D1: + case Key.NumPad1: Handle_Click(BNum1, false); break; + case Key.D2: + case Key.NumPad2: Handle_Click(BNum2, false); break; + case Key.D3: + case Key.NumPad3: Handle_Click(BNum3, false); break; + case Key.D4: + case Key.NumPad4: Handle_Click(BNum4, false); break; + case Key.D5: + case Key.NumPad5: Handle_Click(BNum5, false); break; + case Key.D6: + case Key.NumPad6: Handle_Click(BNum6, false); break; + case Key.D7: + case Key.NumPad7: Handle_Click(BNum7, false); break; + case Key.D8: + case Key.NumPad8: Handle_Click(BNum8, false); break; + case Key.D9: + case Key.NumPad9: Handle_Click(BNum9, false); break; + case Key.OemPeriod: + case Key.Decimal: Handle_Click(BPeriod, false); break; + + // Binary Operators + case Key.Add: + case Key.OemPlus: Handle_Click(BOpAdd, false); break; + + case Key.Subtract: + case Key.OemMinus: Handle_Click(BOpSub, false); break; + + case Key.Multiply: Handle_Click(BOpMultiply, false); break; + + case Key.OemBackslash: + case Key.Divide: Handle_Click(BOpDivide, false); break; + + // Others + case Key.Return: Handle_Click(BEqual, false); break; + case Key.Escape: Handle_Click(BClearAC, false); break; + case Key.Back: Handle_Click(BBackspace, false); break; + case Key.Delete: Handle_Click(BClear, false); break; + case Key.F1: BHelp_Click(this, new RoutedEventArgs()); break; + } + } + + private void BHelp_Click(object sender, RoutedEventArgs e) + { + DynamicLink.Launcher.StartModule("Help", "Calculator"); + } + + #endregion + } +} diff --git a/Source/Calculator/MathHelper.cs b/Source/Calculator/MathHelper.cs new file mode 100644 index 0000000..829abf9 --- /dev/null +++ b/Source/Calculator/MathHelper.cs @@ -0,0 +1,43 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Calculator +{ + public static class MathHelper + { + + #region Combinations + public static double Combinations(double n, double k) + { + k = Math.Min(k, n - k); + double a = 1, b = 1; + + for (int i = 1; i <= k; i++) + { + a *= n - i + 1; + b *= i; + } + + return a / b; + } + #endregion + + public static double Arrangements(double n, double k) + { + double a = 1; + for (int i = 0; i < k; i++) a *= n - i; + + return a; + } + + public static double Factorial(double n) + { + double a = 1; + for (int i = 1; i <= n; i++) a *= i; + + return a; + } + } +} diff --git a/Source/Calculator/Properties/AssemblyInfo.cs b/Source/Calculator/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..302bf10 --- /dev/null +++ b/Source/Calculator/Properties/AssemblyInfo.cs @@ -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("Scientific Calculator")] +[assembly: AssemblyDescription("A calculator with various functions.")] +[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 +//CultureYouAreCodingWith in your .csproj file +//inside a . For example, if you are using US english +//in your source files, set the 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")] diff --git a/Source/Calculator/Properties/Resources.Designer.cs b/Source/Calculator/Properties/Resources.Designer.cs new file mode 100644 index 0000000..a19431b --- /dev/null +++ b/Source/Calculator/Properties/Resources.Designer.cs @@ -0,0 +1,71 @@ +//------------------------------------------------------------------------------ +// +// 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. +// +//------------------------------------------------------------------------------ + +namespace Calculator.Properties +{ + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // 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() + { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [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("Calculator.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture + { + get + { + return resourceCulture; + } + set + { + resourceCulture = value; + } + } + } +} diff --git a/Source/Calculator/Properties/Resources.resx b/Source/Calculator/Properties/Resources.resx new file mode 100644 index 0000000..af7dbeb --- /dev/null +++ b/Source/Calculator/Properties/Resources.resx @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Source/Calculator/Properties/Settings.Designer.cs b/Source/Calculator/Properties/Settings.Designer.cs new file mode 100644 index 0000000..b3bf827 --- /dev/null +++ b/Source/Calculator/Properties/Settings.Designer.cs @@ -0,0 +1,30 @@ +//------------------------------------------------------------------------------ +// +// 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. +// +//------------------------------------------------------------------------------ + +namespace Calculator.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; + } + } + } +} diff --git a/Source/Calculator/Properties/Settings.settings b/Source/Calculator/Properties/Settings.settings new file mode 100644 index 0000000..033d7a5 --- /dev/null +++ b/Source/Calculator/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/Source/Calculator/Styles/Buttons.xaml b/Source/Calculator/Styles/Buttons.xaml new file mode 100644 index 0000000..756c141 --- /dev/null +++ b/Source/Calculator/Styles/Buttons.xaml @@ -0,0 +1,102 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Source/Calculator/Styles/Display.xaml b/Source/Calculator/Styles/Display.xaml new file mode 100644 index 0000000..119021c --- /dev/null +++ b/Source/Calculator/Styles/Display.xaml @@ -0,0 +1,26 @@ + + + + + + + \ No newline at end of file diff --git a/Source/Calculator/calculator-logo.ico b/Source/Calculator/calculator-logo.ico new file mode 100644 index 0000000..9c5200f Binary files /dev/null and b/Source/Calculator/calculator-logo.ico differ diff --git a/Source/Factorizator/App.xaml b/Source/Factorizator/App.xaml new file mode 100644 index 0000000..496f2d8 --- /dev/null +++ b/Source/Factorizator/App.xaml @@ -0,0 +1,8 @@ + + + + + diff --git a/Source/Factorizator/App.xaml.cs b/Source/Factorizator/App.xaml.cs new file mode 100644 index 0000000..07ee7ed --- /dev/null +++ b/Source/Factorizator/App.xaml.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Configuration; +using System.Data; +using System.Linq; +using System.Windows; + +namespace Factorizator +{ + /// + /// Interaction logic for App.xaml + /// + public partial class App : Application + { + } +} diff --git a/Source/Factorizator/DecimalPair.cs b/Source/Factorizator/DecimalPair.cs new file mode 100644 index 0000000..e24cefd --- /dev/null +++ b/Source/Factorizator/DecimalPair.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Factorizator +{ + public class DecimalPair + { + public decimal First { get; set; } + public decimal Second { get; set; } + + public string FirstString { get { return First.ToString(); } } + public string SecondString + { + get + { + if (Second == 0) return ""; + else return Second.ToString(); + } + } + + public DecimalPair() { First = Second = 0; } + public DecimalPair(decimal a, decimal b) + { + First = a; Second = b; + } + } +} diff --git a/Source/Factorizator/Factorizator.csproj b/Source/Factorizator/Factorizator.csproj new file mode 100644 index 0000000..8c929d7 --- /dev/null +++ b/Source/Factorizator/Factorizator.csproj @@ -0,0 +1,139 @@ + + + + Debug + x86 + 8.0.30703 + 2.0 + {FB3CFDCE-C816-4F4A-AEF4-5C0240396C60} + WinExe + Properties + Factorizator + Factorizator + v4.0 + Client + 512 + {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + 4 + + + x86 + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + x86 + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + ..\..\TibisMathematicsSuite - Release\ + TRACE + true + pdbonly + x86 + prompt + false + false + false + + + factorizator-logo.ico + + + true + + + + + + + + + + + 4.0 + + + + + + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + App.xaml + Code + + + + + MainWindow.xaml + Code + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + + + Code + + + True + True + Resources.resx + + + True + Settings.settings + True + + + ResXFileCodeGenerator + Resources.Designer.cs + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + + + + {A04B247B-6A95-462B-9E07-3337A1C158F1} + DynamicLink + + + + + + + + \ No newline at end of file diff --git a/Source/Factorizator/FactorizatorAlgorithm.cs b/Source/Factorizator/FactorizatorAlgorithm.cs new file mode 100644 index 0000000..b24148b --- /dev/null +++ b/Source/Factorizator/FactorizatorAlgorithm.cs @@ -0,0 +1,48 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Factorizator +{ + static class FactorizatorAlgorithm + { + public static bool Abort { get; set; } + + public static void Factorize(decimal number, out decimal[] fact, out decimal[] num) + { + Abort = false; + bool negative = (number < 0); + number = Math.Abs(number); + + List resultFact = new List(); + List resultNum = new List(); + + for (decimal i = 2; i * i <= number && !Abort; i++) + { + while (number % i == 0) + { + resultFact.Add(i); + if (negative) resultNum.Add(-number); + else resultNum.Add(number); + number /= i; + } + } + + if (negative) resultNum.Add(-number); + else resultNum.Add(number); + + if (number > 1) + { + if (negative) resultNum.Add(-1); + else resultNum.Add(1); + resultFact.Add(number); + } + + fact = resultFact.ToArray(); + num = resultNum.ToArray(); + } + } + + +} diff --git a/Source/Factorizator/MainWindow.xaml b/Source/Factorizator/MainWindow.xaml new file mode 100644 index 0000000..a7fa537 --- /dev/null +++ b/Source/Factorizator/MainWindow.xaml @@ -0,0 +1,111 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Ready + + + + + + + + + + + + Help + + + + + + diff --git a/Source/Factorizator/MainWindow.xaml.cs b/Source/Factorizator/MainWindow.xaml.cs new file mode 100644 index 0000000..581a47a --- /dev/null +++ b/Source/Factorizator/MainWindow.xaml.cs @@ -0,0 +1,179 @@ +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; +using System.Threading; + +namespace Factorizator +{ + /// + /// Interaction logic for MainWindow.xaml + /// + public partial class MainWindow : Window + { + #region Error variable + private bool error = false; + private bool Error + { + get { return error; } + set + { + error = value; + inputNumber.Background = (value) ? (Brushes.Pink) : (Brushes.White); + } + } + #endregion + + #region Vars + Thread worker = null; + #endregion + + #region Constructor + public MainWindow() + { + InitializeComponent(); + } + #endregion + + #region Keyboard handler + private void Window_KeyDown(object sender, KeyEventArgs e) + { + e.Handled = true; + var text = Keyboard.FocusedElement as TextBox; + + if (e.KeyboardDevice.Modifiers == ModifierKeys.None) + { + switch (e.Key) + { + case Key.Enter: buttonCalculate_Click(this, new RoutedEventArgs()); break; + case Key.Escape: statusCancel_Click(this, new RoutedEventArgs()); break; + case Key.F1: DynamicLink.Launcher.StartModule("Help", "factorizator"); break; + default: e.Handled = false; break; + } + } + + else if (text == null && e.KeyboardDevice.Modifiers == ModifierKeys.Control && e.Key == Key.C) + contextCopyRem_Click(this, new RoutedEventArgs()); + + else if (text == null && e.KeyboardDevice.Modifiers == (ModifierKeys.Control | ModifierKeys.Shift) && e.Key == Key.C) + contextCopyDiv_Click(this, new RoutedEventArgs()); + + else e.Handled = false; + } + #endregion + + #region UI handlers + private void inputNumber_TextChanged(object sender, TextChangedEventArgs e) + { + if (Error) + { + Error = false; + statusMessage.Text = "Ready"; + } + } + + private void buttonCalculate_Click(object sender, RoutedEventArgs e) + { + if (inputNumber.Text == "") return; + + decimal d; + + if (!decimal.TryParse(inputNumber.Text, out d)) + { + Error = true; + statusMessage.Text = "Bad number."; + } + + else BeginWork(d); + } + + private void contextCopyRem_Click(object sender, RoutedEventArgs e) + { + DecimalPair pair = factorizationDisplay.SelectedItem as DecimalPair; + if (pair == null) return; + + Clipboard.SetText(pair.First.ToString()); + } + + private void contextCopyDiv_Click(object sender, RoutedEventArgs e) + { + DecimalPair pair = factorizationDisplay.SelectedItem as DecimalPair; + if (pair == null) return; + + Clipboard.SetText(pair.Second.ToString()); + } + + private void contextClear_Click(object sender, RoutedEventArgs e) + { + factorizationDisplay.Items.Clear(); + } + + private void statusCancel_Click(object sender, RoutedEventArgs e) + { + FactorizatorAlgorithm.Abort = true; + } + + private void TextBlock_MouseUp(object sender, MouseButtonEventArgs e) + { + DynamicLink.Launcher.StartModule("Help", "factorizator"); + } + + #endregion + + #region Worker + void BeginWork(decimal num) + { + num = Math.Truncate(num); + + // Visual stuff + statusMessage.Text = "Calculating..."; + statusProgress.Visibility = System.Windows.Visibility.Visible; + statusCancel.Visibility = System.Windows.Visibility.Visible; + + // Start thread + worker = new Thread(new ParameterizedThreadStart(DoWork)); + worker.Start(num); + } + + delegate void FinishWorkDelegate(decimal[] resultFact, decimal[] resultNum); + void DoWork(object param) + { + decimal number = (decimal)param; + decimal[] resultFact, resultNum; + + FactorizatorAlgorithm.Factorize(number, out resultFact, out resultNum); + Dispatcher.Invoke(new FinishWorkDelegate(FinishWork), resultFact, resultNum); + } + + void FinishWork(decimal[] resultFact, decimal[] resultNum) + { + factorizationDisplay.Items.Clear(); + + // Show results + for (int i = 0; i < resultNum.Length; i++) + { + if (i < resultFact.Length) + factorizationDisplay.Items.Add(new DecimalPair(resultNum[i], resultFact[i])); + else factorizationDisplay.Items.Add(new DecimalPair(resultNum[i], 0)); + } + + // Update visual stuff + statusMessage.Text = "Ready"; + statusProgress.Visibility = System.Windows.Visibility.Hidden; + statusCancel.Visibility = System.Windows.Visibility.Hidden; + } + + #endregion + + + } +} diff --git a/Source/Factorizator/Properties/AssemblyInfo.cs b/Source/Factorizator/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..a38ff3c --- /dev/null +++ b/Source/Factorizator/Properties/AssemblyInfo.cs @@ -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("Factorizator")] +[assembly: AssemblyDescription("Displays the factorization of a number.")] +[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 +//CultureYouAreCodingWith in your .csproj file +//inside a . For example, if you are using US english +//in your source files, set the 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")] diff --git a/Source/Factorizator/Properties/Resources.Designer.cs b/Source/Factorizator/Properties/Resources.Designer.cs new file mode 100644 index 0000000..c9e7e0d --- /dev/null +++ b/Source/Factorizator/Properties/Resources.Designer.cs @@ -0,0 +1,71 @@ +//------------------------------------------------------------------------------ +// +// 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. +// +//------------------------------------------------------------------------------ + +namespace Factorizator.Properties +{ + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // 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() + { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [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("Factorizator.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture + { + get + { + return resourceCulture; + } + set + { + resourceCulture = value; + } + } + } +} diff --git a/Source/Factorizator/Properties/Resources.resx b/Source/Factorizator/Properties/Resources.resx new file mode 100644 index 0000000..af7dbeb --- /dev/null +++ b/Source/Factorizator/Properties/Resources.resx @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Source/Factorizator/Properties/Settings.Designer.cs b/Source/Factorizator/Properties/Settings.Designer.cs new file mode 100644 index 0000000..e8e29b4 --- /dev/null +++ b/Source/Factorizator/Properties/Settings.Designer.cs @@ -0,0 +1,30 @@ +//------------------------------------------------------------------------------ +// +// 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. +// +//------------------------------------------------------------------------------ + +namespace Factorizator.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; + } + } + } +} diff --git a/Source/Factorizator/Properties/Settings.settings b/Source/Factorizator/Properties/Settings.settings new file mode 100644 index 0000000..033d7a5 --- /dev/null +++ b/Source/Factorizator/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/Source/Factorizator/Styles/ButtonStyle.xaml b/Source/Factorizator/Styles/ButtonStyle.xaml new file mode 100644 index 0000000..07837e9 --- /dev/null +++ b/Source/Factorizator/Styles/ButtonStyle.xaml @@ -0,0 +1,107 @@ + + + + + + + \ No newline at end of file diff --git a/Source/Factorizator/Styles/GroupBoxStyle.xaml b/Source/Factorizator/Styles/GroupBoxStyle.xaml new file mode 100644 index 0000000..407b612 --- /dev/null +++ b/Source/Factorizator/Styles/GroupBoxStyle.xaml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Source/Factorizator/factorizator-logo.ico b/Source/Factorizator/factorizator-logo.ico new file mode 100644 index 0000000..1885159 Binary files /dev/null and b/Source/Factorizator/factorizator-logo.ico differ diff --git a/Source/GraphingCalculator/App.xaml b/Source/GraphingCalculator/App.xaml new file mode 100644 index 0000000..93c5689 --- /dev/null +++ b/Source/GraphingCalculator/App.xaml @@ -0,0 +1,8 @@ + + + + + diff --git a/Source/GraphingCalculator/App.xaml.cs b/Source/GraphingCalculator/App.xaml.cs new file mode 100644 index 0000000..41c7ae6 --- /dev/null +++ b/Source/GraphingCalculator/App.xaml.cs @@ -0,0 +1,42 @@ +using System; +using System.Collections.Generic; +using System.Configuration; +using System.Data; +using System.Linq; +using System.Windows; + +namespace GraphingCalculator +{ + /// + /// Interaction logic for App.xaml + /// + 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(); + } + } +} diff --git a/Source/GraphingCalculator/Bounds.cs b/Source/GraphingCalculator/Bounds.cs new file mode 100644 index 0000000..62f49ef --- /dev/null +++ b/Source/GraphingCalculator/Bounds.cs @@ -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 + } +} diff --git a/Source/GraphingCalculator/Controls/EvaluateWindow.xaml b/Source/GraphingCalculator/Controls/EvaluateWindow.xaml new file mode 100644 index 0000000..5f3853a --- /dev/null +++ b/Source/GraphingCalculator/Controls/EvaluateWindow.xaml @@ -0,0 +1,101 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Name: + + Value: + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/GraphingCalculator/Controls/EvaluateWindow.xaml.cs b/Source/GraphingCalculator/Controls/EvaluateWindow.xaml.cs new file mode 100644 index 0000000..e8c7338 --- /dev/null +++ b/Source/GraphingCalculator/Controls/EvaluateWindow.xaml.cs @@ -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 +{ + /// + /// Interaction logic for EvaluateWindow.xaml + /// + public partial class EvaluateWindow : Window + { + private Dictionary variables = new Dictionary(); + + #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 + } +} diff --git a/Source/GraphingCalculator/Controls/GraphingCanvas.xaml b/Source/GraphingCalculator/Controls/GraphingCanvas.xaml new file mode 100644 index 0000000..7a92984 --- /dev/null +++ b/Source/GraphingCalculator/Controls/GraphingCanvas.xaml @@ -0,0 +1,137 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/GraphingCalculator/Controls/GraphingCanvas.xaml.cs b/Source/GraphingCalculator/Controls/GraphingCanvas.xaml.cs new file mode 100644 index 0000000..31498bc --- /dev/null +++ b/Source/GraphingCalculator/Controls/GraphingCanvas.xaml.cs @@ -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 +{ + /// + /// Interaction logic for GraphingCanvas.xaml + /// + 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 expressions = new List(); + public List Expressions { get { return expressions; } } + + /// + /// Adds an expression to be plotted + /// + 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 queuedPoints = new List(); + + 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 + } +} diff --git a/Source/GraphingCalculator/Controls/IntegralWindow.xaml b/Source/GraphingCalculator/Controls/IntegralWindow.xaml new file mode 100644 index 0000000..cfc9209 --- /dev/null +++ b/Source/GraphingCalculator/Controls/IntegralWindow.xaml @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + This feature is experimental, so the given results may not fully be accurate. + + + + + + + + + + + + + + + + + + + From: + -1 + To: + 1 + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/GraphingCalculator/Controls/IntegralWindow.xaml.cs b/Source/GraphingCalculator/Controls/IntegralWindow.xaml.cs new file mode 100644 index 0000000..e4393fd --- /dev/null +++ b/Source/GraphingCalculator/Controls/IntegralWindow.xaml.cs @@ -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 +{ + /// + /// Interaction logic for LimitWindow.xaml + /// + 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 + } +} diff --git a/Source/GraphingCalculator/Controls/LogWindow.xaml b/Source/GraphingCalculator/Controls/LogWindow.xaml new file mode 100644 index 0000000..070f1ca --- /dev/null +++ b/Source/GraphingCalculator/Controls/LogWindow.xaml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/GraphingCalculator/Controls/LogWindow.xaml.cs b/Source/GraphingCalculator/Controls/LogWindow.xaml.cs new file mode 100644 index 0000000..1555bf7 --- /dev/null +++ b/Source/GraphingCalculator/Controls/LogWindow.xaml.cs @@ -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 +{ + /// + /// Interaction logic for LogWindow.xaml + /// + 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!"); + } + } + } +} diff --git a/Source/GraphingCalculator/Controls/SettingsWindow.xaml b/Source/GraphingCalculator/Controls/SettingsWindow.xaml new file mode 100644 index 0000000..6f7cd9b --- /dev/null +++ b/Source/GraphingCalculator/Controls/SettingsWindow.xaml @@ -0,0 +1,165 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Minimum + Maximum + + + + A higher precision means that drawing takes longer to render, making the application slower. + + + + + + + + + + + + + + Higher + Lower + + + + A higher density means that more grid lines are drawn. + + + + + + + + + + + + + + 0 + ? decimals + 15 + + + + A higher precision means that more decimals appear in the graph. If the value is too high, values may overlap each other. + + + + + + + + + + + + + + 1% + ?% of screen + 150% + + + + + + + + + + + + + + + + 1% + ?% of screen + 150% + + + + + + + + + + + + + + + + + + + + diff --git a/Source/GraphingCalculator/Controls/SettingsWindow.xaml.cs b/Source/GraphingCalculator/Controls/SettingsWindow.xaml.cs new file mode 100644 index 0000000..f3d5707 --- /dev/null +++ b/Source/GraphingCalculator/Controls/SettingsWindow.xaml.cs @@ -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 +{ + /// + /// Interaction logic for SettingsWindow.xaml + /// + 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 e) + { + if (outputDoublePrecision != null) + outputDoublePrecision.Text = e.NewValue.ToString() + " decimals"; + } + + private void sliderNavigationSensitivity_ValueChanged(object sender, RoutedPropertyChangedEventArgs e) + { + if (outputNavigationSensitivity != null) + outputNavigationSensitivity.Text = Math.Round(e.NewValue * 100, 0).ToString() + "% of screen"; + } + + private void sliderZoomSensitivity_ValueChanged(object sender, RoutedPropertyChangedEventArgs e) + { + if (outputZoomSensitivity != null) + outputZoomSensitivity.Text = Math.Round((e.NewValue-1) * 100, 0).ToString() + "% of screen"; + } + + } +} diff --git a/Source/GraphingCalculator/Expression/Expression.cs b/Source/GraphingCalculator/Expression/Expression.cs new file mode 100644 index 0000000..458dd0e --- /dev/null +++ b/Source/GraphingCalculator/Expression/Expression.cs @@ -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> tokens = new List>(); + private List> output = new List>(); + private Dictionary variables = new Dictionary(); + + protected List> Tokens { get { return tokens; } } + protected List> Output { get { return output; } } + public Dictionary 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.Operator, "!-")); + + // Any other operator + else tokens.Add(new KeyValuePair(Token.Operator, ExpressionString[i].ToString())); + + } + + else if (ExpressionString[i] == '(') + tokens.Add(new KeyValuePair(Token.LeftParanthesis, ExpressionString[i].ToString())); + + else if (ExpressionString[i] == ')') + tokens.Add(new KeyValuePair(Token.RightParanthesis, ExpressionString[i].ToString())); + + else if (ExpressionString[i] == ',') + tokens.Add(new KeyValuePair(Token.FunctionArgumentSeparator, ExpressionString[i].ToString())); + + else if (Char.IsDigit(ExpressionString[i])) + tokens.Add(new KeyValuePair(Token.Literal, GetLiteral(ExpressionString, ref i))); + + else if (Char.IsLetter(ExpressionString[i])) + { + if (IsFunction(ExpressionString, i)) tokens.Add(new KeyValuePair(Token.Function, GetVariable(ExpressionString, ref i))); + else tokens.Add(new KeyValuePair(Token.Variable, GetVariable(ExpressionString, ref i))); + } + + else throw new Exception("Unrecognized character found!"); + } + } + + private void ShuntingYard() + { + Stack> stack = new Stack>(); + + 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 stack = new Stack(); + + 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 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 + + } +} diff --git a/Source/GraphingCalculator/Expression/Integrator.cs b/Source/GraphingCalculator/Expression/Integrator.cs new file mode 100644 index 0000000..2cc45ef --- /dev/null +++ b/Source/GraphingCalculator/Expression/Integrator.cs @@ -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 results = new Dictionary(); + #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); + } + + /// + /// Calculates a definite integral (the area between the function graph and the X axis, where x ranges between beg and end. + /// + /// An expression to integrate. + /// Beginning of the interval + /// End of the interval + /// The name of the variable, by default is 'x' + 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; + } + } +} diff --git a/Source/GraphingCalculator/Expression/VisualExpression.cs b/Source/GraphingCalculator/Expression/VisualExpression.cs new file mode 100644 index 0000000..694d073 --- /dev/null +++ b/Source/GraphingCalculator/Expression/VisualExpression.cs @@ -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)); + } + } +} diff --git a/Source/GraphingCalculator/GraphingCalculator.csproj b/Source/GraphingCalculator/GraphingCalculator.csproj new file mode 100644 index 0000000..95c97d8 --- /dev/null +++ b/Source/GraphingCalculator/GraphingCalculator.csproj @@ -0,0 +1,187 @@ + + + + Debug + x86 + 8.0.30703 + 2.0 + {A1B63EB2-82CF-4589-8AE2-18FAAF51B662} + WinExe + Properties + GraphingCalculator + GraphingCalculator + v4.0 + Client + 512 + {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + 4 + + + x86 + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + x86 + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + true + + + ..\..\TibisMathematicsSuite - Release\ + TRACE + true + pdbonly + x86 + prompt + true + true + false + + + graphing-logo.ico + + + + + + + + + + + 4.0 + + + + + + + + MSBuild:Compile + Designer + + + IntegralWindow.xaml + + + EvaluateWindow.xaml + + + + + SettingsWindow.xaml + + + MSBuild:Compile + Designer + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + MSBuild:Compile + Designer + + + App.xaml + Code + + + + + GraphingCanvas.xaml + + + + + LogWindow.xaml + + + MainWindow.xaml + Code + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + + + Code + + + True + True + Resources.resx + + + True + Settings.settings + True + + + ResXFileCodeGenerator + Resources.Designer.cs + + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + + + + {A04B247B-6A95-462B-9E07-3337A1C158F1} + Launcher + + + + + + + + \ No newline at end of file diff --git a/Source/GraphingCalculator/IO/ExpressionFile.cs b/Source/GraphingCalculator/IO/ExpressionFile.cs new file mode 100644 index 0000000..cbfc6ad --- /dev/null +++ b/Source/GraphingCalculator/IO/ExpressionFile.cs @@ -0,0 +1,88 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace GraphingCalculator.IO +{ + public class ExpressionFile + { + private List expressions = new List(); + public List 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(); + } + } +} diff --git a/Source/GraphingCalculator/Log.cs b/Source/GraphingCalculator/Log.cs new file mode 100644 index 0000000..8d63410 --- /dev/null +++ b/Source/GraphingCalculator/Log.cs @@ -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 entries = new List(); + public static List Entries { get { return entries; } } + + public static void LogEvent (string format, params object[] p) + { + entries.Add(DateTime.Now + ": " + String.Format(format, p)); + } + } +} diff --git a/Source/GraphingCalculator/MainWindow.xaml b/Source/GraphingCalculator/MainWindow.xaml new file mode 100644 index 0000000..a604155 --- /dev/null +++ b/Source/GraphingCalculator/MainWindow.xaml @@ -0,0 +1,163 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Bottom: + Left: + Top: + Right: + + + + + + + + + + + + + + + + + + + + diff --git a/Source/GraphingCalculator/MainWindow.xaml.cs b/Source/GraphingCalculator/MainWindow.xaml.cs new file mode 100644 index 0000000..d5846e3 --- /dev/null +++ b/Source/GraphingCalculator/MainWindow.xaml.cs @@ -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 +{ + /// + /// Interaction logic for MainWindow.xaml + /// + 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 + } +} diff --git a/Source/GraphingCalculator/Properties/AssemblyInfo.cs b/Source/GraphingCalculator/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..606d224 --- /dev/null +++ b/Source/GraphingCalculator/Properties/AssemblyInfo.cs @@ -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 +//CultureYouAreCodingWith in your .csproj file +//inside a . For example, if you are using US english +//in your source files, set the 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")] diff --git a/Source/GraphingCalculator/Properties/Resources.Designer.cs b/Source/GraphingCalculator/Properties/Resources.Designer.cs new file mode 100644 index 0000000..a2550f0 --- /dev/null +++ b/Source/GraphingCalculator/Properties/Resources.Designer.cs @@ -0,0 +1,71 @@ +//------------------------------------------------------------------------------ +// +// 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. +// +//------------------------------------------------------------------------------ + +namespace GraphingCalculator.Properties +{ + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // 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() + { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [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; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture + { + get + { + return resourceCulture; + } + set + { + resourceCulture = value; + } + } + } +} diff --git a/Source/GraphingCalculator/Properties/Resources.resx b/Source/GraphingCalculator/Properties/Resources.resx new file mode 100644 index 0000000..af7dbeb --- /dev/null +++ b/Source/GraphingCalculator/Properties/Resources.resx @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Source/GraphingCalculator/Properties/Settings.Designer.cs b/Source/GraphingCalculator/Properties/Settings.Designer.cs new file mode 100644 index 0000000..f1041f4 --- /dev/null +++ b/Source/GraphingCalculator/Properties/Settings.Designer.cs @@ -0,0 +1,86 @@ +//------------------------------------------------------------------------------ +// +// 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. +// +//------------------------------------------------------------------------------ + +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; + } + } + } +} diff --git a/Source/GraphingCalculator/Properties/Settings.settings b/Source/GraphingCalculator/Properties/Settings.settings new file mode 100644 index 0000000..5ca87c5 --- /dev/null +++ b/Source/GraphingCalculator/Properties/Settings.settings @@ -0,0 +1,21 @@ + + + + + + 600 + + + 41 + + + 4 + + + 0.1 + + + 1.075 + + + \ No newline at end of file diff --git a/Source/GraphingCalculator/Styles/ButtonStyle.xaml b/Source/GraphingCalculator/Styles/ButtonStyle.xaml new file mode 100644 index 0000000..53c5b96 --- /dev/null +++ b/Source/GraphingCalculator/Styles/ButtonStyle.xaml @@ -0,0 +1,55 @@ + + + + + \ No newline at end of file diff --git a/Source/GraphingCalculator/Styles/GroupBoxStyle.xaml b/Source/GraphingCalculator/Styles/GroupBoxStyle.xaml new file mode 100644 index 0000000..407b612 --- /dev/null +++ b/Source/GraphingCalculator/Styles/GroupBoxStyle.xaml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Source/GraphingCalculator/Styles/RadioButtonStyle.xaml b/Source/GraphingCalculator/Styles/RadioButtonStyle.xaml new file mode 100644 index 0000000..5eddd6d --- /dev/null +++ b/Source/GraphingCalculator/Styles/RadioButtonStyle.xaml @@ -0,0 +1,63 @@ + + + + \ No newline at end of file diff --git a/Source/GraphingCalculator/Styles/WarningGroupBoxStyle.xaml b/Source/GraphingCalculator/Styles/WarningGroupBoxStyle.xaml new file mode 100644 index 0000000..d9c8f3f --- /dev/null +++ b/Source/GraphingCalculator/Styles/WarningGroupBoxStyle.xaml @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Source/GraphingCalculator/app.config b/Source/GraphingCalculator/app.config new file mode 100644 index 0000000..378cb70 --- /dev/null +++ b/Source/GraphingCalculator/app.config @@ -0,0 +1,27 @@ + + + + +
+ + + + + + 600 + + + 41 + + + 4 + + + 0.1 + + + 1.075 + + + + \ No newline at end of file diff --git a/Source/GraphingCalculator/graphing-logo.ico b/Source/GraphingCalculator/graphing-logo.ico new file mode 100644 index 0000000..28db9e9 Binary files /dev/null and b/Source/GraphingCalculator/graphing-logo.ico differ diff --git a/Source/Help/App.xaml b/Source/Help/App.xaml new file mode 100644 index 0000000..c616ebf --- /dev/null +++ b/Source/Help/App.xaml @@ -0,0 +1,8 @@ + + + + + diff --git a/Source/Help/App.xaml.cs b/Source/Help/App.xaml.cs new file mode 100644 index 0000000..8f8a8b6 --- /dev/null +++ b/Source/Help/App.xaml.cs @@ -0,0 +1,42 @@ +using System; +using System.Collections.Generic; +using System.Configuration; +using System.Data; +using System.Linq; +using System.Windows; + +namespace Help +{ + /// + /// Interaction logic for App.xaml + /// + public partial class App : Application + { + protected override void OnStartup(StartupEventArgs e) + { + // We need to initialize the help system now + try + { + string file = DynamicLink.Launcher.FindHelpFiles(); + if (System.IO.File.Exists(file)) + HelpSystem.HelpManager.Load(file); + + else Properties["ERROR"] = new Exception("Could not find index file documentation\\index.xml."); + } + + catch (Exception ex) + { + Properties["ERROR"] = ex; + } + + // Check if we were asked to load anything + if (e.Args.Length != 0) + { + Properties["APPLICATION"] = e.Args[0]; + } + + // Continue + base.OnStartup(e); + } + } +} diff --git a/Source/Help/Help.csproj b/Source/Help/Help.csproj new file mode 100644 index 0000000..6a17a8e --- /dev/null +++ b/Source/Help/Help.csproj @@ -0,0 +1,733 @@ + + + + Debug + x86 + 8.0.30703 + 2.0 + {5BF4AB9C-9AE0-44ED-B49E-09ACE92C8D89} + WinExe + Properties + Help + Help + v3.5 + 512 + {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + 4 + + + x86 + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + x86 + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + help-logo.ico + + + true + + + ..\..\TibisMathematicsSuite - Release\ + TRACE + true + pdbonly + x86 + prompt + false + false + false + + + + + + + + + + + + + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + App.xaml + Code + + + + + + + MainWindow.xaml + Code + + + Designer + MSBuild:Compile + + + + + Code + + + True + True + Resources.resx + + + True + Settings.settings + True + + + ResXFileCodeGenerator + Resources.Designer.cs + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + + + + {A04B247B-6A95-462B-9E07-3337A1C158F1} + Launcher + + + + + {3050F1C5-98B5-11CF-BB82-00AA00BDCE0B} + 4 + 0 + 0 + primary + False + True + + + + + + + + + + + + + + + + + + + + + + + + + + + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + + + \ No newline at end of file diff --git a/Source/Help/HelpSystem/HelpChapter.cs b/Source/Help/HelpSystem/HelpChapter.cs new file mode 100644 index 0000000..12322ca --- /dev/null +++ b/Source/Help/HelpSystem/HelpChapter.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Help.HelpSystem +{ + public class HelpChapter + { + private List topics = new List(); + public List Topics { get { return topics; } } + + public string Application { get; set; } + public string Title { get; set; } + public string Filename { get; set; } + + public HelpChapter(string app = "", string title = "", string filename = "") + { + Application = app; Title = title; Filename = filename; + } + } +} diff --git a/Source/Help/HelpSystem/HelpHtmlWrapper.cs b/Source/Help/HelpSystem/HelpHtmlWrapper.cs new file mode 100644 index 0000000..3f8bb96 --- /dev/null +++ b/Source/Help/HelpSystem/HelpHtmlWrapper.cs @@ -0,0 +1,54 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Help.HelpSystem +{ + public static class HelpHtmlWrapper + { + public static void Find(object Document, string text) + { + var doc = Document as mshtml.IHTMLDocument2; + if (doc == null || doc.body == null || text == "") return; + + string html = doc.body.innerHTML; + string temp = ""; + + int index = html.IndexOf(text, StringComparison.CurrentCultureIgnoreCase); + while (index != -1) + { + int min = html.IndexOf('<', index); + int max = html.IndexOf('>', index); + + if (min <= max) + { + temp = "" + html.Substring(index, text.Length) + ""; + html = html.Substring(0, index) + temp + html.Substring(index + text.Length); + + index += temp.Length - text.Length; + } + + index = html.IndexOf(text, index + 1, StringComparison.CurrentCultureIgnoreCase); + } + + doc.body.innerHTML = html; + } + + public static string GetHtml(object document) + { + var doc = document as mshtml.IHTMLDocument2; + if (doc == null || doc.body == null) return ""; + + return doc.body.innerHTML; + } + + public static void SetHtml(object document, string html) + { + var doc = document as mshtml.IHTMLDocument2; + if (doc == null || doc.body == null) return; + + doc.body.innerHTML = html; + } + } +} diff --git a/Source/Help/HelpSystem/HelpManager.cs b/Source/Help/HelpSystem/HelpManager.cs new file mode 100644 index 0000000..fa1f2d6 --- /dev/null +++ b/Source/Help/HelpSystem/HelpManager.cs @@ -0,0 +1,134 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Xml; + +namespace Help.HelpSystem +{ + static class HelpManager + { + public static List Chapters = new List(); + + public static string DocumentationPath = ""; + + public static string GetFullPath(string relative) + { + return System.IO.Path.Combine(DocumentationPath, relative); + } + + public static void Load(string indexfile) + { + XmlTextReader reader = new XmlTextReader(indexfile); + + HelpChapter currentChapter = new HelpChapter(); + HelpTopic currentTopic = new HelpTopic(); + bool isTopic = false; + + while (reader.Read()) + { + switch (reader.NodeType) + { + case XmlNodeType.Element: + if (reader.Name == "chapter") + { + isTopic = false; + currentChapter = new HelpChapter(); + } + + else if (reader.Name == "topic") + { + isTopic = true; + currentTopic = new HelpTopic(); + } + + + while (reader.MoveToNextAttribute()) + { + switch (reader.Name) + { + case "application": if (!isTopic) currentChapter.Application = reader.Value; break; + case "title": + if (isTopic) currentTopic.Title = reader.Value; + else currentChapter.Title = reader.Value; + break; + + case "filename": + if (isTopic) currentTopic.Filename = reader.Value; + else currentChapter.Filename = reader.Value; + break; + } + } + + if (isTopic) currentChapter.Topics.Add(currentTopic); + + break; + + case XmlNodeType.EndElement: + if (reader.Name == "topic") currentChapter.Topics.Add(currentTopic); + else if (reader.Name == "chapter") Chapters.Add(currentChapter); + + break; + } + + } + + reader.Close(); + DocumentationPath = System.IO.Path.GetDirectoryName(indexfile); + } + + private static string[] FindInFile(string file, string q) + { + int min, max; + string text = System.IO.File.ReadAllText(file); + List ret = new List(); + + // Remove html tags + min = text.IndexOf('<'); + max = text.IndexOf('>'); + while (min != -1 && max != -1 && min < max) + { + text = text.Remove(min, max - min + 1); + min = text.IndexOf('<'); + max = text.IndexOf('>'); + } + + // Search each line + foreach (var line in text.Split('\n', '\r')) + if (line.ToLower().Contains(q.ToLower())) ret.Add(line.TrimStart(' ', '\t', '\n', '\r')); + + return ret.ToArray(); + } + + public static HelpTopic[] SearchText(string text, HelpChapter chapter) + { + var list = new List(); + + // Make a list of files to be checked + var temp = new List(); + temp.Add(new HelpTopic(chapter.Title, chapter.Filename)); + temp.AddRange(chapter.Topics); + + // Search + foreach (var top in temp) + { + string[] f = FindInFile(GetFullPath(top.Filename), text); + foreach (var i in f) + list.Add(new HelpTopic() + { + Title = top.Title, + Filename = top.Filename, + Context = i, + IsSearchResult = true + }); + } + + return list.ToArray(); + } + + public static HelpTopic[] SearchTitle(string text, HelpChapter chapter) + { + return chapter.Topics.Where(x => x.Title.ToLower().Contains(text.ToLower())).ToArray(); + } + } +} diff --git a/Source/Help/HelpSystem/HelpTopic.cs b/Source/Help/HelpSystem/HelpTopic.cs new file mode 100644 index 0000000..4a0b6bb --- /dev/null +++ b/Source/Help/HelpSystem/HelpTopic.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Help.HelpSystem +{ + public class HelpTopic + { + public string Title { get; set; } + public string Filename { get; set; } + public string Context { get; set; } + public bool IsSearchResult { get; set; } + + public HelpTopic(string title = "", string filename = "", string context = "") + { + Title = title; Filename = filename; + Context = context; + IsSearchResult = (context != ""); + } + } +} diff --git a/Source/Help/Images/help-back.png b/Source/Help/Images/help-back.png new file mode 100644 index 0000000..e22d00a Binary files /dev/null and b/Source/Help/Images/help-back.png differ diff --git a/Source/Help/Images/help-clear.png b/Source/Help/Images/help-clear.png new file mode 100644 index 0000000..23378f5 Binary files /dev/null and b/Source/Help/Images/help-clear.png differ diff --git a/Source/Help/Images/help-forward.png b/Source/Help/Images/help-forward.png new file mode 100644 index 0000000..086d3bc Binary files /dev/null and b/Source/Help/Images/help-forward.png differ diff --git a/Source/Help/Images/help-home.png b/Source/Help/Images/help-home.png new file mode 100644 index 0000000..d87f1f9 Binary files /dev/null and b/Source/Help/Images/help-home.png differ diff --git a/Source/Help/Images/help-logo-small.png b/Source/Help/Images/help-logo-small.png new file mode 100644 index 0000000..14a3433 Binary files /dev/null and b/Source/Help/Images/help-logo-small.png differ diff --git a/Source/Help/Images/help-search.png b/Source/Help/Images/help-search.png new file mode 100644 index 0000000..cd0c612 Binary files /dev/null and b/Source/Help/Images/help-search.png differ diff --git a/Source/Help/Images/help-searchopt.png b/Source/Help/Images/help-searchopt.png new file mode 100644 index 0000000..9bfa580 Binary files /dev/null and b/Source/Help/Images/help-searchopt.png differ diff --git a/Source/Help/MainWindow.xaml b/Source/Help/MainWindow.xaml new file mode 100644 index 0000000..9f818bd --- /dev/null +++ b/Source/Help/MainWindow.xaml @@ -0,0 +1,137 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Navigation: + + + + + + + + + + + + Application: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/Help/MainWindow.xaml.cs b/Source/Help/MainWindow.xaml.cs new file mode 100644 index 0000000..0be974f --- /dev/null +++ b/Source/Help/MainWindow.xaml.cs @@ -0,0 +1,219 @@ +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 Help +{ + /// + /// Interaction logic for MainWindow.xaml + /// + public partial class MainWindow : Window + { + string searchSavedHtml = string.Empty; + int searchLastType = -1; + + public MainWindow() + { + InitializeComponent(); + + PopulateChapters(); + if (HelpSystem.HelpManager.Chapters.Count != 0) + PopulateTopics(); + + // Check for errors, exceptions + if (Application.Current.Properties.Contains("ERROR")) + { + var ex = Application.Current.Properties["ERROR"] as Exception; + if (ex != null) MessageBox.Show(ex.Message, "Could not load the help documents.", MessageBoxButton.OK, MessageBoxImage.Error); + } + + // Check for arguments + if (Application.Current.Properties.Contains("APPLICATION")) + SetApplication(Application.Current.Properties["APPLICATION"].ToString()); + } + + public void SetApplication(string application) + { + int item = HelpSystem.HelpManager.Chapters.FindIndex(x => x.Application == application); + if (item != -1) this.listChapters.SelectedItem = HelpSystem.HelpManager.Chapters[item]; + } + + #region Populate routines + + public void PopulateChapters() + { + foreach (var i in HelpSystem.HelpManager.Chapters) + listChapters.Items.Add(i); + + listChapters.SelectedIndex = 0; + } + + public void PopulateTopics() + { + var chapter = listChapters.SelectedItem as HelpSystem.HelpChapter; + if (chapter == null) return; + + this.listTopics.Items.Clear(); + + // Populate + foreach (var i in chapter.Topics) + listTopics.Items.Add(i); + } + + public void PopulateTopics(IEnumerable topics) + { + this.listTopics.Items.Clear(); + foreach (var i in topics) listTopics.Items.Add(i); + } + + #endregion + + #region User input + + private void Button_IsEnabledChanged(object sender, DependencyPropertyChangedEventArgs e) + { + Button b = sender as Button; + if (b == null) return; + + b.Opacity = (b.IsEnabled) ? 1.0 : .5; + } + + #region Search function + + private void bSearchOptions_Click(object sender, RoutedEventArgs e) + { + bSearchOptions.ContextMenu.IsOpen = true; + } + + private void bSearchHandler() + { + if (textSearch.Text == "") return; + + // Hide search button, and show clear button + bClear.Visibility = System.Windows.Visibility.Visible; + bSearch.Visibility = System.Windows.Visibility.Collapsed; + + // Clear previous searches + if (searchLastType != -1) clearSearchCommon(); + + // Search title only + if (searchTitleOnly.IsChecked.HasValue && searchTitleOnly.IsChecked.Value) + { + var temp = listChapters.SelectedItem as HelpSystem.HelpChapter; + if (temp == null) return; + + listTopics.Items.Clear(); + + PopulateTopics(HelpSystem.HelpManager.SearchTitle(textSearch.Text, temp)); + } + + else if (searchContent.IsChecked.HasValue && searchContent.IsChecked.Value) + { + var temp = listChapters.SelectedItem as HelpSystem.HelpChapter; + if (temp == null) return; + + listTopics.Items.Clear(); + + PopulateTopics(HelpSystem.HelpManager.SearchText(textSearch.Text, temp)); + } + + else if (searchPage.IsChecked.HasValue && searchPage.IsChecked.Value) + { + searchSavedHtml = HelpSystem.HelpHtmlWrapper.GetHtml(webBrowser.Document); + HelpSystem.HelpHtmlWrapper.Find(webBrowser.Document, textSearch.Text); + searchLastType = 3; + } + + } + + private void clearSearchCommon() + { + if (searchLastType == 3) HelpSystem.HelpHtmlWrapper.SetHtml(webBrowser.Document, searchSavedHtml); + else PopulateTopics(); + + searchLastType = -1; + } + + private void bClear_Click(object sender, RoutedEventArgs e) + { + bClear.Visibility = System.Windows.Visibility.Collapsed; + bSearch.Visibility = System.Windows.Visibility.Visible; + textSearch.Clear(); + + clearSearchCommon(); + } + + private void bSearch_Click(object sender, RoutedEventArgs e) + { + bSearchHandler(); + } + + private void textSearch_KeyDown(object sender, KeyEventArgs e) + { + if (e.Key == Key.Return) + { + e.Handled = true; + bSearchHandler(); + } + } + + #endregion + + #region Web Browser + private void bBrowseBack_Click(object sender, RoutedEventArgs e) + { + webBrowser.GoBack(); + } + + private void bBrowseForward_Click(object sender, RoutedEventArgs e) + { + webBrowser.GoForward(); + } + + private void bBrowseHome_Click(object sender, RoutedEventArgs e) + { + var item = listChapters.SelectedItem as HelpSystem.HelpChapter; + if (item != null) webBrowser.Navigate(new Uri(HelpSystem.HelpManager.GetFullPath(item.Filename))); + } + + private void webBrowser_Navigated(object sender, System.Windows.Navigation.NavigationEventArgs e) + { + if (searchLastType == 3) bClear_Click(this, new RoutedEventArgs()); + + bBrowseBack.IsEnabled = webBrowser.CanGoBack; + bBrowseForward.IsEnabled = webBrowser.CanGoForward; + } + + #endregion + + #region Navigation + private void listTopics_SelectionChanged(object sender, SelectionChangedEventArgs e) + { + var sel = listTopics.SelectedItem as HelpSystem.HelpTopic; + if (sel != null) webBrowser.Navigate(new Uri(HelpSystem.HelpManager.GetFullPath(sel.Filename))); + } + + private void listChapters_SelectionChanged(object sender, SelectionChangedEventArgs e) + { + var sel = listChapters.SelectedItem as HelpSystem.HelpChapter; + if (sel != null) + { + webBrowser.Navigate(new Uri(HelpSystem.HelpManager.GetFullPath(sel.Filename))); + PopulateTopics(); + } + } + #endregion + + #endregion + } +} diff --git a/Source/Help/Properties/AssemblyInfo.cs b/Source/Help/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..61b5788 --- /dev/null +++ b/Source/Help/Properties/AssemblyInfo.cs @@ -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("Help")] +[assembly: AssemblyDescription("Displays help content.")] +[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 +//CultureYouAreCodingWith in your .csproj file +//inside a . For example, if you are using US english +//in your source files, set the 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")] diff --git a/Source/Help/Properties/Resources.Designer.cs b/Source/Help/Properties/Resources.Designer.cs new file mode 100644 index 0000000..49ae0f2 --- /dev/null +++ b/Source/Help/Properties/Resources.Designer.cs @@ -0,0 +1,71 @@ +//------------------------------------------------------------------------------ +// +// 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. +// +//------------------------------------------------------------------------------ + +namespace Help.Properties +{ + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // 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() + { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [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("Help.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture + { + get + { + return resourceCulture; + } + set + { + resourceCulture = value; + } + } + } +} diff --git a/Source/Help/Properties/Resources.resx b/Source/Help/Properties/Resources.resx new file mode 100644 index 0000000..af7dbeb --- /dev/null +++ b/Source/Help/Properties/Resources.resx @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Source/Help/Properties/Settings.Designer.cs b/Source/Help/Properties/Settings.Designer.cs new file mode 100644 index 0000000..1cb7aea --- /dev/null +++ b/Source/Help/Properties/Settings.Designer.cs @@ -0,0 +1,30 @@ +//------------------------------------------------------------------------------ +// +// 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. +// +//------------------------------------------------------------------------------ + +namespace Help.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; + } + } + } +} diff --git a/Source/Help/Properties/Settings.settings b/Source/Help/Properties/Settings.settings new file mode 100644 index 0000000..033d7a5 --- /dev/null +++ b/Source/Help/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/Source/Help/Styles/SearchTextbox.xaml b/Source/Help/Styles/SearchTextbox.xaml new file mode 100644 index 0000000..11e9d68 --- /dev/null +++ b/Source/Help/Styles/SearchTextbox.xaml @@ -0,0 +1,43 @@ + + + + + \ No newline at end of file diff --git a/Source/Help/documentation/apps/calculator/2ndf.htm b/Source/Help/documentation/apps/calculator/2ndf.htm new file mode 100644 index 0000000..e31366e --- /dev/null +++ b/Source/Help/documentation/apps/calculator/2ndf.htm @@ -0,0 +1,50 @@ + + + + + Scientific Calculator: 2nd function button + + + + + +

Scientific Calculator: 2nd function button

+ +
+

Content

+ +
+ +
+
+
+ When activated, an indicator shows up on the display. +
+ + +

Description

+ +

The 2nd function button is used to change the function of a button when clicked.

+

Usually, the 2nd function is the inverse of the function the button is assigned to. The exact function is displayed in gray above each button. You can find more information about the function and 2nd function of a button when hovering over the button with the mouse.

+

You can also use the 2nd function of a button using the right mouse button.

+
+ +
+ +

Example

+ + +

To calculate the square root of a number, you have to press 2ndf and then the x2 button.

+

Note: You can also right click the x2 button.

+ +
+ + + + \ No newline at end of file diff --git a/Source/Help/documentation/apps/calculator/abs.htm b/Source/Help/documentation/apps/calculator/abs.htm new file mode 100644 index 0000000..04ccac5 --- /dev/null +++ b/Source/Help/documentation/apps/calculator/abs.htm @@ -0,0 +1,41 @@ + + + + + Scientific Calculator: Absolute + + + + + +

Scientific Calculator: Absolute

+ +
+

Content

+ +
+ +
+ +

Description

+ +

In mathematics, the absolute (modulus) of a number, denoted by |n|, is equal to the number without regard to its sign.

+ +
+ +
+ +

Examples

+
+ +
+ + + + \ No newline at end of file diff --git a/Source/Help/documentation/apps/calculator/buttons.htm b/Source/Help/documentation/apps/calculator/buttons.htm new file mode 100644 index 0000000..fe59e73 --- /dev/null +++ b/Source/Help/documentation/apps/calculator/buttons.htm @@ -0,0 +1,377 @@ + + + + + Scientific Calculator: Buttons + + + + + + +

Scientific Calculator: Buttons

+
+ +

Buttons

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Button Description Article
+Adds a number to another.
-Subtracts a number from another.
*Multiplies 2 numbers.
/Divide a number by another.
Toggle sign.
MODCalculates the remainder of division between 2 numbers.
ACResets any calculation.
ClearDeletes the current number.
Removes the last inserted number.
 
HelpOpens help for the application.
M+Adds the number on the display to memory.
M-Subtracts the number on the display from memory.
MCMemory Clear: Clears the memory content.
MSMemory Set: Sets the memory content to the number on the display.
MRMemory Recall: Displays the memory content on the display.
 
2ndfActivates alternative function for the next button pressed.
enExponential function.
lnCalculates natural logarithm.
10nCalculates 10 at nth power.
logCalculates decimal logarithm.
logn xCalculates logarithm of x in base n.
 
{x}Calculates fractional part of a number.
[x]Calculates integer part of a number.
-AbsCalculates negative absolute of a number.
AbsCalculates absolute of a number.
1/xCalculates the multiplicative inverse of a number.
n√xCalculates nth root of a number.
xnCalculates x at nth power.
 
arcsinCalculates arcsine of a number (result is in radians).
sinCalculates sine of a number (in radians).
arccosCalculates arccosine of a number (result is in radians).
cosCalculates cosine of a number (in radians).
arctanCalculates arctangent of a number (result is in radians).
tanCalculates tangent of a number (in radians).
√xCalculates square root of a number.
x2Calculates x squared.
 
arcsinhCalculates hyperbolic arcsine of a number.
sinhCalculates hyperbolic sine of a number.
arccoshCalculates hyperbolic arccosine of a number.
coshCalculates hyperbolic cosine of a number.
arctanhCalculates hyperbolic arctangent of a number.
tanhCalculates hyperbolic tangent of a number.
3√xCalculates cube root of a number.
x3Calculates cube of x.
 
Displays double value of pi.
Displays pi constant.
eDisplays e constant.
xPyCalculates arrangements of y items from x.
xCyCalculates combinations of y items from x.
x!Calculates factorial of x.
+ +
+ +
+ + + + \ No newline at end of file diff --git a/Source/Help/documentation/apps/calculator/combinatorics.htm b/Source/Help/documentation/apps/calculator/combinatorics.htm new file mode 100644 index 0000000..9114be6 --- /dev/null +++ b/Source/Help/documentation/apps/calculator/combinatorics.htm @@ -0,0 +1,90 @@ + + + + + Scientific Calculator: Combinatorics + + + + + +

Scientific Calculator: Combinatorics

+ + + + +
+ +

Factorial

+ +

In mathematics, the factorial of a natural number, denoted by n!, is the product of all natural numbers smaller or equal to n.

+ + + +

This can also be written as:

+ + +

By convention, 0! = 1.

+

Example:

+ +

+
+ +
+ +

Permutations

+ +

In mathematics, a permutation of a set of objects is defined as a particular order of the items.

+

For example, the permutations of the set {1, 2, 3} are:
(1, 2, 3); (1, 3, 2); (2, 1, 3); (2, 3, 1); (3, 1, 2); (3, 2, 1);

+ +

The number of permutations for a set is given by n!.

+
+
+ +
+ +

Permutations of k objects

+ +

Example: the permutations of 2 items from the set {1, 2, 3} are:
+ (1, 2); (2, 1); (1, 3); (3, 1); (2, 3); (3, 2);

+ +

The number of permutations of k objects is given by the formula:

+ +

After making the simplifications, we get:

+ +

+
+ +
+ +

Combinations

+ +

In mathematics, a combination is a method of selecting a number of objects from a larger set, where order doesn't matter.

+ +

For example, the combinations of 2 items from the set {1, 2, 3} are:
+ {1, 2}; {1, 3}; {2, 3};

+ +

The number of combinations is given by the formula:

+ +

After making the simplifications, we get:

+ +

+
+ + + + + + \ No newline at end of file diff --git a/Source/Help/documentation/apps/calculator/constants.htm b/Source/Help/documentation/apps/calculator/constants.htm new file mode 100644 index 0000000..ad5cb9d --- /dev/null +++ b/Source/Help/documentation/apps/calculator/constants.htm @@ -0,0 +1,53 @@ + + + + + Scientific Calculator: Constants + + + + + +

Scientific Calculator: Constants

+ +
+

Content

+ +
+ +
+ +

π

+ +

π (sometimes written pi) is a mathematical constant that is the ratio of any Euclidian circle's circumference to its diameter.

+

The approximate value of pi is:

+ + +

Pi has many uses in mathematics, science and engineering, making it one of the most important constants.

+
+ +
+ +

e

+ +

e is an important mathematical constant that is the base of natural logarithms.

+ +

The constant is the result of the following limit:

+ + +

The approximate value of e is:

+ + + + +
+ + + + \ No newline at end of file diff --git a/Source/Help/documentation/apps/calculator/img/background.png b/Source/Help/documentation/apps/calculator/img/background.png new file mode 100644 index 0000000..a686f00 Binary files /dev/null and b/Source/Help/documentation/apps/calculator/img/background.png differ diff --git a/Source/Help/documentation/apps/calculator/img/calc-2ndf0.png b/Source/Help/documentation/apps/calculator/img/calc-2ndf0.png new file mode 100644 index 0000000..c72ba7e Binary files /dev/null and b/Source/Help/documentation/apps/calculator/img/calc-2ndf0.png differ diff --git a/Source/Help/documentation/apps/calculator/img/calc-2ndf1.png b/Source/Help/documentation/apps/calculator/img/calc-2ndf1.png new file mode 100644 index 0000000..5b9eac4 Binary files /dev/null and b/Source/Help/documentation/apps/calculator/img/calc-2ndf1.png differ diff --git a/Source/Help/documentation/apps/calculator/img/calc-abs-eq0.gif b/Source/Help/documentation/apps/calculator/img/calc-abs-eq0.gif new file mode 100644 index 0000000..098a620 Binary files /dev/null and b/Source/Help/documentation/apps/calculator/img/calc-abs-eq0.gif differ diff --git a/Source/Help/documentation/apps/calculator/img/calc-abs-eq1.gif b/Source/Help/documentation/apps/calculator/img/calc-abs-eq1.gif new file mode 100644 index 0000000..0a10441 Binary files /dev/null and b/Source/Help/documentation/apps/calculator/img/calc-abs-eq1.gif differ diff --git a/Source/Help/documentation/apps/calculator/img/calc-combinatorics-eq0.gif b/Source/Help/documentation/apps/calculator/img/calc-combinatorics-eq0.gif new file mode 100644 index 0000000..845607e Binary files /dev/null and b/Source/Help/documentation/apps/calculator/img/calc-combinatorics-eq0.gif differ diff --git a/Source/Help/documentation/apps/calculator/img/calc-combinatorics-eq1.gif b/Source/Help/documentation/apps/calculator/img/calc-combinatorics-eq1.gif new file mode 100644 index 0000000..0bf0a75 Binary files /dev/null and b/Source/Help/documentation/apps/calculator/img/calc-combinatorics-eq1.gif differ diff --git a/Source/Help/documentation/apps/calculator/img/calc-combinatorics-eq2.gif b/Source/Help/documentation/apps/calculator/img/calc-combinatorics-eq2.gif new file mode 100644 index 0000000..694eedf Binary files /dev/null and b/Source/Help/documentation/apps/calculator/img/calc-combinatorics-eq2.gif differ diff --git a/Source/Help/documentation/apps/calculator/img/calc-combinatorics-eq3.gif b/Source/Help/documentation/apps/calculator/img/calc-combinatorics-eq3.gif new file mode 100644 index 0000000..da99fe5 Binary files /dev/null and b/Source/Help/documentation/apps/calculator/img/calc-combinatorics-eq3.gif differ diff --git a/Source/Help/documentation/apps/calculator/img/calc-combinatorics-eq4.gif b/Source/Help/documentation/apps/calculator/img/calc-combinatorics-eq4.gif new file mode 100644 index 0000000..d1c390c Binary files /dev/null and b/Source/Help/documentation/apps/calculator/img/calc-combinatorics-eq4.gif differ diff --git a/Source/Help/documentation/apps/calculator/img/calc-combinatorics-eq5.gif b/Source/Help/documentation/apps/calculator/img/calc-combinatorics-eq5.gif new file mode 100644 index 0000000..3b1e1d2 Binary files /dev/null and b/Source/Help/documentation/apps/calculator/img/calc-combinatorics-eq5.gif differ diff --git a/Source/Help/documentation/apps/calculator/img/calc-combinatorics-eq6.gif b/Source/Help/documentation/apps/calculator/img/calc-combinatorics-eq6.gif new file mode 100644 index 0000000..acbb37e Binary files /dev/null and b/Source/Help/documentation/apps/calculator/img/calc-combinatorics-eq6.gif differ diff --git a/Source/Help/documentation/apps/calculator/img/calc-constants-eq0.gif b/Source/Help/documentation/apps/calculator/img/calc-constants-eq0.gif new file mode 100644 index 0000000..33f3728 Binary files /dev/null and b/Source/Help/documentation/apps/calculator/img/calc-constants-eq0.gif differ diff --git a/Source/Help/documentation/apps/calculator/img/calc-constants-eq1.gif b/Source/Help/documentation/apps/calculator/img/calc-constants-eq1.gif new file mode 100644 index 0000000..c8d1faa Binary files /dev/null and b/Source/Help/documentation/apps/calculator/img/calc-constants-eq1.gif differ diff --git a/Source/Help/documentation/apps/calculator/img/calc-constants-eq2.gif b/Source/Help/documentation/apps/calculator/img/calc-constants-eq2.gif new file mode 100644 index 0000000..7ca44b5 Binary files /dev/null and b/Source/Help/documentation/apps/calculator/img/calc-constants-eq2.gif differ diff --git a/Source/Help/documentation/apps/calculator/img/calc-int-eq0.gif b/Source/Help/documentation/apps/calculator/img/calc-int-eq0.gif new file mode 100644 index 0000000..1983f58 Binary files /dev/null and b/Source/Help/documentation/apps/calculator/img/calc-int-eq0.gif differ diff --git a/Source/Help/documentation/apps/calculator/img/calc-int-eq1.gif b/Source/Help/documentation/apps/calculator/img/calc-int-eq1.gif new file mode 100644 index 0000000..93212e7 Binary files /dev/null and b/Source/Help/documentation/apps/calculator/img/calc-int-eq1.gif differ diff --git a/Source/Help/documentation/apps/calculator/img/calc-int-eq2.gif b/Source/Help/documentation/apps/calculator/img/calc-int-eq2.gif new file mode 100644 index 0000000..246fd53 Binary files /dev/null and b/Source/Help/documentation/apps/calculator/img/calc-int-eq2.gif differ diff --git a/Source/Help/documentation/apps/calculator/img/calc-int-eq3.gif b/Source/Help/documentation/apps/calculator/img/calc-int-eq3.gif new file mode 100644 index 0000000..2c40ebb Binary files /dev/null and b/Source/Help/documentation/apps/calculator/img/calc-int-eq3.gif differ diff --git a/Source/Help/documentation/apps/calculator/img/calc-int-eq4.gif b/Source/Help/documentation/apps/calculator/img/calc-int-eq4.gif new file mode 100644 index 0000000..199216a Binary files /dev/null and b/Source/Help/documentation/apps/calculator/img/calc-int-eq4.gif differ diff --git a/Source/Help/documentation/apps/calculator/img/calc-inverse-eq0.gif b/Source/Help/documentation/apps/calculator/img/calc-inverse-eq0.gif new file mode 100644 index 0000000..290c4ad Binary files /dev/null and b/Source/Help/documentation/apps/calculator/img/calc-inverse-eq0.gif differ diff --git a/Source/Help/documentation/apps/calculator/img/calc-ui.png b/Source/Help/documentation/apps/calculator/img/calc-ui.png new file mode 100644 index 0000000..04b82b8 Binary files /dev/null and b/Source/Help/documentation/apps/calculator/img/calc-ui.png differ diff --git a/Source/Help/documentation/apps/calculator/img/link.png b/Source/Help/documentation/apps/calculator/img/link.png new file mode 100644 index 0000000..61e8e8e Binary files /dev/null and b/Source/Help/documentation/apps/calculator/img/link.png differ diff --git a/Source/Help/documentation/apps/calculator/index.htm b/Source/Help/documentation/apps/calculator/index.htm new file mode 100644 index 0000000..2d16889 --- /dev/null +++ b/Source/Help/documentation/apps/calculator/index.htm @@ -0,0 +1,83 @@ + + + + + Scientific Calculator + + + + + +

Scientific Calculator

+ + + +
+ +

The user interface

+ + +
    +
  1. Display
  2. +
  3. Indicator area
  4. +
  5. Clearing functions and help
  6. +
  7. Basic operators
  8. +
  9. Numeric keys
  10. +
  11. Memory functions
  12. +
  13. Advanced functions
  14. +
+
+ +
+ +

Limitations

+

The calculator is limited to 64bit floating point numbers (approximate range: 5.0 10-324 to 1.7 10308, or 15-16 digits).

+
+ + + + + + \ No newline at end of file diff --git a/Source/Help/documentation/apps/calculator/int.htm b/Source/Help/documentation/apps/calculator/int.htm new file mode 100644 index 0000000..53b9484 --- /dev/null +++ b/Source/Help/documentation/apps/calculator/int.htm @@ -0,0 +1,63 @@ + + + + + Scientific Calculator: Integer and fractional part + + + + + +

Scientific Calculator: Integer and fractional part

+ +
+

Content

+ +
+ +
+ +

Integer part

+ +

In mathematics, the floor (also known as the integer part) of a number n is the biggest integer number that is smaller than n.

+ +

The ceiling of a number n is the smallest integer number that is greater than n.

+ +
+

Notation:

+

The floor (integer part) of a number n: [n] = ⌊n⌋

+ +

The ceiling: ⌈n⌉

+ +
+

Examples:


+
+

+ +
+ +
+ +

Fractional part

+ +

In mathematics, any real number can be written as n + r, where n is an integer, and r (the fractional part) is a nonnegative real number smaller than 1.

+ +

The fractional part of a number n can be written as the difference between n and its integer part (floor):

+ + +
+

Examples:


+
+

+ +
+ + + + \ No newline at end of file diff --git a/Source/Help/documentation/apps/calculator/inverse.htm b/Source/Help/documentation/apps/calculator/inverse.htm new file mode 100644 index 0000000..0742b60 --- /dev/null +++ b/Source/Help/documentation/apps/calculator/inverse.htm @@ -0,0 +1,28 @@ + + + + + Scientific Calculator: Multiplicative inverse + + + + + +

Scientific Calculator: Multiplicative inverse

+
+

Multiplicative inverse

+ +

In mathematics, the multiplicative inverse of a number n is a number which, when multiplied by n, yields the multiplicative identity 1.

+ +

The multiplicative inverse of a number n is denoted by:

+ +
+ +
+ + + + \ No newline at end of file diff --git a/Source/Help/documentation/apps/calculator/keyshortcuts.htm b/Source/Help/documentation/apps/calculator/keyshortcuts.htm new file mode 100644 index 0000000..3a4b4b0 --- /dev/null +++ b/Source/Help/documentation/apps/calculator/keyshortcuts.htm @@ -0,0 +1,130 @@ + + + + + Scientific Calculator: Keyboard shortcuts + + + + + + +

Scientific Calculator: Keyboard shortcuts

+
+ +

Keyboard shortcuts

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Key combination Button equivalent Action
Num+ (+)+Adds a number to another.
Num- (-)-Subtracts a number from another.
Num**Multiplies 2 numbers.
Num/ (/)/Divide a number by another.
EscapeACResets any calculation.
DeleteClearDeletes the current number.
BackspaceRemoves the last inserted number.
F1HelpOpens help for the application.
Enter=Performs the calculation.
Ctrl + QCloses the application.
+ +
+ +
+ + + + \ No newline at end of file diff --git a/Source/Help/documentation/apps/calculator/logexp.htm b/Source/Help/documentation/apps/calculator/logexp.htm new file mode 100644 index 0000000..1243225 --- /dev/null +++ b/Source/Help/documentation/apps/calculator/logexp.htm @@ -0,0 +1,11 @@ + + + Calculator Help + + + + +

Hello world! :)

+ My name is Tibi. + + \ No newline at end of file diff --git a/Source/Help/documentation/apps/calculator/pow.htm b/Source/Help/documentation/apps/calculator/pow.htm new file mode 100644 index 0000000..1243225 --- /dev/null +++ b/Source/Help/documentation/apps/calculator/pow.htm @@ -0,0 +1,11 @@ + + + Calculator Help + + + + +

Hello world! :)

+ My name is Tibi. + + \ No newline at end of file diff --git a/Source/Help/documentation/apps/calculator/style.css b/Source/Help/documentation/apps/calculator/style.css new file mode 100644 index 0000000..863d322 --- /dev/null +++ b/Source/Help/documentation/apps/calculator/style.css @@ -0,0 +1,119 @@ +body { + font-family: Verdana, sans-serif; + font-size: 10.5pt; + background: #F0F0F0; + margin:0px; + padding: 5px; + + /*filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#F0F0F0', endColorstr='#A0A0A0'); + background: -webkit-gradient(linear, left top, left bottom, from(#F0F0F0), to(#A0A0A0)); + background: -moz-linear-gradient(top, #F0F0F0, #A0A0A0);*/ + + background-image: url("img/background.png"); + background-repeat: repeat-x; + background-position: top center; + background-attachment: fixed; +} + +.section { + margin: 5px; + margin-top: 10px; + padding: 5px; + padding-left: 15px; + min-width: 600px; + + border: 1px solid silver; + background-color: #F5F5F5; + border-radius: 10px; + -moz-border-radius: 10px; + -webkit-border-radius: 10px; + + box-shadow: 0px 3px 7px rgba(68,68,68,0.6); + -mox-box-shadow: 0px 3px 7px rgba(68,68,68,0.6); + -webkig-box-shadow: 0px 3px 7px rgba(68,68,68,0.6); +} + +.footer { + margin-top: 20px; + color: #777; + text-align: center; + font-size: 10pt; +} + +a { + text-decoration: none; + color: #248AC9; +} + +a:hover { + color: #8DCFF7; +} + +a > img { + border: 0px; +} + +h1 { + margin:5px; + margin-bottom: 15px; + font-size: 18pt; + font-family: Arial, sans-serif; + font-weight: normal; + color: #606060; +} + +h1:hover { + color: #909090; +} + +h2 { + margin-top: -2px; + margin-left: -7px; + margin-bottom: 15px; + font-family: Arial, sans-serif; + font-size: 13pt; + font-weight: bold; + color: Silver; +} + +h3 { + margin-top: 10px; + margin-bottom: -10px; + font-family: Arial, sans-serif; + font-size: 14px; + font-weight: bold; + color: #555; +} + + + +img.shadow { + background: white; + + box-shadow: 2px 2px 7px rgba(68,68,68,0.4); + -mox-box-shadow: 2px 2px 7px rgba(68,68,68,0.4); + -webkig-box-shadow: 2px 2px 7px rgba(68,68,68,0.4); +} + +img.maths { + margin-left: 2em; + margin-bottom: 5px; +} + +.captioned_image_right { + float:right; + margin-left: 10px; + margin-bottom: 10px; + text-align: center; + background: white; + padding:5px; + width:150px; + + box-shadow: 2px 2px 7px rgba(68,68,68,0.4); + -mox-box-shadow: 2px 2px 7px rgba(68,68,68,0.4); + -webkig-box-shadow: 2px 2px 7px rgba(68,68,68,0.4); + + border-radius: 5px; + -moz-border-radius: 5px; + -webkit-border-radius: 5px; +} \ No newline at end of file diff --git a/Source/Help/documentation/apps/calculator/trigonometric.htm b/Source/Help/documentation/apps/calculator/trigonometric.htm new file mode 100644 index 0000000..1243225 --- /dev/null +++ b/Source/Help/documentation/apps/calculator/trigonometric.htm @@ -0,0 +1,11 @@ + + + Calculator Help + + + + +

Hello world! :)

+ My name is Tibi. + + \ No newline at end of file diff --git a/Source/Help/documentation/apps/factorizator/img/background.png b/Source/Help/documentation/apps/factorizator/img/background.png new file mode 100644 index 0000000..a686f00 Binary files /dev/null and b/Source/Help/documentation/apps/factorizator/img/background.png differ diff --git a/Source/Help/documentation/apps/factorizator/img/interface.png b/Source/Help/documentation/apps/factorizator/img/interface.png new file mode 100644 index 0000000..bd6dd74 Binary files /dev/null and b/Source/Help/documentation/apps/factorizator/img/interface.png differ diff --git a/Source/Help/documentation/apps/factorizator/img/link.png b/Source/Help/documentation/apps/factorizator/img/link.png new file mode 100644 index 0000000..61e8e8e Binary files /dev/null and b/Source/Help/documentation/apps/factorizator/img/link.png differ diff --git a/Source/Help/documentation/apps/factorizator/index.bak b/Source/Help/documentation/apps/factorizator/index.bak new file mode 100644 index 0000000..d331a7f --- /dev/null +++ b/Source/Help/documentation/apps/factorizator/index.bak @@ -0,0 +1,116 @@ + + + + + Factorizator + + + + + +

Factorizator

+ + + +
+ +

Getting started

+ +

The Factorizator is an application which displays the factorization of natural numbers. Factorization is defined as the decomposition of the number into prime factors, which multiplied will yeld the original number.

+ +

Using the application is very simple, one has to simply type a number in the input text box, and press Calculate (or Enter key). The result is displayed in the Factorization area. The first column shows the original numbers divided by the last divisor, and in the divisor column, the divisors are listed.

+
+ +
+ +

The user interface

+ + +
    +
  1. Input number: this is where a number is written.
  2. +
  3. Calculate button: press this button (or the Enter key) to begin calculation.
  4. +
  5. Remainder column: the result of the previous number divided by the divisor.
  6. +
  7. Divisor column: the smallest divisor (excluding 1) of the coresponding remainder.
  8. +
  9. Copy remainder menu item: copies the selected reminder into clipboard.
  10. +
  11. Copy divisor menu item: copies the selected divisor into clipboard.
  12. +
  13. Copy remainder menu item: empties the Factorization area.
  14. +
  15. Status message: displays the current operation taking place.
  16. +
  17. Cancel button: this button appears when a long calculation is taking place, so that the user may cancel if the operation is taking too long.
  18. + +
+
+ +
+ +

Keyboard shortcuts

+ + + + + + + + + + + + + + + + + + + + + +
Key combination Action
EnterPerforms calculation.
F1Starts help.
Ctrl + CCopies selected remainder into clipboard.
Ctrl + Shift + CCopies selected divisor into clipboard.
+
+ +
+ +

Limitations

+

The calculator is limited to 128bit floating point numbers (approximate range: 1.0 10-28 to 7.9 1028, or 28-29 digits). However, since factorization can only be done for integer numbers, the numbers that are not integer will be trimmed.

+
+ + + + \ No newline at end of file diff --git a/Source/Help/documentation/apps/factorizator/index.htm b/Source/Help/documentation/apps/factorizator/index.htm new file mode 100644 index 0000000..a01da77 --- /dev/null +++ b/Source/Help/documentation/apps/factorizator/index.htm @@ -0,0 +1,116 @@ + + + + + Factorizator + + + + + +

Factorizator

+ + + +
+ +

Getting started

+ +

The Factorizator is an application which displays the factorization of natural numbers. Factorization is defined as the decomposition of the number into prime factors, which multiplied will yield the original number.

+ +

Using the application is very simple, one has to simply type a number in the input text box, and press Calculate (or Enter key). The result is displayed in the Factorization area. The first column shows the original numbers divided by the last divisor, and in the divisor column, the divisors are listed.

+
+ +
+ +

The user interface

+ + +
    +
  1. Input number: this is where a number is written.
  2. +
  3. Calculate button: press this button (or the Enter key) to begin calculation.
  4. +
  5. Remainder column: the result of the previous number divided by the divisor.
  6. +
  7. Divisor column: the smallest divisor (excluding 1) of the corresponding remainder.
  8. +
  9. Copy remainder menu item: copies the selected reminder into clipboard.
  10. +
  11. Copy divisor menu item: copies the selected divisor into clipboard.
  12. +
  13. Copy remainder menu item: empties the Factorization area.
  14. +
  15. Status message: displays the current operation taking place.
  16. +
  17. Cancel button: this button appears when a long calculation is taking place, so that the user may cancel if the operation is taking too long.
  18. + +
+
+ +
+ +

Keyboard shortcuts

+ + + + + + + + + + + + + + + + + + + + + +
Key combination Action
EnterPerforms calculation.
F1Starts help.
Ctrl + CCopies selected remainder into clipboard.
Ctrl + Shift + CCopies selected divisor into clipboard.
+
+ +
+ +

Limitations

+

The calculator is limited to 128bit floating point numbers (approximate range: 1.0 10-28 to 7.9 1028, or 28-29 digits). However, since factorization can only be done for integer numbers, the numbers that are not integer will be trimmed.

+
+ + + + \ No newline at end of file diff --git a/Source/Help/documentation/apps/factorizator/style.css b/Source/Help/documentation/apps/factorizator/style.css new file mode 100644 index 0000000..863d322 --- /dev/null +++ b/Source/Help/documentation/apps/factorizator/style.css @@ -0,0 +1,119 @@ +body { + font-family: Verdana, sans-serif; + font-size: 10.5pt; + background: #F0F0F0; + margin:0px; + padding: 5px; + + /*filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#F0F0F0', endColorstr='#A0A0A0'); + background: -webkit-gradient(linear, left top, left bottom, from(#F0F0F0), to(#A0A0A0)); + background: -moz-linear-gradient(top, #F0F0F0, #A0A0A0);*/ + + background-image: url("img/background.png"); + background-repeat: repeat-x; + background-position: top center; + background-attachment: fixed; +} + +.section { + margin: 5px; + margin-top: 10px; + padding: 5px; + padding-left: 15px; + min-width: 600px; + + border: 1px solid silver; + background-color: #F5F5F5; + border-radius: 10px; + -moz-border-radius: 10px; + -webkit-border-radius: 10px; + + box-shadow: 0px 3px 7px rgba(68,68,68,0.6); + -mox-box-shadow: 0px 3px 7px rgba(68,68,68,0.6); + -webkig-box-shadow: 0px 3px 7px rgba(68,68,68,0.6); +} + +.footer { + margin-top: 20px; + color: #777; + text-align: center; + font-size: 10pt; +} + +a { + text-decoration: none; + color: #248AC9; +} + +a:hover { + color: #8DCFF7; +} + +a > img { + border: 0px; +} + +h1 { + margin:5px; + margin-bottom: 15px; + font-size: 18pt; + font-family: Arial, sans-serif; + font-weight: normal; + color: #606060; +} + +h1:hover { + color: #909090; +} + +h2 { + margin-top: -2px; + margin-left: -7px; + margin-bottom: 15px; + font-family: Arial, sans-serif; + font-size: 13pt; + font-weight: bold; + color: Silver; +} + +h3 { + margin-top: 10px; + margin-bottom: -10px; + font-family: Arial, sans-serif; + font-size: 14px; + font-weight: bold; + color: #555; +} + + + +img.shadow { + background: white; + + box-shadow: 2px 2px 7px rgba(68,68,68,0.4); + -mox-box-shadow: 2px 2px 7px rgba(68,68,68,0.4); + -webkig-box-shadow: 2px 2px 7px rgba(68,68,68,0.4); +} + +img.maths { + margin-left: 2em; + margin-bottom: 5px; +} + +.captioned_image_right { + float:right; + margin-left: 10px; + margin-bottom: 10px; + text-align: center; + background: white; + padding:5px; + width:150px; + + box-shadow: 2px 2px 7px rgba(68,68,68,0.4); + -mox-box-shadow: 2px 2px 7px rgba(68,68,68,0.4); + -webkig-box-shadow: 2px 2px 7px rgba(68,68,68,0.4); + + border-radius: 5px; + -moz-border-radius: 5px; + -webkit-border-radius: 5px; +} \ No newline at end of file diff --git a/Source/Help/documentation/apps/graphing/evaluate.htm b/Source/Help/documentation/apps/graphing/evaluate.htm new file mode 100644 index 0000000..0d28481 --- /dev/null +++ b/Source/Help/documentation/apps/graphing/evaluate.htm @@ -0,0 +1,69 @@ + + + + + Graphing Calculator: Evaluating expressions + + + + + +

Graphing Calculator: Evaluating expressions

+ +
+

Note

+

This article describes how to use the expression evaluator window. If you would like to learn how type an expression, you should go to this article instead.

+
+ +
+

Content

+ +
+ +
+ +

Introduction

+ +

The Expression evaluator is a tool within the Graphing Calculator which can compute the result of a typed mathematical expression.

+
+ +
+ +

Getting started

+

To evaluate an expression, follow the following steps:

+ Step 1: In the application window, click the Evaluate button.
+ Step 2: Type an expression in the Input expression field.
+ Step 3: Add variables to the variable list if needed.
+ Step 4: Click Evaluate.
+ +

Example:

+ +
+ +
+ +

Variables

+ +

A description of what variables are, and why they are useful can be found in the language article.

+ +

To use variables in the evaluator window, you need to type the name in the Name field, the value in the Value field, and click Add. If a variable with the same name already exists, you will be prompted if you want to replace the old value.

+ +

The value of a variable can also be an expression, it doesn't have to be a simple number.

+ + + +

To remove a variable from the list, or edit it, simply right click, and a menu will appear.

+ +
+ + + + + \ No newline at end of file diff --git a/Source/Help/documentation/apps/graphing/export-import.htm b/Source/Help/documentation/apps/graphing/export-import.htm new file mode 100644 index 0000000..31968c1 --- /dev/null +++ b/Source/Help/documentation/apps/graphing/export-import.htm @@ -0,0 +1,40 @@ + + + + + Graphing Calculator: Exporting and importing expressions + + + + + +

Graphing Calculator: Exporting and importing expressions

+ +
+

Content

+ +
+ +
+ +

Exporting

+ +

You can export an expression list from the File menu by clicking Save plotted expressions (or Ctrl+S). Expressions are saved in an XML file which can be imported later.

+
+ +
+ +

Importing

+

To import already saved expressions, select the Import item from the File menu.

+
+ + + + + \ No newline at end of file diff --git a/Source/Help/documentation/apps/graphing/img/background.png b/Source/Help/documentation/apps/graphing/img/background.png new file mode 100644 index 0000000..a686f00 Binary files /dev/null and b/Source/Help/documentation/apps/graphing/img/background.png differ diff --git a/Source/Help/documentation/apps/graphing/img/eval0.png b/Source/Help/documentation/apps/graphing/img/eval0.png new file mode 100644 index 0000000..8f39390 Binary files /dev/null and b/Source/Help/documentation/apps/graphing/img/eval0.png differ diff --git a/Source/Help/documentation/apps/graphing/img/eval1.png b/Source/Help/documentation/apps/graphing/img/eval1.png new file mode 100644 index 0000000..76a12f7 Binary files /dev/null and b/Source/Help/documentation/apps/graphing/img/eval1.png differ diff --git a/Source/Help/documentation/apps/graphing/img/plot0.png b/Source/Help/documentation/apps/graphing/img/plot0.png new file mode 100644 index 0000000..0c7f42c Binary files /dev/null and b/Source/Help/documentation/apps/graphing/img/plot0.png differ diff --git a/Source/Help/documentation/apps/graphing/img/plot1.png b/Source/Help/documentation/apps/graphing/img/plot1.png new file mode 100644 index 0000000..920cbee Binary files /dev/null and b/Source/Help/documentation/apps/graphing/img/plot1.png differ diff --git a/Source/Help/documentation/apps/graphing/img/plot2.png b/Source/Help/documentation/apps/graphing/img/plot2.png new file mode 100644 index 0000000..4e46a17 Binary files /dev/null and b/Source/Help/documentation/apps/graphing/img/plot2.png differ diff --git a/Source/Help/documentation/apps/graphing/img/plot3.png b/Source/Help/documentation/apps/graphing/img/plot3.png new file mode 100644 index 0000000..9f93f3b Binary files /dev/null and b/Source/Help/documentation/apps/graphing/img/plot3.png differ diff --git a/Source/Help/documentation/apps/graphing/img/plot4.png b/Source/Help/documentation/apps/graphing/img/plot4.png new file mode 100644 index 0000000..c2be2f8 Binary files /dev/null and b/Source/Help/documentation/apps/graphing/img/plot4.png differ diff --git a/Source/Help/documentation/apps/graphing/img/pref0.png b/Source/Help/documentation/apps/graphing/img/pref0.png new file mode 100644 index 0000000..92ca947 Binary files /dev/null and b/Source/Help/documentation/apps/graphing/img/pref0.png differ diff --git a/Source/Help/documentation/apps/graphing/img/pref1.png b/Source/Help/documentation/apps/graphing/img/pref1.png new file mode 100644 index 0000000..6223af7 Binary files /dev/null and b/Source/Help/documentation/apps/graphing/img/pref1.png differ diff --git a/Source/Help/documentation/apps/graphing/img/pref2.png b/Source/Help/documentation/apps/graphing/img/pref2.png new file mode 100644 index 0000000..75fc143 Binary files /dev/null and b/Source/Help/documentation/apps/graphing/img/pref2.png differ diff --git a/Source/Help/documentation/apps/graphing/index.htm b/Source/Help/documentation/apps/graphing/index.htm new file mode 100644 index 0000000..1617eaa --- /dev/null +++ b/Source/Help/documentation/apps/graphing/index.htm @@ -0,0 +1,75 @@ + + + + + Graphing Calculator + + + + + +

Graphing Calculator

+ + + +
+ +

Introduction

+ +

The Graphing Calculator is a tool that can evaluate, plot and integrate expressions (or functions). It includes many useful features, like combining multiple graphs, navigation and zoom controls, and saving plotted expressions.

+
+ +
+ +

Limitations

+

All numeric values are limited to 64bit floating point numbers (approximate range: 5.0 10-324 to 1.7 10308, or 15-16 digits).

+ +

Another limitation is the precision of the graph: if the expression has many vertical asymptotes, it may not be plotted correctly.

+
+ + + + + + + \ No newline at end of file diff --git a/Source/Help/documentation/apps/graphing/integrate.bak b/Source/Help/documentation/apps/graphing/integrate.bak new file mode 100644 index 0000000..e0a7a5b --- /dev/null +++ b/Source/Help/documentation/apps/graphing/integrate.bak @@ -0,0 +1,46 @@ + + + + + Graphing Calculator + + + + + +

Graphing Calculator

+ +
+

Content

+ +
+ +
+ +

Introduction

+ +

The Integral calculator is a tool within the Graphing Calculator that can calculate the definite integral of an expression.

+ +

The warning that appears is there because the feature is experimental, and wasn't throughly tested.

+
+ +
+ +

Calculating

+

To calculate a definite integral, follow the steps:

+ Step 1: Click the Integrate button.
+ Step 2: Type an expression in the Expression field.
+ Step 3: Type an interval in the Interval fields.
+ Step 4: Press Calculate to perform the calculation.
+
+ + + + + \ No newline at end of file diff --git a/Source/Help/documentation/apps/graphing/integrate.htm b/Source/Help/documentation/apps/graphing/integrate.htm new file mode 100644 index 0000000..f78c4ee --- /dev/null +++ b/Source/Help/documentation/apps/graphing/integrate.htm @@ -0,0 +1,46 @@ + + + + + Graphing Calculator + + + + + +

Graphing Calculator

+ +
+

Content

+ +
+ +
+ +

Introduction

+ +

The Integral calculator is a tool within the Graphing Calculator that can calculate the definite integral of an expression.

+ +

The warning that appears is there because the feature is experimental, and wasn't thoroughly tested.

+
+ +
+ +

Calculating

+

To calculate a definite integral, follow the steps:

+ Step 1: Click the Integrate button.
+ Step 2: Type an expression in the Expression field.
+ Step 3: Type an interval in the Interval fields.
+ Step 4: Press Calculate to perform the calculation.
+
+ + + + + \ No newline at end of file diff --git a/Source/Help/documentation/apps/graphing/language.bak b/Source/Help/documentation/apps/graphing/language.bak new file mode 100644 index 0000000..574786c --- /dev/null +++ b/Source/Help/documentation/apps/graphing/language.bak @@ -0,0 +1,209 @@ + + + + + Graphing Calculator: The expression language + + + + + + +

Graphing Calculator: The expression language

+ + + +
+ +

Introduction

+ +

The Graphing Calculator evaluates expressions based on a strict set of rules, which form a language. Since the mathematical language is way too complex, and is impossible to write in simple text, this application (and many others) uses a simplified language.

+ +

If you are familiar with programming in a C-like language (C, C++, C#, Java), the language used here is very similar to these programming languages.

+ +
+ +
+ +

Variables

+

A variable is a symbol which may assume any given value. In this application, this symbol is represented by a character string which follows the following rules:

+
    +
  • It always begins with a letter.
  • +
  • It can only contain letters and numbers, so it cannot contain spaces, underscores and other symbols.
  • +
  • Variables are case sensitive. This means that alpha is not the same thing as Alpha. +
+ +

The advantages of using variables are that you can skip having to type an ugly expression multiple times, and you can reevaluate the expression with a different input easily.

+ +

Variables are supported in the Graphing Calculator, with the limitation that they can only be used in the expression evaluator. Using variables in the plotting of graphs, and integrator is not possible. By default, the only used variable is x when plotting and integrating expressions.

+ +
+ +
+ +

Predefined variables

+

The evaluator has two predefined variables:

+
    +
  • pi (π)
  • +
  • e
  • +
+
+ +
+ +

Accepted operators

+

The following operators are accepted:

+ +
    +
  • + (addition)
  • +
  • - (subtraction)
  • +
  • * (multiplication)
  • +
  • / (division)
  • +
  • % (division remainder)
  • +
  • ^ (power)
  • +
+ +

The order of operations is also respected. A higher order means a higher priority. Operations with the same order are evaluated left to right, with the exception of the power operator.

+
    +
  • Order 1: + -
  • +
  • Order 2: * / %
  • +
  • Order 3: ^
  • +
+ +
+ +
+ +

Functions

+

The Graphing Calculator supports only predefined functions at the moment.

+
+ +
+ +

Predefined functions

+

The following functions can be used:

+ +

Roots

+ + + + +
sqrt(x)Square root
cbrt(x)Cube root
root(n, x)Nth root
+ +

Logarithms

+ + + + +
lg(x)Decimal logarithm
ln(x)Natural logarithm
log(b, x)Logarithm of x with base b
+ +

Trigonometric functions:

+ + + + + + + + + + +
sin(x)Sine
sinh(x)Hiperbolic sine
cos(x)Cosine
cosh(x)Hiperbolic cosine
tan(x)Tangent
tanh(x)Hiperbolic tangent
ctan(x)Cotangent
sin(x)Sine
sin(x)Sine
+ +

Inverse trigonometric functions:

+ + + + + +
arcsin(x) or asin(x)Inverse sine
arccos(x) or acos(x)Inverse cosine
arctan(x) or atan(x)Inverse tangent
+ +

Other functions:

+ + + + + + + + + + + +
ceil(x) or ceiling(x)Ceiling, or the smallest integer number, greater than x.
floor(x)Floor, or the greatest integer number, smaller than x.
int(x)Integer part of the number.
truncate(x)Truncates (removes) the fractional part from the number.
round(x, n)Rounds the number to n decimals.
 
abs(x)Absolute
max(x, y)Maximum
min(x, y)Minimum
+ +
+ +
+ +

Syntax rules

+ +

The syntax of this application is more strict than the mathematic language. These are some of the rules:

+ +

Numbers:

+
    +
  • Numbers in scientific format are not accepted.
  • +
  • Digit grouping is not accepted.
  • +
  • The integer and fractional parts of the number must be separated by full stop (.) and not comma.
  • + +
+ +

Functions:

+
    +
  • The parameter(s) of any functions must be enclosed in parantheses. Expressions like sin x will fail to evaluate.
  • +
  • For functions with multiple parameters, the parameters are separated by comma.
  • +
  • The names of functions and variables are case sensitive.
  • +
+ +

Operators:

+
    +
  • Operators of same precedence (order) are evaluated from left to right, with the exception of the power (^) operator which is evaluated from right to left. Otherwise, precedence rules (order of operations) is respected.
  • +
  • Expressions like 3x are not accepted, you must specify the multiplication operator: 3*x
  • +
+ +

Others:

+
    +
  • Writing expressions as functions is currently not supported, so the expression f(x)=2*x will fail to evaluate. Writing it as y=2*x will not work either.
  • +
+ + +
+ + + + + + \ No newline at end of file diff --git a/Source/Help/documentation/apps/graphing/language.htm b/Source/Help/documentation/apps/graphing/language.htm new file mode 100644 index 0000000..692321c --- /dev/null +++ b/Source/Help/documentation/apps/graphing/language.htm @@ -0,0 +1,207 @@ + + + + + Graphing Calculator: The expression language + + + + + + +

Graphing Calculator: The expression language

+ + + +
+ +

Introduction

+ +

The Graphing Calculator evaluates expressions based on a strict set of rules, which form a language. Since the mathematical language is way too complex, and is impossible to write in simple text, this application (and many others) uses a simplified language.

+ +

If you are familiar with programming in a C-like language (C, C++, C#, Java), the language used here is very similar to these programming languages.

+ +
+ +
+ +

Variables

+

A variable is a symbol which may assume any given value. In this application, this symbol is represented by a character string which follows the following rules:

+
    +
  • It always begins with a letter.
  • +
  • It can only contain letters and numbers, so it cannot contain spaces, underscores and other symbols.
  • +
  • Variables are case sensitive. This means that alpha is not the same thing as Alpha. +
+ +

The advantages of using variables are that you can skip having to type an ugly expression multiple times, and you can reevaluate the expression with a different input easily.

+ +

Variables are supported in the Graphing Calculator, with the limitation that they can only be used in the expression evaluator. Using variables in the plotting of graphs, and integrator is not possible. By default, the only used variable is x when plotting and integrating expressions.

+ +
+ +
+ +

Predefined variables

+

The evaluator has two predefined variables:

+
    +
  • pi (π)
  • +
  • e
  • +
+
+ +
+ +

Accepted operators

+

The following operators are accepted:

+ +
    +
  • + (addition)
  • +
  • - (subtraction)
  • +
  • * (multiplication)
  • +
  • / (division)
  • +
  • % (division remainder)
  • +
  • ^ (power)
  • +
+ +

The order of operations is also respected. A higher order means a higher priority. Operations with the same order are evaluated left to right, with the exception of the power operator.

+
    +
  • Order 1: + -
  • +
  • Order 2: * / %
  • +
  • Order 3: ^
  • +
+ +
+ +
+ +

Functions

+

The Graphing Calculator supports only predefined functions at the moment.

+
+ +
+ +

Predefined functions

+

The following functions can be used:

+ +

Roots

+ + + + +
sqrt(x)Square root
cbrt(x)Cube root
root(n, x)Nth root
+ +

Logarithms

+ + + + +
lg(x)Decimal logarithm
ln(x)Natural logarithm
log(b, x)Logarithm of x with base b
+ +

Trigonometric functions:

+ + + + + + + + +
sin(x)Sine
sinh(x)Hyperbolic sine
cos(x)Cosine
cosh(x)Hyperbolic cosine
tan(x)Tangent
tanh(x)Hyperbolic tangent
ctan(x)Cotangent
+ +

Inverse trigonometric functions:

+ + + + + +
arcsin(x) or asin(x)Inverse sine
arccos(x) or acos(x)Inverse cosine
arctan(x) or atan(x)Inverse tangent
+ +

Other functions:

+ + + + + + + + + + + +
ceil(x) or ceiling(x)Ceiling, or the smallest integer number, greater than x.
floor(x)Floor, or the greatest integer number, smaller than x.
int(x)Integer part of the number.
truncate(x)Truncates (removes) the fractional part from the number.
round(x, n)Rounds the number to n decimals.
 
abs(x)Absolute
max(x, y)Maximum
min(x, y)Minimum
+ +
+ +
+ +

Syntax rules

+ +

The syntax of this application is more strict than the mathematic language. These are some of the rules:

+ +

Numbers:

+
    +
  • Numbers in scientific format are not accepted.
  • +
  • Digit grouping is not accepted.
  • +
  • The integer and fractional parts of the number must be separated by full stop (.) and not comma.
  • + +
+ +

Functions:

+
    +
  • The parameter(s) of any functions must be enclosed in parentheses. Expressions like sin x will fail to evaluate.
  • +
  • For functions with multiple parameters, the parameters are separated by comma.
  • +
  • The names of functions and variables are case sensitive.
  • +
+ +

Operators:

+
    +
  • Operators of same precedence (order) are evaluated from left to right, with the exception of the power (^) operator which is evaluated from right to left. Otherwise, precedence rules (order of operations) is respected.
  • +
  • Expressions like 3x are not accepted, you must specify the multiplication operator: 3*x
  • +
+ +

Others:

+
    +
  • Writing expressions as functions is currently not supported, so the expression f(x)=2*x will fail to evaluate. Writing it as y=2*x will not work either.
  • +
+ + +
+ + + + + + \ No newline at end of file diff --git a/Source/Help/documentation/apps/graphing/plot.htm b/Source/Help/documentation/apps/graphing/plot.htm new file mode 100644 index 0000000..0d11675 --- /dev/null +++ b/Source/Help/documentation/apps/graphing/plot.htm @@ -0,0 +1,60 @@ + + + + + Graphing Calculator + + + + + +

Graphing Calculator

+ + + +
+ +

Plotting an expression

+ +

To plot an expression, simply type it in the Input field, and press the Plot button. The color of the expression is generated randomly.

+ + +
+ +
+ +

Multiple expressions

+

Once you plot an expression, it will appear in the Plotted expressions list.

+ + +

From here, you can hide and unhide expressions, delete them from the list, and empty the list using the Clear button.

+
+ +
+ +

Navigation

+

You can navigate using the navigation buttons from the top right corner, or the arrow keys on the keyboard. The center button resets the canvas to the original position.

+ + +

In the bottom right corner, you can see the zoom controls. You can also zoom using the mouse wheel, or the + and - keys.

+ + +

For a better control of the region you want to be drawn, you can type values (or expressions) in the Range area.

+ + +
+ + + + + \ No newline at end of file diff --git a/Source/Help/documentation/apps/graphing/preferences.htm b/Source/Help/documentation/apps/graphing/preferences.htm new file mode 100644 index 0000000..bebb46c --- /dev/null +++ b/Source/Help/documentation/apps/graphing/preferences.htm @@ -0,0 +1,68 @@ + + + + + Graphing Calculator: Preferences + + + + + +

Graphing Calculator: Preferences

+ + + +
+ +

Introduction

+ +

From Preferences you can configure the way graphs are drawn. To access Preferences, open it from the Application menu.

+
+ +
+ +

Graph precision

+

The slider allows you to adjust the precision of the graph. When the precision is lower, drawing is much faster, however it may look bad. When the precision is high, drawing can get very slow, but the graph will look much more accurate.

+ + +
+ +
+ +

Grid numbers precision

+

The slider allows you to adjust how many decimals are shown in the graph. If the value is too high, they may overlap each other.

+ + +
+ +
+ +

Grid density

+

The slider allows you to adjust how many grid lines are drawn.

+ + +
+ +
+ +

Navigation and zoom sensitivity

+

Adjusting these sliders, you can make the graph move and zoom slower or faster.

+
+ + + + + + \ No newline at end of file diff --git a/Source/Help/documentation/apps/graphing/style.css b/Source/Help/documentation/apps/graphing/style.css new file mode 100644 index 0000000..3e03f93 --- /dev/null +++ b/Source/Help/documentation/apps/graphing/style.css @@ -0,0 +1,119 @@ +body { + font-family: Verdana, sans-serif; + font-size: 10.5pt; + background: #F0F0F0; + margin:0px; + padding: 5px; + + /*filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#F0F0F0', endColorstr='#A0A0A0'); + background: -webkit-gradient(linear, left top, left bottom, from(#F0F0F0), to(#A0A0A0)); + background: -moz-linear-gradient(top, #F0F0F0, #A0A0A0);*/ + + background-image: url("img/background.png"); + background-repeat: repeat-x; + background-position: top center; + background-attachment: fixed; +} + +.section { + margin: 5px; + margin-top: 10px; + padding: 5px; + padding-left: 15px; + min-width: 600px; + + border: 1px solid silver; + background-color: #FAFAFA; + border-radius: 10px; + -moz-border-radius: 10px; + -webkit-border-radius: 10px; + + box-shadow: 0px 3px 7px rgba(68,68,68,0.6); + -mox-box-shadow: 0px 3px 7px rgba(68,68,68,0.6); + -webkig-box-shadow: 0px 3px 7px rgba(68,68,68,0.6); +} + +.footer { + margin-top: 20px; + color: #777; + text-align: center; + font-size: 10pt; +} + +a { + text-decoration: none; + color: #248AC9; +} + +a:hover { + color: #8DCFF7; +} + +a > img { + border: 0px; +} + +h1 { + margin:5px; + margin-bottom: 15px; + font-size: 18pt; + font-family: Arial, sans-serif; + font-weight: normal; + color: #606060; +} + +h1:hover { + color: #909090; +} + +h2 { + margin-top: -2px; + margin-left: -7px; + margin-bottom: 15px; + font-family: Arial, sans-serif; + font-size: 13pt; + font-weight: bold; + color: Silver; +} + +h3 { + margin-top: 10px; + margin-bottom: -10px; + font-family: Arial, sans-serif; + font-size: 14px; + font-weight: bold; + color: #555; +} + + + +img.shadow { + background: white; + + box-shadow: 2px 2px 7px rgba(68,68,68,0.4); + -mox-box-shadow: 2px 2px 7px rgba(68,68,68,0.4); + -webkig-box-shadow: 2px 2px 7px rgba(68,68,68,0.4); +} + +img.maths { + margin-left: 2em; + margin-bottom: 5px; +} + +.captioned_image_right { + float:right; + margin-left: 10px; + margin-bottom: 10px; + text-align: center; + background: white; + padding:5px; + width:150px; + + box-shadow: 2px 2px 7px rgba(68,68,68,0.4); + -mox-box-shadow: 2px 2px 7px rgba(68,68,68,0.4); + -webkig-box-shadow: 2px 2px 7px rgba(68,68,68,0.4); + + border-radius: 5px; + -moz-border-radius: 5px; + -webkit-border-radius: 5px; +} \ No newline at end of file diff --git a/Source/Help/documentation/apps/graphing/troubleshooting.bak b/Source/Help/documentation/apps/graphing/troubleshooting.bak new file mode 100644 index 0000000..57189b8 --- /dev/null +++ b/Source/Help/documentation/apps/graphing/troubleshooting.bak @@ -0,0 +1,87 @@ + + + + + Graphing Calculator: Troubleshooting + + + + + +

Graphing Calculator: Troubleshooting

+ + + +
+ +

Application crashes at startup

+

The application needs .NET Framework 4.0 installed. If you don't have it installed, you should download and install it from the Microsoft website.

+
+ +
+ +

Graph is drawn incorrectly

+

Problems with drawing appear when the function has many vertical asymptothes, or the function changes values too often, and is described here. Try increasing the graph precision from preferences.

+
+ +
+ +

Application works slowly

+

This is a known issue, and has to do with the way the functions are drawn. The slowdown appears when resizing the window, or navigating through the graph. We are working on this issue. What you can try is to decrease the graph precision from the preferences.

+
+ +
+ +

I get the Undefined variable error.

+ +

You need to verify you haven't accidentally typed a letter where it shouldn't be. You should also check the language article, to learn about the syntax rules of expressions.

+
+ +
+ +

I get the Undefined function error.

+ +

You have a syntax error, you need to check the language article, to learn the correct syntax of expressions.

+
+ +
+ +

I get the Stack empty error.

+ +

This error usually appears when you didn't give the correct number of parameters to a function. Check this article to verify the parameters.

+
+ +
+ +

I get the Stack empty error.

+ +

This error is pretty self explanatory, check your parantheses.

+
+ +
+ +

I have another problem not covered in the troubleshooting guide.

+ +

You should contact the developer using the contact form. Please, include a useful description of what you were doing when the problem has occured, and eventually a link to a screenshot. The log file which should be located in the directory logs, where the application executable is, would also be very useful.

+
+ + + + + + \ No newline at end of file diff --git a/Source/Help/documentation/apps/graphing/troubleshooting.htm b/Source/Help/documentation/apps/graphing/troubleshooting.htm new file mode 100644 index 0000000..a40acb7 --- /dev/null +++ b/Source/Help/documentation/apps/graphing/troubleshooting.htm @@ -0,0 +1,87 @@ + + + + + Graphing Calculator: Troubleshooting + + + + + +

Graphing Calculator: Troubleshooting

+ + + +
+ +

Application crashes at startup

+

The application needs .NET Framework 4.0 installed. If you don't have it installed, you should download and install it from the Microsoft website.

+
+ +
+ +

Graph is drawn incorrectly

+

Problems with drawing appear when the function has many vertical asymptotes, or the function changes values too often, and is described here. Try increasing the graph precision from preferences.

+
+ +
+ +

Application works slowly

+

This is a known issue, and has to do with the way the functions are drawn. The slowdown appears when resizing the window, or navigating through the graph. We are working on this issue. What you can try is to decrease the graph precision from the preferences.

+
+ +
+ +

I get the Undefined variable error.

+ +

You need to verify you haven't accidentally typed a letter where it shouldn't be. You should also check the language article, to learn about the syntax rules of expressions.

+
+ +
+ +

I get the Undefined function error.

+ +

You have a syntax error, you need to check the language article, to learn the correct syntax of expressions.

+
+ +
+ +

I get the Stack empty error.

+ +

This error usually appears when you didn't give the correct number of parameters to a function. Check this article to verify the parameters.

+
+ +
+ +

I get the Mismatched parentheses error.

+ +

This error is pretty self explanatory, check your parentheses.

+
+ +
+ +

I have another problem not covered in the troubleshooting guide.

+ +

You should contact the developer using the contact form. Please, include a useful description of what you were doing when the problem has occurred, and eventually a link to a screenshot. The log file which should be located in the directory logs, where the application executable is, would also be very useful.

+
+ + + + + + \ No newline at end of file diff --git a/Source/Help/documentation/apps/help/img/background.png b/Source/Help/documentation/apps/help/img/background.png new file mode 100644 index 0000000..a686f00 Binary files /dev/null and b/Source/Help/documentation/apps/help/img/background.png differ diff --git a/Source/Help/documentation/apps/help/img/help-app-toolbar.png b/Source/Help/documentation/apps/help/img/help-app-toolbar.png new file mode 100644 index 0000000..9abfcd4 Binary files /dev/null and b/Source/Help/documentation/apps/help/img/help-app-toolbar.png differ diff --git a/Source/Help/documentation/apps/help/img/help-nav.png b/Source/Help/documentation/apps/help/img/help-nav.png new file mode 100644 index 0000000..1487107 Binary files /dev/null and b/Source/Help/documentation/apps/help/img/help-nav.png differ diff --git a/Source/Help/documentation/apps/help/img/help-search.png b/Source/Help/documentation/apps/help/img/help-search.png new file mode 100644 index 0000000..89e0e0c Binary files /dev/null and b/Source/Help/documentation/apps/help/img/help-search.png differ diff --git a/Source/Help/documentation/apps/help/index.bak b/Source/Help/documentation/apps/help/index.bak new file mode 100644 index 0000000..b66c37f --- /dev/null +++ b/Source/Help/documentation/apps/help/index.bak @@ -0,0 +1,60 @@ + + + + + Help viewer + + + + + +

Help viewer

+ +
+

Content

+ +
+ +
+ +

Introduction

+ +

The Help viewer is an application which displays information about how to use various features of the application.

+
+ +
+ +

Navigation

+ +

You can go back and forward using the navigation buttons in the toolbar:

+ + +

You can also see all the articles listed in the left panel of the application. To view an article, simply click on it.

+ +

To view the help articles for another application, select it from the Application toolbar:

+ +
+ +
+ +

Search

+ +

You can also search through articles, using the search toolbar. You have 3 options:

+ +
    +
  • Search title: searches through the titles of the articles only
  • +
  • Search content: searches trough the content of all the articles for the current application.
  • +
  • Search in current page: highlights all occurences of the specified text in the currently opened page.
  • +
+
+ + + + \ No newline at end of file diff --git a/Source/Help/documentation/apps/help/index.htm b/Source/Help/documentation/apps/help/index.htm new file mode 100644 index 0000000..30c34d0 --- /dev/null +++ b/Source/Help/documentation/apps/help/index.htm @@ -0,0 +1,60 @@ + + + + + Help viewer + + + + + +

Help viewer

+ +
+

Content

+ +
+ +
+ +

Introduction

+ +

The Help viewer is an application which displays information about how to use various features of the application.

+
+ +
+ +

Navigation

+ +

You can go back and forward using the navigation buttons in the toolbar:

+ + +

You can also see all the articles listed in the left panel of the application. To view an article, simply click on it.

+ +

To view the help articles for another application, select it from the Application toolbar:

+ +
+ +
+ +

Search

+ +

You can also search through articles, using the search toolbar. You have 3 options:

+ +
    +
  • Search title: searches through the titles of the articles only
  • +
  • Search content: searches trough the content of all the articles for the current application.
  • +
  • Search in current page: highlights all occurrences of the specified text in the currently opened page.
  • +
+
+ + + + \ No newline at end of file diff --git a/Source/Help/documentation/apps/help/style.css b/Source/Help/documentation/apps/help/style.css new file mode 100644 index 0000000..863d322 --- /dev/null +++ b/Source/Help/documentation/apps/help/style.css @@ -0,0 +1,119 @@ +body { + font-family: Verdana, sans-serif; + font-size: 10.5pt; + background: #F0F0F0; + margin:0px; + padding: 5px; + + /*filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#F0F0F0', endColorstr='#A0A0A0'); + background: -webkit-gradient(linear, left top, left bottom, from(#F0F0F0), to(#A0A0A0)); + background: -moz-linear-gradient(top, #F0F0F0, #A0A0A0);*/ + + background-image: url("img/background.png"); + background-repeat: repeat-x; + background-position: top center; + background-attachment: fixed; +} + +.section { + margin: 5px; + margin-top: 10px; + padding: 5px; + padding-left: 15px; + min-width: 600px; + + border: 1px solid silver; + background-color: #F5F5F5; + border-radius: 10px; + -moz-border-radius: 10px; + -webkit-border-radius: 10px; + + box-shadow: 0px 3px 7px rgba(68,68,68,0.6); + -mox-box-shadow: 0px 3px 7px rgba(68,68,68,0.6); + -webkig-box-shadow: 0px 3px 7px rgba(68,68,68,0.6); +} + +.footer { + margin-top: 20px; + color: #777; + text-align: center; + font-size: 10pt; +} + +a { + text-decoration: none; + color: #248AC9; +} + +a:hover { + color: #8DCFF7; +} + +a > img { + border: 0px; +} + +h1 { + margin:5px; + margin-bottom: 15px; + font-size: 18pt; + font-family: Arial, sans-serif; + font-weight: normal; + color: #606060; +} + +h1:hover { + color: #909090; +} + +h2 { + margin-top: -2px; + margin-left: -7px; + margin-bottom: 15px; + font-family: Arial, sans-serif; + font-size: 13pt; + font-weight: bold; + color: Silver; +} + +h3 { + margin-top: 10px; + margin-bottom: -10px; + font-family: Arial, sans-serif; + font-size: 14px; + font-weight: bold; + color: #555; +} + + + +img.shadow { + background: white; + + box-shadow: 2px 2px 7px rgba(68,68,68,0.4); + -mox-box-shadow: 2px 2px 7px rgba(68,68,68,0.4); + -webkig-box-shadow: 2px 2px 7px rgba(68,68,68,0.4); +} + +img.maths { + margin-left: 2em; + margin-bottom: 5px; +} + +.captioned_image_right { + float:right; + margin-left: 10px; + margin-bottom: 10px; + text-align: center; + background: white; + padding:5px; + width:150px; + + box-shadow: 2px 2px 7px rgba(68,68,68,0.4); + -mox-box-shadow: 2px 2px 7px rgba(68,68,68,0.4); + -webkig-box-shadow: 2px 2px 7px rgba(68,68,68,0.4); + + border-radius: 5px; + -moz-border-radius: 5px; + -webkit-border-radius: 5px; +} \ No newline at end of file diff --git a/Source/Help/documentation/apps/main/hotkeys.htm b/Source/Help/documentation/apps/main/hotkeys.htm new file mode 100644 index 0000000..f702d5f --- /dev/null +++ b/Source/Help/documentation/apps/main/hotkeys.htm @@ -0,0 +1,87 @@ + + + + + Tibi's Mathematics Suite: Hotkeys + + + + + +

Tibi's Mathematics Suite: Hotkeys

+ + + +
+ +

Introduction

+ +

A hotkey means a combination of keys on the keyboard that triggers a specific action. Usually, hotkeys trigger action as long as the application window is focused.

+

A global hotkey is a hotkey with a global scope, this means that pressing that key combination will trigger the action, no matter which application is focused.

+

In the suite application, hotkeys are used to launch applications from the suite. For example, you could set a keyboard combination that opens the Scientific Calculator.

+
+ +
+ +

Setting up hotkeys

+ +

To enable a keyboard hotkey:

+ +

Step 1: Go to the suite preferences (by right clicking the notification area icon, and pressing Preferences).

+ +

Step 2: Select an application from the list.

+ +

Step 3: Click in the Shortcut text area, and press a key combination.

+ +

Step 4: Click the Set button to confirm the hotkey.

+ +

Step 5: Click Accept to apply the modified settings.

+ + + +
+ +
+ +

Removing hotkeys

+ +

To remove a keyboard hotkey:

+ +

Step 1: Go to the suite preferences (by right clicking the notification area icon, and pressing Preferences).

+ +

Step 2: Select an application from the list.

+ +

Step 3: Click on the Clear button.

+ +

Step 4: Press Accept to apply the modification.

+ +
+ +
+ +

Warnings

+ +

It is strongly recommended that you use more uncommon key combinations, otherwise there may be conflicts with the keyboard combinations for other applications.

+ +

For example, you should never use the combination Ctrl + S, as many applications use it as the Save command. However, the combination Ctrl + Alt + Shift + S is a good one.

+ +

You should never use a single key as global hotkey, other than the media keys. For example, you should never use the key A as a global hotkey, because whenever you will have to type a word containing the letter 'a', an application will be launched.

+ +

Also, Microsoft recommends that the Windows key is only used by operating system functions.

+ +
+ + + + diff --git a/Source/Help/documentation/apps/main/img/background.png b/Source/Help/documentation/apps/main/img/background.png new file mode 100644 index 0000000..a686f00 Binary files /dev/null and b/Source/Help/documentation/apps/main/img/background.png differ diff --git a/Source/Help/documentation/apps/main/img/suite-hotkeys0.png b/Source/Help/documentation/apps/main/img/suite-hotkeys0.png new file mode 100644 index 0000000..b331c19 Binary files /dev/null and b/Source/Help/documentation/apps/main/img/suite-hotkeys0.png differ diff --git a/Source/Help/documentation/apps/main/img/suite0.png b/Source/Help/documentation/apps/main/img/suite0.png new file mode 100644 index 0000000..1457cc8 Binary files /dev/null and b/Source/Help/documentation/apps/main/img/suite0.png differ diff --git a/Source/Help/documentation/apps/main/index.bak b/Source/Help/documentation/apps/main/index.bak new file mode 100644 index 0000000..3ee1b45 --- /dev/null +++ b/Source/Help/documentation/apps/main/index.bak @@ -0,0 +1,57 @@ + + + + + Tibi's Mathematics Suite + + + + + +

Tibi's Mathematics Suite

+ + + +
+ +

Introduction

+ +

Tibi's Mathematics Suite is a package of useful mathematical appications. At the moment, it contains the following modules:

+
    +
  • Factorizator
  • +
  • Graphing calculator
  • +
  • Help viewer
  • +
  • Matrix calculator
  • +
  • Scientific calculator
  • +
+ +

The suite application is an utility that makes it much easier to access the individual applications, using a system tray icon and global hotkeys.

+
+
+ +

Getting started

+

At startup, the application appears as an icon in the system tray. When right clicking the icon, you have the option to open an application, change settings, or exit.

+ +

+

The settings window is where you can enable global hotkeys, this means pressing a keyboard combination to open a specific application.

+
+ +
+ +

Suite articles

+ +
+ + + + \ No newline at end of file diff --git a/Source/Help/documentation/apps/main/index.htm b/Source/Help/documentation/apps/main/index.htm new file mode 100644 index 0000000..19520a4 --- /dev/null +++ b/Source/Help/documentation/apps/main/index.htm @@ -0,0 +1,57 @@ + + + + + Tibi's Mathematics Suite + + + + + +

Tibi's Mathematics Suite

+ + + +
+ +

Introduction

+ +

Tibi's Mathematics Suite is a package of useful mathematical applications. At the moment, it contains the following modules:

+
    +
  • Factorizator
  • +
  • Graphing calculator
  • +
  • Help viewer
  • +
  • Matrix calculator
  • +
  • Scientific calculator
  • +
+ +

The suite application is an utility that makes it much easier to access the individual applications, using a system tray icon and global hotkeys.

+
+
+ +

Getting started

+

At startup, the application appears as an icon in the system tray. When right clicking the icon, you have the option to open an application, change settings, or exit.

+ +

+

The settings window is where you can enable global hotkeys, this means pressing a keyboard combination to open a specific application.

+
+ +
+ +

Suite articles

+ +
+ + + + \ No newline at end of file diff --git a/Source/Help/documentation/apps/main/style.css b/Source/Help/documentation/apps/main/style.css new file mode 100644 index 0000000..863d322 --- /dev/null +++ b/Source/Help/documentation/apps/main/style.css @@ -0,0 +1,119 @@ +body { + font-family: Verdana, sans-serif; + font-size: 10.5pt; + background: #F0F0F0; + margin:0px; + padding: 5px; + + /*filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#F0F0F0', endColorstr='#A0A0A0'); + background: -webkit-gradient(linear, left top, left bottom, from(#F0F0F0), to(#A0A0A0)); + background: -moz-linear-gradient(top, #F0F0F0, #A0A0A0);*/ + + background-image: url("img/background.png"); + background-repeat: repeat-x; + background-position: top center; + background-attachment: fixed; +} + +.section { + margin: 5px; + margin-top: 10px; + padding: 5px; + padding-left: 15px; + min-width: 600px; + + border: 1px solid silver; + background-color: #F5F5F5; + border-radius: 10px; + -moz-border-radius: 10px; + -webkit-border-radius: 10px; + + box-shadow: 0px 3px 7px rgba(68,68,68,0.6); + -mox-box-shadow: 0px 3px 7px rgba(68,68,68,0.6); + -webkig-box-shadow: 0px 3px 7px rgba(68,68,68,0.6); +} + +.footer { + margin-top: 20px; + color: #777; + text-align: center; + font-size: 10pt; +} + +a { + text-decoration: none; + color: #248AC9; +} + +a:hover { + color: #8DCFF7; +} + +a > img { + border: 0px; +} + +h1 { + margin:5px; + margin-bottom: 15px; + font-size: 18pt; + font-family: Arial, sans-serif; + font-weight: normal; + color: #606060; +} + +h1:hover { + color: #909090; +} + +h2 { + margin-top: -2px; + margin-left: -7px; + margin-bottom: 15px; + font-family: Arial, sans-serif; + font-size: 13pt; + font-weight: bold; + color: Silver; +} + +h3 { + margin-top: 10px; + margin-bottom: -10px; + font-family: Arial, sans-serif; + font-size: 14px; + font-weight: bold; + color: #555; +} + + + +img.shadow { + background: white; + + box-shadow: 2px 2px 7px rgba(68,68,68,0.4); + -mox-box-shadow: 2px 2px 7px rgba(68,68,68,0.4); + -webkig-box-shadow: 2px 2px 7px rgba(68,68,68,0.4); +} + +img.maths { + margin-left: 2em; + margin-bottom: 5px; +} + +.captioned_image_right { + float:right; + margin-left: 10px; + margin-bottom: 10px; + text-align: center; + background: white; + padding:5px; + width:150px; + + box-shadow: 2px 2px 7px rgba(68,68,68,0.4); + -mox-box-shadow: 2px 2px 7px rgba(68,68,68,0.4); + -webkig-box-shadow: 2px 2px 7px rgba(68,68,68,0.4); + + border-radius: 5px; + -moz-border-radius: 5px; + -webkit-border-radius: 5px; +} \ No newline at end of file diff --git a/Source/Help/documentation/apps/matrixcalc/basic.htm b/Source/Help/documentation/apps/matrixcalc/basic.htm new file mode 100644 index 0000000..5c24efe --- /dev/null +++ b/Source/Help/documentation/apps/matrixcalc/basic.htm @@ -0,0 +1,60 @@ + + + + + Matrix Calculator: Basic guide + + + + + +

Matrix Calculator: Basic guide

+ + + +
+ +

Adding matrices

+ +

In Matrix Calculator, matrices are listed in the left panel. Two default matrices already exist (zero and identity matrices). These don't behave like normal matrices, the size is not fixed, so they are compatible for any type of operation with any other matrix.

+ +

Adding a matrix can be done by either creating a matrix, or importing a matrix.

+ +
+

Creating a matrix

+

Step 1: First open the Matrix menu, and click New matrix... Alternatively, you can also right click in the matrix list.

+ + +

Step 2: Select a width and height for the matrix, and click Apply to update the matrix size. Now you can add the values in the table.

+ + +

Step 3: Give the new matrix a name, and optionally a description, and press Accept.

+ +
+

Importing a matrix

+

This feature is not yet available.

+
+ +
+ +

Performing a calculation

+

In the main window there are two boxes (called slots), labeled Matrix A and Matrix B. These are the two terms that are used in calculation.

+ + +

To insert a matrix into a slot, you can either drag and drop the matrix from the list, or select the Insert in slot _ option in the Matrix menu (or right click).

+ +

After inserting the matrix/matrices, click the button corresponding to the operation. If there was an error, it will be displayed in the Output box. The result will appear in the Result box. +

+ + + + \ No newline at end of file diff --git a/Source/Help/documentation/apps/matrixcalc/buttons.htm b/Source/Help/documentation/apps/matrixcalc/buttons.htm new file mode 100644 index 0000000..446315d --- /dev/null +++ b/Source/Help/documentation/apps/matrixcalc/buttons.htm @@ -0,0 +1,133 @@ + + + + + Matrix Calculator: Buttons + + + + + + +

Matrix Calculator: Buttons

+
+ +

Buttons

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Button Description
A + BAdds two matrices.
A - BSubtracts matrix B from matrix A.
A * BMultiplies 2 matrices.
A + xAdds a number to every element in matrix A.
A - xSubtracts a number from every element in matrix A
A * xMultiplies a number to every element in matrix A
A ^ -1Calculates inverse of matrix A.
A ^ xRaises matrix A to integer power x
Transp(A)Calculates A transposed.
Trace(A)Calculates the trace of matrix A (sum of elements on the diagonal).
Rank(A)Calculates the rank of matrix A.
Det(A)Calculates the determinant of matrix A.
Min(A)Finds the minimum element of matrix A.
Max(A)Finds the maximum element of matrix A.
+ +
+ +
+ + + + \ No newline at end of file diff --git a/Source/Help/documentation/apps/matrixcalc/calc.htm b/Source/Help/documentation/apps/matrixcalc/calc.htm new file mode 100644 index 0000000..fe62a44 --- /dev/null +++ b/Source/Help/documentation/apps/matrixcalc/calc.htm @@ -0,0 +1,275 @@ + + + + + Matrix Calculator: Calculator window + + + + + +

Matrix Calculator: Calculator window

+ + + +
+ +

Calculator window

+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Name Description
1Matrix listThis is where all the created matrices are.
2Preview paneThe matrix selected in the list is displayed here.
3Slot AThe first term of operations.
4Slot BThe second term of operations.
5ResultThis is where the result of the calculation appears.
6FunctionsAll the functions are defined here. For a more detailed explanation, check the What all the buttons do article.
7OutputIf there are any errors (like incompatible matrices), they are displayed here.
+ +
+ +
+ +

The file menu

+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Name Description
1New worksheetCreates a new worksheet*.
2Open...Opens an existing worksheet.
3SaveSaves current worksheet.
4Save as...Saves as a new worksheet.
5Import from csv file...Imports matrices from a Comma Separated Value file. This feature is not (yet) available.
6Import from worksheet...Imports matrices from an existing worksheet. This feature is not (yet) available.
7PreferencesOpens the preferences window.
8ExitCloses the application.
+
+

* A worksheet is defined as a collection of matrices.

+
+ +
+ +

The matrix menu

+

This menu can also be opened by right clicking inside the matrix list.

+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Name Description
1New matrix...Creates a new matrix.
2Edit selected...Edits the selected matrix.
3Delete selectedDeletes the selected matrices.
4Duplicate selected...Creates a new matrix based on the selected one.
5Insert in slot A.Inserts the matrix in slot A (the first term).
6Insert in slot B.Inserts the matrix in slot B (second term).
7CopyCopies the selected matrices into memory. This feature is not (yet) available.
8PastePastes matrices from memory. This feature is not (yet) available.
9CopyPaste matrix from another application. This feature is not (yet) available.
+
+ +
+ +

The help menu

+

+ + + + + + + + + + + + + + + + + + +
Name Description
1AboutOpens a window with information about Tibi's Mathematics Suite.
2HelpDisplays help using the application.
+
+ + + + \ No newline at end of file diff --git a/Source/Help/documentation/apps/matrixcalc/editor.htm b/Source/Help/documentation/apps/matrixcalc/editor.htm new file mode 100644 index 0000000..3a36719 --- /dev/null +++ b/Source/Help/documentation/apps/matrixcalc/editor.htm @@ -0,0 +1,169 @@ + + + + + Matrix Calculator: Editor window + + + + + +

Matrix Calculator: Editor window

+ +
+

Editor window

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Name Description
1NameThe name of the matrix. This field is required.
2DescriptionA description of the matrix. This field is optional.
3Matrix sizeChange the number of rows and columns of the matrix.
4Apply buttonUpdates the matrix with the new size inserted.
5Reset buttonResets the row and column count if change was not applied.
6Accept buttonSaves the modified matrix, and closes the window. If there are empty cells, they are filled with 0.
7Cancel buttonDiscards the modified matrix, and closes the window.
8GridThis is where you can edit the matrix elements.
 
Grid context menu
9CutCuts the selected cells.
ACopyCopies the selected cells into memory.
BPasteInserts cells from memory.
CClear selectedSets the values in the selected cells to 0.
DClear allSets all the values in the matrix to 0.
EInsert rowInserts a row before the selected cell.
FInsert columnInserts a column before the selected cell.
GDelete rowDeletes the row that contains the selected cell(s).
HDelete columnDeletes the column that contains the selected cell(s).
+ +
+ + + + \ No newline at end of file diff --git a/Source/Help/documentation/apps/matrixcalc/img/background.png b/Source/Help/documentation/apps/matrixcalc/img/background.png new file mode 100644 index 0000000..a686f00 Binary files /dev/null and b/Source/Help/documentation/apps/matrixcalc/img/background.png differ diff --git a/Source/Help/documentation/apps/matrixcalc/img/matrix-basic0.png b/Source/Help/documentation/apps/matrixcalc/img/matrix-basic0.png new file mode 100644 index 0000000..1fb1d29 Binary files /dev/null and b/Source/Help/documentation/apps/matrixcalc/img/matrix-basic0.png differ diff --git a/Source/Help/documentation/apps/matrixcalc/img/matrix-basic1.png b/Source/Help/documentation/apps/matrixcalc/img/matrix-basic1.png new file mode 100644 index 0000000..f34261a Binary files /dev/null and b/Source/Help/documentation/apps/matrixcalc/img/matrix-basic1.png differ diff --git a/Source/Help/documentation/apps/matrixcalc/img/matrix-basic2.png b/Source/Help/documentation/apps/matrixcalc/img/matrix-basic2.png new file mode 100644 index 0000000..4caebd1 Binary files /dev/null and b/Source/Help/documentation/apps/matrixcalc/img/matrix-basic2.png differ diff --git a/Source/Help/documentation/apps/matrixcalc/img/matrix-calc0.png b/Source/Help/documentation/apps/matrixcalc/img/matrix-calc0.png new file mode 100644 index 0000000..731fe28 Binary files /dev/null and b/Source/Help/documentation/apps/matrixcalc/img/matrix-calc0.png differ diff --git a/Source/Help/documentation/apps/matrixcalc/img/matrix-calc1.png b/Source/Help/documentation/apps/matrixcalc/img/matrix-calc1.png new file mode 100644 index 0000000..bed0863 Binary files /dev/null and b/Source/Help/documentation/apps/matrixcalc/img/matrix-calc1.png differ diff --git a/Source/Help/documentation/apps/matrixcalc/img/matrix-calc2.png b/Source/Help/documentation/apps/matrixcalc/img/matrix-calc2.png new file mode 100644 index 0000000..13a2acf Binary files /dev/null and b/Source/Help/documentation/apps/matrixcalc/img/matrix-calc2.png differ diff --git a/Source/Help/documentation/apps/matrixcalc/img/matrix-calc3.png b/Source/Help/documentation/apps/matrixcalc/img/matrix-calc3.png new file mode 100644 index 0000000..1d5be59 Binary files /dev/null and b/Source/Help/documentation/apps/matrixcalc/img/matrix-calc3.png differ diff --git a/Source/Help/documentation/apps/matrixcalc/img/matrix-editor0.png b/Source/Help/documentation/apps/matrixcalc/img/matrix-editor0.png new file mode 100644 index 0000000..4943bcd Binary files /dev/null and b/Source/Help/documentation/apps/matrixcalc/img/matrix-editor0.png differ diff --git a/Source/Help/documentation/apps/matrixcalc/index.htm b/Source/Help/documentation/apps/matrixcalc/index.htm new file mode 100644 index 0000000..de794fc --- /dev/null +++ b/Source/Help/documentation/apps/matrixcalc/index.htm @@ -0,0 +1,62 @@ + + + + + Matrix Calculator + + + + + +

Matrix Calculator

+ + + +
+ +

General information

+

The Matrix Calculator is calculator for mathematical matrices. In mathematics, a matrix is a rectangular array of numbers, symbols, or expressions. The individual items in a matrix are called its elements or entries. +

+
+ +

Limitations

+

The calculator is limited to 64bit floating point numbers (approximate range: 5.0 10-324 to 1.7 10308, or 15-16 digits).

+

The size of a matrix is only limited by the system memory, but it is not a very good idea to use large matrices (e.g. bigger than 100x100), since they make the application slow, and unresponsive.

+
+ +
+ +

Matrix calculator articles

+

Getting started

+ + +

Additional articles

+ + +
+ + + + \ No newline at end of file diff --git a/Source/Help/documentation/apps/matrixcalc/keyshortcuts.htm b/Source/Help/documentation/apps/matrixcalc/keyshortcuts.htm new file mode 100644 index 0000000..6fab9c4 --- /dev/null +++ b/Source/Help/documentation/apps/matrixcalc/keyshortcuts.htm @@ -0,0 +1,131 @@ + + + + + Matrix Calculator: Keyboard shortcuts + + + + + + +

Matrix Calculator: Keyboard shortcuts

+
+ +

Keyboard shortcuts

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Key combination Equivalent Action
Ctrl + NFile - New worksheetCreate new worksheet.
Ctrl + OFile - Open...Open worksheet.
Ctrl + SFile - SaveSaves worksheet.
Ctrl + Shift + SFile - Save As...Saves worksheet as a new file.
Ctrl + QFile - ExitCloses the application.
 
Ctrl + Shift + NMatrix - New matrix...Create new matrix.
Ctrl + Shift + EMatrix - Edit selected...Edit selected matrix.
DelMatrix - Delete selectedDelete selected matrix.
Ctrl + DMatrix - Duplicate selected...Duplicate selected matrix.
Ctrl + Alt + AMatrix - Insert in slot AInserts matrix for operand A.
Ctrl + Alt + BMatrix - Insert in slot BInserts matrix for operand B.
Ctrl + CMatrix - CopyCopy selected matrix.
Ctrl + VMatrix - PastePaste a new matrix.
Ctrl + Shift + VMatrix - Paste special...Paste from another application.
 
F1Help - HelpOpen help window.
+ +
+ +
+ + + + \ No newline at end of file diff --git a/Source/Help/documentation/apps/matrixcalc/style.css b/Source/Help/documentation/apps/matrixcalc/style.css new file mode 100644 index 0000000..863d322 --- /dev/null +++ b/Source/Help/documentation/apps/matrixcalc/style.css @@ -0,0 +1,119 @@ +body { + font-family: Verdana, sans-serif; + font-size: 10.5pt; + background: #F0F0F0; + margin:0px; + padding: 5px; + + /*filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#F0F0F0', endColorstr='#A0A0A0'); + background: -webkit-gradient(linear, left top, left bottom, from(#F0F0F0), to(#A0A0A0)); + background: -moz-linear-gradient(top, #F0F0F0, #A0A0A0);*/ + + background-image: url("img/background.png"); + background-repeat: repeat-x; + background-position: top center; + background-attachment: fixed; +} + +.section { + margin: 5px; + margin-top: 10px; + padding: 5px; + padding-left: 15px; + min-width: 600px; + + border: 1px solid silver; + background-color: #F5F5F5; + border-radius: 10px; + -moz-border-radius: 10px; + -webkit-border-radius: 10px; + + box-shadow: 0px 3px 7px rgba(68,68,68,0.6); + -mox-box-shadow: 0px 3px 7px rgba(68,68,68,0.6); + -webkig-box-shadow: 0px 3px 7px rgba(68,68,68,0.6); +} + +.footer { + margin-top: 20px; + color: #777; + text-align: center; + font-size: 10pt; +} + +a { + text-decoration: none; + color: #248AC9; +} + +a:hover { + color: #8DCFF7; +} + +a > img { + border: 0px; +} + +h1 { + margin:5px; + margin-bottom: 15px; + font-size: 18pt; + font-family: Arial, sans-serif; + font-weight: normal; + color: #606060; +} + +h1:hover { + color: #909090; +} + +h2 { + margin-top: -2px; + margin-left: -7px; + margin-bottom: 15px; + font-family: Arial, sans-serif; + font-size: 13pt; + font-weight: bold; + color: Silver; +} + +h3 { + margin-top: 10px; + margin-bottom: -10px; + font-family: Arial, sans-serif; + font-size: 14px; + font-weight: bold; + color: #555; +} + + + +img.shadow { + background: white; + + box-shadow: 2px 2px 7px rgba(68,68,68,0.4); + -mox-box-shadow: 2px 2px 7px rgba(68,68,68,0.4); + -webkig-box-shadow: 2px 2px 7px rgba(68,68,68,0.4); +} + +img.maths { + margin-left: 2em; + margin-bottom: 5px; +} + +.captioned_image_right { + float:right; + margin-left: 10px; + margin-bottom: 10px; + text-align: center; + background: white; + padding:5px; + width:150px; + + box-shadow: 2px 2px 7px rgba(68,68,68,0.4); + -mox-box-shadow: 2px 2px 7px rgba(68,68,68,0.4); + -webkig-box-shadow: 2px 2px 7px rgba(68,68,68,0.4); + + border-radius: 5px; + -moz-border-radius: 5px; + -webkit-border-radius: 5px; +} \ No newline at end of file diff --git a/Source/Help/documentation/icons/calculator-logo.ico b/Source/Help/documentation/icons/calculator-logo.ico new file mode 100644 index 0000000..9c5200f Binary files /dev/null and b/Source/Help/documentation/icons/calculator-logo.ico differ diff --git a/Source/Help/documentation/icons/calculator-logo.png b/Source/Help/documentation/icons/calculator-logo.png new file mode 100644 index 0000000..2d8885f Binary files /dev/null and b/Source/Help/documentation/icons/calculator-logo.png differ diff --git a/Source/Help/documentation/icons/factorizator-logo.ico b/Source/Help/documentation/icons/factorizator-logo.ico new file mode 100644 index 0000000..1885159 Binary files /dev/null and b/Source/Help/documentation/icons/factorizator-logo.ico differ diff --git a/Source/Help/documentation/icons/factorizator-logo.png b/Source/Help/documentation/icons/factorizator-logo.png new file mode 100644 index 0000000..792bb10 Binary files /dev/null and b/Source/Help/documentation/icons/factorizator-logo.png differ diff --git a/Source/Help/documentation/icons/graphing-logo.ico b/Source/Help/documentation/icons/graphing-logo.ico new file mode 100644 index 0000000..28db9e9 Binary files /dev/null and b/Source/Help/documentation/icons/graphing-logo.ico differ diff --git a/Source/Help/documentation/icons/graphing-logo.png b/Source/Help/documentation/icons/graphing-logo.png new file mode 100644 index 0000000..13e8275 Binary files /dev/null and b/Source/Help/documentation/icons/graphing-logo.png differ diff --git a/Source/Help/documentation/icons/help-logo-small.png.old b/Source/Help/documentation/icons/help-logo-small.png.old new file mode 100644 index 0000000..14a3433 Binary files /dev/null and b/Source/Help/documentation/icons/help-logo-small.png.old differ diff --git a/Source/Help/documentation/icons/help-logo.ico b/Source/Help/documentation/icons/help-logo.ico new file mode 100644 index 0000000..47cc377 Binary files /dev/null and b/Source/Help/documentation/icons/help-logo.ico differ diff --git a/Source/Help/documentation/icons/help-logo.png b/Source/Help/documentation/icons/help-logo.png new file mode 100644 index 0000000..7dca70e Binary files /dev/null and b/Source/Help/documentation/icons/help-logo.png differ diff --git a/Source/Help/documentation/icons/matrixcalc-logo-2.ico.old b/Source/Help/documentation/icons/matrixcalc-logo-2.ico.old new file mode 100644 index 0000000..037dd56 Binary files /dev/null and b/Source/Help/documentation/icons/matrixcalc-logo-2.ico.old differ diff --git a/Source/Help/documentation/icons/matrixcalc-logo-2.png.old b/Source/Help/documentation/icons/matrixcalc-logo-2.png.old new file mode 100644 index 0000000..f38d8c6 Binary files /dev/null and b/Source/Help/documentation/icons/matrixcalc-logo-2.png.old differ diff --git a/Source/Help/documentation/icons/matrixcalc-logo.ico b/Source/Help/documentation/icons/matrixcalc-logo.ico new file mode 100644 index 0000000..e44b5d8 Binary files /dev/null and b/Source/Help/documentation/icons/matrixcalc-logo.ico differ diff --git a/Source/Help/documentation/icons/matrixcalc-logo.png b/Source/Help/documentation/icons/matrixcalc-logo.png new file mode 100644 index 0000000..281ffec Binary files /dev/null and b/Source/Help/documentation/icons/matrixcalc-logo.png differ diff --git a/Source/Help/documentation/icons/matrixcalc-logo.png.old b/Source/Help/documentation/icons/matrixcalc-logo.png.old new file mode 100644 index 0000000..b7d07b3 Binary files /dev/null and b/Source/Help/documentation/icons/matrixcalc-logo.png.old differ diff --git a/Source/Help/documentation/icons/suite.ico b/Source/Help/documentation/icons/suite.ico new file mode 100644 index 0000000..f3a9fcc Binary files /dev/null and b/Source/Help/documentation/icons/suite.ico differ diff --git a/Source/Help/documentation/icons/suite.png b/Source/Help/documentation/icons/suite.png new file mode 100644 index 0000000..e19818e Binary files /dev/null and b/Source/Help/documentation/icons/suite.png differ diff --git a/Source/Help/documentation/img/background.png b/Source/Help/documentation/img/background.png new file mode 100644 index 0000000..a686f00 Binary files /dev/null and b/Source/Help/documentation/img/background.png differ diff --git a/Source/Help/documentation/img/calc-2ndf0.png b/Source/Help/documentation/img/calc-2ndf0.png new file mode 100644 index 0000000..c72ba7e Binary files /dev/null and b/Source/Help/documentation/img/calc-2ndf0.png differ diff --git a/Source/Help/documentation/img/calc-2ndf1.png b/Source/Help/documentation/img/calc-2ndf1.png new file mode 100644 index 0000000..5b9eac4 Binary files /dev/null and b/Source/Help/documentation/img/calc-2ndf1.png differ diff --git a/Source/Help/documentation/img/calc-abs-eq0.gif b/Source/Help/documentation/img/calc-abs-eq0.gif new file mode 100644 index 0000000..098a620 Binary files /dev/null and b/Source/Help/documentation/img/calc-abs-eq0.gif differ diff --git a/Source/Help/documentation/img/calc-abs-eq1.gif b/Source/Help/documentation/img/calc-abs-eq1.gif new file mode 100644 index 0000000..0a10441 Binary files /dev/null and b/Source/Help/documentation/img/calc-abs-eq1.gif differ diff --git a/Source/Help/documentation/img/calc-combinatorics-eq0.gif b/Source/Help/documentation/img/calc-combinatorics-eq0.gif new file mode 100644 index 0000000..845607e Binary files /dev/null and b/Source/Help/documentation/img/calc-combinatorics-eq0.gif differ diff --git a/Source/Help/documentation/img/calc-combinatorics-eq1.gif b/Source/Help/documentation/img/calc-combinatorics-eq1.gif new file mode 100644 index 0000000..0bf0a75 Binary files /dev/null and b/Source/Help/documentation/img/calc-combinatorics-eq1.gif differ diff --git a/Source/Help/documentation/img/calc-combinatorics-eq2.gif b/Source/Help/documentation/img/calc-combinatorics-eq2.gif new file mode 100644 index 0000000..694eedf Binary files /dev/null and b/Source/Help/documentation/img/calc-combinatorics-eq2.gif differ diff --git a/Source/Help/documentation/img/calc-combinatorics-eq3.gif b/Source/Help/documentation/img/calc-combinatorics-eq3.gif new file mode 100644 index 0000000..da99fe5 Binary files /dev/null and b/Source/Help/documentation/img/calc-combinatorics-eq3.gif differ diff --git a/Source/Help/documentation/img/calc-combinatorics-eq4.gif b/Source/Help/documentation/img/calc-combinatorics-eq4.gif new file mode 100644 index 0000000..d1c390c Binary files /dev/null and b/Source/Help/documentation/img/calc-combinatorics-eq4.gif differ diff --git a/Source/Help/documentation/img/calc-combinatorics-eq5.gif b/Source/Help/documentation/img/calc-combinatorics-eq5.gif new file mode 100644 index 0000000..3b1e1d2 Binary files /dev/null and b/Source/Help/documentation/img/calc-combinatorics-eq5.gif differ diff --git a/Source/Help/documentation/img/calc-combinatorics-eq6.gif b/Source/Help/documentation/img/calc-combinatorics-eq6.gif new file mode 100644 index 0000000..acbb37e Binary files /dev/null and b/Source/Help/documentation/img/calc-combinatorics-eq6.gif differ diff --git a/Source/Help/documentation/img/calc-constants-eq0.gif b/Source/Help/documentation/img/calc-constants-eq0.gif new file mode 100644 index 0000000..33f3728 Binary files /dev/null and b/Source/Help/documentation/img/calc-constants-eq0.gif differ diff --git a/Source/Help/documentation/img/calc-constants-eq1.gif b/Source/Help/documentation/img/calc-constants-eq1.gif new file mode 100644 index 0000000..c8d1faa Binary files /dev/null and b/Source/Help/documentation/img/calc-constants-eq1.gif differ diff --git a/Source/Help/documentation/img/calc-constants-eq2.gif b/Source/Help/documentation/img/calc-constants-eq2.gif new file mode 100644 index 0000000..7ca44b5 Binary files /dev/null and b/Source/Help/documentation/img/calc-constants-eq2.gif differ diff --git a/Source/Help/documentation/img/calc-int-eq0.gif b/Source/Help/documentation/img/calc-int-eq0.gif new file mode 100644 index 0000000..1983f58 Binary files /dev/null and b/Source/Help/documentation/img/calc-int-eq0.gif differ diff --git a/Source/Help/documentation/img/calc-int-eq1.gif b/Source/Help/documentation/img/calc-int-eq1.gif new file mode 100644 index 0000000..93212e7 Binary files /dev/null and b/Source/Help/documentation/img/calc-int-eq1.gif differ diff --git a/Source/Help/documentation/img/calc-int-eq2.gif b/Source/Help/documentation/img/calc-int-eq2.gif new file mode 100644 index 0000000..246fd53 Binary files /dev/null and b/Source/Help/documentation/img/calc-int-eq2.gif differ diff --git a/Source/Help/documentation/img/calc-int-eq3.gif b/Source/Help/documentation/img/calc-int-eq3.gif new file mode 100644 index 0000000..2c40ebb Binary files /dev/null and b/Source/Help/documentation/img/calc-int-eq3.gif differ diff --git a/Source/Help/documentation/img/calc-int-eq4.gif b/Source/Help/documentation/img/calc-int-eq4.gif new file mode 100644 index 0000000..199216a Binary files /dev/null and b/Source/Help/documentation/img/calc-int-eq4.gif differ diff --git a/Source/Help/documentation/img/calc-inverse-eq0.gif b/Source/Help/documentation/img/calc-inverse-eq0.gif new file mode 100644 index 0000000..290c4ad Binary files /dev/null and b/Source/Help/documentation/img/calc-inverse-eq0.gif differ diff --git a/Source/Help/documentation/img/calc-ui.png b/Source/Help/documentation/img/calc-ui.png new file mode 100644 index 0000000..04b82b8 Binary files /dev/null and b/Source/Help/documentation/img/calc-ui.png differ diff --git a/Source/Help/documentation/img/help-back.png b/Source/Help/documentation/img/help-back.png new file mode 100644 index 0000000..e22d00a Binary files /dev/null and b/Source/Help/documentation/img/help-back.png differ diff --git a/Source/Help/documentation/img/help-clear.png b/Source/Help/documentation/img/help-clear.png new file mode 100644 index 0000000..23378f5 Binary files /dev/null and b/Source/Help/documentation/img/help-clear.png differ diff --git a/Source/Help/documentation/img/help-forward.png b/Source/Help/documentation/img/help-forward.png new file mode 100644 index 0000000..086d3bc Binary files /dev/null and b/Source/Help/documentation/img/help-forward.png differ diff --git a/Source/Help/documentation/img/help-home.png b/Source/Help/documentation/img/help-home.png new file mode 100644 index 0000000..d87f1f9 Binary files /dev/null and b/Source/Help/documentation/img/help-home.png differ diff --git a/Source/Help/documentation/img/help-search.png b/Source/Help/documentation/img/help-search.png new file mode 100644 index 0000000..cd0c612 Binary files /dev/null and b/Source/Help/documentation/img/help-search.png differ diff --git a/Source/Help/documentation/img/help-searchopt.png b/Source/Help/documentation/img/help-searchopt.png new file mode 100644 index 0000000..9bfa580 Binary files /dev/null and b/Source/Help/documentation/img/help-searchopt.png differ diff --git a/Source/Help/documentation/img/link.png b/Source/Help/documentation/img/link.png new file mode 100644 index 0000000..61e8e8e Binary files /dev/null and b/Source/Help/documentation/img/link.png differ diff --git a/Source/Help/documentation/img/matrix-basic0.png b/Source/Help/documentation/img/matrix-basic0.png new file mode 100644 index 0000000..05358f3 Binary files /dev/null and b/Source/Help/documentation/img/matrix-basic0.png differ diff --git a/Source/Help/documentation/img/matrix-basic1.png b/Source/Help/documentation/img/matrix-basic1.png new file mode 100644 index 0000000..f8210e4 Binary files /dev/null and b/Source/Help/documentation/img/matrix-basic1.png differ diff --git a/Source/Help/documentation/img/matrix-basic2.png b/Source/Help/documentation/img/matrix-basic2.png new file mode 100644 index 0000000..41a5645 Binary files /dev/null and b/Source/Help/documentation/img/matrix-basic2.png differ diff --git a/Source/Help/documentation/img/matrix-calc0.png b/Source/Help/documentation/img/matrix-calc0.png new file mode 100644 index 0000000..1adfdae Binary files /dev/null and b/Source/Help/documentation/img/matrix-calc0.png differ diff --git a/Source/Help/documentation/img/matrix-calc1.png b/Source/Help/documentation/img/matrix-calc1.png new file mode 100644 index 0000000..968517f Binary files /dev/null and b/Source/Help/documentation/img/matrix-calc1.png differ diff --git a/Source/Help/documentation/img/matrix-calc2.png b/Source/Help/documentation/img/matrix-calc2.png new file mode 100644 index 0000000..53a90a2 Binary files /dev/null and b/Source/Help/documentation/img/matrix-calc2.png differ diff --git a/Source/Help/documentation/img/matrix-calc3.png b/Source/Help/documentation/img/matrix-calc3.png new file mode 100644 index 0000000..1d5be59 Binary files /dev/null and b/Source/Help/documentation/img/matrix-calc3.png differ diff --git a/Source/Help/documentation/img/matrix-editor0.png b/Source/Help/documentation/img/matrix-editor0.png new file mode 100644 index 0000000..b4fa119 Binary files /dev/null and b/Source/Help/documentation/img/matrix-editor0.png differ diff --git a/Source/Help/documentation/img/suite-hotkeys0.png b/Source/Help/documentation/img/suite-hotkeys0.png new file mode 100644 index 0000000..0a86cbd Binary files /dev/null and b/Source/Help/documentation/img/suite-hotkeys0.png differ diff --git a/Source/Help/documentation/img/suite-updates0.png b/Source/Help/documentation/img/suite-updates0.png new file mode 100644 index 0000000..6cafa9e Binary files /dev/null and b/Source/Help/documentation/img/suite-updates0.png differ diff --git a/Source/Help/documentation/img/suite0.png b/Source/Help/documentation/img/suite0.png new file mode 100644 index 0000000..35facc9 Binary files /dev/null and b/Source/Help/documentation/img/suite0.png differ diff --git a/Source/Help/documentation/index.xml b/Source/Help/documentation/index.xml new file mode 100644 index 0000000..debb1c1 --- /dev/null +++ b/Source/Help/documentation/index.xml @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Source/Help/documentation/printable-new.indd b/Source/Help/documentation/printable-new.indd new file mode 100644 index 0000000..52786b2 Binary files /dev/null and b/Source/Help/documentation/printable-new.indd differ diff --git a/Source/Help/documentation/printable-old.odt b/Source/Help/documentation/printable-old.odt new file mode 100644 index 0000000..310f334 Binary files /dev/null and b/Source/Help/documentation/printable-old.odt differ diff --git a/Source/Help/documentation/printable.pdf b/Source/Help/documentation/printable.pdf new file mode 100644 index 0000000..37091ea Binary files /dev/null and b/Source/Help/documentation/printable.pdf differ diff --git a/Source/Help/documentation/resources/banner-noback.png b/Source/Help/documentation/resources/banner-noback.png new file mode 100644 index 0000000..8e52857 Binary files /dev/null and b/Source/Help/documentation/resources/banner-noback.png differ diff --git a/Source/Help/documentation/resources/banner.png b/Source/Help/documentation/resources/banner.png new file mode 100644 index 0000000..9e42070 Binary files /dev/null and b/Source/Help/documentation/resources/banner.png differ diff --git a/Source/Help/documentation/style.css b/Source/Help/documentation/style.css new file mode 100644 index 0000000..863d322 --- /dev/null +++ b/Source/Help/documentation/style.css @@ -0,0 +1,119 @@ +body { + font-family: Verdana, sans-serif; + font-size: 10.5pt; + background: #F0F0F0; + margin:0px; + padding: 5px; + + /*filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#F0F0F0', endColorstr='#A0A0A0'); + background: -webkit-gradient(linear, left top, left bottom, from(#F0F0F0), to(#A0A0A0)); + background: -moz-linear-gradient(top, #F0F0F0, #A0A0A0);*/ + + background-image: url("img/background.png"); + background-repeat: repeat-x; + background-position: top center; + background-attachment: fixed; +} + +.section { + margin: 5px; + margin-top: 10px; + padding: 5px; + padding-left: 15px; + min-width: 600px; + + border: 1px solid silver; + background-color: #F5F5F5; + border-radius: 10px; + -moz-border-radius: 10px; + -webkit-border-radius: 10px; + + box-shadow: 0px 3px 7px rgba(68,68,68,0.6); + -mox-box-shadow: 0px 3px 7px rgba(68,68,68,0.6); + -webkig-box-shadow: 0px 3px 7px rgba(68,68,68,0.6); +} + +.footer { + margin-top: 20px; + color: #777; + text-align: center; + font-size: 10pt; +} + +a { + text-decoration: none; + color: #248AC9; +} + +a:hover { + color: #8DCFF7; +} + +a > img { + border: 0px; +} + +h1 { + margin:5px; + margin-bottom: 15px; + font-size: 18pt; + font-family: Arial, sans-serif; + font-weight: normal; + color: #606060; +} + +h1:hover { + color: #909090; +} + +h2 { + margin-top: -2px; + margin-left: -7px; + margin-bottom: 15px; + font-family: Arial, sans-serif; + font-size: 13pt; + font-weight: bold; + color: Silver; +} + +h3 { + margin-top: 10px; + margin-bottom: -10px; + font-family: Arial, sans-serif; + font-size: 14px; + font-weight: bold; + color: #555; +} + + + +img.shadow { + background: white; + + box-shadow: 2px 2px 7px rgba(68,68,68,0.4); + -mox-box-shadow: 2px 2px 7px rgba(68,68,68,0.4); + -webkig-box-shadow: 2px 2px 7px rgba(68,68,68,0.4); +} + +img.maths { + margin-left: 2em; + margin-bottom: 5px; +} + +.captioned_image_right { + float:right; + margin-left: 10px; + margin-bottom: 10px; + text-align: center; + background: white; + padding:5px; + width:150px; + + box-shadow: 2px 2px 7px rgba(68,68,68,0.4); + -mox-box-shadow: 2px 2px 7px rgba(68,68,68,0.4); + -webkig-box-shadow: 2px 2px 7px rgba(68,68,68,0.4); + + border-radius: 5px; + -moz-border-radius: 5px; + -webkit-border-radius: 5px; +} \ No newline at end of file diff --git a/Source/Help/documentation/temp/banner-noback.png b/Source/Help/documentation/temp/banner-noback.png new file mode 100644 index 0000000..8e52857 Binary files /dev/null and b/Source/Help/documentation/temp/banner-noback.png differ diff --git a/Source/Help/documentation/temp/banner.png b/Source/Help/documentation/temp/banner.png new file mode 100644 index 0000000..9e42070 Binary files /dev/null and b/Source/Help/documentation/temp/banner.png differ diff --git a/Source/Help/documentation/temp/banner.psd b/Source/Help/documentation/temp/banner.psd new file mode 100644 index 0000000..6962fad Binary files /dev/null and b/Source/Help/documentation/temp/banner.psd differ diff --git a/Source/Help/documentation/temp/factorizator-logo.psd b/Source/Help/documentation/temp/factorizator-logo.psd new file mode 100644 index 0000000..325ee3b Binary files /dev/null and b/Source/Help/documentation/temp/factorizator-logo.psd differ diff --git a/Source/Help/documentation/temp/graphing-logo.psd b/Source/Help/documentation/temp/graphing-logo.psd new file mode 100644 index 0000000..1510421 Binary files /dev/null and b/Source/Help/documentation/temp/graphing-logo.psd differ diff --git a/Source/Help/documentation/temp/help-home.psd b/Source/Help/documentation/temp/help-home.psd new file mode 100644 index 0000000..f154aa5 Binary files /dev/null and b/Source/Help/documentation/temp/help-home.psd differ diff --git a/Source/Help/documentation/temp/help-icons.psd b/Source/Help/documentation/temp/help-icons.psd new file mode 100644 index 0000000..74377cc Binary files /dev/null and b/Source/Help/documentation/temp/help-icons.psd differ diff --git a/Source/Help/documentation/temp/help-logo.psd b/Source/Help/documentation/temp/help-logo.psd new file mode 100644 index 0000000..691dc60 Binary files /dev/null and b/Source/Help/documentation/temp/help-logo.psd differ diff --git a/Source/Help/documentation/temp/icon-calculator.psd b/Source/Help/documentation/temp/icon-calculator.psd new file mode 100644 index 0000000..34917e3 Binary files /dev/null and b/Source/Help/documentation/temp/icon-calculator.psd differ diff --git a/Source/Help/documentation/temp/matrixcalc-logo.psd b/Source/Help/documentation/temp/matrixcalc-logo.psd new file mode 100644 index 0000000..2f0509c Binary files /dev/null and b/Source/Help/documentation/temp/matrixcalc-logo.psd differ diff --git a/Source/Help/documentation/temp/numbers/1.png b/Source/Help/documentation/temp/numbers/1.png new file mode 100644 index 0000000..9dd5375 Binary files /dev/null and b/Source/Help/documentation/temp/numbers/1.png differ diff --git a/Source/Help/documentation/temp/numbers/2.png b/Source/Help/documentation/temp/numbers/2.png new file mode 100644 index 0000000..205b375 Binary files /dev/null and b/Source/Help/documentation/temp/numbers/2.png differ diff --git a/Source/Help/documentation/temp/numbers/3.png b/Source/Help/documentation/temp/numbers/3.png new file mode 100644 index 0000000..dd53527 Binary files /dev/null and b/Source/Help/documentation/temp/numbers/3.png differ diff --git a/Source/Help/documentation/temp/numbers/4.png b/Source/Help/documentation/temp/numbers/4.png new file mode 100644 index 0000000..24f4794 Binary files /dev/null and b/Source/Help/documentation/temp/numbers/4.png differ diff --git a/Source/Help/documentation/temp/numbers/5.png b/Source/Help/documentation/temp/numbers/5.png new file mode 100644 index 0000000..68e9266 Binary files /dev/null and b/Source/Help/documentation/temp/numbers/5.png differ diff --git a/Source/Help/documentation/temp/numbers/6.png b/Source/Help/documentation/temp/numbers/6.png new file mode 100644 index 0000000..dc5a85e Binary files /dev/null and b/Source/Help/documentation/temp/numbers/6.png differ diff --git a/Source/Help/documentation/temp/numbers/7.png b/Source/Help/documentation/temp/numbers/7.png new file mode 100644 index 0000000..92f3406 Binary files /dev/null and b/Source/Help/documentation/temp/numbers/7.png differ diff --git a/Source/Help/documentation/temp/numbers/8.png b/Source/Help/documentation/temp/numbers/8.png new file mode 100644 index 0000000..d60c0e0 Binary files /dev/null and b/Source/Help/documentation/temp/numbers/8.png differ diff --git a/Source/Help/documentation/temp/numbers/9.png b/Source/Help/documentation/temp/numbers/9.png new file mode 100644 index 0000000..a377242 Binary files /dev/null and b/Source/Help/documentation/temp/numbers/9.png differ diff --git a/Source/Help/documentation/temp/numbers/A.png b/Source/Help/documentation/temp/numbers/A.png new file mode 100644 index 0000000..785c070 Binary files /dev/null and b/Source/Help/documentation/temp/numbers/A.png differ diff --git a/Source/Help/documentation/temp/numbers/B.png b/Source/Help/documentation/temp/numbers/B.png new file mode 100644 index 0000000..a4ca7d6 Binary files /dev/null and b/Source/Help/documentation/temp/numbers/B.png differ diff --git a/Source/Help/documentation/temp/numbers/C.png b/Source/Help/documentation/temp/numbers/C.png new file mode 100644 index 0000000..7cd58b2 Binary files /dev/null and b/Source/Help/documentation/temp/numbers/C.png differ diff --git a/Source/Help/documentation/temp/numbers/D.png b/Source/Help/documentation/temp/numbers/D.png new file mode 100644 index 0000000..bc14f08 Binary files /dev/null and b/Source/Help/documentation/temp/numbers/D.png differ diff --git a/Source/Help/documentation/temp/numbers/E.png b/Source/Help/documentation/temp/numbers/E.png new file mode 100644 index 0000000..d5b3c04 Binary files /dev/null and b/Source/Help/documentation/temp/numbers/E.png differ diff --git a/Source/Help/documentation/temp/numbers/F.png b/Source/Help/documentation/temp/numbers/F.png new file mode 100644 index 0000000..2c71b77 Binary files /dev/null and b/Source/Help/documentation/temp/numbers/F.png differ diff --git a/Source/Help/documentation/temp/numbers/G.png b/Source/Help/documentation/temp/numbers/G.png new file mode 100644 index 0000000..edc61d1 Binary files /dev/null and b/Source/Help/documentation/temp/numbers/G.png differ diff --git a/Source/Help/documentation/temp/numbers/H.png b/Source/Help/documentation/temp/numbers/H.png new file mode 100644 index 0000000..4d345fe Binary files /dev/null and b/Source/Help/documentation/temp/numbers/H.png differ diff --git a/Source/Help/documentation/temp/numbers/I.png b/Source/Help/documentation/temp/numbers/I.png new file mode 100644 index 0000000..2c792f5 Binary files /dev/null and b/Source/Help/documentation/temp/numbers/I.png differ diff --git a/Source/Help/documentation/temp/numbers/J.png b/Source/Help/documentation/temp/numbers/J.png new file mode 100644 index 0000000..2aba99a Binary files /dev/null and b/Source/Help/documentation/temp/numbers/J.png differ diff --git a/Source/Help/documentation/temp/suite.png b/Source/Help/documentation/temp/suite.png new file mode 100644 index 0000000..e19818e Binary files /dev/null and b/Source/Help/documentation/temp/suite.png differ diff --git a/Source/Help/documentation/temp/suite.psd b/Source/Help/documentation/temp/suite.psd new file mode 100644 index 0000000..2549f58 Binary files /dev/null and b/Source/Help/documentation/temp/suite.psd differ diff --git a/Source/Help/help-logo.ico b/Source/Help/help-logo.ico new file mode 100644 index 0000000..47cc377 Binary files /dev/null and b/Source/Help/help-logo.ico differ diff --git a/Source/Launcher/Controls/AboutWindow.Designer.cs b/Source/Launcher/Controls/AboutWindow.Designer.cs new file mode 100644 index 0000000..6d1c1f8 --- /dev/null +++ b/Source/Launcher/Controls/AboutWindow.Designer.cs @@ -0,0 +1,237 @@ +namespace DynamicLink +{ + partial class AboutWindow + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(AboutWindow)); + this.pictureBanner = new System.Windows.Forms.PictureBox(); + this.groupGeneral = new DynamicLink.Controls.MyGroupBox(); + this.labelAuthor = new System.Windows.Forms.Label(); + this.labelVersion = new System.Windows.Forms.Label(); + this.groupModules = new DynamicLink.Controls.MyGroupBox(); + this.labelModuleDescription = new System.Windows.Forms.Label(); + this.labelModuleName = new System.Windows.Forms.Label(); + this.listModules = new System.Windows.Forms.ListBox(); + this.groupBugs = new DynamicLink.Controls.MyGroupBox(); + this.linkMail = new System.Windows.Forms.LinkLabel(); + this.labelBugs = new System.Windows.Forms.Label(); + this.buttonClose = new DynamicLink.Controls.MyButton(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBanner)).BeginInit(); + this.groupGeneral.SuspendLayout(); + this.groupModules.SuspendLayout(); + this.groupBugs.SuspendLayout(); + this.SuspendLayout(); + // + // pictureBanner + // + this.pictureBanner.Image = ((System.Drawing.Image)(resources.GetObject("pictureBanner.Image"))); + this.pictureBanner.Location = new System.Drawing.Point(0, 0); + this.pictureBanner.Margin = new System.Windows.Forms.Padding(0); + this.pictureBanner.Name = "pictureBanner"; + this.pictureBanner.Size = new System.Drawing.Size(360, 80); + this.pictureBanner.TabIndex = 0; + this.pictureBanner.TabStop = false; + // + // groupGeneral + // + this.groupGeneral.Controls.Add(this.labelAuthor); + this.groupGeneral.Controls.Add(this.labelVersion); + this.groupGeneral.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.groupGeneral.Location = new System.Drawing.Point(12, 93); + this.groupGeneral.Name = "groupGeneral"; + this.groupGeneral.Padding = new System.Windows.Forms.Padding(3, 10, 3, 3); + this.groupGeneral.Size = new System.Drawing.Size(336, 67); + this.groupGeneral.TabIndex = 1; + this.groupGeneral.TabStop = false; + this.groupGeneral.Text = "Tibi\'s Mathematics Suite"; + // + // labelAuthor + // + this.labelAuthor.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.labelAuthor.BackColor = System.Drawing.Color.Transparent; + this.labelAuthor.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.labelAuthor.Location = new System.Drawing.Point(6, 47); + this.labelAuthor.Name = "labelAuthor"; + this.labelAuthor.Size = new System.Drawing.Size(324, 17); + this.labelAuthor.TabIndex = 1; + this.labelAuthor.Text = "Software created by Chibici Tiberiu."; + // + // labelVersion + // + this.labelVersion.AutoSize = true; + this.labelVersion.BackColor = System.Drawing.Color.Transparent; + this.labelVersion.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.labelVersion.Location = new System.Drawing.Point(6, 23); + this.labelVersion.Name = "labelVersion"; + this.labelVersion.Size = new System.Drawing.Size(84, 13); + this.labelVersion.TabIndex = 0; + this.labelVersion.Text = "Version 2.0 beta"; + // + // groupModules + // + this.groupModules.Controls.Add(this.labelModuleDescription); + this.groupModules.Controls.Add(this.labelModuleName); + this.groupModules.Controls.Add(this.listModules); + this.groupModules.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.groupModules.Location = new System.Drawing.Point(12, 166); + this.groupModules.Name = "groupModules"; + this.groupModules.Padding = new System.Windows.Forms.Padding(3, 10, 3, 3); + this.groupModules.Size = new System.Drawing.Size(336, 101); + this.groupModules.TabIndex = 2; + this.groupModules.TabStop = false; + this.groupModules.Text = "Installed modules:"; + // + // labelModuleDescription + // + this.labelModuleDescription.BackColor = System.Drawing.Color.Transparent; + this.labelModuleDescription.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.labelModuleDescription.Location = new System.Drawing.Point(212, 40); + this.labelModuleDescription.Name = "labelModuleDescription"; + this.labelModuleDescription.Size = new System.Drawing.Size(118, 53); + this.labelModuleDescription.TabIndex = 5; + this.labelModuleDescription.Text = "Description:"; + // + // labelModuleName + // + this.labelModuleName.BackColor = System.Drawing.Color.Transparent; + this.labelModuleName.Location = new System.Drawing.Point(212, 23); + this.labelModuleName.Name = "labelModuleName"; + this.labelModuleName.Size = new System.Drawing.Size(118, 17); + this.labelModuleName.TabIndex = 4; + this.labelModuleName.Text = "Name:"; + // + // listModules + // + this.listModules.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.listModules.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.listModules.FormattingEnabled = true; + this.listModules.Location = new System.Drawing.Point(6, 26); + this.listModules.Name = "listModules"; + this.listModules.Size = new System.Drawing.Size(200, 67); + this.listModules.TabIndex = 3; + this.listModules.SelectedIndexChanged += new System.EventHandler(this.listModules_SelectedIndexChanged); + // + // groupBugs + // + this.groupBugs.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); + this.groupBugs.Controls.Add(this.linkMail); + this.groupBugs.Controls.Add(this.labelBugs); + this.groupBugs.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.groupBugs.Location = new System.Drawing.Point(12, 273); + this.groupBugs.Name = "groupBugs"; + this.groupBugs.Padding = new System.Windows.Forms.Padding(3, 10, 3, 3); + this.groupBugs.Size = new System.Drawing.Size(336, 79); + this.groupBugs.TabIndex = 2; + this.groupBugs.TabStop = false; + this.groupBugs.Text = "Bug reporting"; + // + // linkMail + // + this.linkMail.AutoSize = true; + this.linkMail.BackColor = System.Drawing.Color.Transparent; + this.linkMail.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.linkMail.Location = new System.Drawing.Point(18, 56); + this.linkMail.Name = "linkMail"; + this.linkMail.Size = new System.Drawing.Size(123, 13); + this.linkMail.TabIndex = 2; + this.linkMail.TabStop = true; + this.linkMail.Text = "chibicitiberiu@gmail.com"; + this.linkMail.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkMail_LinkClicked); + // + // labelBugs + // + this.labelBugs.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.labelBugs.BackColor = System.Drawing.Color.Transparent; + this.labelBugs.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.labelBugs.Location = new System.Drawing.Point(6, 23); + this.labelBugs.Name = "labelBugs"; + this.labelBugs.Size = new System.Drawing.Size(324, 30); + this.labelBugs.TabIndex = 1; + this.labelBugs.Text = "If you found a bug in the software, or something doesn\'t work, feel free to repor" + + "t it by writing an e-mail to the address:"; + // + // buttonClose + // + this.buttonClose.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); + this.buttonClose.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.buttonClose.Location = new System.Drawing.Point(143, 359); + this.buttonClose.Name = "buttonClose"; + this.buttonClose.Size = new System.Drawing.Size(75, 23); + this.buttonClose.TabIndex = 3; + this.buttonClose.Text = "Close"; + this.buttonClose.UseVisualStyleBackColor = true; + this.buttonClose.Click += new System.EventHandler(this.buttonOk_Click); + // + // AboutWindow + // + this.AcceptButton = this.buttonClose; + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.CancelButton = this.buttonClose; + this.ClientSize = new System.Drawing.Size(360, 394); + this.Controls.Add(this.buttonClose); + this.Controls.Add(this.groupBugs); + this.Controls.Add(this.groupModules); + this.Controls.Add(this.groupGeneral); + this.Controls.Add(this.pictureBanner); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "AboutWindow"; + this.ShowInTaskbar = false; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; + this.Text = "About"; + this.Paint += new System.Windows.Forms.PaintEventHandler(this.AboutWindow_Paint); + ((System.ComponentModel.ISupportInitialize)(this.pictureBanner)).EndInit(); + this.groupGeneral.ResumeLayout(false); + this.groupGeneral.PerformLayout(); + this.groupModules.ResumeLayout(false); + this.groupBugs.ResumeLayout(false); + this.groupBugs.PerformLayout(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.PictureBox pictureBanner; + private Controls.MyGroupBox groupGeneral; + private System.Windows.Forms.Label labelAuthor; + private System.Windows.Forms.Label labelVersion; + private Controls.MyGroupBox groupModules; + private System.Windows.Forms.ListBox listModules; + private Controls.MyGroupBox groupBugs; + private System.Windows.Forms.LinkLabel linkMail; + private System.Windows.Forms.Label labelBugs; + private Controls.MyButton buttonClose; + private System.Windows.Forms.Label labelModuleDescription; + private System.Windows.Forms.Label labelModuleName; + } +} \ No newline at end of file diff --git a/Source/Launcher/Controls/AboutWindow.cs b/Source/Launcher/Controls/AboutWindow.cs new file mode 100644 index 0000000..3709d8e --- /dev/null +++ b/Source/Launcher/Controls/AboutWindow.cs @@ -0,0 +1,63 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Windows.Forms; + +namespace DynamicLink +{ + public partial class AboutWindow : Form + { + public AboutWindow() + { + InitializeComponent(); + + // Set up controls + groupBugs.BackColor = Color.Transparent; + groupGeneral.BackColor = Color.Transparent; + groupModules.BackColor = Color.Transparent; + buttonClose.BackColor = Color.Transparent; + + // Find modules if list is empty + if (Modules.Items.Count == 0) Modules.CollectData(); + + // Load module list + foreach (var i in Modules.Items) + this.listModules.Items.Add(i.Name); + + listModules.Sorted = true; + listModules.SelectedIndex = 0; + } + + private void linkMail_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) + { + try { System.Diagnostics.Process.Start("mailto:chibicitiberiu@gmail.com?Subject=[Bug report] Tibi's Mathematics Suite"); } + catch { } + } + + private void buttonOk_Click(object sender, EventArgs e) + { + this.Close(); + } + + private void AboutWindow_Paint(object sender, PaintEventArgs e) + { + DynamicLink.Controls.BackgroundGradient.Paint(e.Graphics, new Rectangle(0, 0, this.Width, this.Height)); + } + + private void listModules_SelectedIndexChanged(object sender, EventArgs e) + { + string selected = listModules.SelectedItem as string; + if (selected == null) return; + + labelModuleName.Text = selected; + + var items = Modules.Items.Where(x => x.Name == selected); + if (items.Count() != 0) labelModuleDescription.Text = items.First().Description; + else labelModuleDescription.Text = ""; + } + } +} diff --git a/Source/Launcher/Controls/AboutWindow.resx b/Source/Launcher/Controls/AboutWindow.resx new file mode 100644 index 0000000..beb917f --- /dev/null +++ b/Source/Launcher/Controls/AboutWindow.resx @@ -0,0 +1,832 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + + 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 + rX+rZkvkAAAAAElFTkSuQmCC + + + \ No newline at end of file diff --git a/Source/Launcher/Controls/BackgroundGradient.cs b/Source/Launcher/Controls/BackgroundGradient.cs new file mode 100644 index 0000000..81e4881 --- /dev/null +++ b/Source/Launcher/Controls/BackgroundGradient.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Drawing.Drawing2D; +using System.Linq; +using System.Text; +using System.Windows.Forms; + +namespace DynamicLink.Controls +{ + public static class BackgroundGradient + { + public static readonly Color Color1 = Color.FromArgb(0xff, 0xee, 0xee, 0xee); + public static readonly Color Color2 = Color.FromArgb(0xff, 0xbb, 0xbb, 0xbb); + + public static void Paint(Graphics g, Rectangle area) + { + g.SmoothingMode = SmoothingMode.AntiAlias; + + LinearGradientBrush gradient = new LinearGradientBrush(area, Color1, Color2, 60); + g.FillRectangle(gradient, area); + } + } +} diff --git a/Source/Launcher/Controls/MyButton.cs b/Source/Launcher/Controls/MyButton.cs new file mode 100644 index 0000000..a7e4b15 --- /dev/null +++ b/Source/Launcher/Controls/MyButton.cs @@ -0,0 +1,106 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Drawing.Drawing2D; +using System.Linq; +using System.Text; +using System.Windows.Forms; + +namespace DynamicLink.Controls +{ + public class MyButton : Button + { + private readonly Color ColorNormal1 = Color.FromArgb(0xff, 0xee, 0xee, 0xee); + private readonly Color ColorNormal2 = Color.FromArgb(0xff, 0xbb, 0xbb, 0xbb); + private readonly Color ColorFocus1 = Color.FromArgb(0xff, 0xff, 0xff, 0xff); + private readonly Color ColorFocus2 = Color.FromArgb(0xff, 0xc8, 0xc8, 0xc8); + private readonly Color ColorPressed1 = Color.FromArgb(0xff, 0xbb, 0xbb, 0xbb); + private readonly Color ColorPressed2 = Color.FromArgb(0xff, 0xdd, 0xdd, 0xdd); + + public bool IsMouseOver { get; private set; } + public bool IsPressed { get; private set; } + + public MyButton() : base() + { + this.SetStyle(ControlStyles.SupportsTransparentBackColor, true); + this.SetStyle(ControlStyles.Opaque, false); + + //this.Paint += new PaintEventHandler(MyButton_Paint); + this.MouseEnter += new EventHandler(MyButton_MouseEnter); + this.MouseLeave += new EventHandler(MyButton_MouseLeave); + this.MouseDown += new MouseEventHandler(MyButton_MouseDown); + this.MouseUp += new MouseEventHandler(MyButton_MouseUp); + } + + #region Mouse input + void MyButton_MouseUp(object sender, MouseEventArgs e) + { + if (e.Button == System.Windows.Forms.MouseButtons.Left) + { + IsPressed = false; + this.Invalidate(); + } + } + + void MyButton_MouseDown(object sender, MouseEventArgs e) + { + if (e.Button == System.Windows.Forms.MouseButtons.Left) + { + IsPressed = true; + this.Invalidate(); + } + } + + void MyButton_MouseLeave(object sender, EventArgs e) + { + IsMouseOver = false; + this.Invalidate(); + } + + void MyButton_MouseEnter(object sender, EventArgs e) + { + IsMouseOver = true; + this.Invalidate(); + } + #endregion + + protected override void OnPaint(PaintEventArgs e) + { + // base.OnPaint(pevent); + //InvalidateEx(); + + // Create gradient + LinearGradientBrush brush = new LinearGradientBrush(new Rectangle(0, 0, this.Width, this.Height), ColorNormal1, ColorNormal2, 90); + if (this.IsMouseOver) brush = new LinearGradientBrush(new Rectangle(0, 0, this.Width, this.Height), ColorFocus1, ColorFocus2, 90); + if (this.IsPressed) brush = new LinearGradientBrush(new Rectangle(0, 0, this.Width, this.Height), ColorPressed1, ColorPressed2, 90); + + // Set up graphics + // e.Graphics.Clear(this.BackColor); + e.Graphics.SmoothingMode = SmoothingMode.AntiAlias; + + // Draw rectangle + RoundedRectangle.FillRoundedRectangle(e.Graphics, new Rectangle(0, 0, this.Width - 1, this.Height - 1), brush, 4); + e.Graphics.DrawPath(Pens.Gray, RoundedRectangle.GetPath(new Rectangle(0, 0, this.Width - 1, this.Height - 1), 4)); + + // Draw text + SizeF size = e.Graphics.MeasureString(this.Text, this.Font); + e.Graphics.DrawString(this.Text, this.Font, Brushes.Black, (this.Width - size.Width) / 2, (this.Height - size.Height) / 2); + } + + private void InitializeComponent() + { + this.SuspendLayout(); + // + // MyButton + // + this.BackColor = System.Drawing.Color.Transparent; + this.UseVisualStyleBackColor = false; + this.ResumeLayout(false); + + } + + + } +} diff --git a/Source/Launcher/Controls/MyButton.resx b/Source/Launcher/Controls/MyButton.resx new file mode 100644 index 0000000..73afb87 --- /dev/null +++ b/Source/Launcher/Controls/MyButton.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + False + + \ No newline at end of file diff --git a/Source/Launcher/Controls/MyGroupBox.cs b/Source/Launcher/Controls/MyGroupBox.cs new file mode 100644 index 0000000..f27bc9a --- /dev/null +++ b/Source/Launcher/Controls/MyGroupBox.cs @@ -0,0 +1,53 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Drawing.Drawing2D; +using System.Linq; +using System.Text; +using System.Windows.Forms; + +namespace DynamicLink.Controls +{ + public class MyGroupBox : GroupBox + { + public MyGroupBox() : base() + { + this.Padding = new Padding(3, 8, 3, 3); + this.SetStyle(ControlStyles.SupportsTransparentBackColor, true); + this.SetStyle(ControlStyles.Opaque, false); + } + + protected override void OnPaint(PaintEventArgs e) + { + // base.OnPaint(e); + + // Brushes + Rectangle rectangle = new Rectangle(0, 0, this.Width, this.Height); + Rectangle rectEdge = new Rectangle(0, 0, this.Width - 1, this.Height - 1); + Brush background = new SolidBrush(Color.FromArgb(0xff, 0xFA, 0xF8, 0xF8)); + + // Set up graphics + e.Graphics.SmoothingMode = SmoothingMode.AntiAlias; + + // Draw background + RoundedRectangle.FillRoundedRectangle(e.Graphics, rectEdge, background, 5); + e.Graphics.DrawPath(Pens.White, RoundedRectangle.GetPath(rectEdge, 5)); + + // Draw title + e.Graphics.DrawString(this.Text, this.Font, Brushes.Gray, new PointF(7, 5)); + } + + private void InitializeComponent() + { + this.SuspendLayout(); + // + // MyGroupBox + // + this.BackColor = System.Drawing.Color.Transparent; + this.ResumeLayout(false); + + } + } +} diff --git a/Source/Launcher/Controls/MyGroupBox.resx b/Source/Launcher/Controls/MyGroupBox.resx new file mode 100644 index 0000000..73afb87 --- /dev/null +++ b/Source/Launcher/Controls/MyGroupBox.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + False + + \ No newline at end of file diff --git a/Source/Launcher/Controls/RoundedRectangle.cs b/Source/Launcher/Controls/RoundedRectangle.cs new file mode 100644 index 0000000..2065dc8 --- /dev/null +++ b/Source/Launcher/Controls/RoundedRectangle.cs @@ -0,0 +1,48 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Drawing.Drawing2D; +using System.Linq; +using System.Text; +using System.Windows.Forms; + +namespace DynamicLink.Controls +{ + static class RoundedRectangle + { + public static GraphicsPath GetPath(Rectangle r, int radius) + { + GraphicsPath path = new GraphicsPath(); + int d = radius * 2; + + path.AddLine(r.Left + d, r.Top, r.Right - d, r.Top); + path.AddArc(Rectangle.FromLTRB(r.Right - d, r.Top, r.Right, r.Top + d), -90, 90); + path.AddLine(r.Right, r.Top + d, r.Right, r.Bottom - d); + path.AddArc(Rectangle.FromLTRB(r.Right - d, r.Bottom - d, r.Right, r.Bottom), 0, 90); + path.AddLine(r.Right - d, r.Bottom, r.Left + d, r.Bottom); + path.AddArc(Rectangle.FromLTRB(r.Left, r.Bottom - d, r.Left + d, r.Bottom), 90, 90); + path.AddLine(r.Left, r.Bottom - d, r.Left, r.Top + d); + path.AddArc(Rectangle.FromLTRB(r.Left, r.Top, r.Left + d, r.Top + d), 180, 90); + path.CloseFigure(); + return path; + } + + public static void FillRoundedRectangle(Graphics graphics, Rectangle rectangle, Brush brush, int radius) + { + if (graphics == null) + throw new ArgumentNullException("graphics"); + + SmoothingMode mode = graphics.SmoothingMode; + graphics.SmoothingMode = SmoothingMode.AntiAlias; + + using (GraphicsPath path = GetPath(rectangle, radius)) + { + graphics.FillPath(brush, path); + } + graphics.SmoothingMode = mode; + } + + } +} diff --git a/Source/Launcher/DynamicLink.csproj b/Source/Launcher/DynamicLink.csproj new file mode 100644 index 0000000..31499e8 --- /dev/null +++ b/Source/Launcher/DynamicLink.csproj @@ -0,0 +1,105 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {A04B247B-6A95-462B-9E07-3337A1C158F1} + Library + Properties + DynamicLink + DynamicLink + v3.5 + 512 + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + ..\..\TibisMathematicsSuite - Release\ + TRACE + true + pdbonly + AnyCPU + prompt + true + true + false + + + + + + + + + + + + + + Form + + + AboutWindow.cs + + + + Component + + + + + Component + + + + + + True + True + Resources.resx + + + + + AboutWindow.cs + + + MyButton.cs + + + MyGroupBox.cs + + + ResXFileCodeGenerator + Resources.Designer.cs + + + + + + + + \ No newline at end of file diff --git a/Source/Launcher/Launcher.cs b/Source/Launcher/Launcher.cs new file mode 100644 index 0000000..e60bf7c --- /dev/null +++ b/Source/Launcher/Launcher.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace DynamicLink +{ + public static class Launcher + { + public static void StartModule(string name, string args = "") + { + if (Modules.Items.Count == 0) Modules.CollectData(); + Modules.ExecuteModule(name, args); + } + + public static void About() + { + new AboutWindow().ShowDialog(); + } + + public static string FindHelpFiles() + { + string[] possible_paths = { + Environment.CurrentDirectory + "\\documentation\\index.xml", + Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + "\\documentation\\index.xml" }; + + foreach (var i in possible_paths) + if (System.IO.File.Exists(i)) return i; + + // Haven't found anything? Abandon + return ""; + } + } +} diff --git a/Source/Launcher/ModuleInternal.cs b/Source/Launcher/ModuleInternal.cs new file mode 100644 index 0000000..07d7f79 --- /dev/null +++ b/Source/Launcher/ModuleInternal.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace DynamicLink +{ + public class ModuleInternal + { + public string Name { get; set; } + public string Path { get; set; } + public string Description { get; set; } + public System.Drawing.Icon Icon { get; set; } + } +} diff --git a/Source/Launcher/Modules.cs b/Source/Launcher/Modules.cs new file mode 100644 index 0000000..8ca9adc --- /dev/null +++ b/Source/Launcher/Modules.cs @@ -0,0 +1,103 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace DynamicLink +{ + public static class Modules + { + private static bool foundSolution = false; + + private static List items = new List(); + public static List Items + { + get { return items; } + } + + #region Useful routines + public static void RegisterModule(string name, string path, string description = null, System.Drawing.Icon icon = null) + { + if (!IsRegistered(name)) + items.Add(new ModuleInternal() { Name = name, Description = description, Path = path, Icon = icon }); + + else if (foundSolution == true) + { + int index = 0; + for (int i = 0; i < items.Count; i++) + if (items[i].Name == name) index = i; + + // If new file is an object file, don't allow + if (path.ToLower().Contains("obj")) return; + + // If it is an object file, it won't work, replace it + if (items[index].Path.ToLower().Contains("obj")) + { + // Replace + items[index] = new ModuleInternal() { Name = name, Description = description, Path = path, Icon = icon }; + return; + } + + // If newer, replace + DateTime neww = System.IO.File.GetCreationTime(path); + DateTime old = System.IO.File.GetCreationTime(items[index].Path); + + if (old < neww) + items[index] = new ModuleInternal() { Name = name, Description = description, Path = path, Icon = icon }; + } + } + + public static bool IsRegistered(string name) + { + var list = items.Where(x => x.Name == name); + return (list.Count() != 0); + } + + public static void ExecuteModule(string name, string args = "") + { + var list = items.Where(x => x.Name == name); + if (list.Count() == 0) return; + + System.Diagnostics.Process.Start(list.First().Path, args); + } + #endregion + + #region Collect data + private static string[] CollectData_GetFileList() + { + List files = new List(); + + // Try to find files in the current solution + string dir = System.Reflection.Assembly.GetExecutingAssembly().Location; + int find = dir.IndexOf("TibisMathematicsSuite\\"); + + // Success + if (find != -1) + { + string temp = dir.Remove(find) + "TibisMathematicsSuite\\"; + files.AddRange (System.IO.Directory.GetFiles(temp, "*.exe", System.IO.SearchOption.AllDirectories)); + + foundSolution = true; + } + + // Fail, just add current directory + else files.AddRange(System.IO.Directory.GetFiles(System.IO.Directory.GetCurrentDirectory(), "*.exe", System.IO.SearchOption.AllDirectories)); + + return files.ToArray(); + } + + public static void CollectData() + { + string[] list = CollectData_GetFileList(); + + foreach (var i in list) + { + System.Diagnostics.FileVersionInfo info = System.Diagnostics.FileVersionInfo.GetVersionInfo(i); + if (info.ProductName == "Tibi's Mathematics Suite") + RegisterModule(info.FileDescription, i, info.Comments, System.Drawing.Icon.ExtractAssociatedIcon(i)); + } + } + + #endregion + } +} diff --git a/Source/Launcher/Properties/AssemblyInfo.cs b/Source/Launcher/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..cb74a05 --- /dev/null +++ b/Source/Launcher/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 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("Dynamic link")] +[assembly: AssemblyDescription("Links all the components together.")] +[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)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("96d27379-2793-493d-821e-90543418d65c")] + +// 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")] diff --git a/Source/Launcher/Properties/Resources.Designer.cs b/Source/Launcher/Properties/Resources.Designer.cs new file mode 100644 index 0000000..d9df2f5 --- /dev/null +++ b/Source/Launcher/Properties/Resources.Designer.cs @@ -0,0 +1,70 @@ +//------------------------------------------------------------------------------ +// +// 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. +// +//------------------------------------------------------------------------------ + +namespace DynamicLink.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // 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() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("DynamicLink.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + internal static System.Drawing.Bitmap banner { + get { + object obj = ResourceManager.GetObject("banner", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + } +} diff --git a/Source/Launcher/Properties/Resources.resx b/Source/Launcher/Properties/Resources.resx new file mode 100644 index 0000000..8876d10 --- /dev/null +++ b/Source/Launcher/Properties/Resources.resx @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + ..\Resources\banner.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + \ No newline at end of file diff --git a/Source/Launcher/Resources/banner.png b/Source/Launcher/Resources/banner.png new file mode 100644 index 0000000..9e42070 Binary files /dev/null and b/Source/Launcher/Resources/banner.png differ diff --git a/Source/MatrixCalculator/CsvParser.cs b/Source/MatrixCalculator/CsvParser.cs new file mode 100644 index 0000000..8617dc3 --- /dev/null +++ b/Source/MatrixCalculator/CsvParser.cs @@ -0,0 +1,103 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Data; + +namespace MatrixCalculator +{ + public static class CsvParser + { + /// + /// Converts a CSV string into a DataTable + /// + /// CSV + /// Separator characters + /// Should separators be combined? + public static DataTable GetTable(string csv, char[] separators, bool combine = false) + { + DataTable table = new DataTable("table"); + table.Columns.Add(); + + csv = csv.TrimEnd('\n', '\r'); + string[] lines = csv.Split('\n'); + + for (int i = 0; i < lines.Length; i++) + { + string[] vals = lines[i].Split(separators, (combine ? StringSplitOptions.RemoveEmptyEntries : StringSplitOptions.None)); + table.Rows.Add(""); + + for (int j = 0; j < vals.Length; j++) + { + if (j >= table.Columns.Count) table.Columns.Add(); + table.Rows[i][j] = vals[j]; + } + } + + return table; + } + + /// + /// Converts matrix to CSV string + /// + /// The matrix + /// CSV separator character + public static string ToCSV (MathNet.Numerics.LinearAlgebra.Matrix m, char sep = ',') + { + StringBuilder str = new StringBuilder(); + + for (int i = 0; i < m.RowCount; i++) + { + for (int j = 0; j < m.ColumnCount; j++) { + str.Append(m[i, j]); + if (j < m.ColumnCount - 1) str.Append(sep); + } + + str.Append('\n'); + } + + return str.ToString(); + } + + + /// + /// Converts the data in a DataGridView to CSV format + /// + /// The DataGridView + /// CSV separator + public static string ToCSV(System.Windows.Forms.DataGridView m, char sep = ',') + { + return ToCSV(m, 0, 0, m.Rows.Count, m.Columns.Count, false, sep); + } + + /// + /// Converts the data in a DataGridView to CSV format + /// + /// The DataGridView + /// First row in range. + /// First column in range. + /// Last row in range. + /// Last column in range. + /// Only selected cells will be taken. + /// CSV separator + public static string ToCSV(System.Windows.Forms.DataGridView m, int startRow, int startCol, int endRow, int endCol, bool just_selected = false, char sep = ',') + { + StringBuilder str = new StringBuilder(); + + for (int i = startRow; i < endRow; i++) + { + for (int j = startCol; j < endCol; j++) + { + if (!just_selected || (just_selected && m[j, i].Selected)) + str.Append(m[j, i].Value); + + if (j < m.ColumnCount - 1) str.Append(sep); + } + + str.Append('\n'); + } + + return str.ToString(); + } + } +} diff --git a/Source/MatrixCalculator/Forms/Editor.Designer.cs b/Source/MatrixCalculator/Forms/Editor.Designer.cs new file mode 100644 index 0000000..39da150 --- /dev/null +++ b/Source/MatrixCalculator/Forms/Editor.Designer.cs @@ -0,0 +1,454 @@ +namespace MatrixCalculator +{ + partial class Editor + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + this.dataEditorContextMenu = new System.Windows.Forms.ContextMenuStrip(this.components); + this.contextMenuCut = new System.Windows.Forms.ToolStripMenuItem(); + this.contextMenuCopy = new System.Windows.Forms.ToolStripMenuItem(); + this.contextMenuPaste = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator(); + this.contextMenuClear = new System.Windows.Forms.ToolStripMenuItem(); + this.contextMenuClearAll = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator(); + this.contextMenuInsertRow = new System.Windows.Forms.ToolStripMenuItem(); + this.contextMenuInsertCol = new System.Windows.Forms.ToolStripMenuItem(); + this.contextMenuDelRow = new System.Windows.Forms.ToolStripMenuItem(); + this.contextMenuDelColumn = new System.Windows.Forms.ToolStripMenuItem(); + this.groupSize = new DynamicLink.Controls.MyGroupBox(); + this.buttonResizeReset = new DynamicLink.Controls.MyButton(); + this.labelWarning = new System.Windows.Forms.Label(); + this.buttonResizeApply = new DynamicLink.Controls.MyButton(); + this.labelColumns = new System.Windows.Forms.Label(); + this.labelRows = new System.Windows.Forms.Label(); + this.inputColumns = new System.Windows.Forms.NumericUpDown(); + this.inputRows = new System.Windows.Forms.NumericUpDown(); + this.groupInfo = new DynamicLink.Controls.MyGroupBox(); + this.inputDescription = new System.Windows.Forms.TextBox(); + this.inputName = new System.Windows.Forms.TextBox(); + this.labelDescription = new System.Windows.Forms.Label(); + this.labelName = new System.Windows.Forms.Label(); + this.buttonAccept = new DynamicLink.Controls.MyButton(); + this.buttonCancel = new DynamicLink.Controls.MyButton(); + this.groupBoxMatrixData = new DynamicLink.Controls.MyGroupBox(); + this.dataEditor = new System.Windows.Forms.DataGridView(); + this.dataEditorContextMenu.SuspendLayout(); + this.groupSize.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.inputColumns)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.inputRows)).BeginInit(); + this.groupInfo.SuspendLayout(); + this.groupBoxMatrixData.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.dataEditor)).BeginInit(); + this.SuspendLayout(); + // + // dataEditorContextMenu + // + this.dataEditorContextMenu.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.contextMenuCut, + this.contextMenuCopy, + this.contextMenuPaste, + this.toolStripSeparator1, + this.contextMenuClear, + this.contextMenuClearAll, + this.toolStripSeparator2, + this.contextMenuInsertRow, + this.contextMenuInsertCol, + this.contextMenuDelRow, + this.contextMenuDelColumn}); + this.dataEditorContextMenu.Name = "dataEditorContextMenu"; + this.dataEditorContextMenu.Size = new System.Drawing.Size(226, 214); + // + // contextMenuCut + // + this.contextMenuCut.Name = "contextMenuCut"; + this.contextMenuCut.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.X))); + this.contextMenuCut.Size = new System.Drawing.Size(225, 22); + this.contextMenuCut.Text = "Cu&t"; + this.contextMenuCut.Click += new System.EventHandler(this.contextMenuCut_Click); + // + // contextMenuCopy + // + this.contextMenuCopy.Name = "contextMenuCopy"; + this.contextMenuCopy.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.C))); + this.contextMenuCopy.Size = new System.Drawing.Size(225, 22); + this.contextMenuCopy.Text = "&Copy"; + this.contextMenuCopy.Click += new System.EventHandler(this.contextMenuCopy_Click); + // + // contextMenuPaste + // + this.contextMenuPaste.Name = "contextMenuPaste"; + this.contextMenuPaste.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.V))); + this.contextMenuPaste.Size = new System.Drawing.Size(225, 22); + this.contextMenuPaste.Text = "&Paste"; + this.contextMenuPaste.Click += new System.EventHandler(this.contextMenuPaste_Click); + // + // toolStripSeparator1 + // + this.toolStripSeparator1.Name = "toolStripSeparator1"; + this.toolStripSeparator1.Size = new System.Drawing.Size(222, 6); + // + // contextMenuClear + // + this.contextMenuClear.Name = "contextMenuClear"; + this.contextMenuClear.ShortcutKeys = System.Windows.Forms.Keys.Delete; + this.contextMenuClear.Size = new System.Drawing.Size(225, 22); + this.contextMenuClear.Text = "&Clear selected"; + this.contextMenuClear.Click += new System.EventHandler(this.contextMenuClear_Click); + // + // contextMenuClearAll + // + this.contextMenuClearAll.Name = "contextMenuClearAll"; + this.contextMenuClearAll.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Shift | System.Windows.Forms.Keys.Delete))); + this.contextMenuClearAll.Size = new System.Drawing.Size(225, 22); + this.contextMenuClearAll.Text = "Clear &all"; + this.contextMenuClearAll.Click += new System.EventHandler(this.contextMenuClearAll_Click); + // + // toolStripSeparator2 + // + this.toolStripSeparator2.Name = "toolStripSeparator2"; + this.toolStripSeparator2.Size = new System.Drawing.Size(222, 6); + // + // contextMenuInsertRow + // + this.contextMenuInsertRow.Name = "contextMenuInsertRow"; + this.contextMenuInsertRow.ShortcutKeys = ((System.Windows.Forms.Keys)(((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Alt) + | System.Windows.Forms.Keys.R))); + this.contextMenuInsertRow.Size = new System.Drawing.Size(225, 22); + this.contextMenuInsertRow.Text = "Insert row"; + this.contextMenuInsertRow.Click += new System.EventHandler(this.contextMenuInsertRow_Click); + // + // contextMenuInsertCol + // + this.contextMenuInsertCol.Name = "contextMenuInsertCol"; + this.contextMenuInsertCol.ShortcutKeys = ((System.Windows.Forms.Keys)(((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Alt) + | System.Windows.Forms.Keys.C))); + this.contextMenuInsertCol.Size = new System.Drawing.Size(225, 22); + this.contextMenuInsertCol.Text = "Insert column"; + this.contextMenuInsertCol.Click += new System.EventHandler(this.contextMenuInsertCol_Click); + // + // contextMenuDelRow + // + this.contextMenuDelRow.Name = "contextMenuDelRow"; + this.contextMenuDelRow.ShortcutKeys = ((System.Windows.Forms.Keys)(((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Shift) + | System.Windows.Forms.Keys.R))); + this.contextMenuDelRow.Size = new System.Drawing.Size(225, 22); + this.contextMenuDelRow.Text = "Delete row"; + this.contextMenuDelRow.Click += new System.EventHandler(this.contextMenuDelRow_Click); + // + // contextMenuDelColumn + // + this.contextMenuDelColumn.Name = "contextMenuDelColumn"; + this.contextMenuDelColumn.ShortcutKeys = ((System.Windows.Forms.Keys)(((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Shift) + | System.Windows.Forms.Keys.C))); + this.contextMenuDelColumn.Size = new System.Drawing.Size(225, 22); + this.contextMenuDelColumn.Text = "Delete column"; + this.contextMenuDelColumn.Click += new System.EventHandler(this.contextMenuDelColumn_Click); + // + // groupSize + // + this.groupSize.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.groupSize.BackColor = System.Drawing.Color.Transparent; + this.groupSize.Controls.Add(this.buttonResizeReset); + this.groupSize.Controls.Add(this.labelWarning); + this.groupSize.Controls.Add(this.buttonResizeApply); + this.groupSize.Controls.Add(this.labelColumns); + this.groupSize.Controls.Add(this.labelRows); + this.groupSize.Controls.Add(this.inputColumns); + this.groupSize.Controls.Add(this.inputRows); + this.groupSize.Location = new System.Drawing.Point(382, 135); + this.groupSize.Name = "groupSize"; + this.groupSize.Padding = new System.Windows.Forms.Padding(3, 8, 3, 3); + this.groupSize.Size = new System.Drawing.Size(192, 153); + this.groupSize.TabIndex = 1; + this.groupSize.TabStop = false; + this.groupSize.Text = "Matrix size:"; + // + // buttonResizeReset + // + this.buttonResizeReset.BackColor = System.Drawing.Color.Transparent; + this.buttonResizeReset.Location = new System.Drawing.Point(6, 124); + this.buttonResizeReset.Name = "buttonResizeReset"; + this.buttonResizeReset.Size = new System.Drawing.Size(87, 23); + this.buttonResizeReset.TabIndex = 6; + this.buttonResizeReset.Text = "Reset"; + this.buttonResizeReset.UseVisualStyleBackColor = false; + this.buttonResizeReset.Click += new System.EventHandler(this.buttonResizeReset_Click); + // + // labelWarning + // + this.labelWarning.Location = new System.Drawing.Point(6, 87); + this.labelWarning.Name = "labelWarning"; + this.labelWarning.Size = new System.Drawing.Size(180, 27); + this.labelWarning.TabIndex = 5; + this.labelWarning.Text = "Warning: removing rows or columns will delete the data contained."; + // + // buttonResizeApply + // + this.buttonResizeApply.BackColor = System.Drawing.Color.Transparent; + this.buttonResizeApply.Location = new System.Drawing.Point(99, 124); + this.buttonResizeApply.Name = "buttonResizeApply"; + this.buttonResizeApply.Size = new System.Drawing.Size(87, 23); + this.buttonResizeApply.TabIndex = 4; + this.buttonResizeApply.Text = "Apply"; + this.buttonResizeApply.UseVisualStyleBackColor = false; + this.buttonResizeApply.Click += new System.EventHandler(this.buttonResizeApply_Click); + // + // labelColumns + // + this.labelColumns.AutoSize = true; + this.labelColumns.Location = new System.Drawing.Point(6, 57); + this.labelColumns.Name = "labelColumns"; + this.labelColumns.Size = new System.Drawing.Size(50, 13); + this.labelColumns.TabIndex = 3; + this.labelColumns.Text = "Columns:"; + // + // labelRows + // + this.labelRows.AutoSize = true; + this.labelRows.Location = new System.Drawing.Point(6, 31); + this.labelRows.Name = "labelRows"; + this.labelRows.Size = new System.Drawing.Size(37, 13); + this.labelRows.TabIndex = 2; + this.labelRows.Text = "Rows:"; + // + // inputColumns + // + this.inputColumns.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.inputColumns.Location = new System.Drawing.Point(90, 55); + this.inputColumns.Minimum = new decimal(new int[] { + 1, + 0, + 0, + 0}); + this.inputColumns.Name = "inputColumns"; + this.inputColumns.Size = new System.Drawing.Size(94, 20); + this.inputColumns.TabIndex = 1; + this.inputColumns.Value = new decimal(new int[] { + 1, + 0, + 0, + 0}); + // + // inputRows + // + this.inputRows.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.inputRows.Location = new System.Drawing.Point(90, 29); + this.inputRows.Minimum = new decimal(new int[] { + 1, + 0, + 0, + 0}); + this.inputRows.Name = "inputRows"; + this.inputRows.Size = new System.Drawing.Size(94, 20); + this.inputRows.TabIndex = 0; + this.inputRows.Value = new decimal(new int[] { + 1, + 0, + 0, + 0}); + // + // groupInfo + // + this.groupInfo.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.groupInfo.BackColor = System.Drawing.Color.Transparent; + this.groupInfo.Controls.Add(this.inputDescription); + this.groupInfo.Controls.Add(this.inputName); + this.groupInfo.Controls.Add(this.labelDescription); + this.groupInfo.Controls.Add(this.labelName); + this.groupInfo.Location = new System.Drawing.Point(382, 13); + this.groupInfo.Name = "groupInfo"; + this.groupInfo.Padding = new System.Windows.Forms.Padding(3, 8, 3, 3); + this.groupInfo.Size = new System.Drawing.Size(192, 116); + this.groupInfo.TabIndex = 2; + this.groupInfo.TabStop = false; + this.groupInfo.Text = "Matrix info:"; + // + // inputDescription + // + this.inputDescription.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.inputDescription.Location = new System.Drawing.Point(6, 67); + this.inputDescription.Multiline = true; + this.inputDescription.Name = "inputDescription"; + this.inputDescription.Size = new System.Drawing.Size(178, 43); + this.inputDescription.TabIndex = 7; + // + // inputName + // + this.inputName.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.inputName.Location = new System.Drawing.Point(50, 22); + this.inputName.Name = "inputName"; + this.inputName.Size = new System.Drawing.Size(134, 20); + this.inputName.TabIndex = 6; + // + // labelDescription + // + this.labelDescription.AutoSize = true; + this.labelDescription.Location = new System.Drawing.Point(6, 51); + this.labelDescription.Name = "labelDescription"; + this.labelDescription.Size = new System.Drawing.Size(63, 13); + this.labelDescription.TabIndex = 5; + this.labelDescription.Text = "Description:"; + // + // labelName + // + this.labelName.AutoSize = true; + this.labelName.Location = new System.Drawing.Point(6, 25); + this.labelName.Name = "labelName"; + this.labelName.Size = new System.Drawing.Size(38, 13); + this.labelName.TabIndex = 4; + this.labelName.Text = "Name:"; + // + // buttonAccept + // + this.buttonAccept.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.buttonAccept.BackColor = System.Drawing.Color.Transparent; + this.buttonAccept.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.buttonAccept.ForeColor = System.Drawing.Color.DarkGreen; + this.buttonAccept.Location = new System.Drawing.Point(490, 327); + this.buttonAccept.Name = "buttonAccept"; + this.buttonAccept.Size = new System.Drawing.Size(84, 29); + this.buttonAccept.TabIndex = 8; + this.buttonAccept.Text = "Accept"; + this.buttonAccept.UseVisualStyleBackColor = false; + this.buttonAccept.Click += new System.EventHandler(this.buttonAccept_Click); + // + // buttonCancel + // + this.buttonCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.buttonCancel.BackColor = System.Drawing.Color.Transparent; + this.buttonCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.buttonCancel.Location = new System.Drawing.Point(400, 327); + this.buttonCancel.Name = "buttonCancel"; + this.buttonCancel.Size = new System.Drawing.Size(84, 29); + this.buttonCancel.TabIndex = 7; + this.buttonCancel.Text = "Cancel"; + this.buttonCancel.UseVisualStyleBackColor = false; + this.buttonCancel.Click += new System.EventHandler(this.buttonCancel_Click); + // + // groupBoxMatrixData + // + this.groupBoxMatrixData.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.groupBoxMatrixData.BackColor = System.Drawing.Color.Transparent; + this.groupBoxMatrixData.Controls.Add(this.dataEditor); + this.groupBoxMatrixData.Location = new System.Drawing.Point(12, 13); + this.groupBoxMatrixData.Name = "groupBoxMatrixData"; + this.groupBoxMatrixData.Padding = new System.Windows.Forms.Padding(3, 8, 3, 3); + this.groupBoxMatrixData.Size = new System.Drawing.Size(364, 343); + this.groupBoxMatrixData.TabIndex = 9; + this.groupBoxMatrixData.TabStop = false; + this.groupBoxMatrixData.Text = "Matrix data"; + // + // dataEditor + // + this.dataEditor.AllowUserToAddRows = false; + this.dataEditor.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.dataEditor.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize; + this.dataEditor.ContextMenuStrip = this.dataEditorContextMenu; + this.dataEditor.Location = new System.Drawing.Point(3, 21); + this.dataEditor.Name = "dataEditor"; + this.dataEditor.RowHeadersWidthSizeMode = System.Windows.Forms.DataGridViewRowHeadersWidthSizeMode.AutoSizeToDisplayedHeaders; + this.dataEditor.Size = new System.Drawing.Size(358, 319); + this.dataEditor.TabIndex = 1; + this.dataEditor.CellMouseDown += new System.Windows.Forms.DataGridViewCellMouseEventHandler(this.dataEditor_CellMouseDown); + // + // Editor + // + this.AcceptButton = this.buttonAccept; + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.CancelButton = this.buttonCancel; + this.ClientSize = new System.Drawing.Size(586, 368); + this.Controls.Add(this.groupBoxMatrixData); + this.Controls.Add(this.buttonAccept); + this.Controls.Add(this.buttonCancel); + this.Controls.Add(this.groupInfo); + this.Controls.Add(this.groupSize); + this.HelpButton = true; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "Editor"; + this.ShowInTaskbar = false; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "Editor"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.Editor_FormClosing); + this.dataEditorContextMenu.ResumeLayout(false); + this.groupSize.ResumeLayout(false); + this.groupSize.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.inputColumns)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.inputRows)).EndInit(); + this.groupInfo.ResumeLayout(false); + this.groupInfo.PerformLayout(); + this.groupBoxMatrixData.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.dataEditor)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private DynamicLink.Controls.MyGroupBox groupSize; + private DynamicLink.Controls.MyButton buttonResizeApply; + private System.Windows.Forms.Label labelColumns; + private System.Windows.Forms.Label labelRows; + private System.Windows.Forms.NumericUpDown inputColumns; + private System.Windows.Forms.NumericUpDown inputRows; + private DynamicLink.Controls.MyButton buttonResizeReset; + private System.Windows.Forms.Label labelWarning; + private DynamicLink.Controls.MyGroupBox groupInfo; + private System.Windows.Forms.TextBox inputDescription; + private System.Windows.Forms.TextBox inputName; + private System.Windows.Forms.Label labelDescription; + private System.Windows.Forms.Label labelName; + private DynamicLink.Controls.MyButton buttonAccept; + private DynamicLink.Controls.MyButton buttonCancel; + private System.Windows.Forms.ContextMenuStrip dataEditorContextMenu; + private System.Windows.Forms.ToolStripMenuItem contextMenuCut; + private System.Windows.Forms.ToolStripMenuItem contextMenuCopy; + private System.Windows.Forms.ToolStripMenuItem contextMenuPaste; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator1; + private System.Windows.Forms.ToolStripMenuItem contextMenuClear; + private System.Windows.Forms.ToolStripMenuItem contextMenuClearAll; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator2; + private System.Windows.Forms.ToolStripMenuItem contextMenuInsertRow; + private System.Windows.Forms.ToolStripMenuItem contextMenuInsertCol; + private System.Windows.Forms.ToolStripMenuItem contextMenuDelRow; + private System.Windows.Forms.ToolStripMenuItem contextMenuDelColumn; + private DynamicLink.Controls.MyGroupBox groupBoxMatrixData; + private System.Windows.Forms.DataGridView dataEditor; + } +} \ No newline at end of file diff --git a/Source/MatrixCalculator/Forms/Editor.cs b/Source/MatrixCalculator/Forms/Editor.cs new file mode 100644 index 0000000..dd28900 --- /dev/null +++ b/Source/MatrixCalculator/Forms/Editor.cs @@ -0,0 +1,181 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Windows.Forms; +using MathNet.Numerics.LinearAlgebra; + +namespace MatrixCalculator +{ + public partial class Editor : Form + { + bool allowExit = true; + + #region Setters and getters + public string MatrixName { + get { return inputName.Text; } + set { inputName.Text = value; } + } + + public string MatrixDescription + { + get { return inputDescription.Text; } + set { inputDescription.Text = value; } + } + + public Matrix Matrix + { + get { return GridViewHelper.GetMatrix(dataEditor); } + set { + GridViewHelper.PutMatrix(value, dataEditor); + inputColumns.Value = value.ColumnCount; + inputRows.Value = value.RowCount; + } + } + #endregion + + #region Constructor + public Editor() + { + InitializeComponent(); + + inputName.Text = "New matrix "; + } + #endregion + + #region Resize buttons + private void buttonResizeReset_Click(object sender, EventArgs e) + { + inputRows.Value = dataEditor.Rows.Count; + inputColumns.Value = dataEditor.Columns.Count; + } + + private void buttonResizeApply_Click(object sender, EventArgs e) + { + int rows = Convert.ToInt32(inputRows.Value); + int cols = Convert.ToInt32(inputColumns.Value); + + GridViewHelper.Resize(dataEditor, cols, rows); + } + #endregion + + #region Form buttons + private void buttonAccept_Click(object sender, EventArgs e) + { + this.DialogResult = System.Windows.Forms.DialogResult.OK; + + // Make sure name is not empty + if (MatrixName == "") + { + allowExit = false; + MessageBox.Show("You must enter a name!", "Error!"); + } + + // Make sure size is not empty! Empty matrices behave very weird + else if (dataEditor.Columns.Count == 0 || dataEditor.Rows.Count == 0) + { + allowExit = false; + MessageBox.Show("The matrix must have at least one row and one column!", "Error!"); + } + } + + private void buttonCancel_Click(object sender, EventArgs e) + { + this.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.Close(); + } + #endregion + + #region Right click menu + private void contextMenuCut_Click(object sender, EventArgs e) + { + GridViewHelper.CopySelected(dataEditor); + + foreach (DataGridViewCell i in dataEditor.SelectedCells) i.Value = "0"; + } + + private void contextMenuCopy_Click(object sender, EventArgs e) + { + GridViewHelper.CopySelected(dataEditor); + } + + private void contextMenuPaste_Click(object sender, EventArgs e) + { + GridViewHelper.Paste(dataEditor); + } + + private void contextMenuClear_Click(object sender, EventArgs e) + { + foreach (DataGridViewCell i in dataEditor.SelectedCells) i.Value = "0"; + } + + private void contextMenuClearAll_Click(object sender, EventArgs e) + { + foreach (DataGridViewRow i in dataEditor.Rows) + foreach (DataGridViewCell j in i.Cells) + j.Value = "0"; + } + + private void contextMenuInsertRow_Click(object sender, EventArgs e) + { + if (dataEditor.CurrentCell != null) dataEditor.Rows.Insert(dataEditor.CurrentCell.RowIndex, new DataGridViewRow()); + else dataEditor.Rows.Add(); + } + + private void contextMenuInsertCol_Click(object sender, EventArgs e) + { + var col = new DataGridViewTextBoxColumn() + { + SortMode = DataGridViewColumnSortMode.NotSortable, + AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCellsExceptHeader + }; + + if (dataEditor.CurrentCell != null) dataEditor.Columns.Insert(dataEditor.CurrentCell.ColumnIndex, col); + else dataEditor.Columns.Add(col); + } + + private void contextMenuDelRow_Click(object sender, EventArgs e) + { + foreach (DataGridViewCell i in dataEditor.SelectedCells) + dataEditor.Rows.RemoveAt(i.RowIndex); + } + + private void contextMenuDelColumn_Click(object sender, EventArgs e) + { + foreach (DataGridViewCell i in dataEditor.SelectedCells) + dataEditor.Columns.RemoveAt(i.ColumnIndex); + } + #endregion + + #region Drawing + protected override void OnPaintBackground(PaintEventArgs e) + { + DynamicLink.Controls.BackgroundGradient.Paint(e.Graphics, new Rectangle(-1, -1, this.Width, this.Height)); + } + #endregion + + private void dataEditor_CellMouseDown(object sender, DataGridViewCellMouseEventArgs e) + { + if (e.ColumnIndex < 0 || e.ColumnIndex >= dataEditor.Columns.Count) return; + if (e.RowIndex < 0 || e.RowIndex >= dataEditor.Rows.Count) return; + + if (e.Button == System.Windows.Forms.MouseButtons.Right) + { + dataEditor.CurrentCell = dataEditor.Rows[e.RowIndex].Cells[e.ColumnIndex]; + if (dataEditor.ContextMenu != null) dataEditor.ContextMenu.Show(dataEditor, e.Location); + } + } + + private void Editor_FormClosing(object sender, FormClosingEventArgs e) + { + if (!allowExit) + { + allowExit = true; + e.Cancel = true; + } + } + } +} diff --git a/Source/MatrixCalculator/Forms/Editor.resx b/Source/MatrixCalculator/Forms/Editor.resx new file mode 100644 index 0000000..1564f16 --- /dev/null +++ b/Source/MatrixCalculator/Forms/Editor.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + \ No newline at end of file diff --git a/Source/MatrixCalculator/Forms/ImportCsvWindow.Designer.cs b/Source/MatrixCalculator/Forms/ImportCsvWindow.Designer.cs new file mode 100644 index 0000000..216277b --- /dev/null +++ b/Source/MatrixCalculator/Forms/ImportCsvWindow.Designer.cs @@ -0,0 +1,455 @@ +namespace MatrixCalculator +{ + partial class ImportCsvWindow + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.buttonAccept = new DynamicLink.Controls.MyButton(); + this.buttonCancel = new DynamicLink.Controls.MyButton(); + this.buttonEntire = new DynamicLink.Controls.MyButton(); + this.labelSepChars = new System.Windows.Forms.Label(); + this.checkSepComma = new System.Windows.Forms.CheckBox(); + this.checkSepSemicolon = new System.Windows.Forms.CheckBox(); + this.checkSepTab = new System.Windows.Forms.CheckBox(); + this.checkSepSpace = new System.Windows.Forms.CheckBox(); + this.checkSepOthers = new System.Windows.Forms.CheckBox(); + this.inputSepOthers = new System.Windows.Forms.TextBox(); + this.checkCombine = new System.Windows.Forms.CheckBox(); + this.label1 = new System.Windows.Forms.Label(); + this.groupBoxSelectRange = new DynamicLink.Controls.MyGroupBox(); + this.dataGrid = new System.Windows.Forms.DataGridView(); + this.groupBoxMatrixName = new DynamicLink.Controls.MyGroupBox(); + this.inputName = new System.Windows.Forms.TextBox(); + this.groupBoxRange = new DynamicLink.Controls.MyGroupBox(); + this.labelEndColumn = new System.Windows.Forms.Label(); + this.inputEndColumn = new System.Windows.Forms.NumericUpDown(); + this.labelEndRow = new System.Windows.Forms.Label(); + this.inputEndRow = new System.Windows.Forms.NumericUpDown(); + this.labelStartColumn = new System.Windows.Forms.Label(); + this.inputStartColumn = new System.Windows.Forms.NumericUpDown(); + this.labelStartRow = new System.Windows.Forms.Label(); + this.inputStartRow = new System.Windows.Forms.NumericUpDown(); + this.groupBoxSeparators = new DynamicLink.Controls.MyGroupBox(); + this.groupBoxSelectRange.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.dataGrid)).BeginInit(); + this.groupBoxMatrixName.SuspendLayout(); + this.groupBoxRange.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.inputEndColumn)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.inputEndRow)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.inputStartColumn)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.inputStartRow)).BeginInit(); + this.groupBoxSeparators.SuspendLayout(); + this.SuspendLayout(); + // + // buttonAccept + // + this.buttonAccept.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.buttonAccept.BackColor = System.Drawing.Color.Transparent; + this.buttonAccept.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.buttonAccept.ForeColor = System.Drawing.Color.DarkGreen; + this.buttonAccept.Location = new System.Drawing.Point(426, 401); + this.buttonAccept.Name = "buttonAccept"; + this.buttonAccept.Size = new System.Drawing.Size(75, 23); + this.buttonAccept.TabIndex = 5; + this.buttonAccept.Text = "Accept "; + this.buttonAccept.UseVisualStyleBackColor = false; + this.buttonAccept.Click += new System.EventHandler(this.buttonAccept_Click); + // + // buttonCancel + // + this.buttonCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.buttonCancel.BackColor = System.Drawing.Color.Transparent; + this.buttonCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.buttonCancel.Location = new System.Drawing.Point(345, 401); + this.buttonCancel.Name = "buttonCancel"; + this.buttonCancel.Size = new System.Drawing.Size(75, 23); + this.buttonCancel.TabIndex = 4; + this.buttonCancel.Text = "Cancel"; + this.buttonCancel.UseVisualStyleBackColor = false; + this.buttonCancel.Click += new System.EventHandler(this.buttonCancel_Click); + // + // buttonEntire + // + this.buttonEntire.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); + this.buttonEntire.BackColor = System.Drawing.Color.Transparent; + this.buttonEntire.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.buttonEntire.Location = new System.Drawing.Point(8, 401); + this.buttonEntire.Name = "buttonEntire"; + this.buttonEntire.Size = new System.Drawing.Size(75, 23); + this.buttonEntire.TabIndex = 6; + this.buttonEntire.Text = "Entire grid"; + this.buttonEntire.UseVisualStyleBackColor = false; + this.buttonEntire.Click += new System.EventHandler(this.buttonEntire_Click); + // + // labelSepChars + // + this.labelSepChars.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.labelSepChars.AutoSize = true; + this.labelSepChars.BackColor = System.Drawing.Color.Transparent; + this.labelSepChars.Location = new System.Drawing.Point(6, 28); + this.labelSepChars.Name = "labelSepChars"; + this.labelSepChars.Size = new System.Drawing.Size(85, 13); + this.labelSepChars.TabIndex = 15; + this.labelSepChars.Text = "Separator chars:"; + // + // checkSepComma + // + this.checkSepComma.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.checkSepComma.AutoSize = true; + this.checkSepComma.BackColor = System.Drawing.Color.Transparent; + this.checkSepComma.Checked = true; + this.checkSepComma.CheckState = System.Windows.Forms.CheckState.Checked; + this.checkSepComma.Location = new System.Drawing.Point(28, 69); + this.checkSepComma.Margin = new System.Windows.Forms.Padding(2); + this.checkSepComma.Name = "checkSepComma"; + this.checkSepComma.Size = new System.Drawing.Size(61, 17); + this.checkSepComma.TabIndex = 16; + this.checkSepComma.Text = "Comma"; + this.checkSepComma.UseVisualStyleBackColor = false; + this.checkSepComma.CheckedChanged += new System.EventHandler(this.checkSepComma_CheckedChanged); + // + // checkSepSemicolon + // + this.checkSepSemicolon.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.checkSepSemicolon.AutoSize = true; + this.checkSepSemicolon.BackColor = System.Drawing.Color.Transparent; + this.checkSepSemicolon.Location = new System.Drawing.Point(28, 90); + this.checkSepSemicolon.Margin = new System.Windows.Forms.Padding(2); + this.checkSepSemicolon.Name = "checkSepSemicolon"; + this.checkSepSemicolon.Size = new System.Drawing.Size(75, 17); + this.checkSepSemicolon.TabIndex = 17; + this.checkSepSemicolon.Text = "Semicolon"; + this.checkSepSemicolon.UseVisualStyleBackColor = false; + this.checkSepSemicolon.CheckedChanged += new System.EventHandler(this.checkSepSemicolon_CheckedChanged); + // + // checkSepTab + // + this.checkSepTab.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.checkSepTab.AutoSize = true; + this.checkSepTab.BackColor = System.Drawing.Color.Transparent; + this.checkSepTab.Location = new System.Drawing.Point(28, 48); + this.checkSepTab.Margin = new System.Windows.Forms.Padding(2); + this.checkSepTab.Name = "checkSepTab"; + this.checkSepTab.Size = new System.Drawing.Size(45, 17); + this.checkSepTab.TabIndex = 18; + this.checkSepTab.Text = "Tab"; + this.checkSepTab.UseVisualStyleBackColor = false; + this.checkSepTab.CheckedChanged += new System.EventHandler(this.checkSepTab_CheckedChanged); + // + // checkSepSpace + // + this.checkSepSpace.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.checkSepSpace.AutoSize = true; + this.checkSepSpace.BackColor = System.Drawing.Color.Transparent; + this.checkSepSpace.Location = new System.Drawing.Point(28, 111); + this.checkSepSpace.Margin = new System.Windows.Forms.Padding(2); + this.checkSepSpace.Name = "checkSepSpace"; + this.checkSepSpace.Size = new System.Drawing.Size(57, 17); + this.checkSepSpace.TabIndex = 19; + this.checkSepSpace.Text = "Space"; + this.checkSepSpace.UseVisualStyleBackColor = false; + this.checkSepSpace.CheckedChanged += new System.EventHandler(this.checkSepSpace_CheckedChanged); + // + // checkSepOthers + // + this.checkSepOthers.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.checkSepOthers.AutoSize = true; + this.checkSepOthers.BackColor = System.Drawing.Color.Transparent; + this.checkSepOthers.Location = new System.Drawing.Point(28, 132); + this.checkSepOthers.Margin = new System.Windows.Forms.Padding(2); + this.checkSepOthers.Name = "checkSepOthers"; + this.checkSepOthers.Size = new System.Drawing.Size(60, 17); + this.checkSepOthers.TabIndex = 20; + this.checkSepOthers.Text = "Others:"; + this.checkSepOthers.UseVisualStyleBackColor = false; + this.checkSepOthers.CheckedChanged += new System.EventHandler(this.checkSepOthers_CheckedChanged); + // + // inputSepOthers + // + this.inputSepOthers.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.inputSepOthers.Location = new System.Drawing.Point(93, 130); + this.inputSepOthers.Name = "inputSepOthers"; + this.inputSepOthers.Size = new System.Drawing.Size(59, 20); + this.inputSepOthers.TabIndex = 21; + this.inputSepOthers.TextChanged += new System.EventHandler(this.inputSepOthers_TextChanged); + // + // checkCombine + // + this.checkCombine.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.checkCombine.AutoSize = true; + this.checkCombine.BackColor = System.Drawing.Color.Transparent; + this.checkCombine.Location = new System.Drawing.Point(9, 165); + this.checkCombine.Margin = new System.Windows.Forms.Padding(2); + this.checkCombine.Name = "checkCombine"; + this.checkCombine.Size = new System.Drawing.Size(120, 17); + this.checkCombine.TabIndex = 22; + this.checkCombine.Text = "Combine characters"; + this.checkCombine.UseVisualStyleBackColor = false; + this.checkCombine.CheckedChanged += new System.EventHandler(this.checkCombine_CheckedChanged); + // + // label1 + // + this.label1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(355, 36); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(38, 13); + this.label1.TabIndex = 24; + this.label1.Text = "Name:"; + // + // groupBoxSelectRange + // + this.groupBoxSelectRange.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.groupBoxSelectRange.BackColor = System.Drawing.Color.Transparent; + this.groupBoxSelectRange.Controls.Add(this.dataGrid); + this.groupBoxSelectRange.Location = new System.Drawing.Point(12, 12); + this.groupBoxSelectRange.Name = "groupBoxSelectRange"; + this.groupBoxSelectRange.Padding = new System.Windows.Forms.Padding(4, 9, 4, 4); + this.groupBoxSelectRange.Size = new System.Drawing.Size(326, 383); + this.groupBoxSelectRange.TabIndex = 25; + this.groupBoxSelectRange.TabStop = false; + this.groupBoxSelectRange.Text = "Matrix data"; + // + // dataGrid + // + this.dataGrid.AllowUserToAddRows = false; + this.dataGrid.AllowUserToDeleteRows = false; + this.dataGrid.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize; + this.dataGrid.Dock = System.Windows.Forms.DockStyle.Fill; + this.dataGrid.Location = new System.Drawing.Point(4, 22); + this.dataGrid.Name = "dataGrid"; + this.dataGrid.ReadOnly = true; + this.dataGrid.Size = new System.Drawing.Size(318, 357); + this.dataGrid.TabIndex = 1; + // + // groupBoxMatrixName + // + this.groupBoxMatrixName.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.groupBoxMatrixName.BackColor = System.Drawing.Color.Transparent; + this.groupBoxMatrixName.Controls.Add(this.inputName); + this.groupBoxMatrixName.Location = new System.Drawing.Point(344, 12); + this.groupBoxMatrixName.Name = "groupBoxMatrixName"; + this.groupBoxMatrixName.Padding = new System.Windows.Forms.Padding(3, 8, 3, 3); + this.groupBoxMatrixName.Size = new System.Drawing.Size(158, 49); + this.groupBoxMatrixName.TabIndex = 26; + this.groupBoxMatrixName.TabStop = false; + this.groupBoxMatrixName.Text = "Name"; + // + // inputName + // + this.inputName.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.inputName.Location = new System.Drawing.Point(6, 24); + this.inputName.Name = "inputName"; + this.inputName.Size = new System.Drawing.Size(146, 20); + this.inputName.TabIndex = 24; + this.inputName.Text = "Imported "; + // + // groupBoxRange + // + this.groupBoxRange.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.groupBoxRange.BackColor = System.Drawing.Color.Transparent; + this.groupBoxRange.Controls.Add(this.labelEndColumn); + this.groupBoxRange.Controls.Add(this.inputEndColumn); + this.groupBoxRange.Controls.Add(this.labelEndRow); + this.groupBoxRange.Controls.Add(this.inputEndRow); + this.groupBoxRange.Controls.Add(this.labelStartColumn); + this.groupBoxRange.Controls.Add(this.inputStartColumn); + this.groupBoxRange.Controls.Add(this.labelStartRow); + this.groupBoxRange.Controls.Add(this.inputStartRow); + this.groupBoxRange.Location = new System.Drawing.Point(344, 67); + this.groupBoxRange.Name = "groupBoxRange"; + this.groupBoxRange.Padding = new System.Windows.Forms.Padding(3, 8, 3, 3); + this.groupBoxRange.Size = new System.Drawing.Size(158, 132); + this.groupBoxRange.TabIndex = 27; + this.groupBoxRange.TabStop = false; + this.groupBoxRange.Text = "Range"; + // + // labelEndColumn + // + this.labelEndColumn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.labelEndColumn.AutoSize = true; + this.labelEndColumn.BackColor = System.Drawing.Color.Transparent; + this.labelEndColumn.Location = new System.Drawing.Point(6, 104); + this.labelEndColumn.Name = "labelEndColumn"; + this.labelEndColumn.Size = new System.Drawing.Size(66, 13); + this.labelEndColumn.TabIndex = 22; + this.labelEndColumn.Text = "End column:"; + // + // inputEndColumn + // + this.inputEndColumn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.inputEndColumn.Location = new System.Drawing.Point(96, 102); + this.inputEndColumn.Name = "inputEndColumn"; + this.inputEndColumn.Size = new System.Drawing.Size(56, 20); + this.inputEndColumn.TabIndex = 21; + // + // labelEndRow + // + this.labelEndRow.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.labelEndRow.AutoSize = true; + this.labelEndRow.BackColor = System.Drawing.Color.Transparent; + this.labelEndRow.Location = new System.Drawing.Point(6, 78); + this.labelEndRow.Name = "labelEndRow"; + this.labelEndRow.Size = new System.Drawing.Size(49, 13); + this.labelEndRow.TabIndex = 20; + this.labelEndRow.Text = "End row:"; + // + // inputEndRow + // + this.inputEndRow.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.inputEndRow.Location = new System.Drawing.Point(96, 76); + this.inputEndRow.Name = "inputEndRow"; + this.inputEndRow.Size = new System.Drawing.Size(56, 20); + this.inputEndRow.TabIndex = 19; + // + // labelStartColumn + // + this.labelStartColumn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.labelStartColumn.AutoSize = true; + this.labelStartColumn.BackColor = System.Drawing.Color.Transparent; + this.labelStartColumn.Location = new System.Drawing.Point(6, 52); + this.labelStartColumn.Name = "labelStartColumn"; + this.labelStartColumn.Size = new System.Drawing.Size(69, 13); + this.labelStartColumn.TabIndex = 18; + this.labelStartColumn.Text = "Start column:"; + // + // inputStartColumn + // + this.inputStartColumn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.inputStartColumn.Location = new System.Drawing.Point(96, 50); + this.inputStartColumn.Name = "inputStartColumn"; + this.inputStartColumn.Size = new System.Drawing.Size(56, 20); + this.inputStartColumn.TabIndex = 17; + // + // labelStartRow + // + this.labelStartRow.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.labelStartRow.AutoSize = true; + this.labelStartRow.BackColor = System.Drawing.Color.Transparent; + this.labelStartRow.Location = new System.Drawing.Point(6, 26); + this.labelStartRow.Name = "labelStartRow"; + this.labelStartRow.Size = new System.Drawing.Size(52, 13); + this.labelStartRow.TabIndex = 16; + this.labelStartRow.Text = "Start row:"; + // + // inputStartRow + // + this.inputStartRow.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.inputStartRow.Location = new System.Drawing.Point(96, 24); + this.inputStartRow.Name = "inputStartRow"; + this.inputStartRow.Size = new System.Drawing.Size(56, 20); + this.inputStartRow.TabIndex = 15; + // + // groupBoxSeparators + // + this.groupBoxSeparators.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.groupBoxSeparators.BackColor = System.Drawing.Color.Transparent; + this.groupBoxSeparators.Controls.Add(this.labelSepChars); + this.groupBoxSeparators.Controls.Add(this.checkSepComma); + this.groupBoxSeparators.Controls.Add(this.checkSepSemicolon); + this.groupBoxSeparators.Controls.Add(this.checkSepTab); + this.groupBoxSeparators.Controls.Add(this.checkSepSpace); + this.groupBoxSeparators.Controls.Add(this.checkCombine); + this.groupBoxSeparators.Controls.Add(this.checkSepOthers); + this.groupBoxSeparators.Controls.Add(this.inputSepOthers); + this.groupBoxSeparators.Location = new System.Drawing.Point(344, 206); + this.groupBoxSeparators.Name = "groupBoxSeparators"; + this.groupBoxSeparators.Padding = new System.Windows.Forms.Padding(3, 8, 3, 3); + this.groupBoxSeparators.Size = new System.Drawing.Size(158, 187); + this.groupBoxSeparators.TabIndex = 28; + this.groupBoxSeparators.TabStop = false; + this.groupBoxSeparators.Text = "Separator characters"; + // + // ImportCsvWindow + // + this.AcceptButton = this.buttonAccept; + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.CancelButton = this.buttonCancel; + this.ClientSize = new System.Drawing.Size(513, 436); + this.Controls.Add(this.groupBoxSeparators); + this.Controls.Add(this.groupBoxRange); + this.Controls.Add(this.groupBoxMatrixName); + this.Controls.Add(this.groupBoxSelectRange); + this.Controls.Add(this.label1); + this.Controls.Add(this.buttonEntire); + this.Controls.Add(this.buttonAccept); + this.Controls.Add(this.buttonCancel); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.SizableToolWindow; + this.Name = "ImportCsvWindow"; + this.Text = "Import from CSV file..."; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.ImportCsvWindow_FormClosing); + this.groupBoxSelectRange.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.dataGrid)).EndInit(); + this.groupBoxMatrixName.ResumeLayout(false); + this.groupBoxMatrixName.PerformLayout(); + this.groupBoxRange.ResumeLayout(false); + this.groupBoxRange.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.inputEndColumn)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.inputEndRow)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.inputStartColumn)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.inputStartRow)).EndInit(); + this.groupBoxSeparators.ResumeLayout(false); + this.groupBoxSeparators.PerformLayout(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private DynamicLink.Controls.MyButton buttonAccept; + private DynamicLink.Controls.MyButton buttonCancel; + private DynamicLink.Controls.MyButton buttonEntire; + private System.Windows.Forms.Label labelSepChars; + private System.Windows.Forms.CheckBox checkSepComma; + private System.Windows.Forms.CheckBox checkSepSemicolon; + private System.Windows.Forms.CheckBox checkSepTab; + private System.Windows.Forms.CheckBox checkSepSpace; + private System.Windows.Forms.CheckBox checkSepOthers; + private System.Windows.Forms.TextBox inputSepOthers; + private System.Windows.Forms.CheckBox checkCombine; + private System.Windows.Forms.Label label1; + private DynamicLink.Controls.MyGroupBox groupBoxSelectRange; + public System.Windows.Forms.DataGridView dataGrid; + private DynamicLink.Controls.MyGroupBox groupBoxMatrixName; + private System.Windows.Forms.TextBox inputName; + private DynamicLink.Controls.MyGroupBox groupBoxRange; + private System.Windows.Forms.Label labelEndColumn; + private System.Windows.Forms.NumericUpDown inputEndColumn; + private System.Windows.Forms.Label labelEndRow; + private System.Windows.Forms.NumericUpDown inputEndRow; + private System.Windows.Forms.Label labelStartColumn; + private System.Windows.Forms.NumericUpDown inputStartColumn; + private System.Windows.Forms.Label labelStartRow; + private System.Windows.Forms.NumericUpDown inputStartRow; + private DynamicLink.Controls.MyGroupBox groupBoxSeparators; + } +} \ No newline at end of file diff --git a/Source/MatrixCalculator/Forms/ImportCsvWindow.cs b/Source/MatrixCalculator/Forms/ImportCsvWindow.cs new file mode 100644 index 0000000..e2e14e9 --- /dev/null +++ b/Source/MatrixCalculator/Forms/ImportCsvWindow.cs @@ -0,0 +1,225 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Windows.Forms; + +namespace MatrixCalculator +{ + public partial class ImportCsvWindow : Form + { + private string csv; + private bool allowExit = true; + + #region Public properties + public int StartRow { get; set; } + public int StartCol { get; set; } + public int EndRow { get; set; } + public int EndCol { get; set; } + + public string Csv{ + get { return csv; } + set { csv = value; UpdateGrid(); } + } + + public string MatrixName { + get { + return inputName.Text; + } + + set { + inputName.Text = value; + } + } + + public MathNet.Numerics.LinearAlgebra.Matrix Matrix + { + get { return GridViewHelper.GetMatrix(dataGrid); } + set { GridViewHelper.PutMatrix(value, dataGrid); } + } + #endregion + + private Dictionary separators = new Dictionary(); + + public ImportCsvWindow() + { + InitializeComponent(); + + separators.Add(',', true); + separators.Add('\t', false); + separators.Add(' ', false); + separators.Add(';', false); + } + + public void LoadFile(string filename) + { + if (System.IO.File.Exists(filename)) + Csv = System.IO.File.ReadAllText(filename); + } + + private void UpdateGrid() + { + List sep = new List(); + foreach (var i in separators) + if (i.Value) sep.Add(i.Key); + + // Update data + dataGrid.DataSource = CsvParser.GetTable(Csv, sep.ToArray(), checkCombine.Checked); + + foreach (DataGridViewColumn i in dataGrid.Columns) + { + i.HeaderText = ""; + i.AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells; + } + + // Update sizes + inputStartRow.Value = 0; + inputStartColumn.Value = 0; + inputEndColumn.Value = inputEndColumn.Maximum = dataGrid.Columns.Count - 1; + inputEndRow.Value = inputEndRow.Maximum = dataGrid.Rows.Count - 1; + } + + #region Separators + private void checkCombine_CheckedChanged(object sender, EventArgs e) + { + UpdateGrid(); + } + + private void checkSepComma_CheckedChanged(object sender, EventArgs e) + { + separators[','] = checkSepComma.Checked; + UpdateGrid(); + } + + private void checkSepSemicolon_CheckedChanged(object sender, EventArgs e) + { + separators[';'] = checkSepComma.Checked; + UpdateGrid(); + } + + private void checkSepSpace_CheckedChanged(object sender, EventArgs e) + { + separators[' '] = checkSepComma.Checked; + UpdateGrid(); + } + + private void checkSepOthers_CheckedChanged(object sender, EventArgs e) + { + List temp = new List(); + foreach (var i in separators) + if (i.Key != ' ' && i.Key != '\t' && i.Key != ';' && i.Key != ',') + temp.Add(i.Key); + + foreach (var i in temp) separators[i] = false; + + if (checkSepOthers.Checked) + foreach (var i in inputSepOthers.Text) + separators[i] = true; + + UpdateGrid(); + } + + private void checkSepTab_CheckedChanged(object sender, EventArgs e) + { + separators['\t'] = checkSepComma.Checked; + UpdateGrid(); + } + + private void inputSepOthers_TextChanged(object sender, EventArgs e) + { + List temp = new List(); + foreach (var i in separators) + if (i.Key != ' ' && i.Key != '\t' && i.Key != ';' && i.Key != ',') + temp.Add(i.Key); + + foreach (var i in temp) separators[i] = false; + + if (checkSepOthers.Checked) + foreach (var i in inputSepOthers.Text) + separators[i] = true; + + UpdateGrid(); + } + #endregion + + #region Form buttons + private void buttonEntire_Click(object sender, EventArgs e) + { + StartCol = StartRow = 0; + inputEndColumn.Value = dataGrid.Columns.Count - 1; + inputEndRow.Value = dataGrid.Rows.Count - 1; + + this.DialogResult = System.Windows.Forms.DialogResult.OK; + this.Close(); + } + + private void buttonAccept_Click(object sender, EventArgs e) + { + // Get numbers + StartCol = Convert.ToInt32(inputStartColumn.Value); + StartRow = Convert.ToInt32(inputStartRow.Value); + EndCol = Convert.ToInt32(inputEndColumn.Value); + EndRow = Convert.ToInt32(inputEndRow.Value); + + // Validate input + if (inputName.Text == "") + { + allowExit = false; + MessageBox.Show("Name cannot be empty!", "Error!"); + return; + } + + if (EndCol - StartCol <= 0 || EndRow - StartRow <= 0) + { + allowExit = false; + MessageBox.Show("Invalid range, the matrix must have at least one row and one column.", "Error!"); + return; + } + + // Trim unneeded rows and columns + while (StartCol > 0) { + dataGrid.Columns.RemoveAt(0); + StartCol--; + EndCol--; + } + + while (StartRow > 0) { + dataGrid.Rows.RemoveAt(0); + StartRow--; + EndRow--; + } + + GridViewHelper.Resize(dataGrid, EndCol + 1, EndRow + 1); + + // Done, finish + this.DialogResult = System.Windows.Forms.DialogResult.OK; + this.Close(); + } + + private void buttonCancel_Click(object sender, EventArgs e) + { + this.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.Close(); + } + #endregion + + private void ImportCsvWindow_FormClosing(object sender, FormClosingEventArgs e) + { + if (!allowExit) + { + allowExit = true; + e.Cancel = true; + } + } + + #region Painting + protected override void OnPaintBackground(PaintEventArgs e) + { + DynamicLink.Controls.BackgroundGradient.Paint(e.Graphics, new Rectangle(-1, -1, this.Width, this.Height)); + } + #endregion + } +} diff --git a/Source/MatrixCalculator/Forms/ImportCsvWindow.resx b/Source/MatrixCalculator/Forms/ImportCsvWindow.resx new file mode 100644 index 0000000..7080a7d --- /dev/null +++ b/Source/MatrixCalculator/Forms/ImportCsvWindow.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Source/MatrixCalculator/Forms/ImportWorksheetWindow.Designer.cs b/Source/MatrixCalculator/Forms/ImportWorksheetWindow.Designer.cs new file mode 100644 index 0000000..73c81e0 --- /dev/null +++ b/Source/MatrixCalculator/Forms/ImportWorksheetWindow.Designer.cs @@ -0,0 +1,113 @@ +namespace MatrixCalculator +{ + partial class ImportWorksheetWindow + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.listMatrices = new System.Windows.Forms.CheckedListBox(); + this.buttonAccept = new DynamicLink.Controls.MyButton(); + this.buttonCancel = new DynamicLink.Controls.MyButton(); + this.groupBoxSelectMatrices = new DynamicLink.Controls.MyGroupBox(); + this.groupBoxSelectMatrices.SuspendLayout(); + this.SuspendLayout(); + // + // listMatrices + // + this.listMatrices.CheckOnClick = true; + this.listMatrices.Dock = System.Windows.Forms.DockStyle.Fill; + this.listMatrices.FormattingEnabled = true; + this.listMatrices.Location = new System.Drawing.Point(5, 23); + this.listMatrices.Name = "listMatrices"; + this.listMatrices.Size = new System.Drawing.Size(250, 215); + this.listMatrices.TabIndex = 0; + // + // buttonAccept + // + this.buttonAccept.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.buttonAccept.BackColor = System.Drawing.Color.Transparent; + this.buttonAccept.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.buttonAccept.ForeColor = System.Drawing.Color.DarkGreen; + this.buttonAccept.Location = new System.Drawing.Point(197, 261); + this.buttonAccept.Name = "buttonAccept"; + this.buttonAccept.Size = new System.Drawing.Size(75, 23); + this.buttonAccept.TabIndex = 5; + this.buttonAccept.Text = "Accept"; + this.buttonAccept.UseVisualStyleBackColor = false; + this.buttonAccept.Click += new System.EventHandler(this.buttonAccept_Click); + // + // buttonCancel + // + this.buttonCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.buttonCancel.BackColor = System.Drawing.Color.Transparent; + this.buttonCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.buttonCancel.Location = new System.Drawing.Point(116, 261); + this.buttonCancel.Name = "buttonCancel"; + this.buttonCancel.Size = new System.Drawing.Size(75, 23); + this.buttonCancel.TabIndex = 4; + this.buttonCancel.Text = "Cancel"; + this.buttonCancel.UseVisualStyleBackColor = false; + this.buttonCancel.Click += new System.EventHandler(this.buttonCancel_Click); + // + // groupBoxSelectMatrices + // + this.groupBoxSelectMatrices.BackColor = System.Drawing.Color.Transparent; + this.groupBoxSelectMatrices.Controls.Add(this.listMatrices); + this.groupBoxSelectMatrices.Location = new System.Drawing.Point(12, 12); + this.groupBoxSelectMatrices.Name = "groupBoxSelectMatrices"; + this.groupBoxSelectMatrices.Padding = new System.Windows.Forms.Padding(5, 10, 5, 5); + this.groupBoxSelectMatrices.Size = new System.Drawing.Size(260, 243); + this.groupBoxSelectMatrices.TabIndex = 6; + this.groupBoxSelectMatrices.TabStop = false; + this.groupBoxSelectMatrices.Text = "Select matrices to import:"; + // + // ImportWorksheetWindow + // + this.AcceptButton = this.buttonAccept; + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.CancelButton = this.buttonCancel; + this.ClientSize = new System.Drawing.Size(284, 296); + this.Controls.Add(this.groupBoxSelectMatrices); + this.Controls.Add(this.buttonAccept); + this.Controls.Add(this.buttonCancel); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.SizableToolWindow; + this.Name = "ImportWorksheetWindow"; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "Import from worksheet..."; + this.groupBoxSelectMatrices.ResumeLayout(false); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.CheckedListBox listMatrices; + private DynamicLink.Controls.MyButton buttonAccept; + private DynamicLink.Controls.MyButton buttonCancel; + private DynamicLink.Controls.MyGroupBox groupBoxSelectMatrices; + } +} \ No newline at end of file diff --git a/Source/MatrixCalculator/Forms/ImportWorksheetWindow.cs b/Source/MatrixCalculator/Forms/ImportWorksheetWindow.cs new file mode 100644 index 0000000..0a35d19 --- /dev/null +++ b/Source/MatrixCalculator/Forms/ImportWorksheetWindow.cs @@ -0,0 +1,59 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Windows.Forms; + +namespace MatrixCalculator +{ + public partial class ImportWorksheetWindow : Form + { + public DataTable Data { get; set; } + + public ImportWorksheetWindow() + { + InitializeComponent(); + } + + public void LoadFile(string filename) + { + WorksheetFile file = new WorksheetFile(filename); + Data = file.Read(); + + listMatrices.Items.Clear(); + + foreach (DataRow i in Data.Rows) + listMatrices.Items.Add(i["name"].ToString()); + } + + private void buttonCancel_Click(object sender, EventArgs e) + { + this.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.Close(); + } + + private void buttonAccept_Click(object sender, EventArgs e) + { + List toRemove = new List(); + + foreach (DataRow i in Data.Rows) + if (!listMatrices.CheckedItems.Contains(i["name"].ToString())) toRemove.Add(i); + + foreach (var i in toRemove) + Data.Rows.Remove(i); + + this.DialogResult = System.Windows.Forms.DialogResult.OK; + this.Close(); + } + + #region Paint + protected override void OnPaintBackground(PaintEventArgs e) + { + DynamicLink.Controls.BackgroundGradient.Paint(e.Graphics, new Rectangle(-1, -1, this.Width, this.Height)); + } + #endregion + } +} diff --git a/Source/MatrixCalculator/Forms/ImportWorksheetWindow.resx b/Source/MatrixCalculator/Forms/ImportWorksheetWindow.resx new file mode 100644 index 0000000..7080a7d --- /dev/null +++ b/Source/MatrixCalculator/Forms/ImportWorksheetWindow.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Source/MatrixCalculator/Forms/NumericInput.Designer.cs b/Source/MatrixCalculator/Forms/NumericInput.Designer.cs new file mode 100644 index 0000000..922124e --- /dev/null +++ b/Source/MatrixCalculator/Forms/NumericInput.Designer.cs @@ -0,0 +1,131 @@ +namespace MatrixCalculator +{ + partial class NumericInput + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.inputBox = new System.Windows.Forms.TextBox(); + this.buttonCancel = new DynamicLink.Controls.MyButton(); + this.buttonAccept = new DynamicLink.Controls.MyButton(); + this.labelMessage = new System.Windows.Forms.Label(); + this.myGroupBox = new DynamicLink.Controls.MyGroupBox(); + this.myGroupBox.SuspendLayout(); + this.SuspendLayout(); + // + // inputBox + // + this.inputBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.inputBox.Location = new System.Drawing.Point(6, 26); + this.inputBox.Name = "inputBox"; + this.inputBox.Size = new System.Drawing.Size(256, 20); + this.inputBox.TabIndex = 1; + // + // buttonCancel + // + this.buttonCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.buttonCancel.BackColor = System.Drawing.Color.Transparent; + this.buttonCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.buttonCancel.Location = new System.Drawing.Point(112, 71); + this.buttonCancel.Name = "buttonCancel"; + this.buttonCancel.Size = new System.Drawing.Size(75, 23); + this.buttonCancel.TabIndex = 2; + this.buttonCancel.Text = "Cancel"; + this.buttonCancel.UseVisualStyleBackColor = false; + this.buttonCancel.Click += new System.EventHandler(this.buttonCancel_Click); + // + // buttonAccept + // + this.buttonAccept.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.buttonAccept.BackColor = System.Drawing.Color.Transparent; + this.buttonAccept.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.buttonAccept.ForeColor = System.Drawing.Color.DarkGreen; + this.buttonAccept.Location = new System.Drawing.Point(193, 71); + this.buttonAccept.Name = "buttonAccept"; + this.buttonAccept.Size = new System.Drawing.Size(75, 23); + this.buttonAccept.TabIndex = 3; + this.buttonAccept.Text = "Accept"; + this.buttonAccept.UseVisualStyleBackColor = false; + this.buttonAccept.Click += new System.EventHandler(this.buttonAccept_Click); + // + // labelMessage + // + this.labelMessage.AutoSize = true; + this.labelMessage.BackColor = System.Drawing.Color.Transparent; + this.labelMessage.Location = new System.Drawing.Point(6, 6); + this.labelMessage.Name = "labelMessage"; + this.labelMessage.Size = new System.Drawing.Size(92, 13); + this.labelMessage.TabIndex = 0; + this.labelMessage.Text = "Insert a ? number:"; + // + // myGroupBox + // + this.myGroupBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.myGroupBox.BackColor = System.Drawing.Color.Transparent; + this.myGroupBox.Controls.Add(this.labelMessage); + this.myGroupBox.Controls.Add(this.inputBox); + this.myGroupBox.Location = new System.Drawing.Point(6, 7); + this.myGroupBox.Name = "myGroupBox"; + this.myGroupBox.Padding = new System.Windows.Forms.Padding(3, 8, 3, 3); + this.myGroupBox.Size = new System.Drawing.Size(269, 58); + this.myGroupBox.TabIndex = 4; + this.myGroupBox.TabStop = false; + // + // NumericInput + // + this.AcceptButton = this.buttonAccept; + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.CancelButton = this.buttonCancel; + this.ClientSize = new System.Drawing.Size(280, 106); + this.Controls.Add(this.myGroupBox); + this.Controls.Add(this.buttonAccept); + this.Controls.Add(this.buttonCancel); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "NumericInput"; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.NumericInput_FormClosing); + this.myGroupBox.ResumeLayout(false); + this.myGroupBox.PerformLayout(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.TextBox inputBox; + private DynamicLink.Controls.MyButton buttonCancel; + private DynamicLink.Controls.MyButton buttonAccept; + private System.Windows.Forms.Label labelMessage; + private DynamicLink.Controls.MyGroupBox myGroupBox; + } +} \ No newline at end of file diff --git a/Source/MatrixCalculator/Forms/NumericInput.cs b/Source/MatrixCalculator/Forms/NumericInput.cs new file mode 100644 index 0000000..9f00651 --- /dev/null +++ b/Source/MatrixCalculator/Forms/NumericInput.cs @@ -0,0 +1,109 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Windows.Forms; + +namespace MatrixCalculator +{ + public partial class NumericInput : Form + { + public enum NumberType { Integer, Real }; + + #region Data + bool allowExit = true; + + private NumberType type; + public NumberType Type { + get { return type; } + + set + { + if (value == NumberType.Integer) labelMessage.Text = "Insert an integer number:"; + else labelMessage.Text = "Insert a real number:"; + + type = value; + } + } + + public double NumberReal + { + get { + double ret = 0; + double.TryParse(inputBox.Text, out ret); + return ret; + } + + set { + inputBox.Text = value.ToString(); + } + } + + public int NumberInt + { + get { + int ret = 0; + int.TryParse(inputBox.Text, out ret); + return ret; + } + + set { + inputBox.Text = value.ToString(); + } + } + #endregion + + public NumericInput(NumberType t = NumberType.Real) + { + InitializeComponent(); + Type = t; + } + + private void buttonAccept_Click(object sender, EventArgs e) + { + this.DialogResult = System.Windows.Forms.DialogResult.OK; + + // Validate input + bool ok = true; + double val; + int vali; + + if (Type == NumberType.Real) ok = double.TryParse(inputBox.Text, out val); + else ok = int.TryParse(inputBox.Text, out vali); + + // Is everything ok? + if (!ok) + { + allowExit = false; + inputBox.BackColor = Color.LightPink; + labelMessage.Font = new Font(labelMessage.Font, FontStyle.Bold); + } + } + + private void buttonCancel_Click(object sender, EventArgs e) + { + this.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.Close(); + } + + private void NumericInput_FormClosing(object sender, FormClosingEventArgs e) + { + if (!allowExit) + { + allowExit = true; + e.Cancel = true; + } + } + + #region Paint + protected override void OnPaintBackground(PaintEventArgs e) + { + DynamicLink.Controls.BackgroundGradient.Paint(e.Graphics, new Rectangle(-1, -1, this.Width, this.Height)); + } + #endregion + + } +} diff --git a/Source/MatrixCalculator/Forms/NumericInput.resx b/Source/MatrixCalculator/Forms/NumericInput.resx new file mode 100644 index 0000000..7080a7d --- /dev/null +++ b/Source/MatrixCalculator/Forms/NumericInput.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Source/MatrixCalculator/Forms/SettingsWindow.Designer.cs b/Source/MatrixCalculator/Forms/SettingsWindow.Designer.cs new file mode 100644 index 0000000..672e593 --- /dev/null +++ b/Source/MatrixCalculator/Forms/SettingsWindow.Designer.cs @@ -0,0 +1,169 @@ +namespace MatrixCalculator +{ + partial class SettingsWindow + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + this.buttonAccept = new DynamicLink.Controls.MyButton(); + this.buttonCancel = new DynamicLink.Controls.MyButton(); + this.groupBox1 = new DynamicLink.Controls.MyGroupBox(); + this.label1 = new System.Windows.Forms.Label(); + this.checkResultAsMatrix = new System.Windows.Forms.CheckBox(); + this.inputDoublePrecision = new System.Windows.Forms.NumericUpDown(); + this.checkDoublePrecision = new System.Windows.Forms.CheckBox(); + this.toolTip = new System.Windows.Forms.ToolTip(this.components); + this.groupBox1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.inputDoublePrecision)).BeginInit(); + this.SuspendLayout(); + // + // buttonAccept + // + this.buttonAccept.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.buttonAccept.BackColor = System.Drawing.Color.Transparent; + this.buttonAccept.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.buttonAccept.ForeColor = System.Drawing.Color.DarkGreen; + this.buttonAccept.Location = new System.Drawing.Point(223, 116); + this.buttonAccept.Name = "buttonAccept"; + this.buttonAccept.Size = new System.Drawing.Size(75, 23); + this.buttonAccept.TabIndex = 7; + this.buttonAccept.Text = "Accept"; + this.buttonAccept.UseVisualStyleBackColor = false; + this.buttonAccept.Click += new System.EventHandler(this.buttonAccept_Click); + // + // buttonCancel + // + this.buttonCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.buttonCancel.BackColor = System.Drawing.Color.Transparent; + this.buttonCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.buttonCancel.Location = new System.Drawing.Point(142, 116); + this.buttonCancel.Name = "buttonCancel"; + this.buttonCancel.Size = new System.Drawing.Size(75, 23); + this.buttonCancel.TabIndex = 6; + this.buttonCancel.Text = "Cancel"; + this.buttonCancel.UseVisualStyleBackColor = false; + this.buttonCancel.Click += new System.EventHandler(this.buttonCancel_Click); + // + // groupBox1 + // + this.groupBox1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.groupBox1.BackColor = System.Drawing.Color.Transparent; + this.groupBox1.Controls.Add(this.label1); + this.groupBox1.Controls.Add(this.checkResultAsMatrix); + this.groupBox1.Controls.Add(this.inputDoublePrecision); + this.groupBox1.Controls.Add(this.checkDoublePrecision); + this.groupBox1.Location = new System.Drawing.Point(12, 12); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Padding = new System.Windows.Forms.Padding(3, 8, 3, 3); + this.groupBox1.Size = new System.Drawing.Size(286, 98); + this.groupBox1.TabIndex = 8; + this.groupBox1.TabStop = false; + this.groupBox1.Text = "Matrix calculator preferences"; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.BackColor = System.Drawing.Color.Transparent; + this.label1.Location = new System.Drawing.Point(204, 33); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(70, 13); + this.label1.TabIndex = 15; + this.label1.Text = "decimal digits"; + // + // checkResultAsMatrix + // + this.checkResultAsMatrix.AutoSize = true; + this.checkResultAsMatrix.BackColor = System.Drawing.Color.Transparent; + this.checkResultAsMatrix.Location = new System.Drawing.Point(16, 65); + this.checkResultAsMatrix.Name = "checkResultAsMatrix"; + this.checkResultAsMatrix.Size = new System.Drawing.Size(154, 17); + this.checkResultAsMatrix.TabIndex = 14; + this.checkResultAsMatrix.Text = "Show result as a 1x1 matrix"; + this.toolTip.SetToolTip(this.checkResultAsMatrix, "If set, the result of numeric calculations (like determinant, minimum element etc" + + ") will be displayed as a 1x1 matrix. Otherwise, it will be displayed in the \"Out" + + "put\" box."); + this.checkResultAsMatrix.UseVisualStyleBackColor = false; + // + // inputDoublePrecision + // + this.inputDoublePrecision.Location = new System.Drawing.Point(138, 31); + this.inputDoublePrecision.Name = "inputDoublePrecision"; + this.inputDoublePrecision.Size = new System.Drawing.Size(60, 20); + this.inputDoublePrecision.TabIndex = 13; + this.toolTip.SetToolTip(this.inputDoublePrecision, "For example, if value is 1, number 0.234 will be displayed as 0.2 "); + // + // checkDoublePrecision + // + this.checkDoublePrecision.AutoSize = true; + this.checkDoublePrecision.BackColor = System.Drawing.Color.Transparent; + this.checkDoublePrecision.Location = new System.Drawing.Point(16, 32); + this.checkDoublePrecision.Name = "checkDoublePrecision"; + this.checkDoublePrecision.Size = new System.Drawing.Size(116, 17); + this.checkDoublePrecision.TabIndex = 12; + this.checkDoublePrecision.Text = "Round numbers to:"; + this.toolTip.SetToolTip(this.checkDoublePrecision, "If set, the number of decimals will be limited to the number selected."); + this.checkDoublePrecision.UseVisualStyleBackColor = false; + this.checkDoublePrecision.CheckedChanged += new System.EventHandler(this.checkDoublePrecision_CheckedChanged); + // + // SettingsWindow + // + this.AcceptButton = this.buttonAccept; + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.CancelButton = this.buttonCancel; + this.ClientSize = new System.Drawing.Size(310, 151); + this.Controls.Add(this.groupBox1); + this.Controls.Add(this.buttonAccept); + this.Controls.Add(this.buttonCancel); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "SettingsWindow"; + this.ShowInTaskbar = false; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "Preferences"; + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.inputDoublePrecision)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private DynamicLink.Controls.MyButton buttonAccept; + private DynamicLink.Controls.MyButton buttonCancel; + private DynamicLink.Controls.MyGroupBox groupBox1; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.CheckBox checkResultAsMatrix; + private System.Windows.Forms.ToolTip toolTip; + private System.Windows.Forms.NumericUpDown inputDoublePrecision; + private System.Windows.Forms.CheckBox checkDoublePrecision; + } +} \ No newline at end of file diff --git a/Source/MatrixCalculator/Forms/SettingsWindow.cs b/Source/MatrixCalculator/Forms/SettingsWindow.cs new file mode 100644 index 0000000..7c7d51c --- /dev/null +++ b/Source/MatrixCalculator/Forms/SettingsWindow.cs @@ -0,0 +1,60 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Windows.Forms; + +namespace MatrixCalculator +{ + public partial class SettingsWindow : Form + { + public SettingsWindow() + { + InitializeComponent(); + + // Get settings + int prec = MatrixCalculator.Properties.Settings.Default.DoublePrecision; + bool res = MatrixCalculator.Properties.Settings.Default.NumberResultAsMatrix; + + // Show settings + if (prec == -1) checkDoublePrecision.Checked = false; + else + { + checkDoublePrecision.Checked = true; + inputDoublePrecision.Value = prec; + } + + checkResultAsMatrix.Checked = res; + } + + private void checkDoublePrecision_CheckedChanged(object sender, EventArgs e) + { + inputDoublePrecision.Enabled = checkDoublePrecision.Checked; + } + + private void buttonAccept_Click(object sender, EventArgs e) + { + if (!checkDoublePrecision.Checked) MatrixCalculator.Properties.Settings.Default.DoublePrecision = -1; + else MatrixCalculator.Properties.Settings.Default.DoublePrecision = Convert.ToInt32(inputDoublePrecision.Value); + + MatrixCalculator.Properties.Settings.Default.NumberResultAsMatrix = checkResultAsMatrix.Checked; + + this.Close(); + } + + private void buttonCancel_Click(object sender, EventArgs e) + { + this.Close(); + } + + #region Paint + protected override void OnPaintBackground(PaintEventArgs e) + { + DynamicLink.Controls.BackgroundGradient.Paint(e.Graphics, new Rectangle(-1, -1, this.Width, this.Height)); + } + #endregion + } +} diff --git a/Source/MatrixCalculator/Forms/SettingsWindow.resx b/Source/MatrixCalculator/Forms/SettingsWindow.resx new file mode 100644 index 0000000..5cea0f6 --- /dev/null +++ b/Source/MatrixCalculator/Forms/SettingsWindow.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + \ No newline at end of file diff --git a/Source/MatrixCalculator/Helpers/GridViewHelper.cs b/Source/MatrixCalculator/Helpers/GridViewHelper.cs new file mode 100644 index 0000000..04562c1 --- /dev/null +++ b/Source/MatrixCalculator/Helpers/GridViewHelper.cs @@ -0,0 +1,144 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Windows.Forms; +using MathNet.Numerics.LinearAlgebra; + +namespace MatrixCalculator +{ + static class GridViewHelper + { + /// + /// Loads a matrix in a DataGridView + /// + public static void PutMatrix(Matrix m, DataGridView grid) + { + // Reset grid + grid.Rows.Clear(); + grid.Columns.Clear(); + + // Add columns + for (int i = 0; i < m.ColumnCount; i++) + { + var col = new DataGridViewTextBoxColumn() + { + SortMode = DataGridViewColumnSortMode.NotSortable, + AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells + }; + + grid.Columns.Add(col); + } + + // Add rows and data + for (int i = 0; i < m.RowCount; i++) + { + grid.Rows.Add(); + + for (int j = 0; j < m.ColumnCount; j++) + grid[j, i].Value = MyDouble.String(m[i, j]); + } + } + + /// + /// Gets the matrix from a DataGridView + /// + public static Matrix GetMatrix(DataGridView grid) + { + Matrix m = Matrix.Build.Dense(grid.Rows.Count, grid.Columns.Count); + + for (int i = 0; i < m.RowCount; i++) + for (int j = 0; j < m.ColumnCount; j++) + { + double temp = 0; + + if (grid[j, i].Value != null) + double.TryParse(grid[j, i].Value.ToString(), out temp); + + m[i, j] = temp; + } + + return m; + } + + /// + /// Resizes a DataGridView + /// + /// The DataGridView + /// The new number of columns + /// The new number of rows + public static void Resize(DataGridView grid, int ncols, int nrows) + { + // Add columns + while (grid.Columns.Count < ncols) + { + DataGridViewTextBoxColumn col = new DataGridViewTextBoxColumn() + { + AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells, + SortMode = DataGridViewColumnSortMode.NotSortable + }; + + grid.Columns.Add(col); + } + + // Remove columns + while (grid.Columns.Count > ncols) + grid.Columns.Remove(grid.Columns.GetLastColumn(DataGridViewElementStates.Displayed, DataGridViewElementStates.None)); + + // Add rows + while (grid.Rows.Count < nrows) + grid.Rows.Add(); + + // Remove rows + while (grid.Rows.Count > nrows) + grid.Rows.RemoveAt(grid.Rows.GetLastRow(DataGridViewElementStates.Displayed)); + } + + /// + /// Copies the selected area to clipboard + /// + public static void CopySelected(DataGridView grid) + { + int minRow, minCol, maxRow, maxCol; + minRow = minCol = int.MaxValue; + maxRow = maxCol = int.MinValue; + + foreach (DataGridViewCell i in grid.SelectedCells) + { + minRow = Math.Min(minRow, i.RowIndex); + minCol = Math.Min(minCol, i.ColumnIndex); + maxRow = Math.Max(maxRow, i.RowIndex); + maxCol = Math.Max(maxCol, i.ColumnIndex); + } + + string csv = CsvParser.ToCSV(grid, minRow, minCol, maxRow, maxCol, true); + Clipboard.SetText(csv, TextDataFormat.CommaSeparatedValue); + } + + /// + /// Pastes clipboard content into selected cell and beyond + /// + public static void Paste(DataGridView grid) + { + // Where to paste + int row = 0, col = 0; + if (grid.CurrentCell != null) { + row = grid.CurrentCell.RowIndex; + col = grid.CurrentCell.ColumnIndex; + } + + // Get data + string data = ""; + if (Clipboard.ContainsText(TextDataFormat.CommaSeparatedValue)) data = Clipboard.GetText(TextDataFormat.CommaSeparatedValue); + else if (Clipboard.ContainsText()) data = Clipboard.GetText(); + + var table = CsvParser.GetTable(data, MatrixCalculator.Properties.Settings.Default.InternalCsvSeparators.ToArray()); + + // Put data in table + for (int i = 0; i < table.Rows.Count; i++) + for (int j = 0; j < table.Columns.Count; j++) + if (table.Rows[i][j].ToString() != "" && row + i < grid.Rows.Count && col + j < grid.Columns.Count) + grid[j + col, i + row].Value = table.Rows[i][j]; + } + } +} diff --git a/Source/MatrixCalculator/Helpers/MatrixConverter.cs b/Source/MatrixCalculator/Helpers/MatrixConverter.cs new file mode 100644 index 0000000..89722d4 --- /dev/null +++ b/Source/MatrixCalculator/Helpers/MatrixConverter.cs @@ -0,0 +1,51 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Data; +using MathNet.Numerics.LinearAlgebra; + +namespace MatrixCalculator +{ + static class MatrixConverter + { + /// + /// Puts a matrix in a DataTable + /// + public static DataTable GetTable(Matrix matrix) + { + DataTable table = new DataTable("matrix"); + + for (int i = 0; i < matrix.ColumnCount; i++) + table.Columns.Add(); + + for (int i = 0; i < matrix.RowCount; i++) + { + table.Rows.Add(""); + + for (int j = 0; j < matrix.ColumnCount; j++) + table.Rows[i][j] = matrix[i, j].ToString(); + } + + return table; + } + + /// + /// Converts a DataTable into a matrix + /// + public static Matrix FromTable(DataTable table) + { + Matrix matrix = Matrix.Build.Dense(table.Rows.Count, table.Columns.Count); + + for (int i = 0; i < matrix.RowCount; i++) + for (int j = 0; j < matrix.ColumnCount; j++) + { + double temp = 0; + double.TryParse(table.Rows[i][j].ToString(), out temp); + matrix[i, j] = temp; + } + + return matrix; + } + } +} diff --git a/Source/MatrixCalculator/Helpers/MatrixHelper.cs b/Source/MatrixCalculator/Helpers/MatrixHelper.cs new file mode 100644 index 0000000..884005f --- /dev/null +++ b/Source/MatrixCalculator/Helpers/MatrixHelper.cs @@ -0,0 +1,65 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using MathNet.Numerics.LinearAlgebra; + +namespace MatrixCalculator +{ + static class MatrixHelper + { + public static bool Equal(Matrix a, Matrix b) + { + if (a.RowCount != b.RowCount || a.ColumnCount != b.ColumnCount) return false; + + for (int i = 0; i < a.RowCount; i++) + for (int j = 0; j < a.ColumnCount; j++) + if (a[i, j] != b[i, j]) return false; + + return true; + } + + public static Matrix Power(Matrix mat, int power) + { + // Solution + Matrix sol = Matrix.Build.DenseIdentity(mat.RowCount, mat.ColumnCount); + + if (power < 0) { + mat = mat.Inverse(); + power *= -1; + } + + // Now raise to power binary + for (int i = 0; (1 << i) <= power; i++) + { + if ((power & (1 << i)) != 0) sol = (sol * mat); + mat = (mat * mat); + } + + // Done + return sol; + } + + public static double Max(Matrix mat) + { + double max = double.MinValue; + + for (int i = 0; i < mat.RowCount; i++) + for (int j = 0; j < mat.ColumnCount; j++) + max = Math.Max(mat[i, j], max); + + return max; + } + + public static double Min(Matrix mat) + { + double min = double.MaxValue; + + for (int i = 0; i < mat.RowCount; i++) + for (int j = 0; j < mat.ColumnCount; j++) + min = Math.Min(mat[i, j], min); + + return min; + } + } +} diff --git a/Source/MatrixCalculator/Helpers/MyDouble.cs b/Source/MatrixCalculator/Helpers/MyDouble.cs new file mode 100644 index 0000000..c564390 --- /dev/null +++ b/Source/MatrixCalculator/Helpers/MyDouble.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace MatrixCalculator +{ + static class MyDouble + { + public static string String(double n) + { + if (MatrixCalculator.Properties.Settings.Default.DoublePrecision == -1) return n.ToString(); + else return Math.Round(n, MatrixCalculator.Properties.Settings.Default.DoublePrecision).ToString(); + } + } +} diff --git a/Source/MatrixCalculator/MainWindow.Designer.cs b/Source/MatrixCalculator/MainWindow.Designer.cs new file mode 100644 index 0000000..b3397b6 --- /dev/null +++ b/Source/MatrixCalculator/MainWindow.Designer.cs @@ -0,0 +1,1134 @@ +namespace MatrixCalculator +{ + partial class MainWindow + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainWindow)); + this.menuStrip = new System.Windows.Forms.MenuStrip(); + this.menuFile = new System.Windows.Forms.ToolStripMenuItem(); + this.menuFileNew = new System.Windows.Forms.ToolStripMenuItem(); + this.menuFileOpen = new System.Windows.Forms.ToolStripMenuItem(); + this.menuFileSave = new System.Windows.Forms.ToolStripMenuItem(); + this.menuFileSaveAs = new System.Windows.Forms.ToolStripMenuItem(); + this.menuSeparator1 = new System.Windows.Forms.ToolStripSeparator(); + this.menuFileImport = new System.Windows.Forms.ToolStripMenuItem(); + this.menuFileImportCsv = new System.Windows.Forms.ToolStripMenuItem(); + this.menuFileImportWorksheet = new System.Windows.Forms.ToolStripMenuItem(); + this.menuSeparator2 = new System.Windows.Forms.ToolStripSeparator(); + this.menuFilePreferences = new System.Windows.Forms.ToolStripMenuItem(); + this.menuFileExit = new System.Windows.Forms.ToolStripMenuItem(); + this.menuMatrix = new System.Windows.Forms.ToolStripMenuItem(); + this.menuMatrixNew = new System.Windows.Forms.ToolStripMenuItem(); + this.menuMatrixEdit = new System.Windows.Forms.ToolStripMenuItem(); + this.menuMatrixDelete = new System.Windows.Forms.ToolStripMenuItem(); + this.menuMatrixDuplicate = new System.Windows.Forms.ToolStripMenuItem(); + this.menuSeparator4 = new System.Windows.Forms.ToolStripSeparator(); + this.menuMatrixInsertA = new System.Windows.Forms.ToolStripMenuItem(); + this.menuMatrixInsertB = new System.Windows.Forms.ToolStripMenuItem(); + this.menuSeparator3 = new System.Windows.Forms.ToolStripSeparator(); + this.menuMatrixCopy = new System.Windows.Forms.ToolStripMenuItem(); + this.menuMatrixPaste = new System.Windows.Forms.ToolStripMenuItem(); + this.menuMatrixPasteSpecial = new System.Windows.Forms.ToolStripMenuItem(); + this.menuHelp = new System.Windows.Forms.ToolStripMenuItem(); + this.menuHelpAbout = new System.Windows.Forms.ToolStripMenuItem(); + this.menuHelpHelp = new System.Windows.Forms.ToolStripMenuItem(); + this.layoutSplitMain = new System.Windows.Forms.SplitContainer(); + this.layoutSplitSide = new System.Windows.Forms.SplitContainer(); + this.groupBoxMatrices = new DynamicLink.Controls.MyGroupBox(); + this.listMatrices = new System.Windows.Forms.ListView(); + this.listMatricesColName = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.listMatricesColDesc = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.contextList = new System.Windows.Forms.ContextMenuStrip(this.components); + this.contextMenuListNew = new System.Windows.Forms.ToolStripMenuItem(); + this.contextMenuListEdit = new System.Windows.Forms.ToolStripMenuItem(); + this.contextMenuListDelete = new System.Windows.Forms.ToolStripMenuItem(); + this.contextMenuListDuplicate = new System.Windows.Forms.ToolStripMenuItem(); + this.contextMenuListSeparator1 = new System.Windows.Forms.ToolStripSeparator(); + this.contextMenuListInsertA = new System.Windows.Forms.ToolStripMenuItem(); + this.contextMenuListInsertB = new System.Windows.Forms.ToolStripMenuItem(); + this.contextMenuListSeparator2 = new System.Windows.Forms.ToolStripSeparator(); + this.contextMenuListCopy = new System.Windows.Forms.ToolStripMenuItem(); + this.contextMenuListPaste = new System.Windows.Forms.ToolStripMenuItem(); + this.contextMenuListPasteSpecial = new System.Windows.Forms.ToolStripMenuItem(); + this.groupBoxPreview = new DynamicLink.Controls.MyGroupBox(); + this.labelPreviewDesc = new System.Windows.Forms.Label(); + this.labelPreviewName = new System.Windows.Forms.Label(); + this.dataPreview = new System.Windows.Forms.DataGridView(); + this.layoutTableCalcArea = new System.Windows.Forms.TableLayoutPanel(); + this.groupBoxMatrixA = new DynamicLink.Controls.MyGroupBox(); + this.dataMatrixA = new System.Windows.Forms.DataGridView(); + this.contextData = new System.Windows.Forms.ContextMenuStrip(this.components); + this.contextMenuDataAdd = new System.Windows.Forms.ToolStripMenuItem(); + this.contextMenuDataClear = new System.Windows.Forms.ToolStripMenuItem(); + this.contextMenuDataCopy = new System.Windows.Forms.ToolStripMenuItem(); + this.groupBoxMatrixB = new DynamicLink.Controls.MyGroupBox(); + this.dataMatrixB = new System.Windows.Forms.DataGridView(); + this.groupBoxResult = new DynamicLink.Controls.MyGroupBox(); + this.dataResult = new System.Windows.Forms.DataGridView(); + this.groupBoxOperations = new DynamicLink.Controls.MyGroupBox(); + this.layoutTableButtons = new System.Windows.Forms.TableLayoutPanel(); + this.buttonMax = new DynamicLink.Controls.MyButton(); + this.buttonAdd = new DynamicLink.Controls.MyButton(); + this.buttonMin = new DynamicLink.Controls.MyButton(); + this.buttonDet = new DynamicLink.Controls.MyButton(); + this.buttonTrace = new DynamicLink.Controls.MyButton(); + this.buttonRank = new DynamicLink.Controls.MyButton(); + this.buttonTransp = new DynamicLink.Controls.MyButton(); + this.buttonPow = new DynamicLink.Controls.MyButton(); + this.buttonMulNum = new DynamicLink.Controls.MyButton(); + this.buttonSubNum = new DynamicLink.Controls.MyButton(); + this.buttonAddNum = new DynamicLink.Controls.MyButton(); + this.buttonInv = new DynamicLink.Controls.MyButton(); + this.buttonMul = new DynamicLink.Controls.MyButton(); + this.buttonSub = new DynamicLink.Controls.MyButton(); + this.labelOutput = new System.Windows.Forms.Label(); + this.textOutput = new System.Windows.Forms.TextBox(); + this.toolTip = new System.Windows.Forms.ToolTip(this.components); + this.menuStrip.SuspendLayout(); + this.layoutSplitMain.Panel1.SuspendLayout(); + this.layoutSplitMain.Panel2.SuspendLayout(); + this.layoutSplitMain.SuspendLayout(); + this.layoutSplitSide.Panel1.SuspendLayout(); + this.layoutSplitSide.Panel2.SuspendLayout(); + this.layoutSplitSide.SuspendLayout(); + this.groupBoxMatrices.SuspendLayout(); + this.contextList.SuspendLayout(); + this.groupBoxPreview.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.dataPreview)).BeginInit(); + this.layoutTableCalcArea.SuspendLayout(); + this.groupBoxMatrixA.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.dataMatrixA)).BeginInit(); + this.contextData.SuspendLayout(); + this.groupBoxMatrixB.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.dataMatrixB)).BeginInit(); + this.groupBoxResult.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.dataResult)).BeginInit(); + this.groupBoxOperations.SuspendLayout(); + this.layoutTableButtons.SuspendLayout(); + this.SuspendLayout(); + // + // menuStrip + // + this.menuStrip.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(242)))), ((int)(((byte)(242)))), ((int)(((byte)(242))))); + this.menuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.menuFile, + this.menuMatrix, + this.menuHelp}); + this.menuStrip.Location = new System.Drawing.Point(0, 0); + this.menuStrip.Name = "menuStrip"; + this.menuStrip.Size = new System.Drawing.Size(728, 24); + this.menuStrip.TabIndex = 0; + this.menuStrip.Text = "menuStrip1"; + // + // menuFile + // + this.menuFile.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.menuFileNew, + this.menuFileOpen, + this.menuFileSave, + this.menuFileSaveAs, + this.menuSeparator1, + this.menuFileImport, + this.menuSeparator2, + this.menuFilePreferences, + this.menuFileExit}); + this.menuFile.Name = "menuFile"; + this.menuFile.Size = new System.Drawing.Size(37, 20); + this.menuFile.Text = "&File"; + // + // menuFileNew + // + this.menuFileNew.Image = global::MatrixCalculator.Properties.Resources.page_white_add; + this.menuFileNew.Name = "menuFileNew"; + this.menuFileNew.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.N))); + this.menuFileNew.Size = new System.Drawing.Size(198, 22); + this.menuFileNew.Text = "&New worksheet"; + this.menuFileNew.Click += new System.EventHandler(this.menuFileNew_Click); + // + // menuFileOpen + // + this.menuFileOpen.Image = global::MatrixCalculator.Properties.Resources.folder_page_white; + this.menuFileOpen.Name = "menuFileOpen"; + this.menuFileOpen.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.O))); + this.menuFileOpen.Size = new System.Drawing.Size(198, 22); + this.menuFileOpen.Text = "&Open..."; + this.menuFileOpen.Click += new System.EventHandler(this.menuFileOpen_Click); + // + // menuFileSave + // + this.menuFileSave.Image = global::MatrixCalculator.Properties.Resources.page_save; + this.menuFileSave.Name = "menuFileSave"; + this.menuFileSave.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.S))); + this.menuFileSave.Size = new System.Drawing.Size(198, 22); + this.menuFileSave.Text = "&Save"; + this.menuFileSave.Click += new System.EventHandler(this.menuFileSave_Click); + // + // menuFileSaveAs + // + this.menuFileSaveAs.Name = "menuFileSaveAs"; + this.menuFileSaveAs.ShortcutKeys = ((System.Windows.Forms.Keys)(((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Shift) + | System.Windows.Forms.Keys.S))); + this.menuFileSaveAs.Size = new System.Drawing.Size(198, 22); + this.menuFileSaveAs.Text = "Save &as..."; + this.menuFileSaveAs.Click += new System.EventHandler(this.menuFileSaveAs_Click); + // + // menuSeparator1 + // + this.menuSeparator1.Name = "menuSeparator1"; + this.menuSeparator1.Size = new System.Drawing.Size(195, 6); + // + // menuFileImport + // + this.menuFileImport.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.menuFileImportCsv, + this.menuFileImportWorksheet}); + this.menuFileImport.Name = "menuFileImport"; + this.menuFileImport.Size = new System.Drawing.Size(198, 22); + this.menuFileImport.Text = "&Import"; + // + // menuFileImportCsv + // + this.menuFileImportCsv.Name = "menuFileImportCsv"; + this.menuFileImportCsv.Size = new System.Drawing.Size(212, 22); + this.menuFileImportCsv.Text = "From &csv file..."; + this.menuFileImportCsv.Click += new System.EventHandler(this.menuFileImportCsv_Click); + // + // menuFileImportWorksheet + // + this.menuFileImportWorksheet.Name = "menuFileImportWorksheet"; + this.menuFileImportWorksheet.Size = new System.Drawing.Size(212, 22); + this.menuFileImportWorksheet.Text = "From another &worksheet..."; + this.menuFileImportWorksheet.Click += new System.EventHandler(this.menuFileImportWorksheet_Click); + // + // menuSeparator2 + // + this.menuSeparator2.Name = "menuSeparator2"; + this.menuSeparator2.Size = new System.Drawing.Size(195, 6); + // + // menuFilePreferences + // + this.menuFilePreferences.Image = global::MatrixCalculator.Properties.Resources.wrench_orange; + this.menuFilePreferences.Name = "menuFilePreferences"; + this.menuFilePreferences.Size = new System.Drawing.Size(198, 22); + this.menuFilePreferences.Text = "&Preferences"; + this.menuFilePreferences.Click += new System.EventHandler(this.menuFilePreferences_Click); + // + // menuFileExit + // + this.menuFileExit.Image = global::MatrixCalculator.Properties.Resources.door_out; + this.menuFileExit.Name = "menuFileExit"; + this.menuFileExit.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Q))); + this.menuFileExit.Size = new System.Drawing.Size(198, 22); + this.menuFileExit.Text = "E&xit"; + this.menuFileExit.Click += new System.EventHandler(this.menuFileExit_Click); + // + // menuMatrix + // + this.menuMatrix.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.menuMatrixNew, + this.menuMatrixEdit, + this.menuMatrixDelete, + this.menuMatrixDuplicate, + this.menuSeparator4, + this.menuMatrixInsertA, + this.menuMatrixInsertB, + this.menuSeparator3, + this.menuMatrixCopy, + this.menuMatrixPaste, + this.menuMatrixPasteSpecial}); + this.menuMatrix.Name = "menuMatrix"; + this.menuMatrix.Size = new System.Drawing.Size(52, 20); + this.menuMatrix.Text = "&Matrix"; + // + // menuMatrixNew + // + this.menuMatrixNew.Image = global::MatrixCalculator.Properties.Resources.table_add; + this.menuMatrixNew.Name = "menuMatrixNew"; + this.menuMatrixNew.ShortcutKeys = ((System.Windows.Forms.Keys)(((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Shift) + | System.Windows.Forms.Keys.N))); + this.menuMatrixNew.Size = new System.Drawing.Size(223, 22); + this.menuMatrixNew.Text = "&New matrix..."; + this.menuMatrixNew.Click += new System.EventHandler(this.menuMatrixNew_Click); + // + // menuMatrixEdit + // + this.menuMatrixEdit.Image = global::MatrixCalculator.Properties.Resources.table_edit; + this.menuMatrixEdit.Name = "menuMatrixEdit"; + this.menuMatrixEdit.ShortcutKeys = ((System.Windows.Forms.Keys)(((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Shift) + | System.Windows.Forms.Keys.E))); + this.menuMatrixEdit.Size = new System.Drawing.Size(223, 22); + this.menuMatrixEdit.Text = "&Edit selected..."; + this.menuMatrixEdit.Click += new System.EventHandler(this.menuMatrixEdit_Click); + // + // menuMatrixDelete + // + this.menuMatrixDelete.Image = global::MatrixCalculator.Properties.Resources.table_delete; + this.menuMatrixDelete.Name = "menuMatrixDelete"; + this.menuMatrixDelete.ShortcutKeys = System.Windows.Forms.Keys.Delete; + this.menuMatrixDelete.Size = new System.Drawing.Size(223, 22); + this.menuMatrixDelete.Text = "De&lete selected"; + this.menuMatrixDelete.Click += new System.EventHandler(this.menuMatrixDelete_Click); + // + // menuMatrixDuplicate + // + this.menuMatrixDuplicate.Name = "menuMatrixDuplicate"; + this.menuMatrixDuplicate.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.D))); + this.menuMatrixDuplicate.Size = new System.Drawing.Size(223, 22); + this.menuMatrixDuplicate.Text = "&Duplicate selected..."; + this.menuMatrixDuplicate.Click += new System.EventHandler(this.menuMatrixDuplicate_Click); + // + // menuSeparator4 + // + this.menuSeparator4.Name = "menuSeparator4"; + this.menuSeparator4.Size = new System.Drawing.Size(220, 6); + // + // menuMatrixInsertA + // + this.menuMatrixInsertA.Name = "menuMatrixInsertA"; + this.menuMatrixInsertA.ShortcutKeys = ((System.Windows.Forms.Keys)(((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Alt) + | System.Windows.Forms.Keys.A))); + this.menuMatrixInsertA.Size = new System.Drawing.Size(223, 22); + this.menuMatrixInsertA.Text = "Insert in slot &A"; + this.menuMatrixInsertA.Click += new System.EventHandler(this.menuMatrixInsertA_Click); + // + // menuMatrixInsertB + // + this.menuMatrixInsertB.Name = "menuMatrixInsertB"; + this.menuMatrixInsertB.ShortcutKeys = ((System.Windows.Forms.Keys)(((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Alt) + | System.Windows.Forms.Keys.B))); + this.menuMatrixInsertB.Size = new System.Drawing.Size(223, 22); + this.menuMatrixInsertB.Text = "Insert in slot &B"; + this.menuMatrixInsertB.Click += new System.EventHandler(this.menuMatrixInsertB_Click); + // + // menuSeparator3 + // + this.menuSeparator3.Name = "menuSeparator3"; + this.menuSeparator3.Size = new System.Drawing.Size(220, 6); + // + // menuMatrixCopy + // + this.menuMatrixCopy.Image = global::MatrixCalculator.Properties.Resources.page_white_copy; + this.menuMatrixCopy.Name = "menuMatrixCopy"; + this.menuMatrixCopy.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.C))); + this.menuMatrixCopy.Size = new System.Drawing.Size(223, 22); + this.menuMatrixCopy.Text = "&Copy"; + this.menuMatrixCopy.Click += new System.EventHandler(this.menuMatrixCopy_Click); + // + // menuMatrixPaste + // + this.menuMatrixPaste.Image = global::MatrixCalculator.Properties.Resources.page_white_paste; + this.menuMatrixPaste.Name = "menuMatrixPaste"; + this.menuMatrixPaste.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.V))); + this.menuMatrixPaste.Size = new System.Drawing.Size(223, 22); + this.menuMatrixPaste.Text = "&Paste"; + this.menuMatrixPaste.Click += new System.EventHandler(this.menuMatrixPaste_Click); + // + // menuMatrixPasteSpecial + // + this.menuMatrixPasteSpecial.Name = "menuMatrixPasteSpecial"; + this.menuMatrixPasteSpecial.ShortcutKeys = ((System.Windows.Forms.Keys)(((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Shift) + | System.Windows.Forms.Keys.V))); + this.menuMatrixPasteSpecial.Size = new System.Drawing.Size(223, 22); + this.menuMatrixPasteSpecial.Text = "Paste &special..."; + this.menuMatrixPasteSpecial.Click += new System.EventHandler(this.menuMatrixPasteSpecial_Click); + // + // menuHelp + // + this.menuHelp.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.menuHelpAbout, + this.menuHelpHelp}); + this.menuHelp.Name = "menuHelp"; + this.menuHelp.Size = new System.Drawing.Size(44, 20); + this.menuHelp.Text = "&Help"; + // + // menuHelpAbout + // + this.menuHelpAbout.Name = "menuHelpAbout"; + this.menuHelpAbout.Size = new System.Drawing.Size(118, 22); + this.menuHelpAbout.Text = "&About"; + this.menuHelpAbout.Click += new System.EventHandler(this.menuHelpAbout_Click); + // + // menuHelpHelp + // + this.menuHelpHelp.Image = global::MatrixCalculator.Properties.Resources.help; + this.menuHelpHelp.Name = "menuHelpHelp"; + this.menuHelpHelp.ShortcutKeys = System.Windows.Forms.Keys.F1; + this.menuHelpHelp.Size = new System.Drawing.Size(118, 22); + this.menuHelpHelp.Text = "&Help"; + this.menuHelpHelp.Click += new System.EventHandler(this.menuHelpHelp_Click); + // + // layoutSplitMain + // + this.layoutSplitMain.BackColor = System.Drawing.Color.Transparent; + this.layoutSplitMain.Dock = System.Windows.Forms.DockStyle.Fill; + this.layoutSplitMain.Location = new System.Drawing.Point(0, 24); + this.layoutSplitMain.Name = "layoutSplitMain"; + // + // layoutSplitMain.Panel1 + // + this.layoutSplitMain.Panel1.Controls.Add(this.layoutSplitSide); + // + // layoutSplitMain.Panel2 + // + this.layoutSplitMain.Panel2.Controls.Add(this.layoutTableCalcArea); + this.layoutSplitMain.Size = new System.Drawing.Size(728, 388); + this.layoutSplitMain.SplitterDistance = 230; + this.layoutSplitMain.TabIndex = 1; + // + // layoutSplitSide + // + this.layoutSplitSide.Dock = System.Windows.Forms.DockStyle.Fill; + this.layoutSplitSide.Location = new System.Drawing.Point(0, 0); + this.layoutSplitSide.Name = "layoutSplitSide"; + this.layoutSplitSide.Orientation = System.Windows.Forms.Orientation.Horizontal; + // + // layoutSplitSide.Panel1 + // + this.layoutSplitSide.Panel1.Controls.Add(this.groupBoxMatrices); + this.layoutSplitSide.Panel1.Padding = new System.Windows.Forms.Padding(3); + // + // layoutSplitSide.Panel2 + // + this.layoutSplitSide.Panel2.Controls.Add(this.groupBoxPreview); + this.layoutSplitSide.Panel2.Padding = new System.Windows.Forms.Padding(3); + this.layoutSplitSide.Size = new System.Drawing.Size(230, 388); + this.layoutSplitSide.SplitterDistance = 168; + this.layoutSplitSide.TabIndex = 0; + // + // groupBoxMatrices + // + this.groupBoxMatrices.Controls.Add(this.listMatrices); + this.groupBoxMatrices.Dock = System.Windows.Forms.DockStyle.Fill; + this.groupBoxMatrices.Location = new System.Drawing.Point(3, 3); + this.groupBoxMatrices.Name = "groupBoxMatrices"; + this.groupBoxMatrices.Padding = new System.Windows.Forms.Padding(3, 8, 3, 3); + this.groupBoxMatrices.Size = new System.Drawing.Size(224, 162); + this.groupBoxMatrices.TabIndex = 0; + this.groupBoxMatrices.TabStop = false; + this.groupBoxMatrices.Text = "Matrices"; + // + // listMatrices + // + this.listMatrices.AllowDrop = true; + this.listMatrices.AutoArrange = false; + this.listMatrices.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { + this.listMatricesColName, + this.listMatricesColDesc}); + this.listMatrices.ContextMenuStrip = this.contextList; + this.listMatrices.Dock = System.Windows.Forms.DockStyle.Fill; + this.listMatrices.FullRowSelect = true; + this.listMatrices.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.Nonclickable; + this.listMatrices.HoverSelection = true; + this.listMatrices.Location = new System.Drawing.Point(3, 21); + this.listMatrices.MultiSelect = false; + this.listMatrices.Name = "listMatrices"; + this.listMatrices.Size = new System.Drawing.Size(218, 138); + this.listMatrices.TabIndex = 2; + this.listMatrices.UseCompatibleStateImageBehavior = false; + this.listMatrices.View = System.Windows.Forms.View.Details; + this.listMatrices.SelectedIndexChanged += new System.EventHandler(this.listMatrices_SelectedIndexChanged); + this.listMatrices.DragOver += new System.Windows.Forms.DragEventHandler(this.listMatrices_DragOver); + this.listMatrices.MouseDown += new System.Windows.Forms.MouseEventHandler(this.listMatrices_MouseDown); + // + // listMatricesColName + // + this.listMatricesColName.Text = "Name"; + this.listMatricesColName.Width = 95; + // + // listMatricesColDesc + // + this.listMatricesColDesc.Text = "Description"; + this.listMatricesColDesc.Width = 118; + // + // contextList + // + this.contextList.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.contextMenuListNew, + this.contextMenuListEdit, + this.contextMenuListDelete, + this.contextMenuListDuplicate, + this.contextMenuListSeparator1, + this.contextMenuListInsertA, + this.contextMenuListInsertB, + this.contextMenuListSeparator2, + this.contextMenuListCopy, + this.contextMenuListPaste, + this.contextMenuListPasteSpecial}); + this.contextList.Name = "contextList"; + this.contextList.Size = new System.Drawing.Size(180, 214); + // + // contextMenuListNew + // + this.contextMenuListNew.Image = global::MatrixCalculator.Properties.Resources.table_add; + this.contextMenuListNew.Name = "contextMenuListNew"; + this.contextMenuListNew.Size = new System.Drawing.Size(179, 22); + this.contextMenuListNew.Text = "&New matrix..."; + this.contextMenuListNew.Click += new System.EventHandler(this.menuMatrixNew_Click); + // + // contextMenuListEdit + // + this.contextMenuListEdit.Image = global::MatrixCalculator.Properties.Resources.table_edit; + this.contextMenuListEdit.Name = "contextMenuListEdit"; + this.contextMenuListEdit.Size = new System.Drawing.Size(179, 22); + this.contextMenuListEdit.Text = "&Edit selected..."; + this.contextMenuListEdit.Click += new System.EventHandler(this.menuMatrixEdit_Click); + // + // contextMenuListDelete + // + this.contextMenuListDelete.Image = global::MatrixCalculator.Properties.Resources.table_delete; + this.contextMenuListDelete.Name = "contextMenuListDelete"; + this.contextMenuListDelete.Size = new System.Drawing.Size(179, 22); + this.contextMenuListDelete.Text = "De&lete selected"; + this.contextMenuListDelete.Click += new System.EventHandler(this.menuMatrixDelete_Click); + // + // contextMenuListDuplicate + // + this.contextMenuListDuplicate.Name = "contextMenuListDuplicate"; + this.contextMenuListDuplicate.Size = new System.Drawing.Size(179, 22); + this.contextMenuListDuplicate.Text = "&Duplicate selected..."; + this.contextMenuListDuplicate.Click += new System.EventHandler(this.menuMatrixDuplicate_Click); + // + // contextMenuListSeparator1 + // + this.contextMenuListSeparator1.Name = "contextMenuListSeparator1"; + this.contextMenuListSeparator1.Size = new System.Drawing.Size(176, 6); + // + // contextMenuListInsertA + // + this.contextMenuListInsertA.Name = "contextMenuListInsertA"; + this.contextMenuListInsertA.Size = new System.Drawing.Size(179, 22); + this.contextMenuListInsertA.Text = "Insert in slot &A"; + this.contextMenuListInsertA.Click += new System.EventHandler(this.menuMatrixInsertA_Click); + // + // contextMenuListInsertB + // + this.contextMenuListInsertB.Name = "contextMenuListInsertB"; + this.contextMenuListInsertB.Size = new System.Drawing.Size(179, 22); + this.contextMenuListInsertB.Text = "Insert in slot &B"; + this.contextMenuListInsertB.Click += new System.EventHandler(this.menuMatrixInsertB_Click); + // + // contextMenuListSeparator2 + // + this.contextMenuListSeparator2.Name = "contextMenuListSeparator2"; + this.contextMenuListSeparator2.Size = new System.Drawing.Size(176, 6); + // + // contextMenuListCopy + // + this.contextMenuListCopy.Image = global::MatrixCalculator.Properties.Resources.page_white_copy; + this.contextMenuListCopy.Name = "contextMenuListCopy"; + this.contextMenuListCopy.Size = new System.Drawing.Size(179, 22); + this.contextMenuListCopy.Text = "&Copy"; + this.contextMenuListCopy.Click += new System.EventHandler(this.menuMatrixCopy_Click); + // + // contextMenuListPaste + // + this.contextMenuListPaste.Image = global::MatrixCalculator.Properties.Resources.page_white_paste; + this.contextMenuListPaste.Name = "contextMenuListPaste"; + this.contextMenuListPaste.Size = new System.Drawing.Size(179, 22); + this.contextMenuListPaste.Text = "&Paste"; + this.contextMenuListPaste.Click += new System.EventHandler(this.menuMatrixPaste_Click); + // + // contextMenuListPasteSpecial + // + this.contextMenuListPasteSpecial.Name = "contextMenuListPasteSpecial"; + this.contextMenuListPasteSpecial.Size = new System.Drawing.Size(179, 22); + this.contextMenuListPasteSpecial.Text = "Paste &special..."; + this.contextMenuListPasteSpecial.Click += new System.EventHandler(this.menuMatrixPasteSpecial_Click); + // + // groupBoxPreview + // + this.groupBoxPreview.Controls.Add(this.labelPreviewDesc); + this.groupBoxPreview.Controls.Add(this.labelPreviewName); + this.groupBoxPreview.Controls.Add(this.dataPreview); + this.groupBoxPreview.Dock = System.Windows.Forms.DockStyle.Fill; + this.groupBoxPreview.Location = new System.Drawing.Point(3, 3); + this.groupBoxPreview.Name = "groupBoxPreview"; + this.groupBoxPreview.Padding = new System.Windows.Forms.Padding(3, 8, 3, 3); + this.groupBoxPreview.Size = new System.Drawing.Size(224, 210); + this.groupBoxPreview.TabIndex = 0; + this.groupBoxPreview.TabStop = false; + this.groupBoxPreview.Text = "Preview"; + // + // labelPreviewDesc + // + this.labelPreviewDesc.AutoSize = true; + this.labelPreviewDesc.Location = new System.Drawing.Point(6, 38); + this.labelPreviewDesc.Name = "labelPreviewDesc"; + this.labelPreviewDesc.Size = new System.Drawing.Size(86, 13); + this.labelPreviewDesc.TabIndex = 5; + this.labelPreviewDesc.Text = "Description: N/A"; + // + // labelPreviewName + // + this.labelPreviewName.AutoSize = true; + this.labelPreviewName.Location = new System.Drawing.Point(6, 21); + this.labelPreviewName.Name = "labelPreviewName"; + this.labelPreviewName.Size = new System.Drawing.Size(61, 13); + this.labelPreviewName.TabIndex = 4; + this.labelPreviewName.Text = "Name: N/A"; + // + // dataPreview + // + this.dataPreview.AllowUserToAddRows = false; + this.dataPreview.AllowUserToDeleteRows = false; + this.dataPreview.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.dataPreview.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize; + this.dataPreview.ColumnHeadersVisible = false; + this.dataPreview.EditMode = System.Windows.Forms.DataGridViewEditMode.EditProgrammatically; + this.dataPreview.Location = new System.Drawing.Point(3, 54); + this.dataPreview.Name = "dataPreview"; + this.dataPreview.ReadOnly = true; + this.dataPreview.RowHeadersVisible = false; + this.dataPreview.Size = new System.Drawing.Size(218, 154); + this.dataPreview.TabIndex = 3; + // + // layoutTableCalcArea + // + this.layoutTableCalcArea.ColumnCount = 2; + this.layoutTableCalcArea.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F)); + this.layoutTableCalcArea.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F)); + this.layoutTableCalcArea.Controls.Add(this.groupBoxMatrixA, 0, 0); + this.layoutTableCalcArea.Controls.Add(this.groupBoxMatrixB, 1, 0); + this.layoutTableCalcArea.Controls.Add(this.groupBoxResult, 1, 1); + this.layoutTableCalcArea.Controls.Add(this.groupBoxOperations, 0, 1); + this.layoutTableCalcArea.Dock = System.Windows.Forms.DockStyle.Fill; + this.layoutTableCalcArea.Location = new System.Drawing.Point(0, 0); + this.layoutTableCalcArea.Name = "layoutTableCalcArea"; + this.layoutTableCalcArea.RowCount = 2; + this.layoutTableCalcArea.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F)); + this.layoutTableCalcArea.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F)); + this.layoutTableCalcArea.Size = new System.Drawing.Size(494, 388); + this.layoutTableCalcArea.TabIndex = 0; + // + // groupBoxMatrixA + // + this.groupBoxMatrixA.Controls.Add(this.dataMatrixA); + this.groupBoxMatrixA.Dock = System.Windows.Forms.DockStyle.Fill; + this.groupBoxMatrixA.Location = new System.Drawing.Point(3, 3); + this.groupBoxMatrixA.Name = "groupBoxMatrixA"; + this.groupBoxMatrixA.Padding = new System.Windows.Forms.Padding(3, 8, 3, 3); + this.groupBoxMatrixA.Size = new System.Drawing.Size(241, 188); + this.groupBoxMatrixA.TabIndex = 5; + this.groupBoxMatrixA.TabStop = false; + this.groupBoxMatrixA.Text = "Matrix A"; + // + // dataMatrixA + // + this.dataMatrixA.AllowDrop = true; + this.dataMatrixA.AllowUserToAddRows = false; + this.dataMatrixA.AllowUserToDeleteRows = false; + this.dataMatrixA.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize; + this.dataMatrixA.ColumnHeadersVisible = false; + this.dataMatrixA.ContextMenuStrip = this.contextData; + this.dataMatrixA.Dock = System.Windows.Forms.DockStyle.Fill; + this.dataMatrixA.EditMode = System.Windows.Forms.DataGridViewEditMode.EditProgrammatically; + this.dataMatrixA.Location = new System.Drawing.Point(3, 21); + this.dataMatrixA.Name = "dataMatrixA"; + this.dataMatrixA.ReadOnly = true; + this.dataMatrixA.RowHeadersVisible = false; + this.dataMatrixA.Size = new System.Drawing.Size(235, 164); + this.dataMatrixA.TabIndex = 9; + this.dataMatrixA.DragDrop += new System.Windows.Forms.DragEventHandler(this.dataMatrix_DragDrop); + this.dataMatrixA.DragEnter += new System.Windows.Forms.DragEventHandler(this.dataMatrix_DragEnter); + // + // contextData + // + this.contextData.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.contextMenuDataAdd, + this.contextMenuDataClear, + this.contextMenuDataCopy}); + this.contextData.Name = "contextData"; + this.contextData.Size = new System.Drawing.Size(174, 70); + // + // contextMenuDataAdd + // + this.contextMenuDataAdd.Image = global::MatrixCalculator.Properties.Resources.table_add; + this.contextMenuDataAdd.Name = "contextMenuDataAdd"; + this.contextMenuDataAdd.Size = new System.Drawing.Size(173, 22); + this.contextMenuDataAdd.Text = "&Add matrix to list..."; + this.contextMenuDataAdd.Click += new System.EventHandler(this.contextMenuDataAdd_Click); + // + // contextMenuDataClear + // + this.contextMenuDataClear.Image = global::MatrixCalculator.Properties.Resources.Gnome_Edit_Clear_16; + this.contextMenuDataClear.Name = "contextMenuDataClear"; + this.contextMenuDataClear.Size = new System.Drawing.Size(173, 22); + this.contextMenuDataClear.Text = "C&lear"; + this.contextMenuDataClear.Click += new System.EventHandler(this.contextMenuDataClear_Click); + // + // contextMenuDataCopy + // + this.contextMenuDataCopy.Image = global::MatrixCalculator.Properties.Resources.page_white_copy; + this.contextMenuDataCopy.Name = "contextMenuDataCopy"; + this.contextMenuDataCopy.Size = new System.Drawing.Size(173, 22); + this.contextMenuDataCopy.Text = "&Copy"; + this.contextMenuDataCopy.Click += new System.EventHandler(this.contextMenuDataCopy_Click); + // + // groupBoxMatrixB + // + this.groupBoxMatrixB.Controls.Add(this.dataMatrixB); + this.groupBoxMatrixB.Dock = System.Windows.Forms.DockStyle.Fill; + this.groupBoxMatrixB.Location = new System.Drawing.Point(250, 3); + this.groupBoxMatrixB.Name = "groupBoxMatrixB"; + this.groupBoxMatrixB.Padding = new System.Windows.Forms.Padding(3, 8, 3, 3); + this.groupBoxMatrixB.Size = new System.Drawing.Size(241, 188); + this.groupBoxMatrixB.TabIndex = 6; + this.groupBoxMatrixB.TabStop = false; + this.groupBoxMatrixB.Text = "Matrix B"; + // + // dataMatrixB + // + this.dataMatrixB.AllowDrop = true; + this.dataMatrixB.AllowUserToAddRows = false; + this.dataMatrixB.AllowUserToDeleteRows = false; + this.dataMatrixB.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize; + this.dataMatrixB.ColumnHeadersVisible = false; + this.dataMatrixB.ContextMenuStrip = this.contextData; + this.dataMatrixB.Dock = System.Windows.Forms.DockStyle.Fill; + this.dataMatrixB.EditMode = System.Windows.Forms.DataGridViewEditMode.EditProgrammatically; + this.dataMatrixB.Location = new System.Drawing.Point(3, 21); + this.dataMatrixB.Name = "dataMatrixB"; + this.dataMatrixB.ReadOnly = true; + this.dataMatrixB.RowHeadersVisible = false; + this.dataMatrixB.Size = new System.Drawing.Size(235, 164); + this.dataMatrixB.TabIndex = 8; + this.dataMatrixB.DragDrop += new System.Windows.Forms.DragEventHandler(this.dataMatrix_DragDrop); + this.dataMatrixB.DragEnter += new System.Windows.Forms.DragEventHandler(this.dataMatrix_DragEnter); + // + // groupBoxResult + // + this.groupBoxResult.Controls.Add(this.dataResult); + this.groupBoxResult.Dock = System.Windows.Forms.DockStyle.Fill; + this.groupBoxResult.Location = new System.Drawing.Point(250, 197); + this.groupBoxResult.Name = "groupBoxResult"; + this.groupBoxResult.Padding = new System.Windows.Forms.Padding(3, 8, 3, 3); + this.groupBoxResult.Size = new System.Drawing.Size(241, 188); + this.groupBoxResult.TabIndex = 7; + this.groupBoxResult.TabStop = false; + this.groupBoxResult.Text = "Result"; + // + // dataResult + // + this.dataResult.AllowUserToAddRows = false; + this.dataResult.AllowUserToDeleteRows = false; + this.dataResult.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize; + this.dataResult.ColumnHeadersVisible = false; + this.dataResult.ContextMenuStrip = this.contextData; + this.dataResult.Dock = System.Windows.Forms.DockStyle.Fill; + this.dataResult.EditMode = System.Windows.Forms.DataGridViewEditMode.EditProgrammatically; + this.dataResult.Location = new System.Drawing.Point(3, 21); + this.dataResult.Name = "dataResult"; + this.dataResult.ReadOnly = true; + this.dataResult.RowHeadersVisible = false; + this.dataResult.Size = new System.Drawing.Size(235, 164); + this.dataResult.TabIndex = 8; + // + // groupBoxOperations + // + this.groupBoxOperations.Controls.Add(this.layoutTableButtons); + this.groupBoxOperations.Dock = System.Windows.Forms.DockStyle.Fill; + this.groupBoxOperations.Location = new System.Drawing.Point(3, 197); + this.groupBoxOperations.Name = "groupBoxOperations"; + this.groupBoxOperations.Padding = new System.Windows.Forms.Padding(3, 8, 3, 3); + this.groupBoxOperations.Size = new System.Drawing.Size(241, 188); + this.groupBoxOperations.TabIndex = 8; + this.groupBoxOperations.TabStop = false; + this.groupBoxOperations.Text = "Operations"; + // + // layoutTableButtons + // + this.layoutTableButtons.ColumnCount = 3; + this.layoutTableButtons.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 25F)); + this.layoutTableButtons.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 25F)); + this.layoutTableButtons.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 25F)); + this.layoutTableButtons.Controls.Add(this.buttonMax, 1, 5); + this.layoutTableButtons.Controls.Add(this.buttonAdd, 0, 1); + this.layoutTableButtons.Controls.Add(this.buttonMin, 0, 5); + this.layoutTableButtons.Controls.Add(this.buttonDet, 2, 4); + this.layoutTableButtons.Controls.Add(this.buttonTrace, 0, 4); + this.layoutTableButtons.Controls.Add(this.buttonRank, 1, 4); + this.layoutTableButtons.Controls.Add(this.buttonTransp, 2, 3); + this.layoutTableButtons.Controls.Add(this.buttonPow, 1, 3); + this.layoutTableButtons.Controls.Add(this.buttonMulNum, 2, 2); + this.layoutTableButtons.Controls.Add(this.buttonSubNum, 1, 2); + this.layoutTableButtons.Controls.Add(this.buttonAddNum, 0, 2); + this.layoutTableButtons.Controls.Add(this.buttonInv, 0, 3); + this.layoutTableButtons.Controls.Add(this.buttonMul, 2, 1); + this.layoutTableButtons.Controls.Add(this.buttonSub, 1, 1); + this.layoutTableButtons.Controls.Add(this.labelOutput, 0, 0); + this.layoutTableButtons.Controls.Add(this.textOutput, 1, 0); + this.layoutTableButtons.Dock = System.Windows.Forms.DockStyle.Fill; + this.layoutTableButtons.Location = new System.Drawing.Point(3, 21); + this.layoutTableButtons.Margin = new System.Windows.Forms.Padding(0); + this.layoutTableButtons.Name = "layoutTableButtons"; + this.layoutTableButtons.RowCount = 7; + this.layoutTableButtons.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 14.28571F)); + this.layoutTableButtons.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 14.28571F)); + this.layoutTableButtons.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 14.28571F)); + this.layoutTableButtons.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 14.28571F)); + this.layoutTableButtons.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 14.28571F)); + this.layoutTableButtons.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 14.28571F)); + this.layoutTableButtons.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 14.28571F)); + this.layoutTableButtons.Size = new System.Drawing.Size(235, 164); + this.layoutTableButtons.TabIndex = 5; + // + // buttonMax + // + this.buttonMax.Dock = System.Windows.Forms.DockStyle.Fill; + this.buttonMax.Location = new System.Drawing.Point(79, 116); + this.buttonMax.Margin = new System.Windows.Forms.Padding(1); + this.buttonMax.Name = "buttonMax"; + this.buttonMax.Size = new System.Drawing.Size(76, 21); + this.buttonMax.TabIndex = 48; + this.buttonMax.Text = "Max(A)"; + this.toolTip.SetToolTip(this.buttonMax, "Maximum element in matrix A."); + this.buttonMax.UseVisualStyleBackColor = true; + this.buttonMax.Click += new System.EventHandler(this.buttonMax_Click); + // + // buttonAdd + // + this.buttonAdd.AccessibleRole = System.Windows.Forms.AccessibleRole.TitleBar; + this.buttonAdd.Dock = System.Windows.Forms.DockStyle.Fill; + this.buttonAdd.Location = new System.Drawing.Point(1, 24); + this.buttonAdd.Margin = new System.Windows.Forms.Padding(1); + this.buttonAdd.Name = "buttonAdd"; + this.buttonAdd.Size = new System.Drawing.Size(76, 21); + this.buttonAdd.TabIndex = 46; + this.buttonAdd.Text = "A + B"; + this.toolTip.SetToolTip(this.buttonAdd, "Add matrix A and B."); + this.buttonAdd.UseVisualStyleBackColor = true; + this.buttonAdd.Click += new System.EventHandler(this.buttonAdd_Click); + // + // buttonMin + // + this.buttonMin.Dock = System.Windows.Forms.DockStyle.Fill; + this.buttonMin.Location = new System.Drawing.Point(1, 116); + this.buttonMin.Margin = new System.Windows.Forms.Padding(1); + this.buttonMin.Name = "buttonMin"; + this.buttonMin.Size = new System.Drawing.Size(76, 21); + this.buttonMin.TabIndex = 45; + this.buttonMin.Text = "Min(A)"; + this.toolTip.SetToolTip(this.buttonMin, "Minimum element in matrix A."); + this.buttonMin.UseVisualStyleBackColor = true; + this.buttonMin.Click += new System.EventHandler(this.buttonMin_Click); + // + // buttonDet + // + this.buttonDet.Dock = System.Windows.Forms.DockStyle.Fill; + this.buttonDet.Location = new System.Drawing.Point(157, 93); + this.buttonDet.Margin = new System.Windows.Forms.Padding(1); + this.buttonDet.Name = "buttonDet"; + this.buttonDet.Size = new System.Drawing.Size(77, 21); + this.buttonDet.TabIndex = 44; + this.buttonDet.Text = "Det(A)"; + this.toolTip.SetToolTip(this.buttonDet, "Determinant of matrix A."); + this.buttonDet.UseVisualStyleBackColor = true; + this.buttonDet.Click += new System.EventHandler(this.buttonDet_Click); + // + // buttonTrace + // + this.buttonTrace.Dock = System.Windows.Forms.DockStyle.Fill; + this.buttonTrace.Location = new System.Drawing.Point(1, 93); + this.buttonTrace.Margin = new System.Windows.Forms.Padding(1); + this.buttonTrace.Name = "buttonTrace"; + this.buttonTrace.Size = new System.Drawing.Size(76, 21); + this.buttonTrace.TabIndex = 43; + this.buttonTrace.Text = "Trace(A)"; + this.toolTip.SetToolTip(this.buttonTrace, "Trace of matrix A."); + this.buttonTrace.UseVisualStyleBackColor = true; + this.buttonTrace.Click += new System.EventHandler(this.buttonTrace_Click); + // + // buttonRank + // + this.buttonRank.Dock = System.Windows.Forms.DockStyle.Fill; + this.buttonRank.Location = new System.Drawing.Point(79, 93); + this.buttonRank.Margin = new System.Windows.Forms.Padding(1); + this.buttonRank.Name = "buttonRank"; + this.buttonRank.Size = new System.Drawing.Size(76, 21); + this.buttonRank.TabIndex = 42; + this.buttonRank.Text = "Rank(A)"; + this.toolTip.SetToolTip(this.buttonRank, "Rank of matrix A."); + this.buttonRank.UseVisualStyleBackColor = true; + this.buttonRank.Click += new System.EventHandler(this.buttonRank_Click); + // + // buttonTransp + // + this.buttonTransp.Dock = System.Windows.Forms.DockStyle.Fill; + this.buttonTransp.Location = new System.Drawing.Point(157, 70); + this.buttonTransp.Margin = new System.Windows.Forms.Padding(1); + this.buttonTransp.Name = "buttonTransp"; + this.buttonTransp.Size = new System.Drawing.Size(77, 21); + this.buttonTransp.TabIndex = 41; + this.buttonTransp.Text = "Transp(A)"; + this.toolTip.SetToolTip(this.buttonTransp, "Transpose matrix A."); + this.buttonTransp.UseVisualStyleBackColor = true; + this.buttonTransp.Click += new System.EventHandler(this.buttonTransp_Click); + // + // buttonPow + // + this.buttonPow.Dock = System.Windows.Forms.DockStyle.Fill; + this.buttonPow.Location = new System.Drawing.Point(79, 70); + this.buttonPow.Margin = new System.Windows.Forms.Padding(1); + this.buttonPow.Name = "buttonPow"; + this.buttonPow.Size = new System.Drawing.Size(76, 21); + this.buttonPow.TabIndex = 40; + this.buttonPow.Text = "A ^ x"; + this.toolTip.SetToolTip(this.buttonPow, "Raise matrix A at an integer power."); + this.buttonPow.UseVisualStyleBackColor = true; + this.buttonPow.Click += new System.EventHandler(this.buttonPow_Click); + // + // buttonMulNum + // + this.buttonMulNum.Dock = System.Windows.Forms.DockStyle.Fill; + this.buttonMulNum.Location = new System.Drawing.Point(157, 47); + this.buttonMulNum.Margin = new System.Windows.Forms.Padding(1); + this.buttonMulNum.Name = "buttonMulNum"; + this.buttonMulNum.Size = new System.Drawing.Size(77, 21); + this.buttonMulNum.TabIndex = 39; + this.buttonMulNum.Text = "A * x"; + this.toolTip.SetToolTip(this.buttonMulNum, "Multiply every element in matrix A with a real number."); + this.buttonMulNum.UseVisualStyleBackColor = true; + this.buttonMulNum.Click += new System.EventHandler(this.buttonMulNum_Click); + // + // buttonSubNum + // + this.buttonSubNum.Dock = System.Windows.Forms.DockStyle.Fill; + this.buttonSubNum.Location = new System.Drawing.Point(79, 47); + this.buttonSubNum.Margin = new System.Windows.Forms.Padding(1); + this.buttonSubNum.Name = "buttonSubNum"; + this.buttonSubNum.Size = new System.Drawing.Size(76, 21); + this.buttonSubNum.TabIndex = 38; + this.buttonSubNum.Text = "A - x"; + this.toolTip.SetToolTip(this.buttonSubNum, "Subtract a real number from every element in matrix A."); + this.buttonSubNum.UseVisualStyleBackColor = true; + this.buttonSubNum.Click += new System.EventHandler(this.buttonSubNum_Click); + // + // buttonAddNum + // + this.buttonAddNum.Dock = System.Windows.Forms.DockStyle.Fill; + this.buttonAddNum.Location = new System.Drawing.Point(1, 47); + this.buttonAddNum.Margin = new System.Windows.Forms.Padding(1); + this.buttonAddNum.Name = "buttonAddNum"; + this.buttonAddNum.Size = new System.Drawing.Size(76, 21); + this.buttonAddNum.TabIndex = 37; + this.buttonAddNum.Text = "A + x"; + this.toolTip.SetToolTip(this.buttonAddNum, "Add a real number to every element in matrix A."); + this.buttonAddNum.UseVisualStyleBackColor = true; + this.buttonAddNum.Click += new System.EventHandler(this.buttonAddNum_Click); + // + // buttonInv + // + this.buttonInv.Dock = System.Windows.Forms.DockStyle.Fill; + this.buttonInv.Location = new System.Drawing.Point(1, 70); + this.buttonInv.Margin = new System.Windows.Forms.Padding(1); + this.buttonInv.Name = "buttonInv"; + this.buttonInv.Size = new System.Drawing.Size(76, 21); + this.buttonInv.TabIndex = 36; + this.buttonInv.Text = "A ^ -1"; + this.toolTip.SetToolTip(this.buttonInv, "Inverse of matrix A."); + this.buttonInv.UseVisualStyleBackColor = true; + this.buttonInv.Click += new System.EventHandler(this.buttonInv_Click); + // + // buttonMul + // + this.buttonMul.Dock = System.Windows.Forms.DockStyle.Fill; + this.buttonMul.Location = new System.Drawing.Point(157, 24); + this.buttonMul.Margin = new System.Windows.Forms.Padding(1); + this.buttonMul.Name = "buttonMul"; + this.buttonMul.Size = new System.Drawing.Size(77, 21); + this.buttonMul.TabIndex = 35; + this.buttonMul.Text = "A * B"; + this.toolTip.SetToolTip(this.buttonMul, "Multiply matrix A and B."); + this.buttonMul.UseVisualStyleBackColor = true; + this.buttonMul.Click += new System.EventHandler(this.buttonMul_Click); + // + // buttonSub + // + this.buttonSub.Dock = System.Windows.Forms.DockStyle.Fill; + this.buttonSub.Location = new System.Drawing.Point(79, 24); + this.buttonSub.Margin = new System.Windows.Forms.Padding(1); + this.buttonSub.Name = "buttonSub"; + this.buttonSub.Size = new System.Drawing.Size(76, 21); + this.buttonSub.TabIndex = 34; + this.buttonSub.Text = "A - B"; + this.toolTip.SetToolTip(this.buttonSub, "Subtract matrix B from matrix A."); + this.buttonSub.UseVisualStyleBackColor = true; + this.buttonSub.Click += new System.EventHandler(this.buttonSub_Click); + // + // labelOutput + // + this.labelOutput.Dock = System.Windows.Forms.DockStyle.Fill; + this.labelOutput.Location = new System.Drawing.Point(3, 0); + this.labelOutput.Name = "labelOutput"; + this.labelOutput.Size = new System.Drawing.Size(72, 23); + this.labelOutput.TabIndex = 0; + this.labelOutput.Text = "Output:"; + this.labelOutput.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; + // + // textOutput + // + this.textOutput.BackColor = System.Drawing.SystemColors.Window; + this.layoutTableButtons.SetColumnSpan(this.textOutput, 2); + this.textOutput.Dock = System.Windows.Forms.DockStyle.Fill; + this.textOutput.Location = new System.Drawing.Point(81, 3); + this.textOutput.Name = "textOutput"; + this.textOutput.ReadOnly = true; + this.textOutput.Size = new System.Drawing.Size(151, 20); + this.textOutput.TabIndex = 1; + this.textOutput.TextChanged += new System.EventHandler(this.textOutput_TextChanged); + // + // MainWindow + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(232)))), ((int)(((byte)(232)))), ((int)(((byte)(232))))); + this.ClientSize = new System.Drawing.Size(728, 412); + this.Controls.Add(this.layoutSplitMain); + this.Controls.Add(this.menuStrip); + this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); + this.MainMenuStrip = this.menuStrip; + this.Name = "MainWindow"; + this.Text = "Matrix calculator"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.MainWindow_FormClosing); + this.menuStrip.ResumeLayout(false); + this.menuStrip.PerformLayout(); + this.layoutSplitMain.Panel1.ResumeLayout(false); + this.layoutSplitMain.Panel2.ResumeLayout(false); + this.layoutSplitMain.ResumeLayout(false); + this.layoutSplitSide.Panel1.ResumeLayout(false); + this.layoutSplitSide.Panel2.ResumeLayout(false); + this.layoutSplitSide.ResumeLayout(false); + this.groupBoxMatrices.ResumeLayout(false); + this.contextList.ResumeLayout(false); + this.groupBoxPreview.ResumeLayout(false); + this.groupBoxPreview.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.dataPreview)).EndInit(); + this.layoutTableCalcArea.ResumeLayout(false); + this.groupBoxMatrixA.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.dataMatrixA)).EndInit(); + this.contextData.ResumeLayout(false); + this.groupBoxMatrixB.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.dataMatrixB)).EndInit(); + this.groupBoxResult.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.dataResult)).EndInit(); + this.groupBoxOperations.ResumeLayout(false); + this.layoutTableButtons.ResumeLayout(false); + this.layoutTableButtons.PerformLayout(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.MenuStrip menuStrip; + private System.Windows.Forms.ToolStripMenuItem menuFile; + private System.Windows.Forms.ToolStripMenuItem menuFileNew; + private System.Windows.Forms.ToolStripMenuItem menuFileOpen; + private System.Windows.Forms.ToolStripMenuItem menuFileSave; + private System.Windows.Forms.ToolStripMenuItem menuFileSaveAs; + private System.Windows.Forms.ToolStripSeparator menuSeparator1; + private System.Windows.Forms.ToolStripMenuItem menuFileImport; + private System.Windows.Forms.ToolStripMenuItem menuFileImportCsv; + private System.Windows.Forms.ToolStripMenuItem menuFileImportWorksheet; + private System.Windows.Forms.ToolStripSeparator menuSeparator2; + private System.Windows.Forms.ToolStripMenuItem menuFileExit; + private System.Windows.Forms.ToolStripMenuItem menuMatrix; + private System.Windows.Forms.ToolStripMenuItem menuMatrixNew; + private System.Windows.Forms.ToolStripMenuItem menuMatrixEdit; + private System.Windows.Forms.ToolStripMenuItem menuMatrixDelete; + private System.Windows.Forms.ToolStripMenuItem menuMatrixDuplicate; + private System.Windows.Forms.ToolStripSeparator menuSeparator3; + private System.Windows.Forms.ToolStripMenuItem menuMatrixCopy; + private System.Windows.Forms.ToolStripMenuItem menuMatrixPaste; + private System.Windows.Forms.ToolStripMenuItem menuMatrixPasteSpecial; + private System.Windows.Forms.ToolStripMenuItem menuHelp; + private System.Windows.Forms.ToolStripMenuItem menuHelpAbout; + private System.Windows.Forms.ToolStripMenuItem menuHelpHelp; + private System.Windows.Forms.SplitContainer layoutSplitMain; + private System.Windows.Forms.SplitContainer layoutSplitSide; + private System.Windows.Forms.TableLayoutPanel layoutTableCalcArea; + private System.Windows.Forms.ToolTip toolTip; + private System.Windows.Forms.ToolStripSeparator menuSeparator4; + private System.Windows.Forms.ToolStripMenuItem menuMatrixInsertA; + private System.Windows.Forms.ToolStripMenuItem menuMatrixInsertB; + private System.Windows.Forms.ContextMenuStrip contextList; + private System.Windows.Forms.ToolStripMenuItem contextMenuListNew; + private System.Windows.Forms.ToolStripMenuItem contextMenuListEdit; + private System.Windows.Forms.ToolStripMenuItem contextMenuListDelete; + private System.Windows.Forms.ToolStripMenuItem contextMenuListDuplicate; + private System.Windows.Forms.ToolStripSeparator contextMenuListSeparator1; + private System.Windows.Forms.ToolStripMenuItem contextMenuListInsertA; + private System.Windows.Forms.ToolStripMenuItem contextMenuListInsertB; + private System.Windows.Forms.ToolStripSeparator contextMenuListSeparator2; + private System.Windows.Forms.ToolStripMenuItem contextMenuListCopy; + private System.Windows.Forms.ToolStripMenuItem contextMenuListPaste; + private System.Windows.Forms.ToolStripMenuItem contextMenuListPasteSpecial; + private System.Windows.Forms.ContextMenuStrip contextData; + private System.Windows.Forms.ToolStripMenuItem contextMenuDataAdd; + private System.Windows.Forms.ToolStripMenuItem contextMenuDataClear; + private System.Windows.Forms.ToolStripMenuItem contextMenuDataCopy; + private System.Windows.Forms.ToolStripMenuItem menuFilePreferences; + private DynamicLink.Controls.MyGroupBox groupBoxMatrices; + private System.Windows.Forms.ListView listMatrices; + private System.Windows.Forms.ColumnHeader listMatricesColName; + private System.Windows.Forms.ColumnHeader listMatricesColDesc; + private DynamicLink.Controls.MyGroupBox groupBoxPreview; + private System.Windows.Forms.Label labelPreviewDesc; + private System.Windows.Forms.Label labelPreviewName; + private System.Windows.Forms.DataGridView dataPreview; + private DynamicLink.Controls.MyGroupBox groupBoxMatrixA; + private System.Windows.Forms.DataGridView dataMatrixA; + private DynamicLink.Controls.MyGroupBox groupBoxMatrixB; + private System.Windows.Forms.DataGridView dataMatrixB; + private DynamicLink.Controls.MyGroupBox groupBoxResult; + private System.Windows.Forms.DataGridView dataResult; + private DynamicLink.Controls.MyGroupBox groupBoxOperations; + private System.Windows.Forms.TableLayoutPanel layoutTableButtons; + private DynamicLink.Controls.MyButton buttonMax; + private DynamicLink.Controls.MyButton buttonAdd; + private DynamicLink.Controls.MyButton buttonMin; + private DynamicLink.Controls.MyButton buttonDet; + private DynamicLink.Controls.MyButton buttonTrace; + private DynamicLink.Controls.MyButton buttonRank; + private DynamicLink.Controls.MyButton buttonTransp; + private DynamicLink.Controls.MyButton buttonPow; + private DynamicLink.Controls.MyButton buttonMulNum; + private DynamicLink.Controls.MyButton buttonSubNum; + private DynamicLink.Controls.MyButton buttonAddNum; + private DynamicLink.Controls.MyButton buttonInv; + private DynamicLink.Controls.MyButton buttonMul; + private DynamicLink.Controls.MyButton buttonSub; + private System.Windows.Forms.Label labelOutput; + private System.Windows.Forms.TextBox textOutput; + } +} + diff --git a/Source/MatrixCalculator/MainWindow.cs b/Source/MatrixCalculator/MainWindow.cs new file mode 100644 index 0000000..658f79b --- /dev/null +++ b/Source/MatrixCalculator/MainWindow.cs @@ -0,0 +1,812 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Windows.Forms; +using MathNet.Numerics.LinearAlgebra; + +namespace MatrixCalculator +{ + public partial class MainWindow : Form + { + private WorksheetFile worksheet = new WorksheetFile(); + private List> matrices = new List>(); + private Matrix matrixA, matrixB, matrixResult; + + #region Matrix properties + private Matrix MatrixA { + get { return matrixA; } + set { + matrixA = value; + GridViewHelper.PutMatrix(matrixA, dataMatrixA); + } + } + + private Matrix MatrixB + { + get { return matrixB; } + set + { + matrixB = value; + GridViewHelper.PutMatrix(matrixB, dataMatrixB); + } + } + + private Matrix MatrixResult + { + get { return matrixResult; } + set + { + matrixResult = value; + GridViewHelper.PutMatrix(matrixResult, dataResult); + } + } + + private Matrix MatrixPreview + { + get { + if (listMatrices.SelectedItems.Count == 1) + return matrices[listMatrices.SelectedIndices[0]]; + else return null; + } + set { + GridViewHelper.PutMatrix(value, dataPreview); + } + } + #endregion + + #region Constructor + + public MainWindow() + { + InitializeComponent(); + ResetAll(); + } + + #endregion + + #region User interface + + #region Menus + private void menuFileNew_Click(object sender, EventArgs e) + { + if (!ShowSaveWarningDialog()) return; + + ResetAll(); + worksheet = new WorksheetFile(); + } + + private void menuFileOpen_Click(object sender, EventArgs e) + { + if (!ShowSaveWarningDialog()) return; + + // Open file dialog + string file; + if (!OpenDialog("Open worksheet...", MatrixCalculator.Properties.Resources.WorksheetFormatFilter, out file)) return; + + // Open the file + DataTable data = new DataTable(); + try { + worksheet = new WorksheetFile(file); + data = worksheet.Read(); + } + + catch (Exception ex) { + MessageBox.Show("Error:" + ex.Message, "Error!"); + return; + } + + // Load data + ResetAll(); + AddMatrices(data); + } + + private void menuFileSave_Click(object sender, EventArgs e) + { + if (worksheet.FileName == "") + { + string file; + if (!SaveDialog("Save worksheet...", MatrixCalculator.Properties.Resources.WorksheetFormatFilter, out file)) return; + + worksheet.FileName = file; + } + + try { worksheet.Save(); } + catch (Exception ex) { MessageBox.Show("Error: " + ex.Message, "Error!"); } + } + + private void menuFileSaveAs_Click(object sender, EventArgs e) + { + string file; + if (!SaveDialog("Save worksheet...", MatrixCalculator.Properties.Resources.WorksheetFormatFilter, out file)) return; + + try { worksheet.SaveAs(file); } + catch (Exception ex) { MessageBox.Show("Error: " + ex.Message, "Error!"); } + } + + private void menuFileImportCsv_Click(object sender, EventArgs e) + { + string file; + if (!OpenDialog("Open CSV file...", MatrixCalculator.Properties.Resources.CsvFormatFilter, out file)) + return; + + ImportCsvWindow wind = new ImportCsvWindow(); + try { wind.LoadFile(file); } + catch (Exception ex) + { + MessageBox.Show("Error: " + ex.Message, "Error!"); + } + + if (wind.ShowDialog() != System.Windows.Forms.DialogResult.OK) + return; + + AddMatrix(wind.Matrix, wind.MatrixName, "", true); + } + + private void menuFileImportWorksheet_Click(object sender, EventArgs e) + { + string file; + if (!OpenDialog("Open worksheet...", MatrixCalculator.Properties.Resources.WorksheetFormatFilter, out file)) + return; + + ImportWorksheetWindow wind = new ImportWorksheetWindow(); + try { wind.LoadFile(file); } + catch (Exception ex) + { + MessageBox.Show("Error: " + ex.Message, "Error!"); + } + + if (wind.ShowDialog() != System.Windows.Forms.DialogResult.OK) return; + AddMatrices(wind.Data); + } + + private void menuFilePreferences_Click(object sender, EventArgs e) + { + new SettingsWindow().ShowDialog(); + } + + private void menuFileExit_Click(object sender, EventArgs e) + { + this.Close(); + } + + private void menuMatrixNew_Click(object sender, EventArgs e) + { + Editor edit = new Editor(); + edit.Text = "New matrix..."; + + if (edit.ShowDialog() != System.Windows.Forms.DialogResult.OK) + return; + + AddMatrix(edit.Matrix, edit.MatrixName, edit.MatrixDescription, true); + } + + private void menuMatrixEdit_Click(object sender, EventArgs e) + { + if (listMatrices.SelectedItems.Count != 1) return; + + string old_name, new_name, desc; + Matrix matrix; + // Set up variables + + Editor edit = new Editor(); + edit.Text = "Edit matrix..."; + old_name = edit.MatrixName = listMatrices.SelectedItems[0].Text; + edit.MatrixDescription = listMatrices.SelectedItems[0].SubItems[1].Text; + edit.Matrix = matrices[listMatrices.SelectedIndices[0]]; + + // Dialog + if (edit.ShowDialog() != System.Windows.Forms.DialogResult.OK) return; + + // Update new stuff + new_name = listMatrices.SelectedItems[0].Text = edit.MatrixName; + desc = listMatrices.SelectedItems[0].SubItems[1].Text = edit.MatrixDescription; + matrix = matrices[listMatrices.SelectedIndices[0]] = edit.Matrix; + + // Update in file + worksheet.ModifyMatrix(old_name, new_name, CsvParser.ToCSV(matrix), desc); + + // Update preview + listMatrices_SelectedIndexChanged(this, new EventArgs()); + } + + private void menuMatrixDelete_Click(object sender, EventArgs e) + { + foreach (int i in listMatrices.SelectedIndices) + { + worksheet.DeleteMatrix(listMatrices.Items[i].Text); + listMatrices.Items.RemoveAt(i); + matrices.RemoveAt(i); + } + } + + private void menuMatrixDuplicate_Click(object sender, EventArgs e) + { + if (listMatrices.SelectedItems.Count != 1) return; + + // Set up variables + Editor edit = new Editor(); + edit.Text = "New matrix..."; + edit.MatrixName = listMatrices.SelectedItems[0].Text; + edit.MatrixDescription = listMatrices.SelectedItems[0].SubItems[1].Text; + edit.Matrix = matrices[listMatrices.SelectedIndices[0]]; + + // Dialog + if (edit.ShowDialog() != System.Windows.Forms.DialogResult.OK) return; + + // Update new stuff + AddMatrix(edit.Matrix, edit.MatrixName, edit.MatrixDescription, true); + } + + private void menuMatrixInsertA_Click(object sender, EventArgs e) + { + if (listMatrices.SelectedIndices.Count == 1) + MatrixA = matrices[listMatrices.SelectedIndices[0]]; + } + + private void menuMatrixInsertB_Click(object sender, EventArgs e) + { + if (listMatrices.SelectedIndices.Count == 1) + MatrixB = matrices[listMatrices.SelectedIndices[0]]; + } + + private void menuMatrixCopy_Click(object sender, EventArgs e) + { + if (listMatrices.SelectedIndices.Count != 1) return; + + string csv = CsvParser.ToCSV(matrices[listMatrices.SelectedIndices[0]]); + Clipboard.SetText(csv, TextDataFormat.CommaSeparatedValue); + } + + private void menuMatrixPaste_Click(object sender, EventArgs e) + { + // Get data + string csv = ""; + if (Clipboard.ContainsText(TextDataFormat.CommaSeparatedValue)) + csv = Clipboard.GetText(TextDataFormat.CommaSeparatedValue); + else return; + + // Put it in a matrix + Editor edit = new Editor(); + edit.Text = "Paste matrix..."; + edit.Matrix = MatrixConverter.FromTable(CsvParser.GetTable(csv, ",;\t".ToArray())); + edit.MatrixName = "Pasted matrix"; + + if (edit.ShowDialog() != System.Windows.Forms.DialogResult.OK) return; + + // Get data + AddMatrix(edit.Matrix, edit.MatrixName, edit.MatrixDescription, true); + } + + private void menuMatrixPasteSpecial_Click(object sender, EventArgs e) + { + // Get data + string csv = ""; + if (Clipboard.ContainsText(TextDataFormat.CommaSeparatedValue)) + csv = Clipboard.GetText(TextDataFormat.CommaSeparatedValue); + else if (Clipboard.ContainsText()) + csv = Clipboard.GetText(); + else return; + + // Use CSV importer + ImportCsvWindow wind = new ImportCsvWindow(); + wind.Csv = csv; + + if (wind.ShowDialog() != System.Windows.Forms.DialogResult.OK) return; + + AddMatrix(wind.Matrix, wind.MatrixName, "", true); + } + + private void menuHelpAbout_Click(object sender, EventArgs e) + { + DynamicLink.Launcher.About(); + } + + private void menuHelpHelp_Click(object sender, EventArgs e) + { + DynamicLink.Launcher.StartModule("Help", "matrixcalc"); + } + + private void contextMenuDataAdd_Click(object sender, EventArgs e) + { + var item = sender as ToolStripMenuItem; + var menu = item.Owner as ContextMenuStrip; + var grid = menu.SourceControl as DataGridView; + if (grid == null) return; + + // Create editor window + Editor editwindow = new Editor(); + editwindow.Text = "New matrix..."; + editwindow.Matrix = GridViewHelper.GetMatrix(grid); + + if (editwindow.ShowDialog() == System.Windows.Forms.DialogResult.OK) + AddMatrix(editwindow.Matrix, editwindow.MatrixName, editwindow.MatrixDescription, true); + } + + private void contextMenuDataClear_Click(object sender, EventArgs e) + { + var item = sender as ToolStripMenuItem; + var menu = item.Owner as ContextMenuStrip; + var grid = menu.SourceControl as DataGridView; + if (grid == null) return; + + if (grid == dataMatrixA) matrixA = null; + else if (grid == dataMatrixB) matrixB = null; + + grid.Rows.Clear(); + grid.Columns.Clear(); + } + + private void contextMenuDataCopy_Click(object sender, EventArgs e) + { + var item = sender as ToolStripMenuItem; + var menu = item.Owner as ContextMenuStrip; + var grid = menu.SourceControl as DataGridView; + if (grid == null) return; + + string csv = CsvParser.ToCSV(grid); + Clipboard.SetText(csv, TextDataFormat.CommaSeparatedValue); + } + + #endregion + + #region Calculator buttons + private void buttonAdd_Click(object sender, EventArgs e) + { + if (!VerifyConditions(1, 1, 1, 1, 0, 0)) return; + + try { MatrixResult = matrixA + matrixB; } + catch (Exception ex) + { + textOutput.Text = "Error: " + ex.Message; + } + } + + private void buttonSub_Click(object sender, EventArgs e) + { + if (!VerifyConditions(1, 1, 1, 1, 0, 0)) return; + + try { MatrixResult = matrixA - matrixB; } + catch (Exception ex) + { + textOutput.Text = "Error: " + ex.Message; + } + } + + private void buttonMul_Click(object sender, EventArgs e) + { + if (!VerifyConditions(1, 1, 1, 0, 1, 0)) return; + + try { MatrixResult = matrixA * matrixB; } + catch (Exception ex) + { + textOutput.Text = "Error: " + ex.Message; + } + } + + private void buttonAddNum_Click(object sender, EventArgs e) + { + if (!VerifyConditions(1, 0, 0, 0, 0, 0)) return; + + // Get a number + NumericInput input = new NumericInput(NumericInput.NumberType.Real); + if (input.ShowDialog() != System.Windows.Forms.DialogResult.OK) return; + double number = input.NumberReal; + + // Now add it + Matrix m = Matrix.Build.Dense(matrixA.RowCount, matrixA.ColumnCount, number); + MatrixResult = matrixA + m; + } + + private void buttonSubNum_Click(object sender, EventArgs e) + { + if (!VerifyConditions(1, 0, 0, 0, 0, 0)) return; + + // Get a number + NumericInput input = new NumericInput(NumericInput.NumberType.Real); + if (input.ShowDialog() != System.Windows.Forms.DialogResult.OK) return; + double number = input.NumberReal; + + // Now add it + Matrix m = Matrix.Build.Dense(matrixA.RowCount, matrixA.ColumnCount, number); + MatrixResult = matrixA - m; + } + + private void buttonMulNum_Click(object sender, EventArgs e) + { + if (!VerifyConditions(1, 0, 0, 0, 0, 0)) return; + + // Get a number + NumericInput input = new NumericInput(NumericInput.NumberType.Real); + if (input.ShowDialog() != System.Windows.Forms.DialogResult.OK) return; + double number = input.NumberReal; + + // Now add it + MatrixResult = matrixA * number; + } + + private void buttonInv_Click(object sender, EventArgs e) + { + if (!VerifyConditions(1, 0, 0, 0, 0, 0)) return; + + try { MatrixResult = matrixA.Inverse(); } + catch (Exception ex) + { + textOutput.Text = "Error: " + ex.Message; + } + } + + private void buttonPow_Click(object sender, EventArgs e) + { + if (!VerifyConditions(1, 0, 0, 0, 0, 0)) return; + + // Get a number + NumericInput input = new NumericInput(NumericInput.NumberType.Integer); + if (input.ShowDialog() != System.Windows.Forms.DialogResult.OK) return; + int number = input.NumberInt; + + // Calculate + try { MatrixResult = MatrixHelper.Power (matrixA, number); } + catch (Exception ex) + { + textOutput.Text = "Error: " + ex.Message; + } + } + + private void buttonTransp_Click(object sender, EventArgs e) + { + if (!VerifyConditions(1, 0, 0, 0, 0, 0)) return; + + try { MatrixResult = matrixA.Transpose(); } + catch (Exception ex) + { + textOutput.Text = "Error: " + ex.Message; + } + } + + private void buttonTrace_Click(object sender, EventArgs e) + { + if (!VerifyConditions(1, 0, 0, 0, 0, 0)) return; + + if (MatrixCalculator.Properties.Settings.Default.NumberResultAsMatrix) + MatrixResult = Matrix.Build.Dense(1, 1, matrixA.Trace()); + + else textOutput.Text = MyDouble.String(matrixA.Trace()); + } + + private void buttonRank_Click(object sender, EventArgs e) + { + if (!VerifyConditions(1, 0, 0, 0, 0, 0)) return; + + if (MatrixCalculator.Properties.Settings.Default.NumberResultAsMatrix) + MatrixResult = Matrix.Build.Dense(1, 1, Convert.ToDouble(matrixA.Rank())); + + else textOutput.Text = matrixA.Rank().ToString(); + } + + private void buttonDet_Click(object sender, EventArgs e) + { + if (!VerifyConditions(1, 0, 0, 0, 0, 1)) return; + + if (MatrixCalculator.Properties.Settings.Default.NumberResultAsMatrix) + MatrixResult = Matrix.Build.Dense(1, 1, matrixA.Determinant()); + + else textOutput.Text = MyDouble.String(matrixA.Determinant()); + } + + private void buttonMin_Click(object sender, EventArgs e) + { + if (!VerifyConditions(1, 0, 0, 0, 0, 0)) return; + + if (MatrixCalculator.Properties.Settings.Default.NumberResultAsMatrix) + MatrixResult = Matrix.Build.Dense(1, 1, MatrixHelper.Min(matrixA)); + + else textOutput.Text = MyDouble.String(MatrixHelper.Min(matrixA)); + + } + + private void buttonMax_Click(object sender, EventArgs e) + { + if (!VerifyConditions(1, 0, 0, 0, 0, 0)) return; + + if (MatrixCalculator.Properties.Settings.Default.NumberResultAsMatrix) + MatrixResult = Matrix.Build.Dense(1, 1, MatrixHelper.Max(matrixA)); + + else textOutput.Text = MyDouble.String(MatrixHelper.Max(matrixA)); + } + + #endregion + + #region Drag & drop + private void dataMatrix_DragEnter(object sender, DragEventArgs e) + { + if (e.Data.GetDataPresent(typeof(ListViewItem))) e.Effect = DragDropEffects.Move; + else e.Effect = DragDropEffects.None; + } + + private void dataMatrix_DragDrop(object sender, DragEventArgs e) + { + ListViewItem data = e.Data.GetData(typeof(ListViewItem)) as ListViewItem; + var send = sender as DataGridView; + if (data == null || send == null) return; + + if (send == dataMatrixA) MatrixA = matrices[data.Index]; + else if (send == dataMatrixB) MatrixB = matrices[data.Index]; + } + + private void listMatrices_DragOver(object sender, DragEventArgs e) + { + e.Effect = DragDropEffects.Move; + } + + private void listMatrices_MouseDown(object sender, MouseEventArgs e) + { + if (listMatrices.SelectedItems.Count == 1 && e.Button == System.Windows.Forms.MouseButtons.Left) + listMatrices.DoDragDrop(listMatrices.SelectedItems[0], DragDropEffects.Move); + } + #endregion + + #region List Matrices Selected Index Changed + private void EnableMenus(int insA, int insB, int copy, int edit, int del, int dupl) + { + menuMatrixInsertA.Enabled = contextMenuListInsertA.Enabled = (insA != 0); + menuMatrixInsertB.Enabled = contextMenuListInsertB.Enabled = (insB != 0); + menuMatrixCopy.Enabled = contextMenuListCopy.Enabled = (copy != 0); + menuMatrixEdit.Enabled = contextMenuListEdit.Enabled = (edit != 0); + menuMatrixDelete.Enabled = contextMenuListDelete.Enabled = (del != 0); + menuMatrixDuplicate.Enabled = contextMenuListDuplicate.Enabled = (dupl != 0); + } + + private void listMatrices_SelectedIndexChanged(object sender, EventArgs e) + { + switch (listMatrices.SelectedIndices.Count) + { + case 0: EnableMenus(0, 0, 0, 0, 0, 0); break; + case 1: + this.labelPreviewName.Text = "Name: " + listMatrices.SelectedItems[0].Text; + this.labelPreviewDesc.Text = "Description: " + listMatrices.SelectedItems[0].SubItems[1].Text; + MatrixPreview = matrices[listMatrices.SelectedIndices[0]]; + + EnableMenus(1, 1, 1, 1, 1, 1); + break; + default: EnableMenus(0, 0, 0, 0, 1, 0); break; + } + } + #endregion + + #region Painting + protected override void OnPaintBackground(PaintEventArgs e) + { + DynamicLink.Controls.BackgroundGradient.Paint(e.Graphics, new Rectangle(-1, -1, this.Width, this.Height)); + } + #endregion + + #region Others + private void MainWindow_FormClosing(object sender, FormClosingEventArgs e) + { + if (!ShowSaveWarningDialog()) e.Cancel = true; + + if (!e.Cancel) MatrixCalculator.Properties.Settings.Default.Save(); + } + + private void textOutput_TextChanged(object sender, EventArgs e) + { + toolTip.SetToolTip(textOutput, textOutput.Text); + } + + #endregion + + #endregion + + #region Additional routines + private string MakeUnique(string name) + { + List probl = new List(); + + // Test name uniqueness + bool unique = true; + foreach (ListViewItem i in this.listMatrices.Items) + { + if (i.Text == name) unique = false; + if (i.Text.StartsWith(name)) probl.Add(i.Text); + } + + // If not unique, generate a unique name + if (!unique) + { + int n = 0; + while (probl.Contains(name + n.ToString()) && n < 10000) n++; + name += n.ToString(); + } + + return name; + } + + private void AddMatrix(Matrix m, string name, string desc, bool inFile = false) + { + matrices.Add(m); + name = MakeUnique(name); + + // Add it + ListViewItem item = listMatrices.Items.Add(name); + item.SubItems.Add(desc); + + // To file? + if (inFile) worksheet.AddMatrix(name, CsvParser.ToCSV(m), desc); + + } + + private void AddMatrices(DataTable data, bool infile = false) + { + AddMatrices(data, infile, false, MatrixCalculator.Properties.Settings.Default.InternalCsvSeparators.ToArray()); + } + + private void AddMatrices(DataTable data, bool infile, bool combine, params char[] separs) + { + foreach (DataRow i in data.Rows) + { + try { + string name = i["name"].ToString(); + string desc = i["description"].ToString(); + string csv = i["csv"].ToString(); + DataTable dt = CsvParser.GetTable(csv, separs, combine); + + AddMatrix(MatrixConverter.FromTable(dt), name, desc, infile); + } + + catch (Exception e) + { + MessageBox.Show("Error: " + e.Message, "Error!"); + return; + } + } + } + + private void ResetAll() + { + matrices.Clear(); + listMatrices.Items.Clear(); + + AddMatrix(Matrix.Build.Dense(7, 7, 0), "Zero", "Zero matrix"); + AddMatrix(Matrix.Build.DenseIdentity(7, 7), "One", "Identity matrix"); + } + + private bool ShowSaveWarningDialog() + { + // Nothing to do + if (worksheet.IsQueueEmpty) return true; + + // Show dialog + switch (MessageBox.Show("All the unsaved changes will be lost. Do you want to save the current worksheet?", + "Save?", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question)) + { + + case System.Windows.Forms.DialogResult.Cancel: return false; + case System.Windows.Forms.DialogResult.Yes: + menuFileSave_Click(this, new EventArgs()); + break; + + case System.Windows.Forms.DialogResult.No: + break; + } + + return true; + } + + private bool OpenDialog(string title, string filter, out string filename) + { + bool result; + + // Initialize dialog + OpenFileDialog open = new OpenFileDialog(); + open.Title = title; + open.Filter = filter; + + // Show + if (open.ShowDialog() == System.Windows.Forms.DialogResult.OK) result = true; + else result = false; + + // Output + filename = open.FileName; + return result; + } + + private bool SaveDialog(string title, string filter, out string filename) + { + bool result; + + // Initialize dialog + SaveFileDialog save = new SaveFileDialog(); + save.Title = title; + save.Filter = filter; + + // Show + if (save.ShowDialog() == System.Windows.Forms.DialogResult.OK) result = true; + else result = false; + + // Output + filename = save.FileName; + return result; + } + + #endregion + + #region Additional calculator routines + bool VerifyConditions(int includeA, int includeB, int changeSpecial, int checkSum, int checkMul, int checkSq) + { + // Verify matrix A + if (includeA != 0 && matrixA == null) + { + textOutput.Text = "Error: Missing matrix A!"; + return false; + } + + // Verify matrix B + if (includeB != 0 && matrixB == null) + { + textOutput.Text = "Error: Missing matrix B!"; + return false; + } + + // Replace special matrix types (0 and identity) + if (changeSpecial != 0) + { + // Matrix A + if (MatrixHelper.Equal(matrixA, Matrix.Build.Dense(7, 7, 0))) + { + if (checkSum != 0) matrixA = Matrix.Build.Dense(matrixB.RowCount, matrixB.ColumnCount, 0.0); + if (checkMul != 0) matrixA = Matrix.Build.Dense(matrixB.ColumnCount, matrixB.ColumnCount, 0.0); + } + + if (MatrixHelper.Equal(matrixA, Matrix.Build.DenseIdentity(7, 7))) + { + if (checkSum != 0) matrixA = Matrix.Build.DenseIdentity(matrixB.RowCount, matrixB.ColumnCount); + if (checkMul != 0) matrixA = Matrix.Build.DenseIdentity(matrixB.ColumnCount, matrixB.ColumnCount); + } + + // Matrix B + if (MatrixHelper.Equal(matrixB, Matrix.Build.Dense(7, 7, 0))) + { + if (checkSum != 0) matrixB = Matrix.Build.Dense(matrixA.RowCount, matrixA.ColumnCount, 0.0); + if (checkMul != 0) matrixB = Matrix.Build.Dense(matrixA.ColumnCount, matrixA.ColumnCount, 0.0); + } + + if (MatrixHelper.Equal(matrixB, Matrix.Build.DenseIdentity(7, 7))) + { + if (checkSum != 0) matrixB = Matrix.Build.DenseIdentity(matrixA.RowCount, matrixA.ColumnCount); + if (checkMul != 0) matrixB = Matrix.Build.DenseIdentity(matrixA.ColumnCount, matrixA.ColumnCount); + } + } + + // If sum, make sure sizes match + if (checkSum != 0 && (matrixA.RowCount != matrixB.RowCount || matrixA.ColumnCount != matrixB.ColumnCount)) + { + textOutput.Text = "Error: Incompatible matrices."; + return false; + } + + // If multiplication, check A's width = B's height + if (checkMul != 0 && (matrixA.ColumnCount != matrixB.RowCount)) + { + textOutput.Text = "Error: Incompatible matrices."; + return false; + } + + // If matrix A must be square + if (checkSq != 0 && (matrixA.ColumnCount != matrixA.RowCount)) + { + textOutput.Text = "Error: Invalid matrix."; + return false; + } + + return true; + } + + #endregion + + + } +} diff --git a/Source/MatrixCalculator/MainWindow.resx b/Source/MatrixCalculator/MainWindow.resx new file mode 100644 index 0000000..c67a594 --- /dev/null +++ b/Source/MatrixCalculator/MainWindow.resx @@ -0,0 +1,674 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + 215, 17 + + + 370, 17 + + + 125, 17 + + + 61 + + + + + AAABAAQAEBAAAAAAIABoBAAARgAAACAgAAAAACAAqBAAAK4EAAAwMAAAAAAgAKglAABWFQAAQEAAAAAA + IAAoQgAA/joAACgAAAAQAAAAIAAAAAEAIAAAAAAAQAQAAAAAAAAAAAAAAAAAAAAAAAD///8B////Af// + /wH///8B////AQAAAAsLFRwhLVRxOylMZz0GDBAlAAAAEwAAAAP///8B////Af///wH///8B////Af// + /wH///8BCAgIB0+PuFljtujFZMD8+WHA/v9hw/7/ZcT792K44cFDe5FfCAgIFf///wH///8B////Af// + /wH///8Brre+I47U67eU3vz/YMr6/3vD8P9Nr+v/csj1/2q/8f9v0vv/keX9/ZDR27uFhoY7////Af// + /wH///8BNDQ0BarY8L141P7/csX0/zG09P9Wsur/IZrl/zms7v83p+j/PLz2/2nK9/954f//ms7bwRcX + FxX///8B////AWu33FOX4/3/TsX4/0qd2P8Pidv/eKzX/xh6xv8/l9b/TZXO/yCX4v9zu+j/TMv6/43n + /f9QiJBbAAAAAwAAAANzzPTDhsj3/zKr7/9Zotj/BYbc/02f2v8KgdT/E4nZ/yqM0v8Mj+H/U6Tc/y+z + 8v9zyvj/cMzeuwAAABFCep8Tasz++2zI8/8np+3/TpzU/wCB2f8yhsf/AHPI/y6S2f8+kM//BoTa/1Wh + 1/8jp+z/c871/2/X+fEBAgIhXavfM2PJ//90s+j/HpTg/2acy/8BetD/ZZzK/wxywf88k9T/UZLH/wN5 + z/9Xk8b/GpLe/3i16P9pz///JEZZN16z4zNkzv//W8L0/x6q8f85m93/MqXt/2+25/9otur/cbzt/2Sx + 5v8zpOv/Jo7W/xyl7v9ew/T/a9H//ydKYTVToccRaNL+/YvE8P8onOT/pcXh/2iw4//F2uv/da7a/53K + 6v+gw+D/brLi/6rI4v8nl+D/k8bw/23M+vMDBQcb////AXLd+sNk1Pz/UMv7/3zB7P9gu/H/abLl/12x + 6v9mt+z/ZbDl/2C48P9xuen/U8j7/2XM+/9xxOS5AAAACf///wFv4PdPl+b9/1zF+f+tz+v/YbLm/5e/ + 3v9an9T/hr7l/4u43f9qtOb/q87q/2K+9v+a2/z/V5KwT////wH///8B////AZby/bF56P//htn7/23Q + +v96xvH/Ybzw/2zD8/9uv+//cs34/3zR+f+G5P//ndbptyYmJgf///8B////Af///wHe9fsdm+39tZjl + /f9ry/r/lc30/3O97/96xPH/esDx/4bT+/+Y3/3/ndjwt8PGyCf///8B////Af///wH///8B////AbGx + sQN+3PhLd9j7wW3P/v1ly///Z8v//27N/ft60vS9fb/cS25ubgX///8B////Af///wH///8B////Af// + /wH///8B////Af///wFQlMEPX67kMVum2zE+cZURAAAAA////wH///8B////Af///wH///8BAAD//wAA + //8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//ygA + AAAgAAAAQAAAAAEAIAAAAAAAgBAAAAAAAAAAAAAAAAAAAAAAAAD///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAAAFAAAACQAAAA8AAAATAAAAFwAAABMAAAANAAAACQAA + AAP///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////AQAAAAMAAAALAAAAHwAAAC8VJzVFLVJvWzxulHE5aY5tKUxlWQ4b + JEUAAAA5AAAAKwAAABsAAAAJ////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAAALAAAAIzttkmNYotixYrX152O6//9gt/7/XrX9/161 + /f9hu///Y7z//1+z8d1Tnc2nKU9mXQAAADcAAAAfAAAACf///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAAADCgoKGUJ3nWFnu+3TcMz//2zM//9nyf//Y8j//2HI + //9kzv//ZdD//2PM//9mzP//a9H//2/T//9z1v/9acLjwzFXaV8KCgo1AwMDEf///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8BhISECXyEiUOO0ue1lu7//4Te//9t0f//ceb//1vG + +v9vwfT/UK/w/0vF+/9T0Pz/b770/2i+9f9bzfz/ceb//3LX//+F5f//m/j/+5TM1bNsbGxjXl5eK0ZG + RgP///8B////Af///wH///8B////Af///wH///8B////AampqQuxvMR5mNf25Yro//+F1/7/sNb4/1ip + 6/9Lyv7/cbbo/7DP6/9ppdj/L6Xr/0q79P+81+7/sdHs/zWh5/9Myf7/jcPw/7Lb+v9z3P//ifT//6fa + 6teNjo+Hk5OTN////wH///8B////Af///wH///8B////Af///wH///8Btb3DYbXa89Wi1f//b9b//4HG + 9/+z0+//PZnf/zW8+v9gp97/q8vn/zuIyf8dluP/KaTt/4q44P9/s93/JJDc/zW9+/9lquT/ttjy/17A + +P9y5P//ltz//6TR4cGSkpKBDg4OEf///wH///8B////Af///wH///8B////ATc3NxGT2fC9rN///2zD + /v9k4f//UcX6/0S38v8suPn/JsP//x6r9f8wrPD/F6Du/xSs+v8UsPz/HKPu/x6o8P8dtPn/J8n//zDA + +v9Hxvf/S8z8/2fr//922v//o+r//4nO1r8cHBw5AAAAB////wH///8B////Af///wEAAAADXaDFYaj6 + //+E5P//ZNr//1Hc//9Ar+z/LZHY/xeN3/8Rmu3/NovO/2mh0f8cb7f/BoDX/xGO4P84gsH/W5nO/wx3 + yf8UpfT/KJPe/2Ky5/9BtvD/VeT//2Lc//+F7///qf///TxjbGEAAAAd////Af///wH///8B////AQUJ + DA95zvbZjd3+/6PQ9/9Mq+//N7Ty/3Kq2f9IisL/CnXF/wmJ3P+HtNj/udHl/zyAuv8Cec//GY7c/5u9 + 2//C1+n/C225/wqW5/85j9D/zN/v/1+l2v86xfr/Pqnw/5jS+v9v3P//fNXfvQAAADUAAAAH////Af// + /wH///8BVJnKXYHd//+Nz/v/udfy/z2k6P8yqOr/lbzf/2idyv8HdMX/B4Xa/26j0P+oxd//KHO0/wB4 + 0P8Cgdj/S4m//5S52P8Ka7f/BY/k/yeDyP+10Of/W57S/yy18v87puj/t9r0/1bC/P+L8v/7IURQVQAA + ABf///8B////AQAAAAVhsu21ft///2jA+/9puvP/MrH0/ymv9v9Go+L/IYzW/wSN5P8Bk+//CIfc/xaN + 3f8AhNz/AJTv/wCX8v8AhNz/CYfb/wCH3/8BnPX/Bo7j/yCQ2v8elN//I7X5/zS69v9nw/b/Wcj8/4Pv + //9PoMKbAAAAKQAAAAP///8BESApD2W9+/N23v//Y93//0bN+v8uwfz/G6v1/ymW3v8PgM//AYji/wCM + 6P8Ies3/FH3L/wByx/8AiOT/AI7p/yKFz/8lh9D/AnnQ/wCR7f8Jit7/Pp7d/ySV3v8ds/f/McH6/0zP + +/9o5f//gfD//1++6c8AAAA1AAAAB////wFOj7s5ZL///2rX//+GwfT/gLTh/x+X4/8zmd//o8Tg/12V + xP8AdMj/AHvT/zh/u/92pMz/AVml/wB4z/8JhNn/jLPV/7/V5/8TbbX/AIPc/w9zv/+Xu9r/WpbJ/xiU + 4P8kld7/n8fp/3u/9P914v//Zcf89wIFBj0AAAAL////AVqn2l9gvf//Z9T//6TP8/+OvOL/HJbh/ySP + 2P+wzOT/XZTE/wB1yf8DfNL/To3C/5a61/8YaK3/AHjP/xGI2/+UuNj/zt/s/xdvtf8Ag9z/Bm28/2OY + xv9knMv/GJLe/x6Q2v+w0Ov/jcLv/2/d//9lx///I0RWVQAAABH///8BXq/kbWC9//9l1f//Uqjv/06b + 2/8cnOn/Ho/d/2mh0P8icbX/AHjP/wR/1/9Ah8L/cKPO/xlss/8Ae9T/BYTc/0eIwf9WksX/CGi2/wCF + 4P8HcMP/VZLG/0CHw/8UkuL/HZPg/0mW2P9aq+//bNr//2LA//8yYXxjAAAAE////wFesuVtYL7//27j + //9X3P//O8v+/yPE//8Vsfz/HqLu/waT6v8AmvX/EaL3/z6r8P9ct/H/YLry/2PB+f9jwvr/Zbvy/1Oz + 7/81qfH/EaT4/wCV8f8KlOn/Dpns/xWx/P8oxP//QMz+/1vd//926f//Yr///zNffWMAAAAR////AV6z + 4l1fwv//Ztb//3q88/9ipt//G5zq/yaX4f9+sNj/QofD/02h3/9ttun/ibbc/5vA3/90qdT/a7Tn/225 + 7f+Rut3/mb/e/2+p2P9rue7/U53W/02Oxv80f7//E47g/x+R3v91sOL/a7Tx/3Hc//9kwP//J0lfVQAA + AAv///8BWa3WN2PG//9p2v//nc/3/5rE5/8fmeP/IJPd/5e93f+bvtz/Z6zf/2615/+81Oj/1OPv/4ix + 1f9nr+P/drvq/8ja6//Y5fD/cqfT/2e26/9/tN3/3+rz/3eo0v8WkN7/KJPa/8DZ7/+EwPL/dd7//2W/ + /PkFCg05AAAAB////wEwX3QLZcr99XDg//90w/n/gbvp/ySc5v8/qen/vNXq/6TF4P9kq97/abPn/7PP + 5v/U4+//gKzS/2St4f9wuOn/xtnq/83e7P9so9H/ZLTr/26p1/+50eX/mb/e/y6g5/8wmOD/nsjs/2y3 + 9P963v//X7Lr0wAAACkAAAAD////Af///wFlyvaze+n//2zq//9V2v//ONX//1/R/f97x/H/bLjn/2G5 + 7/9gu/L/bLHj/3y45P9iqN3/X7Tu/2C38f93tOH/dbPh/2Cr4v9fvPT/YbHo/2my4/9uvO3/Yc/8/zvP + /v9c1///c+X//4Xl//9UmcqdAAAAGf///wH///8B////AWLH7Fl65///adL//2a59f81tff/dNP8/5HK + 8P95vOj/YLju/16/9v9dr+f/YLDm/1uv5/9buvX/W7z2/2W16v9ksuf/XLLq/16/+P9itOv/erzn/3O7 + 7P900/z/PK70/2m18/9ev/3/heD//SxRa08AAAAJ////Af///wH///8BN3KEB3Dk+92A5P//pdX4/zyp + 8P9y1Pr/rdDs/6nJ5P9gqd3/XLXr/3Go1P+rx+H/V5LF/1am4P9brub/o8Pf/7nR5v9anND/Xbfv/3av + 3P/Q4fD/kL/k/3XT+/9Cn+f/rNP1/3vT//9wwOW/AAAAH////wH///8B////Af///wH///8Bbt3xV5b5 + //+i5/7/WL38/2na//+n0vD/t9Pr/2qv4f9evPD/fbLb/8TY6v9nnMv/Vafh/2Cz6f+81Oj/w9jq/1id + 0/9eu/D/eLDe/8zf8P9/uuf/a9T+/2W09/+l2/7/m+z//URsiFMAAAAJ////Af///wH///8B////Af// + /wFxcXEDp/j7t4f2//916///b/X//37j/v+D0vX/asb1/2TO/P9yve3/mcns/2qr3v9YtO//Wrny/5HC + 6P+Mv+f/XLDp/2bL+/9vv+//hs/0/3zb+/9z8P//fuT//5Ts//+f2ea1KCgoF////wH///8B////Af// + /wH///8B////Af///wHK7fMrjuv+45bd//9s4///dNT+/6La+v92zPn/cuH//2nJ9/9yyPT/YcH0/2LO + /f9j0P7/YcH0/2nD9P9oy/r/c93//4DO+P+O0Pn/Ycv+/3Lc//+14f//nMvsxbGys2UcHBwD////Af// + /wH///8B////Af///wH///8B////Af///wXb9PtlqOv+33no//963f//s9r4/2my7v9u1f//iMXx/8Lb + 8f+OveT/aL/z/2rH9v+KuuP/osjp/2y98f9u0f7/s9b1/7XZ+P941P//gd3//7LW8MvAxMZ7rq6uDf// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wXa8fY7pfb8vZv5//+Z5f//csv9/2TZ + //9hwPr/qtP1/3m37P9fw/r/ZM38/5HE7/+Fvu//VL77/2TV//+Rz/z/k9z//6L1//+d3fC9wsTFV9/f + 3xf///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wGxsbEFftrzT3/g + /NN94f//g+j//3jj//9w1///ZtH//2zd//9v4f//Z8///2/U//995P//iev//4bh//+D0vHDf7DMV2ho + aBGqqqoD////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8BJ01fBWO87lVnwPazZ8P982TB//9iv///Yr7//2O+//9kvv//Zb///2a++u1ktuurUZLBTwUF + BQ3///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEsUWoJVqDQM12t4FdgrudtXavha1ih1FVKiLMzAAAACwAA + AAX///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAoAAAAMAAAAGAAAAABACAAAAAAAIAlAAAAAAAAAAAAAAAAAAAAAAAA////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAAAwAA + AAMAAAAFAAAACQAAAAsAAAAPAAAADwAAAA8AAAANAAAACQAAAAcAAAAFAAAAA////wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA + AAUAAAAJAAAAEwAAAB0AAAAjAAAAJwAAACsAAAAvAAAAMQAAAC8AAAArAAAAKQAAACUAAAAfAAAAFQAA + AAsAAAAF////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wEAAAAFAAAADQAAABsAAAApAAAANQMGCT0kQ1lVM15+Z0F4ontLi7uRSIa1iz5zmncvWHVjHDREUQAA + AEEAAAA9AAAANQAAACsAAAAfAAAADwAAAAf///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8BAAAABQAAABEAAAAhIT5TRTloi2dPkcGXXq/r02W6+/dlvP//Y7n+/2G4/v9ht/7/Ybf+/2G5 + /v9kvf//ZL7//2O5+O9aquPFR4axiy1XcGURISpJAAAANQAAACcAAAAVAAAABwAAAAP///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////AQAAAAMAAAAJAAAAHR86TT1IhbF5Xq3jwWS6+O1kvf7/Y7z//2C6/v9euf7/W7b+/1y4 + /v9bt/3/W7j9/1y6/v9evf//X73//2K///9kwP//ZcL9+2G+8uFYqdezO3GPcQ0ZHkUAAAAzAAAAIQAA + AA8AAAAD////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8BAAAAAwYGBg8NDQ0jQ3WaZWS26sNux/nvdND//3PS/v9w0///a9D//2jP + /v9lzf//Y83//2TQ/v9n1///adr//2TS//9l0v//aNL//2rU//9w2f//ddr//3bc//943P7/dNb152S4 + 2bExUF9dDw8PPwkJCSkDAwMRAAAAA////wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wF6enoHbnJ0KWiEkFWDx+Otkur//Yzn//+G4f//d9v//3fk + //957P//ZNb9/2HH+v9pxvn/Urj3/0u6+f9T0/7/Wd3+/1jB+v9pwvr/ZcT6/1zI+/9o3f7/ee7//3bk + //9+4///iun//5Lz//+a9//3irvHpWh5fG9UVFRLU1NTJTw8PAv///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Abu7uxGxsbFBnrzKj5Tc8dWg9f/7k+z//4nZ + /v+N0fv/Ybj2/1PA+/9X0v7/Wbbz/3636f+axuv/c6/i/ziY4f88t/f/R8n7/2i07P+qz+//ocvu/1ao + 6P9GuPf/W9b//1i/+v+GzPr/lNj9/4Dd//+T9f//o/v9+ZHa5s2Rn6SbkJCQeYSEhDtXV1cJ////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BqampCcfHx1Wes8OHmNb46YHZ + /v2K6f//f9f+/7HZ+v+z1vX/Y6vo/0S29f9Gxv7/ZbPp/5rD5v+y0Ov/gLLd/yyL0/8vqvD/QL74/367 + 6P/N4fL/w9vw/1yk3f82p+v/Ssv+/0yy8/+p0vP/xOL5/4fO/P9z4P//jPT//4vn/vm13+3ffYGCfZiY + mHmNjY0xAAAAA////wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BrLCyN5+5 + yY++3/bhuOD//3nN//902///bcL6/7HV9P+qzu3/SJrc/ze08v8zt/j/Xajg/6zM6f+z0On/U5XN/x6B + zP8gnej/Kazy/1ul3v+20ur/pMnm/0uX1P8omeL/N7/8/zOl6v+Lvun/w9/1/4XF8/9gyfz/d+n//3LY + //+s5f//stnnzZWgo52Dg4NhEBAQEwAAAAP///8B////Af///wH///8B////Af///wH///8B////Af// + /wEuLi4Jk665X6rd9unM6v/9nND9/2jH//9m1v//br/6/5PF8P9mrOT/MZfk/y61+P8ruPv/MJ7m/1eq + 4/9eruX/LZTb/xaR4P8ZpPT/G635/yab5/9Ho+L/QKPh/yiX4P8ho+7/LL/9/y2w9P9QrOv/er7v/2S0 + 7/9Tv/v/aeT//2vW//+W2v//u+r995fP3cl+i42DGhoaLQAAAA0AAAAD////Af///wH///8B////Af// + /wH///8B////AQAAAAU+Pj4dk9byu5fh/v2l2v//Z8L+/2TW/v9f5P//TtD9/03J+v85wPf/LMD6/ynI + /v8jwf//G7D5/yWs8/8lqvH/FaLv/xGk8/8SrPv/ErH8/xOm9v8Yo+//G6fx/xqt9P8euvz/I8f//ynK + /v8zy/z/Qc/7/0jU+/9R3P7/ZO///2vn//9z3f//n+n//4Hs+/OUzNTDJycnRQAAAB8AAAAH////Af// + /wH///8B////Af///wH///8B////AQUICQ9gnsNrrvv//4/v//+G5///b+T//2Tq//9S4f//P7/1/z2s + 6/8klN7/GZDi/xek9v8Rme7/H4XR/0uTzv9Hjcr/F264/wZuwf8HiOD/C5Pp/xd6yP8jdbz/PYfG/yF7 + xf8NgdX/Fab3/xij8v8qmOP/Tq3p/0y38v9Bxvj/Vuf//2Ts//9x6f//i/T//5n7//+w///7P15lYwMD + AzMAAAAT////Af///wH///8B////Af///wH///8BAAAABTxrizF1zfXJo/P//4bc//+Cz/v/VLb3/0fG + /f88uff/UJ3c/22l1/8mdrz/DnLC/w+R4v8LiNv/XJ3P/5u+2/+lxN//Uo7B/wNmtf8EgNf/D5Hj/0qT + zf+MtNb/ts/k/1WTxf8KdML/DJXn/xCR4P9JlNH/qcrm/4a44f9Go+L/P8n8/0jM/v9Htff/edX9/37j + //+a9///c8zZrQ4VF0MAAAAjAAAABf///wH///8B////Af///wH///8BBQkMC1ym2nWE2/3zjOD+/63Z + /P+o0fT/U6jq/zy7+P8xqev/U5fR/5i93v8qdbf/CWy7/wqM3/8Igtb/fa/W/7TO5P+2z+T/WJHD/wBj + s/8BfdX/DI3i/1GXzv+yzOP/zN3s/2CYx/8HcL7/CZLk/wuN3v9OltD/zt/v/6nK5f9Jm9f/M7v2/z/C + +v89pOr/mM/3/4XR/f914v//ju304zpvg2kAAAAzAAAADf///wH///8B////Af///wH///8BQnmfMWi+ + 8MeJ4///e879/8rj+f+qz+//RJ/j/zK09P8woeX/c6fW/7DM5P9QjcH/CGu6/waJ3v8JgdX/aaLQ/7TN + 5P+tyOD/Roa8/wBktP8Afdb/AYfg/xx2v/9tn8r/q8fg/1mSxP8Hbrz/BYvh/wWJ3P8+i8j/wNfq/6LF + 4f9IldH/Kq/u/zS99/8+oOT/ns3w/5LQ+/9ezf7/l/f//Vu70akMGR5FAAAAGwAAAAX///8B////Af// + /wEAAAAFUpXFW2rF+/OL6P7/bcD8/7PV9P+JvOn/N5nj/y6y9f8zoOb/cqnY/4Gw2P86gr//BG7B/wSM + 5f8Egtv/Jn7F/1ub0P9Lkcv/FHG8/wBvxf8AheH/AI3o/wVzyP8cdr7/P4vI/yN5v/8DccX/A4/o/wSN + 4/8ZesX/Y57R/1+d0P8xiM3/IqPr/zC6+f85oeX/icHs/47L9v9WxPz/k/b//2XQ7dUnUWFdAAAAKQAA + AAn///8B////Af///wEAAAAJXarin2fE//+H6f//XMH+/2/B+/9Rtvb/M7P4/y3C/f8osPj/N6Xp/zSh + 5f8UkN//BJHp/wOd9f8Al/H/Ao7n/xKU5/8Kkub/AI3n/wCT7f8Am/X/AJ73/wCT7f8Ajub/BZDm/wOO + 5v8Akuz/AJ32/wOh9v8GlOn/GJjk/yCd5f8Zn+r/ILb6/y/J/v82vvn/UcD5/2HI/P9d0/7/jPX//2zZ + /Pk/f5p7AAAAMwAAABEAAAAD////Af///wEKExkRZbr342XD//9/6v//bej//1jf/v9I2vz/M8r8/yjG + /v8asPj/Hp7o/yKZ4v8JiNv/Ao3m/wCX8v8AkO3/AoLa/xCF1v8JgNT/AHvS/wCD3v8AkO3/AJby/waH + 3/8fjNn/HYvZ/wuC1v8AhN7/AJTw/wGZ8v8LkeT/L57k/zOk5/8Ynen/Hbf5/yvK/v82zPv/TNr8/2Lm + //9z8P//iff//3Hc//9WrNKvAAAAOwAAABsAAAAD////AQAAAAM+dJcvZ8L+/2bG//904f7/XsH8/2S6 + 8v9IpOb/JJrp/x6q9f8pleD/WZnQ/16Yy/8odrj/AG3C/wCG4f8AedH/EGm0/1eSxf8zerf/AFmn/wBn + uf8Af9n/Aoni/x56w/9vos3/fKrS/z2Cvf8Fabr/AILc/wCD3P8VdL//dajT/3mr1f8pfcP/F5Ti/yGt + 9f8nl+T/WK3p/2vB9f9dx/z/fOv//2/Y//9gv+/bAAAAPwAAACEAAAAF////AQAAAAVTmslbZcD//2PG + //9p2f//g8H2/7XV7/94r93/H43b/xqg7P9DnNr/osPf/6PD3v9RjL//AGu9/wCF3v8Adsz/HW+z/5e6 + 2P9bksL/A1mj/wBktP8Afdb/BYng/ziIyP+qx+D/zt7s/3KjzP8Ka7b/AH/Y/wCB2P8Ub7j/iLHV/6PD + 3v8+hcH/F4zY/x6l7P8li9b/ocfo/7XW8f90vfT/cuH//27V//9myPz5BQoMQwAAACUAAAAH////AQAA + AAddreGDY77//2TH//9m1f//mcr0/8ng8/93rdv/HY3a/xee6/8ih9D/j7fZ/7bP5P9Mib3/AGy//wCF + 3v8DeMz/K3e3/5y+2v92pMv/Gmms/wBltf8Afdb/CIvh/0SOy/+qx+D/1+Tw/32pz/8Ma7f/AH/Y/wCB + 2P8FZbL/N3u1/4mz1f9EicL/F4vY/xui6/8ehtH/rc7q/8ff8/96uu//atr//23V//9mx///KVBlXwAA + ACsAAAAL////AQAAAAdhs+mTYr7+/2PH//9i0/7/arLu/6bM7P9pptn/HIza/xee6v89ltb/n8He/5i7 + 2f83e7b/AG3A/wCF3v8Hec3/RYjA/5q92f+UuNb/Nnu3/wBktf8Afdb/B4rh/zmHyP+Wudj/sMrh/2CW + xf8IabX/AH/Y/wCB2f8RbLb/fKnO/52/2/9LjcP/GIvX/xqh6/8dhdH/ZaPW/6nN6/9us+3/adb//2zS + //9lxf//OG2LbwAAAC0AAAAN////AQAAAAditu2fYr7//2PH//9j1///Rab2/0+i5f8zjdf/HJXm/xak + 8/8Zhtf/Q4vH/0WJxP8OZrL/AHHI/wCI5P8EfNT/KXu//16Yyv9Xk8f/HW+2/wBpvf8Agdz/AYrl/xFz + w/8+hMD/P4S//x1vtf8Carz/AIPf/wCF3/8Ha73/NX69/1CQx/8idb3/EIvd/xql8v8di9z/MYnU/1Oi + 5P9Jp/X/adn//2rO//9jwP//P3udeQAAAC0AAAAN////AQAAAAdiue6fYr7//2TJ//9v6v//WOD//0vX + //81yv7/JcT//xq+//8Tr/r/GKDu/xSZ6/8Dker/AJfy/wGe+P8Mnvb/I5/t/0Gr7f9Rsu//WLXw/126 + 9f9ewPn/XsL6/1679f9dt/D/Sa7t/zCj7P8anvD/CqD3/wGd9/8Bku7/CZLo/xWa6v8Omez/E637/x/B + //8qw///Ocr+/0/Y//9e4f//d+3//2vQ//9jvv//QHieewAAACsAAAAN////AQAAAAdiuuyVYcL//2PJ + /v9o3v//VsP7/1m+8/81qez/IKz0/xmz+/8eoOz/N53f/zKV2/8PgdL/EJDl/zGr9P9MsPD/abPn/369 + 6f92uOb/bLTl/2y47P9swPX/bMP3/2657P95u+j/eLnn/3G15v9mtev/S7T0/zGp8v8Ridz/A3rN/w+B + 0f8KgNP/E5zt/xyw+P8jpu7/Oqrq/1q+8v9Vwvv/ceP+/2vP/v9kwP//Om2PcQAAACkAAAAJ////AQAA + AAVguOiDYcL//2DJ/v9m2P7/fr71/5vH7P9ipNz/G5Dg/xik7/81l9r/h7Ta/4Sx1v9OjcP/WKDY/2a4 + 7v9vs+X/jLfb/6nH4v+kxOD/f63U/2qn1/9qten/bLvv/36z3f+lxeD/q8ni/4u12P9tqNf/arbq/2i2 + 6/9jodP/a5/N/3ip0v8terv/E4bX/xqd6v8ghdP/gbbi/5fF6/9rtfP/bdr//2vN/v9mwf7/LVVwXwAA + ACUAAAAH////AQAAAANcsdxZZcb//2LK//9p3f//iMX3/8bf8/+CteH/Ho/b/xum7/8qkdj/ibTZ/77U + 6P+Qt9f/Z6fZ/2e37P9xtOT/ss7l/8/g7f/S4u7/mLva/2ej0/9nsuf/brvt/5fB4v/S4e7/3Ojy/6XD + 3v9tptT/Z7To/2u26f+GtNr/1ePv/9vn8v9IisL/FIjX/x6g6v8ritP/s9Hr/7/a8v9zufP/dN///23O + //9mwP37ChQaQQAAAB0AAAAF////Af///wFRn8MtZ8v+/2HK/v9x4v//hMf7/8Hd8/+Ju+P/H4za/x6p + 8P8slNr/krrc/7/W6f+bv93/ZqbY/2W26/9wtOX/ttHn/9Tj7//T4u7/lrrZ/2Wi0v9mseb/brvt/53E + 5P/Y5fD/3ejy/6LB3f9rpdP/ZbPo/2i06P+Cs9n/0uHv/+Hr9f9poM7/GY3a/yCh6/8yj9b/uNXt/7rX + 8f9wuPb/eOH+/2rL/v9htvDfAAAANwAAABcAAAAD////Af///wEiQ1ILZsr76WLM/v966v7/XsD8/4HB + 8v9kreT/JJLh/yKt9P9Wruf/stDo/7zU6P+Yvdz/ZKbX/2O26/9qseT/o8Xh/9Lh7v/L3ev/jLPV/2Og + 0f9jsOX/aLjs/4+84P/S4e7/0eDu/5a62f9no9L/Y7Lp/2Oy5/9updL/n8Dc/8fb6/9/r9f/QaTm/yKl + 7v8zk9z/hrrn/4W97f9ctfn/gub//2rH/v9YpNm1AAAALwAAAA////8B////Af///wEAAAADYsXwn2bS + //+E8f//ce///2Pd//9L0v//Nsj//znN//9myvv/d77s/4TA6P9orN3/Ya/l/2G88/9gtOz/aqrd/4e4 + 4P9+s93/ZqTW/1+m3P9fs+3/YLjx/2ms3/+Ft97/gLTc/2un1/9gqN7/X7fw/2G37/9iqN3/Z6nZ/2+v + 3/9ttej/Zsj5/zzH//85wv7/Usz//2nY//915///j+///2vH/ftFfqZ9AAAAIwAAAAf///8B////Af// + /wH///8BYMDmV2nV/fWE7///auL//1zO/v9Nyfv/PNH+/1De//9x2P//eND6/3fM9v9pw/T/YcL4/1/I + /P9exPv/Xrrz/2W88v9iuvH/Xbjx/1y79f9dwPr/XMH6/1679f9lu/H/Y7rx/1648P9du/X/XsL6/2DE + +/9hvvX/asLz/2/F9f9vy/r/ctn+/1PZ/v9Bz/7/Usr8/1/L/f9v2v//k+7+/2e/8NswWHRXAAAAFQAA + AAP///8B////Af///wH///8BXLzfKWrX+cmA6/7/cdz//3/J+/9jtfD/M6bv/1TN/f92zfj/lMft/5jI + 6v92s+H/YK7k/1699P9dufH/Xani/2Kp3v9fqN7/Wqff/1qt5/9auPT/Wrv3/12w6P9sseP/aK3h/1+p + 3/9crub/Xbv1/1648f9lrOH/e7Xg/4G55P9zt+j/dMz5/1fF+v8/ouv/crbv/2i09v9oyf3/jub+/V+t + 2K0VJzM3AAAAC////wH///8B////Af///wH///8BO3mNBWbR9HN16f71huv//4XS/P+YzfT/OaPs/1TH + +/90z/f/rdDs/83g8P+Xvt//YaTY/1237P9bsef/ZKLT/6bF4P+Rttf/V5LE/1aaz/9WquX/WLLs/3Cq + 2P+px+H/ts/l/4Ct1P9Zn9T/XLXt/16y6P+Cs9v/zd/v/7zV6v+Hu+P/dc34/1e+9v9JnuT/qNDz/4LF + +v+C2v//f9X25UJ1m2UAAAAbAAAAA////wH///8B////Af///wH///8B////AVu+3Cly6vvJmvf//4zf + /v+44fz/VrLy/1LH/f9z1Pz/kcTp/7vW7P+lx+T/Z6ja/1657f9ctOv/Z6XV/7bQ5v+nxeD/W5TF/1WY + zv9VquT/WrPs/36y3P++1ej/0ODu/4mz1/9ZoNb/XLbu/16x5/9/sdv/yNzt/7/Y7P9/uub/dtP8/1K7 + 9v9cqer/wuD6/4vP/f+d6v//abjisRIfKDEAAAAN////Af///wH///8B////Af///wH///8B////AS5j + cAVw3PFjnP3//5Xz//+d6P7/XsL9/1DM/v9v2v//ntHy/7/a8P+y0On/ca7e/1+78P9due7/eLHd/7rU + 6f+/1ej/eafQ/1WZz/9Vq+b/Wrbt/4O23//T4/D/y93t/3+u1f9Zotj/Xrrw/16x5/+LuOD/yd3v/6rM + 6f93uur/cdX+/1K+/P9yvfv/o9v+/4ng/v+o8/75RWZ8VQEBARkAAAAF////Af///wH///8B////Af// + /wH///8B////Af///wFxcXEFkvb8r6L+/v2O9///fO///3Dy//9q8f//fN7+/4zT+P98wu3/aLjt/2TI + +f9ixvn/cLnp/5bF6P+iyej/d67b/1ei2/9Ys+7/Wbrz/3Cy4/+tz+v/nsbm/26s3P9brub/Y8X5/2W+ + 8v9zuOj/h8Xt/4HG8/961vz/buv//3Ln//+C5f//mu///6r3//mb0N+tLy8vIwAAAAf///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8BuuruRZn3/dt/6P79ieL//2rk/v9v8f//bub//4fj + //+E3v//c9r//3Di//9r3///atL8/3LO+f9zy/b/ZsT0/17E9/9ezP3/X879/2HF9/9ux/T/ccj1/2jH + 9v9mz/z/bdz//3Da/v921v3/g9z+/3vb//9u5v//du7//3jg//+U3///md/++ZfW8NuNnqZlJCQkDf// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B1OvvEbTy+3OM6f7ru+n//2DP + /v9x5///btb+/6PY+v+k1vj/ecP0/3LT/P9x2///asP2/3K+7/90wO//YLfu/2C+9f9jzf3/ZNH+/2C+ + 9v9hue//abvv/2e68P9px/r/ctr//3PL+f+My/X/mND2/3C/+f9kz/7/d+H//4nT///R6///pNDv0Zyt + uYmoqKk7HBwcA////wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////A/v7 + +zu87ft1xPD+6Xre/v1+6v//dN///5HS/P+02fb/cbXs/2jC9/9z1v//icnz/7DS7v+/2fD/msPm/2at + 4/9nw/f/as36/2yx5v+Nu+P/psrp/3q15f9twfT/ddb+/3jD9f/H4ff/xeD4/4PG+v942P//heL//5TW + /vvK4vPbsrm9gcnJyVWkpKQJ////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af7+/gf7+/s7uu76fZTv/t2U9/79j/P//5Le/v+w3fz/gMP2/1a8+v9h0///Z773/5vJ + 7//K4fT/pszs/2yy6P9wy/r/ddb7/3i67P+qzuz/sdLu/3K16v9hwvr/ZdX//3HC+v/N5fv/ut78/33P + /f+N6v//kOn/+ZPS89OjtcJ/ysrKT+Hh4R/b29sD////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8F5/P2Hbjp8Euh9Py9pP3//5fy//+W6P//dtP+/2PP + /v9q4P//Xcj9/3zB+P+fzfX/eLju/1Gr8f9ayf3/YNb+/2C19f+SxfH/hr7w/1ev9f9byv7/bN///2fF + /v+Hz/7/kt7//5br//+v+v/9oNzvu6y+yGnExcU13t7eE/Ly8gP///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AczMzAOsrKwJfdbzW4Xn + /MGF5v7xg+X//4To//+J8P//fOn//3Hb//9u1f//Ys7//2HQ//9r4f//b+f//2PR//9iy///bNL//3La + //+C6v//jvL//4ro//+L5P//juD76YzY9LmErsdjaGhoG39/fwuqqqoD////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8BWVlZA2Wz2h9px/RnbM75x3DR/vVy0v//b9H//2vO/v9ozP//Z8v//2jM/v9r0P//bND//2nM + //9qy///asv//23N//9x0P//d9T//3XO++9wwuy5WZzLXztVZyE5OTkLMjIyA////wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEqVGgDXbLgJ2G36VVkuvGdZ8H652jD/v9lwf//ZMD//2O+ + /v9jvf//Y73//2O9//9lv///Zr///2jA/ftlufTZXarekVGTwFE9bI8pBQUFCQAAAAP///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wEAAAADHjhJC06Q + vClZpddTYLLnfWGy6o1jte+hYrPsn16t5Ilbp9x3UZTEUzNefCUAAAAPAAAACQAAAAP///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wEAAAADAAAABQAAAAUAAAAHAAAABwAAAAcAAAAHAAAABQAAAAP///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8BAAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAA + AAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA + //8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAA + AAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA + //8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAA + AAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA + //8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//KAAAAEAAAACAAAAAAQAgAAAA + AAAAQgAAAAAAAAAAAAAAAAAAAAAAAP///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wEAAAADAAAABQAAAAcAAAAJAAAACQAAAAkAAAAHAAAABwAAAAUAAAAD////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////AQAAAAMAAAAHAAAACwAAAA8AAAATAAAAFwAAABsAAAAfAAAAIQAAACUAAAAjAAAAIQAA + AB0AAAAZAAAAFwAAABMAAAANAAAACQAAAAX///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8BAAAABQAAAAsAAAATAAAAHQAAACcAAAAvAAAANQAAADcAAAA5AAAAOwAA + AD0AAAA9AAAAPQAAADsAAAA5AAAAOQAAADcAAAAzAAAALQAAACMAAAAZAAAAEQAAAAkAAAAD////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////AQAAAAMAAAAHAAAADwAAABsAAAApAAAAMwAAADsAAAA/CRAWRzNd + fGk1YoNvSoe2j0uKupVXoNi1VJvRrUqHto9FgKqHMl17aypOZ2EAAABFAAAARQAAAEEAAAA9AAAANwAA + AC8AAAAjAAAAFwAAAAsAAAAF////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////AQAAAAcAAAAPAAAAHQAAAC0AAAA3EiArSUV/ + qYNZpNu5ZLj26Wi///9ov///Z73//2S6//9kuv//ZLr//2S6//9kuv//ZL3//2fA//9nwP//Z8D//2Cy + 7dVSmsylOWmMcwAAAEUAAABDAAAAPQAAADMAAAAnAAAAGQAAAAsAAAAD////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAAAwAAAA0AAAAbAAAAKwAA + ADk7bZFvW6ffvWe+/flov///Zb3//2S6//9gt///XbX//1qy/f9bs/7/W7P+/1iv+/9Yr/v/W7P+/1u2 + //9euf//Xbj//2G6//9ivP//Zb7//2fB//9jvvXnUp3KoxoyQFUAAABDAAAAPwAAADUAAAAlAAAAFQAA + AAkAAAAD////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAABwAA + ABMAAAAlAAAAN0F2nnditPDVa8T//2jC//9kvv//Ybz//2K9//9gvP//YL3//169//9cu///Xb3//16/ + //9ewP//X8H//16///9dwf//YcP//1/B//9jw///Y8P//2XD//9lwv//Zcn//2jK//9pyv/7W6/dtyZI + WF0EBARFAAAAPQAAADMAAAAhAAAADQAAAAP///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wEAAAADAAAACwkJCRsQEBAvOFt1XWS49M9xzf//dM///3jV//931///edv//3Xb//9w2P//bdb//2vV + //9m0///Z9T//2XU//9o2v//bOL//2/l//9o3P//Zdb//2nY//9s2P//a9f//3Dd//924v//e+P//3rg + //9/5f//fuH//3zj//953f/7Xq7VpyMsMFMVFRVJDQ0NOwcHByUAAAAPAAAABf///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wFVVVUDS0tLETIyMik/Pz9Fdrznr4rl//2Q6f//jOb//4jl//+C5P//fuf//4Tz + //+B9P//b+X//2DT//9jzf//Ysr//0/A/v9Pvv//Usv//1vf//9g6f//V9D//1jA//9gxP//XMf//17M + //9m2v//duz//4L2//9+7///gu3//4nu//+P7///k/P//5v6//+U9P/veqa7l1paWmk0NDRJKysrMS8v + LxscHBwJ////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wGqqqoHgICAG5SUlFGLm6eBmOP/4az8//+w/P//ke7//4Hd + //980///XsH//1a7//9i2P//X9n//1G+//9Nou3/ebfq/3+56v9nq+P/PZTg/zun8P9Gxv//Tdj//0iw + 9f9rruf/mcfu/4zB7v9ap+n/QKj2/1LJ//9n4v//X9H//1a+//9nxv//etT//3ng//+P9v//r////7b/ + //+b4/TNjY2Nl4CAgH15eXldTU1NKUZGRgv///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wHGxsYJvLy8L7u7u3+owdSzn+v/8Y3r + //+f+P//gej//3bK//+g0v3/nMz3/3S27v9CofH/VM///0/L//9YtfD/hbnl/63O6/+61u7/pcno/zqL + 0f8xnOP/N7j6/z3L//9Zsu7/mMLn/9jn9v/V5/X/jL3l/zSW3/9EuPr/UtL//1DE//9erO3/xOL5/7vf + +/+Lzf//btX//4b2//+c////h/v//5jj+tGdoaKpnZ2dq6SkpI1eXl4nVVVVCf///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wG/v78Fnp6eHc/P + z7F+pcGFm9v/84TT//9y1P//i+v//3HT//+u1/v/z+X5/7XW8/9vruX/PJ/q/0nO//9Bwf7/WLDq/4+8 + 5P+oyuj/tNHr/5jA4v8tgMj/J5Lb/zCw9v81wf3/X7Hp/6PH5//f7Pf/1eb0/4685P8pitX/Nq3w/0jN + //9Iwv7/S5/m/8ji9v/W6vr/rNb3/2nE//9y5P//kPb//3Li//+i6f//xev552ducGt/f399sLCwi2ho + aCEAAAAF////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8BmZmZFb29vXNxkqhzxOf/+c3q//+Lzf//b9D//3rh//9fw///drfv/9/t+f+mzO3/Vp3a/zSe + 5/9Bzv//MrP3/1ao4v+cwuX/4Oz2/73W6/9wptT/InjA/yGM1v8jpO7/JrT3/0Gf4f+SvOD/5u/3/8/i + 8v+It97/IoHO/y2j6f86w/7/O7/5/zGN2/+41/D/1Oj4/7TZ9P9ctff/ZNP//3/w//9v3///dtX//8jv + ///A5fPhU1NTX7W1tctVVVU5EBAQEQAAAAP///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8BAAAABXl5eSm/z9rRnNv/7d3w//+/4f//cr///2zT//9q1///dsb8/7rZ + 9P/V5/f/da7f/z6O1v8sm+f/NcL+/yyt9v83l93/WZzU/5nB5P92q9r/RI7M/xh2xf8WiNn/G6Dy/x2u + +v8ikeP/QY7R/3Kq2v9jo9b/RJHR/x6A0f8jnej/Lrj9/zG6+f8qj+D/gbfl/63S7/+jz+//Xa/r/1vJ + //9w5///a9z//3bO//+k4f//vez//43X68Wbm5urWFhYVxQUFCcAAAANAAAAA////wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8BAAAAAzw8PBFlam1Do+j/6a/i///W7P//n9D7/1m0 + //9s2v//Xtb//1W5//9Zqe7/Zq7q/zSW4/8plun/LbT//y7H//8nu///IKf2/yWg6/9Ir+3/Oqzu/yai + 7P8Wne3/GKn4/xmy//8auP//GKz8/x6h7f8upez/KKrv/yGm7v8fqPH/IbX9/yjE//8uy///K677/zmr + 8f9Hq+//VbHx/z2k9P9Qxf//Y+T//2vj//9jy///pN7//8zu//+q7f//hM/es4iIiJEkJCRBAAAAHwAA + AAn///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAAAAlDQ0MrmNn6x4/p + //+V2f//mdX//1q9//9fy///bO3//1vn//9N2v//S9j//0XQ//8zy/7/L8v//yvO//8my///IMD//xm1 + /f8dsPf/I630/xuo8v8So/H/D6Hw/xCo+P8Qrfz/EbL9/xCq+/8To/L/EqPw/xel8f8YrPT/GLL4/x/B + //8gxv//Js///yrP//812P//PNn//0Xj//9M4f//Vun//2Hz//9w9f//aeT//2jd//+c6f//fOb//3n6 + //ekytXFMjIyUwAAADEAAAATAAAAA////wH///8B////Af///wH///8B////Af///wH///8B////AQAA + AAMAAAATW4qsabX8//+U+P//iuj//4rt//987///cPP//2j1//9T6f//Q9P//zy9+v80q+//IZvn/xyV + 6P8bpfj/GK7//xGZ8P8Ogtj/HnzI/0+Vz/8jeML/B2W2/wdnuv8Ie9L/CZDq/wqc8/8KgNb/Cmm7/wpm + tv8bc77/G3bD/w10yf8QjOL/F6j7/x23//8Zm/D/KJzo/zen7P9KtvT/PsL+/0bX//9Y7f//avf//2/0 + //+B9v//k/r//53+//+h////tv//9zk/P1sEBAQ/AAAAIwAAAAn///8B////Af///wH///8B////Af// + /wH///8B////Af///wEAAAAJEBcbJ3TP/9+9////mvj//4bm//941v//VsP//0/G//9N2P//PLr//zKV + 4f9QmNf/TJLO/xVuvP8Sb8D/FI7f/xGc7f8Nh9n/PY3L/3Cjzv+iwt7/kbfY/2CWxf8DXKj/BHHC/wWG + 3/8Fk+r/LInQ/1OQxP98qtD/qsfg/4+21/8IZK7/C3vL/w2T5v8SpPH/EoPU/06Tz/+Htt3/grXf/0yd + 3P81per/Qcv//1Lj//9Jw///UsX//2rc//976f//mP///7n///9qwdilBwcHRQAAADMAAAAVAAAAA/// + /wH///8B////Af///wH///8B////Af///wEAAAADAAAAE1aZyYOC3///oPT//2vK//+Nyv//icP1/1qo + 7P9BsPj/Qcr//zWo7P9Wndf/mb/h/4Cv1/8OZK//C2W0/w2I2P8Oluj/CIDU/2Gg0f+ev9z/vtXn/7TO + 5P96p87/A12p/wRxw/8Fht//BZPq/zWP0v91pc//udHl/9Pj7/+xzOP/EGew/wh4x/8Jj+L/D6Dv/w5/ + 0P9rpNP/zuDw/8fc7v+Ds9z/QqDe/zW7+f9G1v//QbT7/z6j7P+Eyfv/iNL//2DT//+Q+v//jfj/9yc9 + Q1cAAAA9AAAAIwAAAAn///8B////Af///wH///8B////Af///wH///8BAAAABwoRFyFswv/nj+b//3/f + //+s2P7/z+X5/6rQ8f9bpeX/O7L0/zzD/P8rneT/LIDH/6/M5v+KtNj/C2Gs/wlksf8Jhdj/CpHm/wd9 + 0P91q9X/q8jh/8LX6f+zzOP/daPM/wBZpv8AbcD/AILc/wCO6P8riM7/daTO/8zd7P/X5PD/rsri/xNl + rP8Dc8P/CY7h/wqd7f8LfdD/Yp7P/8/g7//P4fD/hrXb/zKO0/8tsvL/QdL//zyw9P89n+X/k8v0/8Pk + /P9Tvf//eun//57+//9cs9OlAAAAQwAAADMAAAATAAAAA////wH///8B////Af///wH///8B////AQAA + AA9SlsZ5cs///5Dp//9tz///stj6/+Pw+/+axuz/S5rg/zay8v8yufj/LZng/0uPzP/I2+3/ncDd/zd9 + uf8JY7D/CYfa/wWM4/8Mf9H/ZKDQ/6vI4f/a5vH/tM3j/2udyP8AWqb/AG7B/wCC3P8Ajuj/CHXH/zx/ + uv+Vudf/xNjp/6/K4f8XaK7/A3LC/wWI3v8Fl+r/CH3O/1mWyv/N4O//yN3u/4u32/8zjM//KKrs/zbM + /v81sfL/QJrg/4nD7v/R6vv/TrX9/2ja//+k/v//cOT/8RAhJ08AAAA7AAAAHwAAAAf///8B////Af// + /wH///8B////AQAAAAMAAAAXZLbw027P//+V7///Wr3//7zb9//W6Pj/k8Hp/0OV3f8zsvL/LLH0/z2d + 3v9+r9n/xNnr/5C32P8+gbr/BmKw/wWF2v8FjOT/CX3Q/zeDwf9zpM7/o8Le/2+gy/83fLj/AFyq/wBv + xP8AhN//AI/q/wByyP8WaLD/Roa8/3KjzP9tn8v/DmOs/wNvwf8Fid//BZfr/wR6zf83gb7/oMLf/6HD + 4P95q9X/NYrM/yKa4/8yxvz/M7Px/0ad4P+SxOv/8fj9/0it9f9bzf//pv3//3Pq//9IlLCLAAAAQQAA + ACsAAAAN////Af///wH///8B////Af///wEAAAAJO2uNQWrB//9szv//lvP//1e3//+byvL/oMrw/1+k + 4v8vjN3/MbX4/ymw+f8wmeP/TpXT/3Cm1v9Di8j/GW+6/wNpv/8Fjuf/BZPv/wCA3f8AcMj/HXvH/zqN + z/8QdcX/AG3C/wByyv8Agd3/AJDw/wCY9f8Ag+D/AHHJ/wBuw/8NdcX/EnbH/wNvwv8AetT/AI/s/wWe + 9v8Fh+D/CW/B/yF4wv82hMf/L4LH/xZ9zv8cmun/Krn9/zG5+v8xl+H/U6bm/63Y9v9UsPP/WMz//5r7 + //9t4///X8PqzwAAAEUAAAA1AAAAFQAAAAP///8B////Af///wH///8BAAAADVqk2ZVnv///Zsj//5H0 + //9Zx///Vrj//2vE//88tvz/Nbf//zPO//8pw///JbP9/yup8v8yqe7/HZ/s/wuX6v8FmfL/BaT6/wCf + +f8Anff/AJjz/waZ8P8NnPH/A5nx/wCY8v8AmvX/AJ74/wCh+f8ApPv/AJ74/wCa9P8AmPL/A5ny/wOZ + 8f8AmPL/AJz3/wCf+P8Ap/v/Baf6/wed8v8So/D/GKPv/x6p8f8Xq/b/Hrn//ynK//840///OMb//0XE + //9Xyv//Vsv//2Lc//+T/P//dOP//2nS//0fP01ZAAAAOwAAAB8AAAAH////Af///wH///8B////AQAA + ABNktvDPZb3//2XI//+K9///ePL//2Xr//9X7f//S+n//zrY//8x1f//Jcf//xm2//8ZqvX/I6bw/xSc + 6/8Fkej/BZXv/wCc9/8AnPf/AJb0/wCM6P8GiuH/C4vh/wOH4P8Aht//AIfj/wCR7/8AmPX/AJ34/wCT + 8v8IieL/GZHh/xOP4v8Ki+H/Aofi/wCQ7P8AmPX/AJ34/wWi+f8Lmez/IaDs/yqp7/8lqfH/E6n2/x+/ + //8lyv//Ntn//z3b//9N6f//YfD//2/1//9++v//k////3no//9r1P//RYuqhwAAAD8AAAAnAAAAC/// + /wH///8B////AQAAAAUdNkYhasP+/WO///9pzP//gPD//2HY//9Owf//Rrf7/zKn8v8on/P/J7v//xuo + +v8Tit//G3jH/06RzP8dcrn/BmOz/wBovv8AiOT/AInm/wB30f8AZLf/HG+0/zV+vP8OZK//AFuq/wBh + sv8Ac8r/AIbj/wCR7f8Dd87/Gm+2/06NxP9IicL/MXu7/whisf8AbcL/AIHd/wCO6/8Af9f/FXG+/06R + yf9gntH/TZLM/wxxxv8TkeT/ILL9/yq4/f8qm+7/M6Xv/0++//9Tyf//Ydz//4X2//924///Z8///1mx + 27kAAABDAAAALwAAAA////8B////Af///wEAAAAHTpC7V2rE//9hvv//a9L//2/g//9Xr/7/e7fq/4S5 + 5/9NltX/IYXX/yCr8v8Zmur/SpnW/4ay1/+ewN3/b6DL/zh9t/8AY7P/AIXd/wCF3/8Acsf/AF6s/2ea + x/+oxd7/Mniz/wBWof8AW6j/AG/C/wCC3f8Ajuj/DnjJ/06Mwf+40OT/vtTn/56/2/8hbq//AGi5/wB9 + 1f8Ai+X/AHfM/yV0tv+Tudn/rMnh/4621/8ab7f/F4jV/xqj7v8jqe3/JoLR/22q3f+VxOv/ebvu/1W2 + //925///e+T//2TL//9kwvTlAAAARQAAADMAAAAT////Af///wH///8BAAAAC1ii039nwf//Xrz//2jP + //9o2///fL72/8rh9P/G3fH/bKfY/x6D0/8grPL/FJTm/1ag1/+ewd//zd7t/4611v9Cgrn/AGOz/wCG + 3v8Ahd//AHLH/wBeq/97qM7/v9Xn/z+AuP8GWqP/AFuo/wBvwv8Agt3/AI7o/xl+zP9gl8f/ytzr/9zo + 8v/F2en/Lna0/wBouP8AfNT/AIvl/wB3zf8ZarD/daXP/6rI4f+gwt7/InS5/xaE0f8aou3/I6ns/yeB + zv+jyOf/1+f2/7TU8P9qufT/bt///3fh//9lyP//aMr+/QkRFUkAAAA3AAAAFwAAAAP///8B////AQAA + AA1fsOWlZ8H//1y6//9u1v//Zdb//5DH9f/Z6ff/wtzx/1+e1P8fhdT/G6nx/xSU5f8bfMb/Zp3M/+Tt + 9f+Otdb/On23/wBktf8Aht7/AITe/wJ0xv8FYKz/eafO/7nR5f9Pi73/F2aq/wBbqP8Ab8L/AILd/wCO + 6P8ig87/ZprJ/8LX6P/f6vP/0ODt/zJ5tf8AaLj/AHzU/wCL5P8Ad83/Alyn/wZaov9vosz/kbjZ/yV2 + uv8WhNH/GqLt/x6l6/8ffMn/sNDr/9/s+P+31vH/Z7Lw/2bZ//955P//Ysf//2jI//8sVWtlAAAAOQAA + ABsAAAAF////Af///wEAAAANY7btu2S///9cu///atP//2DU//9rtPH/vNny/73Z8P9dn9b/HILR/xyp + 8f8UlOX/TZnS/53A3v/b5/L/f6vR/zB2s/8AZbb/AIbe/wCE3v8Kdsj/MHy6/4201f/C1+j/j7XV/0qH + vP8AW6j/AG/C/wCC3f8Ajuj/IoPO/2aayf/C1+j/0uHu/7nR5f8rdLL/AGi4/wB81P8Ai+X/AHjO/xdp + r/9xocr/qMbg/6fF3/81gL3/G4bS/xad6/8epev/HnzJ/2qn2f/K4PL/s9Pv/2Ou7v9m1P//eeT//2PI + //9oyP//PXaWewAAADsAAAAdAAAAB////wH///8BAAAADWS48Mdkv///XLv//2rT//9g1P//RKHt/4e8 + 5/+ZxOf/SZLQ/xyF1P8cqfH/EpLj/0qX0v+Js9f/sczj/1iRwv8caq3/AGW2/wCH3/8AhN7/C3fJ/zJ9 + u/94p87/pMPd/4Wu0f9Ihrz/AFuo/wBvwv8Agt3/AI7o/xZ8y/9Ihr7/lrnY/5u92v+Bq9D/HGut/wBo + uP8AfNT/AIvl/wB4zv8Xaa//caHK/5i82v+Otdb/LXu7/xmF0f8Wnev/HqXr/xx6yf8ugMb/mMPm/5LB + 6f9Yqe3/Y9P//3Xe//9gv///ZcX//0WFqocAAAA7AAAAHwAAAAf///8B////AQAAAA1lu/PRZL///1y7 + //9r1f//Ytr//0Gq//8+nOr/NpTh/yCD1f8dj+T/HLP7/xKa8f8Mes//HnW//0yQyf8Va7b/AF+x/wBr + wv8Ai+f/AInn/wV60f8Wcr7/QYbD/1yXyv8+hMH/HW+3/wBhtP8AdMz/AIfl/wCS7/8AdtH/Dmi1/zB8 + vP8ndrn/Fmu0/wVisv8AbsT/AIHe/wCP7P8Aftj/BWS3/xZrtP84gsL/PYXD/wpouv8Mg9j/FqP0/x+s + 9f8ehNn/I4LU/zyV4P8+m+j/Qaj+/2bZ//913///YL///2W///9Kj7aPAAAAOwAAAB8AAAAH////Af// + /wEAAAANZbz002S///9cu///bNn//3Lx//9b5P//Ut3//0LW//8xyf//KMX//yDH//8Wt///EKz5/xKe + 7/8fn+3/BpLp/wCQ6v8AlPD/AJ74/wCd+P8Cmfb/CJPs/yKd6v8/qe3/Sq7u/1Cx7v9YtfH/WLv4/1u/ + +f9bwvv/WLv4/1u28f9Vs+//Q6vs/ymf6v8Ok+n/AJTw/wCb9/8An/n/AJr2/wKP6/8IkOf/GJvr/xmc + 6/8Mme3/EKj6/xm8//8lyP//LMP//zXI//9H1///VNz//2Pm//948v//d+P//2C///9lv///S4u3kwAA + ADsAAAAdAAAAB////wH///8BAAAADWS/8clkxP//XLv//2zY//9u7P//Wdv//1fU//9Kz///L8H+/yfA + //8gxv//Fbb//xuu+f8gqPH/J6Pu/xCX6/8Fk+v/AJf0/wCf+f8Oo/j/Nq/4/1u69f9zw/X/eMX1/3DC + 9P9twfT/bcL2/23F+v9tx/v/bcn8/23F+v9vwvX/dcT1/3PD9f9wwvT/bsH1/1u9+P82sfj/DqX5/wCc + 9/8Aku3/AJDp/wqW6/8Ll+r/Cprv/xSr+/8Ztv//Jcf//yu///80wv3/UNL//1fW//9e3f//dO7//3fi + //9gv///Zb///0WBqocAAAA5AAAAGwAAAAX///8B////AQAAAAtkvvC9ZMT//1zB//9q0///Ytj//0+u + /f9mr+v/Xafl/yeH1/8cjuX/HLL7/xWf8/8ojdf/R5HO/2Kf0f8xf8P/Dmq4/xR6zP9MsPH/bLzy/2yz + 5/9sqdr/gbLb/4+63/90qtf/bKbV/2yp2v9ssub/bLzz/2zC+P9stOn/c6za/4W13P+Bstv/eK3Y/2+o + 2P9sruH/bLnv/2zA9v9Mpub/FHC//wBgsf8Ra7f/F2+5/wdmuf8PhNn/Fp7y/x+m8v8ehNj/LYfU/2Sq + 5P9equr/Sar8/2rb//964f//X77//2jC//9AeJ5/AAAANwAAABkAAAAD////Af///wEAAAAJYrrrp2TE + //9bv///ZNP//2jb//99vvX/uNfx/6XL6v9hotn/GoTW/x2u8/8Umej/SZrV/4632v/D2er/bKDM/16V + xf9qpNT/arnt/2q57f9yseH/jrjb/6vH4f+90+f/rsrh/5C11/9qoM3/aqvb/2q36/9qvvL/dbLh/5G3 + 2P+80+b/vtTn/67K4f95p9D/aqfX/2qy5v9qvPD/b7Pk/32r0v+JsNT/nL/c/5i82v8abbP/E3/O/xaZ + 6P8eoOn/InrH/5C94/+11O//nsns/2e09P9r2v//ddv//2LA//9owv//MVt3ZwAAADUAAAAT////Af// + /wH///8BAAAABV614X9nx///XsH//2fT//9p4P//c7r2/8fg9f/D3fL/a6jb/x2F1P8hsfT/FZrp/zuT + 1P+Ar9b/0+Lv/63K4/+Fr9P/aKPU/2i47P9ot+3/dbTi/6jI4//H2ur/1+Xw/9Hh7v+pxt//aJ7L/2iq + 2/9otev/aLzx/4C44/+qx+H/3ejz/+Hr9P/O3u3/fqrR/2im1v9osub/aLrw/3Cz4/+MtNf/ydvr/+bv + 9v/K3e3/Gm2z/xOB0P8anuv/I6Pp/y2Cy/+oy+j/1OX1/6rQ7/9isvX/cuD//3nd//9kwf//aML//xEf + KUsAAAAvAAAAD////wH///8B////AQAAAANZrtVXas3//1/E//9l0P//ceb//3fD/f/F3/X/zeL0/22q + 3P8dgdL/Ia/z/xuh7v8Vfsz/So7G/8LY6/+uy+P/jrbY/2eh0v9nt+v/Z7ft/3a04/+00Of/zd7t/9fl + 8P/R4e7/qcbf/2edy/9nqdv/Z7Tr/2e88f+LveX/ts/l/+Pt9P/k7fX/zd7t/3yp0P9npdX/Z7Ln/2e6 + 8P9vsuL/lLrb/9/q9P/w9fr/2OXy/yNzt/8Sg9L/Gp/s/yKh6P8xhs//qcvp/9vq9/+mze7/YLL4/3fj + //9y2P//ZMD//2S69ecAAAA/AAAAKQAAAAv///8B////Af///wH///8BPnmUH2rP/v1ixv//YM///3vs + //9qvv//uNr0/73b8v9/teH/H4HS/ySy8/8bou7/UKPb/7bR6P/R4e//vtXp/5e93P9lotL/ZbXq/2W3 + 7f9ysuL/qsrk/8/g7v/h7PT/0ODt/6TD3v9lm8n/Zaja/2W06v9lu/H/g7rj/7LM5P/n7/b/4+31/8jb + 6v94ps7/ZaTV/2Ww5v9lue//aa7g/4Gu1P+1zuT/5u/2/9rn8v9mn8//IIrW/x+k7v8mpOr/PY3S/7jV + 7v/J4PP/oMnt/1+z+v+A5///cNT//2bB//9bqt/BAAAAOwAAAB8AAAAH////Af///wH///8B////AQAA + AAlnyvjZZMr//2LR//+G9v//UsP//12z9f+AwPD/SJ/h/yaJ3f8otfb/IKn1/3G25/+py+f/w9nr/6/M + 5P+Nttj/ZaLS/2O26v9jtu3/a6/h/5O83f/B1+n/3+rz/8LX6P+Xutj/Y5rJ/2Om2f9js+r/Y7rx/3Wy + 4P+iwt7/3+rz/9Xj8P+2z+T/cKHM/2Ok1f9jsOf/Y7nw/2Oq3v9toc3/hK7S/8XZ6v+60+f/aqPS/1yt + 5/8gqPL/JqTs/zeO2f9srOP/jcDt/1+r7f9UuP//jfH//27P//9mvv//TY65kQAAADUAAAAXAAAAA/// + /wH///8B////Af///wEAAAAFYcLqk2fN//9l1///jvv//3j1//9h3///Ztn//z/H//80uv//LMj//zvE + //9xxPj/cLPm/5fE6P99st7/YqDT/2Kj2v9juvH/YLfx/2Gu5f9no9b/g7DY/53A3/9/rdX/bKHP/2Cb + zv9gp93/YLTu/2C69P9kquD/dqnT/5e83P+Nttn/e6vT/2Sczv9gpdv/YLLr/2C68/9ireX/Y5/R/2ag + 0P9wptX/cKra/2uu5P9wwvb/PsP//y+9//82s/7/Rr7//2zR//9k1v//d+r//5r6//9tz///asL//ypM + ZF0AAAAtAAAAD////wH///8B////Af///wH///8B////AVatzj9q0///Z9f//5L7//908f//ZuX//17j + //9S5///Rer//z3q//9e4v//c9z//3DU/v910vv/cMz4/2TD9f9hwPf/Ycn8/2HJ/P9ev/n/Xrjy/2i5 + 7/9zve//ZLbt/16z6/9etO7/Xrr2/16++f9ewfv/Xrr2/2O07P9uuuz/arjt/2S16/9es+3/Xrr0/16/ + +f9hxvv/YcH6/2G68v9kv/P/a8T1/27J+P9x0v7/ddr//2Lg//884P//TOz//1jo//9o5///cOb//4Lw + //+f+///cNL//2O179sAAAA7AAAAIQAAAAn///8B////Af///wH///8B////Af///wEAAAAJaNH522vc + //+I8v//auD//1O7//9auP7/Pqr3/zSv/v851P//bdv//3fS//9+zfn/g8z1/3fH9P9owfP/YsL3/1/I + /P9fyv3/X8f8/1y99/9evfX/X771/1299v9cvvf/XL74/1zC+/9cxPz/XMX8/1zC+/9ev/j/Yb72/2C+ + 9v9evfX/XLz1/1y/+f9fxPv/YMf8/1/D+/9kwPX/bcPz/3PG8/9xxPX/bcf5/3XV//9y3f//Pcr//zuw + /f9ErPn/VbD7/1Cw//9nz///n/X//3HS//9PkL6VAAAAMwAAABUAAAAD////Af///wH///8B////Af// + /wH///8BAAAAA2HG6X1v4P//hu///3bl//9zyP//ptX3/1uu6/8ymOX/Nbn6/3Xc//94xfT/lsPq/63O + 6v+XweT/canY/2Ci2P9gt+//Xbz1/12y7P9dpN3/YKHW/2il2P9eodb/Wp/W/1qi2v9arej/Wrj2/1q9 + +f9aruv/Yqfc/3aw3v9uqtv/ZKTY/12i2P9dq+T/Xbfz/1299/9frOb/aaTX/3yu2f+MueD/gLLf/3Gy + 5P9zxPb/edn//zao8v9EmOL/e7bq/5LF8f9OqPf/ddX//5Xs//9yzf/3HTRFTwAAACUAAAAL////Af// + /wH///8B////Af///wH///8B////Af///wE9fpIVa9r/7Xru//+N9P//Wcb//6nY+v+Gw/H/Npzo/zmy + 9/9x3P//d8r0/6/R7f/d6vX/y9/v/4Sy2f9in9L/XLLo/1678f9areT/WZ3S/4Ov1f++1Oj/eafP/1eR + xP9XlMf/V6HY/1eu6/9Xt/L/XqXc/3yr0v+vyuP/s83k/53A3f9clsn/WaLY/12z7P9evPP/Xqje/4+4 + 2//O3+//zuDv/6fI5f9/uOP/dcj2/3fa/v85pO7/Up/i/6HL8f+m0PX/V7T//4nj//+M5P//X6jesQAA + ADUAAAAXAAAABf///wH///8B////Af///wH///8B////Af///wH///8BAAAAA2HL64d28v//p/7//3PZ + //+w3fz/td35/0Wk6/8+svn/a93//3bO+f93teP/tNLr/8La7f+TvN7/Z6PV/16y6P9ev/P/Wq/m/1qf + 0/+QuNj/4+31/5K32P9ak8T/V5PG/1We1v9Vren/VbXw/2So3P+Sudr/0ODu/9nm8v+91Of/WZTH/1qk + 2v9bsuz/X73y/1+n3f+PuNz/xtvt/9/r9f+lyOb/eLfk/3rP+v9u3P//PaHu/0OY4P+93ff/rtf6/23F + //+g8P//etj/+yhFWVUAAAAlAAAAC////wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wE9gZIVdOz/5aj///9w6f//oN7//8jo/v93wPX/QrL9/17d//971f//lcvt/7fU7f/C2u7/pMfk/2+n + 1/9esuf/YML2/1yz6v9bodX/i7bZ/93p8/+YvNv/YZfG/1WSxv9Wn9f/Vq/q/1a48v9ur+D/lbzb/8nc + 7P/X5fH/utLn/1eUyP9aptz/XLXt/2C/8/9epd3/hrPb/7rU6v/h7fb/mMHj/3O46f9+1P7/YNT//0Cf + 7/+KwfL/2+38/6DS/v9z0f//ufr//2ew5K8FBQUzAAAAFwAAAAX///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8BAAAAA2/T61+b////pf///4/y//+U5v//Ycj//0m8//9X3///ddr//5bQ + 9v+72vH/x93x/6/O6f97r93/YLTq/2DF9/9ctuz/c7Hf/57D4f/b6PP/wNbp/5G32f9Vk8f/VaHY/1aw + 6/9XuvP/Zavf/6PE4f/v9fr/1+Xx/6TE4P9Wlcr/W6je/1+68f9fvvL/XqTc/6HE5P/M3/D/zN/x/36y + 4f9zvu//eNf//1jS//9Or///fMT//53X//9/2f//lfP//6/1//U7Q0hNAAAAIQAAAAn///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wFxcXEJffX/ubH///+X////lfr//4b1 + //9w7///bvb//2Xt//992///gcr7/5zL8v9yseX/Z6rk/2K48v9jyv7/Yb72/2yz5f+IuN//t9Pq/6zK + 5v+Ktdr/VpXM/1ak3f9YtO//WL31/12p4f+OuNz/0OHw/7TQ5/+Kttv/WJvT/1us5f9gv/f/ZMT4/2Gq + 5P97suH/irzn/4y/7P9zuPL/fdP//2nn//9t6///b97//4rp//+e8///r/v//7T///+Wx9+tNTU1MQAA + AA8AAAAD////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AZrB + ySvA///3efv//3rl//9w4v//cOn//3f6//9z+f//cvX//4jz//+F7f//eeL//3Ha//9v3f//ad7//2bU + //9oyvz/bsL0/4fI8/98wO3/bbfr/1uu6v9buPT/WsH+/1vH/v9buvf/Z7Pr/3++7P9/vu3/c7vt/121 + 7/9ix/3/aNP//2zZ//9tz/7/dNL7/3/d/v+E5f//ie3//3f2//95+P//gPf//3/p//+C4f//gtz//4Pn + //+m5v/XZWVlUSkpKRkAAAAD////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wHb29sPxPD4g33y//WI4v//u+j//1vO//9o4f//bOz//2Hb//910P//m97//4nW + //941///deL//3Xt//9w5v//bN///2nZ//9q1/7/aNT+/2bV/v9i1f//Y9f//2Pa//9k2///YtX//2HS + /v9l1f7/ZtT+/2nW/v9o1///bd7//3Hj//915f//ddv//33c//+I3P//hdX//1zI//9k3v//dOv//2zX + //94yv//t+P//7/m//9+yP3PvL7AyWpqajEcHBwJ////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////A+fn5xXG9f2fhOj/++f4//9cx///ZdT//3nt + //9k1///l9D7/8Lh+P+l0/X/f7zv/2289/913v//cNb//2vA+P9mren/hL7s/3S46/9grun/Xq/s/2G9 + +P9kzf//ZtT//2G/+/9esOz/YrDr/2uz6v9qser/Y7Lu/2rF/f9y2P//ddT//3G28f+dy/P/p9H1/4XA + 8v9btPz/adT//4Do//9oyP//u+L//+v2//+m1vnnanR7YcLCwoOQkJAX////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8N+/v7iYji + /HHf+P//keD//2XW//+E7///ceL//2TE//+02/j/s9j1/3O06v9ksO//fNv//3fX//+GyvX/sNLv/73Z + 8P+81+//psro/2em3P9isen/Z8f7/2rT//9itOz/cqzf/4684v+pzOr/jLvk/2Wt5P9vx/f/edr//3fN + /P+Au+3/2uv5/9Pn+P+ezPX/bL///3je//+I6P//d83//7vj///h8f35oq62f8zMzKGioqIfmZmZBf// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Bf///xP7+/uJue36iYHp//d06v//ifT//4Py//+S3v//rtv9/7nd+f+LxvL/RaHw/17Q + //9p1f//cMT4/3u26P/B3PL/zuP0/7vX7/9yreD/aLbr/2/P/v903f//abnw/4C14/+rzuv/wNrw/5TC + 6P9stOv/c8z+/3Dc//9awv//hL7y/+/2/f/W6fv/jsj5/3LM//+K6P//jun//3rW//+R0P7daXeAW7i4 + uG3i4uJf1dXVDf///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8F////D/f390XK8PmNqvv/8aT///+h////fOn//4/Z + //+z4P//ltH9/1qy+v9bzv//XNb//1S///92uO7/vdz0/8/k9/+31vH/b63k/2q78f941P//fuL//2y+ + 9v+Nvur/wdzy/73Z8f9+t+j/S6nw/1TG//9k3P//Vb///5TJ+P/Z7P3/xeT//3TI//+A4v//n/n//5n0 + //+V3P/Pv8LGn87Oznnc3NxB6urqDf///wP///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wP///8H39/fEbXP + 2Tmd8v/Nqf///6b9//+V9P//j+n//3XZ//9j0P//adr//3Ho//9f0///XLj//4rF9/+TyPX/dLjv/0qh + 7P9Hsfz/Vc///17g//9Itv//ZrDv/5PG8/+EvvH/WKrz/0+1//9k1///der//2TP//9ivf//eM3//4Xb + //+Q6v//sfz//7r+//2i2/K7sbGxb7GxsTHGxsYT39/fCf///wP///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wHMzMwFqqqqD3nL7VeD5//bjO///4zs//+K6v//her//4zx//+P+P//g/L//3Lh + //9v1///bdP//1/N//9Zx///YNT//2vm//9x7///Ytf//1zI//9ex///as///2rS//934v//ifP//5X6 + //+N8P//jun//5Lp//+X6v//lur//43X/8eGna5jaWlpJ3NzcxWqqqoH////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wFVVVUDXV1dC2i/62tu0f/hcdf//3Xa + //952///et///3je//922///c9n//3HZ//9x2f//b9f//3Lb//924v//eOT//3Pc//9v1///c9j//3XZ + //912f//etz//3zf//+C4///gd///3/c//981v//abv1wUx2k082NjYhQEBAETMzMwX///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wEAAAADLVhtD2G56HVoxvvZbMj//2rG//9oxv//ZcT//2LB//9fv///Xb3//2HA//9hv///YsD//2LA + //9iv///Yb7//2TA//9gvf//Y7///2XB//9oxP//bsj//23F//tkte/DSH2kWQkJCR0AAAAPAAAABf// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAAADAAAAB1WizD1iteyTZ77302rE//9qxP//Z8H//2fB + //9kwP//ZL3//2S9//9kvf//ZL3//2S9//9nwP//Z7///2rB//9pv/zzYrLrwVad0IEpSmIvAAAAFQAA + AA0AAAAF////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAABQAA + AAk5aYkdVqDQUVup3HditeujYbTqp2W38stmufXVZbn01WKz7L1gr+epXargl1adz3dHgapJAAAAGQAA + ABEAAAANAAAABwAAAAP///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////AQAAAAMAAAAFAAAABwAAAAkAAAALAAAADQAAAA8AAAANAAAADQAA + AAsAAAAJAAAABwAAAAP///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA== + + + \ No newline at end of file diff --git a/Source/MatrixCalculator/MatrixCalculator.csproj b/Source/MatrixCalculator/MatrixCalculator.csproj new file mode 100644 index 0000000..31b9991 --- /dev/null +++ b/Source/MatrixCalculator/MatrixCalculator.csproj @@ -0,0 +1,221 @@ + + + + Debug + x86 + 8.0.30703 + 2.0 + {9C7FBEFC-5219-41CE-9EB3-24AC382C0A7A} + WinExe + Properties + MatrixCalculator + MatrixCalculator + v3.5 + 512 + + + + + x86 + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + x86 + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + Resources\matrixcalc-logo.ico + + + true + + + ..\..\TibisMathematicsSuite - Release\ + TRACE + true + pdbonly + x86 + prompt + false + false + false + + + + ..\packages\MathNet.Numerics.3.20.2\lib\net35\MathNet.Numerics.dll + + + + + ..\packages\System.Data.SQLite.Core.1.0.106.0\lib\net20\System.Data.SQLite.dll + + + ..\packages\System.Data.SQLite.Linq.1.0.106.0\lib\net20\System.Data.SQLite.Linq.dll + + + ..\packages\TaskParallelLibrary.1.0.2856.0\lib\Net35\System.Threading.dll + + + + + + + + + + + + + Form + + + Editor.cs + + + + Form + + + ImportCsvWindow.cs + + + Form + + + ImportWorksheetWindow.cs + + + + Form + + + MainWindow.cs + + + + Form + + + NumericInput.cs + + + + + + Form + + + SettingsWindow.cs + + + + Editor.cs + + + ImportCsvWindow.cs + + + ImportWorksheetWindow.cs + + + SettingsWindow.cs + + + MainWindow.cs + + + NumericInput.cs + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + True + Resources.resx + True + + + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + + + {A04B247B-6A95-462B-9E07-3337A1C158F1} + Launcher + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + \ No newline at end of file diff --git a/Source/MatrixCalculator/Program.cs b/Source/MatrixCalculator/Program.cs new file mode 100644 index 0000000..eb0a000 --- /dev/null +++ b/Source/MatrixCalculator/Program.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Windows.Forms; + +namespace MatrixCalculator +{ + static class Program + { + /// + /// The main entry point for the application. + /// + [STAThread] + static void Main() + { + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + Application.Run(new MainWindow()); + } + } +} diff --git a/Source/MatrixCalculator/Properties/AssemblyInfo.cs b/Source/MatrixCalculator/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..a57c83a --- /dev/null +++ b/Source/MatrixCalculator/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 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("Matrix Calculator")] +[assembly: AssemblyDescription("Performs various calculations with matrices.")] +[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)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("940536d9-62a8-488d-a640-2a7440966996")] + +// 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")] diff --git a/Source/MatrixCalculator/Properties/Resources.Designer.cs b/Source/MatrixCalculator/Properties/Resources.Designer.cs new file mode 100644 index 0000000..ceaa570 --- /dev/null +++ b/Source/MatrixCalculator/Properties/Resources.Designer.cs @@ -0,0 +1,174 @@ +//------------------------------------------------------------------------------ +// +// 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. +// +//------------------------------------------------------------------------------ + +namespace MatrixCalculator.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // 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() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("MatrixCalculator.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to Comma Separated Values file|*.csv;*.txt|All files|*.*. + /// + internal static string CsvFormatFilter { + get { + return ResourceManager.GetString("CsvFormatFilter", resourceCulture); + } + } + + internal static System.Drawing.Bitmap door_out { + get { + object obj = ResourceManager.GetObject("door_out", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + internal static System.Drawing.Bitmap folder_page_white { + get { + object obj = ResourceManager.GetObject("folder_page_white", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + internal static System.Drawing.Bitmap Gnome_Edit_Clear_16 { + get { + object obj = ResourceManager.GetObject("Gnome-Edit-Clear-16", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + internal static System.Drawing.Bitmap help { + get { + object obj = ResourceManager.GetObject("help", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + internal static System.Drawing.Bitmap page_save { + get { + object obj = ResourceManager.GetObject("page_save", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + internal static System.Drawing.Bitmap page_white_add { + get { + object obj = ResourceManager.GetObject("page_white_add", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + internal static System.Drawing.Bitmap page_white_copy { + get { + object obj = ResourceManager.GetObject("page_white_copy", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + internal static System.Drawing.Bitmap page_white_paste { + get { + object obj = ResourceManager.GetObject("page_white_paste", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + internal static System.Drawing.Bitmap table_add { + get { + object obj = ResourceManager.GetObject("table_add", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + internal static System.Drawing.Bitmap table_delete { + get { + object obj = ResourceManager.GetObject("table_delete", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + internal static System.Drawing.Bitmap table_edit { + get { + object obj = ResourceManager.GetObject("table_edit", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized string similar to mxs. + /// + internal static string WorksheetFormat { + get { + return ResourceManager.GetString("WorksheetFormat", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Matrix calculator worksheets|*.mxs|All files|*.*. + /// + internal static string WorksheetFormatFilter { + get { + return ResourceManager.GetString("WorksheetFormatFilter", resourceCulture); + } + } + + internal static System.Drawing.Bitmap wrench_orange { + get { + object obj = ResourceManager.GetObject("wrench_orange", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + } +} diff --git a/Source/MatrixCalculator/Properties/Resources.resx b/Source/MatrixCalculator/Properties/Resources.resx new file mode 100644 index 0000000..387743e --- /dev/null +++ b/Source/MatrixCalculator/Properties/Resources.resx @@ -0,0 +1,166 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + ..\Resources\table_add.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\folder_page_white.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\page_white_copy.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\table_edit.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\page_save.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\page_white_add.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\page_white_paste.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\door_out.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\help.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\table_delete.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\Gnome-Edit-Clear-16.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\wrench_orange.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + mxs + + + Matrix calculator worksheets|*.mxs|All files|*.* + + + Comma Separated Values file|*.csv;*.txt|All files|*.* + + \ No newline at end of file diff --git a/Source/MatrixCalculator/Properties/Settings.Designer.cs b/Source/MatrixCalculator/Properties/Settings.Designer.cs new file mode 100644 index 0000000..83c4f2a --- /dev/null +++ b/Source/MatrixCalculator/Properties/Settings.Designer.cs @@ -0,0 +1,62 @@ +//------------------------------------------------------------------------------ +// +// 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. +// +//------------------------------------------------------------------------------ + +namespace MatrixCalculator.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("3")] + public int DoublePrecision { + get { + return ((int)(this["DoublePrecision"])); + } + set { + this["DoublePrecision"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("True")] + public bool NumberResultAsMatrix { + get { + return ((bool)(this["NumberResultAsMatrix"])); + } + set { + this["NumberResultAsMatrix"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute(",;")] + public string InternalCsvSeparators { + get { + return ((string)(this["InternalCsvSeparators"])); + } + set { + this["InternalCsvSeparators"] = value; + } + } + } +} diff --git a/Source/MatrixCalculator/Properties/Settings.settings b/Source/MatrixCalculator/Properties/Settings.settings new file mode 100644 index 0000000..123faa0 --- /dev/null +++ b/Source/MatrixCalculator/Properties/Settings.settings @@ -0,0 +1,15 @@ + + + + + + 3 + + + True + + + ,; + + + \ No newline at end of file diff --git a/Source/MatrixCalculator/Resources/Gnome-Edit-Clear-16.png b/Source/MatrixCalculator/Resources/Gnome-Edit-Clear-16.png new file mode 100644 index 0000000..eb06c93 Binary files /dev/null and b/Source/MatrixCalculator/Resources/Gnome-Edit-Clear-16.png differ diff --git a/Source/MatrixCalculator/Resources/door_out.png b/Source/MatrixCalculator/Resources/door_out.png new file mode 100644 index 0000000..2541d2b Binary files /dev/null and b/Source/MatrixCalculator/Resources/door_out.png differ diff --git a/Source/MatrixCalculator/Resources/folder_page_white.png b/Source/MatrixCalculator/Resources/folder_page_white.png new file mode 100644 index 0000000..14d6b61 Binary files /dev/null and b/Source/MatrixCalculator/Resources/folder_page_white.png differ diff --git a/Source/MatrixCalculator/Resources/help.png b/Source/MatrixCalculator/Resources/help.png new file mode 100644 index 0000000..5c87017 Binary files /dev/null and b/Source/MatrixCalculator/Resources/help.png differ diff --git a/Source/MatrixCalculator/Resources/matrixcalc-logo-2.ico b/Source/MatrixCalculator/Resources/matrixcalc-logo-2.ico new file mode 100644 index 0000000..037dd56 Binary files /dev/null and b/Source/MatrixCalculator/Resources/matrixcalc-logo-2.ico differ diff --git a/Source/MatrixCalculator/Resources/matrixcalc-logo.ico b/Source/MatrixCalculator/Resources/matrixcalc-logo.ico new file mode 100644 index 0000000..e44b5d8 Binary files /dev/null and b/Source/MatrixCalculator/Resources/matrixcalc-logo.ico differ diff --git a/Source/MatrixCalculator/Resources/page_save.png b/Source/MatrixCalculator/Resources/page_save.png new file mode 100644 index 0000000..caea546 Binary files /dev/null and b/Source/MatrixCalculator/Resources/page_save.png differ diff --git a/Source/MatrixCalculator/Resources/page_white_add.png b/Source/MatrixCalculator/Resources/page_white_add.png new file mode 100644 index 0000000..aa23dde Binary files /dev/null and b/Source/MatrixCalculator/Resources/page_white_add.png differ diff --git a/Source/MatrixCalculator/Resources/page_white_copy.png b/Source/MatrixCalculator/Resources/page_white_copy.png new file mode 100644 index 0000000..a9f31a2 Binary files /dev/null and b/Source/MatrixCalculator/Resources/page_white_copy.png differ diff --git a/Source/MatrixCalculator/Resources/page_white_paste.png b/Source/MatrixCalculator/Resources/page_white_paste.png new file mode 100644 index 0000000..5b2cbb3 Binary files /dev/null and b/Source/MatrixCalculator/Resources/page_white_paste.png differ diff --git a/Source/MatrixCalculator/Resources/table_add.png b/Source/MatrixCalculator/Resources/table_add.png new file mode 100644 index 0000000..2a3e5c4 Binary files /dev/null and b/Source/MatrixCalculator/Resources/table_add.png differ diff --git a/Source/MatrixCalculator/Resources/table_delete.png b/Source/MatrixCalculator/Resources/table_delete.png new file mode 100644 index 0000000..b85916d Binary files /dev/null and b/Source/MatrixCalculator/Resources/table_delete.png differ diff --git a/Source/MatrixCalculator/Resources/table_edit.png b/Source/MatrixCalculator/Resources/table_edit.png new file mode 100644 index 0000000..bfcb024 Binary files /dev/null and b/Source/MatrixCalculator/Resources/table_edit.png differ diff --git a/Source/MatrixCalculator/Resources/wrench_orange.png b/Source/MatrixCalculator/Resources/wrench_orange.png new file mode 100644 index 0000000..565a933 Binary files /dev/null and b/Source/MatrixCalculator/Resources/wrench_orange.png differ diff --git a/Source/MatrixCalculator/WorksheetFile.cs b/Source/MatrixCalculator/WorksheetFile.cs new file mode 100644 index 0000000..6bb0a45 --- /dev/null +++ b/Source/MatrixCalculator/WorksheetFile.cs @@ -0,0 +1,136 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Data; +using System.Data.SQLite; + +namespace MatrixCalculator +{ + class WorksheetFile + { + private string filename = ""; + private Queue queue = new Queue(); + + public string FileName + { + get { return filename; } + set { filename = value; } + } + + /// + /// Creates a new worksheet that will be destroyed at exit + /// + public WorksheetFile() + { + queue.Enqueue(new SQLiteCommand("CREATE TABLE matrices (name TEXT PRIMARY KEY, description TEXT, csv TEXT)")); + } + + /// + /// Opens an existing worksheet + /// + public WorksheetFile(string filename) + { + this.filename = filename; + if (!System.IO.File.Exists(filename)) throw new Exception("Could not open file."); + } + + public bool IsQueueEmpty { + get { + if (queue.Count == 1 && queue.Peek().CommandText.StartsWith("CREATE TABLE matrices")) return true; + return queue.Count == 0; + } + } + + public void Save() + { + System.Diagnostics.Debug.Assert(filename != ""); + + // Open database + SQLiteConnection connection = new SQLiteConnection("Data Source=" + filename + ";Version=3"); + connection.Open(); + + // Write changes + while (queue.Count > 0) + { + var cmd = queue.Dequeue(); + cmd.Connection = connection; + cmd.ExecuteNonQuery(); + cmd.Dispose(); + } + + // Done + connection.Close(); + connection.Dispose(); + } + + public void SaveAs(string new_file) + { + // Copy old file + if (System.IO.File.Exists(filename)) + System.IO.File.Copy(filename, new_file, true); + + filename = new_file; + + // Save file + Save(); + } + + public DataTable Read() + { + if (!System.IO.File.Exists(filename)) throw new Exception("File not found."); + + // Open connection + SQLiteConnection connection = new SQLiteConnection("Data Source=" + filename + ";Version=3;"); + connection.Open(); + + // Set up command + SQLiteCommand command = connection.CreateCommand(); + command.CommandText = "SELECT * FROM matrices"; + + // Read data + SQLiteDataReader reader = command.ExecuteReader(); + + // Load in table + DataTable table = new DataTable(); + table.Load(reader); + + // Cleanup + reader.Close(); + reader.Dispose(); + command.Dispose(); + connection.Close(); + connection.Dispose(); + + return table; + } + + public void AddMatrix(string name, string csv, string description = "") + { + SQLiteCommand cmd = new SQLiteCommand("INSERT INTO matrices VALUES (@name, @desc, @csv)"); + cmd.Parameters.AddWithValue("@name", name); + cmd.Parameters.AddWithValue("@desc", description); + cmd.Parameters.AddWithValue("@csv", csv); + + queue.Enqueue(cmd); + } + + public void DeleteMatrix(string name) + { + SQLiteCommand cmd = new SQLiteCommand("DELETE FROM matrices WHERE name=@name"); + cmd.Parameters.AddWithValue("@name", name); + queue.Enqueue(cmd); + } + + public void ModifyMatrix(string old_name, string new_name, string csv, string description = "") + { + SQLiteCommand cmd = new SQLiteCommand("UPDATE matrices SET name=@newname, description=@desc, csv=@csv WHERE name=@oldname"); + cmd.Parameters.AddWithValue("@oldname", old_name); + cmd.Parameters.AddWithValue("@newname", new_name); + cmd.Parameters.AddWithValue("@desc", description); + cmd.Parameters.AddWithValue("@csv", csv); + + queue.Enqueue(cmd); + } + } +} diff --git a/Source/MatrixCalculator/app.config b/Source/MatrixCalculator/app.config new file mode 100644 index 0000000..506e553 --- /dev/null +++ b/Source/MatrixCalculator/app.config @@ -0,0 +1,26 @@ + + + + +
+ + + + + + 3 + + + True + + + ,; + + + + + + + + + \ No newline at end of file diff --git a/Source/MatrixCalculator/packages.config b/Source/MatrixCalculator/packages.config new file mode 100644 index 0000000..8217707 --- /dev/null +++ b/Source/MatrixCalculator/packages.config @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/Source/TibisMathematicsSuite.sln b/Source/TibisMathematicsSuite.sln new file mode 100644 index 0000000..bdc90f9 --- /dev/null +++ b/Source/TibisMathematicsSuite.sln @@ -0,0 +1,158 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TibisMathematicsSuite", "TibisMathematicsSuite\TibisMathematicsSuite.csproj", "{9A45DFCA-EA4F-4950-8519-F1BCE929D5CA}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GraphingCalculator", "GraphingCalculator\GraphingCalculator.csproj", "{A1B63EB2-82CF-4589-8AE2-18FAAF51B662}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Factorizator", "Factorizator\Factorizator.csproj", "{FB3CFDCE-C816-4F4A-AEF4-5C0240396C60}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Calculator", "Calculator\Calculator.csproj", "{D0040DA8-5B61-4B40-AF35-1320C1CC7121}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Help", "Help\Help.csproj", "{5BF4AB9C-9AE0-44ED-B49E-09ACE92C8D89}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DynamicLink", "Launcher\DynamicLink.csproj", "{A04B247B-6A95-462B-9E07-3337A1C158F1}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MatrixCalculator", "MatrixCalculator\MatrixCalculator.csproj", "{9C7FBEFC-5219-41CE-9EB3-24AC382C0A7A}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|Mixed Platforms = Debug|Mixed Platforms + Debug|x86 = Debug|x86 + Release - Publish|Any CPU = Release - Publish|Any CPU + Release - Publish|Mixed Platforms = Release - Publish|Mixed Platforms + Release - Publish|x86 = Release - Publish|x86 + Release|Any CPU = Release|Any CPU + Release|Mixed Platforms = Release|Mixed Platforms + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {9A45DFCA-EA4F-4950-8519-F1BCE929D5CA}.Debug|Any CPU.ActiveCfg = Debug|x86 + {9A45DFCA-EA4F-4950-8519-F1BCE929D5CA}.Debug|Any CPU.Build.0 = Debug|x86 + {9A45DFCA-EA4F-4950-8519-F1BCE929D5CA}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 + {9A45DFCA-EA4F-4950-8519-F1BCE929D5CA}.Debug|Mixed Platforms.Build.0 = Debug|x86 + {9A45DFCA-EA4F-4950-8519-F1BCE929D5CA}.Debug|x86.ActiveCfg = Debug|x86 + {9A45DFCA-EA4F-4950-8519-F1BCE929D5CA}.Debug|x86.Build.0 = Debug|x86 + {9A45DFCA-EA4F-4950-8519-F1BCE929D5CA}.Release - Publish|Any CPU.ActiveCfg = Release - Publish|x86 + {9A45DFCA-EA4F-4950-8519-F1BCE929D5CA}.Release - Publish|Any CPU.Build.0 = Release - Publish|x86 + {9A45DFCA-EA4F-4950-8519-F1BCE929D5CA}.Release - Publish|Mixed Platforms.ActiveCfg = Release - Publish|x86 + {9A45DFCA-EA4F-4950-8519-F1BCE929D5CA}.Release - Publish|Mixed Platforms.Build.0 = Release - Publish|x86 + {9A45DFCA-EA4F-4950-8519-F1BCE929D5CA}.Release - Publish|x86.ActiveCfg = Release - Publish|x86 + {9A45DFCA-EA4F-4950-8519-F1BCE929D5CA}.Release - Publish|x86.Build.0 = Release - Publish|x86 + {9A45DFCA-EA4F-4950-8519-F1BCE929D5CA}.Release|Any CPU.ActiveCfg = Release|x86 + {9A45DFCA-EA4F-4950-8519-F1BCE929D5CA}.Release|Any CPU.Build.0 = Release|x86 + {9A45DFCA-EA4F-4950-8519-F1BCE929D5CA}.Release|Mixed Platforms.ActiveCfg = Release|x86 + {9A45DFCA-EA4F-4950-8519-F1BCE929D5CA}.Release|Mixed Platforms.Build.0 = Release|x86 + {9A45DFCA-EA4F-4950-8519-F1BCE929D5CA}.Release|x86.ActiveCfg = Release|x86 + {9A45DFCA-EA4F-4950-8519-F1BCE929D5CA}.Release|x86.Build.0 = Release|x86 + {A1B63EB2-82CF-4589-8AE2-18FAAF51B662}.Debug|Any CPU.ActiveCfg = Debug|x86 + {A1B63EB2-82CF-4589-8AE2-18FAAF51B662}.Debug|Any CPU.Build.0 = Debug|x86 + {A1B63EB2-82CF-4589-8AE2-18FAAF51B662}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 + {A1B63EB2-82CF-4589-8AE2-18FAAF51B662}.Debug|Mixed Platforms.Build.0 = Debug|x86 + {A1B63EB2-82CF-4589-8AE2-18FAAF51B662}.Debug|x86.ActiveCfg = Debug|x86 + {A1B63EB2-82CF-4589-8AE2-18FAAF51B662}.Debug|x86.Build.0 = Debug|x86 + {A1B63EB2-82CF-4589-8AE2-18FAAF51B662}.Release - Publish|Any CPU.ActiveCfg = Release - Publish|x86 + {A1B63EB2-82CF-4589-8AE2-18FAAF51B662}.Release - Publish|Any CPU.Build.0 = Release - Publish|x86 + {A1B63EB2-82CF-4589-8AE2-18FAAF51B662}.Release - Publish|Mixed Platforms.ActiveCfg = Release - Publish|x86 + {A1B63EB2-82CF-4589-8AE2-18FAAF51B662}.Release - Publish|Mixed Platforms.Build.0 = Release - Publish|x86 + {A1B63EB2-82CF-4589-8AE2-18FAAF51B662}.Release - Publish|x86.ActiveCfg = Release - Publish|x86 + {A1B63EB2-82CF-4589-8AE2-18FAAF51B662}.Release - Publish|x86.Build.0 = Release - Publish|x86 + {A1B63EB2-82CF-4589-8AE2-18FAAF51B662}.Release|Any CPU.ActiveCfg = Release|x86 + {A1B63EB2-82CF-4589-8AE2-18FAAF51B662}.Release|Any CPU.Build.0 = Release|x86 + {A1B63EB2-82CF-4589-8AE2-18FAAF51B662}.Release|Mixed Platforms.ActiveCfg = Release|x86 + {A1B63EB2-82CF-4589-8AE2-18FAAF51B662}.Release|Mixed Platforms.Build.0 = Release|x86 + {A1B63EB2-82CF-4589-8AE2-18FAAF51B662}.Release|x86.ActiveCfg = Release|x86 + {A1B63EB2-82CF-4589-8AE2-18FAAF51B662}.Release|x86.Build.0 = Release|x86 + {FB3CFDCE-C816-4F4A-AEF4-5C0240396C60}.Debug|Any CPU.ActiveCfg = Debug|x86 + {FB3CFDCE-C816-4F4A-AEF4-5C0240396C60}.Debug|Any CPU.Build.0 = Debug|x86 + {FB3CFDCE-C816-4F4A-AEF4-5C0240396C60}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 + {FB3CFDCE-C816-4F4A-AEF4-5C0240396C60}.Debug|Mixed Platforms.Build.0 = Debug|x86 + {FB3CFDCE-C816-4F4A-AEF4-5C0240396C60}.Debug|x86.ActiveCfg = Debug|x86 + {FB3CFDCE-C816-4F4A-AEF4-5C0240396C60}.Debug|x86.Build.0 = Debug|x86 + {FB3CFDCE-C816-4F4A-AEF4-5C0240396C60}.Release - Publish|Any CPU.ActiveCfg = Release - Publish|x86 + {FB3CFDCE-C816-4F4A-AEF4-5C0240396C60}.Release - Publish|Any CPU.Build.0 = Release - Publish|x86 + {FB3CFDCE-C816-4F4A-AEF4-5C0240396C60}.Release - Publish|Mixed Platforms.ActiveCfg = Release - Publish|x86 + {FB3CFDCE-C816-4F4A-AEF4-5C0240396C60}.Release - Publish|Mixed Platforms.Build.0 = Release - Publish|x86 + {FB3CFDCE-C816-4F4A-AEF4-5C0240396C60}.Release - Publish|x86.ActiveCfg = Release - Publish|x86 + {FB3CFDCE-C816-4F4A-AEF4-5C0240396C60}.Release - Publish|x86.Build.0 = Release - Publish|x86 + {FB3CFDCE-C816-4F4A-AEF4-5C0240396C60}.Release|Any CPU.ActiveCfg = Release|x86 + {FB3CFDCE-C816-4F4A-AEF4-5C0240396C60}.Release|Any CPU.Build.0 = Release|x86 + {FB3CFDCE-C816-4F4A-AEF4-5C0240396C60}.Release|Mixed Platforms.ActiveCfg = Release|x86 + {FB3CFDCE-C816-4F4A-AEF4-5C0240396C60}.Release|Mixed Platforms.Build.0 = Release|x86 + {FB3CFDCE-C816-4F4A-AEF4-5C0240396C60}.Release|x86.ActiveCfg = Release|x86 + {FB3CFDCE-C816-4F4A-AEF4-5C0240396C60}.Release|x86.Build.0 = Release|x86 + {D0040DA8-5B61-4B40-AF35-1320C1CC7121}.Debug|Any CPU.ActiveCfg = Debug|x86 + {D0040DA8-5B61-4B40-AF35-1320C1CC7121}.Debug|Any CPU.Build.0 = Debug|x86 + {D0040DA8-5B61-4B40-AF35-1320C1CC7121}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 + {D0040DA8-5B61-4B40-AF35-1320C1CC7121}.Debug|Mixed Platforms.Build.0 = Debug|x86 + {D0040DA8-5B61-4B40-AF35-1320C1CC7121}.Debug|x86.ActiveCfg = Debug|x86 + {D0040DA8-5B61-4B40-AF35-1320C1CC7121}.Debug|x86.Build.0 = Debug|x86 + {D0040DA8-5B61-4B40-AF35-1320C1CC7121}.Release - Publish|Any CPU.ActiveCfg = Release - Publish|x86 + {D0040DA8-5B61-4B40-AF35-1320C1CC7121}.Release - Publish|Any CPU.Build.0 = Release - Publish|x86 + {D0040DA8-5B61-4B40-AF35-1320C1CC7121}.Release - Publish|Mixed Platforms.ActiveCfg = Release - Publish|x86 + {D0040DA8-5B61-4B40-AF35-1320C1CC7121}.Release - Publish|Mixed Platforms.Build.0 = Release - Publish|x86 + {D0040DA8-5B61-4B40-AF35-1320C1CC7121}.Release - Publish|x86.ActiveCfg = Release - Publish|x86 + {D0040DA8-5B61-4B40-AF35-1320C1CC7121}.Release - Publish|x86.Build.0 = Release - Publish|x86 + {D0040DA8-5B61-4B40-AF35-1320C1CC7121}.Release|Any CPU.ActiveCfg = Release|x86 + {D0040DA8-5B61-4B40-AF35-1320C1CC7121}.Release|Any CPU.Build.0 = Release|x86 + {D0040DA8-5B61-4B40-AF35-1320C1CC7121}.Release|Mixed Platforms.ActiveCfg = Release|x86 + {D0040DA8-5B61-4B40-AF35-1320C1CC7121}.Release|Mixed Platforms.Build.0 = Release|x86 + {D0040DA8-5B61-4B40-AF35-1320C1CC7121}.Release|x86.ActiveCfg = Release|x86 + {D0040DA8-5B61-4B40-AF35-1320C1CC7121}.Release|x86.Build.0 = Release|x86 + {5BF4AB9C-9AE0-44ED-B49E-09ACE92C8D89}.Debug|Any CPU.ActiveCfg = Debug|x86 + {5BF4AB9C-9AE0-44ED-B49E-09ACE92C8D89}.Debug|Any CPU.Build.0 = Debug|x86 + {5BF4AB9C-9AE0-44ED-B49E-09ACE92C8D89}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 + {5BF4AB9C-9AE0-44ED-B49E-09ACE92C8D89}.Debug|Mixed Platforms.Build.0 = Debug|x86 + {5BF4AB9C-9AE0-44ED-B49E-09ACE92C8D89}.Debug|x86.ActiveCfg = Debug|x86 + {5BF4AB9C-9AE0-44ED-B49E-09ACE92C8D89}.Debug|x86.Build.0 = Debug|x86 + {5BF4AB9C-9AE0-44ED-B49E-09ACE92C8D89}.Release - Publish|Any CPU.ActiveCfg = Release - Publish|x86 + {5BF4AB9C-9AE0-44ED-B49E-09ACE92C8D89}.Release - Publish|Any CPU.Build.0 = Release - Publish|x86 + {5BF4AB9C-9AE0-44ED-B49E-09ACE92C8D89}.Release - Publish|Mixed Platforms.ActiveCfg = Release - Publish|x86 + {5BF4AB9C-9AE0-44ED-B49E-09ACE92C8D89}.Release - Publish|Mixed Platforms.Build.0 = Release - Publish|x86 + {5BF4AB9C-9AE0-44ED-B49E-09ACE92C8D89}.Release - Publish|x86.ActiveCfg = Release - Publish|x86 + {5BF4AB9C-9AE0-44ED-B49E-09ACE92C8D89}.Release - Publish|x86.Build.0 = Release - Publish|x86 + {5BF4AB9C-9AE0-44ED-B49E-09ACE92C8D89}.Release|Any CPU.ActiveCfg = Release|x86 + {5BF4AB9C-9AE0-44ED-B49E-09ACE92C8D89}.Release|Any CPU.Build.0 = Release|x86 + {5BF4AB9C-9AE0-44ED-B49E-09ACE92C8D89}.Release|Mixed Platforms.ActiveCfg = Release|x86 + {5BF4AB9C-9AE0-44ED-B49E-09ACE92C8D89}.Release|Mixed Platforms.Build.0 = Release|x86 + {5BF4AB9C-9AE0-44ED-B49E-09ACE92C8D89}.Release|x86.ActiveCfg = Release|x86 + {5BF4AB9C-9AE0-44ED-B49E-09ACE92C8D89}.Release|x86.Build.0 = Release|x86 + {A04B247B-6A95-462B-9E07-3337A1C158F1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A04B247B-6A95-462B-9E07-3337A1C158F1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A04B247B-6A95-462B-9E07-3337A1C158F1}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {A04B247B-6A95-462B-9E07-3337A1C158F1}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {A04B247B-6A95-462B-9E07-3337A1C158F1}.Debug|x86.ActiveCfg = Debug|Any CPU + {A04B247B-6A95-462B-9E07-3337A1C158F1}.Release - Publish|Any CPU.ActiveCfg = Release - Publish|Any CPU + {A04B247B-6A95-462B-9E07-3337A1C158F1}.Release - Publish|Any CPU.Build.0 = Release - Publish|Any CPU + {A04B247B-6A95-462B-9E07-3337A1C158F1}.Release - Publish|Mixed Platforms.ActiveCfg = Release - Publish|Any CPU + {A04B247B-6A95-462B-9E07-3337A1C158F1}.Release - Publish|Mixed Platforms.Build.0 = Release - Publish|Any CPU + {A04B247B-6A95-462B-9E07-3337A1C158F1}.Release - Publish|x86.ActiveCfg = Release - Publish|Any CPU + {A04B247B-6A95-462B-9E07-3337A1C158F1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A04B247B-6A95-462B-9E07-3337A1C158F1}.Release|Any CPU.Build.0 = Release|Any CPU + {A04B247B-6A95-462B-9E07-3337A1C158F1}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {A04B247B-6A95-462B-9E07-3337A1C158F1}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {A04B247B-6A95-462B-9E07-3337A1C158F1}.Release|x86.ActiveCfg = Release|Any CPU + {9C7FBEFC-5219-41CE-9EB3-24AC382C0A7A}.Debug|Any CPU.ActiveCfg = Debug|x86 + {9C7FBEFC-5219-41CE-9EB3-24AC382C0A7A}.Debug|Any CPU.Build.0 = Debug|x86 + {9C7FBEFC-5219-41CE-9EB3-24AC382C0A7A}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 + {9C7FBEFC-5219-41CE-9EB3-24AC382C0A7A}.Debug|Mixed Platforms.Build.0 = Debug|x86 + {9C7FBEFC-5219-41CE-9EB3-24AC382C0A7A}.Debug|x86.ActiveCfg = Debug|x86 + {9C7FBEFC-5219-41CE-9EB3-24AC382C0A7A}.Debug|x86.Build.0 = Debug|x86 + {9C7FBEFC-5219-41CE-9EB3-24AC382C0A7A}.Release - Publish|Any CPU.ActiveCfg = Release - Publish|x86 + {9C7FBEFC-5219-41CE-9EB3-24AC382C0A7A}.Release - Publish|Any CPU.Build.0 = Release - Publish|x86 + {9C7FBEFC-5219-41CE-9EB3-24AC382C0A7A}.Release - Publish|Mixed Platforms.ActiveCfg = Release - Publish|x86 + {9C7FBEFC-5219-41CE-9EB3-24AC382C0A7A}.Release - Publish|Mixed Platforms.Build.0 = Release - Publish|x86 + {9C7FBEFC-5219-41CE-9EB3-24AC382C0A7A}.Release - Publish|x86.ActiveCfg = Release - Publish|x86 + {9C7FBEFC-5219-41CE-9EB3-24AC382C0A7A}.Release - Publish|x86.Build.0 = Release - Publish|x86 + {9C7FBEFC-5219-41CE-9EB3-24AC382C0A7A}.Release|Any CPU.ActiveCfg = Release|x86 + {9C7FBEFC-5219-41CE-9EB3-24AC382C0A7A}.Release|Any CPU.Build.0 = Release|x86 + {9C7FBEFC-5219-41CE-9EB3-24AC382C0A7A}.Release|Mixed Platforms.ActiveCfg = Release|x86 + {9C7FBEFC-5219-41CE-9EB3-24AC382C0A7A}.Release|Mixed Platforms.Build.0 = Release|x86 + {9C7FBEFC-5219-41CE-9EB3-24AC382C0A7A}.Release|x86.ActiveCfg = Release|x86 + {9C7FBEFC-5219-41CE-9EB3-24AC382C0A7A}.Release|x86.Build.0 = Release|x86 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Source/TibisMathematicsSuite/KeyboardIO/Hotkey.cs b/Source/TibisMathematicsSuite/KeyboardIO/Hotkey.cs new file mode 100644 index 0000000..113a794 --- /dev/null +++ b/Source/TibisMathematicsSuite/KeyboardIO/Hotkey.cs @@ -0,0 +1,44 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Runtime.InteropServices; + +namespace TibisMathematicsSuite.KeyboardIO +{ + public static class Hotkey + { + private static HotkeyWindow window = new HotkeyWindow(); + private static int currentId = 0; + + public static event EventHandler HotkeyPressed + { + add { window.HotkeyPressed += value; } + remove { window.HotkeyPressed -= value; } + } + + #region Winapi routines + // Registers a hot key with Windows. + [DllImport("user32.dll")] + private static extern bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint vk); + + // Unregisters the hot key with Windows. + [DllImport("user32.dll")] + private static extern bool UnregisterHotKey(IntPtr hWnd, int id); + #endregion + + public static void Register(MyKey key) + { + currentId++; + + if (!RegisterHotKey(window.Handle, currentId, (uint)key.Mods, (uint)key.Key)) + throw new InvalidOperationException("Could not register the hotkey!"); + } + + public static void UnregisterAll() + { + for (; currentId > 0; currentId--) + UnregisterHotKey(window.Handle, currentId); + } + } +} diff --git a/Source/TibisMathematicsSuite/KeyboardIO/HotkeyWindow.cs b/Source/TibisMathematicsSuite/KeyboardIO/HotkeyWindow.cs new file mode 100644 index 0000000..cdcac5d --- /dev/null +++ b/Source/TibisMathematicsSuite/KeyboardIO/HotkeyWindow.cs @@ -0,0 +1,48 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Windows.Forms; + +namespace TibisMathematicsSuite.KeyboardIO +{ + class HotkeyWindow : NativeWindow, IDisposable + { + #region Constants + private const int WM_HOTKEY = 0x312; + #endregion + + #region Events + public event EventHandler HotkeyPressed; + #endregion + + #region Constructor + public HotkeyWindow() + { + this.CreateHandle(new System.Windows.Forms.CreateParams()); + } + #endregion + + #region Processor + protected override void WndProc(ref System.Windows.Forms.Message m) + { + base.WndProc(ref m); + + if (m.Msg == WM_HOTKEY && HotkeyPressed != null) + { + int vk = ((int)m.LParam >> 16) & 0xffff; + int mods = (int)m.LParam & 0xffff; + + HotkeyPressed(this, new MyKeyEventArgs((Keys) vk, (MyKey.Modifiers) mods)); + } + } + #endregion + + #region Dispose + public void Dispose() + { + this.DestroyHandle(); + } + #endregion + } +} diff --git a/Source/TibisMathematicsSuite/KeyboardIO/KeyMessageFilter.cs b/Source/TibisMathematicsSuite/KeyboardIO/KeyMessageFilter.cs new file mode 100644 index 0000000..8ad7d0d --- /dev/null +++ b/Source/TibisMathematicsSuite/KeyboardIO/KeyMessageFilter.cs @@ -0,0 +1,42 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Windows.Forms; + +namespace TibisMathematicsSuite.KeyboardIO +{ + class KeyMessageFilter : IMessageFilter + { + private const int WM_KEYDOWN = 0x0100; + private const int WM_KEYUP = 0x0101; + + private Dictionary keyPressed = new Dictionary(); + public Dictionary KeyPressedTable { get { return keyPressed; } } + + public event EventHandler KeyDown; + public event EventHandler KeyUp; + + public bool IsKeyPressed(Keys key) + { + return keyPressed[key]; + } + + public bool PreFilterMessage(ref Message m) + { + if (m.Msg == WM_KEYDOWN) + { + keyPressed[(Keys)m.WParam] = true; + if (KeyDown != null) KeyDown(this, new KeyEventArgs((Keys)m.WParam)); + } + + else if (m.Msg == WM_KEYUP) + { + keyPressed[(Keys)m.WParam] = false; + if (KeyUp != null) KeyUp(this, new KeyEventArgs((Keys)m.WParam)); + } + + return false; + } + } +} diff --git a/Source/TibisMathematicsSuite/KeyboardIO/KeyShortcutBox.cs b/Source/TibisMathematicsSuite/KeyboardIO/KeyShortcutBox.cs new file mode 100644 index 0000000..aa888c0 --- /dev/null +++ b/Source/TibisMathematicsSuite/KeyboardIO/KeyShortcutBox.cs @@ -0,0 +1,111 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Drawing; +using System.Windows.Forms; + +namespace TibisMathematicsSuite.KeyboardIO +{ + public class KeyShortcutBox : TextBox + { + #region Variables + private KeyMessageFilter keyFilter = new KeyMessageFilter(); + private MyKey currentKey = new MyKey(); + private bool inputFinished = false; + #endregion + + #region Properties + public MyKey Key + { + get { + return MyKey.Parse(this.Text); + } + } + + #endregion + + #region Constructor + public KeyShortcutBox() : base() + { + this.ReadOnly = true; + this.BackColor = SystemColors.Window; + + Application.AddMessageFilter(keyFilter); + + keyFilter.KeyDown += new EventHandler(keyFilter_KeyDown); + keyFilter.KeyUp += new EventHandler(keyFilter_KeyUp); + } + #endregion + + #region Key updating + private void keyFilter_KeyUp(object sender, KeyEventArgs e) + { + switch (e.KeyCode) + { + case Keys.LMenu: + case Keys.RMenu: + case Keys.Menu: currentKey.Mods &= ~MyKey.Modifiers.Alt; break; + + case Keys.LShiftKey: + case Keys.RShiftKey: + case Keys.ShiftKey: currentKey.Mods &= ~MyKey.Modifiers.Shift; break; + + case Keys.LControlKey: + case Keys.RControlKey: + case Keys.ControlKey: currentKey.Mods &= ~MyKey.Modifiers.Ctrl; break; + + case Keys.LWin: + case Keys.RWin: currentKey.Mods &= ~MyKey.Modifiers.Win; break; + + default: + inputFinished = true; + currentKey.Key = Keys.None; + break; + } + + updateKey(); + } + + private void keyFilter_KeyDown(object sender, KeyEventArgs e) + { + switch (e.KeyCode) + { + case Keys.LMenu: + case Keys.RMenu: + case Keys.Menu: currentKey.Mods |= MyKey.Modifiers.Alt; break; + + case Keys.LShiftKey: + case Keys.RShiftKey: + case Keys.ShiftKey: currentKey.Mods |= MyKey.Modifiers.Shift; break; + + case Keys.LControlKey: + case Keys.RControlKey: + case Keys.ControlKey: currentKey.Mods |= MyKey.Modifiers.Ctrl; break; + + case Keys.LWin: + case Keys.RWin: currentKey.Mods |= MyKey.Modifiers.Win; break; + + default: currentKey.Key = e.KeyCode; break; + } + + inputFinished = false; + updateKey(); + } + + private void updateKey() + { + if (!inputFinished && this.Focused && this.Enabled) + this.Text = currentKey.ToString(); + } + #endregion + + #region Reset + public void Reset() + { + this.Text = ""; + this.inputFinished = false; + } + #endregion + } +} diff --git a/Source/TibisMathematicsSuite/KeyboardIO/MyKey.cs b/Source/TibisMathematicsSuite/KeyboardIO/MyKey.cs new file mode 100644 index 0000000..6a1effd --- /dev/null +++ b/Source/TibisMathematicsSuite/KeyboardIO/MyKey.cs @@ -0,0 +1,119 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace TibisMathematicsSuite.KeyboardIO +{ + public class MyKey + { + #region Data types + [Flags] + public enum Modifiers + { + None = 0x0, Alt = 0x1, Ctrl = 0x2, Shift = 0x4, Win = 0x8 + } + #endregion + + #region Properties + public Modifiers Mods { get; set; } + public System.Windows.Forms.Keys Key { get; set; } + + public bool TestModifier(Modifiers m) + { + return ((this.Mods & m) > 0); + } + #endregion + + #region Constructors + public MyKey() + { + Mods = Modifiers.None; + Key = System.Windows.Forms.Keys.None; + } + + public MyKey(System.Windows.Forms.Keys key) + { + Key = key; + Mods = Modifiers.None; + } + + public MyKey(System.Windows.Forms.Keys key, Modifiers mods) + { + Key = key; + Mods = mods; + } + #endregion + + #region To and from string + public static MyKey Parse(string str) + { + MyKey key = new MyKey(); + System.Windows.Forms.Keys temp; + var keys = str.Split('+'); + + foreach (var i in keys) + switch (i) + { + case "Alt": key.Mods |= Modifiers.Alt; break; + case "Ctrl": key.Mods |= Modifiers.Ctrl; break; + case "Shift": key.Mods |= Modifiers.Shift; break; + case "Win": key.Mods |= Modifiers.Win; break; + default: + Enum.TryParse(i, out temp); + key.Key = temp; + break; + } + + return key; + } + + public static string ToString(MyKey key) + { + StringBuilder str = new StringBuilder(); + + if ((key.Mods & Modifiers.Win) != 0) str.Append("Win+"); + if ((key.Mods & Modifiers.Ctrl) != 0) str.Append("Ctrl+"); + if ((key.Mods & Modifiers.Alt) != 0) str.Append("Alt+"); + if ((key.Mods & Modifiers.Shift) != 0) str.Append("Shift+"); + + str.Append(Enum.GetName(typeof(System.Windows.Forms.Keys), key.Key)); + return str.ToString(); + } + + public override string ToString() + { + return MyKey.ToString(this); + } + + #endregion + + #region Overloads + public override bool Equals(object obj) + { + MyKey b = obj as MyKey; + if (b == null) return false; + + return (b.Key == this.Key && b.Mods == this.Mods); + } + + public override int GetHashCode() + { + return base.GetHashCode(); + } + + public static bool operator== (MyKey A, MyKey B) + { + if ((object)A == null || (object)B == null) return ((object)A == (object)B); + + return (A.Key == B.Key) && (A.Mods == B.Mods); + } + + public static bool operator!=(MyKey A, MyKey B) + { + return !(A == B); + } + + #endregion + } +} diff --git a/Source/TibisMathematicsSuite/KeyboardIO/MyKeyEventArgs.cs b/Source/TibisMathematicsSuite/KeyboardIO/MyKeyEventArgs.cs new file mode 100644 index 0000000..bf5cd59 --- /dev/null +++ b/Source/TibisMathematicsSuite/KeyboardIO/MyKeyEventArgs.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace TibisMathematicsSuite.KeyboardIO +{ + public class MyKeyEventArgs : EventArgs + { + public MyKey Key { get; set; } + + public MyKeyEventArgs() : base() { } + + public MyKeyEventArgs(MyKey key) + { + Key = key; + } + + public MyKeyEventArgs(System.Windows.Forms.Keys k, MyKey.Modifiers mods = MyKey.Modifiers.None) + { + Key = new MyKey(k, mods); + } + } +} diff --git a/Source/TibisMathematicsSuite/MainWindow.Designer.cs b/Source/TibisMathematicsSuite/MainWindow.Designer.cs new file mode 100644 index 0000000..55c7cdc --- /dev/null +++ b/Source/TibisMathematicsSuite/MainWindow.Designer.cs @@ -0,0 +1,262 @@ +namespace TibisMathematicsSuite +{ + partial class MainWindow + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainWindow)); + this.buttonCancel = new DynamicLink.Controls.MyButton(); + this.buttonAccept = new DynamicLink.Controls.MyButton(); + this.groupKeyboardShortcuts = new DynamicLink.Controls.MyGroupBox(); + this.keyShortcutBox = new TibisMathematicsSuite.KeyboardIO.KeyShortcutBox(); + this.buttonSet = new DynamicLink.Controls.MyButton(); + this.buttonClear = new DynamicLink.Controls.MyButton(); + this.labelShortcut = new System.Windows.Forms.Label(); + this.listModules = new System.Windows.Forms.ListView(); + this.listModules_Mod = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.listModules_Key = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.notify = new System.Windows.Forms.NotifyIcon(this.components); + this.notifyContext = new System.Windows.Forms.ContextMenuStrip(this.components); + this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator(); + this.notifyContextAbout = new System.Windows.Forms.ToolStripMenuItem(); + this.notifyContextSettings = new System.Windows.Forms.ToolStripMenuItem(); + this.notifyContextExit = new System.Windows.Forms.ToolStripMenuItem(); + this.toolTip = new System.Windows.Forms.ToolTip(this.components); + this.groupKeyboardShortcuts.SuspendLayout(); + this.notifyContext.SuspendLayout(); + this.SuspendLayout(); + // + // buttonCancel + // + this.buttonCancel.Anchor = System.Windows.Forms.AnchorStyles.Bottom; + this.buttonCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.buttonCancel.Location = new System.Drawing.Point(62, 246); + this.buttonCancel.Name = "buttonCancel"; + this.buttonCancel.Size = new System.Drawing.Size(75, 23); + this.buttonCancel.TabIndex = 5; + this.buttonCancel.Text = "Cancel"; + this.buttonCancel.UseVisualStyleBackColor = true; + this.buttonCancel.Click += new System.EventHandler(this.buttonCancel_Click); + // + // buttonAccept + // + this.buttonAccept.Anchor = System.Windows.Forms.AnchorStyles.Bottom; + this.buttonAccept.Location = new System.Drawing.Point(143, 246); + this.buttonAccept.Name = "buttonAccept"; + this.buttonAccept.Size = new System.Drawing.Size(75, 23); + this.buttonAccept.TabIndex = 4; + this.buttonAccept.Text = "Accept"; + this.buttonAccept.UseVisualStyleBackColor = true; + this.buttonAccept.Click += new System.EventHandler(this.buttonAccept_Click); + // + // groupKeyboardShortcuts + // + this.groupKeyboardShortcuts.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.groupKeyboardShortcuts.BackColor = System.Drawing.Color.Transparent; + this.groupKeyboardShortcuts.Controls.Add(this.keyShortcutBox); + this.groupKeyboardShortcuts.Controls.Add(this.buttonSet); + this.groupKeyboardShortcuts.Controls.Add(this.buttonClear); + this.groupKeyboardShortcuts.Controls.Add(this.labelShortcut); + this.groupKeyboardShortcuts.Controls.Add(this.listModules); + this.groupKeyboardShortcuts.Location = new System.Drawing.Point(12, 12); + this.groupKeyboardShortcuts.Name = "groupKeyboardShortcuts"; + this.groupKeyboardShortcuts.Padding = new System.Windows.Forms.Padding(3, 7, 3, 3); + this.groupKeyboardShortcuts.Size = new System.Drawing.Size(257, 223); + this.groupKeyboardShortcuts.TabIndex = 2; + this.groupKeyboardShortcuts.TabStop = false; + this.groupKeyboardShortcuts.Text = "Global keyboard shortcuts"; + // + // keyShortcutBox + // + this.keyShortcutBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.keyShortcutBox.BackColor = System.Drawing.SystemColors.Window; + this.keyShortcutBox.Enabled = false; + this.keyShortcutBox.Location = new System.Drawing.Point(62, 197); + this.keyShortcutBox.Name = "keyShortcutBox"; + this.keyShortcutBox.ReadOnly = true; + this.keyShortcutBox.Size = new System.Drawing.Size(113, 20); + this.keyShortcutBox.TabIndex = 1; + // + // buttonSet + // + this.buttonSet.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.buttonSet.Location = new System.Drawing.Point(179, 197); + this.buttonSet.Margin = new System.Windows.Forms.Padding(1); + this.buttonSet.Name = "buttonSet"; + this.buttonSet.Size = new System.Drawing.Size(35, 20); + this.buttonSet.TabIndex = 2; + this.buttonSet.Text = "Set"; + this.buttonSet.UseVisualStyleBackColor = true; + this.buttonSet.Click += new System.EventHandler(this.buttonSet_Click); + // + // buttonClear + // + this.buttonClear.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.buttonClear.Location = new System.Drawing.Point(216, 197); + this.buttonClear.Margin = new System.Windows.Forms.Padding(1); + this.buttonClear.Name = "buttonClear"; + this.buttonClear.Size = new System.Drawing.Size(35, 20); + this.buttonClear.TabIndex = 3; + this.buttonClear.Text = "Clear"; + this.buttonClear.UseVisualStyleBackColor = true; + this.buttonClear.Click += new System.EventHandler(this.buttonClear_Click); + // + // labelShortcut + // + this.labelShortcut.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); + this.labelShortcut.AutoSize = true; + this.labelShortcut.Location = new System.Drawing.Point(6, 200); + this.labelShortcut.Name = "labelShortcut"; + this.labelShortcut.Size = new System.Drawing.Size(50, 13); + this.labelShortcut.TabIndex = 3; + this.labelShortcut.Text = "Shortcut:"; + // + // listModules + // + this.listModules.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.listModules.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.listModules.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { + this.listModules_Mod, + this.listModules_Key}); + this.listModules.FullRowSelect = true; + this.listModules.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.Nonclickable; + this.listModules.HideSelection = false; + this.listModules.Location = new System.Drawing.Point(7, 24); + this.listModules.MultiSelect = false; + this.listModules.Name = "listModules"; + this.listModules.Size = new System.Drawing.Size(244, 168); + this.listModules.Sorting = System.Windows.Forms.SortOrder.Ascending; + this.listModules.TabIndex = 0; + this.listModules.UseCompatibleStateImageBehavior = false; + this.listModules.View = System.Windows.Forms.View.Details; + this.listModules.SelectedIndexChanged += new System.EventHandler(this.listModules_SelectedIndexChanged); + // + // listModules_Mod + // + this.listModules_Mod.Text = "Module"; + this.listModules_Mod.Width = 137; + // + // listModules_Key + // + this.listModules_Key.Text = "Shortcut"; + this.listModules_Key.Width = 100; + // + // notify + // + this.notify.ContextMenuStrip = this.notifyContext; + this.notify.Icon = ((System.Drawing.Icon)(resources.GetObject("notify.Icon"))); + this.notify.Text = "Tibi\'s Mathematics Suite"; + this.notify.Visible = true; + // + // notifyContext + // + this.notifyContext.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.toolStripSeparator1, + this.notifyContextAbout, + this.notifyContextSettings, + this.notifyContextExit}); + this.notifyContext.Name = "contextMenuStrip1"; + this.notifyContext.Size = new System.Drawing.Size(117, 76); + // + // toolStripSeparator1 + // + this.toolStripSeparator1.Name = "toolStripSeparator1"; + this.toolStripSeparator1.Size = new System.Drawing.Size(113, 6); + // + // notifyContextAbout + // + this.notifyContextAbout.Name = "notifyContextAbout"; + this.notifyContextAbout.Size = new System.Drawing.Size(116, 22); + this.notifyContextAbout.Text = "&About"; + this.notifyContextAbout.Click += new System.EventHandler(this.notifyContextAbout_Click); + // + // notifyContextSettings + // + this.notifyContextSettings.Image = ((System.Drawing.Image)(resources.GetObject("notifyContextSettings.Image"))); + this.notifyContextSettings.Name = "notifyContextSettings"; + this.notifyContextSettings.Size = new System.Drawing.Size(116, 22); + this.notifyContextSettings.Text = "&Settings"; + this.notifyContextSettings.Click += new System.EventHandler(this.notifyContextSettings_Click); + // + // notifyContextExit + // + this.notifyContextExit.Image = ((System.Drawing.Image)(resources.GetObject("notifyContextExit.Image"))); + this.notifyContextExit.Name = "notifyContextExit"; + this.notifyContextExit.Size = new System.Drawing.Size(116, 22); + this.notifyContextExit.Text = "E&xit"; + this.notifyContextExit.Click += new System.EventHandler(this.notifyContextExit_Click); + // + // MainWindow + // + this.AcceptButton = this.buttonAccept; + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.BackColor = System.Drawing.Color.Gainsboro; + this.CancelButton = this.buttonCancel; + this.ClientSize = new System.Drawing.Size(281, 281); + this.Controls.Add(this.buttonCancel); + this.Controls.Add(this.buttonAccept); + this.Controls.Add(this.groupKeyboardShortcuts); + this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); + this.Name = "MainWindow"; + this.Text = "Suite settings"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.MainWindow_FormClosing); + this.groupKeyboardShortcuts.ResumeLayout(false); + this.groupKeyboardShortcuts.PerformLayout(); + this.notifyContext.ResumeLayout(false); + this.ResumeLayout(false); + + } + + #endregion + + private DynamicLink.Controls.MyGroupBox groupKeyboardShortcuts; + private System.Windows.Forms.ListView listModules; + private DynamicLink.Controls.MyButton buttonAccept; + private DynamicLink.Controls.MyButton buttonCancel; + private System.Windows.Forms.ColumnHeader listModules_Mod; + private System.Windows.Forms.ColumnHeader listModules_Key; + private DynamicLink.Controls.MyButton buttonSet; + private DynamicLink.Controls.MyButton buttonClear; + private System.Windows.Forms.Label labelShortcut; + private System.Windows.Forms.NotifyIcon notify; + private System.Windows.Forms.ContextMenuStrip notifyContext; + private KeyboardIO.KeyShortcutBox keyShortcutBox; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator1; + private System.Windows.Forms.ToolStripMenuItem notifyContextAbout; + private System.Windows.Forms.ToolStripMenuItem notifyContextSettings; + private System.Windows.Forms.ToolStripMenuItem notifyContextExit; + private System.Windows.Forms.ToolTip toolTip; + } +} + diff --git a/Source/TibisMathematicsSuite/MainWindow.cs b/Source/TibisMathematicsSuite/MainWindow.cs new file mode 100644 index 0000000..a4049ff --- /dev/null +++ b/Source/TibisMathematicsSuite/MainWindow.cs @@ -0,0 +1,245 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Windows.Forms; +using TibisMathematicsSuite.KeyboardIO; + +namespace TibisMathematicsSuite +{ + public partial class MainWindow : Form + { + private Dictionary moduleShortcuts = new Dictionary(); + bool allowExit = false, allowShow = false; + + #region Constructor + public MainWindow() + { + InitializeComponent(); + PopulateModules(); + PopulateNotificationList(); + UpdateGlobalHotkeys(); + + // Hotkey + Hotkey.HotkeyPressed += new EventHandler(Hotkey_HotkeyPressed); + + // Show baloon message + notify.ShowBalloonTip(2, "Tibi's Mathematics Suite", + "The suite is running. Right click this icon to open an application.", ToolTipIcon.None); + } + #endregion + + #region Rendering + protected override void OnPaint(PaintEventArgs e) + { + base.OnPaint(e); + + DynamicLink.Controls.BackgroundGradient.Paint(e.Graphics, new Rectangle(0, 0, this.Width, this.Height)); + } + + protected override void OnResize(EventArgs e) + { + base.OnResize(e); + + this.Invalidate(); + } + #endregion + + #region Update routines + private void PopulateModules() + { + // Collect data + if (DynamicLink.Modules.Items.Count == 0) DynamicLink.Modules.CollectData(); + + // Get the already made dictionary + var dict = TibisMathematicsSuite.Properties.Settings.Default.ModuleKeys; + if (dict == null) dict = new System.Collections.Specialized.StringDictionary(); + + foreach (var i in DynamicLink.Modules.Items) + { + if (dict.ContainsKey(i.Name)) moduleShortcuts.Add(i.Name, MyKey.Parse(dict[i.Name])); + else moduleShortcuts.Add(i.Name, null); + } + + // Now that our dictionary is complete, add it to list box + UpdateModules(); + } + + private void PopulateNotificationList() + { + // Collect data + if (DynamicLink.Modules.Items.Count == 0) DynamicLink.Modules.CollectData(); + + // Add items + int j = 0; + foreach (var i in DynamicLink.Modules.Items.OrderBy(x => x.Name)) + { + ToolStripMenuItem item = new ToolStripMenuItem(i.Name); + item.Click += new EventHandler(menuContextModule_Click); + item.Image = i.Icon.ToBitmap(); + item.ToolTipText = i.Description; + + notifyContext.Items.Insert(j++, item); + } + } + + private void UpdateModules() + { + listModules.Items.Clear(); + foreach (var i in moduleShortcuts) + if (i.Value == null) listModules.Items.Add(new ListViewItem (new string[] { i.Key, "" })); + else listModules.Items.Add(new ListViewItem(new string[] { i.Key, i.Value.ToString() })); + } + + private void UpdateModule(string name) + { + foreach (ListViewItem i in listModules.Items) + if (i.Text == name) + { + if (moduleShortcuts[name] == null) i.SubItems[1].Text = ""; + else i.SubItems[1].Text = moduleShortcuts[name].ToString(); + + return; + } + } + + private void UpdateGlobalHotkeys() + { + KeyboardIO.Hotkey.UnregisterAll(); + foreach (var i in moduleShortcuts) + if (i.Value != null) KeyboardIO.Hotkey.Register(i.Value); + } + + #endregion + + #region Buttons + private void buttonClear_Click(object sender, EventArgs e) + { + if (listModules.SelectedItems.Count != 1) return; + + string name = listModules.SelectedItems[0].Text; + moduleShortcuts[name] = null; + + UpdateModule(name); + } + + private void buttonSet_Click(object sender, EventArgs e) + { + if (listModules.SelectedItems.Count != 1) return; + + string name = listModules.SelectedItems[0].Text; + moduleShortcuts[name] = keyShortcutBox.Key; + + UpdateModule(name); + } + + private void buttonAccept_Click(object sender, EventArgs e) + { + // Update hotkey list + UpdateGlobalHotkeys(); + + // Save settings + if (TibisMathematicsSuite.Properties.Settings.Default.ModuleKeys == null) + TibisMathematicsSuite.Properties.Settings.Default.ModuleKeys = new System.Collections.Specialized.StringDictionary(); + + TibisMathematicsSuite.Properties.Settings.Default.ModuleKeys.Clear(); + foreach (var i in moduleShortcuts) + if (i.Value != null) TibisMathematicsSuite.Properties.Settings.Default.ModuleKeys.Add(i.Key, i.Value.ToString()); + + // Hide window + this.Hide(); + } + + private void buttonCancel_Click(object sender, EventArgs e) + { + this.Close(); + } + + void menuContextModule_Click(object sender, EventArgs e) + { + ToolStripMenuItem menu = sender as ToolStripMenuItem; + + if (menu != null) DynamicLink.Launcher.StartModule(menu.Text); + } + + #endregion + + #region Context menu + private void notifyContextAbout_Click(object sender, EventArgs e) + { + DynamicLink.Launcher.About(); + } + + private void notifyContextSettings_Click(object sender, EventArgs e) + { + allowShow = true; + this.Show(); + } + + private void notifyContextExit_Click(object sender, EventArgs e) + { + allowExit = true; + Application.Exit(); + } + + #endregion + + #region Other event handlers + + void Hotkey_HotkeyPressed(object sender, MyKeyEventArgs e) + { + foreach (var i in moduleShortcuts) + if (e.Key == i.Value) + { + DynamicLink.Launcher.StartModule(i.Key); + return; + } + } + + private void listModules_SelectedIndexChanged(object sender, EventArgs e) + { + if (listModules.SelectedItems.Count == 1) keyShortcutBox.Enabled = true; + + else + { + keyShortcutBox.Reset(); + keyShortcutBox.Enabled = false; + } + } + + private void MainWindow_FormClosing(object sender, FormClosingEventArgs e) + { + if (e.CloseReason == CloseReason.UserClosing && !allowExit) + { + e.Cancel = true; + this.Hide(); + } + + else + { + notify.Visible = false; + TibisMathematicsSuite.Properties.Settings.Default.Save(); + } + } + + protected override void SetVisibleCore(bool value) + { + base.SetVisibleCore((allowShow) ? value : false); + + // We need to reinitialize some settings + if (allowShow && value) + { + moduleShortcuts.Clear(); + listModules.Items.Clear(); + + PopulateModules(); + } + } + + #endregion + + } +} diff --git a/Source/TibisMathematicsSuite/MainWindow.resx b/Source/TibisMathematicsSuite/MainWindow.resx new file mode 100644 index 0000000..7224eaa --- /dev/null +++ b/Source/TibisMathematicsSuite/MainWindow.resx @@ -0,0 +1,1239 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + 130, 17 + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29m + dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAHhSURBVDhPlZO9axNxGMfzfzhIKQ5Ojo6uOoogikPp + IOJkNimt1ry/mBe9mHgxLwg2fdGAYpPWhKgx72I0EGIyZQmBbBmEIHjSj8+ZIYptrg7H3XCfz/f7e+45 + E2AyupLJpDkej3djsZgWjUa1P983hBOJhFnAyXA4ZDweE4lEhJ+FGgoE7g4GA0ajEblcjlAo9H8CVVU1 + Pb3VaqEoSklPDwQC+Hw+vF6vZthAKv/s9/tUq1WCweAHv99fTqfT9Ho9XC7XfEE4HD4vlQ86nQ6NRoNC + oUA+n6dUKlGpVHA4HN3DG7y4qUxSN1pSWavX6zSbTfR7rVajXC5TLBax2+0Tq9Vq/lewc11h3wKZNb5t + 3aLdbpPNZvF4PAd6ZUnVbDZb12KxmPV5/C3Y0uG78GUHPm9D2sz4yRJut/u70+lcPGxfZoLUssLemsAC + vn8Ab+9D4ylsLPPDdfbjUcs2FaSWFDKr0NyEdwHYFdEbB1RjkLwKltPPjxY8u6awuyJwSlL98Fqe92xQ + jkL8CqyfSs9bdROJS/BpAwpS+dVtyN4TWBX4MtxZnAtPhxi+AHU5676kZtah9BiiIl1deGn0k00FD881 + 9UH9BouPQL0IKyePBc8+o+PMVxmUVF4Q+MSxYV3wC96R+On8pC6/AAAAAElFTkSuQmCC + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29m + dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAALeSURBVDhPlZNrS5NhGID9AUVBEfQhIsoK6Yx0VrNY + I7WWNWra1JU1MUqbupa2rdVWuZbpTG3ulNNNK1EztexodrLSDuowsnPRAaH+QMHVuwW+9CXow/Xxuu77 + eXieCCDifwm691oHnLt/Pjuj/vFf8pB33ytBZrj1KFftqfSeVo2MBkwmE0ajEb1eT1FRETqdDq1WS15e + HkGvhiFvLq8vHefbYCNfnp+ns0zBg1MpYsBgMFBdXR3G6XSGcblcYQY9uXztvyDQyIceB2/v2LlSuoVu + 6yYxEJrqqHaQYt80KrvdbkI8d+7h89MG3nWX8vqmVcDG5ZLN3LAkioHQyvKy9UhOxISnhkSPxxOmr0rN + p97asDx81SxgocOWzGXjGjEgs0rJblCxy59G7JElrDBGs6RwIdHaeTwqV/Gxx8twp5kX7QZetBlpt8po + LVzxJyA9GTeQVZ9B1ZMSynutlDy0UPzAhPnuQRbsi+LeqVTe33UIop6hlgK+30unrTiRxvzokYi1tlif + OpBORZ+NY/cN6G/no7uZg+Z6NvouLXP2zKLLKudNVwXBJi0fOjMhmEinbTX1OXP+bBBnXhpM82wZnXqo + W0fhrTy0N3KZnTWDa5YkXl0vof9cDv31at61Z9B6VIovO1K8g9j9y5BXrmejfR1zc2YTtXsms9TTicyc + RrtRwssrxTyry6LPu52+s5m0miW4d04VAyqVijjdcuL3x+Dz+aitrQ1TV1fHxcIY4fxHBHEHj5ypPHal + 03J4DQ7VZDGgVCqpqalhVf7KUTEk+/1+LhQsJthiEORt9FTKeViloNkUT4VyghhQKBR/TQ2JIQKBAIHc + +Qw0HmBQoL8hnyc12TQfWoU9ZdxIROjpajQa5HI5ycnJyGQykpKSSEhIQCqVIpFI8GRFcq5gES36GDos + Uq6d2ECTMZbSrWPEDf71pV2ZUyYJ511WmTZxR3nq+OIyxVh/uXLCLyHw/TcG7aVnWm0CjgAAAABJRU5E + rkJggg== + + + + + AAABAAQAEBAAAAAAIABoBAAARgAAACAgAAAAACAAqBAAAK4EAAAwMAAAAAAgAKglAABWFQAAQEAAAAAA + IAAoQgAA/joAACgAAAAQAAAAIAAAAAEAIAAAAAAAQAQAAAAAAAAAAAAAAAAAAAAAAAD///8B////Af// + /wH///8B////AQAAAAUAAAAJAAAABQAAAAP///8B////Af///wH///8B////Af///wH///8B////Af// + /wEAAAAHAAAAGwAAAEcXCgODXjMQpRMKBIMAAABlAAAASwAAADEAAAAdAAAADwAAAAf///8B////Af// + /wEAAAAdBAEAe0wiCbuSQhLlxVkZ/eyVKv/6qzH/1o8p9ahsIOV0RhbTOR8LuwEBAJ8AAACBAAAAMQAA + AAMAAAADkUQTn7VSF/vKWxr/y1sa/8tbGv/sliv/+64y//mnMP/2oS7/8pkt/+2RK//egij9r2Qg75pX + H7llRjMJ////AbZWGte+Vxr/xVka/8paGv/LWxr/65Mq//inMf/1pzH/8qQx/+ySLP/miiv/4IQp/9d6 + J//PcyX/tX5aC////wGqURrVsVIa/7tVGv/DWBr/yVsa/+mPKf/zoDD/98hl//vtvf/rqTf/7blZ/+7E + d//Sfin/xGkk/7J8Vwv///8Bm0wZ1aNOGf+tURr/t1Qa/8BYGv/khyj/7ZUu//C1Qv/+++L/8s9k//rr + vP/54KX/0Yg+/7diIv+nc08L////AYxHGdWUSRn/n0wZ/6lQGf+0VBr/238n/+WJK//hiiv/89J+//TS + gP/547H/355E/7djI/+pWSD/nGhGCf///wF+QxnVhUQZ/49HGf+bSxn/pk8Z/9J3Jf/ehCv/3pE4/+es + R//10pL/+Nie/+CgVP+sXCL/mVAe/49dOwn///8Bcz4Z1XdAGf+BQxn/i0YZ/5dKGf/GbST/1X0o/+3F + if/64Kj//vLa//7t1P/z07H/sW88/4hJHf+CUzEJ////AWs7GdVtOxn/dD4Z/31BGf+IRRn/umQh/8Zs + I//HdSj/045G/8p+NP+5ayf/pFsj/4pMHv96Qxv/dkgnCf///wFpOxnVZzkZ/2o6Gf9xPRn/ekEZ/61c + IP+4YSH/rVog/6JUHv+VTh3/iUkc/35FG/92QRv/bj0a/2w+Hgn///8BajsZoWc5GftmORn/aToZ/289 + Gf+gVB7/qlcf/51RHv+PSxz/hEcb/3pDGv9yPxr/bDwa6Wg6GbVmORkF////Af///wFoOhkZZzkZcWY5 + Gc1pOhn/kk0d/5hPHf+LSh3xgUccvXlDHIlyQBtVbj8cIf///wH///8B////Af///wH///8B////Af// + /wH///8BZzkZK4dLIGGOUScphlg3A////wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAD//wAA + //8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//ygA + AAAgAAAAQAAAAAEAIAAAAAAAgBAAAAAAAAAAAAAAAAAAAAAAAAD///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////AQAAAAMAAAAHAAAADQAAABMAAAARAAAADQAAAAkAAAAFAAAAA/// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8BAAAAAwAAAAcAAAARAAAAIwAAAD0AAABZAAAAawAAAGcAAABZAAAARwAA + ADcAAAArAAAAHwAAABcAAAAPAAAACQAAAAcAAAADAAAAA////wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8BAAAABQAAABEAAAAjAAAAPQAAAGMAAACFAAAApzwbB9GUURjpf0UX1zUb + DMMAAACrAAAAnwAAAJEAAACBAAAAcQAAAF8AAABNAAAAPQAAAC8AAAAjAAAAFwAAABEAAAAJAAAABf// + /wH///8B////Af///wH///8BAAAAAwAAABEAAAAzAAAAXwAAAIcAAAChIg8Eu3EzDt2zUBb3y10a/916 + Iv/8rzL//K8x//SfL/3Ifijzkl8d4Wg1FNUYDQbBAAAAtQAAAK0AAACjAAAAlwAAAIcAAAB1AAAAYwAA + AEcAAAAlAAAAC////wH///8B////Af///wEAAAARAAAASwAAAJkKBAHBVycL16FJFO/KWxn/y1sa/8tb + Gv/LXBr/3Xwj//yxM//8sDP//K8y//uuMP/7qzD/+akw//mmL//kiCv7qmki7X9IGN9DIQ7TBgMCwQAA + ALsAAAC3AAAApQAAAHEAAAAlAAAABf///wH///8BAAAABQAAACtKIgmlhD0R78BXGP3LWxr/y1sa/8tb + Gv/LWxr/y1sa/8tcGv/dfCP//LEz//yxMv/7rzL/+qsx//moL//4pS//9qEu//WeLv/ymi3/8JUs/+6S + LP/oiir/xW4l945TG+djMhPbLBgMsQAAAEEAAAAJ////Af///wEAAAAHsVQYq8JaGv/FWhr/x1oa/8pa + Gv/LWxr/y1sa/8tbGv/LWxr/y1wa/918I//8sDL/+64y//qrMv/5pzD/96Uv//ahLv/0nS3/8pkt/++U + LP/tkSv/6o0r/+eJKv/khin/4YMp/92AKP/Zeyf/0Xcr9YtgRhn///8B////AQAAAAOzVhqzvFga/79Y + Gv/DWBr/xlka/8laGv/KWxr/y1sa/8tbGv/LXBr/3Xsj//qtMv/5qzH/+Kcx//elMP/1oy7/9J4u//GZ + Lf/ulCz/7I8r/+mMKv/mhyr/4oQp/9+BKP/cfij/2Hon/9R3Jv/QdCX/sXtXF////wH///8B////AbJW + Gq21VRr/uVUa/71XGv/CVxr/xVka/8haGv/KWhr/y1sa/8tcGv/deyP/+akx//inMf/2pDD/9aYy//Wu + Nf/zsDf/8acz/+2XLv/ojCv/5oor/+SMLP/hiSv/3YMq/9d6KP/TdiX/znIl/8puJf+6gl0V////Af// + /wH///8BrFMbra5SGv+yUxr/t1Qa/7xVGv/AVxr/xFga/8ZZGv/KWhr/y1wa/9x5I//3pzD/9qQw//Sh + Mf/0rTb/+NFn//vnpf/20mT/7ag1/+eSLv/lmC//6ak2/+mrN//hmjH/1oIp/85zJv/JbST/xWok/7V+ + WhX///8B////Af///wGlURqtp1Aa/6xRGv+xUhr/tVQa/7pVGv++Vhr/wlga/8VZGv/KWxr/23gi//Wi + MP/zny//8Z0w//OyOP/88L////////796//yyEj/6KM0/+y1QP/67sH//vvx//LQhf/aji7/y3Qn/8Nq + JP++ZiP/sHlVFf///wH///8B////AZ1OGq2fTRn/pE4Z/6lQGv+uURr/s1Ma/7hUGv+9Vhr/wVga/8Va + Gv/ZdSL/8p0v//CZLv/umC//76k1//jdav////f////8//fjef/rtDr/9NR3/////v//++3//ffk/92b + Qv/IdCf/vWUj/7hiIv+qdlET////Af///wH///8BlkwarZhLGf+dTBn/ok4Z/6hPGv+sURr/slMa/7dU + Gv+7Vhr/wFka/9VyIf/vmC7/7ZQt/+qRLf/ply7/77g7//zymP//////+uqg/+68Pf/32n3///////zd + ef/qs0z/3KVp/8JtJv+3YiL/sF4h/6VxTRP///8B////Af///wGPSRqtkEgZ/5VJGf+bSxn/oEwZ/6VO + Gv+rUBr/r1Ia/7VUGv+6Vxr/0HAh/+yULf/pjiz/5oor/+OIKv/lmjD/8clH//753f/87bj/7ro7//XQ + bv///v3/8sBa/9WJLv/BbSf/uGMj/69dIf+qWSD/n2tIE////wH///8B////AYdGGq2JRhn/jkcZ/5NJ + Gf+YShn/nkwZ/6NOGf+pUBr/rlIa/7RUGv/LbSH/6I4s/+WJK//hhSr/3oEo/92GK//mpTb/+OKf//zx + 0v/ssjr/8cJe///9+f/rtmD/ynkr/7VhI/+uWyH/qFgg/6NVH/+ZZkMT////Af///wH///8BgUUarYJD + Gf+GRBn/i0YZ/5FIGf+WShn/m0sZ/6FNGf+nTxr/rlIa/8VpIf/kiSv/4YUr/96EKv/chCr/2YIq/96W + MP/wxWz//fXj/+qqOf/vtk///vv2/+27cv/IeCv/r10i/6dXIP+gUx//mlAe/5JgPhH///8B////Af// + /wF6Qhqte0IZ/39CGf+EQxn/iUUZ/45HGf+USRn/mksZ/6BNGf+mUBr/v2Ug/9+DKv/cgSr/3Ics/+Sl + Vv/elzX/4Z4z/++4Tf/++e3/8rI9//a1Qv//+vL/98eD/9WFMf+1ZSb/pFch/5hQHv+RTR7/i1s4Ef// + /wH///8B////AXVAGq12Pxn/eEAZ/31CGf+CQxn/h0UZ/4xHGf+SSRn/mEoZ/59NGf+5YiD/2n0p/9d8 + Kf/ZiCv/7seP//Xbq//wukr/+slb///57v/+0n3//tWN///79f/+5sb/89Kt/8uRX/+hVyH/kE0e/4lK + Hf+GVjQR////Af///wH///8BcT4arXA9Gf9yPxn/dj8Z/3pBGf+AQhn/hUQZ/4tGGf+QSBn/l0sZ/7Je + H//VeCf/0XUm/9J8J//bkzT/9t64///+/P/////////////////++vb//OzZ//bXuP/nv5r/v4FP/5hT + If+ISh3/gUYc/39QLhH///8B////Af///wFtPBqtbDwZ/208Gf9wPRn/dT8Z/3lAGf9+Qhn/g0MZ/4lF + Gf+PSBn/rFse/89yJf/LbyT/yXAk/8x5KP/WijP/5Kld/+m0b//lolH/3Iw2/9SCL//MeS3/wW4p/7Bj + Jv+cViH/ikwe/4BGHP97Qxv/eUsqEf///wH///8B////AWs7Gq1oOhn/aTsZ/2w7Gf9vPBn/cz4Z/3dA + Gf98QRn/gkMZ/4hGGf+lVx7/yW4l/8RpI//AZiL/vWYj/75pJP+/bSb/vm0n/7hnJf+wYSP/p1si/55W + IP+WUR//jEwe/4RIHf9+RRz/eUIb/3RAGv9zRSQP////Af///wH///8BazwarWg6Gf9nORn/aDoZ/2s7 + Gf9tPBn/cT0Z/3Y/Gf97QRn/gUQZ/55UHf/DaST/vmUi/7lhIf+0XiD/r1sg/6pYIP+kVR//nlIe/5dP + Hf+QTB3/ikoc/4VIHP9/RRz/ekMb/3dBG/9zPxr/bz4a/25BIA////8B////Af///wFrPBqtaDoZ/2c5 + Gf9mORn/aDoZ/2o6Gf9sOxn/cD0Z/3Q/Gf96QRn/mFEd/71jIv+4YCH/sl0g/61ZIP+nVh//oFIe/5pQ + Hv+TTh3/jksc/4dJHP+CRxv/fUQb/3hCG/90QBv/cj8a/249Gv9rOxn/ajwcD////wH///8B////AWw8 + Gq1pOhn/ZzkZ/2Y5Gf9mORn/ZzkZ/2k6Gf9rOxn/bz0Z/3Q/Gf+STRz/tmAh/7FcIP+rWB//pVUf/55R + Hv+XTh3/kEwd/4tKHP+FSBv/f0Yb/3tDGv93QRr/cz8a/3A+Gv9tPRr/ajsZ/2g5Gf9mORkP////Af// + /wH///8BajsaN2o7GaFoOhnxZzkZ/2Y5Gf9mORn/ZjkZ/2g6Gf9rOxn/bz0Z/4tKHP+uWyD/qVcf/6NU + Hv+cUR7/lU0d/45KHP+ISRz/gkYb/35FG/95Qxr/dUAa/3E+Gv9tPRr/bDwa72k7GblmORmFZjkZUWY5 + GQP///8B////Af///wH///8B////AWk7GQloOhlZaDoZtWc5GftnORn/ZjkZ/2g6Gf9sPBn/hkcc/6dV + H/+hUx7/mVAe/5JNHf+MShz/hUgc/4BGG/97Qxv/eEIa9XRBHMNwPhqNbz8cWWw/HiX///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BaDoZFWg6GW1mORnHZjkZ/2k7 + Gf+ARRz/nlIe/5dPHf+QSx3/iUkd+YRKIM2ARx6XfEYgY3lIJi93SSgD////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wFmORklaDoZgX1GH+WWUiOhkFAja4pULzmGWDcH////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAoAAAAMAAAAGAAAAABACAAAAAAAIAlAAAAAAAAAAAAAAAAAAAAAAAA////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA + AAMAAAADAAAABQAAAAUAAAADAAAAAwAAAAP///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wEAAAADAAAABwAAAA0AAAATAAAAFwAAABkAAAAVAAAAEQAAAA0AAAALAAAACQAAAAcAAAAFAAAAA/// + /wEAAAAD////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA + AAMAAAAFAAAACwAAABMAAAAfAAAALQAAAD0AAABNAAAAWwAAAFsAAABXAAAATQAAAEMAAAA5AAAALQAA + ACcAAAAfAAAAGQAAABMAAAAPAAAACwAAAAkAAAAHAAAABQAAAAMAAAAD////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA + AAMAAAAFAAAACwAAABEAAAAbAAAALwAAAD8AAABVAAAAbwAAAIcAAACbLRcKswgEAacAAACdAAAAkQAA + AIcAAAB9AAAAcQAAAGUAAABZAAAATQAAAEMAAAA5AAAALwAAACUAAAAfAAAAFwAAABMAAAAPAAAACwAA + AAkAAAAFAAAABQAAAAMAAAAD////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wEAAAADAAAABwAAAA8AAAAXAAAAKQAAADkAAABPAAAAawAAAIEAAACXAAAArRwNA8djLQzjtl0b9b90 + Iu+qWB/nWS4U0xYMBr0AAACzAAAAqwAAAKMAAACdAAAAkQAAAIcAAAB9AAAAbwAAAGUAAABZAAAASwAA + AEEAAAA3AAAALQAAACUAAAAdAAAAFwAAABEAAAALAAAABwAAAAP///8B////Af///wH///8B////Af// + /wH///8B////AQAAAAUAAAAPAAAAJQAAAD0AAABXAAAAdQAAAIkAAACbCwUBrygSBcFPIwrTm0UT78VZ + Gf3LXBr/1Gwe//WjLv/8rzH//K8x//qqMP/skC77umol8XpMG99QMxDPPB8LySIRB8MHBAK5AAAAsQAA + AKsAAAClAAAAmwAAAJMAAACJAAAAewAAAHEAAABlAAAAVwAAAEkAAAA3AAAAIQAAABEAAAAH////Af// + /wH///8B////Af///wH///8BAAAABQAAABUAAAAvAAAAWwAAAH8AAACbAAAArRQJArtJIQnNgjsQ46tN + FfPGWRn9ylsZ/8tcGf/LXRn/1W0f//WjL//8rzP//K8x//uuMf/8rzH//K8x//yuMP/3pC//4Ykr+bt1 + JfGXZB3jfEQX3VYrEdUjEwnJAAAAuwAAALkAAAC1AAAArwAAAKkAAACjAAAAmQAAAIkAAAB1AAAATwAA + ACsAAAARAAAABf///wH///8B////Af///wEAAAADAAAAEQAAAC8AAABhAAAAnQAAAL0WCgLLbTEN4aNK + FO+6VBf5ylsZ/8pbGf/LWxn/y1sZ/8pbGf/LXBn/1W0f//SlL//8sDP//LAz//uvMv/8rzL/+64w//us + MP/6qjD/+akw//mnL//4pC//75ct/eCMKvvNgyf1uGsj75JKHOdTKhPZDQgExQAAAL8AAAC/AAAAvQAA + ALcAAACrAAAAhQAAAFEAAAAhAAAACf///wH///8B////Af///wEAAAAFAAAAIRUJAlcsFQWjUiYK4ZJD + E/fDWRn9y1sa/8tbGv/LWxr/ylsZ/8tbGv/LWxr/ylsZ/8tbGv/LXBr/1W0f//WlL//8sDP//LAy//uw + Mv/7rjL/+qsx//qpL//5qC//+KYv//ejLv/2oS7/9Z8u//SdLf/ymi3/8ZYs/++TLP/ukiz/6Ywr/9V1 + JvunWiHxZjoV30IkDNEwGAnNGg4GswoGA3MAAAA1AAAADQAAAAP///8B////Af///wEAAAAJejkRUZZG + FLWoThbrxVsZ/8hbGv/KWxr/y1sa/8pbGv/KWxr/ylsZ/8taGf/KWhn/ylsZ/8tbGf/LXBn/1W0f//Wl + L//8sDP/+7Ay//uuMf/6rTH/+aox//mnL//4pi//96Qu//WhLv/0ny7/85wt//KaLf/wlyz/75Ms/+2R + LP/sjyv/6Ywq/+eKKv/liSr/44Yp/9t9KP3CaiT5oVsg55lYH7+kYCuNXEAvFwAAAAP///8B////Af// + /wEAAAAHqVAXi79aGv3CWhr/w1oa/8ZZGf/HWRr/yVoa/8pbGf/LWxr/y1sZ/8pbGf/LWxn/y1sZ/8pb + Gf/LXBn/1W0f//SlL//8sDL/+64y//qsMf/6qjL/+acw//elL//3pC//9qEu//SeLv/zmy3/8pkt//CW + LP/ukyz/7ZAr/+uOK//piyv/54kq/+WHKv/jhSn/4YMp/96BKP/cfyj/2Xsn/9Z5J//Rdyn3mWpMJwAA + AAP///8B////Af///wEAAAAFrVMZjbtZGv+9WBr/v1ga/8FYGv/EWBr/xlka/8haGv/KWhr/ylsZ/8tb + Gv/LWxr/ylsZ/8tbGv/LXBr/1W0e//SjLv/6rTL/+asx//mqMf/4qDD/96Yw//akLv/1oi7/9J8u//Kb + Lf/xmS3/75Us/+6SLP/skCv/6o0q/+iKKv/mhyr/44Up/+GDKf/fgSj/3YAo/9p9J//Yeif/1Xcm/9N1 + Jf/QdCX/sHpXI////wH///8B////Af///wEAAAADsFQaibhXGv+5Vhr/vFYa/75XGv/BWBr/w1ga/8VZ + Gv/HWRr/yVoZ/8paGf/KWhn/ylsZ/8tbGf/LXBn/1G0e//OhLv/6qzH/+akx//inMP/3pTD/9qQx//Wl + MP/0pjH/86Ux//GgMf/wnC//7ZUt/+yQLP/pjCv/54oq/+WIKv/khyr/4YQp/9+CKf/dgCj/2Xwn/9d5 + J//Vdyb/0XUm/89yJf/NcCX/t39bIf///wH///8B////Af///wH///8BsFUahbNVGv+1VRr/uFUa/7pV + Gf+9Vxr/wVca/8NXGf/FWRr/x1kZ/8haGf/KWhn/y1sZ/8pbGf/LXBn/1G0e//OgLv/5qDH/+Kcx//al + MP/2pDD/9aYy//WrNP/1sTb/9LQ5//OwN//wqDT/7Zov/+qRLf/niyv/5osr/+WNLP/kjiz/4o0s/9+I + K//cgyr/2Hso/9R3Jv/SdSX/znIl/8twJf/JbSX/uYJdIf///wH///8B////Af///wH///8BrFMbg65T + Gv+vUhr/slMa/7VUGv+4VBr/vFUa/75WGv/BVxr/w1gZ/8ZZGv/HWRr/yVoZ/8pbGv/LXBr/1Gwe//Kf + Lv/3pzD/9qQw//WiMP/0ojH/9Ko1//W4Pf/4z2D/+dx7//jWa//0xEj/7qg1/+mXL//mkC3/5ZMu/+ad + Mf/opTT/6Kc1/+SfM//fky//14Iq/9J5Jv/OciX/ym4k/8dsJP/FaiT/tX5aH////wH///8B////Af// + /wH///8BqFMbg6lRGv+rURr/r1Ia/7JTGv+1Uxr/uFQa/7tVGv+9Vhr/wVcZ/8NXGf/FWRn/x1kZ/8la + Gf/LXBn/1Gse//CcLf/2pDD/9aIv//OfL//zoDH/8603//fJWP/88MD///////798f/66p7/8Lw8/+mi + M//mmDD/56Ez/+y1Qf/yzm7/9dmS//DJcP/mqDv/2ows/9F7KP/Lcib/xmsk/8NpJP/BZyP/snxYH/// + /wH///8B////Af///wH///8Bo1Eag6VQGv+nTxr/qlAa/61RGf+wUhr/tFMa/7ZUGf+5VRr/vVYZ/8BW + Gf/CWBn/xFkZ/8ZaGf/JWxn/02se/++aLf/0oTD/854v//GbL//xnTD/8q03//bOYP/999f///////// + ///+/er/9NVW/+yxOP/opDT/67M+//bbjv/9+OT//v35//335v/xzX//3ZUw/9F/Kv/Jcib/w2ok/8Bn + I/+9ZSP/r3lVH////wH///8B////Af///wH///8Bnk8ag59OGf+gTRn/pU4Z/6hQGv+rURr/rlEa/7JT + Gv+0VBr/uFQZ/7tVGv++Vxr/wVgZ/8NZGv/GWhr/0Wke/+6XLP/ynS//8Zsu/++YLv/umTD/76c0//PA + Q//76on////5//////////r/+uyO/+7APf/qsjn/8MZY//z11P////7///76//777f/9+e7/4KFD/9CA + K//HcSb/v2ck/7tjI/+4YiL/q3VRHf///wH///8B////Af///wH///8BmU0ag5pMGf+cTBn/oE0Z/6NO + Gf+mTxr/q1Aa/61RGv+xUhr/tVMZ/7hUGf+6Vhn/vVcZ/8BXGf/DWhn/zmge/+yTK//wmi7/75cu/+2U + Lf/slS7/7J0x/++wOP/1007//vvB////+/////7/+/Ky//HHQf/suDz/881e//343v///////vPI//vd + fv/226P/5bR0/8x8K//Ebib/u2Qj/7dhIv+0XyL/p3RPHf///wH///8B////Af///wH///8BlUsag5ZL + Gf+XSxn/nEwZ/55MGf+iThn/pk8a/6lPGf+sURr/sFIZ/7NTGf+3VBn/ulUZ/71WGf/AWRn/zGYe/+mQ + K//uly7/7JQt/+uRLf/pkC3/6JQt/+qgMv/vujv/+ehw//792////////fTH//PNTv/uuj3/9M9e//73 + 3f///////OGK//K9P//lqUn/5LiI/8d1KP+/aiX/tmIi/7JfIv+vXSH/pHBNHf///wH///8B////Af// + /wH///8BkEoag5BJGf+SSBn/lUkZ/5lKGf+cSxn/oEwZ/6NNGf+nThr/q1AZ/65RGv+xUhr/tVQZ/7hV + Gv+7WBr/x2Qe/+eOKv/sky3/6o8s/+iNLP/liiv/5Ikq/+SQLP/noTP/8MdE//rqlP/+/fP//fXT//TO + Xf/uuDv/8shW//zy0P///v7/981r/+WjNv/Uhy3/xXEo/71qJf+4YyP/sV4i/65bIP+qWSD/n2tIG/// + /wH///8B////Af///wH///8Bi0gag4xHGf+NRxn/kUgZ/5RJGf+XShn/m0sZ/59MGf+iTRn/pk8Z/6lR + Gf+tURn/sVIZ/7VUGf+4Vhn/xWMe/+WLKv/pjyz/54ws/+WJK//jhyv/4IQp/+CGKv/hkS7/6a45//TQ + X//99tz//fbd//TMaP/ttTr/8cBR//zsxf///v3/8cVu/92UMv/Leir/vGck/7ZiI/+xXSL/rFsh/6lZ + IP+mViD/nGlGG////wH///8B////Af///wH///8BhkYag4dGGf+JRhn/jEcZ/49HGf+TSRn/l0oZ/5pK + Gf+dTBn/ok0Z/6VOGf+pUBn/rFEZ/7BSGf+0VBn/wWIe/+KIKv/njCz/5Ykr/+KHK//ghCr/3oEo/9yB + Kf/chiv/45wz/+y6R//56bf//fjp//PLc//rsDr/7rhL//rmuP///vz/8MN3/9iNMP/FdCn/tWEj/7Bc + If+sWiH/qFgg/6RWIP+hVB//mWVDG////wH///8B////Af///wH///8BgkUag4JEGf+DQxj/hkQZ/4pF + Gf+MRxn/kUgZ/5RJGf+YShn/m0sZ/6BNGf+jThn/p08a/6tRGv+vUxr/vWAd/9+EKf/kiSv/4YYr/+CF + K//egyn/3IQq/9qBKv/Zgir/3ZIu/+apOv/004r//fnv//LKfv/pqjn/7a9E//jeq//+/fr/8suO/9iN + MP/Dcin/sF4i/6pYIf+nViD/oVQf/59SH/+aUR7/k2A+G////wH///8B////Af///wH///8BfkMag35C + Gf9+Qxn/gkMZ/4VEGf+IRRn/jEYZ/5BIGf+TSRn/l0oZ/5tKGP+eTBn/ok0Z/6ZPGf+rURr/uV4d/9uA + KP/hhSr/3oMq/96EK//dhiv/3Ios/9uJLP/aiSv/3JMv/+SiNv/wwmf//vv1//TPif/sqzn/77BB//nZ + nv/+/Pn/99Oc/9+SM//JeSz/tGIk/6paIf+kViD/nFIe/5lQHv+UTh7/jl47G////wH///8B////Af// + /wH///8BeUIag3lBGf96QRj/fkEZ/4BCGf+DQxn/iEQZ/4tGGf+ORxn/kkgY/5ZJGf+aSxn/nUwZ/6JO + Gf+mUBn/tVwd/9l9KP/egir/3IAp/9uCK//ciS3/57Fp/+WqV//fmjX/4Z80/+ipOP/yv1X//vz2//nV + j//0tD7/97VA//zXlP/+/Pj/+9qq/+maOP/SgjD/uWkn/6tdI/+hViH/mFAe/5NNHv+PTB7/i1o4G/// + /wH///8B////Af///wH///8BdkAag3ZAGf93Pxj/eUAZ/3tBGf9+Qhn/gkMZ/4VEGf+JRRn/jEcZ/5BI + Gf+USRn/mEoZ/5xMGf+gThn/r1kd/9V5J//afSn/2Hwp/9iBK//aiyz/7MGF//flxv/uw3X/7LRE//K6 + Qv/6yFr///rx//7gpP/+x2D//sdm//7epf///Pf//ubG//e/eP/quof/0Zln/61gJP+eVSD/kk4e/41L + Hf+JSh3/h1c1G////wH///8B////Af///wH///8Bcz8ag3I+Gf9yPhn/dT8Z/3dAGf96QBn/fUIZ/4FD + Gf+EQxn/iEUZ/4tGGP+PRxn/k0kZ/5dKGP+bTBn/q1gc/9F2Jv/Xeij/1Hgn/9R9KP/WhSr/4J9G//PX + q//89OX/+eKx//vhp//+6bn//vz1//735///8tv//vbp//779////v7//v7+//7+/v//////4b+i/6tf + JP+bVCD/jUwe/4hJHP+ERxz/glMxGf///wH///8B////Af///wH///8BcD4ag3A9Gf9vPRj/cT4Z/3M+ + Gf92Pxn/eUAZ/3xBGf+AQhn/g0MY/4dEGf+KRhn/j0cY/5JJGf+XSxn/p1Yc/85zJv/Udyb/0XQm/892 + Jv/RfCf/2Isu/+SqVv/24Lv///37//7+/f/+/v7///////7+/v/+/v7//vr2//3v3v/74MD/88ib/+ew + e//Ym2T/vntF/6JZI/+UUSD/iEod/4NHHP9/RRz/fk4tGf///wH///8B////Af///wH///8BbT0ag208 + Gf9sOxj/bTwZ/288Gf9yPRn/dT8Z/3hAGf96QRn/fkIZ/4FCGf+FQxn/iUUZ/41HGf+RSRn/olMc/8pv + JP/PciX/zHAk/8pvJP/KcSX/zXoo/9OFLP/bkzr/6bNr//DHkP/wxYn/7bJn/+ehTP/hkTb/24gx/9aD + MP/RfS7/yXUr/79tKf+yZCf/olkj/5VSIP+KSx7/gkcc/35FHP97Qxv/ekwqGf///wH///8B////Af// + /wH///8BbDwag2o7Gf9qOxn/azsZ/2w7Gf9uPBn/cT0Z/3Q+Gf93Pxn/ekAZ/3xCGP+AQhn/hUQZ/4hF + GP+NRxn/nVEb/8ZsI//LbyX/yG0k/8VrI//EayP/xG0k/8ZzJ//KeCn/z38s/9GCLf/RgS7/zX0s/8l3 + K//Ecyn/vW0o/7dpJv+yZCX/ql4j/6JZI/+aVCH/kU4f/4lLHf+CSBz/fUQb/3lDG/93QRv/dkgnGf// + /wH///8B////Af///wH///8BbDwag2k6Gf9oOhj/aDoZ/2o7Gf9rOxn/bjwZ/3A8Gf9yPhn/dj8Y/3hA + Gf98QRn/gEIY/4NEGf+IRhn/mU8b/8JpI//IbSX/xGkj/8FnIv++ZSL/vGUi/7tlI/+7ZyT/u2kk/7tp + Jf+5ZyX/tGMk/69gI/+qXCL/o1gh/55VIP+YUh//k08e/41NHv+ISh3/g0cc/39GHP98RBv/eUIb/3ZB + G/9zQBr/c0QjF////wH///8B////Af///wH///8BbDwag2o7Gf9nOhj/ZzkZ/2g6Gf9pOhn/azsZ/2w7 + Gf9uPBn/cT0Z/3U+Gf93Pxn/e0EZ/35CGf+DRBn/k00b/75mIv/DaCT/v2Yi/7xkIf+5YSH/tl8g/7Jd + IP+vWyD/rFkg/6lYIP+lVh//oVMe/5tSHv+YUB3/kU0d/45LHP+LShz/hkgc/4JHHP9/RRz/e0Mb/3lD + G/93QRv/dEAa/3E/Gv9vPhr/b0IhF////wH///8B////Af///wH///8BbDwag2k7Gf9oOhn/ZzkZ/2Y5 + Gf9nORn/aToZ/2o7Gf9rOxn/bjwZ/3A8GP9zPhn/d0AZ/3pBGP9+Qhn/j0sb/7ljIv/AZSP/vGMh/7lh + If+1XyH/sVsg/61ZH/+qVx//pVUe/6FTHv+dUR7/mU8d/5VOHf+RTB3/jEsc/4hJHP+GSBz/gUYb/35E + G/97Qxz/eEEb/3VBGv90QBr/cD4a/249Gf9sPBr/bD4eF////wH///8B////Af///wH///8BbDwag2o7 + Gf9oOhj/ZzkZ/2Y5Gf9mORn/ZzkZ/2g6Gf9qOhn/azsY/207Gf9wPRn/cj8Y/3Y/Gf96QRn/i0ob/7Zg + If+7YiL/t2Ah/7ReIP+wXCD/rVkg/6hXH/+lVR//oFIe/5tRHv+YTx7/kk4d/49MHf+MShz/h0kc/4NI + G/+ARhv/fEQb/3pDG/93QRv/dD8b/3I/Gv9wPhr/bj0a/2s8Gv9qOxn/aTwbF////wH///8B////Af// + /wH///8BbDwag2s7Gf9oOhn/ZzkZ/2c5Gf9mORn/ZjgZ/2Y5Gf9nORn/aToZ/2s7Gf9sOxn/bz0Z/3I+ + Gf92QBn/h0gb/7FdIP+2YCH/sl0g/69aIP+rWB//p1Yf/6NTHv+eUR7/mE8d/5RNHf+RTB3/jEsc/4hJ + HP+FSBv/gUYb/35FG/97Qxr/eEEa/3ZBG/9zPxr/cT4a/289Gv9tPRr/azsZ/2k6Gf9oORn/ZjkZF/// + /wH///8B////Af///wH///8BazsaZ2o7Ge1pOxn/aDoY/2c5GP9nORn/ZjgY/2U4GP9mORn/ZzkZ/2k6 + Gf9qOhn/bDwZ/289Gf9yPxn/g0Yb/6xbH/+xXSD/rlog/6pXH/+nVR//oVMe/55RHv+ZTx7/k00d/49L + Hf+MShz/h0kc/4RHG/+ARhv/fEQb/3lDGv93QRr/dD8a/3I/Gv9wPhr/bj0a/2w8Gv9qOxn/aDoZ/Wc5 + GetmORnJZjkZEf///wH///8B////Af///wH///8BajsaE2o7Gj9qOxmDaDoZ4Wg6Gf9nORn/ZjgZ/2Y4 + Gf9mOBn/ZjkZ/2Y5Gf9oOhn/ajsZ/2w7Gf9vPRn/f0Qb/6hYH/+sWSD/qVcf/6VVH/+hUx7/nFAe/5ZO + Hf+TTB3/jkoc/4lJHP+HSBz/gkYb/39FG/99RBv/eUIa/3ZBGv9zPxr/cT4a/24+Gv9sPRr/bDwa72k7 + Gr9oOhmNZzkYU2Y5GTdmOBglZjkYA////wH///8B////Af///wH///8B////Af///wH///8BaTsZB2k6 + GT9oOhmXaDoZ1Wc6GO9nORn9ZzkZ/2Y5Gf9mORn/aDoZ/2o7Gf9tPBn/e0Ib/6NUHv+nVR//o1Qe/55S + Hv+aUB7/lE4d/5BMHf+MShz/h0gc/4RHG/+BRhv/fEQb/3pDGv94Qhr3dEEb5XE/GtNwPhnDbz8ckW0/ + HV9rPx0t////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8BaDoYK2g6GWFoOhmbZzkZ4Wc5GP1mORn/ZjkZ/2g6Gf9rPBn/eUIb/55S + Hv+iUx7/nVIe/5hPHf+UTR3/j0sc/4pJHP+HSBz/gkYb/39FHPd8RR3bekQetXhCHJN2Qhxxc0IgS3FC + ISlxQyIJ////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wFoOhgPaDkZM2c5GWlmORm9ZjgZ/2c5 + Gf9pOxn/dkAa/5hQHv+cUR7/lk8d/5JNHf+OSh3/iUkc+4ZKINuCTCOrgEojbX5GHkN7RyEveUgmG3dJ + KAv///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8BZjkZJ2c5GX9oORnBdEAb9ZJOIOGVUB/LkVAhq41SK32JVTBLhlg3Ef///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wFoOhkTfkgibYpULkWQXjoZ////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8BAAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAA + AAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA + //8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAA + AAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA + //8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAA + AAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA + //8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//KAAAAEAAAACAAAAAAQAgAAAA + AAAAQgAAAAAAAAAAAAAAAAAAAAAAAP///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wEAAAAD////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8BAAAAAwAAAAUAAAAHAAAACQAAAAkAAAAHAAAABwAAAAUAAAAFAAAAAwAA + AAP///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////AQAAAAMAAAAFAAAACQAAAA0AAAATAAAAFwAAABsAAAAfAAAAHQAA + ABkAAAAVAAAAEwAAAA8AAAANAAAACwAAAAkAAAAHAAAABQAAAAMAAAAD////AQAAAAP///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////AQAAAAMAAAADAAAABQAAAAsAAAAPAAAAFwAAAB8AAAApAAAANQAA + AEEAAABJAAAASwAAAEsAAABFAAAAPwAAADkAAAAxAAAAKQAAACMAAAAdAAAAGQAAABUAAAARAAAADQAA + AAsAAAAJAAAABwAAAAUAAAAFAAAAAwAAAAMAAAAD////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8BAAAAAwAAAAUAAAAJAAAADQAAABcAAAAhAAAALQAA + AD0AAABPAAAAXwAAAHEAAACBAAAAiwAAAI0AAACJAAAAgwAAAHsAAABxAAAAZwAAAF8AAABVAAAASwAA + AEMAAAA7AAAANQAAACsAAAAlAAAAIQAAABkAAAAVAAAAEQAAAA8AAAALAAAACQAAAAcAAAAFAAAABQAA + AAUAAAAD////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////AQAAAAMAAAAFAAAACQAAAA8AAAAXAAAAHwAA + AC0AAAA/AAAATwAAAGEAAAB1AAAAhwAAAJsAAACvAAAAvVkuFN8dDgXLAAAAuwAAALMAAACtAAAApQAA + AJ8AAACXAAAAkQAAAIcAAAB9AAAAdQAAAGsAAABhAAAAWQAAAE8AAABHAAAAPQAAADMAAAAtAAAAJwAA + ACEAAAAdAAAAFwAAABMAAAAPAAAACwAAAAkAAAAJAAAABwAAAAUAAAADAAAAA////wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAAAwAAAAcAAAANAAAAFwAA + AB8AAAAtAAAAOwAAAE0AAABfAAAAdQAAAIcAAACZAAAApwAAALUAAADDRB8J4Y5BEvXNXxv/7pcq/+yK + LP3MZSX1gkId5zYeENEAAAC7AAAAuwAAALUAAACxAAAArQAAAKcAAAChAAAAmQAAAJEAAACLAAAAgQAA + AHcAAABvAAAAZQAAAFsAAABRAAAASQAAAD8AAAA5AAAALwAAACkAAAAjAAAAHQAAABkAAAATAAAACwAA + AAkAAAAFAAAAA////wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAABQAA + AA0AAAAXAAAAJwAAADkAAABNAAAAYwAAAHUAAACHAAAAlwAAAKUAAACvAAAAuSgSBcl4Ng/lu1QY+8tc + Gv/MXRr/zF4a/+6XKv/8rzH//K8x//yvMf/8rzH/+aQw/+J8LPm2WiTxaDYa3yESCssAAAC9AAAAuwAA + ALkAAAC3AAAAsQAAAK8AAACpAAAAowAAAJsAAACVAAAAjQAAAIUAAAB7AAAAcQAAAGcAAABfAAAAUwAA + AEsAAABBAAAANQAAACkAAAAbAAAAEQAAAAkAAAAD////Af///wH///8B////Af///wH///8B////Af// + /wH///8BAAAABwAAABEAAAAjAAAAOwAAAFUAAABxAAAAhwAAAJsAAACnAAAAsQAAALcTCQLBZS4N26dM + FfHLWxr/y1sa/8tcGv/MXRr/zF4a/81fG//ulyz//K8z//yvM//8rzH//K8x//yvMf/8rzH//K8x//yv + Mf/8rzH/8ZYu/dZvKfeaTCDrTyoU2QgFA8MAAAC/AAAAvQAAAL0AAAC7AAAAtwAAALUAAACvAAAAqwAA + AKUAAACfAAAAlwAAAI8AAACFAAAAeQAAAGkAAABXAAAAPwAAACcAAAAVAAAACQAAAAP///8B////Af// + /wH///8B////Af///wH///8BAAAABwAAABEAAAAnAAAASQAAAG0AAACRAAAAqQAAALcAAAC9AAAAv0kh + CdOVRBPrx1oZ/8tcGv/LWxr/y1sa/8tbGv/LXBr/y1wa/8xeGv/NXxv/7pks//yxM//8sTP//LEz//yv + M//8rzP//K8x//yvMf/8rzH//K4w//urMP/6qzD/+qow//qoMP/5py//5IAs/cBeJPN1PRvlMRsO0QAA + AMEAAADBAAAAwQAAAL8AAAC9AAAAuwAAALcAAAC1AAAAsQAAAKkAAACdAAAAiwAAAG8AAABJAAAAKQAA + ABEAAAAHAAAAA////wH///8B////Af///wH///8BAAAAAwAAAA0AAAAjAAAARwAAAHcAAACjAAAAwwAA + AM8mEQXVeDcP571WGPvLXBr/y1wa/8tcGv/LWxr/y1sa/8tbGv/LWxr/y1wa/8tcGv/MXRr/zV8b/+6Z + LP/8sTP//LEz//yxM//8sTP//K8z//yvM//8rzH/+6ww//urMP/6qjD/+qow//mnMP/5pi//+KMv//ei + L//2oS7/9Z8u//SeLv/ujy3/1W8p+ZxNIO1ZLhbfGA4IywAAAMMAAADBAAAAwQAAAMEAAAC/AAAAuwAA + ALMAAACbAAAAbwAAAEEAAAAbAAAACwAAAAP///8B////Af///wH///8B////AQAAAAcAAAAXAAAANQAA + AGcAAAChEQgCz1oqDO2iShX5zF0a/8tcGv/LXBr/y1wa/8tbGv/LWxr/y1sa/8tbGv/LWxr/y1sa/8tc + Gv/LXBr/zF0a/81fG//umSz//LEz//yxM//8sTP//LEz//yxM//8rjL/+6wy//urMP/6qjD/+qgw//mn + L//4pi//+KMv//eiL//2oS7/9Z4u//SdLv/zmy3/8pgt//GVLf/vkyz/7pIs/+2RLP/ffSj9v14j9YBB + HOlCJBHZBAIBwwAAAMEAAADBAAAAswAAAIkAAABTAAAAKQAAAA8AAAAF////Af///wH///8B////AQAA + AAMAAAAJAAAAHQAAAEVaKgylk0UT6cRbGf/KXBr/ylwa/8tcGv/LXBr/y1sa/8tbGv/LWxr/y1sa/8tb + Gv/LWxr/y1sa/8tbGv/LWxr/y1wa/8xdGv/NXxv/7pks//yxM//8sTP//LEz//yxMv/7sDL/+60y//qr + Mv/6qjD/+acw//mnL//4pi//96Mv//aiLv/1ny7/9Z4u//SdLv/ymi3/8Zkt//CULf/vkyz/7pIs/+2R + LP/rjiv/6o0r/+iKK//niyr/5Ygq/+SFKv/KaSb5mUwf72Q1Gd02IROrAAAAWwAAACsAAAAPAAAABf// + /wH///8B////Af///wEAAAADAAAAC4U+E1O9WRrvw1sb/8RbGv/GWxr/x1oa/8hbGv/KWhr/y1sa/8tb + Gv/LWxr/y1sa/8tbGv/LWxr/y1sa/8tbGv/LWxr/y1sa/8tcGv/MXRr/zV8b/+6ZLP/8sTP//LEz//yx + Mv/7rjL/+60y//qsMv/6qjL/+acv//mmL//4pS//96Qv//ahLv/1ny7/9J4u//ObLv/ymi3/8Zct//CU + Lf/vkyz/7ZIs/+yPLP/rjiv/6Ysr/+eKKv/miSr/5Icq/+OFKf/hhSn/34Ip/96BKP/cfij/2nwo/9N5 + K/nJdzrbg1xEKQAAAAX///8B////Af///wH///8BAAAAAwAAAAmcShZtv1sb/8BaG//CWhr/wloa/8VZ + Gv/GWRr/x1oa/8laGv/KWxr/y1sa/8tbGv/LWxr/y1sa/8tbGv/LWxr/y1sa/8tbGv/LXBr/zF0a/81f + G//umSz//LEz//ywMv/7rjL/+60y//qsMv/6qjL/+acx//imL//3pS//96Qv//ahLv/1ni7/9J0u//Oa + Lf/ymS3/8Zct/++VLP/ukiz/7ZEs/+yOK//qjSv/6Yor/+eJKv/mhyr/5Icq/+KEKf/hgyn/34Ip/91/ + KP/bfij/2Xso/9d6J//Wdyf/03cl/6JwUDUAAAAD////Af///wH///8B////AQAAAAMAAAAHoU4Xabta + G/+9WRr/vlga/8BZGv/CWRr/w1ka/8VZGv/GWRr/yVoa/8pbGv/LWxr/y1sa/8tbGv/LWxr/y1sa/8tb + Gv/LWxr/y1wa/8xdGv/NXxv/7pkr//uwMv/7rTL/+q0y//qsMv/5qTH/+akx//ioMf/3pS//9qQu//Wh + Lv/1oC7/9Jsu//KaLf/xmS3/8JYt/++VLP/ukiz/7JEs/+uOK//qjSv/6Ior/+eHKv/lhir/44Uq/+KE + Kf/ggSn/3oIo/91/KP/afSj/2Xsn/9d4J//Vdyf/03Yl/9F1Jf+welcv////Af///wH///8B////Af// + /wH///8BAAAABadRGWO5WBv/ulga/7xXGv++Vxr/vlga/8FYGv/DWRr/xFka/8ZZGv/HWhr/yVoa/8pb + Gv/LWxr/y1sa/8tbGv/LWxr/y1sa/8tcGv/MXRr/zV8b/+2XK//7rTL/+qwy//qqMv/5qTH/+agx//il + Mf/3pTL/9qUv//WjL//0pDD/9KEv//OfL//ymy//8Jku/+6ULf/tkyz/7I8s/+qNK//piyv/54oq/+aH + Kv/khir/4oQp/+GDKf/fgSn/3oAo/9x+KP/afCj/2Hon/9Z4J//Udyf/0nYm/9BzJv/Ocib/tH1ZLf// + /wH///8B////Af///wH///8B////Af///wGtVBpftlcb/7dWGv+4Vhr/ulYa/7xWGv++Vxr/wVga/8JY + Gv/EWBr/xVka/8daGv/JWhr/ylsa/8tbGv/LWxr/y1sa/8tbGv/LXBr/zF0a/81fG//tmCv/+qwy//qq + Mv/5qTH/+Kgx//elMf/3pTH/9qQy//amMf/1qDP/9aoz//SrNP/ypjT/8aMy//CeMP/umC//7ZIs/+qO + LP/oiiv/54oq/+aJK//liCv/44gq/+GFKv/fhCn/3oAp/9yAKf/ZfCj/13gn/9V3J//TdyX/0XUm/89z + Jv/NcCX/y28l/7uDXiv///8B////Af///wH///8B////Af///wH///8BrlYbW7JWG/+zVRr/tVUa/7dV + Gv+5VRr/u1Ya/71XGv/AVxr/wlca/8NYGv/FWRr/xlka/8daGv/KWhr/y1sa/8tbGv/LWxr/y1wa/8xd + Gv/NXxv/7Zcr//qpMf/5qDH/+Kgx//emMf/2pDD/9qQx//amM//1qTT/9bA2//a2Of/1uTv/9Lc6//Oy + OP/wqjX/7p4x/+yWLv/pjy3/54or/+aLLP/ljSz/5ZAt/+SRLv/jkS3/4Y0t/96JLP/chCr/2X0p/9Z5 + KP/TdyX/0XQm/89yJv/McCX/ym8l/8htJf+5gl0r////Af///wH///8B////Af///wH///8B////AatU + G1uvVBv/sFMa/7FTGv+zUxr/tVQa/7hVGv+6VRr/vFYa/75WGv/BVxr/w1ga/8RZGv/GWRr/x1oa/8la + Gv/KWxr/y1sa/8tcGv/MXRr/zV8b/+yVK//5qjH/+Kcx//emMf/2pTD/9aEw//SjMv/0pzT/9a82//a6 + PP/4y1D/+NJU//fORP/1x0L/8ro8/++oNv/rmzD/6JEt/+aOLf/lkC3/5pYv/+acMv/noTP/56M0/+Wd + M//hlzD/3Y0u/9mCK//UfCf/0XYl/85yJv/MbyX/yW0l/8hsJf/FayT/tn9aKf///wH///8B////Af// + /wH///8B////Af///wGqVBtbq1Mb/6xSGv+uUhr/sFIa/7JTGv+1VBr/uFUa/7pVGv+8VRr/vlYa/8BX + Gv/CWBr/xFga/8VZGv/GWhr/yVoa/8pbGv/LXBr/zF0a/81fG//rlCv/96cx//emMP/2ozD/9aIw//Sg + Mf/0ojL/9Ko2//W2Ov/40V7//fC1/////////////ffJ//bTTP/xujv/66M0/+iXMP/mlC7/5Zcw/+ek + M//rrzj/7bk8/+27Pf/rszv/56o4/+GaMf/aiyz/1IAo/891J//McSb/yW0l/8ZrJP/EayT/w2gk/7R+ + Win///8B////Af///wH///8B////Af///wH///8BplMbW6dSG/+oURr/q1Ea/61SGv+vUhr/slMa/7RT + Gv+3VBr/uFUa/7tVGv+9Vhr/wFca/8FXGv/DWBr/xVka/8ZZGv/HWhr/ylsa/8xdGv/NXxv/65Ir//al + MP/2ozD/9aIw//SfL//znTD/8qAy//OqNv/1uzv/++SP/////v/////////////////9+MP/9MxC/+2x + OP/ooDP/5pwy/+ilNP/stTr/889f//vvuf/+++7//fXY//TSdf/mqTX/3pUv/9WDKv/OeCj/ynAm/8Zr + JP/EaiT/wWgk/79nI/+xelYp////Af///wH///8B////Af///wH///8B////AaJRGlukUBr/pU8a/6dP + Gv+pUBr/q1Ea/65SGv+wUhr/s1Ma/7VUGv+3VRr/uVUa/7xWGv++Vhr/wVca/8JZGv/EWRr/xVka/8hb + Gv/KXBr/zF8b/+qRKv/1ojD/9KEw//OeL//ynS//8Zkw//GeMf/xqTb/87o8//rhgf///u////////// + ///////////u//jkaf/vvz3/6qs3/+imNf/qsDn/881a//787////////////////////fj/8cpy/+Gc + M//Why7/znkp/8dwJv/DayT/wWgk/75mI/+8ZCP/r3lVKf///wH///8B////Af///wH///8B////Af// + /wGfUBpbn08a/6FPGf+iThr/pk8a/6hQGv+qURr/rVIa/69SGv+yUxr/tFQa/7ZVGv+4VRr/u1Ua/71W + Gv/AWBr/wlka/8NZGv/GWhr/x1sa/8teG//pjyr/9KEw//OeL//ynS//8Zou/++YL//vnDH/8KY0//K1 + Of/301P//vix////////////////////+P/99Z//8ctA/+uzOf/psDn/7bk8//rppv////3///////// + //////////////768f/jpT3/1ogu/817Kf/Gbyb/wWkl/71lI/+7ZCP/uWIj/6x2Uif///8B////Af// + /wH///8B////Af///wH///8BnE4aW5xNGv+dTRn/n00Z/6FOGf+kThr/pk8a/6pQGv+sURr/rlEa/7BS + Gv+0Uxr/tlQa/7lVGv+7VRr/vVca/75YGv/BWBr/w1ka/8VbGv/IXRv/6Iwp//OeL//xmi//8Jku/++W + Lv/uli7/7Zcv/+2eMv/wqzb/88Q///roZf///+L///////////////3//v3F//PRQ//tuT3/67U6/++/ + P//98b7//////////////vv///K8//3tuP/9+Ov/6bpx/9OGLv/LeCr/xG4l/71nJP+7YiP/uGIj/7Zh + Iv+pdlEn////Af///wH///8B////Af///wH///8B////AZdNGluZTRr/mUwZ/5xMGf+eTRn/oE0Z/6NO + Gv+lTxr/qVAa/6tQGv+tURr/sFIa/7NTGv+1VBr/uFUa/7pWGv+8Vhr/vlca/8FYGv/DWxr/xlwb/+aL + Kf/xmi//8Jku/++WLv/tlS7/7JIt/+uULv/rly7/66Ay/++zOf/10ET//fV9////8f/////////////+ + 6P/11Uj/778+/+25Pf/xxD7//fK+//////////////TG//7XSP/zwD//7sJ2/+/QqP/PgC3/x3Qo/8Fr + Jf+6ZCT/uGEi/7RgIv+xXiL/pnJOJ////wH///8B////Af///wH///8B////Af///wGUSxpblUsa/5ZK + Gf+XSxn/m0wZ/5xMGf+gTRn/ok4a/6RPGv+oTxr/qlAa/6xRGv+vUhr/slMa/7RUGv+3VBr/uVUa/7tW + Gv++Vxr/wVoa/8RbG//kiCj/75gu/+6XLv/tlS3/65It/+qQLf/pjy3/6JIs/+iWL//rpDT/77w8//bb + Tf/++6X//////////////ez/+Ntm/+/BQP/uuTz/8cU///3vvP////////////7nl//3xEH/6q06/+Ce + Qf/szKj/yXgp/8NvJ/+9aCX/t2Mj/7NgIv+wXiL/rl0h/6RwTSf///8B////Af///wH///8B////Af// + /wH///8BkUsaW5FKGv+SSRn/lEkZ/5ZKGf+ZShn/m0sZ/59MGf+hTRn/o00a/6ZOGv+pTxr/rFAa/65S + Gv+wUhr/s1Ma/7VUGv+4VRr/ulYa/71ZGv/AWhv/4oco/+6XLv/slC3/65Et/+qOLf/ojSz/5oos/+aJ + K//ljSv/5pgv/+mqNv/wxj7/+eRh///94/////////3v//neev/vvz3/7rc7//DAPf/756b////+//// + ///82nz/7rQ8/+CaM//ThS3/yXYq/8JuJ/+9aib/uWMj/7NfI/+wXSH/rlsh/6paIf+gbEkl////Af// + /wH///8B////Af///wH///8B////AY1KGluOSRr/jkgZ/49IGf+SSRn/lUoZ/5hKGf+aSxn/nUwZ/6BN + Gf+jTRr/pU4a/6hPGv+rURr/rVIa/69SGv+yUxr/tVQa/7hWGv+7WBr/vlkb/+CGKP/slC3/6pEt/+mO + LP/njSz/5oos/+SJK//ihin/4oYq/+KNLf/kmjH/6rE5//LKRv/865b////////98v/534j/77s8/+23 + O//vuz3/+uGb///++///////99B5/+elN//YjTD/ynoq/8FsJ/+7ZiT/t2Mj/7NfI/+vXiH/rVsh/6pa + If+nVyD/nmtIJf///wH///8B////Af///wH///8B////Af///wGJSBpbiUca/4tHGf+MRxn/j0cZ/5FI + Gf+TSRn/l0oZ/5lKGf+cSxn/n00Z/6JNGv+kThr/plAa/6pRGv+sUhr/r1Ia/7JTGv+1VBr/uFYa/7tZ + G//egyj/6pIt/+iNLP/niyz/5Yos/+SHK//ihSv/4IMp/96DKP/fhSr/4JAu/+WgNP/stjz/9tZm///+ + +v///vr/+uOh/+62PP/ssjr/7rU7//jWif///Pb///////bTif/inTX/04Qu/8VyKf+6ZiT/tWEj/7Je + I/+vWyH/rFoh/6lYIf+mVyD/pFUg/5pnRCX///8B////Af///wH///8B////Af///wH///8BhkcaW4ZG + Gv+GRhn/iUYZ/4pHGf+ORxn/kEgZ/5NJGf+WShn/l0oZ/5tLGf+dTBn/oU0Z/6NOGv+mTxr/qVAa/6tR + Gv+vUhr/sVMa/7RVGv+4WBv/3IAo/+iPLP/niiz/5Ykr/+OIK//hhiv/4IMq/96BKP/dgCn/24Ap/9uG + K//glDH/56o5//DET//88c7///////rlsf/ssDr/67A6/+yvO//10Hn///vy///////20Y//4Jc0/9CC + Lf/Bbyj/tmEk/7BdIf+uWyH/qloh/6hYIP+kVyD/olUg/6BTH/+ZZUMl////Af///wH///8B////Af// + /wH///8B////AYNGGluDRhr/g0QZ/4VEGf+HRRn/iUUZ/41GGf+OSBn/kkkZ/5RKGf+WShn/mksZ/5xM + Gf+gTRn/ok4a/6VPGv+oUBr/qlEa/65TGv+xVBr/tVcb/9l/J//mjCz/5Ikr/+OHK//hhSz/4IUr/96D + Kf/dhCr/24Eq/9l/Kf/Zgiv/3Y8t/+OiNP/rtkT/+eOt///////657z/6606/+mqOf/rqTn/88Vr//75 + 7///////+Nup/+CXNP/Pgi3/vmwo/7JgI/+sWiH/qlch/6dXIP+jVSD/oVQg/59SH/+bUh//lGE/I/// + /wH///8B////Af///wH///8B////Af///wGARBpbgEQa/4BDGf+BRBn/hEQZ/4ZEGf+IRRn/i0YZ/41H + Gf+RSBn/k0kZ/5ZKGf+YShn/m0sZ/59MGf+hTRn/pE4a/6dPGv+rURr/rlIa/7FVG//XfCf/5Igr/+KH + K//ghSr/4IYr/9+FLP/dhSv/3Ygr/9yGLP/ahSz/2YUq/9uMLf/gnDL/6Ko8//TShf///////O/V/+us + Ov/qqDj/7Ko6//PAX//+9+v///////vit//kmjX/0oQu/8FwKf+0YiT/rFsh/6hYIf+kViD/n1Qf/55S + H/+aUB//lk8e/5FgPSP///8B////Af///wH///8B////Af///wH///8BfEMaW31DGv98Qhn/fUMZ/4BD + Gf+DQxn/hEQZ/4hFGf+KRhn/jEcZ/5BIGf+SSRn/lUoZ/5hKGf+bSxn/nUwZ/6BNGf+kThr/plAa/6pR + Gv+uVBv/1Hom/+GGK//fhCr/3oIq/92CK//dhSz/3Yks/92NLv/dji//3I4t/9uNLf/clC//4p40/+em + N//zxWn///////3y2v/vsDv/7qw7//CvPf/2uUr///bm///////+6cX/7KI4/9uMMv/IeS3/uWcm/65e + I/+oWiL/olYg/5xTH/+YUB//lU8e/5JNHv+MXDkj////Af///wH///8B////Af///wH///8B////AXlC + Glt5Qhr/eUEZ/3pCGf99QRn/f0IZ/4FDGf+DQxn/h0QZ/4lFGf+LRhn/jkcZ/5FIGf+VSRn/l0oZ/5pL + Gf+cTBn/oE4Z/6NPGv+mUBr/q1Mb/9J2Jv/fgyr/3YEq/9yAKf/bgSv/24Qt/9yMLv/qvH3/7MB//+So + S//gmzL/4qA1/+epN//ssDv/9sZc///////+9d//9rhC//a3P//5tT///LpE///15P///////+7U//Sm + PP/jkjf/0H8v/75uKv+xYiX/p1oi/59VIf+ZUB//k04e/5FMHv+OTR7/i1o4I////wH///8B////Af// + /wH///8B////Af///wF3QRpbd0Ea/3dAGf94QBn/ekAZ/3tBGf9+Qhn/gEMZ/4JDGf+FRBn/iEUZ/4tG + Gf+NRxn/kEgZ/5NJGf+WShn/mUoZ/5xMGf+gTRn/ok8Z/6ZRG//QdSb/3YAq/9p9Kf/ZfSn/2H4q/9qF + Lf/bjy3/675+//rt2P/02av/56g2/+mtOf/usjz/9LtA//vJWP///fj///bk//7BSP/+vUL//rtC//65 + QP//8dr////////v2P/7rkX/7qdT/+GjZP/TmWL/tGUm/6hbI/+cVCD/lU8f/5BMHv+NSx7/iksd/4hY + NiP///8B////Af///wH///8B////Af///wH///8BdEAaW3RAGv90Pxn/dT8Z/3ZAGf94QBn/ekEZ/3xC + Gf9/Qxn/gkMZ/4REGf+HRRn/ikYZ/4xHGf+OSBn/kkkZ/5VKGf+YSxn/m0wZ/59OGf+jURr/zXMl/9p9 + Kf/YfCn/1noo/9Z8Kf/Xgyr/2osr/+CbO//02az///78//vt0f/0yW3/9sBI//vKWP/+1nz///nr///7 + 8v//5LD//+a7///sz///9OP///7+////////////////////////////8t/N/7VnKP+mXCP/m1Mg/5BO + H/+MSx3/iUod/4ZIHf+EVTIh////Af///wH///8B////Af///wH///8B////AXI/GltyPxr/cT4Z/3E+ + Gf9zPxn/dUAZ/3dAGf95QBn/e0EZ/35CGf+BQxn/g0MZ/4VEGf+JRRn/i0YZ/49HGf+RSBn/k0kZ/5hL + Gf+aTBn/oE8a/8lwJf/Xein/1Xko/9R3Jv/SeSf/030n/9WDKv/akC//5KVG//jkwf////////////// + //////////////////////////////////////////////////////////////////////////////Dc + yv+wZCb/o1kj/5ZSIP+NTR7/iEod/4ZIHf+BRxz/gVIwIf///wH///8B////Af///wH///8B////Af// + /wFwPxpbcD4a/289Gf9vPRn/cT4Z/3E/Gf90Phn/dj8Z/3hAGf96QRn/fkIZ/4BDGf+CQxn/hEQZ/4hF + Gf+KRhn/jkcZ/5BIGf+UShn/l0sZ/5tOGv/HbST/1Xko/9N2Jv/Rcyb/z3Qn/893Jv/RfCj/1oUs/9uS + MP/os17/+eXD///9+v///fr///////////////////////////////////z5//7x4v/848X/+dKk//O8 + hP/opGD/2IlA/8d1LP+3aCj/plwk/5pUIv+QUB//iEoe/4NIHf+BRhz/fkUc/31OLSH///8B////Af// + /wH///8B////Af///wH///8Bbj4aW249Gv9tPBn/bTwZ/249Gf9vPRn/cT0Z/3Q+Gf92Pxn/eEAZ/3pB + Gf98Qhn/f0MZ/4FDGf+EQxn/h0QZ/4lFGf+NRxn/j0kZ/5RKGf+YTRr/xGsj/9J1Jv/Pcyb/zXIl/81w + Jf/LcST/zHQm/856Kf/ThCv/2I8x/+KdRP/tvHP/9tWk//nhu//41Z//9cSA//G1ZP/roUj/5pU1/+KP + NP/fizP/24cx/9eBMP/RfC7/ynQr/8BwKv+1Zij/qF4l/51WIf+TUSD/ikse/4RJHP+ARhz/fkUc/3xD + HP97TSsh////Af///wH///8B////Af///wH///8B////AW4+GltsPBr/azwZ/2w8Gf9sPBn/bTwZ/248 + Gf9wPRn/cj4Z/3U/Gf93Pxn/eUAZ/3tBGf9+Qhn/gEMZ/4NDGf+GRBn/iEYZ/4xHGf+QSBn/lUsa/8Fp + Iv/Pcib/zHAl/8pvJf/IbSP/x20k/8duJf/HcSX/ynco/819K//SgS7/14gv/9mMMf/bjzP/240y/9mL + Mf/WhjH/0oAu/899Lf/LeS3/xnYq/8JwKv+9bSn/uGcm/7FjJ/+qXiX/olkk/5tUIf+SUCD/ikwe/4RJ + Hf+ARxz/fEUc/3pDHP94Qxv/eEopIf///wH///8B////Af///wH///8B////Af///wFtPRpbazsa/2k7 + Gf9qOxn/ajsZ/2s8Gf9sOxn/bjwZ/289Gf9xPRn/dD4Z/3Y/Gf94QBn/ekEZ/3xCGf+AQxn/g0MZ/4VF + Gf+JRhn/jEgZ/5BKGv++ZyL/zHAl/8pvJf/IbSX/xWoj/8NpI//BaCP/wWgj/8FrJf/CbiX/xXEn/8d2 + Kf/Idin/yHgq/8d1Kv/Dcin/wG4o/71rJ/+3aCX/s2Ml/69iJP+pXiT/pVsi/6FXIf+bVSL/lVEh/5BO + H/+MSx7/hkoe/4NHHP9/Rhz/fEMc/3lDG/93Qhv/dUAb/3RGJR////8B////Af///wH///8B////Af// + /wH///8BbT0aW2s7Gv9oOhn/aDsZ/2g6Gf9qOxn/azsZ/2s7Gf9tPBn/bzwZ/3A9Gf9yPhn/dT8Z/3dA + Gf95QRn/fEEZ/39CGf+BQxn/hEQZ/4lGGf+NSBr/umQi/8ltJf/HbCX/xGkk/8JnIv+/ZiL/vWQi/7tk + Iv+6ZCL/umMj/7llJP+4ZSP/t2Uk/7dkJf+0YyP/sWAj/61eI/+pWyH/pFgh/6BWIP+cUx//mFEf/5NO + Hv+QTR3/jEwe/4dKHf+GSB3/gkcc/39GHP99RRz/e0Mc/3lDG/93QRv/dUAb/3JAGv9zRCMf////Af// + /wH///8B////Af///wH///8B////AW09GltrPBr/aToZ/2c6Gf9oOhn/aDoZ/2k7Gf9qOxn/azsZ/2w7 + Gf9uPBn/cD0Z/3I+Gf91Phn/dz8Z/3lAGf98QRn/fkIZ/4FEGf+FRRn/iUca/7hjIv/GayT/xGkk/8Fn + Iv+/ZiL/vGQi/7phIv+4YSH/tV4h/7NeIP+wXCH/r1sh/61bIf+qWSD/p1gg/6RUH/+fVR//m1Ie/5lR + Hv+TTh3/kEwd/45LHf+MSxz/iUoc/4VIHf+CRx3/f0Uc/31EHP97RRz/ekMb/3dCG/91QRv/c0Ab/3E/ + Gv9wPhr/cEMiH////wH///8B////Af///wH///8B////Af///wFtPRpbazwa/2k6Gf9oOhn/ZzkZ/2c5 + Gf9nOhn/aToZ/2o7Gf9rOxn/bDsZ/208Gf9vPRn/cT0Z/3Q+Gf92Pxn/eUAZ/3tBGf99Qxn/gUQZ/4ZG + Gv+0YSH/w2ok/8FmJP++ZCL/vGMi/7lhIf+2YCH/tF4h/7FbIP+uWiD/q1gg/6hXH/+mVR//oVQf/59S + Hv+dUB7/mlEe/5ZOHf+TTh3/kEwd/41LHf+JShz/h0kc/4RHHP+CRxz/f0Uc/31EHP97Qhz/eEMb/3dC + G/91QBv/c0Ab/3E+Gv9vPhr/bT0a/20/Hx////8B////Af///wH///8B////Af///wH///8BbT0aW2s8 + Gv9pOxn/aDoZ/2c5Gf9nORn/ZjkZ/2c6Gf9oOhn/aTsZ/2s7Gf9rOxn/bTwZ/248Gf9wPRn/cj4Z/3VA + Gf93QBn/ekEZ/35CGf+CRRr/sV4h/8BmJP++ZCL/u2Mi/7lhIf+2YCH/s10h/7FbIP+tWiD/qlgg/6hW + H/+lVR//oFMf/55SHv+bUB7/l1Ae/5ROHf+STR3/jksd/4pLHP+IShz/hkkc/4RHHP+ARhv/f0Qc/3tE + HP95Qhz/d0Eb/3RBG/91QBv/ckAa/3A+Gv9uPRr/bT0a/2s8Gv9rPR0f////Af///wH///8B////Af// + /wH///8B////AW09GltrPBr/aTsZ/2g6Gf9nOhn/ZzkZ/2Y5Gf9mORn/ZzkZ/2g6Gf9pOhn/ajsZ/2s7 + Gf9sOxn/bjwZ/3A9Gf9xPxn/dD8Z/3dAGf97QRn/f0Qa/65dIP+9ZCL/umEi/7dgIf+1XyH/sl0g/69b + IP+tWSD/qlgg/6ZVH/+kVR//oFIe/5tRHv+aUB7/lk4e/5JOHf+PTB3/jksd/4pKHP+HShz/hEgc/4FH + G/9+RRv/fEQb/3tEHP95Qhv/dkEb/3Q/G/9yQBv/cT8a/3A+Gv9uPRr/bD0a/2o7Gv9qOxn/aTwbH/// + /wH///8B////Af///wH///8B////Af///wFtPRpbbDwa/2o7Gf9oOhn/aDoZ/2c5Gf9nORn/ZjkZ/2Y5 + Gf9mORn/ZzoZ/2g6Gf9qOxn/azsZ/2w7Gf9tPBn/bz0Z/3I+Gf91Pxn/eEEZ/31DGv+rWiD/uWEh/7dg + If+0XyH/sVsg/69aIP+rWCD/qVcf/6ZVH/+iUx//n1Ie/5tQHv+XTx7/lE0d/5JNHf+PTB3/i0sd/4hJ + HP+GSRz/g0cc/4BHG/9+RRv/fEQb/3pCG/94Qhv/dkEb/3Q/G/9yPxv/cD4a/28+Gv9tPRr/bDwa/2o7 + Gf9qOxn/aToZ/2c5GR////8B////Af///wH///8B////Af///wH///8BbDwaW2w8Gv9qOxr/aTsZ/2g6 + Gf9nOhn/ZzkZ/2c5Gf9mORn/ZjkZ/2Y5Gf9nOhn/aDoZ/2k7Gf9rOxn/azsZ/208Gf9vPRn/cT4Z/3VA + Gf95Qhr/p1gf/7ZgIf+zXyH/sVwg/65aIP+rWCD/qVYf/6VVH/+iUx//n1Ie/5pQHv+WTx7/lE0d/5BM + Hf+NSx3/iksc/4hJHP+FSRz/gkcb/39GG/98RBv/ekQb/3hCGv92QRr/dEAb/3Q/G/9xPhr/cD4a/249 + Gv9tPRr/azwa/2o7Gf9pOxn/ZzkZ/2Y5Gf9mORkf////Af///wH///8B////Af///wH///8B////AWo7 + GidrPBq1azwa/2o7Gf9pOhn/aDoZ/2c6Gf9nORn/ZzkZ/2Y5Gf9mORn/ZjkZ/2Y5Gf9nOhn/aToZ/2o7 + Gf9rPBn/bTwZ/289Gf9yPxn/dkAa/6RWH/+yXiD/r1wg/65ZIP+qWCD/p1Uf/6VVH/+gVB7/nVEe/5pQ + Hv+WTh7/kk0d/49LHf+MSh3/ikkc/4ZIHP+DRhz/gUcb/35FG/98RBv/ekQb/3hCGv91QRr/cz8a/3I/ + G/9wPhr/bj4a/249Gv9sPBr/ajsa/2k7Gf9oOhn/ZjkZ8WY5GbtmORmHZjkZDf///wH///8B////Af// + /wH///8B////Af///wH///8B////AWo7GhVqOxlvaTsZyWk6Gf9oOhn/aDoZ/2c5Gf9nORn/ZzkZ/2c5 + Gf9mORn/ZjkZ/2c6Gf9oOhn/ajsZ/2s7Gf9tPBn/cD4Z/3Q/Gv+gVR7/r1wg/6tYIP+pVx//plUf/6JU + H/+fUx7/nVAe/5dPHv+UTR3/kUwd/49KHf+JSRz/h0kc/4ZIHP+DRhz/f0Ub/35FG/98RBv/ekIb/3dC + Gv91QRr/cj8a/3E/Gv9vPhr/bT4a/2w9Gv9sPBr3ajwaxWg8Go9oOhpbZjkZJf///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wFpOxklaToZgWg6 + GeFoOhn/aDoZ/2c6Gf9nORn/ZzkZ/2c5Gf9mORn/ZzoZ/2g6Gf9qOxn/azwZ/249Gf9xPhr/nVIe/6tY + IP+nVh//pVUf/6JUH/+dUx7/m1Ee/5ZPHv+UTR3/kEwd/41KHf+JSRz/h0kc/4RIHP+CRhv/fkUb/3tD + G/96RBv/eEIa/3ZBGv9zQBr/cT8a/3A+Gf9wQBzNbj8dmW1AHmNrPx4v////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8BaToZPWg6GZdoOhntaDoZ/2c6Gf9nORn/ZzkZ/2Y5Gf9nORn/aDoZ/2o7 + Gf9tPRn/cD4a/5pRHv+nVR//pFQf/6BUHv+dUR7/mlEe/5VOHv+STR3/j0sd/4xKHf+JSRz/hUgc/4JG + HP+ARhv/fUQb/3tDG/95QRv/eEIa/3ZDHdV0QyClckMhbXFDIjn///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BaToZA2g6GU9oOhmvaDoZ+Wc5 + Gf9mORn/ZjkZ/2c5Gf9pOxn/azwZ/24+Gv+WTh7/olQf/59THv+dUR7/l1Ae/5RNHf+RTB3/j0od/4lJ + HP+HSRz/hEgc/4JGHP9/RRv/fkYf33tII6t6SCZ5eEkoQXdJKAv///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////AWg6GQ9oOhljZzkZvWY5Gf9nORn/aDoZ/2o7Gf9sPBr/kk0e/51THv+aUR7/llAe/5NO + Hf+QSx3/jEod/4lJHP+GSiDlhU0mt4BPKoN/UC1Lf1MzEf///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wFmORkbZzkZe2g6GdVoOhn/aTsZ/45L + Hf+aUR7/lU8e/5JQIO+PUSm/jFQujYhWMlWGWDcd////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8BaDoZMXxGIOeGUCqvkl03YZBgPSP///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA== + + + + 255, 17 + + + + AAABAAQAEBAAAAAAIABoBAAARgAAACAgAAAAACAAqBAAAK4EAAAwMAAAAAAgAKglAABWFQAAQEAAAAAA + IAAoQgAA/joAACgAAAAQAAAAIAAAAAEAIAAAAAAAQAQAAAAAAAAAAAAAAAAAAAAAAAD///8B////Af// + /wH///8B////AQAAAAUAAAAJAAAABQAAAAP///8B////Af///wH///8B////Af///wH///8B////Af// + /wEAAAAHAAAAGwAAAEcXCgODXjMQpRMKBIMAAABlAAAASwAAADEAAAAdAAAADwAAAAf///8B////Af// + /wEAAAAdBAEAe0wiCbuSQhLlxVkZ/eyVKv/6qzH/1o8p9ahsIOV0RhbTOR8LuwEBAJ8AAACBAAAAMQAA + AAMAAAADkUQTn7VSF/vKWxr/y1sa/8tbGv/sliv/+64y//mnMP/2oS7/8pkt/+2RK//egij9r2Qg75pX + H7llRjMJ////AbZWGte+Vxr/xVka/8paGv/LWxr/65Mq//inMf/1pzH/8qQx/+ySLP/miiv/4IQp/9d6 + J//PcyX/tX5aC////wGqURrVsVIa/7tVGv/DWBr/yVsa/+mPKf/zoDD/98hl//vtvf/rqTf/7blZ/+7E + d//Sfin/xGkk/7J8Vwv///8Bm0wZ1aNOGf+tURr/t1Qa/8BYGv/khyj/7ZUu//C1Qv/+++L/8s9k//rr + vP/54KX/0Yg+/7diIv+nc08L////AYxHGdWUSRn/n0wZ/6lQGf+0VBr/238n/+WJK//hiiv/89J+//TS + gP/547H/355E/7djI/+pWSD/nGhGCf///wF+QxnVhUQZ/49HGf+bSxn/pk8Z/9J3Jf/ehCv/3pE4/+es + R//10pL/+Nie/+CgVP+sXCL/mVAe/49dOwn///8Bcz4Z1XdAGf+BQxn/i0YZ/5dKGf/GbST/1X0o/+3F + if/64Kj//vLa//7t1P/z07H/sW88/4hJHf+CUzEJ////AWs7GdVtOxn/dD4Z/31BGf+IRRn/umQh/8Zs + I//HdSj/045G/8p+NP+5ayf/pFsj/4pMHv96Qxv/dkgnCf///wFpOxnVZzkZ/2o6Gf9xPRn/ekEZ/61c + IP+4YSH/rVog/6JUHv+VTh3/iUkc/35FG/92QRv/bj0a/2w+Hgn///8BajsZoWc5GftmORn/aToZ/289 + Gf+gVB7/qlcf/51RHv+PSxz/hEcb/3pDGv9yPxr/bDwa6Wg6GbVmORkF////Af///wFoOhkZZzkZcWY5 + Gc1pOhn/kk0d/5hPHf+LSh3xgUccvXlDHIlyQBtVbj8cIf///wH///8B////Af///wH///8B////Af// + /wH///8BZzkZK4dLIGGOUScphlg3A////wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAD//wAA + //8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//ygA + AAAgAAAAQAAAAAEAIAAAAAAAgBAAAAAAAAAAAAAAAAAAAAAAAAD///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////AQAAAAMAAAAHAAAADQAAABMAAAARAAAADQAAAAkAAAAFAAAAA/// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8BAAAAAwAAAAcAAAARAAAAIwAAAD0AAABZAAAAawAAAGcAAABZAAAARwAA + ADcAAAArAAAAHwAAABcAAAAPAAAACQAAAAcAAAADAAAAA////wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8BAAAABQAAABEAAAAjAAAAPQAAAGMAAACFAAAApzwbB9GUURjpf0UX1zUb + DMMAAACrAAAAnwAAAJEAAACBAAAAcQAAAF8AAABNAAAAPQAAAC8AAAAjAAAAFwAAABEAAAAJAAAABf// + /wH///8B////Af///wH///8BAAAAAwAAABEAAAAzAAAAXwAAAIcAAAChIg8Eu3EzDt2zUBb3y10a/916 + Iv/8rzL//K8x//SfL/3Ifijzkl8d4Wg1FNUYDQbBAAAAtQAAAK0AAACjAAAAlwAAAIcAAAB1AAAAYwAA + AEcAAAAlAAAAC////wH///8B////Af///wEAAAARAAAASwAAAJkKBAHBVycL16FJFO/KWxn/y1sa/8tb + Gv/LXBr/3Xwj//yxM//8sDP//K8y//uuMP/7qzD/+akw//mmL//kiCv7qmki7X9IGN9DIQ7TBgMCwQAA + ALsAAAC3AAAApQAAAHEAAAAlAAAABf///wH///8BAAAABQAAACtKIgmlhD0R78BXGP3LWxr/y1sa/8tb + Gv/LWxr/y1sa/8tcGv/dfCP//LEz//yxMv/7rzL/+qsx//moL//4pS//9qEu//WeLv/ymi3/8JUs/+6S + LP/oiir/xW4l945TG+djMhPbLBgMsQAAAEEAAAAJ////Af///wEAAAAHsVQYq8JaGv/FWhr/x1oa/8pa + Gv/LWxr/y1sa/8tbGv/LWxr/y1wa/918I//8sDL/+64y//qrMv/5pzD/96Uv//ahLv/0nS3/8pkt/++U + LP/tkSv/6o0r/+eJKv/khin/4YMp/92AKP/Zeyf/0Xcr9YtgRhn///8B////AQAAAAOzVhqzvFga/79Y + Gv/DWBr/xlka/8laGv/KWxr/y1sa/8tbGv/LXBr/3Xsj//qtMv/5qzH/+Kcx//elMP/1oy7/9J4u//GZ + Lf/ulCz/7I8r/+mMKv/mhyr/4oQp/9+BKP/cfij/2Hon/9R3Jv/QdCX/sXtXF////wH///8B////AbJW + Gq21VRr/uVUa/71XGv/CVxr/xVka/8haGv/KWhr/y1sa/8tcGv/deyP/+akx//inMf/2pDD/9aYy//Wu + Nf/zsDf/8acz/+2XLv/ojCv/5oor/+SMLP/hiSv/3YMq/9d6KP/TdiX/znIl/8puJf+6gl0V////Af// + /wH///8BrFMbra5SGv+yUxr/t1Qa/7xVGv/AVxr/xFga/8ZZGv/KWhr/y1wa/9x5I//3pzD/9qQw//Sh + Mf/0rTb/+NFn//vnpf/20mT/7ag1/+eSLv/lmC//6ak2/+mrN//hmjH/1oIp/85zJv/JbST/xWok/7V+ + WhX///8B////Af///wGlURqtp1Aa/6xRGv+xUhr/tVQa/7pVGv++Vhr/wlga/8VZGv/KWxr/23gi//Wi + MP/zny//8Z0w//OyOP/88L////////796//yyEj/6KM0/+y1QP/67sH//vvx//LQhf/aji7/y3Qn/8Nq + JP++ZiP/sHlVFf///wH///8B////AZ1OGq2fTRn/pE4Z/6lQGv+uURr/s1Ma/7hUGv+9Vhr/wVga/8Va + Gv/ZdSL/8p0v//CZLv/umC//76k1//jdav////f////8//fjef/rtDr/9NR3/////v//++3//ffk/92b + Qv/IdCf/vWUj/7hiIv+qdlET////Af///wH///8BlkwarZhLGf+dTBn/ok4Z/6hPGv+sURr/slMa/7dU + Gv+7Vhr/wFka/9VyIf/vmC7/7ZQt/+qRLf/ply7/77g7//zymP//////+uqg/+68Pf/32n3///////zd + ef/qs0z/3KVp/8JtJv+3YiL/sF4h/6VxTRP///8B////Af///wGPSRqtkEgZ/5VJGf+bSxn/oEwZ/6VO + Gv+rUBr/r1Ia/7VUGv+6Vxr/0HAh/+yULf/pjiz/5oor/+OIKv/lmjD/8clH//753f/87bj/7ro7//XQ + bv///v3/8sBa/9WJLv/BbSf/uGMj/69dIf+qWSD/n2tIE////wH///8B////AYdGGq2JRhn/jkcZ/5NJ + Gf+YShn/nkwZ/6NOGf+pUBr/rlIa/7RUGv/LbSH/6I4s/+WJK//hhSr/3oEo/92GK//mpTb/+OKf//zx + 0v/ssjr/8cJe///9+f/rtmD/ynkr/7VhI/+uWyH/qFgg/6NVH/+ZZkMT////Af///wH///8BgUUarYJD + Gf+GRBn/i0YZ/5FIGf+WShn/m0sZ/6FNGf+nTxr/rlIa/8VpIf/kiSv/4YUr/96EKv/chCr/2YIq/96W + MP/wxWz//fXj/+qqOf/vtk///vv2/+27cv/IeCv/r10i/6dXIP+gUx//mlAe/5JgPhH///8B////Af// + /wF6Qhqte0IZ/39CGf+EQxn/iUUZ/45HGf+USRn/mksZ/6BNGf+mUBr/v2Ug/9+DKv/cgSr/3Ics/+Sl + Vv/elzX/4Z4z/++4Tf/++e3/8rI9//a1Qv//+vL/98eD/9WFMf+1ZSb/pFch/5hQHv+RTR7/i1s4Ef// + /wH///8B////AXVAGq12Pxn/eEAZ/31CGf+CQxn/h0UZ/4xHGf+SSRn/mEoZ/59NGf+5YiD/2n0p/9d8 + Kf/ZiCv/7seP//Xbq//wukr/+slb///57v/+0n3//tWN///79f/+5sb/89Kt/8uRX/+hVyH/kE0e/4lK + Hf+GVjQR////Af///wH///8BcT4arXA9Gf9yPxn/dj8Z/3pBGf+AQhn/hUQZ/4tGGf+QSBn/l0sZ/7Je + H//VeCf/0XUm/9J8J//bkzT/9t64///+/P/////////////////++vb//OzZ//bXuP/nv5r/v4FP/5hT + If+ISh3/gUYc/39QLhH///8B////Af///wFtPBqtbDwZ/208Gf9wPRn/dT8Z/3lAGf9+Qhn/g0MZ/4lF + Gf+PSBn/rFse/89yJf/LbyT/yXAk/8x5KP/WijP/5Kld/+m0b//lolH/3Iw2/9SCL//MeS3/wW4p/7Bj + Jv+cViH/ikwe/4BGHP97Qxv/eUsqEf///wH///8B////AWs7Gq1oOhn/aTsZ/2w7Gf9vPBn/cz4Z/3dA + Gf98QRn/gkMZ/4hGGf+lVx7/yW4l/8RpI//AZiL/vWYj/75pJP+/bSb/vm0n/7hnJf+wYSP/p1si/55W + IP+WUR//jEwe/4RIHf9+RRz/eUIb/3RAGv9zRSQP////Af///wH///8BazwarWg6Gf9nORn/aDoZ/2s7 + Gf9tPBn/cT0Z/3Y/Gf97QRn/gUQZ/55UHf/DaST/vmUi/7lhIf+0XiD/r1sg/6pYIP+kVR//nlIe/5dP + Hf+QTB3/ikoc/4VIHP9/RRz/ekMb/3dBG/9zPxr/bz4a/25BIA////8B////Af///wFrPBqtaDoZ/2c5 + Gf9mORn/aDoZ/2o6Gf9sOxn/cD0Z/3Q/Gf96QRn/mFEd/71jIv+4YCH/sl0g/61ZIP+nVh//oFIe/5pQ + Hv+TTh3/jksc/4dJHP+CRxv/fUQb/3hCG/90QBv/cj8a/249Gv9rOxn/ajwcD////wH///8B////AWw8 + Gq1pOhn/ZzkZ/2Y5Gf9mORn/ZzkZ/2k6Gf9rOxn/bz0Z/3Q/Gf+STRz/tmAh/7FcIP+rWB//pVUf/55R + Hv+XTh3/kEwd/4tKHP+FSBv/f0Yb/3tDGv93QRr/cz8a/3A+Gv9tPRr/ajsZ/2g5Gf9mORkP////Af// + /wH///8BajsaN2o7GaFoOhnxZzkZ/2Y5Gf9mORn/ZjkZ/2g6Gf9rOxn/bz0Z/4tKHP+uWyD/qVcf/6NU + Hv+cUR7/lU0d/45KHP+ISRz/gkYb/35FG/95Qxr/dUAa/3E+Gv9tPRr/bDwa72k7GblmORmFZjkZUWY5 + GQP///8B////Af///wH///8B////AWk7GQloOhlZaDoZtWc5GftnORn/ZjkZ/2g6Gf9sPBn/hkcc/6dV + H/+hUx7/mVAe/5JNHf+MShz/hUgc/4BGG/97Qxv/eEIa9XRBHMNwPhqNbz8cWWw/HiX///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BaDoZFWg6GW1mORnHZjkZ/2k7 + Gf+ARRz/nlIe/5dPHf+QSx3/iUkd+YRKIM2ARx6XfEYgY3lIJi93SSgD////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wFmORklaDoZgX1GH+WWUiOhkFAja4pULzmGWDcH////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAoAAAAMAAAAGAAAAABACAAAAAAAIAlAAAAAAAAAAAAAAAAAAAAAAAA////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA + AAMAAAADAAAABQAAAAUAAAADAAAAAwAAAAP///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wEAAAADAAAABwAAAA0AAAATAAAAFwAAABkAAAAVAAAAEQAAAA0AAAALAAAACQAAAAcAAAAFAAAAA/// + /wEAAAAD////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA + AAMAAAAFAAAACwAAABMAAAAfAAAALQAAAD0AAABNAAAAWwAAAFsAAABXAAAATQAAAEMAAAA5AAAALQAA + ACcAAAAfAAAAGQAAABMAAAAPAAAACwAAAAkAAAAHAAAABQAAAAMAAAAD////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AQAA + AAMAAAAFAAAACwAAABEAAAAbAAAALwAAAD8AAABVAAAAbwAAAIcAAACbLRcKswgEAacAAACdAAAAkQAA + AIcAAAB9AAAAcQAAAGUAAABZAAAATQAAAEMAAAA5AAAALwAAACUAAAAfAAAAFwAAABMAAAAPAAAACwAA + AAkAAAAFAAAABQAAAAMAAAAD////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wEAAAADAAAABwAAAA8AAAAXAAAAKQAAADkAAABPAAAAawAAAIEAAACXAAAArRwNA8djLQzjtl0b9b90 + Iu+qWB/nWS4U0xYMBr0AAACzAAAAqwAAAKMAAACdAAAAkQAAAIcAAAB9AAAAbwAAAGUAAABZAAAASwAA + AEEAAAA3AAAALQAAACUAAAAdAAAAFwAAABEAAAALAAAABwAAAAP///8B////Af///wH///8B////Af// + /wH///8B////AQAAAAUAAAAPAAAAJQAAAD0AAABXAAAAdQAAAIkAAACbCwUBrygSBcFPIwrTm0UT78VZ + Gf3LXBr/1Gwe//WjLv/8rzH//K8x//qqMP/skC77umol8XpMG99QMxDPPB8LySIRB8MHBAK5AAAAsQAA + AKsAAAClAAAAmwAAAJMAAACJAAAAewAAAHEAAABlAAAAVwAAAEkAAAA3AAAAIQAAABEAAAAH////Af// + /wH///8B////Af///wH///8BAAAABQAAABUAAAAvAAAAWwAAAH8AAACbAAAArRQJArtJIQnNgjsQ46tN + FfPGWRn9ylsZ/8tcGf/LXRn/1W0f//WjL//8rzP//K8x//uuMf/8rzH//K8x//yuMP/3pC//4Ykr+bt1 + JfGXZB3jfEQX3VYrEdUjEwnJAAAAuwAAALkAAAC1AAAArwAAAKkAAACjAAAAmQAAAIkAAAB1AAAATwAA + ACsAAAARAAAABf///wH///8B////Af///wEAAAADAAAAEQAAAC8AAABhAAAAnQAAAL0WCgLLbTEN4aNK + FO+6VBf5ylsZ/8pbGf/LWxn/y1sZ/8pbGf/LXBn/1W0f//SlL//8sDP//LAz//uvMv/8rzL/+64w//us + MP/6qjD/+akw//mnL//4pC//75ct/eCMKvvNgyf1uGsj75JKHOdTKhPZDQgExQAAAL8AAAC/AAAAvQAA + ALcAAACrAAAAhQAAAFEAAAAhAAAACf///wH///8B////Af///wEAAAAFAAAAIRUJAlcsFQWjUiYK4ZJD + E/fDWRn9y1sa/8tbGv/LWxr/ylsZ/8tbGv/LWxr/ylsZ/8tbGv/LXBr/1W0f//WlL//8sDP//LAy//uw + Mv/7rjL/+qsx//qpL//5qC//+KYv//ejLv/2oS7/9Z8u//SdLf/ymi3/8ZYs/++TLP/ukiz/6Ywr/9V1 + JvunWiHxZjoV30IkDNEwGAnNGg4GswoGA3MAAAA1AAAADQAAAAP///8B////Af///wEAAAAJejkRUZZG + FLWoThbrxVsZ/8hbGv/KWxr/y1sa/8pbGv/KWxr/ylsZ/8taGf/KWhn/ylsZ/8tbGf/LXBn/1W0f//Wl + L//8sDP/+7Ay//uuMf/6rTH/+aox//mnL//4pi//96Qu//WhLv/0ny7/85wt//KaLf/wlyz/75Ms/+2R + LP/sjyv/6Ywq/+eKKv/liSr/44Yp/9t9KP3CaiT5oVsg55lYH7+kYCuNXEAvFwAAAAP///8B////Af// + /wEAAAAHqVAXi79aGv3CWhr/w1oa/8ZZGf/HWRr/yVoa/8pbGf/LWxr/y1sZ/8pbGf/LWxn/y1sZ/8pb + Gf/LXBn/1W0f//SlL//8sDL/+64y//qsMf/6qjL/+acw//elL//3pC//9qEu//SeLv/zmy3/8pkt//CW + LP/ukyz/7ZAr/+uOK//piyv/54kq/+WHKv/jhSn/4YMp/96BKP/cfyj/2Xsn/9Z5J//Rdyn3mWpMJwAA + AAP///8B////Af///wEAAAAFrVMZjbtZGv+9WBr/v1ga/8FYGv/EWBr/xlka/8haGv/KWhr/ylsZ/8tb + Gv/LWxr/ylsZ/8tbGv/LXBr/1W0e//SjLv/6rTL/+asx//mqMf/4qDD/96Yw//akLv/1oi7/9J8u//Kb + Lf/xmS3/75Us/+6SLP/skCv/6o0q/+iKKv/mhyr/44Up/+GDKf/fgSj/3YAo/9p9J//Yeif/1Xcm/9N1 + Jf/QdCX/sHpXI////wH///8B////Af///wEAAAADsFQaibhXGv+5Vhr/vFYa/75XGv/BWBr/w1ga/8VZ + Gv/HWRr/yVoZ/8paGf/KWhn/ylsZ/8tbGf/LXBn/1G0e//OhLv/6qzH/+akx//inMP/3pTD/9qQx//Wl + MP/0pjH/86Ux//GgMf/wnC//7ZUt/+yQLP/pjCv/54oq/+WIKv/khyr/4YQp/9+CKf/dgCj/2Xwn/9d5 + J//Vdyb/0XUm/89yJf/NcCX/t39bIf///wH///8B////Af///wH///8BsFUahbNVGv+1VRr/uFUa/7pV + Gf+9Vxr/wVca/8NXGf/FWRr/x1kZ/8haGf/KWhn/y1sZ/8pbGf/LXBn/1G0e//OgLv/5qDH/+Kcx//al + MP/2pDD/9aYy//WrNP/1sTb/9LQ5//OwN//wqDT/7Zov/+qRLf/niyv/5osr/+WNLP/kjiz/4o0s/9+I + K//cgyr/2Hso/9R3Jv/SdSX/znIl/8twJf/JbSX/uYJdIf///wH///8B////Af///wH///8BrFMbg65T + Gv+vUhr/slMa/7VUGv+4VBr/vFUa/75WGv/BVxr/w1gZ/8ZZGv/HWRr/yVoZ/8pbGv/LXBr/1Gwe//Kf + Lv/3pzD/9qQw//WiMP/0ojH/9Ko1//W4Pf/4z2D/+dx7//jWa//0xEj/7qg1/+mXL//mkC3/5ZMu/+ad + Mf/opTT/6Kc1/+SfM//fky//14Iq/9J5Jv/OciX/ym4k/8dsJP/FaiT/tX5aH////wH///8B////Af// + /wH///8BqFMbg6lRGv+rURr/r1Ia/7JTGv+1Uxr/uFQa/7tVGv+9Vhr/wVcZ/8NXGf/FWRn/x1kZ/8la + Gf/LXBn/1Gse//CcLf/2pDD/9aIv//OfL//zoDH/8603//fJWP/88MD///////798f/66p7/8Lw8/+mi + M//mmDD/56Ez/+y1Qf/yzm7/9dmS//DJcP/mqDv/2ows/9F7KP/Lcib/xmsk/8NpJP/BZyP/snxYH/// + /wH///8B////Af///wH///8Bo1Eag6VQGv+nTxr/qlAa/61RGf+wUhr/tFMa/7ZUGf+5VRr/vVYZ/8BW + Gf/CWBn/xFkZ/8ZaGf/JWxn/02se/++aLf/0oTD/854v//GbL//xnTD/8q03//bOYP/999f///////// + ///+/er/9NVW/+yxOP/opDT/67M+//bbjv/9+OT//v35//335v/xzX//3ZUw/9F/Kv/Jcib/w2ok/8Bn + I/+9ZSP/r3lVH////wH///8B////Af///wH///8Bnk8ag59OGf+gTRn/pU4Z/6hQGv+rURr/rlEa/7JT + Gv+0VBr/uFQZ/7tVGv++Vxr/wVgZ/8NZGv/GWhr/0Wke/+6XLP/ynS//8Zsu/++YLv/umTD/76c0//PA + Q//76on////5//////////r/+uyO/+7APf/qsjn/8MZY//z11P////7///76//777f/9+e7/4KFD/9CA + K//HcSb/v2ck/7tjI/+4YiL/q3VRHf///wH///8B////Af///wH///8BmU0ag5pMGf+cTBn/oE0Z/6NO + Gf+mTxr/q1Aa/61RGv+xUhr/tVMZ/7hUGf+6Vhn/vVcZ/8BXGf/DWhn/zmge/+yTK//wmi7/75cu/+2U + Lf/slS7/7J0x/++wOP/1007//vvB////+/////7/+/Ky//HHQf/suDz/881e//343v///////vPI//vd + fv/226P/5bR0/8x8K//Ebib/u2Qj/7dhIv+0XyL/p3RPHf///wH///8B////Af///wH///8BlUsag5ZL + Gf+XSxn/nEwZ/55MGf+iThn/pk8a/6lPGf+sURr/sFIZ/7NTGf+3VBn/ulUZ/71WGf/AWRn/zGYe/+mQ + K//uly7/7JQt/+uRLf/pkC3/6JQt/+qgMv/vujv/+ehw//792////////fTH//PNTv/uuj3/9M9e//73 + 3f///////OGK//K9P//lqUn/5LiI/8d1KP+/aiX/tmIi/7JfIv+vXSH/pHBNHf///wH///8B////Af// + /wH///8BkEoag5BJGf+SSBn/lUkZ/5lKGf+cSxn/oEwZ/6NNGf+nThr/q1AZ/65RGv+xUhr/tVQZ/7hV + Gv+7WBr/x2Qe/+eOKv/sky3/6o8s/+iNLP/liiv/5Ikq/+SQLP/noTP/8MdE//rqlP/+/fP//fXT//TO + Xf/uuDv/8shW//zy0P///v7/981r/+WjNv/Uhy3/xXEo/71qJf+4YyP/sV4i/65bIP+qWSD/n2tIG/// + /wH///8B////Af///wH///8Bi0gag4xHGf+NRxn/kUgZ/5RJGf+XShn/m0sZ/59MGf+iTRn/pk8Z/6lR + Gf+tURn/sVIZ/7VUGf+4Vhn/xWMe/+WLKv/pjyz/54ws/+WJK//jhyv/4IQp/+CGKv/hkS7/6a45//TQ + X//99tz//fbd//TMaP/ttTr/8cBR//zsxf///v3/8cVu/92UMv/Leir/vGck/7ZiI/+xXSL/rFsh/6lZ + IP+mViD/nGlGG////wH///8B////Af///wH///8BhkYag4dGGf+JRhn/jEcZ/49HGf+TSRn/l0oZ/5pK + Gf+dTBn/ok0Z/6VOGf+pUBn/rFEZ/7BSGf+0VBn/wWIe/+KIKv/njCz/5Ykr/+KHK//ghCr/3oEo/9yB + Kf/chiv/45wz/+y6R//56bf//fjp//PLc//rsDr/7rhL//rmuP///vz/8MN3/9iNMP/FdCn/tWEj/7Bc + If+sWiH/qFgg/6RWIP+hVB//mWVDG////wH///8B////Af///wH///8BgkUag4JEGf+DQxj/hkQZ/4pF + Gf+MRxn/kUgZ/5RJGf+YShn/m0sZ/6BNGf+jThn/p08a/6tRGv+vUxr/vWAd/9+EKf/kiSv/4YYr/+CF + K//egyn/3IQq/9qBKv/Zgir/3ZIu/+apOv/004r//fnv//LKfv/pqjn/7a9E//jeq//+/fr/8suO/9iN + MP/Dcin/sF4i/6pYIf+nViD/oVQf/59SH/+aUR7/k2A+G////wH///8B////Af///wH///8BfkMag35C + Gf9+Qxn/gkMZ/4VEGf+IRRn/jEYZ/5BIGf+TSRn/l0oZ/5tKGP+eTBn/ok0Z/6ZPGf+rURr/uV4d/9uA + KP/hhSr/3oMq/96EK//dhiv/3Ios/9uJLP/aiSv/3JMv/+SiNv/wwmf//vv1//TPif/sqzn/77BB//nZ + nv/+/Pn/99Oc/9+SM//JeSz/tGIk/6paIf+kViD/nFIe/5lQHv+UTh7/jl47G////wH///8B////Af// + /wH///8BeUIag3lBGf96QRj/fkEZ/4BCGf+DQxn/iEQZ/4tGGf+ORxn/kkgY/5ZJGf+aSxn/nUwZ/6JO + Gf+mUBn/tVwd/9l9KP/egir/3IAp/9uCK//ciS3/57Fp/+WqV//fmjX/4Z80/+ipOP/yv1X//vz2//nV + j//0tD7/97VA//zXlP/+/Pj/+9qq/+maOP/SgjD/uWkn/6tdI/+hViH/mFAe/5NNHv+PTB7/i1o4G/// + /wH///8B////Af///wH///8BdkAag3ZAGf93Pxj/eUAZ/3tBGf9+Qhn/gkMZ/4VEGf+JRRn/jEcZ/5BI + Gf+USRn/mEoZ/5xMGf+gThn/r1kd/9V5J//afSn/2Hwp/9iBK//aiyz/7MGF//flxv/uw3X/7LRE//K6 + Qv/6yFr///rx//7gpP/+x2D//sdm//7epf///Pf//ubG//e/eP/quof/0Zln/61gJP+eVSD/kk4e/41L + Hf+JSh3/h1c1G////wH///8B////Af///wH///8Bcz8ag3I+Gf9yPhn/dT8Z/3dAGf96QBn/fUIZ/4FD + Gf+EQxn/iEUZ/4tGGP+PRxn/k0kZ/5dKGP+bTBn/q1gc/9F2Jv/Xeij/1Hgn/9R9KP/WhSr/4J9G//PX + q//89OX/+eKx//vhp//+6bn//vz1//735///8tv//vbp//779////v7//v7+//7+/v//////4b+i/6tf + JP+bVCD/jUwe/4hJHP+ERxz/glMxGf///wH///8B////Af///wH///8BcD4ag3A9Gf9vPRj/cT4Z/3M+ + Gf92Pxn/eUAZ/3xBGf+AQhn/g0MY/4dEGf+KRhn/j0cY/5JJGf+XSxn/p1Yc/85zJv/Udyb/0XQm/892 + Jv/RfCf/2Isu/+SqVv/24Lv///37//7+/f/+/v7///////7+/v/+/v7//vr2//3v3v/74MD/88ib/+ew + e//Ym2T/vntF/6JZI/+UUSD/iEod/4NHHP9/RRz/fk4tGf///wH///8B////Af///wH///8BbT0ag208 + Gf9sOxj/bTwZ/288Gf9yPRn/dT8Z/3hAGf96QRn/fkIZ/4FCGf+FQxn/iUUZ/41HGf+RSRn/olMc/8pv + JP/PciX/zHAk/8pvJP/KcSX/zXoo/9OFLP/bkzr/6bNr//DHkP/wxYn/7bJn/+ehTP/hkTb/24gx/9aD + MP/RfS7/yXUr/79tKf+yZCf/olkj/5VSIP+KSx7/gkcc/35FHP97Qxv/ekwqGf///wH///8B////Af// + /wH///8BbDwag2o7Gf9qOxn/azsZ/2w7Gf9uPBn/cT0Z/3Q+Gf93Pxn/ekAZ/3xCGP+AQhn/hUQZ/4hF + GP+NRxn/nVEb/8ZsI//LbyX/yG0k/8VrI//EayP/xG0k/8ZzJ//KeCn/z38s/9GCLf/RgS7/zX0s/8l3 + K//Ecyn/vW0o/7dpJv+yZCX/ql4j/6JZI/+aVCH/kU4f/4lLHf+CSBz/fUQb/3lDG/93QRv/dkgnGf// + /wH///8B////Af///wH///8BbDwag2k6Gf9oOhj/aDoZ/2o7Gf9rOxn/bjwZ/3A8Gf9yPhn/dj8Y/3hA + Gf98QRn/gEIY/4NEGf+IRhn/mU8b/8JpI//IbSX/xGkj/8FnIv++ZSL/vGUi/7tlI/+7ZyT/u2kk/7tp + Jf+5ZyX/tGMk/69gI/+qXCL/o1gh/55VIP+YUh//k08e/41NHv+ISh3/g0cc/39GHP98RBv/eUIb/3ZB + G/9zQBr/c0QjF////wH///8B////Af///wH///8BbDwag2o7Gf9nOhj/ZzkZ/2g6Gf9pOhn/azsZ/2w7 + Gf9uPBn/cT0Z/3U+Gf93Pxn/e0EZ/35CGf+DRBn/k00b/75mIv/DaCT/v2Yi/7xkIf+5YSH/tl8g/7Jd + IP+vWyD/rFkg/6lYIP+lVh//oVMe/5tSHv+YUB3/kU0d/45LHP+LShz/hkgc/4JHHP9/RRz/e0Mb/3lD + G/93QRv/dEAa/3E/Gv9vPhr/b0IhF////wH///8B////Af///wH///8BbDwag2k7Gf9oOhn/ZzkZ/2Y5 + Gf9nORn/aToZ/2o7Gf9rOxn/bjwZ/3A8GP9zPhn/d0AZ/3pBGP9+Qhn/j0sb/7ljIv/AZSP/vGMh/7lh + If+1XyH/sVsg/61ZH/+qVx//pVUe/6FTHv+dUR7/mU8d/5VOHf+RTB3/jEsc/4hJHP+GSBz/gUYb/35E + G/97Qxz/eEEb/3VBGv90QBr/cD4a/249Gf9sPBr/bD4eF////wH///8B////Af///wH///8BbDwag2o7 + Gf9oOhj/ZzkZ/2Y5Gf9mORn/ZzkZ/2g6Gf9qOhn/azsY/207Gf9wPRn/cj8Y/3Y/Gf96QRn/i0ob/7Zg + If+7YiL/t2Ah/7ReIP+wXCD/rVkg/6hXH/+lVR//oFIe/5tRHv+YTx7/kk4d/49MHf+MShz/h0kc/4NI + G/+ARhv/fEQb/3pDG/93QRv/dD8b/3I/Gv9wPhr/bj0a/2s8Gv9qOxn/aTwbF////wH///8B////Af// + /wH///8BbDwag2s7Gf9oOhn/ZzkZ/2c5Gf9mORn/ZjgZ/2Y5Gf9nORn/aToZ/2s7Gf9sOxn/bz0Z/3I+ + Gf92QBn/h0gb/7FdIP+2YCH/sl0g/69aIP+rWB//p1Yf/6NTHv+eUR7/mE8d/5RNHf+RTB3/jEsc/4hJ + HP+FSBv/gUYb/35FG/97Qxr/eEEa/3ZBG/9zPxr/cT4a/289Gv9tPRr/azsZ/2k6Gf9oORn/ZjkZF/// + /wH///8B////Af///wH///8BazsaZ2o7Ge1pOxn/aDoY/2c5GP9nORn/ZjgY/2U4GP9mORn/ZzkZ/2k6 + Gf9qOhn/bDwZ/289Gf9yPxn/g0Yb/6xbH/+xXSD/rlog/6pXH/+nVR//oVMe/55RHv+ZTx7/k00d/49L + Hf+MShz/h0kc/4RHG/+ARhv/fEQb/3lDGv93QRr/dD8a/3I/Gv9wPhr/bj0a/2w8Gv9qOxn/aDoZ/Wc5 + GetmORnJZjkZEf///wH///8B////Af///wH///8BajsaE2o7Gj9qOxmDaDoZ4Wg6Gf9nORn/ZjgZ/2Y4 + Gf9mOBn/ZjkZ/2Y5Gf9oOhn/ajsZ/2w7Gf9vPRn/f0Qb/6hYH/+sWSD/qVcf/6VVH/+hUx7/nFAe/5ZO + Hf+TTB3/jkoc/4lJHP+HSBz/gkYb/39FG/99RBv/eUIa/3ZBGv9zPxr/cT4a/24+Gv9sPRr/bDwa72k7 + Gr9oOhmNZzkYU2Y5GTdmOBglZjkYA////wH///8B////Af///wH///8B////Af///wH///8BaTsZB2k6 + GT9oOhmXaDoZ1Wc6GO9nORn9ZzkZ/2Y5Gf9mORn/aDoZ/2o7Gf9tPBn/e0Ib/6NUHv+nVR//o1Qe/55S + Hv+aUB7/lE4d/5BMHf+MShz/h0gc/4RHG/+BRhv/fEQb/3pDGv94Qhr3dEEb5XE/GtNwPhnDbz8ckW0/ + HV9rPx0t////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8BaDoYK2g6GWFoOhmbZzkZ4Wc5GP1mORn/ZjkZ/2g6Gf9rPBn/eUIb/55S + Hv+iUx7/nVIe/5hPHf+UTR3/j0sc/4pJHP+HSBz/gkYb/39FHPd8RR3bekQetXhCHJN2Qhxxc0IgS3FC + ISlxQyIJ////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wFoOhgPaDkZM2c5GWlmORm9ZjgZ/2c5 + Gf9pOxn/dkAa/5hQHv+cUR7/lk8d/5JNHf+OSh3/iUkc+4ZKINuCTCOrgEojbX5GHkN7RyEveUgmG3dJ + KAv///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8BZjkZJ2c5GX9oORnBdEAb9ZJOIOGVUB/LkVAhq41SK32JVTBLhlg3Ef///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wFoOhkTfkgibYpULkWQXjoZ////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8BAAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAA + AAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA + //8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAA + AAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA + //8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAA + AAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA + //8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//KAAAAEAAAACAAAAAAQAgAAAA + AAAAQgAAAAAAAAAAAAAAAAAAAAAAAP///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wEAAAAD////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8BAAAAAwAAAAUAAAAHAAAACQAAAAkAAAAHAAAABwAAAAUAAAAFAAAAAwAA + AAP///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////AQAAAAMAAAAFAAAACQAAAA0AAAATAAAAFwAAABsAAAAfAAAAHQAA + ABkAAAAVAAAAEwAAAA8AAAANAAAACwAAAAkAAAAHAAAABQAAAAMAAAAD////AQAAAAP///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////AQAAAAMAAAADAAAABQAAAAsAAAAPAAAAFwAAAB8AAAApAAAANQAA + AEEAAABJAAAASwAAAEsAAABFAAAAPwAAADkAAAAxAAAAKQAAACMAAAAdAAAAGQAAABUAAAARAAAADQAA + AAsAAAAJAAAABwAAAAUAAAAFAAAAAwAAAAMAAAAD////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8BAAAAAwAAAAUAAAAJAAAADQAAABcAAAAhAAAALQAA + AD0AAABPAAAAXwAAAHEAAACBAAAAiwAAAI0AAACJAAAAgwAAAHsAAABxAAAAZwAAAF8AAABVAAAASwAA + AEMAAAA7AAAANQAAACsAAAAlAAAAIQAAABkAAAAVAAAAEQAAAA8AAAALAAAACQAAAAcAAAAFAAAABQAA + AAUAAAAD////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////AQAAAAMAAAAFAAAACQAAAA8AAAAXAAAAHwAA + AC0AAAA/AAAATwAAAGEAAAB1AAAAhwAAAJsAAACvAAAAvVkuFN8dDgXLAAAAuwAAALMAAACtAAAApQAA + AJ8AAACXAAAAkQAAAIcAAAB9AAAAdQAAAGsAAABhAAAAWQAAAE8AAABHAAAAPQAAADMAAAAtAAAAJwAA + ACEAAAAdAAAAFwAAABMAAAAPAAAACwAAAAkAAAAJAAAABwAAAAUAAAADAAAAA////wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAAAwAAAAcAAAANAAAAFwAA + AB8AAAAtAAAAOwAAAE0AAABfAAAAdQAAAIcAAACZAAAApwAAALUAAADDRB8J4Y5BEvXNXxv/7pcq/+yK + LP3MZSX1gkId5zYeENEAAAC7AAAAuwAAALUAAACxAAAArQAAAKcAAAChAAAAmQAAAJEAAACLAAAAgQAA + AHcAAABvAAAAZQAAAFsAAABRAAAASQAAAD8AAAA5AAAALwAAACkAAAAjAAAAHQAAABkAAAATAAAACwAA + AAkAAAAFAAAAA////wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BAAAABQAA + AA0AAAAXAAAAJwAAADkAAABNAAAAYwAAAHUAAACHAAAAlwAAAKUAAACvAAAAuSgSBcl4Ng/lu1QY+8tc + Gv/MXRr/zF4a/+6XKv/8rzH//K8x//yvMf/8rzH/+aQw/+J8LPm2WiTxaDYa3yESCssAAAC9AAAAuwAA + ALkAAAC3AAAAsQAAAK8AAACpAAAAowAAAJsAAACVAAAAjQAAAIUAAAB7AAAAcQAAAGcAAABfAAAAUwAA + AEsAAABBAAAANQAAACkAAAAbAAAAEQAAAAkAAAAD////Af///wH///8B////Af///wH///8B////Af// + /wH///8BAAAABwAAABEAAAAjAAAAOwAAAFUAAABxAAAAhwAAAJsAAACnAAAAsQAAALcTCQLBZS4N26dM + FfHLWxr/y1sa/8tcGv/MXRr/zF4a/81fG//ulyz//K8z//yvM//8rzH//K8x//yvMf/8rzH//K8x//yv + Mf/8rzH/8ZYu/dZvKfeaTCDrTyoU2QgFA8MAAAC/AAAAvQAAAL0AAAC7AAAAtwAAALUAAACvAAAAqwAA + AKUAAACfAAAAlwAAAI8AAACFAAAAeQAAAGkAAABXAAAAPwAAACcAAAAVAAAACQAAAAP///8B////Af// + /wH///8B////Af///wH///8BAAAABwAAABEAAAAnAAAASQAAAG0AAACRAAAAqQAAALcAAAC9AAAAv0kh + CdOVRBPrx1oZ/8tcGv/LWxr/y1sa/8tbGv/LXBr/y1wa/8xeGv/NXxv/7pks//yxM//8sTP//LEz//yv + M//8rzP//K8x//yvMf/8rzH//K4w//urMP/6qzD/+qow//qoMP/5py//5IAs/cBeJPN1PRvlMRsO0QAA + AMEAAADBAAAAwQAAAL8AAAC9AAAAuwAAALcAAAC1AAAAsQAAAKkAAACdAAAAiwAAAG8AAABJAAAAKQAA + ABEAAAAHAAAAA////wH///8B////Af///wH///8BAAAAAwAAAA0AAAAjAAAARwAAAHcAAACjAAAAwwAA + AM8mEQXVeDcP571WGPvLXBr/y1wa/8tcGv/LWxr/y1sa/8tbGv/LWxr/y1wa/8tcGv/MXRr/zV8b/+6Z + LP/8sTP//LEz//yxM//8sTP//K8z//yvM//8rzH/+6ww//urMP/6qjD/+qow//mnMP/5pi//+KMv//ei + L//2oS7/9Z8u//SeLv/ujy3/1W8p+ZxNIO1ZLhbfGA4IywAAAMMAAADBAAAAwQAAAMEAAAC/AAAAuwAA + ALMAAACbAAAAbwAAAEEAAAAbAAAACwAAAAP///8B////Af///wH///8B////AQAAAAcAAAAXAAAANQAA + AGcAAAChEQgCz1oqDO2iShX5zF0a/8tcGv/LXBr/y1wa/8tbGv/LWxr/y1sa/8tbGv/LWxr/y1sa/8tc + Gv/LXBr/zF0a/81fG//umSz//LEz//yxM//8sTP//LEz//yxM//8rjL/+6wy//urMP/6qjD/+qgw//mn + L//4pi//+KMv//eiL//2oS7/9Z4u//SdLv/zmy3/8pgt//GVLf/vkyz/7pIs/+2RLP/ffSj9v14j9YBB + HOlCJBHZBAIBwwAAAMEAAADBAAAAswAAAIkAAABTAAAAKQAAAA8AAAAF////Af///wH///8B////AQAA + AAMAAAAJAAAAHQAAAEVaKgylk0UT6cRbGf/KXBr/ylwa/8tcGv/LXBr/y1sa/8tbGv/LWxr/y1sa/8tb + Gv/LWxr/y1sa/8tbGv/LWxr/y1wa/8xdGv/NXxv/7pks//yxM//8sTP//LEz//yxMv/7sDL/+60y//qr + Mv/6qjD/+acw//mnL//4pi//96Mv//aiLv/1ny7/9Z4u//SdLv/ymi3/8Zkt//CULf/vkyz/7pIs/+2R + LP/rjiv/6o0r/+iKK//niyr/5Ygq/+SFKv/KaSb5mUwf72Q1Gd02IROrAAAAWwAAACsAAAAPAAAABf// + /wH///8B////Af///wEAAAADAAAAC4U+E1O9WRrvw1sb/8RbGv/GWxr/x1oa/8hbGv/KWhr/y1sa/8tb + Gv/LWxr/y1sa/8tbGv/LWxr/y1sa/8tbGv/LWxr/y1sa/8tcGv/MXRr/zV8b/+6ZLP/8sTP//LEz//yx + Mv/7rjL/+60y//qsMv/6qjL/+acv//mmL//4pS//96Qv//ahLv/1ny7/9J4u//ObLv/ymi3/8Zct//CU + Lf/vkyz/7ZIs/+yPLP/rjiv/6Ysr/+eKKv/miSr/5Icq/+OFKf/hhSn/34Ip/96BKP/cfij/2nwo/9N5 + K/nJdzrbg1xEKQAAAAX///8B////Af///wH///8BAAAAAwAAAAmcShZtv1sb/8BaG//CWhr/wloa/8VZ + Gv/GWRr/x1oa/8laGv/KWxr/y1sa/8tbGv/LWxr/y1sa/8tbGv/LWxr/y1sa/8tbGv/LXBr/zF0a/81f + G//umSz//LEz//ywMv/7rjL/+60y//qsMv/6qjL/+acx//imL//3pS//96Qv//ahLv/1ni7/9J0u//Oa + Lf/ymS3/8Zct/++VLP/ukiz/7ZEs/+yOK//qjSv/6Yor/+eJKv/mhyr/5Icq/+KEKf/hgyn/34Ip/91/ + KP/bfij/2Xso/9d6J//Wdyf/03cl/6JwUDUAAAAD////Af///wH///8B////AQAAAAMAAAAHoU4Xabta + G/+9WRr/vlga/8BZGv/CWRr/w1ka/8VZGv/GWRr/yVoa/8pbGv/LWxr/y1sa/8tbGv/LWxr/y1sa/8tb + Gv/LWxr/y1wa/8xdGv/NXxv/7pkr//uwMv/7rTL/+q0y//qsMv/5qTH/+akx//ioMf/3pS//9qQu//Wh + Lv/1oC7/9Jsu//KaLf/xmS3/8JYt/++VLP/ukiz/7JEs/+uOK//qjSv/6Ior/+eHKv/lhir/44Uq/+KE + Kf/ggSn/3oIo/91/KP/afSj/2Xsn/9d4J//Vdyf/03Yl/9F1Jf+welcv////Af///wH///8B////Af// + /wH///8BAAAABadRGWO5WBv/ulga/7xXGv++Vxr/vlga/8FYGv/DWRr/xFka/8ZZGv/HWhr/yVoa/8pb + Gv/LWxr/y1sa/8tbGv/LWxr/y1sa/8tcGv/MXRr/zV8b/+2XK//7rTL/+qwy//qqMv/5qTH/+agx//il + Mf/3pTL/9qUv//WjL//0pDD/9KEv//OfL//ymy//8Jku/+6ULf/tkyz/7I8s/+qNK//piyv/54oq/+aH + Kv/khir/4oQp/+GDKf/fgSn/3oAo/9x+KP/afCj/2Hon/9Z4J//Udyf/0nYm/9BzJv/Ocib/tH1ZLf// + /wH///8B////Af///wH///8B////Af///wGtVBpftlcb/7dWGv+4Vhr/ulYa/7xWGv++Vxr/wVga/8JY + Gv/EWBr/xVka/8daGv/JWhr/ylsa/8tbGv/LWxr/y1sa/8tbGv/LXBr/zF0a/81fG//tmCv/+qwy//qq + Mv/5qTH/+Kgx//elMf/3pTH/9qQy//amMf/1qDP/9aoz//SrNP/ypjT/8aMy//CeMP/umC//7ZIs/+qO + LP/oiiv/54oq/+aJK//liCv/44gq/+GFKv/fhCn/3oAp/9yAKf/ZfCj/13gn/9V3J//TdyX/0XUm/89z + Jv/NcCX/y28l/7uDXiv///8B////Af///wH///8B////Af///wH///8BrlYbW7JWG/+zVRr/tVUa/7dV + Gv+5VRr/u1Ya/71XGv/AVxr/wlca/8NYGv/FWRr/xlka/8daGv/KWhr/y1sa/8tbGv/LWxr/y1wa/8xd + Gv/NXxv/7Zcr//qpMf/5qDH/+Kgx//emMf/2pDD/9qQx//amM//1qTT/9bA2//a2Of/1uTv/9Lc6//Oy + OP/wqjX/7p4x/+yWLv/pjy3/54or/+aLLP/ljSz/5ZAt/+SRLv/jkS3/4Y0t/96JLP/chCr/2X0p/9Z5 + KP/TdyX/0XQm/89yJv/McCX/ym8l/8htJf+5gl0r////Af///wH///8B////Af///wH///8B////AatU + G1uvVBv/sFMa/7FTGv+zUxr/tVQa/7hVGv+6VRr/vFYa/75WGv/BVxr/w1ga/8RZGv/GWRr/x1oa/8la + Gv/KWxr/y1sa/8tcGv/MXRr/zV8b/+yVK//5qjH/+Kcx//emMf/2pTD/9aEw//SjMv/0pzT/9a82//a6 + PP/4y1D/+NJU//fORP/1x0L/8ro8/++oNv/rmzD/6JEt/+aOLf/lkC3/5pYv/+acMv/noTP/56M0/+Wd + M//hlzD/3Y0u/9mCK//UfCf/0XYl/85yJv/MbyX/yW0l/8hsJf/FayT/tn9aKf///wH///8B////Af// + /wH///8B////Af///wGqVBtbq1Mb/6xSGv+uUhr/sFIa/7JTGv+1VBr/uFUa/7pVGv+8VRr/vlYa/8BX + Gv/CWBr/xFga/8VZGv/GWhr/yVoa/8pbGv/LXBr/zF0a/81fG//rlCv/96cx//emMP/2ozD/9aIw//Sg + Mf/0ojL/9Ko2//W2Ov/40V7//fC1/////////////ffJ//bTTP/xujv/66M0/+iXMP/mlC7/5Zcw/+ek + M//rrzj/7bk8/+27Pf/rszv/56o4/+GaMf/aiyz/1IAo/891J//McSb/yW0l/8ZrJP/EayT/w2gk/7R+ + Win///8B////Af///wH///8B////Af///wH///8BplMbW6dSG/+oURr/q1Ea/61SGv+vUhr/slMa/7RT + Gv+3VBr/uFUa/7tVGv+9Vhr/wFca/8FXGv/DWBr/xVka/8ZZGv/HWhr/ylsa/8xdGv/NXxv/65Ir//al + MP/2ozD/9aIw//SfL//znTD/8qAy//OqNv/1uzv/++SP/////v/////////////////9+MP/9MxC/+2x + OP/ooDP/5pwy/+ilNP/stTr/889f//vvuf/+++7//fXY//TSdf/mqTX/3pUv/9WDKv/OeCj/ynAm/8Zr + JP/EaiT/wWgk/79nI/+xelYp////Af///wH///8B////Af///wH///8B////AaJRGlukUBr/pU8a/6dP + Gv+pUBr/q1Ea/65SGv+wUhr/s1Ma/7VUGv+3VRr/uVUa/7xWGv++Vhr/wVca/8JZGv/EWRr/xVka/8hb + Gv/KXBr/zF8b/+qRKv/1ojD/9KEw//OeL//ynS//8Zkw//GeMf/xqTb/87o8//rhgf///u////////// + ///////////u//jkaf/vvz3/6qs3/+imNf/qsDn/881a//787////////////////////fj/8cpy/+Gc + M//Why7/znkp/8dwJv/DayT/wWgk/75mI/+8ZCP/r3lVKf///wH///8B////Af///wH///8B////Af// + /wGfUBpbn08a/6FPGf+iThr/pk8a/6hQGv+qURr/rVIa/69SGv+yUxr/tFQa/7ZVGv+4VRr/u1Ua/71W + Gv/AWBr/wlka/8NZGv/GWhr/x1sa/8teG//pjyr/9KEw//OeL//ynS//8Zou/++YL//vnDH/8KY0//K1 + Of/301P//vix////////////////////+P/99Z//8ctA/+uzOf/psDn/7bk8//rppv////3///////// + //////////////768f/jpT3/1ogu/817Kf/Gbyb/wWkl/71lI/+7ZCP/uWIj/6x2Uif///8B////Af// + /wH///8B////Af///wH///8BnE4aW5xNGv+dTRn/n00Z/6FOGf+kThr/pk8a/6pQGv+sURr/rlEa/7BS + Gv+0Uxr/tlQa/7lVGv+7VRr/vVca/75YGv/BWBr/w1ka/8VbGv/IXRv/6Iwp//OeL//xmi//8Jku/++W + Lv/uli7/7Zcv/+2eMv/wqzb/88Q///roZf///+L///////////////3//v3F//PRQ//tuT3/67U6/++/ + P//98b7//////////////vv///K8//3tuP/9+Ov/6bpx/9OGLv/LeCr/xG4l/71nJP+7YiP/uGIj/7Zh + Iv+pdlEn////Af///wH///8B////Af///wH///8B////AZdNGluZTRr/mUwZ/5xMGf+eTRn/oE0Z/6NO + Gv+lTxr/qVAa/6tQGv+tURr/sFIa/7NTGv+1VBr/uFUa/7pWGv+8Vhr/vlca/8FYGv/DWxr/xlwb/+aL + Kf/xmi//8Jku/++WLv/tlS7/7JIt/+uULv/rly7/66Ay/++zOf/10ET//fV9////8f/////////////+ + 6P/11Uj/778+/+25Pf/xxD7//fK+//////////////TG//7XSP/zwD//7sJ2/+/QqP/PgC3/x3Qo/8Fr + Jf+6ZCT/uGEi/7RgIv+xXiL/pnJOJ////wH///8B////Af///wH///8B////Af///wGUSxpblUsa/5ZK + Gf+XSxn/m0wZ/5xMGf+gTRn/ok4a/6RPGv+oTxr/qlAa/6xRGv+vUhr/slMa/7RUGv+3VBr/uVUa/7tW + Gv++Vxr/wVoa/8RbG//kiCj/75gu/+6XLv/tlS3/65It/+qQLf/pjy3/6JIs/+iWL//rpDT/77w8//bb + Tf/++6X//////////////ez/+Ntm/+/BQP/uuTz/8cU///3vvP////////////7nl//3xEH/6q06/+Ce + Qf/szKj/yXgp/8NvJ/+9aCX/t2Mj/7NgIv+wXiL/rl0h/6RwTSf///8B////Af///wH///8B////Af// + /wH///8BkUsaW5FKGv+SSRn/lEkZ/5ZKGf+ZShn/m0sZ/59MGf+hTRn/o00a/6ZOGv+pTxr/rFAa/65S + Gv+wUhr/s1Ma/7VUGv+4VRr/ulYa/71ZGv/AWhv/4oco/+6XLv/slC3/65Et/+qOLf/ojSz/5oos/+aJ + K//ljSv/5pgv/+mqNv/wxj7/+eRh///94/////////3v//neev/vvz3/7rc7//DAPf/756b////+//// + ///82nz/7rQ8/+CaM//ThS3/yXYq/8JuJ/+9aib/uWMj/7NfI/+wXSH/rlsh/6paIf+gbEkl////Af// + /wH///8B////Af///wH///8B////AY1KGluOSRr/jkgZ/49IGf+SSRn/lUoZ/5hKGf+aSxn/nUwZ/6BN + Gf+jTRr/pU4a/6hPGv+rURr/rVIa/69SGv+yUxr/tVQa/7hWGv+7WBr/vlkb/+CGKP/slC3/6pEt/+mO + LP/njSz/5oos/+SJK//ihin/4oYq/+KNLf/kmjH/6rE5//LKRv/865b////////98v/534j/77s8/+23 + O//vuz3/+uGb///++///////99B5/+elN//YjTD/ynoq/8FsJ/+7ZiT/t2Mj/7NfI/+vXiH/rVsh/6pa + If+nVyD/nmtIJf///wH///8B////Af///wH///8B////Af///wGJSBpbiUca/4tHGf+MRxn/j0cZ/5FI + Gf+TSRn/l0oZ/5lKGf+cSxn/n00Z/6JNGv+kThr/plAa/6pRGv+sUhr/r1Ia/7JTGv+1VBr/uFYa/7tZ + G//egyj/6pIt/+iNLP/niyz/5Yos/+SHK//ihSv/4IMp/96DKP/fhSr/4JAu/+WgNP/stjz/9tZm///+ + +v///vr/+uOh/+62PP/ssjr/7rU7//jWif///Pb///////bTif/inTX/04Qu/8VyKf+6ZiT/tWEj/7Je + I/+vWyH/rFoh/6lYIf+mVyD/pFUg/5pnRCX///8B////Af///wH///8B////Af///wH///8BhkcaW4ZG + Gv+GRhn/iUYZ/4pHGf+ORxn/kEgZ/5NJGf+WShn/l0oZ/5tLGf+dTBn/oU0Z/6NOGv+mTxr/qVAa/6tR + Gv+vUhr/sVMa/7RVGv+4WBv/3IAo/+iPLP/niiz/5Ykr/+OIK//hhiv/4IMq/96BKP/dgCn/24Ap/9uG + K//glDH/56o5//DET//88c7///////rlsf/ssDr/67A6/+yvO//10Hn///vy///////20Y//4Jc0/9CC + Lf/Bbyj/tmEk/7BdIf+uWyH/qloh/6hYIP+kVyD/olUg/6BTH/+ZZUMl////Af///wH///8B////Af// + /wH///8B////AYNGGluDRhr/g0QZ/4VEGf+HRRn/iUUZ/41GGf+OSBn/kkkZ/5RKGf+WShn/mksZ/5xM + Gf+gTRn/ok4a/6VPGv+oUBr/qlEa/65TGv+xVBr/tVcb/9l/J//mjCz/5Ikr/+OHK//hhSz/4IUr/96D + Kf/dhCr/24Eq/9l/Kf/Zgiv/3Y8t/+OiNP/rtkT/+eOt///////657z/6606/+mqOf/rqTn/88Vr//75 + 7///////+Nup/+CXNP/Pgi3/vmwo/7JgI/+sWiH/qlch/6dXIP+jVSD/oVQg/59SH/+bUh//lGE/I/// + /wH///8B////Af///wH///8B////Af///wGARBpbgEQa/4BDGf+BRBn/hEQZ/4ZEGf+IRRn/i0YZ/41H + Gf+RSBn/k0kZ/5ZKGf+YShn/m0sZ/59MGf+hTRn/pE4a/6dPGv+rURr/rlIa/7FVG//XfCf/5Igr/+KH + K//ghSr/4IYr/9+FLP/dhSv/3Ygr/9yGLP/ahSz/2YUq/9uMLf/gnDL/6Ko8//TShf///////O/V/+us + Ov/qqDj/7Ko6//PAX//+9+v///////vit//kmjX/0oQu/8FwKf+0YiT/rFsh/6hYIf+kViD/n1Qf/55S + H/+aUB//lk8e/5FgPSP///8B////Af///wH///8B////Af///wH///8BfEMaW31DGv98Qhn/fUMZ/4BD + Gf+DQxn/hEQZ/4hFGf+KRhn/jEcZ/5BIGf+SSRn/lUoZ/5hKGf+bSxn/nUwZ/6BNGf+kThr/plAa/6pR + Gv+uVBv/1Hom/+GGK//fhCr/3oIq/92CK//dhSz/3Yks/92NLv/dji//3I4t/9uNLf/clC//4p40/+em + N//zxWn///////3y2v/vsDv/7qw7//CvPf/2uUr///bm///////+6cX/7KI4/9uMMv/IeS3/uWcm/65e + I/+oWiL/olYg/5xTH/+YUB//lU8e/5JNHv+MXDkj////Af///wH///8B////Af///wH///8B////AXlC + Glt5Qhr/eUEZ/3pCGf99QRn/f0IZ/4FDGf+DQxn/h0QZ/4lFGf+LRhn/jkcZ/5FIGf+VSRn/l0oZ/5pL + Gf+cTBn/oE4Z/6NPGv+mUBr/q1Mb/9J2Jv/fgyr/3YEq/9yAKf/bgSv/24Qt/9yMLv/qvH3/7MB//+So + S//gmzL/4qA1/+epN//ssDv/9sZc///////+9d//9rhC//a3P//5tT///LpE///15P///////+7U//Sm + PP/jkjf/0H8v/75uKv+xYiX/p1oi/59VIf+ZUB//k04e/5FMHv+OTR7/i1o4I////wH///8B////Af// + /wH///8B////Af///wF3QRpbd0Ea/3dAGf94QBn/ekAZ/3tBGf9+Qhn/gEMZ/4JDGf+FRBn/iEUZ/4tG + Gf+NRxn/kEgZ/5NJGf+WShn/mUoZ/5xMGf+gTRn/ok8Z/6ZRG//QdSb/3YAq/9p9Kf/ZfSn/2H4q/9qF + Lf/bjy3/675+//rt2P/02av/56g2/+mtOf/usjz/9LtA//vJWP///fj///bk//7BSP/+vUL//rtC//65 + QP//8dr////////v2P/7rkX/7qdT/+GjZP/TmWL/tGUm/6hbI/+cVCD/lU8f/5BMHv+NSx7/iksd/4hY + NiP///8B////Af///wH///8B////Af///wH///8BdEAaW3RAGv90Pxn/dT8Z/3ZAGf94QBn/ekEZ/3xC + Gf9/Qxn/gkMZ/4REGf+HRRn/ikYZ/4xHGf+OSBn/kkkZ/5VKGf+YSxn/m0wZ/59OGf+jURr/zXMl/9p9 + Kf/YfCn/1noo/9Z8Kf/Xgyr/2osr/+CbO//02az///78//vt0f/0yW3/9sBI//vKWP/+1nz///nr///7 + 8v//5LD//+a7///sz///9OP///7+////////////////////////////8t/N/7VnKP+mXCP/m1Mg/5BO + H/+MSx3/iUod/4ZIHf+EVTIh////Af///wH///8B////Af///wH///8B////AXI/GltyPxr/cT4Z/3E+ + Gf9zPxn/dUAZ/3dAGf95QBn/e0EZ/35CGf+BQxn/g0MZ/4VEGf+JRRn/i0YZ/49HGf+RSBn/k0kZ/5hL + Gf+aTBn/oE8a/8lwJf/Xein/1Xko/9R3Jv/SeSf/030n/9WDKv/akC//5KVG//jkwf////////////// + //////////////////////////////////////////////////////////////////////////////Dc + yv+wZCb/o1kj/5ZSIP+NTR7/iEod/4ZIHf+BRxz/gVIwIf///wH///8B////Af///wH///8B////Af// + /wFwPxpbcD4a/289Gf9vPRn/cT4Z/3E/Gf90Phn/dj8Z/3hAGf96QRn/fkIZ/4BDGf+CQxn/hEQZ/4hF + Gf+KRhn/jkcZ/5BIGf+UShn/l0sZ/5tOGv/HbST/1Xko/9N2Jv/Rcyb/z3Qn/893Jv/RfCj/1oUs/9uS + MP/os17/+eXD///9+v///fr///////////////////////////////////z5//7x4v/848X/+dKk//O8 + hP/opGD/2IlA/8d1LP+3aCj/plwk/5pUIv+QUB//iEoe/4NIHf+BRhz/fkUc/31OLSH///8B////Af// + /wH///8B////Af///wH///8Bbj4aW249Gv9tPBn/bTwZ/249Gf9vPRn/cT0Z/3Q+Gf92Pxn/eEAZ/3pB + Gf98Qhn/f0MZ/4FDGf+EQxn/h0QZ/4lFGf+NRxn/j0kZ/5RKGf+YTRr/xGsj/9J1Jv/Pcyb/zXIl/81w + Jf/LcST/zHQm/856Kf/ThCv/2I8x/+KdRP/tvHP/9tWk//nhu//41Z//9cSA//G1ZP/roUj/5pU1/+KP + NP/fizP/24cx/9eBMP/RfC7/ynQr/8BwKv+1Zij/qF4l/51WIf+TUSD/ikse/4RJHP+ARhz/fkUc/3xD + HP97TSsh////Af///wH///8B////Af///wH///8B////AW4+GltsPBr/azwZ/2w8Gf9sPBn/bTwZ/248 + Gf9wPRn/cj4Z/3U/Gf93Pxn/eUAZ/3tBGf9+Qhn/gEMZ/4NDGf+GRBn/iEYZ/4xHGf+QSBn/lUsa/8Fp + Iv/Pcib/zHAl/8pvJf/IbSP/x20k/8duJf/HcSX/ynco/819K//SgS7/14gv/9mMMf/bjzP/240y/9mL + Mf/WhjH/0oAu/899Lf/LeS3/xnYq/8JwKv+9bSn/uGcm/7FjJ/+qXiX/olkk/5tUIf+SUCD/ikwe/4RJ + Hf+ARxz/fEUc/3pDHP94Qxv/eEopIf///wH///8B////Af///wH///8B////Af///wFtPRpbazsa/2k7 + Gf9qOxn/ajsZ/2s8Gf9sOxn/bjwZ/289Gf9xPRn/dD4Z/3Y/Gf94QBn/ekEZ/3xCGf+AQxn/g0MZ/4VF + Gf+JRhn/jEgZ/5BKGv++ZyL/zHAl/8pvJf/IbSX/xWoj/8NpI//BaCP/wWgj/8FrJf/CbiX/xXEn/8d2 + Kf/Idin/yHgq/8d1Kv/Dcin/wG4o/71rJ/+3aCX/s2Ml/69iJP+pXiT/pVsi/6FXIf+bVSL/lVEh/5BO + H/+MSx7/hkoe/4NHHP9/Rhz/fEMc/3lDG/93Qhv/dUAb/3RGJR////8B////Af///wH///8B////Af// + /wH///8BbT0aW2s7Gv9oOhn/aDsZ/2g6Gf9qOxn/azsZ/2s7Gf9tPBn/bzwZ/3A9Gf9yPhn/dT8Z/3dA + Gf95QRn/fEEZ/39CGf+BQxn/hEQZ/4lGGf+NSBr/umQi/8ltJf/HbCX/xGkk/8JnIv+/ZiL/vWQi/7tk + Iv+6ZCL/umMj/7llJP+4ZSP/t2Uk/7dkJf+0YyP/sWAj/61eI/+pWyH/pFgh/6BWIP+cUx//mFEf/5NO + Hv+QTR3/jEwe/4dKHf+GSB3/gkcc/39GHP99RRz/e0Mc/3lDG/93QRv/dUAb/3JAGv9zRCMf////Af// + /wH///8B////Af///wH///8B////AW09GltrPBr/aToZ/2c6Gf9oOhn/aDoZ/2k7Gf9qOxn/azsZ/2w7 + Gf9uPBn/cD0Z/3I+Gf91Phn/dz8Z/3lAGf98QRn/fkIZ/4FEGf+FRRn/iUca/7hjIv/GayT/xGkk/8Fn + Iv+/ZiL/vGQi/7phIv+4YSH/tV4h/7NeIP+wXCH/r1sh/61bIf+qWSD/p1gg/6RUH/+fVR//m1Ie/5lR + Hv+TTh3/kEwd/45LHf+MSxz/iUoc/4VIHf+CRx3/f0Uc/31EHP97RRz/ekMb/3dCG/91QRv/c0Ab/3E/ + Gv9wPhr/cEMiH////wH///8B////Af///wH///8B////Af///wFtPRpbazwa/2k6Gf9oOhn/ZzkZ/2c5 + Gf9nOhn/aToZ/2o7Gf9rOxn/bDsZ/208Gf9vPRn/cT0Z/3Q+Gf92Pxn/eUAZ/3tBGf99Qxn/gUQZ/4ZG + Gv+0YSH/w2ok/8FmJP++ZCL/vGMi/7lhIf+2YCH/tF4h/7FbIP+uWiD/q1gg/6hXH/+mVR//oVQf/59S + Hv+dUB7/mlEe/5ZOHf+TTh3/kEwd/41LHf+JShz/h0kc/4RHHP+CRxz/f0Uc/31EHP97Qhz/eEMb/3dC + G/91QBv/c0Ab/3E+Gv9vPhr/bT0a/20/Hx////8B////Af///wH///8B////Af///wH///8BbT0aW2s8 + Gv9pOxn/aDoZ/2c5Gf9nORn/ZjkZ/2c6Gf9oOhn/aTsZ/2s7Gf9rOxn/bTwZ/248Gf9wPRn/cj4Z/3VA + Gf93QBn/ekEZ/35CGf+CRRr/sV4h/8BmJP++ZCL/u2Mi/7lhIf+2YCH/s10h/7FbIP+tWiD/qlgg/6hW + H/+lVR//oFMf/55SHv+bUB7/l1Ae/5ROHf+STR3/jksd/4pLHP+IShz/hkkc/4RHHP+ARhv/f0Qc/3tE + HP95Qhz/d0Eb/3RBG/91QBv/ckAa/3A+Gv9uPRr/bT0a/2s8Gv9rPR0f////Af///wH///8B////Af// + /wH///8B////AW09GltrPBr/aTsZ/2g6Gf9nOhn/ZzkZ/2Y5Gf9mORn/ZzkZ/2g6Gf9pOhn/ajsZ/2s7 + Gf9sOxn/bjwZ/3A9Gf9xPxn/dD8Z/3dAGf97QRn/f0Qa/65dIP+9ZCL/umEi/7dgIf+1XyH/sl0g/69b + IP+tWSD/qlgg/6ZVH/+kVR//oFIe/5tRHv+aUB7/lk4e/5JOHf+PTB3/jksd/4pKHP+HShz/hEgc/4FH + G/9+RRv/fEQb/3tEHP95Qhv/dkEb/3Q/G/9yQBv/cT8a/3A+Gv9uPRr/bD0a/2o7Gv9qOxn/aTwbH/// + /wH///8B////Af///wH///8B////Af///wFtPRpbbDwa/2o7Gf9oOhn/aDoZ/2c5Gf9nORn/ZjkZ/2Y5 + Gf9mORn/ZzoZ/2g6Gf9qOxn/azsZ/2w7Gf9tPBn/bz0Z/3I+Gf91Pxn/eEEZ/31DGv+rWiD/uWEh/7dg + If+0XyH/sVsg/69aIP+rWCD/qVcf/6ZVH/+iUx//n1Ie/5tQHv+XTx7/lE0d/5JNHf+PTB3/i0sd/4hJ + HP+GSRz/g0cc/4BHG/9+RRv/fEQb/3pCG/94Qhv/dkEb/3Q/G/9yPxv/cD4a/28+Gv9tPRr/bDwa/2o7 + Gf9qOxn/aToZ/2c5GR////8B////Af///wH///8B////Af///wH///8BbDwaW2w8Gv9qOxr/aTsZ/2g6 + Gf9nOhn/ZzkZ/2c5Gf9mORn/ZjkZ/2Y5Gf9nOhn/aDoZ/2k7Gf9rOxn/azsZ/208Gf9vPRn/cT4Z/3VA + Gf95Qhr/p1gf/7ZgIf+zXyH/sVwg/65aIP+rWCD/qVYf/6VVH/+iUx//n1Ie/5pQHv+WTx7/lE0d/5BM + Hf+NSx3/iksc/4hJHP+FSRz/gkcb/39GG/98RBv/ekQb/3hCGv92QRr/dEAb/3Q/G/9xPhr/cD4a/249 + Gv9tPRr/azwa/2o7Gf9pOxn/ZzkZ/2Y5Gf9mORkf////Af///wH///8B////Af///wH///8B////AWo7 + GidrPBq1azwa/2o7Gf9pOhn/aDoZ/2c6Gf9nORn/ZzkZ/2Y5Gf9mORn/ZjkZ/2Y5Gf9nOhn/aToZ/2o7 + Gf9rPBn/bTwZ/289Gf9yPxn/dkAa/6RWH/+yXiD/r1wg/65ZIP+qWCD/p1Uf/6VVH/+gVB7/nVEe/5pQ + Hv+WTh7/kk0d/49LHf+MSh3/ikkc/4ZIHP+DRhz/gUcb/35FG/98RBv/ekQb/3hCGv91QRr/cz8a/3I/ + G/9wPhr/bj4a/249Gv9sPBr/ajsa/2k7Gf9oOhn/ZjkZ8WY5GbtmORmHZjkZDf///wH///8B////Af// + /wH///8B////Af///wH///8B////AWo7GhVqOxlvaTsZyWk6Gf9oOhn/aDoZ/2c5Gf9nORn/ZzkZ/2c5 + Gf9mORn/ZjkZ/2c6Gf9oOhn/ajsZ/2s7Gf9tPBn/cD4Z/3Q/Gv+gVR7/r1wg/6tYIP+pVx//plUf/6JU + H/+fUx7/nVAe/5dPHv+UTR3/kUwd/49KHf+JSRz/h0kc/4ZIHP+DRhz/f0Ub/35FG/98RBv/ekIb/3dC + Gv91QRr/cj8a/3E/Gv9vPhr/bT4a/2w9Gv9sPBr3ajwaxWg8Go9oOhpbZjkZJf///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wFpOxklaToZgWg6 + GeFoOhn/aDoZ/2c6Gf9nORn/ZzkZ/2c5Gf9mORn/ZzoZ/2g6Gf9qOxn/azwZ/249Gf9xPhr/nVIe/6tY + IP+nVh//pVUf/6JUH/+dUx7/m1Ee/5ZPHv+UTR3/kEwd/41KHf+JSRz/h0kc/4RIHP+CRhv/fkUb/3tD + G/96RBv/eEIa/3ZBGv9zQBr/cT8a/3A+Gf9wQBzNbj8dmW1AHmNrPx4v////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8BaToZPWg6GZdoOhntaDoZ/2c6Gf9nORn/ZzkZ/2Y5Gf9nORn/aDoZ/2o7 + Gf9tPRn/cD4a/5pRHv+nVR//pFQf/6BUHv+dUR7/mlEe/5VOHv+STR3/j0sd/4xKHf+JSRz/hUgc/4JG + HP+ARhv/fUQb/3tDG/95QRv/eEIa/3ZDHdV0QyClckMhbXFDIjn///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8BaToZA2g6GU9oOhmvaDoZ+Wc5 + Gf9mORn/ZjkZ/2c5Gf9pOxn/azwZ/24+Gv+WTh7/olQf/59THv+dUR7/l1Ae/5RNHf+RTB3/j0od/4lJ + HP+HSRz/hEgc/4JGHP9/RRv/fkYf33tII6t6SCZ5eEkoQXdJKAv///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////AWg6GQ9oOhljZzkZvWY5Gf9nORn/aDoZ/2o7Gf9sPBr/kk0e/51THv+aUR7/llAe/5NO + Hf+QSx3/jEod/4lJHP+GSiDlhU0mt4BPKoN/UC1Lf1MzEf///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wFmORkbZzkZe2g6GdVoOhn/aTsZ/45L + Hf+aUR7/lU8e/5JQIO+PUSm/jFQujYhWMlWGWDcd////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8BaDoZMXxGIOeGUCqvkl03YZBgPSP///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Af///wH///8B////Af///wEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA== + + + \ No newline at end of file diff --git a/Source/TibisMathematicsSuite/Program.cs b/Source/TibisMathematicsSuite/Program.cs new file mode 100644 index 0000000..184f292 --- /dev/null +++ b/Source/TibisMathematicsSuite/Program.cs @@ -0,0 +1,21 @@ + using System; +using System.Collections.Generic; +using System.Linq; +using System.Windows.Forms; + +namespace TibisMathematicsSuite +{ + static class Program + { + /// + /// The main entry point for the application. + /// + [STAThread] + static void Main() + { + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + Application.Run(new MainWindow()); + } + } +} diff --git a/Source/TibisMathematicsSuite/Properties/AssemblyInfo.cs b/Source/TibisMathematicsSuite/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..a85920a --- /dev/null +++ b/Source/TibisMathematicsSuite/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 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("Main application")] +[assembly: AssemblyDescription("This is the main application of the suite.")] +[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)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("e2784748-c70f-438c-aa4b-fbb512c39906")] + +// 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")] diff --git a/Source/TibisMathematicsSuite/Properties/Resources.Designer.cs b/Source/TibisMathematicsSuite/Properties/Resources.Designer.cs new file mode 100644 index 0000000..37ce345 --- /dev/null +++ b/Source/TibisMathematicsSuite/Properties/Resources.Designer.cs @@ -0,0 +1,71 @@ +//------------------------------------------------------------------------------ +// +// 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. +// +//------------------------------------------------------------------------------ + +namespace TibisMathematicsSuite.Properties +{ + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // 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() + { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [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("TibisMathematicsSuite.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture + { + get + { + return resourceCulture; + } + set + { + resourceCulture = value; + } + } + } +} diff --git a/Source/TibisMathematicsSuite/Properties/Resources.resx b/Source/TibisMathematicsSuite/Properties/Resources.resx new file mode 100644 index 0000000..af7dbeb --- /dev/null +++ b/Source/TibisMathematicsSuite/Properties/Resources.resx @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Source/TibisMathematicsSuite/Properties/Settings.Designer.cs b/Source/TibisMathematicsSuite/Properties/Settings.Designer.cs new file mode 100644 index 0000000..944be29 --- /dev/null +++ b/Source/TibisMathematicsSuite/Properties/Settings.Designer.cs @@ -0,0 +1,37 @@ +//------------------------------------------------------------------------------ +// +// 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. +// +//------------------------------------------------------------------------------ + +namespace TibisMathematicsSuite.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()] + public global::System.Collections.Specialized.StringDictionary ModuleKeys { + get { + return ((global::System.Collections.Specialized.StringDictionary)(this["ModuleKeys"])); + } + set { + this["ModuleKeys"] = value; + } + } + } +} diff --git a/Source/TibisMathematicsSuite/Properties/Settings.settings b/Source/TibisMathematicsSuite/Properties/Settings.settings new file mode 100644 index 0000000..4466368 --- /dev/null +++ b/Source/TibisMathematicsSuite/Properties/Settings.settings @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/Source/TibisMathematicsSuite/TibisMathematicsSuite.csproj b/Source/TibisMathematicsSuite/TibisMathematicsSuite.csproj new file mode 100644 index 0000000..82a1b22 --- /dev/null +++ b/Source/TibisMathematicsSuite/TibisMathematicsSuite.csproj @@ -0,0 +1,117 @@ + + + + Debug + x86 + 8.0.30703 + 2.0 + {9A45DFCA-EA4F-4950-8519-F1BCE929D5CA} + WinExe + Properties + TibisMathematicsSuite + TibisMathematicsSuite + v4.0 + Client + 512 + + + x86 + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + x86 + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + suite.ico + + + ..\..\TibisMathematicsSuite - Release\ + TRACE + true + pdbonly + x86 + prompt + true + + + + + + + + + + + + + + + + Component + + + Form + + + MainWindow.cs + + + + + + + + + + MainWindow.cs + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + True + Resources.resx + + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + + + {A04B247B-6A95-462B-9E07-3337A1C158F1} + DynamicLink + + + + + + + + \ No newline at end of file diff --git a/Source/TibisMathematicsSuite/app.config b/Source/TibisMathematicsSuite/app.config new file mode 100644 index 0000000..3e4f9f3 --- /dev/null +++ b/Source/TibisMathematicsSuite/app.config @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/Source/TibisMathematicsSuite/suite.ico b/Source/TibisMathematicsSuite/suite.ico new file mode 100644 index 0000000..f3a9fcc Binary files /dev/null and b/Source/TibisMathematicsSuite/suite.ico differ