Merge master into feature/GraphingCalculator branch (#585)
* Merge master into feature/GraphingCalculator branch
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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" />
|
||||
|
||||
@@ -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>
|
||||
@@ -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;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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())
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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 ¶Cmd)
|
||||
void SerializeCommandVisitor::Visit(_In_ CParentheses& paraCmd)
|
||||
{
|
||||
int parenthesisCmd = paraCmd.GetCommand();
|
||||
m_dataWriter->WriteInt32(parenthesisCmd);
|
||||
|
||||
@@ -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 ¶Cmd);
|
||||
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;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"";
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)¤cyTrailingDigits,
|
||||
sizeof(currencyTrailingDigits) / sizeof(WCHAR));
|
||||
@@ -93,7 +84,8 @@ namespace CalculatorApp
|
||||
// Currency symbol precedence is either 0 or 1.
|
||||
// A value of 0 indicates the symbol follows the currency value.
|
||||
int currencySymbolPrecedence = 1;
|
||||
result = GetLocaleInfoEx(LOCALE_NAME_USER_DEFAULT,
|
||||
result = GetLocaleInfoEx(
|
||||
m_resolvedName.c_str(),
|
||||
LOCALE_IPOSSYMPRECEDES | LOCALE_RETURN_NUMBER,
|
||||
(LPWSTR)¤cySymbolPrecedence,
|
||||
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;
|
||||
|
||||
@@ -19,13 +19,7 @@ namespace CalculatorApp
|
||||
std::unique_ptr<wchar_t[]> spBuffer = std::unique_ptr<wchar_t[]>(new wchar_t[length]);
|
||||
va_list args = NULL;
|
||||
va_start(args, pMessage);
|
||||
DWORD fmtReturnVal = FormatMessage(FORMAT_MESSAGE_FROM_STRING,
|
||||
pMessage,
|
||||
0,
|
||||
0,
|
||||
spBuffer.get(),
|
||||
length,
|
||||
&args);
|
||||
DWORD fmtReturnVal = FormatMessage(FORMAT_MESSAGE_FROM_STRING, pMessage, 0, 0, spBuffer.get(), length, &args);
|
||||
va_end(args);
|
||||
|
||||
if (fmtReturnVal != 0)
|
||||
|
||||
@@ -7,7 +7,8 @@ namespace CalculatorApp
|
||||
{
|
||||
namespace Common
|
||||
{
|
||||
public enum class MyVirtualKey
|
||||
public
|
||||
enum class MyVirtualKey
|
||||
{
|
||||
None = 0,
|
||||
LeftButton = 1,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -11,20 +11,21 @@ namespace CalculatorApp
|
||||
class TraceActivity
|
||||
{
|
||||
public:
|
||||
TraceActivity() :
|
||||
m_channel(nullptr),
|
||||
m_activity(nullptr),
|
||||
m_fields(nullptr)
|
||||
{ }
|
||||
TraceActivity()
|
||||
: m_channel(nullptr)
|
||||
, m_activity(nullptr)
|
||||
, m_fields(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
TraceActivity(
|
||||
winrt::Windows::Foundation::Diagnostics::LoggingChannel channel,
|
||||
std::wstring_view activityName,
|
||||
winrt::Windows::Foundation::Diagnostics::LoggingFields fields) :
|
||||
m_channel(channel),
|
||||
m_activityName(activityName),
|
||||
m_fields(fields),
|
||||
m_activity(nullptr)
|
||||
winrt::Windows::Foundation::Diagnostics::LoggingFields fields)
|
||||
: m_channel(channel)
|
||||
, m_activityName(activityName)
|
||||
, m_fields(fields)
|
||||
, m_activity(nullptr)
|
||||
{
|
||||
// Write the activity's START event. Note that you must not specify keyword
|
||||
// or level for START and STOP events because they always use the activity's
|
||||
@@ -33,8 +34,7 @@ namespace CalculatorApp
|
||||
m_activityName,
|
||||
m_fields,
|
||||
winrt::Windows::Foundation::Diagnostics::LoggingLevel::Verbose,
|
||||
winrt::Windows::Foundation::Diagnostics::LoggingOptions(WINEVENT_KEYWORD_RESPONSE_TIME)
|
||||
);
|
||||
winrt::Windows::Foundation::Diagnostics::LoggingOptions(WINEVENT_KEYWORD_RESPONSE_TIME));
|
||||
}
|
||||
|
||||
~TraceActivity()
|
||||
|
||||
@@ -21,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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
};
|
||||
}}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
¤cyCode,
|
||||
¤cyName,
|
||||
¤cySymbol
|
||||
};
|
||||
vector<wstring*> values = { &countryCode, &countryName, ¤cyCode, ¤cyName, ¤cySymbol };
|
||||
|
||||
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()));
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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()));
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
13
src/CalcViewModel/DataLoaders/DataLoaderMockConstants.h
Normal file
13
src/CalcViewModel/DataLoaders/DataLoaderMockConstants.h
Normal 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=";
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
@@ -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;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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{};
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -10,6 +10,6 @@ namespace CalculatorApp
|
||||
extern Platform::StringReference Snap;
|
||||
extern Platform::StringReference DockedView;
|
||||
|
||||
bool IsValidViewState(Platform::String^ viewState);
|
||||
bool IsValidViewState(Platform::String ^ viewState);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,4 +2,3 @@
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#include "pch.h"
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -9,4 +9,3 @@
|
||||
// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h.
|
||||
|
||||
#include <SDKDDKVer.h>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user