diff --git a/build/config/TRexDefs/amd64/performance.xml b/build/config/TRexDefs/amd64/performance.xml
deleted file mode 100644
index e6b6b40e0..000000000
--- a/build/config/TRexDefs/amd64/performance.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-
-
-
-
- RS_APPS_VALIDATE AMD64 Desktop WinPerf Test Run
- 134858
- paxeedev
- true
- true
- Performance_AMD64.testlist
-
-
-
- VSTS\IsReliabilityRun
- True
-
-
-
-
- AlternatePackageRoot
- \\pkges\release\TAEF\validation.taef.provenance\1812.20007-develop\UniversalTestPackages;\\edge-svcs\Release\MITALite\Apps_eng.mitalite_ci\Latest.tst
-
-
- _AlternatePackageRoot
- \\pkges\release\TAEF\validation.taef.provenance\1812.20007-develop\UniversalTestPackages;\\edge-svcs\Release\MITALite\Apps_eng.mitalite_ci\Latest.tst
-
-
-
-
-
\ No newline at end of file
diff --git a/build/config/TRexDefs/amd64/rs4_release.xml b/build/config/TRexDefs/amd64/rs4_release.xml
deleted file mode 100644
index 78a52df95..000000000
--- a/build/config/TRexDefs/amd64/rs4_release.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-
-
-
-
- RS4_RELEASE AMD64 DesktopVM Test Run
- 139642
- paxeedev
- true
- true
- Desktop_AMD64.testlist
- rs4_release
-
-
- AlternatePackageRoot
- \\pkges\release\TAEF\validation.taef.provenance\1812.20007-develop\UniversalTestPackages;\\edge-svcs\Release\MITALite\Apps_eng.mitalite_ci\Latest.tst
-
-
- _AlternatePackageRoot
- \\pkges\release\TAEF\validation.taef.provenance\1812.20007-develop\UniversalTestPackages;\\edge-svcs\Release\MITALite\Apps_eng.mitalite_ci\Latest.tst
-
-
-
-
-
\ No newline at end of file
diff --git a/build/config/TRexDefs/amd64/rs5_release.xml b/build/config/TRexDefs/amd64/rs5_release.xml
deleted file mode 100644
index 7fbccdc21..000000000
--- a/build/config/TRexDefs/amd64/rs5_release.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-
-
-
-
-
- RS5_RELEASE AMD64 DesktopVM Test Run
- 139642
- paxeedev
- true
- true
- Desktop_AMD64.testlist
- rs5_release
-
-
- AlternatePackageRoot
- \\pkges\release\TAEF\validation.taef.provenance\1812.20007-develop\UniversalTestPackages;\\edge-svcs\Release\MITALite\Apps_eng.mitalite_ci\Latest.tst
-
-
- _AlternatePackageRoot
- \\pkges\release\TAEF\validation.taef.provenance\1812.20007-develop\UniversalTestPackages;\\edge-svcs\Release\MITALite\Apps_eng.mitalite_ci\Latest.tst
-
-
-
-
-
\ No newline at end of file
diff --git a/build/config/TRexDefs/amd64/rs_apps_validate.xml b/build/config/TRexDefs/amd64/rs_apps_validate.xml
deleted file mode 100644
index a90ca2881..000000000
--- a/build/config/TRexDefs/amd64/rs_apps_validate.xml
+++ /dev/null
@@ -1,44 +0,0 @@
-
-
-
-
- RS_APPS_VALIDATE AMD64 DesktopVM Test Run
- 139642
- paxeedev
- true
- true
- Desktop_AMD64.testlist
- rs_apps_validate
-
-
- AlternatePackageRoot
- \\pkges\release\TAEF\validation.taef.provenance\1812.20007-develop\UniversalTestPackages;\\edge-svcs\Release\MITALite\Apps_eng.mitalite_ci\Latest.tst
-
-
- _AlternatePackageRoot
- \\pkges\release\TAEF\validation.taef.provenance\1812.20007-develop\UniversalTestPackages;\\edge-svcs\Release\MITALite\Apps_eng.mitalite_ci\Latest.tst
-
-
-
-
-
- RS_APPS_VALIDATE AMD64 WCOS Test Run
- 153648
- paxeedev
- true
- true
- WCOS_AMD64.testlist
- rs_apps_validate
-
-
- AlternatePackageRoot
- \\pkges\release\TAEF\validation.taef.provenance\1812.20007-develop\UniversalTestPackages;\\edge-svcs\Release\MITALite\Apps_eng.mitalite_ci\Latest.tst
-
-
- _AlternatePackageRoot
- \\pkges\release\TAEF\validation.taef.provenance\1812.20007-develop\UniversalTestPackages;\\edge-svcs\Release\MITALite\Apps_eng.mitalite_ci\Latest.tst
-
-
-
-
-
\ No newline at end of file
diff --git a/build/config/TRexDefs/arm/performance.xml b/build/config/TRexDefs/arm/performance.xml
deleted file mode 100644
index 5fde2b8a5..000000000
--- a/build/config/TRexDefs/arm/performance.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-
-
-
-
-
- RS_PRERELEASE ARM WindowsCore WinPerf Test Run
- 135258
- paxeedev
- true
- true
- Performance_ARM.testlist
-
-
-
- VSTS\IsReliabilityRun
- True
-
-
-
-
- AlternatePackageRoot
- \\pkges\release\TAEF\validation.taef.provenance\1812.20007-develop\UniversalTestPackages;\\edge-svcs\Release\MITALite\Apps_eng.mitalite_ci\Latest.tst
-
-
- _AlternatePackageRoot
- \\pkges\release\TAEF\validation.taef.provenance\1812.20007-develop\UniversalTestPackages;\\edge-svcs\Release\MITALite\Apps_eng.mitalite_ci\Latest.tst
-
-
-
-
-
\ No newline at end of file
diff --git a/build/config/TRexDefs/arm/rs_apps_validate.xml b/build/config/TRexDefs/arm/rs_apps_validate.xml
deleted file mode 100644
index 277c97612..000000000
--- a/build/config/TRexDefs/arm/rs_apps_validate.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/build/config/TRexDefs/x86/rs4_release.xml b/build/config/TRexDefs/x86/rs4_release.xml
deleted file mode 100644
index 7f3f2cbfd..000000000
--- a/build/config/TRexDefs/x86/rs4_release.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-
-
-
-
-
- RS_APPS_VALIDATE x86 DesktopVM Test Run
- 139643
- paxeedev
- true
- true
- Desktop_x86.testlist
- rs4_release
-
-
- AlternatePackageRoot
- \\pkges\release\TAEF\validation.taef.provenance\1812.20007-develop\UniversalTestPackages;\\edge-svcs\Release\MITALite\Apps_eng.mitalite_ci\Latest.tst
-
-
- _AlternatePackageRoot
- \\pkges\release\TAEF\validation.taef.provenance\1812.20007-develop\UniversalTestPackages;\\edge-svcs\Release\MITALite\Apps_eng.mitalite_ci\Latest.tst
-
-
-
-
-
\ No newline at end of file
diff --git a/build/config/TRexDefs/x86/rs5_release.xml b/build/config/TRexDefs/x86/rs5_release.xml
deleted file mode 100644
index 205a9c09f..000000000
--- a/build/config/TRexDefs/x86/rs5_release.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-
-
-
-
-
- RS_APPS_VALIDATE x86 DesktopVM Test Run
- 139643
- paxeedev
- true
- true
- Desktop_x86.testlist
- rs5_release
-
-
- AlternatePackageRoot
- \\pkges\release\TAEF\validation.taef.provenance\1812.20007-develop\UniversalTestPackages;\\edge-svcs\Release\MITALite\Apps_eng.mitalite_ci\Latest.tst
-
-
- _AlternatePackageRoot
- \\pkges\release\TAEF\validation.taef.provenance\1812.20007-develop\UniversalTestPackages;\\edge-svcs\Release\MITALite\Apps_eng.mitalite_ci\Latest.tst
-
-
-
-
-
\ No newline at end of file
diff --git a/build/config/TRexDefs/x86/rs_apps_validate.xml b/build/config/TRexDefs/x86/rs_apps_validate.xml
deleted file mode 100644
index 130dc8f7a..000000000
--- a/build/config/TRexDefs/x86/rs_apps_validate.xml
+++ /dev/null
@@ -1,46 +0,0 @@
-
-
-
-
-
- RS_APPS_VALIDATE x86 DesktopVM Test Run
- 139643
- paxeedev
- true
- true
- Desktop_x86.testlist
- rs_apps_validate
-
-
- AlternatePackageRoot
- \\pkges\release\TAEF\validation.taef.provenance\1812.20007-develop\UniversalTestPackages;\\edge-svcs\Release\MITALite\Apps_eng.mitalite_ci\Latest.tst
-
-
- _AlternatePackageRoot
- \\pkges\release\TAEF\validation.taef.provenance\1812.20007-develop\UniversalTestPackages;\\edge-svcs\Release\MITALite\Apps_eng.mitalite_ci\Latest.tst
-
-
-
-
-
-
- RS_PRERELEASE x86 WindowsCoreVM Test Run
- 153715
- paxeedev
- true
- true
- WCOS_x86.testlist
- rs_apps_validate
-
-
- AlternatePackageRoot
- \\pkges\release\TAEF\validation.taef.provenance\1812.20007-develop\UniversalTestPackages;\\edge-svcs\Release\MITALite\Apps_eng.mitalite_ci\Latest.tst
-
-
- _AlternatePackageRoot
- \\pkges\release\TAEF\validation.taef.provenance\1812.20007-develop\UniversalTestPackages;\\edge-svcs\Release\MITALite\Apps_eng.mitalite_ci\Latest.tst
-
-
-
-
-
\ No newline at end of file
diff --git a/build/config/TestLists/ARM/Desktop_ARM.testlist b/build/config/TestLists/ARM/Desktop_ARM.testlist
deleted file mode 100644
index cf0e5b66f..000000000
--- a/build/config/TestLists/ARM/Desktop_ARM.testlist
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "$schema": "http://universaltest/schema/testlist-2.json",
- "TestMDs": [
- {
- "FilePath": "Calculator.UITests\\Prebuilt\\Test\\arm\\fre\\Calculator.UITests.testmd",
- "ExecutionProfile": "All"
- },
- {
- "FilePath": "CalculatorUnitTests\\Prebuilt\\Test\\arm\\fre\\CalculatorUnitTests.testmd",
- }
- ]
-}
\ No newline at end of file
diff --git a/build/config/TestLists/ARM/Performance_ARM.testlist b/build/config/TestLists/ARM/Performance_ARM.testlist
deleted file mode 100644
index 2ec2d9337..000000000
--- a/build/config/TestLists/ARM/Performance_ARM.testlist
+++ /dev/null
@@ -1,9 +0,0 @@
-{
- "$schema": "http://universaltest/schema/testlist-2.json",
- "TestMDs": [
- {
- "FilePath": "Calculator.UITests\\Prebuilt\\Test\\arm\\fre\\Calculator.UITests.testmd",
- "ExecutionProfile": "Performance"
- }
- ]
-}
\ No newline at end of file
diff --git a/build/config/TestLists/ARM/WCOS_ARM.testlist b/build/config/TestLists/ARM/WCOS_ARM.testlist
deleted file mode 100644
index cf0e5b66f..000000000
--- a/build/config/TestLists/ARM/WCOS_ARM.testlist
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "$schema": "http://universaltest/schema/testlist-2.json",
- "TestMDs": [
- {
- "FilePath": "Calculator.UITests\\Prebuilt\\Test\\arm\\fre\\Calculator.UITests.testmd",
- "ExecutionProfile": "All"
- },
- {
- "FilePath": "CalculatorUnitTests\\Prebuilt\\Test\\arm\\fre\\CalculatorUnitTests.testmd",
- }
- ]
-}
\ No newline at end of file
diff --git a/build/config/TestLists/ARM64/Desktop_ARM64.testlist b/build/config/TestLists/ARM64/Desktop_ARM64.testlist
deleted file mode 100644
index a2e620caf..000000000
--- a/build/config/TestLists/ARM64/Desktop_ARM64.testlist
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "$schema": "http://universaltest/schema/testlist-2.json",
- "TestMDs": [
- {
- "FilePath": "Calculator.UITests\\Prebuilt\\Test\\arm64\\fre\\Calculator.UITests.testmd",
- "ExecutionProfile": "All"
- },
- {
- "FilePath": "CalculatorUnitTests\\Prebuilt\\Test\\arm64\\fre\\CalculatorUnitTests.testmd",
- }
- ]
-}
\ No newline at end of file
diff --git a/build/config/TestLists/ARM64/WCOS_ARM64.testlist b/build/config/TestLists/ARM64/WCOS_ARM64.testlist
deleted file mode 100644
index a2e620caf..000000000
--- a/build/config/TestLists/ARM64/WCOS_ARM64.testlist
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "$schema": "http://universaltest/schema/testlist-2.json",
- "TestMDs": [
- {
- "FilePath": "Calculator.UITests\\Prebuilt\\Test\\arm64\\fre\\Calculator.UITests.testmd",
- "ExecutionProfile": "All"
- },
- {
- "FilePath": "CalculatorUnitTests\\Prebuilt\\Test\\arm64\\fre\\CalculatorUnitTests.testmd",
- }
- ]
-}
\ No newline at end of file
diff --git a/build/config/rs_apps_utils.json b/build/config/rs_apps_utils.json
deleted file mode 100644
index 9c16d817a..000000000
--- a/build/config/rs_apps_utils.json
+++ /dev/null
@@ -1,28 +0,0 @@
-{
- "Branch": [
- {
- "collection":"microsoft",
- "project":"OS",
- "repo":"os",
- "name":"official/rs_apps_utils",
- "CheckinFiles": [
- {
- "source":"vpack/app/calculator.app.man",
- "path": "/redist/mspartners/ipa/Calculator",
- "type": "File"
- },
- {
- "source":"vpack/app/calculator.app.man",
- "path": "/onecoreuap/redist/mspartners/ipa/Calculator",
- "type": "File"
- }
- ]
- }
- ],
- "Email": [
- {
- "sendTo":"paxeedev",
- "sendOnErrorOnly": "True"
- }
- ]
-}
\ No newline at end of file
diff --git a/build/config/rs_apps_validate.json b/build/config/rs_apps_validate.json
deleted file mode 100644
index 3fbe98b5c..000000000
--- a/build/config/rs_apps_validate.json
+++ /dev/null
@@ -1,28 +0,0 @@
-{
- "Branch": [
- {
- "collection":"microsoft",
- "project":"OS",
- "repo":"os",
- "name":"official/rs_apps_validate",
- "CheckinFiles": [
- {
- "source":"vpack/app/calculator.app.man",
- "path": "/redist/mspartners/ipa/Calculator",
- "type": "File"
- },
- {
- "source":"vpack/app/calculator.app.man",
- "path": "/onecoreuap/redist/mspartners/ipa/Calculator",
- "type": "File"
- }
- ]
- }
- ],
- "Email": [
- {
- "sendTo":"paxeedev",
- "sendOnErrorOnly": "True"
- }
- ]
-}
\ No newline at end of file
diff --git a/build/pipelines/azure-pipelines.release.yaml b/build/pipelines/azure-pipelines.release.yaml
index e81c33964..7817e22be 100644
--- a/build/pipelines/azure-pipelines.release.yaml
+++ b/build/pipelines/azure-pipelines.release.yaml
@@ -9,8 +9,8 @@ pr: none
variables:
versionMajor: 10
- versionMinor: 2001
- versionBuild: $[counter('10.2001.*', 0)]
+ versionMinor: 2003
+ versionBuild: $[counter('10.2003.*', 0)]
versionPatch: 0
name: '$(versionMajor).$(versionMinor).$(versionBuild).$(versionPatch)'
diff --git a/build/pipelines/templates/build-app-internal.yaml b/build/pipelines/templates/build-app-internal.yaml
index fbaafc18c..882af645a 100644
--- a/build/pipelines/templates/build-app-internal.yaml
+++ b/build/pipelines/templates/build-app-internal.yaml
@@ -29,7 +29,7 @@ jobs:
downloadDirectory: $(Build.SourcesDirectory)
vstsFeed: WindowsApps
vstsFeedPackage: calculator-internals
- vstsPackageVersion: 0.0.35
+ vstsPackageVersion: 0.0.40
- template: ./build-single-architecture.yaml
parameters:
diff --git a/build/pipelines/templates/prepare-release-internalonly.yaml b/build/pipelines/templates/prepare-release-internalonly.yaml
index 8f44434d9..f33247d5f 100644
--- a/build/pipelines/templates/prepare-release-internalonly.yaml
+++ b/build/pipelines/templates/prepare-release-internalonly.yaml
@@ -90,8 +90,6 @@ jobs:
pathtoPublish: $(XES_VPACKMANIFESTDIRECTORY)\$(XES_VPACKMANIFESTNAME)
artifactName: vpack\app
- # TODO (macool): create and push internal test packages and test config
-
- task: UniversalPackages@0
displayName: Download internals package
inputs:
@@ -99,7 +97,7 @@ jobs:
downloadDirectory: $(Build.SourcesDirectory)
vstsFeed: WindowsApps
vstsFeedPackage: calculator-internals
- vstsPackageVersion: 0.0.22
+ vstsPackageVersion: 0.0.40
- powershell: |
# Just modify this line to indicate where your en-us PDP file is. Leave the other lines alone.
diff --git a/docs/Roadmap.md b/docs/Roadmap.md
index 0b969c5cd..59a4e5475 100644
--- a/docs/Roadmap.md
+++ b/docs/Roadmap.md
@@ -4,15 +4,12 @@ Windows Calculator is under active development by Microsoft.
## Focus
-In 2019, the Windows Calculator team is focused on:
-* Refining our open source development process on GitHub
-* Iterating upon the existing app design based on the latest [Fluent Design guidelines](https://developer.microsoft.com/en-us/windows/apps/design)
-* Improving testing and diagnostics within the project
-* Investigating new features with a focus on addressing top user feedback, including:
- * Adding graphing mode
- * Adding the ability for users to pin Calculator on top of other windows
- * Providing additional customization options
- * [Your feature idea here] - please review our [new feature development process](https://github.com/Microsoft/calculator/blob/master/docs/NewFeatureProcess.md) to get started!
+In 2020, the Windows Calculator team is focused on:
+* Iterating upon the existing app design based on the latest guidelines for [Fluent Design](https://developer.microsoft.com/en-us/windows/apps/design), [Windows 10X dual-screen devices](https://docs.microsoft.com/en-us/dual-screen/windows/), and [WinUI 3.0](https://github.com/microsoft/microsoft-ui-xaml).
+* Unblocking community contributions by identifying and addressing bottlenecks affecting developers, including migrating portions of the codebase to C# ([#893](https://github.com/microsoft/calculator/issues/893)) and adding a settings page ([#596](https://github.com/microsoft/calculator/issues/596)).
+* Addressing top user pain points, including clearing up confusion around how Standard Calculator behaves ([#138](https://github.com/microsoft/calculator/issues/138)) and fixing hidden characters in copied results ([#504](https://github.com/microsoft/calculator/issues/504)).
+* Investigating unit converter improvements ([#379](https://github.com/microsoft/calculator/issues/379), [#589](https://github.com/microsoft/calculator/issues/589) and [#594](https://github.com/microsoft/calculator/issues/594))
+* [Your feature idea here] - please review our [new feature development process](https://github.com/Microsoft/calculator/blob/master/docs/NewFeatureProcess.md) to get started!
We welcome contributions of all kinds from the community, but especially those that support the efforts above. Please see our [contributing guidelines](https://github.com/Microsoft/calculator/blob/master/CONTRIBUTING.md) for more information on how to get involved.
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
deleted file mode 100644
index ef9032690..000000000
--- a/src/CMakeLists.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-cmake_minimum_required(VERSION 3.13)
-project(calculator CXX)
-set(CMAKE_CXX_STANDARD 17)
-
-if(CMAKE_CXX_COMPILER MATCHES ".*clang")
- # Clang disagress with libstdc++ about constexpr-ness of wstring_view
- # See https://github.com/Microsoft/calculator/pull/321
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++")
-endif()
-
-add_subdirectory(CalcManager)
diff --git a/src/CalcManager/Algebra.cpp b/src/CalcManager/Algebra.cpp
new file mode 100644
index 000000000..a08e6d74b
--- /dev/null
+++ b/src/CalcManager/Algebra.cpp
@@ -0,0 +1,243 @@
+/*
+This class was created by Nico Comendador for the purpose of
+WSU CEG 4110-01. This class will handle and house all of the
+functionality for any algebraic operations for a symbolic
+calculator feature add on to the Microsoft Calculator.
+*/
+#include "Algebra.h"
+#include
+
+using namespace std;
+
+///\return Constructor will instantiate the class variables.
+Algebra::Algebra(string expression)
+{
+ newExpression(expression);
+}
+
+///\return Since there is no garbage collector for C++, we must
+/// include a destructor for the class. Every class with a contructor
+/// must have one.
+Algebra::~Algebra()
+{
+}
+
+///\return This method is used to simplify an expression by
+/// multpliying out the terms to get rid of parenthesis and
+/// exponents.
+string Algebra::simplifyExpression()
+{
+ int result = evaluate(expression);
+ return to_string(result);
+}
+
+///\return This method ensures that the expression has spaces
+/// in between each token. Due to how this class parses and
+/// simplifies things, it is best to first format before
+/// continuing.
+string Algebra::format(string expression)
+{
+ bool space = false;
+ for (int x = 0; x < expression.length(); x++)
+ {
+ if (space)
+ {
+ expression.insert(x, " ");
+ space = false;
+ }
+ else
+ {
+ space = true;
+ }
+ }
+
+ return expression;
+}
+
+///\return This method is responsible for parsing through
+/// and evaluating the expression. Once evaluated, we can
+/// then simplify.
+inline int Algebra::evaluate(string tokens)
+{
+ int i;
+
+ stack values;
+
+ stack ops;
+
+ for (i = 0; i < tokens.length(); i++)
+ {
+ if (tokens[i] == ' ')
+ continue;
+
+ else if (tokens[i] == '(')
+ {
+ ops.push(tokens[i]);
+ }
+
+ else if (isdigit(tokens[i]))
+ {
+ int val = 0;
+
+ while (i < tokens.length() && isdigit(tokens[i]))
+ {
+ val = (val * 10) + (tokens[i] - '0');
+ i++;
+ }
+
+ values.push(val);
+ }
+ else if (tokens[i] == ')')
+ {
+ while (!ops.empty() && ops.top() != '(')
+ {
+ int val2 = values.top();
+ values.pop();
+
+ int val1 = values.top();
+ values.pop();
+
+ char op = ops.top();
+ ops.pop();
+
+ values.push(applyOp(val1, val2, op));
+ }
+
+ if (!ops.empty())
+ ops.pop();
+ }
+ else
+ {
+ while (!ops.empty() && precedence(ops.top()) >= precedence(tokens[i]))
+ {
+ int val2 = values.top();
+ values.pop();
+
+ int val1 = values.top();
+ values.pop();
+
+ char op = ops.top();
+ ops.pop();
+
+ values.push(applyOp(val1, val2, op));
+ }
+
+ ops.push(tokens[i]);
+ }
+ }
+
+ while (!ops.empty())
+ {
+ int val2 = values.top();
+ values.pop();
+
+ int val1 = values.top();
+ values.pop();
+
+ char op = ops.top();
+ ops.pop();
+
+ values.push(applyOp(val1, val2, op));
+ }
+
+ return values.top();
+}
+
+///\return This method applies the operation on the expression
+/// based off of a simple case switch. This is used for
+/// evaluating and so it is needed in order to simplify.
+inline int Algebra::applyOp(int a, int b, char op)
+{
+ switch (op)
+ {
+ case '+':
+ return a + b;
+ case '-':
+ return a - b;
+ case '*':
+ return a * b;
+ case '/':
+ return a / b;
+ }
+}
+
+///\return This method determines the precedence an operator
+/// has. This helps set up the rules (PEMDAS) for evalutaing
+/// and simplifying expressions.
+inline int Algebra::precedence(char op)
+{
+ if (op == '+' || op == '-')
+ return 1;
+ if (op == '*' || op == '/')
+ return 2;
+ return 0;
+}
+
+///\return This method allows the algebra object to create
+/// new expressions without having to instantiate a new
+/// algebra object. The constructor makes use of this.
+void Algebra::newExpression(string expression)
+{
+ clearExpression();
+ this->unformattedExpression = expression;
+ this->expression = format(expression);
+}
+
+///\return This function is created so that a user may solve for a
+/// variable in the symbolic calculator option.
+string Algebra::solveForVariable()
+{
+ int n = unformattedExpression.size(), sign = 1, coeff = 0;
+ int total = 0, i = 0;
+
+ for (int j = 0; j < n; j++)
+ {
+ if (unformattedExpression[j] == '+' || unformattedExpression[j] == '-')
+ {
+ if (j > i)
+ total += sign * stoi(unformattedExpression.substr(i, j - i));
+ i = j;
+ }
+
+ else if (unformattedExpression[j] == 'x')
+ {
+ if ((i == j) || unformattedExpression[j - 1] == '+')
+ coeff += sign;
+ else if (unformattedExpression[j - 1] == '-')
+ coeff -= sign;
+ else
+ coeff += sign * stoi(unformattedExpression.substr(i, j - i));
+ i = j + 1;
+ }
+ }
+
+ if (i < n)
+ total += sign * stoi(unformattedExpression.substr(i));
+
+ if (coeff == 0 && total == 0)
+ return "Infinite solutions";
+
+ if (coeff == 0 && total)
+ return "No solution";
+
+ int ans = -total / coeff;
+ return "x = " + to_string(ans);
+}
+
+///\return A getter function is useful for a parent class to get
+/// more information on what expression is being handled. It will
+/// reutrn the raw unformatted version to avoid any complications.
+string Algebra::getExpression()
+{
+ return unformattedExpression;
+}
+
+///\return This function is added for a manager class or a parent
+/// class to empty the variables. It's purpose is to ensure that
+/// the variables are cleared of everything before having something
+/// set into them.
+void Algebra::clearExpression()
+{
+ this->unformattedExpression = "";
+ this->expression = "";
+}
diff --git a/src/CalcManager/Algebra.h b/src/CalcManager/Algebra.h
new file mode 100644
index 000000000..65c23a0b6
--- /dev/null
+++ b/src/CalcManager/Algebra.h
@@ -0,0 +1,44 @@
+/*
+This class was created by Nico Comendador for the purpose of
+WSU CEG 4110-01. This class will handle and house all of the
+functionality for any algebraic operations for a symbolic
+calculator feature add on to the Microsoft Calculator.
+*/
+
+#pragma once
+
+#include
+#include
+
+#ifndef _Algebra_
+#define _Algebra_
+
+using namespace std;
+
+class Algebra
+{
+private:
+ ///\return Each Algebra object will hold a
+ /// a string continaing the information of
+ /// the input given from a parent class.
+ string expression;
+ string unformattedExpression;
+
+public:
+ ///\return The following lets the compiler
+ /// know that the following methods will be
+ /// instantiated.
+ inline Algebra(string expression);
+ inline virtual ~Algebra();
+ inline string simplifyExpression();
+ inline int evaluate(string tokens);
+ inline int applyOp(int a, int b, char op);
+ inline int precedence(char op);
+ inline string format(string expression);
+ inline void newExpression(string expression);
+ inline string solveForVariable();
+ inline string getExpression();
+ inline void clearExpression();
+};
+
+#endif
diff --git a/src/CalcManager/CEngine/CMakeLists.txt b/src/CalcManager/CEngine/CMakeLists.txt
deleted file mode 100644
index ba4348ffd..000000000
--- a/src/CalcManager/CEngine/CMakeLists.txt
+++ /dev/null
@@ -1,14 +0,0 @@
-target_sources(CalcManager PRIVATE
- calc.cpp
- CalcInput.cpp
- CalcUtils.cpp
- History.cpp
- Number.cpp
- Rational.cpp
- RationalMath.cpp
- scicomm.cpp
- scidisp.cpp
- scifunc.cpp
- scioper.cpp
- sciset.cpp
-)
diff --git a/src/CalcManager/CEngine/History.cpp b/src/CalcManager/CEngine/History.cpp
index d3a32ebb9..ea73e18ca 100644
--- a/src/CalcManager/CEngine/History.cpp
+++ b/src/CalcManager/CEngine/History.cpp
@@ -210,7 +210,7 @@ bool CHistoryCollector::FOpndAddedToHistory()
// This is does the postfix to prefix translation of the input and adds the text to the history. Eg. doing 2 + 4 (sqrt),
// this routine will ensure the last sqrt call unary operator, actually goes back in history and wraps 4 in sqrt(4)
//
-void CHistoryCollector::AddUnaryOpToHistory(int nOpCode, bool fInv, ANGLE_TYPE angletype)
+void CHistoryCollector::AddUnaryOpToHistory(int nOpCode, bool fInv, AngleType angletype)
{
int iCommandEnd;
// When successfully applying a unary op, there should be an opnd already
@@ -230,15 +230,15 @@ void CHistoryCollector::AddUnaryOpToHistory(int nOpCode, bool fInv, ANGLE_TYPE a
else
{
CalculationManager::Command angleOpCode;
- if (angletype == ANGLE_DEG)
+ if (angletype == AngleType::Degrees)
{
angleOpCode = CalculationManager::Command::CommandDEG;
}
- else if (angletype == ANGLE_RAD)
+ else if (angletype == AngleType::Radians)
{
angleOpCode = CalculationManager::Command::CommandRAD;
}
- else // (angletype == ANGLE_GRAD)
+ else // (angletype == AngleType::Gradians)
{
angleOpCode = CalculationManager::Command::CommandGRAD;
}
diff --git a/src/CalcManager/CEngine/Rational.cpp b/src/CalcManager/CEngine/Rational.cpp
index 8eb4a91a2..c703f61dd 100644
--- a/src/CalcManager/CEngine/Rational.cpp
+++ b/src/CalcManager/CEngine/Rational.cpp
@@ -460,7 +460,7 @@ namespace CalcEngine
return !(lhs < rhs);
}
- wstring Rational::ToString(uint32_t radix, NUMOBJ_FMT fmt, int32_t precision) const
+ wstring Rational::ToString(uint32_t radix, NumberFormat fmt, int32_t precision) const
{
PRAT rat = this->ToPRAT();
wstring result{};
diff --git a/src/CalcManager/CEngine/RationalMath.cpp b/src/CalcManager/CEngine/RationalMath.cpp
index 4b1a4b8af..00b628ab7 100644
--- a/src/CalcManager/CEngine/RationalMath.cpp
+++ b/src/CalcManager/CEngine/RationalMath.cpp
@@ -147,7 +147,7 @@ Rational RationalMath::Abs(Rational const& rat)
return Rational{ Number{ 1, rat.P().Exp(), rat.P().Mantissa() }, Number{ 1, rat.Q().Exp(), rat.Q().Mantissa() } };
}
-Rational RationalMath::Sin(Rational const& rat, ANGLE_TYPE angletype)
+Rational RationalMath::Sin(Rational const& rat, AngleType angletype)
{
PRAT prat = rat.ToPRAT();
@@ -167,7 +167,7 @@ Rational RationalMath::Sin(Rational const& rat, ANGLE_TYPE angletype)
return result;
}
-Rational RationalMath::Cos(Rational const& rat, ANGLE_TYPE angletype)
+Rational RationalMath::Cos(Rational const& rat, AngleType angletype)
{
PRAT prat = rat.ToPRAT();
@@ -187,7 +187,7 @@ Rational RationalMath::Cos(Rational const& rat, ANGLE_TYPE angletype)
return result;
}
-Rational RationalMath::Tan(Rational const& rat, ANGLE_TYPE angletype)
+Rational RationalMath::Tan(Rational const& rat, AngleType angletype)
{
PRAT prat = rat.ToPRAT();
@@ -207,7 +207,7 @@ Rational RationalMath::Tan(Rational const& rat, ANGLE_TYPE angletype)
return result;
}
-Rational RationalMath::ASin(Rational const& rat, ANGLE_TYPE angletype)
+Rational RationalMath::ASin(Rational const& rat, AngleType angletype)
{
PRAT prat = rat.ToPRAT();
@@ -227,7 +227,7 @@ Rational RationalMath::ASin(Rational const& rat, ANGLE_TYPE angletype)
return result;
}
-Rational RationalMath::ACos(Rational const& rat, ANGLE_TYPE angletype)
+Rational RationalMath::ACos(Rational const& rat, AngleType angletype)
{
PRAT prat = rat.ToPRAT();
@@ -247,7 +247,7 @@ Rational RationalMath::ACos(Rational const& rat, ANGLE_TYPE angletype)
return result;
}
-Rational RationalMath::ATan(Rational const& rat, ANGLE_TYPE angletype)
+Rational RationalMath::ATan(Rational const& rat, AngleType angletype)
{
PRAT prat = rat.ToPRAT();
diff --git a/src/CalcManager/CEngine/calc.cpp b/src/CalcManager/CEngine/calc.cpp
index c57753799..dd70fb634 100644
--- a/src/CalcManager/CEngine/calc.cpp
+++ b/src/CalcManager/CEngine/calc.cpp
@@ -73,7 +73,7 @@ CCalcEngine::CCalcEngine(
, m_bRecord(false)
, m_bSetCalcState(false)
, m_input(DEFAULT_DEC_SEPARATOR)
- , m_nFE(FMT_FLOAT)
+ , m_nFE(NumberFormat::Float)
, m_memoryValue{ make_unique() }
, m_holdVal{}
, m_currentVal{}
@@ -94,8 +94,8 @@ CCalcEngine::CCalcEngine(
, m_nPrecOp()
, m_precedenceOpCount(0)
, m_nLastCom(0)
- , m_angletype(ANGLE_DEG)
- , m_numwidth(QWORD_WIDTH)
+ , m_angletype(AngleType::Degrees)
+ , m_numwidth(NUM_WIDTH::QWORD_WIDTH)
, m_HistoryCollector(pCalcDisplay, pHistoryDisplay, DEFAULT_DEC_SEPARATOR)
, m_groupSeparator(DEFAULT_GRP_SEPARATOR)
{
@@ -105,7 +105,7 @@ CCalcEngine::CCalcEngine(
m_maxTrigonometricNum = RationalMath::Pow(10, 100);
- SetRadixTypeAndNumWidth(DEC_RADIX, m_numwidth);
+ SetRadixTypeAndNumWidth(RadixType::Decimal, m_numwidth);
SettingsChanged();
DisplayNum();
}
@@ -128,10 +128,20 @@ void CCalcEngine::InitChopNumbers()
auto maxVal = m_chopNumbers[i] / 2;
maxVal = RationalMath::Integer(maxVal);
- m_maxDecimalValueStrings[i] = maxVal.ToString(10, FMT_FLOAT, m_precision);
+ m_maxDecimalValueStrings[i] = maxVal.ToString(10, NumberFormat::Float, m_precision);
}
}
+CalcEngine::Rational CCalcEngine::GetChopNumber() const
+{
+ return m_chopNumbers[static_cast(m_numwidth)];
+}
+
+std::wstring CCalcEngine::GetMaxDecimalValueString() const
+{
+ return m_maxDecimalValueStrings[static_cast(m_numwidth)];
+}
+
// Gets the number in memory for UI to keep it persisted and set it again to a different instance
// of CCalcEngine. Otherwise it will get destructed with the CalcEngine
unique_ptr CCalcEngine::PersistedMemObject()
diff --git a/src/CalcManager/CEngine/scicomm.cpp b/src/CalcManager/CEngine/scicomm.cpp
index f7509ab3b..04bdda740 100644
--- a/src/CalcManager/CEngine/scicomm.cpp
+++ b/src/CalcManager/CEngine/scicomm.cpp
@@ -35,19 +35,16 @@ namespace
IDC_ADD,2, IDC_SUB,2,
IDC_RSHF,3, IDC_LSHF,3, IDC_RSHFL,3,
IDC_MOD,3, IDC_DIV,3, IDC_MUL,3,
- IDC_PWR,4, IDC_ROOT,4, IDC_LOGBASEX,4 };
- unsigned int iPrec;
+ IDC_PWR,4, IDC_ROOT,4, IDC_LOGBASEY,4 };
- iPrec = 0;
- while ((iPrec < size(rgbPrec)) && (nopCode != rgbPrec[iPrec]))
+ for (unsigned int iPrec = 0; iPrec < size(rgbPrec); iPrec += 2)
{
- iPrec += 2;
- }
- if (iPrec >= size(rgbPrec))
- {
- iPrec = 0;
+ if (nopCode == rgbPrec[iPrec])
+ {
+ return rgbPrec[iPrec + 1];
+ }
}
- return rgbPrec[iPrec + 1];
+ return 0;
}
}
@@ -104,8 +101,6 @@ void CCalcEngine::ProcessCommand(OpCode wParam)
void CCalcEngine::ProcessCommandWorker(OpCode wParam)
{
- int nx, ni;
-
// Save the last command. Some commands are not saved in this manor, these
// commands are:
// Inv, Deg, Rad, Grad, Stat, FE, MClear, Back, and Exp. The excluded
@@ -163,14 +158,11 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam)
DisplayNum(); // Causes 3.000 to shrink to 3. on first op.
}
}
- else
+ else if (IsDigitOpCode(wParam) || wParam == IDC_PNT)
{
- if (IsDigitOpCode(wParam) || wParam == IDC_PNT)
- {
- m_bRecord = true;
- m_input.Clear();
- CheckAndAddLastBinOpToHistory();
- }
+ m_bRecord = true;
+ m_input.Clear();
+ CheckAndAddLastBinOpToHistory();
}
// Interpret digit keys.
@@ -185,7 +177,7 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam)
return;
}
- if (!m_input.TryAddDigit(iValue, m_radix, m_fIntegerMode, m_maxDecimalValueStrings[m_numwidth], m_dwWordBitWidth, m_cIntDigitsSav))
+ if (!m_input.TryAddDigit(iValue, m_radix, m_fIntegerMode, GetMaxDecimalValueString(), m_dwWordBitWidth, m_cIntDigitsSav))
{
HandleErrorCommand(wParam);
HandleMaxDigitsReached();
@@ -203,7 +195,6 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam)
// Change the operation if last input was operation.
if (IsBinOpCode(m_nLastCom))
{
- int nPrev;
bool fPrecInvToHigher = false; // Is Precedence Inversion from lower to higher precedence happening ??
m_nOpCode = (int)wParam;
@@ -214,9 +205,9 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam)
// Here * is m_nPrevOpCode, m_currentVal is 2 (by 1*2), m_nLastCom is +, m_nOpCode is ^
if (m_fPrecedence && 0 != m_nPrevOpCode)
{
- nPrev = NPrecedenceOfOp(m_nPrevOpCode);
- nx = NPrecedenceOfOp(m_nLastCom);
- ni = NPrecedenceOfOp(m_nOpCode);
+ int nPrev = NPrecedenceOfOp(m_nPrevOpCode);
+ int nx = NPrecedenceOfOp(m_nLastCom);
+ int ni = NPrecedenceOfOp(m_nOpCode);
if (nx <= nPrev && ni > nPrev) // condition for Precedence Inversion
{
fPrecInvToHigher = true;
@@ -243,8 +234,8 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam)
{
DoPrecedenceCheckAgain:
- nx = NPrecedenceOfOp((int)wParam);
- ni = NPrecedenceOfOp(m_nOpCode);
+ int nx = NPrecedenceOfOp((int)wParam);
+ int ni = NPrecedenceOfOp(m_nOpCode);
if ((nx > ni) && m_fPrecedence)
{
@@ -492,8 +483,8 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam)
m_lastVal = m_precedenceVals[m_precedenceOpCount];
// Precedence Inversion check
- ni = NPrecedenceOfOp(m_nPrevOpCode);
- nx = NPrecedenceOfOp(m_nOpCode);
+ int ni = NPrecedenceOfOp(m_nPrevOpCode);
+ int nx = NPrecedenceOfOp(m_nOpCode);
if (ni <= nx)
{
m_HistoryCollector.EnclosePrecInversionBrackets();
@@ -518,20 +509,15 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam)
case IDC_OPENP:
case IDC_CLOSEP:
- nx = 0;
- if (wParam == IDC_OPENP)
- {
- nx = 1;
- }
// -IF- the Paren holding array is full and we try to add a paren
// -OR- the paren holding array is empty and we try to remove a
// paren
// -OR- the precedence holding array is full
- if ((m_openParenCount >= MAXPRECDEPTH && nx) || (!m_openParenCount && !nx)
+ if ((m_openParenCount >= MAXPRECDEPTH && (wParam == IDC_OPENP)) || (!m_openParenCount && (wParam != IDC_OPENP))
|| ((m_precedenceOpCount >= MAXPRECDEPTH && m_nPrecOp[m_precedenceOpCount - 1] != 0)))
{
- if (!m_openParenCount && !nx)
+ if (!m_openParenCount && (wParam != IDC_OPENP))
{
m_pCalcDisplay->OnNoRightParenAdded();
}
@@ -540,7 +526,7 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam)
break;
}
- if (nx)
+ if (wParam == IDC_OPENP)
{
CheckAndAddLastBinOpToHistory();
m_HistoryCollector.AddOpenBraceToHistory();
@@ -588,8 +574,8 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam)
for (m_nOpCode = m_nPrecOp[--m_precedenceOpCount]; m_nOpCode; m_nOpCode = m_nPrecOp[--m_precedenceOpCount])
{
// Precedence Inversion check
- ni = NPrecedenceOfOp(m_nPrevOpCode);
- nx = NPrecedenceOfOp(m_nOpCode);
+ int ni = NPrecedenceOfOp(m_nPrevOpCode);
+ int nx = NPrecedenceOfOp(m_nOpCode);
if (ni <= nx)
{
m_HistoryCollector.EnclosePrecInversionBrackets();
@@ -633,7 +619,7 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam)
case IDM_OCT:
case IDM_BIN:
{
- SetRadixTypeAndNumWidth((RADIX_TYPE)(wParam - IDM_HEX), (NUM_WIDTH)-1);
+ SetRadixTypeAndNumWidth((RadixType)(wParam - IDM_HEX), (NUM_WIDTH)-1);
m_HistoryCollector.UpdateHistoryExpression(m_radix, m_precision);
break;
}
@@ -649,20 +635,20 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam)
}
// Compat. mode BaseX: Qword, Dword, Word, Byte
- SetRadixTypeAndNumWidth((RADIX_TYPE)-1, (NUM_WIDTH)(wParam - IDM_QWORD));
+ SetRadixTypeAndNumWidth((RadixType)-1, (NUM_WIDTH)(wParam - IDM_QWORD));
break;
case IDM_DEG:
case IDM_RAD:
case IDM_GRAD:
- m_angletype = static_cast(wParam - IDM_DEG);
+ m_angletype = static_cast(wParam - IDM_DEG);
break;
case IDC_SIGN:
{
if (m_bRecord)
{
- if (m_input.TryToggleSign(m_fIntegerMode, m_maxDecimalValueStrings[m_numwidth]))
+ if (m_input.TryToggleSign(m_fIntegerMode, GetMaxDecimalValueString()))
{
DisplayNum();
}
@@ -780,7 +766,7 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam)
break;
case IDC_FE:
// Toggle exponential notation display.
- m_nFE = NUMOBJ_FMT(!(int)m_nFE);
+ m_nFE = NumberFormat(!(int)m_nFE);
DisplayNum();
break;
@@ -952,7 +938,7 @@ static const std::unordered_map operatorStringTable =
{ IDC_SECH, { SIDS_SECH, SIDS_ASECH } },
{ IDC_CSCH, { SIDS_CSCH, SIDS_ACSCH } },
{ IDC_COTH, { SIDS_COTH, SIDS_ACOTH } },
-
+
{ IDC_LN, { L"", SIDS_POWE } },
{ IDC_SQR, { SIDS_SQR } },
{ IDC_CUB, { SIDS_CUBE } },
@@ -962,7 +948,7 @@ static const std::unordered_map operatorStringTable =
{ IDC_SIGN, { SIDS_NEGATE } },
{ IDC_DEGREES, { SIDS_DEGREES } },
{ IDC_POW2, { SIDS_TWOPOWX } },
- { IDC_LOGBASEX, { SIDS_LOGBASEX } },
+ { IDC_LOGBASEY, { SIDS_LOGBASEY } },
{ IDC_ABS, { SIDS_ABS } },
{ IDC_CEIL, { SIDS_CEIL } },
{ IDC_FLOOR, { SIDS_FLOOR } },
@@ -971,11 +957,11 @@ static const std::unordered_map operatorStringTable =
{ IDC_RSHFL, { SIDS_RSH } },
{ IDC_RORC, { SIDS_ROR } },
{ IDC_ROLC, { SIDS_ROL } },
- { IDC_CUBEROOT, {SIDS_CUBEROOT} },
- { IDC_MOD, {SIDS_MOD, L"", L"", L"", L"", L"", SIDS_PROGRAMMER_MOD} },
+ { IDC_CUBEROOT, { SIDS_CUBEROOT } },
+ { IDC_MOD, { SIDS_MOD, L"", L"", L"", L"", L"", SIDS_PROGRAMMER_MOD } },
};
-wstring_view CCalcEngine::OpCodeToUnaryString(int nOpCode, bool fInv, ANGLE_TYPE angletype)
+wstring_view CCalcEngine::OpCodeToUnaryString(int nOpCode, bool fInv, AngleType angletype)
{
// Try to lookup the ID in the UFNE table
wstring ids = L"";
@@ -983,7 +969,7 @@ wstring_view CCalcEngine::OpCodeToUnaryString(int nOpCode, bool fInv, ANGLE_TYPE
if (auto pair = operatorStringTable.find(nOpCode); pair != operatorStringTable.end())
{
const FunctionNameElement& element = pair->second;
- if (!element.hasAngleStrings || ANGLE_DEG == angletype)
+ if (!element.hasAngleStrings || AngleType::Degrees == angletype)
{
if (fInv)
{
@@ -995,7 +981,7 @@ wstring_view CCalcEngine::OpCodeToUnaryString(int nOpCode, bool fInv, ANGLE_TYPE
ids = element.degreeString;
}
}
- else if (ANGLE_RAD == angletype)
+ else if (AngleType::Radians == angletype)
{
if (fInv)
{
@@ -1006,7 +992,7 @@ wstring_view CCalcEngine::OpCodeToUnaryString(int nOpCode, bool fInv, ANGLE_TYPE
ids = element.radString;
}
}
- else if (ANGLE_GRAD == angletype)
+ else if (AngleType::Gradians == angletype)
{
if (fInv)
{
@@ -1108,7 +1094,7 @@ wstring CCalcEngine::GetStringForDisplay(Rational const& rat, uint32_t radix)
if ((radix == 10) && fMsb)
{
// If high bit is set, then get the decimal number in negative 2's complement form.
- tempRat = -((tempRat ^ m_chopNumbers[m_numwidth]) + 1);
+ tempRat = -((tempRat ^ GetChopNumber()) + 1);
}
result = tempRat.ToString(radix, m_nFE, m_precision);
diff --git a/src/CalcManager/CEngine/scidisp.cpp b/src/CalcManager/CEngine/scidisp.cpp
index 632969fda..0074c77ab 100644
--- a/src/CalcManager/CEngine/scidisp.cpp
+++ b/src/CalcManager/CEngine/scidisp.cpp
@@ -67,10 +67,10 @@ CalcEngine::Rational CCalcEngine::TruncateNumForIntMath(CalcEngine::Rational con
{
// if negative make positive by doing a twos complement
result = -(result)-1;
- result ^= m_chopNumbers[m_numwidth];
+ result ^= GetChopNumber();
}
- result &= m_chopNumbers[m_numwidth];
+ result &= GetChopNumber();
return result;
}
@@ -85,7 +85,7 @@ void CCalcEngine::DisplayNum(void)
// called.
//
if (m_bRecord || gldPrevious.value != m_currentVal || gldPrevious.precision != m_precision || gldPrevious.radix != m_radix || gldPrevious.nFE != (int)m_nFE
- || gldPrevious.bUseSep != true || gldPrevious.numwidth != m_numwidth || gldPrevious.fIntMath != m_fIntegerMode || gldPrevious.bRecord != m_bRecord)
+ || !gldPrevious.bUseSep || gldPrevious.numwidth != m_numwidth || gldPrevious.fIntMath != m_fIntegerMode || gldPrevious.bRecord != m_bRecord)
{
gldPrevious.precision = m_precision;
gldPrevious.radix = m_radix;
diff --git a/src/CalcManager/CEngine/scifunc.cpp b/src/CalcManager/CEngine/scifunc.cpp
index 15ef164b3..b767968a2 100644
--- a/src/CalcManager/CEngine/scifunc.cpp
+++ b/src/CalcManager/CEngine/scifunc.cpp
@@ -42,7 +42,7 @@ CalcEngine::Rational CCalcEngine::SciCalcFunctions(CalcEngine::Rational const& r
}
else
{
- result = rat ^ m_chopNumbers[m_numwidth];
+ result = rat ^ GetChopNumber();
}
break;
diff --git a/src/CalcManager/CEngine/scioper.cpp b/src/CalcManager/CEngine/scioper.cpp
index 6ea3956b9..fdb9a7c03 100644
--- a/src/CalcManager/CEngine/scioper.cpp
+++ b/src/CalcManager/CEngine/scioper.cpp
@@ -29,11 +29,11 @@ CalcEngine::Rational CCalcEngine::DoOperation(int operation, CalcEngine::Rationa
break;
case IDC_NAND:
- result = (result & rhs) ^ m_chopNumbers[m_numwidth];
+ result = (result & rhs) ^ GetChopNumber();
break;
case IDC_NOR:
- result = (result | rhs) ^ m_chopNumbers[m_numwidth];
+ result = (result | rhs) ^ GetChopNumber();
break;
case IDC_RSHF:
@@ -53,10 +53,10 @@ CalcEngine::Rational CCalcEngine::DoOperation(int operation, CalcEngine::Rationa
{
result = Integer(result);
- auto tempRat = m_chopNumbers[m_numwidth] >> holdVal;
+ auto tempRat = GetChopNumber() >> holdVal;
tempRat = Integer(tempRat);
- result |= tempRat ^ m_chopNumbers[m_numwidth];
+ result |= tempRat ^ GetChopNumber();
}
break;
}
@@ -105,7 +105,7 @@ CalcEngine::Rational CCalcEngine::DoOperation(int operation, CalcEngine::Rationa
if (fMsb)
{
- result = (rhs ^ m_chopNumbers[m_numwidth]) + 1;
+ result = (rhs ^ GetChopNumber()) + 1;
iNumeratorSign = -1;
}
@@ -115,7 +115,7 @@ CalcEngine::Rational CCalcEngine::DoOperation(int operation, CalcEngine::Rationa
if (fMsb)
{
- temp = (temp ^ m_chopNumbers[m_numwidth]) + 1;
+ temp = (temp ^ GetChopNumber()) + 1;
iDenominatorSign = -1;
}
@@ -158,8 +158,8 @@ CalcEngine::Rational CCalcEngine::DoOperation(int operation, CalcEngine::Rationa
result = Root(rhs, result);
break;
- case IDC_LOGBASEX:
- result = (Log(result) / Log(rhs));
+ case IDC_LOGBASEY:
+ result = (Log(rhs) / Log(result));
break;
}
}
diff --git a/src/CalcManager/CEngine/sciset.cpp b/src/CalcManager/CEngine/sciset.cpp
index 676ab0ebe..cb1435593 100644
--- a/src/CalcManager/CEngine/sciset.cpp
+++ b/src/CalcManager/CEngine/sciset.cpp
@@ -9,7 +9,7 @@ using namespace std;
// To be called when either the radix or num width changes. You can use -1 in either of these values to mean
// dont change that.
-void CCalcEngine::SetRadixTypeAndNumWidth(RADIX_TYPE radixtype, NUM_WIDTH numwidth)
+void CCalcEngine::SetRadixTypeAndNumWidth(RadixType radixtype, NUM_WIDTH numwidth)
{
// When in integer mode, the number is represented in 2's complement form. When a bit width is changing, we can
// change the number representation back to sign, abs num form in ratpak. Soon when display sees this, it will
@@ -24,19 +24,19 @@ void CCalcEngine::SetRadixTypeAndNumWidth(RADIX_TYPE radixtype, NUM_WIDTH numwid
if (fMsb)
{
// If high bit is set, then get the decimal number in -ve 2'scompl form.
- auto tempResult = m_currentVal ^ m_chopNumbers[m_numwidth];
+ auto tempResult = m_currentVal ^ GetChopNumber();
m_currentVal = -(tempResult + 1);
}
}
- if (radixtype >= HEX_RADIX && radixtype <= BIN_RADIX)
+ if (radixtype >= RadixType::Hex && radixtype <= RadixType::Binary)
{
m_radix = NRadixFromRadixType(radixtype);
// radixtype is not even saved
}
- if (numwidth >= QWORD_WIDTH && numwidth <= BYTE_WIDTH)
+ if (numwidth >= NUM_WIDTH::QWORD_WIDTH && numwidth <= NUM_WIDTH::BYTE_WIDTH)
{
m_numwidth = numwidth;
m_dwWordBitWidth = DwWordBitWidthFromeNumWidth(numwidth);
@@ -50,29 +50,36 @@ void CCalcEngine::SetRadixTypeAndNumWidth(RADIX_TYPE radixtype, NUM_WIDTH numwid
DisplayNum();
}
-int32_t CCalcEngine::DwWordBitWidthFromeNumWidth(NUM_WIDTH /*numwidth*/)
+int32_t CCalcEngine::DwWordBitWidthFromeNumWidth(NUM_WIDTH numwidth)
{
- static constexpr int nBitMax[] = { 64, 32, 16, 8 };
- int32_t wmax = nBitMax[0];
-
- if (m_numwidth >= 0 && (size_t)m_numwidth < size(nBitMax))
+ switch (numwidth)
{
- wmax = nBitMax[m_numwidth];
+ case NUM_WIDTH::DWORD_WIDTH:
+ return 32;
+ case NUM_WIDTH::WORD_WIDTH:
+ return 16;
+ case NUM_WIDTH::BYTE_WIDTH:
+ return 8;
+ case NUM_WIDTH::QWORD_WIDTH:
+ default:
+ return 64;
}
- return wmax;
}
-uint32_t CCalcEngine::NRadixFromRadixType(RADIX_TYPE radixtype)
+uint32_t CCalcEngine::NRadixFromRadixType(RadixType radixtype)
{
- static constexpr uint32_t rgnRadish[4] = { 16, 10, 8, 2 }; /* Number bases in the same order as radixtype */
- uint32_t radix = 10;
-
- // convert special bases into symbolic values
- if (radixtype >= 0 && (size_t)radixtype < size(rgnRadish))
+ switch (radixtype)
{
- radix = rgnRadish[radixtype];
+ case RadixType::Hex:
+ return 16;
+ case RadixType::Octal:
+ return 8;
+ case RadixType::Binary:
+ return 2;
+ case RadixType::Decimal:
+ default:
+ return 10;
}
- return radix;
}
// Toggles a given bit into the number representation. returns true if it changed it actually.
@@ -141,7 +148,7 @@ void CCalcEngine::UpdateMaxIntDigits()
// if in integer mode you still have to honor the max digits you can enter based on bit width
if (m_fIntegerMode)
{
- m_cIntDigitsSav = static_cast(m_maxDecimalValueStrings[m_numwidth].length()) - 1;
+ m_cIntDigitsSav = static_cast(GetMaxDecimalValueString().length()) - 1;
// This is the max digits you can enter a decimal in fixed width mode aka integer mode -1. The last digit
// has to be checked separately
}
diff --git a/src/CalcManager/CMakeLists.txt b/src/CalcManager/CMakeLists.txt
deleted file mode 100644
index c02bc78d2..000000000
--- a/src/CalcManager/CMakeLists.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-add_library(CalcManager
- CalculatorHistory.cpp
- CalculatorManager.cpp
- ExpressionCommand.cpp
- pch.cpp
- UnitConverter.cpp
-)
-target_include_directories(CalcManager PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
-
-add_subdirectory(Ratpack)
-add_subdirectory(CEngine)
diff --git a/src/CalcManager/CalculatorHistory.cpp b/src/CalcManager/CalculatorHistory.cpp
index 6c9a002b1..384db076e 100644
--- a/src/CalcManager/CalculatorHistory.cpp
+++ b/src/CalcManager/CalculatorHistory.cpp
@@ -41,7 +41,6 @@ unsigned int CalculatorHistory::AddToHistory(
_In_ shared_ptr>> const& commands,
wstring_view result)
{
- unsigned int addedIndex;
shared_ptr spHistoryItem = make_shared();
spHistoryItem->historyItemVector.spTokens = tokens;
@@ -53,9 +52,7 @@ unsigned int CalculatorHistory::AddToHistory(
// in the history doesn't get broken for RTL languages
spHistoryItem->historyItemVector.expression = L'\u202d' + generatedExpression + L'\u202c';
spHistoryItem->historyItemVector.result = wstring(result);
- addedIndex = AddItem(spHistoryItem);
-
- return addedIndex;
+ return AddItem(spHistoryItem);
}
unsigned int CalculatorHistory::AddItem(_In_ shared_ptr const& spHistoryItem)
@@ -66,19 +63,18 @@ unsigned int CalculatorHistory::AddItem(_In_ shared_ptr const& spHi
}
m_historyItems.push_back(spHistoryItem);
- unsigned int lastIndex = static_cast(m_historyItems.size() - 1);
- return lastIndex;
+ return static_cast(m_historyItems.size() - 1);
}
bool CalculatorHistory::RemoveItem(unsigned int uIdx)
{
- if (uIdx > m_historyItems.size() - 1)
+ if (uIdx < m_historyItems.size())
{
- return false;
+ m_historyItems.erase(m_historyItems.begin() + uIdx);
+ return true;
}
- m_historyItems.erase(m_historyItems.begin() + uIdx);
- return true;
+ return false;
}
vector> const& CalculatorHistory::GetHistory()
diff --git a/src/CalcManager/CalculatorHistory.h b/src/CalcManager/CalculatorHistory.h
index e8c874a00..2c8499064 100644
--- a/src/CalcManager/CalculatorHistory.h
+++ b/src/CalcManager/CalculatorHistory.h
@@ -7,12 +7,6 @@
namespace CalculationManager
{
- enum CALCULATOR_MODE
- {
- CM_STD = 0,
- CM_SCI,
- };
-
struct HISTORYITEMVECTOR
{
std::shared_ptr>> spTokens;
diff --git a/src/CalcManager/CalculatorManager.cpp b/src/CalcManager/CalculatorManager.cpp
index 8d6f1e51e..7b3854d03 100644
--- a/src/CalcManager/CalculatorManager.cpp
+++ b/src/CalcManager/CalculatorManager.cpp
@@ -33,6 +33,7 @@ namespace CalculationManager
, m_savedDegreeMode(Command::CommandDEG)
, m_pStdHistory(new CalculatorHistory(MAX_HISTORY_ITEMS))
, m_pSciHistory(new CalculatorHistory(MAX_HISTORY_ITEMS))
+ , m_pHistory(nullptr)
{
CCalcEngine::InitialOneTimeOnlySetup(*m_resourceProvider);
}
@@ -551,9 +552,9 @@ namespace CalculationManager
return m_pHistory->GetHistory();
}
- vector> const& CalculatorManager::GetHistoryItems(_In_ CALCULATOR_MODE mode)
+ vector> const& CalculatorManager::GetHistoryItems(_In_ CalculatorMode mode)
{
- return (mode == CM_STD) ? m_pStdHistory->GetHistory() : m_pSciHistory->GetHistory();
+ return (mode == CalculatorMode::Standard) ? m_pStdHistory->GetHistory() : m_pSciHistory->GetHistory();
}
shared_ptr const& CalculatorManager::GetHistoryItem(_In_ unsigned int uIdx)
@@ -576,20 +577,20 @@ namespace CalculationManager
m_pHistory->ClearHistory();
}
- void CalculatorManager::SetRadix(RADIX_TYPE iRadixType)
+ void CalculatorManager::SetRadix(RadixType iRadixType)
{
switch (iRadixType)
{
- case RADIX_TYPE::HEX_RADIX:
+ case RadixType::Hex:
m_currentCalculatorEngine->ProcessCommand(IDC_HEX);
break;
- case RADIX_TYPE::DEC_RADIX:
+ case RadixType::Decimal:
m_currentCalculatorEngine->ProcessCommand(IDC_DEC);
break;
- case RADIX_TYPE::OCT_RADIX:
+ case RadixType::Octal:
m_currentCalculatorEngine->ProcessCommand(IDC_OCT);
break;
- case RADIX_TYPE::BIN_RADIX:
+ case RadixType::Binary:
m_currentCalculatorEngine->ProcessCommand(IDC_BIN);
break;
default:
@@ -623,16 +624,16 @@ namespace CalculationManager
return m_currentDegreeMode;
}
- void CalculatorManager::SetHistory(_In_ CALCULATOR_MODE eMode, _In_ vector> const& history)
+ void CalculatorManager::SetHistory(_In_ CalculatorMode eMode, _In_ vector> const& history)
{
CalculatorHistory* pHistory = nullptr;
switch (eMode)
{
- case CM_STD:
+ case CalculatorMode::Standard:
pHistory = m_pStdHistory.get();
break;
- case CM_SCI:
+ case CalculatorMode::Scientific:
pHistory = m_pSciHistory.get();
break;
}
@@ -669,7 +670,7 @@ namespace CalculationManager
bool CalculatorManager::IsEngineRecording()
{
- return m_currentCalculatorEngine->FInRecordingState() ? true : false;
+ return m_currentCalculatorEngine->FInRecordingState();
}
bool CalculatorManager::IsInputEmpty()
diff --git a/src/CalcManager/CalculatorManager.h b/src/CalcManager/CalculatorManager.h
index dd30c16a1..23134e3a8 100644
--- a/src/CalcManager/CalculatorManager.h
+++ b/src/CalcManager/CalculatorManager.h
@@ -15,9 +15,8 @@ namespace CalculationManager
enum class CalculatorMode
{
- StandardMode,
- ScientificMode,
- ProgrammerMode,
+ Standard = 0,
+ Scientific,
};
enum class CalculatorPrecision
@@ -117,7 +116,7 @@ namespace CalculationManager
{
return m_savedCommands;
}
- void SetRadix(RADIX_TYPE iRadixType);
+ void SetRadix(RadixType iRadixType);
void SetMemorizedNumbersString();
std::wstring GetResultForRadix(uint32_t radix, int32_t precision, bool groupDigitsPerRadix);
void SetPrecision(int32_t precision);
@@ -125,7 +124,7 @@ namespace CalculationManager
wchar_t DecimalSeparator();
std::vector> const& GetHistoryItems();
- std::vector> const& GetHistoryItems(_In_ CalculationManager::CALCULATOR_MODE mode);
+ std::vector> const& GetHistoryItems(_In_ CalculatorMode mode);
std::shared_ptr const& GetHistoryItem(_In_ unsigned int uIdx);
bool RemoveHistoryItem(_In_ unsigned int uIdx);
void ClearHistory();
@@ -134,7 +133,7 @@ namespace CalculationManager
return m_pHistory->MaxHistorySize();
}
CalculationManager::Command GetCurrentDegreeMode();
- void SetHistory(_In_ CALCULATOR_MODE eMode, _In_ std::vector> const& history);
+ void SetHistory(_In_ CalculatorMode eMode, _In_ std::vector> const& history);
void SetInHistoryItemLoadMode(_In_ bool isHistoryItemLoadMode);
};
}
diff --git a/src/CalcManager/Command.h b/src/CalcManager/Command.h
index 4331ddf7d..764a2227e 100644
--- a/src/CalcManager/Command.h
+++ b/src/CalcManager/Command.h
@@ -172,7 +172,7 @@ namespace CalculationManager
CommandCeil = 415,
CommandROLC = 416,
CommandRORC = 417,
- CommandLogBaseX = 500,
+ CommandLogBaseY = 500,
CommandNand = 501,
CommandNor = 502,
diff --git a/src/CalcManager/ExpressionCommand.cpp b/src/CalcManager/ExpressionCommand.cpp
index 628805fbf..d574c9dae 100644
--- a/src/CalcManager/ExpressionCommand.cpp
+++ b/src/CalcManager/ExpressionCommand.cpp
@@ -277,7 +277,7 @@ wstring COpndCommand::GetString(uint32_t radix, int32_t precision)
{
if (m_fInitialized)
{
- return m_value.ToString(radix, eNUMOBJ_FMT::FMT_FLOAT, precision);
+ return m_value.ToString(radix, NumberFormat::Float, precision);
}
return wstring{};
diff --git a/src/CalcManager/Header Files/CCommand.h b/src/CalcManager/Header Files/CCommand.h
index f6d74d259..440c6283b 100644
--- a/src/CalcManager/Header Files/CCommand.h
+++ b/src/CalcManager/Header Files/CCommand.h
@@ -166,7 +166,7 @@
#define IDC_LASTCONTROL IDC_CEIL
#define IDC_BINARYEXTENDEDFIRST 500
-#define IDC_LOGBASEX 500 // logx(y)
+#define IDC_LOGBASEY 500 // logy(x)
#define IDC_NAND 501 // Nand
#define IDC_NOR 502 // Nor
diff --git a/src/CalcManager/Header Files/CalcEngine.h b/src/CalcManager/Header Files/CalcEngine.h
index 26b80515b..0158e6286 100644
--- a/src/CalcManager/Header Files/CalcEngine.h
+++ b/src/CalcManager/Header Files/CalcEngine.h
@@ -31,14 +31,13 @@
// The real exports follows later
// This is expected to be in same order as IDM_QWORD, IDM_DWORD etc.
-enum eNUM_WIDTH
+enum class NUM_WIDTH
{
QWORD_WIDTH, // Number width of 64 bits mode (default)
DWORD_WIDTH, // Number width of 32 bits mode
WORD_WIDTH, // Number width of 16 bits mode
BYTE_WIDTH // Number width of 16 bits mode
};
-typedef enum eNUM_WIDTH NUM_WIDTH;
static constexpr size_t NUM_WIDTH_LENGTH = 4;
namespace CalculationManager
@@ -106,7 +105,7 @@ class CCalcEngine
{
return GetString(IdStrFromCmdId(nOpCode));
}
- static std::wstring_view OpCodeToUnaryString(int nOpCode, bool fInv, ANGLE_TYPE angletype);
+ static std::wstring_view OpCodeToUnaryString(int nOpCode, bool fInv, AngleType angletype);
static std::wstring_view OpCodeToBinaryString(int nOpCode, bool isIntegerMode);
private:
@@ -117,11 +116,11 @@ class CCalcEngine
int m_nOpCode; /* ID value of operation. */
int m_nPrevOpCode; // opcode which computed the number in m_currentVal. 0 if it is already bracketed or plain number or
// if it hasn't yet been computed
- bool m_bChangeOp; /* Flag for changing operation. */
+ bool m_bChangeOp; // Flag for changing operation
bool m_bRecord; // Global mode: recording or displaying
bool m_bSetCalcState; // Flag for setting the engine result state
CalcEngine::CalcInput m_input; // Global calc input object for decimal strings
- eNUMOBJ_FMT m_nFE; /* Scientific notation conversion flag. */
+ NumberFormat m_nFE; // Scientific notation conversion flag
CalcEngine::Rational m_maxTrigonometricNum;
std::unique_ptr m_memoryValue; // Current memory value.
@@ -148,7 +147,7 @@ class CCalcEngine
std::array m_nPrecOp; /* Holding array for precedence operations. */
size_t m_precedenceOpCount; /* Current number of precedence ops in holding. */
int m_nLastCom; // Last command entered.
- ANGLE_TYPE m_angletype; // Current Angle type when in dec mode. one of deg, rad or grad
+ AngleType m_angletype; // Current Angle type when in dec mode. one of deg, rad or grad
NUM_WIDTH m_numwidth; // one of qword, dword, word or byte mode.
int32_t m_dwWordBitWidth; // # of bits in currently selected word size
@@ -179,15 +178,17 @@ class CCalcEngine
CalcEngine::Rational TruncateNumForIntMath(CalcEngine::Rational const& rat);
CalcEngine::Rational SciCalcFunctions(CalcEngine::Rational const& rat, uint32_t op);
CalcEngine::Rational DoOperation(int operation, CalcEngine::Rational const& lhs, CalcEngine::Rational const& rhs);
- void SetRadixTypeAndNumWidth(RADIX_TYPE radixtype, NUM_WIDTH numwidth);
+ void SetRadixTypeAndNumWidth(RadixType radixtype, NUM_WIDTH numwidth);
int32_t DwWordBitWidthFromeNumWidth(NUM_WIDTH numwidth);
- uint32_t NRadixFromRadixType(RADIX_TYPE radixtype);
+ uint32_t NRadixFromRadixType(RadixType radixtype);
double GenerateRandomNumber();
bool TryToggleBit(CalcEngine::Rational& rat, uint32_t wbitno);
void CheckAndAddLastBinOpToHistory(bool addToHistory = true);
void InitChopNumbers();
+ CalcEngine::Rational GetChopNumber() const;
+ std::wstring GetMaxDecimalValueString() const;
static void LoadEngineStrings(CalculationManager::IResourceProvider& resourceProvider);
static int IdStrFromCmdId(int id)
diff --git a/src/CalcManager/Header Files/EngineStrings.h b/src/CalcManager/Header Files/EngineStrings.h
index 958c828bd..7e0932370 100644
--- a/src/CalcManager/Header Files/EngineStrings.h
+++ b/src/CalcManager/Header Files/EngineStrings.h
@@ -196,7 +196,7 @@ inline constexpr auto SIDS_ACSCH = L"InverseCsch";
inline constexpr auto SIDS_COTH = L"Coth";
inline constexpr auto SIDS_ACOTH = L"InverseCoth";
inline constexpr auto SIDS_TWOPOWX = L"TwoPowX";
-inline constexpr auto SIDS_LOGBASEX = L"LogBaseX";
+inline constexpr auto SIDS_LOGBASEY = L"LogBaseY";
inline constexpr auto SIDS_ABS = L"Abs";
inline constexpr auto SIDS_FLOOR = L"Floor";
inline constexpr auto SIDS_CEIL = L"Ceil";
@@ -352,7 +352,7 @@ inline constexpr std::array g_sids =
SIDS_COTH,
SIDS_ACOTH,
SIDS_TWOPOWX,
- SIDS_LOGBASEX,
+ SIDS_LOGBASEY,
SIDS_ABS,
SIDS_FLOOR,
SIDS_CEIL,
diff --git a/src/CalcManager/Header Files/History.h b/src/CalcManager/Header Files/History.h
index 66bac67fa..f88f61c38 100644
--- a/src/CalcManager/Header Files/History.h
+++ b/src/CalcManager/Header Files/History.h
@@ -23,7 +23,7 @@ class CHistoryCollector
void RemoveLastOpndFromHistory();
void AddBinOpToHistory(int nOpCode, bool isIntgerMode, bool fNoRepetition = true);
void ChangeLastBinOp(int nOpCode, bool fPrecInvToHigher, bool isIntgerMode);
- void AddUnaryOpToHistory(int nOpCode, bool fInv, ANGLE_TYPE angletype);
+ void AddUnaryOpToHistory(int nOpCode, bool fInv, AngleType angletype);
void AddOpenBraceToHistory();
void AddCloseBraceToHistory();
void PushLastOpndStart(int ichOpndStart = -1);
diff --git a/src/CalcManager/Header Files/RadixType.h b/src/CalcManager/Header Files/RadixType.h
index 380d6afe0..2ae0f90ab 100644
--- a/src/CalcManager/Header Files/RadixType.h
+++ b/src/CalcManager/Header Files/RadixType.h
@@ -4,11 +4,10 @@
#pragma once
// This is expected to be in same order as IDM_HEX, IDM_DEC, IDM_OCT, IDM_BIN
-enum eRADIX_TYPE
+enum class RadixType
{
- HEX_RADIX,
- DEC_RADIX,
- OCT_RADIX,
- BIN_RADIX
+ Hex,
+ Decimal,
+ Octal,
+ Binary
};
-typedef enum eRADIX_TYPE RADIX_TYPE;
diff --git a/src/CalcManager/Header Files/Rational.h b/src/CalcManager/Header Files/Rational.h
index 8ded3c27d..25df92bda 100644
--- a/src/CalcManager/Header Files/Rational.h
+++ b/src/CalcManager/Header Files/Rational.h
@@ -64,7 +64,7 @@ namespace CalcEngine
friend bool operator<=(Rational const& lhs, Rational const& rhs);
friend bool operator>=(Rational const& lhs, Rational const& rhs);
- std::wstring ToString(uint32_t radix, NUMOBJ_FMT format, int32_t precision) const;
+ std::wstring ToString(uint32_t radix, NumberFormat format, int32_t precision) const;
uint64_t ToUInt64_t() const;
private:
diff --git a/src/CalcManager/Header Files/RationalMath.h b/src/CalcManager/Header Files/RationalMath.h
index 59500573f..f3ba56eca 100644
--- a/src/CalcManager/Header Files/RationalMath.h
+++ b/src/CalcManager/Header Files/RationalMath.h
@@ -22,12 +22,12 @@ namespace CalcEngine::RationalMath
Rational Invert(Rational const& rat);
Rational Abs(Rational const& rat);
- Rational Sin(Rational const& rat, ANGLE_TYPE angletype);
- Rational Cos(Rational const& rat, ANGLE_TYPE angletype);
- Rational Tan(Rational const& rat, ANGLE_TYPE angletype);
- Rational ASin(Rational const& rat, ANGLE_TYPE angletype);
- Rational ACos(Rational const& rat, ANGLE_TYPE angletype);
- Rational ATan(Rational const& rat, ANGLE_TYPE angletype);
+ Rational Sin(Rational const& rat, AngleType angletype);
+ Rational Cos(Rational const& rat, AngleType angletype);
+ Rational Tan(Rational const& rat, AngleType angletype);
+ Rational ASin(Rational const& rat, AngleType angletype);
+ Rational ACos(Rational const& rat, AngleType angletype);
+ Rational ATan(Rational const& rat, AngleType angletype);
Rational Sinh(Rational const& rat);
Rational Cosh(Rational const& rat);
diff --git a/src/CalcManager/Ratpack/CMakeLists.txt b/src/CalcManager/Ratpack/CMakeLists.txt
deleted file mode 100644
index 3fbd7ae31..000000000
--- a/src/CalcManager/Ratpack/CMakeLists.txt
+++ /dev/null
@@ -1,14 +0,0 @@
-target_sources(CalcManager PRIVATE
- basex.cpp
- conv.cpp
- exp.cpp
- fact.cpp
- itrans.cpp
- itransh.cpp
- logic.cpp
- num.cpp
- rat.cpp
- support.cpp
- trans.cpp
- transh.cpp
-)
diff --git a/src/CalcManager/Ratpack/conv.cpp b/src/CalcManager/Ratpack/conv.cpp
index ab7aba058..4f7609de0 100644
--- a/src/CalcManager/Ratpack/conv.cpp
+++ b/src/CalcManager/Ratpack/conv.cpp
@@ -303,17 +303,13 @@ PRAT numtorat(_In_ PNUMBER pin, uint32_t radix)
PNUMBER nRadixxtonum(_In_ PNUMBER a, uint32_t radix, int32_t precision)
{
- uint32_t bitmask;
- uint32_t cdigits;
- MANTTYPE* ptr;
-
PNUMBER sum = i32tonum(0, radix);
PNUMBER powofnRadix = i32tonum(BASEX, radix);
// A large penalty is paid for conversion of digits no one will see anyway.
// limit the digits to the minimum of the existing precision or the
// requested precision.
- cdigits = precision + 1;
+ uint32_t cdigits = precision + 1;
if (cdigits > (uint32_t)a->cdigit)
{
cdigits = (uint32_t)a->cdigit;
@@ -323,10 +319,10 @@ PNUMBER nRadixxtonum(_In_ PNUMBER a, uint32_t radix, int32_t precision)
numpowi32(&powofnRadix, a->exp + (a->cdigit - cdigits), radix, precision);
// Loop over all the relative digits from MSD to LSD
- for (ptr = &(a->mant[a->cdigit - 1]); cdigits > 0; ptr--, cdigits--)
+ for (MANTTYPE* ptr = &(a->mant[a->cdigit - 1]); cdigits > 0; ptr--, cdigits--)
{
// Loop over all the bits from MSB to LSB
- for (bitmask = BASEX / 2; bitmask > 0; bitmask /= 2)
+ for (uint32_t bitmask = BASEX / 2; bitmask > 0; bitmask /= 2)
{
addnum(&sum, sum, radix);
if (*ptr & bitmask)
@@ -368,9 +364,7 @@ PNUMBER numtonRadixx(_In_ PNUMBER a, uint32_t radix)
ptrdigit += a->cdigit - 1;
PNUMBER thisdigit = nullptr; // thisdigit holds the current digit of a
- // being summed into result.
- int32_t idigit; // idigit is the iterate of digits in a.
- for (idigit = 0; idigit < a->cdigit; idigit++)
+ for (int32_t idigit = 0; idigit < a->cdigit; idigit++)
{
mulnumx(&pnumret, num_radix);
// WARNING:
@@ -628,11 +622,10 @@ PNUMBER StringToNumber(wstring_view numberString, uint32_t radix, int32_t precis
MANTTYPE* pmant = pnumret->mant + numberString.length() - 1;
uint8_t state = START; // state is the state of the input state machine.
- wchar_t curChar;
for (const auto& c : numberString)
{
// If the character is the decimal separator, use L'.' for the purposes of the state machine.
- curChar = (c == g_decimalSeparator ? L'.' : c);
+ wchar_t curChar = (c == g_decimalSeparator ? L'.' : c);
// Switch states based on the character we encountered
switch (curChar)
@@ -1032,13 +1025,10 @@ int32_t numtoi32(_In_ PNUMBER pnum, uint32_t radix)
bool stripzeroesnum(_Inout_ PNUMBER pnum, int32_t starting)
{
- MANTTYPE* pmant;
- int32_t cdigits;
bool fstrip = false;
-
// point pmant to the LeastCalculatedDigit
- pmant = pnum->mant;
- cdigits = pnum->cdigit;
+ MANTTYPE* pmant = pnum->mant;
+ int32_t cdigits = pnum->cdigit;
// point pmant to the LSD
if (cdigits > starting)
{
@@ -1073,27 +1063,27 @@ bool stripzeroesnum(_Inout_ PNUMBER pnum, int32_t starting)
// FUNCTION: NumberToString
//
// ARGUMENTS: number representation
-// fmt, one of FMT_FLOAT FMT_SCIENTIFIC or
-// FMT_ENGINEERING
+// fmt, one of NumberFormat::Float, NumberFormat::Scientific or
+// NumberFormat::Engineering
// integer radix and int32_t precision value
//
// RETURN: String representation of number.
//
-// DESCRIPTION: Converts a number to it's string
+// DESCRIPTION: Converts a number to its string
// representation.
//
//-----------------------------------------------------------------------------
-wstring NumberToString(_Inout_ PNUMBER& pnum, int format, uint32_t radix, int32_t precision)
+wstring NumberToString(_Inout_ PNUMBER& pnum, NumberFormat format, uint32_t radix, int32_t precision)
{
stripzeroesnum(pnum, precision + 2);
int32_t length = pnum->cdigit;
int32_t exponent = pnum->exp + length; // Actual number of digits to the left of decimal
- int32_t oldFormat = format;
- if (exponent > precision && format == FMT_FLOAT)
+ NumberFormat oldFormat = format;
+ if (exponent > precision && format == NumberFormat::Float)
{
// Force scientific mode to prevent user from assuming 33rd digit is exact.
- format = FMT_SCIENTIFIC;
+ format = NumberFormat::Scientific;
}
// Make length small enough to fit in pret.
@@ -1113,7 +1103,7 @@ wstring NumberToString(_Inout_ PNUMBER& pnum, int format, uint32_t radix, int32_
divnum(&round, num_two, radix, precision);
// Make round number exponent one below the LSD for the number.
- if (exponent > 0 || format == FMT_FLOAT)
+ if (exponent > 0 || format == NumberFormat::Float)
{
round->exp = pnum->exp + pnum->cdigit - round->cdigit - precision;
}
@@ -1126,7 +1116,7 @@ wstring NumberToString(_Inout_ PNUMBER& pnum, int format, uint32_t radix, int32_
round->sign = pnum->sign;
}
- if (format == FMT_FLOAT)
+ if (format == NumberFormat::Float)
{
// Figure out if the exponent will fill more space than the non-exponent field.
if ((length - exponent > precision) || (exponent > precision + 3))
@@ -1140,7 +1130,7 @@ wstring NumberToString(_Inout_ PNUMBER& pnum, int format, uint32_t radix, int32_
{
// Case where too many zeros are to the right or left of the
// decimal pt. And we are forced to switch to scientific form.
- format = FMT_SCIENTIFIC;
+ format = NumberFormat::Scientific;
}
}
else if (length + abs(exponent) < precision && round)
@@ -1173,13 +1163,13 @@ wstring NumberToString(_Inout_ PNUMBER& pnum, int format, uint32_t radix, int32_
int32_t eout = exponent - 1; // Displayed exponent.
MANTTYPE* pmant = pnum->mant + pnum->cdigit - 1;
// Case where too many digits are to the left of the decimal or
- // FMT_SCIENTIFIC or FMT_ENGINEERING was specified.
- if ((format == FMT_SCIENTIFIC) || (format == FMT_ENGINEERING))
+ // NumberFormat::Scientific or NumberFormat::Engineering was specified.
+ if ((format == NumberFormat::Scientific) || (format == NumberFormat::Engineering))
{
useSciForm = true;
if (eout != 0)
{
- if (format == FMT_ENGINEERING)
+ if (format == NumberFormat::Engineering)
{
exponent = (eout % 3);
eout -= exponent;
@@ -1280,7 +1270,7 @@ wstring NumberToString(_Inout_ PNUMBER& pnum, int format, uint32_t radix, int32_
// ARGUMENTS:
// PRAT *representation of a number.
// i32 representation of base to dump to screen.
-// fmt, one of FMT_FLOAT FMT_SCIENTIFIC or FMT_ENGINEERING
+// fmt, one of NumberFormat::Float, NumberFormat::Scientific, or NumberFormat::Engineering
// precision uint32_t
//
// RETURN: string
@@ -1293,7 +1283,7 @@ wstring NumberToString(_Inout_ PNUMBER& pnum, int format, uint32_t radix, int32_
// why a pointer to the rational is passed in.
//
//-----------------------------------------------------------------------------
-wstring RatToString(_Inout_ PRAT& prat, int format, uint32_t radix, int32_t precision)
+wstring RatToString(_Inout_ PRAT& prat, NumberFormat format, uint32_t radix, int32_t precision)
{
PNUMBER p = RatToNumber(prat, radix, precision);
diff --git a/src/CalcManager/Ratpack/exp.cpp b/src/CalcManager/Ratpack/exp.cpp
index 23257f731..b4020d45c 100644
--- a/src/CalcManager/Ratpack/exp.cpp
+++ b/src/CalcManager/Ratpack/exp.cpp
@@ -63,7 +63,6 @@ void exprat(_Inout_ PRAT* px, uint32_t radix, int32_t precision)
{
PRAT pwr = nullptr;
PRAT pint = nullptr;
- int32_t intpwr;
if (rat_gt(*px, rat_max_exp, precision) || rat_lt(*px, rat_min_exp, precision))
{
@@ -76,7 +75,7 @@ void exprat(_Inout_ PRAT* px, uint32_t radix, int32_t precision)
intrat(&pint, radix, precision);
- intpwr = rattoi32(pint, radix, precision);
+ const int32_t intpwr = rattoi32(pint, radix, precision);
ratpowi32(&pwr, intpwr, precision);
subrat(px, pint, precision);
@@ -153,7 +152,6 @@ void _lograt(PRAT* px, int32_t precision)
void lograt(_Inout_ PRAT* px, int32_t precision)
{
- bool fneglog;
PRAT pwr = nullptr; // pwr is the large scaling factor.
PRAT offset = nullptr; // offset is the incremental scaling factor.
@@ -164,12 +162,10 @@ void lograt(_Inout_ PRAT* px, int32_t precision)
}
// Get number > 1, for scaling
- fneglog = rat_lt(*px, rat_one, precision);
+ bool fneglog = rat_lt(*px, rat_one, precision);
if (fneglog)
{
- // WARNING: This is equivalent to doing *px = 1 / *px
- PNUMBER pnumtemp = nullptr;
- pnumtemp = (*px)->pp;
+ PNUMBER pnumtemp = (*px)->pp;
(*px)->pp = (*px)->pq;
(*px)->pq = pnumtemp;
}
@@ -178,10 +174,7 @@ void lograt(_Inout_ PRAT* px, int32_t precision)
// log(x*2^(BASEXPWR*k)) = BASEXPWR*k*log(2)+log(x)
if (LOGRAT2(*px) > 1)
{
- // Take advantage of px's base BASEX to scale quickly down to
- // a reasonable range.
- int32_t intpwr;
- intpwr = LOGRAT2(*px) - 1;
+ const int32_t intpwr = LOGRAT2(*px) - 1;
(*px)->pq->exp += intpwr;
pwr = i32torat(intpwr * BASEXPWR);
mulrat(&pwr, ln_two, precision);
@@ -448,10 +441,9 @@ void powratcomp(_Inout_ PRAT* px, _In_ PRAT y, uint32_t radix, int32_t precision
{
// If power is an integer let ratpowi32 deal with it.
PRAT iy = nullptr;
- int32_t inty;
DUPRAT(iy, y);
subrat(&iy, podd, precision);
- inty = rattoi32(iy, radix, precision);
+ int32_t inty = rattoi32(iy, radix, precision);
PRAT plnx = nullptr;
DUPRAT(plnx, *px);
diff --git a/src/CalcManager/Ratpack/fact.cpp b/src/CalcManager/Ratpack/fact.cpp
index c026e536a..f0905e4fd 100644
--- a/src/CalcManager/Ratpack/fact.cpp
+++ b/src/CalcManager/Ratpack/fact.cpp
@@ -67,13 +67,9 @@ void _gamma(PRAT* pn, uint32_t radix, int32_t precision)
PRAT sum = nullptr;
PRAT err = nullptr;
PRAT mpy = nullptr;
- PRAT ratprec = nullptr;
- PRAT ratRadix = nullptr;
- int32_t oldprec;
// Set up constants and initial conditions
- oldprec = precision;
- ratprec = i32torat(oldprec);
+ PRAT ratprec = i32torat(precision);
// Find the best 'A' for convergence to the required precision.
a = i32torat(radix);
@@ -102,7 +98,7 @@ void _gamma(PRAT* pn, uint32_t radix, int32_t precision)
exprat(&tmp, radix, precision);
mulrat(&term, tmp, precision);
lograt(&term, precision);
- ratRadix = i32torat(radix);
+ const auto ratRadix = i32torat(radix);
DUPRAT(tmp, ratRadix);
lograt(&tmp, precision);
subrat(&term, tmp, precision);
@@ -173,7 +169,6 @@ void _gamma(PRAT* pn, uint32_t radix, int32_t precision)
mulrat(&sum, mpy, precision);
// And cleanup
- precision = oldprec;
destroyrat(ratprec);
destroyrat(err);
destroyrat(term);
diff --git a/src/CalcManager/Ratpack/itrans.cpp b/src/CalcManager/Ratpack/itrans.cpp
index 9bb94358b..75e747858 100644
--- a/src/CalcManager/Ratpack/itrans.cpp
+++ b/src/CalcManager/Ratpack/itrans.cpp
@@ -17,17 +17,17 @@
//-----------------------------------------------------------------------------
#include "ratpak.h"
-void ascalerat(_Inout_ PRAT* pa, ANGLE_TYPE angletype, int32_t precision)
+void ascalerat(_Inout_ PRAT* pa, AngleType angletype, int32_t precision)
{
switch (angletype)
{
- case ANGLE_RAD:
+ case AngleType::Radians:
break;
- case ANGLE_DEG:
+ case AngleType::Degrees:
divrat(pa, two_pi, precision);
mulrat(pa, rat_360, precision);
break;
- case ANGLE_GRAD:
+ case AngleType::Gradians:
divrat(pa, two_pi, precision);
mulrat(pa, rat_400, precision);
break;
@@ -76,7 +76,7 @@ void _asinrat(PRAT* px, int32_t precision)
DESTROYTAYLOR();
}
-void asinanglerat(_Inout_ PRAT* pa, ANGLE_TYPE angletype, uint32_t radix, int32_t precision)
+void asinanglerat(_Inout_ PRAT* pa, AngleType angletype, uint32_t radix, int32_t precision)
{
asinrat(pa, radix, precision);
@@ -164,7 +164,7 @@ void asinrat(_Inout_ PRAT* px, uint32_t radix, int32_t precision)
//
//-----------------------------------------------------------------------------
-void acosanglerat(_Inout_ PRAT* pa, ANGLE_TYPE angletype, uint32_t radix, int32_t precision)
+void acosanglerat(_Inout_ PRAT* pa, AngleType angletype, uint32_t radix, int32_t precision)
{
acosrat(pa, radix, precision);
@@ -249,7 +249,7 @@ void acosrat(_Inout_ PRAT* px, uint32_t radix, int32_t precision)
//
//-----------------------------------------------------------------------------
-void atananglerat(_Inout_ PRAT* pa, ANGLE_TYPE angletype, uint32_t radix, int32_t precision)
+void atananglerat(_Inout_ PRAT* pa, AngleType angletype, uint32_t radix, int32_t precision)
{
atanrat(pa, radix, precision);
diff --git a/src/CalcManager/Ratpack/logic.cpp b/src/CalcManager/Ratpack/logic.cpp
index c9094f339..197bda902 100644
--- a/src/CalcManager/Ratpack/logic.cpp
+++ b/src/CalcManager/Ratpack/logic.cpp
@@ -21,7 +21,6 @@ void lshrat(_Inout_ PRAT* pa, _In_ PRAT b, uint32_t radix, int32_t precision)
{
PRAT pwr = nullptr;
- int32_t intb;
intrat(pa, radix, precision);
if (!zernum((*pa)->pp))
@@ -32,7 +31,7 @@ void lshrat(_Inout_ PRAT* pa, _In_ PRAT b, uint32_t radix, int32_t precision)
// Don't attempt lsh of anything big
throw(CALC_E_DOMAIN);
}
- intb = rattoi32(b, radix, precision);
+ const int32_t intb = rattoi32(b, radix, precision);
DUPRAT(pwr, rat_two);
ratpowi32(&pwr, intb, precision);
mulrat(pa, pwr, precision);
@@ -44,7 +43,6 @@ void rshrat(_Inout_ PRAT* pa, _In_ PRAT b, uint32_t radix, int32_t precision)
{
PRAT pwr = nullptr;
- int32_t intb;
intrat(pa, radix, precision);
if (!zernum((*pa)->pp))
@@ -55,7 +53,7 @@ void rshrat(_Inout_ PRAT* pa, _In_ PRAT b, uint32_t radix, int32_t precision)
// Don't attempt rsh of anything big and negative.
throw(CALC_E_DOMAIN);
}
- intb = rattoi32(b, radix, precision);
+ const int32_t intb = rattoi32(b, radix, precision);
DUPRAT(pwr, rat_two);
ratpowi32(&pwr, intb, precision);
divrat(pa, pwr, precision);
diff --git a/src/CalcManager/Ratpack/num.cpp b/src/CalcManager/Ratpack/num.cpp
index c45610524..6055e41d3 100644
--- a/src/CalcManager/Ratpack/num.cpp
+++ b/src/CalcManager/Ratpack/num.cpp
@@ -67,8 +67,7 @@ void _addnum(PNUMBER* pa, PNUMBER b, uint32_t radix)
MANTTYPE* pcha; // pcha is a pointer to the mantissa of a.
MANTTYPE* pchb; // pchb is a pointer to the mantissa of b.
MANTTYPE* pchc; // pchc is a pointer to the mantissa of c.
- int32_t cdigits; // cdigits is the max count of the digits results
- // used as a counter.
+ int32_t cdigits; // cdigits is the max count of the digits results used as a counter.
int32_t mexp; // mexp is the exponent of the result.
MANTTYPE da; // da is a single 'digit' after possible padding.
MANTTYPE db; // db is a single 'digit' after possible padding.
@@ -558,48 +557,34 @@ bool equnum(_In_ PNUMBER a, _In_ PNUMBER b)
bool lessnum(_In_ PNUMBER a, _In_ PNUMBER b)
{
- int32_t diff;
- MANTTYPE* pa;
- MANTTYPE* pb;
- int32_t cdigits;
- int32_t ccdigits;
- MANTTYPE da;
- MANTTYPE db;
-
- diff = (a->cdigit + a->exp) - (b->cdigit + b->exp);
+ int32_t diff = (a->cdigit + a->exp) - (b->cdigit + b->exp);
if (diff < 0)
{
// The exponent of a is less than b
return true;
}
- else
+ if (diff > 0)
{
- if (diff > 0)
- {
- return false;
- }
- else
+ return false;
+ }
+ MANTTYPE* pa = a->mant;
+ MANTTYPE* pb = b->mant;
+ pa += a->cdigit - 1;
+ pb += b->cdigit - 1;
+ int32_t cdigits = max(a->cdigit, b->cdigit);
+ int32_t ccdigits = cdigits;
+ for (; cdigits > 0; cdigits--)
+ {
+ MANTTYPE da = ((cdigits > (ccdigits - a->cdigit)) ? *pa-- : 0);
+ MANTTYPE db = ((cdigits > (ccdigits - b->cdigit)) ? *pb-- : 0);
+ diff = da - db;
+ if (diff)
{
- pa = a->mant;
- pb = b->mant;
- pa += a->cdigit - 1;
- pb += b->cdigit - 1;
- cdigits = max(a->cdigit, b->cdigit);
- ccdigits = cdigits;
- for (; cdigits > 0; cdigits--)
- {
- da = ((cdigits > (ccdigits - a->cdigit)) ? *pa-- : 0);
- db = ((cdigits > (ccdigits - b->cdigit)) ? *pb-- : 0);
- diff = da - db;
- if (diff)
- {
- return (diff < 0);
- }
- }
- // In this case, they are equal.
- return false;
+ return (diff < 0);
}
}
+ // In this case, they are equal.
+ return false;
}
//----------------------------------------------------------------------------
diff --git a/src/CalcManager/Ratpack/ratpak.h b/src/CalcManager/Ratpack/ratpak.h
index 18b2d0249..0b3771f36 100644
--- a/src/CalcManager/Ratpack/ratpak.h
+++ b/src/CalcManager/Ratpack/ratpak.h
@@ -31,25 +31,20 @@ static constexpr uint32_t BASEX = 0x80000000; // Internal radix used in calculat
typedef uint32_t MANTTYPE;
typedef uint64_t TWO_MANTTYPE;
-enum eNUMOBJ_FMT
+enum class NumberFormat
{
- FMT_FLOAT, // returns floating point, or exponential if number is too big
- FMT_SCIENTIFIC, // always returns scientific notation
- FMT_ENGINEERING // always returns engineering notation such that exponent is a multiple of 3
-
+ Float, // returns floating point, or exponential if number is too big
+ Scientific, // always returns scientific notation
+ Engineering // always returns engineering notation such that exponent is a multiple of 3
};
-enum eANGLE_TYPE
+enum class AngleType
{
- ANGLE_DEG, // Calculate trig using 360 degrees per revolution
- ANGLE_RAD, // Calculate trig using 2 pi radians per revolution
- ANGLE_GRAD // Calculate trig using 400 gradients per revolution
-
+ Degrees, // Calculate trig using 360 degrees per revolution
+ Radians, // Calculate trig using 2 pi radians per revolution
+ Gradians // Calculate trig using 400 gradians per revolution
};
-typedef enum eNUMOBJ_FMT NUMOBJ_FMT;
-typedef enum eANGLE_TYPE ANGLE_TYPE;
-
//-----------------------------------------------------------------------------
//
// NUMBER type is a representation of a generic sized generic radix number
@@ -341,10 +336,10 @@ extern bool equnum(_In_ PNUMBER a, _In_ PNUMBER b); // returns true of a == b
extern bool lessnum(_In_ PNUMBER a, _In_ PNUMBER b); // returns true of a < b
extern bool zernum(_In_ PNUMBER a); // returns true of a == 0
extern bool zerrat(_In_ PRAT a); // returns true if a == 0/q
-extern std::wstring NumberToString(_Inout_ PNUMBER& pnum, int format, uint32_t radix, int32_t precision);
+extern std::wstring NumberToString(_Inout_ PNUMBER& pnum, NumberFormat format, uint32_t radix, int32_t precision);
// returns a text representation of a PRAT
-extern std::wstring RatToString(_Inout_ PRAT& prat, int format, uint32_t radix, int32_t precision);
+extern std::wstring RatToString(_Inout_ PRAT& prat, NumberFormat format, uint32_t radix, int32_t precision);
// converts a PRAT into a PNUMBER
extern PNUMBER RatToNumber(_In_ PRAT prat, uint32_t radix, int32_t precision);
// flattens a PRAT by converting it to a PNUMBER and back to a PRAT
@@ -376,7 +371,7 @@ extern PRAT _createrat(void);
// returns a new rat structure with the acos of x->p/x->q taking into account
// angle type
-extern void acosanglerat(_Inout_ PRAT* px, ANGLE_TYPE angletype, uint32_t radix, int32_t precision);
+extern void acosanglerat(_Inout_ PRAT* px, AngleType angletype, uint32_t radix, int32_t precision);
// returns a new rat structure with the acosh of x->p/x->q
extern void acoshrat(_Inout_ PRAT* px, uint32_t radix, int32_t precision);
@@ -386,7 +381,7 @@ extern void acosrat(_Inout_ PRAT* px, uint32_t radix, int32_t precision);
// returns a new rat structure with the asin of x->p/x->q taking into account
// angle type
-extern void asinanglerat(_Inout_ PRAT* px, ANGLE_TYPE angletype, uint32_t radix, int32_t precision);
+extern void asinanglerat(_Inout_ PRAT* px, AngleType angletype, uint32_t radix, int32_t precision);
extern void asinhrat(_Inout_ PRAT* px, uint32_t radix, int32_t precision);
// returns a new rat structure with the asinh of x->p/x->q
@@ -396,7 +391,7 @@ extern void asinrat(_Inout_ PRAT* px, uint32_t radix, int32_t precision);
// returns a new rat structure with the atan of x->p/x->q taking into account
// angle type
-extern void atananglerat(_Inout_ PRAT* px, ANGLE_TYPE angletype, uint32_t radix, int32_t precision);
+extern void atananglerat(_Inout_ PRAT* px, AngleType angletype, uint32_t radix, int32_t precision);
// returns a new rat structure with the atanh of x->p/x->q
extern void atanhrat(_Inout_ PRAT* px, int32_t precision);
@@ -412,7 +407,7 @@ extern void cosrat(_Inout_ PRAT* px, uint32_t radix, int32_t precision);
// returns a new rat structure with the cos of x->p/x->q taking into account
// angle type
-extern void cosanglerat(_Inout_ PRAT* px, ANGLE_TYPE angletype, uint32_t radix, int32_t precision);
+extern void cosanglerat(_Inout_ PRAT* px, AngleType angletype, uint32_t radix, int32_t precision);
// returns a new rat structure with the exp of x->p/x->q this should not be called explicitly.
extern void _exprat(_Inout_ PRAT* px, int32_t precision);
@@ -435,14 +430,14 @@ extern void sinrat(_Inout_ PRAT* px);
// returns a new rat structure with the sin of x->p/x->q taking into account
// angle type
-extern void sinanglerat(_Inout_ PRAT* px, ANGLE_TYPE angletype, uint32_t radix, int32_t precision);
+extern void sinanglerat(_Inout_ PRAT* px, AngleType angletype, uint32_t radix, int32_t precision);
extern void tanhrat(_Inout_ PRAT* px, uint32_t radix, int32_t precision);
extern void tanrat(_Inout_ PRAT* px, uint32_t radix, int32_t precision);
// returns a new rat structure with the tan of x->p/x->q taking into account
// angle type
-extern void tananglerat(_Inout_ PRAT* px, ANGLE_TYPE angletype, uint32_t radix, int32_t precision);
+extern void tananglerat(_Inout_ PRAT* px, AngleType angletype, uint32_t radix, int32_t precision);
extern void _dupnum(_In_ PNUMBER dest, _In_ const NUMBER* const src);
diff --git a/src/CalcManager/Ratpack/support.cpp b/src/CalcManager/Ratpack/support.cpp
index 81c737f5f..ef9e41063 100644
--- a/src/CalcManager/Ratpack/support.cpp
+++ b/src/CalcManager/Ratpack/support.cpp
@@ -596,15 +596,13 @@ void _dumprawrat(_In_ const wchar_t* varname, _In_ PRAT rat, wostream& out)
void _dumprawnum(_In_ const wchar_t* varname, _In_ PNUMBER num, wostream& out)
{
- int i;
-
out << L"NUMBER " << varname << L" = {\n";
out << L"\t" << num->sign << L",\n";
out << L"\t" << num->cdigit << L",\n";
out << L"\t" << num->exp << L",\n";
out << L"\t{ ";
- for (i = 0; i < num->cdigit; i++)
+ for (int i = 0; i < num->cdigit; i++)
{
out << L" " << num->mant[i] << L",";
}
@@ -681,10 +679,9 @@ void trimit(_Inout_ PRAT* px, int32_t precision)
{
if (!g_ftrueinfinite)
{
- int32_t trim;
PNUMBER pp = (*px)->pp;
PNUMBER pq = (*px)->pq;
- trim = g_ratio * (min((pp->cdigit + pp->exp), (pq->cdigit + pq->exp)) - 1) - precision;
+ int32_t trim = g_ratio * (min((pp->cdigit + pp->exp), (pq->cdigit + pq->exp)) - 1) - precision;
if (trim > g_ratio)
{
trim /= g_ratio;
diff --git a/src/CalcManager/Ratpack/trans.cpp b/src/CalcManager/Ratpack/trans.cpp
index e848155d8..50055e220 100644
--- a/src/CalcManager/Ratpack/trans.cpp
+++ b/src/CalcManager/Ratpack/trans.cpp
@@ -16,17 +16,17 @@
#include "ratpak.h"
-void scalerat(_Inout_ PRAT* pa, ANGLE_TYPE angletype, uint32_t radix, int32_t precision)
+void scalerat(_Inout_ PRAT* pa, AngleType angletype, uint32_t radix, int32_t precision)
{
switch (angletype)
{
- case ANGLE_RAD:
+ case AngleType::Radians:
scale2pi(pa, radix, precision);
break;
- case ANGLE_DEG:
+ case AngleType::Degrees:
scale(pa, rat_360, radix, precision);
break;
- case ANGLE_GRAD:
+ case AngleType::Gradians:
scale(pa, rat_400, radix, precision);
break;
}
@@ -98,13 +98,13 @@ void sinrat(PRAT* px, uint32_t radix, int32_t precision)
_sinrat(px, precision);
}
-void sinanglerat(_Inout_ PRAT* pa, ANGLE_TYPE angletype, uint32_t radix, int32_t precision)
+void sinanglerat(_Inout_ PRAT* pa, AngleType angletype, uint32_t radix, int32_t precision)
{
scalerat(pa, angletype, radix, precision);
switch (angletype)
{
- case ANGLE_DEG:
+ case AngleType::Degrees:
if (rat_gt(*pa, rat_180, precision))
{
subrat(pa, rat_360, precision);
@@ -112,7 +112,7 @@ void sinanglerat(_Inout_ PRAT* pa, ANGLE_TYPE angletype, uint32_t radix, int32_t
divrat(pa, rat_180, precision);
mulrat(pa, pi, precision);
break;
- case ANGLE_GRAD:
+ case AngleType::Gradians:
if (rat_gt(*pa, rat_200, precision))
{
subrat(pa, rat_400, precision);
@@ -193,13 +193,13 @@ void cosrat(_Inout_ PRAT* px, uint32_t radix, int32_t precision)
_cosrat(px, radix, precision);
}
-void cosanglerat(_Inout_ PRAT* pa, ANGLE_TYPE angletype, uint32_t radix, int32_t precision)
+void cosanglerat(_Inout_ PRAT* pa, AngleType angletype, uint32_t radix, int32_t precision)
{
scalerat(pa, angletype, radix, precision);
switch (angletype)
{
- case ANGLE_DEG:
+ case AngleType::Degrees:
if (rat_gt(*pa, rat_180, precision))
{
PRAT ptmp = nullptr;
@@ -211,7 +211,7 @@ void cosanglerat(_Inout_ PRAT* pa, ANGLE_TYPE angletype, uint32_t radix, int32_t
divrat(pa, rat_180, precision);
mulrat(pa, pi, precision);
break;
- case ANGLE_GRAD:
+ case AngleType::Gradians:
if (rat_gt(*pa, rat_200, precision))
{
PRAT ptmp = nullptr;
@@ -263,13 +263,13 @@ void tanrat(_Inout_ PRAT* px, uint32_t radix, int32_t precision)
_tanrat(px, radix, precision);
}
-void tananglerat(_Inout_ PRAT* pa, ANGLE_TYPE angletype, uint32_t radix, int32_t precision)
+void tananglerat(_Inout_ PRAT* pa, AngleType angletype, uint32_t radix, int32_t precision)
{
scalerat(pa, angletype, radix, precision);
switch (angletype)
{
- case ANGLE_DEG:
+ case AngleType::Degrees:
if (rat_gt(*pa, rat_180, precision))
{
subrat(pa, rat_180, precision);
@@ -277,7 +277,7 @@ void tananglerat(_Inout_ PRAT* pa, ANGLE_TYPE angletype, uint32_t radix, int32_t
divrat(pa, rat_180, precision);
mulrat(pa, pi, precision);
break;
- case ANGLE_GRAD:
+ case AngleType::Gradians:
if (rat_gt(*pa, rat_200, precision))
{
subrat(pa, rat_200, precision);
diff --git a/src/CalcManager/UnitConverter.cpp b/src/CalcManager/UnitConverter.cpp
index ce0ebb810..05242a081 100644
--- a/src/CalcManager/UnitConverter.cpp
+++ b/src/CalcManager/UnitConverter.cpp
@@ -209,7 +209,7 @@ vector UnitConverter::StringToVector(wstring_view w, wstring_view delim
while (delimiterIndex != wstring_view::npos)
{
serializedTokens.emplace_back(w.substr(startIndex, delimiterIndex - startIndex));
- startIndex = delimiterIndex + (int)delimiter.size();
+ startIndex = delimiterIndex + static_cast(delimiter.size());
delimiterIndex = w.find(delimiter, startIndex);
}
if (addRemainder)
@@ -244,9 +244,9 @@ Unit UnitConverter::StringToUnit(wstring_view w)
serializedUnit.name = Unquote(tokenList[1]);
serializedUnit.accessibleName = serializedUnit.name;
serializedUnit.abbreviation = Unquote(tokenList[2]);
- serializedUnit.isConversionSource = (tokenList[3].compare(L"1") == 0);
- serializedUnit.isConversionTarget = (tokenList[4].compare(L"1") == 0);
- serializedUnit.isWhimsical = (tokenList[5].compare(L"1") == 0);
+ serializedUnit.isConversionSource = (tokenList[3] == L"1");
+ serializedUnit.isConversionTarget = (tokenList[4] == L"1");
+ serializedUnit.isWhimsical = (tokenList[5] == L"1");
return serializedUnit;
}
@@ -256,7 +256,7 @@ Category UnitConverter::StringToCategory(wstring_view w)
assert(tokenList.size() == EXPECTEDSERIALIZEDCATEGORYTOKENCOUNT);
Category serializedCategory;
serializedCategory.id = wcstol(Unquote(tokenList[0]).c_str(), nullptr, 10);
- serializedCategory.supportsNegative = (tokenList[1].compare(L"1") == 0);
+ serializedCategory.supportsNegative = (tokenList[1] == L"1");
serializedCategory.name = Unquote(tokenList[2]);
return serializedCategory;
}
@@ -559,7 +559,7 @@ future> UnitConverter::RefreshCurrencyRatios()
}
shared_future sharedLoadResult = loadDataResult.share();
- return async([this, currencyDataLoader, sharedLoadResult]() {
+ return async([currencyDataLoader, sharedLoadResult]() {
sharedLoadResult.wait();
bool didLoad = sharedLoadResult.get();
wstring timestamp;
@@ -618,10 +618,10 @@ vector> UnitConverter::CalculateSuggested()
newEntry.magnitude = log10(convertedValue);
newEntry.value = convertedValue;
newEntry.type = cur.first;
- if (newEntry.type.isWhimsical == false)
- intermediateVector.push_back(newEntry);
- else
+ if (newEntry.type.isWhimsical)
intermediateWhimsicalVector.push_back(newEntry);
+ else
+ intermediateVector.push_back(newEntry);
}
}
@@ -896,7 +896,7 @@ void UnitConverter::Calculate()
else
{
int currentNumberSignificantDigits = GetNumberDigits(m_currentDisplay);
- int precision = 0;
+ int precision;
if (abs(returnValue) < OPTIMALDECIMALALLOWED)
{
precision = MAXIMUMDIGITSALLOWED;
diff --git a/src/CalcManager/UnitConverter.h b/src/CalcManager/UnitConverter.h
index 9d65324ec..d97e9ce20 100644
--- a/src/CalcManager/UnitConverter.h
+++ b/src/CalcManager/UnitConverter.h
@@ -6,8 +6,8 @@
#include
#include
#include
-#include "sal_cross_platform.h" // for SAL
-#include // for std::shared_ptr
+#include "sal_cross_platform.h" // for SAL
+#include // for std::shared_ptr
namespace UnitConversionManager
{
@@ -18,11 +18,11 @@ namespace UnitConversionManager
Unit()
{
}
- Unit(int id, std::wstring name, std::wstring abbreviation, bool isConversionSource, bool isConversionTarget, bool isWhimsical)
+ Unit(int id, std::wstring_view name, std::wstring abbreviation, bool isConversionSource, bool isConversionTarget, bool isWhimsical)
: id(id)
, name(name)
, accessibleName(name)
- , abbreviation(abbreviation)
+ , abbreviation(std::move(abbreviation))
, isConversionSource(isConversionSource)
, isConversionTarget(isConversionTarget)
, isWhimsical(isWhimsical)
@@ -31,23 +31,26 @@ namespace UnitConversionManager
Unit(
int id,
- std::wstring currencyName,
- std::wstring countryName,
+ std::wstring_view currencyName,
+ std::wstring_view countryName,
std::wstring abbreviation,
bool isRtlLanguage,
bool isConversionSource,
bool isConversionTarget)
: id(id)
- , abbreviation(abbreviation)
+ , abbreviation(std::move(abbreviation))
, isConversionSource(isConversionSource)
, isConversionTarget(isConversionTarget)
, isWhimsical(false)
{
- std::wstring nameValue1 = isRtlLanguage ? currencyName : countryName;
- std::wstring nameValue2 = isRtlLanguage ? countryName : currencyName;
+ auto nameValue1 = isRtlLanguage ? currencyName : countryName;
+ auto nameValue2 = isRtlLanguage ? countryName : currencyName;
- name = nameValue1 + L" - " + nameValue2;
- accessibleName = nameValue1 + L" " + nameValue2;
+ name = nameValue1;
+ name.append(L" - ").append(nameValue2);
+
+ accessibleName = nameValue1;
+ accessibleName.append(1, L' ').append(nameValue2);
}
int id;
@@ -84,7 +87,7 @@ namespace UnitConversionManager
Category(int id, std::wstring name, bool supportsNegative)
: id(id)
- , name(name)
+ , name(std::move(name))
, supportsNegative(supportsNegative)
{
}
diff --git a/src/CalcManager/pch.h b/src/CalcManager/pch.h
index 288bbc91e..9c71ff3a5 100644
--- a/src/CalcManager/pch.h
+++ b/src/CalcManager/pch.h
@@ -21,6 +21,6 @@
#include
#include
#include
-#include
+#include
#include
#include
diff --git a/src/CalcViewModel/CalcViewModel.vcxproj b/src/CalcViewModel/CalcViewModel.vcxproj
index db212ad0a..c2a69b5c0 100644
--- a/src/CalcViewModel/CalcViewModel.vcxproj
+++ b/src/CalcViewModel/CalcViewModel.vcxproj
@@ -314,7 +314,6 @@
-
@@ -383,6 +382,9 @@
{e727a92b-f149-492c-8117-c039a298719b}
+
+ {fc81ff41-02cd-4cd9-9bc5-45a1e39ac6ed}
+
diff --git a/src/CalcViewModel/CalcViewModel.vcxproj.filters b/src/CalcViewModel/CalcViewModel.vcxproj.filters
index 0b3507fe3..7a0619ee4 100644
--- a/src/CalcViewModel/CalcViewModel.vcxproj.filters
+++ b/src/CalcViewModel/CalcViewModel.vcxproj.filters
@@ -169,9 +169,6 @@
DataLoaders
-
- Common
-
DataLoaders
@@ -200,7 +197,7 @@
GraphingCalculator
- Common
+ Common
diff --git a/src/CalcViewModel/Common/Automation/NarratorAnnouncement.cpp b/src/CalcViewModel/Common/Automation/NarratorAnnouncement.cpp
index 15fca2c6e..72ae293e4 100644
--- a/src/CalcViewModel/Common/Automation/NarratorAnnouncement.cpp
+++ b/src/CalcViewModel/Common/Automation/NarratorAnnouncement.cpp
@@ -24,6 +24,9 @@ namespace CalculatorApp::Common::Automation
StringReference OpenParenthesisCountChanged(L"OpenParenthesisCountChanged");
StringReference NoParenthesisAdded(L"NoParenthesisAdded");
StringReference GraphModeChanged(L"GraphModeChanged");
+ StringReference GraphViewChanged(L"GraphViewChanged");
+ StringReference FunctionRemoved(L"FunctionRemoved");
+ StringReference GraphViewBestFitChanged(L"GraphViewBestFitChanged");
}
}
@@ -142,7 +145,7 @@ NarratorAnnouncement ^ CalculatorAnnouncement::GetNoRightParenthesisAddedAnnounc
AutomationNotificationProcessing::ImportantMostRecent);
}
-NarratorAnnouncement ^ CalculatorAnnouncement::GetGraphModeChangedAnnouncement(Platform::String ^ announcement)
+NarratorAnnouncement ^ CalculatorAnnouncement::GetGraphModeChangedAnnouncement(String ^ announcement)
{
return ref new NarratorAnnouncement(
announcement,
@@ -150,3 +153,30 @@ NarratorAnnouncement ^ CalculatorAnnouncement::GetGraphModeChangedAnnouncement(P
AutomationNotificationKind::ActionCompleted,
AutomationNotificationProcessing::ImportantMostRecent);
}
+
+NarratorAnnouncement ^ CalculatorAnnouncement::GetGraphViewChangedAnnouncement(String ^ announcement)
+{
+ return ref new NarratorAnnouncement(
+ announcement,
+ CalculatorActivityIds::GraphViewChanged,
+ AutomationNotificationKind::ActionCompleted,
+ AutomationNotificationProcessing::MostRecent);
+}
+
+NarratorAnnouncement ^ CalculatorAnnouncement::GetFunctionRemovedAnnouncement(String ^ announcement)
+{
+ return ref new NarratorAnnouncement(
+ announcement,
+ CalculatorActivityIds::FunctionRemoved,
+ AutomationNotificationKind::ItemRemoved,
+ AutomationNotificationProcessing::MostRecent);
+}
+
+NarratorAnnouncement ^ CalculatorAnnouncement::GetGraphViewBestFitChangedAnnouncement(Platform::String ^ announcement)
+{
+ return ref new NarratorAnnouncement(
+ announcement,
+ CalculatorActivityIds::GraphViewBestFitChanged,
+ AutomationNotificationKind::ActionCompleted,
+ AutomationNotificationProcessing::MostRecent);
+}
diff --git a/src/CalcViewModel/Common/Automation/NarratorAnnouncement.h b/src/CalcViewModel/Common/Automation/NarratorAnnouncement.h
index 81c3856b4..b378e5207 100644
--- a/src/CalcViewModel/Common/Automation/NarratorAnnouncement.h
+++ b/src/CalcViewModel/Common/Automation/NarratorAnnouncement.h
@@ -68,6 +68,10 @@ public
static NarratorAnnouncement ^ GetNoRightParenthesisAddedAnnouncement(Platform::String ^ announcement);
static NarratorAnnouncement ^ GetGraphModeChangedAnnouncement(Platform::String ^ announcement);
+ static NarratorAnnouncement ^ GetGraphViewChangedAnnouncement(Platform::String ^ announcement);
+ static NarratorAnnouncement ^ GetGraphViewBestFitChangedAnnouncement(Platform::String ^ announcement);
+
+ static NarratorAnnouncement ^ GetFunctionRemovedAnnouncement(Platform::String ^ announcement);
};
}
diff --git a/src/CalcViewModel/Common/CalculatorButtonUser.h b/src/CalcViewModel/Common/CalculatorButtonUser.h
index 8afd0fe9a..a7b72189f 100644
--- a/src/CalcViewModel/Common/CalculatorButtonUser.h
+++ b/src/CalcViewModel/Common/CalculatorButtonUser.h
@@ -109,7 +109,7 @@ public
InvCoth = (int) CM::Command::CommandACOTH,
CubeRoot = (int) CM::Command::CommandCUBEROOT,
TwoPowerX = (int) CM::Command::CommandPOW2,
- LogBaseX = (int) CM::Command::CommandLogBaseX,
+ LogBaseY = (int) CM::Command::CommandLogBaseY,
Nand = (int) CM::Command::CommandNand,
Nor = (int) CM::Command::CommandNor,
Abs = (int) CM::Command::CommandAbs,
@@ -202,6 +202,7 @@ public
GreaterThan,
GreaterThanOrEqualTo,
X,
- Y
+ Y,
+ Submit
};
}
diff --git a/src/CalcViewModel/Common/LocalizationService.cpp b/src/CalcViewModel/Common/LocalizationService.cpp
index 9060b04a6..c7fb9e0c3 100644
--- a/src/CalcViewModel/Common/LocalizationService.cpp
+++ b/src/CalcViewModel/Common/LocalizationService.cpp
@@ -545,7 +545,7 @@ unordered_map LocalizationService::GetTokenToReadableNameMap()
static vector> s_noParenEngineKeyResourceMap = { // Programmer mode functions
make_pair(L"9", L"LeftShift"),
make_pair(L"10", L"RightShift"),
- make_pair(L"LogBaseX", L"Logx"),
+ make_pair(L"LogBaseY", L"Logy"),
// Y Root scientific function
make_pair(L"16", L"YRoot")
diff --git a/src/CalcViewModel/Common/LocalizationStringUtil.h b/src/CalcViewModel/Common/LocalizationStringUtil.h
index 0e3d9dff9..73da6d0df 100644
--- a/src/CalcViewModel/Common/LocalizationStringUtil.h
+++ b/src/CalcViewModel/Common/LocalizationStringUtil.h
@@ -81,6 +81,18 @@ namespace CalculatorApp
{
return LocalizationStringUtilInternal::GetLocalizedString(pMessage, param1->Data(), param2->Data(), param3->Data(), param4->Data());
}
+
+ static Platform::String
+ ^ GetLocalizedString(
+ Platform::String ^ pMessage,
+ Platform::String ^ param1,
+ Platform::String ^ param2,
+ Platform::String ^ param3,
+ Platform::String ^ param4,
+ Platform::String ^ param5)
+ {
+ return LocalizationStringUtilInternal::GetLocalizedString(pMessage, param1->Data(), param2->Data(), param3->Data(), param4->Data(), param5->Data());
+ }
};
}
}
diff --git a/src/CalcViewModel/Common/TraceActivity.h b/src/CalcViewModel/Common/TraceActivity.h
deleted file mode 100644
index 003bf6bd0..000000000
--- a/src/CalcViewModel/Common/TraceActivity.h
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-
-#pragma once
-#include
-
-namespace CalculatorApp
-{
- // RAII wrapper that automatically sends the Stop event when the class gets destructed.
- class TraceActivity
- {
- public:
- TraceActivity()
- : m_channel(nullptr)
- , m_activity(nullptr)
- , m_fields(nullptr)
- {
- }
-
- TraceActivity(
- winrt::Windows::Foundation::Diagnostics::LoggingChannel channel,
- std::wstring_view activityName,
- winrt::Windows::Foundation::Diagnostics::LoggingFields fields)
- : m_channel(channel)
- , m_activityName(activityName)
- , m_fields(fields)
- , m_activity(nullptr)
- {
- // Write the activity's START event. Note that you must not specify keyword
- // or level for START and STOP events because they always use the activity's
- // keyword and level.
- m_activity = m_channel.StartActivity(
- m_activityName,
- m_fields,
- winrt::Windows::Foundation::Diagnostics::LoggingLevel::Verbose,
- winrt::Windows::Foundation::Diagnostics::LoggingOptions(WINEVENT_KEYWORD_RESPONSE_TIME));
- }
-
- ~TraceActivity()
- {
- if (m_activity != nullptr)
- {
- // Write the activity's STOP event.
- m_activity.StopActivity(m_activityName, m_fields);
- m_activity = nullptr;
- }
- }
-
- private:
- std::wstring m_activityName;
- winrt::Windows::Foundation::Diagnostics::LoggingChannel m_channel;
- winrt::Windows::Foundation::Diagnostics::LoggingFields m_fields;
- winrt::Windows::Foundation::Diagnostics::LoggingActivity m_activity;
- };
-}
diff --git a/src/CalcViewModel/Common/TraceLogger.cpp b/src/CalcViewModel/Common/TraceLogger.cpp
index 845b010bc..f58513de2 100644
--- a/src/CalcViewModel/Common/TraceLogger.cpp
+++ b/src/CalcViewModel/Common/TraceLogger.cpp
@@ -8,15 +8,15 @@
using namespace CalculatorApp;
using namespace CalculatorApp::Common;
+using namespace TraceLogging;
using namespace Concurrency;
using namespace std;
using namespace Platform;
-using namespace winrt;
-using namespace winrt::Windows::Foundation;
-using namespace winrt::Windows::Foundation::Diagnostics;
-using namespace winrt::Windows::Globalization;
-using namespace winrt::Windows::Globalization::DateTimeFormatting;
-using namespace winrt::Windows::System::UserProfile;
+using namespace Windows::Foundation;
+using namespace Windows::Foundation::Diagnostics;
+using namespace Windows::Globalization;
+using namespace Windows::Globalization::DateTimeFormatting;
+using namespace Windows::System::UserProfile;
namespace CalculatorApp
{
@@ -35,36 +35,23 @@ namespace CalculatorApp
constexpr auto EVENT_NAME_VISUAL_STATE_CHANGED = L"VisualStateChanged";
constexpr auto EVENT_NAME_CONVERTER_INPUT_RECEIVED = L"ConverterInputReceived";
constexpr auto EVENT_NAME_INPUT_PASTED = L"InputPasted";
+ constexpr auto EVENT_NAME_SHOW_HIDE_BUTTON_CLICKED = L"ShowHideButtonClicked";
+ constexpr auto EVENT_NAME_GRAPH_BUTTON_CLICKED = L"GraphButtonClicked";
+ constexpr auto EVENT_NAME_GRAPH_LINE_STYLE_CHANGED = L"GraphLineStyleChanged";
+ constexpr auto EVENT_NAME_VARIABLE_CHANGED = L"VariableChanged";
+ constexpr auto EVENT_NAME_VARIABLE_SETTING_CHANGED = L"VariableSettingChanged";
+ constexpr auto EVENT_NAME_GRAPH_SETTINGS_CHANGED = L"GraphSettingsChanged";
+ constexpr auto EVENT_NAME_GRAPH_THEME = L"GraphTheme";
constexpr auto EVENT_NAME_EXCEPTION = L"Exception";
- constexpr auto PDT_PRIVACY_DATA_TAG = L"PartA_PrivTags";
- constexpr auto PDT_PRODUCT_AND_SERVICE_USAGE = 0x0000'0000'0200'0000u;
-
-#ifdef SEND_DIAGNOSTICS
- // c.f. WINEVENT_KEYWORD_RESERVED_63-56 0xFF00000000000000 // Bits 63-56 - channel keywords
- // c.f. WINEVENT_KEYWORD_* 0x00FF000000000000 // Bits 55-48 - system-reserved keywords
- constexpr int64_t MICROSOFT_KEYWORD_LEVEL_1 = 0x0000800000000000; // Bit 47
- constexpr int64_t MICROSOFT_KEYWORD_LEVEL_2 = 0x0000400000000000; // Bit 46
- constexpr int64_t MICROSOFT_KEYWORD_LEVEL_3 = 0x0000200000000000; // Bit 45
-#else
- // define all Keyword options as 0 when we do not want to upload app diagnostics
- constexpr int64_t MICROSOFT_KEYWORD_LEVEL_1 = 0;
- constexpr int64_t MICROSOFT_KEYWORD_LEVEL_2 = 0;
- constexpr int64_t MICROSOFT_KEYWORD_LEVEL_3 = 0;
-#endif
+ constexpr auto CALC_MODE = L"CalcMode";
+ constexpr auto GRAPHING_MODE = L"Graphing";
#pragma region TraceLogger setup and cleanup
TraceLogger::TraceLogger()
- : g_calculatorProvider(
- L"MicrosoftCalculator",
- LoggingChannelOptions(GUID{ 0x4f50731a, 0x89cf, 0x4782, 0xb3, 0xe0, 0xdc, 0xe8, 0xc9, 0x4, 0x76, 0xba }),
- GUID{ 0x905ca09, 0x610e, 0x401e, 0xb6, 0x50, 0x2f, 0x21, 0x29, 0x80, 0xb9, 0xe0 })
- , // Unique providerID {0905CA09-610E-401E-B650-2F212980B9E0}
- m_appLaunchActivity{ nullptr }
{
- CoCreateGuid(&sessionGuid);
}
TraceLogger ^ TraceLogger::GetInstance()
@@ -73,33 +60,6 @@ namespace CalculatorApp
return s_selfInstance;
}
- bool TraceLogger::GetTraceLoggingProviderEnabled()
- {
- return g_calculatorProvider.Enabled();
- }
-
-#pragma region Tracing methods
- void TraceLogger::LogLevel1Event(wstring_view eventName, LoggingFields fields)
- {
- g_calculatorProvider.LogEvent(eventName, fields, LoggingLevel::Verbose, LoggingOptions(MICROSOFT_KEYWORD_LEVEL_1));
- }
-
- void TraceLogger::LogLevel2Event(wstring_view eventName, LoggingFields fields)
- {
- g_calculatorProvider.LogEvent(eventName, fields, LoggingLevel::Verbose, LoggingOptions(MICROSOFT_KEYWORD_LEVEL_2));
- }
-
- void TraceLogger::LogLevel3Event(wstring_view eventName, LoggingFields fields)
- {
- g_calculatorProvider.LogEvent(eventName, fields, LoggingLevel::Verbose, LoggingOptions(MICROSOFT_KEYWORD_LEVEL_3));
- }
-
- unique_ptr TraceLogger::CreateTraceActivity(wstring_view eventName, LoggingFields fields)
- {
- return make_unique(g_calculatorProvider, eventName, fields);
- }
-#pragma endregion
-
// return true if windowId is logged once else return false
bool TraceLogger::IsWindowIdInLog(int windowId)
{
@@ -116,18 +76,12 @@ namespace CalculatorApp
void TraceLogger::LogVisualStateChanged(ViewMode mode, String ^ state, bool isAlwaysOnTop)
{
- if (!GetTraceLoggingProviderEnabled())
- {
- return;
- }
+ auto fields = ref new LoggingFields();
- LoggingFields fields{};
- fields.AddGuid(L"SessionGuid", sessionGuid);
- fields.AddString(L"CalcMode", NavCategory::GetFriendlyName(mode)->Data());
- fields.AddString(L"VisualState", state->Data());
- fields.AddBoolean(L"IsAlwaysOnTop", isAlwaysOnTop);
- fields.AddUInt64(PDT_PRIVACY_DATA_TAG, PDT_PRODUCT_AND_SERVICE_USAGE);
- LogLevel2Event(EVENT_NAME_VISUAL_STATE_CHANGED, fields);
+ fields->AddString(StringReference(CALC_MODE), NavCategory::GetFriendlyName(mode));
+ fields->AddString(StringReference(L"VisualState"), state);
+ fields->AddBoolean(StringReference(L"IsAlwaysOnTop"), isAlwaysOnTop);
+ TraceLoggingCommon::GetInstance()->LogLevel2Event(StringReference(EVENT_NAME_VISUAL_STATE_CHANGED), fields);
}
void TraceLogger::LogWindowCreated(ViewMode mode, int windowId)
@@ -138,122 +92,69 @@ namespace CalculatorApp
windowIdLog.push_back(windowId);
}
- if (!GetTraceLoggingProviderEnabled())
- return;
-
- LoggingFields fields{};
- fields.AddGuid(L"SessionGuid", sessionGuid);
- fields.AddString(L"CalcMode", NavCategory::GetFriendlyName(mode)->Data());
- fields.AddUInt64(L"NumOfOpenWindows", currentWindowCount);
- fields.AddUInt64(PDT_PRIVACY_DATA_TAG, PDT_PRODUCT_AND_SERVICE_USAGE);
- LogLevel2Event(EVENT_NAME_WINDOW_ON_CREATED, fields);
+ auto fields = ref new LoggingFields();
+ fields->AddString(StringReference(CALC_MODE), NavCategory::GetFriendlyName(mode));
+ fields->AddUInt64(StringReference(L"NumOfOpenWindows"), currentWindowCount);
+ TraceLoggingCommon::GetInstance()->LogLevel2Event(StringReference(EVENT_NAME_WINDOW_ON_CREATED), fields);
}
void TraceLogger::LogModeChange(ViewMode mode)
{
- if (!GetTraceLoggingProviderEnabled())
- return;
-
if (NavCategory::IsValidViewMode(mode))
{
- LoggingFields fields{};
- fields.AddGuid(L"SessionGuid", sessionGuid);
- fields.AddString(L"CalcMode", NavCategory::GetFriendlyName(mode)->Data());
- fields.AddUInt64(PDT_PRIVACY_DATA_TAG, PDT_PRODUCT_AND_SERVICE_USAGE);
- LogLevel2Event(EVENT_NAME_MODE_CHANGED, fields);
+ auto fields = ref new LoggingFields();
+ ;
+ fields->AddString(StringReference(CALC_MODE), NavCategory::GetFriendlyName(mode));
+ TraceLoggingCommon::GetInstance()->LogLevel2Event(StringReference(EVENT_NAME_MODE_CHANGED), fields);
}
}
void TraceLogger::LogHistoryItemLoad(ViewMode mode, int historyListSize, int loadedIndex)
{
- if (!GetTraceLoggingProviderEnabled())
- {
- return;
- }
-
- LoggingFields fields{};
- fields.AddGuid(L"SessionGuid", sessionGuid);
- fields.AddString(L"CalcMode", NavCategory::GetFriendlyName(mode)->Data());
- fields.AddInt32(L"HistoryListSize", historyListSize);
- fields.AddInt32(L"HistoryItemIndex", loadedIndex);
- fields.AddUInt64(PDT_PRIVACY_DATA_TAG, PDT_PRODUCT_AND_SERVICE_USAGE);
- LogLevel2Event(EVENT_NAME_HISTORY_ITEM_LOAD, fields);
+ auto fields = ref new LoggingFields();
+ fields->AddString(StringReference(CALC_MODE), NavCategory::GetFriendlyName(mode));
+ fields->AddInt32(StringReference(L"HistoryListSize"), historyListSize);
+ fields->AddInt32(StringReference(L"HistoryItemIndex"), loadedIndex);
+ TraceLoggingCommon::GetInstance()->LogLevel2Event(StringReference(EVENT_NAME_HISTORY_ITEM_LOAD), fields);
}
void TraceLogger::LogMemoryItemLoad(ViewMode mode, int memoryListSize, int loadedIndex)
{
- if (!GetTraceLoggingProviderEnabled())
- {
- return;
- }
-
- LoggingFields fields{};
- fields.AddGuid(L"SessionGuid", sessionGuid);
- fields.AddString(L"CalcMode", NavCategory::GetFriendlyName(mode)->Data());
- fields.AddInt32(L"MemoryListSize", memoryListSize);
- fields.AddInt32(L"MemoryItemIndex", loadedIndex);
- fields.AddUInt64(PDT_PRIVACY_DATA_TAG, PDT_PRODUCT_AND_SERVICE_USAGE);
- LogLevel2Event(EVENT_NAME_MEMORY_ITEM_LOAD, fields);
+ auto fields = ref new LoggingFields();
+ fields->AddString(StringReference(CALC_MODE), NavCategory::GetFriendlyName(mode));
+ fields->AddInt32(StringReference(L"MemoryListSize"), memoryListSize);
+ fields->AddInt32(StringReference(L"MemoryItemIndex"), loadedIndex);
+ TraceLoggingCommon::GetInstance()->LogLevel2Event(StringReference(EVENT_NAME_MEMORY_ITEM_LOAD), fields);
}
void TraceLogger::LogError(ViewMode mode, Platform::String ^ functionName, Platform::String ^ errorString)
{
- if (!GetTraceLoggingProviderEnabled())
- return;
-
- LoggingFields fields{};
- fields.AddGuid(L"SessionGuid", sessionGuid);
- fields.AddString(L"CalcMode", NavCategory::GetFriendlyName(mode)->Data());
- fields.AddString(L"FunctionName", functionName->Data());
- fields.AddString(L"Message", errorString->Data());
- fields.AddUInt64(PDT_PRIVACY_DATA_TAG, PDT_PRODUCT_AND_SERVICE_USAGE);
- LogLevel2Event(EVENT_NAME_EXCEPTION, fields);
+ auto fields = ref new LoggingFields();
+ fields->AddString(StringReference(CALC_MODE), NavCategory::GetFriendlyName(mode));
+ fields->AddString(StringReference(L"FunctionName"), functionName);
+ fields->AddString(StringReference(L"Message"), errorString);
+ TraceLoggingCommon::GetInstance()->LogLevel2Event(StringReference(EVENT_NAME_EXCEPTION), fields);
}
void TraceLogger::LogStandardException(ViewMode mode, wstring_view functionName, const exception& e)
{
- if (!GetTraceLoggingProviderEnabled())
- return;
-
- LoggingFields fields{};
- fields.AddGuid(L"SessionGuid", sessionGuid);
- fields.AddString(L"CalcMode", NavCategory::GetFriendlyName(mode)->Data());
- fields.AddString(L"FunctionName", functionName);
+ auto fields = ref new LoggingFields();
+ fields->AddString(StringReference(CALC_MODE), NavCategory::GetFriendlyName(mode));
+ fields->AddString(StringReference(L"FunctionName"), StringReference(functionName.data()));
wstringstream exceptionMessage;
exceptionMessage << e.what();
- fields.AddString(L"Message", exceptionMessage.str());
- fields.AddUInt64(PDT_PRIVACY_DATA_TAG, PDT_PRODUCT_AND_SERVICE_USAGE);
- LogLevel2Event(EVENT_NAME_EXCEPTION, fields);
- }
-
- void TraceLogger::LogWinRTException(ViewMode mode, wstring_view functionName, hresult_error const& e)
- {
- if (!GetTraceLoggingProviderEnabled())
- return;
-
- LoggingFields fields{};
- fields.AddGuid(L"SessionGuid", sessionGuid);
- fields.AddString(L"CalcMode", NavCategory::GetFriendlyName(mode)->Data());
- fields.AddString(L"FunctionName", functionName);
- fields.AddString(L"Message", e.message());
- fields.AddInt32(L"HRESULT", e.code());
- fields.AddUInt64(PDT_PRIVACY_DATA_TAG, PDT_PRODUCT_AND_SERVICE_USAGE);
- LogLevel2Event(EVENT_NAME_EXCEPTION, fields);
+ fields->AddString(StringReference(L"Message"), StringReference(exceptionMessage.str().data()));
+ TraceLoggingCommon::GetInstance()->LogLevel2Event(StringReference(EVENT_NAME_EXCEPTION), fields);
}
void TraceLogger::LogPlatformException(ViewMode mode, wstring_view functionName, Platform::Exception ^ e)
{
- if (!GetTraceLoggingProviderEnabled())
- return;
-
- LoggingFields fields{};
- fields.AddGuid(L"SessionGuid", sessionGuid);
- fields.AddString(L"CalcMode", NavCategory::GetFriendlyName(mode)->Data());
- fields.AddString(L"FunctionName", functionName);
- fields.AddString(L"Message", e->Message->Data());
- fields.AddInt32(L"HRESULT", e->HResult);
- fields.AddUInt64(PDT_PRIVACY_DATA_TAG, PDT_PRODUCT_AND_SERVICE_USAGE);
- LogLevel2Event(EVENT_NAME_EXCEPTION, fields);
+ auto fields = ref new LoggingFields();
+ fields->AddString(StringReference(CALC_MODE), NavCategory::GetFriendlyName(mode));
+ fields->AddString(StringReference(L"FunctionName"), StringReference(functionName.data()));
+ fields->AddString(StringReference(L"Message"), e->Message);
+ fields->AddInt32(StringReference(L"HRESULT"), e->HResult);
+ TraceLoggingCommon::GetInstance()->LogLevel2Event(StringReference(EVENT_NAME_EXCEPTION), fields);
}
void TraceLogger::UpdateButtonUsage(NumbersAndOperatorsEnum button, ViewMode mode)
@@ -305,9 +206,6 @@ namespace CalculatorApp
void TraceLogger::LogButtonUsage()
{
- if (!GetTraceLoggingProviderEnabled())
- return;
-
// Writer lock for the buttonLog resource
reader_writer_lock::scoped_lock lock(s_traceLoggerLock);
@@ -330,11 +228,9 @@ namespace CalculatorApp
}
}
- LoggingFields fields{};
- fields.AddGuid(L"SessionGuid", sessionGuid);
- fields.AddString(L"ButtonUsage", buttonUsageString->Data());
- fields.AddUInt64(PDT_PRIVACY_DATA_TAG, PDT_PRODUCT_AND_SERVICE_USAGE);
- LogLevel2Event(EVENT_NAME_BUTTON_USAGE, fields);
+ auto fields = ref new LoggingFields();
+ fields->AddString(StringReference(L"ButtonUsage"), buttonUsageString);
+ TraceLoggingCommon::GetInstance()->LogLevel2Event(StringReference(EVENT_NAME_BUTTON_USAGE), fields);
buttonLog.clear();
}
@@ -342,46 +238,89 @@ namespace CalculatorApp
void TraceLogger::LogDateCalculationModeUsed(bool AddSubtractMode)
{
const wchar_t* calculationType = AddSubtractMode ? L"AddSubtractMode" : L"DateDifferenceMode";
- LoggingFields fields{};
- fields.AddGuid(L"SessionGuid", sessionGuid);
- fields.AddString(L"CalcMode", NavCategory::GetFriendlyName(ViewMode::Date)->Data());
- fields.AddString(L"CalculationType", calculationType);
- fields.AddUInt64(PDT_PRIVACY_DATA_TAG, PDT_PRODUCT_AND_SERVICE_USAGE);
- LogLevel2Event(EVENT_NAME_DATE_CALCULATION_MODE_USED, fields);
+ auto fields = ref new LoggingFields();
+ fields->AddString(StringReference(CALC_MODE), NavCategory::GetFriendlyName(ViewMode::Date));
+ fields->AddString(StringReference(L"CalculationType"), StringReference(calculationType));
+ TraceLoggingCommon::GetInstance()->LogLevel2Event(StringReference(EVENT_NAME_DATE_CALCULATION_MODE_USED), fields);
}
void TraceLogger::LogConverterInputReceived(ViewMode mode)
{
- if (!GetTraceLoggingProviderEnabled())
- return;
-
- LoggingFields fields{};
- fields.AddGuid(L"SessionGuid", sessionGuid);
- fields.AddString(L"CalcMode", NavCategory::GetFriendlyName(mode)->Data());
- fields.AddUInt64(PDT_PRIVACY_DATA_TAG, PDT_PRODUCT_AND_SERVICE_USAGE);
- LogLevel2Event(EVENT_NAME_CONVERTER_INPUT_RECEIVED, fields);
+ auto fields = ref new LoggingFields();
+ fields->AddString(StringReference(CALC_MODE), NavCategory::GetFriendlyName(mode));
+ TraceLoggingCommon::GetInstance()->LogLevel2Event(StringReference(EVENT_NAME_CONVERTER_INPUT_RECEIVED), fields);
}
void TraceLogger::LogNavBarOpened()
{
- if (!GetTraceLoggingProviderEnabled())
- return;
-
- LoggingFields fields{};
- fields.AddGuid(L"SessionGuid", sessionGuid);
- fields.AddUInt64(PDT_PRIVACY_DATA_TAG, PDT_PRODUCT_AND_SERVICE_USAGE);
- LogLevel2Event(EVENT_NAME_NAV_BAR_OPENED, fields);
+ auto fields = ref new LoggingFields();
+ TraceLoggingCommon::GetInstance()->LogLevel2Event(StringReference(EVENT_NAME_NAV_BAR_OPENED), fields);
}
void TraceLogger::LogInputPasted(ViewMode mode)
{
- if (!GetTraceLoggingProviderEnabled())
- return;
+ auto fields = ref new LoggingFields();
+ fields->AddString(StringReference(CALC_MODE), NavCategory::GetFriendlyName(mode));
+ TraceLoggingCommon::GetInstance()->LogLevel2Event(StringReference(EVENT_NAME_INPUT_PASTED), fields);
+ }
+
+ void TraceLogger::LogShowHideButtonClicked(bool isHideButton)
+ {
+ auto fields = ref new LoggingFields();
+ fields->AddString(StringReference(CALC_MODE), StringReference(GRAPHING_MODE));
+ fields->AddBoolean(StringReference(L"IsHideButton"), isHideButton);
+ TraceLoggingCommon::GetInstance()->LogLevel2Event(StringReference(EVENT_NAME_SHOW_HIDE_BUTTON_CLICKED), fields);
+ }
+
+ void TraceLogger::LogGraphButtonClicked(GraphButton buttonName, GraphButtonValue buttonValue)
+ {
+ auto fields = ref new LoggingFields();
+ fields->AddString(StringReference(CALC_MODE), StringReference(GRAPHING_MODE));
+ fields->AddInt16(StringReference(L"ButtonName"), static_cast(buttonName));
+ fields->AddInt16(StringReference(L"ButtonValue"), static_cast(buttonValue));
+ TraceLoggingCommon::GetInstance()->LogLevel2Event(StringReference(EVENT_NAME_GRAPH_BUTTON_CLICKED), fields);
+ }
+
+ void TraceLogger::LogGraphLineStyleChanged(LineStyleType style)
+ {
+ auto fields = ref new LoggingFields();
+ fields->AddString(StringReference(CALC_MODE), StringReference(GRAPHING_MODE));
+ fields->AddInt16(StringReference(L"StyleType"), static_cast(style));
+ TraceLoggingCommon::GetInstance()->LogLevel2Event(StringReference(EVENT_NAME_GRAPH_LINE_STYLE_CHANGED), fields);
+ }
+
+ void TraceLogger::LogVariableChanged(String ^ inputChangedType, String ^ variableName)
+ {
+ auto fields = ref new LoggingFields();
+ fields->AddString(StringReference(CALC_MODE), StringReference(GRAPHING_MODE));
+ fields->AddString(StringReference(L"InputChangedType"), inputChangedType);
+ fields->AddString(StringReference(L"VariableName"), variableName);
+ TraceLoggingCommon::GetInstance()->LogLevel2Event(StringReference(EVENT_NAME_VARIABLE_CHANGED), fields);
+ }
+ void TraceLogger::LogVariableSettingsChanged(String ^ setting)
+ {
+ auto fields = ref new LoggingFields();
+ fields->AddString(StringReference(CALC_MODE), StringReference(GRAPHING_MODE));
+ fields->AddString(StringReference(L"SettingChanged"), setting);
+ TraceLoggingCommon::GetInstance()->LogLevel2Event(StringReference(EVENT_NAME_VARIABLE_SETTING_CHANGED), fields);
+ }
+
+ void TraceLogger::LogGraphSettingsChanged(GraphSettingsType settingType, String ^ settingValue)
+ {
+ auto fields = ref new LoggingFields();
+ fields->AddString(StringReference(CALC_MODE), StringReference(GRAPHING_MODE));
+ fields->AddInt16(L"SettingType", static_cast(settingType));
+ fields->AddString(L"SettingValue", settingValue);
+
+ TraceLoggingCommon::GetInstance()->LogLevel2Event(StringReference(EVENT_NAME_GRAPH_SETTINGS_CHANGED), fields);
+ }
+
+ void TraceLogger::LogGraphTheme(String ^ graphTheme)
+ {
+ auto fields = ref new LoggingFields();
+ fields->AddString(StringReference(CALC_MODE), StringReference(GRAPHING_MODE));
+ fields->AddString(L"GraphTheme", graphTheme);
- LoggingFields fields{};
- fields.AddGuid(L"SessionGuid", sessionGuid);
- fields.AddString(L"Mode", NavCategory::GetFriendlyName(mode)->Data());
- fields.AddUInt64(PDT_PRIVACY_DATA_TAG, PDT_PRODUCT_AND_SERVICE_USAGE);
- LogLevel2Event(EVENT_NAME_INPUT_PASTED, fields);
+ TraceLoggingCommon::GetInstance()->LogLevel2Event(StringReference(EVENT_NAME_GRAPH_THEME), fields);
}
}
diff --git a/src/CalcViewModel/Common/TraceLogger.h b/src/CalcViewModel/Common/TraceLogger.h
index fa24f8e08..cef592e8c 100644
--- a/src/CalcViewModel/Common/TraceLogger.h
+++ b/src/CalcViewModel/Common/TraceLogger.h
@@ -3,13 +3,9 @@
#pragma once
-#include "CalcManager/Command.h"
-#include "TraceActivity.h"
#include "NavCategory.h"
#include "CalculatorButtonUser.h"
-static const int maxFunctionSize = (int)CalculationManager::Command::CommandBINEDITEND;
-
// A trace logging provider can only be instantiated and registered once per module.
// This class implements a singleton model ensure that only one instance is created.
namespace CalculatorApp
@@ -28,12 +24,44 @@ namespace CalculatorApp
}
};
-public
- ref class TraceLogger sealed
+ public enum class GraphSettingsType
+ {
+ Grid,
+ TrigUnits,
+ Theme
+ };
+
+ public enum class GraphButton
+ {
+ StylePicker,
+ RemoveFunction,
+ ActiveTracingChecked,
+ ActiveTracingUnchecked,
+ GraphSettings,
+ Share,
+ ZoomIn,
+ ZoomOut,
+ GraphView
+ };
+
+ public enum class GraphButtonValue
+ {
+ None,
+ AutomaticBestFit,
+ ManualAdjustment
+ };
+
+ public enum class LineStyleType
+ {
+ Color,
+ Pattern
+ };
+
+ public ref class TraceLogger sealed
{
public:
static TraceLogger ^ GetInstance();
- bool GetTraceLoggingProviderEnabled();
+
void LogModeChange(CalculatorApp::Common::ViewMode mode);
void LogHistoryItemLoad(CalculatorApp::Common::ViewMode mode, int historyListSize, int loadedIndex);
void LogMemoryItemLoad(CalculatorApp::Common::ViewMode mode, int memoryListSize, int loadedIndex);
@@ -48,9 +76,15 @@ public
void LogConverterInputReceived(CalculatorApp::Common::ViewMode mode);
void LogNavBarOpened();
void LogError(CalculatorApp::Common::ViewMode mode, Platform::String ^ functionName, Platform::String ^ errorString);
- internal :
+ void LogShowHideButtonClicked(bool isHideButton);
+ void LogGraphButtonClicked(GraphButton buttonName, GraphButtonValue buttonValue);
+ void LogGraphLineStyleChanged(LineStyleType style);
+ void LogVariableChanged(Platform::String ^ inputChangedType, Platform::String ^ variableName);
+ void LogVariableSettingsChanged(Platform::String ^ setting);
+ void LogGraphSettingsChanged(GraphSettingsType settingsType, Platform::String ^ settingValue);
+ void LogGraphTheme(Platform::String ^ graphTheme);
+ internal:
void LogStandardException(CalculatorApp::Common::ViewMode mode, std::wstring_view functionName, _In_ const std::exception& e);
- void LogWinRTException(CalculatorApp::Common::ViewMode mode, std::wstring_view functionName, _In_ winrt::hresult_error const& e);
void LogPlatformException(CalculatorApp::Common::ViewMode mode, std::wstring_view functionName, _In_ Platform::Exception ^ e);
void LogInputPasted(CalculatorApp::Common::ViewMode mode);
@@ -58,24 +92,8 @@ public
// Create an instance of TraceLogger
TraceLogger();
- // As mentioned in Microsoft's Privacy Statement(https://privacy.microsoft.com/en-US/privacystatement#maindiagnosticsmodule),
- // sampling is involved in Microsoft's diagnostic data collection process.
- // These keywords provide additional input into how frequently an event might be sampled.
- // The lower the level of the keyword, the higher the possibility that the corresponding event may be sampled.
- void LogLevel1Event(std::wstring_view eventName, winrt::Windows::Foundation::Diagnostics::LoggingFields fields);
- void LogLevel2Event(std::wstring_view eventName, winrt::Windows::Foundation::Diagnostics::LoggingFields fields);
- void LogLevel3Event(std::wstring_view eventName, winrt::Windows::Foundation::Diagnostics::LoggingFields fields);
-
- std::unique_ptr CreateTraceActivity(std::wstring_view activityName, winrt::Windows::Foundation::Diagnostics::LoggingFields fields);
-
- winrt::Windows::Foundation::Diagnostics::LoggingChannel g_calculatorProvider;
-
std::vector buttonLog;
std::vector windowIdLog;
-
- GUID sessionGuid;
uint64 currentWindowCount = 0;
-
- winrt::Windows::Foundation::Diagnostics::LoggingActivity m_appLaunchActivity;
};
}
diff --git a/src/CalcViewModel/Common/Utils.cpp b/src/CalcViewModel/Common/Utils.cpp
index 27c325415..d87e78926 100644
--- a/src/CalcViewModel/Common/Utils.cpp
+++ b/src/CalcViewModel/Common/Utils.cpp
@@ -36,17 +36,6 @@ void Utils::IFTPlatformException(HRESULT hr)
}
}
-String ^ Utils::GetStringValue(String ^ input)
-{
- // Remove first and last " characters
- if (input->Length() >= 3)
- {
- wstring out(input->Begin() + 1, input->End() - 1);
- return ref new String(out.c_str());
- }
- return input;
-}
-
double Utils::GetDoubleFromWstring(wstring input)
{
constexpr wchar_t unWantedChars[] = { L' ', L',', 8234, 8235, 8236, 8237 };
diff --git a/src/CalcViewModel/Common/Utils.h b/src/CalcViewModel/Common/Utils.h
index 7836b9bb1..670274c42 100644
--- a/src/CalcViewModel/Common/Utils.h
+++ b/src/CalcViewModel/Common/Utils.h
@@ -98,7 +98,7 @@ private:
#define OBSERVABLE_NAMED_PROPERTY_R(t, n) \
OBSERVABLE_PROPERTY_R(t, n) \
- internal: \
+public: \
static property Platform::String ^ n##PropertyName \
{ \
Platform::String ^ get() { return Platform::StringReference(L#n); } \
@@ -108,7 +108,7 @@ private:
#define OBSERVABLE_NAMED_PROPERTY_RW(t, n) \
OBSERVABLE_PROPERTY_RW(t, n) \
- internal: \
+public: \
static property Platform::String ^ n##PropertyName \
{ \
Platform::String ^ get() { return Platform::StringReference(L#n); } \
@@ -373,7 +373,6 @@ namespace Utils
}
void IFTPlatformException(HRESULT hr);
- Platform::String ^ GetStringValue(Platform::String ^ input);
bool IsLastCharacterTarget(std::wstring const& input, wchar_t target);
// Return wstring after removing characters specified by unwantedChars array
diff --git a/src/CalcViewModel/DateCalculatorViewModel.cpp b/src/CalcViewModel/DateCalculatorViewModel.cpp
index 20ee012bf..a34c1288d 100644
--- a/src/CalcViewModel/DateCalculatorViewModel.cpp
+++ b/src/CalcViewModel/DateCalculatorViewModel.cpp
@@ -60,7 +60,7 @@ DateCalculatorViewModel::DateCalculatorViewModel()
auto today = calendar->GetDateTime();
// FromDate and ToDate should be clipped (adjusted to a consistent hour in UTC)
- m_fromDate = m_toDate = ClipTime(today, true);
+ m_fromDate = m_toDate = ClipTime(today);
// StartDate should not be clipped
m_startDate = today;
@@ -83,7 +83,7 @@ DateCalculatorViewModel::DateCalculatorViewModel()
DayOfWeek trueDayOfWeek = calendar->DayOfWeek;
- DateTime clippedTime = ClipTime(today, false);
+ DateTime clippedTime = ClipTime(today);
calendar->SetDateTime(clippedTime);
if (calendar->DayOfWeek != trueDayOfWeek)
{
@@ -113,8 +113,8 @@ void DateCalculatorViewModel::OnInputsChanged()
{
if (m_IsDateDiffMode)
{
- DateTime clippedFromDate = ClipTime(FromDate, true);
- DateTime clippedToDate = ClipTime(ToDate, true);
+ DateTime clippedFromDate = ClipTime(FromDate);
+ DateTime clippedToDate = ClipTime(ToDate);
// Calculate difference between two dates
auto dateDiff = m_dateCalcEngine->TryGetDateDifference(clippedFromDate, clippedToDate, m_daysOutputFormat);
diff --git a/src/CalcViewModel/DateCalculatorViewModel.h b/src/CalcViewModel/DateCalculatorViewModel.h
index d9e73f4bc..485737841 100644
--- a/src/CalcViewModel/DateCalculatorViewModel.h
+++ b/src/CalcViewModel/DateCalculatorViewModel.h
@@ -110,7 +110,7 @@ namespace CalculatorApp
Platform::String ^ GetDateDiffString() const;
Platform::String ^ GetDateDiffStringInDays() const;
Platform::String ^ GetLocalizedNumberString(int value) const;
- static Windows::Foundation::DateTime ClipTime(Windows::Foundation::DateTime dateTime, bool adjustToLocalTime);
+ static Windows::Foundation::DateTime ClipTime(Windows::Foundation::DateTime dateTime, bool adjustUsingLocalTime = false);
property bool IsOutOfBound
{
diff --git a/src/CalcViewModel/GraphingCalculator/EquationViewModel.cpp b/src/CalcViewModel/GraphingCalculator/EquationViewModel.cpp
index 94b97794f..666f55ec1 100644
--- a/src/CalcViewModel/GraphingCalculator/EquationViewModel.cpp
+++ b/src/CalcViewModel/GraphingCalculator/EquationViewModel.cpp
@@ -11,6 +11,7 @@ using namespace Graphing;
using namespace Platform;
using namespace Platform::Collections;
using namespace std;
+using namespace Windows::ApplicationModel::Resources;
using namespace Windows::UI;
using namespace Windows::UI::Xaml;
using namespace Windows::Foundation::Collections;
@@ -32,11 +33,11 @@ namespace CalculatorApp::ViewModel
{
}
- EquationViewModel::EquationViewModel(Equation ^ equation, int functionLabelIndex, Windows::UI::Color color)
+ EquationViewModel::EquationViewModel(Equation ^ equation, int functionLabelIndex, Windows::UI::Color color, int colorIndex)
: m_AnalysisErrorVisible{ false }
, m_FunctionLabelIndex{ functionLabelIndex }
, m_KeyGraphFeaturesItems{ ref new Vector() }
- , m_resourceLoader{ Windows::ApplicationModel::Resources::ResourceLoader::GetForCurrentView() }
+ , m_resourceLoader{ ::ResourceLoader::GetForCurrentView() }
{
if (equation == nullptr)
{
@@ -45,6 +46,7 @@ namespace CalculatorApp::ViewModel
GraphEquation = equation;
LineColor = color;
+ LineColorIndex = colorIndex;
IsLineEnabled = true;
}
@@ -72,11 +74,14 @@ namespace CalculatorApp::ViewModel
AddKeyGraphFeature(m_resourceLoader->GetString(L"YIntercept"), graphEquation->YIntercept, m_resourceLoader->GetString(L"KGFYInterceptNone"));
AddKeyGraphFeature(m_resourceLoader->GetString(L"Minima"), graphEquation->Minima, m_resourceLoader->GetString(L"KGFMinimaNone"));
AddKeyGraphFeature(m_resourceLoader->GetString(L"Maxima"), graphEquation->Maxima, m_resourceLoader->GetString(L"KGFMaximaNone"));
- AddKeyGraphFeature(m_resourceLoader->GetString(L"InflectionPoints"), graphEquation->InflectionPoints, m_resourceLoader->GetString(L"KGFInflectionPointsNone"));
+ AddKeyGraphFeature(
+ m_resourceLoader->GetString(L"InflectionPoints"), graphEquation->InflectionPoints, m_resourceLoader->GetString(L"KGFInflectionPointsNone"));
AddKeyGraphFeature(
m_resourceLoader->GetString(L"VerticalAsymptotes"), graphEquation->VerticalAsymptotes, m_resourceLoader->GetString(L"KGFVerticalAsymptotesNone"));
AddKeyGraphFeature(
- m_resourceLoader->GetString(L"HorizontalAsymptotes"), graphEquation->HorizontalAsymptotes, m_resourceLoader->GetString(L"KGFHorizontalAsymptotesNone"));
+ m_resourceLoader->GetString(L"HorizontalAsymptotes"),
+ graphEquation->HorizontalAsymptotes,
+ m_resourceLoader->GetString(L"KGFHorizontalAsymptotesNone"));
AddKeyGraphFeature(
m_resourceLoader->GetString(L"ObliqueAsymptotes"), graphEquation->ObliqueAsymptotes, m_resourceLoader->GetString(L"KGFObliqueAsymptotesNone"));
AddParityKeyGraphFeature(graphEquation);
@@ -299,4 +304,154 @@ namespace CalculatorApp::ViewModel
KeyGraphFeaturesItems->Append(tooComplexItem);
}
+
+ String ^ EquationViewModel::EquationErrorText(ErrorType errorType, int errorCode)
+ {
+ auto resLoader = ResourceLoader::GetForCurrentView();
+ if (errorType == ::ErrorType::Evaluation)
+ {
+ switch (static_cast(errorCode))
+ {
+ case (EvaluationErrorCode::Overflow):
+ return resLoader->GetString(L"Overflow");
+ break;
+ case (EvaluationErrorCode::RequireRadiansMode):
+ return resLoader->GetString(L"RequireRadiansMode");
+ break;
+ case (EvaluationErrorCode::TooComplexToSolve):
+ return resLoader->GetString(L"TooComplexToSolve");
+ break;
+ case (EvaluationErrorCode::RequireDegreesMode):
+ return resLoader->GetString(L"RequireDegreesMode");
+ break;
+ case (EvaluationErrorCode::FactorialInvalidArgument):
+ case (EvaluationErrorCode::Factorial2InvalidArgument):
+ return resLoader->GetString(L"FactorialInvalidArgument");
+ break;
+ case (EvaluationErrorCode::FactorialCannotPerformOnLargeNumber):
+ return resLoader->GetString(L"FactorialCannotPerformOnLargeNumber");
+ break;
+ case (EvaluationErrorCode::ModuloCannotPerformOnFloat):
+ return resLoader->GetString(L"ModuloCannotPerformOnFloat");
+ break;
+ case (EvaluationErrorCode::EquationTooComplexToSolve):
+ case (EvaluationErrorCode::EquationTooComplexToSolveSymbolic):
+ case (EvaluationErrorCode::EquationTooComplexToPlot):
+ case (EvaluationErrorCode::InequalityTooComplexToSolve):
+ case (EvaluationErrorCode::GE_TooComplexToSolve):
+ return resLoader->GetString(L"TooComplexToSolve");
+ break;
+ case (EvaluationErrorCode::EquationHasNoSolution):
+ case (EvaluationErrorCode::InequalityHasNoSolution):
+ return resLoader->GetString(L"EquationHasNoSolution");
+ break;
+ case (EvaluationErrorCode::DivideByZero):
+ return resLoader->GetString(L"DivideByZero");
+ break;
+ case (EvaluationErrorCode::MutuallyExclusiveConditions):
+ return resLoader->GetString(L"MutuallyExclusiveConditions");
+ break;
+ case (EvaluationErrorCode::OutOfDomain):
+ return resLoader->GetString(L"OutOfDomain");
+ break;
+ case (EvaluationErrorCode::GE_NotSupported):
+ return resLoader->GetString(L"GE_NotSupported");
+ break;
+ default:
+ return resLoader->GetString(L"GeneralError");
+ break;
+ }
+ }
+ else if (errorType == ::ErrorType::Syntax)
+ {
+ switch (static_cast(errorCode))
+ {
+ case (SyntaxErrorCode::ParenthesisMismatch):
+ return resLoader->GetString(L"ParenthesisMismatch");
+ break;
+ case (SyntaxErrorCode::UnmatchedParenthesis):
+ return resLoader->GetString(L"UnmatchedParenthesis");
+ break;
+ case (SyntaxErrorCode::TooManyDecimalPoints):
+ return resLoader->GetString(L"TooManyDecimalPoints");
+ break;
+ case (SyntaxErrorCode::DecimalPointWithoutDigits):
+ return resLoader->GetString(L"DecimalPointWithoutDigits");
+ break;
+ case (SyntaxErrorCode::UnexpectedEndOfExpression):
+ return resLoader->GetString(L"UnexpectedEndOfExpression");
+ break;
+ case (SyntaxErrorCode::UnexpectedToken):
+ return resLoader->GetString(L"UnexpectedToken");
+ break;
+ case (SyntaxErrorCode::InvalidToken):
+ return resLoader->GetString(L"InvalidToken");
+ break;
+ case (SyntaxErrorCode::TooManyEquals):
+ return resLoader->GetString(L"TooManyEquals");
+ break;
+ case (SyntaxErrorCode::EqualWithoutGraphVariable):
+ return resLoader->GetString(L"EqualWithoutGraphVariable");
+ break;
+ case (SyntaxErrorCode::InvalidEquationSyntax):
+ case (SyntaxErrorCode::InvalidEquationFormat):
+ return resLoader->GetString(L"InvalidEquationSyntax");
+ break;
+ case (SyntaxErrorCode::EmptyExpression):
+ return resLoader->GetString(L"EmptyExpression");
+ break;
+ case (SyntaxErrorCode::EqualWithoutEquation):
+ return resLoader->GetString(L"EqualWithoutEquation");
+ break;
+ case (SyntaxErrorCode::ExpectParenthesisAfterFunctionName):
+ return resLoader->GetString(L"ExpectParenthesisAfterFunctionName");
+ break;
+ case (SyntaxErrorCode::IncorrectNumParameter):
+ return resLoader->GetString(L"IncorrectNumParameter");
+ break;
+ case (SyntaxErrorCode::InvalidVariableNameFormat):
+ return resLoader->GetString(L"InvalidVariableNameFormat");
+ break;
+ case (SyntaxErrorCode::BracketMismatch):
+ return resLoader->GetString(L"BracketMismatch");
+ break;
+ case (SyntaxErrorCode::UnmatchedBracket):
+ return resLoader->GetString(L"UnmatchedBracket");
+ break;
+ case (SyntaxErrorCode::CannotUseIInReal):
+ return resLoader->GetString(L"CannotUseIInReal");
+ break;
+ case (SyntaxErrorCode::InvalidNumberDigit):
+ return resLoader->GetString(L"InvalidNumberDigit");
+ break;
+ case (SyntaxErrorCode::InvalidNumberBase):
+ return resLoader->GetString(L"InvalidNumberBase");
+ break;
+ case (SyntaxErrorCode::InvalidVariableSpecification):
+ return resLoader->GetString(L"InvalidVariableSpecification");
+ break;
+ case (SyntaxErrorCode::ExpectingLogicalOperands):
+ case (SyntaxErrorCode::ExpectingScalarOperands):
+ return resLoader->GetString(L"ExpectingLogicalOperands");
+ break;
+ case (SyntaxErrorCode::CannotUseIndexVarInOpLimits):
+ return resLoader->GetString(L"CannotUseIndexVarInOpLimits");
+ break;
+ case (SyntaxErrorCode::CannotUseIndexVarInLimPoint):
+ return resLoader->GetString(L"Overflow");
+ break;
+ case (SyntaxErrorCode::CannotUseComplexInfinityInReal):
+ return resLoader->GetString(L"CannotUseComplexInfinityInReal");
+ break;
+ case (SyntaxErrorCode::CannotUseIInInequalitySolving):
+ return resLoader->GetString(L"CannotUseIInInequalitySolving");
+ break;
+ default:
+ return resLoader->GetString(L"GeneralError");
+ break;
+ }
+ }
+
+ return resLoader->GetString(L"GeneralError");
+ }
}
diff --git a/src/CalcViewModel/GraphingCalculator/EquationViewModel.h b/src/CalcViewModel/GraphingCalculator/EquationViewModel.h
index 143254b0b..292e857d5 100644
--- a/src/CalcViewModel/GraphingCalculator/EquationViewModel.h
+++ b/src/CalcViewModel/GraphingCalculator/EquationViewModel.h
@@ -41,12 +41,13 @@ public
ref class EquationViewModel sealed : public Windows::UI::Xaml::Data::INotifyPropertyChanged
{
public:
- EquationViewModel(GraphControl::Equation ^ equation, int functionLabelIndex, Windows::UI::Color color);
+ EquationViewModel(GraphControl::Equation ^ equation, int functionLabelIndex, Windows::UI::Color color, int colorIndex);
OBSERVABLE_OBJECT();
OBSERVABLE_PROPERTY_R(GraphControl::Equation ^, GraphEquation);
OBSERVABLE_PROPERTY_RW(int, FunctionLabelIndex);
OBSERVABLE_PROPERTY_RW(bool, IsLastItemInList);
+ PROPERTY_RW(int, LineColorIndex);
property Platform::String ^ Expression
{
@@ -103,6 +104,8 @@ public
void PopulateKeyGraphFeatures(GraphControl::KeyGraphFeaturesInfo ^ info);
+ static Platform::String ^ EquationErrorText(GraphControl::ErrorType errorType, int errorCode);
+
private:
void AddKeyGraphFeature(Platform::String ^ title, Platform::String ^ expression, Platform::String ^ errorString);
void AddKeyGraphFeature(
diff --git a/src/CalcViewModel/GraphingCalculator/GraphingCalculatorViewModel.cpp b/src/CalcViewModel/GraphingCalculator/GraphingCalculatorViewModel.cpp
index 974cf8f85..4e6056124 100644
--- a/src/CalcViewModel/GraphingCalculator/GraphingCalculatorViewModel.cpp
+++ b/src/CalcViewModel/GraphingCalculator/GraphingCalculatorViewModel.cpp
@@ -10,6 +10,7 @@ using namespace Platform::Collections;
using namespace Windows::Foundation;
using namespace Windows::Foundation::Collections;
using namespace Windows::UI::Xaml::Data;
+using namespace GraphControl;
namespace CalculatorApp::ViewModel
{
@@ -24,12 +25,12 @@ namespace CalculatorApp::ViewModel
{
}
- void GraphingCalculatorViewModel::UpdateVariables(IMap ^ variables)
+ void GraphingCalculatorViewModel::UpdateVariables(IMap ^ variables)
{
Variables->Clear();
- for (auto var : variables)
+ for (auto variablePair : variables)
{
- auto variable = ref new VariableViewModel(var->Key, var->Value);
+ auto variable = ref new VariableViewModel(variablePair->Key, variablePair->Value);
variable->VariableUpdated += ref new EventHandler([this, variable](Object ^ sender, VariableChangedEventArgs e) {
VariableUpdated(variable, VariableChangedEventArgs{ e.variableName, e.newValue });
});
diff --git a/src/CalcViewModel/GraphingCalculator/GraphingCalculatorViewModel.h b/src/CalcViewModel/GraphingCalculator/GraphingCalculatorViewModel.h
index 78e89479b..eabd88e96 100644
--- a/src/CalcViewModel/GraphingCalculator/GraphingCalculatorViewModel.h
+++ b/src/CalcViewModel/GraphingCalculator/GraphingCalculatorViewModel.h
@@ -24,7 +24,7 @@ namespace CalculatorApp::ViewModel
event Windows::Foundation::EventHandler ^ VariableUpdated;
- void UpdateVariables(Windows::Foundation::Collections::IMap ^ variables);
+ void UpdateVariables(Windows::Foundation::Collections::IMap ^ variables);
void SetSelectedEquation(EquationViewModel ^ equation);
private:
diff --git a/src/CalcViewModel/GraphingCalculator/GraphingSettingsViewModel.cpp b/src/CalcViewModel/GraphingCalculator/GraphingSettingsViewModel.cpp
index c261890cd..3c7de3531 100644
--- a/src/CalcViewModel/GraphingCalculator/GraphingSettingsViewModel.cpp
+++ b/src/CalcViewModel/GraphingCalculator/GraphingSettingsViewModel.cpp
@@ -10,6 +10,7 @@ using namespace CalcManager::NumberFormattingUtils;
using namespace GraphControl;
using namespace std;
using namespace Platform;
+using namespace Windows::UI::Xaml;
GraphingSettingsViewModel::GraphingSettingsViewModel()
: m_XMinValue(0)
@@ -20,7 +21,7 @@ GraphingSettingsViewModel::GraphingSettingsViewModel()
, m_XMaxError(false)
, m_YMinError(false)
, m_YMaxError(false)
- , m_dontUpdateDisplayRange(false)
+ , m_dontUpdateDisplayRange()
, m_XIsMinLastChanged(true)
, m_YIsMinLastChanged(true)
{
@@ -36,6 +37,7 @@ void GraphingSettingsViewModel::SetGrapher(Grapher ^ grapher)
}
}
Graph = grapher;
+
InitRanges();
RaisePropertyChanged(L"TrigUnit");
}
@@ -54,93 +56,53 @@ void GraphingSettingsViewModel::InitRanges()
m_YMaxValue = yMax;
auto valueStr = to_wstring(m_XMinValue);
TrimTrailingZeros(valueStr);
- m_XMin = ref new String(valueStr.c_str());
+ XMin = ref new String(valueStr.c_str());
valueStr = to_wstring(m_XMaxValue);
TrimTrailingZeros(valueStr);
- m_XMax = ref new String(valueStr.c_str());
+ XMax = ref new String(valueStr.c_str());
valueStr = to_wstring(m_YMinValue);
TrimTrailingZeros(valueStr);
- m_YMin = ref new String(valueStr.c_str());
+ YMin = ref new String(valueStr.c_str());
valueStr = to_wstring(m_YMaxValue);
TrimTrailingZeros(valueStr);
- m_YMax = ref new String(valueStr.c_str());
+ YMax = ref new String(valueStr.c_str());
m_dontUpdateDisplayRange = false;
}
-void GraphingSettingsViewModel::UpdateDisplayRange(bool XValuesModified)
+void GraphingSettingsViewModel::ResetView()
{
- if (m_Graph == nullptr || m_dontUpdateDisplayRange || HasError())
+ if (m_Graph != nullptr)
{
- return;
+ m_Graph->ResetGrid();
+ InitRanges();
+ m_XMinError = false;
+ m_XMaxError = false;
+ m_YMinError = false;
+ m_YMaxError = false;
+
+ RaisePropertyChanged("XError");
+ RaisePropertyChanged("XMin");
+ RaisePropertyChanged("XMax");
+ RaisePropertyChanged("YError");
+ RaisePropertyChanged("YMin");
+ RaisePropertyChanged("YMax");
}
+}
- if (m_Graph->ForceProportionalAxes)
+void GraphingSettingsViewModel::UpdateDisplayRange()
+{
+ if (m_Graph == nullptr || m_dontUpdateDisplayRange || HasError())
{
- // If ForceProportionalAxes is set, the graph will try to automatically adjust ranges to remain proportional.
- // but without a logic to choose which values can be modified or not.
- // To solve this problem, we calculate the new ranges here, taking care to not modify the current axis and
- // modifying only the least recently updated value of the other axis.
-
- if (XValuesModified)
- {
- if (m_YIsMinLastChanged)
- {
- auto yMaxValue = m_YMinValue + (m_XMaxValue - m_XMinValue) * m_Graph->ActualHeight / m_Graph->ActualWidth;
- if (m_YMaxValue != yMaxValue)
- {
- m_YMaxValue = yMaxValue;
- auto valueStr = to_wstring(m_YMaxValue);
- TrimTrailingZeros(valueStr);
- m_YMax = ref new String(valueStr.c_str());
- RaisePropertyChanged("YMax");
- }
- }
- else
- {
- auto yMinValue = m_YMaxValue - (m_XMaxValue - m_XMinValue) * m_Graph->ActualHeight / m_Graph->ActualWidth;
- if (m_YMinValue != yMinValue)
- {
- m_YMinValue = yMinValue;
- auto valueStr = to_wstring(m_YMinValue);
- TrimTrailingZeros(valueStr);
- m_YMin = ref new String(valueStr.c_str());
- RaisePropertyChanged("YMin");
- }
- }
- }
- else
- {
- if (m_XIsMinLastChanged)
- {
- auto xMaxValue = m_XMinValue + (m_YMaxValue - m_YMinValue) * m_Graph->ActualWidth / m_Graph->ActualHeight;
- if (m_XMaxValue != xMaxValue)
- {
- m_XMaxValue = xMaxValue;
- auto valueStr = to_wstring(m_XMaxValue);
- TrimTrailingZeros(valueStr);
- m_XMax = ref new String(valueStr.c_str());
- RaisePropertyChanged("XMax");
- }
- }
- else
- {
- auto xMinValue = m_XMaxValue - (m_YMaxValue - m_YMinValue) * m_Graph->ActualWidth / m_Graph->ActualHeight;
- if (m_XMinValue != xMinValue)
- {
- m_XMinValue = xMinValue;
- auto valueStr = to_wstring(m_XMinValue);
- TrimTrailingZeros(valueStr);
- m_XMin = ref new String(valueStr.c_str());
- RaisePropertyChanged("XMin");
- }
- }
- }
+ return;
}
+
m_Graph->SetDisplayRanges(m_XMinValue, m_XMaxValue, m_YMinValue, m_YMaxValue);
+
+ TraceLogger::GetInstance()->LogGraphSettingsChanged(GraphSettingsType::Grid, L"");
}
bool GraphingSettingsViewModel::HasError()
diff --git a/src/CalcViewModel/GraphingCalculator/GraphingSettingsViewModel.h b/src/CalcViewModel/GraphingCalculator/GraphingSettingsViewModel.h
index ed250bebd..6d6045c01 100644
--- a/src/CalcViewModel/GraphingCalculator/GraphingSettingsViewModel.h
+++ b/src/CalcViewModel/GraphingCalculator/GraphingSettingsViewModel.h
@@ -2,6 +2,7 @@
// Licensed under the MIT License.
#include "../Common/Utils.h"
+#include "CalcViewModel/Common/TraceLogger.h"
namespace CalculatorApp::ViewModel
{
@@ -71,7 +72,7 @@ namespace CalculatorApp::ViewModel
}
RaisePropertyChanged("XError");
RaisePropertyChanged("XMin");
- UpdateDisplayRange(true);
+ UpdateDisplayRange();
}
}
@@ -112,7 +113,7 @@ namespace CalculatorApp::ViewModel
}
RaisePropertyChanged("XError");
RaisePropertyChanged("XMax");
- UpdateDisplayRange(true);
+ UpdateDisplayRange();
}
}
@@ -153,7 +154,7 @@ namespace CalculatorApp::ViewModel
}
RaisePropertyChanged("YError");
RaisePropertyChanged("YMin");
- UpdateDisplayRange(false);
+ UpdateDisplayRange();
}
}
@@ -194,7 +195,7 @@ namespace CalculatorApp::ViewModel
}
RaisePropertyChanged("YError");
RaisePropertyChanged("YMax");
- UpdateDisplayRange(false);
+ UpdateDisplayRange();
}
}
@@ -226,9 +227,12 @@ namespace CalculatorApp::ViewModel
if (value && m_Graph != nullptr && m_Graph->TrigUnitMode != (int)Graphing::EvalTrigUnitMode::Radians)
{
m_Graph->TrigUnitMode = (int)Graphing::EvalTrigUnitMode::Radians;
+
RaisePropertyChanged(L"TrigModeRadians");
RaisePropertyChanged(L"TrigModeDegrees");
RaisePropertyChanged(L"TrigModeGradians");
+
+ TraceLogger::GetInstance()->LogGraphSettingsChanged(GraphSettingsType::TrigUnits, L"Radians");
}
}
}
@@ -244,9 +248,12 @@ namespace CalculatorApp::ViewModel
if (value && m_Graph != nullptr && m_Graph->TrigUnitMode != (int)Graphing::EvalTrigUnitMode::Degrees)
{
m_Graph->TrigUnitMode = (int)Graphing::EvalTrigUnitMode::Degrees;
+
RaisePropertyChanged(L"TrigModeDegrees");
RaisePropertyChanged(L"TrigModeRadians");
RaisePropertyChanged(L"TrigModeGradians");
+
+ TraceLogger::GetInstance()->LogGraphSettingsChanged(GraphSettingsType::TrigUnits, L"Degrees");
}
}
}
@@ -262,19 +269,23 @@ namespace CalculatorApp::ViewModel
if (value && m_Graph != nullptr && m_Graph->TrigUnitMode != (int)Graphing::EvalTrigUnitMode::Grads)
{
m_Graph->TrigUnitMode = (int)Graphing::EvalTrigUnitMode::Grads;
+
RaisePropertyChanged(L"TrigModeGradians");
RaisePropertyChanged(L"TrigModeDegrees");
RaisePropertyChanged(L"TrigModeRadians");
+
+ TraceLogger::GetInstance()->LogGraphSettingsChanged(GraphSettingsType::TrigUnits, L"Gradians");
}
}
}
public:
- void UpdateDisplayRange(bool XValuesModified);
+ void UpdateDisplayRange();
public:
void SetGrapher(GraphControl::Grapher ^ grapher);
void InitRanges();
+ void ResetView();
bool HasError();
private:
diff --git a/src/CalcViewModel/GraphingCalculator/VariableViewModel.h b/src/CalcViewModel/GraphingCalculator/VariableViewModel.h
index 4d9240e83..cd5ffce92 100644
--- a/src/CalcViewModel/GraphingCalculator/VariableViewModel.h
+++ b/src/CalcViewModel/GraphingCalculator/VariableViewModel.h
@@ -4,6 +4,7 @@
#pragma once
#include "../Common/Utils.h"
+#include "CalcViewModel/Common/LocalizationStringUtil.h"
#include "EquationViewModel.h"
namespace CalculatorApp::ViewModel
@@ -18,54 +19,105 @@ public
[Windows::UI::Xaml::Data::Bindable] public ref class VariableViewModel sealed : public Windows::UI::Xaml::Data::INotifyPropertyChanged
{
public:
- VariableViewModel(Platform::String ^ name, double value)
+ VariableViewModel(Platform::String ^ name, GraphControl::Variable ^ variable)
: m_Name(name)
- , m_Value(value)
+ , m_variable{ variable }
, m_SliderSettingsVisible(false)
- , m_Min(0.0)
- , m_Step(0.1)
- , m_Max(2.0)
{
}
OBSERVABLE_OBJECT();
OBSERVABLE_PROPERTY_R(Platform::String ^, Name);
- OBSERVABLE_PROPERTY_RW(double, Min);
- OBSERVABLE_PROPERTY_RW(double, Step);
- OBSERVABLE_PROPERTY_RW(double, Max);
OBSERVABLE_PROPERTY_RW(bool, SliderSettingsVisible);
+ property double Min
+ {
+ double get()
+ {
+ return m_variable->Min;
+ }
+ void set(double value)
+ {
+ if (m_variable->Min != value)
+ {
+ m_variable->Min = value;
+ RaisePropertyChanged("Min");
+ }
+ }
+ }
+
+ property double Step
+ {
+ double get()
+ {
+ return m_variable->Step;
+ }
+ void set(double value)
+ {
+ if (m_variable->Step != value)
+ {
+ m_variable->Step = value;
+ RaisePropertyChanged("Step");
+ }
+ }
+ }
+
+ property double Max
+ {
+ double get()
+ {
+ return m_variable->Max;
+ }
+ void set(double value)
+ {
+ if (m_variable->Max != value)
+ {
+ m_variable->Max = value;
+ RaisePropertyChanged("Max");
+ }
+ }
+ }
+
event Windows::Foundation::EventHandler ^ VariableUpdated;
property double Value
{
double get()
{
- return m_Value;
+ return m_variable->Value;
}
void set(double value)
{
- if (value < Min)
+ if (value < m_variable->Min)
{
- Min = value;
+ m_variable->Min = value;
RaisePropertyChanged(L"Min");
}
- else if (value > Max)
+ else if (value > m_variable->Max)
{
- Max = value;
+ m_variable->Max = value;
RaisePropertyChanged(L"Max");
}
- if (Value != value)
+ if (m_variable->Value != value)
{
- m_Value = value;
+ m_variable->Value = value;
VariableUpdated(this, VariableChangedEventArgs{ Name, value });
RaisePropertyChanged(L"Value");
}
}
}
+ property Platform::String ^ VariableAutomationName
+ {
+ Platform::String ^ get()
+ {
+ return CalculatorApp::Common::LocalizationStringUtil::GetLocalizedString(
+ CalculatorApp::AppResourceProvider::GetInstance()->GetResourceString(L"VariableListViewItem"), Name);
+ }
+ }
+
private:
- double m_Value;
+ GraphControl::Variable ^ m_variable;
};
}
diff --git a/src/CalcViewModel/HistoryViewModel.cpp b/src/CalcViewModel/HistoryViewModel.cpp
index 473322edc..37f721322 100644
--- a/src/CalcViewModel/HistoryViewModel.cpp
+++ b/src/CalcViewModel/HistoryViewModel.cpp
@@ -6,6 +6,7 @@
#include "Common/TraceLogger.h"
#include "Common/LocalizationStringUtil.h"
#include "Common/LocalizationSettings.h"
+#include "StandardCalculatorViewModel.h"
using namespace CalculatorApp;
using namespace CalculatorApp::Common;
@@ -41,11 +42,11 @@ void HistoryViewModel::ReloadHistory(_In_ ViewMode currentMode)
{
if (currentMode == ViewMode::Standard)
{
- m_currentMode = CalculationManager::CALCULATOR_MODE::CM_STD;
+ m_currentMode = CalculationManager::CalculatorMode::Standard;
}
else if (currentMode == ViewMode::Scientific)
{
- m_currentMode = CalculationManager::CALCULATOR_MODE::CM_SCI;
+ m_currentMode = CalculationManager::CalculatorMode::Scientific;
}
else
{
@@ -127,7 +128,7 @@ void HistoryViewModel::DeleteItem(_In_ HistoryItemViewModel ^ e)
{
// Keys for the history container are index based.
// SaveHistory() re-inserts the items anyway, so it's faster to just clear out the container.
- CalculationManager::CALCULATOR_MODE currentMode = m_currentMode;
+ CalculationManager::CalculatorMode currentMode = m_currentMode;
ApplicationDataContainer ^ historyContainer = GetHistoryContainer(currentMode);
historyContainer->Values->Clear();
@@ -152,7 +153,7 @@ void HistoryViewModel::OnClearCommand(_In_ Platform::Object ^ e)
if (Items->Size > 0)
{
- CalculationManager::CALCULATOR_MODE currentMode = m_currentMode;
+ CalculationManager::CalculatorMode currentMode = m_currentMode;
ClearHistoryContainer(currentMode);
Items->Clear();
UpdateItemSize();
@@ -167,7 +168,7 @@ void HistoryViewModel::OnClearCommand(_In_ Platform::Object ^ e)
}
// this method restores history vector per mode
-void HistoryViewModel::RestoreHistory(_In_ CalculationManager::CALCULATOR_MODE cMode)
+void HistoryViewModel::RestoreHistory(_In_ CalculationManager::CalculatorMode cMode)
{
ApplicationDataContainer ^ historyContainer = GetHistoryContainer(cMode);
std::shared_ptr>> historyVector =
@@ -209,13 +210,13 @@ void HistoryViewModel::RestoreHistory(_In_ CalculationManager::CALCULATOR_MODE c
}
}
-Platform::String ^ HistoryViewModel::GetHistoryContainerKey(_In_ CalculationManager::CALCULATOR_MODE cMode)
+Platform::String ^ HistoryViewModel::GetHistoryContainerKey(_In_ CalculationManager::CalculatorMode cMode)
{
Platform::ValueType ^ modeValue = static_cast(cMode);
return Platform::String::Concat(modeValue->ToString(), L"_History");
}
-ApplicationDataContainer ^ HistoryViewModel::GetHistoryContainer(_In_ CalculationManager::CALCULATOR_MODE cMode)
+ApplicationDataContainer ^ HistoryViewModel::GetHistoryContainer(_In_ CalculationManager::CalculatorMode cMode)
{
ApplicationDataContainer ^ localSettings = ApplicationData::Current->LocalSettings;
ApplicationDataContainer ^ historyContainer;
@@ -238,14 +239,14 @@ ApplicationDataContainer ^ HistoryViewModel::GetHistoryContainer(_In_ Calculatio
return historyContainer;
}
-void HistoryViewModel::ClearHistoryContainer(_In_ CalculationManager::CALCULATOR_MODE cMode)
+void HistoryViewModel::ClearHistoryContainer(_In_ CalculationManager::CalculatorMode cMode)
{
ApplicationDataContainer ^ localSettings = ApplicationData::Current->LocalSettings;
localSettings->DeleteContainer(GetHistoryContainerKey(cMode));
}
// this method will be used to update the history item length
-void HistoryViewModel::UpdateHistoryVectorLength(_In_ int newValue, _In_ CalculationManager::CALCULATOR_MODE cMode)
+void HistoryViewModel::UpdateHistoryVectorLength(_In_ int newValue, _In_ CalculationManager::CalculatorMode cMode)
{
ApplicationDataContainer ^ historyContainer = GetHistoryContainer(cMode);
historyContainer->Values->Remove(HistoryVectorLengthKey);
@@ -254,8 +255,13 @@ void HistoryViewModel::UpdateHistoryVectorLength(_In_ int newValue, _In_ Calcula
void HistoryViewModel::ClearHistory()
{
- ClearHistoryContainer(CalculationManager::CALCULATOR_MODE::CM_STD);
- ClearHistoryContainer(CalculationManager::CALCULATOR_MODE::CM_SCI);
+ ClearHistoryContainer(CalculationManager::CalculatorMode::Standard);
+ ClearHistoryContainer(CalculationManager::CalculatorMode::Scientific);
+}
+
+unsigned long long HistoryViewModel::GetMaxItemSize()
+{
+ return static_cast(m_calculatorManager->MaxHistorySize());
}
void HistoryViewModel::SaveHistory()
diff --git a/src/CalcViewModel/HistoryViewModel.h b/src/CalcViewModel/HistoryViewModel.h
index c1c377319..cc393219a 100644
--- a/src/CalcViewModel/HistoryViewModel.h
+++ b/src/CalcViewModel/HistoryViewModel.h
@@ -15,6 +15,8 @@ namespace CalculatorApp
namespace ViewModel
{
+ ref class StandardCalculatorViewModel;
+
public
delegate void HideHistoryClickedHandler();
public
@@ -45,6 +47,7 @@ namespace CalculatorApp
internal : HistoryViewModel(_In_ CalculationManager::CalculatorManager* calculatorManager);
void SetCalculatorDisplay(CalculatorDisplay& calculatorDisplay);
void ReloadHistory(_In_ CalculatorApp::Common::ViewMode currentMode);
+ unsigned long long GetMaxItemSize();
void DeleteItem(_In_ CalculatorApp::ViewModel::HistoryItemViewModel ^ e);
@@ -55,16 +58,16 @@ namespace CalculatorApp
private:
CalculationManager::CalculatorManager* const m_calculatorManager;
CalculatorDisplay m_calculatorDisplay;
- CalculationManager::CALCULATOR_MODE m_currentMode;
+ CalculationManager::CalculatorMode m_currentMode;
Platform::String ^ m_localizedHistoryCleared;
- void RestoreHistory(_In_ CalculationManager::CALCULATOR_MODE cMode);
+ void RestoreHistory(_In_ CalculationManager::CalculatorMode cMode);
CalculationManager::HISTORYITEM
DeserializeHistoryItem(_In_ Platform::String ^ historyItemKey, _In_ Windows::Storage::ApplicationDataContainer ^ historyContainer);
- Windows::Storage::ApplicationDataContainer ^ GetHistoryContainer(_In_ CalculationManager::CALCULATOR_MODE cMode);
- Platform::String ^ GetHistoryContainerKey(_In_ CalculationManager::CALCULATOR_MODE cMode);
- void ClearHistoryContainer(_In_ CalculationManager::CALCULATOR_MODE cMode);
- void UpdateHistoryVectorLength(_In_ int newValue, _In_ CalculationManager::CALCULATOR_MODE cMode);
+ Windows::Storage::ApplicationDataContainer ^ GetHistoryContainer(_In_ CalculationManager::CalculatorMode cMode);
+ Platform::String ^ GetHistoryContainerKey(_In_ CalculationManager::CalculatorMode cMode);
+ void ClearHistoryContainer(_In_ CalculationManager::CalculatorMode cMode);
+ void UpdateHistoryVectorLength(_In_ int newValue, _In_ CalculationManager::CalculatorMode cMode);
bool IsValid(_In_ CalculationManager::HISTORYITEM item);
friend class CalculatorDisplay;
diff --git a/src/CalcViewModel/StandardCalculatorViewModel.cpp b/src/CalcViewModel/StandardCalculatorViewModel.cpp
index 2bfeb521d..7c0b291d4 100644
--- a/src/CalcViewModel/StandardCalculatorViewModel.cpp
+++ b/src/CalcViewModel/StandardCalculatorViewModel.cpp
@@ -679,18 +679,18 @@ void StandardCalculatorViewModel::OnButtonPressed(Object ^ parameter)
}
}
-RADIX_TYPE StandardCalculatorViewModel::GetRadixTypeFromNumberBase(NumberBase base)
+RadixType StandardCalculatorViewModel::GetRadixTypeFromNumberBase(NumberBase base)
{
switch (base)
{
case NumberBase::BinBase:
- return RADIX_TYPE::BIN_RADIX;
+ return RadixType::Binary;
case NumberBase::HexBase:
- return RADIX_TYPE::HEX_RADIX;
+ return RadixType::Hex;
case NumberBase::OctBase:
- return RADIX_TYPE::OCT_RADIX;
+ return RadixType::Octal;
default:
- return RADIX_TYPE::DEC_RADIX;
+ return RadixType::Decimal;
}
}
@@ -1228,7 +1228,7 @@ void StandardCalculatorViewModel::ResetDisplay()
{
AreHEXButtonsEnabled = false;
CurrentRadixType = NumberBase::DecBase;
- m_standardCalculatorManager.SetRadix(DEC_RADIX);
+ m_standardCalculatorManager.SetRadix(RadixType::Decimal);
}
void StandardCalculatorViewModel::SetPrecision(int32_t precision)
@@ -1253,16 +1253,16 @@ void StandardCalculatorViewModel::SetMemorizedNumbersString()
m_standardCalculatorManager.SetMemorizedNumbersString();
}
-ANGLE_TYPE GetAngleTypeFromCommand(Command command)
+AngleType GetAngleTypeFromCommand(Command command)
{
switch (command)
{
case Command::CommandDEG:
- return ANGLE_DEG;
+ return AngleType::Degrees;
case Command::CommandRAD:
- return ANGLE_RAD;
+ return AngleType::Radians;
case Command::CommandGRAD:
- return ANGLE_GRAD;
+ return AngleType::Gradians;
default:
throw ref new Exception(E_FAIL, L"Invalid command type");
}
@@ -1279,7 +1279,7 @@ void StandardCalculatorViewModel::SaveEditedCommand(_In_ unsigned int tokenPosit
if (IsUnaryOp(command) && command != Command::CommandSIGN)
{
int angleCmd = static_cast(m_standardCalculatorManager.GetCurrentDegreeMode());
- ANGLE_TYPE angleType = GetAngleTypeFromCommand(static_cast(angleCmd));
+ AngleType angleType = GetAngleTypeFromCommand(static_cast(angleCmd));
if (IsTrigOp(command))
{
@@ -1812,3 +1812,13 @@ void StandardCalculatorViewModel::SelectHistoryItem(HistoryItemViewModel ^ item)
SetPrimaryDisplay(item->Result, false);
IsFToEEnabled = false;
}
+
+void StandardCalculatorViewModel::ResetCalcManager(bool clearMemory)
+{
+ m_standardCalculatorManager.Reset(clearMemory);
+}
+
+void StandardCalculatorViewModel::SendCommandToCalcManager(int commandId)
+{
+ m_standardCalculatorManager.SendCommand(static_cast(commandId));
+}
diff --git a/src/CalcViewModel/StandardCalculatorViewModel.h b/src/CalcViewModel/StandardCalculatorViewModel.h
index 38584b5db..a5095791e 100644
--- a/src/CalcViewModel/StandardCalculatorViewModel.h
+++ b/src/CalcViewModel/StandardCalculatorViewModel.h
@@ -12,11 +12,6 @@
#include "Common/BitLength.h"
#include "Common/NumberBase.h"
-namespace CalculatorFunctionalTests
-{
- class HistoryTests;
-}
-
namespace CalculatorUnitTests
{
class MultiWindowUnitTests;
@@ -247,7 +242,11 @@ namespace CalculatorApp
}
}
- internal :
+ // Used by unit tests
+ void ResetCalcManager(bool clearMemory);
+ void SendCommandToCalcManager(int command);
+
+ internal:
void OnPaste(Platform::String ^ pastedString);
void OnCopyCommand(Platform::Object ^ parameter);
void OnPasteCommand(Platform::Object ^ parameter);
@@ -307,7 +306,7 @@ namespace CalculatorApp
_Inout_ std::shared_ptr>> const& commands);
void SetTokens(_Inout_ std::shared_ptr>> const& tokens);
NumbersAndOperatorsEnum ConvertIntegerToNumbersAndOperatorsEnum(unsigned int parameter);
- static RADIX_TYPE GetRadixTypeFromNumberBase(CalculatorApp::Common::NumberBase base);
+ static RadixType GetRadixTypeFromNumberBase(CalculatorApp::Common::NumberBase base);
NumbersAndOperatorsEnum m_CurrentAngleType;
wchar_t m_decimalSeparator;
CalculatorDisplay m_calculatorDisplay;
@@ -373,7 +372,6 @@ namespace CalculatorApp
CalculatorApp::Common::ViewMode GetCalculatorMode();
friend class CalculatorDisplay;
- friend class CalculatorFunctionalTests::HistoryTests;
friend class CalculatorUnitTests::MultiWindowUnitTests;
};
}
diff --git a/src/CalcViewModel/UnitConverterViewModel.cpp b/src/CalcViewModel/UnitConverterViewModel.cpp
index ff77cd770..3b46d9aba 100644
--- a/src/CalcViewModel/UnitConverterViewModel.cpp
+++ b/src/CalcViewModel/UnitConverterViewModel.cpp
@@ -171,9 +171,6 @@ void UnitConverterViewModel::OnCategoryChanged(Object ^ parameter)
void UnitConverterViewModel::ResetCategory()
{
- UCM::Category currentCategory = CurrentCategory->GetModelCategory();
- IsCurrencyCurrentCategory = currentCategory.id == NavCategory::Serialize(ViewMode::Currency);
-
m_isInputBlocked = false;
SetSelectedUnits();
diff --git a/src/CalcViewModel/UnitConverterViewModel.h b/src/CalcViewModel/UnitConverterViewModel.h
index 5891f037c..1f95a47a0 100644
--- a/src/CalcViewModel/UnitConverterViewModel.h
+++ b/src/CalcViewModel/UnitConverterViewModel.h
@@ -143,7 +143,6 @@ namespace CalculatorApp
OBSERVABLE_OBJECT_CALLBACK(OnPropertyChanged);
OBSERVABLE_PROPERTY_R(Windows::Foundation::Collections::IObservableVector ^, Categories);
- OBSERVABLE_PROPERTY_RW(Category ^, CurrentCategory);
OBSERVABLE_PROPERTY_RW(CalculatorApp::Common::ViewMode, Mode);
OBSERVABLE_PROPERTY_R(Windows::Foundation::Collections::IObservableVector ^, Units);
OBSERVABLE_PROPERTY_RW(Platform::String ^, CurrencySymbol1);
@@ -164,7 +163,7 @@ namespace CalculatorApp
OBSERVABLE_PROPERTY_RW(bool, IsDropDownOpen);
OBSERVABLE_PROPERTY_RW(bool, IsDropDownEnabled);
OBSERVABLE_NAMED_PROPERTY_RW(bool, IsCurrencyLoadingVisible);
- OBSERVABLE_PROPERTY_RW(bool, IsCurrencyCurrentCategory);
+ OBSERVABLE_NAMED_PROPERTY_R(bool, IsCurrencyCurrentCategory);
OBSERVABLE_PROPERTY_RW(Platform::String ^, CurrencyRatioEquality);
OBSERVABLE_PROPERTY_RW(Platform::String ^, CurrencyRatioEqualityAutomationName);
OBSERVABLE_PROPERTY_RW(Platform::String ^, CurrencyTimestamp);
@@ -172,6 +171,26 @@ namespace CalculatorApp
OBSERVABLE_NAMED_PROPERTY_RW(bool, CurrencyDataLoadFailed);
OBSERVABLE_NAMED_PROPERTY_RW(bool, CurrencyDataIsWeekOld);
+ public:
+ property Category ^ CurrentCategory
+ {
+ Category ^ get() { return m_CurrentCategory; }
+ void set(Category ^ value)
+ {
+ if (m_CurrentCategory == value)
+ {
+ return;
+ }
+ m_CurrentCategory = value;
+ if (value != nullptr)
+ {
+ auto currentCategory = value->GetModelCategory();
+ IsCurrencyCurrentCategory = currentCategory.id == CalculatorApp::Common::NavCategory::Serialize(CalculatorApp::Common::ViewMode::Currency);
+ }
+ OnPropertyChanged("CurrentCategory");
+ }
+ }
+
property Windows::UI::Xaml::Visibility SupplementaryVisibility
{
Windows::UI::Xaml::Visibility get()
@@ -321,7 +340,7 @@ namespace CalculatorApp
std::wstring m_lastAnnouncedFrom;
std::wstring m_lastAnnouncedTo;
Platform::String ^ m_lastAnnouncedConversionResult;
-
+ Category ^ m_CurrentCategory;
bool m_isCurrencyDataLoaded;
};
diff --git a/src/Calculator.sln b/src/Calculator.sln
index 717c6b8c9..ce6eb3b2e 100644
--- a/src/Calculator.sln
+++ b/src/Calculator.sln
@@ -25,6 +25,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GraphingImpl", "GraphingImp
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GraphControl", "GraphControl\GraphControl.vcxproj", "{E727A92B-F149-492C-8117-C039A298719B}"
EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TraceLogging", "TraceLogging\TraceLogging.vcxproj", "{FC81FF41-02CD-4CD9-9BC5-45A1E39AC6ED}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|ARM = Debug|ARM
@@ -173,6 +175,22 @@ Global
{E727A92B-F149-492C-8117-C039A298719B}.Release|x64.Build.0 = Release|x64
{E727A92B-F149-492C-8117-C039A298719B}.Release|x86.ActiveCfg = Release|Win32
{E727A92B-F149-492C-8117-C039A298719B}.Release|x86.Build.0 = Release|Win32
+ {FC81FF41-02CD-4CD9-9BC5-45A1E39AC6ED}.Debug|ARM.ActiveCfg = Debug|ARM
+ {FC81FF41-02CD-4CD9-9BC5-45A1E39AC6ED}.Debug|ARM.Build.0 = Debug|ARM
+ {FC81FF41-02CD-4CD9-9BC5-45A1E39AC6ED}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {FC81FF41-02CD-4CD9-9BC5-45A1E39AC6ED}.Debug|ARM64.Build.0 = Debug|ARM64
+ {FC81FF41-02CD-4CD9-9BC5-45A1E39AC6ED}.Debug|x64.ActiveCfg = Debug|x64
+ {FC81FF41-02CD-4CD9-9BC5-45A1E39AC6ED}.Debug|x64.Build.0 = Debug|x64
+ {FC81FF41-02CD-4CD9-9BC5-45A1E39AC6ED}.Debug|x86.ActiveCfg = Debug|Win32
+ {FC81FF41-02CD-4CD9-9BC5-45A1E39AC6ED}.Debug|x86.Build.0 = Debug|Win32
+ {FC81FF41-02CD-4CD9-9BC5-45A1E39AC6ED}.Release|ARM.ActiveCfg = Release|ARM
+ {FC81FF41-02CD-4CD9-9BC5-45A1E39AC6ED}.Release|ARM.Build.0 = Release|ARM
+ {FC81FF41-02CD-4CD9-9BC5-45A1E39AC6ED}.Release|ARM64.ActiveCfg = Release|ARM64
+ {FC81FF41-02CD-4CD9-9BC5-45A1E39AC6ED}.Release|ARM64.Build.0 = Release|ARM64
+ {FC81FF41-02CD-4CD9-9BC5-45A1E39AC6ED}.Release|x64.ActiveCfg = Release|x64
+ {FC81FF41-02CD-4CD9-9BC5-45A1E39AC6ED}.Release|x64.Build.0 = Release|x64
+ {FC81FF41-02CD-4CD9-9BC5-45A1E39AC6ED}.Release|x86.ActiveCfg = Release|Win32
+ {FC81FF41-02CD-4CD9-9BC5-45A1E39AC6ED}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/src/Calculator/App.xaml b/src/Calculator/App.xaml
index 50472efd6..7082c7523 100644
--- a/src/Calculator/App.xaml
+++ b/src/Calculator/App.xaml
@@ -70,20 +70,33 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -163,6 +176,19 @@
+
+
+
+
+
+
+
0,1,0,0
@@ -197,6 +223,26 @@
+
+
+
+
+
+
+
@@ -1764,6 +1810,25 @@
+
+
+
+
+
diff --git a/src/Calculator/Assets/CalcMDL2.ttf b/src/Calculator/Assets/CalcMDL2.ttf
index fda499276..9ee5deb05 100644
Binary files a/src/Calculator/Assets/CalcMDL2.ttf and b/src/Calculator/Assets/CalcMDL2.ttf differ
diff --git a/src/Calculator/Assets/Graphing.targetsize-16.png b/src/Calculator/Assets/Graphing.targetsize-16.png
new file mode 100644
index 000000000..485e73498
Binary files /dev/null and b/src/Calculator/Assets/Graphing.targetsize-16.png differ
diff --git a/src/Calculator/Assets/Graphing.targetsize-16_contrast-black.png b/src/Calculator/Assets/Graphing.targetsize-16_contrast-black.png
new file mode 100644
index 000000000..485e73498
Binary files /dev/null and b/src/Calculator/Assets/Graphing.targetsize-16_contrast-black.png differ
diff --git a/src/Calculator/Assets/Graphing.targetsize-16_contrast-white.png b/src/Calculator/Assets/Graphing.targetsize-16_contrast-white.png
new file mode 100644
index 000000000..467880450
Binary files /dev/null and b/src/Calculator/Assets/Graphing.targetsize-16_contrast-white.png differ
diff --git a/src/Calculator/Assets/Graphing.targetsize-20.png b/src/Calculator/Assets/Graphing.targetsize-20.png
new file mode 100644
index 000000000..9b1754ed8
Binary files /dev/null and b/src/Calculator/Assets/Graphing.targetsize-20.png differ
diff --git a/src/Calculator/Assets/Graphing.targetsize-20_contrast-black.png b/src/Calculator/Assets/Graphing.targetsize-20_contrast-black.png
new file mode 100644
index 000000000..9b1754ed8
Binary files /dev/null and b/src/Calculator/Assets/Graphing.targetsize-20_contrast-black.png differ
diff --git a/src/Calculator/Assets/Graphing.targetsize-20_contrast-white.png b/src/Calculator/Assets/Graphing.targetsize-20_contrast-white.png
new file mode 100644
index 000000000..517e7413d
Binary files /dev/null and b/src/Calculator/Assets/Graphing.targetsize-20_contrast-white.png differ
diff --git a/src/Calculator/Assets/Graphing.targetsize-24.png b/src/Calculator/Assets/Graphing.targetsize-24.png
new file mode 100644
index 000000000..2670817a1
Binary files /dev/null and b/src/Calculator/Assets/Graphing.targetsize-24.png differ
diff --git a/src/Calculator/Assets/Graphing.targetsize-24_contrast-black.png b/src/Calculator/Assets/Graphing.targetsize-24_contrast-black.png
new file mode 100644
index 000000000..2670817a1
Binary files /dev/null and b/src/Calculator/Assets/Graphing.targetsize-24_contrast-black.png differ
diff --git a/src/Calculator/Assets/Graphing.targetsize-24_contrast-white.png b/src/Calculator/Assets/Graphing.targetsize-24_contrast-white.png
new file mode 100644
index 000000000..f603fc856
Binary files /dev/null and b/src/Calculator/Assets/Graphing.targetsize-24_contrast-white.png differ
diff --git a/src/Calculator/Assets/Graphing.targetsize-32.png b/src/Calculator/Assets/Graphing.targetsize-32.png
new file mode 100644
index 000000000..b8ae7bb5a
Binary files /dev/null and b/src/Calculator/Assets/Graphing.targetsize-32.png differ
diff --git a/src/Calculator/Assets/Graphing.targetsize-32_contrast-black.png b/src/Calculator/Assets/Graphing.targetsize-32_contrast-black.png
new file mode 100644
index 000000000..b8ae7bb5a
Binary files /dev/null and b/src/Calculator/Assets/Graphing.targetsize-32_contrast-black.png differ
diff --git a/src/Calculator/Assets/Graphing.targetsize-32_contrast-white.png b/src/Calculator/Assets/Graphing.targetsize-32_contrast-white.png
new file mode 100644
index 000000000..8dd829ac8
Binary files /dev/null and b/src/Calculator/Assets/Graphing.targetsize-32_contrast-white.png differ
diff --git a/src/Calculator/Assets/Graphing.targetsize-64.png b/src/Calculator/Assets/Graphing.targetsize-64.png
new file mode 100644
index 000000000..e347e193f
Binary files /dev/null and b/src/Calculator/Assets/Graphing.targetsize-64.png differ
diff --git a/src/Calculator/Assets/Graphing.targetsize-64_contrast-black.png b/src/Calculator/Assets/Graphing.targetsize-64_contrast-black.png
new file mode 100644
index 000000000..e347e193f
Binary files /dev/null and b/src/Calculator/Assets/Graphing.targetsize-64_contrast-black.png differ
diff --git a/src/Calculator/Assets/Graphing.targetsize-64_contrast-white.png b/src/Calculator/Assets/Graphing.targetsize-64_contrast-white.png
new file mode 100644
index 000000000..d5cdc05b7
Binary files /dev/null and b/src/Calculator/Assets/Graphing.targetsize-64_contrast-white.png differ
diff --git a/src/Calculator/Calculator.vcxproj b/src/Calculator/Calculator.vcxproj
index ae195362c..908d8fc56 100644
--- a/src/Calculator/Calculator.vcxproj
+++ b/src/Calculator/Calculator.vcxproj
@@ -17,7 +17,7 @@
black
Always
TemporaryKey.pfx
- true
+ True
False
@@ -262,6 +262,7 @@
+
App.xaml
@@ -431,6 +432,7 @@
+
Create
Create
@@ -897,6 +899,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -959,7 +976,7 @@
-
+
@@ -967,6 +984,6 @@
-
+
-
\ No newline at end of file
+
diff --git a/src/Calculator/Calculator.vcxproj.filters b/src/Calculator/Calculator.vcxproj.filters
index 5b6e9ec7e..9ffafdb44 100644
--- a/src/Calculator/Calculator.vcxproj.filters
+++ b/src/Calculator/Calculator.vcxproj.filters
@@ -328,6 +328,7 @@
Common
+
@@ -435,6 +436,7 @@
Common
+
@@ -520,7 +522,6 @@
Views\GraphingCalculator
-
@@ -1523,6 +1524,51 @@
Assets
+
+ Assets
+
+
+ Assets
+
+
+ Assets
+
+
+ Assets
+
+
+ Assets
+
+
+ Assets
+
+
+ Assets
+
+
+ Assets
+
+
+ Assets
+
+
+ Assets
+
+
+ Assets
+
+
+ Assets
+
+
+ Assets
+
+
+ Assets
+
+
+ Assets
+
@@ -1535,7 +1581,5 @@
-
-
\ No newline at end of file
diff --git a/src/Calculator/Common/KeyboardShortcutManager.cpp b/src/Calculator/Common/KeyboardShortcutManager.cpp
index d5c78c05e..f05e3c486 100644
--- a/src/Calculator/Common/KeyboardShortcutManager.cpp
+++ b/src/Calculator/Common/KeyboardShortcutManager.cpp
@@ -56,6 +56,8 @@ static map s_AboutFlyout;
static reader_writer_lock s_keyboardShortcutMapLock;
+static bool s_shortcutsDisabled = false;
+
namespace CalculatorApp
{
namespace Common
@@ -642,6 +644,13 @@ void KeyboardShortcutManager::OnAcceleratorKeyActivated(CoreDispatcher ^, Accele
return;
}
+ // Ctrl is pressed in addition to alt, this means Alt Gr is intended. do not navigate.
+ if ((static_cast(Window::Current->CoreWindow->GetKeyState(VirtualKey::Control)) & static_cast(CoreVirtualKeyStates::Down))
+ == static_cast(CoreVirtualKeyStates::Down))
+ {
+ return;
+ }
+
const auto& lookupMap = GetCurrentKeyDictionary(static_cast(key), altPressed);
auto listItems = lookupMap.equal_range(static_cast(key));
for (auto listIterator = listItems.first; listIterator != listItems.second; ++listIterator)
@@ -728,6 +737,11 @@ void KeyboardShortcutManager::UpdateDropDownState(Flyout ^ aboutPageFlyout)
void KeyboardShortcutManager::HonorShortcuts(bool allow)
{
+ if (s_shortcutsDisabled)
+ {
+ return;
+ }
+
// Writer lock for the static maps
reader_writer_lock::scoped_lock lock(s_keyboardShortcutMapLock);
@@ -821,3 +835,9 @@ void KeyboardShortcutManager::OnWindowClosed(int viewId)
s_fHonorShortcuts.erase(viewId);
s_AboutFlyout.erase(viewId);
}
+
+void KeyboardShortcutManager::DisableShortcuts(bool disable)
+{
+ s_shortcutsDisabled = disable;
+ HonorShortcuts(!disable);
+}
diff --git a/src/Calculator/Common/KeyboardShortcutManager.h b/src/Calculator/Common/KeyboardShortcutManager.h
index 124ae167e..32ace85bd 100644
--- a/src/Calculator/Common/KeyboardShortcutManager.h
+++ b/src/Calculator/Common/KeyboardShortcutManager.h
@@ -43,6 +43,7 @@ namespace CalculatorApp
static void IgnoreEscape(bool onlyOnce);
static void HonorEscape();
static void HonorShortcuts(bool allow);
+ static void DisableShortcuts(bool disable);
static void UpdateDropDownState(bool);
static void ShiftButtonChecked(bool checked);
static void UpdateDropDownState(Windows::UI::Xaml::Controls::Flyout ^ aboutPageFlyout);
diff --git a/src/Calculator/Controls/CalculationResult.cpp b/src/Calculator/Controls/CalculationResult.cpp
index ed092fab9..1b15333ac 100644
--- a/src/Calculator/Controls/CalculationResult.cpp
+++ b/src/Calculator/Controls/CalculationResult.cpp
@@ -323,17 +323,38 @@ void CalculationResult::UpdateScrollButtons()
return;
}
+ bool shouldTryFocusScrollRight = false;
if (m_scrollLeft != nullptr)
{
- m_scrollLeft->Visibility = m_textContainer->HorizontalOffset > SCROLL_BUTTONS_APPROXIMATION_RANGE ? ::Visibility::Visible : ::Visibility::Collapsed;
+ auto scrollLeftVisibility = m_textContainer->HorizontalOffset > SCROLL_BUTTONS_APPROXIMATION_RANGE ? ::Visibility::Visible : ::Visibility::Collapsed;
+
+ if (scrollLeftVisibility == ::Visibility::Collapsed)
+ {
+ shouldTryFocusScrollRight = m_scrollLeft->Equals(FocusManager::GetFocusedElement());
+ }
+
+ m_scrollLeft->Visibility = scrollLeftVisibility;
}
if (m_scrollRight != nullptr)
{
- m_scrollRight->Visibility =
+ auto scrollRightVisibility =
m_textContainer->HorizontalOffset + m_textContainer->ViewportWidth + SCROLL_BUTTONS_APPROXIMATION_RANGE < m_textContainer->ExtentWidth
? ::Visibility::Visible
: ::Visibility::Collapsed;
+
+ if (scrollRightVisibility == ::Visibility::Collapsed && m_scrollLeft != nullptr && m_scrollLeft->Visibility == ::Visibility::Visible
+ && m_scrollRight->Equals(FocusManager::GetFocusedElement()))
+ {
+ // ScrollRight had the focus and will be collapsed, ScrollLeft should get the focus
+ m_scrollLeft->Focus(::FocusState::Programmatic);
+ }
+ m_scrollRight->Visibility = scrollRightVisibility;
+
+ if (shouldTryFocusScrollRight && scrollRightVisibility == ::Visibility::Visible)
+ {
+ m_scrollRight->Focus(::FocusState::Programmatic);
+ }
}
}
diff --git a/src/Calculator/Controls/EquationTextBox.cpp b/src/Calculator/Controls/EquationTextBox.cpp
index a5d6d69b9..b9daab354 100644
--- a/src/Calculator/Controls/EquationTextBox.cpp
+++ b/src/Calculator/Controls/EquationTextBox.cpp
@@ -27,6 +27,8 @@ DEPENDENCY_PROPERTY_INITIALIZATION(EquationTextBox, EquationButtonContentIndex);
DEPENDENCY_PROPERTY_INITIALIZATION(EquationTextBox, HasError);
DEPENDENCY_PROPERTY_INITIALIZATION(EquationTextBox, IsAddEquationMode);
DEPENDENCY_PROPERTY_INITIALIZATION(EquationTextBox, MathEquation);
+DEPENDENCY_PROPERTY_INITIALIZATION(EquationTextBox, ErrorText);
+DEPENDENCY_PROPERTY_INITIALIZATION(EquationTextBox, IsEquationLineDisabled);
EquationTextBox::EquationTextBox()
{
@@ -44,6 +46,11 @@ void EquationTextBox::OnApplyTemplate()
m_kgfEquationMenuItem = dynamic_cast(GetTemplateChild("FunctionAnalysisMenuItem"));
m_removeMenuItem = dynamic_cast(GetTemplateChild("RemoveFunctionMenuItem"));
m_colorChooserMenuItem = dynamic_cast(GetTemplateChild("ChangeFunctionStyleMenuItem"));
+ m_cutMenuItem = dynamic_cast(GetTemplateChild("CutMenuItem"));
+ m_copyMenuItem = dynamic_cast(GetTemplateChild("CopyMenuItem"));
+ m_pasteMenuItem = dynamic_cast(GetTemplateChild("PasteMenuItem"));
+ m_undoMenuItem = dynamic_cast(GetTemplateChild("UndoMenuItem"));
+ m_selectAllMenuItem = dynamic_cast(GetTemplateChild("SelectAllMenuItem"));
auto resProvider = AppResourceProvider::GetInstance();
@@ -62,8 +69,11 @@ void EquationTextBox::OnApplyTemplate()
m_equationButton->Click += ref new RoutedEventHandler(this, &EquationTextBox::OnEquationButtonClicked);
auto toolTip = ref new ToolTip();
- auto equationButtonMessage = m_equationButton->IsChecked->Value ? resProvider->GetResourceString(L"showEquationButtonToolTip")
- : resProvider->GetResourceString(L"hideEquationButtonToolTip");
+
+ auto equationButtonMessage = LocalizationStringUtil::GetLocalizedString(
+ IsEquationLineDisabled ? resProvider->GetResourceString(L"showEquationButtonToolTip")
+ : resProvider->GetResourceString(L"hideEquationButtonToolTip"), EquationButtonContentIndex);
+
toolTip->Content = equationButtonMessage;
ToolTipService::SetToolTip(m_equationButton, toolTip);
AutomationProperties::SetName(m_equationButton, equationButtonMessage);
@@ -71,7 +81,7 @@ void EquationTextBox::OnApplyTemplate()
if (m_richEditContextMenu != nullptr)
{
- m_richEditContextMenu->Opening += ref new EventHandler(this, &EquationTextBox::OnRichEditMenuOpening);
+ m_richEditContextMenu->Opened += ref new EventHandler(this, &EquationTextBox::OnRichEditMenuOpened);
}
if (m_deleteButton != nullptr)
@@ -119,6 +129,31 @@ void EquationTextBox::OnApplyTemplate()
ColorChooserFlyout->Closed += ref new EventHandler
diff --git a/src/CalculatorUnitTests/Helper.cpp b/src/CalculatorUnitTests/Helper.cpp
new file mode 100644
index 000000000..763618552
--- /dev/null
+++ b/src/CalculatorUnitTests/Helper.cpp
@@ -0,0 +1,14 @@
+#include "pch.h"
+#include "Helpers.h"
+using namespace Platform;
+using namespace std;
+
+String ^ GetStringValue(String ^ input) {
+ // Remove first and last " characters
+ if (input->Length() >= 3)
+ {
+ wstring out(input->Begin() + 1, input->End() - 1);
+ return ref new String(out.c_str());
+ }
+ return input;
+}
diff --git a/src/CalculatorUnitTests/Helpers.h b/src/CalculatorUnitTests/Helpers.h
index 672dd5561..9b364cef5 100644
--- a/src/CalculatorUnitTests/Helpers.h
+++ b/src/CalculatorUnitTests/Helpers.h
@@ -108,3 +108,5 @@ void VERIFY_VECTORS_ARE_EQUAL(Windows::Foundation::Collections::IVector ^ vec
VERIFY_ARE_EQUAL(vecA->GetAt(i), vecB->GetAt(i), __VA_ARGS__);
}
};
+
+Platform::String ^ GetStringValue(Platform::String ^ input);
diff --git a/src/CalculatorUnitTests/HistoryTests.cpp b/src/CalculatorUnitTests/HistoryTests.cpp
index becf1b4b7..71b58ce71 100644
--- a/src/CalculatorUnitTests/HistoryTests.cpp
+++ b/src/CalculatorUnitTests/HistoryTests.cpp
@@ -46,17 +46,16 @@ namespace CalculatorFunctionalTests
{
m_standardViewModel = ref new StandardCalculatorViewModel();
m_standardViewModel->IsStandard = true;
- m_historyViewModel = ref new HistoryViewModel(&(m_standardViewModel->m_standardCalculatorManager));
- m_historyViewModel->SetCalculatorDisplay(m_standardViewModel->m_calculatorDisplay);
+ m_historyViewModel = m_standardViewModel->HistoryVM;
}
void Cleanup()
{
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::ModeBasic);
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::ModeBasic));
m_historyViewModel->OnClearCommand(nullptr);
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::ModeScientific);
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::ModeScientific));
m_historyViewModel->OnClearCommand(nullptr);
- m_standardViewModel->m_standardCalculatorManager.Reset();
+ m_standardViewModel->ResetCalcManager(false);
}
bool IsHistoryContainerEmpty(_In_ String ^ historyContainerKey)
@@ -65,70 +64,60 @@ namespace CalculatorFunctionalTests
return !(localSettings->Containers->HasKey(historyContainerKey));
}
- String^ GetHistoryContainerKeyHelper(CalculationManager::CALCULATOR_MODE cMode)
+ String^ GetHistoryContainerKeyHelper(CalculationManager::CalculatorMode cMode)
{
ValueType^ modeValue = static_cast(cMode);
return String::Concat(modeValue->ToString(), L"_History");
}
- void MockOnHistoryItemClicked(CalculatorApp::ViewModel::HistoryItemViewModel^ e)
- {
- m_standardViewModel->SetHistoryExpressionDisplay(e->GetTokens(), e->GetCommands());
- m_standardViewModel->SetExpressionDisplay(e->GetTokens(), e->GetCommands());
- m_standardViewModel->SetPrimaryDisplay(e->Result, false /*IsError*/);
- m_standardViewModel->IsFToEEnabled = false;
- }
-
void AddSingleHistoryItem()
{
Initialize();
int initialSize = m_historyViewModel->ItemSize;
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::Command1);
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::CommandADD);
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::Command8);
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::CommandEQU);
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::Command1));
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::CommandADD));
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::Command8));
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::CommandEQU));
int sizeAfterItemAdd = m_historyViewModel->ItemSize;
- auto historyItem = m_standardViewModel->m_standardCalculatorManager.GetHistoryItem(0);
+ auto historyItem = static_cast(m_historyViewModel->Items->GetAt(0));
String ^ expression = UtfUtils::LRO + L"1 + 8 =" + UtfUtils::PDF;
- String ^ result = StringReference(L"9");
VERIFY_ARE_EQUAL(initialSize + 1, sizeAfterItemAdd);
- VERIFY_ARE_EQUAL(expression, StringReference(historyItem->historyItemVector.expression.c_str()));
- VERIFY_ARE_EQUAL(result, StringReference(historyItem->historyItemVector.result.c_str()));
+ VERIFY_ARE_EQUAL(historyItem->Expression, expression);
+ VERIFY_ARE_EQUAL(historyItem->Result, L"9");
Cleanup();
}
void AddMaxHistoryItems()
{
Initialize();
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::Command1);
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::CommandADD);
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::Command1);
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::CommandEQU);
- for (size_t i = 1; i < m_standardViewModel->m_standardCalculatorManager.MaxHistorySize(); i++)
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::Command1));
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::CommandADD));
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::Command1));
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::CommandEQU));
+ for (unsigned long long i = 1; i < m_historyViewModel->GetMaxItemSize(); i++)
{
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::Command1);
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::CommandADD);
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::Command2);
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::CommandEQU);
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::Command1));
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::CommandADD));
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::Command2));
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::CommandEQU));
}
- VERIFY_ARE_EQUAL((size_t)m_historyViewModel->ItemSize, m_standardViewModel->m_standardCalculatorManager.MaxHistorySize());
+ VERIFY_ARE_EQUAL((size_t)m_historyViewModel->ItemSize, m_historyViewModel->GetMaxItemSize());
String ^ expression = UtfUtils::LRO + L"1 + 1 =" + UtfUtils::PDF;
int output = 2;
String ^ result = output.ToString();
- auto historyItem = m_standardViewModel->m_standardCalculatorManager.GetHistoryItem(0);
- VERIFY_ARE_EQUAL(expression, StringReference(historyItem->historyItemVector.expression.c_str()));
- VERIFY_ARE_EQUAL(result, StringReference(historyItem->historyItemVector.result.c_str()));
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::Command1);
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::CommandADD);
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::Command5);
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::CommandEQU);
- VERIFY_ARE_EQUAL((size_t)m_historyViewModel->ItemSize, m_standardViewModel->m_standardCalculatorManager.MaxHistorySize());
+ auto historyItem = static_cast(m_historyViewModel->Items->GetAt(m_historyViewModel->ItemSize - 1));
+ VERIFY_ARE_EQUAL(historyItem->Expression, expression);
+ VERIFY_ARE_EQUAL(historyItem->Result, result);
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::Command1));
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::CommandADD));
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::Command5));
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::CommandEQU));
expression = UtfUtils::LRO + L"1 + 2 =" + UtfUtils::PDF;
output = 3;
result = output.ToString();
- historyItem = m_standardViewModel->m_standardCalculatorManager.GetHistoryItem(0);
- VERIFY_ARE_EQUAL(expression, StringReference(historyItem->historyItemVector.expression.c_str()));
- VERIFY_ARE_EQUAL(result, StringReference(historyItem->historyItemVector.result.c_str()));
+ historyItem = static_cast(m_historyViewModel->Items->GetAt(m_historyViewModel->ItemSize - 1));
+ VERIFY_ARE_EQUAL(historyItem->Expression, expression);
+ VERIFY_ARE_EQUAL(historyItem->Result, result);
Cleanup();
}
@@ -136,30 +125,30 @@ namespace CalculatorFunctionalTests
{
Initialize();
- m_standardViewModel->m_standardCalculatorManager.Reset();
+ m_standardViewModel->ResetCalcManager(false);
int scientificItems = 5;
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::ModeScientific);
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::ModeScientific));
for (int i = 0; i < scientificItems; i++)
{
Command nextCommand = Command(130 + i);
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::Command1);
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::CommandADD);
- m_standardViewModel->m_standardCalculatorManager.SendCommand(nextCommand);
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::CommandEQU);
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::Command1));
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::CommandADD));
+ m_standardViewModel->SendCommandToCalcManager((int)nextCommand);
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::CommandEQU));
}
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::ModeBasic);
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::ModeBasic));
int standardItems = 2;
for (int i = 0; i < standardItems; i++)
{
Command nextCommand = Command(130 + i);
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::Command1);
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::CommandADD);
- m_standardViewModel->m_standardCalculatorManager.SendCommand(nextCommand);
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::CommandEQU);
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::Command1));
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::CommandADD));
+ m_standardViewModel->SendCommandToCalcManager((int)nextCommand);
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::CommandEQU));
}
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::ModeScientific);
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::ModeScientific));
m_historyViewModel->ReloadHistory(ViewMode::Scientific);
VERIFY_ARE_EQUAL(scientificItems, m_historyViewModel->ItemSize);
for (int i = 0; i < scientificItems; i++)
@@ -168,13 +157,13 @@ namespace CalculatorFunctionalTests
expr = UtfUtils::LRO + expr + UtfUtils::PDF;
int output = 1 + i;
String ^ result = output.ToString();
- auto historyItem = m_standardViewModel->m_standardCalculatorManager.GetHistoryItem(i);
- VERIFY_ARE_EQUAL(expr, historyItem->historyItemVector.expression);
- VERIFY_ARE_EQUAL(result, StringReference(historyItem->historyItemVector.result.c_str()));
+ auto historyItem = static_cast(m_historyViewModel->Items->GetAt(m_historyViewModel->ItemSize - 1 - i));
+ VERIFY_ARE_EQUAL(historyItem->Expression, StringReference(expr.c_str()));
+ VERIFY_ARE_EQUAL(historyItem->Result, result);
}
m_historyViewModel->ReloadHistory(ViewMode::Standard);
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::ModeBasic);
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::ModeBasic));
VERIFY_ARE_EQUAL(standardItems, m_historyViewModel->ItemSize);
for (int i = 0; i < standardItems; i++)
{
@@ -182,9 +171,9 @@ namespace CalculatorFunctionalTests
expr = UtfUtils::LRO + expr + UtfUtils::PDF;
int output = 1 + i;
String ^ result = output.ToString();
- auto historyItem = m_standardViewModel->m_standardCalculatorManager.GetHistoryItem(i);
- VERIFY_ARE_EQUAL(expr, historyItem->historyItemVector.expression);
- VERIFY_ARE_EQUAL(result, StringReference(historyItem->historyItemVector.result.c_str()));
+ auto historyItem = static_cast(m_historyViewModel->Items->GetAt(m_historyViewModel->ItemSize - 1 - i));
+ VERIFY_ARE_EQUAL(historyItem->Expression, StringReference(expr.c_str()));
+ VERIFY_ARE_EQUAL(historyItem->Result, result);
}
Cleanup();
}
@@ -192,73 +181,71 @@ namespace CalculatorFunctionalTests
void ClearHistory()
{
Initialize();
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::ModeScientific);
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::Command1);
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::CommandADD);
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::Command2);
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::CommandEQU);
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::ModeBasic);
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::Command1);
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::CommandADD);
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::Command2);
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::CommandEQU);
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::ModeScientific));
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::Command1));
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::CommandADD));
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::Command2));
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::CommandEQU));
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::ModeBasic));
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::Command1));
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::CommandADD));
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::Command2));
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::CommandEQU));
m_historyViewModel->OnClearCommand(nullptr);
VERIFY_ARE_EQUAL(0, m_historyViewModel->ItemSize);
- VERIFY_IS_TRUE(IsHistoryContainerEmpty(GetHistoryContainerKeyHelper(CM_STD)));
- VERIFY_IS_TRUE(IsHistoryContainerEmpty(GetHistoryContainerKeyHelper(CM_SCI)));
+ VERIFY_IS_TRUE(IsHistoryContainerEmpty(GetHistoryContainerKeyHelper(CalculatorMode::Standard)));
+ VERIFY_IS_TRUE(IsHistoryContainerEmpty(GetHistoryContainerKeyHelper(CalculatorMode::Scientific)));
Cleanup();
}
void SerializeDeSerializeHistoryItem()
{
Initialize();
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::ModeScientific);
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::Command1);
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::CommandADD);
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::Command2);
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::CommandEQU);
- auto itemBeforeSerializeDeserialize = m_standardViewModel->m_standardCalculatorManager.GetHistoryItem(0);
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::ModeScientific));
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::Command1));
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::CommandADD));
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::Command2));
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::CommandEQU));
+ auto itemBeforeSerializeDeserialize = static_cast(m_historyViewModel->Items->GetAt(0));
m_historyViewModel->SaveHistory();
m_historyViewModel->ReloadHistory(ViewMode::Scientific);
- auto itemAfterSerializeDeserialize = m_standardViewModel->m_standardCalculatorManager.GetHistoryItem(0);
+ auto itemAfterSerializeDeserialize = static_cast(m_historyViewModel->Items->GetAt(0));
VERIFY_IS_TRUE(
- (itemBeforeSerializeDeserialize->historyItemVector.expression == itemAfterSerializeDeserialize->historyItemVector.expression)
- && (itemBeforeSerializeDeserialize->historyItemVector.result == itemAfterSerializeDeserialize->historyItemVector.result)
- && (itemBeforeSerializeDeserialize->historyItemVector.spCommands == itemAfterSerializeDeserialize->historyItemVector.spCommands)
- && (itemBeforeSerializeDeserialize->historyItemVector.spTokens == itemAfterSerializeDeserialize->historyItemVector.spTokens));
+ itemBeforeSerializeDeserialize->Expression == itemAfterSerializeDeserialize->Expression
+ && itemBeforeSerializeDeserialize->Result == itemAfterSerializeDeserialize->Result);
Cleanup();
}
void SaveAndReloadHistory()
{
Initialize();
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::ModeScientific);
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::Command1);
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::CommandADD);
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::Command8);
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::CommandEQU);
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::Command1);
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::CommandADD);
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::Command2);
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::CommandEQU);
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::ModeBasic);
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::Command1);
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::CommandADD);
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::Command6);
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::CommandEQU);
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::ModeScientific));
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::Command1));
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::CommandADD));
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::Command8));
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::CommandEQU));
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::Command1));
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::CommandADD));
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::Command2));
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::CommandEQU));
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::ModeBasic));
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::Command1));
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::CommandADD));
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::Command6));
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::CommandEQU));
int itemsBeforeSaveAndReload = m_historyViewModel->ItemSize;
m_historyViewModel->SaveHistory();
m_historyViewModel->ReloadHistory(ViewMode::Scientific);
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::ModeScientific);
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::ModeScientific));
wstring expr = L"1 + 8 =";
// add double quotes around the expression
expr = UtfUtils::LRO + expr + UtfUtils::PDF;
String ^ result = StringReference(L"9");
int itemsAfterSaveAndReload = m_historyViewModel->ItemSize;
- auto historyItem = m_standardViewModel->m_standardCalculatorManager.GetHistoryItem(0);
- VERIFY_ARE_EQUAL(expr, historyItem->historyItemVector.expression);
- VERIFY_ARE_EQUAL(result, StringReference(historyItem->historyItemVector.result.c_str()));
+ auto historyItem = static_cast(m_historyViewModel->Items->GetAt(m_historyViewModel->ItemSize - 1));
+ VERIFY_ARE_EQUAL(historyItem->Expression, StringReference(expr.c_str()));
+ VERIFY_ARE_EQUAL(historyItem->Result, result);
VERIFY_ARE_NOT_EQUAL(itemsBeforeSaveAndReload, itemsAfterSaveAndReload);
VERIFY_ARE_EQUAL(itemsBeforeSaveAndReload, itemsAfterSaveAndReload + 1);
Cleanup();
@@ -275,21 +262,21 @@ namespace CalculatorFunctionalTests
ResourceLoader ^ m_uiResourceLoader = ResourceLoader::GetForViewIndependentUse(L"CEngineStrings");
int itemIndex = 0;
int commandResource = 67;
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::ModeScientific);
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::ModeScientific));
for (int index = 0; index < modes; index++)
{
- m_standardViewModel->m_standardCalculatorManager.SendCommand(mode[index]);
+ m_standardViewModel->SendCommandToCalcManager((int)mode[index]);
for (int command = 0; command < commandsSize; command++)
{
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::Command1);
- m_standardViewModel->m_standardCalculatorManager.SendCommand(commands[command]);
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::CommandEQU);
- auto historyItem = m_standardViewModel->m_standardCalculatorManager.GetHistoryItem(itemIndex);
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::Command1));
+ m_standardViewModel->SendCommandToCalcManager(static_cast(commands[command]));
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::CommandEQU));
+ auto historyItem = static_cast(m_historyViewModel->Items->GetAt(m_historyViewModel->ItemSize - 1 - itemIndex));
String ^ expression = m_uiResourceLoader->GetString(commandResource.ToString());
expression += L"( 1 ) =";
wstring expr = wstring(expression->Data());
expr = UtfUtils::LRO + expr + UtfUtils::PDF;
- VERIFY_ARE_EQUAL(historyItem->historyItemVector.expression, expr);
+ VERIFY_ARE_EQUAL(historyItem->Expression, StringReference(expr.c_str()));
commandResource++;
itemIndex++;
}
@@ -301,20 +288,20 @@ namespace CalculatorFunctionalTests
{
Initialize();
ResourceLoader ^ m_uiResourceLoader = ResourceLoader::GetForViewIndependentUse(L"CEngineStrings");
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::ModeScientific);
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::CommandDEG);
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::Command1);
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::CommandSIN);
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::CommandADD);
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::CommandRAD);
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::Command1);
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::CommandSIN);
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::CommandADD);
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::CommandGRAD);
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::Command1);
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::CommandSIN);
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::CommandEQU);
- auto historyItem = m_standardViewModel->m_standardCalculatorManager.GetHistoryItem(0);
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::ModeScientific));
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::CommandDEG));
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::Command1));
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::CommandSIN));
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::CommandADD));
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::CommandRAD));
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::Command1));
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::CommandSIN));
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::CommandADD));
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::CommandGRAD));
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::Command1));
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::CommandSIN));
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::CommandEQU));
+ auto historyItem = static_cast(m_historyViewModel->Items->GetAt(m_historyViewModel->ItemSize - 1));
String ^ expression = m_uiResourceLoader->GetString(L"67");
expression += L"( 1 ) + ";
expression += m_uiResourceLoader->GetString(L"73");
@@ -323,7 +310,7 @@ namespace CalculatorFunctionalTests
expression += L"( 1 ) =";
wstring expr = wstring(expression->Data());
expr = UtfUtils::LRO + expr + UtfUtils::PDF;
- VERIFY_ARE_EQUAL(historyItem->historyItemVector.expression, expr);
+ VERIFY_ARE_EQUAL(historyItem->Expression, StringReference(expr.c_str()));
Cleanup();
}
@@ -331,19 +318,15 @@ namespace CalculatorFunctionalTests
void HistoryItemClicked()
{
Initialize();
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::ModeScientific);
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::Command1);
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::CommandADD);
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::Command5);
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::CommandADD);
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::Command3);
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::CommandEQU);
- auto historyItem = m_standardViewModel->m_standardCalculatorManager.GetHistoryItem(0);
- String ^ expression = StringReference(historyItem->historyItemVector.expression.c_str());
- String ^ result = StringReference(historyItem->historyItemVector.result.c_str());
- HistoryItemViewModel ^ item =
- ref new HistoryItemViewModel(expression, result, historyItem->historyItemVector.spTokens, historyItem->historyItemVector.spCommands);
- MockOnHistoryItemClicked(item);
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::ModeScientific));
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::Command1));
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::CommandADD));
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::Command5));
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::CommandADD));
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::Command3));
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::CommandEQU));
+ auto historyItem = static_cast(m_historyViewModel->Items->GetAt(m_historyViewModel->ItemSize - 1));
+ m_standardViewModel->SelectHistoryItem(historyItem);
VERIFY_ARE_EQUAL(StringReference(L"9"), m_standardViewModel->DisplayValue);
VERIFY_ARE_EQUAL(StringReference(L"1"), m_standardViewModel->ExpressionTokens->GetAt(0)->Token);
VERIFY_ARE_EQUAL(StringReference(L" "), m_standardViewModel->ExpressionTokens->GetAt(1)->Token);
@@ -359,37 +342,27 @@ namespace CalculatorFunctionalTests
void HistoryItemLoadAndContinueCalculation()
{
Initialize();
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::ModeBasic);
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::Command1);
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::CommandADD);
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::Command5);
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::CommandADD);
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::Command3);
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::CommandEQU);
-
- auto historyItem = m_standardViewModel->m_standardCalculatorManager.GetHistoryItem(0);
- String ^ expression = StringReference(historyItem->historyItemVector.expression.c_str());
- String ^ result = StringReference(historyItem->historyItemVector.result.c_str());
- HistoryItemViewModel ^ item =
- ref new HistoryItemViewModel(expression, result, historyItem->historyItemVector.spTokens, historyItem->historyItemVector.spCommands);
- MockOnHistoryItemClicked(item);
-
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::CommandADD);
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::Command5);
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::CommandEQU);
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::ModeBasic));
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::Command1));
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::CommandADD));
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::Command5));
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::CommandADD));
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::Command3));
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::CommandEQU));
+
+ auto historyItem = static_cast(m_historyViewModel->Items->GetAt(m_historyViewModel->ItemSize - 1));
+ m_standardViewModel->SelectHistoryItem(historyItem);
+
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::CommandADD));
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::Command5));
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::CommandEQU));
VERIFY_ARE_EQUAL(StringReference(L"14"), m_standardViewModel->DisplayValue);
- historyItem = m_standardViewModel->m_standardCalculatorManager.GetHistoryItem(0);
- expression = StringReference(historyItem->historyItemVector.expression.c_str());
- result = StringReference(historyItem->historyItemVector.result.c_str());
- item = ref new HistoryItemViewModel(expression, result, historyItem->historyItemVector.spTokens, historyItem->historyItemVector.spCommands);
- MockOnHistoryItemClicked(item);
+ historyItem = static_cast(m_historyViewModel->Items->GetAt(m_historyViewModel->ItemSize - 1));
+ m_standardViewModel->SelectHistoryItem(historyItem);
VERIFY_ARE_EQUAL(StringReference(L"9"), m_standardViewModel->DisplayValue);
- historyItem = m_standardViewModel->m_standardCalculatorManager.GetHistoryItem(1);
- expression = StringReference(historyItem->historyItemVector.expression.c_str());
- result = StringReference(historyItem->historyItemVector.result.c_str());
- item = ref new HistoryItemViewModel(expression, result, historyItem->historyItemVector.spTokens, historyItem->historyItemVector.spCommands);
- MockOnHistoryItemClicked(item);
+ historyItem = static_cast(m_historyViewModel->Items->GetAt(m_historyViewModel->ItemSize - 2));
+ m_standardViewModel->SelectHistoryItem(historyItem);
VERIFY_ARE_EQUAL(StringReference(L"14"), m_standardViewModel->DisplayValue);
Cleanup();
}
@@ -397,26 +370,26 @@ namespace CalculatorFunctionalTests
void DisplayValueAutomationNames()
{
Initialize();
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::Command1);
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::CommandADD);
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::Command8);
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::CommandEQU);
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::Command1));
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::CommandADD));
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::Command8));
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::CommandEQU));
String ^ expression = StringReference(L"Display is 9");
VERIFY_ARE_EQUAL(expression, m_standardViewModel->CalculationResultAutomationName);
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::ModeScientific);
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::Command1);
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::CommandADD);
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::Command5);
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::CommandEQU);
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::ModeScientific));
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::Command1));
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::CommandADD));
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::Command5));
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::CommandEQU));
expression = StringReference(L"Display is 6");
VERIFY_ARE_EQUAL(expression, m_standardViewModel->CalculationResultAutomationName);
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::ModeProgrammer);
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::Command1);
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::CommandADD);
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::Command2);
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::CommandEQU);
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::ModeProgrammer));
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::Command1));
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::CommandADD));
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::Command2));
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::CommandEQU));
expression = StringReference(L"Display is 3");
VERIFY_ARE_EQUAL(expression, m_standardViewModel->CalculationResultAutomationName);
@@ -426,20 +399,20 @@ namespace CalculatorFunctionalTests
void RadixAutomationName()
{
Initialize();
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::ModeProgrammer);
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::ModeProgrammer));
m_standardViewModel->IsProgrammer = true;
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::Command1);
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::CommandADD);
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::Command7);
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::CommandEQU);
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::Command1));
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::CommandADD));
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::Command7));
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::CommandEQU));
String ^ expression = L"HexaDecimal" + L" 8";
- String ^ result = L"HexaDecimal " + Utils::GetStringValue(m_standardViewModel->HexDisplayValue);
+ String ^ result = L"HexaDecimal " + GetStringValue(m_standardViewModel->HexDisplayValue);
VERIFY_ARE_EQUAL(expression, result);
expression = StringReference(L"Octal 10");
- result = L"Octal " + Utils::GetStringValue(m_standardViewModel->OctalDisplayValue);
+ result = L"Octal " + GetStringValue(m_standardViewModel->OctalDisplayValue);
VERIFY_ARE_EQUAL(expression, result);
expression = StringReference(L"Binary 1000");
- result = L"Binary " + Utils::GetStringValue(m_standardViewModel->BinaryDisplayValue);
+ result = L"Binary " + GetStringValue(m_standardViewModel->BinaryDisplayValue);
VERIFY_ARE_EQUAL(expression, result);
Cleanup();
}
@@ -448,7 +421,7 @@ namespace CalculatorFunctionalTests
{
Initialize();
VERIFY_ARE_EQUAL(0, m_historyViewModel->ItemSize);
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::ModeScientific);
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::ModeScientific));
VERIFY_ARE_EQUAL(0, m_historyViewModel->ItemSize);
Cleanup();
}
@@ -457,7 +430,7 @@ namespace CalculatorFunctionalTests
{
Initialize();
VERIFY_ARE_EQUAL(0, m_historyViewModel->ItemSize);
- m_standardViewModel->m_standardCalculatorManager.SendCommand(Command::ModeScientific);
+ m_standardViewModel->SendCommandToCalcManager(static_cast(Command::ModeScientific));
m_historyViewModel->OnClearCommand(nullptr);
VERIFY_ARE_EQUAL(0, m_historyViewModel->ItemSize);
Cleanup();
diff --git a/src/CalculatorUnitTests/MultiWindowUnitTests.cpp b/src/CalculatorUnitTests/MultiWindowUnitTests.cpp
index b41a6113f..1aa861a1a 100644
--- a/src/CalculatorUnitTests/MultiWindowUnitTests.cpp
+++ b/src/CalculatorUnitTests/MultiWindowUnitTests.cpp
@@ -369,7 +369,7 @@ TEST_METHOD(MultipleModesHistoryAddItemTest)
ChangeMode(viewModels[i], i);
// Validate that the history items list is initially empty
- VERIFY_IS_TRUE(0 == viewModels[i]->m_standardCalculatorManager.GetHistoryItems().size());
+ VERIFY_IS_TRUE(0 == viewModels[i]->HistoryVM->ItemSize);
}
// Perform Calculations on both the instances and check that the History items work independently
@@ -390,24 +390,24 @@ TEST_METHOD(MultipleModesHistoryAddItemTest)
ValidateViewModelByCommands(viewModels[1], scientificModeTestItems, true);
// Assert for the history list items of 1st instance
- VERIFY_IS_TRUE(1 == viewModels[0]->m_standardCalculatorManager.GetHistoryItems().size());
+ VERIFY_IS_TRUE(1 == viewModels[0]->HistoryVM->ItemSize);
- auto item1 = viewModels[0]->m_standardCalculatorManager.GetHistoryItem(0);
+ auto item1 = static_cast(viewModels[0]->HistoryVM->Items->GetAt(0));
String ^ expression1 = UtfUtils::LRO + L"1 + 2 =" + UtfUtils::PDF;
String ^ result1 = L"3";
- VERIFY_ARE_EQUAL(expression1, StringReference(item1->historyItemVector.expression.c_str()));
- VERIFY_ARE_EQUAL(result1, StringReference(item1->historyItemVector.result.c_str()));
+ VERIFY_ARE_EQUAL(expression1, item1->Expression);
+ VERIFY_ARE_EQUAL(result1, item1->Result);
// Assert for the history list items of 2nd instance
- VERIFY_IS_TRUE(1 == viewModels[1]->m_standardCalculatorManager.GetHistoryItems().size());
+ VERIFY_IS_TRUE(1 == viewModels[1]->HistoryVM->ItemSize);
- auto item2 = viewModels[1]->m_standardCalculatorManager.GetHistoryItem(0);
+ auto item2 = static_cast(viewModels[1]->HistoryVM->Items->GetAt(0));
String ^ expression2 = UtfUtils::LRO + L"1 + 2 " + UtfUtils::MUL + L" 3 =" + UtfUtils::PDF;
String ^ result2 = L"7";
- VERIFY_ARE_EQUAL(expression2, StringReference(item2->historyItemVector.expression.c_str()));
- VERIFY_ARE_EQUAL(result2, StringReference(item2->historyItemVector.result.c_str()));
+ VERIFY_ARE_EQUAL(expression2, item2->Expression);
+ VERIFY_ARE_EQUAL(result2, item2->Result);
}
// Perform calculations on 2 separate instances of Standard Modes and verify that their History list items are maintained separately
@@ -424,7 +424,7 @@ TEST_METHOD(MultipleStandardModesHistoryAddItemTest)
ChangeMode(viewModels[i], 0);
// Validate that the history items list is initially empty
- VERIFY_IS_TRUE(0 == viewModels[i]->m_standardCalculatorManager.GetHistoryItems().size());
+ VERIFY_IS_TRUE(0 == viewModels[i]->HistoryVM->ItemSize);
}
// Perform Calculations on both the instances and check that the History items work independently
@@ -457,12 +457,12 @@ TEST_METHOD(MultipleStandardModesHistoryAddItemTest)
// Assert for the history list items of the instances
for (int i = 0; i < 2; i++)
{
- VERIFY_IS_TRUE(1 == viewModels[i]->m_standardCalculatorManager.GetHistoryItems().size());
+ VERIFY_IS_TRUE(1 == viewModels[i]->HistoryVM->ItemSize);
- auto item = viewModels[i]->m_standardCalculatorManager.GetHistoryItem(0);
+ auto item = static_cast(viewModels[i]->HistoryVM->Items->GetAt(0));
- VERIFY_ARE_EQUAL(expression[i], StringReference(item->historyItemVector.expression.c_str()));
- VERIFY_ARE_EQUAL(result[i], StringReference(item->historyItemVector.result.c_str()));
+ VERIFY_ARE_EQUAL(expression[i], item->Expression);
+ VERIFY_ARE_EQUAL(result[i], item->Result);
}
}
@@ -480,7 +480,7 @@ TEST_METHOD(MultipleScientificModesHistoryAddItemTest)
ChangeMode(viewModels[i], 1);
// Validate that the history items list is initially empty
- VERIFY_IS_TRUE(0 == viewModels[i]->m_standardCalculatorManager.GetHistoryItems().size());
+ VERIFY_IS_TRUE(0 == viewModels[i]->HistoryVM->ItemSize);
}
// Perform Calculations on both the instances and check that the History items work independently
@@ -513,12 +513,12 @@ TEST_METHOD(MultipleScientificModesHistoryAddItemTest)
// Assert for the history list items of the instances
for (int i = 0; i < 2; i++)
{
- VERIFY_IS_TRUE(1 == viewModels[i]->m_standardCalculatorManager.GetHistoryItems().size());
+ VERIFY_IS_TRUE(1 == viewModels[i]->HistoryVM->ItemSize);
- auto item = viewModels[i]->m_standardCalculatorManager.GetHistoryItem(0);
+ auto item = static_cast(viewModels[i]->HistoryVM->Items->GetAt(0));
- VERIFY_ARE_EQUAL(expression[i], StringReference(item->historyItemVector.expression.c_str()));
- VERIFY_ARE_EQUAL(result[i], StringReference(item->historyItemVector.result.c_str()));
+ VERIFY_ARE_EQUAL(expression[i], item->Expression);
+ VERIFY_ARE_EQUAL(result[i], item->Result);
}
}
diff --git a/src/CalculatorUnitTests/RationalTest.cpp b/src/CalculatorUnitTests/RationalTest.cpp
index dcfcdd89a..7c8aebb6f 100644
--- a/src/CalculatorUnitTests/RationalTest.cpp
+++ b/src/CalculatorUnitTests/RationalTest.cpp
@@ -78,25 +78,25 @@ TEST_METHOD(TestModuloRational)
{
// Test with rational numbers
auto res = Mod(Rational(Number(1, 0, { 250 }), Number(1, 0, { 100 })), Rational(89));
- VERIFY_ARE_EQUAL(res.ToString(10, FMT_FLOAT, 8), L"2.5");
+ VERIFY_ARE_EQUAL(res.ToString(10, NumberFormat::Float, 8), L"2.5");
res = Mod(Rational(Number(1, 0, { 3330 }), Number(1, 0, { 1332 })), Rational(1));
- VERIFY_ARE_EQUAL(res.ToString(10, FMT_FLOAT, 8), L"0.5");
+ VERIFY_ARE_EQUAL(res.ToString(10, NumberFormat::Float, 8), L"0.5");
res = Mod(Rational(Number(1, 0, { 12250 }), Number(1, 0, { 100 })), Rational(10));
- VERIFY_ARE_EQUAL(res.ToString(10, FMT_FLOAT, 8), L"2.5");
+ VERIFY_ARE_EQUAL(res.ToString(10, NumberFormat::Float, 8), L"2.5");
res = Mod(Rational(Number(-1, 0, { 12250 }), Number(1, 0, { 100 })), Rational(10));
- VERIFY_ARE_EQUAL(res.ToString(10, FMT_FLOAT, 8), L"7.5");
+ VERIFY_ARE_EQUAL(res.ToString(10, NumberFormat::Float, 8), L"7.5");
res = Mod(Rational(Number(-1, 0, { 12250 }), Number(1, 0, { 100 })), Rational(-10));
- VERIFY_ARE_EQUAL(res.ToString(10, FMT_FLOAT, 8), L"-2.5");
+ VERIFY_ARE_EQUAL(res.ToString(10, NumberFormat::Float, 8), L"-2.5");
res = Mod(Rational(Number(1, 0, { 12250 }), Number(1, 0, { 100 })), Rational(-10));
- VERIFY_ARE_EQUAL(res.ToString(10, FMT_FLOAT, 8), L"-7.5");
+ VERIFY_ARE_EQUAL(res.ToString(10, NumberFormat::Float, 8), L"-7.5");
res = Mod(Rational(Number(1, 0, { 1000 }), Number(1, 0, { 3 })), Rational(1));
- VERIFY_ARE_EQUAL(res.ToString(10, FMT_FLOAT, 8), L"0.33333333");
+ VERIFY_ARE_EQUAL(res.ToString(10, NumberFormat::Float, 8), L"0.33333333");
res = Mod(Rational(Number(1, 0, { 1000 }), Number(1, 0, { 3 })), Rational(-10));
- VERIFY_ARE_EQUAL(res.ToString(10, FMT_FLOAT, 8), L"-6.6666667");
+ VERIFY_ARE_EQUAL(res.ToString(10, NumberFormat::Float, 8), L"-6.6666667");
res = Mod(Rational(834345), Rational(Number(1, 0, { 103 }), Number(1, 0, { 100 })));
- VERIFY_ARE_EQUAL(res.ToString(10, FMT_FLOAT, 8), L"0.71");
+ VERIFY_ARE_EQUAL(res.ToString(10, NumberFormat::Float, 8), L"0.71");
res = Mod(Rational(834345), Rational(Number(-1, 0, { 103 }), Number(1, 0, { 100 })));
- VERIFY_ARE_EQUAL(res.ToString(10, FMT_FLOAT, 8), L"-0.32");
+ VERIFY_ARE_EQUAL(res.ToString(10, NumberFormat::Float, 8), L"-0.32");
}
TEST_METHOD(TestRemainderOperandsNotModified)
@@ -192,29 +192,29 @@ TEST_METHOD(TestRemainderRational)
{
// Test with rational numbers
auto res = Rational(Number(1, 0, { 250 }), Number(1, 0, { 100 })) % Rational(89);
- VERIFY_ARE_EQUAL(res.ToString(10, FMT_FLOAT, 8), L"2.5");
+ VERIFY_ARE_EQUAL(res.ToString(10, NumberFormat::Float, 8), L"2.5");
res = Rational(Number(1, 0, { 3330 }), Number(1, 0, { 1332 })) % Rational(1);
- VERIFY_ARE_EQUAL(res.ToString(10, FMT_FLOAT, 8), L"0.5");
+ VERIFY_ARE_EQUAL(res.ToString(10, NumberFormat::Float, 8), L"0.5");
res = Rational(Number(1, 0, { 12250 }), Number(1, 0, { 100 })) % Rational(10);
- VERIFY_ARE_EQUAL(res.ToString(10, FMT_FLOAT, 8), L"2.5");
+ VERIFY_ARE_EQUAL(res.ToString(10, NumberFormat::Float, 8), L"2.5");
res = Rational(Number(-1, 0, { 12250 }), Number(1, 0, { 100 })) % Rational(10);
- VERIFY_ARE_EQUAL(res.ToString(10, FMT_FLOAT, 8), L"-2.5");
+ VERIFY_ARE_EQUAL(res.ToString(10, NumberFormat::Float, 8), L"-2.5");
res = Rational(Number(-1, 0, { 12250 }), Number(1, 0, { 100 })) % Rational(-10);
- VERIFY_ARE_EQUAL(res.ToString(10, FMT_FLOAT, 8), L"-2.5");
+ VERIFY_ARE_EQUAL(res.ToString(10, NumberFormat::Float, 8), L"-2.5");
res = Rational(Number(1, 0, { 12250 }), Number(1, 0, { 100 })) % Rational(-10);
- VERIFY_ARE_EQUAL(res.ToString(10, FMT_FLOAT, 8), L"2.5");
+ VERIFY_ARE_EQUAL(res.ToString(10, NumberFormat::Float, 8), L"2.5");
res = Rational(Number(1, 0, { 1000 }), Number(1, 0, { 3 })) % Rational(1);
- VERIFY_ARE_EQUAL(res.ToString(10, FMT_FLOAT, 8), L"0.33333333");
+ VERIFY_ARE_EQUAL(res.ToString(10, NumberFormat::Float, 8), L"0.33333333");
res = Rational(Number(1, 0, { 1000 }), Number(1, 0, { 3 })) % Rational(-10);
- VERIFY_ARE_EQUAL(res.ToString(10, FMT_FLOAT, 8), L"3.3333333");
+ VERIFY_ARE_EQUAL(res.ToString(10, NumberFormat::Float, 8), L"3.3333333");
res = Rational(Number(-1, 0, { 1000 }), Number(1, 0, { 3 })) % Rational(-10);
- VERIFY_ARE_EQUAL(res.ToString(10, FMT_FLOAT, 8), L"-3.3333333");
+ VERIFY_ARE_EQUAL(res.ToString(10, NumberFormat::Float, 8), L"-3.3333333");
res = Rational(834345) % Rational(Number(1, 0, { 103 }), Number(1, 0, { 100 }));
- VERIFY_ARE_EQUAL(res.ToString(10, FMT_FLOAT, 8), L"0.71");
+ VERIFY_ARE_EQUAL(res.ToString(10, NumberFormat::Float, 8), L"0.71");
res = Rational(834345) % Rational(Number(-1, 0, { 103 }), Number(1, 0, { 100 }));
- VERIFY_ARE_EQUAL(res.ToString(10, FMT_FLOAT, 8), L"0.71");
+ VERIFY_ARE_EQUAL(res.ToString(10, NumberFormat::Float, 8), L"0.71");
res = Rational(-834345) % Rational(Number(1, 0, { 103 }), Number(1, 0, { 100 }));
- VERIFY_ARE_EQUAL(res.ToString(10, FMT_FLOAT, 8), L"-0.71");
+ VERIFY_ARE_EQUAL(res.ToString(10, NumberFormat::Float, 8), L"-0.71");
}
}
;
diff --git a/src/CalculatorUnitTests/StandardViewModelUnitTests.cpp b/src/CalculatorUnitTests/StandardViewModelUnitTests.cpp
index 1f9d40d71..58711635a 100644
--- a/src/CalculatorUnitTests/StandardViewModelUnitTests.cpp
+++ b/src/CalculatorUnitTests/StandardViewModelUnitTests.cpp
@@ -9,6 +9,7 @@
#include "CalcViewModel/StandardCalculatorViewModel.h"
#include "CalcViewModel/Common/CalculatorButtonPressedEventArgs.h"
+#include "Helpers.h"
using namespace CalculationManager;
using namespace CalculatorApp;
@@ -494,10 +495,10 @@ namespace CalculatorUnitTests
{ NumbersAndOperatorsEnum::F, L"F", L"" },
{ NumbersAndOperatorsEnum::None, L"", L"" } };
ValidateViewModelByCommands(m_viewModel, items, false);
- VERIFY_ARE_EQUAL(Utils::GetStringValue(m_viewModel->HexDisplayValue), StringReference(L"F"));
- VERIFY_ARE_EQUAL(Utils::GetStringValue(m_viewModel->DecimalDisplayValue), StringReference(L"15"));
- VERIFY_ARE_EQUAL(Utils::GetStringValue(m_viewModel->OctalDisplayValue), StringReference(L"17"));
- VERIFY_ARE_EQUAL(Utils::GetStringValue(m_viewModel->BinaryDisplayValue), StringReference(L"1111"));
+ VERIFY_ARE_EQUAL(GetStringValue(m_viewModel->HexDisplayValue), StringReference(L"F"));
+ VERIFY_ARE_EQUAL(GetStringValue(m_viewModel->DecimalDisplayValue), StringReference(L"15"));
+ VERIFY_ARE_EQUAL(GetStringValue(m_viewModel->OctalDisplayValue), StringReference(L"17"));
+ VERIFY_ARE_EQUAL(GetStringValue(m_viewModel->BinaryDisplayValue), StringReference(L"1111"));
auto val = ref new Platform::Collections::Vector(64, false);
val->SetAt(0, true);
val->SetAt(1, true);
@@ -510,19 +511,19 @@ namespace CalculatorUnitTests
TEST_METHOD(ProgrammerModeButtonsDisable)
{
/* m_viewModel->IsProgrammer = true;
- m_viewModel->SwitchProgrammerModeBase(OCT_RADIX);
+ m_viewModel->SwitchProgrammerModeBase(RadixType::Octal);
VERIFY_IS_TRUE(m_viewModel->AreOCTButtonsEnabled);
VERIFY_IS_FALSE(m_viewModel->AreHEXButtonsEnabled);
VERIFY_IS_FALSE(m_viewModel->AreDECButtonsEnabled);
- m_viewModel->SwitchProgrammerModeBase(DEC_RADIX);
+ m_viewModel->SwitchProgrammerModeBase(RadixType::Decimal);
VERIFY_IS_FALSE(m_viewModel->AreHEXButtonsEnabled);
VERIFY_IS_TRUE(m_viewModel->AreDECButtonsEnabled);
VERIFY_IS_TRUE(m_viewModel->AreOCTButtonsEnabled);
- m_viewModel->SwitchProgrammerModeBase(HEX_RADIX);
+ m_viewModel->SwitchProgrammerModeBase(RadixType::Hex);
VERIFY_IS_TRUE(m_viewModel->AreHEXButtonsEnabled);
VERIFY_IS_TRUE(m_viewModel->AreDECButtonsEnabled);
VERIFY_IS_TRUE(m_viewModel->AreOCTButtonsEnabled);
- m_viewModel->SwitchProgrammerModeBase(BIN_RADIX);
+ m_viewModel->SwitchProgrammerModeBase(RadixType::Binary);
VERIFY_IS_FALSE(m_viewModel->AreHEXButtonsEnabled);
VERIFY_IS_FALSE(m_viewModel->AreDECButtonsEnabled);
VERIFY_IS_FALSE(m_viewModel->AreOCTButtonsEnabled);*/
@@ -547,10 +548,10 @@ namespace CalculatorUnitTests
{ NumbersAndOperatorsEnum::None, L"1", L"" },
};
ValidateViewModelByCommands(m_viewModel, items, true);
- VERIFY_ARE_EQUAL(Utils::GetStringValue(m_viewModel->HexDisplayValue), StringReference(L"75B CD15"));
- VERIFY_ARE_EQUAL(Utils::GetStringValue(m_viewModel->DecimalDisplayValue), StringReference(L"123,456,789"));
- VERIFY_ARE_EQUAL(Utils::GetStringValue(m_viewModel->OctalDisplayValue), StringReference(L"726 746 425"));
- VERIFY_ARE_EQUAL(Utils::GetStringValue(m_viewModel->BinaryDisplayValue), StringReference(L"0111 0101 1011 1100 1101 0001 0101"));
+ VERIFY_ARE_EQUAL(GetStringValue(m_viewModel->HexDisplayValue), StringReference(L"75B CD15"));
+ VERIFY_ARE_EQUAL(GetStringValue(m_viewModel->DecimalDisplayValue), StringReference(L"123,456,789"));
+ VERIFY_ARE_EQUAL(GetStringValue(m_viewModel->OctalDisplayValue), StringReference(L"726 746 425"));
+ VERIFY_ARE_EQUAL(GetStringValue(m_viewModel->BinaryDisplayValue), StringReference(L"0111 0101 1011 1100 1101 0001 0101"));
auto val = ref new Platform::Collections::Vector(64, false);
val->SetAt(0, true);
val->SetAt(2, true);
@@ -581,11 +582,11 @@ namespace CalculatorUnitTests
{ NumbersAndOperatorsEnum::Not, L"-2", L"~(1)" },
{ NumbersAndOperatorsEnum::None, L"N/A", L"N/A" } };
ValidateViewModelByCommands(m_viewModel, items, false);
- VERIFY_ARE_EQUAL(Utils::GetStringValue(m_viewModel->HexDisplayValue), StringReference(L"FFFF FFFF FFFF FFFE"));
- VERIFY_ARE_EQUAL(Utils::GetStringValue(m_viewModel->DecimalDisplayValue), StringReference(L"-2"));
- VERIFY_ARE_EQUAL(Utils::GetStringValue(m_viewModel->OctalDisplayValue), StringReference(L"1 777 777 777 777 777 777 776"));
+ VERIFY_ARE_EQUAL(GetStringValue(m_viewModel->HexDisplayValue), StringReference(L"FFFF FFFF FFFF FFFE"));
+ VERIFY_ARE_EQUAL(GetStringValue(m_viewModel->DecimalDisplayValue), StringReference(L"-2"));
+ VERIFY_ARE_EQUAL(GetStringValue(m_viewModel->OctalDisplayValue), StringReference(L"1 777 777 777 777 777 777 776"));
VERIFY_ARE_EQUAL(
- Utils::GetStringValue(m_viewModel->BinaryDisplayValue),
+ GetStringValue(m_viewModel->BinaryDisplayValue),
StringReference(L"1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1110"));
VERIFY_ARE_EQUAL(m_viewModel->DisplayValue, StringReference(L"-2"));
auto val = ref new Platform::Collections::Vector(64, true);
@@ -775,13 +776,13 @@ namespace CalculatorUnitTests
m_viewModel->OnMemoryItemPressed(ref new Platform::Box(0));
VERIFY_ARE_EQUAL(Platform::StringReference(L"-1,001"), m_viewModel->DisplayValue);
MemoryItemViewModel ^ memorySlotStandard = (MemoryItemViewModel ^) m_viewModel->MemorizedNumbers->GetAt(0);
- VERIFY_ARE_EQUAL(Platform::StringReference(L"-1,001"), Utils::GetStringValue(memorySlotStandard->Value));
+ VERIFY_ARE_EQUAL(Platform::StringReference(L"-1,001"), GetStringValue(memorySlotStandard->Value));
ChangeMode(m_viewModel, 1 /*scientific*/);
MemoryItemViewModel ^ memorySlotScientific = (MemoryItemViewModel ^) m_viewModel->MemorizedNumbers->GetAt(0);
- VERIFY_ARE_EQUAL(Platform::StringReference(L"-1,001"), Utils::GetStringValue(memorySlotScientific->Value));
+ VERIFY_ARE_EQUAL(Platform::StringReference(L"-1,001"), GetStringValue(memorySlotScientific->Value));
ChangeMode(m_viewModel, 2 /*Programmer*/);
MemoryItemViewModel ^ memorySlotProgrammer = (MemoryItemViewModel ^) m_viewModel->MemorizedNumbers->GetAt(0);
- VERIFY_ARE_EQUAL(Platform::StringReference(L"-1,001"), Utils::GetStringValue(memorySlotProgrammer->Value));
+ VERIFY_ARE_EQUAL(Platform::StringReference(L"-1,001"), GetStringValue(memorySlotProgrammer->Value));
}
// When decimal number is saved in memory
@@ -799,13 +800,13 @@ namespace CalculatorUnitTests
m_viewModel->OnMemoryItemPressed(ref new Platform::Box(0));
VERIFY_ARE_EQUAL(Platform::StringReference(L"1,001.1"), m_viewModel->DisplayValue);
MemoryItemViewModel ^ memorySlotStandard = (MemoryItemViewModel ^) m_viewModel->MemorizedNumbers->GetAt(0);
- VERIFY_ARE_EQUAL(Platform::StringReference(L"1,001.1"), Utils::GetStringValue(memorySlotStandard->Value));
+ VERIFY_ARE_EQUAL(Platform::StringReference(L"1,001.1"), GetStringValue(memorySlotStandard->Value));
ChangeMode(m_viewModel, 1 /*Scientific*/);
MemoryItemViewModel ^ memorySlotScientific = (MemoryItemViewModel ^) m_viewModel->MemorizedNumbers->GetAt(0);
- VERIFY_ARE_EQUAL(Platform::StringReference(L"1,001.1"), Utils::GetStringValue(memorySlotScientific->Value));
+ VERIFY_ARE_EQUAL(Platform::StringReference(L"1,001.1"), GetStringValue(memorySlotScientific->Value));
ChangeMode(m_viewModel, 2 /*Programmer*/);
MemoryItemViewModel ^ memorySlotProgrammer = (MemoryItemViewModel ^) m_viewModel->MemorizedNumbers->GetAt(0);
- VERIFY_ARE_EQUAL(Platform::StringReference(L"1,001"), Utils::GetStringValue(memorySlotProgrammer->Value));
+ VERIFY_ARE_EQUAL(Platform::StringReference(L"1,001"), GetStringValue(memorySlotProgrammer->Value));
}
// When negative decimal number is saved in memory
@@ -864,7 +865,7 @@ namespace CalculatorUnitTests
m_viewModel->OnMemoryItemPressed(ref new Box(0));
VERIFY_ARE_EQUAL(Platform::StringReference(L"255"), m_viewModel->DisplayValue);
MemoryItemViewModel ^ memorySlot = (MemoryItemViewModel ^) m_viewModel->MemorizedNumbers->GetAt(0);
- VERIFY_ARE_EQUAL(Platform::StringReference(L"255"), Utils::GetStringValue(memorySlot->Value));
+ VERIFY_ARE_EQUAL(Platform::StringReference(L"255"), GetStringValue(memorySlot->Value));
}
TEST_METHOD(OnMemorySavedInHexRadixAndRadixChanges)
@@ -880,13 +881,13 @@ namespace CalculatorUnitTests
m_viewModel->OnMemoryButtonPressed();
m_viewModel->SwitchProgrammerModeBase(NumberBase::OctBase);
MemoryItemViewModel ^ memorySlotOct = (MemoryItemViewModel ^) m_viewModel->MemorizedNumbers->GetAt(0);
- VERIFY_ARE_EQUAL(Platform::StringReference(L"377"), Utils::GetStringValue(memorySlotOct->Value));
+ VERIFY_ARE_EQUAL(Platform::StringReference(L"377"), GetStringValue(memorySlotOct->Value));
m_viewModel->SwitchProgrammerModeBase(NumberBase::DecBase);
MemoryItemViewModel ^ memorySlotDec = (MemoryItemViewModel ^) m_viewModel->MemorizedNumbers->GetAt(0);
- VERIFY_ARE_EQUAL(Platform::StringReference(L"255"), Utils::GetStringValue(memorySlotDec->Value));
+ VERIFY_ARE_EQUAL(Platform::StringReference(L"255"), GetStringValue(memorySlotDec->Value));
m_viewModel->SwitchProgrammerModeBase(NumberBase::BinBase);
MemoryItemViewModel ^ memorySlotBin = (MemoryItemViewModel ^) m_viewModel->MemorizedNumbers->GetAt(0);
- VERIFY_ARE_EQUAL(Platform::StringReference(L"1111 1111"), Utils::GetStringValue(memorySlotBin->Value));
+ VERIFY_ARE_EQUAL(Platform::StringReference(L"1111 1111"), GetStringValue(memorySlotBin->Value));
}
// When memory button is pressed more than max number of slots allowed,
@@ -965,7 +966,7 @@ namespace CalculatorUnitTests
m_viewModel->OnMemoryItemPressed(1);
m_viewModel->OnMemoryAdd(ref new Platform::Box(0));
MemoryItemViewModel ^ memorySlot = (MemoryItemViewModel ^) m_viewModel->MemorizedNumbers->GetAt(0);
- VERIFY_ARE_EQUAL(Platform::StringReference(L"3,003"), Utils::GetStringValue(memorySlot->Value));
+ VERIFY_ARE_EQUAL(Platform::StringReference(L"3,003"), GetStringValue(memorySlot->Value));
}
// Verify that raw, unformatted numbers are provided correctly
diff --git a/src/CalculatorUnitTests/pch.h b/src/CalculatorUnitTests/pch.h
index b4137b224..e24dd5304 100644
--- a/src/CalculatorUnitTests/pch.h
+++ b/src/CalculatorUnitTests/pch.h
@@ -21,7 +21,7 @@
#include
#include
#include
-#include
+#include
#include
#include
#include
diff --git a/src/GraphControl/Control/Grapher.cpp b/src/GraphControl/Control/Grapher.cpp
index 3a7708081..1e2b6c5b0 100644
--- a/src/GraphControl/Control/Grapher.cpp
+++ b/src/GraphControl/Control/Grapher.cpp
@@ -16,6 +16,7 @@ using namespace Concurrency;
using namespace Windows::Devices::Input;
using namespace Windows::Foundation;
using namespace Windows::Foundation::Collections;
+using namespace Windows::Storage;
using namespace Windows::Storage::Streams;
using namespace Windows::System;
using namespace Windows::System::Threading;
@@ -29,10 +30,14 @@ using namespace Windows::UI::Xaml::Media;
using namespace GraphControl;
DEPENDENCY_PROPERTY_INITIALIZATION(Grapher, ForceProportionalAxes);
+DEPENDENCY_PROPERTY_INITIALIZATION(Grapher, UseCommaDecimalSeperator);
DEPENDENCY_PROPERTY_INITIALIZATION(Grapher, Variables);
DEPENDENCY_PROPERTY_INITIALIZATION(Grapher, Equations);
DEPENDENCY_PROPERTY_INITIALIZATION(Grapher, AxesColor);
DEPENDENCY_PROPERTY_INITIALIZATION(Grapher, GraphBackground);
+DEPENDENCY_PROPERTY_INITIALIZATION(Grapher, GridLinesColor);
+DEPENDENCY_PROPERTY_INITIALIZATION(Grapher, LineWidth);
+DEPENDENCY_PROPERTY_INITIALIZATION(Grapher, IsKeepCurrentView);
namespace
{
@@ -83,6 +88,7 @@ namespace GraphControl
void Grapher::ZoomFromCenter(double scale)
{
ScaleRange(0, 0, scale);
+ GraphViewChangedEvent(this, GraphViewChangedReason::Manipulation);
}
void Grapher::ScaleRange(double centerX, double centerY, double scale)
@@ -91,9 +97,18 @@ namespace GraphControl
{
if (auto renderer = m_graph->GetRenderer())
{
+ m_renderMain->GetCriticalSection().lock();
+
if (SUCCEEDED(renderer->ScaleRange(centerX, centerY, scale)))
{
+ m_renderMain->GetCriticalSection().unlock();
+
m_renderMain->RunRenderPass();
+ GraphViewChangedEvent(this, GraphViewChangedReason::Manipulation);
+ }
+ else
+ {
+ m_renderMain->GetCriticalSection().unlock();
}
}
}
@@ -108,6 +123,7 @@ namespace GraphControl
if (SUCCEEDED(renderer->ResetRange()))
{
m_renderMain->RunRenderPass();
+ GraphViewChangedEvent(this, GraphViewChangedReason::Reset);
}
}
}
@@ -175,6 +191,7 @@ namespace GraphControl
{
if (m_graph)
{
+ m_graph->TryResetSelection();
UpdateGraphOptions(m_graph->GetOptions(), GetGraphableEquations());
}
@@ -191,14 +208,24 @@ namespace GraphControl
{
return;
}
+ bool keepCurrentView = true;
- PlotGraph(true);
+ // If the equation has changed, the IsLineEnabled state is reset.
+ // This checks if the equation has been reset and sets keepCurrentView to false in this case.
+ if (!equation->HasGraphError && !equation->IsValidated && equation->IsLineEnabled)
+ {
+ keepCurrentView = false;
+ }
+
+ PlotGraph(keepCurrentView);
}
KeyGraphFeaturesInfo ^ Grapher::AnalyzeEquation(Equation ^ equation)
{
if (auto graph = GetGraph(equation))
{
+ SetGraphArgs(graph);
+
if (auto analyzer = graph->GetAnalyzer())
{
vector equationVector;
@@ -227,7 +254,7 @@ namespace GraphControl
void Grapher::PlotGraph(bool keepCurrentView)
{
- TryPlotGraph(keepCurrentView, false);
+ TryPlotGraph(keepCurrentView,false);
}
task Grapher::TryPlotGraph(bool keepCurrentView, bool shouldRetry)
@@ -246,12 +273,35 @@ namespace GraphControl
co_await TryUpdateGraph(keepCurrentView);
}
}
+
+ int valid = 0;
+ int invalid = 0;
+ for (Equation ^ eq : Equations)
+ {
+ if (eq->HasGraphError)
+ {
+ invalid++;
+ }
+ if (eq->IsValidated)
+ {
+ valid++;
+ }
+ }
+ if (!m_trigUnitsChanged)
+ {
+ TraceLogger::GetInstance()->LogEquationCountChanged(valid, invalid);
+ }
+
+ m_trigUnitsChanged = false;
+ GraphPlottedEvent(this, ref new RoutedEventArgs());
}
task Grapher::TryUpdateGraph(bool keepCurrentView)
{
optional>> initResult = nullopt;
bool successful = false;
+ m_errorCode = 0;
+ m_errorType = 0;
if (m_renderMain && m_graph != nullptr)
{
@@ -277,7 +327,14 @@ namespace GraphControl
if (numValidEquations++ > 0)
{
- request += L",";
+ if (!UseCommaDecimalSeperator)
+ {
+ request += L",";
+ }
+ else
+ {
+ request += L";";
+ }
}
auto equationRequest = eq->GetRequest()->Data();
@@ -287,20 +344,38 @@ namespace GraphControl
co_return false;
}
+ unique_ptr expr;
+ wstring parsableEquation = s_getGraphOpeningTags;
+ parsableEquation += equationRequest;
+ parsableEquation += s_getGraphClosingTags;
+
+ // Wire up the corresponding error to an error message in the UI at some point
+ if (!(expr = m_solver->ParseInput(parsableEquation, m_errorCode, m_errorType)))
+ {
+ co_return false;
+ }
+
request += equationRequest;
}
request += s_getGraphClosingTags;
}
- if (graphExpression = m_solver->ParseInput(request))
+ if (graphExpression = m_solver->ParseInput(request, m_errorCode, m_errorType))
{
initResult = TryInitializeGraph(keepCurrentView, graphExpression.get());
if (initResult != nullopt)
{
+ auto graphedEquations = initResult.value();
+
+ for (int i = 0; i < validEqs.size(); i++)
+ {
+ validEqs[i]->GraphedEquation = graphedEquations[i];
+ }
+
UpdateGraphOptions(m_graph->GetOptions(), validEqs);
- SetGraphArgs();
+ SetGraphArgs(m_graph);
m_renderMain->Graph = m_graph;
@@ -316,8 +391,13 @@ namespace GraphControl
// If we failed to render then we have already lost the previous graph
shouldKeepPreviousGraph = false;
initResult = nullopt;
+ m_solver->HRErrorToErrorInfo(m_renderMain->GetRenderError(), m_errorCode, m_errorType);
}
}
+ else
+ {
+ m_solver->HRErrorToErrorInfo(m_graph->GetInitializationError(), m_errorCode, m_errorType);
+ }
}
if (initResult == nullopt)
@@ -325,11 +405,11 @@ namespace GraphControl
// Do not re-initialize the graph to empty if there are still valid equations graphed
if (!shouldKeepPreviousGraph)
{
- initResult = m_graph->TryInitialize();
+ initResult = TryInitializeGraph(false, nullptr);
if (initResult != nullopt)
{
- UpdateGraphOptions(m_graph->GetOptions(), validEqs);
- SetGraphArgs();
+ UpdateGraphOptions(m_graph->GetOptions(), vector());
+ SetGraphArgs(m_graph);
m_renderMain->Graph = m_graph;
co_await m_renderMain->RunRenderPassAsync();
@@ -361,20 +441,22 @@ namespace GraphControl
{
if (!eq->IsValidated)
{
+ eq->GraphErrorType = static_cast(m_errorType);
+ eq->GraphErrorCode = m_errorCode;
eq->HasGraphError = true;
}
}
}
- void Grapher::SetGraphArgs()
+ void Grapher::SetGraphArgs(shared_ptr graph)
{
- if (m_graph != nullptr && m_renderMain != nullptr)
+ if (graph != nullptr && m_renderMain != nullptr)
{
critical_section::scoped_lock lock(m_renderMain->GetCriticalSection());
- for (auto variable : Variables)
+ for (auto variablePair : Variables)
{
- m_graph->SetArgValue(variable->Key->Data(), variable->Value);
+ graph->SetArgValue(variablePair->Key->Data(), variablePair->Value->Value);
}
}
}
@@ -387,7 +469,7 @@ namespace GraphControl
request += equation->GetRequest()->Data();
request += s_getGraphClosingTags;
- if (unique_ptr graphExpression = m_solver->ParseInput(request))
+ if (unique_ptr graphExpression = m_solver->ParseInput(request, m_errorCode, m_errorType))
{
if (graph->TryInitialize(graphExpression.get()))
{
@@ -400,7 +482,7 @@ namespace GraphControl
void Grapher::UpdateVariables()
{
- auto updatedVariables = ref new Map();
+ auto updatedVariables = ref new Map();
if (m_graph)
{
@@ -413,47 +495,50 @@ namespace GraphControl
auto key = ref new String(graphVar->GetVariableName().data());
double value = 1.0;
+ Variable ^ variable;
+
if (Variables->HasKey(key))
{
- value = Variables->Lookup(key);
+ variable = Variables->Lookup(key);
+ }
+
+ if (variable == nullptr)
+ {
+ variable = ref new Variable(1.0);
}
- updatedVariables->Insert(key, value);
+ updatedVariables->Insert(key, variable);
}
}
}
+ if (Variables->Size != updatedVariables->Size)
+ {
+ TraceLogger::GetInstance()->LogVariableCountChanged(updatedVariables->Size);
+ }
+
Variables = updatedVariables;
VariablesUpdated(this, Variables);
}
void Grapher::SetVariable(Platform::String ^ variableName, double newValue)
{
- if (Variables->HasKey(variableName))
+ if (!Variables->HasKey(variableName))
{
- if (Variables->Lookup(variableName) == newValue)
- {
- return;
- }
-
- Variables->Remove(variableName);
+ Variables->Insert(variableName, ref new Variable(newValue));
}
- Variables->Insert(variableName, newValue);
-
if (m_graph != nullptr && m_renderMain != nullptr)
{
-
- auto workItemHandler = ref new WorkItemHandler([this, variableName, newValue](IAsyncAction ^ action) {
+ auto workItemHandler = ref new WorkItemHandler([this, variableName, newValue](IAsyncAction ^ action) {
m_renderMain->GetCriticalSection().lock();
m_graph->SetArgValue(variableName->Data(), newValue);
m_renderMain->GetCriticalSection().unlock();
- m_renderMain->RunRenderPassAsync();
+ m_renderMain->RunRenderPass();
});
ThreadPool::RunAsync(workItemHandler, WorkItemPriority::High, WorkItemOptions::None);
-
}
}
@@ -474,6 +559,18 @@ namespace GraphControl
{
auto lineColor = eq->LineColor;
graphColors.emplace_back(lineColor.R, lineColor.G, lineColor.B, lineColor.A);
+
+ if (eq->GraphedEquation)
+ {
+ if (!eq->HasGraphError && eq->IsSelected)
+ {
+ eq->GraphedEquation->TrySelectEquation();
+ }
+
+ eq->GraphedEquation->GetGraphEquationOptions()->SetLineStyle(static_cast<::Graphing::Renderer::LineStyle>(eq->EquationStyle));
+ eq->GraphedEquation->GetGraphEquationOptions()->SetLineWidth(LineWidth);
+ eq->GraphedEquation->GetGraphEquationOptions()->SetSelectedEquationLineWidth(LineWidth + ((LineWidth <= 2) ? 1 : 2));
+ }
}
options.SetGraphColors(graphColors);
}
@@ -500,12 +597,25 @@ namespace GraphControl
TryUpdateGraph(false);
}
+ void Grapher::OnUseCommaDecimalSeperatorPropertyChanged(bool oldValue, bool newValue)
+ {
+ if (newValue)
+ {
+ m_solver->ParsingOptions().SetLocalizationType(::LocalizationType::DecimalCommaAndListSemicolon);
+ m_solver->FormatOptions().SetLocalizationType(::LocalizationType::DecimalCommaAndListSemicolon);
+ }
+ else
+ {
+ m_solver->ParsingOptions().SetLocalizationType(::LocalizationType::DecimalPointAndListComma);
+ m_solver->FormatOptions().SetLocalizationType(::LocalizationType::DecimalPointAndListComma);
+ }
+ }
+
void Grapher::OnPointerEntered(PointerRoutedEventArgs ^ e)
{
if (m_renderMain)
{
OnPointerMoved(e);
- m_renderMain->DrawNearestPoint = true;
e->Handled = true;
}
@@ -528,9 +638,34 @@ namespace GraphControl
{
if (m_renderMain)
{
- PointerPoint ^ currPoint = e->GetCurrentPoint(/* relativeTo */ this);
- m_renderMain->PointerLocation = currPoint->Position;
- UpdateTracingChanged();
+ m_renderMain->DrawNearestPoint = true;
+ Point currPosition = e->GetCurrentPoint(/* relativeTo */ this)->Position;
+
+ if (m_renderMain->ActiveTracing)
+ {
+ PointerValueChangedEvent(currPosition);
+ ActiveTraceCursorPosition = currPosition;
+
+ if (m_cachedCursor == nullptr)
+ {
+ m_cachedCursor = ::CoreWindow::GetForCurrentThread()->PointerCursor;
+ ::CoreWindow::GetForCurrentThread()->PointerCursor = nullptr;
+ }
+ }
+ else if (m_cachedCursor != nullptr)
+ {
+ m_renderMain->PointerLocation = currPosition;
+
+ ::CoreWindow::GetForCurrentThread()->PointerCursor = m_cachedCursor;
+ m_cachedCursor = nullptr;
+
+ UpdateTracingChanged();
+ }
+ else
+ {
+ m_renderMain->PointerLocation = currPosition;
+ UpdateTracingChanged();
+ }
e->Handled = true;
}
@@ -544,6 +679,12 @@ namespace GraphControl
TracingChangedEvent(false);
e->Handled = true;
}
+
+ if (m_cachedCursor != nullptr)
+ {
+ ::CoreWindow::GetForCurrentThread()->PointerCursor = m_cachedCursor;
+ m_cachedCursor = nullptr;
+ }
}
void Grapher::OnPointerWheelChanged(PointerRoutedEventArgs ^ e)
@@ -570,6 +711,7 @@ namespace GraphControl
const auto [centerX, centerY] = PointerPositionToGraphPosition(pos.X, pos.Y, ActualWidth, ActualHeight);
ScaleRange(centerX, centerY, scale);
+ GraphViewChangedEvent(this, GraphViewChangedReason::Manipulation);
e->Handled = true;
}
@@ -614,11 +756,15 @@ namespace GraphControl
translationX /= -width;
translationY /= height;
+ m_renderMain->GetCriticalSection().lock();
+
if (FAILED(renderer->MoveRangeByRatio(translationX, translationY)))
{
+ m_renderMain->GetCriticalSection().unlock();
return;
}
+ m_renderMain->GetCriticalSection().unlock();
needsRenderPass = true;
}
@@ -632,17 +778,22 @@ namespace GraphControl
const auto& pos = e->Position;
const auto [centerX, centerY] = PointerPositionToGraphPosition(pos.X, pos.Y, width, height);
+ m_renderMain->GetCriticalSection().lock();
+
if (FAILED(renderer->ScaleRange(centerX, centerY, scale)))
{
+ m_renderMain->GetCriticalSection().unlock();
return;
}
+ m_renderMain->GetCriticalSection().unlock();
needsRenderPass = true;
}
if (needsRenderPass)
{
m_renderMain->RunRenderPass();
+ GraphViewChangedEvent(this, GraphViewChangedReason::Manipulation);
}
}
}
@@ -868,7 +1019,7 @@ String ^ Grapher::ConvertToLinear(String ^ mmlString)
{
m_solver->FormatOptions().SetFormatType(FormatType::LinearInput);
- auto expression = m_solver->ParseInput(mmlString->Data());
+ auto expression = m_solver->ParseInput(mmlString->Data(), m_errorCode, m_errorType);
auto linearExpression = m_solver->Serialize(expression.get());
m_solver->FormatOptions().SetFormatType(s_defaultFormatType);
@@ -878,7 +1029,7 @@ String ^ Grapher::ConvertToLinear(String ^ mmlString)
String ^ Grapher::FormatMathML(String ^ mmlString)
{
- auto expression = m_solver->ParseInput(mmlString->Data());
+ auto expression = m_solver->ParseInput(mmlString->Data(), m_errorCode, m_errorType);
auto formattedExpression = m_solver->Serialize(expression.get());
return ref new String(formattedExpression.c_str());
}
@@ -907,14 +1058,41 @@ void Grapher::OnGraphBackgroundPropertyChanged(Windows::UI::Color /*oldValue*/,
}
}
+
+void Grapher::OnGridLinesColorPropertyChanged(Windows::UI::Color /*oldValue*/, Windows::UI::Color newValue)
+{
+ if (m_renderMain != nullptr && m_graph != nullptr)
+ {
+ auto gridLinesColor = Graphing::Color(newValue.R, newValue.G, newValue.B, newValue.A);
+ m_graph->GetOptions().SetGridColor(gridLinesColor);
+ m_renderMain->RunRenderPassAsync();
+ }
+}
+
+void Grapher::OnLineWidthPropertyChanged(double oldValue, double newValue)
+{
+ if (m_graph)
+ {
+ UpdateGraphOptions(m_graph->GetOptions(), GetGraphableEquations());
+ if (m_renderMain)
+ {
+ m_renderMain->SetPointRadius(LineWidth + 1);
+ m_renderMain->RunRenderPass();
+
+ TraceLogger::GetInstance()->LogLineWidthChanged();
+ }
+ }
+}
+
optional>> Grapher::TryInitializeGraph(bool keepCurrentView, const IExpression* graphingExp)
{
- if (keepCurrentView)
+ if (keepCurrentView || IsKeepCurrentView)
{
double xMin, xMax, yMin, yMax;
m_graph->GetRenderer()->GetDisplayRanges(xMin, xMax, yMin, yMax);
auto initResult = m_graph->TryInitialize(graphingExp);
m_graph->GetRenderer()->SetDisplayRanges(xMin, xMax, yMin, yMax);
+
return initResult;
}
else
diff --git a/src/GraphControl/Control/Grapher.h b/src/GraphControl/Control/Grapher.h
index 9b00acc2e..e0fa7a408 100644
--- a/src/GraphControl/Control/Grapher.h
+++ b/src/GraphControl/Control/Grapher.h
@@ -4,14 +4,16 @@
#pragma once
#include "DirectX/RenderMain.h"
-#include "../Models/Equation.h"
-#include "../Models/EquationCollection.h"
-#include "../Utils.h"
+#include "Models/Equation.h"
+#include "Models/EquationCollection.h"
+#include "Models/Variable.h"
+#include "Utils.h"
#include "IGraphAnalyzer.h"
#include "IMathSolver.h"
#include "Common.h"
#include "Models/KeyGraphFeaturesInfo.h"
#include
+#include "Logger/TraceLogger.h"
namespace GraphControl
{
@@ -23,6 +25,12 @@ public
public
delegate void PointerValueChangedEventHandler(Windows::Foundation::Point value);
+public enum class GraphViewChangedReason
+{
+ Manipulation,
+ Reset
+};
+
[Windows::UI::Xaml::Markup::ContentPropertyAttribute(Name = L"Equations")] public ref class Grapher sealed
: public Windows::UI::Xaml::Controls::Control,
public Windows::UI::Xaml::Data::INotifyPropertyChanged
@@ -31,6 +39,8 @@ public
event TracingValueChangedEventHandler ^ TracingValueChangedEvent;
event PointerValueChangedEventHandler ^ PointerValueChangedEvent;
event TracingChangedEventHandler ^ TracingChangedEvent;
+ event Windows::Foundation::EventHandler ^ GraphViewChangedEvent;
+ event Windows::UI::Xaml::RoutedEventHandler ^ GraphPlottedEvent;
virtual event Windows::UI::Xaml::Data::PropertyChangedEventHandler ^ PropertyChanged;
public:
@@ -38,13 +48,17 @@ public
DEPENDENCY_PROPERTY_OWNER(Grapher);
DEPENDENCY_PROPERTY_WITH_DEFAULT_AND_CALLBACK(bool, ForceProportionalAxes, true);
+ DEPENDENCY_PROPERTY_WITH_DEFAULT_AND_CALLBACK(bool, UseCommaDecimalSeperator, false);
DEPENDENCY_PROPERTY_WITH_DEFAULT(
- SINGLE_ARG(Windows::Foundation::Collections::IObservableMap ^),
+ SINGLE_ARG(Windows::Foundation::Collections::IObservableMap ^),
Variables,
- SINGLE_ARG(ref new Platform::Collections::Map()));
+ SINGLE_ARG(ref new Platform::Collections::Map()));
DEPENDENCY_PROPERTY_R_WITH_DEFAULT_AND_CALLBACK(GraphControl::EquationCollection ^, Equations, nullptr);
DEPENDENCY_PROPERTY_WITH_DEFAULT_AND_CALLBACK(Windows::UI::Color, AxesColor, Windows::UI::Colors::Transparent);
DEPENDENCY_PROPERTY_WITH_DEFAULT_AND_CALLBACK(Windows::UI::Color, GraphBackground, Windows::UI::Colors::Transparent);
+ DEPENDENCY_PROPERTY_WITH_DEFAULT_AND_CALLBACK(Windows::UI::Color, GridLinesColor, Windows::UI::Colors::Transparent);
+ DEPENDENCY_PROPERTY_WITH_DEFAULT_AND_CALLBACK(double, LineWidth, 2.0);
+ DEPENDENCY_PROPERTY_WITH_DEFAULT(bool, IsKeepCurrentView, false);
// Pass active tracing turned on or off down to the renderer
property bool ActiveTracing
@@ -101,7 +115,7 @@ public
}
}
- event Windows::Foundation::EventHandler ^> ^ VariablesUpdated;
+ event Windows::Foundation::EventHandler ^> ^ VariablesUpdated;
void SetVariable(Platform::String ^ variableName, double newValue);
Platform::String ^ ConvertToLinear(Platform::String ^ mmlString);
Platform::String ^ FormatMathML(Platform::String ^ mmlString);
@@ -123,6 +137,7 @@ public
if (value != (int)m_solver->EvalOptions().GetTrigUnitMode())
{
m_solver->EvalOptions().SetTrigUnitMode((Graphing::EvalTrigUnitMode)value);
+ m_trigUnitsChanged = true;
PlotGraph(true);
}
}
@@ -241,6 +256,7 @@ public
if (m_renderMain)
{
m_renderMain->RunRenderPass();
+ GraphViewChangedEvent(this, GraphViewChangedReason::Manipulation);
}
}
}
@@ -266,9 +282,12 @@ public
private:
void OnForceProportionalAxesPropertyChanged(bool oldValue, bool newValue);
+ void OnUseCommaDecimalSeperatorPropertyChanged(bool oldValue, bool newValue);
void OnEquationsPropertyChanged(EquationCollection ^ oldValue, EquationCollection ^ newValue);
void OnAxesColorPropertyChanged(Windows::UI::Color oldValue, Windows::UI::Color newValue);
void OnGraphBackgroundPropertyChanged(Windows::UI::Color oldValue, Windows::UI::Color newValue);
+ void OnGridLinesColorPropertyChanged(Windows::UI::Color /*oldValue*/, Windows::UI::Color newValue);
+ void OnLineWidthPropertyChanged(double oldValue, double newValue);
void OnEquationChanged(Equation ^ equation);
void OnEquationStyleChanged(Equation ^ equation);
void OnEquationLineEnabledChanged(Equation ^ equation);
@@ -276,7 +295,7 @@ public
concurrency::task TryPlotGraph(bool keepCurrentView, bool shouldRetry);
void UpdateGraphOptions(Graphing::IGraphingOptions& options, const std::vector& validEqs);
std::vector GetGraphableEquations();
- void SetGraphArgs();
+ void SetGraphArgs(std::shared_ptr graph);
std::shared_ptr GetGraph(GraphControl::Equation ^ equation);
void UpdateVariables();
@@ -292,6 +311,8 @@ public
void SetEquationsAsValid();
void SetEquationErrors();
std::optional>> TryInitializeGraph(bool keepCurrentView, _In_ const Graphing::IExpression* graphingExp = nullptr);
+
+
private:
DX::RenderMain ^ m_renderMain = nullptr;
@@ -313,6 +334,7 @@ public
const std::shared_ptr m_graph;
bool m_calculatedForceProportional = false;
bool m_tracingTracking;
+ bool m_trigUnitsChanged;
enum KeysPressedSlots
{
Left,
@@ -325,6 +347,9 @@ public
bool m_KeysPressed[5];
bool m_Moving;
Windows::UI::Xaml::DispatcherTimer ^ m_TracingTrackingTimer;
+ Windows::UI::Core::CoreCursor ^ m_cachedCursor;
+ int m_errorType;
+ int m_errorCode;
public:
Windows::Storage::Streams::RandomAccessStreamReference ^ GetGraphBitmapStream();
diff --git a/src/GraphControl/DirectX/NearestPointRenderer.cpp b/src/GraphControl/DirectX/NearestPointRenderer.cpp
index 64b114e33..d820c4f7c 100644
--- a/src/GraphControl/DirectX/NearestPointRenderer.cpp
+++ b/src/GraphControl/DirectX/NearestPointRenderer.cpp
@@ -54,6 +54,12 @@ void NearestPointRenderer::Render(const Point& location)
}
}
+void NearestPointRenderer::SetRadius(float radius)
+{
+ m_ellipse.radiusX = radius;
+ m_ellipse.radiusY = radius;
+}
+
void NearestPointRenderer::SetColor(const ColorF& color)
{
m_color = color;
@@ -63,7 +69,5 @@ void NearestPointRenderer::SetColor(const ColorF& color)
void NearestPointRenderer::CreateBrush()
{
m_brush.Reset();
- ThrowIfFailed(
- m_deviceResources->GetD2DDeviceContext()->CreateSolidColorBrush(m_color, &m_brush)
- );
+ ThrowIfFailed(m_deviceResources->GetD2DDeviceContext()->CreateSolidColorBrush(m_color, &m_brush));
}
diff --git a/src/GraphControl/DirectX/NearestPointRenderer.h b/src/GraphControl/DirectX/NearestPointRenderer.h
index 791496545..541eaba62 100644
--- a/src/GraphControl/DirectX/NearestPointRenderer.h
+++ b/src/GraphControl/DirectX/NearestPointRenderer.h
@@ -17,6 +17,7 @@ namespace GraphControl::DX
void Render(const Windows::Foundation::Point& location);
void SetColor(const D2D1::ColorF& color);
+ void SetRadius(float radius);
private:
void CreateBrush();
diff --git a/src/GraphControl/DirectX/RenderMain.cpp b/src/GraphControl/DirectX/RenderMain.cpp
index 169af46b0..87fac0deb 100644
--- a/src/GraphControl/DirectX/RenderMain.cpp
+++ b/src/GraphControl/DirectX/RenderMain.cpp
@@ -86,7 +86,6 @@ namespace GraphControl::DX
{
m_Tracing = false;
}
- RunRenderPass();
}
}
@@ -95,7 +94,12 @@ namespace GraphControl::DX
if (m_pointerLocation != location)
{
m_pointerLocation = location;
- RunRenderPass();
+
+ bool wasPointRendered = m_Tracing;
+ if (CanRenderPoint() || wasPointRendered)
+ {
+ RunRenderPassAsync();
+ }
}
}
@@ -104,7 +108,12 @@ namespace GraphControl::DX
if (m_drawActiveTracing != value)
{
m_drawActiveTracing = value;
- RunRenderPass();
+
+ bool wasPointRendered = m_Tracing;
+ if (CanRenderPoint() || wasPointRendered)
+ {
+ RunRenderPassAsync();
+ }
}
}
@@ -127,6 +136,56 @@ namespace GraphControl::DX
}
}
+ bool RenderMain::CanRenderPoint()
+ {
+ if (m_drawNearestPoint || m_drawActiveTracing)
+ {
+ Point trackPoint = m_pointerLocation;
+
+ if (m_drawActiveTracing)
+ {
+ trackPoint = m_activeTracingPointerLocation;
+ }
+
+ if (!m_criticalSection.try_lock())
+ {
+ return false;
+ }
+
+ m_criticalSection.unlock();
+
+ critical_section::scoped_lock lock(m_criticalSection);
+
+ int formulaId = -1;
+ float nearestPointLocationX, nearestPointLocationY;
+ double nearestPointValueX, nearestPointValueY, rhoValueOut, thetaValueOut, tValueOut;
+ m_Tracing = m_graph->GetRenderer()->GetClosePointData(
+ trackPoint.X,
+ trackPoint.Y,
+ formulaId,
+ nearestPointLocationX,
+ nearestPointLocationY,
+ nearestPointValueX,
+ nearestPointValueY,
+ rhoValueOut,
+ thetaValueOut,
+ tValueOut)
+ == S_OK;
+ m_Tracing = m_Tracing && !isnan(nearestPointLocationX) && !isnan(nearestPointLocationY);
+ }
+ else
+ {
+ m_Tracing = false;
+ }
+
+ return m_Tracing;
+ }
+
+ void RenderMain::SetPointRadius(float radius)
+ {
+ m_nearestPointRenderer.SetRadius(radius);
+ }
+
bool RenderMain::RunRenderPass()
{
// Non async render passes cancel if they can't obtain the lock immediatly
@@ -214,7 +273,9 @@ namespace GraphControl::DX
pRenderTarget->BeginDraw();
bool hasMissingData = false;
- successful = SUCCEEDED(renderer->DrawD2D1(pFactory, pRenderTarget, hasMissingData));
+ m_HResult = renderer->DrawD2D1(pFactory, pRenderTarget, hasMissingData);
+
+ successful = SUCCEEDED(m_HResult);
// We ignore D2DERR_RECREATE_TARGET here. This error indicates that the device
// is lost. It will be handled during the next call to Present.
@@ -285,6 +346,11 @@ namespace GraphControl::DX
return successful;
}
+ HRESULT RenderMain::GetRenderError()
+ {
+ return m_HResult;
+ }
+
void RenderMain::OnLoaded(Object ^ sender, RoutedEventArgs ^ e)
{
RunRenderPass();
diff --git a/src/GraphControl/DirectX/RenderMain.h b/src/GraphControl/DirectX/RenderMain.h
index f46471130..b9b6e014d 100644
--- a/src/GraphControl/DirectX/RenderMain.h
+++ b/src/GraphControl/DirectX/RenderMain.h
@@ -45,6 +45,10 @@ namespace GraphControl::DX
void CreateWindowSizeDependentResources();
+ bool RenderMain::CanRenderPoint();
+
+ void SetPointRadius(float radius);
+
bool RunRenderPass();
Windows::Foundation::IAsyncAction ^ RunRenderPassAsync(bool allowCancel = true);
@@ -59,6 +63,8 @@ namespace GraphControl::DX
return m_isRenderPassSuccesful;
}
+ HRESULT GetRenderError();
+
// Indicates if we are in active tracing mode (the tracing box is being used and controlled through keyboard input)
property bool ActiveTracing
{
@@ -78,7 +84,12 @@ namespace GraphControl::DX
if (m_activeTracingPointerLocation != newValue)
{
m_activeTracingPointerLocation = newValue;
- RunRenderPass();
+
+ bool wasPointRendered = m_Tracing;
+ if (CanRenderPoint() || wasPointRendered)
+ {
+ RunRenderPassAsync();
+ }
}
}
}
@@ -182,5 +193,7 @@ namespace GraphControl::DX
Windows::Foundation::IAsyncAction ^ m_renderPass = nullptr;
bool m_isRenderPassSuccesful;
+
+ HRESULT m_HResult;
};
}
diff --git a/src/GraphControl/GraphControl.vcxproj b/src/GraphControl/GraphControl.vcxproj
index 460cbdcd0..7a64af776 100644
--- a/src/GraphControl/GraphControl.vcxproj
+++ b/src/GraphControl/GraphControl.vcxproj
@@ -283,17 +283,24 @@
$(GraphingImplLibDir);%(AdditionalLibraryDirectories)
+
+
+ /DSEND_DIAGNOSTICS %(AdditionalOptions)
+
+
+
+
@@ -301,6 +308,7 @@
+
@@ -322,6 +330,11 @@
{52E03A58-B378-4F50-8BFB-F659FB85E790}
+
+
+ {fc81ff41-02cd-4cd9-9bc5-45a1e39ac6ed}
+
+
\ No newline at end of file
diff --git a/src/GraphControl/GraphControl.vcxproj.filters b/src/GraphControl/GraphControl.vcxproj.filters
index 2b7c4e99e..60ea5d322 100644
--- a/src/GraphControl/GraphControl.vcxproj.filters
+++ b/src/GraphControl/GraphControl.vcxproj.filters
@@ -32,6 +32,7 @@
Models
+
@@ -59,15 +60,16 @@
Models
+
+ Models
+
+
Themes
-
-
-
diff --git a/src/GraphControl/Logger/TraceLogger.cpp b/src/GraphControl/Logger/TraceLogger.cpp
new file mode 100644
index 000000000..82a8a98a3
--- /dev/null
+++ b/src/GraphControl/Logger/TraceLogger.cpp
@@ -0,0 +1,97 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+#include "pch.h"
+#include "TraceLogger.h"
+
+using namespace TraceLogging;
+using namespace Concurrency;
+using namespace std;
+using namespace Platform;
+using namespace Windows::Foundation;
+using namespace Windows::Foundation::Diagnostics;
+using namespace Windows::Globalization;
+
+namespace GraphControl
+{
+ static reader_writer_lock s_traceLoggerLock;
+
+ constexpr auto GRAPHING_MODE = L"Graphing";
+ constexpr auto CALC_MODE = L"CalcMode";
+
+ // Diagnostics events. Uploaded to asimov.
+ constexpr auto EVENT_NAME_EQUATION_COUNT_CHANGED = L"EquationCountChanged";
+ constexpr auto EVENT_NAME_FUNCTION_ANALYSIS_PERFORMED = L"FunctionAnalysisPerformed";
+ constexpr auto EVENT_NAME_VARIABLES_COUNT_CHANGED = L"VariablesCountChanged";
+ constexpr auto EVENT_NAME_LINE_WIDTH_CHANGED = L"LineWidthChanged";
+
+ TraceLogger ^ TraceLogger::GetInstance()
+ {
+ static TraceLogger ^ s_selfInstance = ref new TraceLogger();
+ return s_selfInstance;
+ }
+
+ void TraceLogger::LogEquationCountChanged(int currentValidEquations, int currentInvalidEquations)
+ {
+ static bool firstRun = true;
+ if (firstRun)
+ {
+ firstRun = false;
+ return;
+ }
+
+ // Update the total valid/invalid equations to record the max value.
+ // Equations are added/removed/updated one at a time, so we know either
+ // currentValidEquations or currentInvalidEquations increased,
+ // but they cannot both increase at the same time
+ // If an equation was removed, do not decrement the total count.
+ static uint64 TotalValidEquations = 0;
+ static uint64 TotalInvalidEquations = 0;
+ static uint64 PreviousValidEquations = 0;
+ static uint64 PreviousInvalidEquations = 0;
+
+ if (currentValidEquations > PreviousValidEquations)
+ {
+ TotalValidEquations++;
+ }
+ else if (currentInvalidEquations > PreviousInvalidEquations)
+ {
+ TotalInvalidEquations++;
+ }
+
+ PreviousValidEquations = currentValidEquations;
+ PreviousInvalidEquations = currentInvalidEquations;
+
+ auto fields = ref new LoggingFields();
+ fields->AddString(StringReference(CALC_MODE), StringReference(GRAPHING_MODE));
+ fields->AddUInt64(StringReference(L"ConcurrentValidFunctions"), currentValidEquations);
+ fields->AddUInt64(StringReference(L"ConcurrentInvalidFunctions"), currentInvalidEquations);
+ fields->AddUInt64(StringReference(L"TotalValidFunctions"), TotalValidEquations);
+ fields->AddUInt64(StringReference(L"TotalInvalidFunctions"), TotalInvalidEquations);
+ TraceLoggingCommon::GetInstance()->LogLevel2Event(StringReference(EVENT_NAME_EQUATION_COUNT_CHANGED), fields);
+ }
+
+ void TraceLogger::LogFunctionAnalysisPerformed(int analysisErrorType, uint32 tooComplexFlag)
+ {
+ auto fields = ref new LoggingFields();
+ fields->AddString(StringReference(CALC_MODE), StringReference(GRAPHING_MODE));
+ fields->AddInt32(StringReference(L"AnalysisErrorType"), analysisErrorType);
+ fields->AddUInt32(StringReference(L"TooComplexFeatures"), tooComplexFlag);
+ TraceLoggingCommon::GetInstance()->LogLevel2Event(StringReference(EVENT_NAME_FUNCTION_ANALYSIS_PERFORMED), fields);
+ }
+
+ void TraceLogger::LogVariableCountChanged(int variablesCount)
+ {
+ auto fields = ref new LoggingFields();
+ fields->AddString(StringReference(CALC_MODE), StringReference(GRAPHING_MODE));
+ fields->AddInt64(StringReference(L"VariableCount"), variablesCount);
+ TraceLoggingCommon::GetInstance()->LogLevel2Event(StringReference(EVENT_NAME_VARIABLES_COUNT_CHANGED), fields);
+ }
+
+ void TraceLogger::LogLineWidthChanged()
+ {
+ auto fields = ref new LoggingFields();
+ fields->AddString(StringReference(CALC_MODE), StringReference(GRAPHING_MODE));
+ TraceLoggingCommon::GetInstance()->LogLevel2Event(StringReference(EVENT_NAME_LINE_WIDTH_CHANGED), fields);
+ }
+}
diff --git a/src/GraphControl/Logger/TraceLogger.h b/src/GraphControl/Logger/TraceLogger.h
new file mode 100644
index 000000000..5ae60e062
--- /dev/null
+++ b/src/GraphControl/Logger/TraceLogger.h
@@ -0,0 +1,28 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+#pragma once
+
+#include "Common.h"
+
+// A trace logging provider can only be instantiated and registered once per module.
+// This class implements a singleton model ensure that only one instance is created.
+namespace GraphControl
+{
+
+ public ref class TraceLogger sealed
+ {
+ internal:
+ static TraceLogger ^ GetInstance();
+
+ void LogEquationCountChanged(int currentValidEquations, int currentInvalidEquations);
+ void LogFunctionAnalysisPerformed(int analysisErrorType, uint32 tooComplexFlag);
+ void LogVariableCountChanged(int variablesCount);
+ void LogLineWidthChanged();
+
+ private:
+ TraceLogger()
+ {
+ }
+ };
+}
diff --git a/src/GraphControl/Models/Equation.cpp b/src/GraphControl/Models/Equation.cpp
index 02be2cb01..32ae6db78 100644
--- a/src/GraphControl/Models/Equation.cpp
+++ b/src/GraphControl/Models/Equation.cpp
@@ -26,14 +26,16 @@ namespace GraphControl
{
wstring request;
wstring_view expr{ Expression->Data() };
+ IsInequality = false;
// Check for unicode characters of less than, less than or equal to, greater than and greater than or equal to.
if (expr.find(L">><") != wstring_view::npos || expr.find(L"><<") != wstring_view::npos || expr.find(L">≥<") != wstring_view::npos
|| expr.find(L">≤<") != wstring_view::npos || expr.find(8805) != wstring_view::npos || expr.find(8804) != wstring_view::npos
- || expr.find(L"><<") != wstring_view::npos
- || expr.find(L">><") != wstring_view::npos)
+ || expr.find(L"><<") != wstring_view::npos || expr.find(L">><") != wstring_view::npos)
{
request = L"plotIneq2D";
+ IsInequality = true;
+ EquationStyle = EquationLineStyle::Dash;
}
else if (expr.find(L">=<") != wstring_view::npos)
{
diff --git a/src/GraphControl/Models/Equation.h b/src/GraphControl/Models/Equation.h
index cc404b7e0..da5c50cfc 100644
--- a/src/GraphControl/Models/Equation.h
+++ b/src/GraphControl/Models/Equation.h
@@ -7,6 +7,210 @@
namespace GraphControl
{
+public
+ enum class EquationLineStyle : int
+ {
+ Solid,
+ Dot,
+ Dash,
+ DashDot,
+ DashDotDot
+ };
+
+ public enum class ErrorType
+ {
+ Evaluation,
+ Syntax,
+ Abort,
+ };
+
+ public enum class EvaluationErrorCode
+ {
+ // Number is too large. To see this error, assign a large number to variable a, then keep doing "a:=a*a" until it happens
+ Overflow = 2,
+
+ // doing trig in calculus and current mode is not Radians
+ RequireRadiansMode = 3,
+
+ // This is actually abort code generated as time limit reached.
+ TooComplexToSolve = 4,
+
+ // degree sign present and the current mode is not Degrees
+ RequireDegreesMode = 5,
+
+ // n! and n is not an non-negative integer or m/2
+ FactorialInvalidArgument = -1,
+
+ // n!! and n is not an non-negative integer or odd negative integers
+ Factorial2InvalidArgument = -2,
+
+ // n! and n is too big
+ FactorialCannotPerformOnLargeNumber = -3,
+
+ // x mod y, and one of them is not an integer
+ ModuloCannotPerformOnFloat = -5,
+
+ // below are equation solving specific errors
+
+ // example1: sin(x)+x=2 example2: x^4-x^3-8x=9
+ EquationTooComplexToSolveSymbolic = -7,
+
+ // example1: x-x=3 example2: x^2=-1
+ EquationHasNoSolution = -8,
+
+ // only used for numeric solve where the algorithm doesn't converge
+ EquationTooComplexToSolve = -9,
+
+ // used when equation cannot be ploted
+ EquationTooComplexToPlot = -10,
+
+ // example1: 1/0
+ DivideByZero = -15,
+
+ // the inequality is too complex for the engine to solve
+ InequalityTooComplexToSolve = -41,
+
+ // the inequality has no solution
+ InequalityHasNoSolution = -42,
+
+ // An exression contains logical conditions that are mutually exclusive
+ MutuallyExclusiveConditions = -43,
+
+ // Arbitrary Precision Evaluation input is out of domain
+ OutOfDomain = -101,
+
+ // Not supported.
+ GE_NotSupported = -503,
+
+ // General error for graphing engine
+ GE_GeneralError = -504,
+
+ // Failed to calculate
+ GE_TooComplexToSolve = -506,
+ };
+
+ public enum class SyntaxErrorCode
+ {
+ // found ) without matching (
+ ParenthesisMismatch = 1,
+
+ // found ( without matching )
+ UnmatchedParenthesis = 2,
+
+ // more than 1 decimal point in a number. Example: 7.3.2
+ TooManyDecimalPoints = 3,
+
+ // decimal point on its own without any digits surrounding it. Example: 3+.+4
+ DecimalPointWithoutDigits = 4,
+
+ // example: 3-4*
+ UnexpectedEndOfExpression = 5,
+
+ // example: 3-*4
+ UnexpectedToken = 6,
+
+ // example: [ (or many other special characters), another example: "3,5" (comma is invalid here)
+ InvalidToken = 7,
+
+ // example: solve(x+3=8=x)
+ TooManyEquals = 8,
+
+ // example: ploteq(4+83=9)
+ EqualWithoutGraphVariable = 10,
+
+ // example: ploteq(x+y) (expecting "=" in equation ploting)
+ // example2: Solve(5*x+9) (expecting = in the equation solving)
+ InvalidEquationSyntax = 11,
+
+ // there is nothing in the expression
+ EmptyExpression = 12,
+
+ // example: factor(x=3) (expecting solve(x=3)).
+ EqualWithoutEquation = 14,
+
+ // example: solve( (x=3)*2 )
+ InvalidEquationFormat = 15,
+
+ // This error only occurs when CasContext.ParsingOptions.AllowImplicitParentheses == false.
+ // example: sin a (expecting sin(a))
+ ExpectParenthesisAfterFunctionName = 25,
+
+ // example: root(a) (expecting 2 parameters)
+ IncorrectNumParameter = 26,
+
+ // exmaple: "x_", "x_@", "x__1"
+ InvalidVariableNameFormat = 32,
+
+ // found } without matching {
+ BracketMismatch = 34,
+
+ // found { without matching }
+ UnmatchedBracket = 35,
+
+ // syntax error in MathML format. Used only if CasContext.ParsingOptions.FormatType is MathML or MathMLNoWrapper
+ InvalidMathMLFormat = 40,
+
+ // The input has an unknown MathML entity. Used only if CasContext.ParsingOptions.FormatType is MathML or MathMLNoWrapper
+ UnknownMathMLEntity = 41,
+
+ // The input has an unknown MathML element. Used only if CasContext.ParsingOptions.FormatType is MathML or MathMLNoWrapper
+ UnknownMathMLElement = 42,
+
+ // "i" and "I" cannot be used as variable names in real number field
+ CannotUseIInReal = 48,
+
+ // General error
+ GeneralError = 52,
+
+ // used in parsing numbers with arbitrary bases. example: base(2, 1020), base(16, 1AG)
+ InvalidNumberDigit = 55,
+
+ // a valid number base must be an integer >=2 and <=36
+ InvalidNumberBase = 56,
+
+ // some functions require a variable in certain argument position. e.g. 2nd argument of deriv, integral, limit, etc.
+ // this error code is used if the argument at the position is not a variable
+ InvalidVariableSpecification = 57,
+
+ // all operands of logical operators must be logical. example: "true and 1"
+ ExpectingLogicalOperands = 58,
+
+ // all operands of a non-logical operator must not be logical. example: "sin(true)"
+ ExpectingScalarOperands = 59,
+
+ // a list can contain logicals or scalars, but not both.
+ CannotMixLogicalScalarInList = 60,
+
+ // in definite integral, seriesSum and seriesProduct, the index variable is used in the lower/upper limits.
+ // example: integral(sin(x), x, 0, x)
+ CannotUseIndexVarInOpLimits = 61,
+
+ // in limit, the index variable is used in the limit point
+ // example: limit(sin(x), x, x-1)
+ CannotUseIndexVarInLimPoint = 62,
+
+ /// ComplexInfinity cannot be used in real number field
+ CannotUseComplexInfinityInReal = 72,
+
+ // complex numbers are not allowed in inequality solving
+ CannotUseIInInequalitySolving = 123,
+
+ // Indicate a bug in the MathRichEdit serializer
+ RichEditSerializationError = 201,
+
+ // can't initialize math zone in richedit, meaning it's the wrong version richedit dll, need reinstall
+ RichEditInitialization = 202,
+
+ // indicate bug in either richedit or richedit wrapper
+ RichEditInlineObjectStructure = 203,
+
+ // in a structure like integral, sum, product, one of the boxes is not filled
+ RichEditMissingArgument = 204,
+
+ // errors in richedit wrapper that are not specifically handled for
+ RichEditGeneralError = 210,
+ };
+
[Windows::UI::Xaml::Data::Bindable] public ref class Equation sealed : public Windows::UI::Xaml::Data::INotifyPropertyChanged
{
public:
@@ -17,6 +221,11 @@ namespace GraphControl
OBSERVABLE_NAMED_PROPERTY_RW(bool, IsLineEnabled);
OBSERVABLE_NAMED_PROPERTY_RW(bool, IsValidated);
OBSERVABLE_NAMED_PROPERTY_RW(bool, HasGraphError);
+ OBSERVABLE_NAMED_PROPERTY_RW(bool, IsInequality);
+ OBSERVABLE_NAMED_PROPERTY_RW(bool, IsSelected);
+ OBSERVABLE_NAMED_PROPERTY_RW(EquationLineStyle, EquationStyle);
+ OBSERVABLE_NAMED_PROPERTY_RW(ErrorType, GraphErrorType);
+ OBSERVABLE_NAMED_PROPERTY_RW(int, GraphErrorCode);
property Windows::UI::Color LineColor
{
@@ -24,18 +233,30 @@ namespace GraphControl
void set(Windows::UI::Color value);
}
- static property Platform::String
- ^ LineColorPropertyName { Platform::String ^ get(); }
-
- public : Platform::String
- ^ GetRequest();
+ static property Platform::String ^ LineColorPropertyName { Platform::String ^ get(); }
+ public:
+ Platform::String ^ GetRequest();
bool IsGraphableEquation();
+ internal:
+ property std::shared_ptr GraphedEquation
+ {
+ void set(std::shared_ptr graphedEquation)
+ {
+ m_graphedEquation = graphedEquation;
+ }
+ std::shared_ptr get()
+ {
+ return m_graphedEquation;
+ }
+ }
+
private:
std::wstring GetExpression();
private:
Windows::UI::Color m_LineColor;
+ std::shared_ptr m_graphedEquation;
};
}
diff --git a/src/GraphControl/Models/EquationCollection.h b/src/GraphControl/Models/EquationCollection.h
index d1e1ba185..59b9cdbe4 100644
--- a/src/GraphControl/Models/EquationCollection.h
+++ b/src/GraphControl/Models/EquationCollection.h
@@ -158,7 +158,7 @@ public
{
auto equation = static_cast(sender);
auto propertyName = args->PropertyName;
- if (propertyName == GraphControl::Equation::LineColorPropertyName)
+ if (propertyName == GraphControl::Equation::LineColorPropertyName || propertyName == GraphControl::Equation::IsSelectedPropertyName || propertyName == GraphControl::Equation::EquationStylePropertyName)
{
EquationStyleChanged(equation);
}
diff --git a/src/GraphControl/Models/KeyGraphFeaturesInfo.cpp b/src/GraphControl/Models/KeyGraphFeaturesInfo.cpp
index 3d5a7d209..ca48f5c95 100644
--- a/src/GraphControl/Models/KeyGraphFeaturesInfo.cpp
+++ b/src/GraphControl/Models/KeyGraphFeaturesInfo.cpp
@@ -59,6 +59,8 @@ KeyGraphFeaturesInfo ^ KeyGraphFeaturesInfo::Create(IGraphFunctionAnalysisData d
res->ObliqueAsymptotes = ConvertWStringVector(data.ObliqueAsymptotes);
res->TooComplexFeatures = data.TooComplexFeatures;
res->AnalysisError = CalculatorApp::AnalysisErrorType::NoError;
+
+ TraceLogger::GetInstance()->LogFunctionAnalysisPerformed(CalculatorApp::AnalysisErrorType::NoError, res->TooComplexFeatures);
return res;
}
@@ -66,5 +68,7 @@ KeyGraphFeaturesInfo ^ KeyGraphFeaturesInfo::Create(CalculatorApp::AnalysisError
{
auto res = ref new KeyGraphFeaturesInfo();
res->AnalysisError = type;
+
+ TraceLogger::GetInstance()->LogFunctionAnalysisPerformed(type, 0);
return res;
}
diff --git a/src/GraphControl/Models/Variable.h b/src/GraphControl/Models/Variable.h
new file mode 100644
index 000000000..dd3fbb97d
--- /dev/null
+++ b/src/GraphControl/Models/Variable.h
@@ -0,0 +1,26 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+#pragma once
+#include "Utils.h"
+
+namespace GraphControl
+{
+public
+ ref class Variable sealed
+ {
+ public:
+ PROPERTY_RW(double, Value);
+ PROPERTY_RW(double, Step);
+ PROPERTY_RW(double, Min);
+ PROPERTY_RW(double, Max);
+
+ Variable(double value)
+ : m_Value{ value }
+ , m_Step{ 0.1 }
+ , m_Min{ -5.0 }
+ , m_Max{ 5.0 }
+ {
+ }
+ };
+}
diff --git a/src/GraphControl/pch.h b/src/GraphControl/pch.h
index 286138408..21f160824 100644
--- a/src/GraphControl/pch.h
+++ b/src/GraphControl/pch.h
@@ -1,3 +1,6 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
#pragma once
//C4453: A '[WebHostHidden]' type should not be used on the published surface of a public type that is not '[WebHostHidden]'
@@ -14,7 +17,7 @@
#include
#include
#include
-#include
+#include
#include
#include
#include
diff --git a/src/GraphControl/winrtHeaders.h b/src/GraphControl/winrtHeaders.h
index 971dfd361..3730cb593 100644
--- a/src/GraphControl/winrtHeaders.h
+++ b/src/GraphControl/winrtHeaders.h
@@ -3,6 +3,7 @@
#include
#include
#include
+#include
#include
template
diff --git a/src/GraphingImpl/Mocks/Graph.h b/src/GraphingImpl/Mocks/Graph.h
index ae10c35fd..8819e9402 100644
--- a/src/GraphingImpl/Mocks/Graph.h
+++ b/src/GraphingImpl/Mocks/Graph.h
@@ -29,6 +29,11 @@ namespace MockGraphingImpl
return std::nullopt;
}
+ HRESULT GetInitializationError()
+ {
+ return S_OK;
+ }
+
virtual Graphing::IGraphingOptions& GetOptions()
{
return m_graphingOptions;
diff --git a/src/GraphingImpl/Mocks/GraphingOptions.h b/src/GraphingImpl/Mocks/GraphingOptions.h
index 1234a403e..737894999 100644
--- a/src/GraphingImpl/Mocks/GraphingOptions.h
+++ b/src/GraphingImpl/Mocks/GraphingOptions.h
@@ -29,6 +29,7 @@ namespace MockGraphingImpl
, m_asymptotesColor()
, m_axisColor()
, m_boxColor()
+ , m_gridColor()
, m_fontColor()
, m_showAxis(true)
, m_showGrid(true)
@@ -251,6 +252,19 @@ namespace MockGraphingImpl
m_boxColor = Graphing::Color();
}
+ virtual Graphing::Color GetGridColor() const
+ {
+ return m_gridColor;
+ }
+ virtual void SetGridColor(const Graphing::Color& value)
+ {
+ m_gridColor = value;
+ }
+ virtual void ResetGridColor()
+ {
+ m_gridColor = Graphing::Color();
+ }
+
virtual Graphing::Color GetFontColor() const
{
return m_fontColor;
@@ -404,6 +418,7 @@ namespace MockGraphingImpl
Graphing::Color m_asymptotesColor;
Graphing::Color m_axisColor;
Graphing::Color m_boxColor;
+ Graphing::Color m_gridColor;
Graphing::Color m_fontColor;
bool m_showAxis;
bool m_showGrid;
diff --git a/src/GraphingImpl/Mocks/MathSolver.h b/src/GraphingImpl/Mocks/MathSolver.h
index 7f9a0fca6..e6c18df26 100644
--- a/src/GraphingImpl/Mocks/MathSolver.h
+++ b/src/GraphingImpl/Mocks/MathSolver.h
@@ -13,6 +13,10 @@ namespace MockGraphingImpl
void SetFormatType(Graphing::FormatType type) override
{
}
+
+ void SetLocalizationType(Graphing::LocalizationType value) override
+ {
+ }
};
class EvalOptions : public Graphing::IEvalOptions
@@ -46,6 +50,10 @@ namespace MockGraphingImpl
void SetMathMLPrefix(const std::wstring& value) override
{
}
+
+ void SetLocalizationType(Graphing::LocalizationType value) override
+ {
+ }
};
class MockExpression : public Graphing::IExpression
@@ -107,7 +115,7 @@ namespace MockGraphingImpl
return m_formatOptions;
}
- std::unique_ptr ParseInput(const std::wstring& input) override
+ std::unique_ptr ParseInput(const std::wstring& input, int& errorCodeOut, int& errorTypeOut) override
{
if (input.empty())
{
@@ -117,6 +125,10 @@ namespace MockGraphingImpl
return std::make_unique(MockExpression{});
}
+ void HRErrorToErrorInfo(HRESULT hr, int& errorCodeOut, int& errorTypeOut)
+ {
+ }
+
std::shared_ptr CreateGrapher(const Graphing::IExpression* expression) override;
std::shared_ptr CreateGrapher() override;
diff --git a/src/GraphingInterfaces/IGraph.h b/src/GraphingInterfaces/IGraph.h
index 9eca23624..81a04ce49 100644
--- a/src/GraphingInterfaces/IGraph.h
+++ b/src/GraphingInterfaces/IGraph.h
@@ -18,6 +18,8 @@ namespace Graphing
virtual std::optional>> TryInitialize(const IExpression* graphingExp = nullptr) = 0;
+ virtual HRESULT GetInitializationError() = 0;
+
virtual IGraphingOptions& GetOptions() = 0;
virtual std::vector> GetVariables() = 0;
diff --git a/src/GraphingInterfaces/IGraphingOptions.h b/src/GraphingInterfaces/IGraphingOptions.h
index 5d47ded54..d9a2b03d7 100644
--- a/src/GraphingInterfaces/IGraphingOptions.h
+++ b/src/GraphingInterfaces/IGraphingOptions.h
@@ -80,6 +80,10 @@ namespace Graphing
virtual void SetBoxColor(const Graphing::Color& value) = 0;
virtual void ResetBoxColor() = 0;
+ virtual Graphing::Color GetGridColor() const = 0;
+ virtual void SetGridColor(const Graphing::Color& value) = 0;
+ virtual void ResetGridColor() = 0;
+
virtual Graphing::Color GetFontColor() const = 0;
virtual void SetFontColor(const Graphing::Color& value) = 0;
virtual void ResetFontColor() = 0;
diff --git a/src/GraphingInterfaces/IMathSolver.h b/src/GraphingInterfaces/IMathSolver.h
index c1df98ac8..70f728d91 100644
--- a/src/GraphingInterfaces/IMathSolver.h
+++ b/src/GraphingInterfaces/IMathSolver.h
@@ -34,6 +34,7 @@ namespace Graphing
virtual ~IParsingOptions() = default;
virtual void SetFormatType(FormatType type) = 0;
+ virtual void SetLocalizationType(LocalizationType value) = 0;
};
struct IEvalOptions : public NonCopyable, public NonMoveable
@@ -49,7 +50,8 @@ namespace Graphing
virtual ~IFormatOptions() = default;
virtual void SetFormatType(FormatType type) = 0;
- virtual void SetMathMLPrefix(const std::wstring& value) = 0;
+ virtual void SetMathMLPrefix(const std::wstring& value) = 0;
+ virtual void SetLocalizationType(LocalizationType value) = 0;
};
struct IMathSolver : public NonCopyable, public NonMoveable
@@ -62,9 +64,11 @@ namespace Graphing
virtual IEvalOptions& EvalOptions() = 0;
virtual IFormatOptions& FormatOptions() = 0;
- virtual std::unique_ptr ParseInput(const std::wstring& input) = 0;
- virtual std::shared_ptr CreateGrapher(const IExpression* expression) = 0;
+ virtual std::unique_ptr ParseInput(const std::wstring& input, int& errorCodeOut, int& errorTypeOut) = 0;
+
+ virtual void HRErrorToErrorInfo(HRESULT hr, int& errorCodeOut, int& errorTypeOut) = 0;
+ virtual std::shared_ptr CreateGrapher(const IExpression* expression) = 0;
virtual std::shared_ptr CreateGrapher() = 0;
virtual std::wstring Serialize(const IExpression* expression) = 0;
diff --git a/src/Settings.XamlStyler b/src/Settings.XamlStyler
index 07bd12eb1..2c919209a 100644
--- a/src/Settings.XamlStyler
+++ b/src/Settings.XamlStyler
@@ -19,7 +19,8 @@
"*:*, *",
"PageSource, PageIndex, Offset, Color, TargetName, Property, Value, StartPoint, EndPoint",
"mc:Ignorable, d:IsDataSource, d:LayoutOverrides, d:IsStaticText",
- "IsEnabled, x:Load, Load"
+ "IsEnabled, x:Load, Load",
+ "Value, Maximum, Minimum"
],
"OrderAttributesByName": true,
"PutEndingBracketOnNewLine": false,
diff --git a/src/TraceLogging/TraceLogging.vcxproj b/src/TraceLogging/TraceLogging.vcxproj
new file mode 100644
index 000000000..ba0a960ea
--- /dev/null
+++ b/src/TraceLogging/TraceLogging.vcxproj
@@ -0,0 +1,294 @@
+
+
+
+
+ Debug
+ ARM
+
+
+ Debug
+ ARM64
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ ARM
+
+
+ Release
+ ARM64
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+
+ {fc81ff41-02cd-4cd9-9bc5-45a1e39ac6ed}
+ WindowsRuntimeComponent
+ TraceLogging
+ en-US
+ 14.0
+ true
+ Windows Store
+ 10.0.18362.0
+ 10.0.17134.0
+ 10.0
+
+
+
+ DynamicLibrary
+ true
+ v142
+
+
+ DynamicLibrary
+ true
+ v142
+
+
+ DynamicLibrary
+ true
+ v142
+
+
+ DynamicLibrary
+ true
+ v142
+
+
+ DynamicLibrary
+ false
+ true
+ v142
+
+
+ DynamicLibrary
+ false
+ true
+ v142
+
+
+ DynamicLibrary
+ false
+ true
+ v142
+
+
+ DynamicLibrary
+ false
+ true
+ v142
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ false
+
+
+ false
+
+
+ false
+
+
+ false
+
+
+ false
+
+
+ false
+
+
+ false
+
+
+ false
+
+
+
+ Use
+ _WINRT_DLL;%(PreprocessorDefinitions)
+ pch.h
+ $(IntDir)pch.pch
+ $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories)
+ /bigobj /await /std:c++17 /utf-8 %(AdditionalOptions)
+ 28204
+
+
+ Console
+ false
+
+
+
+
+ Use
+ _WINRT_DLL;NDEBUG;%(PreprocessorDefinitions)
+ pch.h
+ $(IntDir)pch.pch
+ $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories)
+ /bigobj %(AdditionalOptions)
+ 28204
+
+
+ Console
+ false
+
+
+
+
+ Use
+ _WINRT_DLL;%(PreprocessorDefinitions)
+ pch.h
+ $(IntDir)pch.pch
+ $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories)
+ /bigobj %(AdditionalOptions)
+ 28204
+
+
+ Console
+ false
+
+
+
+
+ Use
+ _WINRT_DLL;NDEBUG;%(PreprocessorDefinitions)
+ pch.h
+ $(IntDir)pch.pch
+ $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories)
+ /bigobj %(AdditionalOptions)
+ 28204
+
+
+ Console
+ false
+
+
+
+
+ Use
+ _WINRT_DLL;%(PreprocessorDefinitions)
+ pch.h
+ $(IntDir)pch.pch
+ $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories)
+ /bigobj %(AdditionalOptions)
+ 28204
+
+
+ Console
+ false
+
+
+
+
+ Use
+ _WINRT_DLL;NDEBUG;%(PreprocessorDefinitions)
+ pch.h
+ $(IntDir)pch.pch
+ $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories)
+ /bigobj %(AdditionalOptions)
+ 28204
+
+
+ Console
+ false
+
+
+
+
+ Use
+ _WINRT_DLL;%(PreprocessorDefinitions)
+ pch.h
+ $(IntDir)pch.pch
+ $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories)
+ /bigobj %(AdditionalOptions)
+ 28204
+
+
+ Console
+ false
+
+
+
+
+ Use
+ _WINRT_DLL;NDEBUG;%(PreprocessorDefinitions)
+ pch.h
+ $(IntDir)pch.pch
+ $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories)
+ /bigobj %(AdditionalOptions)
+ 28204
+
+
+ Console
+ false
+
+
+
+
+ /DSEND_DIAGNOSTICS %(AdditionalOptions)
+
+
+
+
+
+
+
+
+ Create
+ Create
+ Create
+ Create
+ Create
+ Create
+ Create
+ Create
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/TraceLogging/TraceLogging.vcxproj.filters b/src/TraceLogging/TraceLogging.vcxproj.filters
new file mode 100644
index 000000000..23e4274c1
--- /dev/null
+++ b/src/TraceLogging/TraceLogging.vcxproj.filters
@@ -0,0 +1,17 @@
+
+
+
+
+ 32f35fa0-613c-4f4e-b062-c61ab420e23b
+ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tga;tiff;tif;png;wav;mfcribbon-ms
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/TraceLogging/TraceLoggingCommon.cpp b/src/TraceLogging/TraceLoggingCommon.cpp
new file mode 100644
index 000000000..715bb8ce6
--- /dev/null
+++ b/src/TraceLogging/TraceLoggingCommon.cpp
@@ -0,0 +1,88 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+#include "pch.h"
+#include "TraceLoggingCommon.h"
+
+using namespace TraceLogging;
+using namespace std;
+using namespace Platform;;
+using namespace Windows::Foundation;
+using namespace Windows::Foundation::Diagnostics;
+
+#ifdef SEND_DIAGNOSTICS
+// c.f. WINEVENT_KEYWORD_RESERVED_63-56 0xFF00000000000000 // Bits 63-56 - channel keywords
+// c.f. WINEVENT_KEYWORD_* 0x00FF000000000000 // Bits 55-48 - system-reserved keywords
+constexpr int64_t MICROSOFT_KEYWORD_LEVEL_1 = 0x0000800000000000; // Bit 47
+constexpr int64_t MICROSOFT_KEYWORD_LEVEL_2 = 0x0000400000000000; // Bit 46
+constexpr int64_t MICROSOFT_KEYWORD_LEVEL_3 = 0x0000200000000000; // Bit 45
+#else
+// define all Keyword options as 0 when we do not want to upload app diagnostics
+constexpr int64_t MICROSOFT_KEYWORD_LEVEL_1 = 0;
+constexpr int64_t MICROSOFT_KEYWORD_LEVEL_2 = 0;
+constexpr int64_t MICROSOFT_KEYWORD_LEVEL_3 = 0;
+#endif
+
+constexpr auto SESSION_GUID = L"SessionGuid";
+constexpr auto PDT_PRIVACY_DATA_TAG = L"PartA_PrivTags";
+constexpr auto PDT_PRODUCT_AND_SERVICE_USAGE = 0x0000'0000'0200'0000u;
+
+TraceLoggingCommon::TraceLoggingCommon()
+ : g_calculatorProvider(
+ ref new LoggingChannel(
+ L"MicrosoftCalculator",
+ ref new LoggingChannelOptions(GUID{ 0x4f50731a, 0x89cf, 0x4782, 0xb3, 0xe0, 0xdc, 0xe8, 0xc9, 0x4, 0x76, 0xba }),
+ GUID{ 0x905ca09, 0x610e, 0x401e, 0xb6, 0x50, 0x2f, 0x21, 0x29, 0x80, 0xb9, 0xe0 }))
+ , // Unique providerID {0905CA09-610E-401E-B650-2F212980B9E0}
+ m_appLaunchActivity{ nullptr }
+{
+ CoCreateGuid(&sessionGuid);
+}
+
+ TraceLoggingCommon ^ TraceLoggingCommon::GetInstance()
+{
+ static TraceLoggingCommon ^ s_selfInstance = ref new TraceLoggingCommon();
+ return s_selfInstance;
+}
+
+bool TraceLoggingCommon::GetTraceLoggingProviderEnabled()
+{
+ return g_calculatorProvider->Enabled;
+}
+
+void TraceLoggingCommon::LogLevel1Event(String ^ eventName, LoggingFields ^ fields)
+{
+ if (!GetTraceLoggingProviderEnabled())
+ {
+ return;
+ }
+
+ fields->AddGuid(ref new String(SESSION_GUID), sessionGuid);
+ fields->AddUInt64(ref new String(PDT_PRIVACY_DATA_TAG), PDT_PRODUCT_AND_SERVICE_USAGE);
+
+ g_calculatorProvider->LogEvent(eventName, fields, LoggingLevel::Verbose, ref new LoggingOptions(MICROSOFT_KEYWORD_LEVEL_1));
+}
+
+void TraceLoggingCommon::LogLevel2Event(String ^ eventName, LoggingFields ^ fields)
+{
+ if (!GetTraceLoggingProviderEnabled())
+ {
+ return;
+ }
+
+ fields->AddGuid(ref new String(SESSION_GUID), sessionGuid);
+ fields->AddUInt64(ref new String(PDT_PRIVACY_DATA_TAG), PDT_PRODUCT_AND_SERVICE_USAGE);
+ g_calculatorProvider->LogEvent(eventName, fields, LoggingLevel::Verbose, ref new LoggingOptions(MICROSOFT_KEYWORD_LEVEL_2));
+}
+
+void TraceLoggingCommon::LogLevel3Event(String ^ eventName, LoggingFields ^ fields)
+{
+ if (!GetTraceLoggingProviderEnabled())
+ {
+ return;
+ }
+
+ fields->AddGuid(ref new String(SESSION_GUID), sessionGuid);
+ fields->AddUInt64(ref new String(PDT_PRIVACY_DATA_TAG), PDT_PRODUCT_AND_SERVICE_USAGE);
+ g_calculatorProvider->LogEvent(eventName, fields, LoggingLevel::Verbose, ref new LoggingOptions(MICROSOFT_KEYWORD_LEVEL_3));
+}
diff --git a/src/TraceLogging/TraceLoggingCommon.h b/src/TraceLogging/TraceLoggingCommon.h
new file mode 100644
index 000000000..c81253d57
--- /dev/null
+++ b/src/TraceLogging/TraceLoggingCommon.h
@@ -0,0 +1,31 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+#pragma once
+
+namespace TraceLogging
+{
+ public ref class TraceLoggingCommon sealed
+ {
+ public:
+ static TraceLoggingCommon ^ GetInstance();
+
+ // As mentioned in Microsoft's Privacy Statement(https://privacy.microsoft.com/en-US/privacystatement#maindiagnosticsmodule),
+ // sampling is involved in Microsoft's diagnostic data collection process.
+ // These keywords provide additional input into how frequently an event might be sampled.
+ // The lower the level of the keyword, the higher the possibility that the corresponding event may be sampled.
+ void LogLevel1Event(Platform::String ^ eventName, Windows::Foundation::Diagnostics::LoggingFields ^ fields);
+ void LogLevel2Event(Platform::String ^ eventName, Windows::Foundation::Diagnostics::LoggingFields ^ fields);
+ void LogLevel3Event(Platform::String ^ eventName, Windows::Foundation::Diagnostics::LoggingFields ^ fields);
+
+ bool GetTraceLoggingProviderEnabled();
+
+ private:
+ TraceLoggingCommon();
+
+
+ Windows::Foundation::Diagnostics::LoggingChannel ^ g_calculatorProvider;
+ Windows::Foundation::Diagnostics::LoggingActivity ^ m_appLaunchActivity;
+ GUID sessionGuid;
+ };
+}
diff --git a/src/TraceLogging/pch.cpp b/src/TraceLogging/pch.cpp
new file mode 100644
index 000000000..b175e3fd2
--- /dev/null
+++ b/src/TraceLogging/pch.cpp
@@ -0,0 +1,4 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+#include "pch.h"
diff --git a/src/TraceLogging/pch.h b/src/TraceLogging/pch.h
new file mode 100644
index 000000000..f1d2ac395
--- /dev/null
+++ b/src/TraceLogging/pch.h
@@ -0,0 +1,10 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+#pragma once
+
+#include
+#include
+
+// C++\WinRT Headers
+#include "Windows.Foundation.Diagnostics.h"