Merge master into feature/GraphingCalculator branch (#585)

* Merge master into feature/GraphingCalculator branch
This commit is contained in:
Stephanie Anderl
2019-07-15 11:17:21 -07:00
committed by GitHub
parent 1475b49120
commit a418777f02
447 changed files with 18056 additions and 19323 deletions

View File

@@ -36,7 +36,6 @@ namespace
{
StringReference CategoriesPropertyName(L"Categories");
StringReference ClearMemoryVisibilityPropertyName(L"ClearMemoryVisibility");
StringReference AppBarVisibilityPropertyName(L"AppBarVisibility");
}
ApplicationViewModel::ApplicationViewModel() :
@@ -62,7 +61,7 @@ void ApplicationViewModel::Mode::set(ViewMode value)
}
}
void ApplicationViewModel::Categories::set(IObservableVector<NavCategoryGroup^>^ value)
void ApplicationViewModel::Categories::set(IObservableVector<NavCategoryGroup ^> ^ value)
{
if (m_categories != value)
{
@@ -92,7 +91,7 @@ void ApplicationViewModel::Initialize(ViewMode mode)
throw;
}
}
catch (Exception^ e)
catch (Exception ^ e)
{
TraceLogger::GetInstance().LogPlatformException(__FUNCTIONW__, e);
if (!TryRecoverFromNavigationModeFailure())
@@ -172,10 +171,9 @@ void ApplicationViewModel::OnModeChanged()
TraceLogger::GetInstance().LogModeChangeEnd(m_mode, ApplicationView::GetApplicationViewIdForWindow(CoreWindow::GetForCurrentThread()));
RaisePropertyChanged(ClearMemoryVisibilityPropertyName);
RaisePropertyChanged(AppBarVisibilityPropertyName);
}
void ApplicationViewModel::OnCopyCommand(Object^ parameter)
void ApplicationViewModel::OnCopyCommand(Object ^ parameter)
{
if (NavCategory::IsConverterViewMode(m_mode))
{
@@ -191,13 +189,13 @@ void ApplicationViewModel::OnCopyCommand(Object^ parameter)
}
}
void ApplicationViewModel::OnPasteCommand(Object^ parameter)
void ApplicationViewModel::OnPasteCommand(Object ^ parameter)
{
if (NavCategory::IsConverterViewMode(m_mode))
{
ConverterViewModel->OnPasteCommand(parameter);
}
else
else if (NavCategory::IsCalculatorViewMode(m_mode))
{
CalculatorViewModel->OnPasteCommand(parameter);
}

View File

@@ -12,13 +12,12 @@ 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();
void Initialize(CalculatorApp::Common::ViewMode mode); // Use for first init, use deserialize for rehydration
void Initialize(CalculatorApp::Common::ViewMode mode); // Use for first init, use deserialize for rehydration
OBSERVABLE_OBJECT();
OBSERVABLE_PROPERTY_RW(StandardCalculatorViewModel^, CalculatorViewModel);
@@ -26,7 +25,7 @@ namespace CalculatorApp
OBSERVABLE_PROPERTY_RW(GraphingCalculatorViewModel^, GraphingCalcViewModel);
OBSERVABLE_PROPERTY_RW(UnitConverterViewModel^, ConverterViewModel);
OBSERVABLE_PROPERTY_RW(CalculatorApp::Common::ViewMode, PreviousMode);
OBSERVABLE_NAMED_PROPERTY_RW(Platform::String^, CategoryName);
OBSERVABLE_NAMED_PROPERTY_RW(Platform::String ^, CategoryName);
COMMAND_FOR_METHOD(CopyCommand, ApplicationViewModel::OnCopyCommand);
COMMAND_FOR_METHOD(PasteCommand, ApplicationViewModel::OnPasteCommand);
@@ -62,19 +61,8 @@ namespace CalculatorApp
{
Windows::UI::Xaml::Visibility get()
{
return CalculatorApp::Common::NavCategory::IsCalculatorViewMode(Mode)
? Windows::UI::Xaml::Visibility::Visible
: Windows::UI::Xaml::Visibility::Collapsed;
}
}
property Windows::UI::Xaml::Visibility AppBarVisibility
{
Windows::UI::Xaml::Visibility get()
{
return CalculatorApp::Common::NavCategory::IsCalculatorViewMode(Mode)
? Windows::UI::Xaml::Visibility::Visible
: Windows::UI::Xaml::Visibility::Collapsed;
return CalculatorApp::Common::NavCategory::IsCalculatorViewMode(Mode) ? Windows::UI::Xaml::Visibility::Visible
: Windows::UI::Xaml::Visibility::Collapsed;
}
}
@@ -83,13 +71,13 @@ namespace CalculatorApp
void OnModeChanged();
void OnCopyCommand(Platform::Object^ parameter);
void OnPasteCommand(Platform::Object^ parameter);
void OnCopyCommand(Platform::Object ^ parameter);
void OnPasteCommand(Platform::Object ^ parameter);
void SetMenuCategories();
CalculatorApp::Common::ViewMode m_mode;
Windows::Foundation::Collections::IObservableVector<CalculatorApp::Common::NavCategoryGroup^>^ m_categories;
Windows::Foundation::Collections::IObservableVector<CalculatorApp::Common::NavCategoryGroup ^> ^ m_categories;
};
}
}

View File

@@ -42,54 +42,54 @@
<MinimumVisualStudioVersion>14.0</MinimumVisualStudioVersion>
<AppContainerApplication>true</AppContainerApplication>
<ApplicationType>Windows Store</ApplicationType>
<WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion>
<WindowsTargetPlatformMinVersion>10.0.17134.0</WindowsTargetPlatformMinVersion>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
<WindowsTargetPlatformMinVersion>10.0.18362.0</WindowsTargetPlatformMinVersion>
<ApplicationTypeRevision>10.0</ApplicationTypeRevision>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<PlatformToolset>v142</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<PlatformToolset>v142</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<PlatformToolset>v142</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<PlatformToolset>v142</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<PlatformToolset>v141</PlatformToolset>
<PlatformToolset>v142</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<PlatformToolset>v141</PlatformToolset>
<PlatformToolset>v142</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<PlatformToolset>v141</PlatformToolset>
<PlatformToolset>v142</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<PlatformToolset>v141</PlatformToolset>
<PlatformToolset>v142</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
@@ -153,7 +153,7 @@
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>$(SolutionDir)..\src\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<DisableSpecificWarnings>4453</DisableSpecificWarnings>
<AdditionalOptions>/bigobj /await /std:c++17 %(AdditionalOptions)</AdditionalOptions>
<AdditionalOptions>/bigobj /await /std:c++17 /utf-8 %(AdditionalOptions)</AdditionalOptions>
<WarningLevel>Level4</WarningLevel>
<TreatWarningAsError>true</TreatWarningAsError>
</ClCompile>
@@ -173,7 +173,7 @@
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>$(SolutionDir)..\src\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<DisableSpecificWarnings>4453</DisableSpecificWarnings>
<AdditionalOptions>/bigobj /await /std:c++17 %(AdditionalOptions)</AdditionalOptions>
<AdditionalOptions>/bigobj /await /std:c++17 /utf-8 %(AdditionalOptions)</AdditionalOptions>
<WarningLevel>Level4</WarningLevel>
<TreatWarningAsError>true</TreatWarningAsError>
</ClCompile>
@@ -193,7 +193,7 @@
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>$(SolutionDir)..\src\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<DisableSpecificWarnings>4453</DisableSpecificWarnings>
<AdditionalOptions>/bigobj /await /std:c++17 %(AdditionalOptions)</AdditionalOptions>
<AdditionalOptions>/bigobj /await /std:c++17 /utf-8 %(AdditionalOptions)</AdditionalOptions>
<WarningLevel>Level4</WarningLevel>
<TreatWarningAsError>true</TreatWarningAsError>
</ClCompile>
@@ -213,7 +213,7 @@
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>$(SolutionDir)..\src\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<DisableSpecificWarnings>4453</DisableSpecificWarnings>
<AdditionalOptions>/bigobj /await /std:c++17 %(AdditionalOptions)</AdditionalOptions>
<AdditionalOptions>/bigobj /await /std:c++17 /utf-8 %(AdditionalOptions)</AdditionalOptions>
<WarningLevel>Level4</WarningLevel>
<TreatWarningAsError>true</TreatWarningAsError>
</ClCompile>
@@ -233,7 +233,7 @@
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>$(SolutionDir)..\src\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<DisableSpecificWarnings>4453</DisableSpecificWarnings>
<AdditionalOptions>/bigobj /await /std:c++17 %(AdditionalOptions)</AdditionalOptions>
<AdditionalOptions>/bigobj /await /std:c++17 /utf-8 %(AdditionalOptions)</AdditionalOptions>
<WarningLevel>Level4</WarningLevel>
<TreatWarningAsError>true</TreatWarningAsError>
</ClCompile>
@@ -253,7 +253,7 @@
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>$(SolutionDir)..\src\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<DisableSpecificWarnings>4453</DisableSpecificWarnings>
<AdditionalOptions>/bigobj /await /std:c++17 %(AdditionalOptions)</AdditionalOptions>
<AdditionalOptions>/bigobj /await /std:c++17 /utf-8 %(AdditionalOptions)</AdditionalOptions>
<WarningLevel>Level4</WarningLevel>
<TreatWarningAsError>true</TreatWarningAsError>
</ClCompile>
@@ -273,7 +273,7 @@
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>$(SolutionDir)..\src\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<DisableSpecificWarnings>4453</DisableSpecificWarnings>
<AdditionalOptions>/bigobj /await /std:c++17 %(AdditionalOptions)</AdditionalOptions>
<AdditionalOptions>/bigobj /await /std:c++17 /utf-8 %(AdditionalOptions)</AdditionalOptions>
<WarningLevel>Level4</WarningLevel>
<TreatWarningAsError>true</TreatWarningAsError>
</ClCompile>
@@ -293,7 +293,7 @@
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>$(SolutionDir)..\src\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<DisableSpecificWarnings>4453</DisableSpecificWarnings>
<AdditionalOptions>/bigobj /await /std:c++17 %(AdditionalOptions)</AdditionalOptions>
<AdditionalOptions>/bigobj /await /std:c++17 /utf-8 %(AdditionalOptions)</AdditionalOptions>
<WarningLevel>Level4</WarningLevel>
<TreatWarningAsError>true</TreatWarningAsError>
</ClCompile>
@@ -412,6 +412,23 @@
<Project>{311e866d-8b93-4609-a691-265941fee101}</Project>
</ProjectReference>
</ItemGroup>
<ItemDefinitionGroup Condition="!Exists('DataLoaders\DataLoaderConstants.h')">
<ClCompile>
<AdditionalOptions>/DUSE_MOCK_DATA %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
</ItemDefinitionGroup>
<Choose>
<When Condition="Exists('DataLoaders\DataLoaderConstants.h')">
<ItemGroup>
<ClInclude Include="DataLoaders\DataLoaderConstants.h" />
</ItemGroup>
</When>
<Otherwise>
<ItemGroup>
<ClInclude Include="DataLoaders\DataLoaderMockConstants.h" />
</ItemGroup>
</Otherwise>
</Choose>
<ItemGroup>
<None Include="DataLoaders\DefaultFromToCurrency.json" />
<None Include="packages.config" />

View File

@@ -1,238 +1,95 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Common">
<UniqueIdentifier>{1daab7c4-63f6-4266-a259-f34acad66d09}</UniqueIdentifier>
</Filter>
<Filter Include="Common\Automation">
<UniqueIdentifier>{8d4edf06-c312-4312-978a-b6c2beb8295a}</UniqueIdentifier>
</Filter>
<Filter Include="DataLoaders">
<UniqueIdentifier>{0184f727-b8aa-4af8-a699-63f1b56e7853}</UniqueIdentifier>
</Filter>
<Filter Include="GraphingCalculator">
<UniqueIdentifier>{f7519cec-2ebd-432b-9d59-9647de131d50}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="pch.cpp" />
<ClCompile Include="ApplicationViewModel.cpp" />
<ClCompile Include="Common\AppResourceProvider.cpp" />
<ClCompile Include="Common\Automation\LiveRegionHost.cpp" />
<ClCompile Include="Common\Automation\NarratorAnnouncement.cpp" />
<ClCompile Include="Common\Automation\NarratorAnnouncementHostFactory.cpp" />
<ClCompile Include="Common\Automation\NarratorNotifier.cpp" />
<ClCompile Include="Common\Automation\NotificationHost.cpp" />
<ClCompile Include="Common\BindableBase.cpp" />
<ClCompile Include="Common\CalculatorButtonPressedEventArgs.cpp" />
<ClCompile Include="Common\CalculatorDisplay.cpp" />
<ClCompile Include="Common\ConversionResultTaskHelper.cpp" />
<ClCompile Include="Common\CopyPasteManager.cpp" />
<ClCompile Include="Common\DateCalculator.cpp" />
<ClCompile Include="Common\EngineResourceProvider.cpp" />
<ClCompile Include="Common\ExpressionCommandDeserializer.cpp" />
<ClCompile Include="Common\ExpressionCommandSerializer.cpp" />
<ClCompile Include="Common\KeyboardShortcutManager.cpp" />
<ClCompile Include="Common\LocalizationService.cpp" />
<ClCompile Include="Common\NavCategory.cpp" />
<ClCompile Include="Common\NetworkManager.cpp" />
<ClCompile Include="Common\TraceLogger.cpp" />
<ClCompile Include="Common\Utils.cpp" />
<ClCompile Include="DataLoaders\CurrencyDataLoader.cpp" />
<ClCompile Include="DataLoaders\CurrencyHttpClient.cpp" />
<ClCompile Include="DataLoaders\UnitConverterDataLoader.cpp" />
<ClCompile Include="DateCalculatorViewModel.cpp" />
<ClCompile Include="GraphingCalculator\EquationViewModel.cpp" />
<ClCompile Include="GraphingCalculator\GraphingCalculatorViewModel.cpp" />
<ClCompile Include="HistoryItemViewModel.cpp" />
<ClCompile Include="HistoryViewModel.cpp" />
<ClCompile Include="MemoryItemViewModel.cpp" />
<ClCompile Include="pch.cpp" />
<ClCompile Include="StandardCalculatorViewModel.cpp" />
<ClCompile Include="UnitConverterViewModel.cpp" />
<ClCompile Include="ViewState.cpp" />
<ClCompile Include="Common\AppResourceProvider.cpp">
<Filter>Common</Filter>
</ClCompile>
<ClCompile Include="Common\BindableBase.cpp">
<Filter>Common</Filter>
</ClCompile>
<ClCompile Include="Common\CalculatorButtonPressedEventArgs.cpp">
<Filter>Common</Filter>
</ClCompile>
<ClCompile Include="Common\CalculatorDisplay.cpp">
<Filter>Common</Filter>
</ClCompile>
<ClCompile Include="Common\ConversionResultTaskHelper.cpp">
<Filter>Common</Filter>
</ClCompile>
<ClCompile Include="Common\CopyPasteManager.cpp">
<Filter>Common</Filter>
</ClCompile>
<ClCompile Include="Common\DateCalculator.cpp">
<Filter>Common</Filter>
</ClCompile>
<ClCompile Include="Common\EngineResourceProvider.cpp">
<Filter>Common</Filter>
</ClCompile>
<ClCompile Include="Common\ExpressionCommandDeserializer.cpp">
<Filter>Common</Filter>
</ClCompile>
<ClCompile Include="Common\ExpressionCommandSerializer.cpp">
<Filter>Common</Filter>
</ClCompile>
<ClCompile Include="Common\KeyboardShortcutManager.cpp">
<Filter>Common</Filter>
</ClCompile>
<ClCompile Include="Common\LocalizationService.cpp">
<Filter>Common</Filter>
</ClCompile>
<ClCompile Include="Common\NavCategory.cpp">
<Filter>Common</Filter>
</ClCompile>
<ClCompile Include="Common\NetworkManager.cpp">
<Filter>Common</Filter>
</ClCompile>
<ClCompile Include="Common\TraceLogger.cpp">
<Filter>Common</Filter>
</ClCompile>
<ClCompile Include="Common\Utils.cpp">
<Filter>Common</Filter>
</ClCompile>
<ClCompile Include="Common\Automation\LiveRegionHost.cpp">
<Filter>Common\Automation</Filter>
</ClCompile>
<ClCompile Include="Common\Automation\NarratorAnnouncement.cpp">
<Filter>Common\Automation</Filter>
</ClCompile>
<ClCompile Include="Common\Automation\NarratorAnnouncementHostFactory.cpp">
<Filter>Common\Automation</Filter>
</ClCompile>
<ClCompile Include="Common\Automation\NarratorNotifier.cpp">
<Filter>Common\Automation</Filter>
</ClCompile>
<ClCompile Include="Common\Automation\NotificationHost.cpp">
<Filter>Common\Automation</Filter>
</ClCompile>
<ClCompile Include="DataLoaders\CurrencyDataLoader.cpp">
<Filter>DataLoaders</Filter>
</ClCompile>
<ClCompile Include="DataLoaders\CurrencyHttpClient.cpp">
<Filter>DataLoaders</Filter>
</ClCompile>
<ClCompile Include="DataLoaders\UnitConverterDataLoader.cpp">
<Filter>DataLoaders</Filter>
</ClCompile>
<ClCompile Include="GraphingCalculator\EquationViewModel.cpp">
<Filter>GraphingCalculator</Filter>
</ClCompile>
<ClCompile Include="GraphingCalculator\GraphingCalculatorViewModel.cpp">
<Filter>GraphingCalculator</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="pch.h" />
<ClInclude Include="targetver.h" />
<ClInclude Include="ApplicationViewModel.h" />
<ClInclude Include="Common\AlwaysSelectedCollectionView.h" />
<ClInclude Include="Common\AppResourceProvider.h" />
<ClInclude Include="Common\Automation\INarratorAnnouncementHost.h" />
<ClInclude Include="Common\Automation\LiveRegionHost.h" />
<ClInclude Include="Common\Automation\NarratorAnnouncement.h" />
<ClInclude Include="Common\Automation\NarratorAnnouncementHostFactory.h" />
<ClInclude Include="Common\Automation\NarratorNotifier.h" />
<ClInclude Include="Common\Automation\NotificationHost.h" />
<ClInclude Include="Common\BindableBase.h" />
<ClInclude Include="Common\CalculatorButtonPressedEventArgs.h" />
<ClInclude Include="Common\CalculatorButtonUser.h" />
<ClInclude Include="Common\CalculatorDisplay.h" />
<ClInclude Include="Common\ConversionResultTaskHelper.h" />
<ClInclude Include="Common\CopyPasteManager.h" />
<ClInclude Include="Common\DateCalculator.h" />
<ClInclude Include="Common\DelegateCommand.h" />
<ClInclude Include="Common\DisplayExpressionToken.h" />
<ClInclude Include="Common\EngineResourceProvider.h" />
<ClInclude Include="Common\ExpressionCommandDeserializer.h" />
<ClInclude Include="Common\ExpressionCommandSerializer.h" />
<ClInclude Include="Common\KeyboardShortcutManager.h" />
<ClInclude Include="Common\LocalizationService.h" />
<ClInclude Include="Common\LocalizationSettings.h" />
<ClInclude Include="Common\LocalizationStringUtil.h" />
<ClInclude Include="Common\MyVirtualKey.h" />
<ClInclude Include="Common\NavCategory.h" />
<ClInclude Include="Common\NetworkManager.h" />
<ClInclude Include="Common\TraceActivity.h" />
<ClInclude Include="Common\TraceLogger.h" />
<ClInclude Include="Common\Utils.h" />
<ClInclude Include="Common\ValidatingConverters.h" />
<ClInclude Include="DataLoaders\CurrencyDataLoader.h" />
<ClInclude Include="DataLoaders\CurrencyHttpClient.h" />
<ClInclude Include="DataLoaders\ICurrencyHttpClient.h" />
<ClInclude Include="DataLoaders\UnitConverterDataConstants.h" />
<ClInclude Include="DataLoaders\UnitConverterDataLoader.h" />
<ClInclude Include="DateCalculatorViewModel.h" />
<ClInclude Include="GraphingCalculator\EquationViewModel.h" />
<ClInclude Include="GraphingCalculator\GraphingCalculatorViewModel.h" />
<ClInclude Include="HistoryItemViewModel.h" />
<ClInclude Include="HistoryViewModel.h" />
<ClInclude Include="MemoryItemViewModel.h" />
<ClInclude Include="pch.h" />
<ClInclude Include="StandardCalculatorViewModel.h" />
<ClInclude Include="targetver.h" />
<ClInclude Include="UnitConverterViewModel.h" />
<ClInclude Include="ViewState.h" />
<ClInclude Include="Common\AlwaysSelectedCollectionView.h">
<Filter>Common</Filter>
</ClInclude>
<ClInclude Include="Common\AppResourceProvider.h">
<Filter>Common</Filter>
</ClInclude>
<ClInclude Include="Common\BindableBase.h">
<Filter>Common</Filter>
</ClInclude>
<ClInclude Include="Common\CalculatorButtonPressedEventArgs.h">
<Filter>Common</Filter>
</ClInclude>
<ClInclude Include="Common\CalculatorButtonUser.h">
<Filter>Common</Filter>
</ClInclude>
<ClInclude Include="Common\CalculatorDisplay.h">
<Filter>Common</Filter>
</ClInclude>
<ClInclude Include="Common\ConversionResultTaskHelper.h">
<Filter>Common</Filter>
</ClInclude>
<ClInclude Include="Common\CopyPasteManager.h">
<Filter>Common</Filter>
</ClInclude>
<ClInclude Include="Common\DateCalculator.h">
<Filter>Common</Filter>
</ClInclude>
<ClInclude Include="Common\DelegateCommand.h">
<Filter>Common</Filter>
</ClInclude>
<ClInclude Include="Common\DisplayExpressionToken.h">
<Filter>Common</Filter>
</ClInclude>
<ClInclude Include="Common\EngineResourceProvider.h">
<Filter>Common</Filter>
</ClInclude>
<ClInclude Include="Common\ExpressionCommandDeserializer.h">
<Filter>Common</Filter>
</ClInclude>
<ClInclude Include="Common\ExpressionCommandSerializer.h">
<Filter>Common</Filter>
</ClInclude>
<ClInclude Include="Common\KeyboardShortcutManager.h">
<Filter>Common</Filter>
</ClInclude>
<ClInclude Include="Common\LocalizationService.h">
<Filter>Common</Filter>
</ClInclude>
<ClInclude Include="Common\LocalizationSettings.h">
<Filter>Common</Filter>
</ClInclude>
<ClInclude Include="Common\LocalizationStringUtil.h">
<Filter>Common</Filter>
</ClInclude>
<ClInclude Include="Common\MyVirtualKey.h">
<Filter>Common</Filter>
</ClInclude>
<ClInclude Include="Common\NavCategory.h">
<Filter>Common</Filter>
</ClInclude>
<ClInclude Include="Common\NetworkManager.h">
<Filter>Common</Filter>
</ClInclude>
<ClInclude Include="Common\TraceLogger.h">
<Filter>Common</Filter>
</ClInclude>
<ClInclude Include="Common\Utils.h">
<Filter>Common</Filter>
</ClInclude>
<ClInclude Include="Common\ValidatingConverters.h">
<Filter>Common</Filter>
</ClInclude>
<ClInclude Include="Common\Automation\INarratorAnnouncementHost.h">
<Filter>Common\Automation</Filter>
</ClInclude>
<ClInclude Include="Common\Automation\LiveRegionHost.h">
<Filter>Common\Automation</Filter>
</ClInclude>
<ClInclude Include="Common\Automation\NarratorAnnouncement.h">
<Filter>Common\Automation</Filter>
</ClInclude>
<ClInclude Include="Common\Automation\NarratorAnnouncementHostFactory.h">
<Filter>Common\Automation</Filter>
</ClInclude>
<ClInclude Include="Common\Automation\NarratorNotifier.h">
<Filter>Common\Automation</Filter>
</ClInclude>
<ClInclude Include="Common\Automation\NotificationHost.h">
<Filter>Common\Automation</Filter>
</ClInclude>
<ClInclude Include="DataLoaders\CurrencyDataLoader.h">
<Filter>DataLoaders</Filter>
</ClInclude>
<ClInclude Include="DataLoaders\CurrencyHttpClient.h">
<Filter>DataLoaders</Filter>
</ClInclude>
<ClInclude Include="DataLoaders\ICurrencyHttpClient.h">
<Filter>DataLoaders</Filter>
</ClInclude>
<ClInclude Include="DataLoaders\UnitConverterDataConstants.h">
<Filter>DataLoaders</Filter>
</ClInclude>
<ClInclude Include="DataLoaders\UnitConverterDataLoader.h">
<Filter>DataLoaders</Filter>
</ClInclude>
<ClInclude Include="Common\TraceActivity.h">
<Filter>Common</Filter>
</ClInclude>
<ClInclude Include="GraphingCalculator\EquationViewModel.h">
<Filter>GraphingCalculator</Filter>
</ClInclude>
<ClInclude Include="GraphingCalculator\GraphingCalculatorViewModel.h">
<Filter>GraphingCalculator</Filter>
</ClInclude>
<ClInclude Include="DataLoaders\DataLoaderMockConstants.h" />
</ItemGroup>
<ItemGroup>
<None Include="DataLoaders\DefaultFromToCurrency.json">
<Filter>DataLoaders</Filter>
</None>
<None Include="DataLoaders\DefaultFromToCurrency.json" />
<None Include="packages.config" />
</ItemGroup>
</Project>

View File

@@ -3,107 +3,104 @@
#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
{
m_source = source;
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);
if (observable)
{
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
{
throw ref new Platform::NotImplementedException();
}
virtual bool MoveCurrentToFirst() = Windows::UI::Xaml::Data::ICollectionView::MoveCurrentToFirst
{
throw ref new Platform::NotImplementedException();
}
virtual bool MoveCurrentToLast() = Windows::UI::Xaml::Data::ICollectionView::MoveCurrentToLast
{
throw ref new Platform::NotImplementedException();
}
virtual bool MoveCurrentToNext() = Windows::UI::Xaml::Data::ICollectionView::MoveCurrentToNext
{
throw ref new Platform::NotImplementedException();
}
virtual bool MoveCurrentToPrevious() = Windows::UI::Xaml::Data::ICollectionView::MoveCurrentToPrevious
{
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
{
return ref new Platform::Collections::Vector<Platform::Object^>();
}
}
property bool HasMoreItems
{
virtual bool get() = Windows::UI::Xaml::Data::ICollectionView::HasMoreItems::get
{
return false;
}
}
// Implemented methods
virtual bool MoveCurrentTo(Platform::Object^ item) = Windows::UI::Xaml::Data::ICollectionView::MoveCurrentTo
{
if (item)
{
unsigned int newCurrentPosition = 0;
bool result = m_source->IndexOf(item, &newCurrentPosition);
if (result)
Windows::UI::Xaml::Interop::IBindableObservableVector ^ observable =
dynamic_cast<Windows::UI::Xaml::Interop::IBindableObservableVector ^>(source);
if (observable)
{
m_currentPosition = newCurrentPosition;
m_currentChanged(this, nullptr);
return true;
observable->VectorChanged += ref new Windows::UI::Xaml::Interop::BindableVectorChangedEventHandler(
this, &AlwaysSelectedCollectionView::OnSourceBindableVectorChanged);
}
}
// The item is not in the collection
// We're going to schedule a call back later so we
// restore the selection to the way we wanted it to begin with
if (m_currentPosition >= 0 && m_currentPosition < static_cast<int>(m_source->Size))
private:
// ICollectionView
// Not implemented methods
virtual WF::IAsyncOperation<
Windows::UI::Xaml::Data::LoadMoreItemsResult> ^ LoadMoreItemsAsync(unsigned int) = Windows::UI::Xaml::Data::ICollectionView::LoadMoreItemsAsync
{
this->Dispatcher->RunAsync(Windows::UI::Core::CoreDispatcherPriority::Normal,
ref new Windows::UI::Core::DispatchedHandler(
[this]()
{
m_currentChanged(this, nullptr);
}));
throw ref new Platform::NotImplementedException();
}
return false;
}
virtual bool MoveCurrentToPosition(int index) = Windows::UI::Xaml::Data::ICollectionView::MoveCurrentToPosition
{
if (index < 0 || index >= static_cast<int>(m_source->Size))
virtual bool MoveCurrentToFirst() = Windows::UI::Xaml::Data::ICollectionView::MoveCurrentToFirst
{
throw ref new Platform::NotImplementedException();
}
virtual bool MoveCurrentToLast() = Windows::UI::Xaml::Data::ICollectionView::MoveCurrentToLast
{
throw ref new Platform::NotImplementedException();
}
virtual bool MoveCurrentToNext() = Windows::UI::Xaml::Data::ICollectionView::MoveCurrentToNext
{
throw ref new Platform::NotImplementedException();
}
virtual bool MoveCurrentToPrevious() = Windows::UI::Xaml::Data::ICollectionView::MoveCurrentToPrevious
{
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
{
return ref new Platform::Collections::Vector<Platform::Object ^>();
}
} property bool HasMoreItems
{
virtual bool get() = Windows::UI::Xaml::Data::ICollectionView::HasMoreItems::get
{
return false;
}
}
// Implemented methods
virtual bool MoveCurrentTo(Platform::Object ^ item) = Windows::UI::Xaml::Data::ICollectionView::MoveCurrentTo
{
if (item)
{
unsigned int newCurrentPosition = 0;
bool result = m_source->IndexOf(item, &newCurrentPosition);
if (result)
{
m_currentPosition = newCurrentPosition;
m_currentChanged(this, nullptr);
return true;
}
}
// The item is not in the collection
// We're going to schedule a call back later so we
// 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]() {
m_currentChanged(this, nullptr);
}));
}
return false;
}
m_currentPosition = index;
m_currentChanged(this, nullptr);
return true;
}
virtual bool MoveCurrentToPosition(int index) = Windows::UI::Xaml::Data::ICollectionView::MoveCurrentToPosition
{
if (index < 0 || index >= static_cast<int>(m_source->Size))
{
return false;
}
property Platform::Object^ CurrentItem
m_currentPosition = index;
m_currentChanged(this, nullptr);
return true;
}
property Platform::Object^ CurrentItem
{
virtual Platform::Object^ get() = Windows::UI::Xaml::Data::ICollectionView::CurrentItem::get
{
@@ -116,30 +113,30 @@ namespace CalculatorApp { namespace Common
}
property int CurrentPosition
{
virtual int get() = Windows::UI::Xaml::Data::ICollectionView::CurrentPosition::get
{
return m_currentPosition;
virtual int get() = Windows::UI::Xaml::Data::ICollectionView::CurrentPosition::get
{
return m_currentPosition;
}
}
}
property bool IsCurrentAfterLast
{
virtual bool get() = Windows::UI::Xaml::Data::ICollectionView::IsCurrentAfterLast::get
property bool IsCurrentAfterLast
{
return m_currentPosition >= static_cast<int>(m_source->Size);
virtual bool get() = Windows::UI::Xaml::Data::ICollectionView::IsCurrentAfterLast::get
{
return m_currentPosition >= static_cast<int>(m_source->Size);
}
}
}
property bool IsCurrentBeforeFirst
{
virtual bool get() = Windows::UI::Xaml::Data::ICollectionView::IsCurrentBeforeFirst::get
property bool IsCurrentBeforeFirst
{
return m_currentPosition < 0;
virtual bool get() = Windows::UI::Xaml::Data::ICollectionView::IsCurrentBeforeFirst::get
{
return m_currentPosition < 0;
}
}
}
event WF::EventHandler<Platform::Object^>^ CurrentChanged
event WF::EventHandler<Platform::Object^>^ CurrentChanged
{
virtual WF::EventRegistrationToken add(WF::EventHandler<Platform::Object^>^ handler) = Windows::UI::Xaml::Data::ICollectionView::CurrentChanged::add
{
@@ -165,63 +162,67 @@ namespace CalculatorApp { namespace Common
// IVector<Object^>
// Not implemented methods
virtual void Append(Platform::Object^ /*item*/) = Windows::Foundation::Collections::IVector<Platform::Object^>::Append
{
throw ref new Platform::NotImplementedException();
}
virtual void Clear() = Windows::Foundation::Collections::IVector<Platform::Object^>::Clear
{
throw ref new Platform::NotImplementedException();
}
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
{
throw ref new Platform::NotImplementedException();
}
virtual void InsertAt(unsigned int /*index*/, Platform::Object^ /*item*/) = Windows::Foundation::Collections::IVector<Platform::Object^>::InsertAt
{
throw ref new Platform::NotImplementedException();
}
virtual void RemoveAt(unsigned int /*index*/) = Windows::Foundation::Collections::IVector<Platform::Object^>::RemoveAt
{
throw ref new Platform::NotImplementedException();
}
virtual void RemoveAtEnd() = Windows::Foundation::Collections::IVector<Platform::Object^>::RemoveAtEnd
{
throw ref new Platform::NotImplementedException();
}
virtual void ReplaceAll(const Platform::Array<Platform::Object^>^ /*items*/) = Windows::Foundation::Collections::IVector<Platform::Object^>::ReplaceAll
{
throw ref new Platform::NotImplementedException();
}
virtual void SetAt(unsigned int /*index*/, Platform::Object^ /*item*/) = Windows::Foundation::Collections::IVector<Platform::Object^>::SetAt
{
throw ref new Platform::NotImplementedException();
}
// Implemented methods
virtual Platform::Object^ GetAt(unsigned int index) = Windows::Foundation::Collections::IVector<Platform::Object^>::GetAt
{
return m_source->GetAt(index);
}
virtual bool IndexOf(Platform::Object^ item, unsigned int* index) = Windows::Foundation::Collections::IVector<Platform::Object^>::IndexOf
{
return m_source->IndexOf(item, index);
}
property unsigned int Size
{
virtual unsigned int get() = Windows::Foundation::Collections::IVector<Platform::Object^>::Size::get
{
return m_source->Size;
throw ref new Platform::NotImplementedException();
}
virtual void Clear() = Windows::Foundation::Collections::IVector<Platform::Object ^>::Clear
{
throw ref new Platform::NotImplementedException();
}
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
{
throw ref new Platform::NotImplementedException();
}
virtual void InsertAt(unsigned int /*index*/, Platform::Object ^ /*item*/) = Windows::Foundation::Collections::IVector<Platform::Object ^>::InsertAt
{
throw ref new Platform::NotImplementedException();
}
virtual void RemoveAt(unsigned int /*index*/) = Windows::Foundation::Collections::IVector<Platform::Object ^>::RemoveAt
{
throw ref new Platform::NotImplementedException();
}
virtual void RemoveAtEnd() = Windows::Foundation::Collections::IVector<Platform::Object ^>::RemoveAtEnd
{
throw ref new Platform::NotImplementedException();
}
virtual void
ReplaceAll(const Platform::Array<Platform::Object ^> ^ /*items*/) = Windows::Foundation::Collections::IVector<Platform::Object ^>::ReplaceAll
{
throw ref new Platform::NotImplementedException();
}
virtual void SetAt(unsigned int /*index*/, Platform::Object ^ /*item*/) = Windows::Foundation::Collections::IVector<Platform::Object ^>::SetAt
{
throw ref new Platform::NotImplementedException();
}
}
// IObservableVector<Object^>
event Windows::Foundation::Collections::VectorChangedEventHandler<Platform::Object^>^ VectorChanged
// Implemented methods
virtual Platform::Object ^ GetAt(unsigned int index) = Windows::Foundation::Collections::IVector<Platform::Object ^>::GetAt
{
return m_source->GetAt(index);
}
virtual bool IndexOf(Platform::Object ^ item, unsigned int* index) = Windows::Foundation::Collections::IVector<Platform::Object ^>::IndexOf
{
return m_source->IndexOf(item, index);
}
property unsigned int Size
{
virtual unsigned int get() = Windows::Foundation::Collections::IVector<Platform::Object ^>::Size::get
{
return m_source->Size;
}
}
// IObservableVector<Object^>
event Windows::Foundation::Collections::VectorChangedEventHandler<Platform::Object^>^ VectorChanged
{
virtual WF::EventRegistrationToken add(Windows::Foundation::Collections::VectorChangedEventHandler<Platform::Object^>^ handler) = Windows::Foundation::Collections::IObservableVector<Platform::Object^>::VectorChanged::add
{
@@ -236,52 +237,57 @@ namespace CalculatorApp { namespace Common
// IIterable<Object^>
// Not implemented
virtual Windows::Foundation::Collections::IIterator<Platform::Object^>^ First() = Windows::Foundation::Collections::IIterable<Platform::Object^>::First
{
throw ref new Platform::NotImplementedException();
}
// Event handlers
void OnSourceBindableVectorChanged(Windows::UI::Xaml::Interop::IBindableObservableVector^ source, Platform::Object^ e)
{
Windows::Foundation::Collections::IVectorChangedEventArgs^ args = safe_cast<Windows::Foundation::Collections::IVectorChangedEventArgs^>(e);
m_vectorChanged(this, args);
}
Windows::UI::Xaml::Interop::IBindableVector^ m_source;
int m_currentPosition;
event WF::EventHandler<Platform::Object^>^ m_currentChanged;
event Windows::UI::Xaml::Data::CurrentChangingEventHandler^ m_currentChanging;
event Windows::Foundation::Collections::VectorChangedEventHandler<Platform::Object^>^ m_vectorChanged;
};
public ref class AlwaysSelectedCollectionViewConverter sealed: public Windows::UI::Xaml::Data::IValueConverter
{
public:
AlwaysSelectedCollectionViewConverter()
{ }
private:
virtual Platform::Object^ Convert(
Platform::Object^ value,
Windows::UI::Xaml::Interop::TypeName /*targetType*/,
Platform::Object^ /*parameter*/,
Platform::String^ /*language*/) = Windows::UI::Xaml::Data::IValueConverter::Convert
{
auto result = dynamic_cast<Windows::UI::Xaml::Interop::IBindableVector^>(value);
if (result)
{
return ref new AlwaysSelectedCollectionView(result);
throw ref new Platform::NotImplementedException();
}
return Windows::UI::Xaml::DependencyProperty::UnsetValue; // Can't convert
}
virtual Platform::Object^ ConvertBack(
Platform::Object^ /*value*/,
Windows::UI::Xaml::Interop::TypeName /*targetType*/,
Platform::Object^ /*parameter*/,
Platform::String^ /*language*/) = Windows::UI::Xaml::Data::IValueConverter::ConvertBack
// Event handlers
void OnSourceBindableVectorChanged(Windows::UI::Xaml::Interop::IBindableObservableVector ^ source, Platform::Object ^ e)
{
Windows::Foundation::Collections::IVectorChangedEventArgs ^ args = safe_cast<Windows::Foundation::Collections::IVectorChangedEventArgs ^>(e);
m_vectorChanged(this, args);
}
Windows::UI::Xaml::Interop::IBindableVector ^ m_source;
int m_currentPosition;
event WF::EventHandler<Platform::Object ^> ^ m_currentChanged;
event Windows::UI::Xaml::Data::CurrentChangingEventHandler ^ m_currentChanging;
event Windows::Foundation::Collections::VectorChangedEventHandler<Platform::Object ^> ^ m_vectorChanged;
};
public
ref class AlwaysSelectedCollectionViewConverter sealed : public Windows::UI::Xaml::Data::IValueConverter
{
return Windows::UI::Xaml::DependencyProperty::UnsetValue;
}
};
}}
public:
AlwaysSelectedCollectionViewConverter()
{
}
private:
virtual Platform::Object
^ Convert(
Platform::Object ^ value,
Windows::UI::Xaml::Interop::TypeName /*targetType*/,
Platform::Object ^ /*parameter*/,
Platform::String ^ /*language*/) = Windows::UI::Xaml::Data::IValueConverter::Convert
{
auto result = dynamic_cast<Windows::UI::Xaml::Interop::IBindableVector ^>(value);
if (result)
{
return ref new AlwaysSelectedCollectionView(result);
}
return Windows::UI::Xaml::DependencyProperty::UnsetValue; // Can't convert
}
virtual Platform::Object
^ ConvertBack(
Platform::Object ^ /*value*/,
Windows::UI::Xaml::Interop::TypeName /*targetType*/,
Platform::Object ^ /*parameter*/,
Platform::String ^ /*language*/) = Windows::UI::Xaml::Data::IValueConverter::ConvertBack
{
return Windows::UI::Xaml::DependencyProperty::UnsetValue;
}
};
}
}

View File

@@ -14,18 +14,18 @@ AppResourceProvider::AppResourceProvider()
m_cEngineStringResLoader = ResourceLoader::GetForViewIndependentUse(L"CEngineStrings");
}
AppResourceProvider & AppResourceProvider::GetInstance()
AppResourceProvider& AppResourceProvider::GetInstance()
{
static AppResourceProvider s_instance;
return s_instance;
}
String^ AppResourceProvider::GetResourceString(_In_ String^ key)
String ^ AppResourceProvider::GetResourceString(_In_ String ^ key)
{
return m_stringResLoader->GetString(key);
}
String^ AppResourceProvider::GetCEngineString(_In_ String^ key)
String ^ AppResourceProvider::GetCEngineString(_In_ String ^ key)
{
return m_cEngineStringResLoader->GetString(key);
}

View File

@@ -8,13 +8,13 @@ namespace CalculatorApp
class AppResourceProvider
{
public:
static AppResourceProvider & GetInstance();
Platform::String^ GetResourceString(_In_ Platform::String^ key);
Platform::String^ GetCEngineString(_In_ Platform::String^ key);
static AppResourceProvider& GetInstance();
Platform::String ^ GetResourceString(_In_ Platform::String ^ key);
Platform::String ^ GetCEngineString(_In_ Platform::String ^ key);
private:
AppResourceProvider();
Windows::ApplicationModel::Resources::ResourceLoader^ m_stringResLoader;
Windows::ApplicationModel::Resources::ResourceLoader^ m_cEngineStringResLoader;
Windows::ApplicationModel::Resources::ResourceLoader ^ m_stringResLoader;
Windows::ApplicationModel::Resources::ResourceLoader ^ m_cEngineStringResLoader;
};
}

View File

@@ -11,16 +11,17 @@
namespace CalculatorApp::Common::Automation
{
public interface class INarratorAnnouncementHost
public
interface class INarratorAnnouncementHost
{
public:
// Is the host available on this OS.
bool IsHostAvailable();
// Make a new instance of a concrete host.
INarratorAnnouncementHost^ MakeHost();
INarratorAnnouncementHost ^ MakeHost();
// Make an announcement using the concrete host's preferred method.
void Announce(NarratorAnnouncement^ announcement);
void Announce(NarratorAnnouncement ^ announcement);
};
}

View File

@@ -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()
{
@@ -19,12 +20,12 @@ bool LiveRegionHost::IsHostAvailable()
return true;
}
INarratorAnnouncementHost^ LiveRegionHost::MakeHost()
INarratorAnnouncementHost ^ LiveRegionHost::MakeHost()
{
return ref new LiveRegionHost();
}
void LiveRegionHost::Announce(NarratorAnnouncement^ announcement)
void LiveRegionHost::Announce(NarratorAnnouncement ^ announcement)
{
if (m_host == nullptr)
{
@@ -33,7 +34,7 @@ void LiveRegionHost::Announce(NarratorAnnouncement^ announcement)
}
AutomationProperties::SetName(m_host, announcement->Announcement);
AutomationPeer^ peer = FrameworkElementAutomationPeer::FromElement(m_host);
AutomationPeer ^ peer = FrameworkElementAutomationPeer::FromElement(m_host);
if (peer != nullptr)
{
peer->RaiseAutomationEvent(AutomationEvents::LiveRegionChanged);

View File

@@ -16,17 +16,18 @@ 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();
virtual bool IsHostAvailable();
virtual INarratorAnnouncementHost^ MakeHost();
virtual INarratorAnnouncementHost ^ MakeHost();
virtual void Announce(NarratorAnnouncement^ announcement);
virtual void Announce(NarratorAnnouncement ^ announcement);
private:
Windows::UI::Xaml::UIElement^ m_host;
Windows::UI::Xaml::UIElement ^ m_host;
};
}

View File

@@ -26,23 +26,23 @@ namespace CalculatorApp::Common::Automation
}
NarratorAnnouncement::NarratorAnnouncement(
String^ announcement,
String^ activityId,
String ^ announcement,
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()
String ^ NarratorAnnouncement::Announcement::get()
{
return m_announcement;
}
String^ NarratorAnnouncement::ActivityId::get()
String ^ NarratorAnnouncement::ActivityId::get()
{
return m_activityId;
}
@@ -57,68 +57,48 @@ AutomationNotificationProcessing NarratorAnnouncement::Processing::get()
return m_processing;
}
bool NarratorAnnouncement::IsValid(NarratorAnnouncement^ announcement)
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)
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)
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)
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)
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)
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)
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)
NarratorAnnouncement ^ CalculatorAnnouncement::GetCategoryNameChangedAnnouncement(String ^ announcement)
{
return ref new NarratorAnnouncement(
announcement,
@@ -127,7 +107,7 @@ NarratorAnnouncement^ CalculatorAnnouncement::GetCategoryNameChangedAnnouncement
AutomationNotificationProcessing::ImportantMostRecent);
}
NarratorAnnouncement^ CalculatorAnnouncement::GetUpdateCurrencyRatesAnnouncement(String^ announcement)
NarratorAnnouncement ^ CalculatorAnnouncement::GetUpdateCurrencyRatesAnnouncement(String ^ announcement)
{
return ref new NarratorAnnouncement(
announcement,
@@ -136,16 +116,13 @@ NarratorAnnouncement^ CalculatorAnnouncement::GetUpdateCurrencyRatesAnnouncement
AutomationNotificationProcessing::ImportantMostRecent);
}
NarratorAnnouncement^ CalculatorAnnouncement::GetDisplayCopiedAnnouncement(String^ announcement)
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)
NarratorAnnouncement ^ CalculatorAnnouncement::GetOpenParenthesisCountChangedAnnouncement(String ^ announcement)
{
return ref new NarratorAnnouncement(
announcement,
@@ -154,7 +131,7 @@ NarratorAnnouncement^ CalculatorAnnouncement::GetOpenParenthesisCountChangedAnno
AutomationNotificationProcessing::ImportantMostRecent);
}
NarratorAnnouncement^ CalculatorAnnouncement::GetNoRightParenthesisAddedAnnouncement(String^ announcement)
NarratorAnnouncement ^ CalculatorAnnouncement::GetNoRightParenthesisAddedAnnouncement(String ^ announcement)
{
return ref new NarratorAnnouncement(
announcement,

View File

@@ -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,20 +31,17 @@ 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
property AutomationNotificationKind Kind
{
AutomationNotificationKind get();
}
@@ -52,7 +51,7 @@ namespace CalculatorApp::Common::Automation
AutomationNotificationProcessing get();
}
static bool IsValid(NarratorAnnouncement^ announcement);
static bool IsValid(NarratorAnnouncement ^ announcement);
private:
// Make CalculatorAnnouncement a friend class so it is the only
@@ -60,13 +59,13 @@ namespace CalculatorApp::Common::Automation
friend class CalculatorAnnouncement;
NarratorAnnouncement(
Platform::String^ announcement,
Platform::String^ activityId,
Platform::String ^ announcement,
Platform::String ^ activityId,
AutomationNotificationKind kind,
AutomationNotificationProcessing processing);
Platform::String^ m_announcement;
Platform::String^ m_activityId;
Platform::String ^ m_announcement;
Platform::String ^ m_activityId;
AutomationNotificationKind m_kind;
AutomationNotificationProcessing m_processing;
};
@@ -76,22 +75,22 @@ namespace CalculatorApp::Common::Automation
class CalculatorAnnouncement
{
public:
static NarratorAnnouncement^ GetDisplayUpdatedAnnouncement(Platform::String^ announcement);
static NarratorAnnouncement^ GetMaxDigitsReachedAnnouncement(Platform::String^ announcement);
static NarratorAnnouncement ^ GetDisplayUpdatedAnnouncement(Platform::String ^ announcement);
static NarratorAnnouncement ^ GetMaxDigitsReachedAnnouncement(Platform::String ^ announcement);
static NarratorAnnouncement^ GetMemoryClearedAnnouncement(Platform::String^ announcement);
static NarratorAnnouncement^ GetMemoryItemChangedAnnouncement(Platform::String^ announcement);
static NarratorAnnouncement^ GetMemoryItemAddedAnnouncement(Platform::String^ announcement);
static NarratorAnnouncement ^ GetMemoryClearedAnnouncement(Platform::String ^ announcement);
static NarratorAnnouncement ^ GetMemoryItemChangedAnnouncement(Platform::String ^ announcement);
static NarratorAnnouncement ^ GetMemoryItemAddedAnnouncement(Platform::String ^ announcement);
static NarratorAnnouncement^ GetHistoryClearedAnnouncement(Platform::String^ announcement);
static NarratorAnnouncement ^ GetHistoryClearedAnnouncement(Platform::String ^ announcement);
static NarratorAnnouncement^ GetCategoryNameChangedAnnouncement(Platform::String^ announcement);
static NarratorAnnouncement ^ GetCategoryNameChangedAnnouncement(Platform::String ^ announcement);
static NarratorAnnouncement^ GetUpdateCurrencyRatesAnnouncement(Platform::String^ announcement);
static NarratorAnnouncement ^ GetUpdateCurrencyRatesAnnouncement(Platform::String ^ announcement);
static NarratorAnnouncement^ GetDisplayCopiedAnnouncement(Platform::String^ announcement);
static NarratorAnnouncement ^ GetDisplayCopiedAnnouncement(Platform::String ^ announcement);
static NarratorAnnouncement^ GetOpenParenthesisCountChangedAnnouncement(Platform::String^ announcement);
static NarratorAnnouncement^ GetNoRightParenthesisAddedAnnouncement(Platform::String ^ announcement);
static NarratorAnnouncement ^ GetOpenParenthesisCountChangedAnnouncement(Platform::String ^ announcement);
static NarratorAnnouncement ^ GetNoRightParenthesisAddedAnnouncement(Platform::String ^ announcement);
};
}

View File

@@ -9,8 +9,8 @@
using namespace CalculatorApp::Common::Automation;
using namespace std;
INarratorAnnouncementHost^ NarratorAnnouncementHostFactory::s_hostProducer;
vector<INarratorAnnouncementHost^> NarratorAnnouncementHostFactory::s_hosts;
INarratorAnnouncementHost ^ NarratorAnnouncementHostFactory::s_hostProducer;
vector<INarratorAnnouncementHost ^> NarratorAnnouncementHostFactory::s_hosts;
// This static variable is used only to call the initialization function, to initialize the other static variables.
int NarratorAnnouncementHostFactory::s_init = NarratorAnnouncementHostFactory::Initialize();
@@ -32,15 +32,12 @@ 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()
INarratorAnnouncementHost ^ NarratorAnnouncementHostFactory::GetHostProducer()
{
for (INarratorAnnouncementHost^ host : NarratorAnnouncementHostFactory::s_hosts)
for (INarratorAnnouncementHost ^ host : NarratorAnnouncementHostFactory::s_hosts)
{
if (host->IsHostAvailable())
{
@@ -52,7 +49,7 @@ INarratorAnnouncementHost^ NarratorAnnouncementHostFactory::GetHostProducer()
return nullptr;
}
INarratorAnnouncementHost^ NarratorAnnouncementHostFactory::MakeHost()
INarratorAnnouncementHost ^ NarratorAnnouncementHostFactory::MakeHost()
{
if (NarratorAnnouncementHostFactory::s_hostProducer == nullptr)
{

View File

@@ -14,18 +14,20 @@ namespace CalculatorApp::Common::Automation
class NarratorAnnouncementHostFactory
{
public:
static INarratorAnnouncementHost^ MakeHost();
static INarratorAnnouncementHost ^ MakeHost();
private:
NarratorAnnouncementHostFactory() {}
NarratorAnnouncementHostFactory()
{
}
static int Initialize();
static void RegisterHosts();
static INarratorAnnouncementHost^ GetHostProducer();
static INarratorAnnouncementHost ^ GetHostProducer();
private:
static int s_init;
static INarratorAnnouncementHost^ s_hostProducer;
static std::vector<INarratorAnnouncementHost^> s_hosts;
static INarratorAnnouncementHost ^ s_hostProducer;
static std::vector<INarratorAnnouncementHost ^> s_hosts;
};
}

View File

@@ -1,4 +1,4 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
// Implementation of the NarratorNotifier class.
@@ -13,17 +13,16 @@ using namespace Windows::UI::Xaml;
using namespace Windows::UI::Xaml::Automation;
using namespace Windows::UI::Xaml::Automation::Peers;
DependencyProperty^ NarratorNotifier::s_announcementProperty;
DependencyProperty ^ NarratorNotifier::s_announcementProperty;
NarratorNotifier::NarratorNotifier()
{
m_announcementHost = NarratorAnnouncementHostFactory::MakeHost();
}
void NarratorNotifier::Announce(NarratorAnnouncement^ announcement)
void NarratorNotifier::Announce(NarratorAnnouncement ^ announcement)
{
if (NarratorAnnouncement::IsValid(announcement)
&& m_announcementHost != nullptr)
if (NarratorAnnouncement::IsValid(announcement) && m_announcementHost != nullptr)
{
m_announcementHost->Announce(announcement);
}
@@ -32,19 +31,19 @@ void NarratorNotifier::Announce(NarratorAnnouncement^ announcement)
void NarratorNotifier::RegisterDependencyProperties()
{
s_announcementProperty = DependencyProperty::Register(
L"Announcement", // The name of the dependency property.
L"Announcement", // The name of the dependency property.
NarratorAnnouncement::typeid, // The type of the dependency property.
NarratorNotifier::typeid, // The owner of the dependency property.
NarratorNotifier::typeid, // The owner of the dependency property.
ref new PropertyMetadata(
nullptr, // Default value of the dependency property.
ref new PropertyChangedCallback(OnAnnouncementChanged)));
}
void NarratorNotifier::OnAnnouncementChanged(_In_ DependencyObject^ dependencyObject, _In_ DependencyPropertyChangedEventArgs^ e)
void NarratorNotifier::OnAnnouncementChanged(_In_ DependencyObject ^ dependencyObject, _In_ DependencyPropertyChangedEventArgs ^ e)
{
auto instance = safe_cast<NarratorNotifier^>(dependencyObject);
auto instance = safe_cast<NarratorNotifier ^>(dependencyObject);
if (instance != nullptr)
{
instance->Announce(safe_cast<NarratorAnnouncement^>(e->NewValue));
instance->Announce(safe_cast<NarratorAnnouncement ^>(e->NewValue));
}
}

View File

@@ -8,12 +8,13 @@
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();
void Announce(NarratorAnnouncement^ announcement);
void Announce(NarratorAnnouncement ^ announcement);
property NarratorAnnouncement^ Announcement
{
@@ -26,32 +27,26 @@ 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)
static void SetAnnouncement(Windows::UI::Xaml::DependencyObject ^ element, NarratorAnnouncement ^ value)
{
element->SetValue(s_announcementProperty, value);
}
private:
static void OnAnnouncementChanged(
_In_ Windows::UI::Xaml::DependencyObject^ dependencyObject,
_In_ Windows::UI::Xaml::DependencyPropertyChangedEventArgs^ eventArgs);
_In_ Windows::UI::Xaml::DependencyObject ^ dependencyObject,
_In_ Windows::UI::Xaml::DependencyPropertyChangedEventArgs ^ eventArgs);
static Windows::UI::Xaml::DependencyProperty^ s_announcementProperty;
static Windows::UI::Xaml::DependencyProperty ^ s_announcementProperty;
private:
INarratorAnnouncementHost^ m_announcementHost;
INarratorAnnouncementHost ^ m_announcementHost;
};
}

View File

@@ -10,23 +10,22 @@ 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()
INarratorAnnouncementHost ^ NotificationHost::MakeHost()
{
return ref new NotificationHost();
}
void NotificationHost::Announce(NarratorAnnouncement^ announcement)
void NotificationHost::Announce(NarratorAnnouncement ^ announcement)
{
if (m_host == nullptr)
{
@@ -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)
{

View File

@@ -10,25 +10,25 @@
namespace CalculatorApp::Common::Automation
{
public ref class NotificationHost sealed : public INarratorAnnouncementHost
public
ref class NotificationHost sealed : public INarratorAnnouncementHost
{
public:
NotificationHost();
virtual bool IsHostAvailable();
virtual INarratorAnnouncementHost^ MakeHost();
virtual INarratorAnnouncementHost ^ MakeHost();
virtual void Announce(NarratorAnnouncement^ announcement);
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;
Windows::UI::Xaml::UIElement ^ m_host;
};
}

View File

@@ -13,22 +13,22 @@ using namespace Windows::UI::Xaml::Data;
/// Notifies listeners that a property value has changed.
/// </summary>
/// <param name="propertyName">Name of the property used to notify listeners.</param>
void BindableBase::OnPropertyChanged(String^ propertyName)
void BindableBase::OnPropertyChanged(String ^ propertyName)
{
PropertyChanged(this, ref new PropertyChangedEventArgs(propertyName));
}
Windows::UI::Xaml::Data::ICustomProperty^ BindableBase::GetCustomProperty(Platform::String^ name)
Windows::UI::Xaml::Data::ICustomProperty ^ BindableBase::GetCustomProperty(Platform::String ^ name)
{
return nullptr;
}
Windows::UI::Xaml::Data::ICustomProperty^ BindableBase::GetIndexedProperty(Platform::String^ name, Windows::UI::Xaml::Interop::TypeName type)
Windows::UI::Xaml::Data::ICustomProperty ^ BindableBase::GetIndexedProperty(Platform::String ^ name, Windows::UI::Xaml::Interop::TypeName type)
{
return nullptr;
}
Platform::String^ BindableBase::GetStringRepresentation()
Platform::String ^ BindableBase::GetStringRepresentation()
{
return this->ToString();
}

View File

@@ -10,26 +10,29 @@ 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;
virtual event Windows::UI::Xaml::Data::PropertyChangedEventHandler ^ PropertyChanged;
public:
// ICustomPropertyProvider
virtual Windows::UI::Xaml::Data::ICustomProperty^ GetCustomProperty(Platform::String^ name);
virtual Windows::UI::Xaml::Data::ICustomProperty^ GetIndexedProperty(Platform::String^ name, Windows::UI::Xaml::Interop::TypeName type);
virtual Platform::String^ GetStringRepresentation();
virtual Windows::UI::Xaml::Data::ICustomProperty ^ GetCustomProperty(Platform::String ^ name);
virtual Windows::UI::Xaml::Data::ICustomProperty ^ GetIndexedProperty(Platform::String ^ name, Windows::UI::Xaml::Interop::TypeName type);
virtual Platform::String ^ GetStringRepresentation();
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);
virtual void OnPropertyChanged(Platform::String ^ propertyName);
};
}
}

View File

@@ -8,9 +8,9 @@ using namespace CalculatorApp;
using namespace CalculatorApp::Common;
using namespace Platform;
NumbersAndOperatorsEnum CalculatorButtonPressedEventArgs::GetOperationFromCommandParameter(_In_ Object^ commandParameter)
NumbersAndOperatorsEnum CalculatorButtonPressedEventArgs::GetOperationFromCommandParameter(_In_ Object ^ commandParameter)
{
auto eventArgs = dynamic_cast<CalculatorButtonPressedEventArgs^>(commandParameter);
auto eventArgs = dynamic_cast<CalculatorButtonPressedEventArgs ^>(commandParameter);
if (eventArgs != nullptr)
{
return eventArgs->Operation;
@@ -21,9 +21,9 @@ NumbersAndOperatorsEnum CalculatorButtonPressedEventArgs::GetOperationFromComman
}
}
String^ CalculatorButtonPressedEventArgs::GetAuditoryFeedbackFromCommandParameter(_In_ Object^ commandParameter)
String ^ CalculatorButtonPressedEventArgs::GetAuditoryFeedbackFromCommandParameter(_In_ Object ^ commandParameter)
{
auto eventArgs = dynamic_cast<CalculatorButtonPressedEventArgs^>(commandParameter);
auto eventArgs = dynamic_cast<CalculatorButtonPressedEventArgs ^>(commandParameter);
if (eventArgs != nullptr)
{
return eventArgs->AuditoryFeedback;
@@ -33,4 +33,3 @@ String^ CalculatorButtonPressedEventArgs::GetAuditoryFeedbackFromCommandParamete
return nullptr;
}
}

View File

@@ -10,18 +10,21 @@ namespace CalculatorApp
{
namespace Common
{
public ref class CalculatorButtonPressedEventArgs sealed
public
ref class CalculatorButtonPressedEventArgs sealed
{
public:
PROPERTY_R(Platform::String^, AuditoryFeedback);
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);
static CalculatorApp::NumbersAndOperatorsEnum GetOperationFromCommandParameter(_In_ Platform::Object ^ commandParameter);
static Platform::String ^ GetAuditoryFeedbackFromCommandParameter(_In_ Platform::Object ^ commandParameter);
};
}
}

View File

@@ -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,
@@ -168,50 +169,51 @@ 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,
Percent = (int) CM::Command::CommandPERCENT,
Negate = (int) CM::Command::CommandSIGN,
Degrees = (int) CM::Command::CommandDegrees,
Pi = (int) CM::Command::CommandPI,
Sin = (int) CM::Command::CommandSIN,
Cos = (int) CM::Command::CommandCOS,
Tan = (int) CM::Command::CommandTAN,
Factorial = (int) CM::Command::CommandFAC,
XPower2 = (int) CM::Command::CommandSQR,
Mod = (int) CM::Command::CommandMOD,
FToE = (int) CM::Command::CommandFE,
LogBaseE = (int) CM::Command::CommandLN,
InvSin = (int) CM::Command::CommandASIN,
InvCos = (int) CM::Command::CommandACOS,
InvTan = (int) CM::Command::CommandATAN,
LogBase10 = (int) CM::Command::CommandLOG,
XPowerY = (int) CM::Command::CommandPWR,
YRootX = (int) CM::Command::CommandROOT,
TenPowerX = (int) CM::Command::CommandPOW10,
EPowerX = (int) CM::Command::CommandPOWE,
Exp = (int) CM::Command::CommandEXP,
DecButton = (int) CM::Command::CommandDec,
OctButton = (int) CM::Command::CommandOct,
HexButton = (int) CM::Command::CommandHex,
BinButton = (int) CM::Command::CommandBin,
And = (int) CM::Command::CommandAnd,
Ror = (int) CM::Command::CommandROR,
Rol = (int) CM::Command::CommandROL,
Or = (int) CM::Command::CommandOR,
Lsh = (int) CM::Command::CommandLSHF,
Rsh = (int) CM::Command::CommandRSHF,
Xor = (int) CM::Command::CommandXor,
Not = (int) CM::Command::CommandNot,
Sinh = (int) CM::Command::CommandSINH,
Cosh = (int) CM::Command::CommandCOSH,
Tanh = (int) CM::Command::CommandTANH,
InvSinh = (int) CM::Command::CommandASINH,
InvCosh = (int) CM::Command::CommandACOSH,
InvTanh = (int) CM::Command::CommandATANH,
Cube = (int) CM::Command::CommandCUB,
DMS = (int) CM::Command::CommandDMS,
Invert = (int)CM::Command::CommandREC,
Sqrt = (int)CM::Command::CommandSQRT,
Percent = (int)CM::Command::CommandPERCENT,
Negate = (int)CM::Command::CommandSIGN,
Degrees = (int)CM::Command::CommandDegrees,
Pi = (int)CM::Command::CommandPI,
Sin = (int)CM::Command::CommandSIN,
Cos = (int)CM::Command::CommandCOS,
Tan = (int)CM::Command::CommandTAN,
Factorial = (int)CM::Command::CommandFAC,
XPower2 = (int)CM::Command::CommandSQR,
Mod = (int)CM::Command::CommandMOD,
FToE = (int)CM::Command::CommandFE,
LogBaseE = (int)CM::Command::CommandLN,
InvSin = (int)CM::Command::CommandASIN,
InvCos = (int)CM::Command::CommandACOS,
InvTan = (int)CM::Command::CommandATAN,
LogBase10 = (int)CM::Command::CommandLOG,
XPowerY = (int)CM::Command::CommandPWR,
YRootX = (int)CM::Command::CommandROOT,
TenPowerX = (int)CM::Command::CommandPOW10,
EPowerX = (int)CM::Command::CommandPOWE,
Exp = (int)CM::Command::CommandEXP,
DecButton = (int)CM::Command::CommandDec,
OctButton = (int)CM::Command::CommandOct,
HexButton = (int)CM::Command::CommandHex,
BinButton = (int)CM::Command::CommandBin,
And = (int)CM::Command::CommandAnd,
Ror = (int)CM::Command::CommandROR,
Rol = (int)CM::Command::CommandROL,
Or = (int)CM::Command::CommandOR,
Lsh = (int)CM::Command::CommandLSHF,
Rsh = (int)CM::Command::CommandRSHF,
Xor = (int)CM::Command::CommandXor,
Not = (int)CM::Command::CommandNot,
Sinh = (int)CM::Command::CommandSINH,
Cosh = (int)CM::Command::CommandCOSH,
Tanh = (int)CM::Command::CommandTANH,
InvSinh = (int)CM::Command::CommandASINH,
InvCosh = (int)CM::Command::CommandACOSH,
InvTanh = (int)CM::Command::CommandATANH,
Cube = (int)CM::Command::CommandCUB,
DMS = (int)CM::Command::CommandDMS,
};
}

View File

@@ -36,7 +36,7 @@ void CalculatorDisplay::SetPrimaryDisplay(_In_ const wstring& displayStringValue
}
}
void CalculatorDisplay::SetParenDisplayText(_In_ const std::wstring& parenthesisCount)
void CalculatorDisplay::SetParenthesisNumber(_In_ unsigned int parenthesisCount)
{
if (m_callbackReference != nullptr)
{
@@ -69,11 +69,13 @@ 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)
{
if(auto calcVM = m_callbackReference.Resolve<ViewModel::StandardCalculatorViewModel>())
if (auto calcVM = m_callbackReference.Resolve<ViewModel::StandardCalculatorViewModel>())
{
calcVM->SetExpressionDisplay(tokens, commands);
}

View File

@@ -8,7 +8,7 @@
namespace CalculatorApp
{
// Callback interface to be implemented by the CalculatorManager
class CalculatorDisplay: public ICalcDisplay
class CalculatorDisplay : public ICalcDisplay
{
public:
CalculatorDisplay();
@@ -18,10 +18,12 @@ 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 SetParenDisplayText(_In_ const std::wstring& parenthesisCount) override;
void SetParenthesisNumber(_In_ unsigned int parenthesisCount) override;
void OnNoRightParenAdded() override;
void MaxDigitsReached() override;
void BinaryOperatorReceived() override;

View File

@@ -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]()
{
if (!token.is_canceled())
{
m_storedFunction();
}
}, task_continuation_context::use_current());
delayTask.then(
[this, token]() {
if (!token.is_canceled())
{
m_storedFunction();
}
},
task_continuation_context::use_current());
}
ConversionResultTaskHelper::~ConversionResultTaskHelper()

View File

@@ -15,14 +15,12 @@ using namespace Windows::Foundation;
using namespace Windows::System;
using namespace Windows::ApplicationModel::DataTransfer;
unsigned long long maxOperandNumber;
String ^ CopyPasteManager::supportedFormats[] = { StandardDataFormats::Text };
String^ CopyPasteManager::supportedFormats[] =
{
StandardDataFormats::Text
};
static constexpr wstring_view c_validCharacterSet{ L"0123456789()+-*/.abcdefABCDEF" };
constexpr wstring_view c_validCharacterSet{ L"0123456789()+-*/.abcdefABCDEF" };
// The below values can not be "constexpr"-ed,
// as both wstring_view and wchar[] can not be concatenated
// [\s\x85] means white-space characters
static const wstring c_wspc = L"[\\s\\x85]*";
static const wstring c_wspcLParens = c_wspc + L"[(]*" + c_wspc;
@@ -39,43 +37,27 @@ 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)
},
// 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)
},
// Octal numbers like 06, 010, 0t77, 0o77, 077ull etc
{
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)
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) },
// Octal numbers like 06, 010, 0t77, 0o77, 077ull etc
{ 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) };
void CopyPasteManager::CopyToClipboard(String^ stringToCopy)
void CopyPasteManager::CopyToClipboard(String ^ stringToCopy)
{
// Copy the string to the clipboard
auto dataPackage = ref new DataPackage();
@@ -83,7 +65,7 @@ void CopyPasteManager::CopyToClipboard(String^ stringToCopy)
Clipboard::SetContent(dataPackage);
}
task<String^> CopyPasteManager::GetStringToPaste(ViewMode mode, CategoryGroupType modeType, int programmerNumberBase, int bitLengthType)
task<String ^> CopyPasteManager::GetStringToPaste(ViewMode mode, CategoryGroupType modeType, int programmerNumberBase, int bitLengthType)
{
// Retrieve the text in the clipboard
auto dataPackageView = Clipboard::GetContent();
@@ -94,38 +76,35 @@ 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)
{
return ValidatePasteExpression(pastedText, mode, modeType, programmerNumberBase, bitLengthType);
}
, task_continuation_context::use_arbitrary());
.then(
[mode, modeType, programmerNumberBase, bitLengthType](String ^ pastedText) {
return ValidatePasteExpression(pastedText, mode, modeType, programmerNumberBase, bitLengthType);
},
task_continuation_context::use_arbitrary());
}
int CopyPasteManager::ClipboardTextFormat()
{
int result = -1;
auto dataPackageView = Clipboard::GetContent();
const auto dataPackageView = Clipboard::GetContent();
for (int i = 0; i < RTL_NUMBER_OF(supportedFormats); i++)
{
if (dataPackageView->Contains(supportedFormats[i]))
{
result = i;
break;
return i;
}
}
return result;
return -1;
}
String^ CopyPasteManager::ValidatePasteExpression(String^ pastedText, ViewMode mode, int programmerNumberBase, int bitLengthType)
String ^ CopyPasteManager::ValidatePasteExpression(String ^ pastedText, ViewMode mode, int programmerNumberBase, int bitLengthType)
{
return CopyPasteManager::ValidatePasteExpression(pastedText, mode, NavCategory::GetGroupType(mode), programmerNumberBase, bitLengthType);
}
// return "NoOp" if pastedText is invalid else return pastedText
String^ CopyPasteManager::ValidatePasteExpression(String^ pastedText, ViewMode mode, CategoryGroupType modeType, int programmerNumberBase, int bitLengthType)
String ^ CopyPasteManager::ValidatePasteExpression(String ^ pastedText, ViewMode mode, CategoryGroupType modeType, int programmerNumberBase, int bitLengthType)
{
if (pastedText->Length() > MaxPasteableLength)
{
@@ -137,7 +116,7 @@ String^ CopyPasteManager::ValidatePasteExpression(String^ pastedText, ViewMode m
wstring pasteExpression = pastedText->Data();
// Get english translated expression
String^ englishString = LocalizationSettings::GetInstance().GetEnglishValueFromLocalizedDigits(pasteExpression);
String ^ englishString = LocalizationSettings::GetInstance().GetEnglishValueFromLocalizedDigits(pasteExpression);
// Removing the spaces, comma separator from the pasteExpression to allow pasting of expressions like 1 + 2+1,333
pasteExpression = RemoveUnwantedCharsFromWstring(englishString->Data());
@@ -225,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;
@@ -268,13 +248,8 @@ bool CopyPasteManager::ExpressionRegExMatch(vector<wstring> operands, ViewMode m
return false;
}
bool expMatched = true;
vector<wregex> patterns{};
pair<size_t, uint64_t> operandLimits = GetMaxOperandLengthAndValue(mode, modeType, programmerNumberBase, bitLengthType);
size_t maxOperandLength = operandLimits.first;
uint64_t maxOperandValue = operandLimits.second;
if (mode == ViewMode::Standard)
{
patterns.assign(standardModePatterns.begin(), standardModePatterns.end());
@@ -292,11 +267,14 @@ bool CopyPasteManager::ExpressionRegExMatch(vector<wstring> operands, ViewMode m
patterns.assign(unitConverterPatterns.begin(), unitConverterPatterns.end());
}
for (const wstring& operand : operands)
const auto [maxOperandLength, maxOperandValue] = GetMaxOperandLengthAndValue(mode, modeType, programmerNumberBase, bitLengthType);
bool expMatched = true;
for (const auto& operand : operands)
{
// Each operand only needs to match one of the available patterns.
bool operandMatched = false;
for (const wregex& pattern : patterns)
for (const auto& pattern : patterns)
{
operandMatched = operandMatched || regex_match(operand, pattern);
}
@@ -305,7 +283,7 @@ bool CopyPasteManager::ExpressionRegExMatch(vector<wstring> operands, ViewMode m
{
// Remove characters that are valid in the expression but we do not want to include in length calculations
// or which will break conversion from string-to-ULL.
wstring operandValue = SanitizeOperand(operand);
const wstring operandValue = SanitizeOperand(operand);
// If an operand exceeds the maximum length allowed, break and return.
if (OperandLength(operandValue, mode, modeType, programmerNumberBase) > maxOperandLength)
@@ -341,16 +319,16 @@ bool CopyPasteManager::ExpressionRegExMatch(vector<wstring> operands, ViewMode m
pair<size_t, uint64_t> CopyPasteManager::GetMaxOperandLengthAndValue(ViewMode mode, CategoryGroupType modeType, int programmerNumberBase, int bitLengthType)
{
size_t maxLength = 0;
uint64_t maxValue = 0;
constexpr size_t defaultMaxOperandLength = 0;
constexpr uint64_t defaultMaxValue = 0;
if (mode == ViewMode::Standard)
{
maxLength = MaxStandardOperandLength;
return make_pair(MaxStandardOperandLength, defaultMaxValue);
}
else if (mode == ViewMode::Scientific)
{
maxLength = MaxScientificOperandLength;
return make_pair(MaxScientificOperandLength, defaultMaxValue);
}
else if (mode == ViewMode::Programmer)
{
@@ -390,15 +368,17 @@ pair<size_t, uint64_t> CopyPasteManager::GetMaxOperandLengthAndValue(ViewMode mo
unsigned int signBit = (programmerNumberBase == DecBase) ? 1 : 0;
maxLength = (size_t)ceil((bitLength - signBit) / bitsPerDigit);
maxValue = UINT64_MAX >> (MaxProgrammerBitLength - (bitLength - signBit));
const auto maxLength = static_cast<size_t>(ceil((bitLength - signBit) / bitsPerDigit));
const uint64_t maxValue = UINT64_MAX >> (MaxProgrammerBitLength - (bitLength - signBit));
return make_pair(maxLength, maxValue);
}
else if (modeType == CategoryGroupType::Converter)
{
maxLength = MaxConverterInputLength;
return make_pair(MaxConverterInputLength, defaultMaxValue);
}
return make_pair(maxLength, maxValue);
return make_pair(defaultMaxOperandLength, defaultMaxValue);
}
wstring CopyPasteManager::SanitizeOperand(const wstring& operand)
@@ -417,8 +397,7 @@ bool CopyPasteManager::TryOperandToULL(const wstring& operand, int numberBase, u
return false;
}
// Default to base10
int intBase = 10;
int intBase;
switch (numberBase)
{
case HexBase:
@@ -430,6 +409,7 @@ bool CopyPasteManager::TryOperandToULL(const wstring& operand, int numberBase, u
case BinBase:
intBase = 2;
break;
default:
case DecBase:
intBase = 10;
break;
@@ -441,11 +421,11 @@ bool CopyPasteManager::TryOperandToULL(const wstring& operand, int numberBase, u
result = stoull(operand, &size, intBase);
return true;
}
catch (invalid_argument)
catch (const invalid_argument&)
{
// Do nothing
}
catch (out_of_range)
catch (const out_of_range&)
{
// Do nothing
}
@@ -453,35 +433,30 @@ bool CopyPasteManager::TryOperandToULL(const wstring& operand, int numberBase, u
return false;
}
size_t CopyPasteManager::OperandLength(wstring operand, ViewMode mode, CategoryGroupType modeType, int programmerNumberBase)
size_t CopyPasteManager::OperandLength(const wstring& operand, ViewMode mode, CategoryGroupType modeType, int programmerNumberBase)
{
size_t len = 0;
if (mode == ViewMode::Standard || mode == ViewMode::Scientific)
if (modeType == CategoryGroupType::Converter)
{
len = StandardScientificOperandLength(operand);
}
else if (mode == ViewMode::Programmer)
{
len = ProgrammerOperandLength(operand, programmerNumberBase);
}
else if (modeType == CategoryGroupType::Converter)
{
len = operand.length();
return operand.length();
}
return len;
switch (mode)
{
case ViewMode::Standard:
case ViewMode::Scientific:
return StandardScientificOperandLength(operand);
case ViewMode::Programmer:
return ProgrammerOperandLength(operand, programmerNumberBase);
default:
return 0;
}
}
size_t CopyPasteManager::StandardScientificOperandLength(wstring operand)
size_t CopyPasteManager::StandardScientificOperandLength(const wstring& operand)
{
bool hasDecimal = false;
for (size_t i = 0; i < operand.length(); i++)
{
if (operand[i] == L'.')
{
hasDecimal = true;
}
}
const bool hasDecimal = operand.find('.') != wstring::npos;
if (hasDecimal)
{
@@ -503,8 +478,6 @@ size_t CopyPasteManager::StandardScientificOperandLength(wstring operand)
size_t CopyPasteManager::ProgrammerOperandLength(const wstring& operand, int numberBase)
{
size_t len = operand.length();
vector<wstring> prefixes{};
vector<wstring> suffixes{};
switch (numberBase)
@@ -525,7 +498,7 @@ size_t CopyPasteManager::ProgrammerOperandLength(const wstring& operand, int num
break;
default:
// No defined prefixes/suffixes
break;
return 0;
}
// UInt suffixes are common across all modes
@@ -535,9 +508,11 @@ size_t CopyPasteManager::ProgrammerOperandLength(const wstring& operand, int num
wstring operandUpper = operand;
transform(operandUpper.begin(), operandUpper.end(), operandUpper.begin(), towupper);
size_t len = operand.length();
// Detect if there is a suffix and subtract its length
// Check suffixes first to allow e.g. "0b" to result in length 1 (value 0), rather than length 0 (no value).
for (const wstring& suffix : suffixes)
for (const auto& suffix : suffixes)
{
if (len < suffix.length())
{
@@ -552,7 +527,7 @@ size_t CopyPasteManager::ProgrammerOperandLength(const wstring& operand, int num
}
// Detect if there is a prefix and subtract its length
for (const wstring& prefix : prefixes)
for (const auto& prefix : prefixes)
{
if (len < prefix.length())
{

View File

@@ -13,21 +13,24 @@ namespace CalculatorUnitTests
namespace CalculatorApp
{
#define QwordType 1
#define DwordType 2
#define WordType 3
#define ByteType 4
#define HexBase 5
#define DecBase 6
#define OctBase 7
#define BinBase 8
inline constexpr auto QwordType = 1;
inline constexpr auto DwordType = 2;
inline constexpr auto WordType = 3;
inline constexpr auto ByteType = 4;
inline constexpr auto HexBase = 5;
inline constexpr auto DecBase = 6;
inline constexpr auto OctBase = 7;
inline constexpr auto BinBase = 8;
class CopyPasteManager
{
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 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 bool HasStringToPaste()
{
return ClipboardTextFormat() >= 0;
@@ -37,26 +40,38 @@ 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(
Platform::String^ pastedText,
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,
int bitLengthType);
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(std::wstring operand, CalculatorApp::Common::ViewMode mode, CalculatorApp::Common::CategoryGroupType modeType, int programmerNumberBase = -1);
static size_t StandardScientificOperandLength(std::wstring operand);
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);
@@ -68,7 +83,7 @@ namespace CalculatorApp
static constexpr size_t MaxExponentLength = 4;
static constexpr size_t MaxProgrammerBitLength = 64;
static Platform::String^ supportedFormats[];
static Platform::String ^ supportedFormats[];
friend class CalculatorUnitTests::CopyPasteManagerTest;
};

View File

@@ -9,7 +9,7 @@ using namespace Windows::Foundation;
using namespace Windows::Globalization;
using namespace CalculatorApp::Common::DateCalculation;
DateCalculationEngine::DateCalculationEngine(_In_ String^ calendarIdentifier)
DateCalculationEngine::DateCalculationEngine(_In_ String ^ calendarIdentifier)
{
m_calendar = ref new Calendar();
m_calendar->ChangeTimeZone("UTC");
@@ -18,12 +18,25 @@ DateCalculationEngine::DateCalculationEngine(_In_ String^ calendarIdentifier)
// Adding Duration to a Date
// 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)
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);
@@ -39,25 +52,43 @@ bool DateCalculationEngine::AddDuration(_In_ DateTime startDate, _In_ const Date
*endDate = m_calendar->GetDateTime();
}
catch (Platform::InvalidArgumentException^ ex)
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;
}
// Subtracting Duration from a 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)
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,21 +101,25 @@ bool DateCalculationEngine::SubtractDuration(_In_ DateTime startDate, _In_ const
{
m_calendar->AddYears(-duration.year);
}
*endDate = m_calendar->GetDateTime();
}
catch (Platform::InvalidArgumentException^ ex)
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);
}
// Calculate the difference between two dates
void DateCalculationEngine::GetDateDifference(_In_ DateTime date1, _In_ DateTime date2, _In_ DateUnit outputFormat, _Out_ DateDifference *difference)
bool DateCalculationEngine::TryGetDateDifference(_In_ DateTime date1, _In_ DateTime date2, _In_ DateUnit outputFormat, _Out_ DateDifference* difference)
{
DateTime startDate;
DateTime endDate;
@@ -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 };
@@ -139,11 +173,12 @@ void DateCalculationEngine::GetDateDifference(_In_ DateTime date1, _In_ DateTime
{
pivotDate = AdjustCalendarDate(pivotDate, dateUnit, static_cast<int>(differenceInDates[unitIndex]));
}
catch (Platform::InvalidArgumentException^)
catch (Platform::InvalidArgumentException ^)
{
// Operation failed due to out of bound result
// Do nothing
differenceInDates[unitIndex] = 0;
// For example: 31st Dec, 9999 - last valid date
*difference = DateDifferenceUnknown;
return false;
}
}
@@ -156,6 +191,12 @@ void DateCalculationEngine::GetDateDifference(_In_ DateTime date1, _In_ DateTime
if (tempDaysDiff < 0)
{
// pivotDate has gone over the end date; start from the beginning of this unit
if (differenceInDates[unitIndex] == 0)
{
// differenceInDates[unitIndex] is unsigned, the value can't be negative
*difference = DateDifferenceUnknown;
return false;
}
differenceInDates[unitIndex] -= 1;
pivotDate = tempPivotDate;
pivotDate = AdjustCalendarDate(pivotDate, dateUnit, static_cast<int>(differenceInDates[unitIndex]));
@@ -172,21 +213,30 @@ void DateCalculationEngine::GetDateDifference(_In_ DateTime date1, _In_ DateTime
// pivotDate is still below the end date
try
{
pivotDate = AdjustCalendarDate(pivotDate, dateUnit, 1);
pivotDate = AdjustCalendarDate(tempPivotDate, dateUnit, static_cast<int>(differenceInDates[unitIndex] + 1));
differenceInDates[unitIndex] += 1;
}
catch (Platform::InvalidArgumentException^)
catch (Platform::InvalidArgumentException ^)
{
// handling for 31st Dec, 9999 last valid date
// Do nothing - break out
break;
// Operation failed due to out of bound result
// For example: 31st Dec, 9999 - last valid date
*difference = DateDifferenceUnknown;
return false;
}
}
} while (tempDaysDiff != 0); // dates are the same - exit the loop
tempPivotDate = AdjustCalendarDate(tempPivotDate, dateUnit, static_cast<int>(differenceInDates[unitIndex]));
pivotDate = tempPivotDate;
daysDiff = GetDifferenceInDays(pivotDate, endDate);
int signedDaysDiff = GetDifferenceInDays(pivotDate, endDate);
if (signedDaysDiff < 0)
{
// daysDiff is unsigned, the value can't be negative
*difference = DateDifferenceUnknown;
return false;
}
daysDiff = signedDaysDiff;
}
}
}
@@ -198,9 +248,9 @@ void DateCalculationEngine::GetDateDifference(_In_ DateTime date1, _In_ DateTime
difference->month = differenceInDates[1];
difference->week = differenceInDates[2];
difference->day = differenceInDates[3];
return true;
}
// Private Methods
// Gets number of days between the two date time values
@@ -274,34 +324,34 @@ 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);
// 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:
{
// 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.
auto currentCalendarSystem = m_calendar->GetCalendarSystem();
if (currentCalendarSystem == CalendarIdentifiers::Japanese)
{
m_calendar->ChangeCalendarSystem(CalendarIdentifiers::Gregorian);
}
m_calendar->AddYears(difference);
m_calendar->ChangeCalendarSystem(currentCalendarSystem);
break;
}
case DateUnit::Month:
m_calendar->AddMonths(difference);
break;
case DateUnit::Week:
m_calendar->AddWeeks(difference);
break;
case DateUnit::Year:
m_calendar->AddYears(difference);
break;
case DateUnit::Month:
m_calendar->AddMonths(difference);
break;
case DateUnit::Week:
m_calendar->AddWeeks(difference);
break;
}
m_calendar->ChangeCalendarSystem(currentCalendarSystem);
return m_calendar->GetDateTime();
}

View File

@@ -1,4 +1,4 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#pragma once
@@ -9,8 +9,8 @@ const uint64_t c_minute = 60 * c_second;
const uint64_t c_hour = 60 * c_minute;
const uint64_t c_day = 24 * c_hour;
const int c_unitsOfDate = 4; // Units Year,Month,Week,Day
const int c_unitsGreaterThanDays = 3; // Units Greater than Days (Year/Month/Week) 3
const int c_unitsOfDate = 4; // Units Year,Month,Week,Day
const int c_unitsGreaterThanDays = 3; // Units Greater than Days (Year/Month/Week) 3
const int c_daysInWeek = 7;
namespace CalculatorApp
@@ -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,
@@ -34,22 +35,37 @@ namespace CalculatorApp
int month = 0;
int week = 0;
int day = 0;
bool operator==(const DateDifference& dd) const
{
return year == dd.year && month == dd.month && week == dd.week && day == day;
}
};
const DateDifference DateDifferenceUnknown{ INT_MIN, INT_MIN, INT_MIN, INT_MIN };
class DateCalculationEngine
{
public:
// Constructor
DateCalculationEngine(_In_ Platform::String^ calendarIdentifier);
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);
bool __nothrow TryGetDateDifference(
_In_ Windows::Foundation::DateTime date1,
_In_ Windows::Foundation::DateTime date2,
_In_ DateUnit outputFormat,
_Out_ DateDifference* difference);
private:
// Private Variables
Windows::Globalization::Calendar^ m_calendar;
Windows::Globalization::Calendar ^ m_calendar;
// Private Methods
int GetDifferenceInDays(Windows::Foundation::DateTime date1, Windows::Foundation::DateTime date2);

View File

@@ -8,33 +8,33 @@ namespace CalculatorApp
namespace Common
{
template <typename TTarget>
ref class DelegateCommand: public Windows::UI::Xaml::Input::ICommand
ref class DelegateCommand : public Windows::UI::Xaml::Input::ICommand
{
internal:
internal :
typedef void (TTarget::*CommandHandlerFunc)(Platform::Object^);
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
// code in the app calling Execute.
virtual void ExecuteImpl(Platform::Object^ parameter) sealed = Windows::UI::Xaml::Input::ICommand::Execute
virtual void ExecuteImpl(Platform::Object ^ parameter) sealed = Windows::UI::Xaml::Input::ICommand::Execute
{
TTarget^ target = m_weakTarget.Resolve<TTarget>();
TTarget ^ target = m_weakTarget.Resolve<TTarget>();
if (target)
{
(target->*m_function)(parameter);
}
}
virtual bool CanExecuteImpl(Platform::Object^ parameter) sealed = Windows::UI::Xaml::Input::ICommand::CanExecute
virtual bool CanExecuteImpl(Platform::Object ^ parameter) sealed = Windows::UI::Xaml::Input::ICommand::CanExecute
{
return true;
}
@@ -57,14 +57,12 @@ namespace CalculatorApp
CommandHandlerFunc m_function;
Platform::WeakReference m_weakTarget;
};
template <typename TTarget, typename TFuncPtr>
DelegateCommand<TTarget>^ MakeDelegate(TTarget^ target, TFuncPtr&& function)
{
return ref new DelegateCommand<TTarget>(target, std::forward<TFuncPtr>(function));
}
DelegateCommand<TTarget> ^ MakeDelegate(TTarget ^ target, TFuncPtr&& function) {
return ref new DelegateCommand<TTarget>(target, std::forward<TFuncPtr>(function));
}
}
}

View File

@@ -7,30 +7,40 @@
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);
OBSERVABLE_PROPERTY_RW(Platform::String ^, Token);
OBSERVABLE_PROPERTY_RW(int, TokenPosition);
OBSERVABLE_PROPERTY_RW(bool, IsTokenEditable);
OBSERVABLE_PROPERTY_RW(int, CommandIndex);
OBSERVABLE_PROPERTY_R(Platform::String^, OriginalToken);
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;
};

View File

@@ -44,7 +44,7 @@ namespace CalculatorApp
}
StringReference idRef(id.c_str());
String^ str = m_resLoader->GetString(idRef);
String ^ str = m_resLoader->GetString(idRef);
return str->Begin();
}
}

View File

@@ -14,6 +14,6 @@ namespace CalculatorApp
virtual std::wstring GetCEngineString(const std::wstring& id) override;
private:
Windows::ApplicationModel::Resources::ResourceLoader^ m_resLoader;
Windows::ApplicationModel::Resources::ResourceLoader ^ m_resLoader;
};
}

View File

@@ -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)
{
@@ -20,7 +23,7 @@ std::shared_ptr<IExpressionCommand> CommandDeserializer::Deserialize(_In_ Calcul
case CalculationManager::CommandType::Parentheses:
return std::make_shared<CParentheses>(DeserializeParentheses());
return std::make_shared<CParentheses>(DeserializeParentheses());
break;
case CalculationManager::CommandType::UnaryCommand:

View File

@@ -12,11 +12,11 @@ namespace CalculatorApp
class CommandDeserializer
{
public:
CommandDeserializer(_In_ Windows::Storage::Streams::DataReader^ dataReader);
CommandDeserializer(_In_ Windows::Storage::Streams::DataReader ^ dataReader);
std::shared_ptr<IExpressionCommand> Deserialize(_In_ CalculationManager::CommandType cmdType);
private:
Windows::Storage::Streams::DataReader^ m_dataReader;
Windows::Storage::Streams::DataReader ^ m_dataReader;
COpndCommand DeserializeOperand();
CParentheses DeserializeParentheses();
CUnaryCommand DeserializeUnary();

View File

@@ -7,11 +7,12 @@
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)
{
}
void SerializeCommandVisitor::Visit(_In_ COpndCommand &opndCmd)
void SerializeCommandVisitor::Visit(_In_ COpndCommand& opndCmd)
{
m_dataWriter->WriteBoolean(opndCmd.IsNegative());
m_dataWriter->WriteBoolean(opndCmd.IsDecimalPresent());
@@ -29,7 +30,7 @@ void SerializeCommandVisitor::Visit(_In_ COpndCommand &opndCmd)
}
}
void SerializeCommandVisitor::Visit(_In_ CUnaryCommand &unaryCmd)
void SerializeCommandVisitor::Visit(_In_ CUnaryCommand& unaryCmd)
{
auto cmds = unaryCmd.GetCommands();
unsigned int cmdSize;
@@ -43,13 +44,13 @@ void SerializeCommandVisitor::Visit(_In_ CUnaryCommand &unaryCmd)
}
}
void SerializeCommandVisitor::Visit(_In_ CBinaryCommand &binaryCmd)
void SerializeCommandVisitor::Visit(_In_ CBinaryCommand& binaryCmd)
{
int cmd = binaryCmd.GetCommand();
m_dataWriter->WriteInt32(cmd);
}
void SerializeCommandVisitor::Visit(_In_ CParentheses &paraCmd)
void SerializeCommandVisitor::Visit(_In_ CParentheses& paraCmd)
{
int parenthesisCmd = paraCmd.GetCommand();
m_dataWriter->WriteInt32(parenthesisCmd);

View File

@@ -12,15 +12,15 @@ namespace CalculatorApp
class SerializeCommandVisitor : public ISerializeCommandVisitor
{
public:
SerializeCommandVisitor(_In_ Windows::Storage::Streams::DataWriter^ dataWriter);
SerializeCommandVisitor(_In_ Windows::Storage::Streams::DataWriter ^ dataWriter);
void Visit(_In_ COpndCommand &opndCmd);
void Visit(_In_ CUnaryCommand &unaryCmd);
void Visit(_In_ CBinaryCommand &binaryCmd);
void Visit(_In_ CParentheses &paraCmd);
void Visit(_In_ COpndCommand& opndCmd);
void Visit(_In_ CUnaryCommand& unaryCmd);
void Visit(_In_ CBinaryCommand& binaryCmd);
void Visit(_In_ CParentheses& paraCmd);
private:
Windows::Storage::Streams::DataWriter^ m_dataWriter;
Windows::Storage::Streams::DataWriter ^ m_dataWriter;
};
}
}

View File

@@ -71,11 +71,11 @@ namespace CalculatorApp
}
}
winrt::fire_and_forget LightUpButton(ButtonBase^ button)
void LightUpButton(ButtonBase ^ button)
{
// If the button is a toggle button then we don't need
// to change the UI of the button
if (dynamic_cast<ToggleButton^>(button))
if (dynamic_cast<ToggleButton ^>(button))
{
return;
}
@@ -83,15 +83,31 @@ namespace CalculatorApp
// The button will go into the visual Pressed state with this call
VisualStateManager::GoToState(button, "Pressed", true);
winrt::apartment_context uiThreadContext;
// This timer will fire after lightUpTime and make the button
// go back to the normal state.
// This timer will only fire once after which it will be destroyed
auto timer = ref new DispatcherTimer();
TimeSpan lightUpTime{};
lightUpTime.Duration = 500000L; // Half second (in 100-ns units)
timer->Interval = lightUpTime;
co_await winrt::resume_background();
co_await winrt::resume_after(500ms);
WeakReference timerWeakReference(timer);
WeakReference buttonWeakReference(button);
timer->Tick += ref new EventHandler<Object ^>([buttonWeakReference, timerWeakReference](Object ^, Object ^) {
auto button = buttonWeakReference.Resolve<ButtonBase>();
if (button)
{
VisualStateManager::GoToState(button, "Normal", true);
}
co_await uiThreadContext;
// Restore the normal state
VisualStateManager::GoToState(button, "Normal", true);
// Cancel the timer after we're done so it only fires once
auto timer = timerWeakReference.Resolve<DispatcherTimer>();
if (timer)
{
timer->Stop();
}
});
timer->Start();
}
// Looks for the first button reference that it can resolve
@@ -113,7 +129,7 @@ namespace CalculatorApp
}
}
void RunButtonCommand(ButtonBase^ button)
void RunButtonCommand(ButtonBase ^ button)
{
if (button->IsEnabled)
{
@@ -124,14 +140,14 @@ namespace CalculatorApp
command->Execute(parameter);
}
auto radio = dynamic_cast<RadioButton^>(button);
auto radio = dynamic_cast<RadioButton ^>(button);
if (radio)
{
radio->IsChecked = true;
return;
}
auto toggle = dynamic_cast<ToggleButton^>(button);
auto toggle = dynamic_cast<ToggleButton ^>(button);
if (toggle)
{
toggle->IsChecked = !toggle->IsChecked->Value;
@@ -146,7 +162,7 @@ static multimap<int, bool> s_ignoreNextEscape;
static multimap<int, bool> s_keepIgnoringEscape;
static multimap<int, bool> s_fHonorShortcuts;
static multimap<int, bool> s_fHandledEnter;
static multimap<int, Flyout^> s_AboutFlyout;
static multimap<int, Flyout ^> s_AboutFlyout;
void KeyboardShortcutManager::IgnoreEscape(bool onlyOnce)
{
@@ -188,15 +204,12 @@ 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);
auto button = safe_cast<ButtonBase^>(target);
auto button = safe_cast<ButtonBase ^>(target);
int viewId = Utils::GetWindowId();
auto iterViewMap = s_CharacterForButtons.find(viewId);
@@ -237,15 +250,12 @@ 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);
auto button = static_cast<ButtonBase^>(target);
auto button = static_cast<ButtonBase ^>(target);
int viewId = Utils::GetWindowId();
auto iterViewMap = s_VirtualKeysForButtons.find(viewId);
@@ -263,20 +273,17 @@ 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);
Control^ control = dynamic_cast<ButtonBase^>(target);
Control ^ control = dynamic_cast<ButtonBase ^>(target);
if (control == nullptr)
{
// Handling Ctrl+E shortcut for Date Calc, target would be NavigationView^ in that case
control = safe_cast<MUXC::NavigationView^>(target);
control = safe_cast<MUXC::NavigationView ^>(target);
}
int viewId = Utils::GetWindowId();
@@ -295,15 +302,12 @@ 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);
auto button = safe_cast<ButtonBase^>(target);
auto button = safe_cast<ButtonBase ^>(target);
int viewId = Utils::GetWindowId();
auto iterViewMap = s_VirtualKeyShiftChordsForButtons.find(viewId);
@@ -321,15 +325,12 @@ 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);
MUXC::NavigationView^ navView = safe_cast<MUXC::NavigationView^>(target);
MUXC::NavigationView ^ navView = safe_cast<MUXC::NavigationView ^>(target);
int viewId = Utils::GetWindowId();
auto iterViewMap = s_VirtualKeyAltChordsForButtons.find(viewId);
@@ -347,15 +348,12 @@ 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);
auto button = safe_cast<ButtonBase^>(target);
auto button = safe_cast<ButtonBase ^>(target);
int viewId = Utils::GetWindowId();
auto iterViewMap = s_VirtualKeyControlShiftChordsForButtons.find(viewId);
@@ -373,15 +371,12 @@ 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);
auto button = safe_cast<ButtonBase^>(target);
auto button = safe_cast<ButtonBase ^>(target);
int viewId = Utils::GetWindowId();
auto iterViewMap = s_VirtualKeyInverseChordsForButtons.find(viewId);
@@ -399,15 +394,12 @@ 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);
auto button = safe_cast<ButtonBase^>(target);
auto button = safe_cast<ButtonBase ^>(target);
int viewId = Utils::GetWindowId();
auto iterViewMap = s_VirtualKeyControlInverseChordsForButtons.find(viewId);
@@ -428,7 +420,7 @@ void KeyboardShortcutManager::OnVirtualKeyControlInverseChordPropertyChanged(
// In the three event handlers below we will not mark the event as handled
// because this is a supplemental operation and we don't want to interfere with
// the normal keyboard handling.
void KeyboardShortcutManager::OnCharacterReceivedHandler(CoreWindow^ sender, CharacterReceivedEventArgs^ args)
void KeyboardShortcutManager::OnCharacterReceivedHandler(CoreWindow ^ sender, CharacterReceivedEventArgs ^ args)
{
int viewId = Utils::GetWindowId();
auto currentHonorShortcuts = s_fHonorShortcuts.find(viewId);
@@ -454,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;
}
@@ -503,7 +497,7 @@ const std::multimap<MyVirtualKey, WeakReference>& GetCurrentKeyDictionary(MyVirt
}
}
void KeyboardShortcutManager::OnKeyDownHandler(CoreWindow^ sender, KeyEventArgs^ args)
void KeyboardShortcutManager::OnKeyDownHandler(CoreWindow ^ sender, KeyEventArgs ^ args)
{
// If keyboard shortcuts like Ctrl+C or Ctrl+V are not handled
if (!args->Handled)
@@ -518,25 +512,23 @@ 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));
auto navView = buttons.first->second.Resolve<MUXC::NavigationView>();
auto appViewModel = safe_cast<ApplicationViewModel^>(navView->DataContext);
auto appViewModel = safe_cast<ApplicationViewModel ^>(navView->DataContext);
appViewModel->Mode = ViewMode::Date;
auto categoryName = AppResourceProvider::GetInstance().GetResourceString(L"DateCalculationModeText");
appViewModel->CategoryName = categoryName;
auto menuItems = static_cast<IObservableVector<Object^>^>(navView->MenuItemsSource);
auto menuItems = static_cast<IObservableVector<Object ^> ^>(navView->MenuItemsSource);
auto flatIndex = NavCategory::GetFlatIndex(ViewMode::Date);
navView->SelectedItem = menuItems->GetAt(flatIndex);
return;
}
auto currentHonorShortcuts = s_fHonorShortcuts.find(viewId);
auto currentHonorShortcuts = s_fHonorShortcuts.find(viewId);
auto currentIgnoreNextEscape = s_ignoreNextEscape.find(viewId);
@@ -595,9 +587,11 @@ void KeyboardShortcutManager::OnKeyDownHandler(CoreWindow^ sender, KeyEventArgs^
{
if (currentHonorShortcuts->second)
{
// 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
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
if (currentIsDropDownOpen != s_IsDropDownOpen.end() && !currentIsDropDownOpen->second)
{
// Do not Light Up Buttons when Ctrl+C, Ctrl+V, Ctrl+Insert or Shift+Insert is pressed
@@ -614,7 +608,7 @@ void KeyboardShortcutManager::OnKeyDownHandler(CoreWindow^ sender, KeyEventArgs^
}
}
void KeyboardShortcutManager::OnKeyUpHandler(CoreWindow^ sender, KeyEventArgs^ args)
void KeyboardShortcutManager::OnKeyUpHandler(CoreWindow ^ sender, KeyEventArgs ^ args)
{
int viewId = Utils::GetWindowId();
auto key = args->VirtualKey;
@@ -647,7 +641,7 @@ void KeyboardShortcutManager::OnKeyUpHandler(CoreWindow^ sender, KeyEventArgs^ a
}
}
void KeyboardShortcutManager::OnAcceleratorKeyActivated(CoreDispatcher^, AcceleratorKeyEventArgs^ args)
void KeyboardShortcutManager::OnAcceleratorKeyActivated(CoreDispatcher ^, AcceleratorKeyEventArgs ^ args)
{
if (args->KeyStatus.IsKeyReleased)
{
@@ -667,12 +661,12 @@ void KeyboardShortcutManager::OnAcceleratorKeyActivated(CoreDispatcher^, Acceler
auto item = listIterator->second.Resolve<MUXC::NavigationView>();
if (item != nullptr)
{
auto navView = safe_cast<MUXC::NavigationView^> (item);
auto navView = safe_cast<MUXC::NavigationView ^>(item);
auto menuItems = static_cast<IObservableVector<Object^>^>(navView->MenuItemsSource);
auto menuItems = static_cast<IObservableVector<Object ^> ^>(navView->MenuItemsSource);
if (menuItems != nullptr)
{
auto vm = safe_cast<ApplicationViewModel^>(navView->DataContext);
auto vm = safe_cast<ApplicationViewModel ^>(navView->DataContext);
if (nullptr != vm)
{
ViewMode toMode = NavCategory::GetViewModeForVirtualKey(static_cast<MyVirtualKey>(key));
@@ -704,13 +698,11 @@ 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);
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->Dispatcher->AcceleratorKeyActivated +=
ref new TypedEventHandler<CoreDispatcher^, AcceleratorKeyEventArgs^>(&KeyboardShortcutManager::OnAcceleratorKeyActivated);
ref new TypedEventHandler<CoreDispatcher ^, AcceleratorKeyEventArgs ^>(&KeyboardShortcutManager::OnAcceleratorKeyActivated);
KeyboardShortcutManager::RegisterNewAppViewId();
}
@@ -737,7 +729,7 @@ void KeyboardShortcutManager::UpdateDropDownState(bool isOpen)
}
}
void KeyboardShortcutManager::UpdateDropDownState(Flyout^ aboutPageFlyout)
void KeyboardShortcutManager::UpdateDropDownState(Flyout ^ aboutPageFlyout)
{
int viewId = Utils::GetWindowId();

View File

@@ -10,14 +10,17 @@ namespace CalculatorApp
{
namespace Common
{
public ref class KeyboardShortcutManager sealed
public
ref class KeyboardShortcutManager sealed
{
public:
KeyboardShortcutManager() {}
KeyboardShortcutManager()
{
}
DEPENDENCY_PROPERTY_OWNER(KeyboardShortcutManager);
DEPENDENCY_PROPERTY_ATTACHED_WITH_CALLBACK(Platform::String^, Character);
DEPENDENCY_PROPERTY_ATTACHED_WITH_CALLBACK(Platform::String ^, Character);
DEPENDENCY_PROPERTY_ATTACHED_WITH_CALLBACK(MyVirtualKey, VirtualKey);
DEPENDENCY_PROPERTY_ATTACHED_WITH_CALLBACK(MyVirtualKey, VirtualKeyControlChord);
DEPENDENCY_PROPERTY_ATTACHED_WITH_CALLBACK(MyVirtualKey, VirtualKeyShiftChord);
@@ -26,9 +29,10 @@ namespace CalculatorApp
DEPENDENCY_PROPERTY_ATTACHED_WITH_CALLBACK(MyVirtualKey, VirtualKeyInverseChord);
DEPENDENCY_PROPERTY_ATTACHED_WITH_CALLBACK(MyVirtualKey, VirtualKeyControlInverseChord);
internal:
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
@@ -42,57 +46,34 @@ namespace CalculatorApp
static void HandledEnter(bool ishandled);
static void UpdateDropDownState(bool);
static void ShiftButtonChecked(bool checked);
static void UpdateDropDownState(Windows::UI::Xaml::Controls::Flyout^ aboutPageFlyout);
static void UpdateDropDownState(Windows::UI::Xaml::Controls::Flyout ^ aboutPageFlyout);
static void RegisterNewAppViewId();
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);
static void OnKeyUpHandler(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::KeyEventArgs^ args);
static void OnAcceleratorKeyActivated(Windows::UI::Core::CoreDispatcher^, Windows::UI::Core::AcceleratorKeyEventArgs^ args);
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);
static void OnKeyUpHandler(Windows::UI::Core::CoreWindow ^ sender, Windows::UI::Core::KeyEventArgs ^ args);
static void OnAcceleratorKeyActivated(Windows::UI::Core::CoreDispatcher ^, Windows::UI::Core::AcceleratorKeyEventArgs ^ args);
};
}
}

View File

@@ -1,4 +1,4 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#include "pch.h"
@@ -33,16 +33,15 @@ DEPENDENCY_PROPERTY_INITIALIZATION(LocalizationService, FontSize);
static reader_writer_lock s_locServiceInstanceLock;
LocalizationService^ LocalizationService::s_singletonInstance = nullptr;
LocalizationService ^ LocalizationService::s_singletonInstance = nullptr;
// Resources for the engine use numbers as keys. It's inconvenient, but also difficult to
// change given that the engine heavily relies on perfect ordering of certain elements.
// The key for open parenthesis, '(', is "48".
static constexpr auto s_openParenResourceKey = L"48";
LocalizationService^ LocalizationService::GetInstance()
LocalizationService ^ LocalizationService::GetInstance()
{
if (s_singletonInstance == nullptr)
{
// Writer lock for the static maps
@@ -50,29 +49,46 @@ LocalizationService^ LocalizationService::GetInstance()
if (s_singletonInstance == nullptr)
{
s_singletonInstance = ref new LocalizationService();
s_singletonInstance = ref new LocalizationService(nullptr);
}
}
return s_singletonInstance;
}
LocalizationService::LocalizationService()
/// <summary>
/// Replace (or create) the single instance of this singleton class by one with the language passed as parameter
/// </summary>
/// <param name="language">RFC-5646 identifier of the language to use</param>
/// <remarks>
/// Should only be used for test purpose
/// </remarks>
void LocalizationService::OverrideWithLanguage(_In_ const wchar_t * const language)
{
m_language = ApplicationLanguages::Languages->GetAt(0);
s_singletonInstance = ref new LocalizationService(language);
}
/// <summary>
/// Constructor
/// </summary>
/// <param name="overridedLanguage">RFC-5646 identifier of the language to use, if null, will use the current language of the system</param>
LocalizationService::LocalizationService(_In_ const wchar_t * const overridedLanguage)
{
m_isLanguageOverrided = overridedLanguage != nullptr;
m_language = m_isLanguageOverrided ? ref new Platform::String(overridedLanguage) : ApplicationLanguages::Languages->GetAt(0);
m_flowDirection = ResourceContext::GetForCurrentView()->QualifierValues->Lookup(L"LayoutDirection")
!= L"LTR" ? FlowDirection::RightToLeft : FlowDirection::LeftToRight;
auto resourceLoader = AppResourceProvider::GetInstance();
m_fontFamilyOverride = resourceLoader.GetResourceString(L"LocalizedFontFamilyOverride");
String^ reserved = L"RESERVED_FOR_FONTLOC";
String ^ reserved = L"RESERVED_FOR_FONTLOC";
m_overrideFontApiValues = ((m_fontFamilyOverride != nullptr) && (m_fontFamilyOverride != reserved));
if (m_overrideFontApiValues)
{
String^ localizedUICaptionFontSizeFactorOverride = resourceLoader.GetResourceString(L"LocalizedUICaptionFontSizeFactorOverride");
String^ localizedUITextFontSizeFactorOverride = resourceLoader.GetResourceString(L"LocalizedUITextFontSizeFactorOverride");
String^ localizedFontWeightOverride = resourceLoader.GetResourceString(L"LocalizedFontWeightOverride");
String ^ localizedUICaptionFontSizeFactorOverride = resourceLoader.GetResourceString(L"LocalizedUICaptionFontSizeFactorOverride");
String ^ localizedUITextFontSizeFactorOverride = resourceLoader.GetResourceString(L"LocalizedUITextFontSizeFactorOverride");
String ^ localizedFontWeightOverride = resourceLoader.GetResourceString(L"LocalizedFontWeightOverride");
// If any of the font overrides are modified then all of them need to be modified
assert(localizedFontWeightOverride != reserved);
@@ -87,7 +103,7 @@ LocalizationService::LocalizationService()
m_fontGroup = ref new LanguageFontGroup(m_language);
}
FontWeight LocalizationService::ParseFontWeight(String^ fontWeight)
FontWeight LocalizationService::ParseFontWeight(String ^ fontWeight)
{
wstring weight = fontWeight->Data();
transform(weight.begin(), weight.end(), weight.begin(), towlower);
@@ -153,7 +169,7 @@ bool LocalizationService::IsRtlLayout()
return m_flowDirection == FlowDirection::RightToLeft;
}
String^ LocalizationService::GetLanguage()
String ^ LocalizationService::GetLanguage()
{
return m_language;
}
@@ -163,7 +179,7 @@ bool LocalizationService::GetOverrideFontApiValues()
return m_overrideFontApiValues;
}
FontFamily^ LocalizationService::GetLanguageFontFamilyForType(LanguageFontType fontType)
FontFamily ^ LocalizationService::GetLanguageFontFamilyForType(LanguageFontType fontType)
{
if (m_overrideFontApiValues)
{
@@ -175,7 +191,7 @@ FontFamily^ LocalizationService::GetLanguageFontFamilyForType(LanguageFontType f
}
}
LanguageFont^ LocalizationService::GetLanguageFont(LanguageFontType fontType)
LanguageFont ^ LocalizationService::GetLanguageFont(LanguageFontType fontType)
{
assert(!m_overrideFontApiValues);
assert(m_fontGroup);
@@ -191,7 +207,7 @@ LanguageFont^ LocalizationService::GetLanguageFont(LanguageFontType fontType)
}
}
String^ LocalizationService::GetFontFamilyOverride()
String ^ LocalizationService::GetFontFamilyOverride()
{
assert(m_overrideFontApiValues);
return m_fontFamilyOverride;
@@ -218,24 +234,24 @@ double LocalizationService::GetFontScaleFactorOverride(LanguageFontType fontType
}
}
void LocalizationService::OnFontTypePropertyChanged(DependencyObject^ target, LanguageFontType /*oldValue*/, LanguageFontType /*newValue*/)
void LocalizationService::OnFontTypePropertyChanged(DependencyObject ^ target, LanguageFontType /*oldValue*/, LanguageFontType /*newValue*/)
{
UpdateFontFamilyAndSize(target);
}
void LocalizationService::OnFontWeightPropertyChanged(DependencyObject^ target, FontWeight /*oldValue*/, FontWeight /*newValue*/)
void LocalizationService::OnFontWeightPropertyChanged(DependencyObject ^ target, FontWeight /*oldValue*/, FontWeight /*newValue*/)
{
UpdateFontFamilyAndSize(target);
}
void LocalizationService::OnFontSizePropertyChanged(DependencyObject^ target, double /*oldValue*/, double /*newValue*/)
void LocalizationService::OnFontSizePropertyChanged(DependencyObject ^ target, double /*oldValue*/, double /*newValue*/)
{
UpdateFontFamilyAndSize(target);
}
void LocalizationService::UpdateFontFamilyAndSize(DependencyObject^ target)
void LocalizationService::UpdateFontFamilyAndSize(DependencyObject ^ target)
{
FontFamily^ fontFamily;
FontFamily ^ fontFamily;
FontWeight fontWeight;
bool fOverrideFontWeight = false;
double scaleFactor;
@@ -259,7 +275,7 @@ void LocalizationService::UpdateFontFamilyAndSize(DependencyObject^ target)
double sizeToUse = LocalizationService::GetFontSize(target) * scaleFactor;
auto control = dynamic_cast<Control^>(target);
auto control = dynamic_cast<Control ^>(target);
if (control)
{
control->FontFamily = fontFamily;
@@ -278,7 +294,7 @@ void LocalizationService::UpdateFontFamilyAndSize(DependencyObject^ target)
}
else
{
auto textBlock = dynamic_cast<TextBlock^>(target);
auto textBlock = dynamic_cast<TextBlock ^>(target);
if (textBlock)
{
textBlock->FontFamily = fontFamily;
@@ -297,7 +313,7 @@ void LocalizationService::UpdateFontFamilyAndSize(DependencyObject^ target)
}
else
{
RichTextBlock^ richTextBlock = dynamic_cast<RichTextBlock^>(target);
RichTextBlock ^ richTextBlock = dynamic_cast<RichTextBlock ^>(target);
if (richTextBlock)
{
richTextBlock->FontFamily = fontFamily;
@@ -316,7 +332,7 @@ void LocalizationService::UpdateFontFamilyAndSize(DependencyObject^ target)
}
else
{
TextElement^ textElement = dynamic_cast<TextElement^>(target);
TextElement ^ textElement = dynamic_cast<TextElement ^>(target);
if (textElement)
{
textElement->FontFamily = fontFamily;
@@ -340,9 +356,9 @@ void LocalizationService::UpdateFontFamilyAndSize(DependencyObject^ target)
// If successful, returns a formatter that respects the user's regional format settings,
// as configured by running intl.cpl.
DecimalFormatter^ LocalizationService::GetRegionalSettingsAwareDecimalFormatter()
DecimalFormatter ^ LocalizationService::GetRegionalSettingsAwareDecimalFormatter() const
{
IIterable<String^>^ languageIdentifiers = LocalizationService::GetLanguageIdentifiers();
IIterable<String ^> ^ languageIdentifiers = LocalizationService::GetLanguageIdentifiers();
if (languageIdentifiers != nullptr)
{
return ref new DecimalFormatter(languageIdentifiers, GlobalizationPreferences::HomeGeographicRegion);
@@ -355,9 +371,9 @@ DecimalFormatter^ LocalizationService::GetRegionalSettingsAwareDecimalFormatter(
// as configured by running intl.cpl.
//
// This helper function creates a DateTimeFormatter with a TwentyFour hour clock
DateTimeFormatter^ LocalizationService::GetRegionalSettingsAwareDateTimeFormatter(_In_ String^ format)
DateTimeFormatter ^ LocalizationService::GetRegionalSettingsAwareDateTimeFormatter(_In_ String^ format) const
{
IIterable<String^>^ languageIdentifiers = LocalizationService::GetLanguageIdentifiers();
IIterable<String ^> ^ languageIdentifiers = LocalizationService::GetLanguageIdentifiers();
if (languageIdentifiers == nullptr)
{
languageIdentifiers = ApplicationLanguages::Languages;
@@ -368,41 +384,29 @@ 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) const
{
IIterable<String^>^ languageIdentifiers = LocalizationService::GetLanguageIdentifiers();
IIterable<String ^> ^ languageIdentifiers = LocalizationService::GetLanguageIdentifiers();
if (languageIdentifiers == nullptr)
{
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()
CurrencyFormatter ^ LocalizationService::GetRegionalSettingsAwareCurrencyFormatter() const
{
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();
IIterable<String ^> ^ languageIdentifiers = GetLanguageIdentifiers();
if (languageIdentifiers == nullptr)
{
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;
@@ -410,10 +414,18 @@ CurrencyFormatter^ LocalizationService::GetRegionalSettingsAwareCurrencyFormatte
return currencyFormatter;
}
IIterable<String^>^ LocalizationService::GetLanguageIdentifiers()
IIterable<String ^> ^ LocalizationService::GetLanguageIdentifiers() const
{
WCHAR currentLocale[LOCALE_NAME_MAX_LENGTH] = {};
int result = GetUserDefaultLocaleName(currentLocale, LOCALE_NAME_MAX_LENGTH);
if (m_isLanguageOverrided)
{
auto overridedLanguageList = ref new Vector<String^>();
overridedLanguageList->Append(m_language);
return overridedLanguageList;
}
if (result != 0)
{
// GetUserDefaultLocaleName may return an invalid bcp47 language tag with trailing non-BCP47 friendly characters,
@@ -426,12 +438,12 @@ IIterable<String^>^ LocalizationService::GetLanguageIdentifiers()
*underscore = L'\0';
}
String^ localeString = ref new String(currentLocale);
String ^ localeString = ref new String(currentLocale);
// validate if the locale we have is valid
// otherwise we fallback to the default.
if (Language::IsWellFormed(localeString))
{
auto languageList = ref new Vector<String^>();
auto languageList = ref new Vector<String ^>();
languageList->Append(localeString);
return languageList;
}
@@ -446,51 +458,49 @@ 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
make_pair<wstring, wstring>(L"67", L"SineDegrees"),
make_pair<wstring, wstring>(L"73", L"SineRadians"),
make_pair<wstring, wstring>(L"79", L"SineGradians"),
make_pair<wstring, wstring>(L"70", L"InverseSineDegrees"),
make_pair<wstring, wstring>(L"76", L"InverseSineRadians"),
make_pair<wstring, wstring>(L"82", L"InverseSineGradians"),
make_pair<wstring, wstring>(L"25", L"HyperbolicSine"),
make_pair<wstring, wstring>(L"85", L"InverseHyperbolicSine"),
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"),
make_pair<wstring, wstring>(L"70", L"InverseSineDegrees"),
make_pair<wstring, wstring>(L"76", L"InverseSineRadians"),
make_pair<wstring, wstring>(L"82", L"InverseSineGradians"),
make_pair<wstring, wstring>(L"25", L"HyperbolicSine"),
make_pair<wstring, wstring>(L"85", L"InverseHyperbolicSine"),
// Cosine permutations
make_pair<wstring, wstring>(L"68", L"CosineDegrees"),
make_pair<wstring, wstring>(L"74", L"CosineRadians"),
make_pair<wstring, wstring>(L"80", L"CosineGradians"),
make_pair<wstring, wstring>(L"71", L"InverseCosineDegrees"),
make_pair<wstring, wstring>(L"77", L"InverseCosineRadians"),
make_pair<wstring, wstring>(L"83", L"InverseCosineGradians"),
make_pair<wstring, wstring>(L"26", L"HyperbolicCosine"),
make_pair<wstring, wstring>(L"86", L"InverseHyperbolicCosine"),
// Cosine permutations
make_pair<wstring, wstring>(L"68", L"CosineDegrees"),
make_pair<wstring, wstring>(L"74", L"CosineRadians"),
make_pair<wstring, wstring>(L"80", L"CosineGradians"),
make_pair<wstring, wstring>(L"71", L"InverseCosineDegrees"),
make_pair<wstring, wstring>(L"77", L"InverseCosineRadians"),
make_pair<wstring, wstring>(L"83", L"InverseCosineGradians"),
make_pair<wstring, wstring>(L"26", L"HyperbolicCosine"),
make_pair<wstring, wstring>(L"86", L"InverseHyperbolicCosine"),
// Tangent permutations
make_pair<wstring, wstring>(L"69", L"TangentDegrees"),
make_pair<wstring, wstring>(L"75", L"TangentRadians"),
make_pair<wstring, wstring>(L"81", L"TangentGradians"),
make_pair<wstring, wstring>(L"72", L"InverseTangentDegrees"),
make_pair<wstring, wstring>(L"78", L"InverseTangentRadians"),
make_pair<wstring, wstring>(L"84", L"InverseTangentGradians"),
make_pair<wstring, wstring>(L"27", L"HyperbolicTangent"),
make_pair<wstring, wstring>(L"87", L"InverseHyperbolicTangent"),
// Tangent permutations
make_pair<wstring, wstring>(L"69", L"TangentDegrees"),
make_pair<wstring, wstring>(L"75", L"TangentRadians"),
make_pair<wstring, wstring>(L"81", L"TangentGradians"),
make_pair<wstring, wstring>(L"72", L"InverseTangentDegrees"),
make_pair<wstring, wstring>(L"78", L"InverseTangentRadians"),
make_pair<wstring, wstring>(L"84", L"InverseTangentGradians"),
make_pair<wstring, wstring>(L"27", L"HyperbolicTangent"),
make_pair<wstring, wstring>(L"87", L"InverseHyperbolicTangent"),
// Miscellaneous Scientific functions
make_pair<wstring, wstring>(L"94", L"Factorial"),
make_pair<wstring, wstring>(L"35", L"DegreeMinuteSecond"),
make_pair<wstring, wstring>(L"28", L"NaturalLog"),
make_pair<wstring, wstring>(L"91", L"Square")
// Miscellaneous Scientific functions
make_pair<wstring, wstring>(L"94", L"Factorial"),
make_pair<wstring, wstring>(L"35", L"DegreeMinuteSecond"),
make_pair<wstring, wstring>(L"28", L"NaturalLog"),
make_pair<wstring, wstring>(L"91", L"Square")
};
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"),
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"),
// Y Root scientific function
make_pair<wstring, wstring>(L"16", L"YRoot")
// Y Root scientific function
make_pair<wstring, wstring>(L"16", L"YRoot")
};
unordered_map<wstring, wstring> tokenToReadableNameMap{};
@@ -523,7 +533,7 @@ unordered_map<wstring, wstring> LocalizationService::GetTokenToReadableNameMap()
return tokenToReadableNameMap;
}
String^ LocalizationService::GetNarratorReadableToken(String^ rawToken)
String ^ LocalizationService::GetNarratorReadableToken(String ^ rawToken)
{
static unordered_map<wstring, wstring> s_tokenToReadableNameMap = GetTokenToReadableNameMap();
@@ -534,12 +544,12 @@ String^ LocalizationService::GetNarratorReadableToken(String^ rawToken)
}
else
{
static const String^ openParen = AppResourceProvider::GetInstance().GetCEngineString(StringReference(s_openParenResourceKey));
static const String ^ openParen = AppResourceProvider::GetInstance().GetCEngineString(StringReference(s_openParenResourceKey));
return ref new String(itr->second.c_str()) + L" " + openParen;
}
}
String^ LocalizationService::GetNarratorReadableString(String^ rawString)
String ^ LocalizationService::GetNarratorReadableString(String ^ rawString)
{
wstringstream readableString{};
readableString << L"";

View File

@@ -5,81 +5,87 @@
#include "Utils.h"
namespace CalculatorApp { namespace Common
namespace CalculatorApp
{
namespace LocalizationServiceProperties
namespace Common
{
static constexpr std::wstring_view DefaultCurrencyCode{ L"USD" };
}
namespace LocalizationServiceProperties
{
static constexpr std::wstring_view DefaultCurrencyCode{ L"USD" };
}
public enum class LanguageFontType
{
UIText,
UICaption,
};
public
enum class LanguageFontType
{
UIText,
UICaption,
};
public ref class LocalizationService sealed
{
public:
public
ref class LocalizationService sealed
{
public:
DEPENDENCY_PROPERTY_OWNER(LocalizationService);
DEPENDENCY_PROPERTY_OWNER(LocalizationService);
DEPENDENCY_PROPERTY_ATTACHED_WITH_DEFAULT_AND_CALLBACK(LanguageFontType, FontType, LanguageFontType::UIText);
DEPENDENCY_PROPERTY_ATTACHED_WITH_CALLBACK(double, FontSize);
DEPENDENCY_PROPERTY_ATTACHED_WITH_DEFAULT_AND_CALLBACK(LanguageFontType, FontType, LanguageFontType::UIText);
DEPENDENCY_PROPERTY_ATTACHED_WITH_CALLBACK(double, FontSize);
internal:
static LocalizationService^ GetInstance();
static void OverrideWithLanguage(_In_ const wchar_t * const language);
Windows::UI::Xaml::FlowDirection GetFlowDirection();
bool IsRtlLayout();
bool GetOverrideFontApiValues();
Platform::String^ GetLanguage();
Windows::UI::Xaml::Media::FontFamily^ GetLanguageFontFamilyForType(LanguageFontType fontType);
Platform::String^ GetFontFamilyOverride();
Windows::UI::Text::FontWeight GetFontWeightOverride();
double GetFontScaleFactorOverride(LanguageFontType fontType);
Windows::UI::Xaml::FlowDirection GetFlowDirection();
bool IsRtlLayout();
bool GetOverrideFontApiValues();
Platform::String ^ GetLanguage();
Windows::UI::Xaml::Media::FontFamily ^ GetLanguageFontFamilyForType(LanguageFontType fontType);
Platform::String ^ GetFontFamilyOverride();
Windows::UI::Text::FontWeight GetFontWeightOverride();
double GetFontScaleFactorOverride(LanguageFontType fontType);
static Windows::Globalization::NumberFormatting::DecimalFormatter^ GetRegionalSettingsAwareDecimalFormatter();
static Windows::Globalization::DateTimeFormatting::DateTimeFormatter^ GetRegionalSettingsAwareDateTimeFormatter(_In_ Platform::String^ format);
static Windows::Globalization::DateTimeFormatting::DateTimeFormatter^ GetRegionalSettingsAwareDateTimeFormatter(
_In_ Platform::String^ format,
_In_ Platform::String^ calendarIdentifier,
_In_ Platform::String^ clockIdentifier);
Windows::Globalization::NumberFormatting::DecimalFormatter ^ GetRegionalSettingsAwareDecimalFormatter() const;
Windows::Globalization::DateTimeFormatting::DateTimeFormatter ^ GetRegionalSettingsAwareDateTimeFormatter(_In_ Platform::String ^ format) const;
Windows::Globalization::DateTimeFormatting::DateTimeFormatter ^ GetRegionalSettingsAwareDateTimeFormatter(
_In_ Platform::String ^ format,
_In_ Platform::String ^ calendarIdentifier,
_In_ Platform::String ^ clockIdentifier) const;
static Windows::Globalization::NumberFormatting::CurrencyFormatter^ GetRegionalSettingsAwareCurrencyFormatter();
Windows::Globalization::NumberFormatting::CurrencyFormatter ^ GetRegionalSettingsAwareCurrencyFormatter() const;
static Platform::String^ GetNarratorReadableToken(Platform::String^ rawToken);
static Platform::String^ GetNarratorReadableString(Platform::String^ rawString);
static Platform::String ^ GetNarratorReadableToken(Platform::String ^ rawToken);
static Platform::String ^ GetNarratorReadableString(Platform::String ^ rawString);
private:
Windows::Globalization::Fonts::LanguageFont^ GetLanguageFont(LanguageFontType fontType);
Windows::UI::Text::FontWeight ParseFontWeight(Platform::String^ fontWeight);
private:
LocalizationService(_In_ const wchar_t* const overridedLanguage);
Windows::Globalization::Fonts::LanguageFont ^ GetLanguageFont(LanguageFontType fontType);
Windows::UI::Text::FontWeight ParseFontWeight(Platform::String ^ fontWeight);
static Windows::Foundation::Collections::IIterable<Platform::String^>^ GetLanguageIdentifiers();
Windows::Foundation::Collections::IIterable<Platform::String ^> ^ GetLanguageIdentifiers() const;
// 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 OnFontSizePropertyChanged(Windows::UI::Xaml::DependencyObject^ target, double oldValue, double newValue);
// 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 OnFontSizePropertyChanged(Windows::UI::Xaml::DependencyObject ^ target, double oldValue, double newValue);
static void UpdateFontFamilyAndSize(Windows::UI::Xaml::DependencyObject^ target);
static void UpdateFontFamilyAndSize(Windows::UI::Xaml::DependencyObject ^ target);
static std::unordered_map<std::wstring, std::wstring> GetTokenToReadableNameMap();
static std::unordered_map<std::wstring, std::wstring> GetTokenToReadableNameMap();
private:
LocalizationService();
static LocalizationService ^ s_singletonInstance;
static LocalizationService^ s_singletonInstance;
Windows::Globalization::Fonts::LanguageFontGroup^ m_fontGroup;
Platform::String^ m_language;
Windows::UI::Xaml::FlowDirection m_flowDirection;
bool m_overrideFontApiValues;
Platform::String^ m_fontFamilyOverride;
Windows::UI::Text::FontWeight m_fontWeightOverride;
double m_uiTextFontScaleFactorOverride;
double m_uiCaptionFontScaleFactorOverride;
};
}}
Windows::Globalization::Fonts::LanguageFontGroup ^ m_fontGroup;
Platform::String ^ m_language;
Windows::UI::Xaml::FlowDirection m_flowDirection;
bool m_overrideFontApiValues;
Platform::String ^ m_fontFamilyOverride;
bool m_isLanguageOverrided;
Windows::UI::Text::FontWeight m_fontWeightOverride;
double m_uiTextFontScaleFactorOverride;
double m_uiCaptionFontScaleFactorOverride;
};
}
}

View File

@@ -18,8 +18,8 @@ namespace CalculatorApp
int result = 0;
// Use DecimalFormatter as it respects the locale and the user setting
Windows::Globalization::NumberFormatting::DecimalFormatter^ formatter;
formatter = CalculatorApp::Common::LocalizationService::GetRegionalSettingsAwareDecimalFormatter();
Windows::Globalization::NumberFormatting::DecimalFormatter ^ formatter;
formatter = LocalizationService::GetInstance()->GetRegionalSettingsAwareDecimalFormatter();
formatter->FractionDigits = 0;
formatter->IsDecimalPointAlwaysDisplayed = false;
@@ -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(
m_resolvedName.c_str(),
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)&currencyTrailingDigits,
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(
m_resolvedName.c_str(),
LOCALE_IPOSSYMPRECEDES | LOCALE_RETURN_NUMBER,
(LPWSTR)&currencySymbolPrecedence,
sizeof(currencySymbolPrecedence) / sizeof(WCHAR));
@@ -112,24 +104,22 @@ 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(m_resolvedName.c_str(), 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,
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
::GetLocaleInfoEx(
m_resolvedName.c_str(),
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
// The LOCALE_IFIRSTDAYOFWEEK integer value varies from 0, 1, .. 6 for Monday, Tuesday, ... Sunday
// DayOfWeek enum value varies from 0, 1, .. 6 for Sunday, Monday, ... Saturday
// Hence, DayOfWeek = (valueof(LOCALE_IFIRSTDAYOFWEEK) + 1) % 7
m_firstDayOfWeek = static_cast<Windows::Globalization::DayOfWeek>((_wtoi(day) + 1) % 7); // static cast int to DayOfWeek enum
m_firstDayOfWeek = static_cast<Windows::Globalization::DayOfWeek>((_wtoi(day) + 1) % 7); // static cast int to DayOfWeek enum
}
public:
@@ -149,7 +139,7 @@ namespace CalculatorApp
return localizationSettings;
}
Platform::String^ GetLocaleName() const
Platform::String ^ GetLocaleName() const
{
return ref new Platform::String(m_resolvedName.c_str());
}
@@ -179,7 +169,7 @@ namespace CalculatorApp
}
}
Platform::String^ GetEnglishValueFromLocalizedDigits(const std::wstring& localizedString) const
Platform::String ^ GetEnglishValueFromLocalizedDigits(const std::wstring& localizedString) const
{
if (m_resolvedName == L"en-US")
{
@@ -201,7 +191,7 @@ namespace CalculatorApp
{
ch = j.ToString()->Data()[0];
break;
//ch = val - L'0';
// ch = val - L'0';
}
}
}
@@ -305,7 +295,7 @@ namespace CalculatorApp
}
}
Platform::String^ GetCalendarIdentifier() const
Platform::String ^ GetCalendarIdentifier() const
{
return m_calendarIdentifier;
}
@@ -378,7 +368,7 @@ namespace CalculatorApp
// Hexadecimal characters are not currently localized
static constexpr std::array<wchar_t, 6> s_hexSymbols{ L'A', L'B', L'C', L'D', L'E', L'F' };
std::wstring m_listSeparator;
Platform::String^ m_calendarIdentifier;
Platform::String ^ m_calendarIdentifier;
Windows::Globalization::DayOfWeek m_firstDayOfWeek;
int m_currencySymbolPrecedence;
std::wstring m_resolvedName;

View File

@@ -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)

View File

@@ -7,7 +7,8 @@ namespace CalculatorApp
{
namespace Common
{
public enum class MyVirtualKey
public
enum class MyVirtualKey
{
None = 0,
LeftButton = 1,

View File

@@ -24,18 +24,18 @@ static constexpr bool POSITIVE_ONLY = false;
// The order of items in this list determines the order of groups in the menu.
static constexpr array<const NavCategoryGroupInitializer, 2> s_categoryGroupManifest = {
NavCategoryGroupInitializer { CategoryGroupType::Calculator, L"CalculatorModeTextCaps", L"CalculatorModeText", L"CalculatorModePluralText"},
NavCategoryGroupInitializer { CategoryGroupType::Converter, L"ConverterModeTextCaps", L"ConverterModeText", L"ConverterModePluralText" }
NavCategoryGroupInitializer{ CategoryGroupType::Calculator, L"CalculatorModeTextCaps", L"CalculatorModeText", L"CalculatorModePluralText" },
NavCategoryGroupInitializer{ CategoryGroupType::Converter, L"ConverterModeTextCaps", L"ConverterModeText", L"ConverterModePluralText" }
};
// vvv THESE CONSTANTS SHOULD NEVER CHANGE vvv
static constexpr int STANDARD_ID = 0;
static constexpr int SCIENTIFIC_ID = 1;
static constexpr int PROGRAMMER_ID = 2;
static constexpr int DATE_ID = 3;
static constexpr int VOLUME_ID = 4;
static constexpr int LENGTH_ID = 5;
static constexpr int WEIGHT_ID = 6;
static constexpr int STANDARD_ID = 0;
static constexpr int SCIENTIFIC_ID = 1;
static constexpr int PROGRAMMER_ID = 2;
static constexpr int DATE_ID = 3;
static constexpr int VOLUME_ID = 4;
static constexpr int LENGTH_ID = 5;
static constexpr int WEIGHT_ID = 6;
static constexpr int TEMPERATURE_ID = 7;
static constexpr int ENERGY_ID = 8;
static constexpr int AREA_ID = 9;
@@ -74,30 +74,23 @@ static constexpr array<const NavCategoryInitializer, 18> s_categoryManifest = {
// 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.
ViewMode NavCategory::Deserialize(Platform::Object^ obj)
ViewMode NavCategory::Deserialize(Platform::Object ^ obj)
{
// If we cast directly to ViewMode we will fail
// because we technically store an int.
// Need to cast to int, then ViewMode.
auto boxed = dynamic_cast<Box<int>^>(obj);
auto boxed = dynamic_cast<Box<int> ^>(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;
});
@@ -112,11 +105,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();
}
@@ -146,65 +136,44 @@ 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;
});
return iter != s_categoryManifest.end();
}
String^ NavCategory::GetFriendlyName(ViewMode mode)
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)
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)
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
@@ -218,9 +187,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)
{
@@ -231,18 +198,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++;
@@ -252,38 +215,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()
@@ -300,36 +253,33 @@ 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;
auto resProvider = AppResourceProvider::GetInstance();
String^ headerResourceKey = StringReference(groupInitializer.headerResourceKey);
String^ modeResourceKey = StringReference(groupInitializer.modeResourceKey);
String^ automationResourceKey = StringReference(groupInitializer.automationResourceKey);
String ^ headerResourceKey = StringReference(groupInitializer.headerResourceKey);
String ^ modeResourceKey = StringReference(groupInitializer.modeResourceKey);
String ^ automationResourceKey = StringReference(groupInitializer.automationResourceKey);
m_Name = resProvider.GetResourceString(headerResourceKey);
String^ groupMode = resProvider.GetResourceString(modeResourceKey);
String^ automationName = resProvider.GetResourceString(automationResourceKey);
String ^ groupMode = resProvider.GetResourceString(modeResourceKey);
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());
String ^ navCategoryHeaderAutomationNameFormat = resProvider.GetResourceString(L"NavCategoryHeader_AutomationNameFormat");
m_AutomationName =
ref new String(LocalizationStringUtil::GetLocalizedString(navCategoryHeaderAutomationNameFormat->Data(), automationName->Data()).c_str());
String^ navCategoryItemAutomationNameFormat = resProvider.GetResourceString(L"NavCategoryItem_AutomationNameFormat");
String ^ navCategoryItemAutomationNameFormat = resProvider.GetResourceString(L"NavCategoryItem_AutomationNameFormat");
for (const NavCategoryInitializer& categoryInitializer : s_categoryManifest)
{
if (categoryInitializer.groupType == groupInitializer.type)
{
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 ^ 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());
m_Categories->Append(ref new NavCategory(
categoryName,
@@ -343,20 +293,20 @@ NavCategoryGroup::NavCategoryGroup(const NavCategoryGroupInitializer& groupIniti
}
}
IObservableVector<NavCategoryGroup^>^ NavCategoryGroup::CreateMenuOptions()
IObservableVector<NavCategoryGroup ^> ^ NavCategoryGroup::CreateMenuOptions()
{
auto menuOptions = ref new Vector<NavCategoryGroup^>();
auto menuOptions = ref new Vector<NavCategoryGroup ^>();
menuOptions->Append(CreateCalculatorCategory());
menuOptions->Append(CreateConverterCategory());
return menuOptions;
}
NavCategoryGroup^ NavCategoryGroup::CreateCalculatorCategory()
NavCategoryGroup ^ NavCategoryGroup::CreateCalculatorCategory()
{
return ref new NavCategoryGroup(s_categoryGroupManifest.at(0));
}
NavCategoryGroup^ NavCategoryGroup::CreateConverterCategory()
NavCategoryGroup ^ NavCategoryGroup::CreateConverterCategory()
{
return ref new NavCategoryGroup(s_categoryGroupManifest.at(1));
}
@@ -364,24 +314,18 @@ 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;
});
return initializers;
}
String^ NavCategoryGroup::GetHeaderResourceKey(CategoryGroupType type)
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;
}

View File

@@ -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,
@@ -47,81 +48,84 @@ namespace CalculatorApp
Graphing = 17
};
public enum class CategoryGroupType
public
enum class CategoryGroupType
{
None = -1,
Calculator = 0,
Converter = 1
};
private struct NavCategoryInitializer
private
struct NavCategoryInitializer
{
constexpr NavCategoryInitializer(
ViewMode mode,
int id,
wchar_t const * name,
wchar_t const * nameKey,
wchar_t const * glyph,
wchar_t const* name,
wchar_t const* nameKey,
wchar_t const* glyph,
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;
const wchar_t * const friendlyName;
const wchar_t * const nameResourceKey;
const wchar_t * const glyph;
const wchar_t* const friendlyName;
const wchar_t* const nameResourceKey;
const wchar_t* const glyph;
const CategoryGroupType groupType;
const MyVirtualKey virtualKey;
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;
const wchar_t *modeResourceKey;
const wchar_t *automationResourceKey;
const wchar_t* headerResourceKey;
const wchar_t* modeResourceKey;
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
property int Position
{
int get() { return m_position; }
int get()
{
return m_position;
}
}
property ViewMode Mode
@@ -132,24 +136,13 @@ namespace CalculatorApp
}
}
property Platform::String^ AutomationId
{
Platform::String^ get()
{
return m_viewMode.ToString();
}
}
property Platform::String
^ AutomationId { Platform::String ^ get() { return m_viewMode.ToString(); } }
property Platform::String^ AccessKey
{
Platform::String^ get()
{
return m_accessKey;
}
}
property Platform::String
^ AccessKey { Platform::String ^ get() { return m_accessKey; } }
property bool SupportsNegative
property bool SupportsNegative
{
bool get()
{
@@ -159,8 +152,8 @@ namespace CalculatorApp
// For saving/restoring last mode used.
static int Serialize(ViewMode mode);
static ViewMode Deserialize(Platform::Object^ obj);
static ViewMode GetViewModeForFriendlyName(Platform::String^ name);
static ViewMode Deserialize(Platform::Object ^ obj);
static ViewMode GetViewModeForFriendlyName(Platform::String ^ name);
static bool IsValidViewMode(ViewMode mode);
static bool IsCalculatorViewMode(ViewMode mode);
@@ -168,8 +161,8 @@ namespace CalculatorApp
static bool IsDateCalculatorViewMode(ViewMode mode);
static bool IsConverterViewMode(ViewMode mode);
static Platform::String^ GetFriendlyName(ViewMode mode);
static Platform::String^ GetNameResourceKey(ViewMode mode);
static Platform::String ^ GetFriendlyName(ViewMode mode);
static Platform::String ^ GetNameResourceKey(ViewMode mode);
static CategoryGroupType GetGroupType(ViewMode mode);
// GetIndex is 0-based, GetPosition is 1-based
@@ -180,15 +173,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);
}
@@ -199,33 +198,30 @@ namespace CalculatorApp
static bool IsModeInCategoryGroup(ViewMode mode, CategoryGroupType groupType);
ViewMode m_viewMode;
Platform::String^ m_name;
Platform::String^ m_automationName;
Platform::String^ m_glyph;
Platform::String^ m_accessKey;
Platform::String^ m_mode;
Platform::String ^ m_name;
Platform::String ^ m_automationName;
Platform::String ^ m_glyph;
Platform::String ^ m_accessKey;
Platform::String ^ m_mode;
int m_position;
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);
OBSERVABLE_PROPERTY_R(Platform::String^, AutomationName);
OBSERVABLE_PROPERTY_R(Platform::String ^, Name);
OBSERVABLE_PROPERTY_R(Platform::String ^, AutomationName);
OBSERVABLE_PROPERTY_R(CategoryGroupType, GroupType);
OBSERVABLE_PROPERTY_R(Windows::Foundation::Collections::IObservableVector<NavCategory^>^, Categories);
OBSERVABLE_PROPERTY_R(Windows::Foundation::Collections::IObservableVector<NavCategory ^> ^, Categories);
static Windows::Foundation::Collections::IObservableVector<NavCategoryGroup^>^ CreateMenuOptions();
static Windows::Foundation::Collections::IObservableVector<NavCategoryGroup ^> ^ CreateMenuOptions();
static Platform::String^ GetHeaderResourceKey(CategoryGroupType type);
static Platform::String ^ GetHeaderResourceKey(CategoryGroupType type);
internal:
static NavCategoryGroup^ CreateCalculatorCategory();
static NavCategoryGroup^ CreateConverterCategory();
internal : static NavCategoryGroup ^ CreateCalculatorCategory();
static NavCategoryGroup ^ CreateConverterCategory();
private:
NavCategoryGroup(const NavCategoryGroupInitializer& groupInitializer);

View File

@@ -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()
@@ -23,14 +22,13 @@ NetworkManager::~NetworkManager()
NetworkAccessBehavior NetworkManager::GetNetworkAccessBehavior()
{
NetworkAccessBehavior behavior = NetworkAccessBehavior::Offline;
ConnectionProfile^ connectionProfile = NetworkInformation::GetInternetConnectionProfile();
ConnectionProfile ^ connectionProfile = NetworkInformation::GetInternetConnectionProfile();
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();
ConnectionCost ^ connectionCost = connectionProfile->GetConnectionCost();
behavior = ConvertCostInfoToBehavior(connectionCost);
}
}
@@ -38,16 +36,15 @@ NetworkAccessBehavior NetworkManager::GetNetworkAccessBehavior()
return behavior;
}
void NetworkManager::OnNetworkStatusChange(_In_ Object^ /*sender*/)
void NetworkManager::OnNetworkStatusChange(_In_ Object ^ /*sender*/)
{
NetworkBehaviorChanged(GetNetworkAccessBehavior());
}
// 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)
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;

View File

@@ -5,29 +5,32 @@
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();
static NetworkAccessBehavior GetNetworkAccessBehavior();
event NetworkBehaviorChangedHandler^ NetworkBehaviorChanged;
event NetworkBehaviorChangedHandler ^ NetworkBehaviorChanged;
private:
~NetworkManager();
void OnNetworkStatusChange(_In_ Platform::Object^ sender);
static NetworkAccessBehavior ConvertCostInfoToBehavior(_In_ Windows::Networking::Connectivity::ConnectionCost^ connectionCost);
void OnNetworkStatusChange(_In_ Platform::Object ^ sender);
static NetworkAccessBehavior ConvertCostInfoToBehavior(_In_ Windows::Networking::Connectivity::ConnectionCost ^ connectionCost);
private:
Windows::Foundation::EventRegistrationToken m_NetworkStatusChangedToken;

View File

@@ -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()

View File

@@ -21,74 +21,72 @@ 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.
constexpr auto EVENT_NAME_DEBUG = L"Debug";
constexpr auto EVENT_NAME_ERROR = L"ErrorMessage";
constexpr auto EVENT_NAME_APP_PRELAUNCHED_BY_SYSTEM = L"AppPrelaunchedBySystem";
constexpr auto EVENT_NAME_PRELAUNCHED_APP_ACTIVATED_BY_USER = L"PrelaunchedAppActivatedByUser";
constexpr auto EVENT_NAME_APP_LAUNCH_BEGIN = L"AppLaunchBegin";
constexpr auto EVENT_NAME_APP_LAUNCH_END = L"AppLaunchEnd";
constexpr auto EVENT_NAME_APP_RESUME_END = L"AppResumeEnd";
constexpr auto EVENT_NAME_PREVIOUS_STATE_WINDOW_ON_CREATION = L"PreviousStateOnWindowCreation";
constexpr auto EVENT_NAME_SIZE_ON_SUSPENSION = L"CalculatorSizeOnSuspension";
constexpr auto EVENT_NAME_CALCULATOR_VIEWED_IN_SESSION = L"CalculatorViewedInSession";
constexpr auto EVENT_NAME_DATE_CALCULATOR_VIEWED_IN_SESSION = L"DateCalculatorViewedInSession";
constexpr auto EVENT_NAME_CONVERTER_VIEWED_IN_SESSION = L"ConverterViewedInSession";
constexpr auto EVENT_NAME_MODE_CHANGE_BEGIN = L"ModeChangeBegin";
constexpr auto EVENT_NAME_MODE_CHANGE_END = L"ModeChangeEnd";
constexpr auto EVENT_NAME_HISTORY_BODY_OPENED = L"HistoryBodyOpened";
constexpr auto EVENT_NAME_HISTORY_ITEM_LOAD_BEGIN = L"HistoryItemLoadBegin";
constexpr auto EVENT_NAME_HISTORY_ITEM_LOAD_END = L"HistoryItemLoadEnd";
constexpr auto EVENT_NAME_HISTORY_FLYOUT_OPEN_BEGIN = L"HistoryFlyoutOpenBegin";
constexpr auto EVENT_NAME_HISTORY_FLYOUT_OPEN_END = L"HistoryFlyoutOpenEnd";
constexpr auto EVENT_NAME_NEW_WINDOW_CREATION_BEGIN = L"NewWindowCreationBegin";
constexpr auto EVENT_NAME_NEW_WINDOW_CREATION_END = L"NewWindowCreationEnd";
constexpr auto EVENT_NAME_HISTORY_CLEAR = L"HistoryClearBegin";
constexpr auto EVENT_NAME_MULTIPLE_MEMORY_USED = L"MultipleMemoryUsed";
constexpr auto EVENT_NAME_SINGLE_MEMORY_USED = L"SingleMemoryUsed";
constexpr auto EVENT_NAME_SHARED_MEMORY_USED = L"SharedMemoryUsed";
constexpr auto EVENT_NAME_MEMORY_BODY_OPENED = L"MemoryBodyOpened";
constexpr auto EVENT_NAME_MEMORY_FLYOUT_OPEN_BEGIN = L"MemoryFlyoutOpenBegin";
constexpr auto EVENT_NAME_MEMORY_FLYOUT_OPEN_END = L"MemoryFlyoutOpenEnd";
constexpr auto EVENT_NAME_MEMORY_CLEAR_ALL = L"MemoryClearAll";
constexpr auto EVENT_NAME_INVALID_PASTED_INPUT_OCCURRED = L"InvalidPastedInputOccurred";
constexpr auto EVENT_NAME_VALID_INPUT_PASTED = L"ValidInputPasted";
constexpr auto EVENT_NAME_BITFLIP_PANE_CLICKED = L"BitFlipPaneClicked";
constexpr auto EVENT_NAME_BITFLIP_BUTTONS_USED = L"BitFlipToggleButtonUsed";
constexpr auto EVENT_NAME_ANGLE_BUTTONS_USED = L"AngleButtonUsedInSession";
constexpr auto EVENT_NAME_HYP_BUTTON_USED = L"HypButtonUsedInSession";
constexpr auto EVENT_NAME_FUNCTION_USAGE = L"FunctionUsageInSession";
constexpr auto EVENT_NAME_BITLENGTH_BUTTON_USED = L"BitLengthButtonUsed";
constexpr auto EVENT_NAME_RADIX_BUTTON_USED = L"RadixButtonUsed";
constexpr auto EVENT_NAME_MAX_WINDOW_COUNT = L"MaxWindowCountInSession";
constexpr auto EVENT_NAME_WINDOW_LAUNCHED_PROTOCOL = L"WindowActivatedThroughProtocol";
constexpr auto EVENT_NAME_WINDOW_LAUNCHED_TILESEARCH = L"WindowLaunchedThroughTile";
constexpr auto EVENT_NAME_DATE_DIFFERENCE_USED = L"DateDifferenceModeUsed";
constexpr auto EVENT_NAME_DATE_ADD_SUBTRACT_USED = L"DateAddSubtractModeUsed";
constexpr auto EVENT_NAME_DATE_DIFFERENCE_FOUND = L"DateDifferenceFound";
constexpr auto EVENT_NAME_HIDE_IF_SHOWN = L"HideIfShown";
constexpr auto EVENT_NAME_ABOUT_FLYOUT_OPENED = L"AboutFlyoutOpened";
constexpr auto EVENT_NAME_NAV_BAR_OPENED = L"NavBarOpened";
constexpr auto EVENT_NAME_CORE_WINDOW_WAS_NULL = L"CoreWindowWasNull";
constexpr auto EVENT_NAME_DEBUG = L"Debug";
constexpr auto EVENT_NAME_ERROR = L"ErrorMessage";
constexpr auto EVENT_NAME_APP_PRELAUNCHED_BY_SYSTEM = L"AppPrelaunchedBySystem";
constexpr auto EVENT_NAME_PRELAUNCHED_APP_ACTIVATED_BY_USER = L"PrelaunchedAppActivatedByUser";
constexpr auto EVENT_NAME_APP_LAUNCH_BEGIN = L"AppLaunchBegin";
constexpr auto EVENT_NAME_APP_LAUNCH_END = L"AppLaunchEnd";
constexpr auto EVENT_NAME_APP_RESUME_END = L"AppResumeEnd";
constexpr auto EVENT_NAME_PREVIOUS_STATE_WINDOW_ON_CREATION = L"PreviousStateOnWindowCreation";
constexpr auto EVENT_NAME_SIZE_ON_SUSPENSION = L"CalculatorSizeOnSuspension";
constexpr auto EVENT_NAME_CALCULATOR_VIEWED_IN_SESSION = L"CalculatorViewedInSession";
constexpr auto EVENT_NAME_DATE_CALCULATOR_VIEWED_IN_SESSION = L"DateCalculatorViewedInSession";
constexpr auto EVENT_NAME_CONVERTER_VIEWED_IN_SESSION = L"ConverterViewedInSession";
constexpr auto EVENT_NAME_MODE_CHANGE_BEGIN = L"ModeChangeBegin";
constexpr auto EVENT_NAME_MODE_CHANGE_END = L"ModeChangeEnd";
constexpr auto EVENT_NAME_HISTORY_BODY_OPENED = L"HistoryBodyOpened";
constexpr auto EVENT_NAME_HISTORY_ITEM_LOAD_BEGIN = L"HistoryItemLoadBegin";
constexpr auto EVENT_NAME_HISTORY_ITEM_LOAD_END = L"HistoryItemLoadEnd";
constexpr auto EVENT_NAME_HISTORY_FLYOUT_OPEN_BEGIN = L"HistoryFlyoutOpenBegin";
constexpr auto EVENT_NAME_HISTORY_FLYOUT_OPEN_END = L"HistoryFlyoutOpenEnd";
constexpr auto EVENT_NAME_NEW_WINDOW_CREATION_BEGIN = L"NewWindowCreationBegin";
constexpr auto EVENT_NAME_NEW_WINDOW_CREATION_END = L"NewWindowCreationEnd";
constexpr auto EVENT_NAME_HISTORY_CLEAR = L"HistoryClearBegin";
constexpr auto EVENT_NAME_MULTIPLE_MEMORY_USED = L"MultipleMemoryUsed";
constexpr auto EVENT_NAME_SINGLE_MEMORY_USED = L"SingleMemoryUsed";
constexpr auto EVENT_NAME_SHARED_MEMORY_USED = L"SharedMemoryUsed";
constexpr auto EVENT_NAME_MEMORY_BODY_OPENED = L"MemoryBodyOpened";
constexpr auto EVENT_NAME_MEMORY_FLYOUT_OPEN_BEGIN = L"MemoryFlyoutOpenBegin";
constexpr auto EVENT_NAME_MEMORY_FLYOUT_OPEN_END = L"MemoryFlyoutOpenEnd";
constexpr auto EVENT_NAME_MEMORY_CLEAR_ALL = L"MemoryClearAll";
constexpr auto EVENT_NAME_INVALID_PASTED_INPUT_OCCURRED = L"InvalidPastedInputOccurred";
constexpr auto EVENT_NAME_VALID_INPUT_PASTED = L"ValidInputPasted";
constexpr auto EVENT_NAME_BITFLIP_PANE_CLICKED = L"BitFlipPaneClicked";
constexpr auto EVENT_NAME_BITFLIP_BUTTONS_USED = L"BitFlipToggleButtonUsed";
constexpr auto EVENT_NAME_ANGLE_BUTTONS_USED = L"AngleButtonUsedInSession";
constexpr auto EVENT_NAME_HYP_BUTTON_USED = L"HypButtonUsedInSession";
constexpr auto EVENT_NAME_FUNCTION_USAGE = L"FunctionUsageInSession";
constexpr auto EVENT_NAME_BITLENGTH_BUTTON_USED = L"BitLengthButtonUsed";
constexpr auto EVENT_NAME_RADIX_BUTTON_USED = L"RadixButtonUsed";
constexpr auto EVENT_NAME_MAX_WINDOW_COUNT = L"MaxWindowCountInSession";
constexpr auto EVENT_NAME_WINDOW_LAUNCHED_PROTOCOL = L"WindowActivatedThroughProtocol";
constexpr auto EVENT_NAME_WINDOW_LAUNCHED_TILESEARCH = L"WindowLaunchedThroughTile";
constexpr auto EVENT_NAME_DATE_DIFFERENCE_USED = L"DateDifferenceModeUsed";
constexpr auto EVENT_NAME_DATE_ADD_SUBTRACT_USED = L"DateAddSubtractModeUsed";
constexpr auto EVENT_NAME_DATE_DIFFERENCE_FOUND = L"DateDifferenceFound";
constexpr auto EVENT_NAME_HIDE_IF_SHOWN = L"HideIfShown";
constexpr auto EVENT_NAME_ABOUT_FLYOUT_OPENED = L"AboutFlyoutOpened";
constexpr auto EVENT_NAME_NAV_BAR_OPENED = L"NavBarOpened";
constexpr auto EVENT_NAME_CORE_WINDOW_WAS_NULL = L"CoreWindowWasNull";
constexpr auto EVENT_NAME_EXCEPTION = L"Exception";
constexpr auto EVENT_NAME_EXCEPTION = L"Exception";
constexpr auto PDT_PRIVACY_DATA_TAG = L"PartA_PrivTags";
constexpr auto PDT_PRODUCT_AND_SERVICE_USAGE = 0x0000'0000'0200'0000u;
constexpr auto PDT_PRIVACY_DATA_TAG = L"PartA_PrivTags";
constexpr auto PDT_PRODUCT_AND_SERVICE_USAGE = 0x0000'0000'0200'0000u;
#ifdef SEND_TELEMETRY
// c.f. WINEVENT_KEYWORD_RESERVED_63-56 0xFF00000000000000 // Bits 63-56 - channel keywords
// c.f. WINEVENT_KEYWORD_* 0x00FF000000000000 // Bits 55-48 - system-reserved keywords
constexpr int64_t MICROSOFT_KEYWORD_CRITICAL_DATA = 0x0000800000000000; // Bit 47
constexpr int64_t MICROSOFT_KEYWORD_MEASURES = 0x0000400000000000; // Bit 46
constexpr int64_t MICROSOFT_KEYWORD_TELEMETRY = 0x0000200000000000; // Bit 45
constexpr int64_t MICROSOFT_KEYWORD_RESERVED_44 = 0x0000100000000000; // Bit 44 (reserved for future assignment)
constexpr int64_t MICROSOFT_KEYWORD_MEASURES = 0x0000400000000000; // Bit 46
constexpr int64_t MICROSOFT_KEYWORD_TELEMETRY = 0x0000200000000000; // Bit 45
constexpr int64_t MICROSOFT_KEYWORD_RESERVED_44 = 0x0000100000000000; // Bit 44 (reserved for future assignment)
#else
// define all Keyword options as 0 when we do not want to upload app telemetry
constexpr int64_t MICROSOFT_KEYWORD_CRITICAL_DATA = 0;
@@ -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);
@@ -687,9 +714,10 @@ namespace CalculatorApp
LogMeasureEvent(EVENT_NAME_EXCEPTION, fields);
}
void TraceLogger::LogPlatformException(wstring_view functionName, Platform::Exception^ e) const
void TraceLogger::LogPlatformException(wstring_view functionName, Platform::Exception ^ e) const
{
if (!GetTraceLoggingProviderEnabled()) return;
if (!GetTraceLoggingProviderEnabled())
return;
LoggingFields fields{};
fields.AddString(L"FunctionName", functionName);
@@ -733,11 +761,11 @@ namespace CalculatorApp
{
return s_programmerType[index];
}
//return "N/A"
// return "N/A"
return s_programmerType[0];
}
bool TraceLogger::GetIndex(int &index)
bool TraceLogger::GetIndex(int& index)
{
if (findIndex[index] > 0)
{
@@ -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);
}
}

View File

@@ -18,7 +18,10 @@ namespace CalculatorApp
public:
int count;
std::wstring funcName;
FuncLog() { count = 0; }
FuncLog()
{
count = 0;
}
FuncLog(std::wstring fName)
{
funcName = fName;
@@ -30,7 +33,7 @@ namespace CalculatorApp
{
public:
TraceLogger(_In_ TraceLogger const&) = delete;
TraceLogger const & operator= (_In_ TraceLogger const&) = delete;
TraceLogger const& operator=(_In_ TraceLogger const&) = delete;
~TraceLogger();
static TraceLogger& GetInstance();
bool GetTraceLoggingProviderEnabled() const;
@@ -93,21 +96,22 @@ 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;
void LogPlatformException(std::wstring_view functionName, _In_ Platform::Exception^ e) const;
void LogPlatformException(std::wstring_view functionName, _In_ Platform::Exception ^ e) const;
private:
// Create an instance of TraceLogger
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;
@@ -133,7 +137,7 @@ namespace CalculatorApp
bool isHypButtonLogged = false;
bool isAngleButtonInitialized = false;
unsigned int findIndex[maxFunctionSize] = { 0 };
bool GetIndex(int &index);
bool GetIndex(int& index);
std::wstring GetProgrammerType(int index);
size_t maxWindowCount = 0;
bool isAppLaunchBeginLogged = false;

View File

@@ -32,12 +32,12 @@ void Utils::IFTPlatformException(HRESULT hr)
{
if (FAILED(hr))
{
Platform::Exception^ exception = ref new Platform::Exception(hr);
Platform::Exception ^ exception = ref new Platform::Exception(hr);
throw(exception);
}
}
String^ Utils::GetStringValue(String^ input)
String ^ Utils::GetStringValue(String ^ input)
{
// Remove first and last " characters
if (input->Length() >= 3)
@@ -52,8 +52,7 @@ double Utils::GetDoubleFromWstring(wstring input)
{
wchar_t unWantedChars[] = { L' ', L',', 8234, 8235, 8236, 8237 };
wstring ws = RemoveUnwantedCharsFromWstring(input, unWantedChars, 6);
string inputString(ws.begin(), ws.end());
return ::atof(inputString.c_str());
return stod(ws);
}
// Returns windowId for the current view
@@ -70,20 +69,16 @@ int Utils::GetWindowId()
return windowId;
}
void Utils::RunOnUIThreadNonblocking(function<void()>&& function, _In_ CoreDispatcher^ currentDispatcher)
void Utils::RunOnUIThreadNonblocking(std::function<void()>&& function, _In_ CoreDispatcher ^ currentDispatcher)
{
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(); })));
}
}
// Returns if the last character of a wstring is the target wchar_t
bool Utils::IsLastCharacterTarget(_In_ wstring const &input, _In_ wchar_t target)
bool Utils::IsLastCharacterTarget(_In_ wstring const& input, _In_ wchar_t target)
{
return !input.empty() && input.back() == target;
}
@@ -98,9 +93,10 @@ wstring Utils::RemoveUnwantedCharsFromWstring(wstring input, wchar_t* unwantedCh
return input;
}
void Utils::SerializeCommandsAndTokens(_In_ shared_ptr<CalculatorVector <pair<wstring, int>>> const &tokens,
_In_ shared_ptr<CalculatorVector<shared_ptr<IExpressionCommand>>> const &commands,
DataWriter^ writer)
void Utils::SerializeCommandsAndTokens(
_In_ shared_ptr<CalculatorVector<pair<wstring, int>>> const& tokens,
_In_ shared_ptr<CalculatorVector<shared_ptr<IExpressionCommand>>> const& commands,
DataWriter ^ writer)
{
unsigned int commandsSize;
IFTPlatformException(commands->GetSize(&commandsSize));
@@ -136,7 +132,7 @@ void Utils::SerializeCommandsAndTokens(_In_ shared_ptr<CalculatorVector <pair<ws
}
}
const shared_ptr<CalculatorVector<shared_ptr<IExpressionCommand>>> Utils::DeserializeCommands(DataReader^ reader)
const shared_ptr<CalculatorVector<shared_ptr<IExpressionCommand>>> Utils::DeserializeCommands(DataReader ^ reader)
{
shared_ptr<CalculatorVector<shared_ptr<IExpressionCommand>>> commandVector = make_shared<CalculatorVector<shared_ptr<IExpressionCommand>>>();
auto commandVectorSize = reader->ReadUInt32();
@@ -153,9 +149,9 @@ const shared_ptr<CalculatorVector<shared_ptr<IExpressionCommand>>> Utils::Deseri
return commandVector;
}
const shared_ptr<CalculatorVector <pair<wstring, int>>> Utils::DeserializeTokens(DataReader^ reader)
const shared_ptr<CalculatorVector<pair<wstring, int>>> Utils::DeserializeTokens(DataReader ^ reader)
{
shared_ptr<CalculatorVector <pair<wstring, int>>> tokenVector = make_shared<CalculatorVector<pair<wstring, int>>>();
shared_ptr<CalculatorVector<pair<wstring, int>>> tokenVector = make_shared<CalculatorVector<pair<wstring, int>>>();
auto tokensSize = reader->ReadUInt32();
for (unsigned int i = 0; i < tokensSize; ++i)
@@ -195,14 +191,14 @@ bool Utils::IsDateTimeOlderThan(DateTime dateTime, const long long duration)
return dateTime.UniversalTime + duration < now.UniversalTime;
}
task<void> Utils::WriteFileToFolder(IStorageFolder^ folder, String^ fileName, String^ contents, CreationCollisionOption collisionOption)
task<void> Utils::WriteFileToFolder(IStorageFolder ^ folder, String ^ fileName, String ^ contents, CreationCollisionOption collisionOption)
{
if (folder == nullptr)
{
co_return;
}
StorageFile^ file = co_await folder->CreateFileAsync(fileName, collisionOption);
StorageFile ^ file = co_await folder->CreateFileAsync(fileName, collisionOption);
if (file == nullptr)
{
co_return;
@@ -211,20 +207,20 @@ task<void> Utils::WriteFileToFolder(IStorageFolder^ folder, String^ fileName, St
co_await FileIO::WriteTextAsync(file, contents);
}
task<String^> Utils::ReadFileFromFolder(IStorageFolder^ folder, String^ fileName)
task<String ^> Utils::ReadFileFromFolder(IStorageFolder ^ folder, String ^ fileName)
{
if (folder == nullptr)
{
co_return nullptr;
}
StorageFile^ file = co_await folder->GetFileAsync(fileName);
StorageFile ^ file = co_await folder->GetFileAsync(fileName);
if (file == nullptr)
{
co_return nullptr;
}
String^ contents = co_await FileIO::ReadTextAsync(file);
String ^ contents = co_await FileIO::ReadTextAsync(file);
co_return contents;
}

View File

@@ -10,92 +10,187 @@
// 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:
#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:
#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:
#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:
#define OBSERVABLE_PROPERTY_R(t, n)\
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:
#define OBSERVABLE_PROPERTY_R(t, n) \
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:
#define OBSERVABLE_PROPERTY_RW(t, n)\
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:
#define OBSERVABLE_PROPERTY_RW(t, n) \
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:
#define OBSERVABLE_NAMED_PROPERTY_R(t, n)\
OBSERVABLE_PROPERTY_R(t, n)\
internal: static property Platform::String^ n##PropertyName {\
Platform::String^ get() { return Platform::StringReference(L#n); }\
} public:
#define OBSERVABLE_NAMED_PROPERTY_R(t, n) \
OBSERVABLE_PROPERTY_R(t, n) \
internal: \
static property Platform::String ^ n##PropertyName \
{ \
Platform::String ^ get() { return Platform::StringReference(L#n); } \
} \
\
public:
#define OBSERVABLE_NAMED_PROPERTY_RW(t, n)\
OBSERVABLE_PROPERTY_RW(t, n)\
internal: static property Platform::String^ n##PropertyName {\
Platform::String^ get() { return Platform::StringReference(L#n); }\
} public:
#define OBSERVABLE_NAMED_PROPERTY_RW(t, n) \
OBSERVABLE_PROPERTY_RW(t, n) \
internal: \
static property Platform::String ^ n##PropertyName \
{ \
Platform::String ^ get() { return Platform::StringReference(L#n); } \
} \
\
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) {\
PropertyChanged(this, ref new Windows::UI::Xaml::Data::PropertyChangedEventArgs(p));\
c(p);\
} public:
#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:
#else
#define OBSERVABLE_OBJECT_CALLBACK(c) virtual event Windows::UI::Xaml::Data::PropertyChangedEventHandler^ PropertyChanged;\
internal: void RaisePropertyChanged(Platform::String^ p) {\
c(p);\
} public:
#define OBSERVABLE_OBJECT_CALLBACK(c) \
virtual event Windows::UI::Xaml::Data::PropertyChangedEventHandler ^ PropertyChanged; \
internal: \
void RaisePropertyChanged(Platform::String ^ p) \
{ \
c(p); \
} \
\
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:
#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:
// Utilities for DependencyProperties
namespace Utils
@@ -115,13 +210,13 @@ namespace Utils
};
template <typename T>
struct RemoveHat<T^>
struct RemoveHat<T ^>
{
typedef T type;
};
template <typename T>
typename std::enable_if<IsRefClass<T>::value, T^>::type MakeDefault()
typename std::enable_if<IsRefClass<T>::value, T ^>::type MakeDefault()
{
return nullptr;
}
@@ -284,18 +379,19 @@ namespace Utils
}
void IFTPlatformException(HRESULT hr);
Platform::String^ GetStringValue(Platform::String^ input);
bool IsLastCharacterTarget(std::wstring const &input, wchar_t target);
Platform::String ^ GetStringValue(Platform::String ^ input);
bool IsLastCharacterTarget(std::wstring const& input, wchar_t target);
std::wstring RemoveUnwantedCharsFromWstring(std::wstring inputString, wchar_t* unwantedChars, unsigned int size);
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,
_In_ std::shared_ptr<CalculatorVector<std::shared_ptr<IExpressionCommand>>> const &commands,
Windows::Storage::Streams::DataWriter^ writer);
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,
_In_ std::shared_ptr<CalculatorVector<std::shared_ptr<IExpressionCommand>>> const& commands,
Windows::Storage::Streams::DataWriter ^ writer);
const std::shared_ptr<CalculatorVector<std::shared_ptr<IExpressionCommand>>> DeserializeCommands(Windows::Storage::Streams::DataReader^ reader);
const std::shared_ptr<CalculatorVector <std::pair<std::wstring, int>>> DeserializeTokens(Windows::Storage::Streams::DataReader^ reader);
const std::shared_ptr<CalculatorVector<std::shared_ptr<IExpressionCommand>>> DeserializeCommands(Windows::Storage::Streams::DataReader ^ reader);
const std::shared_ptr<CalculatorVector<std::pair<std::wstring, int>>> DeserializeTokens(Windows::Storage::Streams::DataReader ^ reader);
Windows::Foundation::DateTime GetUniversalSystemTime();
bool IsDateTimeOlderThan(Windows::Foundation::DateTime dateTime, const long long duration);
@@ -314,119 +410,295 @@ namespace Utils
}
// 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:
#define DEPENDENCY_PROPERTY_OWNER(owner) \
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; }\
}\
private: static Windows::UI::Xaml::DependencyProperty^ Initialize##name##Property() {\
return Utils::RegisterDependencyProperty<DependencyPropertiesOwner, type>(L#name); } public:
#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; \
} \
} \
\
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; }\
}\
private: static Windows::UI::Xaml::DependencyProperty^ Initialize##name##Property() {\
return Utils::RegisterDependencyProperty<DependencyPropertiesOwner, type>(L#name, defaultValue); } 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; \
} \
} \
\
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; }\
}\
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:
#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; \
} \
} \
\
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:
#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; }\
}\
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:
#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; \
} \
} \
\
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:
// 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; }\
}\
private: static Windows::UI::Xaml::DependencyProperty^ Initialize##name##Property() {\
return Utils::RegisterDependencyPropertyAttached<DependencyPropertiesOwner, type>(L#name); } public:
#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; \
} \
} \
\
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; }\
}\
private: static Windows::UI::Xaml::DependencyProperty^ Initialize##name##Property() {\
return Utils::RegisterDependencyPropertyAttached<DependencyPropertiesOwner, type>(L#name, defaultValue); } 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; \
} \
} \
\
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; }\
}\
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_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; \
} \
} \
\
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; }\
}\
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:
#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; \
} \
} \
\
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
{
template <typename T>
T from_cx(Platform::Object^ from)
T from_cx(Platform::Object ^ from)
{
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;
}

View File

@@ -3,81 +3,90 @@
#pragma once
namespace CalculatorApp { namespace Common
namespace CalculatorApp
{
public ref class ValidSelectedItemConverter sealed: public Windows::UI::Xaml::Data::IValueConverter
namespace Common
{
public:
ValidSelectedItemConverter()
{ }
private:
virtual Platform::Object^ Convert(
Platform::Object^ value,
Windows::UI::Xaml::Interop::TypeName /*targetType*/,
Platform::Object^ /*parameter*/,
Platform::String^ /*language*/) = Windows::UI::Xaml::Data::IValueConverter::Convert
public
ref class ValidSelectedItemConverter sealed : public Windows::UI::Xaml::Data::IValueConverter
{
// Pass through as we don't want to change the value from the source
return value;
}
virtual Platform::Object^ ConvertBack(
Platform::Object^ value,
Windows::UI::Xaml::Interop::TypeName /*targetType*/,
Platform::Object^ /*parameter*/,
Platform::String^ /*language*/) = Windows::UI::Xaml::Data::IValueConverter::ConvertBack
{
if (value)
public:
ValidSelectedItemConverter()
{
}
private:
virtual Platform::Object
^ Convert(
Platform::Object ^ value,
Windows::UI::Xaml::Interop::TypeName /*targetType*/,
Platform::Object ^ /*parameter*/,
Platform::String ^ /*language*/) = Windows::UI::Xaml::Data::IValueConverter::Convert
{
// Pass through as we don't want to change the value from the source
return value;
}
// Stop the binding if the object is nullptr
return Windows::UI::Xaml::DependencyProperty::UnsetValue;
}
};
public ref class ValidSelectedIndexConverter sealed: public Windows::UI::Xaml::Data::IValueConverter
{
public:
ValidSelectedIndexConverter()
{ }
private:
virtual Platform::Object^ Convert(
Platform::Object^ value,
Windows::UI::Xaml::Interop::TypeName /*targetType*/,
Platform::Object^ /*parameter*/,
Platform::String^ /*language*/) = Windows::UI::Xaml::Data::IValueConverter::Convert
{
// Pass through as we don't want to change the value from the source
return value;
}
virtual Platform::Object^ ConvertBack(
Platform::Object^ value,
Windows::UI::Xaml::Interop::TypeName /*targetType*/,
Platform::Object^ /*parameter*/,
Platform::String^ /*language*/) = Windows::UI::Xaml::Data::IValueConverter::ConvertBack
{
// The value to be valid has to be a boxed int32 value
// extract that value and ensure it is valid, ie >= 0
if (value)
virtual Platform::Object
^ ConvertBack(
Platform::Object ^ value,
Windows::UI::Xaml::Interop::TypeName /*targetType*/,
Platform::Object ^ /*parameter*/,
Platform::String ^ /*language*/) = Windows::UI::Xaml::Data::IValueConverter::ConvertBack
{
auto box = dynamic_cast<Windows::Foundation::IPropertyValue^>(value);
if (box && box->Type == Windows::Foundation::PropertyType::Int32)
if (value)
{
int index = box->GetInt32();
if (index >= 0)
return value;
}
// Stop the binding if the object is nullptr
return Windows::UI::Xaml::DependencyProperty::UnsetValue;
}
};
public
ref class ValidSelectedIndexConverter sealed : public Windows::UI::Xaml::Data::IValueConverter
{
public:
ValidSelectedIndexConverter()
{
}
private:
virtual Platform::Object
^ Convert(
Platform::Object ^ value,
Windows::UI::Xaml::Interop::TypeName /*targetType*/,
Platform::Object ^ /*parameter*/,
Platform::String ^ /*language*/) = Windows::UI::Xaml::Data::IValueConverter::Convert
{
// Pass through as we don't want to change the value from the source
return value;
}
virtual Platform::Object
^ ConvertBack(
Platform::Object ^ value,
Windows::UI::Xaml::Interop::TypeName /*targetType*/,
Platform::Object ^ /*parameter*/,
Platform::String ^ /*language*/) = Windows::UI::Xaml::Data::IValueConverter::ConvertBack
{
// The value to be valid has to be a boxed int32 value
// extract that value and ensure it is valid, ie >= 0
if (value)
{
auto box = dynamic_cast<Windows::Foundation::IPropertyValue ^>(value);
if (box && box->Type == Windows::Foundation::PropertyType::Int32)
{
return value;
int index = box->GetInt32();
if (index >= 0)
{
return value;
}
}
}
// The value is not valid therefore stop the binding right here
return Windows::UI::Xaml::DependencyProperty::UnsetValue;
}
// The value is not valid therefore stop the binding right here
return Windows::UI::Xaml::DependencyProperty::UnsetValue;
}
};
}}
};
}
}

View File

@@ -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 },
wstring_view{ L"CountryName", 11 },
wstring_view{ L"CurrencyCode", 12 },
wstring_view{ L"CurrencyName", 12 },
wstring_view{ L"CurrencySymbol", 14 }
};
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 } };
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,18 +87,29 @@ 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, const wchar_t * forcedResponseLanguage)
: 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)
if (forcedResponseLanguage != nullptr)
{
m_responseLanguage = GlobalizationPreferences::Languages->GetAt(0);
m_responseLanguage = ref new Platform::String(forcedResponseLanguage);
}
else
{
if (GlobalizationPreferences::Languages->Size > 0)
{
m_responseLanguage = GlobalizationPreferences::Languages->GetAt(0);
}
else
{
m_responseLanguage = L"en-US";
}
}
if (m_client != nullptr)
@@ -112,13 +118,14 @@ CurrencyDataLoader::CurrencyDataLoader(_In_ unique_ptr<ICurrencyHttpClient> clie
m_client->SetResponseLanguage(m_responseLanguage);
}
auto localizationService = LocalizationService::GetInstance();
if (CoreWindow::GetForCurrentThread() != nullptr)
{
// Must have a CoreWindow to access the resource context.
m_isRtlLanguage = LocalizationService::GetInstance()->IsRtlLayout();
m_isRtlLanguage = localizationService->IsRtlLayout();
}
m_ratioFormatter = LocalizationService::GetRegionalSettingsAwareDecimalFormatter();
m_ratioFormatter = localizationService->GetRegionalSettingsAwareDecimalFormatter();
m_ratioFormatter->IsGrouped = true;
m_ratioFormatter->IsDecimalPointAlwaysDisplayed = true;
m_ratioFormatter->FractionDigits = FORMATTER_DIGIT_COUNT;
@@ -141,11 +148,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,9 +190,8 @@ void CurrencyDataLoader::LoadData()
if (!LoadFinished())
{
create_task([this]() -> task<bool>
{
vector<function<task<bool>()>> loadFunctions = {
create_task([this]() -> task<bool> {
vector<function<future<bool>()>> loadFunctions = {
[this]() { return TryLoadDataFromCacheAsync(); },
[this]() { return TryLoadDataFromWebAsync(); },
};
@@ -204,11 +207,13 @@ void CurrencyDataLoader::LoadData()
}
co_return didLoad;
}).then([this](bool didLoad)
{
UpdateDisplayedTimestamp();
NotifyDataLoadFinished(didLoad);
}, task_continuation_context::use_current());
})
.then(
[this](bool didLoad) {
UpdateDisplayedTimestamp();
NotifyDataLoadFinished(didLoad);
},
task_continuation_context::use_current());
}
};
#pragma optimize("", on)
@@ -285,32 +290,24 @@ 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"");
}
#pragma optimize("", off) // Turn off optimizations to work around DevDiv 393321
task<bool> CurrencyDataLoader::TryLoadDataFromCacheAsync()
future<bool> CurrencyDataLoader::TryLoadDataFromCacheAsync()
{
try
{
@@ -324,8 +321,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();
}
@@ -337,7 +333,7 @@ task<bool> CurrencyDataLoader::TryLoadDataFromCacheAsync()
co_return loadComplete;
}
catch (Exception^ ex)
catch (Exception ^ ex)
{
TraceLogger::GetInstance().LogPlatformException(__FUNCTIONW__, ex);
co_return false;
@@ -353,7 +349,7 @@ task<bool> CurrencyDataLoader::TryLoadDataFromCacheAsync()
}
}
task<bool> CurrencyDataLoader::TryFinishLoadFromCacheAsync()
future<bool> CurrencyDataLoader::TryFinishLoadFromCacheAsync()
{
auto localSettings = ApplicationData::Current->LocalSettings;
if (localSettings == nullptr)
@@ -361,29 +357,24 @@ 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;
}
StorageFolder^ localCacheFolder = ApplicationData::Current->LocalCacheFolder;
StorageFolder ^ localCacheFolder = ApplicationData::Current->LocalCacheFolder;
if (localCacheFolder == nullptr)
{
co_return false;
}
String^ staticDataResponse = co_await Utils::ReadFileFromFolder(localCacheFolder, StaticDataFilename);
String^ allRatiosResponse = co_await Utils::ReadFileFromFolder(localCacheFolder, AllRatiosDataFilename);
String ^ staticDataResponse = co_await Utils::ReadFileFromFolder(localCacheFolder, StaticDataFilename);
String ^ allRatiosResponse = co_await Utils::ReadFileFromFolder(localCacheFolder, AllRatiosDataFilename);
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;
@@ -395,7 +386,7 @@ task<bool> CurrencyDataLoader::TryFinishLoadFromCacheAsync()
co_return true;
}
task<bool> CurrencyDataLoader::TryLoadDataFromWebAsync()
future<bool> CurrencyDataLoader::TryLoadDataFromWebAsync()
{
try
{
@@ -406,14 +397,13 @@ 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;
}
String^ staticDataResponse = co_await m_client->GetCurrencyMetadata();
String^ allRatiosResponse = co_await m_client->GetCurrencyRatios();
String ^ staticDataResponse = co_await m_client->GetCurrencyMetadata();
String ^ allRatiosResponse = co_await m_client->GetCurrencyRatios();
if (staticDataResponse == nullptr || allRatiosResponse == nullptr)
{
co_return false;
@@ -422,11 +412,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 +423,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;
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();
@@ -464,7 +443,7 @@ task<bool> CurrencyDataLoader::TryLoadDataFromWebAsync()
co_return true;
}
catch (Exception^ ex)
catch (Exception ^ ex)
{
TraceLogger::GetInstance().LogPlatformException(__FUNCTIONW__, ex);
co_return false;
@@ -480,7 +459,7 @@ task<bool> CurrencyDataLoader::TryLoadDataFromWebAsync()
}
}
task<bool> CurrencyDataLoader::TryLoadDataFromWebOverrideAsync()
future<bool> CurrencyDataLoader::TryLoadDataFromWebOverrideAsync()
{
m_meteredOverrideSet = true;
bool didLoad = co_await TryLoadDataFromWebAsync();
@@ -495,18 +474,17 @@ task<bool> CurrencyDataLoader::TryLoadDataFromWebOverrideAsync()
#pragma optimize("", on)
bool CurrencyDataLoader::TryParseWebResponses(
_In_ String^ staticDataJson,
_In_ String^ allRatiosJson,
_In_ String ^ staticDataJson,
_In_ String ^ allRatiosJson,
_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)
bool CurrencyDataLoader::TryParseStaticData(_In_ String ^ rawJson, _Inout_ vector<UCM::CurrencyStaticData>& staticData)
{
JsonArray^ data = nullptr;
JsonArray ^ data = nullptr;
if (!JsonArray::TryParse(rawJson, &data))
{
return false;
@@ -518,46 +496,46 @@ bool CurrencyDataLoader::TryParseStaticData(_In_ String^ rawJson, _Inout_ vector
wstring currencyName{ L"" };
wstring currencySymbol{ L"" };
vector<wstring*> values = {
&countryCode,
&countryName,
&currencyCode,
&currencyName,
&currencySymbol
};
vector<wstring*> values = { &countryCode, &countryName, &currencyCode, &currencyName, &currencySymbol };
assert(values.size() == STATIC_DATA_PROPERTIES.size());
staticData.resize(size_t{ data->Size });
for (unsigned int i = 0; i < data->Size; i++)
{
JsonObject^ obj = data->GetAt(i)->GetObject();
JsonObject ^ obj;
try
{
obj = data->GetAt(i)->GetObject();
}
catch (COMException ^ e)
{
if (e->HResult == E_ILLEGAL_METHOD_CALL)
{
continue;
}
else
{
throw;
}
}
for (size_t j = 0; j < values.size(); j++)
{
(*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;
}
bool CurrencyDataLoader::TryParseAllRatiosData(_In_ String^ rawJson, _Inout_ CurrencyRatioMap& allRatios)
bool CurrencyDataLoader::TryParseAllRatiosData(_In_ String ^ rawJson, _Inout_ CurrencyRatioMap& allRatios)
{
JsonArray^ data = nullptr;
JsonArray ^ data = nullptr;
if (!JsonArray::TryParse(rawJson, &data))
{
return false;
@@ -568,17 +546,28 @@ bool CurrencyDataLoader::TryParseAllRatiosData(_In_ String^ rawJson, _Inout_ Cur
allRatios.clear();
for (unsigned int i = 0; i < data->Size; i++)
{
JsonObject^ obj = data->GetAt(i)->GetObject();
JsonObject ^ obj;
try
{
obj = data->GetAt(i)->GetObject();
}
catch (COMException^ e)
{
if (e->HResult == E_ILLEGAL_METHOD_CALL)
{
continue;
}
else
{
throw;
}
}
// Rt is ratio, An is target currency ISO code.
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;
@@ -685,6 +674,23 @@ void CurrencyDataLoader::GuaranteeSelectedUnits()
isConversionTargetSet = true;
}
}
// If still not set for either source or target, just select the first currency in the list
if (!m_currencyUnits.empty())
{
if (!isConversionSourceSet)
{
m_currencyUnits[0].isConversionSource = true;
isConversionSourceSet = true;
}
if (!isConversionTargetSet)
{
m_currencyUnits[0].isConversionTarget = true;
isConversionTargetSet = true;
}
}
}
void CurrencyDataLoader::NotifyDataLoadFinished(bool didLoad)
@@ -702,7 +708,7 @@ void CurrencyDataLoader::NotifyDataLoadFinished(bool didLoad)
void CurrencyDataLoader::SaveLangCodeAndTimestamp()
{
ApplicationDataContainer^ localSettings = ApplicationData::Current->LocalSettings;
ApplicationDataContainer ^ localSettings = ApplicationData::Current->LocalSettings;
if (localSettings == nullptr)
{
return;
@@ -729,17 +735,13 @@ wstring CurrencyDataLoader::GetCurrencyTimestamp()
DateTime epoch{};
if (m_cacheTimestamp.UniversalTime != epoch.UniversalTime)
{
DateTimeFormatter^ dateFormatter = ref new DateTimeFormatter(L"{month.abbreviated} {day.integer}, {year.full}");
DateTimeFormatter ^ dateFormatter = ref new DateTimeFormatter(L"{month.abbreviated} {day.integer}, {year.full}");
wstring date = dateFormatter->Format(m_cacheTimestamp)->Data();
DateTimeFormatter^ timeFormatter = ref new DateTimeFormatter(L"shorttime");
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;
@@ -758,23 +760,25 @@ task<SelectedUnits> CurrencyDataLoader::GetDefaultFromToCurrency()
try
{
// Second, see if the current locale has preset defaults in DefaultFromToCurrency.json.
Uri^ fileUri = ref new Uri(StringReference(DEFAULT_FROM_TO_CURRENCY_FILE_URI));
StorageFile^ defaultFromToCurrencyFile = co_await StorageFile::GetFileFromApplicationUriAsync(fileUri);
Uri ^ fileUri = ref new Uri(StringReference(DEFAULT_FROM_TO_CURRENCY_FILE_URI));
StorageFile ^ defaultFromToCurrencyFile = co_await StorageFile::GetFileFromApplicationUriAsync(fileUri);
if (defaultFromToCurrencyFile != nullptr)
{
String^ fileContents = co_await FileIO::ReadTextAsync(defaultFromToCurrencyFile);
JsonObject^ fromToObject = JsonObject::Parse(fileContents);
JsonObject^ regionalDefaults = fromToObject->GetNamedObject(m_responseLanguage);
String ^ fileContents = co_await FileIO::ReadTextAsync(defaultFromToCurrencyFile);
JsonObject ^ fromToObject = JsonObject::Parse(fileContents);
JsonObject ^ regionalDefaults = fromToObject->GetNamedObject(m_responseLanguage);
// Get both values before assignment in-case either fails.
String^ selectedFrom = regionalDefaults->GetNamedString(StringReference(FROM_KEY));
String^ selectedTo = regionalDefaults->GetNamedString(StringReference(TO_KEY));
String ^ selectedFrom = regionalDefaults->GetNamedString(StringReference(FROM_KEY));
String ^ selectedTo = regionalDefaults->GetNamedString(StringReference(TO_KEY));
fromCurrency = selectedFrom->Data();
toCurrency = selectedTo->Data();
}
}
catch (...) {}
catch (...)
{
}
}
co_return make_pair(fromCurrency, toCurrency);
@@ -783,16 +787,16 @@ task<SelectedUnits> CurrencyDataLoader::GetDefaultFromToCurrency()
bool CurrencyDataLoader::TryGetLastUsedCurrenciesFromLocalSettings(_Out_ wstring* const fromCurrency, _Out_ wstring* const toCurrency)
{
String^ fromKey = UnitConverterResourceKeys::CurrencyUnitFromKey;
String^ toKey = UnitConverterResourceKeys::CurrencyUnitToKey;
ApplicationDataContainer^ localSettings = ApplicationData::Current->LocalSettings;
String ^ fromKey = UnitConverterResourceKeys::CurrencyUnitFromKey;
String ^ toKey = UnitConverterResourceKeys::CurrencyUnitToKey;
ApplicationDataContainer ^ localSettings = ApplicationData::Current->LocalSettings;
if (localSettings != nullptr && localSettings->Values != nullptr)
{
IPropertySet^ values = localSettings->Values;
IPropertySet ^ values = localSettings->Values;
if (values->HasKey(fromKey) && values->HasKey(toKey))
{
*fromCurrency = static_cast<String^>(values->Lookup(fromKey))->Data();
*toCurrency = static_cast<String^>(values->Lookup(toKey))->Data();
*fromCurrency = static_cast<String ^>(values->Lookup(fromKey))->Data();
*toCurrency = static_cast<String ^>(values->Lookup(toKey))->Data();
return true;
}
@@ -803,12 +807,12 @@ bool CurrencyDataLoader::TryGetLastUsedCurrenciesFromLocalSettings(_Out_ wstring
void CurrencyDataLoader::SaveSelectedUnitsToLocalSettings(_In_ const SelectedUnits& selectedUnits)
{
String^ fromKey = UnitConverterResourceKeys::CurrencyUnitFromKey;
String^ toKey = UnitConverterResourceKeys::CurrencyUnitToKey;
ApplicationDataContainer^ localSettings = ApplicationData::Current->LocalSettings;
String ^ fromKey = UnitConverterResourceKeys::CurrencyUnitFromKey;
String ^ toKey = UnitConverterResourceKeys::CurrencyUnitToKey;
ApplicationDataContainer ^ localSettings = ApplicationData::Current->LocalSettings;
if (localSettings != nullptr && localSettings->Values != nullptr)
{
IPropertySet^ values = localSettings->Values;
IPropertySet ^ values = localSettings->Values;
values->Insert(fromKey, StringReference(selectedUnits.first.c_str()));
values->Insert(toKey, StringReference(selectedUnits.second.c_str()));
}

View File

@@ -11,7 +11,8 @@ namespace CalculatorApp
{
namespace ViewModel
{
public enum class CurrencyLoadStatus
public
enum class CurrencyLoadStatus
{
NotLoaded = 0,
FailedToLoad = 1,
@@ -42,16 +43,18 @@ namespace CalculatorApp
struct CurrencyUnitMetadata
{
CurrencyUnitMetadata(const std::wstring& s) : symbol(s) {}
CurrencyUnitMetadata(const std::wstring& s)
: symbol(s)
{
}
const std::wstring symbol;
};
class CurrencyDataLoader : public UCM::IConverterDataLoader,
public UCM::ICurrencyConverterDataLoader
class CurrencyDataLoader : public UCM::IConverterDataLoader, public UCM::ICurrencyConverterDataLoader
{
public:
CurrencyDataLoader(_In_ std::unique_ptr<CalculatorApp::DataLoaders::ICurrencyHttpClient> client);
CurrencyDataLoader(_In_ std::unique_ptr<CalculatorApp::DataLoaders::ICurrencyHttpClient> client, const wchar_t* overrideLanguage = nullptr);
~CurrencyDataLoader();
bool LoadFinished();
@@ -69,12 +72,13 @@ namespace CalculatorApp
// ICurrencyConverterDataLoader
void SetViewModelCallback(const std::shared_ptr<UCM::IViewModelCurrencyCallback>& callback) override;
std::pair<std::wstring, std::wstring> GetCurrencySymbols(const UCM::Unit& unit1, const UCM::Unit& unit2) override;
std::pair<std::wstring, std::wstring> GetCurrencyRatioEquality(_In_ const UnitConversionManager::Unit& unit1, _In_ const UnitConversionManager::Unit& unit2) override;
std::pair<std::wstring, std::wstring>
GetCurrencyRatioEquality(_In_ const UnitConversionManager::Unit& unit1, _In_ const UnitConversionManager::Unit& unit2) override;
std::wstring GetCurrencyTimestamp() override;
concurrency::task<bool> TryLoadDataFromCacheAsync() override;
concurrency::task<bool> TryLoadDataFromWebAsync() override;
concurrency::task<bool> TryLoadDataFromWebOverrideAsync() override;
std::future<bool> TryLoadDataFromCacheAsync() override;
std::future<bool> TryLoadDataFromWebAsync() override;
std::future<bool> TryLoadDataFromWebOverrideAsync() override;
// ICurrencyConverterDataLoader
void OnNetworkBehaviorChanged(CalculatorApp::NetworkAccessBehavior newBehavior);
@@ -83,15 +87,15 @@ namespace CalculatorApp
void ResetLoadStatus();
void NotifyDataLoadFinished(bool didLoad);
concurrency::task<bool> TryFinishLoadFromCacheAsync();
std::future<bool> TryFinishLoadFromCacheAsync();
bool TryParseWebResponses(
_In_ Platform::String^ staticDataJson,
_In_ Platform::String^ allRatiosJson,
_In_ Platform::String ^ staticDataJson,
_In_ Platform::String ^ allRatiosJson,
_Inout_ std::vector<UCM::CurrencyStaticData>& staticData,
_Inout_ CurrencyRatioMap& allRatiosData);
bool TryParseStaticData(_In_ Platform::String^ rawJson, _Inout_ std::vector<UCM::CurrencyStaticData>& staticData);
bool TryParseAllRatiosData(_In_ Platform::String^ rawJson, _Inout_ CurrencyRatioMap& allRatiosData);
bool TryParseStaticData(_In_ Platform::String ^ rawJson, _Inout_ std::vector<UCM::CurrencyStaticData>& staticData);
bool TryParseAllRatiosData(_In_ Platform::String ^ rawJson, _Inout_ CurrencyRatioMap& allRatiosData);
concurrency::task<void> FinalizeUnits(_In_ const std::vector<UCM::CurrencyStaticData>& staticData, _In_ const CurrencyRatioMap& ratioMap);
void GuaranteeSelectedUnits();
@@ -106,7 +110,7 @@ namespace CalculatorApp
void SaveSelectedUnitsToLocalSettings(_In_ const SelectedUnits& selectedUnits);
private:
Platform::String^ m_responseLanguage;
Platform::String ^ m_responseLanguage;
std::unique_ptr<CalculatorApp::DataLoaders::ICurrencyHttpClient> m_client;
bool m_isRtlLanguage;
@@ -118,14 +122,14 @@ namespace CalculatorApp
std::shared_ptr<UCM::IViewModelCurrencyCallback> m_vmCallback;
Windows::Globalization::NumberFormatting::DecimalFormatter^ m_ratioFormatter;
Windows::Globalization::NumberFormatting::DecimalFormatter ^ m_ratioFormatter;
std::wstring m_ratioFormat;
Windows::Foundation::DateTime m_cacheTimestamp;
std::wstring m_timestampFormat;
CurrencyLoadStatus m_loadStatus;
CalculatorApp::NetworkManager^ m_networkManager;
CalculatorApp::NetworkManager ^ m_networkManager;
CalculatorApp::NetworkAccessBehavior m_networkAccessBehavior;
Windows::Foundation::EventRegistrationToken m_networkBehaviorToken;
bool m_meteredOverrideSet;

View File

@@ -1,35 +1,38 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#include "pch.h"
#include "CurrencyHttpClient.h"
#ifdef USE_MOCK_DATA
#include "DataLoaderMockConstants.h"
#else
#include "DataLoaderConstants.h"
#endif
using namespace CalculatorApp::DataLoaders;
using namespace Platform;
using namespace std;
using namespace Windows::Foundation;
using namespace Windows::Web::Http;
static constexpr auto sc_MetadataUriLocalizeFor = L"https://go.microsoft.com/fwlink/?linkid=2041093&localizeFor=";
static constexpr auto sc_RatiosUriRelativeTo = L"https://go.microsoft.com/fwlink/?linkid=2041339&localCurrency=";
CurrencyHttpClient::CurrencyHttpClient() :
m_client(ref new HttpClient()),
m_responseLanguage(L"en-US")
CurrencyHttpClient::CurrencyHttpClient()
: m_client(ref new HttpClient())
, m_responseLanguage(L"en-US")
{
}
void CurrencyHttpClient::SetSourceCurrencyCode(String^ sourceCurrencyCode)
void CurrencyHttpClient::SetSourceCurrencyCode(String ^ sourceCurrencyCode)
{
m_sourceCurrencyCode = sourceCurrencyCode;
}
void CurrencyHttpClient::SetResponseLanguage(String^ responseLanguage)
void CurrencyHttpClient::SetResponseLanguage(String ^ responseLanguage)
{
m_responseLanguage = responseLanguage;
}
IAsyncOperationWithProgress<String^, HttpProgress>^ CurrencyHttpClient::GetCurrencyMetadata()
IAsyncOperationWithProgress<String ^, HttpProgress> ^ CurrencyHttpClient::GetCurrencyMetadata()
{
wstring uri = wstring{ sc_MetadataUriLocalizeFor } + m_responseLanguage->Data();
auto metadataUri = ref new Uri(StringReference(uri.c_str()));
@@ -37,7 +40,7 @@ IAsyncOperationWithProgress<String^, HttpProgress>^ CurrencyHttpClient::GetCurre
return m_client->GetStringAsync(metadataUri);
}
IAsyncOperationWithProgress<String^, HttpProgress>^ CurrencyHttpClient::GetCurrencyRatios()
IAsyncOperationWithProgress<String ^, HttpProgress> ^ CurrencyHttpClient::GetCurrencyRatios()
{
wstring uri = wstring{ sc_RatiosUriRelativeTo } + m_sourceCurrencyCode->Data();
auto ratiosUri = ref new Uri(StringReference(uri.c_str()));

View File

@@ -14,16 +14,16 @@ namespace CalculatorApp
public:
CurrencyHttpClient();
void SetSourceCurrencyCode(Platform::String^ sourceCurrencyCode) override;
void SetResponseLanguage(Platform::String^ responseLanguage) override;
void SetSourceCurrencyCode(Platform::String ^ sourceCurrencyCode) override;
void SetResponseLanguage(Platform::String ^ responseLanguage) override;
Windows::Foundation::IAsyncOperationWithProgress<Platform::String^, Windows::Web::Http::HttpProgress>^ GetCurrencyMetadata() override;
Windows::Foundation::IAsyncOperationWithProgress<Platform::String^, Windows::Web::Http::HttpProgress>^ GetCurrencyRatios() override;
Windows::Foundation::IAsyncOperationWithProgress<Platform::String ^, Windows::Web::Http::HttpProgress> ^ GetCurrencyMetadata() override;
Windows::Foundation::IAsyncOperationWithProgress<Platform::String ^, Windows::Web::Http::HttpProgress> ^ GetCurrencyRatios() override;
private:
Windows::Web::Http::HttpClient^ m_client;
Platform::String^ m_responseLanguage;
Platform::String^ m_sourceCurrencyCode;
Windows::Web::Http::HttpClient ^ m_client;
Platform::String ^ m_responseLanguage;
Platform::String ^ m_sourceCurrencyCode;
};
}
}

View File

@@ -0,0 +1,13 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#pragma once
namespace CalculatorApp
{
namespace DataLoaders
{
static constexpr auto sc_MetadataUriLocalizeFor = L"https://go.microsoft.com/fwlink/?linkid=2091028&localizeFor=";
static constexpr auto sc_RatiosUriRelativeTo = L"https://go.microsoft.com/fwlink/?linkid=2091307&localCurrency=";
}
}

View File

@@ -10,13 +10,15 @@ namespace CalculatorApp
class ICurrencyHttpClient
{
public:
virtual ~ICurrencyHttpClient() {}
virtual ~ICurrencyHttpClient()
{
}
virtual void SetSourceCurrencyCode(Platform::String^ sourceCurrencyCode) = 0;
virtual void SetResponseLanguage(Platform::String^ responseLanguage) = 0;
virtual void SetSourceCurrencyCode(Platform::String ^ sourceCurrencyCode) = 0;
virtual void SetResponseLanguage(Platform::String ^ responseLanguage) = 0;
virtual Windows::Foundation::IAsyncOperationWithProgress<Platform::String^, Windows::Web::Http::HttpProgress>^ GetCurrencyMetadata() = 0;
virtual Windows::Foundation::IAsyncOperationWithProgress<Platform::String^, Windows::Web::Http::HttpProgress>^ GetCurrencyRatios() = 0;
virtual Windows::Foundation::IAsyncOperationWithProgress<Platform::String ^, Windows::Web::Http::HttpProgress> ^ GetCurrencyMetadata() = 0;
virtual Windows::Foundation::IAsyncOperationWithProgress<Platform::String ^, Windows::Web::Http::HttpProgress> ^ GetCurrencyRatios() = 0;
};
}
}

View File

@@ -1,11 +1,12 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
namespace CalculatorApp
{
namespace ViewModel
{
private enum UnitConverterUnits
private
enum UnitConverterUnits
{
UnitStart = 0,
Area_Acre = UnitStart + 1,
@@ -162,7 +163,8 @@ namespace CalculatorApp
Data_Zebibytes = UnitStart + 162,
Data_Zetabits = UnitStart + 163,
Data_Zetabytes = UnitStart + 164,
UnitEnd = Data_Zetabytes
Area_Pyeong = UnitStart + 165,
UnitEnd = Area_Pyeong
};
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -12,10 +12,20 @@ namespace CalculatorApp
{
struct OrderedUnit : UnitConversionManager::Unit
{
OrderedUnit(){}
OrderedUnit()
{
}
OrderedUnit(int id, std::wstring name, std::wstring abbreviation, int order, bool isConversionSource = false, bool isConversionTarget = false, bool isWhimsical = false)
: UnitConversionManager::Unit(id, name, abbreviation, isConversionSource, isConversionTarget, isWhimsical), order(order)
OrderedUnit(
int id,
std::wstring name,
std::wstring abbreviation,
int order,
bool isConversionSource = false,
bool isConversionTarget = false,
bool isWhimsical = false)
: UnitConversionManager::Unit(id, name, abbreviation, isConversionSource, isConversionTarget, isWhimsical)
, order(order)
{
}
@@ -31,11 +41,21 @@ namespace CalculatorApp
struct ExplicitUnitConversionData : UnitConversionManager::ConversionData
{
ExplicitUnitConversionData(){}
ExplicitUnitConversionData(CalculatorApp::Common::ViewMode categoryId, int parentUnitId, int unitId, double ratio, double offset, bool offsetFirst = false) :
categoryId(categoryId), parentUnitId(parentUnitId), unitId(unitId), UnitConversionManager::ConversionData(ratio, offset, offsetFirst)
ExplicitUnitConversionData()
{
}
ExplicitUnitConversionData(
CalculatorApp::Common::ViewMode categoryId,
int parentUnitId,
int unitId,
double ratio,
double offset,
bool offsetFirst = false)
: categoryId(categoryId)
, parentUnitId(parentUnitId)
, unitId(unitId)
, UnitConversionManager::ConversionData(ratio, offset, offsetFirst)
{
}
CalculatorApp::Common::ViewMode categoryId;
@@ -43,32 +63,33 @@ namespace CalculatorApp
int unitId;
};
class UnitConverterDataLoader : public UnitConversionManager::IConverterDataLoader,
public std::enable_shared_from_this<UnitConverterDataLoader>
class UnitConverterDataLoader : public UnitConversionManager::IConverterDataLoader, public std::enable_shared_from_this<UnitConverterDataLoader>
{
public:
UnitConverterDataLoader(Windows::Globalization::GeographicRegion^ region);
UnitConverterDataLoader(Windows::Globalization::GeographicRegion ^ region);
private:
// IConverterDataLoader
void LoadData() override;
std::vector<UnitConversionManager::Category> LoadOrderedCategories() override;
std::vector<UnitConversionManager::Unit> LoadOrderedUnits(const UnitConversionManager::Category& c) override;
std::unordered_map<UnitConversionManager::Unit, UnitConversionManager::ConversionData, UnitConversionManager::UnitHash> LoadOrderedRatios(const UnitConversionManager::Unit& unit) override;
std::unordered_map<UnitConversionManager::Unit, UnitConversionManager::ConversionData, UnitConversionManager::UnitHash>
LoadOrderedRatios(const UnitConversionManager::Unit& unit) override;
bool SupportsCategory(const UnitConversionManager::Category& target) override;
// IConverterDataLoader
void GetCategories(_In_ std::shared_ptr<std::vector<UnitConversionManager::Category>> categoriesList);
void GetUnits(_In_ std::unordered_map<CalculatorApp::Common::ViewMode, std::vector<CalculatorApp::ViewModel::OrderedUnit>>& unitMap);
void GetConversionData(_In_ std::unordered_map<CalculatorApp::Common::ViewMode, std::unordered_map<int, double>>& categoryToUnitConversionMap);
void GetExplicitConversionData(_In_ std::unordered_map<int, std::unordered_map<int, UnitConversionManager::ConversionData>>& unitToUnitConversionList);
void
GetExplicitConversionData(_In_ std::unordered_map<int, std::unordered_map<int, UnitConversionManager::ConversionData>>& unitToUnitConversionList);
std::wstring GetLocalizedStringName(_In_ Platform::String^ stringId);
std::wstring GetLocalizedStringName(_In_ Platform::String ^ stringId);
std::shared_ptr<std::vector<UnitConversionManager::Category>> m_categoryList;
std::shared_ptr<UnitConversionManager::CategoryToUnitVectorMap> m_categoryToUnits;
std::shared_ptr<UnitConversionManager::UnitToUnitToConversionDataMap> m_ratioMap;
Platform::String^ m_currentRegionCode;
Platform::String ^ m_currentRegionCode;
};
}
}

View File

@@ -32,18 +32,18 @@ namespace
StringReference IsDiffInDaysPropertyName(L"IsDiffInDays");
}
DateCalculatorViewModel::DateCalculatorViewModel() :
m_IsDateDiffMode(true),
m_IsAddMode(true),
m_isOutOfBound(false),
m_DaysOffset(0),
m_MonthsOffset(0),
m_YearsOffset(0),
m_StrDateDiffResult(L""),
m_StrDateDiffResultAutomationName(L""),
m_StrDateDiffResultInDays(L""),
m_StrDateResult(L""),
m_StrDateResultAutomationName(L"")
DateCalculatorViewModel::DateCalculatorViewModel()
: m_IsDateDiffMode(true)
, m_IsAddMode(true)
, m_isOutOfBound(false)
, m_DaysOffset(0)
, m_MonthsOffset(0)
, m_YearsOffset(0)
, m_StrDateDiffResult(L"")
, m_StrDateDiffResultAutomationName(L"")
, m_StrDateDiffResultInDays(L"")
, m_StrDateResult(L"")
, m_StrDateResultAutomationName(L"")
{
const auto& localizationSettings = LocalizationSettings::GetInstance();
@@ -55,13 +55,12 @@ DateCalculatorViewModel::DateCalculatorViewModel() :
// Initialize dates of DatePicker controls to today's date
auto calendar = ref new Calendar();
// We force the timezone to UTC, in order to avoid being affected by Daylight Saving Time
// when we calculate the difference between 2 dates.
// when we calculate the difference between 2 dates.
calendar->ChangeTimeZone("UTC");
auto today = calendar->GetDateTime();
// FromDate and ToDate should be clipped (adjusted to a consistent hour in UTC)
m_fromDate = ClipTime(today);
m_toDate = ClipTime(today);
m_fromDate = m_toDate = ClipTime(today, true);
// StartDate should not be clipped
m_startDate = today;
@@ -74,7 +73,7 @@ DateCalculatorViewModel::DateCalculatorViewModel() :
// Initialize the output results
UpdateDisplayResult();
m_offsetValues = ref new Vector<String^>();
m_offsetValues = ref new Vector<String ^>();
for (int i = 0; i <= c_maxOffsetValue; i++)
{
wstring numberStr(to_wstring(i));
@@ -84,7 +83,7 @@ DateCalculatorViewModel::DateCalculatorViewModel() :
DayOfWeek trueDayOfWeek = calendar->DayOfWeek;
DateTime clippedTime = ClipTime(today);
DateTime clippedTime = ClipTime(today, false);
calendar->SetDateTime(clippedTime);
if (calendar->DayOfWeek != trueDayOfWeek)
{
@@ -95,7 +94,7 @@ DateCalculatorViewModel::DateCalculatorViewModel() :
}
}
void DateCalculatorViewModel::OnPropertyChanged(_In_ String^ prop)
void DateCalculatorViewModel::OnPropertyChanged(_In_ String ^ prop)
{
if (prop == StrDateDiffResultPropertyName)
{
@@ -105,9 +104,8 @@ void DateCalculatorViewModel::OnPropertyChanged(_In_ String^ prop)
{
UpdateStrDateResultAutomationName();
}
else if (prop != StrDateDiffResultAutomationNamePropertyName
&& prop != StrDateDiffResultInDaysPropertyName
&& prop != StrDateResultAutomationNamePropertyName
else if (
prop != StrDateDiffResultAutomationNamePropertyName && prop != StrDateDiffResultInDaysPropertyName && prop != StrDateResultAutomationNamePropertyName
&& prop != IsDiffInDaysPropertyName)
{
OnInputsChanged();
@@ -120,15 +118,28 @@ void DateCalculatorViewModel::OnInputsChanged()
if (m_IsDateDiffMode)
{
DateTime clippedFromDate = ClipTime(FromDate);
DateTime clippedToDate = ClipTime(ToDate);
DateTime clippedFromDate = ClipTime(FromDate, true);
DateTime clippedToDate = ClipTime(ToDate, true);
// Calculate difference between two dates
m_dateCalcEngine->GetDateDifference(clippedFromDate, clippedToDate, m_allDateUnitsOutputFormat, &dateDiff);
DateDiffResult = dateDiff;
m_dateCalcEngine->GetDateDifference(clippedFromDate, clippedToDate, m_daysOutputFormat, &dateDiff);
DateDiffResultInDays = dateDiff;
if (m_dateCalcEngine->TryGetDateDifference(clippedFromDate, clippedToDate, m_daysOutputFormat, &dateDiff))
{
DateDiffResultInDays = dateDiff;
if (m_dateCalcEngine->TryGetDateDifference(clippedFromDate, clippedToDate, m_allDateUnitsOutputFormat, &dateDiff))
{
DateDiffResult = dateDiff;
}
else
{
// TryGetDateDifference wasn't able to calculate the difference in days/weeks/months/years, we will instead display the difference in days.
DateDiffResult = DateDiffResultInDays;
}
}
else
{
DateDiffResult = DateDifferenceUnknown;
DateDiffResultInDays = DateDifferenceUnknown;
}
}
else
{
@@ -160,16 +171,21 @@ void DateCalculatorViewModel::UpdateDisplayResult()
{
if (m_IsDateDiffMode)
{
// Are to and from dates the same
if (m_dateDiffResultInDays.day == 0)
if (m_dateDiffResultInDays == DateDifferenceUnknown)
{
IsDiffInDays = false;
StrDateDiffResultInDays = L"";
StrDateDiffResult = AppResourceProvider::GetInstance().GetResourceString(L"CalculationFailed");
}
else if (m_dateDiffResultInDays.day == 0)
{
// to and from dates the same
IsDiffInDays = true;
StrDateDiffResultInDays = L"";
StrDateDiffResult = AppResourceProvider::GetInstance().GetResourceString(L"Date_SameDates");
}
else if ((m_dateDiffResult.year == 0) &&
(m_dateDiffResult.month == 0) &&
(m_dateDiffResult.week == 0))
else if (m_dateDiffResult == DateDifferenceUnknown ||
(m_dateDiffResult.year == 0 && m_dateDiffResult.month == 0 && m_dateDiffResult.week == 0))
{
IsDiffInDays = true;
StrDateDiffResultInDays = L"";
@@ -205,22 +221,22 @@ void DateCalculatorViewModel::UpdateDisplayResult()
void DateCalculatorViewModel::UpdateStrDateDiffResultAutomationName()
{
String^ automationFormat = AppResourceProvider::GetInstance().GetResourceString(L"Date_DifferenceResultAutomationName");
String ^ automationFormat = AppResourceProvider::GetInstance().GetResourceString(L"Date_DifferenceResultAutomationName");
wstring localizedAutomationName = LocalizationStringUtil::GetLocalizedString(automationFormat->Data(), StrDateDiffResult->Data());
StrDateDiffResultAutomationName = ref new String(localizedAutomationName.c_str());
}
void DateCalculatorViewModel::UpdateStrDateResultAutomationName()
{
String^ automationFormat = AppResourceProvider::GetInstance().GetResourceString(L"Date_ResultingDateAutomationName");
String ^ automationFormat = AppResourceProvider::GetInstance().GetResourceString(L"Date_ResultingDateAutomationName");
wstring localizedAutomationName = LocalizationStringUtil::GetLocalizedString(automationFormat->Data(), StrDateResult->Data());
StrDateResultAutomationName = ref new String(localizedAutomationName.c_str());
}
void DateCalculatorViewModel::InitializeDateOutputFormats(_In_ String^ calendarIdentifier)
void DateCalculatorViewModel::InitializeDateOutputFormats(_In_ String ^ calendarIdentifier)
{
// Format for Add/Subtract days
m_dateTimeFormatter = LocalizationService::GetRegionalSettingsAwareDateTimeFormatter(
m_dateTimeFormatter = LocalizationService::GetInstance()->GetRegionalSettingsAwareDateTimeFormatter(
L"longdate",
calendarIdentifier,
ClockIdentifiers::TwentyFourHour); // Clock Identifier is not used
@@ -230,7 +246,7 @@ void DateCalculatorViewModel::InitializeDateOutputFormats(_In_ String^ calendarI
m_daysOutputFormat = DateUnit::Day;
}
String^ DateCalculatorViewModel::GetDateDiffString() const
String ^ DateCalculatorViewModel::GetDateDiffString() const
{
wstring result;
bool addDelimiter = false;
@@ -333,7 +349,7 @@ String^ DateCalculatorViewModel::GetDateDiffString() const
return ref new String(result.data());
}
String^ DateCalculatorViewModel::GetDateDiffStringInDays() const
String ^ DateCalculatorViewModel::GetDateDiffStringInDays() const
{
wstring result = GetLocalizedNumberString(m_dateDiffResultInDays.day)->Data();
result += L" ";
@@ -351,7 +367,7 @@ String^ DateCalculatorViewModel::GetDateDiffStringInDays() const
return ref new String(result.data());
}
void DateCalculatorViewModel::OnCopyCommand(Platform::Object^ parameter)
void DateCalculatorViewModel::OnCopyCommand(Platform::Object ^ parameter)
{
if (m_IsDateDiffMode)
{
@@ -363,19 +379,41 @@ void DateCalculatorViewModel::OnCopyCommand(Platform::Object^ parameter)
}
}
String^ DateCalculatorViewModel::GetLocalizedNumberString(int value) const
String ^ DateCalculatorViewModel::GetLocalizedNumberString(int value) const
{
wstring numberStr(to_wstring(value));
LocalizationSettings::GetInstance().LocalizeDisplayValue(&numberStr);
return ref new String(numberStr.c_str());
}
// Adjusts the given DateTime to 12AM (UTC) of the same day
DateTime DateCalculatorViewModel::ClipTime(DateTime dateTime)
/// <summary>
/// Adjusts the given DateTime to 12AM of the same day
/// </summary>
/// <param name="dateTime">DateTime to clip</param>
/// <param name="adjustUsingLocalTime">Adjust the datetime using local time (by default adjust using UTC time)</param>
DateTime DateCalculatorViewModel::ClipTime(DateTime dateTime, bool adjustUsingLocalTime)
{
DateTime referenceDateTime;
if (adjustUsingLocalTime)
{
FILETIME fileTime;
fileTime.dwLowDateTime = (DWORD)(dateTime.UniversalTime & 0xffffffff);
fileTime.dwHighDateTime = (DWORD)(dateTime.UniversalTime >> 32);
FILETIME localFileTime;
FileTimeToLocalFileTime(&fileTime, &localFileTime);
referenceDateTime.UniversalTime = (DWORD)localFileTime.dwHighDateTime;
referenceDateTime.UniversalTime <<= 32;
referenceDateTime.UniversalTime |= (DWORD)localFileTime.dwLowDateTime;
}
else
{
referenceDateTime = dateTime;
}
auto calendar = ref new Calendar();
calendar->ChangeTimeZone("UTC");
calendar->SetDateTime(dateTime);
calendar->SetDateTime(referenceDateTime);
calendar->Period = calendar->FirstPeriodInThisDay;
calendar->Hour = calendar->FirstHourInThisPeriod;
calendar->Minute = 0;

View File

@@ -12,8 +12,7 @@ namespace CalculatorApp
{
namespace ViewModel
{
[Windows::UI::Xaml::Data::Bindable]
public ref class DateCalculatorViewModel sealed : public Windows::UI::Xaml::Data::INotifyPropertyChanged
[Windows::UI::Xaml::Data::Bindable] public ref class DateCalculatorViewModel sealed : public Windows::UI::Xaml::Data::INotifyPropertyChanged
{
public:
DateCalculatorViewModel();
@@ -23,8 +22,8 @@ namespace CalculatorApp
// Input Properties
OBSERVABLE_PROPERTY_RW(bool, IsDateDiffMode);
OBSERVABLE_PROPERTY_RW(bool, IsAddMode);
OBSERVABLE_PROPERTY_R(bool, IsDiffInDays); // If diff is only in days or the dates are the same,
// then show only one result and avoid redundancy
OBSERVABLE_PROPERTY_R(bool, IsDiffInDays); // If diff is only in days or the dates are the same,
// then show only one result and avoid redundancy
OBSERVABLE_PROPERTY_RW(int, DaysOffset);
OBSERVABLE_PROPERTY_RW(int, MonthsOffset);
@@ -39,7 +38,10 @@ namespace CalculatorApp
// From date for Date Diff
property Windows::Foundation::DateTime FromDate
{
Windows::Foundation::DateTime get() { return m_fromDate; }
Windows::Foundation::DateTime get()
{
return m_fromDate;
}
void set(Windows::Foundation::DateTime value)
{
@@ -54,7 +56,10 @@ namespace CalculatorApp
// To date for Date Diff
property Windows::Foundation::DateTime ToDate
{
Windows::Foundation::DateTime get() { return m_toDate; }
Windows::Foundation::DateTime get()
{
return m_toDate;
}
void set(Windows::Foundation::DateTime value)
{
@@ -69,7 +74,10 @@ namespace CalculatorApp
// Start date for Add/Subtract date
property Windows::Foundation::DateTime StartDate
{
Windows::Foundation::DateTime get() { return m_startDate; }
Windows::Foundation::DateTime get()
{
return m_startDate;
}
void set(Windows::Foundation::DateTime value)
{
@@ -82,56 +90,84 @@ namespace CalculatorApp
}
// Output Properties
OBSERVABLE_PROPERTY_R(Platform::String^, StrDateDiffResult);
OBSERVABLE_PROPERTY_R(Platform::String^, StrDateDiffResultAutomationName);
OBSERVABLE_PROPERTY_R(Platform::String^, StrDateDiffResultInDays);
OBSERVABLE_PROPERTY_R(Platform::String^, StrDateResult);
OBSERVABLE_PROPERTY_R(Platform::String^, StrDateResultAutomationName);
OBSERVABLE_PROPERTY_R(Platform::String ^, StrDateDiffResult);
OBSERVABLE_PROPERTY_R(Platform::String ^, StrDateDiffResultAutomationName);
OBSERVABLE_PROPERTY_R(Platform::String ^, StrDateDiffResultInDays);
OBSERVABLE_PROPERTY_R(Platform::String ^, StrDateResult);
OBSERVABLE_PROPERTY_R(Platform::String ^, StrDateResultAutomationName);
COMMAND_FOR_METHOD(CopyCommand, DateCalculatorViewModel::OnCopyCommand);
void OnCopyCommand(Platform::Object^ parameter);
void OnCopyCommand(Platform::Object ^ parameter);
private:
void OnPropertyChanged(_In_ Platform::String^ prop);
void OnPropertyChanged(_In_ Platform::String ^ prop);
void OnInputsChanged();
void UpdateDisplayResult();
void UpdateStrDateDiffResultAutomationName();
void UpdateStrDateResultAutomationName();
void InitializeDateOutputFormats(Platform::String^ calendarIdentifier);
Platform::String^ GetDateDiffString() const;
Platform::String^ GetDateDiffStringInDays() const;
Platform::String^ GetLocalizedNumberString(int value) const;
static Windows::Foundation::DateTime ClipTime(Windows::Foundation::DateTime dateTime);
void InitializeDateOutputFormats(Platform::String ^ calendarIdentifier);
Platform::String ^ GetDateDiffString() const;
Platform::String ^ GetDateDiffStringInDays() const;
Platform::String ^ GetLocalizedNumberString(int value) const;
static Windows::Foundation::DateTime ClipTime(Windows::Foundation::DateTime dateTime, bool adjustToLocalTime);
property bool IsOutOfBound
{
bool get() { return m_isOutOfBound; }
void set(bool value) { m_isOutOfBound = value; UpdateDisplayResult(); }
bool get()
{
return m_isOutOfBound;
}
void set(bool value)
{
m_isOutOfBound = value;
UpdateDisplayResult();
}
}
property CalculatorApp::Common::DateCalculation::DateDifference DateDiffResult
{
CalculatorApp::Common::DateCalculation::DateDifference get() { return m_dateDiffResult; }
void set(CalculatorApp::Common::DateCalculation::DateDifference value) { m_dateDiffResult = value; UpdateDisplayResult(); }
CalculatorApp::Common::DateCalculation::DateDifference get()
{
return m_dateDiffResult;
}
void set(CalculatorApp::Common::DateCalculation::DateDifference value)
{
m_dateDiffResult = value;
UpdateDisplayResult();
}
}
property CalculatorApp::Common::DateCalculation::DateDifference DateDiffResultInDays
{
CalculatorApp::Common::DateCalculation::DateDifference get() { return m_dateDiffResultInDays; }
void set(CalculatorApp::Common::DateCalculation::DateDifference value) { m_dateDiffResultInDays = value; UpdateDisplayResult(); }
CalculatorApp::Common::DateCalculation::DateDifference get()
{
return m_dateDiffResultInDays;
}
void set(CalculatorApp::Common::DateCalculation::DateDifference value)
{
m_dateDiffResultInDays = value;
UpdateDisplayResult();
}
}
property Windows::Foundation::DateTime DateResult
{
Windows::Foundation::DateTime get() { return m_dateResult; }
void set(Windows::Foundation::DateTime value) { m_dateResult = value; UpdateDisplayResult();}
Windows::Foundation::DateTime get()
{
return m_dateResult;
}
void set(Windows::Foundation::DateTime value)
{
m_dateResult = value;
UpdateDisplayResult();
}
}
private:
// Property variables
bool m_isOutOfBound;
Platform::Collections::Vector<Platform::String^>^ m_offsetValues;
Platform::Collections::Vector<Platform::String ^> ^ m_offsetValues;
Windows::Foundation::DateTime m_fromDate;
Windows::Foundation::DateTime m_toDate;
Windows::Foundation::DateTime m_startDate;
@@ -143,7 +179,7 @@ namespace CalculatorApp
std::shared_ptr<CalculatorApp::Common::DateCalculation::DateCalculationEngine> m_dateCalcEngine;
CalculatorApp::Common::DateCalculation::DateUnit m_daysOutputFormat;
CalculatorApp::Common::DateCalculation::DateUnit m_allDateUnitsOutputFormat;
Windows::Globalization::DateTimeFormatting::DateTimeFormatter^ m_dateTimeFormatter;
Windows::Globalization::DateTimeFormatting::DateTimeFormatter ^ m_dateTimeFormatter;
std::wstring m_listSeparator;
};
}

View File

@@ -10,17 +10,25 @@ using namespace CalculatorApp::ViewModel;
using namespace std;
using namespace Platform;
HistoryItemViewModel::HistoryItemViewModel(String^ expression, String^ result,
_In_ const shared_ptr<CalculatorVector <pair<wstring, int>>> &spTokens,
_In_ const shared_ptr<CalculatorVector<shared_ptr<IExpressionCommand>>> &spCommands) :m_expression(expression), m_result(result), m_spTokens(spTokens), m_spCommands(spCommands)
HistoryItemViewModel::HistoryItemViewModel(
String ^ expression,
String ^ result,
_In_ const shared_ptr<CalculatorVector<pair<wstring, int>>>& spTokens,
_In_ const shared_ptr<CalculatorVector<shared_ptr<IExpressionCommand>>>& spCommands)
: m_expression(expression)
, m_result(result)
, m_spTokens(spTokens)
, m_spCommands(spCommands)
{
// updating accessibility names for expression and result
m_accExpression = HistoryItemViewModel::GetAccessibleExpressionFromTokens(spTokens, m_expression);
m_accResult = LocalizationService::GetNarratorReadableString(m_result);
}
String^ HistoryItemViewModel::GetAccessibleExpressionFromTokens(_In_ shared_ptr< CalculatorVector< pair< wstring, int > > > const &spTokens, _In_ String^ fallbackExpression)
String
^ HistoryItemViewModel::GetAccessibleExpressionFromTokens(
_In_ shared_ptr<CalculatorVector<pair<wstring, int>>> const& spTokens,
_In_ String ^ fallbackExpression)
{
// updating accessibility names for expression and result
wstringstream accExpression{};

View File

@@ -10,18 +10,17 @@ namespace CalculatorApp
{
namespace ViewModel
{
[Windows::UI::Xaml::Data::Bindable]
public ref class HistoryItemViewModel sealed : Windows::UI::Xaml::Data::ICustomPropertyProvider
[Windows::UI::Xaml::Data::Bindable] public ref class HistoryItemViewModel sealed : Windows::UI::Xaml::Data::ICustomPropertyProvider
{
internal :
internal:
HistoryItemViewModel(
Platform::String ^ expression,
Platform::String ^ result,
_In_ std::shared_ptr<CalculatorVector<std::pair<std::wstring, int>>> const& spTokens,
_In_ std::shared_ptr<CalculatorVector<std::shared_ptr<IExpressionCommand>>> const& spCommands);
HistoryItemViewModel(Platform::String^ expression,
Platform::String^ result,
_In_ std::shared_ptr<CalculatorVector <std::pair<std::wstring, int>>> const &spTokens,
_In_ std::shared_ptr<CalculatorVector<std::shared_ptr<IExpressionCommand>>> const &spCommands);
std::shared_ptr<CalculatorVector <std::pair<std::wstring, int>>> const& GetTokens()
std::shared_ptr<CalculatorVector<std::pair<std::wstring, int>>> const& GetTokens()
{
return m_spTokens;
}
@@ -32,38 +31,25 @@ namespace CalculatorApp
}
public:
property Platform::String
^ Expression { Platform::String ^ get() { return m_expression; } }
property Platform::String^ Expression
{
Platform::String^ get() { return m_expression; }
}
property Platform::String
^ AccExpression { Platform::String ^ get() { return m_accExpression; } }
property Platform::String^ AccExpression
{
Platform::String^ get() { return m_accExpression; }
}
property Platform::String
^ Result { Platform::String ^ get() { return m_result; } }
property Platform::String^ Result
{
Platform::String^ get() { return m_result; }
}
property Platform::String
^ AccResult { Platform::String ^ get() { return m_accResult; } }
property Platform::String^ AccResult
{
Platform::String^ get() { return m_accResult; }
}
virtual Windows::UI::Xaml::Data::ICustomProperty
^ GetCustomProperty(Platform::String ^ name) { return nullptr; }
virtual Windows::UI::Xaml::Data::ICustomProperty^ GetCustomProperty(Platform::String^ name)
{
return nullptr;
}
virtual Windows::UI::Xaml::Data::ICustomProperty
^ GetIndexedProperty(Platform::String ^ name, Windows::UI::Xaml::Interop::TypeName type) { return nullptr; }
virtual Windows::UI::Xaml::Data::ICustomProperty^ GetIndexedProperty(Platform::String^ name, Windows::UI::Xaml::Interop::TypeName type)
{
return nullptr;
}
virtual property Windows::UI::Xaml::Interop::TypeName Type
virtual property Windows::UI::Xaml::Interop::TypeName Type
{
Windows::UI::Xaml::Interop::TypeName get()
{
@@ -71,22 +57,20 @@ namespace CalculatorApp
}
}
virtual Platform::String^ GetStringRepresentation()
{
return m_accExpression + " " + m_accResult;
}
virtual Platform::String
^ GetStringRepresentation() { return m_accExpression + " " + m_accResult; }
private : static Platform::String
^ GetAccessibleExpressionFromTokens(
_In_ std::shared_ptr<CalculatorVector<std::pair<std::wstring, int>>> const& spTokens,
_In_ Platform::String ^ fallbackExpression);
private:
static Platform::String^ GetAccessibleExpressionFromTokens(
_In_ std::shared_ptr<CalculatorVector <std::pair<std::wstring, int>>> const &spTokens,
_In_ Platform::String^ fallbackExpression);
private:
Platform::String^ m_expression;
Platform::String^ m_accExpression;
Platform::String^ m_accResult;
Platform::String^ m_result;
std::shared_ptr<CalculatorVector <std::pair<std::wstring, int>>> m_spTokens;
Platform::String ^ m_expression;
Platform::String ^ m_accExpression;
Platform::String ^ m_accResult;
Platform::String ^ m_result;
std::shared_ptr<CalculatorVector<std::pair<std::wstring, int>>> m_spTokens;
std::shared_ptr<CalculatorVector<std::shared_ptr<IExpressionCommand>>> m_spCommands;
};
}

View File

@@ -26,13 +26,13 @@ namespace CalculatorApp::ViewModel::HistoryResourceKeys
StringReference HistoryCleared(L"HistoryList_Cleared");
}
HistoryViewModel::HistoryViewModel(_In_ CalculationManager::CalculatorManager* calculatorManager) :
m_calculatorManager(calculatorManager),
m_localizedHistoryCleared(nullptr)
HistoryViewModel::HistoryViewModel(_In_ CalculationManager::CalculatorManager* calculatorManager)
: m_calculatorManager(calculatorManager)
, m_localizedHistoryCleared(nullptr)
{
AreHistoryShortcutsEnabled = true;
Items = ref new Platform::Collections::Vector<HistoryItemViewModel^>();
Items = ref new Platform::Collections::Vector<HistoryItemViewModel ^>();
ItemSize = 0;
}
@@ -59,7 +59,7 @@ void HistoryViewModel::ReloadHistory(_In_ ViewMode currentMode)
}
auto historyListModel = m_calculatorManager->GetHistoryItems(m_currentMode);
auto historyListVM = ref new Platform::Collections::Vector<HistoryItemViewModel^>();
auto historyListVM = ref new Platform::Collections::Vector<HistoryItemViewModel ^>();
const auto& localizer = LocalizationSettings::GetInstance();
if (historyListModel.size() > 0)
{
@@ -70,9 +70,11 @@ void HistoryViewModel::ReloadHistory(_In_ ViewMode currentMode)
localizer.LocalizeDisplayValue(&expression);
localizer.LocalizeDisplayValue(&result);
auto item = ref new HistoryItemViewModel(ref new Platform::String( expression.c_str()),
auto item = ref new HistoryItemViewModel(
ref new Platform::String(expression.c_str()),
ref new Platform::String(result.c_str()),
(*ritr)->historyItemVector.spTokens, (*ritr)->historyItemVector.spCommands);
(*ritr)->historyItemVector.spTokens,
(*ritr)->historyItemVector.spCommands);
historyListVM->Append(item);
}
}
@@ -89,15 +91,17 @@ void HistoryViewModel::OnHistoryItemAdded(_In_ unsigned int addedItemIndex)
wstring result = newItem->historyItemVector.result;
localizer.LocalizeDisplayValue(&expression);
localizer.LocalizeDisplayValue(&result);
auto item = ref new HistoryItemViewModel(ref new Platform::String(expression.c_str()),
ref new Platform::String(result.c_str()),
newItem->historyItemVector.spTokens, newItem->historyItemVector.spCommands );
auto item = ref new HistoryItemViewModel(
ref new Platform::String(expression.c_str()),
ref new Platform::String(result.c_str()),
newItem->historyItemVector.spTokens,
newItem->historyItemVector.spCommands);
// check if we have not hit the max items
if (Items->Size >= m_calculatorManager->MaxHistorySize())
{
// this means the item already exists
Items->RemoveAt(Items->Size -1);
Items->RemoveAt(Items->Size - 1);
}
assert(addedItemIndex <= m_calculatorManager->MaxHistorySize() && addedItemIndex >= 0);
@@ -106,18 +110,18 @@ void HistoryViewModel::OnHistoryItemAdded(_In_ unsigned int addedItemIndex)
SaveHistory();
}
void HistoryViewModel::SetCalculatorDisplay(CalculatorDisplay &calculatorDisplay)
void HistoryViewModel::SetCalculatorDisplay(CalculatorDisplay& calculatorDisplay)
{
WeakReference historyViewModel(this);
calculatorDisplay.SetHistoryCallback(historyViewModel);
}
void HistoryViewModel::ShowItem(_In_ HistoryItemViewModel^ e)
void HistoryViewModel::ShowItem(_In_ HistoryItemViewModel ^ e)
{
HistoryItemClicked(e);
}
void HistoryViewModel::DeleteItem(_In_ HistoryItemViewModel^ e)
void HistoryViewModel::DeleteItem(_In_ HistoryItemViewModel ^ e)
{
uint32_t itemIndex;
if (Items->IndexOf(e, &itemIndex))
@@ -127,7 +131,7 @@ void HistoryViewModel::DeleteItem(_In_ HistoryItemViewModel^ e)
// Keys for the history container are index based.
// SaveHistory() re-inserts the items anyway, so it's faster to just clear out the container.
CalculationManager::CALCULATOR_MODE currentMode = m_currentMode;
ApplicationDataContainer^ historyContainer = GetHistoryContainer(currentMode);
ApplicationDataContainer ^ historyContainer = GetHistoryContainer(currentMode);
historyContainer->Values->Clear();
Items->RemoveAt(itemIndex);
@@ -137,13 +141,13 @@ void HistoryViewModel::DeleteItem(_In_ HistoryItemViewModel^ e)
}
}
void HistoryViewModel::OnHideCommand(_In_ Platform::Object^ e)
void HistoryViewModel::OnHideCommand(_In_ Platform::Object ^ e)
{
// added at VM layer so that the views do not have to individually raise events
HideHistoryClicked();
}
void HistoryViewModel::OnClearCommand(_In_ Platform::Object^ e)
void HistoryViewModel::OnClearCommand(_In_ Platform::Object ^ e)
{
TraceLogger::GetInstance().LogClearHistory();
if (AreHistoryShortcutsEnabled == true)
@@ -165,8 +169,9 @@ void HistoryViewModel::OnClearCommand(_In_ Platform::Object^ e)
// this method restores history vector per mode
void HistoryViewModel::RestoreHistory(_In_ CalculationManager::CALCULATOR_MODE cMode)
{
ApplicationDataContainer^ historyContainer = GetHistoryContainer(cMode);
std::shared_ptr<std::vector<std::shared_ptr<CalculationManager::HISTORYITEM>>> historyVector = std::make_shared<std::vector<std::shared_ptr<CalculationManager::HISTORYITEM>>>();
ApplicationDataContainer ^ historyContainer = GetHistoryContainer(cMode);
std::shared_ptr<std::vector<std::shared_ptr<CalculationManager::HISTORYITEM>>> historyVector =
std::make_shared<std::vector<std::shared_ptr<CalculationManager::HISTORYITEM>>>();
auto historyVectorLength = static_cast<int>(historyContainer->Values->Lookup(HistoryVectorLengthKey));
bool failure = false;
@@ -181,7 +186,7 @@ void HistoryViewModel::RestoreHistory(_In_ CalculationManager::CALCULATOR_MODE c
std::shared_ptr<CalculationManager::HISTORYITEM> Item = std::make_shared<CalculationManager::HISTORYITEM>(item);
historyVector->push_back(Item);
}
catch (Platform::Exception^ e)
catch (Platform::Exception ^ e)
{
failure = true;
break;
@@ -204,19 +209,19 @@ void HistoryViewModel::RestoreHistory(_In_ CalculationManager::CALCULATOR_MODE c
}
}
Platform::String^ HistoryViewModel::GetHistoryContainerKey(_In_ CalculationManager::CALCULATOR_MODE cMode)
Platform::String ^ HistoryViewModel::GetHistoryContainerKey(_In_ CalculationManager::CALCULATOR_MODE cMode)
{
Platform::ValueType^ modeValue = static_cast<int>(cMode);
Platform::ValueType ^ modeValue = static_cast<int>(cMode);
return Platform::String::Concat(modeValue->ToString(), L"_History");
}
ApplicationDataContainer^ HistoryViewModel::GetHistoryContainer(_In_ CalculationManager::CALCULATOR_MODE cMode)
ApplicationDataContainer ^ HistoryViewModel::GetHistoryContainer(_In_ CalculationManager::CALCULATOR_MODE cMode)
{
ApplicationDataContainer^ localSettings = ApplicationData::Current->LocalSettings;
ApplicationDataContainer^ historyContainer;
ApplicationDataContainer ^ localSettings = ApplicationData::Current->LocalSettings;
ApplicationDataContainer ^ historyContainer;
// naming container based on mode
Platform::String^ historyContainerKey = GetHistoryContainerKey(cMode);
Platform::String ^ historyContainerKey = GetHistoryContainerKey(cMode);
if (localSettings->Containers->HasKey(historyContainerKey))
{
@@ -235,14 +240,14 @@ ApplicationDataContainer^ HistoryViewModel::GetHistoryContainer(_In_ Calculation
void HistoryViewModel::ClearHistoryContainer(_In_ CalculationManager::CALCULATOR_MODE cMode)
{
ApplicationDataContainer^ localSettings = ApplicationData::Current->LocalSettings;
ApplicationDataContainer ^ localSettings = ApplicationData::Current->LocalSettings;
localSettings->DeleteContainer(GetHistoryContainerKey(cMode));
}
// this method will be used to update the history item length
void HistoryViewModel::UpdateHistoryVectorLength(_In_ int newValue, _In_ CalculationManager::CALCULATOR_MODE cMode)
{
ApplicationDataContainer^ historyContainer = GetHistoryContainer(cMode);
ApplicationDataContainer ^ historyContainer = GetHistoryContainer(cMode);
historyContainer->Values->Remove(HistoryVectorLengthKey);
historyContainer->Values->Insert(HistoryVectorLengthKey, newValue);
}
@@ -255,11 +260,11 @@ void HistoryViewModel::ClearHistory()
void HistoryViewModel::SaveHistory()
{
ApplicationDataContainer^ historyContainer = GetHistoryContainer(m_currentMode);
ApplicationDataContainer ^ historyContainer = GetHistoryContainer(m_currentMode);
auto currentHistoryVector = m_calculatorManager->GetHistoryItems(m_currentMode);
bool failure = false;
int index = 0;
Platform::String^ serializedHistoryItem;
Platform::String ^ serializedHistoryItem;
for (auto iter = currentHistoryVector.begin(); iter != currentHistoryVector.end(); ++iter)
{
@@ -268,7 +273,7 @@ void HistoryViewModel::SaveHistory()
serializedHistoryItem = SerializeHistoryItem(*iter);
historyContainer->Values->Insert(index.ToString(), serializedHistoryItem);
}
catch (Platform::Exception^)
catch (Platform::Exception ^)
{
failure = true;
break;
@@ -289,9 +294,9 @@ void HistoryViewModel::SaveHistory()
}
// this serializes a history item into a base64 encoded string
Platform::String^ HistoryViewModel::SerializeHistoryItem(_In_ std::shared_ptr<CalculationManager::HISTORYITEM> const &item)
Platform::String ^ HistoryViewModel::SerializeHistoryItem(_In_ std::shared_ptr<CalculationManager::HISTORYITEM> const& item)
{
DataWriter^ writer = ref new DataWriter();
DataWriter ^ writer = ref new DataWriter();
auto expr = item->historyItemVector.expression;
auto result = item->historyItemVector.result;
auto platformExpr = ref new Platform::String(expr.c_str());
@@ -303,7 +308,7 @@ Platform::String^ HistoryViewModel::SerializeHistoryItem(_In_ std::shared_ptr<Ca
Utils::SerializeCommandsAndTokens(item->historyItemVector.spTokens, item->historyItemVector.spCommands, writer);
IBuffer^ buffer = writer->DetachBuffer();
IBuffer ^ buffer = writer->DetachBuffer();
if (buffer == nullptr)
{
throw ref new Platform::Exception(E_POINTER, ref new Platform::String(L"History Item is NULL"));
@@ -312,27 +317,28 @@ Platform::String^ HistoryViewModel::SerializeHistoryItem(_In_ std::shared_ptr<Ca
return CryptographicBuffer::EncodeToBase64String(buffer);
}
CalculationManager::HISTORYITEM HistoryViewModel::DeserializeHistoryItem(_In_ Platform::String^ historyItemKey, _In_ ApplicationDataContainer^ historyContainer)
CalculationManager::HISTORYITEM
HistoryViewModel::DeserializeHistoryItem(_In_ Platform::String ^ historyItemKey, _In_ ApplicationDataContainer ^ historyContainer)
{
CalculationManager::HISTORYITEM historyItem;
if (historyContainer->Values->HasKey(historyItemKey))
{
Object^ historyItemValues = historyContainer->Values->Lookup(historyItemKey);
Object ^ historyItemValues = historyContainer->Values->Lookup(historyItemKey);
if (historyItemValues == nullptr)
{
throw ref new Platform::Exception(E_POINTER, ref new Platform::String(L"History Item is NULL"));
}
String^ historyData = safe_cast<Platform::String^>(historyItemValues);
IBuffer^ buffer = CryptographicBuffer::DecodeFromBase64String(historyData);
String ^ historyData = safe_cast<Platform::String ^>(historyItemValues);
IBuffer ^ buffer = CryptographicBuffer::DecodeFromBase64String(historyData);
if (buffer == nullptr)
{
throw ref new Platform::Exception(E_POINTER, ref new Platform::String(L"History Item is NULL"));
}
DataReader^ reader = DataReader::FromBuffer(buffer);
DataReader ^ reader = DataReader::FromBuffer(buffer);
auto exprLen = reader->ReadUInt32();
auto expression = reader->ReadString(exprLen);
historyItem.historyItemVector.expression = expression->Data();
@@ -353,10 +359,9 @@ CalculationManager::HISTORYITEM HistoryViewModel::DeserializeHistoryItem(_In_ Pl
bool HistoryViewModel::IsValid(_In_ CalculationManager::HISTORYITEM item)
{
return (!item.historyItemVector.expression.empty() &&
!item.historyItemVector.result.empty() &&
(bool)item.historyItemVector.spCommands &&
(bool)item.historyItemVector.spTokens);
return (
!item.historyItemVector.expression.empty() && !item.historyItemVector.result.empty() && (bool)item.historyItemVector.spCommands
&& (bool)item.historyItemVector.spTokens);
}
void HistoryViewModel::UpdateItemSize()
@@ -364,9 +369,9 @@ void HistoryViewModel::UpdateItemSize()
ItemSize = Items->Size;
}
void HistoryViewModel::MakeHistoryClearedNarratorAnnouncement(String^ resourceKey, String^& formatVariable)
void HistoryViewModel::MakeHistoryClearedNarratorAnnouncement(String ^ resourceKey, String ^ &formatVariable)
{
String^ announcement = LocalizationStringUtil::GetLocalizedNarratorAnnouncement(resourceKey, formatVariable);
String ^ announcement = LocalizationStringUtil::GetLocalizedNarratorAnnouncement(resourceKey, formatVariable);
HistoryAnnouncement = CalculatorAnnouncement::GetHistoryClearedAnnouncement(announcement);
}

View File

@@ -15,60 +15,60 @@ namespace CalculatorApp
namespace ViewModel
{
public delegate void HideHistoryClickedHandler();
public delegate void HistoryItemClickedHandler(CalculatorApp::ViewModel::HistoryItemViewModel^ e);
public
delegate void HideHistoryClickedHandler();
public
delegate void HistoryItemClickedHandler(CalculatorApp::ViewModel::HistoryItemViewModel ^ e);
[Windows::UI::Xaml::Data::Bindable]
public ref class HistoryViewModel sealed : public Windows::UI::Xaml::Data::INotifyPropertyChanged
[Windows::UI::Xaml::Data::Bindable] public ref class HistoryViewModel sealed : public Windows::UI::Xaml::Data::INotifyPropertyChanged
{
public:
OBSERVABLE_OBJECT();
OBSERVABLE_PROPERTY_RW(int, ItemSize);
OBSERVABLE_PROPERTY_RW(Windows::UI::Xaml::Interop::IBindableObservableVector^, Items);
OBSERVABLE_PROPERTY_RW(Windows::UI::Xaml::Interop::IBindableObservableVector ^, Items);
OBSERVABLE_PROPERTY_RW(bool, AreHistoryShortcutsEnabled);
OBSERVABLE_PROPERTY_RW(CalculatorApp::Common::Automation::NarratorAnnouncement^, HistoryAnnouncement);
OBSERVABLE_PROPERTY_RW(CalculatorApp::Common::Automation::NarratorAnnouncement ^, HistoryAnnouncement);
void OnHistoryItemAdded(_In_ unsigned int addedItemIndex);
COMMAND_FOR_METHOD(HideCommand, HistoryViewModel::OnHideCommand);
void OnHideCommand(_In_ Platform::Object^ e);
void OnHideCommand(_In_ Platform::Object ^ e);
COMMAND_FOR_METHOD(ClearCommand, HistoryViewModel::OnClearCommand);
void OnClearCommand(_In_ Platform::Object^ e);
void OnClearCommand(_In_ Platform::Object ^ e);
// events that are created
event HideHistoryClickedHandler^ HideHistoryClicked;
event HistoryItemClickedHandler^ HistoryItemClicked;
void ShowItem(_In_ CalculatorApp::ViewModel::HistoryItemViewModel^ e);
event HideHistoryClickedHandler ^ HideHistoryClicked;
event HistoryItemClickedHandler ^ HistoryItemClicked;
void ShowItem(_In_ CalculatorApp::ViewModel::HistoryItemViewModel ^ e);
void ClearHistory();
void RestoreCompleteHistory();
internal:
HistoryViewModel(_In_ CalculationManager::CalculatorManager* calculatorManager);
void SetCalculatorDisplay(CalculatorDisplay &calculatorDisplay);
internal : HistoryViewModel(_In_ CalculationManager::CalculatorManager* calculatorManager);
void SetCalculatorDisplay(CalculatorDisplay& calculatorDisplay);
void ReloadHistory(_In_ CalculatorApp::Common::ViewMode currentMode);
void DeleteItem(_In_ CalculatorApp::ViewModel::HistoryItemViewModel^ e);
void DeleteItem(_In_ CalculatorApp::ViewModel::HistoryItemViewModel ^ e);
// store history in app data functions
Platform::String^ SerializeHistoryItem(_In_ std::shared_ptr<CalculationManager::HISTORYITEM> const &item);
Platform::String ^ SerializeHistoryItem(_In_ std::shared_ptr<CalculationManager::HISTORYITEM> const& item);
void SaveHistory();
private:
CalculationManager::CalculatorManager* const m_calculatorManager;
CalculatorDisplay m_calculatorDisplay;
CalculationManager::CALCULATOR_MODE m_currentMode;
Platform::String^ m_localizedHistoryCleared;
Platform::String ^ m_localizedHistoryCleared;
void RestoreHistory(_In_ CalculationManager::CALCULATOR_MODE cMode);
CalculationManager::HISTORYITEM DeserializeHistoryItem(_In_ Platform::String^ historyItemKey, _In_ Windows::Storage::ApplicationDataContainer^ historyContainer);
Windows::Storage::ApplicationDataContainer^ GetHistoryContainer(_In_ CalculationManager::CALCULATOR_MODE cMode);
Platform::String^ GetHistoryContainerKey(_In_ CalculationManager::CALCULATOR_MODE cMode);
CalculationManager::HISTORYITEM
DeserializeHistoryItem(_In_ Platform::String ^ historyItemKey, _In_ Windows::Storage::ApplicationDataContainer ^ historyContainer);
Windows::Storage::ApplicationDataContainer ^ GetHistoryContainer(_In_ CalculationManager::CALCULATOR_MODE cMode);
Platform::String ^ GetHistoryContainerKey(_In_ CalculationManager::CALCULATOR_MODE cMode);
void ClearHistoryContainer(_In_ CalculationManager::CALCULATOR_MODE cMode);
void UpdateHistoryVectorLength(_In_ int newValue, _In_ CalculationManager::CALCULATOR_MODE cMode);
bool IsValid(_In_ CalculationManager::HISTORYITEM item);
void MakeHistoryClearedNarratorAnnouncement(Platform::String^ resourceKey, Platform::String^& formatVariable);
void MakeHistoryClearedNarratorAnnouncement(Platform::String ^ resourceKey, Platform::String ^ &formatVariable);
friend class CalculatorDisplay;
void UpdateItemSize();

View File

@@ -14,28 +14,26 @@ namespace CalculatorApp
/// <summary>
/// Model representation of a single item in the Memory list
/// </summary>
[Windows::UI::Xaml::Data::Bindable]
public ref class MemoryItemViewModel sealed :
public Windows::UI::Xaml::Data::INotifyPropertyChanged,
Windows::UI::Xaml::Data::ICustomPropertyProvider
[Windows::UI::Xaml::Data::Bindable] public ref class MemoryItemViewModel sealed : public Windows::UI::Xaml::Data::INotifyPropertyChanged,
Windows::UI::Xaml::Data::ICustomPropertyProvider
{
public:
MemoryItemViewModel(StandardCalculatorViewModel^ calcVM) : m_Position(-1), m_calcVM(calcVM) {}
MemoryItemViewModel(StandardCalculatorViewModel ^ calcVM)
: m_Position(-1)
, m_calcVM(calcVM)
{
}
OBSERVABLE_OBJECT();
OBSERVABLE_PROPERTY_RW(int, Position);
OBSERVABLE_PROPERTY_RW(Platform::String^, Value);
OBSERVABLE_PROPERTY_RW(Platform::String ^, Value);
virtual Windows::UI::Xaml::Data::ICustomProperty^ GetCustomProperty(Platform::String^ name)
{
return nullptr;
}
virtual Windows::UI::Xaml::Data::ICustomProperty
^ GetCustomProperty(Platform::String ^ name) { return nullptr; }
virtual Windows::UI::Xaml::Data::ICustomProperty^ GetIndexedProperty(Platform::String^ name, Windows::UI::Xaml::Interop::TypeName type)
{
return nullptr;
}
virtual Windows::UI::Xaml::Data::ICustomProperty
^ GetIndexedProperty(Platform::String ^ name, Windows::UI::Xaml::Interop::TypeName type) { return nullptr; }
virtual property Windows::UI::Xaml::Interop::TypeName Type
virtual property Windows::UI::Xaml::Interop::TypeName Type
{
Windows::UI::Xaml::Interop::TypeName get()
{
@@ -43,17 +41,15 @@ namespace CalculatorApp
}
}
virtual Platform::String^ GetStringRepresentation()
{
return Value;
}
virtual Platform::String
^ GetStringRepresentation() { return Value; }
void Clear();
void Clear();
void MemoryAdd();
void MemorySubtract();
private:
StandardCalculatorViewModel^ m_calcVM;
StandardCalculatorViewModel ^ m_calcVM;
};
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -29,73 +29,77 @@ namespace CalculatorApp
namespace ViewModel
{
#define ASCII_0 48
public delegate void HideMemoryClickedHandler();
public delegate void ProgModeRadixChangeHandler();
public
delegate void HideMemoryClickedHandler();
public
delegate void ProgModeRadixChangeHandler();
[Windows::UI::Xaml::Data::Bindable]
public ref class StandardCalculatorViewModel sealed : public Windows::UI::Xaml::Data::INotifyPropertyChanged
[Windows::UI::Xaml::Data::Bindable] public ref class StandardCalculatorViewModel sealed : public Windows::UI::Xaml::Data::INotifyPropertyChanged
{
public:
StandardCalculatorViewModel();
void UpdateOperand(int pos, Platform::String^ text);
void UpdateOperand(int pos, Platform::String ^ text);
void UpdatecommandsInRecordingMode();
int GetBitLengthType();
int GetNumberBase();
OBSERVABLE_OBJECT_CALLBACK(OnPropertyChanged);
OBSERVABLE_PROPERTY_RW(Platform::String^, DisplayValue);
OBSERVABLE_PROPERTY_RW(HistoryViewModel^, HistoryVM);
OBSERVABLE_PROPERTY_RW(Platform::String ^, DisplayValue);
OBSERVABLE_PROPERTY_RW(HistoryViewModel ^, HistoryVM);
OBSERVABLE_NAMED_PROPERTY_RW(bool, IsInError);
OBSERVABLE_PROPERTY_RW(bool, IsOperatorCommand);
OBSERVABLE_PROPERTY_RW(Platform::String^, DisplayStringExpression);
OBSERVABLE_PROPERTY_RW(Windows::Foundation::Collections::IVector<Common::DisplayExpressionToken^>^, ExpressionTokens);
OBSERVABLE_PROPERTY_RW(Platform::String^, DecimalDisplayValue);
OBSERVABLE_PROPERTY_RW(Platform::String^, HexDisplayValue);
OBSERVABLE_PROPERTY_RW(Platform::String^, OctalDisplayValue);
OBSERVABLE_NAMED_PROPERTY_RW(Platform::String^, BinaryDisplayValue);
OBSERVABLE_PROPERTY_RW(Platform::String^, HexDisplayValue_AutomationName);
OBSERVABLE_PROPERTY_RW(Platform::String^, DecDisplayValue_AutomationName);
OBSERVABLE_PROPERTY_RW(Platform::String^, OctDisplayValue_AutomationName);
OBSERVABLE_PROPERTY_RW(Platform::String^, BinDisplayValue_AutomationName);
OBSERVABLE_PROPERTY_RW(Platform::String ^, DisplayStringExpression);
OBSERVABLE_PROPERTY_R(Windows::Foundation::Collections::IObservableVector<Common::DisplayExpressionToken ^> ^, ExpressionTokens);
OBSERVABLE_PROPERTY_RW(Platform::String ^, DecimalDisplayValue);
OBSERVABLE_PROPERTY_RW(Platform::String ^, HexDisplayValue);
OBSERVABLE_PROPERTY_RW(Platform::String ^, OctalDisplayValue);
OBSERVABLE_NAMED_PROPERTY_RW(Platform::String ^, BinaryDisplayValue);
OBSERVABLE_PROPERTY_RW(Platform::String ^, HexDisplayValue_AutomationName);
OBSERVABLE_PROPERTY_RW(Platform::String ^, DecDisplayValue_AutomationName);
OBSERVABLE_PROPERTY_RW(Platform::String ^, OctDisplayValue_AutomationName);
OBSERVABLE_PROPERTY_RW(Platform::String ^, BinDisplayValue_AutomationName);
OBSERVABLE_PROPERTY_RW(bool, IsBinaryOperatorEnabled);
OBSERVABLE_PROPERTY_RW(bool, IsUnaryOperatorEnabled);
OBSERVABLE_PROPERTY_RW(bool, IsNegateEnabled);
OBSERVABLE_PROPERTY_RW(bool, IsDecimalEnabled);
OBSERVABLE_PROPERTY_RW(bool, IsCurrentViewPinned);
OBSERVABLE_PROPERTY_RW(Windows::Foundation::Collections::IVector<MemoryItemViewModel^>^, MemorizedNumbers);
OBSERVABLE_PROPERTY_RW(Windows::Foundation::Collections::IVector<MemoryItemViewModel ^> ^, MemorizedNumbers);
OBSERVABLE_NAMED_PROPERTY_RW(bool, IsMemoryEmpty);
OBSERVABLE_PROPERTY_RW(bool, IsFToEChecked);
OBSERVABLE_PROPERTY_RW(bool, IsFToEEnabled);
OBSERVABLE_PROPERTY_RW(bool, IsHyperbolicChecked);
OBSERVABLE_PROPERTY_RW(bool, AreHEXButtonsEnabled);
OBSERVABLE_PROPERTY_RW(Platform::String^, CalculationResultAutomationName);
OBSERVABLE_PROPERTY_RW(Platform::String^, CalculationExpressionAutomationName);
OBSERVABLE_PROPERTY_RW(Platform::String ^, CalculationResultAutomationName);
OBSERVABLE_PROPERTY_RW(Platform::String ^, CalculationExpressionAutomationName);
OBSERVABLE_PROPERTY_RW(bool, IsShiftProgrammerChecked);
OBSERVABLE_PROPERTY_RW(bool, IsQwordEnabled);
OBSERVABLE_PROPERTY_RW(bool, IsDwordEnabled);
OBSERVABLE_PROPERTY_RW(bool, IsWordEnabled);
OBSERVABLE_PROPERTY_RW(bool, IsByteEnabled);
OBSERVABLE_NAMED_PROPERTY_RW(Platform::String^, OpenParenthesisCount);
OBSERVABLE_PROPERTY_RW(int, CurrentRadixType);
OBSERVABLE_PROPERTY_RW(bool, AreTokensUpdated);
OBSERVABLE_PROPERTY_RW(bool, AreHistoryShortcutsEnabled);
OBSERVABLE_PROPERTY_RW(bool, AreProgrammerRadixOperatorsEnabled);
OBSERVABLE_PROPERTY_RW(CalculatorApp::Common::Automation::NarratorAnnouncement^, Announcement);
OBSERVABLE_PROPERTY_RW(CalculatorApp::Common::Automation::NarratorAnnouncement ^, Announcement);
OBSERVABLE_PROPERTY_R(unsigned int, OpenParenthesisCount);
COMMAND_FOR_METHOD(CopyCommand, StandardCalculatorViewModel::OnCopyCommand);
COMMAND_FOR_METHOD(PasteCommand, StandardCalculatorViewModel::OnPasteCommand);
COMMAND_FOR_METHOD(ButtonPressed, StandardCalculatorViewModel::OnButtonPressed);
COMMAND_FOR_METHOD(ClearMemoryCommand, StandardCalculatorViewModel::OnClearMemoryCommand);
COMMAND_FOR_METHOD(PinUnpinAppBarButtonOnClicked, StandardCalculatorViewModel::OnPinUnpinCommand);
COMMAND_FOR_METHOD(MemoryItemPressed, StandardCalculatorViewModel::OnMemoryItemPressed);
COMMAND_FOR_METHOD(MemoryAdd, StandardCalculatorViewModel::OnMemoryAdd);
COMMAND_FOR_METHOD(MemorySubtract, StandardCalculatorViewModel::OnMemorySubtract);
event HideMemoryClickedHandler^ HideMemoryClicked;
event ProgModeRadixChangeHandler^ ProgModeRadixChange;
event HideMemoryClickedHandler ^ HideMemoryClicked;
event ProgModeRadixChangeHandler ^ ProgModeRadixChange;
property bool IsShiftChecked {
bool get() { return m_isShiftChecked; }
property bool IsShiftChecked
{
bool get()
{
return m_isShiftChecked;
}
void set(bool value)
{
if (m_isShiftChecked != value)
@@ -106,8 +110,12 @@ namespace CalculatorApp
}
}
property bool IsBitFlipChecked {
bool get() { return m_isBitFlipChecked; }
property bool IsBitFlipChecked
{
bool get()
{
return m_isBitFlipChecked;
}
void set(bool value)
{
if (m_isBitFlipChecked != value)
@@ -120,8 +128,12 @@ namespace CalculatorApp
}
}
property bool IsBinaryBitFlippingEnabled {
bool get() { return m_isBinaryBitFlippingEnabled; }
property bool IsBinaryBitFlippingEnabled
{
bool get()
{
return m_isBinaryBitFlippingEnabled;
}
void set(bool value)
{
if (m_isBinaryBitFlippingEnabled != value)
@@ -132,8 +144,12 @@ namespace CalculatorApp
}
}
property bool IsStandard {
bool get() { return m_isStandard; }
property bool IsStandard
{
bool get()
{
return m_isStandard;
}
void set(bool value)
{
if (m_isStandard != value)
@@ -149,8 +165,12 @@ namespace CalculatorApp
}
}
property bool IsScientific {
bool get() { return m_isScientific; }
property bool IsScientific
{
bool get()
{
return m_isScientific;
}
void set(bool value)
{
if (m_isScientific != value)
@@ -166,8 +186,12 @@ namespace CalculatorApp
}
}
property bool IsProgrammer {
bool get() { return m_isProgrammer; }
property bool IsProgrammer
{
bool get()
{
return m_isProgrammer;
}
void set(bool value)
{
if (m_isProgrammer != value)
@@ -189,9 +213,14 @@ namespace CalculatorApp
}
}
property bool IsEditingEnabled {
bool get() { return m_isEditingEnabled; }
void set(bool value) {
property bool IsEditingEnabled
{
bool get()
{
return m_isEditingEnabled;
}
void set(bool value)
{
if (m_isEditingEnabled != value)
{
// Numbers::Common::KeyboardShortcutManager::IsCalculatorInEditingMode = value;
@@ -207,13 +236,22 @@ namespace CalculatorApp
}
}
property bool IsEngineRecording {
bool get() { return m_standardCalculatorManager.IsEngineRecording(); }
property bool IsEngineRecording
{
bool get()
{
return m_standardCalculatorManager.IsEngineRecording();
}
}
property bool IsOperandEnabled {
bool get() { return m_isOperandEnabled; }
void set(bool value) {
property bool IsOperandEnabled
{
bool get()
{
return m_isOperandEnabled;
}
void set(bool value)
{
if (m_isOperandEnabled != value)
{
m_isOperandEnabled = value;
@@ -227,8 +265,14 @@ namespace CalculatorApp
property int TokenPosition
{
int get() { return m_tokenPosition; }
void set(int value) { m_tokenPosition = value; }
int get()
{
return m_tokenPosition;
}
void set(int value)
{
m_tokenPosition = value;
}
}
property Platform::String^ SelectedExpressionLastData
@@ -239,51 +283,64 @@ namespace CalculatorApp
property bool KeyPressed
{
bool get() { return m_keyPressed; }
void set(bool value) { m_keyPressed = value; }
bool get()
{
return m_keyPressed;
}
void set(bool value)
{
m_keyPressed = value;
}
}
property bool IsOperandUpdatedUsingViewModel
{
bool get() { return m_operandUpdated; }
void set(bool value) { m_operandUpdated = value; }
bool get()
{
return m_operandUpdated;
}
void set(bool value)
{
m_operandUpdated = value;
}
}
property bool IsOperandTextCompletelySelected
{
bool get() { return m_completeTextSelection; }
void set(bool value) { m_completeTextSelection = value; }
}
property Platform::String^ LeftParenthesisAutomationName
{
Platform::String^ get()
bool get()
{
return GetLeftParenthesisAutomationName();
return m_completeTextSelection;
}
void set(bool value)
{
m_completeTextSelection = value;
}
}
internal:
void OnPaste(Platform::String^ pastedString, CalculatorApp::Common::ViewMode mode);
void OnCopyCommand(Platform::Object^ parameter);
void OnPasteCommand(Platform::Object^ parameter);
internal : void OnPaste(Platform::String ^ pastedString, CalculatorApp::Common::ViewMode mode);
void OnCopyCommand(Platform::Object ^ parameter);
void OnPasteCommand(Platform::Object ^ parameter);
NumbersAndOperatorsEnum MapCharacterToButtonId(const wchar_t ch, bool& canSendNegate);
// Memory feature related methods. They are internal because they need to called from the MainPage code-behind
void OnMemoryButtonPressed();
void OnMemoryItemPressed(Platform::Object^ memoryItemPosition);
void OnMemoryAdd(Platform::Object^ memoryItemPosition);
void OnMemorySubtract(Platform::Object^ memoryItemPosition);
void OnMemoryClear(_In_ Platform::Object^ memoryItemPosition);
void OnPinUnpinCommand(Platform::Object^ parameter);
void OnMemoryItemPressed(Platform::Object ^ memoryItemPosition);
void OnMemoryAdd(Platform::Object ^ memoryItemPosition);
void OnMemorySubtract(Platform::Object ^ memoryItemPosition);
void OnMemoryClear(_In_ Platform::Object ^ memoryItemPosition);
void OnPinUnpinCommand(Platform::Object ^ parameter);
void SetPrimaryDisplay(_In_ std::wstring const&displayString, _In_ bool isError);
void SetPrimaryDisplay(_In_ std::wstring const& displayString, _In_ bool isError);
void DisplayPasteError();
void SetTokens(_Inout_ std::shared_ptr<CalculatorVector<std::pair<std::wstring, int>>> const &tokens);
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);
void SetHistoryExpressionDisplay(_Inout_ std::shared_ptr<CalculatorVector<std::pair<std::wstring, int>>> const &tokens, _Inout_ std::shared_ptr<CalculatorVector <std::shared_ptr<IExpressionCommand>>> const &commands);
void SetParenthesisCount(_In_ const std::wstring& parenthesisCount);
void SetTokens(_Inout_ std::shared_ptr<CalculatorVector<std::pair<std::wstring, int>>> const& tokens);
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);
void SetHistoryExpressionDisplay(
_Inout_ std::shared_ptr<CalculatorVector<std::pair<std::wstring, int>>> const& tokens,
_Inout_ std::shared_ptr<CalculatorVector<std::shared_ptr<IExpressionCommand>>> const& commands);
void SetParenthesisCount(_In_ unsigned int parenthesisCount);
void SetOpenParenthesisCountNarratorAnnouncement();
void OnNoRightParenAdded();
void SetNoParenAddedNarratorAnnouncement();
@@ -291,14 +348,12 @@ namespace CalculatorApp
void OnBinaryOperatorReceived();
void OnMemoryItemChanged(unsigned int indexOfMemory);
Platform::Array<unsigned char>^ Serialize();
void Deserialize(Platform::Array<unsigned char>^ state);
Platform::String^ GetLocalizedStringFormat(Platform::String^ format, Platform::String^ displayValue);
void OnPropertyChanged(Platform::String^ propertyname);
Platform::String ^ GetLocalizedStringFormat(Platform::String ^ format, Platform::String ^ displayValue);
void OnPropertyChanged(Platform::String ^ propertyname);
void SetCalculatorType(CalculatorApp::Common::ViewMode targetState);
Platform::String^ GetRawDisplayValue();
Platform::String ^ GetRawDisplayValue();
void Recalculate(bool fromHistory = false);
bool IsOperator(CalculationManager::Command cmdenum);
void FtoEButtonToggled();
@@ -306,10 +361,19 @@ namespace CalculatorApp
void SetMemorizedNumbersString();
void SwitchAngleType(NumbersAndOperatorsEnum num);
void ResetDisplay();
RADIX_TYPE GetCurrentRadixType() { return (RADIX_TYPE)m_CurrentRadixType; }
RADIX_TYPE GetCurrentRadixType()
{
return (RADIX_TYPE)m_CurrentRadixType;
}
void SetPrecision(int32_t precision);
void UpdateMaxIntDigits() { m_standardCalculatorManager.UpdateMaxIntDigits(); }
NumbersAndOperatorsEnum GetCurrentAngleType() { return m_CurrentAngleType; }
void UpdateMaxIntDigits()
{
m_standardCalculatorManager.UpdateMaxIntDigits();
}
NumbersAndOperatorsEnum GetCurrentAngleType()
{
return m_CurrentAngleType;
}
private:
void SetMemorizedNumbers(const std::vector<std::wstring>& memorizedNumbers);
@@ -321,21 +385,21 @@ namespace CalculatorApp
CalculatorDisplay m_calculatorDisplay;
CalculatorApp::EngineResourceProvider m_resourceProvider;
CalculationManager::CalculatorManager m_standardCalculatorManager;
Platform::String^ m_expressionAutomationNameFormat;
Platform::String^ m_localizedCalculationResultAutomationFormat;
Platform::String^ m_localizedCalculationResultDecimalAutomationFormat;
Platform::String^ m_localizedHexaDecimalAutomationFormat;
Platform::String^ m_localizedDecimalAutomationFormat;
Platform::String^ m_localizedOctalAutomationFormat;
Platform::String^ m_localizedBinaryAutomationFormat;
Platform::String^ m_localizedMaxDigitsReachedAutomationFormat;
Platform::String^ m_localizedButtonPressFeedbackAutomationFormat;
Platform::String^ m_localizedMemorySavedAutomationFormat;
Platform::String^ m_localizedMemoryItemChangedAutomationFormat;
Platform::String^ m_localizedMemoryItemClearedAutomationFormat;
Platform::String^ m_localizedMemoryCleared;
Platform::String^ m_localizedOpenParenthesisCountChangedAutomationFormat;
Platform::String^ m_localizedNoRightParenthesisAddedFormat;
Platform::String ^ m_expressionAutomationNameFormat;
Platform::String ^ m_localizedCalculationResultAutomationFormat;
Platform::String ^ m_localizedCalculationResultDecimalAutomationFormat;
Platform::String ^ m_localizedHexaDecimalAutomationFormat;
Platform::String ^ m_localizedDecimalAutomationFormat;
Platform::String ^ m_localizedOctalAutomationFormat;
Platform::String ^ m_localizedBinaryAutomationFormat;
Platform::String ^ m_localizedMaxDigitsReachedAutomationFormat;
Platform::String ^ m_localizedButtonPressFeedbackAutomationFormat;
Platform::String ^ m_localizedMemorySavedAutomationFormat;
Platform::String ^ m_localizedMemoryItemChangedAutomationFormat;
Platform::String ^ m_localizedMemoryItemClearedAutomationFormat;
Platform::String ^ m_localizedMemoryCleared;
Platform::String ^ m_localizedOpenParenthesisCountChangedAutomationFormat;
Platform::String ^ m_localizedNoRightParenthesisAddedFormat;
bool m_pinned;
bool m_isOperandEnabled;
@@ -352,28 +416,27 @@ namespace CalculatorApp
bool m_operandUpdated;
bool m_completeTextSelection;
bool m_isLastOperationHistoryLoad;
Platform::String^ m_selectedExpressionLastData;
Common::DisplayExpressionToken^ m_selectedExpressionToken;
Platform::String^ m_leftParenthesisAutomationFormat;
Platform::String ^ m_selectedExpressionLastData;
Common::DisplayExpressionToken ^ m_selectedExpressionToken;
Platform::String^ LocalizeDisplayValue(_In_ std::wstring const &displayValue, _In_ bool isError);
Platform::String^ CalculateNarratorDisplayValue(_In_ std::wstring const &displayValue, _In_ Platform::String^ localizedDisplayValue, _In_ bool isError);
CalculatorApp::Common::Automation::NarratorAnnouncement^ GetDisplayUpdatedNarratorAnnouncement();
Platform::String^ GetCalculatorExpressionAutomationName();
Platform::String^ GetNarratorStringReadRawNumbers(_In_ Platform::String^ localizedDisplayValue);
Platform::String ^ LocalizeDisplayValue(_In_ std::wstring const& displayValue, _In_ bool isError);
Platform::String
^ CalculateNarratorDisplayValue(_In_ std::wstring const& displayValue, _In_ Platform::String ^ localizedDisplayValue, _In_ bool isError);
CalculatorApp::Common::Automation::NarratorAnnouncement ^ GetDisplayUpdatedNarratorAnnouncement();
Platform::String ^ GetCalculatorExpressionAutomationName();
Platform::String ^ GetNarratorStringReadRawNumbers(_In_ Platform::String ^ localizedDisplayValue);
CalculationManager::Command ConvertToOperatorsEnum(NumbersAndOperatorsEnum operation);
void DisableButtons(CalculationManager::CommandType selectedExpressionCommandType);
Platform::String^ GetLeftParenthesisAutomationName();
Platform::String^ m_feedbackForButtonPress;
void OnButtonPressed(Platform::Object^ parameter);
void OnClearMemoryCommand(Platform::Object^ parameter);
Platform::String ^ m_feedbackForButtonPress;
void OnButtonPressed(Platform::Object ^ parameter);
void OnClearMemoryCommand(Platform::Object ^ parameter);
std::wstring AddPadding(std::wstring);
size_t LengthWithoutPadding(std::wstring);
std::shared_ptr<CalculatorVector<std::pair<std::wstring, int>>> m_tokens;
std::shared_ptr<CalculatorVector <std::shared_ptr<IExpressionCommand>>> m_commands;
std::shared_ptr<CalculatorVector<std::shared_ptr<IExpressionCommand>>> m_commands;
// Token types
bool IsUnaryOp(int nOpCode);

View File

@@ -1,4 +1,4 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#include "pch.h"
@@ -45,7 +45,7 @@ constexpr unsigned int TIMER_INTERVAL_IN_MS = 10000;
const TimeSpan SUPPLEMENTARY_VALUES_INTERVAL = { 10 * TIMER_INTERVAL_IN_MS };
static Unit^ EMPTY_UNIT = ref new Unit(UCM::EMPTY_UNIT);
static Unit ^ EMPTY_UNIT = ref new Unit(UCM::EMPTY_UNIT);
constexpr size_t UNIT_LIST = 0;
constexpr size_t SELECTED_SOURCE_UNIT = 1;
@@ -89,47 +89,48 @@ namespace CalculatorApp::ViewModel::UnitConverterResourceKeys
StringReference CurrencyRatesUpdateFailed(L"CurrencyRatesUpdateFailed");
}
UnitConverterViewModel::UnitConverterViewModel(const shared_ptr<UCM::IUnitConverter>& model) :
m_model(model),
m_resettingTimer(false),
m_value1cp(ConversionParameter::Source),
m_Value1Active(true),
m_Value2Active(false),
m_Value1("0"),
m_Value2("0"),
m_valueToUnlocalized(L"0"),
m_valueFromUnlocalized(L"0"),
m_relocalizeStringOnSwitch(false),
m_Categories(ref new Vector<Category^>()),
m_Units(ref new Vector<Unit^>()),
m_SupplementaryResults(ref new Vector<SupplementaryResult^>),
m_IsDropDownOpen(false),
m_IsDropDownEnabled(true),
m_IsCurrencyLoadingVisible(false),
m_isCurrencyDataLoaded(false),
m_lastAnnouncedFrom(L""),
m_lastAnnouncedTo(L""),
m_lastAnnouncedConversionResult(L""),
m_isValue1Updating(false),
m_isValue2Updating(false),
m_Announcement(nullptr),
m_Mode(ViewMode::None),
m_CurrencySymbol1(L""),
m_CurrencySymbol2(L""),
m_IsCurrencyCurrentCategory(false),
m_CurrencyRatioEquality(L""),
m_CurrencyRatioEqualityAutomationName(L""),
m_isInputBlocked(false),
m_CurrencyDataLoadFailed(false)
UnitConverterViewModel::UnitConverterViewModel(const shared_ptr<UCM::IUnitConverter>& model)
: m_model(model)
, m_resettingTimer(false)
, m_value1cp(ConversionParameter::Source)
, m_Value1Active(true)
, m_Value2Active(false)
, m_Value1("0")
, m_Value2("0")
, m_valueToUnlocalized(L"0")
, m_valueFromUnlocalized(L"0")
, m_relocalizeStringOnSwitch(false)
, m_Categories(ref new Vector<Category ^>())
, m_Units(ref new Vector<Unit ^>())
, m_SupplementaryResults(ref new Vector<SupplementaryResult ^>)
, m_IsDropDownOpen(false)
, m_IsDropDownEnabled(true)
, m_IsCurrencyLoadingVisible(false)
, m_isCurrencyDataLoaded(false)
, m_lastAnnouncedFrom(L"")
, m_lastAnnouncedTo(L"")
, m_lastAnnouncedConversionResult(L"")
, m_isValue1Updating(false)
, m_isValue2Updating(false)
, m_Announcement(nullptr)
, m_Mode(ViewMode::None)
, m_CurrencySymbol1(L"")
, m_CurrencySymbol2(L"")
, m_IsCurrencyCurrentCategory(false)
, m_CurrencyRatioEquality(L"")
, m_CurrencyRatioEqualityAutomationName(L"")
, m_isInputBlocked(false)
, m_CurrencyDataLoadFailed(false)
{
auto localizationService = LocalizationService::GetInstance();
m_model->SetViewModelCallback(make_shared<UnitConverterVMCallback>(this));
m_model->SetViewModelCurrencyCallback(make_shared<ViewModelCurrencyCallback>(this));
m_decimalFormatter = LocalizationService::GetRegionalSettingsAwareDecimalFormatter();
m_decimalFormatter = localizationService->GetRegionalSettingsAwareDecimalFormatter();
m_decimalFormatter->FractionDigits = 0;
m_decimalFormatter->IsGrouped = true;
m_decimalSeparator = LocalizationSettings::GetInstance().GetDecimalSeparator();
m_currencyFormatter = LocalizationService::GetRegionalSettingsAwareCurrencyFormatter();
m_currencyFormatter = localizationService->GetRegionalSettingsAwareCurrencyFormatter();
m_currencyFormatter->IsGrouped = true;
m_currencyFormatter->Mode = CurrencyFormatterMode::UseCurrencyCode;
m_currencyFormatter->ApplyRoundingForCurrency(RoundingAlgorithm::RoundHalfDown);
@@ -164,13 +165,17 @@ void UnitConverterViewModel::PopulateData()
InitializeView();
}
void UnitConverterViewModel::OnCategoryChanged(Object^ parameter)
void UnitConverterViewModel::OnCategoryChanged(Object ^ parameter)
{
m_model->SendCommand(UCM::Command::Clear);
ResetCategory();
}
void UnitConverterViewModel::ResetCategory()
{
UCM::Category currentCategory = CurrentCategory->GetModelCategory();
IsCurrencyCurrentCategory = currentCategory.id == NavCategory::Serialize(ViewMode::Currency);
m_model->SendCommand(UCM::Command::Clear);
m_isInputBlocked = false;
SetSelectedUnits();
@@ -206,9 +211,9 @@ void UnitConverterViewModel::BuildUnitList(const vector<UCM::Unit>& modelUnitLis
}
}
Unit^ UnitConverterViewModel::FindUnitInList(UCM::Unit target)
Unit ^ UnitConverterViewModel::FindUnitInList(UCM::Unit target)
{
for (Unit^ vmUnit : m_Units)
for (Unit ^ vmUnit : m_Units)
{
UCM::Unit modelUnit = vmUnit->GetModelUnit();
if (modelUnit.id == target.id)
@@ -220,7 +225,7 @@ Unit^ UnitConverterViewModel::FindUnitInList(UCM::Unit target)
return EMPTY_UNIT;
}
void UnitConverterViewModel::OnUnitChanged(Object^ parameter)
void UnitConverterViewModel::OnUnitChanged(Object ^ parameter)
{
if ((m_Unit1 == nullptr) || (m_Unit2 == nullptr))
{
@@ -245,7 +250,7 @@ void UnitConverterViewModel::OnUnitChanged(Object^ parameter)
}
}
void UnitConverterViewModel::OnSwitchActive(Platform::Object^ unused)
void UnitConverterViewModel::OnSwitchActive(Platform::Object ^ unused)
{
// this can be false if this switch occurs without the user having explicitly updated any strings
// (for example, during deserialization). We only want to try this cleanup if there's actually
@@ -278,9 +283,9 @@ void UnitConverterViewModel::OnSwitchActive(Platform::Object^ unused)
m_model->SwitchActive(m_valueFromUnlocalized);
}
String^ UnitConverterViewModel::ConvertToLocalizedString(const std::wstring& stringToLocalize, bool allowPartialStrings)
String ^ UnitConverterViewModel::ConvertToLocalizedString(const std::wstring& stringToLocalize, bool allowPartialStrings)
{
Platform::String^ result;
Platform::String ^ result;
if (stringToLocalize.empty())
{
@@ -364,7 +369,7 @@ String^ UnitConverterViewModel::ConvertToLocalizedString(const std::wstring& str
// Since the output from GetLocaleInfoEx() and DecimalFormatter are differing for decimal string
// we are adding the below work-around of editing the string returned by DecimalFormatter
// and replacing the decimal separator with the one returned by GetLocaleInfoEx()
String^ formattedSampleString = m_decimalFormatter->Format(stod("1.1"));
String ^ formattedSampleString = m_decimalFormatter->Format(stod("1.1"));
wstring formattedSampleWString = wstring(formattedSampleString->Data());
wstring resultWithDecimal = wstring(result->Data());
@@ -394,7 +399,7 @@ String^ UnitConverterViewModel::ConvertToLocalizedString(const std::wstring& str
void UnitConverterViewModel::DisplayPasteError()
{
String^ errorMsg = AppResourceProvider::GetInstance().GetCEngineString(SIDS_DOMAIN); /*SIDS_DOMAIN is for "invalid input"*/
String ^ errorMsg = AppResourceProvider::GetInstance().GetCEngineString(StringReference(SIDS_DOMAIN)); /*SIDS_DOMAIN is for "invalid input"*/
Value1 = errorMsg;
Value2 = errorMsg;
m_relocalizeStringOnSwitch = false;
@@ -402,9 +407,9 @@ void UnitConverterViewModel::DisplayPasteError()
void UnitConverterViewModel::UpdateDisplay(const wstring& from, const wstring& to)
{
String^ fromStr = this->ConvertToLocalizedString(from, true);
String ^ fromStr = this->ConvertToLocalizedString(from, true);
UpdateInputBlocked(from);
String^ toStr = this->ConvertToLocalizedString(to, true);
String ^ toStr = this->ConvertToLocalizedString(to, true);
bool updatedValueFrom = ValueFrom != fromStr;
bool updatedValueTo = ValueTo != toStr;
@@ -464,12 +469,12 @@ void UnitConverterViewModel::UpdateSupplementaryResults(const std::vector<std::t
ref new TimerDestroyedHandler(this, &UnitConverterViewModel::SupplementaryResultsTimerCancel, TIMER_CALLBACK_CONTEXT));
}
void UnitConverterViewModel::OnValueActivated(IActivatable^ control)
void UnitConverterViewModel::OnValueActivated(IActivatable ^ control)
{
control->IsActive = true;
}
void UnitConverterViewModel::OnButtonPressed(Platform::Object^ parameter)
void UnitConverterViewModel::OnButtonPressed(Platform::Object ^ parameter)
{
NumbersAndOperatorsEnum numOpEnum = CalculatorButtonPressedEventArgs::GetOperationFromCommandParameter(parameter);
UCM::Command command = CommandFromButtonId(numOpEnum);
@@ -480,18 +485,8 @@ void UnitConverterViewModel::OnButtonPressed(Platform::Object^ parameter)
return;
}
static const vector<UCM::Command> OPERANDS = {
UCM::Command::Zero,
UCM::Command::One,
UCM::Command::Two,
UCM::Command::Three,
UCM::Command::Four,
UCM::Command::Five,
UCM::Command::Six,
UCM::Command::Seven,
UCM::Command::Eight,
UCM::Command::Nine
};
static const vector<UCM::Command> OPERANDS = { UCM::Command::Zero, UCM::Command::One, UCM::Command::Two, UCM::Command::Three, UCM::Command::Four,
UCM::Command::Five, UCM::Command::Six, UCM::Command::Seven, UCM::Command::Eight, UCM::Command::Nine };
if (find(begin(OPERANDS), end(OPERANDS), command) != OPERANDS.end())
{
@@ -509,14 +504,14 @@ void UnitConverterViewModel::OnButtonPressed(Platform::Object^ parameter)
m_model->SendCommand(command);
}
void UnitConverterViewModel::OnCopyCommand(Platform::Object^ parameter)
void UnitConverterViewModel::OnCopyCommand(Platform::Object ^ parameter)
{
//EventWriteClipboardCopy_Start();
// EventWriteClipboardCopy_Start();
CopyPasteManager::CopyToClipboard(ref new Platform::String(m_valueFromUnlocalized.c_str()));
//EventWriteClipboardCopy_Stop();
// EventWriteClipboardCopy_Stop();
}
void UnitConverterViewModel::OnPasteCommand(Platform::Object^ parameter)
void UnitConverterViewModel::OnPasteCommand(Platform::Object ^ parameter)
{
// if there's nothing to copy early out
if (!CopyPasteManager::HasStringToPaste())
@@ -525,13 +520,10 @@ void UnitConverterViewModel::OnPasteCommand(Platform::Object^ parameter)
}
// Ensure that the paste happens on the UI thread
//EventWriteClipboardPaste_Start();
// EventWriteClipboardPaste_Start();
// Any converter ViewMode is fine here.
CopyPasteManager::GetStringToPaste(m_Mode, NavCategory::GetGroupType(m_Mode)).then(
[this](String^ pastedString)
{
OnPaste(pastedString, m_Mode);
}, concurrency::task_continuation_context::use_current());
CopyPasteManager::GetStringToPaste(m_Mode, NavCategory::GetGroupType(m_Mode))
.then([this](String ^ pastedString) { OnPaste(pastedString, m_Mode); }, concurrency::task_continuation_context::use_current());
}
void UnitConverterViewModel::InitializeView()
@@ -539,7 +531,7 @@ void UnitConverterViewModel::InitializeView()
vector<UCM::Category> categories = m_model->GetCategories();
for (UINT i = 0; i < categories.size(); i++)
{
Category^ category = ref new Category(categories[i]);
Category ^ category = ref new Category(categories[i]);
m_Categories->Append(category);
}
@@ -547,7 +539,7 @@ void UnitConverterViewModel::InitializeView()
CurrentCategory = ref new Category(m_model->GetCurrentCategory());
}
void UnitConverterViewModel::OnPropertyChanged(Platform::String^ prop)
void UnitConverterViewModel::OnPropertyChanged(Platform::String ^ prop)
{
static bool isCategoryChanging = false;
@@ -621,58 +613,12 @@ void UnitConverterViewModel::OnPropertyChanged(Platform::String^ prop)
}
}
String^ UnitConverterViewModel::Serialize()
{
wstringstream out(wstringstream::out);
const wchar_t * delimiter = L"[;;;]";
out << std::to_wstring(m_resettingTimer) << delimiter;
out << std::to_wstring(static_cast<int>(m_value1cp)) << delimiter;
out << m_Value1Active << delimiter << m_Value2Active << delimiter;
out << m_Value1->Data() << delimiter << m_Value2->Data() << delimiter;
out << m_valueFromUnlocalized << delimiter << m_valueToUnlocalized << delimiter << L"[###]";
wstring unitConverterSerializedData = m_model->Serialize();
if (!unitConverterSerializedData.empty())
{
out << m_model->Serialize() << L"[###]";
String^ serializedData = ref new String(wstring(out.str()).c_str());
return serializedData;
}
return nullptr;
}
void UnitConverterViewModel::Deserialize(Platform::String^ state)
{
wstring serializedData = wstring(state->Data());
vector<wstring> tokens = UCM::UnitConverter::StringToVector(serializedData, L"[###]");
assert(tokens.size() >= 2);
vector<wstring> viewModelData = UCM::UnitConverter::StringToVector(tokens[0], L"[;;;]");
assert(viewModelData.size() == EXPECTEDVIEWMODELDATATOKENS);
m_resettingTimer = (viewModelData[0].compare(L"1") == 0);
m_value1cp = (ConversionParameter)_wtoi(viewModelData[1].c_str());
m_Value1Active = (viewModelData[2].compare(L"1") == 0);
m_Value2Active = (viewModelData[3].compare(L"1") == 0);
m_Value1 = ref new String(viewModelData[4].c_str());
m_Value2 = ref new String(viewModelData[5].c_str());
m_valueFromUnlocalized = viewModelData[6];
m_valueToUnlocalized = viewModelData[7];
wstringstream modelData(wstringstream::out);
for (unsigned int i = 1; i < tokens.size(); i++)
{
modelData << tokens[i] << L"[###]";
}
m_model->DeSerialize(modelData.str());
InitializeView();
RaisePropertyChanged(nullptr); // Update since all props have been updated.
}
// Saving User Preferences of Category and Associated-Units across Sessions.
void UnitConverterViewModel::SaveUserPreferences()
{
if (UnitsAreValid())
{
ApplicationDataContainer^ localSettings = ApplicationData::Current->LocalSettings;
ApplicationDataContainer ^ localSettings = ApplicationData::Current->LocalSettings;
if (!m_IsCurrencyCurrentCategory)
{
auto userPreferences = m_model->SaveUserPreferences();
@@ -693,10 +639,10 @@ void UnitConverterViewModel::RestoreUserPreferences()
{
if (!IsCurrencyCurrentCategory)
{
ApplicationDataContainer^ localSettings = ApplicationData::Current->LocalSettings;
ApplicationDataContainer ^ localSettings = ApplicationData::Current->LocalSettings;
if (localSettings->Values->HasKey(ref new String(L"UnitConverterPreferences")))
{
String^ userPreferences = safe_cast<String^>(localSettings->Values->Lookup(ref new String(L"UnitConverterPreferences")));
String ^ userPreferences = safe_cast<String ^>(localSettings->Values->Lookup(ref new String(L"UnitConverterPreferences")));
m_model->RestoreUserPreferences(userPreferences->Data());
}
}
@@ -706,10 +652,12 @@ void UnitConverterViewModel::OnCurrencyDataLoadFinished(bool didLoad)
{
m_isCurrencyDataLoaded = true;
CurrencyDataLoadFailed = !didLoad;
ResetView();
m_model->ResetCategoriesAndRatios();
m_model->Calculate();
ResetCategory();
StringReference key = didLoad ? UnitConverterResourceKeys::CurrencyRatesUpdated : UnitConverterResourceKeys::CurrencyRatesUpdateFailed;
String^ announcement = AppResourceProvider::GetInstance().GetResourceString(key);
String ^ announcement = AppResourceProvider::GetInstance().GetResourceString(key);
Announcement = CalculatorAnnouncement::GetUpdateCurrencyRatesAnnouncement(announcement);
}
@@ -724,18 +672,19 @@ void UnitConverterViewModel::RefreshCurrencyRatios()
m_isCurrencyDataLoaded = false;
IsCurrencyLoadingVisible = true;
String^ announcement = AppResourceProvider::GetInstance().GetResourceString(UnitConverterResourceKeys::UpdatingCurrencyRates);
String ^ announcement = AppResourceProvider::GetInstance().GetResourceString(UnitConverterResourceKeys::UpdatingCurrencyRates);
Announcement = CalculatorAnnouncement::GetUpdateCurrencyRatesAnnouncement(announcement);
auto refreshTask = create_task(m_model->RefreshCurrencyRatios());
refreshTask.then([this](const pair<bool, wstring>& refreshResult)
{
bool didLoad = refreshResult.first;
wstring timestamp = refreshResult.second;
auto refreshTask = create_task([this] { return m_model->RefreshCurrencyRatios().get(); });
refreshTask.then(
[this](const pair<bool, wstring>& refreshResult) {
bool didLoad = refreshResult.first;
wstring timestamp = refreshResult.second;
OnCurrencyTimestampUpdated(timestamp, false /*isWeekOldData*/);
OnCurrencyDataLoadFinished(didLoad);
}, task_continuation_context::use_current());
OnCurrencyTimestampUpdated(timestamp, false /*isWeekOldData*/);
OnCurrencyDataLoadFinished(didLoad);
},
task_continuation_context::use_current());
}
void UnitConverterViewModel::OnNetworkBehaviorChanged(_In_ NetworkAccessBehavior newBehavior)
@@ -800,12 +749,12 @@ UnitConversionManager::Command UnitConverterViewModel::CommandFromButtonId(Numbe
return command;
}
void UnitConverterViewModel::SupplementaryResultsTimerTick(ThreadPoolTimer^ timer)
void UnitConverterViewModel::SupplementaryResultsTimerTick(ThreadPoolTimer ^ timer)
{
timer->Cancel();
}
void UnitConverterViewModel::SupplementaryResultsTimerCancel(ThreadPoolTimer^ timer)
void UnitConverterViewModel::SupplementaryResultsTimerCancel(ThreadPoolTimer ^ timer)
{
if (!m_resettingTimer)
{
@@ -818,14 +767,12 @@ void UnitConverterViewModel::RefreshSupplementaryResults()
m_cacheMutex.lock();
m_SupplementaryResults->Clear();
vector<SupplementaryResult^> whimsicals;
vector<SupplementaryResult ^> whimsicals;
for (tuple<wstring, UCM::Unit> suggestedValue : m_cachedSuggestedValues)
{
SupplementaryResult^ result =
ref new SupplementaryResult(
this->ConvertToLocalizedString(get<0>(suggestedValue), false),
ref new Unit(get<1>(suggestedValue)));
SupplementaryResult ^ result =
ref new SupplementaryResult(this->ConvertToLocalizedString(get<0>(suggestedValue), false), ref new Unit(get<1>(suggestedValue)));
if (result->IsWhimsical())
{
whimsicals.push_back(result);
@@ -843,7 +790,7 @@ void UnitConverterViewModel::RefreshSupplementaryResults()
m_cacheMutex.unlock();
RaisePropertyChanged(SupplementaryResultsPropertyName);
//EventWriteConverterSupplementaryResultsUpdated();
// EventWriteConverterSupplementaryResultsUpdated();
}
// When UpdateDisplay is called, the ViewModel will remember the From/To unlocalized display values
@@ -852,16 +799,13 @@ void UnitConverterViewModel::RefreshSupplementaryResults()
// values are not both zero.
void UnitConverterViewModel::AnnounceConversionResult()
{
if ((m_valueFromUnlocalized != m_lastAnnouncedFrom
|| m_valueToUnlocalized != m_lastAnnouncedTo)
&& Unit1 != nullptr
&& Unit2 != nullptr)
if ((m_valueFromUnlocalized != m_lastAnnouncedFrom || m_valueToUnlocalized != m_lastAnnouncedTo) && Unit1 != nullptr && Unit2 != nullptr)
{
m_lastAnnouncedFrom = m_valueFromUnlocalized;
m_lastAnnouncedTo = m_valueToUnlocalized;
Unit^ unitFrom = Value1Active ? Unit1 : Unit2;
Unit^ unitTo = (unitFrom == Unit1) ? Unit2 : Unit1;
Unit ^ unitFrom = Value1Active ? Unit1 : Unit2;
Unit ^ unitTo = (unitFrom == Unit1) ? Unit2 : Unit1;
m_lastAnnouncedConversionResult = GetLocalizedConversionResultStringFormat(ValueFrom, unitFrom->Name, ValueTo, unitTo->Name);
Announcement = CalculatorAnnouncement::GetDisplayUpdatedAnnouncement(m_lastAnnouncedConversionResult);
@@ -872,16 +816,14 @@ void UnitConverterViewModel::UpdateInputBlocked(_In_ const wstring& currencyInpu
{
// currencyInput is in en-US and has the default decimal separator, so this is safe to do.
auto posOfDecimal = currencyInput.find(L'.');
m_isInputBlocked = false;
m_isInputBlocked = false;
if (posOfDecimal != wstring::npos && IsCurrencyCurrentCategory)
{
m_isInputBlocked = (posOfDecimal + static_cast<size_t>(m_currencyMaxFractionDigits) + 1 == currencyInput.length());
}
}
NumbersAndOperatorsEnum UnitConverterViewModel::MapCharacterToButtonId(
const wchar_t ch,
bool& canSendNegate)
NumbersAndOperatorsEnum UnitConverterViewModel::MapCharacterToButtonId(const wchar_t ch, bool& canSendNegate)
{
static_assert(NumbersAndOperatorsEnum::Zero < NumbersAndOperatorsEnum::One, "NumbersAndOperatorsEnum order is invalid");
static_assert(NumbersAndOperatorsEnum::One < NumbersAndOperatorsEnum::Two, "NumbersAndOperatorsEnum order is invalid");
@@ -931,7 +873,8 @@ NumbersAndOperatorsEnum UnitConverterViewModel::MapCharacterToButtonId(
{
if (LocalizationSettings::GetInstance().IsLocalizedDigit(ch))
{
mappedValue = NumbersAndOperatorsEnum::Zero + static_cast<NumbersAndOperatorsEnum>(ch - LocalizationSettings::GetInstance().GetDigitSymbolFromEnUsDigit(L'0'));
mappedValue = NumbersAndOperatorsEnum::Zero
+ static_cast<NumbersAndOperatorsEnum>(ch - LocalizationSettings::GetInstance().GetDigitSymbolFromEnUsDigit(L'0'));
canSendNegate = true;
}
}
@@ -939,7 +882,7 @@ NumbersAndOperatorsEnum UnitConverterViewModel::MapCharacterToButtonId(
return mappedValue;
}
void UnitConverterViewModel::OnPaste(String^ stringToPaste, ViewMode mode)
void UnitConverterViewModel::OnPaste(String ^ stringToPaste, ViewMode mode)
{
// If pastedString is invalid("NoOp") then display pasteError else process the string
if (stringToPaste == StringReference(CopyPasteManager::PasteErrorString))
@@ -1007,9 +950,9 @@ void UnitConverterViewModel::OnPaste(String^ stringToPaste, ViewMode mode)
}
}
String^ UnitConverterViewModel::GetLocalizedAutomationName(_In_ String^ displayvalue, _In_ String^ unitname, _In_ String^ format)
String ^ UnitConverterViewModel::GetLocalizedAutomationName(_In_ String ^ displayvalue, _In_ String ^ unitname, _In_ String ^ format)
{
String^ valueToLocalize = displayvalue;
String ^ valueToLocalize = displayvalue;
if (displayvalue == ValueFrom && Utils::IsLastCharacterTarget(m_valueFromUnlocalized, m_decimalSeparator))
{
// Need to compute a second localized value for the automation
@@ -1022,9 +965,17 @@ String^ UnitConverterViewModel::GetLocalizedAutomationName(_In_ String^ displayv
return ref new String(localizedResult.c_str());
}
String^ UnitConverterViewModel::GetLocalizedConversionResultStringFormat(_In_ String^ fromValue, _In_ String^ fromUnit, _In_ String^ toValue, _In_ String^ toUnit)
String
^ UnitConverterViewModel::GetLocalizedConversionResultStringFormat(
_In_ String ^ fromValue,
_In_ String ^ fromUnit,
_In_ String ^ toValue,
_In_ String ^ toUnit)
{
String^ localizedString = ref new String(LocalizationStringUtil::GetLocalizedString(m_localizedConversionResultFormat->Data(), fromValue->Data(), fromUnit->Data(), toValue->Data(), toUnit->Data()).c_str());
String ^ localizedString =
ref new String(LocalizationStringUtil::GetLocalizedString(
m_localizedConversionResultFormat->Data(), fromValue->Data(), fromUnit->Data(), toValue->Data(), toUnit->Data())
.c_str());
return localizedString;
}
@@ -1046,7 +997,7 @@ void UnitConverterViewModel::UpdateValue2AutomationName()
void UnitConverterViewModel::OnMaxDigitsReached()
{
String^ format = AppResourceProvider::GetInstance().GetResourceString(UnitConverterResourceKeys::MaxDigitsReachedFormat);
String ^ format = AppResourceProvider::GetInstance().GetResourceString(UnitConverterResourceKeys::MaxDigitsReachedFormat);
const wstring& announcement = LocalizationStringUtil::GetLocalizedString(format->Data(), m_lastAnnouncedConversionResult->Data());
Announcement = CalculatorAnnouncement::GetMaxDigitsReachedAnnouncement(StringReference(announcement.c_str()));
}
@@ -1058,27 +1009,18 @@ bool UnitConverterViewModel::UnitsAreValid()
void UnitConverterViewModel::StartConversionResultTimer()
{
m_conversionResultTaskHelper = make_unique<ConversionResultTaskHelper>(
CONVERSION_FINALIZED_DELAY_IN_MS, [this]()
{
m_conversionResultTaskHelper = make_unique<ConversionResultTaskHelper>(CONVERSION_FINALIZED_DELAY_IN_MS, [this]() {
if (UnitsAreValid())
{
String^ valueFrom = m_Value1Active ? m_Value1 : m_Value2;
String^ valueTo = m_Value1Active ? m_Value2 : m_Value1;
TraceLogger::GetInstance().LogConversionResult(
valueFrom->Data(),
UnitFrom->ToString()->Data(),
valueTo->Data(),
UnitTo->ToString()->Data());
String ^ valueFrom = m_Value1Active ? m_Value1 : m_Value2;
String ^ valueTo = m_Value1Active ? m_Value2 : m_Value1;
TraceLogger::GetInstance().LogConversionResult(valueFrom->Data(), UnitFrom->ToString()->Data(), valueTo->Data(), UnitTo->ToString()->Data());
}
});
}
String^ SupplementaryResult::GetLocalizedAutomationName()
String ^ SupplementaryResult::GetLocalizedAutomationName()
{
auto format = AppResourceProvider::GetInstance().GetResourceString("SupplementaryUnit_AutomationName");
return ref new String(LocalizationStringUtil::GetLocalizedString(
format->Data(),
this->Value->Data(),
this->Unit->Name->Data()).c_str());
return ref new String(LocalizationStringUtil::GetLocalizedString(format->Data(), this->Value->Data(), this->Unit->Name->Data()).c_str());
}

View File

@@ -15,99 +15,91 @@ namespace CalculatorApp
{
namespace ViewModel
{
[Windows::UI::Xaml::Data::Bindable]
public ref class Category sealed : public Windows::UI::Xaml::Data::INotifyPropertyChanged
[Windows::UI::Xaml::Data::Bindable] public ref class Category sealed : public Windows::UI::Xaml::Data::INotifyPropertyChanged
{
internal:
Category(const UnitConversionManager::Category& category) :
m_original(category)
{ }
internal : Category(const UnitConversionManager::Category& category)
: m_original(category)
{
}
public:
OBSERVABLE_OBJECT();
property Platform::String^ Name
{
Platform::String^ get() { return ref new Platform::String(m_original.name.c_str()); }
}
property Platform::String
^ Name { Platform::String ^ get() { return ref new Platform::String(m_original.name.c_str()); } }
property Windows::UI::Xaml::Visibility NegateVisibility
property Windows::UI::Xaml::Visibility NegateVisibility
{
Windows::UI::Xaml::Visibility get()
{
return m_original.supportsNegative
? Windows::UI::Xaml::Visibility::Visible
: Windows::UI::Xaml::Visibility::Collapsed;
return m_original.supportsNegative ? Windows::UI::Xaml::Visibility::Visible : Windows::UI::Xaml::Visibility::Collapsed;
}
}
internal:
const UnitConversionManager::Category& GetModelCategory() const { return m_original; }
internal : const UnitConversionManager::Category& GetModelCategory() const
{
return m_original;
}
private:
const UnitConversionManager::Category m_original;
};
[Windows::UI::Xaml::Data::Bindable]
public ref class Unit sealed : public Windows::UI::Xaml::Data::INotifyPropertyChanged
[Windows::UI::Xaml::Data::Bindable] public ref class Unit sealed : public Windows::UI::Xaml::Data::INotifyPropertyChanged
{
internal:
Unit(const UnitConversionManager::Unit& unit) :
m_original(unit)
{ }
internal : Unit(const UnitConversionManager::Unit& unit)
: m_original(unit)
{
}
public:
OBSERVABLE_OBJECT();
property Platform::String^ Name
{
Platform::String^ get() { return ref new Platform::String(m_original.name.c_str()); }
}
property Platform::String
^ Name { Platform::String ^ get() { return ref new Platform::String(m_original.name.c_str()); } }
property Platform::String^ AccessibleName
{
Platform::String^ get() { return ref new Platform::String(m_original.accessibleName.c_str()); }
}
property Platform::String
^ AccessibleName { Platform::String ^ get() { return ref new Platform::String(m_original.accessibleName.c_str()); } }
property Platform::String^ Abbreviation
{
Platform::String^ get() { return ref new Platform::String(m_original.abbreviation.c_str()); }
}
property Platform::String
^ Abbreviation { Platform::String ^ get() { return ref new Platform::String(m_original.abbreviation.c_str()); } }
// This method is used to return the desired automation name for default unit in UnitConverter combo box.
Platform::String^ ToString() override
// This method is used to return the desired automation name for default unit in UnitConverter combo box.
Platform::String
^ ToString() override
{
return AccessibleName;
}
internal:
const UnitConversionManager::Unit& GetModelUnit() const { return m_original; }
internal : const UnitConversionManager::Unit& GetModelUnit() const
{
return m_original;
}
private:
const UnitConversionManager::Unit m_original;
};
[Windows::UI::Xaml::Data::Bindable]
public ref class SupplementaryResult sealed : public Windows::UI::Xaml::Data::INotifyPropertyChanged
[Windows::UI::Xaml::Data::Bindable] public ref class SupplementaryResult sealed : public Windows::UI::Xaml::Data::INotifyPropertyChanged
{
internal:
SupplementaryResult(Platform::String^ value, Unit^ unit) :
m_Value(value),
m_Unit(unit)
{}
internal : SupplementaryResult(Platform::String ^ value, Unit ^ unit)
: m_Value(value)
, m_Unit(unit)
{
}
bool IsWhimsical() const
{
return m_Unit->GetModelUnit().isWhimsical;
}
Platform::String^ GetLocalizedAutomationName();
Platform::String ^ GetLocalizedAutomationName();
public:
OBSERVABLE_OBJECT();
OBSERVABLE_PROPERTY_R(Platform::String^, Value);
OBSERVABLE_PROPERTY_R(CalculatorApp::ViewModel::Unit^, Unit);
OBSERVABLE_PROPERTY_R(Platform::String ^, Value);
OBSERVABLE_PROPERTY_R(CalculatorApp::ViewModel::Unit ^, Unit);
};
interface class IActivatable
@@ -115,64 +107,68 @@ namespace CalculatorApp
virtual property bool IsActive;
};
template<typename TActivatable>
template <typename TActivatable>
ref class Activatable sealed : public IActivatable
{
private:
TActivatable m_activatable;
public:
Activatable(TActivatable activatable) : m_activatable(activatable)
{ }
Activatable(TActivatable activatable)
: m_activatable(activatable)
{
}
virtual property bool IsActive
{
bool get() { return m_activatable->IsActive; }
void set(bool value) { m_activatable->IsActive = value; }
bool get()
{
return m_activatable->IsActive;
}
void set(bool value)
{
m_activatable->IsActive = value;
}
}
};
template<typename TActivatable>
IActivatable^ AsActivatable(TActivatable activatable)
{
return ref new Activatable<TActivatable>(activatable);
}
template <typename TActivatable>
IActivatable
^ AsActivatable(TActivatable activatable) { return ref new Activatable<TActivatable>(activatable); }
[Windows::UI::Xaml::Data::Bindable]
public ref class UnitConverterViewModel sealed : public Windows::UI::Xaml::Data::INotifyPropertyChanged
[Windows::UI::Xaml::Data::Bindable] public ref class UnitConverterViewModel sealed : public Windows::UI::Xaml::Data::INotifyPropertyChanged
{
internal:
UnitConverterViewModel(const std::shared_ptr<UnitConversionManager::IUnitConverter>& model);
internal : UnitConverterViewModel(const std::shared_ptr<UnitConversionManager::IUnitConverter>& model);
public:
OBSERVABLE_OBJECT_CALLBACK(OnPropertyChanged);
OBSERVABLE_PROPERTY_R(Windows::Foundation::Collections::IObservableVector<Category^>^, Categories);
OBSERVABLE_PROPERTY_RW(Category^, CurrentCategory);
OBSERVABLE_PROPERTY_R(Windows::Foundation::Collections::IObservableVector<Category ^> ^, Categories);
OBSERVABLE_PROPERTY_RW(Category ^, CurrentCategory);
OBSERVABLE_PROPERTY_RW(CalculatorApp::Common::ViewMode, Mode);
OBSERVABLE_PROPERTY_R(Windows::Foundation::Collections::IObservableVector<Unit^>^, Units);
OBSERVABLE_PROPERTY_RW(Platform::String^, CurrencySymbol1);
OBSERVABLE_PROPERTY_RW(Unit^, Unit1);
OBSERVABLE_PROPERTY_RW(Platform::String^, Value1);
OBSERVABLE_PROPERTY_RW(Platform::String^, CurrencySymbol2);
OBSERVABLE_PROPERTY_RW(Unit^, Unit2);
OBSERVABLE_PROPERTY_RW(Platform::String^, Value2);
OBSERVABLE_NAMED_PROPERTY_R(Windows::Foundation::Collections::IObservableVector<SupplementaryResult^>^, SupplementaryResults);
OBSERVABLE_PROPERTY_R(Windows::Foundation::Collections::IObservableVector<Unit ^> ^, Units);
OBSERVABLE_PROPERTY_RW(Platform::String ^, CurrencySymbol1);
OBSERVABLE_PROPERTY_RW(Unit ^, Unit1);
OBSERVABLE_PROPERTY_RW(Platform::String ^, Value1);
OBSERVABLE_PROPERTY_RW(Platform::String ^, CurrencySymbol2);
OBSERVABLE_PROPERTY_RW(Unit ^, Unit2);
OBSERVABLE_PROPERTY_RW(Platform::String ^, Value2);
OBSERVABLE_NAMED_PROPERTY_R(Windows::Foundation::Collections::IObservableVector<SupplementaryResult ^> ^, SupplementaryResults);
OBSERVABLE_PROPERTY_RW(bool, Value1Active);
OBSERVABLE_PROPERTY_RW(bool, Value2Active);
OBSERVABLE_PROPERTY_RW(Platform::String^, Value1AutomationName);
OBSERVABLE_PROPERTY_RW(Platform::String^, Value2AutomationName);
OBSERVABLE_PROPERTY_RW(Platform::String^, Unit1AutomationName);
OBSERVABLE_PROPERTY_RW(Platform::String^, Unit2AutomationName);
OBSERVABLE_PROPERTY_RW(CalculatorApp::Common::Automation::NarratorAnnouncement^, Announcement);
OBSERVABLE_PROPERTY_RW(Platform::String ^, Value1AutomationName);
OBSERVABLE_PROPERTY_RW(Platform::String ^, Value2AutomationName);
OBSERVABLE_PROPERTY_RW(Platform::String ^, Unit1AutomationName);
OBSERVABLE_PROPERTY_RW(Platform::String ^, Unit2AutomationName);
OBSERVABLE_PROPERTY_RW(CalculatorApp::Common::Automation::NarratorAnnouncement ^, Announcement);
OBSERVABLE_PROPERTY_RW(bool, IsDecimalEnabled);
OBSERVABLE_PROPERTY_RW(bool, IsDropDownOpen);
OBSERVABLE_PROPERTY_RW(bool, IsDropDownEnabled);
OBSERVABLE_NAMED_PROPERTY_RW(bool, IsCurrencyLoadingVisible);
OBSERVABLE_PROPERTY_RW(bool, IsCurrencyCurrentCategory);
OBSERVABLE_PROPERTY_RW(Platform::String^, CurrencyRatioEquality);
OBSERVABLE_PROPERTY_RW(Platform::String^, CurrencyRatioEqualityAutomationName);
OBSERVABLE_PROPERTY_RW(Platform::String^, CurrencyTimestamp);
OBSERVABLE_PROPERTY_RW(Platform::String ^, CurrencyRatioEquality);
OBSERVABLE_PROPERTY_RW(Platform::String ^, CurrencyRatioEqualityAutomationName);
OBSERVABLE_PROPERTY_RW(Platform::String ^, CurrencyTimestamp);
OBSERVABLE_NAMED_PROPERTY_RW(CalculatorApp::NetworkAccessBehavior, NetworkBehavior);
OBSERVABLE_NAMED_PROPERTY_RW(bool, CurrencyDataLoadFailed);
OBSERVABLE_NAMED_PROPERTY_RW(bool, CurrencyDataIsWeekOld);
@@ -181,9 +177,7 @@ namespace CalculatorApp
{
Windows::UI::Xaml::Visibility get()
{
return SupplementaryResults->Size > 0
? Windows::UI::Xaml::Visibility::Visible
: Windows::UI::Xaml::Visibility::Collapsed;
return SupplementaryResults->Size > 0 ? Windows::UI::Xaml::Visibility::Visible : Windows::UI::Xaml::Visibility::Collapsed;
}
}
@@ -191,9 +185,8 @@ namespace CalculatorApp
{
Windows::UI::Xaml::Visibility get()
{
return (CurrencySymbol1->IsEmpty() || CurrencySymbol2->IsEmpty())
? Windows::UI::Xaml::Visibility::Collapsed
: Windows::UI::Xaml::Visibility::Visible;
return (CurrencySymbol1->IsEmpty() || CurrencySymbol2->IsEmpty()) ? Windows::UI::Xaml::Visibility::Collapsed
: Windows::UI::Xaml::Visibility::Visible;
}
}
@@ -206,23 +199,26 @@ namespace CalculatorApp
void AnnounceConversionResult();
internal:
void ResetView();
internal : void ResetView();
void PopulateData();
NumbersAndOperatorsEnum MapCharacterToButtonId(const wchar_t ch, bool& canSendNegate);
void DisplayPasteError();
void OnValueActivated(IActivatable^ control);
void OnPaste(Platform::String^ stringToPaste, CalculatorApp::Common::ViewMode mode);
void OnValueActivated(IActivatable ^ control);
void OnPaste(Platform::String ^ stringToPaste, CalculatorApp::Common::ViewMode mode);
void OnCopyCommand(Platform::Object^ parameter);
void OnPasteCommand(Platform::Object^ parameter);
void OnCopyCommand(Platform::Object ^ parameter);
void OnPasteCommand(Platform::Object ^ parameter);
Platform::String^ GetLocalizedAutomationName(_In_ Platform::String^ displayvalue, _In_ Platform::String^ unitname, _In_ Platform::String^ format);
Platform::String^ GetLocalizedConversionResultStringFormat(_In_ Platform::String^ fromValue, _In_ Platform::String^ fromUnit, _In_ Platform::String^ toValue, _In_ Platform::String^ toUnit);
Platform::String
^ GetLocalizedAutomationName(_In_ Platform::String ^ displayvalue, _In_ Platform::String ^ unitname, _In_ Platform::String ^ format);
Platform::String
^ GetLocalizedConversionResultStringFormat(
_In_ Platform::String ^ fromValue,
_In_ Platform::String ^ fromUnit,
_In_ Platform::String ^ toValue,
_In_ Platform::String ^ toUnit);
void UpdateValue1AutomationName();
void UpdateValue2AutomationName();
Platform::String^ Serialize();
void Deserialize(Platform::String^ state);
// Saving And Restoring User Preferences of Category and Associated-Units across Sessions.
void SaveUserPreferences();
@@ -248,24 +244,25 @@ namespace CalculatorApp
void OnMaxDigitsReached();
void BuildUnitList(const std::vector<UnitConversionManager::Unit>& modelUnitList);
Unit^ FindUnitInList(UnitConversionManager::Unit target);
Unit ^ FindUnitInList(UnitConversionManager::Unit target);
void SetSelectedUnits();
private:
void InitializeView();
void OnPropertyChanged(Platform::String^ prop);
void OnCategoryChanged(Platform::Object^ unused);
void OnUnitChanged(Platform::Object^ unused);
void OnSwitchActive(Platform::Object^ unused);
void OnPropertyChanged(Platform::String ^ prop);
void OnCategoryChanged(Platform::Object ^ unused);
void OnUnitChanged(Platform::Object ^ unused);
void OnSwitchActive(Platform::Object ^ unused);
UnitConversionManager::Command CommandFromButtonId(CalculatorApp::NumbersAndOperatorsEnum button);
void SupplementaryResultsTimerTick(Windows::System::Threading::ThreadPoolTimer^ timer);
void SupplementaryResultsTimerCancel(Windows::System::Threading::ThreadPoolTimer^ timer);
void SupplementaryResultsTimerTick(Windows::System::Threading::ThreadPoolTimer ^ timer);
void SupplementaryResultsTimerCancel(Windows::System::Threading::ThreadPoolTimer ^ timer);
void RefreshSupplementaryResults();
void UpdateInputBlocked(_In_ const std::wstring& currencyInput);
bool UnitsAreValid();
void ResetCategory();
void OnButtonPressed(Platform::Object^ parameter);
Platform::String^ ConvertToLocalizedString(const std::wstring& stringToLocalize, bool allowPartialStrings);
void OnButtonPressed(Platform::Object ^ parameter);
Platform::String ^ ConvertToLocalizedString(const std::wstring& stringToLocalize, bool allowPartialStrings);
void StartConversionResultTimer();
@@ -304,12 +301,12 @@ namespace CalculatorApp
private:
bool m_isInputBlocked;
Windows::System::Threading::ThreadPoolTimer^ m_supplementaryResultsTimer;
Windows::System::Threading::ThreadPoolTimer ^ m_supplementaryResultsTimer;
bool m_resettingTimer;
std::vector<std::tuple<std::wstring, UnitConversionManager::Unit>> m_cachedSuggestedValues;
std::mutex m_cacheMutex;
Windows::Globalization::NumberFormatting::DecimalFormatter^ m_decimalFormatter;
Windows::Globalization::NumberFormatting::CurrencyFormatter^ m_currencyFormatter;
Windows::Globalization::NumberFormatting::DecimalFormatter ^ m_decimalFormatter;
Windows::Globalization::NumberFormatting::CurrencyFormatter ^ m_currencyFormatter;
int m_currencyMaxFractionDigits;
std::wstring m_valueFromUnlocalized;
std::wstring m_valueToUnlocalized;
@@ -317,18 +314,18 @@ namespace CalculatorApp
// For Saving the User Preferences only if the Unit converter ViewModel is initialised for the first time
bool m_IsFirstTime;
Platform::String^ m_localizedValueFromFormat;
Platform::String^ m_localizedValueFromDecimalFormat;
Platform::String^ m_localizedValueToFormat;
Platform::String^ m_localizedConversionResultFormat;
Platform::String^ m_localizedInputUnitName;
Platform::String^ m_localizedOutputUnitName;
Platform::String ^ m_localizedValueFromFormat;
Platform::String ^ m_localizedValueFromDecimalFormat;
Platform::String ^ m_localizedValueToFormat;
Platform::String ^ m_localizedConversionResultFormat;
Platform::String ^ m_localizedInputUnitName;
Platform::String ^ m_localizedOutputUnitName;
bool m_isValue1Updating;
bool m_isValue2Updating;
std::wstring m_lastAnnouncedFrom;
std::wstring m_lastAnnouncedTo;
Platform::String^ m_lastAnnouncedConversionResult;
Platform::String ^ m_lastAnnouncedConversionResult;
bool m_isCurrencyDataLoaded;
@@ -338,16 +335,17 @@ namespace CalculatorApp
class UnitConverterVMCallback : public UnitConversionManager::IUnitConverterVMCallback
{
public:
UnitConverterVMCallback(UnitConverterViewModel^ viewModel) : m_viewModel(viewModel)
{}
UnitConverterVMCallback(UnitConverterViewModel ^ viewModel)
: m_viewModel(viewModel)
{
}
void DisplayCallback(const std::wstring& from, const std::wstring& to) override
{
m_viewModel->UpdateDisplay(from, to);
}
void SuggestedValueCallback(
const std::vector<std::tuple<std::wstring, UnitConversionManager::Unit>>& suggestedValues) override
void SuggestedValueCallback(const std::vector<std::tuple<std::wstring, UnitConversionManager::Unit>>& suggestedValues) override
{
m_viewModel->UpdateSupplementaryResults(suggestedValues);
}
@@ -358,14 +356,16 @@ namespace CalculatorApp
}
private:
UnitConverterViewModel^ m_viewModel;
UnitConverterViewModel ^ m_viewModel;
};
class ViewModelCurrencyCallback : public UnitConversionManager::IViewModelCurrencyCallback
{
public:
ViewModelCurrencyCallback(UnitConverterViewModel^ viewModel) : m_viewModel(viewModel)
{}
ViewModelCurrencyCallback(UnitConverterViewModel ^ viewModel)
: m_viewModel(viewModel)
{
}
void CurrencyDataLoadFinished(bool didLoad) override
{
@@ -374,8 +374,8 @@ namespace CalculatorApp
void CurrencySymbolsCallback(const std::wstring& symbol1, const std::wstring& symbol2) override
{
Platform::String^ sym1 = Platform::StringReference(symbol1.c_str());
Platform::String^ sym2 = Platform::StringReference(symbol2.c_str());
Platform::String ^ sym1 = Platform::StringReference(symbol1.c_str());
Platform::String ^ sym2 = Platform::StringReference(symbol2.c_str());
bool value1Active = m_viewModel->Value1Active;
m_viewModel->CurrencySymbol1 = value1Active ? sym1 : sym2;
@@ -399,7 +399,7 @@ namespace CalculatorApp
}
private:
UnitConverterViewModel^ m_viewModel;
UnitConverterViewModel ^ m_viewModel;
};
}
}

View File

@@ -11,7 +11,7 @@ namespace CalculatorApp
Platform::StringReference Snap(L"Snap");
Platform::StringReference DockedView(L"DockedView");
bool IsValidViewState(Platform::String^ viewState)
bool IsValidViewState(Platform::String ^ viewState)
{
return viewState->Equals(ViewState::Snap) || viewState->Equals(ViewState::DockedView);
}

View File

@@ -10,6 +10,6 @@ namespace CalculatorApp
extern Platform::StringReference Snap;
extern Platform::StringReference DockedView;
bool IsValidViewState(Platform::String^ viewState);
bool IsValidViewState(Platform::String ^ viewState);
}
}

View File

@@ -2,4 +2,3 @@
// Licensed under the MIT License.
#include "pch.h"

View File

@@ -3,7 +3,6 @@
#pragma once
#include "targetver.h"
#ifndef WIN32_LEAN_AND_MEAN
@@ -45,5 +44,7 @@
// Once the app switches to min version RS3, the namespaces can be removed.
// TODO - MSFT 12735088
namespace StandardPeers = Windows::UI::Xaml::Automation::Peers;
namespace CalculatorApp::Common::Automation {}
namespace CalculatorApp::Common::Automation
{
}
namespace CustomPeers = CalculatorApp::Common::Automation;

View File

@@ -9,4 +9,3 @@
// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h.
#include <SDKDDKVer.h>