mirror of
https://github.com/Microsoft/calculator.git
synced 2025-08-22 22:23:29 -07:00
Merge branch 'master' into Fix420
This commit is contained in:
commit
63b8920032
316 changed files with 14739 additions and 12465 deletions
99
.clang-format
Normal file
99
.clang-format
Normal file
|
@ -0,0 +1,99 @@
|
|||
AccessModifierOffset: -4
|
||||
AlignAfterOpenBracket: AlwaysBreak
|
||||
AlignConsecutiveAssignments: false
|
||||
AlignConsecutiveDeclarations: false
|
||||
AlignEscapedNewlines: Right
|
||||
AlignOperands: true
|
||||
AlignTrailingComments: true
|
||||
AllowAllParametersOfDeclarationOnNextLine: false
|
||||
AllowShortBlocksOnASingleLine: false
|
||||
AllowShortCaseLabelsOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: None
|
||||
AllowShortIfStatementsOnASingleLine: false
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
AlwaysBreakAfterDefinitionReturnType: None
|
||||
AlwaysBreakAfterReturnType: None
|
||||
AlwaysBreakBeforeMultilineStrings: false
|
||||
AlwaysBreakTemplateDeclarations: true
|
||||
BinPackArguments: false
|
||||
BinPackParameters: false
|
||||
BreakBeforeBinaryOperators: NonAssignment
|
||||
BreakBeforeBraces: Allman
|
||||
BreakBeforeInheritanceComma: false
|
||||
BreakBeforeTernaryOperators: true
|
||||
BreakConstructorInitializersBeforeComma: false
|
||||
BreakConstructorInitializers: BeforeComma
|
||||
BreakAfterJavaFieldAnnotations: true
|
||||
BreakStringLiterals: true
|
||||
ColumnLimit: 160
|
||||
CommentPragmas: '^ IWYU pragma:'
|
||||
CompactNamespaces: true
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
||||
ConstructorInitializerIndentWidth: 4
|
||||
ContinuationIndentWidth: 4
|
||||
Cpp11BracedListStyle: false
|
||||
DerivePointerAlignment: false
|
||||
DisableFormat: false
|
||||
ExperimentalAutoDetectBinPacking: false
|
||||
FixNamespaceComments: false
|
||||
IncludeBlocks: Preserve
|
||||
IncludeCategories:
|
||||
- Regex: '^<ext/.*\.h>'
|
||||
Priority: 2
|
||||
- Regex: '^<.*\.h>'
|
||||
Priority: 1
|
||||
- Regex: '^<.*'
|
||||
Priority: 2
|
||||
- Regex: '.*'
|
||||
Priority: 3
|
||||
IncludeIsMainRegex: '([-_](test|unittest))?$'
|
||||
IndentCaseLabels: false
|
||||
IndentPPDirectives: None
|
||||
IndentWidth: 4
|
||||
IndentWrappedFunctionNames: false
|
||||
JavaScriptQuotes: Single
|
||||
JavaScriptWrapImports: true
|
||||
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||
MacroBlockBegin: ''
|
||||
MacroBlockEnd: ''
|
||||
MaxEmptyLinesToKeep: 1
|
||||
NamespaceIndentation: All
|
||||
ObjCBlockIndentWidth: 4
|
||||
ObjCSpaceAfterProperty: false
|
||||
ObjCSpaceBeforeProtocolList: true
|
||||
PenaltyBreakAssignment: 2
|
||||
PenaltyBreakBeforeFirstCallParameter: 19
|
||||
PenaltyBreakComment: 300
|
||||
PenaltyBreakFirstLessLess: 120
|
||||
PenaltyBreakString: 1000
|
||||
PenaltyExcessCharacter: 1000000
|
||||
PenaltyReturnTypeOnItsOwnLine: 60
|
||||
PointerAlignment: Left
|
||||
ReflowComments: true
|
||||
SortIncludes: false
|
||||
SortUsingDeclarations: true
|
||||
SpaceAfterCStyleCast: false
|
||||
SpaceAfterTemplateKeyword: true
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
SpaceBeforeParens: ControlStatements
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesBeforeTrailingComments: 1
|
||||
SpacesInAngles: false
|
||||
SpacesInContainerLiterals: false
|
||||
SpacesInCStyleCastParentheses: false
|
||||
SpacesInParentheses: false
|
||||
SpacesInSquareBrackets: false
|
||||
Standard: Cpp11
|
||||
TabWidth: 4
|
||||
UseTab: Never
|
||||
#...
|
||||
# unsupported rules
|
||||
#BreakInheritanceList: AfterColon
|
||||
#Language: None
|
||||
#ObjCBinPackProtocolList: Auto
|
||||
#PenaltyBreakTemplateDeclaration: 10
|
||||
#SpaceBeforeCpp11BracedList: false
|
||||
#SpaceBeforeCtorInitializerColon: true
|
||||
#SpaceBeforeInheritanceColon: true
|
||||
#SpaceBeforeRangeBasedForLoopColon: true
|
||||
|
23
.gitattributes
vendored
23
.gitattributes
vendored
|
@ -12,29 +12,6 @@
|
|||
###############################################################################
|
||||
*.cs diff=csharp
|
||||
|
||||
###############################################################################
|
||||
# Set the merge driver for project and solution files
|
||||
#
|
||||
# Merging from the command prompt will add diff markers to the files if there
|
||||
# are conflicts (Merging from VS is not affected by the settings below, in VS
|
||||
# the diff markers are never inserted). Diff markers may cause the following
|
||||
# file extensions to fail to load in VS. An alternative would be to treat
|
||||
# these files as binary and thus will always conflict and require user
|
||||
# intervention with every merge. To do so, just uncomment the entries below
|
||||
###############################################################################
|
||||
*.sln merge=binary
|
||||
*.csproj merge=binary
|
||||
*.vbproj merge=binary
|
||||
*.vcxproj merge=binary
|
||||
*.vcproj merge=binary
|
||||
*.dbproj merge=binary
|
||||
*.fsproj merge=binary
|
||||
*.lsproj merge=binary
|
||||
*.wixproj merge=binary
|
||||
*.modelproj merge=binary
|
||||
*.sqlproj merge=binary
|
||||
*.wwaproj merge=binary
|
||||
|
||||
###############################################################################
|
||||
# behavior for image files
|
||||
#
|
||||
|
|
91
Tools/Scripts/clang-format/clang-format-all.ps1
Normal file
91
Tools/Scripts/clang-format/clang-format-all.ps1
Normal file
|
@ -0,0 +1,91 @@
|
|||
<#
|
||||
.DESCRIPTION
|
||||
Helper script to format all header and source files in the repository.
|
||||
|
||||
By default, the script will recursively search under the repo root for
|
||||
files to format. Users can give explicit parameters indicating how the
|
||||
search should include and exclude filetypes.
|
||||
|
||||
If users don't want the search functionality, they can instead provide
|
||||
an explicit list of files to format.
|
||||
|
||||
.PARAMETER RepoRoot
|
||||
Full path to the root of the repository which is the target of the search.
|
||||
Will default to the root of the current working directory.
|
||||
|
||||
.PARAMETER Include
|
||||
Array of filetype extensions to target for formatting.
|
||||
By default, targets standard extensions for header and source files.
|
||||
Follows the same rules as the -Include parameter for Get-ChildItem.
|
||||
|
||||
.PARAMETER Exclude
|
||||
Array of filetype extensions to exclude from formatting.
|
||||
By default, excludes generated XAML files.
|
||||
Follows the same rules as the -Exclude paramter for Get-ChildItem.
|
||||
|
||||
.PARAMETER Files
|
||||
Array of files to format. The script will exit if one of the provided
|
||||
filepaths does not exist.
|
||||
|
||||
.EXAMPLE
|
||||
.\clang-format-all.ps1
|
||||
|
||||
Formats all header and source files under the repository root.
|
||||
|
||||
.EXAMPLE
|
||||
.\clang-format-all.ps1 -RepoRoot 'S:\repos\calculator' -Include '*.h', '*.cpp' -Exclude '*.g.*'
|
||||
|
||||
Formats all *.h and *.cpp files under 'S:\repos\calculator', excluding files with an extension
|
||||
like *.g.*
|
||||
|
||||
.EXAMPLE
|
||||
.\clang-format-all.ps1 -File 'S:\repos\calculator\src\CalcViewModel\UnitConverterViewModel.h', 'S:\repos\calculator\src\CalcViewModel\MemoryItemViewModel.cpp'
|
||||
|
||||
Formats the specified files.
|
||||
#>
|
||||
[CmdletBinding( DefaultParameterSetName = 'Search' )]
|
||||
param(
|
||||
[Parameter( ParameterSetName = 'Search' )]
|
||||
[ValidateScript({ Test-Path -PathType Container -Path $_ })]
|
||||
[string] $RepoRoot = "$( git rev-parse --show-toplevel )",
|
||||
|
||||
[Parameter( ParameterSetName = 'Search' )]
|
||||
[string[]] $Include = ( '*.h', '*.hh', '*.hpp', '*.c', '*.cc', '*.cpp' ),
|
||||
|
||||
[Parameter( ParameterSetName = 'Search' )]
|
||||
[string[]] $Exclude = '*.g.*',
|
||||
|
||||
[Parameter(
|
||||
ParameterSetName = 'Explicit',
|
||||
Mandatory)]
|
||||
[ValidateScript({
|
||||
$_ | Where-Object { -not (Test-Path -PathType Leaf -Path $_) } |
|
||||
ForEach-Object { throw "Could not find file: [$_]" }
|
||||
|
||||
return $true
|
||||
})]
|
||||
[string[]] $Files
|
||||
)
|
||||
|
||||
if ($PSCmdlet.ParameterSetName -eq 'Explicit')
|
||||
{
|
||||
# Use the file paths we were given.
|
||||
$targetFiles = @($Files)
|
||||
}
|
||||
else
|
||||
{
|
||||
# Gather the files to be formatted.
|
||||
$targetFiles = @(
|
||||
Get-ChildItem -Recurse -Path $RepoRoot -Include $Include -Exclude $Exclude |
|
||||
Select-Object -ExpandProperty FullName
|
||||
)
|
||||
}
|
||||
|
||||
# Format the files.
|
||||
$formatParams = @(
|
||||
'-i' # In-place
|
||||
'-style=file' # Search for a .clang-format file in the parent directory of the source file.
|
||||
'-verbose'
|
||||
)
|
||||
|
||||
clang-format $formatParams $targetFiles
|
53
Tools/Scripts/clang-format/clang-format-all.sh
Normal file
53
Tools/Scripts/clang-format/clang-format-all.sh
Normal file
|
@ -0,0 +1,53 @@
|
|||
#!/bin/bash
|
||||
|
||||
function usage {
|
||||
echo "Usage: $0 DIR..."
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Variable that will hold the name of the clang-format command
|
||||
FMT=""
|
||||
|
||||
# Some distros just call it clang-format. Others (e.g. Ubuntu) are insistent
|
||||
# that the version number be part of the command. We prefer clang-format if
|
||||
# that's present, otherwise we work backwards from highest version to lowest
|
||||
# version.
|
||||
for clangfmt in clang-format{,-{4,3}.{9,8,7,6,5,4,3,2,1,0}}; do
|
||||
if which "$clangfmt" &>/dev/null; then
|
||||
FMT="$clangfmt"
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
# Check if we found a working clang-format
|
||||
if [ -z "$FMT" ]; then
|
||||
echo "failed to find clang-format"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
SRC_PATH="$@"
|
||||
if [ -z "$SRC_PATH" ]; then
|
||||
SRC_PATH="../../../src"
|
||||
fi
|
||||
|
||||
# Check all of the arguments first to make sure they're all directories
|
||||
for dir in "$SRC_PATH"; do
|
||||
if [ ! -d "${dir}" ]; then
|
||||
echo "${dir} is not a directory"
|
||||
usage
|
||||
fi
|
||||
done
|
||||
|
||||
# Run clang-format -i on all of the things
|
||||
for dir in "$SRC_PATH"; do
|
||||
pushd "${dir}" &>/dev/null
|
||||
find . \
|
||||
\( -name '*.c' \
|
||||
-o -name '*.cc' \
|
||||
-o -name '*.cpp' \
|
||||
-o -name '*.h' \
|
||||
-o -name '*.hh' \
|
||||
-o -name '*.hpp' \) \
|
||||
-exec "${FMT}" -style=file -i '{}' \;
|
||||
popd &>/dev/null
|
||||
done
|
|
@ -1,5 +1,5 @@
|
|||
<SignConfigXML>
|
||||
<job platform="" configuration="" certSubject="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" jobname="EngFunSimpleSign" approvers="gstolt;vigarg">
|
||||
<job platform="" configuration="" certSubject="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" jobname="EngFunSimpleSign" approvers="">
|
||||
<file src="__INPATHROOT__\Microsoft.WindowsCalculator_8wekyb3d8bbwe.appxbundle" signType="136020001" dest="__OUTPATHROOT__\Microsoft.WindowsCalculator_8wekyb3d8bbwe.appxbundle" />
|
||||
</job>
|
||||
</SignConfigXML>
|
|
@ -33,6 +33,10 @@ jobs:
|
|||
platform: ARM64
|
||||
condition: not(eq(variables['Build.Reason'], 'PullRequest'))
|
||||
|
||||
- template: ./templates/run-ui-tests.yaml
|
||||
parameters:
|
||||
platform: x64
|
||||
|
||||
- template: ./templates/run-unit-tests.yaml
|
||||
parameters:
|
||||
platform: x64
|
||||
|
|
|
@ -9,8 +9,8 @@ pr: none
|
|||
|
||||
variables:
|
||||
versionMajor: 10
|
||||
versionMinor: 1904
|
||||
versionBuild: $[counter('10.1904.*', 0)]
|
||||
versionMinor: 1905
|
||||
versionBuild: $[counter('10.1905.*', 0)]
|
||||
versionPatch: 0
|
||||
|
||||
name: '$(versionMajor).$(versionMinor).$(versionBuild).$(versionPatch)'
|
||||
|
|
|
@ -30,7 +30,7 @@ steps:
|
|||
inputs:
|
||||
solution: src/Calculator.sln
|
||||
vsVersion: 15.0
|
||||
msbuildArgs: /bl:$(Build.BinariesDirectory)\$(BuildConfiguration)\$(BuildPlatform)\Calculator.binlog /p:OutDir=$(Build.BinariesDirectory)\$(BuildConfiguration)\$(BuildPlatform)\ /p:GenerateProjectSpecificOutputFolder=true /p:AppVersion=$(Build.BuildNumber) ${{ parameters.extraMsBuildArgs }}
|
||||
msbuildArgs: /bl:$(Build.BinariesDirectory)\$(BuildConfiguration)\$(BuildPlatform)\Calculator.binlog /p:OutDir=$(Build.BinariesDirectory)\$(BuildConfiguration)\$(BuildPlatform)\ /p:GenerateProjectSpecificOutputFolder=true /p:AppVersion=$(Build.BuildNumber) /t:Publish /p:PublishDir=$(Build.BinariesDirectory)\$(BuildConfiguration)\$(BuildPlatform)\publish\ ${{ parameters.extraMsBuildArgs }}
|
||||
platform: $(BuildPlatform)
|
||||
configuration: $(BuildConfiguration)
|
||||
clean: true
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# This template contains a job which builds artifacts needed to release the app to the store and to
|
||||
# Windows using Microsoft-internal systems. It relies Microsoft-internal resources and will not
|
||||
# Windows using Microsoft-internal systems. It relies on Microsoft-internal resources and will not
|
||||
# work outside of Microsoft.
|
||||
# Specifically, this job:
|
||||
# - Signs the bundle using a secure system. If you want to build your own, use SignTool following
|
||||
|
|
55
build/pipelines/templates/run-ui-tests.yaml
Normal file
55
build/pipelines/templates/run-ui-tests.yaml
Normal file
|
@ -0,0 +1,55 @@
|
|||
# This template contains jobs to run UI tests using WinAppDriver.
|
||||
|
||||
parameters:
|
||||
platform: ''
|
||||
|
||||
jobs:
|
||||
- job: UITests${{ parameters.platform }}
|
||||
displayName: UITests ${{ parameters.platform }}
|
||||
dependsOn: Build${{ parameters.platform }}
|
||||
condition: succeeded()
|
||||
pool:
|
||||
vmImage: windows-2019
|
||||
variables:
|
||||
skipComponentGovernanceDetection: true
|
||||
steps:
|
||||
- checkout: none
|
||||
|
||||
- task: DownloadBuildArtifacts@0
|
||||
displayName: Download AppxBundle and CalculatorUITests
|
||||
inputs:
|
||||
artifactName: drop
|
||||
itemPattern: |
|
||||
drop/Release/${{ parameters.platform }}/Calculator/AppPackages/**
|
||||
drop/Release/${{ parameters.platform }}/publish/**
|
||||
|
||||
- task: PowerShell@2
|
||||
displayName: Install certificate
|
||||
inputs:
|
||||
filePath: $(Build.ArtifactStagingDirectory)/drop/Release/${{ parameters.platform }}/Calculator/AppPackages/Calculator_$(Build.BuildNumber)_Test/Add-AppDevPackage.ps1
|
||||
arguments: -CertificatePath $(Build.ArtifactStagingDirectory)/drop/Release/${{ parameters.platform }}/Calculator/AppPackages/Calculator_$(Build.BuildNumber)_Test/Calculator_$(Build.BuildNumber)_${{ parameters.platform }}.cer -Force
|
||||
|
||||
- task: PowerShell@2
|
||||
displayName: Install app
|
||||
inputs:
|
||||
filePath: $(Build.ArtifactStagingDirectory)/drop/Release/${{ parameters.platform }}/Calculator/AppPackages/Calculator_$(Build.BuildNumber)_Test/Add-AppDevPackage.ps1
|
||||
arguments: -Force
|
||||
|
||||
- task: WinAppDriver.winappdriver-pipelines-task.winappdriver-pipelines-task.Windows Application Driver@0
|
||||
displayName: 'WinAppDriver - Start'
|
||||
inputs:
|
||||
AgentResolution: 1080p
|
||||
|
||||
- task: VSTest@2
|
||||
displayName: Run CalculatorUITests
|
||||
inputs:
|
||||
testAssemblyVer2: $(Build.ArtifactStagingDirectory)/drop/Release/${{ parameters.platform }}/publish/CalculatorUITests.dll
|
||||
vsTestVersion: 16.0
|
||||
runSettingsFile: $(Build.ArtifactStagingDirectory)/drop/Release/${{ parameters.platform }}/publish/CalculatorUITests.runsettings
|
||||
platform: ${{ parameters.platform }}
|
||||
configuration: Release
|
||||
|
||||
- task: WinAppDriver.winappdriver-pipelines-task.winappdriver-pipelines-task.Windows Application Driver@0
|
||||
displayName: 'WinAppDriver - Stop'
|
||||
inputs:
|
||||
OperationType: Stop
|
|
@ -201,4 +201,5 @@ instead of regular floating point arithmetic). The interface to this layer is de
|
|||
[CalcManager folder]: ../src/CalcManager
|
||||
[CalculatorManager.h]: ../src/CalcManager/CalculatorManager.h
|
||||
[CalcEngine.h]: ../src/CalcManager/Header Files/CalcEngine.h
|
||||
[Infinite Precision]: https://en.wikipedia.org/wiki/Arbitrary-precision_arithmetic
|
||||
[ratpak.h]: ../src/CalcManager/Ratpack/ratpak.h
|
||||
|
|
|
@ -123,7 +123,7 @@
|
|||
<AppxPackageTestDir>@(AppxBundleOutput->'%(RootDir)%(Directory)')</AppxPackageTestDir>
|
||||
<UniversalTestCustomMacros Condition="'$(Configuration)'=='Debug'">$(UniversalTestCustomMacros)AppxPackageVCLibsDependency=$(AppxPackageTestDir)Dependencies\$(PlatformTarget)\Microsoft.VCLibs.$(PlatformTarget).Debug.14.00.appx;</UniversalTestCustomMacros>
|
||||
<UniversalTestCustomMacros Condition="'$(Configuration)'=='Release'">$(UniversalTestCustomMacros)AppxPackageVCLibsDependency=$(AppxPackageTestDir)Dependencies\$(PlatformTarget)\Microsoft.VCLibs.$(PlatformTarget).14.00.appx;</UniversalTestCustomMacros>
|
||||
<UniversalTestCustomMacros>$(UniversalTestCustomMacros)AppxPackageWinUIDependency=$(AppxPackageTestDir)Dependencies\$(PlatformTarget)\Microsoft.UI.Xaml.2.0.appx;</UniversalTestCustomMacros>
|
||||
<UniversalTestCustomMacros>$(UniversalTestCustomMacros)AppxPackageWinUIDependency=$(AppxPackageTestDir)Dependencies\$(PlatformTarget)\Microsoft.UI.Xaml.2.1.appx;</UniversalTestCustomMacros>
|
||||
<UniversalTestCustomMacros>$(UniversalTestCustomMacros)AppxPackagePublicKeyFile=@(AppxPackagePublicKeyFile->'%(FullPath)');AppxBundleOutput=@(AppxBundleOutput->'%(FullPath)');</UniversalTestCustomMacros>
|
||||
</PropertyGroup>
|
||||
</Target>
|
||||
|
|
|
@ -33,9 +33,7 @@ bool IsDigitOpCode(OpCode opCode)
|
|||
// was never inout, we need to revert the state changes made as a result of this test
|
||||
bool IsGuiSettingOpCode(OpCode opCode)
|
||||
{
|
||||
if (IsOpInRange(opCode, IDM_HEX, IDM_BIN) ||
|
||||
IsOpInRange(opCode, IDM_QWORD, IDM_BYTE) ||
|
||||
IsOpInRange(opCode, IDM_DEG, IDM_GRAD))
|
||||
if (IsOpInRange(opCode, IDM_HEX, IDM_BIN) || IsOpInRange(opCode, IDM_QWORD, IDM_BYTE) || IsOpInRange(opCode, IDM_DEG, IDM_GRAD))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -11,7 +11,8 @@ constexpr int ASCII_0 = 48;
|
|||
using namespace std;
|
||||
using namespace CalcEngine;
|
||||
|
||||
namespace {
|
||||
namespace
|
||||
{
|
||||
void IFT(ResultCode hr)
|
||||
{
|
||||
if (FAILED(hr))
|
||||
|
@ -38,11 +39,11 @@ void CHistoryCollector::ReinitHistory()
|
|||
|
||||
// Constructor
|
||||
// Can throw Out of memory error
|
||||
CHistoryCollector::CHistoryCollector(ICalcDisplay *pCalcDisplay, std::shared_ptr<IHistoryDisplay> pHistoryDisplay, wchar_t decimalSymbol) :
|
||||
m_pHistoryDisplay(pHistoryDisplay),
|
||||
m_pCalcDisplay(pCalcDisplay),
|
||||
m_iCurLineHistStart(-1),
|
||||
m_decimalSymbol(decimalSymbol)
|
||||
CHistoryCollector::CHistoryCollector(ICalcDisplay* pCalcDisplay, std::shared_ptr<IHistoryDisplay> pHistoryDisplay, wchar_t decimalSymbol)
|
||||
: m_pHistoryDisplay(pHistoryDisplay)
|
||||
, m_pCalcDisplay(pCalcDisplay)
|
||||
, m_iCurLineHistStart(-1)
|
||||
, m_decimalSymbol(decimalSymbol)
|
||||
{
|
||||
ReinitHistory();
|
||||
}
|
||||
|
@ -302,7 +303,8 @@ void CHistoryCollector::CompleteHistoryLine(wstring_view numStr)
|
|||
{
|
||||
if (nullptr != m_pCalcDisplay)
|
||||
{
|
||||
m_pCalcDisplay->SetExpressionDisplay(std::make_shared<CalculatorVector<std::pair<std::wstring, int>>>(), std::make_shared<CalculatorVector<std::shared_ptr<IExpressionCommand>>>());
|
||||
m_pCalcDisplay->SetExpressionDisplay(
|
||||
std::make_shared<CalculatorVector<std::pair<std::wstring, int>>>(), std::make_shared<CalculatorVector<std::shared_ptr<IExpressionCommand>>>());
|
||||
}
|
||||
|
||||
if (nullptr != m_pHistoryDisplay)
|
||||
|
@ -323,14 +325,14 @@ void CHistoryCollector::ClearHistoryLine(wstring_view errStr)
|
|||
{
|
||||
if (nullptr != m_pCalcDisplay)
|
||||
{
|
||||
m_pCalcDisplay->SetExpressionDisplay(std::make_shared<CalculatorVector<std::pair<std::wstring, int>>>(), std::make_shared<CalculatorVector<std::shared_ptr<IExpressionCommand>>>());
|
||||
m_pCalcDisplay->SetExpressionDisplay(
|
||||
std::make_shared<CalculatorVector<std::pair<std::wstring, int>>>(), std::make_shared<CalculatorVector<std::shared_ptr<IExpressionCommand>>>());
|
||||
}
|
||||
m_iCurLineHistStart = -1; // It will get recomputed at the first Opnd
|
||||
ReinitHistory();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Adds the given string psz to the globally maintained current equation string at the end.
|
||||
// Also returns the 0 based index in the string just added. Can throw out of memory error
|
||||
int CHistoryCollector::IchAddSzToEquationSz(wstring_view str, int icommandIndex)
|
||||
|
@ -392,7 +394,6 @@ void CHistoryCollector::SetExpressionDisplay()
|
|||
{
|
||||
m_pCalcDisplay->SetExpressionDisplay(m_spTokens, m_spCommands);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int CHistoryCollector::AddCommand(_In_ const std::shared_ptr<IExpressionCommand>& spCommand)
|
||||
|
|
|
@ -7,20 +7,22 @@ using namespace std;
|
|||
|
||||
namespace CalcEngine
|
||||
{
|
||||
Number::Number() noexcept :
|
||||
Number(1, 0, { 0 })
|
||||
{}
|
||||
Number::Number() noexcept
|
||||
: Number(1, 0, { 0 })
|
||||
{
|
||||
}
|
||||
|
||||
Number::Number(int32_t sign, int32_t exp, vector<uint32_t> const& mantissa) noexcept :
|
||||
m_sign{ sign },
|
||||
m_exp{ exp },
|
||||
m_mantissa{ mantissa }
|
||||
{}
|
||||
Number::Number(int32_t sign, int32_t exp, vector<uint32_t> const& mantissa) noexcept
|
||||
: m_sign{ sign }
|
||||
, m_exp{ exp }
|
||||
, m_mantissa{ mantissa }
|
||||
{
|
||||
}
|
||||
|
||||
Number::Number(PNUMBER p) noexcept :
|
||||
m_sign{ p->sign },
|
||||
m_exp{ p->exp },
|
||||
m_mantissa{}
|
||||
Number::Number(PNUMBER p) noexcept
|
||||
: m_sign{ p->sign }
|
||||
, m_exp{ p->exp }
|
||||
, m_mantissa{}
|
||||
{
|
||||
m_mantissa.reserve(p->cdigit);
|
||||
copy(p->mant, p->mant + p->cdigit, back_inserter(m_mantissa));
|
||||
|
|
|
@ -7,10 +7,11 @@ using namespace std;
|
|||
|
||||
namespace CalcEngine
|
||||
{
|
||||
Rational::Rational() noexcept :
|
||||
m_p{},
|
||||
m_q{ 1, 0, { 1 } }
|
||||
{}
|
||||
Rational::Rational() noexcept
|
||||
: m_p{}
|
||||
, m_q{ 1, 0, { 1 } }
|
||||
{
|
||||
}
|
||||
|
||||
Rational::Rational(Number const& n) noexcept
|
||||
{
|
||||
|
@ -24,10 +25,11 @@ namespace CalcEngine
|
|||
m_q = Number(1, qExp, { 1 });
|
||||
}
|
||||
|
||||
Rational::Rational(Number const& p, Number const& q) noexcept :
|
||||
m_p{ p },
|
||||
m_q{ q }
|
||||
{}
|
||||
Rational::Rational(Number const& p, Number const& q) noexcept
|
||||
: m_p{ p }
|
||||
, m_q{ q }
|
||||
{
|
||||
}
|
||||
|
||||
Rational::Rational(int32_t i)
|
||||
{
|
||||
|
@ -60,10 +62,11 @@ namespace CalcEngine
|
|||
m_q = Number{ temp.Q() };
|
||||
}
|
||||
|
||||
Rational::Rational(PRAT prat) noexcept :
|
||||
m_p{ Number{prat->pp} },
|
||||
m_q{ Number{prat->pq} }
|
||||
{}
|
||||
Rational::Rational(PRAT prat) noexcept
|
||||
: m_p{ Number{ prat->pp } }
|
||||
, m_q{ Number{ prat->pq } }
|
||||
{
|
||||
}
|
||||
|
||||
PRAT Rational::ToPRAT() const
|
||||
{
|
||||
|
@ -353,7 +356,8 @@ namespace CalcEngine
|
|||
/// Calculate the remainder after division, the sign of a result will match the sign of lhs.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This function has the same behavior as the standard C/C++ operator '%', to calculate the modulus after division instead, use <see cref="Rational::operator%"/> instead.
|
||||
/// This function has the same behavior as the standard C/C++ operator '%', to calculate the modulus after division instead, use <see
|
||||
/// cref="Rational::operator%"/> instead.
|
||||
/// </remarks>
|
||||
Rational operator%(Rational lhs, Rational const& rhs)
|
||||
{
|
||||
|
|
|
@ -58,42 +58,47 @@ void CCalcEngine::InitialOneTimeOnlySetup(CalculationManager::IResourceProvider&
|
|||
// CCalcEngine::CCalcEngine
|
||||
//
|
||||
//////////////////////////////////////////////////
|
||||
CCalcEngine::CCalcEngine(bool fPrecedence, bool fIntegerMode, CalculationManager::IResourceProvider* const pResourceProvider, __in_opt ICalcDisplay *pCalcDisplay, __in_opt shared_ptr<IHistoryDisplay> pHistoryDisplay) :
|
||||
m_fPrecedence(fPrecedence),
|
||||
m_fIntegerMode(fIntegerMode),
|
||||
m_pCalcDisplay(pCalcDisplay),
|
||||
m_resourceProvider(pResourceProvider),
|
||||
m_nOpCode(0),
|
||||
m_nPrevOpCode(0),
|
||||
m_bChangeOp(false),
|
||||
m_bRecord(false),
|
||||
m_bSetCalcState(false),
|
||||
m_input(DEFAULT_DEC_SEPARATOR),
|
||||
m_nFE(FMT_FLOAT),
|
||||
m_memoryValue{ make_unique<Rational>() },
|
||||
m_holdVal{},
|
||||
m_currentVal{},
|
||||
m_lastVal{},
|
||||
m_parenVals{},
|
||||
m_precedenceVals{},
|
||||
m_bError(false),
|
||||
m_bInv(false),
|
||||
m_bNoPrevEqu(true),
|
||||
m_radix(DEFAULT_RADIX),
|
||||
m_precision(DEFAULT_PRECISION),
|
||||
m_cIntDigitsSav(DEFAULT_MAX_DIGITS),
|
||||
m_decGrouping(),
|
||||
m_numberString(DEFAULT_NUMBER_STR),
|
||||
m_nTempCom(0),
|
||||
m_openParenCount(0),
|
||||
m_nOp(),
|
||||
m_nPrecOp(),
|
||||
m_precedenceOpCount(0),
|
||||
m_nLastCom(0),
|
||||
m_angletype(ANGLE_DEG),
|
||||
m_numwidth(QWORD_WIDTH),
|
||||
m_HistoryCollector(pCalcDisplay, pHistoryDisplay, DEFAULT_DEC_SEPARATOR),
|
||||
m_groupSeparator(DEFAULT_GRP_SEPARATOR)
|
||||
CCalcEngine::CCalcEngine(
|
||||
bool fPrecedence,
|
||||
bool fIntegerMode,
|
||||
CalculationManager::IResourceProvider* const pResourceProvider,
|
||||
__in_opt ICalcDisplay* pCalcDisplay,
|
||||
__in_opt shared_ptr<IHistoryDisplay> pHistoryDisplay)
|
||||
: m_fPrecedence(fPrecedence)
|
||||
, m_fIntegerMode(fIntegerMode)
|
||||
, m_pCalcDisplay(pCalcDisplay)
|
||||
, m_resourceProvider(pResourceProvider)
|
||||
, m_nOpCode(0)
|
||||
, m_nPrevOpCode(0)
|
||||
, m_bChangeOp(false)
|
||||
, m_bRecord(false)
|
||||
, m_bSetCalcState(false)
|
||||
, m_input(DEFAULT_DEC_SEPARATOR)
|
||||
, m_nFE(FMT_FLOAT)
|
||||
, m_memoryValue{ make_unique<Rational>() }
|
||||
, m_holdVal{}
|
||||
, m_currentVal{}
|
||||
, m_lastVal{}
|
||||
, m_parenVals{}
|
||||
, m_precedenceVals{}
|
||||
, m_bError(false)
|
||||
, m_bInv(false)
|
||||
, m_bNoPrevEqu(true)
|
||||
, m_radix(DEFAULT_RADIX)
|
||||
, m_precision(DEFAULT_PRECISION)
|
||||
, m_cIntDigitsSav(DEFAULT_MAX_DIGITS)
|
||||
, m_decGrouping()
|
||||
, m_numberString(DEFAULT_NUMBER_STR)
|
||||
, m_nTempCom(0)
|
||||
, m_openParenCount(0)
|
||||
, m_nOp()
|
||||
, m_nPrecOp()
|
||||
, m_precedenceOpCount(0)
|
||||
, m_nLastCom(0)
|
||||
, m_angletype(ANGLE_DEG)
|
||||
, m_numwidth(QWORD_WIDTH)
|
||||
, m_HistoryCollector(pCalcDisplay, pHistoryDisplay, DEFAULT_DEC_SEPARATOR)
|
||||
, m_groupSeparator(DEFAULT_GRP_SEPARATOR)
|
||||
{
|
||||
InitChopNumbers();
|
||||
|
||||
|
|
|
@ -20,16 +20,16 @@
|
|||
using namespace std;
|
||||
using namespace CalcEngine;
|
||||
|
||||
namespace {
|
||||
namespace
|
||||
{
|
||||
// NPrecedenceOfOp
|
||||
//
|
||||
// returns a virtual number for precedence for the operator. We expect binary operator only, otherwise the lowest number
|
||||
// 0 is returned. Higher the number, higher the precedence of the operator.
|
||||
int NPrecedenceOfOp(int nopCode)
|
||||
{
|
||||
static uint8_t rgbPrec[] = { 0,0, IDC_OR,0, IDC_XOR,0, IDC_AND,1,
|
||||
IDC_ADD,2, IDC_SUB,2, IDC_RSHF,3, IDC_LSHF,3,
|
||||
IDC_MOD,3, IDC_DIV,3, IDC_MUL,3, IDC_PWR,4, IDC_ROOT, 4 };
|
||||
static uint8_t rgbPrec[] = { 0, 0, IDC_OR, 0, IDC_XOR, 0, IDC_AND, 1, IDC_ADD, 2, IDC_SUB, 2, IDC_RSHF,
|
||||
3, IDC_LSHF, 3, IDC_MOD, 3, IDC_DIV, 3, IDC_MUL, 3, IDC_PWR, 4, IDC_ROOT, 4 };
|
||||
unsigned int iPrec;
|
||||
|
||||
iPrec = 0;
|
||||
|
@ -42,7 +42,6 @@ namespace {
|
|||
iPrec = 0;
|
||||
}
|
||||
return rgbPrec[iPrec + 1];
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -125,14 +124,9 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam)
|
|||
// Toggle Record/Display mode if appropriate.
|
||||
if (m_bRecord)
|
||||
{
|
||||
if (IsOpInRange(wParam, IDC_AND, IDC_MMINUS) ||
|
||||
IsOpInRange(wParam, IDC_OPENP, IDC_CLOSEP) ||
|
||||
IsOpInRange(wParam, IDM_HEX, IDM_BIN) ||
|
||||
IsOpInRange(wParam, IDM_QWORD, IDM_BYTE) ||
|
||||
IsOpInRange(wParam, IDM_DEG, IDM_GRAD) ||
|
||||
IsOpInRange(wParam, IDC_BINEDITSTART, IDC_BINEDITSTART + 63) ||
|
||||
(IDC_INV == wParam) ||
|
||||
(IDC_SIGN == wParam && 10 != m_radix))
|
||||
if (IsOpInRange(wParam, IDC_AND, IDC_MMINUS) || IsOpInRange(wParam, IDC_OPENP, IDC_CLOSEP) || IsOpInRange(wParam, IDM_HEX, IDM_BIN)
|
||||
|| IsOpInRange(wParam, IDM_QWORD, IDM_BYTE) || IsOpInRange(wParam, IDM_DEG, IDM_GRAD)
|
||||
|| IsOpInRange(wParam, IDC_BINEDITSTART, IDC_BINEDITSTART + 63) || (IDC_INV == wParam) || (IDC_SIGN == wParam && 10 != m_radix))
|
||||
{
|
||||
m_bRecord = false;
|
||||
m_currentVal = m_input.ToRational(m_radix, m_precision);
|
||||
|
@ -272,7 +266,6 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam)
|
|||
m_HistoryCollector.PopLastOpndStart();
|
||||
goto DoPrecedenceCheckAgain;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -337,11 +330,9 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam)
|
|||
/* reset the m_bInv flag and indicators if it is set
|
||||
and have been used */
|
||||
|
||||
if (m_bInv &&
|
||||
((wParam == IDC_CHOP) ||
|
||||
(wParam == IDC_SIN) || (wParam == IDC_COS) || (wParam == IDC_TAN) ||
|
||||
(wParam == IDC_LN) || (wParam == IDC_DMS) || (wParam == IDC_DEGREES) ||
|
||||
(wParam == IDC_SINH) || (wParam == IDC_COSH) || (wParam == IDC_TANH)))
|
||||
if (m_bInv
|
||||
&& ((wParam == IDC_CHOP) || (wParam == IDC_SIN) || (wParam == IDC_COS) || (wParam == IDC_TAN) || (wParam == IDC_LN) || (wParam == IDC_DMS)
|
||||
|| (wParam == IDC_DEGREES) || (wParam == IDC_SINH) || (wParam == IDC_COSH) || (wParam == IDC_TANH)))
|
||||
{
|
||||
m_bInv = false;
|
||||
}
|
||||
|
@ -386,13 +377,13 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam)
|
|||
m_nPrevOpCode = 0;
|
||||
m_bNoPrevEqu = true;
|
||||
|
||||
|
||||
/* clear the parenthesis status box indicator, this will not be
|
||||
cleared for CENTR */
|
||||
if (nullptr != m_pCalcDisplay)
|
||||
{
|
||||
m_pCalcDisplay->SetParenthesisNumber(0);
|
||||
m_pCalcDisplay->SetExpressionDisplay(make_shared<CalculatorVector<pair<wstring, int>>>(), make_shared<CalculatorVector<shared_ptr<IExpressionCommand>>>());
|
||||
m_pCalcDisplay->SetExpressionDisplay(
|
||||
make_shared<CalculatorVector<pair<wstring, int>>>(), make_shared<CalculatorVector<shared_ptr<IExpressionCommand>>>());
|
||||
}
|
||||
|
||||
m_HistoryCollector.ClearHistoryLine(wstring());
|
||||
|
@ -485,7 +476,8 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam)
|
|||
m_HistoryCollector.CompleteHistoryLine(groupedString);
|
||||
if (nullptr != m_pCalcDisplay)
|
||||
{
|
||||
m_pCalcDisplay->SetExpressionDisplay(make_shared<CalculatorVector<pair<wstring, int>>>(), make_shared<CalculatorVector<shared_ptr<IExpressionCommand>>>());
|
||||
m_pCalcDisplay->SetExpressionDisplay(
|
||||
make_shared<CalculatorVector<pair<wstring, int>>>(), make_shared<CalculatorVector<shared_ptr<IExpressionCommand>>>());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -749,7 +741,6 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam)
|
|||
m_bInv = !m_bInv;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Helper function to resolve one item on the precedence stack.
|
||||
|
@ -814,7 +805,6 @@ void CCalcEngine::CheckAndAddLastBinOpToHistory(bool addToHistory)
|
|||
// So erase the last operand
|
||||
m_HistoryCollector.RemoveLastOpndFromHistory();
|
||||
}
|
||||
|
||||
}
|
||||
else if (m_HistoryCollector.FOpndAddedToHistory() && !m_bError)
|
||||
{
|
||||
|
@ -823,8 +813,7 @@ void CCalcEngine::CheckAndAddLastBinOpToHistory(bool addToHistory)
|
|||
// Let us make a current value =. So in case of 4 SQRT (or a equation under braces) and then a new equation is started, we can just form
|
||||
// a useful equation of sqrt(4) = 2 and continue a new equation from now on. But no point in doing this for things like
|
||||
// MR, SUM etc. All you will get is 5 = 5 kind of no useful equation.
|
||||
if ((IsUnaryOpCode(m_nLastCom) || IDC_SIGN == m_nLastCom || IDC_CLOSEP == m_nLastCom) &&
|
||||
0 == m_openParenCount)
|
||||
if ((IsUnaryOpCode(m_nLastCom) || IDC_SIGN == m_nLastCom || IDC_CLOSEP == m_nLastCom) && 0 == m_openParenCount)
|
||||
{
|
||||
if (addToHistory)
|
||||
{
|
||||
|
@ -877,8 +866,7 @@ struct FunctionNameElement
|
|||
};
|
||||
|
||||
// Table for each unary operator
|
||||
static const std::unordered_map<int, FunctionNameElement> unaryOperatorStringTable =
|
||||
{
|
||||
static const std::unordered_map<int, FunctionNameElement> unaryOperatorStringTable = {
|
||||
{ IDC_CHOP, { L"", SIDS_FRAC } },
|
||||
|
||||
{ IDC_SIN, { SIDS_SIND, SIDS_ASIND, SIDS_SINR, SIDS_ASINR, SIDS_SING, SIDS_ASING } },
|
||||
|
|
|
@ -25,7 +25,6 @@ constexpr uint32_t MAX_GROUPING_SIZE = 16;
|
|||
constexpr wstring_view c_decPreSepStr = L"[+-]?(\\d*)[";
|
||||
constexpr wstring_view c_decPostSepStr = L"]?(\\d*)(?:e[+-]?(\\d*))?$";
|
||||
|
||||
|
||||
/****************************************************************************\
|
||||
* void DisplayNum(void)
|
||||
*
|
||||
|
@ -37,7 +36,8 @@ constexpr wstring_view c_decPostSepStr = L"]?(\\d*)(?:e[+-]?(\\d*))?$";
|
|||
//
|
||||
// State of calc last time DisplayNum was called
|
||||
//
|
||||
typedef struct {
|
||||
typedef struct
|
||||
{
|
||||
Rational value;
|
||||
int32_t precision;
|
||||
uint32_t radix;
|
||||
|
@ -84,15 +84,8 @@ void CCalcEngine::DisplayNum(void)
|
|||
// something important has changed since the last time DisplayNum was
|
||||
// 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)
|
||||
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.precision = m_precision;
|
||||
gldPrevious.radix = m_radix;
|
||||
|
|
|
@ -226,4 +226,3 @@ void CCalcEngine::DisplayError(uint32_t nError)
|
|||
|
||||
m_HistoryCollector.ClearHistoryLine(errorString);
|
||||
}
|
||||
|
||||
|
|
|
@ -7,11 +7,15 @@
|
|||
using namespace std;
|
||||
using namespace CalculationManager;
|
||||
|
||||
CalculatorHistory::CalculatorHistory(size_t maxSize) :
|
||||
m_maxHistorySize(maxSize)
|
||||
{}
|
||||
CalculatorHistory::CalculatorHistory(size_t maxSize)
|
||||
: m_maxHistorySize(maxSize)
|
||||
{
|
||||
}
|
||||
|
||||
unsigned int CalculatorHistory::AddToHistory(_In_ shared_ptr<CalculatorVector <pair<wstring, int>>> const &tokens, _In_ shared_ptr<CalculatorVector<shared_ptr<IExpressionCommand>>> const &commands, _In_ wstring_view result)
|
||||
unsigned int CalculatorHistory::AddToHistory(
|
||||
_In_ shared_ptr<CalculatorVector<pair<wstring, int>>> const& tokens,
|
||||
_In_ shared_ptr<CalculatorVector<shared_ptr<IExpressionCommand>>> const& commands,
|
||||
_In_ wstring_view result)
|
||||
{
|
||||
unsigned int addedIndex;
|
||||
wstring generatedExpression;
|
||||
|
@ -31,7 +35,6 @@ unsigned int CalculatorHistory::AddToHistory(_In_ shared_ptr<CalculatorVector <p
|
|||
return addedIndex;
|
||||
}
|
||||
|
||||
|
||||
unsigned int CalculatorHistory::AddItem(_In_ shared_ptr<HISTORYITEM> const& spHistoryItem)
|
||||
{
|
||||
if (m_historyItems.size() >= m_maxHistorySize)
|
||||
|
|
|
@ -26,19 +26,23 @@ namespace CalculationManager
|
|||
HISTORYITEMVECTOR historyItemVector;
|
||||
};
|
||||
|
||||
class CalculatorHistory :
|
||||
public IHistoryDisplay
|
||||
class CalculatorHistory : public IHistoryDisplay
|
||||
{
|
||||
|
||||
public:
|
||||
CalculatorHistory(const size_t maxSize);
|
||||
unsigned int AddToHistory(_In_ std::shared_ptr<CalculatorVector <std::pair<std::wstring, int>>> const &spTokens, _In_ std::shared_ptr<CalculatorVector<std::shared_ptr<IExpressionCommand>>> const &spCommands, std::wstring_view result);
|
||||
unsigned int AddToHistory(
|
||||
_In_ std::shared_ptr<CalculatorVector<std::pair<std::wstring, int>>> const& spTokens,
|
||||
_In_ std::shared_ptr<CalculatorVector<std::shared_ptr<IExpressionCommand>>> const& spCommands,
|
||||
std::wstring_view result);
|
||||
std::vector<std::shared_ptr<HISTORYITEM>> const& GetHistory();
|
||||
std::shared_ptr<HISTORYITEM> const& GetHistoryItem(unsigned int uIdx);
|
||||
void ClearHistory();
|
||||
unsigned int AddItem(_In_ std::shared_ptr<HISTORYITEM> const& spHistoryItem);
|
||||
bool RemoveItem(unsigned int uIdx);
|
||||
size_t MaxHistorySize() const { return m_maxHistorySize; }
|
||||
size_t MaxHistorySize() const
|
||||
{
|
||||
return m_maxHistorySize;
|
||||
}
|
||||
~CalculatorHistory(void);
|
||||
|
||||
private:
|
||||
|
|
|
@ -14,25 +14,21 @@ static constexpr size_t SERIALIZED_NUMBER_MINSIZE = 3;
|
|||
|
||||
// Converts Memory Command enum value to unsigned char,
|
||||
// while ignoring Warning C4309: 'conversion' : truncation of constant value
|
||||
#define MEMORY_COMMAND_TO_UNSIGNED_CHAR(c)\
|
||||
__pragma(warning(push))\
|
||||
__pragma(warning(disable: 4309))\
|
||||
static_cast<unsigned char>(c)\
|
||||
__pragma(warning(pop))
|
||||
#define MEMORY_COMMAND_TO_UNSIGNED_CHAR(c) __pragma(warning(push)) __pragma(warning(disable : 4309)) static_cast<unsigned char>(c) __pragma(warning(pop))
|
||||
|
||||
namespace CalculationManager
|
||||
{
|
||||
CalculatorManager::CalculatorManager(_In_ ICalcDisplay* displayCallback, _In_ IResourceProvider* resourceProvider) :
|
||||
m_displayCallback(displayCallback),
|
||||
m_currentCalculatorEngine(nullptr),
|
||||
m_resourceProvider(resourceProvider),
|
||||
m_inHistoryItemLoadMode(false),
|
||||
m_persistedPrimaryValue(),
|
||||
m_isExponentialFormat(false),
|
||||
m_currentDegreeMode(Command::CommandNULL),
|
||||
m_savedDegreeMode(Command::CommandDEG),
|
||||
m_pStdHistory(new CalculatorHistory(MAX_HISTORY_ITEMS)),
|
||||
m_pSciHistory(new CalculatorHistory(MAX_HISTORY_ITEMS))
|
||||
CalculatorManager::CalculatorManager(_In_ ICalcDisplay* displayCallback, _In_ IResourceProvider* resourceProvider)
|
||||
: m_displayCallback(displayCallback)
|
||||
, m_currentCalculatorEngine(nullptr)
|
||||
, m_resourceProvider(resourceProvider)
|
||||
, m_inHistoryItemLoadMode(false)
|
||||
, m_persistedPrimaryValue()
|
||||
, m_isExponentialFormat(false)
|
||||
, m_currentDegreeMode(Command::CommandNULL)
|
||||
, m_savedDegreeMode(Command::CommandDEG)
|
||||
, m_pStdHistory(new CalculatorHistory(MAX_HISTORY_ITEMS))
|
||||
, m_pSciHistory(new CalculatorHistory(MAX_HISTORY_ITEMS))
|
||||
{
|
||||
CCalcEngine::InitialOneTimeOnlySetup(*m_resourceProvider);
|
||||
}
|
||||
|
@ -89,7 +85,9 @@ namespace CalculationManager
|
|||
/// Used to set the expression display value on ViewModel
|
||||
/// </summary>
|
||||
/// <param name="expressionString">wstring representing expression to be displayed</param>
|
||||
void CalculatorManager::SetExpressionDisplay(_Inout_ shared_ptr<CalculatorVector<pair<wstring, int>>> const &tokens, _Inout_ shared_ptr<CalculatorVector<shared_ptr<IExpressionCommand>>> const &commands)
|
||||
void CalculatorManager::SetExpressionDisplay(
|
||||
_Inout_ shared_ptr<CalculatorVector<pair<wstring, int>>> const& tokens,
|
||||
_Inout_ shared_ptr<CalculatorVector<shared_ptr<IExpressionCommand>>> const& commands)
|
||||
{
|
||||
if (!m_inHistoryItemLoadMode)
|
||||
{
|
||||
|
@ -165,7 +163,8 @@ namespace CalculationManager
|
|||
{
|
||||
if (!m_standardCalculatorEngine)
|
||||
{
|
||||
m_standardCalculatorEngine = make_unique<CCalcEngine>(false /* Respect Order of Operations */, false /* Set to Integer Mode */, m_resourceProvider, this, m_pStdHistory);
|
||||
m_standardCalculatorEngine =
|
||||
make_unique<CCalcEngine>(false /* Respect Order of Operations */, false /* Set to Integer Mode */, m_resourceProvider, this, m_pStdHistory);
|
||||
}
|
||||
|
||||
m_currentCalculatorEngine = m_standardCalculatorEngine.get();
|
||||
|
@ -183,7 +182,8 @@ namespace CalculationManager
|
|||
{
|
||||
if (!m_scientificCalculatorEngine)
|
||||
{
|
||||
m_scientificCalculatorEngine = make_unique<CCalcEngine>(true /* Respect Order of Operations */, false /* Set to Integer Mode */, m_resourceProvider, this, m_pSciHistory);
|
||||
m_scientificCalculatorEngine =
|
||||
make_unique<CCalcEngine>(true /* Respect Order of Operations */, false /* Set to Integer Mode */, m_resourceProvider, this, m_pSciHistory);
|
||||
}
|
||||
|
||||
m_currentCalculatorEngine = m_scientificCalculatorEngine.get();
|
||||
|
@ -200,7 +200,8 @@ namespace CalculationManager
|
|||
{
|
||||
if (!m_programmerCalculatorEngine)
|
||||
{
|
||||
m_programmerCalculatorEngine = make_unique<CCalcEngine>(true /* Respect Order of Operations */, true /* Set to Integer Mode */, m_resourceProvider, this, nullptr);
|
||||
m_programmerCalculatorEngine =
|
||||
make_unique<CCalcEngine>(true /* Respect Order of Operations */, true /* Set to Integer Mode */, m_resourceProvider, this, nullptr);
|
||||
}
|
||||
|
||||
m_currentCalculatorEngine = m_programmerCalculatorEngine.get();
|
||||
|
@ -209,7 +210,6 @@ namespace CalculationManager
|
|||
m_currentCalculatorEngine->ChangePrecision(static_cast<int>(CalculatorPrecision::ProgrammerModePrecision));
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Send command to the Calc Engine
|
||||
/// Cast Command Enum to OpCode.
|
||||
|
@ -220,8 +220,8 @@ namespace CalculationManager
|
|||
{
|
||||
// When the expression line is cleared, we save the current state, which includes,
|
||||
// primary display, memory, and degree mode
|
||||
if (command == Command::CommandCLEAR || command == Command::CommandEQU
|
||||
|| command == Command::ModeBasic || command == Command::ModeScientific || command == Command::ModeProgrammer)
|
||||
if (command == Command::CommandCLEAR || command == Command::CommandEQU || command == Command::ModeBasic || command == Command::ModeScientific
|
||||
|| command == Command::ModeProgrammer)
|
||||
{
|
||||
switch (command)
|
||||
{
|
||||
|
@ -244,8 +244,6 @@ namespace CalculationManager
|
|||
{
|
||||
m_savedCommands.push_back(MapCommandForSerialize(command));
|
||||
}
|
||||
this->SerializePrimaryDisplay();
|
||||
this->SerializeMemory();
|
||||
m_savedDegreeMode = m_currentDegreeMode;
|
||||
return;
|
||||
}
|
||||
|
@ -330,47 +328,6 @@ namespace CalculationManager
|
|||
return commandToLoad;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return saved degree mode which is saved when last time the expression was cleared.
|
||||
/// </summary>
|
||||
Command CalculatorManager::SerializeSavedDegreeMode()
|
||||
{
|
||||
return m_savedDegreeMode;
|
||||
}
|
||||
|
||||
void CalculatorManager::SerializePrimaryDisplay()
|
||||
{
|
||||
m_savedPrimaryValue.clear();
|
||||
m_currentCalculatorEngine->ProcessCommand(IDC_STORE);
|
||||
auto memoryObject = m_currentCalculatorEngine->PersistedMemObject();
|
||||
if (memoryObject != nullptr)
|
||||
{
|
||||
m_savedPrimaryValue = SerializeRational(*memoryObject);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return serialized primary display that is saved when the expression line was cleared.
|
||||
/// </summary>
|
||||
vector<long> CalculatorManager::GetSerializedPrimaryDisplay()
|
||||
{
|
||||
return m_savedPrimaryValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// DeSerialize the primary display from vector of long
|
||||
/// </summary>
|
||||
/// <param name = "serializedPrimaryDisplay">Serialized Rational of primary display</param>
|
||||
void CalculatorManager::DeSerializePrimaryDisplay(const vector<long> &serializedPrimaryDisplay)
|
||||
{
|
||||
if (serializedPrimaryDisplay.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
m_persistedPrimaryValue = DeSerializeRational(serializedPrimaryDisplay.begin());
|
||||
this->LoadPersistedPrimaryValue();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Load the persisted value that is saved in memory of CalcEngine
|
||||
/// </summary>
|
||||
|
@ -380,112 +337,6 @@ namespace CalculationManager
|
|||
m_currentCalculatorEngine->ProcessCommand(IDC_RECALL);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Serialize the Memory to vector of long
|
||||
/// </summary>
|
||||
/// <return type = "std::vector<long>">Serialized Rational of memory</return>
|
||||
void CalculatorManager::SerializeMemory()
|
||||
{
|
||||
m_serializedMemory.clear();
|
||||
|
||||
for (auto const& memoryItem : m_memorizedNumbers)
|
||||
{
|
||||
auto serialMem = SerializeRational(memoryItem);
|
||||
m_serializedMemory.insert(m_serializedMemory.end(), serialMem.begin(), serialMem.end());
|
||||
}
|
||||
}
|
||||
|
||||
vector<long> CalculatorManager::GetSerializedMemory()
|
||||
{
|
||||
return m_serializedMemory;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// DeSerialize the Memory from vector of long
|
||||
/// </summary>
|
||||
/// <param name = "serializedMemory">Serialized Rational of memory</param>
|
||||
void CalculatorManager::DeSerializeMemory(const vector<long> &serializedMemory)
|
||||
{
|
||||
vector<long>::const_iterator itr = serializedMemory.begin();
|
||||
while (itr != serializedMemory.end())
|
||||
{
|
||||
Rational memoryItem = DeSerializeRational(itr);
|
||||
auto lengthMemoryItem = (2 * SERIALIZED_NUMBER_MINSIZE) + memoryItem.P().Mantissa().size() + memoryItem.Q().Mantissa().size();
|
||||
m_memorizedNumbers.push_back(memoryItem);
|
||||
itr += lengthMemoryItem;
|
||||
}
|
||||
this->SetMemorizedNumbersString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return the commands saved since the expression has been cleared.
|
||||
/// </summary>
|
||||
vector<unsigned char> CalculatorManager::SerializeCommands()
|
||||
{
|
||||
return m_savedCommands;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Replay the serialized commands
|
||||
/// </summary>
|
||||
/// <param name = "serializedData">Serialized commands</param>
|
||||
void CalculatorManager::DeSerializeCommands(_In_ const vector<unsigned char>& serializedData)
|
||||
{
|
||||
m_savedCommands.clear();
|
||||
|
||||
for (auto commandItr = serializedData.begin(); commandItr != serializedData.end(); ++commandItr)
|
||||
{
|
||||
if (*commandItr >= MEMORY_COMMAND_TO_UNSIGNED_CHAR(MemoryCommand::MemorizeNumber) &&
|
||||
*commandItr <= MEMORY_COMMAND_TO_UNSIGNED_CHAR(MemoryCommand::MemorizedNumberClearAll))
|
||||
{
|
||||
// MemoryCommands(which have values above 255) are pushed on m_savedCommands upon casting to unsigned char.
|
||||
// SerializeCommands uses m_savedCommands, which is then used in DeSerializeCommands.
|
||||
// Hence, a simple cast to MemoryCommand is not sufficient.
|
||||
MemoryCommand memoryCommand = static_cast<MemoryCommand>(*commandItr + UCHAR_MAX + 1);
|
||||
unsigned int indexOfMemory = 0;
|
||||
switch (memoryCommand)
|
||||
{
|
||||
case MemoryCommand::MemorizeNumber:
|
||||
this->MemorizeNumber();
|
||||
break;
|
||||
case MemoryCommand::MemorizedNumberLoad:
|
||||
if (commandItr + 1 == serializedData.end())
|
||||
{
|
||||
throw out_of_range("Expecting index of memory, data ended prematurely");
|
||||
}
|
||||
indexOfMemory = *(++commandItr);
|
||||
this->MemorizedNumberLoad(indexOfMemory);
|
||||
break;
|
||||
case MemoryCommand::MemorizedNumberAdd:
|
||||
if (commandItr + 1 == serializedData.end())
|
||||
{
|
||||
throw out_of_range("Expecting index of memory, data ended prematurely");
|
||||
}
|
||||
indexOfMemory = *(++commandItr);
|
||||
this->MemorizedNumberAdd(indexOfMemory);
|
||||
break;
|
||||
case MemoryCommand::MemorizedNumberSubtract:
|
||||
if (commandItr + 1 == serializedData.end())
|
||||
{
|
||||
throw out_of_range("Expecting index of memory, data ended prematurely");
|
||||
}
|
||||
indexOfMemory = *(++commandItr);
|
||||
this->MemorizedNumberSubtract(indexOfMemory);
|
||||
break;
|
||||
case MemoryCommand::MemorizedNumberClearAll:
|
||||
this->MemorizedNumberClearAll();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this->SendCommand(static_cast<Command>(MapCommandForDeSerialize(*commandItr)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Memorize the current displayed value
|
||||
/// Notify the client with new the new memorize value vector
|
||||
|
@ -673,9 +524,7 @@ namespace CalculationManager
|
|||
|
||||
vector<shared_ptr<HISTORYITEM>> const& CalculatorManager::GetHistoryItems(_In_ CALCULATOR_MODE mode)
|
||||
{
|
||||
return (mode == CM_STD) ?
|
||||
m_pStdHistory->GetHistory() :
|
||||
m_pSciHistory->GetHistory();
|
||||
return (mode == CM_STD) ? m_pStdHistory->GetHistory() : m_pSciHistory->GetHistory();
|
||||
}
|
||||
|
||||
shared_ptr<HISTORYITEM> const& CalculatorManager::GetHistoryItem(_In_ unsigned int uIdx)
|
||||
|
|
|
@ -63,7 +63,6 @@ namespace CalculationManager
|
|||
// For persistence
|
||||
std::vector<unsigned char> m_savedCommands;
|
||||
std::vector<long> m_savedPrimaryValue;
|
||||
std::vector<long> m_serializedMemory;
|
||||
std::vector<long> m_currentSerializedMemory;
|
||||
Command m_currentDegreeMode;
|
||||
Command m_savedDegreeMode;
|
||||
|
@ -91,7 +90,9 @@ namespace CalculationManager
|
|||
// ICalcDisplay
|
||||
void SetPrimaryDisplay(_In_ const std::wstring& displayString, _In_ bool isError) override;
|
||||
void SetIsInError(bool isError) override;
|
||||
void SetExpressionDisplay(_Inout_ std::shared_ptr<CalculatorVector<std::pair<std::wstring, int>>> const &tokens, _Inout_ std::shared_ptr<CalculatorVector<std::shared_ptr<IExpressionCommand>>> const &commands) override;
|
||||
void SetExpressionDisplay(
|
||||
_Inout_ std::shared_ptr<CalculatorVector<std::pair<std::wstring, int>>> const& tokens,
|
||||
_Inout_ std::shared_ptr<CalculatorVector<std::shared_ptr<IExpressionCommand>>> const& commands) override;
|
||||
void SetMemorizedNumbers(_In_ const std::vector<std::wstring>& memorizedNumbers) override;
|
||||
void OnHistoryItemAdded(_In_ unsigned int addedItemIndex) override;
|
||||
void SetParenthesisNumber(_In_ unsigned int parenthesisCount) override;
|
||||
|
@ -101,7 +102,6 @@ namespace CalculationManager
|
|||
void BinaryOperatorReceived() override;
|
||||
void MemoryItemChanged(unsigned int indexOfMemory) override;
|
||||
|
||||
|
||||
CalculatorManager(ICalcDisplay* displayCallback, IResourceProvider* resourceProvider);
|
||||
~CalculatorManager();
|
||||
|
||||
|
@ -110,15 +110,6 @@ namespace CalculationManager
|
|||
void SetScientificMode();
|
||||
void SetProgrammerMode();
|
||||
void SendCommand(_In_ Command command);
|
||||
std::vector<unsigned char> SerializeCommands();
|
||||
void DeSerializeCommands(_In_ const std::vector<unsigned char>& serializedData);
|
||||
void SerializeMemory();
|
||||
std::vector<long> GetSerializedMemory();
|
||||
void DeSerializeMemory(const std::vector<long> &serializedMemory);
|
||||
void SerializePrimaryDisplay();
|
||||
std::vector<long> GetSerializedPrimaryDisplay();
|
||||
void DeSerializePrimaryDisplay(const std::vector<long> &serializedPrimaryDisplay);
|
||||
Command SerializeSavedDegreeMode();
|
||||
|
||||
void MemorizeNumber();
|
||||
void MemorizedNumberLoad(_In_ unsigned int);
|
||||
|
@ -128,7 +119,10 @@ namespace CalculationManager
|
|||
void MemorizedNumberClearAll();
|
||||
|
||||
bool IsEngineRecording();
|
||||
std::vector<unsigned char> GetSavedCommands(){ return m_savedCommands; }
|
||||
std::vector<unsigned char> GetSavedCommands()
|
||||
{
|
||||
return m_savedCommands;
|
||||
}
|
||||
void SetRadix(RADIX_TYPE iRadixType);
|
||||
void SetMemorizedNumbersString();
|
||||
std::wstring GetResultForRadix(uint32_t radix, int32_t precision);
|
||||
|
@ -141,7 +135,10 @@ namespace CalculationManager
|
|||
std::shared_ptr<HISTORYITEM> const& GetHistoryItem(_In_ unsigned int uIdx);
|
||||
bool RemoveHistoryItem(_In_ unsigned int uIdx);
|
||||
void ClearHistory();
|
||||
size_t MaxHistorySize() const { return m_pHistory->MaxHistorySize(); }
|
||||
size_t MaxHistorySize() const
|
||||
{
|
||||
return m_pHistory->MaxHistorySize();
|
||||
}
|
||||
CalculationManager::Command GetCurrentDegreeMode();
|
||||
void SetHistory(_In_ CALCULATOR_MODE eMode, _In_ std::vector<std::shared_ptr<HISTORYITEM>> const& history);
|
||||
void SetInHistoryItemLoadMode(_In_ bool isHistoryItemLoadMode);
|
||||
|
|
|
@ -8,7 +8,9 @@ namespace CalculationManager
|
|||
class IResourceProvider
|
||||
{
|
||||
public:
|
||||
virtual ~IResourceProvider() { }
|
||||
virtual ~IResourceProvider()
|
||||
{
|
||||
}
|
||||
|
||||
// Should return a string from the resource table for strings used
|
||||
// by the calculation engine. The strings that must be defined
|
||||
|
|
|
@ -7,9 +7,19 @@ namespace UnitConversionManager
|
|||
{
|
||||
enum class Command
|
||||
{
|
||||
Zero, One, Two, Three, Four, Five, Six, Seven, Eight, Nine,
|
||||
Zero,
|
||||
One,
|
||||
Two,
|
||||
Three,
|
||||
Four,
|
||||
Five,
|
||||
Six,
|
||||
Seven,
|
||||
Eight,
|
||||
Nine,
|
||||
Decimal,
|
||||
Negate, Backspace,
|
||||
Negate,
|
||||
Backspace,
|
||||
Clear,
|
||||
Reset,
|
||||
None
|
||||
|
@ -20,9 +30,19 @@ namespace CurrencyConversionManager
|
|||
{
|
||||
enum class Command
|
||||
{
|
||||
Zero, One, Two, Three, Four, Five, Six, Seven, Eight, Nine,
|
||||
Zero,
|
||||
One,
|
||||
Two,
|
||||
Three,
|
||||
Four,
|
||||
Five,
|
||||
Six,
|
||||
Seven,
|
||||
Eight,
|
||||
Nine,
|
||||
Decimal,
|
||||
Negate, Backspace,
|
||||
Negate,
|
||||
Backspace,
|
||||
Clear,
|
||||
None
|
||||
};
|
||||
|
@ -85,7 +105,6 @@ namespace CalculationManager
|
|||
CommandCOSH = 106,
|
||||
CommandTANH = 107,
|
||||
|
||||
|
||||
CommandLN = 108,
|
||||
CommandLOG = 109,
|
||||
CommandSQRT = 110,
|
||||
|
|
|
@ -13,8 +13,10 @@ constexpr wchar_t chNegate = L'-';
|
|||
constexpr wchar_t chExp = L'e';
|
||||
constexpr wchar_t chPlus = L'+';
|
||||
|
||||
CParentheses::CParentheses(_In_ int command) :m_command(command)
|
||||
{}
|
||||
CParentheses::CParentheses(_In_ int command)
|
||||
: m_command(command)
|
||||
{
|
||||
}
|
||||
|
||||
int CParentheses::GetCommand() const
|
||||
{
|
||||
|
@ -72,8 +74,10 @@ void CUnaryCommand::Accept(_In_ ISerializeCommandVisitor &commandVisitor)
|
|||
commandVisitor.Visit(*this);
|
||||
}
|
||||
|
||||
CBinaryCommand::CBinaryCommand(int command) :m_command(command)
|
||||
{}
|
||||
CBinaryCommand::CBinaryCommand(int command)
|
||||
: m_command(command)
|
||||
{
|
||||
}
|
||||
|
||||
void CBinaryCommand::SetCommand(int command)
|
||||
{
|
||||
|
@ -95,14 +99,15 @@ void CBinaryCommand::Accept(_In_ ISerializeCommandVisitor &commandVisitor)
|
|||
commandVisitor.Visit(*this);
|
||||
}
|
||||
|
||||
COpndCommand::COpndCommand(shared_ptr<CalculatorVector<int>> const &commands, bool fNegative, bool fDecimal, bool fSciFmt) :
|
||||
m_commands(commands),
|
||||
m_fNegative(fNegative),
|
||||
m_fSciFmt(fSciFmt),
|
||||
m_fDecimal(fDecimal),
|
||||
m_fInitialized(false),
|
||||
m_value{}
|
||||
{}
|
||||
COpndCommand::COpndCommand(shared_ptr<CalculatorVector<int>> const& commands, bool fNegative, bool fDecimal, bool fSciFmt)
|
||||
: m_commands(commands)
|
||||
, m_fNegative(fNegative)
|
||||
, m_fSciFmt(fSciFmt)
|
||||
, m_fDecimal(fDecimal)
|
||||
, m_fInitialized(false)
|
||||
, m_value{}
|
||||
{
|
||||
}
|
||||
|
||||
void COpndCommand::Initialize(Rational const& rat)
|
||||
{
|
||||
|
|
|
@ -49,11 +49,7 @@ private:
|
|||
class COpndCommand final : public IOpndCommand
|
||||
{
|
||||
public:
|
||||
COpndCommand(
|
||||
std::shared_ptr<CalculatorVector<int>> const &commands,
|
||||
bool fNegative,
|
||||
bool fDecimal,
|
||||
bool fSciFmt);
|
||||
COpndCommand(std::shared_ptr<CalculatorVector<int>> const& commands, bool fNegative, bool fDecimal, bool fSciFmt);
|
||||
void Initialize(CalcEngine::Rational const& rat);
|
||||
|
||||
const std::shared_ptr<CalculatorVector<int>>& GetCommands() const override;
|
||||
|
|
|
@ -45,7 +45,6 @@
|
|||
#define IDC_WORD IDM_WORD
|
||||
#define IDC_BYTE IDM_BYTE
|
||||
|
||||
|
||||
// Key IDs:
|
||||
// These id's must be consecutive from IDC_FIRSTCONTROL to IDC_LASTCONTROL.
|
||||
// The actual values don't matter but the order and sequence are very important.
|
||||
|
@ -77,7 +76,6 @@
|
|||
#define IDC_ROOT 96
|
||||
#define IDC_PWR 97
|
||||
|
||||
|
||||
#define IDC_UNARYFIRST IDC_CHOP
|
||||
#define IDC_CHOP 98 // Unary operators must be between IDC_CHOP and IDC_EQU
|
||||
#define IDC_ROL 99
|
||||
|
@ -116,7 +114,6 @@
|
|||
|
||||
#define IDC_EXP 127
|
||||
|
||||
|
||||
#define IDC_OPENP 128
|
||||
#define IDC_CLOSEP 129
|
||||
|
||||
|
@ -208,9 +205,7 @@
|
|||
#define IDC_BINPOS63 763
|
||||
#define IDC_BINEDITEND 763
|
||||
|
||||
|
||||
// The strings in the following range IDS_ENGINESTR_FIRST ... IDS_ENGINESTR_MAX are strings allocated in the
|
||||
// resource for the purpose internal to Engine and cant be used by the clients
|
||||
#define IDS_ENGINESTR_FIRST 0
|
||||
#define IDS_ENGINESTR_MAX 200
|
||||
|
||||
|
|
|
@ -31,7 +31,8 @@
|
|||
// The real exports follows later
|
||||
|
||||
// This is expected to be in same order as IDM_QWORD, IDM_DWORD etc.
|
||||
enum eNUM_WIDTH {
|
||||
enum eNUM_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
|
||||
|
@ -50,31 +51,57 @@ namespace CalculatorEngineTests
|
|||
class CalcEngineTests;
|
||||
}
|
||||
|
||||
class CCalcEngine {
|
||||
class CCalcEngine
|
||||
{
|
||||
public:
|
||||
CCalcEngine(bool fPrecedence, bool fIntegerMode, CalculationManager::IResourceProvider* const pResourceProvider, __in_opt ICalcDisplay *pCalcDisplay, __in_opt std::shared_ptr<IHistoryDisplay> pHistoryDisplay);
|
||||
CCalcEngine(
|
||||
bool fPrecedence,
|
||||
bool fIntegerMode,
|
||||
CalculationManager::IResourceProvider* const pResourceProvider,
|
||||
__in_opt ICalcDisplay* pCalcDisplay,
|
||||
__in_opt std::shared_ptr<IHistoryDisplay> pHistoryDisplay);
|
||||
void ProcessCommand(OpCode wID);
|
||||
void DisplayError(uint32_t nError);
|
||||
std::unique_ptr<CalcEngine::Rational> PersistedMemObject();
|
||||
void PersistedMemObject(CalcEngine::Rational const& memObject);
|
||||
bool FInErrorState() { return m_bError; }
|
||||
bool FInRecordingState() { return m_bRecord; }
|
||||
bool FInErrorState()
|
||||
{
|
||||
return m_bError;
|
||||
}
|
||||
bool FInRecordingState()
|
||||
{
|
||||
return m_bRecord;
|
||||
}
|
||||
void SettingsChanged();
|
||||
bool IsCurrentTooBigForTrig();
|
||||
int GetCurrentRadix();
|
||||
std::wstring GetCurrentResultForRadix(uint32_t radix, int32_t precision);
|
||||
void ChangePrecision(int32_t precision) { m_precision = precision; ChangeConstants(m_radix, precision); }
|
||||
void ChangePrecision(int32_t precision)
|
||||
{
|
||||
m_precision = precision;
|
||||
ChangeConstants(m_radix, precision);
|
||||
}
|
||||
std::wstring GroupDigitsPerRadix(std::wstring_view numberString, uint32_t radix);
|
||||
std::wstring GetStringForDisplay(CalcEngine::Rational const& rat, uint32_t radix);
|
||||
void UpdateMaxIntDigits();
|
||||
wchar_t DecimalSeparator() const;
|
||||
|
||||
// Static methods for the instance
|
||||
static void InitialOneTimeOnlySetup(CalculationManager::IResourceProvider& resourceProvider); // Once per load time to call to initialize all shared global variables
|
||||
static void
|
||||
InitialOneTimeOnlySetup(CalculationManager::IResourceProvider& resourceProvider); // Once per load time to call to initialize all shared global variables
|
||||
// returns the ptr to string representing the operator. Mostly same as the button, but few special cases for x^y etc.
|
||||
static std::wstring_view GetString(int ids) { return s_engineStrings[std::to_wstring(ids)]; }
|
||||
static std::wstring_view GetString(std::wstring ids) { return s_engineStrings[ids]; }
|
||||
static std::wstring_view OpCodeToString(int nOpCode) { return GetString(IdStrFromCmdId(nOpCode)); }
|
||||
static std::wstring_view GetString(int ids)
|
||||
{
|
||||
return s_engineStrings[std::to_wstring(ids)];
|
||||
}
|
||||
static std::wstring_view GetString(std::wstring ids)
|
||||
{
|
||||
return s_engineStrings[ids];
|
||||
}
|
||||
static std::wstring_view OpCodeToString(int nOpCode)
|
||||
{
|
||||
return GetString(IdStrFromCmdId(nOpCode));
|
||||
}
|
||||
static std::wstring_view OpCodeToUnaryString(int nOpCode, bool fInv, ANGLE_TYPE angletype);
|
||||
|
||||
private:
|
||||
|
@ -151,7 +178,10 @@ private:
|
|||
void InitChopNumbers();
|
||||
|
||||
static void LoadEngineStrings(CalculationManager::IResourceProvider& resourceProvider);
|
||||
static int IdStrFromCmdId(int id) { return id - IDC_FIRSTCONTROL + IDS_ENGINESTR_FIRST; }
|
||||
static int IdStrFromCmdId(int id)
|
||||
{
|
||||
return id - IDC_FIRSTCONTROL + IDS_ENGINESTR_FIRST;
|
||||
}
|
||||
|
||||
static std::vector<uint32_t> DigitGroupingStringToGroupingVector(std::wstring_view groupingString);
|
||||
std::wstring GroupDigits(std::wstring_view delimiter, std::vector<uint32_t> const& grouping, std::wstring_view displayString, bool isNumNegative = false);
|
||||
|
|
|
@ -13,16 +13,26 @@ namespace CalcEngine
|
|||
class CalcNumSec
|
||||
{
|
||||
public:
|
||||
CalcNumSec() :
|
||||
value(),
|
||||
m_isNegative(false)
|
||||
{}
|
||||
CalcNumSec()
|
||||
: value()
|
||||
, m_isNegative(false)
|
||||
{
|
||||
}
|
||||
|
||||
void Clear();
|
||||
bool IsEmpty() { return value.empty(); }
|
||||
bool IsEmpty()
|
||||
{
|
||||
return value.empty();
|
||||
}
|
||||
|
||||
bool IsNegative() { return m_isNegative; }
|
||||
void IsNegative(bool isNegative) { m_isNegative = isNegative; }
|
||||
bool IsNegative()
|
||||
{
|
||||
return m_isNegative;
|
||||
}
|
||||
void IsNegative(bool isNegative)
|
||||
{
|
||||
m_isNegative = isNegative;
|
||||
}
|
||||
|
||||
std::wstring value;
|
||||
|
||||
|
@ -33,17 +43,20 @@ namespace CalcEngine
|
|||
class CalcInput
|
||||
{
|
||||
public:
|
||||
CalcInput() : CalcInput(L'.')
|
||||
{}
|
||||
CalcInput()
|
||||
: CalcInput(L'.')
|
||||
{
|
||||
}
|
||||
|
||||
CalcInput(wchar_t decSymbol) :
|
||||
m_hasExponent(false),
|
||||
m_hasDecimal(false),
|
||||
m_decPtIndex(0),
|
||||
m_decSymbol(decSymbol),
|
||||
m_base(),
|
||||
m_exponent()
|
||||
{}
|
||||
CalcInput(wchar_t decSymbol)
|
||||
: m_hasExponent(false)
|
||||
, m_hasDecimal(false)
|
||||
, m_decPtIndex(0)
|
||||
, m_decSymbol(decSymbol)
|
||||
, m_base()
|
||||
, m_exponent()
|
||||
{
|
||||
}
|
||||
|
||||
void Clear();
|
||||
bool TryToggleSign(bool isIntegerMode, std::wstring_view maxNumStr);
|
||||
|
|
|
@ -171,9 +171,7 @@ inline constexpr auto SIDS_ERR_INPUT_OVERFLOW = L"119";
|
|||
inline constexpr auto SIDS_ERR_OUTPUT_OVERFLOW = L"120";
|
||||
|
||||
// Include the resource key ID from above into this vector to load it into memory for the engine to use
|
||||
inline constexpr std::array<std::wstring_view, 120> g_sids =
|
||||
{
|
||||
SIDS_PLUS_MINUS,
|
||||
inline constexpr std::array<std::wstring_view, 120> g_sids = { SIDS_PLUS_MINUS,
|
||||
SIDS_C,
|
||||
SIDS_CE,
|
||||
SIDS_BACKSPACE,
|
||||
|
@ -292,5 +290,4 @@ inline constexpr std::array<std::wstring_view, 120> g_sids =
|
|||
SIDS_ERR_UNEX_END,
|
||||
SIDS_ERR_SG_INV_ERROR,
|
||||
SIDS_ERR_INPUT_OVERFLOW,
|
||||
SIDS_ERR_OUTPUT_OVERFLOW
|
||||
};
|
||||
SIDS_ERR_OUTPUT_OVERFLOW };
|
||||
|
|
|
@ -14,7 +14,8 @@ static constexpr size_t MAXPRECDEPTH = 25;
|
|||
// Helper class really a internal class to CCalcEngine, to accumulate each history line of text by collecting the
|
||||
// operands, operator, unary operator etc. Since it is a separate entity, it can be unit tested on its own but does
|
||||
// rely on CCalcEngine calling it in appropriate order.
|
||||
class CHistoryCollector {
|
||||
class CHistoryCollector
|
||||
{
|
||||
public:
|
||||
CHistoryCollector(ICalcDisplay* pCalcDisplay, std::shared_ptr<IHistoryDisplay> pHistoryDisplay, wchar_t decimalSymbol); // Can throw errors
|
||||
~CHistoryCollector();
|
||||
|
@ -44,7 +45,8 @@ private:
|
|||
// attaching the unary op around the last operand
|
||||
int m_lastOpStartIndex; // index of the beginning of the last operand added to the history
|
||||
int m_lastBinOpStartIndex; // index of the beginning of the last binary operator added to the history
|
||||
std::array<int, MAXPRECDEPTH> m_operandIndices; // Stack of index of opnd's beginning for each '('. A parallel array to m_hnoParNum, but abstracted independently of that
|
||||
std::array<int, MAXPRECDEPTH>
|
||||
m_operandIndices; // Stack of index of opnd's beginning for each '('. A parallel array to m_hnoParNum, but abstracted independently of that
|
||||
int m_curOperandIndex; // Stack index for the above stack
|
||||
bool m_bLastOpndBrace; // iff the last opnd in history is already braced so we can avoid putting another one for unary operator
|
||||
wchar_t m_decimalSymbol;
|
||||
|
|
|
@ -7,11 +7,14 @@
|
|||
#include "../ExpressionCommandInterface.h"
|
||||
|
||||
// Callback interface to be implemented by the clients of CCalcEngine
|
||||
class ICalcDisplay {
|
||||
class ICalcDisplay
|
||||
{
|
||||
public:
|
||||
virtual void SetPrimaryDisplay(const std::wstring& pszText, bool isError) = 0;
|
||||
virtual void SetIsInError(bool isInError) = 0;
|
||||
virtual void SetExpressionDisplay(_Inout_ std::shared_ptr<CalculatorVector<std::pair<std::wstring, int>>> const &tokens, _Inout_ std::shared_ptr<CalculatorVector<std::shared_ptr<IExpressionCommand>>> const &commands) = 0;
|
||||
virtual void SetExpressionDisplay(
|
||||
_Inout_ std::shared_ptr<CalculatorVector<std::pair<std::wstring, int>>> const& tokens,
|
||||
_Inout_ std::shared_ptr<CalculatorVector<std::shared_ptr<IExpressionCommand>>> const& commands) = 0;
|
||||
virtual void SetParenthesisNumber(_In_ unsigned int count) = 0;
|
||||
virtual void OnNoRightParenAdded() = 0;
|
||||
virtual void MaxDigitsReached() = 0; // not an error but still need to inform UI layer.
|
||||
|
|
|
@ -4,8 +4,12 @@
|
|||
#pragma once
|
||||
|
||||
// Callback interface to be implemented by the clients of CCalcEngine if they require equation history
|
||||
class IHistoryDisplay {
|
||||
class IHistoryDisplay
|
||||
{
|
||||
public:
|
||||
virtual ~IHistoryDisplay(){};
|
||||
virtual unsigned int AddToHistory(_In_ std::shared_ptr<CalculatorVector <std::pair<std::wstring, int>>> const &tokens, _In_ std::shared_ptr<CalculatorVector<std::shared_ptr<IExpressionCommand>>> const &commands, _In_ std::wstring_view result) = 0;
|
||||
virtual unsigned int AddToHistory(
|
||||
_In_ std::shared_ptr<CalculatorVector<std::pair<std::wstring, int>>> const& tokens,
|
||||
_In_ std::shared_ptr<CalculatorVector<std::shared_ptr<IExpressionCommand>>> const& commands,
|
||||
_In_ std::wstring_view result) = 0;
|
||||
};
|
||||
|
|
|
@ -4,7 +4,8 @@
|
|||
#pragma once
|
||||
|
||||
// This is expected to be in same order as IDM_HEX, IDM_DEC, IDM_OCT, IDM_BIN
|
||||
enum eRADIX_TYPE {
|
||||
enum eRADIX_TYPE
|
||||
{
|
||||
HEX_RADIX,
|
||||
DEC_RADIX,
|
||||
OCT_RADIX,
|
||||
|
|
|
@ -83,4 +83,3 @@ typedef int32_t ResultCode;
|
|||
//
|
||||
// The result of this operation is undefined
|
||||
#define CALC_E_NORESULT ((uint32_t)0x80000009)
|
||||
|
||||
|
|
|
@ -130,7 +130,6 @@ void _mulnumx( PNUMBER *pa, PNUMBER b )
|
|||
// If result is nonzero, or while result of carry is nonzero...
|
||||
while (mcy || cy)
|
||||
{
|
||||
|
||||
// update carry from addition(s) and multiply.
|
||||
cy += (TWO_MANTTYPE)ptrc[icdigit] + ((uint32_t)mcy & ((uint32_t)~BASEX));
|
||||
|
||||
|
@ -144,7 +143,6 @@ void _mulnumx( PNUMBER *pa, PNUMBER b )
|
|||
|
||||
ptrb++;
|
||||
ptrc++;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -198,7 +196,6 @@ void numpowi32x( _Inout_ PNUMBER *proot, _In_ int32_t power )
|
|||
}
|
||||
destroynum(*proot);
|
||||
*proot = lret;
|
||||
|
||||
}
|
||||
|
||||
void _divnumx(PNUMBER* pa, PNUMBER b, int32_t precision);
|
||||
|
@ -363,5 +360,3 @@ void _divnumx( PNUMBER *pa, PNUMBER b, int32_t precision)
|
|||
destroynum(*pa);
|
||||
*pa = c;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -42,8 +42,7 @@ wchar_t g_decimalSeparator = L'.';
|
|||
// See also
|
||||
// * https://docs.microsoft.com/en-us/cpp/preprocessor/predefined-macros
|
||||
// * https://sourceforge.net/p/predef/wiki/Architectures/
|
||||
#if defined(MIDL_PASS) || defined(RC_INVOKED) || defined(_M_CEE_PURE) \
|
||||
|| defined(_M_AMD64) || defined(__ARM_ARCH) || defined(__x86_64__) || defined(_M_ARM64)
|
||||
#if defined(MIDL_PASS) || defined(RC_INVOKED) || defined(_M_CEE_PURE) || defined(_M_AMD64) || defined(__ARM_ARCH) || defined(__x86_64__) || defined(_M_ARM64)
|
||||
|
||||
#ifndef Calc_UInt32x32To64
|
||||
#define Calc_UInt32x32To64(a, b) ((uint64_t)((uint32_t)(a)) * (uint64_t)((uint32_t)(b)))
|
||||
|
@ -63,12 +62,9 @@ wchar_t g_decimalSeparator = L'.';
|
|||
#define CALC_INTSAFE_E_ARITHMETIC_OVERFLOW ((int32_t)0x80070216L) // 0x216 = 534 = ERROR_ARITHMETIC_OVERFLOW
|
||||
#define CALC_ULONG_ERROR ((uint32_t)0xffffffffU)
|
||||
|
||||
namespace {
|
||||
int32_t
|
||||
Calc_ULongAdd(
|
||||
_In_ uint32_t ulAugend,
|
||||
_In_ uint32_t ulAddend,
|
||||
_Out_ uint32_t* pulResult)
|
||||
namespace
|
||||
{
|
||||
int32_t Calc_ULongAdd(_In_ uint32_t ulAugend, _In_ uint32_t ulAddend, _Out_ uint32_t* pulResult)
|
||||
{
|
||||
int32_t hr = CALC_INTSAFE_E_ARITHMETIC_OVERFLOW;
|
||||
*pulResult = CALC_ULONG_ERROR;
|
||||
|
@ -82,10 +78,7 @@ namespace {
|
|||
return hr;
|
||||
}
|
||||
|
||||
int32_t
|
||||
Calc_ULongLongToULong(
|
||||
_In_ uint64_t ullOperand,
|
||||
_Out_ uint32_t* pulResult)
|
||||
int32_t Calc_ULongLongToULong(_In_ uint64_t ullOperand, _Out_ uint32_t* pulResult)
|
||||
{
|
||||
int32_t hr = CALC_INTSAFE_E_ARITHMETIC_OVERFLOW;
|
||||
*pulResult = CALC_ULONG_ERROR;
|
||||
|
@ -99,11 +92,7 @@ namespace {
|
|||
return hr;
|
||||
}
|
||||
|
||||
int32_t
|
||||
Calc_ULongMult(
|
||||
_In_ uint32_t ulMultiplicand,
|
||||
_In_ uint32_t ulMultiplier,
|
||||
_Out_ uint32_t* pulResult)
|
||||
int32_t Calc_ULongMult(_In_ uint32_t ulMultiplicand, _In_ uint32_t ulMultiplier, _Out_ uint32_t* pulResult)
|
||||
{
|
||||
uint64_t ull64Result = Calc_UInt32x32To64(ulMultiplicand, ulMultiplier);
|
||||
|
||||
|
@ -165,7 +154,6 @@ void _destroynum( _In_ PNUMBER pnum )
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// FUNCTION: _destroyrat
|
||||
|
@ -190,7 +178,6 @@ void _destroyrat( _In_ PRAT prat )
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// FUNCTION: _createnum
|
||||
|
@ -210,9 +197,8 @@ PNUMBER _createnum( _In_ uint32_t size )
|
|||
uint32_t cbAlloc;
|
||||
|
||||
// sizeof( MANTTYPE ) is the size of a 'digit'
|
||||
if (SUCCEEDED(Calc_ULongAdd(size, 1, &cbAlloc)) &&
|
||||
SUCCEEDED(Calc_ULongMult(cbAlloc, sizeof(MANTTYPE), &cbAlloc)) &&
|
||||
SUCCEEDED(Calc_ULongAdd(cbAlloc, sizeof(NUMBER), &cbAlloc)))
|
||||
if (SUCCEEDED(Calc_ULongAdd(size, 1, &cbAlloc)) && SUCCEEDED(Calc_ULongMult(cbAlloc, sizeof(MANTTYPE), &cbAlloc))
|
||||
&& SUCCEEDED(Calc_ULongAdd(cbAlloc, sizeof(NUMBER), &cbAlloc)))
|
||||
{
|
||||
pnumret = (PNUMBER)zmalloc(cbAlloc);
|
||||
if (pnumret == nullptr)
|
||||
|
@ -241,7 +227,6 @@ PNUMBER _createnum( _In_ uint32_t size )
|
|||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
PRAT _createrat(void)
|
||||
|
||||
{
|
||||
|
@ -258,8 +243,6 @@ PRAT _createrat( void )
|
|||
return (prat);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// FUNCTION: numtorat
|
||||
|
@ -297,15 +280,12 @@ PRAT numtorat( _In_ PNUMBER pin, uint32_t radix)
|
|||
pout->pp = numtonRadixx(pnRadixn, radix);
|
||||
pout->pq = numtonRadixx(qnRadixn, radix);
|
||||
|
||||
|
||||
destroynum(pnRadixn);
|
||||
destroynum(qnRadixn);
|
||||
|
||||
return (pout);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// FUNCTION: nRadixxtonum
|
||||
|
@ -343,8 +323,7 @@ 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 (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)
|
||||
|
@ -585,21 +564,7 @@ static constexpr uint8_t ERR = 14;
|
|||
|
||||
#if defined(DEBUG)
|
||||
char* statestr[] = {
|
||||
"START",
|
||||
"MANTS",
|
||||
"LZ",
|
||||
"LZDP",
|
||||
"LD",
|
||||
"DZ",
|
||||
"DD",
|
||||
"DDP",
|
||||
"EXPB",
|
||||
"EXPS",
|
||||
"EXPD",
|
||||
"EXPBZ",
|
||||
"EXPSZ",
|
||||
"EXPDZ",
|
||||
"ERR",
|
||||
"START", "MANTS", "LZ", "LZDP", "LD", "DZ", "DD", "DDP", "EXPB", "EXPS", "EXPD", "EXPBZ", "EXPSZ", "EXPDZ", "ERR",
|
||||
};
|
||||
#endif
|
||||
|
||||
|
@ -862,7 +827,8 @@ PNUMBER i32tonum( int32_t ini32, uint32_t radix)
|
|||
pnumret->sign = 1;
|
||||
}
|
||||
|
||||
do {
|
||||
do
|
||||
{
|
||||
*pmant++ = (MANTTYPE)(ini32 % radix);
|
||||
ini32 /= radix;
|
||||
pnumret->cdigit++;
|
||||
|
@ -885,7 +851,6 @@ PNUMBER i32tonum( int32_t ini32, uint32_t radix)
|
|||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
PNUMBER Ui32tonum(uint32_t ini32, uint32_t radix)
|
||||
{
|
||||
MANTTYPE* pmant;
|
||||
|
@ -897,7 +862,8 @@ PNUMBER Ui32tonum(uint32_t ini32, uint32_t radix)
|
|||
pnumret->exp = 0;
|
||||
pnumret->sign = 1;
|
||||
|
||||
do {
|
||||
do
|
||||
{
|
||||
*pmant++ = (MANTTYPE)(ini32 % radix);
|
||||
ini32 /= radix;
|
||||
pnumret->cdigit++;
|
||||
|
@ -906,7 +872,6 @@ PNUMBER Ui32tonum(uint32_t ini32, uint32_t radix)
|
|||
return (pnumret);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// FUNCTION: rattoi32
|
||||
|
@ -978,7 +943,6 @@ uint32_t rattoUi32( _In_ PRAT prat, uint32_t radix, int32_t precision)
|
|||
return (lret);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// FUNCTION: rattoUi64
|
||||
|
@ -1531,7 +1495,6 @@ void numpowi32( _Inout_ PNUMBER *proot, int32_t power, uint32_t radix, int32_t p
|
|||
}
|
||||
destroynum(*proot);
|
||||
*proot = lret;
|
||||
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
#include "ratpak.h"
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// FUNCTION: exprat
|
||||
|
@ -51,7 +50,8 @@ void _exprat( PRAT *px, int32_t precision)
|
|||
|
||||
n2 = i32tonum(0L, BASEX);
|
||||
|
||||
do {
|
||||
do
|
||||
{
|
||||
NEXTTERM(*px, INC(n2) DIVNUM(n2), precision);
|
||||
} while (!SMALL_ENOUGH_RAT(thisterm, precision));
|
||||
|
||||
|
@ -96,7 +96,6 @@ void exprat( PRAT *px, uint32_t radix, int32_t precision)
|
|||
destroyrat(pint);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// FUNCTION: lograt, _lograt
|
||||
|
@ -142,7 +141,8 @@ void _lograt( PRAT *px, int32_t precision)
|
|||
n2 = i32tonum(1L, BASEX);
|
||||
(*px)->pp->sign *= -1;
|
||||
|
||||
do {
|
||||
do
|
||||
{
|
||||
NEXTTERM(*px, MULNUM(n2) INC(n2) DIVNUM(n2), precision);
|
||||
TRIMTOP(*px, precision);
|
||||
} while (!SMALL_ENOUGH_RAT(thisterm, precision));
|
||||
|
@ -150,7 +150,6 @@ void _lograt( PRAT *px, int32_t precision)
|
|||
DESTROYTAYLOR();
|
||||
}
|
||||
|
||||
|
||||
void lograt(PRAT* px, int32_t precision)
|
||||
|
||||
{
|
||||
|
@ -158,7 +157,6 @@ void lograt( PRAT *px, int32_t precision)
|
|||
PRAT pwr = nullptr; // pwr is the large scaling factor.
|
||||
PRAT offset = nullptr; // offset is the incremental scaling factor.
|
||||
|
||||
|
||||
// Check for someone taking the log of zero or a negative number.
|
||||
if (rat_le(*px, rat_zero, precision))
|
||||
{
|
||||
|
@ -433,8 +431,7 @@ void powratcomp(PRAT *px, PRAT y, uint32_t radix, int32_t precision)
|
|||
PRAT pxint = nullptr;
|
||||
DUPRAT(pxint, *px);
|
||||
subrat(&pxint, rat_one, precision);
|
||||
if ( rat_gt( pxint, rat_negsmallest, precision) &&
|
||||
rat_lt( pxint, rat_smallest, precision) && ( sign == 1 ) )
|
||||
if (rat_gt(pxint, rat_negsmallest, precision) && rat_lt(pxint, rat_smallest, precision) && (sign == 1))
|
||||
{
|
||||
// *px is one, special case a 1 return.
|
||||
DUPRAT(*px, rat_one);
|
||||
|
@ -443,7 +440,6 @@ void powratcomp(PRAT *px, PRAT y, uint32_t radix, int32_t precision)
|
|||
}
|
||||
else
|
||||
{
|
||||
|
||||
// Only do the exp if the number isn't zero or one
|
||||
PRAT podd = nullptr;
|
||||
DUPRAT(podd, y);
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
#include "ratpak.h"
|
||||
|
||||
|
||||
#define ABSRAT(x) (((x)->pp->sign = 1), ((x)->pq->sign = 1))
|
||||
#define NEGATE(x) ((x)->pp->sign *= -1)
|
||||
|
||||
|
@ -55,7 +54,6 @@
|
|||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
void _gamma(PRAT* pn, uint32_t radix, int32_t precision)
|
||||
|
||||
{
|
||||
|
@ -214,13 +212,11 @@ void factrat( PRAT *px, uint32_t radix, int32_t precision)
|
|||
fracrat(&frac, radix, precision);
|
||||
|
||||
// Check for negative integers and throw an error.
|
||||
if ( ( zerrat(frac) || ( LOGRATRADIX(frac) <= -precision) ) &&
|
||||
( SIGN(*px) == -1 ) )
|
||||
if ((zerrat(frac) || (LOGRATRADIX(frac) <= -precision)) && (SIGN(*px) == -1))
|
||||
{
|
||||
throw CALC_E_DOMAIN;
|
||||
}
|
||||
while ( rat_gt( *px, rat_zero, precision) &&
|
||||
( LOGRATRADIX(*px) > -precision) )
|
||||
while (rat_gt(*px, rat_zero, precision) && (LOGRATRADIX(*px) > -precision))
|
||||
{
|
||||
mulrat(&fact, *px, precision);
|
||||
subrat(px, rat_one, precision);
|
||||
|
@ -254,4 +250,3 @@ void factrat( PRAT *px, uint32_t radix, int32_t precision)
|
|||
destroyrat(frac);
|
||||
destroyrat(neg_rat_one);
|
||||
}
|
||||
|
||||
|
|
|
@ -17,8 +17,6 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
#include "ratpak.h"
|
||||
|
||||
|
||||
|
||||
void ascalerat(_Inout_ PRAT* pa, ANGLE_TYPE angletype, int32_t precision)
|
||||
{
|
||||
switch (angletype)
|
||||
|
@ -36,7 +34,6 @@ void ascalerat( _Inout_ PRAT *pa, ANGLE_TYPE angletype, int32_t precision)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// FUNCTION: asinrat, _asinrat
|
||||
|
@ -74,10 +71,8 @@ void _asinrat( PRAT *px, int32_t precision)
|
|||
|
||||
do
|
||||
{
|
||||
NEXTTERM(xx,MULNUM(n2) MULNUM(n2)
|
||||
INC(n2) DIVNUM(n2) INC(n2) DIVNUM(n2), precision);
|
||||
}
|
||||
while ( !SMALL_ENOUGH_RAT( thisterm, precision) );
|
||||
NEXTTERM(xx, MULNUM(n2) MULNUM(n2) INC(n2) DIVNUM(n2) INC(n2) DIVNUM(n2), precision);
|
||||
} while (!SMALL_ENOUGH_RAT(thisterm, precision));
|
||||
DESTROYTAYLOR();
|
||||
}
|
||||
|
||||
|
@ -143,7 +138,6 @@ void asinrat( PRAT *px, uint32_t radix, int32_t precision)
|
|||
(*px)->pq->sign = 1;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// FUNCTION: acosrat, _acosrat
|
||||
|
@ -190,10 +184,8 @@ void _acosrat( PRAT *px, int32_t precision)
|
|||
|
||||
do
|
||||
{
|
||||
NEXTTERM(xx,MULNUM(n2) MULNUM(n2)
|
||||
INC(n2) DIVNUM(n2) INC(n2) DIVNUM(n2), precision);
|
||||
}
|
||||
while ( !SMALL_ENOUGH_RAT( thisterm, precision) );
|
||||
NEXTTERM(xx, MULNUM(n2) MULNUM(n2) INC(n2) DIVNUM(n2) INC(n2) DIVNUM(n2), precision);
|
||||
} while (!SMALL_ENOUGH_RAT(thisterm, precision));
|
||||
|
||||
DESTROYTAYLOR();
|
||||
}
|
||||
|
@ -276,7 +268,8 @@ void _atanrat( PRAT *px, int32_t precision)
|
|||
|
||||
xx->pp->sign *= -1;
|
||||
|
||||
do {
|
||||
do
|
||||
{
|
||||
NEXTTERM(xx, MULNUM(n2) INC(n2) INC(n2) DIVNUM(n2), precision);
|
||||
} while (!SMALL_ENOUGH_RAT(thisterm, precision));
|
||||
|
||||
|
@ -332,4 +325,3 @@ void atanrat( PRAT *px, uint32_t radix, int32_t precision)
|
|||
subrat(px, pi, precision);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -18,8 +18,6 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
#include "ratpak.h"
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// FUNCTION: asinhrat
|
||||
|
@ -79,17 +77,14 @@ void asinhrat( PRAT *px, uint32_t radix, int32_t precision)
|
|||
|
||||
do
|
||||
{
|
||||
NEXTTERM(xx,MULNUM(n2) MULNUM(n2)
|
||||
INC(n2) DIVNUM(n2) INC(n2) DIVNUM(n2), precision);
|
||||
}
|
||||
while ( !SMALL_ENOUGH_RAT( thisterm, precision) );
|
||||
NEXTTERM(xx, MULNUM(n2) MULNUM(n2) INC(n2) DIVNUM(n2) INC(n2) DIVNUM(n2), precision);
|
||||
} while (!SMALL_ENOUGH_RAT(thisterm, precision));
|
||||
|
||||
DESTROYTAYLOR();
|
||||
}
|
||||
destroyrat(neg_pt_eight_five);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// FUNCTION: acoshrat
|
||||
|
@ -156,4 +151,3 @@ void atanhrat( PRAT *px, int32_t precision)
|
|||
divrat(px, rat_two, precision);
|
||||
destroyrat(ptmp);
|
||||
}
|
||||
|
||||
|
|
|
@ -66,8 +66,8 @@ void rshrat(PRAT *pa, PRAT b, uint32_t radix, int32_t precision)
|
|||
void boolrat(PRAT* pa, PRAT b, int func, uint32_t radix, int32_t precision);
|
||||
void boolnum(PNUMBER* pa, PNUMBER b, int func);
|
||||
|
||||
|
||||
enum {
|
||||
enum
|
||||
{
|
||||
FUNC_AND,
|
||||
FUNC_OR,
|
||||
FUNC_XOR
|
||||
|
@ -143,8 +143,7 @@ void boolnum(PNUMBER *pa, PNUMBER b, int func)
|
|||
MANTTYPE db;
|
||||
|
||||
a = *pa;
|
||||
cdigits = max(a->cdigit + a->exp, b->cdigit + b->exp) -
|
||||
min(a->exp, b->exp);
|
||||
cdigits = max(a->cdigit + a->exp, b->cdigit + b->exp) - min(a->exp, b->exp);
|
||||
createnum(c, cdigits);
|
||||
c->exp = min(a->exp, b->exp);
|
||||
mexp = c->exp;
|
||||
|
@ -154,12 +153,8 @@ void boolnum(PNUMBER *pa, PNUMBER b, int func)
|
|||
pchc = c->mant;
|
||||
for (; cdigits > 0; cdigits--, mexp++)
|
||||
{
|
||||
da = (((mexp >= a->exp) && (cdigits + a->exp - c->exp >
|
||||
(c->cdigit - a->cdigit))) ?
|
||||
*pcha++ : 0);
|
||||
db = (((mexp >= b->exp) && (cdigits + b->exp - c->exp >
|
||||
(c->cdigit - b->cdigit))) ?
|
||||
*pchb++ : 0);
|
||||
da = (((mexp >= a->exp) && (cdigits + a->exp - c->exp > (c->cdigit - a->cdigit))) ? *pcha++ : 0);
|
||||
db = (((mexp >= b->exp) && (cdigits + b->exp - c->exp > (c->cdigit - b->cdigit))) ? *pchb++ : 0);
|
||||
switch (func)
|
||||
{
|
||||
case FUNC_AND:
|
||||
|
|
|
@ -78,11 +78,9 @@ void _addnum( PNUMBER *pa, PNUMBER b, uint32_t radix)
|
|||
|
||||
a = *pa;
|
||||
|
||||
|
||||
// Calculate the overlap of the numbers after alignment, this includes
|
||||
// necessary padding 0's
|
||||
cdigits = max( a->cdigit+a->exp, b->cdigit+b->exp ) -
|
||||
min( a->exp, b->exp );
|
||||
cdigits = max(a->cdigit + a->exp, b->cdigit + b->exp) - min(a->exp, b->exp);
|
||||
|
||||
createnum(c, cdigits + 1);
|
||||
c->exp = min(a->exp, b->exp);
|
||||
|
@ -104,15 +102,10 @@ void _addnum( PNUMBER *pa, PNUMBER b, uint32_t radix)
|
|||
// aligned
|
||||
for (; cdigits > 0; cdigits--, mexp++)
|
||||
{
|
||||
|
||||
// Get digit from a, taking padding into account.
|
||||
da = ( ( ( mexp >= a->exp ) && ( cdigits + a->exp - c->exp >
|
||||
(c->cdigit - a->cdigit) ) ) ?
|
||||
*pcha++ : 0 );
|
||||
da = (((mexp >= a->exp) && (cdigits + a->exp - c->exp > (c->cdigit - a->cdigit))) ? *pcha++ : 0);
|
||||
// Get digit from b, taking padding into account.
|
||||
db = ( ( ( mexp >= b->exp ) && ( cdigits + b->exp - c->exp >
|
||||
(c->cdigit - b->cdigit) ) ) ?
|
||||
*pchb++ : 0 );
|
||||
db = (((mexp >= b->exp) && (cdigits + b->exp - c->exp > (c->cdigit - b->cdigit))) ? *pchb++ : 0);
|
||||
|
||||
// Handle complementing for a and b digit. Might be a better way, but
|
||||
// haven't found it yet.
|
||||
|
@ -157,9 +150,7 @@ void _addnum( PNUMBER *pa, PNUMBER b, uint32_t radix)
|
|||
// slower on average.
|
||||
c->sign = -1;
|
||||
cy = 1;
|
||||
for ( ( cdigits = c->cdigit ), (pchc = c->mant);
|
||||
cdigits > 0;
|
||||
cdigits-- )
|
||||
for ((cdigits = c->cdigit), (pchc = c->mant); cdigits > 0; cdigits--)
|
||||
{
|
||||
cy = (MANTTYPE)radix - (MANTTYPE)1 - *pchc + cy;
|
||||
*pchc++ = (MANTTYPE)(cy % (MANTTYPE)radix);
|
||||
|
@ -269,7 +260,6 @@ void _mulnum( PNUMBER *pa, PNUMBER b, uint32_t radix)
|
|||
// If result is nonzero, or while result of carry is nonzero...
|
||||
while (mcy || cy)
|
||||
{
|
||||
|
||||
// update carry from addition(s) and multiply.
|
||||
cy += (TWO_MANTTYPE)pchc[icdigit] + (mcy % (TWO_MANTTYPE)radix);
|
||||
|
||||
|
@ -297,7 +287,6 @@ void _mulnum( PNUMBER *pa, PNUMBER b, uint32_t radix)
|
|||
*pa = c;
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// FUNCTION: remnum
|
||||
|
@ -357,11 +346,9 @@ void remnum( PNUMBER *pa, PNUMBER b, uint32_t radix)
|
|||
|
||||
destroynum(tmp);
|
||||
destroynum(lasttmp);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// FUNCTION: divnum
|
||||
|
@ -489,7 +476,6 @@ void _divnum( PNUMBER *pa, PNUMBER b, uint32_t radix, int32_t precision)
|
|||
*pa = c;
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// FUNCTION: equnum
|
||||
|
@ -541,10 +527,8 @@ bool equnum( PNUMBER a, PNUMBER b )
|
|||
// difference in the digits.
|
||||
for (; cdigits > 0; cdigits--)
|
||||
{
|
||||
da = ( (cdigits > (ccdigits - a->cdigit) ) ?
|
||||
*pa-- : 0 );
|
||||
db = ( (cdigits > (ccdigits - b->cdigit) ) ?
|
||||
*pb-- : 0 );
|
||||
da = ((cdigits > (ccdigits - a->cdigit)) ? *pa-- : 0);
|
||||
db = ((cdigits > (ccdigits - b->cdigit)) ? *pb-- : 0);
|
||||
if (da != db)
|
||||
{
|
||||
return false;
|
||||
|
@ -582,7 +566,6 @@ bool lessnum( PNUMBER a, PNUMBER b )
|
|||
MANTTYPE da;
|
||||
MANTTYPE db;
|
||||
|
||||
|
||||
diff = (a->cdigit + a->exp) - (b->cdigit + b->exp);
|
||||
if (diff < 0)
|
||||
{
|
||||
|
@ -605,10 +588,8 @@ bool lessnum( PNUMBER a, PNUMBER b )
|
|||
ccdigits = cdigits;
|
||||
for (; cdigits > 0; cdigits--)
|
||||
{
|
||||
da = ( (cdigits > (ccdigits - a->cdigit) ) ?
|
||||
*pa-- : 0 );
|
||||
db = ( (cdigits > (ccdigits - b->cdigit) ) ?
|
||||
*pb-- : 0 );
|
||||
da = ((cdigits > (ccdigits - a->cdigit)) ? *pa-- : 0);
|
||||
db = ((cdigits > (ccdigits - b->cdigit)) ? *pb-- : 0);
|
||||
diff = da - db;
|
||||
if (diff)
|
||||
{
|
||||
|
|
|
@ -117,7 +117,6 @@ void mulrat( PRAT *pa, PRAT b, int32_t precision)
|
|||
#ifdef MULGCD
|
||||
gcdrat(pa);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -133,11 +132,9 @@ void mulrat( PRAT *pa, PRAT b, int32_t precision)
|
|||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
void divrat(PRAT* pa, PRAT b, int32_t precision)
|
||||
|
||||
{
|
||||
|
||||
if (!zernum((*pa)->pp))
|
||||
{
|
||||
// Only do the divide if the top isn't zero.
|
||||
|
@ -170,7 +167,6 @@ void divrat( PRAT *pa, PRAT b, int32_t precision)
|
|||
#ifdef DIVGCD
|
||||
gcdrat(pa);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -244,11 +240,8 @@ void addrat( PRAT *pa, PRAT b, int32_t precision)
|
|||
#ifdef ADDGCD
|
||||
gcdrat(pa);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// FUNCTION: rootrat
|
||||
|
@ -274,7 +267,6 @@ void rootrat( PRAT *py, PRAT n, uint32_t radix, int32_t precision)
|
|||
destroyrat(oneovern);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// FUNCTION: zerrat
|
||||
|
@ -293,5 +285,3 @@ bool zerrat( PRAT a )
|
|||
{
|
||||
return (zernum(a->pp));
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -4,481 +4,591 @@
|
|||
#pragma once
|
||||
|
||||
// Autogenerated by _dumprawrat in support.cpp
|
||||
inline const NUMBER init_num_one= {
|
||||
1,
|
||||
inline const NUMBER init_num_one = { 1,
|
||||
1,
|
||||
0,
|
||||
{ 1,}
|
||||
};
|
||||
{
|
||||
1,
|
||||
} };
|
||||
// Autogenerated by _dumprawrat in support.cpp
|
||||
inline const NUMBER init_num_two= {
|
||||
1,
|
||||
inline const NUMBER init_num_two = { 1,
|
||||
1,
|
||||
0,
|
||||
{ 2,}
|
||||
};
|
||||
{
|
||||
2,
|
||||
} };
|
||||
// Autogenerated by _dumprawrat in support.cpp
|
||||
inline const NUMBER init_num_five= {
|
||||
1,
|
||||
inline const NUMBER init_num_five = { 1,
|
||||
1,
|
||||
0,
|
||||
{ 5,}
|
||||
};
|
||||
{
|
||||
5,
|
||||
} };
|
||||
// Autogenerated by _dumprawrat in support.cpp
|
||||
inline const NUMBER init_num_six= {
|
||||
1,
|
||||
inline const NUMBER init_num_six = { 1,
|
||||
1,
|
||||
0,
|
||||
{ 6,}
|
||||
};
|
||||
{
|
||||
6,
|
||||
} };
|
||||
// Autogenerated by _dumprawrat in support.cpp
|
||||
inline const NUMBER init_num_ten= {
|
||||
1,
|
||||
inline const NUMBER init_num_ten = { 1,
|
||||
1,
|
||||
0,
|
||||
{ 10,}
|
||||
};
|
||||
{
|
||||
10,
|
||||
} };
|
||||
// Autogenerated by _dumprawrat in support.cpp
|
||||
inline const NUMBER init_p_rat_smallest = {
|
||||
1,
|
||||
inline const NUMBER init_p_rat_smallest = { 1,
|
||||
1,
|
||||
0,
|
||||
{ 1,}
|
||||
};
|
||||
inline const NUMBER init_q_rat_smallest = {
|
||||
{
|
||||
1,
|
||||
} };
|
||||
inline const NUMBER init_q_rat_smallest = { 1,
|
||||
4,
|
||||
0,
|
||||
{ 0, 190439170, 901055854, 10097,}
|
||||
};
|
||||
{
|
||||
0,
|
||||
190439170,
|
||||
901055854,
|
||||
10097,
|
||||
} };
|
||||
// Autogenerated by _dumprawrat in support.cpp
|
||||
inline const NUMBER init_p_rat_negsmallest = {
|
||||
-1,
|
||||
inline const NUMBER init_p_rat_negsmallest = { -1,
|
||||
1,
|
||||
0,
|
||||
{ 1,}
|
||||
};
|
||||
inline const NUMBER init_q_rat_negsmallest = {
|
||||
{
|
||||
1,
|
||||
} };
|
||||
inline const NUMBER init_q_rat_negsmallest = { 1,
|
||||
4,
|
||||
0,
|
||||
{ 0, 190439170, 901055854, 10097,}
|
||||
};
|
||||
{
|
||||
0,
|
||||
190439170,
|
||||
901055854,
|
||||
10097,
|
||||
} };
|
||||
// Autogenerated by _dumprawrat in support.cpp
|
||||
inline const NUMBER init_p_pt_eight_five = {
|
||||
1,
|
||||
inline const NUMBER init_p_pt_eight_five = { 1,
|
||||
1,
|
||||
0,
|
||||
{ 85,}
|
||||
};
|
||||
inline const NUMBER init_q_pt_eight_five = {
|
||||
1,
|
||||
{
|
||||
85,
|
||||
} };
|
||||
inline const NUMBER init_q_pt_eight_five = { 1,
|
||||
1,
|
||||
0,
|
||||
{ 100,}
|
||||
};
|
||||
{
|
||||
100,
|
||||
} };
|
||||
// Autogenerated by _dumprawrat in support.cpp
|
||||
inline const NUMBER init_p_rat_six = {
|
||||
1,
|
||||
inline const NUMBER init_p_rat_six = { 1,
|
||||
1,
|
||||
0,
|
||||
{ 6,}
|
||||
};
|
||||
inline const NUMBER init_q_rat_six = {
|
||||
1,
|
||||
{
|
||||
6,
|
||||
} };
|
||||
inline const NUMBER init_q_rat_six = { 1,
|
||||
1,
|
||||
0,
|
||||
{ 1,}
|
||||
};
|
||||
{
|
||||
1,
|
||||
} };
|
||||
// Autogenerated by _dumprawrat in support.cpp
|
||||
inline const NUMBER init_p_rat_two = {
|
||||
1,
|
||||
inline const NUMBER init_p_rat_two = { 1,
|
||||
1,
|
||||
0,
|
||||
{ 2,}
|
||||
};
|
||||
inline const NUMBER init_q_rat_two = {
|
||||
1,
|
||||
{
|
||||
2,
|
||||
} };
|
||||
inline const NUMBER init_q_rat_two = { 1,
|
||||
1,
|
||||
0,
|
||||
{ 1,}
|
||||
};
|
||||
{
|
||||
1,
|
||||
} };
|
||||
// Autogenerated by _dumprawrat in support.cpp
|
||||
inline const NUMBER init_p_rat_zero = {
|
||||
1,
|
||||
inline const NUMBER init_p_rat_zero = { 1,
|
||||
1,
|
||||
0,
|
||||
{ 0,}
|
||||
};
|
||||
inline const NUMBER init_q_rat_zero = {
|
||||
1,
|
||||
{
|
||||
0,
|
||||
} };
|
||||
inline const NUMBER init_q_rat_zero = { 1,
|
||||
1,
|
||||
0,
|
||||
{ 1,}
|
||||
};
|
||||
{
|
||||
1,
|
||||
} };
|
||||
// Autogenerated by _dumprawrat in support.cpp
|
||||
inline const NUMBER init_p_rat_one = {
|
||||
1,
|
||||
inline const NUMBER init_p_rat_one = { 1,
|
||||
1,
|
||||
0,
|
||||
{ 1,}
|
||||
};
|
||||
inline const NUMBER init_q_rat_one = {
|
||||
{
|
||||
1,
|
||||
} };
|
||||
inline const NUMBER init_q_rat_one = { 1,
|
||||
1,
|
||||
0,
|
||||
{ 1,}
|
||||
};
|
||||
{
|
||||
1,
|
||||
} };
|
||||
// Autogenerated by _dumprawrat in support.cpp
|
||||
inline const NUMBER init_p_rat_neg_one = {
|
||||
-1,
|
||||
inline const NUMBER init_p_rat_neg_one = { -1,
|
||||
1,
|
||||
0,
|
||||
{ 1,}
|
||||
};
|
||||
inline const NUMBER init_q_rat_neg_one = {
|
||||
{
|
||||
1,
|
||||
} };
|
||||
inline const NUMBER init_q_rat_neg_one = { 1,
|
||||
1,
|
||||
0,
|
||||
{ 1,}
|
||||
};
|
||||
{
|
||||
1,
|
||||
} };
|
||||
// Autogenerated by _dumprawrat in support.cpp
|
||||
inline const NUMBER init_p_rat_half = {
|
||||
1,
|
||||
inline const NUMBER init_p_rat_half = { 1,
|
||||
1,
|
||||
0,
|
||||
{ 1,}
|
||||
};
|
||||
inline const NUMBER init_q_rat_half = {
|
||||
{
|
||||
1,
|
||||
} };
|
||||
inline const NUMBER init_q_rat_half = { 1,
|
||||
1,
|
||||
0,
|
||||
{ 2,}
|
||||
};
|
||||
{
|
||||
2,
|
||||
} };
|
||||
// Autogenerated by _dumprawrat in support.cpp
|
||||
inline const NUMBER init_p_rat_ten = {
|
||||
1,
|
||||
inline const NUMBER init_p_rat_ten = { 1,
|
||||
1,
|
||||
0,
|
||||
{ 10,}
|
||||
};
|
||||
inline const NUMBER init_q_rat_ten = {
|
||||
1,
|
||||
{
|
||||
10,
|
||||
} };
|
||||
inline const NUMBER init_q_rat_ten = { 1,
|
||||
1,
|
||||
0,
|
||||
{ 1,}
|
||||
};
|
||||
{
|
||||
1,
|
||||
} };
|
||||
// Autogenerated by _dumprawrat in support.cpp
|
||||
inline const NUMBER init_p_pi = {
|
||||
1,
|
||||
inline const NUMBER init_p_pi = { 1,
|
||||
6,
|
||||
0,
|
||||
{ 125527896, 283898350, 1960493936, 1672850762, 1288168272, 8,}
|
||||
};
|
||||
inline const NUMBER init_q_pi = {
|
||||
1,
|
||||
{
|
||||
125527896,
|
||||
283898350,
|
||||
1960493936,
|
||||
1672850762,
|
||||
1288168272,
|
||||
8,
|
||||
} };
|
||||
inline const NUMBER init_q_pi = { 1,
|
||||
6,
|
||||
0,
|
||||
{ 1288380402, 1120116153, 1860424692, 1944118326, 1583591604, 2,}
|
||||
};
|
||||
{
|
||||
1288380402,
|
||||
1120116153,
|
||||
1860424692,
|
||||
1944118326,
|
||||
1583591604,
|
||||
2,
|
||||
} };
|
||||
// Autogenerated by _dumprawrat in support.cpp
|
||||
inline const NUMBER init_p_two_pi = {
|
||||
1,
|
||||
inline const NUMBER init_p_two_pi = { 1,
|
||||
6,
|
||||
0,
|
||||
{ 251055792, 567796700, 1773504224, 1198217877, 428852897, 17,}
|
||||
};
|
||||
inline const NUMBER init_q_two_pi = {
|
||||
1,
|
||||
{
|
||||
251055792,
|
||||
567796700,
|
||||
1773504224,
|
||||
1198217877,
|
||||
428852897,
|
||||
17,
|
||||
} };
|
||||
inline const NUMBER init_q_two_pi = { 1,
|
||||
6,
|
||||
0,
|
||||
{ 1288380402, 1120116153, 1860424692, 1944118326, 1583591604, 2,}
|
||||
};
|
||||
{
|
||||
1288380402,
|
||||
1120116153,
|
||||
1860424692,
|
||||
1944118326,
|
||||
1583591604,
|
||||
2,
|
||||
} };
|
||||
// Autogenerated by _dumprawrat in support.cpp
|
||||
inline const NUMBER init_p_pi_over_two = {
|
||||
1,
|
||||
inline const NUMBER init_p_pi_over_two = { 1,
|
||||
6,
|
||||
0,
|
||||
{ 125527896, 283898350, 1960493936, 1672850762, 1288168272, 8,}
|
||||
};
|
||||
inline const NUMBER init_q_pi_over_two = {
|
||||
1,
|
||||
{
|
||||
125527896,
|
||||
283898350,
|
||||
1960493936,
|
||||
1672850762,
|
||||
1288168272,
|
||||
8,
|
||||
} };
|
||||
inline const NUMBER init_q_pi_over_two = { 1,
|
||||
6,
|
||||
0,
|
||||
{ 429277156, 92748659, 1573365737, 1740753005, 1019699561, 5,}
|
||||
};
|
||||
{
|
||||
429277156,
|
||||
92748659,
|
||||
1573365737,
|
||||
1740753005,
|
||||
1019699561,
|
||||
5,
|
||||
} };
|
||||
// Autogenerated by _dumprawrat in support.cpp
|
||||
inline const NUMBER init_p_one_pt_five_pi = {
|
||||
1,
|
||||
inline const NUMBER init_p_one_pt_five_pi = { 1,
|
||||
6,
|
||||
0,
|
||||
{ 1241201312, 270061909, 1051574664, 1924965045, 1340320627, 70,}
|
||||
};
|
||||
inline const NUMBER init_q_one_pt_five_pi = {
|
||||
1,
|
||||
{
|
||||
1241201312,
|
||||
270061909,
|
||||
1051574664,
|
||||
1924965045,
|
||||
1340320627,
|
||||
70,
|
||||
} };
|
||||
inline const NUMBER init_q_one_pt_five_pi = { 1,
|
||||
6,
|
||||
0,
|
||||
{ 1579671539, 1837970263, 1067644340, 523549916, 2119366659, 14,}
|
||||
};
|
||||
{
|
||||
1579671539,
|
||||
1837970263,
|
||||
1067644340,
|
||||
523549916,
|
||||
2119366659,
|
||||
14,
|
||||
} };
|
||||
// Autogenerated by _dumprawrat in support.cpp
|
||||
inline const NUMBER init_p_e_to_one_half = {
|
||||
1,
|
||||
inline const NUMBER init_p_e_to_one_half = { 1,
|
||||
6,
|
||||
0,
|
||||
{ 256945612, 216219427, 223516738, 477442596, 581063757, 23,}
|
||||
};
|
||||
inline const NUMBER init_q_e_to_one_half = {
|
||||
1,
|
||||
{
|
||||
256945612,
|
||||
216219427,
|
||||
223516738,
|
||||
477442596,
|
||||
581063757,
|
||||
23,
|
||||
} };
|
||||
inline const NUMBER init_q_e_to_one_half = { 1,
|
||||
6,
|
||||
0,
|
||||
{ 1536828363, 698484484, 1127331835, 224219346, 245499408, 14,}
|
||||
};
|
||||
{
|
||||
1536828363,
|
||||
698484484,
|
||||
1127331835,
|
||||
224219346,
|
||||
245499408,
|
||||
14,
|
||||
} };
|
||||
// Autogenerated by _dumprawrat in support.cpp
|
||||
inline const NUMBER init_p_rat_exp = {
|
||||
1,
|
||||
inline const NUMBER init_p_rat_exp = { 1,
|
||||
6,
|
||||
0,
|
||||
{ 943665199, 1606559160, 1094967530, 1759391384, 1671799163, 1123581,}
|
||||
};
|
||||
inline const NUMBER init_q_rat_exp = {
|
||||
1,
|
||||
{
|
||||
943665199,
|
||||
1606559160,
|
||||
1094967530,
|
||||
1759391384,
|
||||
1671799163,
|
||||
1123581,
|
||||
} };
|
||||
inline const NUMBER init_q_rat_exp = { 1,
|
||||
6,
|
||||
0,
|
||||
{ 879242208, 2022880100, 617392930, 1374929092, 1367479163, 413342,}
|
||||
};
|
||||
{
|
||||
879242208,
|
||||
2022880100,
|
||||
617392930,
|
||||
1374929092,
|
||||
1367479163,
|
||||
413342,
|
||||
} };
|
||||
// Autogenerated by _dumprawrat in support.cpp
|
||||
inline const NUMBER init_p_ln_ten = {
|
||||
1,
|
||||
inline const NUMBER init_p_ln_ten = { 1,
|
||||
6,
|
||||
0,
|
||||
{ 2086268922, 165794492, 1416063951, 1851428830, 1893239400, 65366841,}
|
||||
};
|
||||
inline const NUMBER init_q_ln_ten = {
|
||||
1,
|
||||
{
|
||||
2086268922,
|
||||
165794492,
|
||||
1416063951,
|
||||
1851428830,
|
||||
1893239400,
|
||||
65366841,
|
||||
} };
|
||||
inline const NUMBER init_q_ln_ten = { 1,
|
||||
6,
|
||||
0,
|
||||
{ 26790652, 564532679, 783998273, 216030448, 1564709968, 28388458,}
|
||||
};
|
||||
{
|
||||
26790652,
|
||||
564532679,
|
||||
783998273,
|
||||
216030448,
|
||||
1564709968,
|
||||
28388458,
|
||||
} };
|
||||
// Autogenerated by _dumprawrat in support.cpp
|
||||
inline const NUMBER init_p_ln_two = {
|
||||
1,
|
||||
inline const NUMBER init_p_ln_two = { 1,
|
||||
6,
|
||||
0,
|
||||
{ 1789230241, 1057927868, 715399197, 908801241, 1411265331, 3,}
|
||||
};
|
||||
inline const NUMBER init_q_ln_two = {
|
||||
1,
|
||||
{
|
||||
1789230241,
|
||||
1057927868,
|
||||
715399197,
|
||||
908801241,
|
||||
1411265331,
|
||||
3,
|
||||
} };
|
||||
inline const NUMBER init_q_ln_two = { 1,
|
||||
6,
|
||||
0,
|
||||
{ 1559869847, 1930657510, 1228561531, 219003871, 593099283, 5,}
|
||||
};
|
||||
{
|
||||
1559869847,
|
||||
1930657510,
|
||||
1228561531,
|
||||
219003871,
|
||||
593099283,
|
||||
5,
|
||||
} };
|
||||
// Autogenerated by _dumprawrat in support.cpp
|
||||
inline const NUMBER init_p_rad_to_deg = {
|
||||
1,
|
||||
inline const NUMBER init_p_rad_to_deg = { 1,
|
||||
6,
|
||||
0,
|
||||
{ 2127722024, 1904928383, 2016479213, 2048947859, 1578647346, 492,}
|
||||
};
|
||||
inline const NUMBER init_q_rad_to_deg = {
|
||||
1,
|
||||
{
|
||||
2127722024,
|
||||
1904928383,
|
||||
2016479213,
|
||||
2048947859,
|
||||
1578647346,
|
||||
492,
|
||||
} };
|
||||
inline const NUMBER init_q_rad_to_deg = { 1,
|
||||
6,
|
||||
0,
|
||||
{ 125527896, 283898350, 1960493936, 1672850762, 1288168272, 8,}
|
||||
};
|
||||
{
|
||||
125527896,
|
||||
283898350,
|
||||
1960493936,
|
||||
1672850762,
|
||||
1288168272,
|
||||
8,
|
||||
} };
|
||||
// Autogenerated by _dumprawrat in support.cpp
|
||||
inline const NUMBER init_p_rad_to_grad = {
|
||||
1,
|
||||
inline const NUMBER init_p_rad_to_grad = { 1,
|
||||
6,
|
||||
0,
|
||||
{ 2125526288, 684931327, 570267400, 129125085, 1038224725, 547,}
|
||||
};
|
||||
inline const NUMBER init_q_rad_to_grad = {
|
||||
1,
|
||||
{
|
||||
2125526288,
|
||||
684931327,
|
||||
570267400,
|
||||
129125085,
|
||||
1038224725,
|
||||
547,
|
||||
} };
|
||||
inline const NUMBER init_q_rad_to_grad = { 1,
|
||||
6,
|
||||
0,
|
||||
{ 125527896, 283898350, 1960493936, 1672850762, 1288168272, 8,}
|
||||
};
|
||||
{
|
||||
125527896,
|
||||
283898350,
|
||||
1960493936,
|
||||
1672850762,
|
||||
1288168272,
|
||||
8,
|
||||
} };
|
||||
// Autogenerated by _dumprawrat in support.cpp
|
||||
inline const NUMBER init_p_rat_qword = {
|
||||
1,
|
||||
inline const NUMBER init_p_rat_qword = { 1,
|
||||
3,
|
||||
0,
|
||||
{ 2147483647, 2147483647, 3,}
|
||||
};
|
||||
inline const NUMBER init_q_rat_qword = {
|
||||
1,
|
||||
{
|
||||
2147483647,
|
||||
2147483647,
|
||||
3,
|
||||
} };
|
||||
inline const NUMBER init_q_rat_qword = { 1,
|
||||
1,
|
||||
0,
|
||||
{ 1,}
|
||||
};
|
||||
// Autogenerated by _dumprawrat in support.cpp
|
||||
inline const NUMBER init_p_rat_dword = {
|
||||
{
|
||||
1,
|
||||
} };
|
||||
// Autogenerated by _dumprawrat in support.cpp
|
||||
inline const NUMBER init_p_rat_dword = { 1,
|
||||
2,
|
||||
0,
|
||||
{ 2147483647, 1,}
|
||||
};
|
||||
inline const NUMBER init_q_rat_dword = {
|
||||
{
|
||||
2147483647,
|
||||
1,
|
||||
} };
|
||||
inline const NUMBER init_q_rat_dword = { 1,
|
||||
1,
|
||||
0,
|
||||
{ 1,}
|
||||
};
|
||||
{
|
||||
1,
|
||||
} };
|
||||
// Autogenerated by _dumprawrat in support.cpp
|
||||
inline const NUMBER init_p_rat_max_i32 = {
|
||||
1,
|
||||
inline const NUMBER init_p_rat_max_i32 = { 1,
|
||||
1,
|
||||
0,
|
||||
{ 2147483647,}
|
||||
};
|
||||
inline const NUMBER init_q_rat_max_i32 = {
|
||||
1,
|
||||
{
|
||||
2147483647,
|
||||
} };
|
||||
inline const NUMBER init_q_rat_max_i32 = { 1,
|
||||
1,
|
||||
0,
|
||||
{ 1,}
|
||||
};
|
||||
{
|
||||
1,
|
||||
} };
|
||||
// Autogenerated by _dumprawrat in support.cpp
|
||||
inline const NUMBER init_p_rat_min_i32 = {
|
||||
-1,
|
||||
inline const NUMBER init_p_rat_min_i32 = { -1,
|
||||
2,
|
||||
0,
|
||||
{ 0, 1,}
|
||||
};
|
||||
inline const NUMBER init_q_rat_min_i32 = {
|
||||
{
|
||||
0,
|
||||
1,
|
||||
} };
|
||||
inline const NUMBER init_q_rat_min_i32 = { 1,
|
||||
1,
|
||||
0,
|
||||
{ 1,}
|
||||
};
|
||||
{
|
||||
1,
|
||||
} };
|
||||
// Autogenerated by _dumprawrat in support.cpp
|
||||
inline const NUMBER init_p_rat_word = {
|
||||
1,
|
||||
inline const NUMBER init_p_rat_word = { 1,
|
||||
1,
|
||||
0,
|
||||
{ 65535,}
|
||||
};
|
||||
inline const NUMBER init_q_rat_word = {
|
||||
1,
|
||||
{
|
||||
65535,
|
||||
} };
|
||||
inline const NUMBER init_q_rat_word = { 1,
|
||||
1,
|
||||
0,
|
||||
{ 1,}
|
||||
};
|
||||
{
|
||||
1,
|
||||
} };
|
||||
// Autogenerated by _dumprawrat in support.cpp
|
||||
inline const NUMBER init_p_rat_byte = {
|
||||
1,
|
||||
inline const NUMBER init_p_rat_byte = { 1,
|
||||
1,
|
||||
0,
|
||||
{ 255,}
|
||||
};
|
||||
inline const NUMBER init_q_rat_byte = {
|
||||
1,
|
||||
{
|
||||
255,
|
||||
} };
|
||||
inline const NUMBER init_q_rat_byte = { 1,
|
||||
1,
|
||||
0,
|
||||
{ 1,}
|
||||
};
|
||||
{
|
||||
1,
|
||||
} };
|
||||
// Autogenerated by _dumprawrat in support.cpp
|
||||
inline const NUMBER init_p_rat_400 = {
|
||||
1,
|
||||
inline const NUMBER init_p_rat_400 = { 1,
|
||||
1,
|
||||
0,
|
||||
{ 400,}
|
||||
};
|
||||
inline const NUMBER init_q_rat_400 = {
|
||||
1,
|
||||
{
|
||||
400,
|
||||
} };
|
||||
inline const NUMBER init_q_rat_400 = { 1,
|
||||
1,
|
||||
0,
|
||||
{ 1,}
|
||||
};
|
||||
{
|
||||
1,
|
||||
} };
|
||||
// Autogenerated by _dumprawrat in support.cpp
|
||||
inline const NUMBER init_p_rat_360 = {
|
||||
1,
|
||||
inline const NUMBER init_p_rat_360 = { 1,
|
||||
1,
|
||||
0,
|
||||
{ 360,}
|
||||
};
|
||||
inline const NUMBER init_q_rat_360 = {
|
||||
1,
|
||||
{
|
||||
360,
|
||||
} };
|
||||
inline const NUMBER init_q_rat_360 = { 1,
|
||||
1,
|
||||
0,
|
||||
{ 1,}
|
||||
};
|
||||
{
|
||||
1,
|
||||
} };
|
||||
// Autogenerated by _dumprawrat in support.cpp
|
||||
inline const NUMBER init_p_rat_200 = {
|
||||
1,
|
||||
inline const NUMBER init_p_rat_200 = { 1,
|
||||
1,
|
||||
0,
|
||||
{ 200,}
|
||||
};
|
||||
inline const NUMBER init_q_rat_200 = {
|
||||
1,
|
||||
{
|
||||
200,
|
||||
} };
|
||||
inline const NUMBER init_q_rat_200 = { 1,
|
||||
1,
|
||||
0,
|
||||
{ 1,}
|
||||
};
|
||||
{
|
||||
1,
|
||||
} };
|
||||
// Autogenerated by _dumprawrat in support.cpp
|
||||
inline const NUMBER init_p_rat_180 = {
|
||||
1,
|
||||
inline const NUMBER init_p_rat_180 = { 1,
|
||||
1,
|
||||
0,
|
||||
{ 180,}
|
||||
};
|
||||
inline const NUMBER init_q_rat_180 = {
|
||||
1,
|
||||
{
|
||||
180,
|
||||
} };
|
||||
inline const NUMBER init_q_rat_180 = { 1,
|
||||
1,
|
||||
0,
|
||||
{ 1,}
|
||||
};
|
||||
{
|
||||
1,
|
||||
} };
|
||||
// Autogenerated by _dumprawrat in support.cpp
|
||||
inline const NUMBER init_p_rat_max_exp = {
|
||||
1,
|
||||
inline const NUMBER init_p_rat_max_exp = { 1,
|
||||
1,
|
||||
0,
|
||||
{ 100000,}
|
||||
};
|
||||
inline const NUMBER init_q_rat_max_exp = {
|
||||
1,
|
||||
{
|
||||
100000,
|
||||
} };
|
||||
inline const NUMBER init_q_rat_max_exp = { 1,
|
||||
1,
|
||||
0,
|
||||
{ 1,}
|
||||
};
|
||||
{
|
||||
1,
|
||||
} };
|
||||
// Autogenerated by _dumprawrat in support.cpp
|
||||
inline const NUMBER init_p_rat_min_exp = {
|
||||
-1,
|
||||
inline const NUMBER init_p_rat_min_exp = { -1,
|
||||
1,
|
||||
0,
|
||||
{ 100000,}
|
||||
};
|
||||
inline const NUMBER init_q_rat_min_exp = {
|
||||
1,
|
||||
{
|
||||
100000,
|
||||
} };
|
||||
inline const NUMBER init_q_rat_min_exp = { 1,
|
||||
1,
|
||||
0,
|
||||
{ 1,}
|
||||
};
|
||||
{
|
||||
1,
|
||||
} };
|
||||
|
||||
// Autogenerated by _dumprawrat in support.cpp
|
||||
inline const NUMBER init_p_rat_max_fact = {
|
||||
1,
|
||||
inline const NUMBER init_p_rat_max_fact = { 1,
|
||||
1,
|
||||
0,
|
||||
{ 3249, }
|
||||
};
|
||||
inline const NUMBER init_q_rat_max_fact = {
|
||||
1,
|
||||
{
|
||||
3249,
|
||||
} };
|
||||
inline const NUMBER init_q_rat_max_fact = { 1,
|
||||
1,
|
||||
0,
|
||||
{ 1, }
|
||||
};
|
||||
{
|
||||
1,
|
||||
} };
|
||||
|
||||
// Autogenerated by _dumprawrat in support.cpp
|
||||
inline const NUMBER init_p_rat_min_fact = {
|
||||
-1,
|
||||
inline const NUMBER init_p_rat_min_fact = { -1,
|
||||
1,
|
||||
0,
|
||||
{ 1000, }
|
||||
};
|
||||
inline const NUMBER init_q_rat_min_fact = {
|
||||
1,
|
||||
{
|
||||
1000,
|
||||
} };
|
||||
inline const NUMBER init_q_rat_min_fact = { 1,
|
||||
1,
|
||||
0,
|
||||
{ 1, }
|
||||
};
|
||||
{
|
||||
1,
|
||||
} };
|
||||
|
|
|
@ -31,14 +31,16 @@ static constexpr uint32_t BASEX = 0x80000000; // Internal radix used in calculat
|
|||
typedef uint32_t MANTTYPE;
|
||||
typedef uint64_t TWO_MANTTYPE;
|
||||
|
||||
enum eNUMOBJ_FMT {
|
||||
enum eNUMOBJ_FMT
|
||||
{
|
||||
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
|
||||
|
||||
};
|
||||
|
||||
enum eANGLE_TYPE {
|
||||
enum eANGLE_TYPE
|
||||
{
|
||||
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
|
||||
|
@ -69,7 +71,6 @@ typedef struct _number
|
|||
} NUMBER, *PNUMBER, **PPNUMBER;
|
||||
#pragma warning(pop)
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// RAT type is a representation radix on 2 NUMBER types.
|
||||
|
@ -135,10 +136,17 @@ extern PRAT rat_max_i32;
|
|||
extern PRAT rat_min_i32;
|
||||
|
||||
// DUPNUM Duplicates a number taking care of allocation and internals
|
||||
#define DUPNUM(a,b) destroynum(a);createnum( a, (b)->cdigit );_dupnum(a, b);
|
||||
#define DUPNUM(a, b) \
|
||||
destroynum(a); \
|
||||
createnum(a, (b)->cdigit); \
|
||||
_dupnum(a, b);
|
||||
|
||||
// DUPRAT Duplicates a rational taking care of allocation and internals
|
||||
#define DUPRAT(a,b) destroyrat(a);createrat(a);DUPNUM((a)->pp,(b)->pp);DUPNUM((a)->pq,(b)->pq);
|
||||
#define DUPRAT(a, b) \
|
||||
destroyrat(a); \
|
||||
createrat(a); \
|
||||
DUPNUM((a)->pp, (b)->pp); \
|
||||
DUPNUM((a)->pq, (b)->pq);
|
||||
|
||||
// LOG*RADIX calculates the integral portion of the log of a number in
|
||||
// the base currently being used, only accurate to within g_ratio
|
||||
|
@ -163,7 +171,8 @@ extern PRAT rat_min_i32;
|
|||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#define createrat(y) (y)=_createrat(); \
|
||||
#define createrat(y) \
|
||||
(y) = _createrat(); \
|
||||
{ \
|
||||
std::wstringstream outputString; \
|
||||
outputString << "createrat " << y << " " << #y << " file= " << __FILE__ << ", line= " << __LINE__ << "\n"; \
|
||||
|
@ -176,7 +185,8 @@ extern PRAT rat_min_i32;
|
|||
OutputDebugString(outputString.str().c_str()); \
|
||||
} \
|
||||
_destroyrat(x), (x) = nullptr
|
||||
#define createnum(y,x) (y)=_createnum(x); \
|
||||
#define createnum(y, x) \
|
||||
(y) = _createnum(x); \
|
||||
{ \
|
||||
std::wstringstream outputString; \
|
||||
outputString << "createnum " << y << " " << #y << " file= " << __FILE__ << ", line= " << __LINE__ << "\n"; \
|
||||
|
@ -204,17 +214,22 @@ _destroynum(x),(x)=nullptr
|
|||
//-----------------------------------------------------------------------------
|
||||
|
||||
// RENORMALIZE, gets the exponents non-negative.
|
||||
#define RENORMALIZE(x) if ( (x)->pp->exp < 0 ) { \
|
||||
#define RENORMALIZE(x) \
|
||||
if ((x)->pp->exp < 0) \
|
||||
{ \
|
||||
(x)->pq->exp -= (x)->pp->exp; \
|
||||
(x)->pp->exp = 0; \
|
||||
} \
|
||||
if ( (x)->pq->exp < 0 ) { \
|
||||
if ((x)->pq->exp < 0) \
|
||||
{ \
|
||||
(x)->pp->exp -= (x)->pq->exp; \
|
||||
(x)->pq->exp = 0; \
|
||||
}
|
||||
|
||||
// TRIMNUM ASSUMES the number is in radix form NOT INTERNAL BASEX!!!
|
||||
#define TRIMNUM(x, precision) if ( !g_ftrueinfinite ) { \
|
||||
#define TRIMNUM(x, precision) \
|
||||
if (!g_ftrueinfinite) \
|
||||
{ \
|
||||
int32_t trim = (x)->cdigit - precision - g_ratio; \
|
||||
if (trim > 1) \
|
||||
{ \
|
||||
|
@ -224,7 +239,9 @@ memmove( (x)->mant, &((x)->mant[trim]), sizeof(MANTTYPE)*((x)->cdigit-trim) ); \
|
|||
} \
|
||||
}
|
||||
// TRIMTOP ASSUMES the number is in INTERNAL BASEX!!!
|
||||
#define TRIMTOP(x, precision) if ( !g_ftrueinfinite ) { \
|
||||
#define TRIMTOP(x, precision) \
|
||||
if (!g_ftrueinfinite) \
|
||||
{ \
|
||||
int32_t trim = (x)->pp->cdigit - (precision / g_ratio) - 2; \
|
||||
if (trim > 1) \
|
||||
{ \
|
||||
|
@ -246,7 +263,8 @@ memmove( (x)->pp->mant, &((x)->pp->mant[trim]), sizeof(MANTTYPE)*((x)->pp->cdigi
|
|||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#define CREATETAYLOR() PRAT xx=nullptr;\
|
||||
#define CREATETAYLOR() \
|
||||
PRAT xx = nullptr; \
|
||||
PNUMBER n2 = nullptr; \
|
||||
PRAT pret = nullptr; \
|
||||
PRAT thisterm = nullptr; \
|
||||
|
@ -256,7 +274,8 @@ memmove( (x)->pp->mant, &((x)->pp->mant[trim]), sizeof(MANTTYPE)*((x)->pp->cdigi
|
|||
pret->pp = i32tonum(0L, BASEX); \
|
||||
pret->pq = i32tonum(0L, BASEX);
|
||||
|
||||
#define DESTROYTAYLOR() destroynum( n2 ); \
|
||||
#define DESTROYTAYLOR() \
|
||||
destroynum(n2); \
|
||||
destroyrat(xx); \
|
||||
destroyrat(thisterm); \
|
||||
destroyrat(*px); \
|
||||
|
@ -265,7 +284,8 @@ memmove( (x)->pp->mant, &((x)->pp->mant[trim]), sizeof(MANTTYPE)*((x)->pp->cdigi
|
|||
|
||||
// INC(a) is the rational equivalent of a++
|
||||
// Check to see if we can avoid doing this the hard way.
|
||||
#define INC(a) if ( (a)->mant[0] < BASEX - 1 ) \
|
||||
#define INC(a) \
|
||||
if ((a)->mant[0] < BASEX - 1) \
|
||||
{ \
|
||||
(a)->mant[0]++; \
|
||||
} \
|
||||
|
@ -289,7 +309,9 @@ memmove( (x)->pp->mant, &((x)->pp->mant[trim]), sizeof(MANTTYPE)*((x)->pp->cdigi
|
|||
// thisterm *= p
|
||||
// d <d is usually an expansion of operations to get thisterm updated.>
|
||||
// pret += thisterm
|
||||
#define NEXTTERM(p,d,precision) mulrat(&thisterm,p,precision);d addrat( &pret, thisterm, precision )
|
||||
#define NEXTTERM(p, d, precision) \
|
||||
mulrat(&thisterm, p, precision); \
|
||||
d addrat(&pret, thisterm, precision)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
|
@ -334,10 +356,14 @@ uint64_t rattoUi64(_In_ PRAT prat, uint32_t radix, int32_t precision);
|
|||
extern PNUMBER _createnum(_In_ uint32_t size); // returns an empty number structure with size digits
|
||||
extern PNUMBER nRadixxtonum(_In_ PNUMBER a, uint32_t radix, int32_t precision);
|
||||
extern PNUMBER gcd(_In_ PNUMBER a, _In_ PNUMBER b);
|
||||
extern PNUMBER StringToNumber(std::wstring_view numberString, uint32_t radix, int32_t precision); // takes a text representation of a number and returns a number.
|
||||
extern PNUMBER StringToNumber(
|
||||
std::wstring_view numberString,
|
||||
uint32_t radix,
|
||||
int32_t precision); // takes a text representation of a number and returns a number.
|
||||
|
||||
// takes a text representation of a number as a mantissa with sign and an exponent with sign.
|
||||
extern PRAT StringToRat(bool mantissaIsNegative, std::wstring_view mantissa, bool exponentIsNegative, std::wstring_view exponent, uint32_t radix, int32_t precision);
|
||||
extern PRAT
|
||||
StringToRat(bool mantissaIsNegative, std::wstring_view mantissa, bool exponentIsNegative, std::wstring_view exponent, uint32_t radix, int32_t precision);
|
||||
|
||||
extern PNUMBER i32factnum(int32_t ini32, uint32_t radix);
|
||||
extern PNUMBER i32prodnum(int32_t start, int32_t stop, uint32_t radix);
|
||||
|
|
|
@ -32,23 +32,34 @@ static int cbitsofprecision = 0;
|
|||
#define READRAWRAT(v)
|
||||
#define READRAWNUM(v)
|
||||
#define DUMPRAWRAT(v) _dumprawrat(#v, v, wcout)
|
||||
#define DUMPRAWNUM(v) fprintf( stderr, \
|
||||
"// Autogenerated by _dumprawrat in support.cpp\n" ); \
|
||||
#define DUMPRAWNUM(v) \
|
||||
fprintf(stderr, "// Autogenerated by _dumprawrat in support.cpp\n"); \
|
||||
fprintf(stderr, "inline const NUMBER init_" #v "= {\n"); \
|
||||
_dumprawnum(v, wcout); \
|
||||
fprintf(stderr, "};\n")
|
||||
|
||||
|
||||
#else
|
||||
|
||||
#define DUMPRAWRAT(v)
|
||||
#define DUMPRAWNUM(v)
|
||||
#define READRAWRAT(v) createrat(v); DUPNUM((v)->pp,(&(init_p_##v))); \
|
||||
#define READRAWRAT(v) \
|
||||
createrat(v); \
|
||||
DUPNUM((v)->pp, (&(init_p_##v))); \
|
||||
DUPNUM((v)->pq, (&(init_q_##v)));
|
||||
#define READRAWNUM(v) DUPNUM(v, (&(init_##v)))
|
||||
|
||||
#define INIT_AND_DUMP_RAW_NUM_IF_NULL(r, v) if (r == nullptr) { r = i32tonum(v, BASEX); DUMPRAWNUM(v); }
|
||||
#define INIT_AND_DUMP_RAW_RAT_IF_NULL(r, v) if (r == nullptr) { r = i32torat(v); DUMPRAWRAT(v); }
|
||||
#define INIT_AND_DUMP_RAW_NUM_IF_NULL(r, v) \
|
||||
if (r == nullptr) \
|
||||
{ \
|
||||
r = i32tonum(v, BASEX); \
|
||||
DUMPRAWNUM(v); \
|
||||
}
|
||||
#define INIT_AND_DUMP_RAW_RAT_IF_NULL(r, v) \
|
||||
if (r == nullptr) \
|
||||
{ \
|
||||
r = i32torat(v); \
|
||||
DUMPRAWRAT(v); \
|
||||
}
|
||||
|
||||
static constexpr int RATIO_FOR_DECIMAL = 9;
|
||||
static constexpr int DECIMAL = 10;
|
||||
|
@ -253,7 +264,6 @@ void ChangeConstants(uint32_t radix, int32_t precision)
|
|||
lograt(&ln_two, extraPrecision);
|
||||
DUMPRAWRAT(ln_two);
|
||||
|
||||
|
||||
destroyrat(rad_to_deg);
|
||||
rad_to_deg = i32torat(180L);
|
||||
divrat(&rad_to_deg, pi, extraPrecision);
|
||||
|
@ -273,7 +283,6 @@ void ChangeConstants(uint32_t radix, int32_t precision)
|
|||
DUPRAT(rat_negsmallest, rat_smallest);
|
||||
rat_negsmallest->pp->sign = -1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
@ -355,7 +364,6 @@ bool rat_ge( PRAT a, PRAT b, int32_t precision)
|
|||
return (bret);
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// FUNCTION: rat_gt
|
||||
|
@ -394,7 +402,6 @@ bool rat_gt( PRAT a, PRAT b, int32_t precision)
|
|||
bool rat_le(PRAT a, PRAT b, int32_t precision)
|
||||
|
||||
{
|
||||
|
||||
PRAT rattmp = nullptr;
|
||||
DUPRAT(rattmp, a);
|
||||
b->pp->sign *= -1;
|
||||
|
@ -405,7 +412,6 @@ bool rat_le( PRAT a, PRAT b, int32_t precision)
|
|||
return (bret);
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// FUNCTION: rat_lt
|
||||
|
@ -430,7 +436,6 @@ bool rat_lt( PRAT a, PRAT b, int32_t precision)
|
|||
return (bret);
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// FUNCTION: rat_neq
|
||||
|
@ -442,7 +447,6 @@ bool rat_lt( PRAT a, PRAT b, int32_t precision)
|
|||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
|
||||
bool rat_neq(PRAT a, PRAT b, int32_t precision)
|
||||
|
||||
{
|
||||
|
@ -473,8 +477,7 @@ void scale( PRAT *px, PRAT scalefact, uint32_t radix, int32_t precision )
|
|||
|
||||
// Logscale is a quick way to tell how much extra precision is needed for
|
||||
// scaling by scalefact.
|
||||
int32_t logscale = g_ratio * ( (pret->pp->cdigit+pret->pp->exp) -
|
||||
(pret->pq->cdigit+pret->pq->exp) );
|
||||
int32_t logscale = g_ratio * ((pret->pp->cdigit + pret->pp->exp) - (pret->pq->cdigit + pret->pq->exp));
|
||||
if (logscale > 0)
|
||||
{
|
||||
precision += logscale;
|
||||
|
@ -508,8 +511,7 @@ void scale2pi( PRAT *px, uint32_t radix, int32_t precision )
|
|||
|
||||
// Logscale is a quick way to tell how much extra precision is needed for
|
||||
// scaling by 2 pi.
|
||||
int32_t logscale = g_ratio * ( (pret->pp->cdigit+pret->pp->exp) -
|
||||
(pret->pq->cdigit+pret->pq->exp) );
|
||||
int32_t logscale = g_ratio * ((pret->pp->cdigit + pret->pp->exp) - (pret->pq->cdigit + pret->pq->exp));
|
||||
if (logscale > 0)
|
||||
{
|
||||
precision += logscale;
|
||||
|
|
|
@ -16,8 +16,6 @@
|
|||
|
||||
#include "ratpak.h"
|
||||
|
||||
|
||||
|
||||
void scalerat(_Inout_ PRAT* pa, ANGLE_TYPE angletype, uint32_t radix, int32_t precision)
|
||||
{
|
||||
switch (angletype)
|
||||
|
@ -34,7 +32,6 @@ void scalerat( _Inout_ PRAT *pa, ANGLE_TYPE angletype, uint32_t radix, int32_t p
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// FUNCTION: sinrat, _sinrat
|
||||
|
@ -66,7 +63,6 @@ void scalerat( _Inout_ PRAT *pa, ANGLE_TYPE angletype, uint32_t radix, int32_t p
|
|||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
void _sinrat(PRAT* px, int32_t precision)
|
||||
|
||||
{
|
||||
|
@ -78,7 +74,8 @@ void _sinrat( PRAT *px, int32_t precision)
|
|||
DUPNUM(n2, num_one);
|
||||
xx->pp->sign *= -1;
|
||||
|
||||
do {
|
||||
do
|
||||
{
|
||||
NEXTTERM(xx, INC(n2) DIVNUM(n2) INC(n2) DIVNUM(n2), precision);
|
||||
} while (!SMALL_ENOUGH_RAT(thisterm, precision));
|
||||
|
||||
|
@ -158,7 +155,6 @@ void sinanglerat( _Inout_ PRAT *pa, ANGLE_TYPE angletype, uint32_t radix, int32_
|
|||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
void _cosrat(PRAT* px, uint32_t radix, int32_t precision)
|
||||
|
||||
{
|
||||
|
@ -175,7 +171,8 @@ void _cosrat( PRAT *px, uint32_t radix, int32_t precision)
|
|||
n2 = i32tonum(0L, radix);
|
||||
xx->pp->sign *= -1;
|
||||
|
||||
do {
|
||||
do
|
||||
{
|
||||
NEXTTERM(xx, INC(n2) DIVNUM(n2) INC(n2) DIVNUM(n2), precision);
|
||||
} while (!SMALL_ENOUGH_RAT(thisterm, precision));
|
||||
|
||||
|
@ -242,7 +239,6 @@ void cosanglerat( _Inout_ PRAT *pa, ANGLE_TYPE angletype, uint32_t radix, int32_
|
|||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
void _tanrat(PRAT* px, uint32_t radix, int32_t precision)
|
||||
|
||||
{
|
||||
|
@ -259,7 +255,6 @@ void _tanrat( PRAT *px, uint32_t radix, int32_t precision)
|
|||
divrat(px, ptmp, precision);
|
||||
|
||||
destroyrat(ptmp);
|
||||
|
||||
}
|
||||
|
||||
void tanrat(PRAT* px, uint32_t radix, int32_t precision)
|
||||
|
@ -293,4 +288,3 @@ void tananglerat( _Inout_ PRAT *pa, ANGLE_TYPE angletype, uint32_t radix, int32_
|
|||
}
|
||||
_tanrat(pa, radix, precision);
|
||||
}
|
||||
|
||||
|
|
|
@ -16,8 +16,6 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
#include "ratpak.h"
|
||||
|
||||
|
||||
|
||||
bool IsValidForHypFunc(PRAT px, int32_t precision)
|
||||
{
|
||||
PRAT ptmp = nullptr;
|
||||
|
@ -31,7 +29,6 @@ bool IsValidForHypFunc(PRAT px, int32_t precision)
|
|||
}
|
||||
destroyrat(ptmp);
|
||||
return bRet;
|
||||
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -67,7 +64,6 @@ bool IsValidForHypFunc(PRAT px, int32_t precision)
|
|||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
void _sinhrat(PRAT* px, int32_t precision)
|
||||
|
||||
{
|
||||
|
@ -84,7 +80,8 @@ void _sinhrat( PRAT *px, int32_t precision)
|
|||
|
||||
DUPNUM(n2, num_one);
|
||||
|
||||
do {
|
||||
do
|
||||
{
|
||||
NEXTTERM(xx, INC(n2) DIVNUM(n2) INC(n2) DIVNUM(n2), precision);
|
||||
} while (!SMALL_ENOUGH_RAT(thisterm, precision));
|
||||
|
||||
|
@ -146,7 +143,6 @@ void sinhrat( PRAT *px, uint32_t radix, int32_t precision)
|
|||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
void _coshrat(PRAT* px, uint32_t radix, int32_t precision)
|
||||
|
||||
{
|
||||
|
@ -165,7 +161,8 @@ void _coshrat( PRAT *px, uint32_t radix, int32_t precision)
|
|||
|
||||
n2 = i32tonum(0L, radix);
|
||||
|
||||
do {
|
||||
do
|
||||
{
|
||||
NEXTTERM(xx, INC(n2) DIVNUM(n2) INC(n2) DIVNUM(n2), precision);
|
||||
} while (!SMALL_ENOUGH_RAT(thisterm, precision));
|
||||
|
||||
|
@ -226,5 +223,4 @@ void tanhrat( PRAT *px, uint32_t radix, int32_t precision)
|
|||
mulnumx(&((*px)->pq), ptmp->pp);
|
||||
|
||||
destroyrat(ptmp);
|
||||
|
||||
}
|
||||
|
|
|
@ -11,8 +11,6 @@ using namespace concurrency;
|
|||
using namespace std;
|
||||
using namespace UnitConversionManager;
|
||||
|
||||
static constexpr uint32_t EXPECTEDSERIALIZEDTOKENCOUNT = 7;
|
||||
static constexpr uint32_t EXPECTEDSERIALIZEDCONVERSIONDATATOKENCOUNT = 3;
|
||||
static constexpr uint32_t EXPECTEDSERIALIZEDCATEGORYTOKENCOUNT = 3;
|
||||
static constexpr uint32_t EXPECTEDSERIALIZEDUNITTOKENCOUNT = 6;
|
||||
static constexpr uint32_t EXPECTEDSTATEDATATOKENCOUNT = 5;
|
||||
|
@ -34,8 +32,8 @@ unordered_map<wstring, wchar_t> unquoteConversions;
|
|||
/// Constructor, sets up all the variables and requires a configLoader
|
||||
/// </summary>
|
||||
/// <param name="dataLoader">An instance of the IConverterDataLoader interface which we use to read in category/unit names and conversion data</param>
|
||||
UnitConverter::UnitConverter(_In_ const shared_ptr<IConverterDataLoader>& dataLoader) :
|
||||
UnitConverter::UnitConverter(dataLoader, nullptr)
|
||||
UnitConverter::UnitConverter(_In_ const shared_ptr<IConverterDataLoader>& dataLoader)
|
||||
: UnitConverter::UnitConverter(dataLoader, nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -217,22 +215,12 @@ vector<wstring> UnitConverter::StringToVector(const wstring& w, const wchar_t *
|
|||
}
|
||||
return serializedTokens;
|
||||
}
|
||||
|
||||
Category UnitConverter::StringToCategory(const wstring& w)
|
||||
{
|
||||
vector<wstring> tokenList = StringToVector(w, L";");
|
||||
assert(tokenList.size() == EXPECTEDSERIALIZEDCATEGORYTOKENCOUNT);
|
||||
Category serializedCategory;
|
||||
serializedCategory.id = _wtoi(Unquote(tokenList[0]).c_str());
|
||||
serializedCategory.supportsNegative = (tokenList[1].compare(L"1") == 0);
|
||||
serializedCategory.name = Unquote(tokenList[2]);
|
||||
return serializedCategory;
|
||||
}
|
||||
|
||||
wstring UnitConverter::UnitToString(const Unit& u, const wchar_t* delimiter)
|
||||
{
|
||||
wstringstream out(wstringstream::out);
|
||||
out << Quote(std::to_wstring(u.id)) << delimiter << Quote(u.name) << delimiter << Quote(u.abbreviation) << delimiter << std::to_wstring(u.isConversionSource) << delimiter << std::to_wstring(u.isConversionTarget) << delimiter << std::to_wstring(u.isWhimsical) << delimiter;
|
||||
out << Quote(std::to_wstring(u.id)) << delimiter << Quote(u.name) << delimiter << Quote(u.abbreviation) << delimiter
|
||||
<< std::to_wstring(u.isConversionSource) << delimiter << std::to_wstring(u.isConversionTarget) << delimiter << std::to_wstring(u.isWhimsical)
|
||||
<< delimiter;
|
||||
return out.str();
|
||||
}
|
||||
|
||||
|
@ -251,147 +239,15 @@ Unit UnitConverter::StringToUnit(const wstring& w)
|
|||
return serializedUnit;
|
||||
}
|
||||
|
||||
ConversionData UnitConverter::StringToConversionData(const wstring& w)
|
||||
Category UnitConverter::StringToCategory(const wstring& w)
|
||||
{
|
||||
vector<wstring> tokenList = StringToVector(w, L";");
|
||||
assert(tokenList.size() == EXPECTEDSERIALIZEDCONVERSIONDATATOKENCOUNT);
|
||||
ConversionData serializedConversionData;
|
||||
serializedConversionData.ratio = stod(Unquote(tokenList[0]).c_str());
|
||||
serializedConversionData.offset = stod(Unquote(tokenList[1]).c_str());
|
||||
serializedConversionData.offsetFirst = (tokenList[2].compare(L"1") == 0);
|
||||
return serializedConversionData;
|
||||
}
|
||||
|
||||
wstring UnitConverter::ConversionDataToString(ConversionData d, const wchar_t * delimiter)
|
||||
{
|
||||
wstringstream out(wstringstream::out);
|
||||
out.precision(32);
|
||||
out << fixed << d.ratio;
|
||||
wstring ratio = out.str();
|
||||
out.str(L"");
|
||||
out << fixed << d.offset;
|
||||
wstring offset = out.str();
|
||||
out.str(L"");
|
||||
TrimString(ratio);
|
||||
TrimString(offset);
|
||||
out << Quote(ratio) << delimiter << Quote(offset) << delimiter << std::to_wstring(d.offsetFirst) << delimiter;
|
||||
return out.str();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Serializes the data in the converter and returns it as a string
|
||||
/// </summary>
|
||||
wstring UnitConverter::Serialize()
|
||||
{
|
||||
if (!CheckLoad())
|
||||
{
|
||||
return wstring();
|
||||
}
|
||||
|
||||
wstringstream out(wstringstream::out);
|
||||
const wchar_t * delimiter = L";";
|
||||
|
||||
out << UnitToString(m_fromType, delimiter) << "|";
|
||||
out << UnitToString(m_toType, delimiter) << "|";
|
||||
out << CategoryToString(m_currentCategory, delimiter) << "|";
|
||||
out << std::to_wstring(m_currentHasDecimal) << delimiter << std::to_wstring(m_returnHasDecimal) << delimiter << std::to_wstring(m_switchedActive) << delimiter;
|
||||
out << m_currentDisplay << delimiter << m_returnDisplay << delimiter << "|";
|
||||
wstringstream categoryString(wstringstream::out);
|
||||
wstringstream categoryToUnitString(wstringstream::out);
|
||||
wstringstream unitToUnitToDoubleString(wstringstream::out);
|
||||
for (const Category& c : m_categories)
|
||||
{
|
||||
categoryString << CategoryToString(c, delimiter) << ",";
|
||||
}
|
||||
|
||||
for (const auto& cur : m_categoryToUnits)
|
||||
{
|
||||
categoryToUnitString << CategoryToString(cur.first, delimiter) << "[";
|
||||
for (const Unit& u : cur.second)
|
||||
{
|
||||
categoryToUnitString << UnitToString(u, delimiter) << ",";
|
||||
}
|
||||
categoryToUnitString << "[" << "]";
|
||||
}
|
||||
|
||||
for (const auto& cur : m_ratioMap)
|
||||
{
|
||||
unitToUnitToDoubleString << UnitToString(cur.first, delimiter) << "[";
|
||||
for (const auto& curConversion : cur.second)
|
||||
{
|
||||
unitToUnitToDoubleString << UnitToString(curConversion.first, delimiter) << ":";
|
||||
unitToUnitToDoubleString << ConversionDataToString(curConversion.second, delimiter) << ":,";
|
||||
}
|
||||
unitToUnitToDoubleString << "[" << "]";
|
||||
}
|
||||
|
||||
out << categoryString.str() << "|";
|
||||
out << categoryToUnitString.str() << "|";
|
||||
out << unitToUnitToDoubleString.str() << "|";
|
||||
wstring test = out.str();
|
||||
return test;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// De-Serializes the data in the converter from a string
|
||||
/// </summary>
|
||||
/// <param name="serializedData">wstring holding the serialized data. If it does not have expected number of parameters, we will ignore it</param>
|
||||
void UnitConverter::DeSerialize(const wstring& serializedData)
|
||||
{
|
||||
ClearValues();
|
||||
ResetCategoriesAndRatios();
|
||||
|
||||
if (serializedData.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
vector<wstring> outerTokens = StringToVector(serializedData, L"|");
|
||||
assert(outerTokens.size() == EXPECTEDSERIALIZEDTOKENCOUNT);
|
||||
m_fromType = StringToUnit(outerTokens[0]);
|
||||
m_toType = StringToUnit(outerTokens[1]);
|
||||
m_currentCategory = StringToCategory(outerTokens[2]);
|
||||
vector<wstring> stateDataTokens = StringToVector(outerTokens[3], L";");
|
||||
assert(stateDataTokens.size() == EXPECTEDSTATEDATATOKENCOUNT);
|
||||
m_currentHasDecimal = (stateDataTokens[0].compare(L"1") == 0);
|
||||
m_returnHasDecimal = (stateDataTokens[1].compare(L"1") == 0);
|
||||
m_switchedActive = (stateDataTokens[2].compare(L"1") == 0);
|
||||
m_currentDisplay = stateDataTokens[3];
|
||||
m_returnDisplay = stateDataTokens[4];
|
||||
vector<wstring> categoryListTokens = StringToVector(outerTokens[4], L",");
|
||||
for (wstring token : categoryListTokens)
|
||||
{
|
||||
m_categories.push_back(StringToCategory(token));
|
||||
}
|
||||
vector<wstring> unitVectorTokens = StringToVector(outerTokens[5], L"]");
|
||||
for (wstring unitVector : unitVectorTokens)
|
||||
{
|
||||
vector<wstring> mapcomponents = StringToVector(unitVector, L"[");
|
||||
assert(mapcomponents.size() == EXPECTEDMAPCOMPONENTTOKENCOUNT);
|
||||
Category key = StringToCategory(mapcomponents[0]);
|
||||
vector<wstring> units = StringToVector(mapcomponents[1], L",");
|
||||
for (wstring unit : units)
|
||||
{
|
||||
m_categoryToUnits[key].push_back(StringToUnit(unit));
|
||||
}
|
||||
}
|
||||
vector<wstring> ratioMapTokens = StringToVector(outerTokens[6], L"]");
|
||||
for (wstring token : ratioMapTokens)
|
||||
{
|
||||
vector<wstring> ratioMapComponentTokens = StringToVector(token, L"[");
|
||||
assert(ratioMapComponentTokens.size() == EXPECTEDMAPCOMPONENTTOKENCOUNT);
|
||||
Unit key = StringToUnit(ratioMapComponentTokens[0]);
|
||||
vector<wstring> ratioMapList = StringToVector(ratioMapComponentTokens[1], L",");
|
||||
for (wstring subtoken : ratioMapList)
|
||||
{
|
||||
vector<wstring> ratioMapSubComponentTokens = StringToVector(subtoken, L":");
|
||||
assert(ratioMapSubComponentTokens.size() == EXPECTEDMAPCOMPONENTTOKENCOUNT);
|
||||
Unit subkey = StringToUnit(ratioMapSubComponentTokens[0]);
|
||||
ConversionData conversion = StringToConversionData(ratioMapSubComponentTokens[1]);
|
||||
m_ratioMap[key][subkey] = conversion;
|
||||
}
|
||||
}
|
||||
UpdateViewModel();
|
||||
assert(tokenList.size() == EXPECTEDSERIALIZEDCATEGORYTOKENCOUNT);
|
||||
Category serializedCategory;
|
||||
serializedCategory.id = _wtoi(Unquote(tokenList[0]).c_str());
|
||||
serializedCategory.supportsNegative = (tokenList[1].compare(L"1") == 0);
|
||||
serializedCategory.name = Unquote(tokenList[2]);
|
||||
return serializedCategory;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -429,7 +285,6 @@ void UnitConverter::RestoreUserPreferences(const wstring& userPreferences)
|
|||
m_toType = toType;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -529,7 +384,8 @@ void UnitConverter::SendCommand(Command command)
|
|||
clearFront = true;
|
||||
}
|
||||
bool clearBack = false;
|
||||
if ((m_currentHasDecimal && m_currentDisplay.size() - 1 >= MAXIMUMDIGITSALLOWED) || (!m_currentHasDecimal && m_currentDisplay.size() >= MAXIMUMDIGITSALLOWED))
|
||||
if ((m_currentHasDecimal && m_currentDisplay.size() - 1 >= MAXIMUMDIGITSALLOWED)
|
||||
|| (!m_currentHasDecimal && m_currentDisplay.size() >= MAXIMUMDIGITSALLOWED))
|
||||
{
|
||||
clearBack = true;
|
||||
}
|
||||
|
@ -643,7 +499,6 @@ void UnitConverter::SendCommand(Command command)
|
|||
break;
|
||||
}
|
||||
|
||||
|
||||
if (clearFront)
|
||||
{
|
||||
m_currentDisplay.erase(0, 1);
|
||||
|
@ -684,8 +539,7 @@ void UnitConverter::SetViewModelCurrencyCallback(_In_ const shared_ptr<IViewMode
|
|||
task<pair<bool, wstring>> UnitConverter::RefreshCurrencyRatios()
|
||||
{
|
||||
shared_ptr<ICurrencyConverterDataLoader> currencyDataLoader = GetCurrencyConverterDataLoader();
|
||||
return create_task([this, currencyDataLoader]()
|
||||
{
|
||||
return create_task([this, currencyDataLoader]() {
|
||||
if (currencyDataLoader != nullptr)
|
||||
{
|
||||
return currencyDataLoader->TryLoadDataFromWebOverrideAsync();
|
||||
|
@ -694,8 +548,9 @@ task<pair<bool, wstring>> UnitConverter::RefreshCurrencyRatios()
|
|||
{
|
||||
return task_from_result(false);
|
||||
}
|
||||
}).then([this, currencyDataLoader](bool didLoad)
|
||||
{
|
||||
})
|
||||
.then(
|
||||
[this, currencyDataLoader](bool didLoad) {
|
||||
wstring timestamp = L"";
|
||||
if (currencyDataLoader != nullptr)
|
||||
{
|
||||
|
@ -703,7 +558,8 @@ task<pair<bool, wstring>> UnitConverter::RefreshCurrencyRatios()
|
|||
}
|
||||
|
||||
return make_pair(didLoad, timestamp);
|
||||
}, task_continuation_context::use_default());
|
||||
},
|
||||
task_continuation_context::use_default());
|
||||
}
|
||||
|
||||
shared_ptr<ICurrencyConverterDataLoader> UnitConverter::GetCurrencyConverterDataLoader()
|
||||
|
@ -760,9 +616,7 @@ vector<tuple<wstring, Unit>> UnitConverter::CalculateSuggested()
|
|||
}
|
||||
|
||||
// Sort the resulting list by absolute magnitude, breaking ties by choosing the positive value
|
||||
sort(intermediateVector.begin(), intermediateVector.end(), []
|
||||
(SuggestedValueIntermediate first, SuggestedValueIntermediate second)
|
||||
{
|
||||
sort(intermediateVector.begin(), intermediateVector.end(), [](SuggestedValueIntermediate first, SuggestedValueIntermediate second) {
|
||||
if (abs(first.magnitude) == abs(second.magnitude))
|
||||
{
|
||||
return first.magnitude > second.magnitude;
|
||||
|
@ -798,9 +652,7 @@ vector<tuple<wstring, Unit>> UnitConverter::CalculateSuggested()
|
|||
|
||||
// The Whimsicals are determined differently
|
||||
// Sort the resulting list by absolute magnitude, breaking ties by choosing the positive value
|
||||
sort(intermediateWhimsicalVector.begin(), intermediateWhimsicalVector.end(), []
|
||||
(SuggestedValueIntermediate first, SuggestedValueIntermediate second)
|
||||
{
|
||||
sort(intermediateWhimsicalVector.begin(), intermediateWhimsicalVector.end(), [](SuggestedValueIntermediate first, SuggestedValueIntermediate second) {
|
||||
if (abs(first.magnitude) == abs(second.magnitude))
|
||||
{
|
||||
return first.magnitude > second.magnitude;
|
||||
|
@ -922,7 +774,6 @@ shared_ptr<IConverterDataLoader> UnitConverter::GetDataLoaderForCategory(const C
|
|||
/// </summary>
|
||||
void UnitConverter::InitializeSelectedUnits()
|
||||
{
|
||||
|
||||
if (m_categoryToUnits.empty())
|
||||
{
|
||||
return;
|
||||
|
|
|
@ -15,14 +15,33 @@ namespace UnitConversionManager
|
|||
|
||||
struct Unit
|
||||
{
|
||||
Unit(){}
|
||||
Unit()
|
||||
{
|
||||
}
|
||||
Unit(int id, std::wstring name, std::wstring abbreviation, bool isConversionSource, bool isConversionTarget, bool isWhimsical)
|
||||
: id(id), name(name), accessibleName(name), abbreviation(abbreviation), isConversionSource(isConversionSource), isConversionTarget(isConversionTarget), isWhimsical(isWhimsical)
|
||||
: id(id)
|
||||
, name(name)
|
||||
, accessibleName(name)
|
||||
, abbreviation(abbreviation)
|
||||
, isConversionSource(isConversionSource)
|
||||
, isConversionTarget(isConversionTarget)
|
||||
, isWhimsical(isWhimsical)
|
||||
{
|
||||
}
|
||||
|
||||
Unit(int id, std::wstring currencyName, std::wstring countryName, std::wstring abbreviation, bool isRtlLanguage, bool isConversionSource, bool isConversionTarget)
|
||||
: id(id), abbreviation(abbreviation), isConversionSource(isConversionSource), isConversionTarget(isConversionTarget), isWhimsical(false)
|
||||
Unit(
|
||||
int id,
|
||||
std::wstring currencyName,
|
||||
std::wstring countryName,
|
||||
std::wstring abbreviation,
|
||||
bool isRtlLanguage,
|
||||
bool isConversionSource,
|
||||
bool isConversionTarget)
|
||||
: id(id)
|
||||
, abbreviation(abbreviation)
|
||||
, isConversionSource(isConversionSource)
|
||||
, isConversionTarget(isConversionTarget)
|
||||
, isWhimsical(false)
|
||||
{
|
||||
std::wstring nameValue1 = isRtlLanguage ? currencyName : countryName;
|
||||
std::wstring nameValue2 = isRtlLanguage ? countryName : currencyName;
|
||||
|
@ -31,7 +50,9 @@ namespace UnitConversionManager
|
|||
accessibleName = nameValue1 + L" " + nameValue2;
|
||||
}
|
||||
|
||||
virtual ~Unit() {}
|
||||
virtual ~Unit()
|
||||
{
|
||||
}
|
||||
|
||||
int id;
|
||||
std::wstring name;
|
||||
|
@ -61,9 +82,14 @@ namespace UnitConversionManager
|
|||
|
||||
struct Category
|
||||
{
|
||||
Category(){}
|
||||
Category()
|
||||
{
|
||||
}
|
||||
|
||||
Category(int id, std::wstring name, bool supportsNegative) : id(id), name(name), supportsNegative(supportsNegative)
|
||||
Category(int id, std::wstring name, bool supportsNegative)
|
||||
: id(id)
|
||||
, name(name)
|
||||
, supportsNegative(supportsNegative)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -85,7 +111,8 @@ namespace UnitConversionManager
|
|||
class UnitHash
|
||||
{
|
||||
public:
|
||||
size_t operator() (const Unit & x) const {
|
||||
size_t operator()(const Unit& x) const
|
||||
{
|
||||
return x.id;
|
||||
}
|
||||
};
|
||||
|
@ -93,7 +120,8 @@ namespace UnitConversionManager
|
|||
class CategoryHash
|
||||
{
|
||||
public:
|
||||
size_t operator() (const Category & x) const {
|
||||
size_t operator()(const Category& x) const
|
||||
{
|
||||
return x.id;
|
||||
}
|
||||
};
|
||||
|
@ -107,12 +135,19 @@ namespace UnitConversionManager
|
|||
|
||||
struct ConversionData
|
||||
{
|
||||
ConversionData(){}
|
||||
ConversionData(double ratio, double offset, bool offsetFirst) : ratio(ratio), offset(offset), offsetFirst(offsetFirst)
|
||||
ConversionData()
|
||||
{
|
||||
}
|
||||
ConversionData(double ratio, double offset, bool offsetFirst)
|
||||
: ratio(ratio)
|
||||
, offset(offset)
|
||||
, offsetFirst(offsetFirst)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~ConversionData() {}
|
||||
virtual ~ConversionData()
|
||||
{
|
||||
}
|
||||
|
||||
double ratio;
|
||||
double offset;
|
||||
|
@ -136,8 +171,13 @@ namespace UnitConversionManager
|
|||
};
|
||||
|
||||
typedef std::tuple<std::vector<UnitConversionManager::Unit>, UnitConversionManager::Unit, UnitConversionManager::Unit> CategorySelectionInitializer;
|
||||
typedef std::unordered_map<UnitConversionManager::Unit, std::unordered_map<UnitConversionManager::Unit, UnitConversionManager::ConversionData, UnitConversionManager::UnitHash>, UnitConversionManager::UnitHash> UnitToUnitToConversionDataMap;
|
||||
typedef std::unordered_map<UnitConversionManager::Category, std::vector<UnitConversionManager::Unit>, UnitConversionManager::CategoryHash> CategoryToUnitVectorMap;
|
||||
typedef std::unordered_map<
|
||||
UnitConversionManager::Unit,
|
||||
std::unordered_map<UnitConversionManager::Unit, UnitConversionManager::ConversionData, UnitConversionManager::UnitHash>,
|
||||
UnitConversionManager::UnitHash>
|
||||
UnitToUnitToConversionDataMap;
|
||||
typedef std::unordered_map<UnitConversionManager::Category, std::vector<UnitConversionManager::Unit>, UnitConversionManager::CategoryHash>
|
||||
CategoryToUnitVectorMap;
|
||||
|
||||
class IViewModelCurrencyCallback
|
||||
{
|
||||
|
@ -165,8 +205,10 @@ namespace UnitConversionManager
|
|||
{
|
||||
public:
|
||||
virtual void SetViewModelCallback(const std::shared_ptr<UnitConversionManager::IViewModelCurrencyCallback>& callback) = 0;
|
||||
virtual std::pair<std::wstring, std::wstring> GetCurrencySymbols(_In_ const UnitConversionManager::Unit& unit1, _In_ const UnitConversionManager::Unit& unit2) = 0;
|
||||
virtual std::pair<std::wstring, std::wstring> GetCurrencyRatioEquality(_In_ const UnitConversionManager::Unit& unit1, _In_ const UnitConversionManager::Unit& unit2) = 0;
|
||||
virtual std::pair<std::wstring, std::wstring>
|
||||
GetCurrencySymbols(_In_ const UnitConversionManager::Unit& unit1, _In_ const UnitConversionManager::Unit& unit2) = 0;
|
||||
virtual std::pair<std::wstring, std::wstring>
|
||||
GetCurrencyRatioEquality(_In_ const UnitConversionManager::Unit& unit1, _In_ const UnitConversionManager::Unit& unit2) = 0;
|
||||
virtual std::wstring GetCurrencyTimestamp() = 0;
|
||||
|
||||
virtual concurrency::task<bool> TryLoadDataFromCacheAsync() = 0;
|
||||
|
@ -186,15 +228,15 @@ namespace UnitConversionManager
|
|||
class IUnitConverter
|
||||
{
|
||||
public:
|
||||
virtual ~IUnitConverter() { }
|
||||
virtual ~IUnitConverter()
|
||||
{
|
||||
}
|
||||
virtual void Initialize() = 0; // Use to initialize first time, use deserialize instead to rehydrate
|
||||
virtual std::vector<Category> GetCategories() = 0;
|
||||
virtual CategorySelectionInitializer SetCurrentCategory(const Category& input) = 0;
|
||||
virtual Category GetCurrentCategory() = 0;
|
||||
virtual void SetCurrentUnitTypes(const Unit& fromType, const Unit& toType) = 0;
|
||||
virtual void SwitchActive(const std::wstring& newValue) = 0;
|
||||
virtual std::wstring Serialize() = 0;
|
||||
virtual void DeSerialize(const std::wstring& serializedData) = 0;
|
||||
virtual std::wstring SaveUserPreferences() = 0;
|
||||
virtual void RestoreUserPreferences(_In_ const std::wstring& userPreferences) = 0;
|
||||
virtual void SendCommand(Command command) = 0;
|
||||
|
@ -218,8 +260,6 @@ namespace UnitConversionManager
|
|||
Category GetCurrentCategory() override;
|
||||
void SetCurrentUnitTypes(const Unit& fromType, const Unit& toType) override;
|
||||
void SwitchActive(const std::wstring& newValue) override;
|
||||
std::wstring Serialize() override;
|
||||
void DeSerialize(const std::wstring& serializedData) override;
|
||||
std::wstring SaveUserPreferences() override;
|
||||
void RestoreUserPreferences(const std::wstring& userPreference) override;
|
||||
void SendCommand(Command command) override;
|
||||
|
@ -246,8 +286,6 @@ namespace UnitConversionManager
|
|||
std::wstring CategoryToString(const Category& c, const wchar_t* delimiter);
|
||||
std::wstring UnitToString(const Unit& u, const wchar_t* delimiter);
|
||||
Unit StringToUnit(const std::wstring& w);
|
||||
ConversionData StringToConversionData(const std::wstring& w);
|
||||
std::wstring ConversionDataToString(ConversionData d, const wchar_t * delimiter);
|
||||
void UpdateCurrencySymbols();
|
||||
void UpdateViewModel();
|
||||
bool AnyUnitIsEmpty();
|
||||
|
|
|
@ -38,13 +38,13 @@ namespace
|
|||
StringReference ClearMemoryVisibilityPropertyName(L"ClearMemoryVisibility");
|
||||
}
|
||||
|
||||
ApplicationViewModel::ApplicationViewModel() :
|
||||
m_CalculatorViewModel(nullptr),
|
||||
m_DateCalcViewModel(nullptr),
|
||||
m_ConverterViewModel(nullptr),
|
||||
m_PreviousMode(ViewMode::None),
|
||||
m_mode(ViewMode::None),
|
||||
m_categories(nullptr)
|
||||
ApplicationViewModel::ApplicationViewModel()
|
||||
: m_CalculatorViewModel(nullptr)
|
||||
, m_DateCalcViewModel(nullptr)
|
||||
, m_ConverterViewModel(nullptr)
|
||||
, m_PreviousMode(ViewMode::None)
|
||||
, m_mode(ViewMode::None)
|
||||
, m_categories(nullptr)
|
||||
{
|
||||
SetMenuCategories();
|
||||
}
|
||||
|
|
|
@ -11,8 +11,7 @@ namespace CalculatorApp
|
|||
{
|
||||
namespace ViewModel
|
||||
{
|
||||
[Windows::UI::Xaml::Data::Bindable]
|
||||
public ref class ApplicationViewModel sealed : public Windows::UI::Xaml::Data::INotifyPropertyChanged
|
||||
[Windows::UI::Xaml::Data::Bindable] public ref class ApplicationViewModel sealed : public Windows::UI::Xaml::Data::INotifyPropertyChanged
|
||||
{
|
||||
public:
|
||||
ApplicationViewModel();
|
||||
|
@ -60,8 +59,7 @@ namespace CalculatorApp
|
|||
{
|
||||
Windows::UI::Xaml::Visibility get()
|
||||
{
|
||||
return CalculatorApp::Common::NavCategory::IsCalculatorViewMode(Mode)
|
||||
? Windows::UI::Xaml::Visibility::Visible
|
||||
return CalculatorApp::Common::NavCategory::IsCalculatorViewMode(Mode) ? Windows::UI::Xaml::Visibility::Visible
|
||||
: Windows::UI::Xaml::Visibility::Collapsed;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,30 +3,31 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
namespace CalculatorApp { namespace Common
|
||||
namespace CalculatorApp
|
||||
{
|
||||
ref class AlwaysSelectedCollectionView sealed:
|
||||
public Windows::UI::Xaml::DependencyObject,
|
||||
public Windows::UI::Xaml::Data::ICollectionView
|
||||
namespace Common
|
||||
{
|
||||
internal:
|
||||
AlwaysSelectedCollectionView(Windows::UI::Xaml::Interop::IBindableVector^ source):
|
||||
m_currentPosition(-1)
|
||||
ref class AlwaysSelectedCollectionView sealed : public Windows::UI::Xaml::DependencyObject, public Windows::UI::Xaml::Data::ICollectionView
|
||||
{
|
||||
internal : AlwaysSelectedCollectionView(Windows::UI::Xaml::Interop::IBindableVector ^ source)
|
||||
: m_currentPosition(-1)
|
||||
{
|
||||
m_source = source;
|
||||
|
||||
Windows::UI::Xaml::Interop::IBindableObservableVector^ observable = dynamic_cast<Windows::UI::Xaml::Interop::IBindableObservableVector^>(source);
|
||||
Windows::UI::Xaml::Interop::IBindableObservableVector ^ observable =
|
||||
dynamic_cast<Windows::UI::Xaml::Interop::IBindableObservableVector ^>(source);
|
||||
if (observable)
|
||||
{
|
||||
observable->VectorChanged +=
|
||||
ref new Windows::UI::Xaml::Interop::BindableVectorChangedEventHandler(this, &AlwaysSelectedCollectionView::OnSourceBindableVectorChanged);
|
||||
observable->VectorChanged += ref new Windows::UI::Xaml::Interop::BindableVectorChangedEventHandler(
|
||||
this, &AlwaysSelectedCollectionView::OnSourceBindableVectorChanged);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
// ICollectionView
|
||||
// Not implemented methods
|
||||
virtual WF::IAsyncOperation<Windows::UI::Xaml::Data::LoadMoreItemsResult>^ LoadMoreItemsAsync(unsigned int) = Windows::UI::Xaml::Data::ICollectionView::LoadMoreItemsAsync
|
||||
virtual WF::IAsyncOperation<
|
||||
Windows::UI::Xaml::Data::LoadMoreItemsResult> ^ LoadMoreItemsAsync(unsigned int) = Windows::UI::Xaml::Data::ICollectionView::LoadMoreItemsAsync
|
||||
{
|
||||
throw ref new Platform::NotImplementedException();
|
||||
}
|
||||
|
@ -46,14 +47,13 @@ namespace CalculatorApp { namespace Common
|
|||
{
|
||||
throw ref new Platform::NotImplementedException();
|
||||
}
|
||||
property Windows::Foundation::Collections::IObservableVector<Platform::Object^>^ CollectionGroups
|
||||
{
|
||||
virtual Windows::Foundation::Collections::IObservableVector<Platform::Object^>^ get() = Windows::UI::Xaml::Data::ICollectionView::CollectionGroups::get
|
||||
property Windows::Foundation::Collections::IObservableVector<Platform::Object ^> ^ CollectionGroups {
|
||||
virtual Windows::Foundation::Collections::IObservableVector<
|
||||
Platform::Object ^> ^ get() = Windows::UI::Xaml::Data::ICollectionView::CollectionGroups::get
|
||||
{
|
||||
return ref new Platform::Collections::Vector<Platform::Object ^>();
|
||||
}
|
||||
}
|
||||
property bool HasMoreItems
|
||||
} property bool HasMoreItems
|
||||
{
|
||||
virtual bool get() = Windows::UI::Xaml::Data::ICollectionView::HasMoreItems::get
|
||||
{
|
||||
|
@ -81,10 +81,7 @@ namespace CalculatorApp { namespace Common
|
|||
// restore the selection to the way we wanted it to begin with
|
||||
if (m_currentPosition >= 0 && m_currentPosition < static_cast<int>(m_source->Size))
|
||||
{
|
||||
this->Dispatcher->RunAsync(Windows::UI::Core::CoreDispatcherPriority::Normal,
|
||||
ref new Windows::UI::Core::DispatchedHandler(
|
||||
[this]()
|
||||
{
|
||||
this->Dispatcher->RunAsync(Windows::UI::Core::CoreDispatcherPriority::Normal, ref new Windows::UI::Core::DispatchedHandler([this]() {
|
||||
m_currentChanged(this, nullptr);
|
||||
}));
|
||||
}
|
||||
|
@ -172,11 +169,14 @@ namespace CalculatorApp { namespace Common
|
|||
{
|
||||
throw ref new Platform::NotImplementedException();
|
||||
}
|
||||
virtual unsigned int GetMany(unsigned int /*startIndex*/, Platform::WriteOnlyArray<Platform::Object^>^ /*items*/) = Windows::Foundation::Collections::IVector<Platform::Object^>::GetMany
|
||||
virtual unsigned int GetMany(
|
||||
unsigned int /*startIndex*/,
|
||||
Platform::WriteOnlyArray<Platform::Object ^> ^ /*items*/) = Windows::Foundation::Collections::IVector<Platform::Object ^>::GetMany
|
||||
{
|
||||
throw ref new Platform::NotImplementedException();
|
||||
}
|
||||
virtual Windows::Foundation::Collections::IVectorView<Platform::Object^>^ GetView() = Windows::Foundation::Collections::IVector<Platform::Object^>::GetView
|
||||
virtual Windows::Foundation::Collections::IVectorView<Platform::Object ^> ^ GetView() = Windows::Foundation::Collections::IVector<
|
||||
Platform::Object ^>::GetView
|
||||
{
|
||||
throw ref new Platform::NotImplementedException();
|
||||
}
|
||||
|
@ -192,7 +192,8 @@ namespace CalculatorApp { namespace Common
|
|||
{
|
||||
throw ref new Platform::NotImplementedException();
|
||||
}
|
||||
virtual void ReplaceAll(const Platform::Array<Platform::Object^>^ /*items*/) = Windows::Foundation::Collections::IVector<Platform::Object^>::ReplaceAll
|
||||
virtual void
|
||||
ReplaceAll(const Platform::Array<Platform::Object ^> ^ /*items*/) = Windows::Foundation::Collections::IVector<Platform::Object ^>::ReplaceAll
|
||||
{
|
||||
throw ref new Platform::NotImplementedException();
|
||||
}
|
||||
|
@ -254,14 +255,17 @@ namespace CalculatorApp { namespace Common
|
|||
event Windows::Foundation::Collections::VectorChangedEventHandler<Platform::Object ^> ^ m_vectorChanged;
|
||||
};
|
||||
|
||||
public ref class AlwaysSelectedCollectionViewConverter sealed: public Windows::UI::Xaml::Data::IValueConverter
|
||||
public
|
||||
ref class AlwaysSelectedCollectionViewConverter sealed : public Windows::UI::Xaml::Data::IValueConverter
|
||||
{
|
||||
public:
|
||||
AlwaysSelectedCollectionViewConverter()
|
||||
{ }
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
virtual Platform::Object^ Convert(
|
||||
virtual Platform::Object
|
||||
^ Convert(
|
||||
Platform::Object ^ value,
|
||||
Windows::UI::Xaml::Interop::TypeName /*targetType*/,
|
||||
Platform::Object ^ /*parameter*/,
|
||||
|
@ -275,7 +279,8 @@ namespace CalculatorApp { namespace Common
|
|||
return Windows::UI::Xaml::DependencyProperty::UnsetValue; // Can't convert
|
||||
}
|
||||
|
||||
virtual Platform::Object^ ConvertBack(
|
||||
virtual Platform::Object
|
||||
^ ConvertBack(
|
||||
Platform::Object ^ /*value*/,
|
||||
Windows::UI::Xaml::Interop::TypeName /*targetType*/,
|
||||
Platform::Object ^ /*parameter*/,
|
||||
|
@ -284,4 +289,5 @@ namespace CalculatorApp { namespace Common
|
|||
return Windows::UI::Xaml::DependencyProperty::UnsetValue;
|
||||
}
|
||||
};
|
||||
}}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,7 +11,8 @@
|
|||
|
||||
namespace CalculatorApp::Common::Automation
|
||||
{
|
||||
public interface class INarratorAnnouncementHost
|
||||
public
|
||||
interface class INarratorAnnouncementHost
|
||||
{
|
||||
public:
|
||||
// Is the host available on this OS.
|
||||
|
|
|
@ -9,9 +9,10 @@ using namespace Windows::UI::Xaml::Automation;
|
|||
using namespace Windows::UI::Xaml::Automation::Peers;
|
||||
using namespace Windows::UI::Xaml::Controls;
|
||||
|
||||
LiveRegionHost::LiveRegionHost() :
|
||||
m_host(nullptr)
|
||||
{}
|
||||
LiveRegionHost::LiveRegionHost()
|
||||
: m_host(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
bool LiveRegionHost::IsHostAvailable()
|
||||
{
|
||||
|
|
|
@ -16,7 +16,8 @@ namespace CalculatorApp::Common::Automation
|
|||
// When the app switches to min version RS3, this class can be removed
|
||||
// and the app will switch to using the Notification API.
|
||||
// TODO - MSFT 12735088
|
||||
public ref class LiveRegionHost sealed : public INarratorAnnouncementHost
|
||||
public
|
||||
ref class LiveRegionHost sealed : public INarratorAnnouncementHost
|
||||
{
|
||||
public:
|
||||
LiveRegionHost();
|
||||
|
|
|
@ -30,12 +30,12 @@ NarratorAnnouncement::NarratorAnnouncement(
|
|||
String ^ activityId,
|
||||
AutomationNotificationKind kind,
|
||||
AutomationNotificationProcessing processing)
|
||||
:
|
||||
m_announcement(announcement),
|
||||
m_activityId(activityId),
|
||||
m_kind(kind),
|
||||
m_processing(processing)
|
||||
{}
|
||||
: m_announcement(announcement)
|
||||
, m_activityId(activityId)
|
||||
, m_kind(kind)
|
||||
, m_processing(processing)
|
||||
{
|
||||
}
|
||||
|
||||
String ^ NarratorAnnouncement::Announcement::get()
|
||||
{
|
||||
|
@ -59,63 +59,43 @@ AutomationNotificationProcessing NarratorAnnouncement::Processing::get()
|
|||
|
||||
bool NarratorAnnouncement::IsValid(NarratorAnnouncement ^ announcement)
|
||||
{
|
||||
return announcement != nullptr
|
||||
&& announcement->Announcement != nullptr
|
||||
&& !announcement->Announcement->IsEmpty();
|
||||
return announcement != nullptr && announcement->Announcement != nullptr && !announcement->Announcement->IsEmpty();
|
||||
}
|
||||
|
||||
NarratorAnnouncement ^ CalculatorAnnouncement::GetDisplayUpdatedAnnouncement(String ^ announcement)
|
||||
{
|
||||
return ref new NarratorAnnouncement(
|
||||
announcement,
|
||||
CalculatorActivityIds::DisplayUpdated,
|
||||
AutomationNotificationKind::Other,
|
||||
AutomationNotificationProcessing::ImportantMostRecent);
|
||||
announcement, CalculatorActivityIds::DisplayUpdated, AutomationNotificationKind::Other, AutomationNotificationProcessing::ImportantMostRecent);
|
||||
}
|
||||
|
||||
NarratorAnnouncement ^ CalculatorAnnouncement::GetMaxDigitsReachedAnnouncement(String ^ announcement)
|
||||
{
|
||||
return ref new NarratorAnnouncement(
|
||||
announcement,
|
||||
CalculatorActivityIds::MaxDigitsReached,
|
||||
AutomationNotificationKind::Other,
|
||||
AutomationNotificationProcessing::ImportantMostRecent);
|
||||
announcement, CalculatorActivityIds::MaxDigitsReached, AutomationNotificationKind::Other, AutomationNotificationProcessing::ImportantMostRecent);
|
||||
}
|
||||
|
||||
NarratorAnnouncement ^ CalculatorAnnouncement::GetMemoryClearedAnnouncement(String ^ announcement)
|
||||
{
|
||||
return ref new NarratorAnnouncement(
|
||||
announcement,
|
||||
CalculatorActivityIds::MemoryCleared,
|
||||
AutomationNotificationKind::ItemRemoved,
|
||||
AutomationNotificationProcessing::ImportantMostRecent);
|
||||
announcement, CalculatorActivityIds::MemoryCleared, AutomationNotificationKind::ItemRemoved, AutomationNotificationProcessing::ImportantMostRecent);
|
||||
}
|
||||
|
||||
NarratorAnnouncement ^ CalculatorAnnouncement::GetMemoryItemChangedAnnouncement(String ^ announcement)
|
||||
{
|
||||
return ref new NarratorAnnouncement(
|
||||
announcement,
|
||||
CalculatorActivityIds::MemoryItemChanged,
|
||||
AutomationNotificationKind::ActionCompleted,
|
||||
AutomationNotificationProcessing::MostRecent);
|
||||
announcement, CalculatorActivityIds::MemoryItemChanged, AutomationNotificationKind::ActionCompleted, AutomationNotificationProcessing::MostRecent);
|
||||
}
|
||||
|
||||
NarratorAnnouncement ^ CalculatorAnnouncement::GetMemoryItemAddedAnnouncement(String ^ announcement)
|
||||
{
|
||||
return ref new NarratorAnnouncement(
|
||||
announcement,
|
||||
CalculatorActivityIds::MemoryItemAdded,
|
||||
AutomationNotificationKind::ItemAdded,
|
||||
AutomationNotificationProcessing::MostRecent);
|
||||
announcement, CalculatorActivityIds::MemoryItemAdded, AutomationNotificationKind::ItemAdded, AutomationNotificationProcessing::MostRecent);
|
||||
}
|
||||
|
||||
NarratorAnnouncement ^ CalculatorAnnouncement::GetHistoryClearedAnnouncement(String ^ announcement)
|
||||
{
|
||||
return ref new NarratorAnnouncement(
|
||||
announcement,
|
||||
CalculatorActivityIds::HistoryCleared,
|
||||
AutomationNotificationKind::ItemRemoved,
|
||||
AutomationNotificationProcessing::MostRecent);
|
||||
announcement, CalculatorActivityIds::HistoryCleared, AutomationNotificationKind::ItemRemoved, AutomationNotificationProcessing::MostRecent);
|
||||
}
|
||||
|
||||
NarratorAnnouncement ^ CalculatorAnnouncement::GetCategoryNameChangedAnnouncement(String ^ announcement)
|
||||
|
@ -139,10 +119,7 @@ NarratorAnnouncement^ CalculatorAnnouncement::GetUpdateCurrencyRatesAnnouncement
|
|||
NarratorAnnouncement ^ CalculatorAnnouncement::GetDisplayCopiedAnnouncement(String ^ announcement)
|
||||
{
|
||||
return ref new NarratorAnnouncement(
|
||||
announcement,
|
||||
CalculatorActivityIds::DisplayCopied,
|
||||
AutomationNotificationKind::ActionCompleted,
|
||||
AutomationNotificationProcessing::ImportantMostRecent);
|
||||
announcement, CalculatorActivityIds::DisplayCopied, AutomationNotificationKind::ActionCompleted, AutomationNotificationProcessing::ImportantMostRecent);
|
||||
}
|
||||
|
||||
NarratorAnnouncement ^ CalculatorAnnouncement::GetOpenParenthesisCountChangedAnnouncement(String ^ announcement)
|
||||
|
|
|
@ -11,7 +11,8 @@ namespace CalculatorApp::Common::Automation
|
|||
// enums should be removed and the Windows types should be used
|
||||
// instead.
|
||||
// TODO - MSFT 12735088
|
||||
public enum class AutomationNotificationKind
|
||||
public
|
||||
enum class AutomationNotificationKind
|
||||
{
|
||||
ItemAdded = 0,
|
||||
ItemRemoved = 1,
|
||||
|
@ -20,7 +21,8 @@ namespace CalculatorApp::Common::Automation
|
|||
Other = 4
|
||||
};
|
||||
|
||||
public enum class AutomationNotificationProcessing
|
||||
public
|
||||
enum class AutomationNotificationProcessing
|
||||
{
|
||||
ImportantAll = 0,
|
||||
ImportantMostRecent = 1,
|
||||
|
@ -29,18 +31,15 @@ namespace CalculatorApp::Common::Automation
|
|||
CurrentThenMostRecent = 4
|
||||
};
|
||||
|
||||
public ref class NarratorAnnouncement sealed
|
||||
public
|
||||
ref class NarratorAnnouncement sealed
|
||||
{
|
||||
public:
|
||||
property Platform::String^ Announcement
|
||||
{
|
||||
Platform::String^ get();
|
||||
}
|
||||
property Platform::String
|
||||
^ Announcement { Platform::String ^ get(); }
|
||||
|
||||
property Platform::String^ ActivityId
|
||||
{
|
||||
Platform::String^ get();
|
||||
}
|
||||
property Platform::String
|
||||
^ ActivityId { Platform::String ^ get(); }
|
||||
|
||||
property AutomationNotificationKind Kind
|
||||
{
|
||||
|
|
|
@ -32,10 +32,7 @@ void NarratorAnnouncementHostFactory::RegisterHosts()
|
|||
{
|
||||
// The host that will be used is the first available host,
|
||||
// therefore, order of hosts is important here.
|
||||
NarratorAnnouncementHostFactory::s_hosts = {
|
||||
ref new NotificationHost(),
|
||||
ref new LiveRegionHost()
|
||||
};
|
||||
NarratorAnnouncementHostFactory::s_hosts = { ref new NotificationHost(), ref new LiveRegionHost() };
|
||||
}
|
||||
|
||||
INarratorAnnouncementHost ^ NarratorAnnouncementHostFactory::GetHostProducer()
|
||||
|
|
|
@ -17,7 +17,9 @@ namespace CalculatorApp::Common::Automation
|
|||
static INarratorAnnouncementHost ^ MakeHost();
|
||||
|
||||
private:
|
||||
NarratorAnnouncementHostFactory() {}
|
||||
NarratorAnnouncementHostFactory()
|
||||
{
|
||||
}
|
||||
|
||||
static int Initialize();
|
||||
static void RegisterHosts();
|
||||
|
|
|
@ -22,8 +22,7 @@ NarratorNotifier::NarratorNotifier()
|
|||
|
||||
void NarratorNotifier::Announce(NarratorAnnouncement ^ announcement)
|
||||
{
|
||||
if (NarratorAnnouncement::IsValid(announcement)
|
||||
&& m_announcementHost != nullptr)
|
||||
if (NarratorAnnouncement::IsValid(announcement) && m_announcementHost != nullptr)
|
||||
{
|
||||
m_announcementHost->Announce(announcement);
|
||||
}
|
||||
|
|
|
@ -8,7 +8,8 @@
|
|||
|
||||
namespace CalculatorApp::Common::Automation
|
||||
{
|
||||
public ref class NarratorNotifier sealed : public Windows::UI::Xaml::DependencyObject
|
||||
public
|
||||
ref class NarratorNotifier sealed : public Windows::UI::Xaml::DependencyObject
|
||||
{
|
||||
public:
|
||||
NarratorNotifier();
|
||||
|
@ -26,18 +27,12 @@ namespace CalculatorApp::Common::Automation
|
|||
|
||||
static void RegisterDependencyProperties();
|
||||
|
||||
static property Windows::UI::Xaml::DependencyProperty^ AnnouncementProperty
|
||||
{
|
||||
Windows::UI::Xaml::DependencyProperty^ get()
|
||||
{
|
||||
return s_announcementProperty;
|
||||
}
|
||||
}
|
||||
static property Windows::UI::Xaml::DependencyProperty
|
||||
^ AnnouncementProperty { Windows::UI::Xaml::DependencyProperty ^ get() { return s_announcementProperty; } }
|
||||
|
||||
static NarratorAnnouncement^ GetAnnouncement(Windows::UI::Xaml::DependencyObject^ element)
|
||||
{
|
||||
return safe_cast<NarratorAnnouncement^>(element->GetValue(s_announcementProperty));
|
||||
}
|
||||
static NarratorAnnouncement
|
||||
^ GetAnnouncement(
|
||||
Windows::UI::Xaml::DependencyObject ^ element) { return safe_cast<NarratorAnnouncement ^>(element->GetValue(s_announcementProperty)); }
|
||||
|
||||
static void SetAnnouncement(Windows::UI::Xaml::DependencyObject ^ element, NarratorAnnouncement ^ value)
|
||||
{
|
||||
|
|
|
@ -10,15 +10,14 @@ using namespace Windows::UI::Xaml::Automation;
|
|||
using namespace Windows::UI::Xaml::Automation::Peers;
|
||||
using namespace Windows::UI::Xaml::Controls;
|
||||
|
||||
NotificationHost::NotificationHost() :
|
||||
m_host(nullptr)
|
||||
{}
|
||||
NotificationHost::NotificationHost()
|
||||
: m_host(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
bool NotificationHost::IsHostAvailable()
|
||||
{
|
||||
return ApiInformation::IsMethodPresent(
|
||||
L"Windows.UI.Xaml.Automation.Peers.AutomationPeer",
|
||||
L"RaiseNotificationEvent");
|
||||
return ApiInformation::IsMethodPresent(L"Windows.UI.Xaml.Automation.Peers.AutomationPeer", L"RaiseNotificationEvent");
|
||||
}
|
||||
|
||||
INarratorAnnouncementHost ^ NotificationHost::MakeHost()
|
||||
|
@ -44,8 +43,7 @@ void NotificationHost::Announce(NarratorAnnouncement^ announcement)
|
|||
}
|
||||
}
|
||||
|
||||
StandardPeers::AutomationNotificationKind NotificationHost::GetWindowsNotificationKind(
|
||||
CustomPeers::AutomationNotificationKind customKindType)
|
||||
StandardPeers::AutomationNotificationKind NotificationHost::GetWindowsNotificationKind(CustomPeers::AutomationNotificationKind customKindType)
|
||||
{
|
||||
switch (customKindType)
|
||||
{
|
||||
|
@ -71,8 +69,8 @@ StandardPeers::AutomationNotificationKind NotificationHost::GetWindowsNotificati
|
|||
return StandardPeers::AutomationNotificationKind::Other;
|
||||
}
|
||||
|
||||
StandardPeers::AutomationNotificationProcessing NotificationHost::GetWindowsNotificationProcessing(
|
||||
CustomPeers::AutomationNotificationProcessing customProcessingType)
|
||||
StandardPeers::AutomationNotificationProcessing
|
||||
NotificationHost::GetWindowsNotificationProcessing(CustomPeers::AutomationNotificationProcessing customProcessingType)
|
||||
{
|
||||
switch (customProcessingType)
|
||||
{
|
||||
|
|
|
@ -10,7 +10,8 @@
|
|||
|
||||
namespace CalculatorApp::Common::Automation
|
||||
{
|
||||
public ref class NotificationHost sealed : public INarratorAnnouncementHost
|
||||
public
|
||||
ref class NotificationHost sealed : public INarratorAnnouncementHost
|
||||
{
|
||||
public:
|
||||
NotificationHost();
|
||||
|
@ -21,14 +22,13 @@ namespace CalculatorApp::Common::Automation
|
|||
virtual void Announce(NarratorAnnouncement ^ announcement);
|
||||
|
||||
private:
|
||||
static Windows::UI::Xaml::Automation::Peers::AutomationNotificationKind GetWindowsNotificationKind(
|
||||
CalculatorApp::Common::Automation::AutomationNotificationKind customKindType);
|
||||
static Windows::UI::Xaml::Automation::Peers::AutomationNotificationKind
|
||||
GetWindowsNotificationKind(CalculatorApp::Common::Automation::AutomationNotificationKind customKindType);
|
||||
|
||||
static Windows::UI::Xaml::Automation::Peers::AutomationNotificationProcessing GetWindowsNotificationProcessing(
|
||||
CalculatorApp::Common::Automation::AutomationNotificationProcessing customProcessingType);
|
||||
static Windows::UI::Xaml::Automation::Peers::AutomationNotificationProcessing
|
||||
GetWindowsNotificationProcessing(CalculatorApp::Common::Automation::AutomationNotificationProcessing customProcessingType);
|
||||
|
||||
private:
|
||||
Windows::UI::Xaml::UIElement ^ m_host;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -10,8 +10,9 @@ namespace CalculatorApp
|
|||
/// <summary>
|
||||
/// Implementation of <see cref="INotifyPropertyChanged"/> to simplify models.
|
||||
/// </summary>
|
||||
[Windows::Foundation::Metadata::WebHostHidden]
|
||||
public ref class BindableBase : Windows::UI::Xaml::DependencyObject, Windows::UI::Xaml::Data::INotifyPropertyChanged, Windows::UI::Xaml::Data::ICustomPropertyProvider
|
||||
[Windows::Foundation::Metadata::WebHostHidden] public ref class BindableBase : Windows::UI::Xaml::DependencyObject,
|
||||
Windows::UI::Xaml::Data::INotifyPropertyChanged,
|
||||
Windows::UI::Xaml::Data::ICustomPropertyProvider
|
||||
{
|
||||
public:
|
||||
virtual event Windows::UI::Xaml::Data::PropertyChangedEventHandler ^ PropertyChanged;
|
||||
|
@ -24,9 +25,11 @@ namespace CalculatorApp
|
|||
|
||||
property Windows::UI::Xaml::Interop::TypeName Type
|
||||
{
|
||||
virtual Windows::UI::Xaml::Interop::TypeName get() { return this->GetType(); }
|
||||
virtual Windows::UI::Xaml::Interop::TypeName get()
|
||||
{
|
||||
return this->GetType();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected:
|
||||
virtual void OnPropertyChanged(Platform::String ^ propertyName);
|
||||
|
|
|
@ -33,4 +33,3 @@ String^ CalculatorButtonPressedEventArgs::GetAuditoryFeedbackFromCommandParamete
|
|||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -10,15 +10,18 @@ namespace CalculatorApp
|
|||
{
|
||||
namespace Common
|
||||
{
|
||||
public ref class CalculatorButtonPressedEventArgs sealed
|
||||
public
|
||||
ref class CalculatorButtonPressedEventArgs sealed
|
||||
{
|
||||
public:
|
||||
PROPERTY_R(Platform::String ^, AuditoryFeedback);
|
||||
PROPERTY_R(CalculatorApp::NumbersAndOperatorsEnum, Operation);
|
||||
|
||||
CalculatorButtonPressedEventArgs(
|
||||
Platform::String^ feedback, CalculatorApp::NumbersAndOperatorsEnum operation) :
|
||||
m_AuditoryFeedback(feedback), m_Operation(operation) {}
|
||||
CalculatorButtonPressedEventArgs(Platform::String ^ feedback, CalculatorApp::NumbersAndOperatorsEnum operation)
|
||||
: m_AuditoryFeedback(feedback)
|
||||
, m_Operation(operation)
|
||||
{
|
||||
}
|
||||
|
||||
static CalculatorApp::NumbersAndOperatorsEnum GetOperationFromCommandParameter(_In_ Platform::Object ^ commandParameter);
|
||||
static Platform::String ^ GetAuditoryFeedbackFromCommandParameter(_In_ Platform::Object ^ commandParameter);
|
||||
|
|
|
@ -9,7 +9,8 @@ namespace CalculatorApp
|
|||
{
|
||||
namespace CM = CalculationManager;
|
||||
|
||||
public enum class NumbersAndOperatorsEnum
|
||||
public
|
||||
enum class NumbersAndOperatorsEnum
|
||||
{
|
||||
Zero = (int)CM::Command::Command0,
|
||||
One = (int)CM::Command::Command1,
|
||||
|
@ -164,7 +165,8 @@ namespace CalculatorApp
|
|||
};
|
||||
|
||||
// This contains list of functions whose usage we are tracelogging
|
||||
public enum class FunctionLogEnum
|
||||
public
|
||||
enum class FunctionLogEnum
|
||||
{
|
||||
Invert = (int)CM::Command::CommandREC,
|
||||
Sqrt = (int)CM::Command::CommandSQRT,
|
||||
|
|
|
@ -69,7 +69,9 @@ void CalculatorDisplay::SetIsInError(bool isError)
|
|||
}
|
||||
}
|
||||
|
||||
void CalculatorDisplay::SetExpressionDisplay(_Inout_ std::shared_ptr<CalculatorVector<std::pair<std::wstring, int>>> const &tokens, _Inout_ std::shared_ptr<CalculatorVector <std::shared_ptr<IExpressionCommand>>> const &commands)
|
||||
void CalculatorDisplay::SetExpressionDisplay(
|
||||
_Inout_ std::shared_ptr<CalculatorVector<std::pair<std::wstring, int>>> const& tokens,
|
||||
_Inout_ std::shared_ptr<CalculatorVector<std::shared_ptr<IExpressionCommand>>> const& commands)
|
||||
{
|
||||
if (m_callbackReference != nullptr)
|
||||
{
|
||||
|
|
|
@ -18,7 +18,9 @@ namespace CalculatorApp
|
|||
private:
|
||||
void SetPrimaryDisplay(_In_ const std::wstring& displayString, _In_ bool isError) override;
|
||||
void SetIsInError(bool isError) override;
|
||||
void SetExpressionDisplay(_Inout_ std::shared_ptr<CalculatorVector<std::pair<std::wstring, int>>> const &tokens, _Inout_ std::shared_ptr<CalculatorVector<std::shared_ptr<IExpressionCommand>>> const &commands) override;
|
||||
void SetExpressionDisplay(
|
||||
_Inout_ std::shared_ptr<CalculatorVector<std::pair<std::wstring, int>>> const& tokens,
|
||||
_Inout_ std::shared_ptr<CalculatorVector<std::shared_ptr<IExpressionCommand>>> const& commands) override;
|
||||
void SetMemorizedNumbers(_In_ const std::vector<std::wstring>& memorizedNumbers) override;
|
||||
void OnHistoryItemAdded(_In_ unsigned int addedItemIndex) override;
|
||||
void SetParenthesisNumber(_In_ unsigned int parenthesisCount) override;
|
||||
|
|
|
@ -8,19 +8,20 @@ using namespace CalculatorApp::Common;
|
|||
using namespace concurrency;
|
||||
using namespace std;
|
||||
|
||||
ConversionResultTaskHelper::ConversionResultTaskHelper(unsigned int delay, const function<void()> functionToRun) :
|
||||
m_delay{ delay },
|
||||
m_storedFunction{ functionToRun }
|
||||
ConversionResultTaskHelper::ConversionResultTaskHelper(unsigned int delay, const function<void()> functionToRun)
|
||||
: m_delay{ delay }
|
||||
, m_storedFunction{ functionToRun }
|
||||
{
|
||||
auto token = m_cts.get_token();
|
||||
auto delayTask = CompleteAfter(delay);
|
||||
delayTask.then([this, token]()
|
||||
{
|
||||
delayTask.then(
|
||||
[this, token]() {
|
||||
if (!token.is_canceled())
|
||||
{
|
||||
m_storedFunction();
|
||||
}
|
||||
}, task_continuation_context::use_current());
|
||||
},
|
||||
task_continuation_context::use_current());
|
||||
}
|
||||
|
||||
ConversionResultTaskHelper::~ConversionResultTaskHelper()
|
||||
|
|
|
@ -15,10 +15,7 @@ using namespace Windows::Foundation;
|
|||
using namespace Windows::System;
|
||||
using namespace Windows::ApplicationModel::DataTransfer;
|
||||
|
||||
String^ CopyPasteManager::supportedFormats[] =
|
||||
{
|
||||
StandardDataFormats::Text
|
||||
};
|
||||
String ^ CopyPasteManager::supportedFormats[] = { StandardDataFormats::Text };
|
||||
|
||||
static constexpr wstring_view c_validCharacterSet{ L"0123456789()+-*/.abcdefABCDEF" };
|
||||
|
||||
|
@ -40,41 +37,25 @@ static const wstring c_binProgrammerChars = L"[0-1]+((_|'|`)[0-1]+)*";
|
|||
static const wstring c_uIntSuffixes = L"[uU]?[lL]{0,2}";
|
||||
|
||||
// RegEx Patterns used by various modes
|
||||
static const array<wregex, 1> standardModePatterns =
|
||||
{
|
||||
wregex(c_wspc + c_signedDecFloat + c_wspc)
|
||||
};
|
||||
static const array<wregex, 2> scientificModePatterns =
|
||||
{
|
||||
static const array<wregex, 1> standardModePatterns = { wregex(c_wspc + c_signedDecFloat + c_wspc) };
|
||||
static const array<wregex, 2> scientificModePatterns = {
|
||||
wregex(L"(" + c_wspc + L"[-+]?)|(" + c_wspcLParenSigned + L")" + c_signedDecFloat + c_wspcRParens),
|
||||
wregex(L"(" + c_wspc + L"[-+]?)|(" + c_wspcLParenSigned + L")" + c_signedDecFloat + L"[e]([+]|[-])+\\d+" + c_wspcRParens)
|
||||
wregex(L"(" + c_wspc + L"[-+]?)|(" + c_wspcLParenSigned + L")" + c_signedDecFloat + L"e[+-]?\\d+" + c_wspcRParens)
|
||||
};
|
||||
static const array<array<wregex, 5>, 4> programmerModePatterns =
|
||||
{ {
|
||||
// Hex numbers like 5F, 4A0C, 0xa9, 0xFFull, 47CDh
|
||||
{
|
||||
wregex(c_wspcLParens + L"(0[xX])?" + c_hexProgrammerChars + c_uIntSuffixes + c_wspcRParens),
|
||||
wregex(c_wspcLParens + c_hexProgrammerChars + L"[hH]?" + c_wspcRParens)
|
||||
},
|
||||
static const array<array<wregex, 5>, 4> programmerModePatterns = {
|
||||
{ // Hex numbers like 5F, 4A0C, 0xa9, 0xFFull, 47CDh
|
||||
{ wregex(c_wspcLParens + L"(0[xX])?" + c_hexProgrammerChars + c_uIntSuffixes + c_wspcRParens),
|
||||
wregex(c_wspcLParens + c_hexProgrammerChars + L"[hH]?" + c_wspcRParens) },
|
||||
// Decimal numbers like -145, 145, 0n145, 123ull etc
|
||||
{
|
||||
wregex(c_wspcLParens + L"[-+]?" + c_decProgrammerChars + L"[lL]{0,2}" +c_wspcRParens),
|
||||
wregex(c_wspcLParens + L"(0[nN])?" + c_decProgrammerChars + c_uIntSuffixes + c_wspcRParens)
|
||||
},
|
||||
{ wregex(c_wspcLParens + L"[-+]?" + c_decProgrammerChars + L"[lL]{0,2}" + c_wspcRParens),
|
||||
wregex(c_wspcLParens + L"(0[nN])?" + c_decProgrammerChars + c_uIntSuffixes + c_wspcRParens) },
|
||||
// Octal numbers like 06, 010, 0t77, 0o77, 077ull etc
|
||||
{
|
||||
wregex(c_wspcLParens + L"(0[otOT])?" + c_octProgrammerChars + c_uIntSuffixes + c_wspcRParens)
|
||||
},
|
||||
{ wregex(c_wspcLParens + L"(0[otOT])?" + c_octProgrammerChars + c_uIntSuffixes + c_wspcRParens) },
|
||||
// Binary numbers like 011010110, 0010110, 10101001, 1001b, 0b1001, 0y1001, 0b1001ull
|
||||
{
|
||||
wregex(c_wspcLParens + L"(0[byBY])?" + c_binProgrammerChars + c_uIntSuffixes + c_wspcRParens),
|
||||
wregex(c_wspcLParens + c_binProgrammerChars + L"[bB]?" + c_wspcRParens)
|
||||
}
|
||||
} };
|
||||
static const array<wregex, 1> unitConverterPatterns =
|
||||
{
|
||||
wregex(c_wspc + L"[-+]?\\d*[.]?\\d*" + c_wspc)
|
||||
{ wregex(c_wspcLParens + L"(0[byBY])?" + c_binProgrammerChars + c_uIntSuffixes + c_wspcRParens),
|
||||
wregex(c_wspcLParens + c_binProgrammerChars + L"[bB]?" + c_wspcRParens) } }
|
||||
};
|
||||
static const array<wregex, 1> unitConverterPatterns = { wregex(c_wspc + L"[-+]?\\d*[.]?\\d*" + c_wspc) };
|
||||
|
||||
void CopyPasteManager::CopyToClipboard(String ^ stringToCopy)
|
||||
{
|
||||
|
@ -95,11 +76,11 @@ task<String^> CopyPasteManager::GetStringToPaste(ViewMode mode, CategoryGroupTyp
|
|||
//-- add support to allow pasting for expressions like 1.3e12(as of now we allow 1.3e+12)
|
||||
|
||||
return create_task((dataPackageView->GetTextAsync(::StandardDataFormats::Text)))
|
||||
.then([mode, modeType, programmerNumberBase, bitLengthType](String^ pastedText)
|
||||
{
|
||||
.then(
|
||||
[mode, modeType, programmerNumberBase, bitLengthType](String ^ pastedText) {
|
||||
return ValidatePasteExpression(pastedText, mode, modeType, programmerNumberBase, bitLengthType);
|
||||
}
|
||||
, task_continuation_context::use_arbitrary());
|
||||
},
|
||||
task_continuation_context::use_arbitrary());
|
||||
}
|
||||
|
||||
int CopyPasteManager::ClipboardTextFormat()
|
||||
|
@ -223,7 +204,8 @@ vector<wstring> CopyPasteManager::ExtractOperands(const wstring& pasteExpression
|
|||
if ((pasteExpression.at(i) == L'+') || (pasteExpression.at(i) == L'-'))
|
||||
{
|
||||
// don't break the expression into operands if the encountered character corresponds to sign command(+-)
|
||||
if (isPreviousOpenParen || startOfExpression || isPreviousOperator || ((mode != ViewMode::Programmer) && !((i != 0) && (pasteExpression.at(i - 1) != L'e'))))
|
||||
if (isPreviousOpenParen || startOfExpression || isPreviousOperator
|
||||
|| ((mode != ViewMode::Programmer) && !((i != 0) && (pasteExpression.at(i - 1) != L'e'))))
|
||||
{
|
||||
isPreviousOperator = false;
|
||||
continue;
|
||||
|
@ -453,11 +435,13 @@ bool CopyPasteManager::TryOperandToULL(const wstring& operand, int numberBase, u
|
|||
|
||||
size_t CopyPasteManager::OperandLength(const wstring& operand, ViewMode mode, CategoryGroupType modeType, int programmerNumberBase)
|
||||
{
|
||||
if (modeType == CategoryGroupType::Converter) {
|
||||
if (modeType == CategoryGroupType::Converter)
|
||||
{
|
||||
return operand.length();
|
||||
}
|
||||
|
||||
switch(mode) {
|
||||
switch (mode)
|
||||
{
|
||||
case ViewMode::Standard:
|
||||
case ViewMode::Scientific:
|
||||
return StandardScientificOperandLength(operand);
|
||||
|
@ -494,7 +478,6 @@ size_t CopyPasteManager::StandardScientificOperandLength(const wstring& operand)
|
|||
|
||||
size_t CopyPasteManager::ProgrammerOperandLength(const wstring& operand, int numberBase)
|
||||
{
|
||||
|
||||
vector<wstring> prefixes{};
|
||||
vector<wstring> suffixes{};
|
||||
switch (numberBase)
|
||||
|
|
|
@ -26,7 +26,11 @@ namespace CalculatorApp
|
|||
{
|
||||
public:
|
||||
static void CopyToClipboard(Platform::String ^ stringToCopy);
|
||||
static concurrency::task<Platform::String^> GetStringToPaste(CalculatorApp::Common::ViewMode mode, CalculatorApp::Common::CategoryGroupType modeType, int programmerNumberBase = -1, int bitLengthType = -1);
|
||||
static concurrency::task<Platform::String ^> GetStringToPaste(
|
||||
CalculatorApp::Common::ViewMode mode,
|
||||
CalculatorApp::Common::CategoryGroupType modeType,
|
||||
int programmerNumberBase = -1,
|
||||
int bitLengthType = -1);
|
||||
static bool HasStringToPaste()
|
||||
{
|
||||
return ClipboardTextFormat() >= 0;
|
||||
|
@ -36,25 +40,37 @@ namespace CalculatorApp
|
|||
|
||||
private:
|
||||
static int ClipboardTextFormat();
|
||||
static Platform::String^ ValidatePasteExpression(
|
||||
Platform::String^ pastedText,
|
||||
CalculatorApp::Common::ViewMode mode,
|
||||
int programmerNumberBase,
|
||||
int bitLengthType);
|
||||
static Platform::String^ ValidatePasteExpression(
|
||||
static Platform::String
|
||||
^ ValidatePasteExpression(Platform::String ^ pastedText, CalculatorApp::Common::ViewMode mode, int programmerNumberBase, int bitLengthType);
|
||||
static Platform::String
|
||||
^ ValidatePasteExpression(
|
||||
Platform::String ^ pastedText,
|
||||
CalculatorApp::Common::ViewMode mode,
|
||||
CalculatorApp::Common::CategoryGroupType modeType,
|
||||
int programmerNumberBase,
|
||||
int bitLengthType);
|
||||
|
||||
static std::vector<std::wstring> ExtractOperands(const std::wstring& pasteExpression, CalculatorApp::Common::ViewMode mode, int programmerNumberBase = -1, int bitLengthType = -1);
|
||||
static bool ExpressionRegExMatch(std::vector<std::wstring> operands, CalculatorApp::Common::ViewMode mode, CalculatorApp::Common::CategoryGroupType modeType, int programmerNumberBase = -1, int bitLengthType = -1);
|
||||
static std::vector<std::wstring>
|
||||
ExtractOperands(const std::wstring& pasteExpression, CalculatorApp::Common::ViewMode mode, int programmerNumberBase = -1, int bitLengthType = -1);
|
||||
static bool ExpressionRegExMatch(
|
||||
std::vector<std::wstring> operands,
|
||||
CalculatorApp::Common::ViewMode mode,
|
||||
CalculatorApp::Common::CategoryGroupType modeType,
|
||||
int programmerNumberBase = -1,
|
||||
int bitLengthType = -1);
|
||||
|
||||
static std::pair<size_t, uint64_t> GetMaxOperandLengthAndValue(CalculatorApp::Common::ViewMode mode, CalculatorApp::Common::CategoryGroupType modeType, int programmerNumberBase = -1, int bitLengthType = -1);
|
||||
static std::pair<size_t, uint64_t> GetMaxOperandLengthAndValue(
|
||||
CalculatorApp::Common::ViewMode mode,
|
||||
CalculatorApp::Common::CategoryGroupType modeType,
|
||||
int programmerNumberBase = -1,
|
||||
int bitLengthType = -1);
|
||||
static std::wstring SanitizeOperand(const std::wstring& operand);
|
||||
static bool TryOperandToULL(const std::wstring& operand, int numberBase, unsigned long long int& result);
|
||||
static size_t OperandLength(const std::wstring& operand, CalculatorApp::Common::ViewMode mode, CalculatorApp::Common::CategoryGroupType modeType, int programmerNumberBase = -1);
|
||||
static size_t OperandLength(
|
||||
const std::wstring& operand,
|
||||
CalculatorApp::Common::ViewMode mode,
|
||||
CalculatorApp::Common::CategoryGroupType modeType,
|
||||
int programmerNumberBase = -1);
|
||||
static size_t StandardScientificOperandLength(const std::wstring& operand);
|
||||
static size_t ProgrammerOperandLength(const std::wstring& operand, int numberBase);
|
||||
static std::wstring RemoveUnwantedCharsFromWstring(const std::wstring& input);
|
||||
|
|
|
@ -20,10 +20,23 @@ DateCalculationEngine::DateCalculationEngine(_In_ String^ calendarIdentifier)
|
|||
// Returns: True if function succeeds to calculate the date else returns False
|
||||
bool DateCalculationEngine::AddDuration(_In_ DateTime startDate, _In_ const DateDifference& duration, _Out_ DateTime* endDate)
|
||||
{
|
||||
auto currentCalendarSystem = m_calendar->GetCalendarSystem();
|
||||
|
||||
try
|
||||
{
|
||||
m_calendar->SetDateTime(startDate);
|
||||
|
||||
// The Japanese Era system can have multiple year partitions within the same year.
|
||||
// For example, April 30, 2019 is denoted April 30, Heisei 31; May 1, 2019 is denoted as May 1, Reiwa 1.
|
||||
// The Calendar treats Heisei 31 and Reiwa 1 as separate years, which results in some unexpected behaviors where subtracting a year from Reiwa 1 results
|
||||
// in a date in Heisei 31. To provide the expected result across era boundaries, we first convert the Japanese era system to a Gregorian system, do date
|
||||
// math, and then convert back to the Japanese era system. This works because the Japanese era system maintains the same year/month boundaries and
|
||||
// durations as the Gregorian system and is only different in display value.
|
||||
if (currentCalendarSystem == CalendarIdentifiers::Japanese)
|
||||
{
|
||||
m_calendar->ChangeCalendarSystem(CalendarIdentifiers::Gregorian);
|
||||
}
|
||||
|
||||
if (duration.year != 0)
|
||||
{
|
||||
m_calendar->AddYears(duration.year);
|
||||
|
@ -41,10 +54,15 @@ bool DateCalculationEngine::AddDuration(_In_ DateTime startDate, _In_ const Date
|
|||
}
|
||||
catch (Platform::InvalidArgumentException ^ ex)
|
||||
{
|
||||
// ensure that we revert to the correct calendar system
|
||||
m_calendar->ChangeCalendarSystem(currentCalendarSystem);
|
||||
|
||||
// Do nothing
|
||||
return false;
|
||||
}
|
||||
|
||||
m_calendar->ChangeCalendarSystem(currentCalendarSystem);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -52,12 +70,25 @@ bool DateCalculationEngine::AddDuration(_In_ DateTime startDate, _In_ const Date
|
|||
// Returns: True if function succeeds to calculate the date else returns False
|
||||
bool DateCalculationEngine::SubtractDuration(_In_ DateTime startDate, _In_ const DateDifference& duration, _Out_ DateTime* endDate)
|
||||
{
|
||||
auto currentCalendarSystem = m_calendar->GetCalendarSystem();
|
||||
|
||||
// For Subtract the Algorithm is different than Add. Here the smaller units are subtracted first
|
||||
// and then the larger units.
|
||||
try
|
||||
{
|
||||
m_calendar->SetDateTime(startDate);
|
||||
|
||||
// The Japanese Era system can have multiple year partitions within the same year.
|
||||
// For example, April 30, 2019 is denoted April 30, Heisei 31; May 1, 2019 is denoted as May 1, Reiwa 1.
|
||||
// The Calendar treats Heisei 31 and Reiwa 1 as separate years, which results in some unexpected behaviors where subtracting a year from Reiwa 1 results
|
||||
// in a date in Heisei 31. To provide the expected result across era boundaries, we first convert the Japanese era system to a Gregorian system, do date
|
||||
// math, and then convert back to the Japanese era system. This works because the Japanese era system maintains the same year/month boundaries and
|
||||
// durations as the Gregorian system and is only different in display value.
|
||||
if (currentCalendarSystem == CalendarIdentifiers::Japanese)
|
||||
{
|
||||
m_calendar->ChangeCalendarSystem(CalendarIdentifiers::Gregorian);
|
||||
}
|
||||
|
||||
if (duration.day != 0)
|
||||
{
|
||||
m_calendar->AddDays(-duration.day);
|
||||
|
@ -70,15 +101,19 @@ bool DateCalculationEngine::SubtractDuration(_In_ DateTime startDate, _In_ const
|
|||
{
|
||||
m_calendar->AddYears(-duration.year);
|
||||
}
|
||||
|
||||
*endDate = m_calendar->GetDateTime();
|
||||
}
|
||||
catch (Platform::InvalidArgumentException ^ ex)
|
||||
{
|
||||
// ensure that we revert to the correct calendar system
|
||||
m_calendar->ChangeCalendarSystem(currentCalendarSystem);
|
||||
|
||||
// Do nothing
|
||||
return false;
|
||||
}
|
||||
|
||||
m_calendar->ChangeCalendarSystem(currentCalendarSystem);
|
||||
|
||||
// Check that the UniversalTime value is not negative
|
||||
return (endDate->UniversalTime >= 0);
|
||||
}
|
||||
|
@ -116,8 +151,7 @@ void DateCalculationEngine::GetDateDifference(_In_ DateTime date1, _In_ DateTime
|
|||
UINT approximateDaysInYear;
|
||||
|
||||
// If we're unable to calculate the days-in-month or days-in-year, we'll leave the values at 0.
|
||||
if (TryGetCalendarDaysInMonth(startDate, daysInMonth)
|
||||
&& TryGetCalendarDaysInYear(endDate, approximateDaysInYear))
|
||||
if (TryGetCalendarDaysInMonth(startDate, daysInMonth) && TryGetCalendarDaysInYear(endDate, approximateDaysInYear))
|
||||
{
|
||||
UINT daysIn[c_unitsOfDate] = { approximateDaysInYear, daysInMonth, c_daysInWeek, 1 };
|
||||
|
||||
|
@ -200,7 +234,6 @@ void DateCalculationEngine::GetDateDifference(_In_ DateTime date1, _In_ DateTime
|
|||
difference->day = differenceInDates[3];
|
||||
}
|
||||
|
||||
|
||||
// Private Methods
|
||||
|
||||
// Gets number of days between the two date time values
|
||||
|
@ -274,27 +307,25 @@ bool DateCalculationEngine::TryGetCalendarDaysInYear(_In_ DateTime date, _Out_ U
|
|||
// Adds/Subtracts certain value for a particular date unit
|
||||
DateTime DateCalculationEngine::AdjustCalendarDate(Windows::Foundation::DateTime date, DateUnit dateUnit, int difference)
|
||||
{
|
||||
|
||||
m_calendar->SetDateTime(date);
|
||||
|
||||
switch (dateUnit)
|
||||
{
|
||||
case DateUnit::Year:
|
||||
{
|
||||
// In the Japanese calendar, transition years have 2 partial years.
|
||||
// It is not guaranteed that adding 1 year will always add 365 days in the Japanese Calendar.
|
||||
// To work around this quirk, we will change the calendar system to Gregorian before adding 1 year in the Japanese Calendar case only.
|
||||
// We will then return the calendar system back to the Japanese Calendar.
|
||||
// The Japanese Era system can have multiple year partitions within the same year.
|
||||
// For example, April 30, 2019 is denoted April 30, Heisei 31; May 1, 2019 is denoted as May 1, Reiwa 1.
|
||||
// The Calendar treats Heisei 31 and Reiwa 1 as separate years, which results in some unexpected behaviors where subtracting a year from Reiwa 1 results in
|
||||
// a date in Heisei 31. To provide the expected result across era boundaries, we first convert the Japanese era system to a Gregorian system, do date math,
|
||||
// and then convert back to the Japanese era system. This works because the Japanese era system maintains the same year/month boundaries and durations as
|
||||
// the Gregorian system and is only different in display value.
|
||||
auto currentCalendarSystem = m_calendar->GetCalendarSystem();
|
||||
if (currentCalendarSystem == CalendarIdentifiers::Japanese)
|
||||
{
|
||||
m_calendar->ChangeCalendarSystem(CalendarIdentifiers::Gregorian);
|
||||
}
|
||||
|
||||
switch (dateUnit)
|
||||
{
|
||||
case DateUnit::Year:
|
||||
m_calendar->AddYears(difference);
|
||||
m_calendar->ChangeCalendarSystem(currentCalendarSystem);
|
||||
break;
|
||||
}
|
||||
case DateUnit::Month:
|
||||
m_calendar->AddMonths(difference);
|
||||
break;
|
||||
|
@ -303,5 +334,7 @@ DateTime DateCalculationEngine::AdjustCalendarDate(Windows::Foundation::DateTime
|
|||
break;
|
||||
}
|
||||
|
||||
m_calendar->ChangeCalendarSystem(currentCalendarSystem);
|
||||
|
||||
return m_calendar->GetDateTime();
|
||||
}
|
||||
|
|
|
@ -19,7 +19,8 @@ namespace CalculatorApp
|
|||
{
|
||||
namespace DateCalculation
|
||||
{
|
||||
public enum class _Enum_is_bitflag_ DateUnit
|
||||
public
|
||||
enum class _Enum_is_bitflag_ DateUnit
|
||||
{
|
||||
Year = 0x01,
|
||||
Month = 0x02,
|
||||
|
@ -43,9 +44,17 @@ namespace CalculatorApp
|
|||
DateCalculationEngine(_In_ Platform::String ^ calendarIdentifier);
|
||||
|
||||
// Public Methods
|
||||
bool __nothrow AddDuration(_In_ Windows::Foundation::DateTime startDate, _In_ const DateDifference& duration, _Out_ Windows::Foundation::DateTime *endDate);
|
||||
bool __nothrow SubtractDuration(_In_ Windows::Foundation::DateTime startDate, _In_ const DateDifference& duration, _Out_ Windows::Foundation::DateTime *endDate);
|
||||
void __nothrow GetDateDifference(_In_ Windows::Foundation::DateTime date1, _In_ Windows::Foundation::DateTime date2, _In_ DateUnit outputFormat, _Out_ DateDifference *difference);
|
||||
bool __nothrow
|
||||
AddDuration(_In_ Windows::Foundation::DateTime startDate, _In_ const DateDifference& duration, _Out_ Windows::Foundation::DateTime* endDate);
|
||||
bool __nothrow SubtractDuration(
|
||||
_In_ Windows::Foundation::DateTime startDate,
|
||||
_In_ const DateDifference& duration,
|
||||
_Out_ Windows::Foundation::DateTime* endDate);
|
||||
void __nothrow GetDateDifference(
|
||||
_In_ Windows::Foundation::DateTime date1,
|
||||
_In_ Windows::Foundation::DateTime date2,
|
||||
_In_ DateUnit outputFormat,
|
||||
_Out_ DateDifference* difference);
|
||||
|
||||
private:
|
||||
// Private Variables
|
||||
|
|
|
@ -14,13 +14,13 @@ namespace CalculatorApp
|
|||
|
||||
typedef void (TTarget::*CommandHandlerFunc)(Platform::Object ^);
|
||||
|
||||
DelegateCommand(TTarget^ target, CommandHandlerFunc func):
|
||||
m_weakTarget(target),
|
||||
m_function(func)
|
||||
{ }
|
||||
DelegateCommand(TTarget ^ target, CommandHandlerFunc func)
|
||||
: m_weakTarget(target)
|
||||
, m_function(func)
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
// Explicit, and private, implementation of ICommand, this way of programming makes it so
|
||||
// the ICommand methods will only be available if the ICommand interface is requested via a dynamic_cast
|
||||
// The ICommand interface is meant to be consumed by Xaml and not by the app, this is a defensive measure against
|
||||
|
@ -57,12 +57,10 @@ namespace CalculatorApp
|
|||
|
||||
CommandHandlerFunc m_function;
|
||||
Platform::WeakReference m_weakTarget;
|
||||
|
||||
};
|
||||
|
||||
template <typename TTarget, typename TFuncPtr>
|
||||
DelegateCommand<TTarget>^ MakeDelegate(TTarget^ target, TFuncPtr&& function)
|
||||
{
|
||||
DelegateCommand<TTarget> ^ MakeDelegate(TTarget ^ target, TFuncPtr&& function) {
|
||||
return ref new DelegateCommand<TTarget>(target, std::forward<TFuncPtr>(function));
|
||||
}
|
||||
|
||||
|
|
|
@ -7,20 +7,26 @@
|
|||
|
||||
namespace CalculatorApp::Common
|
||||
{
|
||||
public enum class TokenType
|
||||
public
|
||||
enum class TokenType
|
||||
{
|
||||
Operator,
|
||||
Operand,
|
||||
Separator
|
||||
};
|
||||
|
||||
[Windows::UI::Xaml::Data::Bindable]
|
||||
public ref class DisplayExpressionToken sealed : public Windows::UI::Xaml::Data::INotifyPropertyChanged
|
||||
[Windows::UI::Xaml::Data::Bindable] public ref class DisplayExpressionToken sealed : public Windows::UI::Xaml::Data::INotifyPropertyChanged
|
||||
{
|
||||
internal:
|
||||
DisplayExpressionToken(Platform::String^ token, int tokenPosition, bool fEditable, TokenType type) :
|
||||
m_Token(token), m_TokenPosition(tokenPosition), m_IsTokenEditable(fEditable), m_Type(type), m_OriginalToken(token), m_InEditMode(false)
|
||||
{}
|
||||
internal : DisplayExpressionToken(Platform::String ^ token, int tokenPosition, bool fEditable, TokenType type)
|
||||
: m_Token(token)
|
||||
, m_TokenPosition(tokenPosition)
|
||||
, m_IsTokenEditable(fEditable)
|
||||
, m_Type(type)
|
||||
, m_OriginalToken(token)
|
||||
, m_InEditMode(false)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
OBSERVABLE_OBJECT();
|
||||
OBSERVABLE_PROPERTY_RW(Platform::String ^, Token);
|
||||
|
@ -29,8 +35,12 @@ namespace CalculatorApp::Common
|
|||
OBSERVABLE_PROPERTY_RW(int, CommandIndex);
|
||||
OBSERVABLE_PROPERTY_R(Platform::String ^, OriginalToken);
|
||||
|
||||
property bool IsTokenInEditMode {
|
||||
bool get() { return m_InEditMode; }
|
||||
property bool IsTokenInEditMode
|
||||
{
|
||||
bool get()
|
||||
{
|
||||
return m_InEditMode;
|
||||
}
|
||||
void set(bool val)
|
||||
{
|
||||
if (!val)
|
||||
|
@ -40,8 +50,8 @@ namespace CalculatorApp::Common
|
|||
m_InEditMode = val;
|
||||
}
|
||||
}
|
||||
internal:
|
||||
OBSERVABLE_PROPERTY_RW(TokenType, Type);
|
||||
internal : OBSERVABLE_PROPERTY_RW(TokenType, Type);
|
||||
|
||||
private:
|
||||
bool m_InEditMode;
|
||||
};
|
||||
|
|
|
@ -7,7 +7,10 @@
|
|||
using namespace CalculatorApp::Common;
|
||||
using namespace Windows::Storage::Streams;
|
||||
|
||||
CommandDeserializer::CommandDeserializer(_In_ DataReader^ dataReader) :m_dataReader(dataReader){}
|
||||
CommandDeserializer::CommandDeserializer(_In_ DataReader ^ dataReader)
|
||||
: m_dataReader(dataReader)
|
||||
{
|
||||
}
|
||||
|
||||
std::shared_ptr<IExpressionCommand> CommandDeserializer::Deserialize(_In_ CalculationManager::CommandType cmdType)
|
||||
{
|
||||
|
|
|
@ -7,7 +7,8 @@
|
|||
using namespace CalculatorApp::Common;
|
||||
using namespace Windows::Storage::Streams;
|
||||
|
||||
SerializeCommandVisitor::SerializeCommandVisitor(_In_ DataWriter^ dataWriter) :m_dataWriter(dataWriter)
|
||||
SerializeCommandVisitor::SerializeCommandVisitor(_In_ DataWriter ^ dataWriter)
|
||||
: m_dataWriter(dataWriter)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -92,9 +92,7 @@ namespace CalculatorApp
|
|||
|
||||
WeakReference timerWeakReference(timer);
|
||||
WeakReference buttonWeakReference(button);
|
||||
timer->Tick += ref new EventHandler<Object^>(
|
||||
[buttonWeakReference, timerWeakReference](Object^, Object^)
|
||||
{
|
||||
timer->Tick += ref new EventHandler<Object ^>([buttonWeakReference, timerWeakReference](Object ^, Object ^) {
|
||||
auto button = buttonWeakReference.Resolve<ButtonBase>();
|
||||
if (button)
|
||||
{
|
||||
|
@ -205,10 +203,7 @@ void KeyboardShortcutManager::HonorEscape()
|
|||
}
|
||||
}
|
||||
|
||||
void KeyboardShortcutManager::OnCharacterPropertyChanged(
|
||||
DependencyObject^ target,
|
||||
String^ oldValue,
|
||||
String^ newValue)
|
||||
void KeyboardShortcutManager::OnCharacterPropertyChanged(DependencyObject ^ target, String ^ oldValue, String ^ newValue)
|
||||
{
|
||||
// Writer lock for the static maps
|
||||
reader_writer_lock::scoped_lock lock(s_keyboardShortcutMapLock);
|
||||
|
@ -254,10 +249,7 @@ void KeyboardShortcutManager::OnCharacterPropertyChanged(
|
|||
}
|
||||
}
|
||||
|
||||
void KeyboardShortcutManager::OnVirtualKeyPropertyChanged(
|
||||
DependencyObject^ target,
|
||||
MyVirtualKey /*oldValue*/,
|
||||
MyVirtualKey newValue)
|
||||
void KeyboardShortcutManager::OnVirtualKeyPropertyChanged(DependencyObject ^ target, MyVirtualKey /*oldValue*/, MyVirtualKey newValue)
|
||||
{
|
||||
// Writer lock for the static maps
|
||||
reader_writer_lock::scoped_lock lock(s_keyboardShortcutMapLock);
|
||||
|
@ -280,10 +272,7 @@ void KeyboardShortcutManager::OnVirtualKeyPropertyChanged(
|
|||
}
|
||||
}
|
||||
|
||||
void KeyboardShortcutManager::OnVirtualKeyControlChordPropertyChanged(
|
||||
DependencyObject^ target,
|
||||
MyVirtualKey /*oldValue*/,
|
||||
MyVirtualKey newValue)
|
||||
void KeyboardShortcutManager::OnVirtualKeyControlChordPropertyChanged(DependencyObject ^ target, MyVirtualKey /*oldValue*/, MyVirtualKey newValue)
|
||||
{
|
||||
// Writer lock for the static maps
|
||||
reader_writer_lock::scoped_lock lock(s_keyboardShortcutMapLock);
|
||||
|
@ -312,10 +301,7 @@ void KeyboardShortcutManager::OnVirtualKeyControlChordPropertyChanged(
|
|||
}
|
||||
}
|
||||
|
||||
void KeyboardShortcutManager::OnVirtualKeyShiftChordPropertyChanged(
|
||||
DependencyObject^ target,
|
||||
MyVirtualKey /*oldValue*/,
|
||||
MyVirtualKey newValue)
|
||||
void KeyboardShortcutManager::OnVirtualKeyShiftChordPropertyChanged(DependencyObject ^ target, MyVirtualKey /*oldValue*/, MyVirtualKey newValue)
|
||||
{
|
||||
// Writer lock for the static maps
|
||||
reader_writer_lock::scoped_lock lock(s_keyboardShortcutMapLock);
|
||||
|
@ -338,10 +324,7 @@ void KeyboardShortcutManager::OnVirtualKeyShiftChordPropertyChanged(
|
|||
}
|
||||
}
|
||||
|
||||
void KeyboardShortcutManager::OnVirtualKeyAltChordPropertyChanged(
|
||||
DependencyObject^ target,
|
||||
MyVirtualKey /*oldValue*/,
|
||||
MyVirtualKey newValue)
|
||||
void KeyboardShortcutManager::OnVirtualKeyAltChordPropertyChanged(DependencyObject ^ target, MyVirtualKey /*oldValue*/, MyVirtualKey newValue)
|
||||
{
|
||||
// Writer lock for the static maps
|
||||
reader_writer_lock::scoped_lock lock(s_keyboardShortcutMapLock);
|
||||
|
@ -364,10 +347,7 @@ void KeyboardShortcutManager::OnVirtualKeyAltChordPropertyChanged(
|
|||
}
|
||||
}
|
||||
|
||||
void KeyboardShortcutManager::OnVirtualKeyControlShiftChordPropertyChanged(
|
||||
DependencyObject^ target,
|
||||
MyVirtualKey /*oldValue*/,
|
||||
MyVirtualKey newValue)
|
||||
void KeyboardShortcutManager::OnVirtualKeyControlShiftChordPropertyChanged(DependencyObject ^ target, MyVirtualKey /*oldValue*/, MyVirtualKey newValue)
|
||||
{
|
||||
// Writer lock for the static maps
|
||||
reader_writer_lock::scoped_lock lock(s_keyboardShortcutMapLock);
|
||||
|
@ -390,10 +370,7 @@ void KeyboardShortcutManager::OnVirtualKeyControlShiftChordPropertyChanged(
|
|||
}
|
||||
}
|
||||
|
||||
void KeyboardShortcutManager::OnVirtualKeyInverseChordPropertyChanged(
|
||||
DependencyObject^ target,
|
||||
MyVirtualKey /*oldValue*/,
|
||||
MyVirtualKey newValue)
|
||||
void KeyboardShortcutManager::OnVirtualKeyInverseChordPropertyChanged(DependencyObject ^ target, MyVirtualKey /*oldValue*/, MyVirtualKey newValue)
|
||||
{
|
||||
// Writer lock for the static maps
|
||||
reader_writer_lock::scoped_lock lock(s_keyboardShortcutMapLock);
|
||||
|
@ -416,10 +393,7 @@ void KeyboardShortcutManager::OnVirtualKeyInverseChordPropertyChanged(
|
|||
}
|
||||
}
|
||||
|
||||
void KeyboardShortcutManager::OnVirtualKeyControlInverseChordPropertyChanged(
|
||||
DependencyObject^ target,
|
||||
MyVirtualKey /*oldValue*/,
|
||||
MyVirtualKey newValue)
|
||||
void KeyboardShortcutManager::OnVirtualKeyControlInverseChordPropertyChanged(DependencyObject ^ target, MyVirtualKey /*oldValue*/, MyVirtualKey newValue)
|
||||
{
|
||||
// Writer lock for the static maps
|
||||
reader_writer_lock::scoped_lock lock(s_keyboardShortcutMapLock);
|
||||
|
@ -472,7 +446,9 @@ const std::multimap<MyVirtualKey, WeakReference>& GetCurrentKeyDictionary(MyVirt
|
|||
{
|
||||
return s_VirtualKeyAltChordsForButtons.find(viewId)->second;
|
||||
}
|
||||
else if ((s_ShiftKeyPressed.find(viewId)->second) && ((Window::Current->CoreWindow->GetKeyState(VirtualKey::Control) & CoreVirtualKeyStates::Down) == CoreVirtualKeyStates::Down))
|
||||
else if (
|
||||
(s_ShiftKeyPressed.find(viewId)->second)
|
||||
&& ((Window::Current->CoreWindow->GetKeyState(VirtualKey::Control) & CoreVirtualKeyStates::Down) == CoreVirtualKeyStates::Down))
|
||||
{
|
||||
return s_VirtualKeyControlShiftChordsForButtons.find(viewId)->second;
|
||||
}
|
||||
|
@ -536,9 +512,7 @@ void KeyboardShortcutManager::OnKeyDownHandler(CoreWindow^ sender, KeyEventArgs^
|
|||
bool isShiftKeyPressed = (currentShiftKeyPressed != s_ShiftKeyPressed.end()) && (currentShiftKeyPressed->second);
|
||||
|
||||
// Handle Ctrl + E for DateCalculator
|
||||
if ((key == VirtualKey::E) &&
|
||||
isControlKeyPressed &&
|
||||
!isShiftKeyPressed)
|
||||
if ((key == VirtualKey::E) && isControlKeyPressed && !isShiftKeyPressed)
|
||||
{
|
||||
const auto& lookupMap = GetCurrentKeyDictionary(static_cast<MyVirtualKey>(key));
|
||||
auto buttons = lookupMap.equal_range(static_cast<MyVirtualKey>(key));
|
||||
|
@ -615,9 +589,9 @@ void KeyboardShortcutManager::OnKeyDownHandler(CoreWindow^ sender, KeyEventArgs^
|
|||
{
|
||||
RunFirstEnabledButtonCommand(buttons);
|
||||
|
||||
// Ctrl+C and Ctrl+V shifts focus to some button because of which enter doesn't work after copy/paste. So don't shift focus if Ctrl+C or Ctrl+V is pressed.
|
||||
// When drop down is open, pressing escape shifts focus to clear button. So dont's shift focus if drop down is open.
|
||||
// Ctrl+Insert is equivalent to Ctrl+C and Shift+Insert is equivalent to Ctrl+V
|
||||
// Ctrl+C and Ctrl+V shifts focus to some button because of which enter doesn't work after copy/paste. So don't shift focus if Ctrl+C or Ctrl+V
|
||||
// is pressed. When drop down is open, pressing escape shifts focus to clear button. So dont's shift focus if drop down is open. Ctrl+Insert is
|
||||
// equivalent to Ctrl+C and Shift+Insert is equivalent to Ctrl+V
|
||||
if (currentIsDropDownOpen != s_IsDropDownOpen.end() && !currentIsDropDownOpen->second)
|
||||
{
|
||||
// Do not Light Up Buttons when Ctrl+C, Ctrl+V, Ctrl+Insert or Shift+Insert is pressed
|
||||
|
@ -723,10 +697,8 @@ void KeyboardShortcutManager::Initialize()
|
|||
auto coreWindow = Window::Current->CoreWindow;
|
||||
coreWindow->CharacterReceived +=
|
||||
ref new TypedEventHandler<CoreWindow ^, CharacterReceivedEventArgs ^>(&KeyboardShortcutManager::OnCharacterReceivedHandler);
|
||||
coreWindow->KeyDown +=
|
||||
ref new TypedEventHandler<CoreWindow^, KeyEventArgs^>(&KeyboardShortcutManager::OnKeyDownHandler);
|
||||
coreWindow->KeyUp +=
|
||||
ref new TypedEventHandler<CoreWindow^, KeyEventArgs^>(&KeyboardShortcutManager::OnKeyUpHandler);
|
||||
coreWindow->KeyDown += ref new TypedEventHandler<CoreWindow ^, KeyEventArgs ^>(&KeyboardShortcutManager::OnKeyDownHandler);
|
||||
coreWindow->KeyUp += ref new TypedEventHandler<CoreWindow ^, KeyEventArgs ^>(&KeyboardShortcutManager::OnKeyUpHandler);
|
||||
coreWindow->Dispatcher->AcceleratorKeyActivated +=
|
||||
ref new TypedEventHandler<CoreDispatcher ^, AcceleratorKeyEventArgs ^>(&KeyboardShortcutManager::OnAcceleratorKeyActivated);
|
||||
|
||||
|
|
|
@ -10,10 +10,13 @@ namespace CalculatorApp
|
|||
{
|
||||
namespace Common
|
||||
{
|
||||
public ref class KeyboardShortcutManager sealed
|
||||
public
|
||||
ref class KeyboardShortcutManager sealed
|
||||
{
|
||||
public:
|
||||
KeyboardShortcutManager() {}
|
||||
KeyboardShortcutManager()
|
||||
{
|
||||
}
|
||||
|
||||
DEPENDENCY_PROPERTY_OWNER(KeyboardShortcutManager);
|
||||
|
||||
|
@ -28,7 +31,8 @@ namespace CalculatorApp
|
|||
|
||||
internal :
|
||||
|
||||
static void Initialize();
|
||||
static void
|
||||
Initialize();
|
||||
|
||||
// Sometimes, like with popups, escape is treated as special and even
|
||||
// though it is handled we get it passed through to us. In those cases
|
||||
|
@ -48,46 +52,23 @@ namespace CalculatorApp
|
|||
static void OnWindowClosed(int viewId);
|
||||
|
||||
private:
|
||||
static void OnCharacterPropertyChanged(Windows::UI::Xaml::DependencyObject ^ target, Platform::String ^ oldValue, Platform::String ^ newValue);
|
||||
|
||||
static void OnCharacterPropertyChanged(
|
||||
Windows::UI::Xaml::DependencyObject^ target,
|
||||
Platform::String^ oldValue,
|
||||
Platform::String^ newValue);
|
||||
static void OnVirtualKeyPropertyChanged(Windows::UI::Xaml::DependencyObject ^ target, MyVirtualKey oldValue, MyVirtualKey newValue);
|
||||
|
||||
static void OnVirtualKeyPropertyChanged(
|
||||
Windows::UI::Xaml::DependencyObject^ target,
|
||||
MyVirtualKey oldValue,
|
||||
MyVirtualKey newValue);
|
||||
static void OnVirtualKeyControlChordPropertyChanged(Windows::UI::Xaml::DependencyObject ^ target, MyVirtualKey oldValue, MyVirtualKey newValue);
|
||||
|
||||
static void OnVirtualKeyControlChordPropertyChanged(
|
||||
Windows::UI::Xaml::DependencyObject^ target,
|
||||
MyVirtualKey oldValue,
|
||||
MyVirtualKey newValue);
|
||||
static void OnVirtualKeyShiftChordPropertyChanged(Windows::UI::Xaml::DependencyObject ^ target, MyVirtualKey oldValue, MyVirtualKey newValue);
|
||||
|
||||
static void OnVirtualKeyShiftChordPropertyChanged(
|
||||
Windows::UI::Xaml::DependencyObject^ target,
|
||||
MyVirtualKey oldValue,
|
||||
MyVirtualKey newValue);
|
||||
static void OnVirtualKeyInverseChordPropertyChanged(Windows::UI::Xaml::DependencyObject ^ target, MyVirtualKey oldValue, MyVirtualKey newValue);
|
||||
|
||||
static void OnVirtualKeyInverseChordPropertyChanged(
|
||||
Windows::UI::Xaml::DependencyObject^ target,
|
||||
MyVirtualKey oldValue,
|
||||
MyVirtualKey newValue);
|
||||
static void
|
||||
OnVirtualKeyControlInverseChordPropertyChanged(Windows::UI::Xaml::DependencyObject ^ target, MyVirtualKey oldValue, MyVirtualKey newValue);
|
||||
|
||||
static void OnVirtualKeyControlInverseChordPropertyChanged(
|
||||
Windows::UI::Xaml::DependencyObject^ target,
|
||||
MyVirtualKey oldValue,
|
||||
MyVirtualKey newValue);
|
||||
static void OnVirtualKeyAltChordPropertyChanged(Windows::UI::Xaml::DependencyObject ^ target, MyVirtualKey oldValue, MyVirtualKey newValue);
|
||||
|
||||
static void OnVirtualKeyAltChordPropertyChanged(
|
||||
Windows::UI::Xaml::DependencyObject^ target,
|
||||
MyVirtualKey oldValue,
|
||||
MyVirtualKey newValue);
|
||||
|
||||
static void OnVirtualKeyControlShiftChordPropertyChanged(
|
||||
Windows::UI::Xaml::DependencyObject^ target,
|
||||
MyVirtualKey oldValue,
|
||||
MyVirtualKey newValue);
|
||||
static void
|
||||
OnVirtualKeyControlShiftChordPropertyChanged(Windows::UI::Xaml::DependencyObject ^ target, MyVirtualKey oldValue, MyVirtualKey newValue);
|
||||
|
||||
static void OnCharacterReceivedHandler(Windows::UI::Core::CoreWindow ^ sender, Windows::UI::Core::CharacterReceivedEventArgs ^ args);
|
||||
static void OnKeyDownHandler(Windows::UI::Core::CoreWindow ^ sender, Windows::UI::Core::KeyEventArgs ^ args);
|
||||
|
|
|
@ -42,7 +42,6 @@ static constexpr auto s_openParenResourceKey = L"48";
|
|||
|
||||
LocalizationService ^ LocalizationService::GetInstance()
|
||||
{
|
||||
|
||||
if (s_singletonInstance == nullptr)
|
||||
{
|
||||
// Writer lock for the static maps
|
||||
|
@ -59,8 +58,8 @@ LocalizationService^ LocalizationService::GetInstance()
|
|||
LocalizationService::LocalizationService()
|
||||
{
|
||||
m_language = ApplicationLanguages::Languages->GetAt(0);
|
||||
m_flowDirection = ResourceContext::GetForCurrentView()->QualifierValues->Lookup(L"LayoutDirection")
|
||||
!= L"LTR" ? FlowDirection::RightToLeft : FlowDirection::LeftToRight;
|
||||
m_flowDirection =
|
||||
ResourceContext::GetForCurrentView()->QualifierValues->Lookup(L"LayoutDirection") != L"LTR" ? FlowDirection::RightToLeft : FlowDirection::LeftToRight;
|
||||
|
||||
auto resourceLoader = AppResourceProvider::GetInstance();
|
||||
m_fontFamilyOverride = resourceLoader.GetResourceString(L"LocalizedFontFamilyOverride");
|
||||
|
@ -368,10 +367,8 @@ DateTimeFormatter^ LocalizationService::GetRegionalSettingsAwareDateTimeFormatte
|
|||
|
||||
// If successful, returns a formatter that respects the user's regional format settings,
|
||||
// as configured by running intl.cpl.
|
||||
DateTimeFormatter^ LocalizationService::GetRegionalSettingsAwareDateTimeFormatter(
|
||||
_In_ String^ format,
|
||||
_In_ String^ calendarIdentifier,
|
||||
_In_ String^ clockIdentifier)
|
||||
DateTimeFormatter
|
||||
^ LocalizationService::GetRegionalSettingsAwareDateTimeFormatter(_In_ String ^ format, _In_ String ^ calendarIdentifier, _In_ String ^ clockIdentifier)
|
||||
{
|
||||
IIterable<String ^> ^ languageIdentifiers = LocalizationService::GetLanguageIdentifiers();
|
||||
if (languageIdentifiers == nullptr)
|
||||
|
@ -379,19 +376,13 @@ DateTimeFormatter^ LocalizationService::GetRegionalSettingsAwareDateTimeFormatte
|
|||
languageIdentifiers = ApplicationLanguages::Languages;
|
||||
}
|
||||
|
||||
return ref new DateTimeFormatter(
|
||||
format,
|
||||
languageIdentifiers,
|
||||
GlobalizationPreferences::HomeGeographicRegion,
|
||||
calendarIdentifier,
|
||||
clockIdentifier);
|
||||
return ref new DateTimeFormatter(format, languageIdentifiers, GlobalizationPreferences::HomeGeographicRegion, calendarIdentifier, clockIdentifier);
|
||||
}
|
||||
|
||||
CurrencyFormatter ^ LocalizationService::GetRegionalSettingsAwareCurrencyFormatter()
|
||||
{
|
||||
String^ userCurrency = (GlobalizationPreferences::Currencies->Size > 0)
|
||||
? GlobalizationPreferences::Currencies->GetAt(0)
|
||||
: StringReference(DefaultCurrencyCode.data());
|
||||
String ^ userCurrency =
|
||||
(GlobalizationPreferences::Currencies->Size > 0) ? GlobalizationPreferences::Currencies->GetAt(0) : StringReference(DefaultCurrencyCode.data());
|
||||
|
||||
IIterable<String ^> ^ languageIdentifiers = LocalizationService::GetLanguageIdentifiers();
|
||||
if (languageIdentifiers == nullptr)
|
||||
|
@ -399,10 +390,7 @@ CurrencyFormatter^ LocalizationService::GetRegionalSettingsAwareCurrencyFormatte
|
|||
languageIdentifiers = ApplicationLanguages::Languages;
|
||||
}
|
||||
|
||||
auto currencyFormatter = ref new CurrencyFormatter(
|
||||
userCurrency,
|
||||
languageIdentifiers,
|
||||
GlobalizationPreferences::HomeGeographicRegion);
|
||||
auto currencyFormatter = ref new CurrencyFormatter(userCurrency, languageIdentifiers, GlobalizationPreferences::HomeGeographicRegion);
|
||||
|
||||
int fractionDigits = LocalizationSettings::GetInstance().GetCurrencyTrailingDigits();
|
||||
currencyFormatter->FractionDigits = fractionDigits;
|
||||
|
@ -446,8 +434,7 @@ unordered_map<wstring, wstring> LocalizationService::GetTokenToReadableNameMap()
|
|||
// change given that the engine heavily relies on perfect ordering of certain elements.
|
||||
// To compromise, we'll declare a map from engine resource key to automation name from the
|
||||
// standard project resources.
|
||||
static vector<pair<wstring, wstring>> s_parenEngineKeyResourceMap = {
|
||||
// Sine permutations
|
||||
static vector<pair<wstring, wstring>> s_parenEngineKeyResourceMap = { // Sine permutations
|
||||
make_pair<wstring, wstring>(L"67", L"SineDegrees"),
|
||||
make_pair<wstring, wstring>(L"73", L"SineRadians"),
|
||||
make_pair<wstring, wstring>(L"79", L"SineGradians"),
|
||||
|
@ -484,8 +471,7 @@ unordered_map<wstring, wstring> LocalizationService::GetTokenToReadableNameMap()
|
|||
make_pair<wstring, wstring>(L"91", L"Square")
|
||||
};
|
||||
|
||||
static vector<pair<wstring, wstring>> s_noParenEngineKeyResourceMap = {
|
||||
// Programmer mode functions
|
||||
static vector<pair<wstring, wstring>> s_noParenEngineKeyResourceMap = { // Programmer mode functions
|
||||
make_pair<wstring, wstring>(L"9", L"LeftShift"),
|
||||
make_pair<wstring, wstring>(L"10", L"RightShift"),
|
||||
|
||||
|
|
|
@ -5,30 +5,32 @@
|
|||
|
||||
#include "Utils.h"
|
||||
|
||||
namespace CalculatorApp { namespace Common
|
||||
namespace CalculatorApp
|
||||
{
|
||||
namespace Common
|
||||
{
|
||||
namespace LocalizationServiceProperties
|
||||
{
|
||||
static constexpr std::wstring_view DefaultCurrencyCode{ L"USD" };
|
||||
}
|
||||
|
||||
public enum class LanguageFontType
|
||||
public
|
||||
enum class LanguageFontType
|
||||
{
|
||||
UIText,
|
||||
UICaption,
|
||||
};
|
||||
|
||||
public ref class LocalizationService sealed
|
||||
public
|
||||
ref class LocalizationService sealed
|
||||
{
|
||||
public:
|
||||
|
||||
DEPENDENCY_PROPERTY_OWNER(LocalizationService);
|
||||
|
||||
DEPENDENCY_PROPERTY_ATTACHED_WITH_DEFAULT_AND_CALLBACK(LanguageFontType, FontType, LanguageFontType::UIText);
|
||||
DEPENDENCY_PROPERTY_ATTACHED_WITH_CALLBACK(double, FontSize);
|
||||
|
||||
internal:
|
||||
static LocalizationService^ GetInstance();
|
||||
internal : static LocalizationService ^ GetInstance();
|
||||
|
||||
Windows::UI::Xaml::FlowDirection GetFlowDirection();
|
||||
bool IsRtlLayout();
|
||||
|
@ -41,7 +43,8 @@ namespace CalculatorApp { namespace Common
|
|||
|
||||
static Windows::Globalization::NumberFormatting::DecimalFormatter ^ GetRegionalSettingsAwareDecimalFormatter();
|
||||
static Windows::Globalization::DateTimeFormatting::DateTimeFormatter ^ GetRegionalSettingsAwareDateTimeFormatter(_In_ Platform::String ^ format);
|
||||
static Windows::Globalization::DateTimeFormatting::DateTimeFormatter^ GetRegionalSettingsAwareDateTimeFormatter(
|
||||
static Windows::Globalization::DateTimeFormatting::DateTimeFormatter
|
||||
^ GetRegionalSettingsAwareDateTimeFormatter(
|
||||
_In_ Platform::String ^ format,
|
||||
_In_ Platform::String ^ calendarIdentifier,
|
||||
_In_ Platform::String ^ clockIdentifier);
|
||||
|
@ -59,7 +62,10 @@ namespace CalculatorApp { namespace Common
|
|||
|
||||
// Attached property callbacks
|
||||
static void OnFontTypePropertyChanged(Windows::UI::Xaml::DependencyObject ^ target, LanguageFontType oldValue, LanguageFontType newValue);
|
||||
static void OnFontWeightPropertyChanged(Windows::UI::Xaml::DependencyObject^ target, Windows::UI::Text::FontWeight oldValue, Windows::UI::Text::FontWeight newValue);
|
||||
static void OnFontWeightPropertyChanged(
|
||||
Windows::UI::Xaml::DependencyObject ^ target,
|
||||
Windows::UI::Text::FontWeight oldValue,
|
||||
Windows::UI::Text::FontWeight newValue);
|
||||
static void OnFontSizePropertyChanged(Windows::UI::Xaml::DependencyObject ^ target, double oldValue, double newValue);
|
||||
|
||||
static void UpdateFontFamilyAndSize(Windows::UI::Xaml::DependencyObject ^ target);
|
||||
|
@ -81,5 +87,5 @@ namespace CalculatorApp { namespace Common
|
|||
double m_uiCaptionFontScaleFactorOverride;
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,9 +29,7 @@ namespace CalculatorApp
|
|||
}
|
||||
|
||||
wchar_t resolvedName[LOCALE_NAME_MAX_LENGTH];
|
||||
result = ResolveLocaleName(formatter->ResolvedLanguage->Data(),
|
||||
resolvedName,
|
||||
LOCALE_NAME_MAX_LENGTH);
|
||||
result = ResolveLocaleName(formatter->ResolvedLanguage->Data(), resolvedName, LOCALE_NAME_MAX_LENGTH);
|
||||
if (result == 0)
|
||||
{
|
||||
throw std::runtime_error("Unexpected error resolving locale name");
|
||||
|
@ -40,30 +38,21 @@ namespace CalculatorApp
|
|||
{
|
||||
m_resolvedName = resolvedName;
|
||||
wchar_t decimalString[LocaleSettingBufferSize] = L"";
|
||||
result = GetLocaleInfoEx(m_resolvedName.c_str(),
|
||||
LOCALE_SDECIMAL,
|
||||
decimalString,
|
||||
static_cast<int>(std::size(decimalString)));
|
||||
result = GetLocaleInfoEx(m_resolvedName.c_str(), LOCALE_SDECIMAL, decimalString, static_cast<int>(std::size(decimalString)));
|
||||
if (result == 0)
|
||||
{
|
||||
throw std::runtime_error("Unexpected error while getting locale info");
|
||||
}
|
||||
|
||||
wchar_t groupingSymbolString[LocaleSettingBufferSize] = L"";
|
||||
result = GetLocaleInfoEx(m_resolvedName.c_str(),
|
||||
LOCALE_STHOUSAND,
|
||||
groupingSymbolString,
|
||||
static_cast<int>(std::size(groupingSymbolString)));
|
||||
result = GetLocaleInfoEx(m_resolvedName.c_str(), LOCALE_STHOUSAND, groupingSymbolString, static_cast<int>(std::size(groupingSymbolString)));
|
||||
if (result == 0)
|
||||
{
|
||||
throw std::runtime_error("Unexpected error while getting locale info");
|
||||
}
|
||||
|
||||
wchar_t numberGroupingString[LocaleSettingBufferSize] = L"";
|
||||
result = GetLocaleInfoEx(m_resolvedName.c_str(),
|
||||
LOCALE_SGROUPING,
|
||||
numberGroupingString,
|
||||
static_cast<int>(std::size(numberGroupingString)));
|
||||
result = GetLocaleInfoEx(m_resolvedName.c_str(), LOCALE_SGROUPING, numberGroupingString, static_cast<int>(std::size(numberGroupingString)));
|
||||
if (result == 0)
|
||||
{
|
||||
throw std::runtime_error("Unexpected error while getting locale info");
|
||||
|
@ -71,7 +60,8 @@ namespace CalculatorApp
|
|||
|
||||
// Get locale info for List Separator, eg. comma is used in many locales
|
||||
wchar_t listSeparatorString[4] = L"";
|
||||
result = ::GetLocaleInfoEx(LOCALE_NAME_USER_DEFAULT,
|
||||
result = ::GetLocaleInfoEx(
|
||||
LOCALE_NAME_USER_DEFAULT,
|
||||
LOCALE_SLIST,
|
||||
listSeparatorString,
|
||||
static_cast<int>(std::size(listSeparatorString))); // Max length of the expected return value is 4
|
||||
|
@ -81,7 +71,8 @@ namespace CalculatorApp
|
|||
}
|
||||
|
||||
int currencyTrailingDigits = 0;
|
||||
result = GetLocaleInfoEx(m_resolvedName.c_str(),
|
||||
result = GetLocaleInfoEx(
|
||||
m_resolvedName.c_str(),
|
||||
LOCALE_ICURRDIGITS | LOCALE_RETURN_NUMBER,
|
||||
(LPWSTR)¤cyTrailingDigits,
|
||||
sizeof(currencyTrailingDigits) / sizeof(WCHAR));
|
||||
|
@ -93,7 +84,8 @@ namespace CalculatorApp
|
|||
// Currency symbol precedence is either 0 or 1.
|
||||
// A value of 0 indicates the symbol follows the currency value.
|
||||
int currencySymbolPrecedence = 1;
|
||||
result = GetLocaleInfoEx(LOCALE_NAME_USER_DEFAULT,
|
||||
result = GetLocaleInfoEx(
|
||||
LOCALE_NAME_USER_DEFAULT,
|
||||
LOCALE_IPOSSYMPRECEDES | LOCALE_RETURN_NUMBER,
|
||||
(LPWSTR)¤cySymbolPrecedence,
|
||||
sizeof(currencySymbolPrecedence) / sizeof(WCHAR));
|
||||
|
@ -112,16 +104,14 @@ namespace CalculatorApp
|
|||
// Note: This function returns 0 on failure.
|
||||
// We'll ignore the failure in that case and the CalendarIdentifier would get set to GregorianCalendar.
|
||||
CALID calId;
|
||||
::GetLocaleInfoEx(LOCALE_NAME_USER_DEFAULT,
|
||||
LOCALE_ICALENDARTYPE | LOCALE_RETURN_NUMBER,
|
||||
reinterpret_cast<PWSTR>(&calId),
|
||||
sizeof(calId));
|
||||
::GetLocaleInfoEx(LOCALE_NAME_USER_DEFAULT, LOCALE_ICALENDARTYPE | LOCALE_RETURN_NUMBER, reinterpret_cast<PWSTR>(&calId), sizeof(calId));
|
||||
|
||||
m_calendarIdentifier = GetCalendarIdentifierFromCalid(calId);
|
||||
|
||||
// Get FirstDayOfWeek Date and Time setting
|
||||
wchar_t day[80] = L"";
|
||||
::GetLocaleInfoEx(LOCALE_NAME_USER_DEFAULT,
|
||||
::GetLocaleInfoEx(
|
||||
LOCALE_NAME_USER_DEFAULT,
|
||||
LOCALE_IFIRSTDAYOFWEEK, // The first day in a week
|
||||
reinterpret_cast<PWSTR>(day), // Argument is of type PWSTR
|
||||
static_cast<int>(std::size(day))); // Max return size are 80 characters
|
||||
|
|
|
@ -19,13 +19,7 @@ namespace CalculatorApp
|
|||
std::unique_ptr<wchar_t[]> spBuffer = std::unique_ptr<wchar_t[]>(new wchar_t[length]);
|
||||
va_list args = NULL;
|
||||
va_start(args, pMessage);
|
||||
DWORD fmtReturnVal = FormatMessage(FORMAT_MESSAGE_FROM_STRING,
|
||||
pMessage,
|
||||
0,
|
||||
0,
|
||||
spBuffer.get(),
|
||||
length,
|
||||
&args);
|
||||
DWORD fmtReturnVal = FormatMessage(FORMAT_MESSAGE_FROM_STRING, pMessage, 0, 0, spBuffer.get(), length, &args);
|
||||
va_end(args);
|
||||
|
||||
if (fmtReturnVal != 0)
|
||||
|
|
|
@ -7,7 +7,8 @@ namespace CalculatorApp
|
|||
{
|
||||
namespace Common
|
||||
{
|
||||
public enum class MyVirtualKey
|
||||
public
|
||||
enum class MyVirtualKey
|
||||
{
|
||||
None = 0,
|
||||
LeftButton = 1,
|
||||
|
|
|
@ -49,38 +49,150 @@ static constexpr int CURRENCY_ID = 16;
|
|||
// ^^^ THESE CONSTANTS SHOULD NEVER CHANGE ^^^
|
||||
|
||||
// The order of items in this list determines the order of items in the menu.
|
||||
static constexpr array<const NavCategoryInitializer, 17> s_categoryManifest = {
|
||||
NavCategoryInitializer { ViewMode::Standard, STANDARD_ID, L"Standard", L"StandardMode", L"\uE8EF", CategoryGroupType::Calculator, MyVirtualKey::Number1, SUPPORTS_ALL },
|
||||
NavCategoryInitializer { ViewMode::Scientific, SCIENTIFIC_ID, L"Scientific", L"ScientificMode", L"\uF196", CategoryGroupType::Calculator, MyVirtualKey::Number2, SUPPORTS_ALL },
|
||||
NavCategoryInitializer { ViewMode::Programmer, PROGRAMMER_ID, L"Programmer", L"ProgrammerMode", L"\uECCE", CategoryGroupType::Calculator, MyVirtualKey::Number3, SUPPORTS_ALL },
|
||||
NavCategoryInitializer { ViewMode::Date, DATE_ID, L"Date", L"DateCalculationMode", L"\uE787", CategoryGroupType::Calculator, MyVirtualKey::Number4, SUPPORTS_ALL },
|
||||
NavCategoryInitializer { ViewMode::Currency, CURRENCY_ID, L"Currency", L"CategoryName_Currency", L"\uEB0D", CategoryGroupType::Converter, MyVirtualKey::None, POSITIVE_ONLY },
|
||||
NavCategoryInitializer { ViewMode::Volume, VOLUME_ID, L"Volume", L"CategoryName_Volume", L"\uF1AA", CategoryGroupType::Converter, MyVirtualKey::None, POSITIVE_ONLY },
|
||||
NavCategoryInitializer { ViewMode::Length, LENGTH_ID, L"Length", L"CategoryName_Length", L"\uECC6", CategoryGroupType::Converter, MyVirtualKey::None, POSITIVE_ONLY },
|
||||
NavCategoryInitializer { ViewMode::Weight, WEIGHT_ID, L"Weight and Mass", L"CategoryName_Weight", L"\uF4C1", CategoryGroupType::Converter, MyVirtualKey::None, POSITIVE_ONLY },
|
||||
NavCategoryInitializer { ViewMode::Temperature, TEMPERATURE_ID, L"Temperature", L"CategoryName_Temperature", L"\uE7A3", CategoryGroupType::Converter, MyVirtualKey::None, SUPPORTS_NEGATIVE },
|
||||
NavCategoryInitializer { ViewMode::Energy, ENERGY_ID, L"Energy", L"CategoryName_Energy", L"\uECAD", CategoryGroupType::Converter, MyVirtualKey::None, POSITIVE_ONLY },
|
||||
NavCategoryInitializer { ViewMode::Area, AREA_ID, L"Area", L"CategoryName_Area", L"\uE809", CategoryGroupType::Converter, MyVirtualKey::None, POSITIVE_ONLY },
|
||||
NavCategoryInitializer { ViewMode::Speed, SPEED_ID, L"Speed", L"CategoryName_Speed", L"\uEADA", CategoryGroupType::Converter, MyVirtualKey::None, POSITIVE_ONLY },
|
||||
NavCategoryInitializer { ViewMode::Time, TIME_ID, L"Time", L"CategoryName_Time", L"\uE917", CategoryGroupType::Converter, MyVirtualKey::None, POSITIVE_ONLY },
|
||||
NavCategoryInitializer { ViewMode::Power, POWER_ID, L"Power", L"CategoryName_Power", L"\uE945", CategoryGroupType::Converter, MyVirtualKey::None, POSITIVE_ONLY },
|
||||
NavCategoryInitializer { ViewMode::Data, DATA_ID, L"Data", L"CategoryName_Data", L"\uF20F", CategoryGroupType::Converter, MyVirtualKey::None, POSITIVE_ONLY },
|
||||
NavCategoryInitializer { ViewMode::Pressure, PRESSURE_ID, L"Pressure", L"CategoryName_Pressure", L"\uEC4A", CategoryGroupType::Converter, MyVirtualKey::None, POSITIVE_ONLY },
|
||||
NavCategoryInitializer { ViewMode::Angle, ANGLE_ID, L"Angle", L"CategoryName_Angle", L"\uF515", CategoryGroupType::Converter, MyVirtualKey::None, POSITIVE_ONLY }
|
||||
};
|
||||
static constexpr array<const NavCategoryInitializer, 17> s_categoryManifest = { NavCategoryInitializer{ ViewMode::Standard,
|
||||
STANDARD_ID,
|
||||
L"Standard",
|
||||
L"StandardMode",
|
||||
L"\uE8EF",
|
||||
CategoryGroupType::Calculator,
|
||||
MyVirtualKey::Number1,
|
||||
SUPPORTS_ALL },
|
||||
NavCategoryInitializer{ ViewMode::Scientific,
|
||||
SCIENTIFIC_ID,
|
||||
L"Scientific",
|
||||
L"ScientificMode",
|
||||
L"\uF196",
|
||||
CategoryGroupType::Calculator,
|
||||
MyVirtualKey::Number2,
|
||||
SUPPORTS_ALL },
|
||||
NavCategoryInitializer{ ViewMode::Programmer,
|
||||
PROGRAMMER_ID,
|
||||
L"Programmer",
|
||||
L"ProgrammerMode",
|
||||
L"\uECCE",
|
||||
CategoryGroupType::Calculator,
|
||||
MyVirtualKey::Number3,
|
||||
SUPPORTS_ALL },
|
||||
NavCategoryInitializer{ ViewMode::Date,
|
||||
DATE_ID,
|
||||
L"Date",
|
||||
L"DateCalculationMode",
|
||||
L"\uE787",
|
||||
CategoryGroupType::Calculator,
|
||||
MyVirtualKey::Number4,
|
||||
SUPPORTS_ALL },
|
||||
NavCategoryInitializer{ ViewMode::Currency,
|
||||
CURRENCY_ID,
|
||||
L"Currency",
|
||||
L"CategoryName_Currency",
|
||||
L"\uEB0D",
|
||||
CategoryGroupType::Converter,
|
||||
MyVirtualKey::None,
|
||||
POSITIVE_ONLY },
|
||||
NavCategoryInitializer{ ViewMode::Volume,
|
||||
VOLUME_ID,
|
||||
L"Volume",
|
||||
L"CategoryName_Volume",
|
||||
L"\uF1AA",
|
||||
CategoryGroupType::Converter,
|
||||
MyVirtualKey::None,
|
||||
POSITIVE_ONLY },
|
||||
NavCategoryInitializer{ ViewMode::Length,
|
||||
LENGTH_ID,
|
||||
L"Length",
|
||||
L"CategoryName_Length",
|
||||
L"\uECC6",
|
||||
CategoryGroupType::Converter,
|
||||
MyVirtualKey::None,
|
||||
POSITIVE_ONLY },
|
||||
NavCategoryInitializer{ ViewMode::Weight,
|
||||
WEIGHT_ID,
|
||||
L"Weight and Mass",
|
||||
L"CategoryName_Weight",
|
||||
L"\uF4C1",
|
||||
CategoryGroupType::Converter,
|
||||
MyVirtualKey::None,
|
||||
POSITIVE_ONLY },
|
||||
NavCategoryInitializer{ ViewMode::Temperature,
|
||||
TEMPERATURE_ID,
|
||||
L"Temperature",
|
||||
L"CategoryName_Temperature",
|
||||
L"\uE7A3",
|
||||
CategoryGroupType::Converter,
|
||||
MyVirtualKey::None,
|
||||
SUPPORTS_NEGATIVE },
|
||||
NavCategoryInitializer{ ViewMode::Energy,
|
||||
ENERGY_ID,
|
||||
L"Energy",
|
||||
L"CategoryName_Energy",
|
||||
L"\uECAD",
|
||||
CategoryGroupType::Converter,
|
||||
MyVirtualKey::None,
|
||||
POSITIVE_ONLY },
|
||||
NavCategoryInitializer{ ViewMode::Area,
|
||||
AREA_ID,
|
||||
L"Area",
|
||||
L"CategoryName_Area",
|
||||
L"\uE809",
|
||||
CategoryGroupType::Converter,
|
||||
MyVirtualKey::None,
|
||||
POSITIVE_ONLY },
|
||||
NavCategoryInitializer{ ViewMode::Speed,
|
||||
SPEED_ID,
|
||||
L"Speed",
|
||||
L"CategoryName_Speed",
|
||||
L"\uEADA",
|
||||
CategoryGroupType::Converter,
|
||||
MyVirtualKey::None,
|
||||
POSITIVE_ONLY },
|
||||
NavCategoryInitializer{ ViewMode::Time,
|
||||
TIME_ID,
|
||||
L"Time",
|
||||
L"CategoryName_Time",
|
||||
L"\uE917",
|
||||
CategoryGroupType::Converter,
|
||||
MyVirtualKey::None,
|
||||
POSITIVE_ONLY },
|
||||
NavCategoryInitializer{ ViewMode::Power,
|
||||
POWER_ID,
|
||||
L"Power",
|
||||
L"CategoryName_Power",
|
||||
L"\uE945",
|
||||
CategoryGroupType::Converter,
|
||||
MyVirtualKey::None,
|
||||
POSITIVE_ONLY },
|
||||
NavCategoryInitializer{ ViewMode::Data,
|
||||
DATA_ID,
|
||||
L"Data",
|
||||
L"CategoryName_Data",
|
||||
L"\uF20F",
|
||||
CategoryGroupType::Converter,
|
||||
MyVirtualKey::None,
|
||||
POSITIVE_ONLY },
|
||||
NavCategoryInitializer{ ViewMode::Pressure,
|
||||
PRESSURE_ID,
|
||||
L"Pressure",
|
||||
L"CategoryName_Pressure",
|
||||
L"\uEC4A",
|
||||
CategoryGroupType::Converter,
|
||||
MyVirtualKey::None,
|
||||
POSITIVE_ONLY },
|
||||
NavCategoryInitializer{ ViewMode::Angle,
|
||||
ANGLE_ID,
|
||||
L"Angle",
|
||||
L"CategoryName_Angle",
|
||||
L"\uF515",
|
||||
CategoryGroupType::Converter,
|
||||
MyVirtualKey::None,
|
||||
POSITIVE_ONLY } };
|
||||
|
||||
// This function should only be used when storing the mode to app data.
|
||||
int NavCategory::Serialize(ViewMode mode)
|
||||
{
|
||||
auto iter = find_if(begin(s_categoryManifest), end(s_categoryManifest),
|
||||
[mode](const NavCategoryInitializer& initializer)
|
||||
{
|
||||
return initializer.viewMode == mode;
|
||||
});
|
||||
auto iter =
|
||||
find_if(begin(s_categoryManifest), end(s_categoryManifest), [mode](const NavCategoryInitializer& initializer) { return initializer.viewMode == mode; });
|
||||
|
||||
return (iter != s_categoryManifest.end())
|
||||
? iter->serializationId
|
||||
: -1;
|
||||
return (iter != s_categoryManifest.end()) ? iter->serializationId : -1;
|
||||
}
|
||||
|
||||
// This function should only be used when restoring the mode from app data.
|
||||
|
@ -93,9 +205,7 @@ ViewMode NavCategory::Deserialize(Platform::Object^ obj)
|
|||
if (boxed != nullptr)
|
||||
{
|
||||
int serializationId = boxed->Value;
|
||||
auto iter = find_if(begin(s_categoryManifest), end(s_categoryManifest),
|
||||
[serializationId](const NavCategoryInitializer& initializer)
|
||||
{
|
||||
auto iter = find_if(begin(s_categoryManifest), end(s_categoryManifest), [serializationId](const NavCategoryInitializer& initializer) {
|
||||
return initializer.serializationId == serializationId;
|
||||
});
|
||||
|
||||
|
@ -110,11 +220,8 @@ ViewMode NavCategory::Deserialize(Platform::Object^ obj)
|
|||
|
||||
bool NavCategory::IsValidViewMode(ViewMode mode)
|
||||
{
|
||||
auto iter = find_if(begin(s_categoryManifest), end(s_categoryManifest),
|
||||
[mode](const NavCategoryInitializer& initializer)
|
||||
{
|
||||
return initializer.viewMode == mode;
|
||||
});
|
||||
auto iter =
|
||||
find_if(begin(s_categoryManifest), end(s_categoryManifest), [mode](const NavCategoryInitializer& initializer) { return initializer.viewMode == mode; });
|
||||
|
||||
return iter != s_categoryManifest.end();
|
||||
}
|
||||
|
@ -138,9 +245,7 @@ bool NavCategory::IsConverterViewMode(ViewMode mode)
|
|||
|
||||
bool NavCategory::IsModeInCategoryGroup(ViewMode mode, CategoryGroupType type)
|
||||
{
|
||||
auto iter = find_if(begin(s_categoryManifest), end(s_categoryManifest),
|
||||
[mode, type](const NavCategoryInitializer& initializer)
|
||||
{
|
||||
auto iter = find_if(begin(s_categoryManifest), end(s_categoryManifest), [mode, type](const NavCategoryInitializer& initializer) {
|
||||
return initializer.viewMode == mode && initializer.groupType == type;
|
||||
});
|
||||
|
||||
|
@ -149,54 +254,35 @@ bool NavCategory::IsModeInCategoryGroup(ViewMode mode, CategoryGroupType type)
|
|||
|
||||
String ^ NavCategory::GetFriendlyName(ViewMode mode)
|
||||
{
|
||||
auto iter = find_if(begin(s_categoryManifest), end(s_categoryManifest),
|
||||
[mode](const NavCategoryInitializer& initializer)
|
||||
{
|
||||
return initializer.viewMode == mode;
|
||||
});
|
||||
auto iter =
|
||||
find_if(begin(s_categoryManifest), end(s_categoryManifest), [mode](const NavCategoryInitializer& initializer) { return initializer.viewMode == mode; });
|
||||
|
||||
return (iter != s_categoryManifest.end())
|
||||
? StringReference(iter->friendlyName)
|
||||
: L"None";
|
||||
return (iter != s_categoryManifest.end()) ? StringReference(iter->friendlyName) : L"None";
|
||||
}
|
||||
|
||||
ViewMode NavCategory::GetViewModeForFriendlyName(String ^ name)
|
||||
{
|
||||
auto iter = find_if(begin(s_categoryManifest), end(s_categoryManifest),
|
||||
[name](const NavCategoryInitializer& initializer)
|
||||
{
|
||||
auto iter = find_if(begin(s_categoryManifest), end(s_categoryManifest), [name](const NavCategoryInitializer& initializer) {
|
||||
return wcscmp(initializer.friendlyName, name->Data()) == 0;
|
||||
});
|
||||
|
||||
return (iter != s_categoryManifest.end())
|
||||
? iter->viewMode
|
||||
: ViewMode::None;
|
||||
return (iter != s_categoryManifest.end()) ? iter->viewMode : ViewMode::None;
|
||||
}
|
||||
|
||||
String ^ NavCategory::GetNameResourceKey(ViewMode mode)
|
||||
{
|
||||
auto iter = find_if(begin(s_categoryManifest), end(s_categoryManifest),
|
||||
[mode](const NavCategoryInitializer& initializer)
|
||||
{
|
||||
return initializer.viewMode == mode;
|
||||
});
|
||||
auto iter =
|
||||
find_if(begin(s_categoryManifest), end(s_categoryManifest), [mode](const NavCategoryInitializer& initializer) { return initializer.viewMode == mode; });
|
||||
|
||||
return (iter != s_categoryManifest.end())
|
||||
? StringReference(iter->nameResourceKey) + "Text"
|
||||
: nullptr;
|
||||
return (iter != s_categoryManifest.end()) ? StringReference(iter->nameResourceKey) + "Text" : nullptr;
|
||||
}
|
||||
|
||||
CategoryGroupType NavCategory::GetGroupType(ViewMode mode)
|
||||
{
|
||||
auto iter = find_if(begin(s_categoryManifest), end(s_categoryManifest),
|
||||
[mode](const NavCategoryInitializer& initializer)
|
||||
{
|
||||
return initializer.viewMode == mode;
|
||||
});
|
||||
auto iter =
|
||||
find_if(begin(s_categoryManifest), end(s_categoryManifest), [mode](const NavCategoryInitializer& initializer) { return initializer.viewMode == mode; });
|
||||
|
||||
return (iter != s_categoryManifest.end())
|
||||
? iter->groupType
|
||||
: CategoryGroupType::None;
|
||||
return (iter != s_categoryManifest.end()) ? iter->groupType : CategoryGroupType::None;
|
||||
}
|
||||
|
||||
// GetIndex is 0-based, GetPosition is 1-based
|
||||
|
@ -210,9 +296,7 @@ int NavCategory::GetFlatIndex(ViewMode mode)
|
|||
{
|
||||
int index = -1;
|
||||
CategoryGroupType type = CategoryGroupType::None;
|
||||
auto iter = find_if(begin(s_categoryManifest), end(s_categoryManifest),
|
||||
[mode, &type, &index](const NavCategoryInitializer& initializer)
|
||||
{
|
||||
auto iter = find_if(begin(s_categoryManifest), end(s_categoryManifest), [mode, &type, &index](const NavCategoryInitializer& initializer) {
|
||||
index++;
|
||||
if (initializer.groupType != type)
|
||||
{
|
||||
|
@ -223,18 +307,14 @@ int NavCategory::GetFlatIndex(ViewMode mode)
|
|||
return initializer.viewMode == mode;
|
||||
});
|
||||
|
||||
return (iter != s_categoryManifest.end())
|
||||
? index
|
||||
: -1;
|
||||
return (iter != s_categoryManifest.end()) ? index : -1;
|
||||
}
|
||||
|
||||
// GetIndex is 0-based, GetPosition is 1-based
|
||||
int NavCategory::GetIndexInGroup(ViewMode mode, CategoryGroupType type)
|
||||
{
|
||||
int index = -1;
|
||||
auto iter = find_if(begin(s_categoryManifest), end(s_categoryManifest),
|
||||
[mode, type, &index](const NavCategoryInitializer& initializer)
|
||||
{
|
||||
auto iter = find_if(begin(s_categoryManifest), end(s_categoryManifest), [mode, type, &index](const NavCategoryInitializer& initializer) {
|
||||
if (initializer.groupType == type)
|
||||
{
|
||||
index++;
|
||||
|
@ -244,38 +324,28 @@ int NavCategory::GetIndexInGroup(ViewMode mode, CategoryGroupType type)
|
|||
return false;
|
||||
});
|
||||
|
||||
return (iter != s_categoryManifest.end())
|
||||
? index
|
||||
: -1;
|
||||
return (iter != s_categoryManifest.end()) ? index : -1;
|
||||
}
|
||||
|
||||
// GetIndex is 0-based, GetPosition is 1-based
|
||||
int NavCategory::GetPosition(ViewMode mode)
|
||||
{
|
||||
int position = 0;
|
||||
auto iter = find_if(begin(s_categoryManifest), end(s_categoryManifest),
|
||||
[mode, &position](const NavCategoryInitializer& initializer)
|
||||
{
|
||||
auto iter = find_if(begin(s_categoryManifest), end(s_categoryManifest), [mode, &position](const NavCategoryInitializer& initializer) {
|
||||
position++;
|
||||
return initializer.viewMode == mode;
|
||||
});
|
||||
|
||||
return (iter != s_categoryManifest.end())
|
||||
? position
|
||||
: -1;
|
||||
return (iter != s_categoryManifest.end()) ? position : -1;
|
||||
}
|
||||
|
||||
ViewMode NavCategory::GetViewModeForVirtualKey(MyVirtualKey virtualKey)
|
||||
{
|
||||
auto iter = find_if(begin(s_categoryManifest), end(s_categoryManifest),
|
||||
[virtualKey](const NavCategoryInitializer& initializer)
|
||||
{
|
||||
auto iter = find_if(begin(s_categoryManifest), end(s_categoryManifest), [virtualKey](const NavCategoryInitializer& initializer) {
|
||||
return initializer.virtualKey == virtualKey;
|
||||
});
|
||||
|
||||
return (iter != s_categoryManifest.end())
|
||||
? iter->viewMode
|
||||
: ViewMode::None;
|
||||
return (iter != s_categoryManifest.end()) ? iter->viewMode : ViewMode::None;
|
||||
}
|
||||
|
||||
vector<MyVirtualKey> NavCategory::GetCategoryAcceleratorKeys()
|
||||
|
@ -292,8 +362,8 @@ vector<MyVirtualKey> NavCategory::GetCategoryAcceleratorKeys()
|
|||
return accelerators;
|
||||
}
|
||||
|
||||
NavCategoryGroup::NavCategoryGroup(const NavCategoryGroupInitializer& groupInitializer) :
|
||||
m_Categories(ref new Vector<NavCategory^>())
|
||||
NavCategoryGroup::NavCategoryGroup(const NavCategoryGroupInitializer& groupInitializer)
|
||||
: m_Categories(ref new Vector<NavCategory ^>())
|
||||
{
|
||||
m_GroupType = groupInitializer.type;
|
||||
|
||||
|
@ -306,9 +376,8 @@ NavCategoryGroup::NavCategoryGroup(const NavCategoryGroupInitializer& groupIniti
|
|||
String ^ automationName = resProvider.GetResourceString(automationResourceKey);
|
||||
|
||||
String ^ navCategoryHeaderAutomationNameFormat = resProvider.GetResourceString(L"NavCategoryHeader_AutomationNameFormat");
|
||||
m_AutomationName = ref new String(LocalizationStringUtil::GetLocalizedString(
|
||||
navCategoryHeaderAutomationNameFormat->Data(),
|
||||
automationName->Data()).c_str());
|
||||
m_AutomationName =
|
||||
ref new String(LocalizationStringUtil::GetLocalizedString(navCategoryHeaderAutomationNameFormat->Data(), automationName->Data()).c_str());
|
||||
|
||||
String ^ navCategoryItemAutomationNameFormat = resProvider.GetResourceString(L"NavCategoryItem_AutomationNameFormat");
|
||||
|
||||
|
@ -318,10 +387,8 @@ NavCategoryGroup::NavCategoryGroup(const NavCategoryGroupInitializer& groupIniti
|
|||
{
|
||||
String ^ nameResourceKey = StringReference(categoryInitializer.nameResourceKey);
|
||||
String ^ categoryName = resProvider.GetResourceString(nameResourceKey + "Text");
|
||||
String^ categoryAutomationName = ref new String(LocalizationStringUtil::GetLocalizedString(
|
||||
navCategoryItemAutomationNameFormat->Data(),
|
||||
categoryName->Data(),
|
||||
m_Name->Data()).c_str());
|
||||
String ^ categoryAutomationName = ref new String(
|
||||
LocalizationStringUtil::GetLocalizedString(navCategoryItemAutomationNameFormat->Data(), categoryName->Data(), m_Name->Data()).c_str());
|
||||
|
||||
m_Categories->Append(ref new NavCategory(
|
||||
categoryName,
|
||||
|
@ -356,9 +423,7 @@ NavCategoryGroup^ NavCategoryGroup::CreateConverterCategory()
|
|||
vector<NavCategoryInitializer> NavCategoryGroup::GetInitializerCategoryGroup(CategoryGroupType groupType)
|
||||
{
|
||||
vector<NavCategoryInitializer> initializers{};
|
||||
copy_if(begin(s_categoryManifest), end(s_categoryManifest), back_inserter(initializers),
|
||||
[groupType](const NavCategoryInitializer& initializer)
|
||||
{
|
||||
copy_if(begin(s_categoryManifest), end(s_categoryManifest), back_inserter(initializers), [groupType](const NavCategoryInitializer& initializer) {
|
||||
return initializer.groupType == groupType;
|
||||
});
|
||||
|
||||
|
@ -367,13 +432,9 @@ vector<NavCategoryInitializer> NavCategoryGroup::GetInitializerCategoryGroup(Cat
|
|||
|
||||
String ^ NavCategoryGroup::GetHeaderResourceKey(CategoryGroupType type)
|
||||
{
|
||||
auto iter = find_if(begin(s_categoryGroupManifest), end(s_categoryGroupManifest),
|
||||
[type](const NavCategoryGroupInitializer& initializer)
|
||||
{
|
||||
auto iter = find_if(begin(s_categoryGroupManifest), end(s_categoryGroupManifest), [type](const NavCategoryGroupInitializer& initializer) {
|
||||
return initializer.type == type;
|
||||
});
|
||||
|
||||
return (iter != s_categoryGroupManifest.end())
|
||||
? StringReference(iter->headerResourceKey)
|
||||
: nullptr;
|
||||
return (iter != s_categoryGroupManifest.end()) ? StringReference(iter->headerResourceKey) : nullptr;
|
||||
}
|
||||
|
|
|
@ -24,7 +24,8 @@ namespace CalculatorApp
|
|||
// Don't change the order of these enums
|
||||
// and definitely don't use int arithmetic
|
||||
// to change modes.
|
||||
public enum class ViewMode
|
||||
public
|
||||
enum class ViewMode
|
||||
{
|
||||
None = -1,
|
||||
Standard = 0,
|
||||
|
@ -46,14 +47,16 @@ namespace CalculatorApp
|
|||
Currency = 16
|
||||
};
|
||||
|
||||
public enum class CategoryGroupType
|
||||
public
|
||||
enum class CategoryGroupType
|
||||
{
|
||||
None = -1,
|
||||
Calculator = 0,
|
||||
Converter = 1
|
||||
};
|
||||
|
||||
private struct NavCategoryInitializer
|
||||
private
|
||||
struct NavCategoryInitializer
|
||||
{
|
||||
constexpr NavCategoryInitializer(
|
||||
ViewMode mode,
|
||||
|
@ -64,16 +67,16 @@ namespace CalculatorApp
|
|||
CategoryGroupType group,
|
||||
MyVirtualKey vKey,
|
||||
bool categorySupportsNegative)
|
||||
:
|
||||
viewMode(mode),
|
||||
serializationId(id),
|
||||
friendlyName(name),
|
||||
nameResourceKey(nameKey),
|
||||
glyph(glyph),
|
||||
groupType(group),
|
||||
virtualKey(vKey),
|
||||
supportsNegative(categorySupportsNegative)
|
||||
{}
|
||||
: viewMode(mode)
|
||||
, serializationId(id)
|
||||
, friendlyName(name)
|
||||
, nameResourceKey(nameKey)
|
||||
, glyph(glyph)
|
||||
, groupType(group)
|
||||
, virtualKey(vKey)
|
||||
, supportsNegative(categorySupportsNegative)
|
||||
{
|
||||
}
|
||||
|
||||
const ViewMode viewMode;
|
||||
const int serializationId;
|
||||
|
@ -85,11 +88,16 @@ namespace CalculatorApp
|
|||
const bool supportsNegative;
|
||||
};
|
||||
|
||||
private struct NavCategoryGroupInitializer
|
||||
private
|
||||
struct NavCategoryGroupInitializer
|
||||
{
|
||||
constexpr NavCategoryGroupInitializer(CategoryGroupType t, wchar_t const * h, wchar_t const * n, wchar_t const * a) :
|
||||
type(t), headerResourceKey(h), modeResourceKey(n), automationResourceKey(a)
|
||||
{}
|
||||
constexpr NavCategoryGroupInitializer(CategoryGroupType t, wchar_t const* h, wchar_t const* n, wchar_t const* a)
|
||||
: type(t)
|
||||
, headerResourceKey(h)
|
||||
, modeResourceKey(n)
|
||||
, automationResourceKey(a)
|
||||
{
|
||||
}
|
||||
|
||||
const CategoryGroupType type;
|
||||
const wchar_t* headerResourceKey;
|
||||
|
@ -97,30 +105,26 @@ namespace CalculatorApp
|
|||
const wchar_t* automationResourceKey;
|
||||
};
|
||||
|
||||
[Windows::UI::Xaml::Data::Bindable]
|
||||
public ref class NavCategory sealed : public Windows::UI::Xaml::Data::INotifyPropertyChanged
|
||||
[Windows::UI::Xaml::Data::Bindable] public ref class NavCategory sealed : public Windows::UI::Xaml::Data::INotifyPropertyChanged
|
||||
{
|
||||
public:
|
||||
OBSERVABLE_OBJECT();
|
||||
|
||||
property Platform::String^ Name
|
||||
{
|
||||
Platform::String^ get() { return m_name; }
|
||||
}
|
||||
property Platform::String
|
||||
^ Name { Platform::String ^ get() { return m_name; } }
|
||||
|
||||
property Platform::String^ AutomationName
|
||||
{
|
||||
Platform::String^ get() { return m_automationName; }
|
||||
}
|
||||
property Platform::String
|
||||
^ AutomationName { Platform::String ^ get() { return m_automationName; } }
|
||||
|
||||
property Platform::String^ Glyph
|
||||
{
|
||||
Platform::String^ get() { return m_glyph; }
|
||||
}
|
||||
property Platform::String
|
||||
^ Glyph { Platform::String ^ get() { return m_glyph; } }
|
||||
|
||||
property int Position
|
||||
{
|
||||
int get() { return m_position; }
|
||||
int get()
|
||||
{
|
||||
return m_position;
|
||||
}
|
||||
}
|
||||
|
||||
property ViewMode Mode
|
||||
|
@ -131,22 +135,11 @@ namespace CalculatorApp
|
|||
}
|
||||
}
|
||||
|
||||
property Platform::String^ AutomationId
|
||||
{
|
||||
Platform::String^ get()
|
||||
{
|
||||
return m_viewMode.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
property Platform::String^ AccessKey
|
||||
{
|
||||
Platform::String^ get()
|
||||
{
|
||||
return m_accessKey;
|
||||
}
|
||||
}
|
||||
property Platform::String
|
||||
^ AutomationId { Platform::String ^ get() { return m_viewMode.ToString(); } }
|
||||
|
||||
property Platform::String
|
||||
^ AccessKey { Platform::String ^ get() { return m_accessKey; } }
|
||||
|
||||
property bool SupportsNegative
|
||||
{
|
||||
|
@ -178,15 +171,21 @@ namespace CalculatorApp
|
|||
|
||||
static ViewMode GetViewModeForVirtualKey(MyVirtualKey virtualKey);
|
||||
|
||||
internal:
|
||||
NavCategory(Platform::String^ name, Platform::String^ automationName, Platform::String^ glyph, Platform::String^ accessKey, Platform::String^ mode, ViewMode viewMode, bool supportsNegative) :
|
||||
m_name(name),
|
||||
m_automationName(automationName),
|
||||
m_glyph(glyph),
|
||||
m_accessKey(accessKey),
|
||||
m_mode(mode),
|
||||
m_viewMode(viewMode),
|
||||
m_supportsNegative(supportsNegative)
|
||||
internal : NavCategory(
|
||||
Platform::String ^ name,
|
||||
Platform::String ^ automationName,
|
||||
Platform::String ^ glyph,
|
||||
Platform::String ^ accessKey,
|
||||
Platform::String ^ mode,
|
||||
ViewMode viewMode,
|
||||
bool supportsNegative)
|
||||
: m_name(name)
|
||||
, m_automationName(automationName)
|
||||
, m_glyph(glyph)
|
||||
, m_accessKey(accessKey)
|
||||
, m_mode(mode)
|
||||
, m_viewMode(viewMode)
|
||||
, m_supportsNegative(supportsNegative)
|
||||
{
|
||||
m_position = NavCategory::GetPosition(m_viewMode);
|
||||
}
|
||||
|
@ -206,10 +205,8 @@ namespace CalculatorApp
|
|||
bool m_supportsNegative;
|
||||
};
|
||||
|
||||
[Windows::UI::Xaml::Data::Bindable]
|
||||
public ref class NavCategoryGroup sealed : public Windows::UI::Xaml::Data::INotifyPropertyChanged
|
||||
[Windows::UI::Xaml::Data::Bindable] public ref class NavCategoryGroup sealed : public Windows::UI::Xaml::Data::INotifyPropertyChanged
|
||||
{
|
||||
|
||||
public:
|
||||
OBSERVABLE_OBJECT();
|
||||
OBSERVABLE_PROPERTY_R(Platform::String ^, Name);
|
||||
|
@ -221,8 +218,7 @@ namespace CalculatorApp
|
|||
|
||||
static Platform::String ^ GetHeaderResourceKey(CategoryGroupType type);
|
||||
|
||||
internal:
|
||||
static NavCategoryGroup^ CreateCalculatorCategory();
|
||||
internal : static NavCategoryGroup ^ CreateCalculatorCategory();
|
||||
static NavCategoryGroup ^ CreateConverterCategory();
|
||||
|
||||
private:
|
||||
|
|
|
@ -10,9 +10,8 @@ using namespace Windows::Networking::Connectivity;
|
|||
|
||||
NetworkManager::NetworkManager()
|
||||
{
|
||||
m_NetworkStatusChangedToken =
|
||||
NetworkInformation::NetworkStatusChanged += ref new NetworkStatusChangedEventHandler(
|
||||
this, &NetworkManager::OnNetworkStatusChange, CallbackContext::Same);
|
||||
m_NetworkStatusChangedToken = NetworkInformation::NetworkStatusChanged +=
|
||||
ref new NetworkStatusChangedEventHandler(this, &NetworkManager::OnNetworkStatusChange, CallbackContext::Same);
|
||||
}
|
||||
|
||||
NetworkManager::~NetworkManager()
|
||||
|
@ -27,8 +26,7 @@ NetworkAccessBehavior NetworkManager::GetNetworkAccessBehavior()
|
|||
if (connectionProfile != nullptr)
|
||||
{
|
||||
NetworkConnectivityLevel connectivityLevel = connectionProfile->GetNetworkConnectivityLevel();
|
||||
if (connectivityLevel == NetworkConnectivityLevel::InternetAccess
|
||||
|| connectivityLevel == NetworkConnectivityLevel::ConstrainedInternetAccess)
|
||||
if (connectivityLevel == NetworkConnectivityLevel::InternetAccess || connectivityLevel == NetworkConnectivityLevel::ConstrainedInternetAccess)
|
||||
{
|
||||
ConnectionCost ^ connectionCost = connectionProfile->GetConnectionCost();
|
||||
behavior = ConvertCostInfoToBehavior(connectionCost);
|
||||
|
@ -46,8 +44,7 @@ void NetworkManager::OnNetworkStatusChange(_In_ Object^ /*sender*/)
|
|||
// See app behavior guidelines at https://msdn.microsoft.com/en-us/library/windows/apps/xaml/jj835821(v=win.10).aspx
|
||||
NetworkAccessBehavior NetworkManager::ConvertCostInfoToBehavior(_In_ ConnectionCost ^ connectionCost)
|
||||
{
|
||||
if (connectionCost->Roaming || connectionCost->OverDataLimit
|
||||
|| connectionCost->NetworkCostType == NetworkCostType::Variable
|
||||
if (connectionCost->Roaming || connectionCost->OverDataLimit || connectionCost->NetworkCostType == NetworkCostType::Variable
|
||||
|| connectionCost->NetworkCostType == NetworkCostType::Fixed)
|
||||
{
|
||||
return NetworkAccessBehavior::OptIn;
|
||||
|
|
|
@ -5,16 +5,19 @@
|
|||
|
||||
namespace CalculatorApp
|
||||
{
|
||||
public enum class NetworkAccessBehavior
|
||||
public
|
||||
enum class NetworkAccessBehavior
|
||||
{
|
||||
Normal = 0,
|
||||
OptIn = 1,
|
||||
Offline = 2
|
||||
};
|
||||
|
||||
public delegate void NetworkBehaviorChangedHandler(NetworkAccessBehavior behavior);
|
||||
public
|
||||
delegate void NetworkBehaviorChangedHandler(NetworkAccessBehavior behavior);
|
||||
|
||||
public ref class NetworkManager sealed
|
||||
public
|
||||
ref class NetworkManager sealed
|
||||
{
|
||||
public:
|
||||
NetworkManager();
|
||||
|
|
|
@ -11,20 +11,21 @@ namespace CalculatorApp
|
|||
class TraceActivity
|
||||
{
|
||||
public:
|
||||
TraceActivity() :
|
||||
m_channel(nullptr),
|
||||
m_activity(nullptr),
|
||||
m_fields(nullptr)
|
||||
{ }
|
||||
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)
|
||||
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
|
||||
|
@ -33,8 +34,7 @@ namespace CalculatorApp
|
|||
m_activityName,
|
||||
m_fields,
|
||||
winrt::Windows::Foundation::Diagnostics::LoggingLevel::Verbose,
|
||||
winrt::Windows::Foundation::Diagnostics::LoggingOptions(WINEVENT_KEYWORD_RESPONSE_TIME)
|
||||
);
|
||||
winrt::Windows::Foundation::Diagnostics::LoggingOptions(WINEVENT_KEYWORD_RESPONSE_TIME));
|
||||
}
|
||||
|
||||
~TraceActivity()
|
||||
|
|
|
@ -21,10 +21,8 @@ namespace CalculatorApp
|
|||
{
|
||||
static multimap<int, vector<wstring>> s_memoryMap;
|
||||
|
||||
static constexpr array<const wchar_t * const, 9> s_programmerType{
|
||||
L"N/A", L"QwordType", L"DwordType",
|
||||
L"WordType", L"ByteType", L"HexBase",
|
||||
L"DecBase", L"OctBase", L"BinBase" };
|
||||
static constexpr array<const wchar_t* const, 9> s_programmerType{ L"N/A", L"QwordType", L"DwordType", L"WordType", L"ByteType",
|
||||
L"HexBase", L"DecBase", L"OctBase", L"BinBase" };
|
||||
static reader_writer_lock s_traceLoggerLock;
|
||||
|
||||
// Telemetry events. Uploaded to asimov.
|
||||
|
@ -99,11 +97,12 @@ namespace CalculatorApp
|
|||
|
||||
#pragma region TraceLogger setup and cleanup
|
||||
|
||||
TraceLogger::TraceLogger() :
|
||||
g_calculatorProvider(
|
||||
TraceLogger::TraceLogger()
|
||||
: g_calculatorProvider(
|
||||
L"MicrosoftCalculator",
|
||||
LoggingChannelOptions(GUID{ 0x4f50731a, 0x89cf, 0x4782, 0xb3, 0xe0, 0xdc, 0xe8, 0xc9, 0x4, 0x76, 0xba }), // Microsoft Telemetry group
|
||||
GUID{ 0x905ca09, 0x610e, 0x401e, 0xb6, 0x50, 0x2f, 0x21, 0x29, 0x80, 0xb9, 0xe0 }), // Unique providerID {0905CA09-610E-401E-B650-2F212980B9E0}
|
||||
GUID{ 0x905ca09, 0x610e, 0x401e, 0xb6, 0x50, 0x2f, 0x21, 0x29, 0x80, 0xb9, 0xe0 })
|
||||
, // Unique providerID {0905CA09-610E-401E-B650-2F212980B9E0}
|
||||
m_appLaunchActivity{ nullptr }
|
||||
{
|
||||
// initialize the function array
|
||||
|
@ -307,7 +306,8 @@ namespace CalculatorApp
|
|||
|
||||
void TraceLogger::LogSharedMemoryUsed(wstring_view fromMode, wstring_view toMode, unsigned int memorySize) const
|
||||
{
|
||||
if (!GetTraceLoggingProviderEnabled()) return;
|
||||
if (!GetTraceLoggingProviderEnabled())
|
||||
return;
|
||||
|
||||
LoggingFields fields{};
|
||||
fields.AddString(L"FromMode", fromMode);
|
||||
|
@ -318,7 +318,8 @@ namespace CalculatorApp
|
|||
|
||||
void TraceLogger::LogBitFlipPaneClicked() const
|
||||
{
|
||||
if (!GetTraceLoggingProviderEnabled()) return;
|
||||
if (!GetTraceLoggingProviderEnabled())
|
||||
return;
|
||||
|
||||
LoggingFields fields{};
|
||||
LogTelemetryEvent(EVENT_NAME_BITFLIP_PANE_CLICKED, fields);
|
||||
|
@ -326,7 +327,8 @@ namespace CalculatorApp
|
|||
|
||||
void TraceLogger::LogBitFlipUsed() const
|
||||
{
|
||||
if (!GetTraceLoggingProviderEnabled()) return;
|
||||
if (!GetTraceLoggingProviderEnabled())
|
||||
return;
|
||||
|
||||
LoggingFields fields{};
|
||||
LogTelemetryEvent(EVENT_NAME_BITFLIP_BUTTONS_USED, fields);
|
||||
|
@ -339,11 +341,8 @@ namespace CalculatorApp
|
|||
|
||||
if (!isAppLaunchBeginLogged)
|
||||
{
|
||||
m_appLaunchActivity = g_calculatorProvider.StartActivity(
|
||||
EVENT_NAME_APP_LAUNCH_BEGIN,
|
||||
nullptr,
|
||||
LoggingLevel::Verbose,
|
||||
LoggingOptions(MICROSOFT_KEYWORD_TELEMETRY));
|
||||
m_appLaunchActivity =
|
||||
g_calculatorProvider.StartActivity(EVENT_NAME_APP_LAUNCH_BEGIN, nullptr, LoggingLevel::Verbose, LoggingOptions(MICROSOFT_KEYWORD_TELEMETRY));
|
||||
|
||||
isAppLaunchBeginLogged = true;
|
||||
}
|
||||
|
@ -376,7 +375,8 @@ namespace CalculatorApp
|
|||
|
||||
void TraceLogger::LogDebug(wstring_view debugData)
|
||||
{
|
||||
if (!GetTraceLoggingProviderEnabled()) return;
|
||||
if (!GetTraceLoggingProviderEnabled())
|
||||
return;
|
||||
|
||||
LoggingFields fields{};
|
||||
fields.AddString(L"DebugData", debugData);
|
||||
|
@ -385,7 +385,8 @@ namespace CalculatorApp
|
|||
|
||||
void TraceLogger::LogOnAppLaunch(wstring_view previousExecutionState) const
|
||||
{
|
||||
if (!GetTraceLoggingProviderEnabled()) return;
|
||||
if (!GetTraceLoggingProviderEnabled())
|
||||
return;
|
||||
|
||||
LoggingFields fields{};
|
||||
fields.AddString(L"PreviousExecutionState", previousExecutionState);
|
||||
|
@ -394,7 +395,8 @@ namespace CalculatorApp
|
|||
|
||||
void TraceLogger::LogAboutFlyoutOpened() const
|
||||
{
|
||||
if (!GetTraceLoggingProviderEnabled()) return;
|
||||
if (!GetTraceLoggingProviderEnabled())
|
||||
return;
|
||||
|
||||
LoggingFields fields{};
|
||||
LogTelemetryEvent(EVENT_NAME_ABOUT_FLYOUT_OPENED, fields);
|
||||
|
@ -402,7 +404,8 @@ namespace CalculatorApp
|
|||
|
||||
void TraceLogger::LogNavBarOpened() const
|
||||
{
|
||||
if (!GetTraceLoggingProviderEnabled()) return;
|
||||
if (!GetTraceLoggingProviderEnabled())
|
||||
return;
|
||||
|
||||
LoggingFields fields{};
|
||||
LogTelemetryEvent(EVENT_NAME_NAV_BAR_OPENED, fields);
|
||||
|
@ -410,7 +413,8 @@ namespace CalculatorApp
|
|||
|
||||
void TraceLogger::LogClearHistory() const
|
||||
{
|
||||
if (!GetTraceLoggingProviderEnabled()) return;
|
||||
if (!GetTraceLoggingProviderEnabled())
|
||||
return;
|
||||
|
||||
LoggingFields fields{};
|
||||
LogTelemetryEvent(EVENT_NAME_HISTORY_CLEAR, fields);
|
||||
|
@ -418,7 +422,8 @@ namespace CalculatorApp
|
|||
|
||||
void TraceLogger::LogHistoryFlyoutOpenBegin(unsigned int historyItemCount) const
|
||||
{
|
||||
if (!GetTraceLoggingProviderEnabled()) return;
|
||||
if (!GetTraceLoggingProviderEnabled())
|
||||
return;
|
||||
|
||||
// we want to record the event only when history item count is atleast 20
|
||||
if (historyItemCount >= 20)
|
||||
|
@ -431,7 +436,8 @@ namespace CalculatorApp
|
|||
|
||||
void TraceLogger::LogHistoryFlyoutOpenEnd(int historyItemCount) const
|
||||
{
|
||||
if (!GetTraceLoggingProviderEnabled()) return;
|
||||
if (!GetTraceLoggingProviderEnabled())
|
||||
return;
|
||||
|
||||
if (historyItemCount >= 20)
|
||||
{
|
||||
|
@ -443,7 +449,8 @@ namespace CalculatorApp
|
|||
|
||||
void TraceLogger::LogHistoryBodyOpened() const
|
||||
{
|
||||
if (!GetTraceLoggingProviderEnabled()) return;
|
||||
if (!GetTraceLoggingProviderEnabled())
|
||||
return;
|
||||
|
||||
LoggingFields fields{};
|
||||
LogTelemetryEvent(EVENT_NAME_HISTORY_BODY_OPENED, fields);
|
||||
|
@ -451,7 +458,8 @@ namespace CalculatorApp
|
|||
|
||||
void TraceLogger::LogMemoryFlyoutOpenBegin(unsigned int memoryItemCount) const
|
||||
{
|
||||
if (!GetTraceLoggingProviderEnabled()) return;
|
||||
if (!GetTraceLoggingProviderEnabled())
|
||||
return;
|
||||
|
||||
// we want to record the event only when memory item count is atleast 4
|
||||
if (memoryItemCount >= 4)
|
||||
|
@ -464,7 +472,8 @@ namespace CalculatorApp
|
|||
|
||||
void TraceLogger::LogMemoryFlyoutOpenEnd(unsigned int memoryItemCount) const
|
||||
{
|
||||
if (!GetTraceLoggingProviderEnabled()) return;
|
||||
if (!GetTraceLoggingProviderEnabled())
|
||||
return;
|
||||
|
||||
if (memoryItemCount >= 4)
|
||||
{
|
||||
|
@ -476,7 +485,8 @@ namespace CalculatorApp
|
|||
|
||||
void TraceLogger::LogMemoryBodyOpened() const
|
||||
{
|
||||
if (!GetTraceLoggingProviderEnabled()) return;
|
||||
if (!GetTraceLoggingProviderEnabled())
|
||||
return;
|
||||
|
||||
LoggingFields fields{};
|
||||
LogTelemetryEvent(EVENT_NAME_MEMORY_BODY_OPENED, fields);
|
||||
|
@ -487,7 +497,8 @@ namespace CalculatorApp
|
|||
// Use of this function is to analyze perf of mode change.
|
||||
void TraceLogger::LogModeChangeBegin(ViewMode fromMode, ViewMode toMode, int windowId)
|
||||
{
|
||||
if (!GetTraceLoggingProviderEnabled()) return;
|
||||
if (!GetTraceLoggingProviderEnabled())
|
||||
return;
|
||||
|
||||
if (NavCategory::IsValidViewMode(fromMode) && NavCategory::IsValidViewMode(toMode))
|
||||
{
|
||||
|
@ -502,7 +513,8 @@ namespace CalculatorApp
|
|||
// comment: same as LogModeChangeBegin
|
||||
void TraceLogger::LogModeChangeEnd(ViewMode toMode, int windowId) const
|
||||
{
|
||||
if (!GetTraceLoggingProviderEnabled()) return;
|
||||
if (!GetTraceLoggingProviderEnabled())
|
||||
return;
|
||||
|
||||
if (NavCategory::IsValidViewMode(toMode))
|
||||
{
|
||||
|
@ -515,7 +527,8 @@ namespace CalculatorApp
|
|||
|
||||
void TraceLogger::LogHistoryItemLoadBegin() const
|
||||
{
|
||||
if (!GetTraceLoggingProviderEnabled()) return;
|
||||
if (!GetTraceLoggingProviderEnabled())
|
||||
return;
|
||||
|
||||
LoggingFields fields{};
|
||||
LogTelemetryEvent(EVENT_NAME_HISTORY_ITEM_LOAD_BEGIN, fields);
|
||||
|
@ -523,7 +536,8 @@ namespace CalculatorApp
|
|||
|
||||
void TraceLogger::LogHistoryItemLoadEnd(unsigned int historyTokenCount) const
|
||||
{
|
||||
if (!GetTraceLoggingProviderEnabled()) return;
|
||||
if (!GetTraceLoggingProviderEnabled())
|
||||
return;
|
||||
|
||||
LoggingFields fields{};
|
||||
fields.AddUInt32(L"HistoryTokenCount", historyTokenCount);
|
||||
|
@ -532,7 +546,8 @@ namespace CalculatorApp
|
|||
|
||||
void TraceLogger::LogNewWindowCreationBegin(int windowId)
|
||||
{
|
||||
if (!GetTraceLoggingProviderEnabled()) return;
|
||||
if (!GetTraceLoggingProviderEnabled())
|
||||
return;
|
||||
|
||||
LoggingFields fields{};
|
||||
fields.AddUInt32(L"WindowId", windowId);
|
||||
|
@ -541,7 +556,8 @@ namespace CalculatorApp
|
|||
|
||||
void TraceLogger::LogNewWindowCreationEnd(int windowId)
|
||||
{
|
||||
if (!GetTraceLoggingProviderEnabled()) return;
|
||||
if (!GetTraceLoggingProviderEnabled())
|
||||
return;
|
||||
|
||||
LoggingFields fields{};
|
||||
fields.AddUInt32(L"WindowId", windowId);
|
||||
|
@ -550,7 +566,8 @@ namespace CalculatorApp
|
|||
|
||||
void TraceLogger::LogError(wstring_view errorString)
|
||||
{
|
||||
if (!GetTraceLoggingProviderEnabled()) return;
|
||||
if (!GetTraceLoggingProviderEnabled())
|
||||
return;
|
||||
|
||||
LoggingFields fields{};
|
||||
fields.AddString(L"ErrorString", errorString);
|
||||
|
@ -559,7 +576,8 @@ namespace CalculatorApp
|
|||
|
||||
void TraceLogger::LogPrelaunchedAppActivatedByUser()
|
||||
{
|
||||
if (!GetTraceLoggingProviderEnabled()) return;
|
||||
if (!GetTraceLoggingProviderEnabled())
|
||||
return;
|
||||
|
||||
LoggingFields fields{};
|
||||
LogTelemetryEvent(EVENT_NAME_PRELAUNCHED_APP_ACTIVATED_BY_USER, fields);
|
||||
|
@ -567,7 +585,8 @@ namespace CalculatorApp
|
|||
|
||||
void TraceLogger::LogAppPrelaunchedBySystem()
|
||||
{
|
||||
if (!GetTraceLoggingProviderEnabled()) return;
|
||||
if (!GetTraceLoggingProviderEnabled())
|
||||
return;
|
||||
|
||||
LoggingFields fields{};
|
||||
LogTelemetryEvent(EVENT_NAME_APP_PRELAUNCHED_BY_SYSTEM, fields);
|
||||
|
@ -588,9 +607,11 @@ namespace CalculatorApp
|
|||
}
|
||||
}
|
||||
|
||||
void TraceLogger::LogMemoryUsed(int windowId, unsigned int slotPosition, bool isStandard, bool isScientific, bool isProgrammer, unsigned int memorySize) const
|
||||
void
|
||||
TraceLogger::LogMemoryUsed(int windowId, unsigned int slotPosition, bool isStandard, bool isScientific, bool isProgrammer, unsigned int memorySize) const
|
||||
{
|
||||
if (!GetTraceLoggingProviderEnabled()) return;
|
||||
if (!GetTraceLoggingProviderEnabled())
|
||||
return;
|
||||
|
||||
// Reader lock for the static resources
|
||||
reader_writer_lock::scoped_lock_read lock(s_traceLoggerLock);
|
||||
|
@ -625,7 +646,8 @@ namespace CalculatorApp
|
|||
|
||||
void TraceLogger::LogMultipleMemoryUsed(unsigned int slotPosition, unsigned int memorySize) const
|
||||
{
|
||||
if (!GetTraceLoggingProviderEnabled()) return;
|
||||
if (!GetTraceLoggingProviderEnabled())
|
||||
return;
|
||||
|
||||
LoggingFields fields{};
|
||||
fields.AddUInt32(L"MemoryIndex", slotPosition);
|
||||
|
@ -635,7 +657,8 @@ namespace CalculatorApp
|
|||
|
||||
void TraceLogger::LogSingleMemoryUsed(unsigned int memorySize) const
|
||||
{
|
||||
if (!GetTraceLoggingProviderEnabled()) return;
|
||||
if (!GetTraceLoggingProviderEnabled())
|
||||
return;
|
||||
|
||||
LoggingFields fields{};
|
||||
fields.AddUInt32(L"MemoryListSize", memorySize);
|
||||
|
@ -644,7 +667,8 @@ namespace CalculatorApp
|
|||
|
||||
void TraceLogger::LogInvalidPastedInputOccurred(wstring_view reason, ViewMode mode, int programmerNumberBase, int bitLengthType)
|
||||
{
|
||||
if (!GetTraceLoggingProviderEnabled()) return;
|
||||
if (!GetTraceLoggingProviderEnabled())
|
||||
return;
|
||||
|
||||
LoggingFields fields{};
|
||||
fields.AddString(L"Mode", NavCategory::GetFriendlyName(mode)->Data());
|
||||
|
@ -657,7 +681,8 @@ namespace CalculatorApp
|
|||
|
||||
void TraceLogger::LogValidInputPasted(ViewMode mode) const
|
||||
{
|
||||
if (!GetTraceLoggingProviderEnabled()) return;
|
||||
if (!GetTraceLoggingProviderEnabled())
|
||||
return;
|
||||
|
||||
LoggingFields fields{};
|
||||
fields.AddString(L"Mode", NavCategory::GetFriendlyName(mode)->Data());
|
||||
|
@ -666,7 +691,8 @@ namespace CalculatorApp
|
|||
|
||||
void TraceLogger::LogStandardException(wstring_view functionName, const exception& e) const
|
||||
{
|
||||
if (!GetTraceLoggingProviderEnabled()) return;
|
||||
if (!GetTraceLoggingProviderEnabled())
|
||||
return;
|
||||
|
||||
LoggingFields fields{};
|
||||
fields.AddString(L"FunctionName", functionName);
|
||||
|
@ -678,7 +704,8 @@ namespace CalculatorApp
|
|||
|
||||
void TraceLogger::LogWinRTException(wstring_view functionName, hresult_error const& e) const
|
||||
{
|
||||
if (!GetTraceLoggingProviderEnabled()) return;
|
||||
if (!GetTraceLoggingProviderEnabled())
|
||||
return;
|
||||
|
||||
LoggingFields fields{};
|
||||
fields.AddString(L"FunctionName", functionName);
|
||||
|
@ -689,7 +716,8 @@ namespace CalculatorApp
|
|||
|
||||
void TraceLogger::LogPlatformException(wstring_view functionName, Platform::Exception ^ e) const
|
||||
{
|
||||
if (!GetTraceLoggingProviderEnabled()) return;
|
||||
if (!GetTraceLoggingProviderEnabled())
|
||||
return;
|
||||
|
||||
LoggingFields fields{};
|
||||
fields.AddString(L"FunctionName", functionName);
|
||||
|
@ -755,7 +783,8 @@ namespace CalculatorApp
|
|||
|
||||
void TraceLogger::LogMaxWindowCount()
|
||||
{
|
||||
if (!GetTraceLoggingProviderEnabled()) return;
|
||||
if (!GetTraceLoggingProviderEnabled())
|
||||
return;
|
||||
|
||||
LoggingFields fields{};
|
||||
fields.AddUInt32(L"WindowCount", (unsigned int)maxWindowCount);
|
||||
|
@ -764,7 +793,8 @@ namespace CalculatorApp
|
|||
|
||||
void TraceLogger::LogWindowActivated() const
|
||||
{
|
||||
if (!GetTraceLoggingProviderEnabled()) return;
|
||||
if (!GetTraceLoggingProviderEnabled())
|
||||
return;
|
||||
|
||||
LoggingFields fields{};
|
||||
LogTelemetryEvent(EVENT_NAME_WINDOW_LAUNCHED_PROTOCOL, fields);
|
||||
|
@ -772,7 +802,8 @@ namespace CalculatorApp
|
|||
|
||||
void TraceLogger::LogWindowLaunched() const
|
||||
{
|
||||
if (!GetTraceLoggingProviderEnabled()) return;
|
||||
if (!GetTraceLoggingProviderEnabled())
|
||||
return;
|
||||
|
||||
LoggingFields fields{};
|
||||
LogTelemetryEvent(EVENT_NAME_WINDOW_LAUNCHED_TILESEARCH, fields);
|
||||
|
@ -840,7 +871,8 @@ namespace CalculatorApp
|
|||
|
||||
void TraceLogger::LogFunctionUsage(int windowId)
|
||||
{
|
||||
if (!GetTraceLoggingProviderEnabled()) return;
|
||||
if (!GetTraceLoggingProviderEnabled())
|
||||
return;
|
||||
|
||||
for (int i = 0; i < functionCount; i++)
|
||||
{
|
||||
|
@ -897,8 +929,7 @@ namespace CalculatorApp
|
|||
// Ignore first 3 calls during the initialization of the combo box selected items for Add mode
|
||||
int firstChangeEventCount = isAddMode ? 4 : 1;
|
||||
|
||||
if (((*usageMap)[windowId] == firstChangeEventCount)
|
||||
&& (!(*isLoggedInSession)))
|
||||
if (((*usageMap)[windowId] == firstChangeEventCount) && (!(*isLoggedInSession)))
|
||||
{
|
||||
LoggingFields fields{};
|
||||
fields.AddString(L"AddSubtractMode", isAddMode ? L"Add" : L"Subtract");
|
||||
|
@ -910,16 +941,12 @@ namespace CalculatorApp
|
|||
|
||||
void TraceLogger::LogDateClippedTimeDifferenceFound(Calendar const& today, DateTime const& clippedTime) const
|
||||
{
|
||||
if (!GetTraceLoggingProviderEnabled()) return;
|
||||
if (!GetTraceLoggingProviderEnabled())
|
||||
return;
|
||||
|
||||
auto calendarSystem = today.GetCalendarSystem();
|
||||
auto clock = today.GetClock();
|
||||
DateTimeFormatter dtFormatter{
|
||||
L"longdate shorttime",
|
||||
{ L"en-US" },
|
||||
GlobalizationPreferences::HomeGeographicRegion(),
|
||||
calendarSystem,
|
||||
clock };
|
||||
DateTimeFormatter dtFormatter{ L"longdate shorttime", { L"en-US" }, GlobalizationPreferences::HomeGeographicRegion(), calendarSystem, clock };
|
||||
|
||||
LoggingFields fields{};
|
||||
fields.AddString(L"ResolvedCalendarLanguage", today.ResolvedLanguage());
|
||||
|
@ -934,7 +961,8 @@ namespace CalculatorApp
|
|||
|
||||
void TraceLogger::LogUserRequestedRefreshFailed() const
|
||||
{
|
||||
if (!GetTraceLoggingProviderEnabled()) return;
|
||||
if (!GetTraceLoggingProviderEnabled())
|
||||
return;
|
||||
|
||||
LoggingFields fields{};
|
||||
LogTelemetryEvent(L"UserRequestedRefreshFailed", fields);
|
||||
|
@ -942,7 +970,8 @@ namespace CalculatorApp
|
|||
|
||||
void TraceLogger::LogConversionResult(wstring_view fromValue, wstring_view fromUnit, wstring_view toValue, wstring_view toUnit) const
|
||||
{
|
||||
if (!GetTraceLoggingProviderEnabled()) return;
|
||||
if (!GetTraceLoggingProviderEnabled())
|
||||
return;
|
||||
|
||||
wstring behaviorString{};
|
||||
NetworkAccessBehavior behavior = NetworkManager::GetNetworkAccessBehavior();
|
||||
|
@ -979,10 +1008,10 @@ namespace CalculatorApp
|
|||
|
||||
void TraceLogger::LogCoreWindowWasNull() const
|
||||
{
|
||||
if (!GetTraceLoggingProviderEnabled()) return;
|
||||
if (!GetTraceLoggingProviderEnabled())
|
||||
return;
|
||||
|
||||
LoggingFields fields{};
|
||||
LogTelemetryEvent(EVENT_NAME_CORE_WINDOW_WAS_NULL, fields);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -18,7 +18,10 @@ namespace CalculatorApp
|
|||
public:
|
||||
int count;
|
||||
std::wstring funcName;
|
||||
FuncLog() { count = 0; }
|
||||
FuncLog()
|
||||
{
|
||||
count = 0;
|
||||
}
|
||||
FuncLog(std::wstring fName)
|
||||
{
|
||||
funcName = fName;
|
||||
|
@ -93,7 +96,8 @@ namespace CalculatorApp
|
|||
// Trace methods for Date Calculator usage
|
||||
void LogDateDifferenceModeUsed(int windowId);
|
||||
void LogDateAddSubtractModeUsed(int windowId, bool isAddMode);
|
||||
void LogDateClippedTimeDifferenceFound(winrt::Windows::Globalization::Calendar const& today, winrt::Windows::Foundation::DateTime const& clippedTime) const;
|
||||
void
|
||||
LogDateClippedTimeDifferenceFound(winrt::Windows::Globalization::Calendar const& today, winrt::Windows::Foundation::DateTime const& clippedTime) const;
|
||||
|
||||
void LogStandardException(std::wstring_view functionName, _In_ const std::exception& e) const;
|
||||
void LogWinRTException(std::wstring_view functionName, _In_ winrt::hresult_error const& e) const;
|
||||
|
@ -104,10 +108,10 @@ namespace CalculatorApp
|
|||
TraceLogger();
|
||||
|
||||
// Any new Log method should
|
||||
// a) decide the level of logging. This will help us in limiting recording of events only up to a certain level. See this link for guidance https://msdn.microsoft.com/en-us/library/windows/desktop/aa363742(v=vs.85).aspx
|
||||
// We're using Verbose level for events that are called frequently and needed only for debugging or capturing perf for specific scenarios
|
||||
// b) should decide whether or not to log to telemetry and pass TraceLoggingKeyword(MICROSOFT_KEYWORD_TELEMETRY) accordingly
|
||||
// c) Should accept a variable number of additional data arguments if needed
|
||||
// a) decide the level of logging. This will help us in limiting recording of events only up to a certain level. See this link for guidance
|
||||
// https://msdn.microsoft.com/en-us/library/windows/desktop/aa363742(v=vs.85).aspx We're using Verbose level for events that are called frequently and
|
||||
// needed only for debugging or capturing perf for specific scenarios b) should decide whether or not to log to telemetry and pass
|
||||
// TraceLoggingKeyword(MICROSOFT_KEYWORD_TELEMETRY) accordingly c) Should accept a variable number of additional data arguments if needed
|
||||
void LogTelemetryEvent(std::wstring_view eventName, winrt::Windows::Foundation::Diagnostics::LoggingFields fields) const;
|
||||
void LogMeasureEvent(std::wstring_view eventName, winrt::Windows::Foundation::Diagnostics::LoggingFields fields) const;
|
||||
void LogCriticalDataEvent(std::wstring_view eventName, winrt::Windows::Foundation::Diagnostics::LoggingFields fields) const;
|
||||
|
|
|
@ -72,11 +72,7 @@ void Utils::RunOnUIThreadNonblocking(std::function<void()>&& function, _In_ Core
|
|||
{
|
||||
if (currentDispatcher != nullptr)
|
||||
{
|
||||
auto task = create_task(currentDispatcher->RunAsync(CoreDispatcherPriority::Normal,
|
||||
ref new DispatchedHandler([function]()
|
||||
{
|
||||
function();
|
||||
})));
|
||||
auto task = create_task(currentDispatcher->RunAsync(CoreDispatcherPriority::Normal, ref new DispatchedHandler([function]() { function(); })));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -96,7 +92,8 @@ wstring Utils::RemoveUnwantedCharsFromWstring(wstring input, wchar_t* unwantedCh
|
|||
return input;
|
||||
}
|
||||
|
||||
void Utils::SerializeCommandsAndTokens(_In_ shared_ptr<CalculatorVector <pair<wstring, int>>> const &tokens,
|
||||
void Utils::SerializeCommandsAndTokens(
|
||||
_In_ shared_ptr<CalculatorVector<pair<wstring, int>>> const& tokens,
|
||||
_In_ shared_ptr<CalculatorVector<shared_ptr<IExpressionCommand>>> const& commands,
|
||||
DataWriter ^ writer)
|
||||
{
|
||||
|
|
|
@ -10,91 +10,186 @@
|
|||
// Utility macros to make Models easier to write
|
||||
// generates a member variable called m_<n>
|
||||
#define PROPERTY_R(t, n) \
|
||||
property t n {\
|
||||
t get() { return m_##n; }\
|
||||
private: void set(t value) { m_##n = value; }\
|
||||
} private: t m_##n; public:
|
||||
property t n \
|
||||
{ \
|
||||
t get() \
|
||||
{ \
|
||||
return m_##n; \
|
||||
} \
|
||||
\
|
||||
private: \
|
||||
void set(t value) \
|
||||
{ \
|
||||
m_##n = value; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
private: \
|
||||
t m_##n; \
|
||||
\
|
||||
public:
|
||||
|
||||
#define PROPERTY_RW(t, n) \
|
||||
property t n {\
|
||||
t get() { return m_##n; }\
|
||||
void set(t value) { m_##n = value; }\
|
||||
} private: t m_##n; public:
|
||||
property t n \
|
||||
{ \
|
||||
t get() \
|
||||
{ \
|
||||
return m_##n; \
|
||||
} \
|
||||
void set(t value) \
|
||||
{ \
|
||||
m_##n = value; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
private: \
|
||||
t m_##n; \
|
||||
\
|
||||
public:
|
||||
|
||||
#define OBSERVABLE_PROPERTY_R(t, n) \
|
||||
property t n {\
|
||||
t get() { return m_##n; }\
|
||||
private: void set(t value) {\
|
||||
if (m_##n != value) {\
|
||||
property t n \
|
||||
{ \
|
||||
t get() \
|
||||
{ \
|
||||
return m_##n; \
|
||||
} \
|
||||
\
|
||||
private: \
|
||||
void set(t value) \
|
||||
{ \
|
||||
if (m_##n != value) \
|
||||
{ \
|
||||
m_##n = value; \
|
||||
RaisePropertyChanged(L#n); \
|
||||
}}\
|
||||
} private: t m_##n; public:
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
private: \
|
||||
t m_##n; \
|
||||
\
|
||||
public:
|
||||
|
||||
#define OBSERVABLE_PROPERTY_RW(t, n) \
|
||||
property t n {\
|
||||
t get() { return m_##n; }\
|
||||
void set(t value) {\
|
||||
if (m_##n != value) {\
|
||||
property t n \
|
||||
{ \
|
||||
t get() \
|
||||
{ \
|
||||
return m_##n; \
|
||||
} \
|
||||
void set(t value) \
|
||||
{ \
|
||||
if (m_##n != value) \
|
||||
{ \
|
||||
m_##n = value; \
|
||||
RaisePropertyChanged(L#n); \
|
||||
} \
|
||||
} \
|
||||
} private: t m_##n; public:
|
||||
} \
|
||||
\
|
||||
private: \
|
||||
t m_##n; \
|
||||
\
|
||||
public:
|
||||
|
||||
#define OBSERVABLE_NAMED_PROPERTY_R(t, n) \
|
||||
OBSERVABLE_PROPERTY_R(t, n) \
|
||||
internal: static property Platform::String^ n##PropertyName {\
|
||||
internal: \
|
||||
static property Platform::String ^ n##PropertyName \
|
||||
{ \
|
||||
Platform::String ^ get() { return Platform::StringReference(L#n); } \
|
||||
} public:
|
||||
} \
|
||||
\
|
||||
public:
|
||||
|
||||
#define OBSERVABLE_NAMED_PROPERTY_RW(t, n) \
|
||||
OBSERVABLE_PROPERTY_RW(t, n) \
|
||||
internal: static property Platform::String^ n##PropertyName {\
|
||||
internal: \
|
||||
static property Platform::String ^ n##PropertyName \
|
||||
{ \
|
||||
Platform::String ^ get() { return Platform::StringReference(L#n); } \
|
||||
} public:
|
||||
} \
|
||||
\
|
||||
public:
|
||||
|
||||
#define OBSERVABLE_PROPERTY_FIELD(n) m_##n
|
||||
|
||||
// This variant of the observable object is for objects that don't want to react to property changes
|
||||
#ifndef UNIT_TESTS
|
||||
#define OBSERVABLE_OBJECT() virtual event Windows::UI::Xaml::Data::PropertyChangedEventHandler^ PropertyChanged;\
|
||||
internal: void RaisePropertyChanged(Platform::String^ p) {\
|
||||
PropertyChanged(this, ref new Windows::UI::Xaml::Data::PropertyChangedEventArgs(p)); } public:
|
||||
#define OBSERVABLE_OBJECT() \
|
||||
virtual event Windows::UI::Xaml::Data::PropertyChangedEventHandler ^ PropertyChanged; \
|
||||
internal: \
|
||||
void RaisePropertyChanged(Platform::String ^ p) \
|
||||
{ \
|
||||
PropertyChanged(this, ref new Windows::UI::Xaml::Data::PropertyChangedEventArgs(p)); \
|
||||
} \
|
||||
\
|
||||
public:
|
||||
#else
|
||||
#define OBSERVABLE_OBJECT() virtual event Windows::UI::Xaml::Data::PropertyChangedEventHandler^ PropertyChanged;\
|
||||
internal: void RaisePropertyChanged(Platform::String^ p) {\
|
||||
} public:
|
||||
#define OBSERVABLE_OBJECT() \
|
||||
virtual event Windows::UI::Xaml::Data::PropertyChangedEventHandler ^ PropertyChanged; \
|
||||
internal: \
|
||||
void RaisePropertyChanged(Platform::String ^ p) \
|
||||
{ \
|
||||
} \
|
||||
\
|
||||
public:
|
||||
#endif
|
||||
|
||||
// The callback specified in the macro is a method in the class that will be called every time the object changes
|
||||
// the callback is supposed to be have a single parameter of type Platform::String^
|
||||
#ifndef UNIT_TESTS
|
||||
#define OBSERVABLE_OBJECT_CALLBACK(c) virtual event Windows::UI::Xaml::Data::PropertyChangedEventHandler^ PropertyChanged;\
|
||||
internal: void RaisePropertyChanged(Platform::String^ p) {\
|
||||
#define OBSERVABLE_OBJECT_CALLBACK(c) \
|
||||
virtual event Windows::UI::Xaml::Data::PropertyChangedEventHandler ^ PropertyChanged; \
|
||||
internal: \
|
||||
void RaisePropertyChanged(Platform::String ^ p) \
|
||||
{ \
|
||||
PropertyChanged(this, ref new Windows::UI::Xaml::Data::PropertyChangedEventArgs(p)); \
|
||||
c(p); \
|
||||
} public:
|
||||
} \
|
||||
\
|
||||
public:
|
||||
#else
|
||||
#define OBSERVABLE_OBJECT_CALLBACK(c) virtual event Windows::UI::Xaml::Data::PropertyChangedEventHandler^ PropertyChanged;\
|
||||
internal: void RaisePropertyChanged(Platform::String^ p) {\
|
||||
#define OBSERVABLE_OBJECT_CALLBACK(c) \
|
||||
virtual event Windows::UI::Xaml::Data::PropertyChangedEventHandler ^ PropertyChanged; \
|
||||
internal: \
|
||||
void RaisePropertyChanged(Platform::String ^ p) \
|
||||
{ \
|
||||
c(p); \
|
||||
} public:
|
||||
} \
|
||||
\
|
||||
public:
|
||||
#endif
|
||||
|
||||
// The variable member generated by this macro should not be used in the class code, use the
|
||||
// property getter instead.
|
||||
#define COMMAND_FOR_METHOD(p, m) property Windows::UI::Xaml::Input::ICommand^ p {\
|
||||
#define COMMAND_FOR_METHOD(p, m) \
|
||||
property Windows::UI::Xaml::Input::ICommand^ p {\
|
||||
Windows::UI::Xaml::Input::ICommand^ get() {\
|
||||
if (!donotuse_##p) {\
|
||||
donotuse_##p = CalculatorApp::Common::MakeDelegate(this, &m);\
|
||||
} return donotuse_##p; }} private: Windows::UI::Xaml::Input::ICommand^ donotuse_##p; public:
|
||||
} return donotuse_##p; }} private: Windows::UI::Xaml::Input::ICommand^ donotuse_##p; \
|
||||
\
|
||||
public:
|
||||
|
||||
#define DEPENDENCY_PROPERTY_DECLARATION(t, n) \
|
||||
property t n {\
|
||||
t get() { return safe_cast<t>(GetValue(s_##n##Property)); }\
|
||||
void set(t value) { SetValue(s_##n##Property, value); } }\
|
||||
private: static Windows::UI::Xaml::DependencyProperty^ s_##n##Property; public:
|
||||
property t n \
|
||||
{ \
|
||||
t get() \
|
||||
{ \
|
||||
return safe_cast<t>(GetValue(s_##n##Property)); \
|
||||
} \
|
||||
void set(t value) \
|
||||
{ \
|
||||
SetValue(s_##n##Property, value); \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
private: \
|
||||
static Windows::UI::Xaml::DependencyProperty ^ s_##n##Property; \
|
||||
\
|
||||
public:
|
||||
|
||||
// Utilities for DependencyProperties
|
||||
namespace Utils
|
||||
|
@ -289,7 +384,8 @@ namespace Utils
|
|||
double GetDoubleFromWstring(std::wstring input);
|
||||
int GetWindowId();
|
||||
void RunOnUIThreadNonblocking(std::function<void()>&& function, _In_ Windows::UI::Core::CoreDispatcher ^ currentDispatcher);
|
||||
void SerializeCommandsAndTokens(_In_ std::shared_ptr<CalculatorVector <std::pair<std::wstring, int>>> const &tokens,
|
||||
void SerializeCommandsAndTokens(
|
||||
_In_ std::shared_ptr<CalculatorVector<std::pair<std::wstring, int>>> const& tokens,
|
||||
_In_ std::shared_ptr<CalculatorVector<std::shared_ptr<IExpressionCommand>>> const& commands,
|
||||
Windows::Storage::Streams::DataWriter ^ writer);
|
||||
|
||||
|
@ -299,114 +395,295 @@ namespace Utils
|
|||
Windows::Foundation::DateTime GetUniversalSystemTime();
|
||||
bool IsDateTimeOlderThan(Windows::Foundation::DateTime dateTime, const long long duration);
|
||||
|
||||
concurrency::task<void> WriteFileToFolder(Windows::Storage::IStorageFolder^ folder, Platform::String^ fileName, Platform::String^ contents, Windows::Storage::CreationCollisionOption collisionOption);
|
||||
concurrency::task<void> WriteFileToFolder(
|
||||
Windows::Storage::IStorageFolder ^ folder,
|
||||
Platform::String ^ fileName,
|
||||
Platform::String ^ contents,
|
||||
Windows::Storage::CreationCollisionOption collisionOption);
|
||||
concurrency::task<Platform::String ^> ReadFileFromFolder(Windows::Storage::IStorageFolder ^ folder, Platform::String ^ fileName);
|
||||
}
|
||||
|
||||
// This goes into the header to define the property, in the public: section of the class
|
||||
#define DEPENDENCY_PROPERTY_OWNER(owner) \
|
||||
private: typedef owner DependencyPropertiesOwner; public:
|
||||
private: \
|
||||
typedef owner DependencyPropertiesOwner; \
|
||||
\
|
||||
public:
|
||||
|
||||
// Normal DependencyProperty
|
||||
#define DEPENDENCY_PROPERTY(type, name) \
|
||||
property type name {\
|
||||
type get() { return safe_cast<type>(GetValue(s_##name##Property)); }\
|
||||
void set(type value) { SetValue(s_##name##Property, value); }\
|
||||
} private: static Windows::UI::Xaml::DependencyProperty^ s_##name##Property;\
|
||||
public: static property Windows::UI::Xaml::DependencyProperty^ name##Property {\
|
||||
Windows::UI::Xaml::DependencyProperty^ get() { assert(s_##name##Property); return s_##name##Property; }\
|
||||
property type name \
|
||||
{ \
|
||||
type get() \
|
||||
{ \
|
||||
return safe_cast<type>(GetValue(s_##name##Property)); \
|
||||
} \
|
||||
private: static Windows::UI::Xaml::DependencyProperty^ Initialize##name##Property() {\
|
||||
return Utils::RegisterDependencyProperty<DependencyPropertiesOwner, type>(L#name); } public:
|
||||
void set(type value) \
|
||||
{ \
|
||||
SetValue(s_##name##Property, value); \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
private: \
|
||||
static Windows::UI::Xaml::DependencyProperty ^ s_##name##Property; \
|
||||
\
|
||||
public: \
|
||||
static property Windows::UI::Xaml::DependencyProperty ^ name##Property \
|
||||
{ \
|
||||
Windows::UI::Xaml::DependencyProperty ^ get() { \
|
||||
assert(s_##name##Property); \
|
||||
return s_##name##Property; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
private: \
|
||||
static Windows::UI::Xaml::DependencyProperty ^ Initialize##name##Property() \
|
||||
{ \
|
||||
return Utils::RegisterDependencyProperty<DependencyPropertiesOwner, type>(L#name); \
|
||||
} \
|
||||
\
|
||||
public:
|
||||
|
||||
#define DEPENDENCY_PROPERTY_WITH_DEFAULT(type, name, defaultValue) \
|
||||
property type name {\
|
||||
type get() { return safe_cast<type>(GetValue(s_##name##Property)); }\
|
||||
void set(type value) { SetValue(s_##name##Property, value); }\
|
||||
} private: static Windows::UI::Xaml::DependencyProperty^ s_##name##Property;\
|
||||
public: static property Windows::UI::Xaml::DependencyProperty^ name##Property {\
|
||||
Windows::UI::Xaml::DependencyProperty^ get() { assert(s_##name##Property); return s_##name##Property; }\
|
||||
property type name \
|
||||
{ \
|
||||
type get() \
|
||||
{ \
|
||||
return safe_cast<type>(GetValue(s_##name##Property)); \
|
||||
} \
|
||||
private: static Windows::UI::Xaml::DependencyProperty^ Initialize##name##Property() {\
|
||||
return Utils::RegisterDependencyProperty<DependencyPropertiesOwner, type>(L#name, defaultValue); } public:
|
||||
void set(type value) \
|
||||
{ \
|
||||
SetValue(s_##name##Property, value); \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
private: \
|
||||
static Windows::UI::Xaml::DependencyProperty ^ s_##name##Property; \
|
||||
\
|
||||
public: \
|
||||
static property Windows::UI::Xaml::DependencyProperty ^ name##Property \
|
||||
{ \
|
||||
Windows::UI::Xaml::DependencyProperty ^ get() { \
|
||||
assert(s_##name##Property); \
|
||||
return s_##name##Property; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
private: \
|
||||
static Windows::UI::Xaml::DependencyProperty ^ Initialize##name##Property() \
|
||||
{ \
|
||||
return Utils::RegisterDependencyProperty<DependencyPropertiesOwner, type>(L#name, defaultValue); \
|
||||
} \
|
||||
\
|
||||
public:
|
||||
|
||||
#define DEPENDENCY_PROPERTY_WITH_CALLBACK(type, name) \
|
||||
property type name {\
|
||||
type get() { return safe_cast<type>(GetValue(s_##name##Property)); }\
|
||||
void set(type value) { SetValue(s_##name##Property, value); }\
|
||||
} private: static Windows::UI::Xaml::DependencyProperty^ s_##name##Property;\
|
||||
public: static property Windows::UI::Xaml::DependencyProperty^ name##Property {\
|
||||
Windows::UI::Xaml::DependencyProperty^ get() { assert(s_##name##Property); return s_##name##Property; }\
|
||||
property type name \
|
||||
{ \
|
||||
type get() \
|
||||
{ \
|
||||
return safe_cast<type>(GetValue(s_##name##Property)); \
|
||||
} \
|
||||
private: static Windows::UI::Xaml::DependencyProperty^ Initialize##name##Property() {\
|
||||
return Utils::RegisterDependencyPropertyWithCallback<DependencyPropertiesOwner, type>(L#name, &On##name##PropertyChangedImpl); }\
|
||||
static void On##name##PropertyChangedImpl(Windows::UI::Xaml::DependencyObject^ sender, Windows::UI::Xaml::DependencyPropertyChangedEventArgs^ args) {\
|
||||
void set(type value) \
|
||||
{ \
|
||||
SetValue(s_##name##Property, value); \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
private: \
|
||||
static Windows::UI::Xaml::DependencyProperty ^ s_##name##Property; \
|
||||
\
|
||||
public: \
|
||||
static property Windows::UI::Xaml::DependencyProperty ^ name##Property \
|
||||
{ \
|
||||
Windows::UI::Xaml::DependencyProperty ^ get() { \
|
||||
assert(s_##name##Property); \
|
||||
return s_##name##Property; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
private: \
|
||||
static Windows::UI::Xaml::DependencyProperty ^ Initialize##name##Property() \
|
||||
{ \
|
||||
return Utils::RegisterDependencyPropertyWithCallback<DependencyPropertiesOwner, type>(L#name, &On##name##PropertyChangedImpl); \
|
||||
} \
|
||||
static void On##name##PropertyChangedImpl(Windows::UI::Xaml::DependencyObject ^ sender, Windows::UI::Xaml::DependencyPropertyChangedEventArgs ^ args) \
|
||||
{ \
|
||||
auto self = safe_cast<DependencyPropertiesOwner ^>(sender); \
|
||||
self->On##name##PropertyChanged(safe_cast<type>(args->OldValue), safe_cast<type>(args->NewValue)); } public:
|
||||
self->On##name##PropertyChanged(safe_cast<type>(args->OldValue), safe_cast<type>(args->NewValue)); \
|
||||
} \
|
||||
\
|
||||
public:
|
||||
|
||||
#define DEPENDENCY_PROPERTY_WITH_DEFAULT_AND_CALLBACK(type, name, defaultValue) \
|
||||
property type name {\
|
||||
type get() { return safe_cast<type>(GetValue(s_##name##Property)); }\
|
||||
void set(type value) { SetValue(s_##name##Property, value); }\
|
||||
} private: static Windows::UI::Xaml::DependencyProperty^ s_##name##Property;\
|
||||
public: static property Windows::UI::Xaml::DependencyProperty^ name##Property {\
|
||||
Windows::UI::Xaml::DependencyProperty^ get() { assert(s_##name##Property); return s_##name##Property; }\
|
||||
property type name \
|
||||
{ \
|
||||
type get() \
|
||||
{ \
|
||||
return safe_cast<type>(GetValue(s_##name##Property)); \
|
||||
} \
|
||||
private: static Windows::UI::Xaml::DependencyProperty^ Initialize##name##Property() {\
|
||||
return Utils::RegisterDependencyPropertyWithCallback<DependencyPropertiesOwner, type>(L#name, defaultValue, &On##name##PropertyChangedImpl); }\
|
||||
static void On##name##PropertyChangedImpl(Windows::UI::Xaml::DependencyObject^ sender, Windows::UI::Xaml::DependencyPropertyChangedEventArgs^ args) {\
|
||||
void set(type value) \
|
||||
{ \
|
||||
SetValue(s_##name##Property, value); \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
private: \
|
||||
static Windows::UI::Xaml::DependencyProperty ^ s_##name##Property; \
|
||||
\
|
||||
public: \
|
||||
static property Windows::UI::Xaml::DependencyProperty ^ name##Property \
|
||||
{ \
|
||||
Windows::UI::Xaml::DependencyProperty ^ get() { \
|
||||
assert(s_##name##Property); \
|
||||
return s_##name##Property; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
private: \
|
||||
static Windows::UI::Xaml::DependencyProperty ^ Initialize##name##Property() \
|
||||
{ \
|
||||
return Utils::RegisterDependencyPropertyWithCallback<DependencyPropertiesOwner, type>(L#name, defaultValue, &On##name##PropertyChangedImpl); \
|
||||
} \
|
||||
static void On##name##PropertyChangedImpl(Windows::UI::Xaml::DependencyObject ^ sender, Windows::UI::Xaml::DependencyPropertyChangedEventArgs ^ args) \
|
||||
{ \
|
||||
auto self = safe_cast<DependencyPropertiesOwner ^>(sender); \
|
||||
self->On##name##PropertyChanged(safe_cast<type>(args->OldValue), safe_cast<type>(args->NewValue)); } public:
|
||||
self->On##name##PropertyChanged(safe_cast<type>(args->OldValue), safe_cast<type>(args->NewValue)); \
|
||||
} \
|
||||
\
|
||||
public:
|
||||
|
||||
// Attached DependencyProperty
|
||||
#define DEPENDENCY_PROPERTY_ATTACHED(type, name) \
|
||||
static type Get##name(Windows::UI::Xaml::DependencyObject^ target) { return safe_cast<type>(target->GetValue(s_##name##Property)); }\
|
||||
static void Set##name(Windows::UI::Xaml::DependencyObject^ target, type value) { target->SetValue(s_##name##Property, value); }\
|
||||
private: static Windows::UI::Xaml::DependencyProperty^ s_##name##Property;\
|
||||
public: static property Windows::UI::Xaml::DependencyProperty^ name##Property {\
|
||||
Windows::UI::Xaml::DependencyProperty^ get() { assert(s_##name##Property); return s_##name##Property; }\
|
||||
static type Get##name(Windows::UI::Xaml::DependencyObject ^ target) \
|
||||
{ \
|
||||
return safe_cast<type>(target->GetValue(s_##name##Property)); \
|
||||
} \
|
||||
private: static Windows::UI::Xaml::DependencyProperty^ Initialize##name##Property() {\
|
||||
return Utils::RegisterDependencyPropertyAttached<DependencyPropertiesOwner, type>(L#name); } public:
|
||||
static void Set##name(Windows::UI::Xaml::DependencyObject ^ target, type value) \
|
||||
{ \
|
||||
target->SetValue(s_##name##Property, value); \
|
||||
} \
|
||||
\
|
||||
private: \
|
||||
static Windows::UI::Xaml::DependencyProperty ^ s_##name##Property; \
|
||||
\
|
||||
public: \
|
||||
static property Windows::UI::Xaml::DependencyProperty ^ name##Property \
|
||||
{ \
|
||||
Windows::UI::Xaml::DependencyProperty ^ get() { \
|
||||
assert(s_##name##Property); \
|
||||
return s_##name##Property; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
private: \
|
||||
static Windows::UI::Xaml::DependencyProperty ^ Initialize##name##Property() \
|
||||
{ \
|
||||
return Utils::RegisterDependencyPropertyAttached<DependencyPropertiesOwner, type>(L#name); \
|
||||
} \
|
||||
\
|
||||
public:
|
||||
|
||||
#define DEPENDENCY_PROPERTY_ATTACHED_WITH_DEFAULT(type, name, defaultValue) \
|
||||
static type Get##name(Windows::UI::Xaml::DependencyObject^ target) { return safe_cast<type>(target->GetValue(s_##name##Property)); }\
|
||||
static void Set##name(Windows::UI::Xaml::DependencyObject^ target, type value) { target->SetValue(s_##name##Property, value); }\
|
||||
private: static Windows::UI::Xaml::DependencyProperty^ s_##name##Property;\
|
||||
public: static property Windows::UI::Xaml::DependencyProperty^ name##Property {\
|
||||
Windows::UI::Xaml::DependencyProperty^ get() { assert(s_##name##Property); return s_##name##Property; }\
|
||||
static type Get##name(Windows::UI::Xaml::DependencyObject ^ target) \
|
||||
{ \
|
||||
return safe_cast<type>(target->GetValue(s_##name##Property)); \
|
||||
} \
|
||||
private: static Windows::UI::Xaml::DependencyProperty^ Initialize##name##Property() {\
|
||||
return Utils::RegisterDependencyPropertyAttached<DependencyPropertiesOwner, type>(L#name, defaultValue); } public:
|
||||
static void Set##name(Windows::UI::Xaml::DependencyObject ^ target, type value) \
|
||||
{ \
|
||||
target->SetValue(s_##name##Property, value); \
|
||||
} \
|
||||
\
|
||||
private: \
|
||||
static Windows::UI::Xaml::DependencyProperty ^ s_##name##Property; \
|
||||
\
|
||||
public: \
|
||||
static property Windows::UI::Xaml::DependencyProperty ^ name##Property \
|
||||
{ \
|
||||
Windows::UI::Xaml::DependencyProperty ^ get() { \
|
||||
assert(s_##name##Property); \
|
||||
return s_##name##Property; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
private: \
|
||||
static Windows::UI::Xaml::DependencyProperty ^ Initialize##name##Property() \
|
||||
{ \
|
||||
return Utils::RegisterDependencyPropertyAttached<DependencyPropertiesOwner, type>(L#name, defaultValue); \
|
||||
} \
|
||||
\
|
||||
public:
|
||||
|
||||
#define DEPENDENCY_PROPERTY_ATTACHED_WITH_CALLBACK(type, name) \
|
||||
static type Get##name(Windows::UI::Xaml::DependencyObject^ target) { return safe_cast<type>(target->GetValue(s_##name##Property)); }\
|
||||
static void Set##name(Windows::UI::Xaml::DependencyObject^ target, type value) { target->SetValue(s_##name##Property, value); }\
|
||||
private: static Windows::UI::Xaml::DependencyProperty^ s_##name##Property;\
|
||||
public: static property Windows::UI::Xaml::DependencyProperty^ name##Property {\
|
||||
Windows::UI::Xaml::DependencyProperty^ get() { assert(s_##name##Property); return s_##name##Property; }\
|
||||
static type Get##name(Windows::UI::Xaml::DependencyObject ^ target) \
|
||||
{ \
|
||||
return safe_cast<type>(target->GetValue(s_##name##Property)); \
|
||||
} \
|
||||
private: static Windows::UI::Xaml::DependencyProperty^ Initialize##name##Property() {\
|
||||
return Utils::RegisterDependencyPropertyAttachedWithCallback<DependencyPropertiesOwner, type>(L#name, &On##name##PropertyChangedImpl); }\
|
||||
static void On##name##PropertyChangedImpl(Windows::UI::Xaml::DependencyObject^ sender, Windows::UI::Xaml::DependencyPropertyChangedEventArgs^ args) {\
|
||||
On##name##PropertyChanged(sender, safe_cast<type>(args->OldValue), safe_cast<type>(args->NewValue)); } public:
|
||||
static void Set##name(Windows::UI::Xaml::DependencyObject ^ target, type value) \
|
||||
{ \
|
||||
target->SetValue(s_##name##Property, value); \
|
||||
} \
|
||||
\
|
||||
private: \
|
||||
static Windows::UI::Xaml::DependencyProperty ^ s_##name##Property; \
|
||||
\
|
||||
public: \
|
||||
static property Windows::UI::Xaml::DependencyProperty ^ name##Property \
|
||||
{ \
|
||||
Windows::UI::Xaml::DependencyProperty ^ get() { \
|
||||
assert(s_##name##Property); \
|
||||
return s_##name##Property; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
private: \
|
||||
static Windows::UI::Xaml::DependencyProperty ^ Initialize##name##Property() \
|
||||
{ \
|
||||
return Utils::RegisterDependencyPropertyAttachedWithCallback<DependencyPropertiesOwner, type>(L#name, &On##name##PropertyChangedImpl); \
|
||||
} \
|
||||
static void On##name##PropertyChangedImpl(Windows::UI::Xaml::DependencyObject ^ sender, Windows::UI::Xaml::DependencyPropertyChangedEventArgs ^ args) \
|
||||
{ \
|
||||
On##name##PropertyChanged(sender, safe_cast<type>(args->OldValue), safe_cast<type>(args->NewValue)); \
|
||||
} \
|
||||
\
|
||||
public:
|
||||
|
||||
#define DEPENDENCY_PROPERTY_ATTACHED_WITH_DEFAULT_AND_CALLBACK(type, name, defaultValue) \
|
||||
static type Get##name(Windows::UI::Xaml::DependencyObject^ target) { return safe_cast<type>(target->GetValue(s_##name##Property)); }\
|
||||
static void Set##name(Windows::UI::Xaml::DependencyObject^ target, type value) { target->SetValue(s_##name##Property, value); }\
|
||||
private: static Windows::UI::Xaml::DependencyProperty^ s_##name##Property;\
|
||||
public: static property Windows::UI::Xaml::DependencyProperty^ name##Property {\
|
||||
Windows::UI::Xaml::DependencyProperty^ get() { assert(s_##name##Property); return s_##name##Property; }\
|
||||
static type Get##name(Windows::UI::Xaml::DependencyObject ^ target) \
|
||||
{ \
|
||||
return safe_cast<type>(target->GetValue(s_##name##Property)); \
|
||||
} \
|
||||
private: static Windows::UI::Xaml::DependencyProperty^ Initialize##name##Property() {\
|
||||
return Utils::RegisterDependencyPropertyAttachedWithCallback<DependencyPropertiesOwner, type>(L#name, defaultValue, &On##name##PropertyChangedImpl); }\
|
||||
static void On##name##PropertyChangedImpl(Windows::UI::Xaml::DependencyObject^ sender, Windows::UI::Xaml::DependencyPropertyChangedEventArgs^ args) {\
|
||||
On##name##PropertyChanged(sender, safe_cast<type>(args->OldValue), safe_cast<type>(args->NewValue)); } public:
|
||||
static void Set##name(Windows::UI::Xaml::DependencyObject ^ target, type value) \
|
||||
{ \
|
||||
target->SetValue(s_##name##Property, value); \
|
||||
} \
|
||||
\
|
||||
private: \
|
||||
static Windows::UI::Xaml::DependencyProperty ^ s_##name##Property; \
|
||||
\
|
||||
public: \
|
||||
static property Windows::UI::Xaml::DependencyProperty ^ name##Property \
|
||||
{ \
|
||||
Windows::UI::Xaml::DependencyProperty ^ get() { \
|
||||
assert(s_##name##Property); \
|
||||
return s_##name##Property; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
private: \
|
||||
static Windows::UI::Xaml::DependencyProperty ^ Initialize##name##Property() \
|
||||
{ \
|
||||
return Utils::RegisterDependencyPropertyAttachedWithCallback<DependencyPropertiesOwner, type>(L#name, defaultValue, &On##name##PropertyChangedImpl); \
|
||||
} \
|
||||
static void On##name##PropertyChangedImpl(Windows::UI::Xaml::DependencyObject ^ sender, Windows::UI::Xaml::DependencyPropertyChangedEventArgs ^ args) \
|
||||
{ \
|
||||
On##name##PropertyChanged(sender, safe_cast<type>(args->OldValue), safe_cast<type>(args->NewValue)); \
|
||||
} \
|
||||
\
|
||||
public:
|
||||
|
||||
// This goes into the cpp to initialize the static variable
|
||||
#define DEPENDENCY_PROPERTY_INITIALIZATION(owner, name)\
|
||||
Windows::UI::Xaml::DependencyProperty^ owner::s_##name##Property =\
|
||||
owner::Initialize##name##Property();
|
||||
#define DEPENDENCY_PROPERTY_INITIALIZATION(owner, name) Windows::UI::Xaml::DependencyProperty ^ owner::s_##name##Property = owner::Initialize##name##Property();
|
||||
|
||||
namespace CalculatorApp
|
||||
{
|
||||
|
@ -415,8 +692,7 @@ namespace CalculatorApp
|
|||
{
|
||||
T to{ nullptr };
|
||||
|
||||
winrt::check_hresult(reinterpret_cast<::IUnknown*>(from)->QueryInterface(winrt::guid_of<T>(),
|
||||
reinterpret_cast<void**>(winrt::put_abi(to))));
|
||||
winrt::check_hresult(reinterpret_cast<::IUnknown*>(from)->QueryInterface(winrt::guid_of<T>(), reinterpret_cast<void**>(winrt::put_abi(to))));
|
||||
|
||||
return to;
|
||||
}
|
||||
|
|
|
@ -3,17 +3,21 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
namespace CalculatorApp { namespace Common
|
||||
namespace CalculatorApp
|
||||
{
|
||||
public ref class ValidSelectedItemConverter sealed: public Windows::UI::Xaml::Data::IValueConverter
|
||||
namespace Common
|
||||
{
|
||||
public
|
||||
ref class ValidSelectedItemConverter sealed : public Windows::UI::Xaml::Data::IValueConverter
|
||||
{
|
||||
public:
|
||||
ValidSelectedItemConverter()
|
||||
{ }
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
virtual Platform::Object^ Convert(
|
||||
virtual Platform::Object
|
||||
^ Convert(
|
||||
Platform::Object ^ value,
|
||||
Windows::UI::Xaml::Interop::TypeName /*targetType*/,
|
||||
Platform::Object ^ /*parameter*/,
|
||||
|
@ -23,7 +27,8 @@ namespace CalculatorApp { namespace Common
|
|||
return value;
|
||||
}
|
||||
|
||||
virtual Platform::Object^ ConvertBack(
|
||||
virtual Platform::Object
|
||||
^ ConvertBack(
|
||||
Platform::Object ^ value,
|
||||
Windows::UI::Xaml::Interop::TypeName /*targetType*/,
|
||||
Platform::Object ^ /*parameter*/,
|
||||
|
@ -38,15 +43,17 @@ namespace CalculatorApp { namespace Common
|
|||
}
|
||||
};
|
||||
|
||||
public ref class ValidSelectedIndexConverter sealed: public Windows::UI::Xaml::Data::IValueConverter
|
||||
public
|
||||
ref class ValidSelectedIndexConverter sealed : public Windows::UI::Xaml::Data::IValueConverter
|
||||
{
|
||||
public:
|
||||
ValidSelectedIndexConverter()
|
||||
{ }
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
virtual Platform::Object^ Convert(
|
||||
virtual Platform::Object
|
||||
^ Convert(
|
||||
Platform::Object ^ value,
|
||||
Windows::UI::Xaml::Interop::TypeName /*targetType*/,
|
||||
Platform::Object ^ /*parameter*/,
|
||||
|
@ -56,7 +63,8 @@ namespace CalculatorApp { namespace Common
|
|||
return value;
|
||||
}
|
||||
|
||||
virtual Platform::Object^ ConvertBack(
|
||||
virtual Platform::Object
|
||||
^ ConvertBack(
|
||||
Platform::Object ^ value,
|
||||
Windows::UI::Xaml::Interop::TypeName /*targetType*/,
|
||||
Platform::Object ^ /*parameter*/,
|
||||
|
@ -80,4 +88,5 @@ namespace CalculatorApp { namespace Common
|
|||
return Windows::UI::Xaml::DependencyProperty::UnsetValue;
|
||||
}
|
||||
};
|
||||
}}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,21 +46,16 @@ static constexpr auto CACHE_LANGCODE_KEY = L"CURRENCY_CONVERTER_LANGCODE";
|
|||
static constexpr auto CACHE_DELIMITER = L"%";
|
||||
|
||||
static constexpr auto STATIC_DATA_FILENAME = L"CURRENCY_CONVERTER_STATIC_DATA.txt";
|
||||
static constexpr array<wstring_view, 5> STATIC_DATA_PROPERTIES = {
|
||||
wstring_view{ L"CountryCode", 11 },
|
||||
static constexpr array<wstring_view, 5> STATIC_DATA_PROPERTIES = { wstring_view{ L"CountryCode", 11 },
|
||||
wstring_view{ L"CountryName", 11 },
|
||||
wstring_view{ L"CurrencyCode", 12 },
|
||||
wstring_view{ L"CurrencyName", 12 },
|
||||
wstring_view{ L"CurrencySymbol", 14 }
|
||||
};
|
||||
wstring_view{ L"CurrencySymbol", 14 } };
|
||||
|
||||
static constexpr auto ALL_RATIOS_DATA_FILENAME = L"CURRENCY_CONVERTER_ALL_RATIOS_DATA.txt";
|
||||
static constexpr auto RATIO_KEY = L"Rt";
|
||||
static constexpr auto CURRENCY_CODE_KEY = L"An";
|
||||
static constexpr array<wstring_view, 2> ALL_RATIOS_DATA_PROPERTIES = {
|
||||
wstring_view{ RATIO_KEY, 2 },
|
||||
wstring_view{ CURRENCY_CODE_KEY, 2 }
|
||||
};
|
||||
static constexpr array<wstring_view, 2> ALL_RATIOS_DATA_PROPERTIES = { wstring_view{ RATIO_KEY, 2 }, wstring_view{ CURRENCY_CODE_KEY, 2 } };
|
||||
|
||||
static constexpr auto DEFAULT_FROM_TO_CURRENCY_FILE_URI = L"ms-appx:///DataLoaders/DefaultFromToCurrency.json";
|
||||
static constexpr auto FROM_KEY = L"from";
|
||||
|
@ -92,14 +87,14 @@ namespace CalculatorApp
|
|||
}
|
||||
}
|
||||
|
||||
CurrencyDataLoader::CurrencyDataLoader(_In_ unique_ptr<ICurrencyHttpClient> client) :
|
||||
m_client(move(client)),
|
||||
m_loadStatus(CurrencyLoadStatus::NotLoaded),
|
||||
m_responseLanguage(L"en-US"),
|
||||
m_ratioFormat(L""),
|
||||
m_timestampFormat(L""),
|
||||
m_networkManager(ref new NetworkManager()),
|
||||
m_meteredOverrideSet(false)
|
||||
CurrencyDataLoader::CurrencyDataLoader(_In_ unique_ptr<ICurrencyHttpClient> client)
|
||||
: m_client(move(client))
|
||||
, m_loadStatus(CurrencyLoadStatus::NotLoaded)
|
||||
, m_responseLanguage(L"en-US")
|
||||
, m_ratioFormat(L"")
|
||||
, m_timestampFormat(L"")
|
||||
, m_networkManager(ref new NetworkManager())
|
||||
, m_meteredOverrideSet(false)
|
||||
{
|
||||
if (GlobalizationPreferences::Languages->Size > 0)
|
||||
{
|
||||
|
@ -141,11 +136,8 @@ void CurrencyDataLoader::RegisterForNetworkBehaviorChanges()
|
|||
{
|
||||
UnregisterForNetworkBehaviorChanges();
|
||||
|
||||
m_networkBehaviorToken =
|
||||
m_networkManager->NetworkBehaviorChanged += ref new NetworkBehaviorChangedHandler([this](NetworkAccessBehavior newBehavior)
|
||||
{
|
||||
this->OnNetworkBehaviorChanged(newBehavior);
|
||||
});
|
||||
m_networkBehaviorToken = m_networkManager->NetworkBehaviorChanged +=
|
||||
ref new NetworkBehaviorChangedHandler([this](NetworkAccessBehavior newBehavior) { this->OnNetworkBehaviorChanged(newBehavior); });
|
||||
|
||||
OnNetworkBehaviorChanged(NetworkManager::GetNetworkAccessBehavior());
|
||||
}
|
||||
|
@ -186,8 +178,7 @@ void CurrencyDataLoader::LoadData()
|
|||
|
||||
if (!LoadFinished())
|
||||
{
|
||||
create_task([this]() -> task<bool>
|
||||
{
|
||||
create_task([this]() -> task<bool> {
|
||||
vector<function<task<bool>()>> loadFunctions = {
|
||||
[this]() { return TryLoadDataFromCacheAsync(); },
|
||||
[this]() { return TryLoadDataFromWebAsync(); },
|
||||
|
@ -204,11 +195,13 @@ void CurrencyDataLoader::LoadData()
|
|||
}
|
||||
|
||||
co_return didLoad;
|
||||
}).then([this](bool didLoad)
|
||||
{
|
||||
})
|
||||
.then(
|
||||
[this](bool didLoad) {
|
||||
UpdateDisplayedTimestamp();
|
||||
NotifyDataLoadFinished(didLoad);
|
||||
}, task_continuation_context::use_current());
|
||||
},
|
||||
task_continuation_context::use_current());
|
||||
}
|
||||
};
|
||||
#pragma optimize("", on)
|
||||
|
@ -285,26 +278,18 @@ pair<wstring, wstring> CurrencyDataLoader::GetCurrencyRatioEquality(_In_ const U
|
|||
wstring roundedFormat = m_ratioFormatter->Format(rounded)->Data();
|
||||
|
||||
wstring ratioString = LocalizationStringUtil::GetLocalizedString(
|
||||
m_ratioFormat.c_str(),
|
||||
digitSymbol.c_str(),
|
||||
unit1.abbreviation.c_str(),
|
||||
roundedFormat.c_str(),
|
||||
unit2.abbreviation.c_str()
|
||||
);
|
||||
m_ratioFormat.c_str(), digitSymbol.c_str(), unit1.abbreviation.c_str(), roundedFormat.c_str(), unit2.abbreviation.c_str());
|
||||
|
||||
wstring accessibleRatioString = LocalizationStringUtil::GetLocalizedString(
|
||||
m_ratioFormat.c_str(),
|
||||
digitSymbol.c_str(),
|
||||
unit1.accessibleName.c_str(),
|
||||
roundedFormat.c_str(),
|
||||
unit2.accessibleName.c_str()
|
||||
);
|
||||
m_ratioFormat.c_str(), digitSymbol.c_str(), unit1.accessibleName.c_str(), roundedFormat.c_str(), unit2.accessibleName.c_str());
|
||||
|
||||
return make_pair(ratioString, accessibleRatioString);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (...) {}
|
||||
catch (...)
|
||||
{
|
||||
}
|
||||
|
||||
return make_pair(L"", L"");
|
||||
}
|
||||
|
@ -324,8 +309,7 @@ task<bool> CurrencyDataLoader::TryLoadDataFromCacheAsync()
|
|||
|
||||
bool loadComplete = false;
|
||||
m_cacheTimestamp = static_cast<DateTime>(localSettings->Values->Lookup(CacheTimestampKey));
|
||||
if (Utils::IsDateTimeOlderThan(m_cacheTimestamp, DAY_DURATION)
|
||||
&& m_networkAccessBehavior == NetworkAccessBehavior::Normal)
|
||||
if (Utils::IsDateTimeOlderThan(m_cacheTimestamp, DAY_DURATION) && m_networkAccessBehavior == NetworkAccessBehavior::Normal)
|
||||
{
|
||||
loadComplete = co_await TryLoadDataFromWebAsync();
|
||||
}
|
||||
|
@ -361,8 +345,7 @@ task<bool> CurrencyDataLoader::TryFinishLoadFromCacheAsync()
|
|||
co_return false;
|
||||
}
|
||||
|
||||
if (!localSettings->Values->HasKey(CacheLangcodeKey)
|
||||
|| !static_cast<String^>(localSettings->Values->Lookup(CacheLangcodeKey))->Equals(m_responseLanguage))
|
||||
if (!localSettings->Values->HasKey(CacheLangcodeKey) || !static_cast<String ^>(localSettings->Values->Lookup(CacheLangcodeKey))->Equals(m_responseLanguage))
|
||||
{
|
||||
co_return false;
|
||||
}
|
||||
|
@ -379,11 +362,7 @@ task<bool> CurrencyDataLoader::TryFinishLoadFromCacheAsync()
|
|||
vector<UCM::CurrencyStaticData> staticData{};
|
||||
CurrencyRatioMap ratioMap{};
|
||||
|
||||
bool didParse = TryParseWebResponses(
|
||||
staticDataResponse,
|
||||
allRatiosResponse,
|
||||
staticData,
|
||||
ratioMap);
|
||||
bool didParse = TryParseWebResponses(staticDataResponse, allRatiosResponse, staticData, ratioMap);
|
||||
if (!didParse)
|
||||
{
|
||||
co_return false;
|
||||
|
@ -406,8 +385,7 @@ task<bool> CurrencyDataLoader::TryLoadDataFromWebAsync()
|
|||
co_return false;
|
||||
}
|
||||
|
||||
if (m_networkAccessBehavior == NetworkAccessBehavior::Offline ||
|
||||
(m_networkAccessBehavior == NetworkAccessBehavior::OptIn && !m_meteredOverrideSet))
|
||||
if (m_networkAccessBehavior == NetworkAccessBehavior::Offline || (m_networkAccessBehavior == NetworkAccessBehavior::OptIn && !m_meteredOverrideSet))
|
||||
{
|
||||
co_return false;
|
||||
}
|
||||
|
@ -422,11 +400,7 @@ task<bool> CurrencyDataLoader::TryLoadDataFromWebAsync()
|
|||
vector<UCM::CurrencyStaticData> staticData{};
|
||||
CurrencyRatioMap ratioMap{};
|
||||
|
||||
bool didParse = TryParseWebResponses(
|
||||
staticDataResponse,
|
||||
allRatiosResponse,
|
||||
staticData,
|
||||
ratioMap);
|
||||
bool didParse = TryParseWebResponses(staticDataResponse, allRatiosResponse, staticData, ratioMap);
|
||||
if (!didParse)
|
||||
{
|
||||
co_return false;
|
||||
|
@ -437,19 +411,12 @@ task<bool> CurrencyDataLoader::TryLoadDataFromWebAsync()
|
|||
|
||||
try
|
||||
{
|
||||
const vector<pair<String^, String^>> cachedFiles = {
|
||||
{ StaticDataFilename, staticDataResponse },
|
||||
{ AllRatiosDataFilename, allRatiosResponse }
|
||||
};
|
||||
const vector<pair<String ^, String ^>> cachedFiles = { { StaticDataFilename, staticDataResponse }, { AllRatiosDataFilename, allRatiosResponse } };
|
||||
|
||||
StorageFolder ^ localCacheFolder = ApplicationData::Current->LocalCacheFolder;
|
||||
for (const auto& fileInfo : cachedFiles)
|
||||
{
|
||||
co_await Utils::WriteFileToFolder(
|
||||
localCacheFolder,
|
||||
fileInfo.first,
|
||||
fileInfo.second,
|
||||
CreationCollisionOption::ReplaceExisting);
|
||||
co_await Utils::WriteFileToFolder(localCacheFolder, fileInfo.first, fileInfo.second, CreationCollisionOption::ReplaceExisting);
|
||||
}
|
||||
|
||||
SaveLangCodeAndTimestamp();
|
||||
|
@ -500,8 +467,7 @@ bool CurrencyDataLoader::TryParseWebResponses(
|
|||
_Inout_ vector<UCM::CurrencyStaticData>& staticData,
|
||||
_Inout_ CurrencyRatioMap& allRatiosData)
|
||||
{
|
||||
return TryParseStaticData(staticDataJson, staticData)
|
||||
&& TryParseAllRatiosData(allRatiosJson, allRatiosData);
|
||||
return TryParseStaticData(staticDataJson, staticData) && TryParseAllRatiosData(allRatiosJson, allRatiosData);
|
||||
}
|
||||
|
||||
bool CurrencyDataLoader::TryParseStaticData(_In_ String ^ rawJson, _Inout_ vector<UCM::CurrencyStaticData>& staticData)
|
||||
|
@ -518,13 +484,7 @@ bool CurrencyDataLoader::TryParseStaticData(_In_ String^ rawJson, _Inout_ vector
|
|||
wstring currencyName{ L"" };
|
||||
wstring currencySymbol{ L"" };
|
||||
|
||||
vector<wstring*> values = {
|
||||
&countryCode,
|
||||
&countryName,
|
||||
¤cyCode,
|
||||
¤cyName,
|
||||
¤cySymbol
|
||||
};
|
||||
vector<wstring*> values = { &countryCode, &countryName, ¤cyCode, ¤cyName, ¤cySymbol };
|
||||
|
||||
assert(values.size() == STATIC_DATA_PROPERTIES.size());
|
||||
staticData.resize(size_t{ data->Size });
|
||||
|
@ -537,20 +497,11 @@ bool CurrencyDataLoader::TryParseStaticData(_In_ String^ rawJson, _Inout_ vector
|
|||
(*values[j]) = obj->GetNamedString(StringReference(STATIC_DATA_PROPERTIES[j].data()))->Data();
|
||||
}
|
||||
|
||||
staticData[i] = CurrencyStaticData{
|
||||
countryCode,
|
||||
countryName,
|
||||
currencyCode,
|
||||
currencyName,
|
||||
currencySymbol
|
||||
};
|
||||
staticData[i] = CurrencyStaticData{ countryCode, countryName, currencyCode, currencyName, currencySymbol };
|
||||
}
|
||||
|
||||
// TODO - MSFT 8533667: this sort will be replaced by a WinRT call to sort localized strings
|
||||
sort(begin(staticData), end(staticData), [](CurrencyStaticData unit1, CurrencyStaticData unit2)
|
||||
{
|
||||
return unit1.countryName < unit2.countryName;
|
||||
});
|
||||
sort(begin(staticData), end(staticData), [](CurrencyStaticData unit1, CurrencyStaticData unit2) { return unit1.countryName < unit2.countryName; });
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -574,11 +525,7 @@ bool CurrencyDataLoader::TryParseAllRatiosData(_In_ String^ rawJson, _Inout_ Cur
|
|||
double relativeRatio = obj->GetNamedNumber(StringReference(RATIO_KEY));
|
||||
wstring targetCurrencyCode = obj->GetNamedString(StringReference(CURRENCY_CODE_KEY))->Data();
|
||||
|
||||
allRatios.emplace(targetCurrencyCode, CurrencyRatio{
|
||||
relativeRatio,
|
||||
sourceCurrencyCode,
|
||||
targetCurrencyCode
|
||||
});
|
||||
allRatios.emplace(targetCurrencyCode, CurrencyRatio{ relativeRatio, sourceCurrencyCode, targetCurrencyCode });
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -735,11 +682,7 @@ wstring CurrencyDataLoader::GetCurrencyTimestamp()
|
|||
DateTimeFormatter ^ timeFormatter = ref new DateTimeFormatter(L"shorttime");
|
||||
wstring time = timeFormatter->Format(m_cacheTimestamp)->Data();
|
||||
|
||||
timestamp = LocalizationStringUtil::GetLocalizedString(
|
||||
m_timestampFormat.c_str(),
|
||||
date.c_str(),
|
||||
time.c_str()
|
||||
);
|
||||
timestamp = LocalizationStringUtil::GetLocalizedString(m_timestampFormat.c_str(), date.c_str(), time.c_str());
|
||||
}
|
||||
|
||||
return timestamp;
|
||||
|
@ -774,7 +717,9 @@ task<SelectedUnits> CurrencyDataLoader::GetDefaultFromToCurrency()
|
|||
toCurrency = selectedTo->Data();
|
||||
}
|
||||
}
|
||||
catch (...) {}
|
||||
catch (...)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
co_return make_pair(fromCurrency, toCurrency);
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue