diff --git a/build/pipelines/azure-pipelines.release.yaml b/build/pipelines/azure-pipelines.release.yaml index 8a1328ec..6e049ddd 100644 --- a/build/pipelines/azure-pipelines.release.yaml +++ b/build/pipelines/azure-pipelines.release.yaml @@ -16,8 +16,8 @@ pr: none variables: versionMajor: 10 - versionMinor: 2103 - versionBuild: $[counter('10.2103.*', 0)] + versionMinor: 2108 + versionBuild: $[counter('10.2108.*', 0)] versionPatch: 0 name: '$(versionMajor).$(versionMinor).$(versionBuild).$(versionPatch)' diff --git a/build/pipelines/templates/build-app-internal.yaml b/build/pipelines/templates/build-app-internal.yaml index 9e082815..69b5262e 100644 --- a/build/pipelines/templates/build-app-internal.yaml +++ b/build/pipelines/templates/build-app-internal.yaml @@ -42,11 +42,28 @@ jobs: treatNotIndexedAsWarning: true symbolsArtifactName: $(System.teamProject)/$(Build.BuildNumber)_$(BuildPlatform)$(BuildConfiguration) + - task: CopyFiles@2 + displayName: Copy Files for BinSkim analysis + inputs: + SourceFolder: '$(Build.BinariesDirectory)\$(BuildConfiguration)\$(BuildPlatform)\Calculator\' + # Setting up a folder to store all the binary files that we need BinSkim to scan. + # If we put more things than we produce pdbs for and can index (such as nuget packages that ship without pdbs), binskim will fail. + # Below are ignored files + # - clrcompression.dll + Contents: | + **\* + !**\clrcompression.dll + TargetFolder: '$(Agent.BuildDirectory)\binskim' + CleanTargetFolder: true + OverWrite: true + flattenFolders: false + analyzeTarget: '$(Agent.BuildDirectory)\binskim\*' + - task: securedevelopmentteam.vss-secure-development-tools.build-task-binskim.BinSkim@3 displayName: Run BinSkim inputs: inputType: Basic - analyzeTarget: $(Build.BinariesDirectory)\$(BuildConfiguration)\$(BuildPlatform)\Calculator\* + analyzeTarget: '$(Agent.BuildDirectory)\binskim\*' analyzeVerbose: true analyzeHashes: true continueOnError: true diff --git a/build/pipelines/templates/build-single-architecture.yaml b/build/pipelines/templates/build-single-architecture.yaml index 49056df1..eb9bf805 100644 --- a/build/pipelines/templates/build-single-architecture.yaml +++ b/build/pipelines/templates/build-single-architecture.yaml @@ -29,7 +29,7 @@ steps: inputs: solution: src/Calculator.sln vsVersion: 16.0 - msbuildArgs: /bl:$(Build.BinariesDirectory)\$(BuildConfiguration)\$(BuildPlatform)\Calculator.binlog /p:OutDir=$(Build.BinariesDirectory)\$(BuildConfiguration)\$(BuildPlatform)\ /p:GenerateProjectSpecificOutputFolder=true /p:AppVersion=$(Build.BuildNumber) /t:Publish /p:PublishDir=$(Build.BinariesDirectory)\$(BuildConfiguration)\$(BuildPlatform)\publish\ ${{ parameters.extraMsBuildArgs }} + msbuildArgs: /bl:$(Build.BinariesDirectory)\$(BuildConfiguration)\$(BuildPlatform)\Calculator.binlog /p:OutDir=$(Build.BinariesDirectory)\$(BuildConfiguration)\$(BuildPlatform)\ /p:GenerateProjectSpecificOutputFolder=true /p:Version=$(Build.BuildNumber) /t:Publish /p:PublishDir=$(Build.BinariesDirectory)\$(BuildConfiguration)\$(BuildPlatform)\publish\ ${{ parameters.extraMsBuildArgs }} platform: $(BuildPlatform) configuration: $(BuildConfiguration) maximumCpuCount: true diff --git a/src/CalcViewModel/ApplicationViewModel.cpp b/src/CalcViewModel/ApplicationViewModel.cpp index 0450741b..5235932c 100644 --- a/src/CalcViewModel/ApplicationViewModel.cpp +++ b/src/CalcViewModel/ApplicationViewModel.cpp @@ -12,8 +12,8 @@ #include "DataLoaders/UnitConverterDataLoader.h" using namespace CalculatorApp; -using namespace CalculatorApp::Common; -using namespace CalculatorApp::DataLoaders; +using namespace CalculatorApp::ViewModel::Common; +using namespace CalculatorApp::ViewModel::DataLoaders; using namespace CalculatorApp::ViewModel; using namespace CalculationManager; using namespace Platform; diff --git a/src/CalcViewModel/ApplicationViewModel.h b/src/CalcViewModel/ApplicationViewModel.h index 7e4238d8..ab26c35f 100644 --- a/src/CalcViewModel/ApplicationViewModel.h +++ b/src/CalcViewModel/ApplicationViewModel.h @@ -17,14 +17,14 @@ namespace CalculatorApp public: ApplicationViewModel(); - void Initialize(CalculatorApp::Common::ViewMode mode); // Use for first init, use deserialize for rehydration + void Initialize(CalculatorApp::ViewModel::Common::ViewMode mode); // Use for first init, use deserialize for rehydration OBSERVABLE_OBJECT(); OBSERVABLE_PROPERTY_RW(StandardCalculatorViewModel ^, CalculatorViewModel); OBSERVABLE_PROPERTY_RW(DateCalculatorViewModel ^, DateCalcViewModel); OBSERVABLE_PROPERTY_RW(GraphingCalculatorViewModel ^, GraphingCalcViewModel); OBSERVABLE_PROPERTY_RW(UnitConverterViewModel ^, ConverterViewModel); - OBSERVABLE_PROPERTY_RW(CalculatorApp::Common::ViewMode, PreviousMode); + OBSERVABLE_PROPERTY_RW(CalculatorApp::ViewModel::Common::ViewMode, PreviousMode); OBSERVABLE_PROPERTY_R(bool, IsAlwaysOnTop); OBSERVABLE_NAMED_PROPERTY_RW(Platform::String ^, CategoryName); @@ -34,14 +34,14 @@ namespace CalculatorApp COMMAND_FOR_METHOD(CopyCommand, ApplicationViewModel::OnCopyCommand); COMMAND_FOR_METHOD(PasteCommand, ApplicationViewModel::OnPasteCommand); - property CalculatorApp::Common::ViewMode Mode + property CalculatorApp::ViewModel::Common::ViewMode Mode { - CalculatorApp::Common::ViewMode get() + CalculatorApp::ViewModel::Common::ViewMode get() { return m_mode; } - void set(CalculatorApp::Common::ViewMode value); + void set(CalculatorApp::ViewModel::Common::ViewMode value); } static property Platform::String^ ModePropertyName { @@ -51,21 +51,21 @@ namespace CalculatorApp } } - property Windows::Foundation::Collections::IObservableVector^ Categories + property Windows::Foundation::Collections::IObservableVector^ Categories { - Windows::Foundation::Collections::IObservableVector^ get() + Windows::Foundation::Collections::IObservableVector^ get() { return m_categories; } - void set(Windows::Foundation::Collections::IObservableVector^ value); + void set(Windows::Foundation::Collections::IObservableVector^ value); } property Windows::UI::Xaml::Visibility ClearMemoryVisibility { Windows::UI::Xaml::Visibility get() { - return CalculatorApp::Common::NavCategory::IsCalculatorViewMode(Mode) ? Windows::UI::Xaml::Visibility::Visible + return CalculatorApp::ViewModel::Common::NavCategory::IsCalculatorViewMode(Mode) ? Windows::UI::Xaml::Visibility::Visible : Windows::UI::Xaml::Visibility::Collapsed; } } @@ -106,8 +106,8 @@ namespace CalculatorApp void SetMenuCategories(); - CalculatorApp::Common::ViewMode m_mode; - Windows::Foundation::Collections::IObservableVector ^ m_categories; + CalculatorApp::ViewModel::Common::ViewMode m_mode; + Windows::Foundation::Collections::IObservableVector ^ m_categories; Concurrency::task HandleToggleAlwaysOnTop(float width, float height); void SetDisplayNormalAlwaysOnTopOption(); }; diff --git a/src/Calculator/Calculator.rc b/src/CalcViewModel/CalcViewModel.rc similarity index 74% rename from src/Calculator/Calculator.rc rename to src/CalcViewModel/CalcViewModel.rc index 39e80483..b447542a 100644 --- a/src/Calculator/Calculator.rc +++ b/src/CalcViewModel/CalcViewModel.rc @@ -1,9 +1,9 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -#define APP_FILE_NAME "Calculator" +#define APP_FILE_NAME "CalcViewModel" #define APP_FILE_IS_EXE -#define APP_PRODUCT_NAME "Microsoft Calculator" +#define APP_PRODUCT_NAME "Microsoft Calculator ViewModel" #define APP_COMPANY_NAME "Microsoft Corporation" #define APP_COPYRIGHT "\251 Microsoft Corporation. All rights reserved." diff --git a/src/CalcViewModel/CalcViewModel.vcxproj b/src/CalcViewModel/CalcViewModel.vcxproj index c2a69b5c..7ccf3fcb 100644 --- a/src/CalcViewModel/CalcViewModel.vcxproj +++ b/src/CalcViewModel/CalcViewModel.vcxproj @@ -35,9 +35,9 @@ - {90e9761d-9262-4773-942d-caeae75d7140} - StaticLibrary - CalcViewModel + {812d1a7b-b8ac-49e4-8e6d-af5d59500d56} + WindowsRuntimeComponent + CalculatorApp.ViewModel en-US 14.0 true @@ -48,45 +48,45 @@ - StaticLibrary + DynamicLibrary true v142 - StaticLibrary + DynamicLibrary true v142 - StaticLibrary + DynamicLibrary true v142 - StaticLibrary + DynamicLibrary true v142 - StaticLibrary + DynamicLibrary false true v142 - StaticLibrary + DynamicLibrary false true v142 - StaticLibrary + DynamicLibrary false true v142 - StaticLibrary + DynamicLibrary false true v142 @@ -105,13 +105,13 @@ - - - - + + + + @@ -122,175 +122,181 @@ - + + false + + + false + + + false + + + false + + + false + + + false + + + false + + false - true Use - true - true - $(SolutionDir)..\src\;%(AdditionalIncludeDirectories) - 4453 - /bigobj /await /std:c++17 /utf-8 %(AdditionalOptions) - Level4 - true + _WINRT_DLL;%(PreprocessorDefinitions) + pch.h + $(IntDir)pch.pch + $(SolutionDir);%(AdditionalIncludeDirectories) + $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) + /bigobj /await %(AdditionalOptions) + 28204;4453 + stdcpp17 Console false - false - - /ignore:4264 %(AdditionalOptions) - Use - true - true - $(SolutionDir)..\src\;%(AdditionalIncludeDirectories) - 4453 - /bigobj /await /std:c++17 /utf-8 %(AdditionalOptions) - Level4 - true + _WINRT_DLL;NDEBUG;%(PreprocessorDefinitions) + pch.h + $(IntDir)pch.pch + $(SolutionDir);%(AdditionalIncludeDirectories) + $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) + /bigobj /await %(AdditionalOptions) + 28204;4453 + stdcpp17 + Guard Console false - false - - /ignore:4264 %(AdditionalOptions) - - + Use - true - true - $(SolutionDir)..\src\;%(AdditionalIncludeDirectories) - 4453 - /bigobj /await /std:c++17 /utf-8 %(AdditionalOptions) - Level4 - true + _WINRT_DLL;%(PreprocessorDefinitions) + pch.h + $(IntDir)pch.pch + $(SolutionDir);%(AdditionalIncludeDirectories) + $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) + /bigobj /await %(AdditionalOptions) + 28204;4453 + stdcpp17 Console false - false - - /ignore:4264 %(AdditionalOptions) - - + Use - true - true - $(SolutionDir)..\src\;%(AdditionalIncludeDirectories) - 4453 - /bigobj /await /std:c++17 /utf-8 %(AdditionalOptions) - Level4 - true + _WINRT_DLL;NDEBUG;%(PreprocessorDefinitions) + pch.h + $(IntDir)pch.pch + $(SolutionDir);%(AdditionalIncludeDirectories) + $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) + /bigobj /await %(AdditionalOptions) + 28204;4453 + stdcpp17 + Guard + + + Console + false + + + + + Use + _WINRT_DLL;%(PreprocessorDefinitions) + pch.h + $(IntDir)pch.pch + $(SolutionDir);%(AdditionalIncludeDirectories) + $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) + /bigobj /await %(AdditionalOptions) + 28204;4453 + stdcpp17 + + + Console + false + + + + + Use + _WINRT_DLL;NDEBUG;%(PreprocessorDefinitions) + pch.h + $(IntDir)pch.pch + $(SolutionDir);%(AdditionalIncludeDirectories) + $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) + /bigobj /await %(AdditionalOptions) + 28204;4453 + stdcpp17 + Guard Console false - false - - /ignore:4264 %(AdditionalOptions) - Use - true - true - $(SolutionDir)..\src\;%(AdditionalIncludeDirectories) - 4453 - /bigobj /await /std:c++17 /utf-8 %(AdditionalOptions) - Level4 - true + _WINRT_DLL;%(PreprocessorDefinitions) + pch.h + $(IntDir)pch.pch + $(SolutionDir);%(AdditionalIncludeDirectories) + $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) + /bigobj /await %(AdditionalOptions) + 28204;4453 + stdcpp17 Console false - false - - /ignore:4264 %(AdditionalOptions) - Use - true - true - $(SolutionDir)..\src\;%(AdditionalIncludeDirectories) - 4453 - /bigobj /await /std:c++17 /utf-8 %(AdditionalOptions) - Level4 - true + _WINRT_DLL;NDEBUG;%(PreprocessorDefinitions) + pch.h + $(IntDir)pch.pch + $(SolutionDir);%(AdditionalIncludeDirectories) + $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) + /bigobj /await %(AdditionalOptions) + 28204;4453 + stdcpp17 + Guard Console false - false - - /ignore:4264 %(AdditionalOptions) - - - - - Use - true - true - $(SolutionDir)..\src\;%(AdditionalIncludeDirectories) - 4453 - /bigobj /await /std:c++17 /utf-8 %(AdditionalOptions) - Level4 - true - - - Console - false - false - - - /ignore:4264 %(AdditionalOptions) - - - - - Use - true - true - $(SolutionDir)..\src\;%(AdditionalIncludeDirectories) - 4453 - /bigobj /await /std:c++17 /utf-8 %(AdditionalOptions) - Level4 - true - - - Console - false - false - - - /ignore:4264 %(AdditionalOptions) - /DSEND_DIAGNOSTICS %(AdditionalOptions) + + 0.0.0.0 + + + + @@ -314,6 +320,7 @@ + @@ -350,6 +357,7 @@ + @@ -365,10 +373,10 @@ Create Create - Create Create - Create Create + Create + Create Create Create @@ -407,5 +415,6 @@ - + + \ No newline at end of file diff --git a/src/CalcViewModel/CalcViewModel.vcxproj.filters b/src/CalcViewModel/CalcViewModel.vcxproj.filters index b219806e..cfaa786f 100644 --- a/src/CalcViewModel/CalcViewModel.vcxproj.filters +++ b/src/CalcViewModel/CalcViewModel.vcxproj.filters @@ -2,27 +2,20 @@ - {1daab7c4-63f6-4266-a259-f34acad66d09} + {05fb7833-4679-4430-bf21-808354e815bf} - {8d4edf06-c312-4312-978a-b6c2beb8295a} + {8f1ef587-e5ce-4fc2-b9b7-73326d5e779a} - {0184f727-b8aa-4af8-a699-63f1b56e7853} + {70216695-3d7b-451a-98e4-cacbea3ba0a6} - {cf7dca32-9727-4f98-83c3-1c0ca7dd1e0c} + {9b94309f-6b9b-4cbb-8584-4273061cc432} - - - - - - - Common @@ -56,12 +49,18 @@ Common + + Common + Common Common + + Common\Automation + Common\Automation @@ -80,26 +79,25 @@ GraphingCalculator - - Common\Automation - GraphingCalculator + + + + + + + - - - - - - - - Common + + Common + Common @@ -115,6 +113,9 @@ Common + + Common + Common @@ -145,12 +146,21 @@ Common + + Common + + + Common + Common Common + + Common\Automation + Common\Automation @@ -160,6 +170,9 @@ DataLoaders + + DataLoaders + DataLoaders @@ -169,43 +182,31 @@ DataLoaders - - DataLoaders - - - Common\Automation - - - Common - - - Common - GraphingCalculator GraphingCalculator - - Common + + GraphingCalculator GraphingCalculator - - GraphingCalculator - - - Common - + + + + + + + + + DataLoaders - - - \ No newline at end of file diff --git a/src/CalcViewModel/Common/AppResourceProvider.cpp b/src/CalcViewModel/Common/AppResourceProvider.cpp index b843d55b..bc23e78b 100644 --- a/src/CalcViewModel/Common/AppResourceProvider.cpp +++ b/src/CalcViewModel/Common/AppResourceProvider.cpp @@ -7,6 +7,7 @@ using namespace Platform; using namespace Windows::ApplicationModel::Resources; using namespace CalculatorApp; +using namespace CalculatorApp::ViewModel::Common; AppResourceProvider::AppResourceProvider() { diff --git a/src/CalcViewModel/Common/AppResourceProvider.h b/src/CalcViewModel/Common/AppResourceProvider.h index be429a13..7af2e7fd 100644 --- a/src/CalcViewModel/Common/AppResourceProvider.h +++ b/src/CalcViewModel/Common/AppResourceProvider.h @@ -3,7 +3,7 @@ #pragma once -namespace CalculatorApp +namespace CalculatorApp::ViewModel::Common { public ref class AppResourceProvider sealed { diff --git a/src/CalcViewModel/Common/Automation/INarratorAnnouncementHost.h b/src/CalcViewModel/Common/Automation/INarratorAnnouncementHost.h index 9f947f41..7fccdaaf 100644 --- a/src/CalcViewModel/Common/Automation/INarratorAnnouncementHost.h +++ b/src/CalcViewModel/Common/Automation/INarratorAnnouncementHost.h @@ -9,7 +9,7 @@ // being used. Depending on the version of the OS the app is running on, // the app may need a host that uses LiveRegionChanged or RaiseNotification. -namespace CalculatorApp::Common::Automation +namespace CalculatorApp::ViewModel::Common::Automation { public interface class INarratorAnnouncementHost diff --git a/src/CalcViewModel/Common/Automation/LiveRegionHost.cpp b/src/CalcViewModel/Common/Automation/LiveRegionHost.cpp index 0df3a96c..e242411e 100644 --- a/src/CalcViewModel/Common/Automation/LiveRegionHost.cpp +++ b/src/CalcViewModel/Common/Automation/LiveRegionHost.cpp @@ -4,7 +4,7 @@ #include "pch.h" #include "LiveRegionHost.h" -using namespace CalculatorApp::Common::Automation; +using namespace CalculatorApp::ViewModel::Common::Automation; using namespace Windows::UI::Xaml::Automation; using namespace Windows::UI::Xaml::Automation::Peers; using namespace Windows::UI::Xaml::Controls; diff --git a/src/CalcViewModel/Common/Automation/LiveRegionHost.h b/src/CalcViewModel/Common/Automation/LiveRegionHost.h index fef7c714..66d41e44 100644 --- a/src/CalcViewModel/Common/Automation/LiveRegionHost.h +++ b/src/CalcViewModel/Common/Automation/LiveRegionHost.h @@ -9,7 +9,7 @@ // This event is unreliable and should be deprecated in favor of the new // RaiseNotification API in RS3. -namespace CalculatorApp::Common::Automation +namespace CalculatorApp::ViewModel::Common::Automation { // This class exists so that the app can run on RS2 and use LiveRegions // to host notifications on those builds. diff --git a/src/CalcViewModel/Common/Automation/NarratorAnnouncement.cpp b/src/CalcViewModel/Common/Automation/NarratorAnnouncement.cpp index 271a4c24..9751c7dc 100644 --- a/src/CalcViewModel/Common/Automation/NarratorAnnouncement.cpp +++ b/src/CalcViewModel/Common/Automation/NarratorAnnouncement.cpp @@ -4,11 +4,11 @@ #include "pch.h" #include "NarratorAnnouncement.h" -using namespace CalculatorApp::Common::Automation; +using namespace CalculatorApp::ViewModel::Common::Automation; using namespace Platform; using namespace Windows::UI::Xaml::Automation::Peers; -namespace CalculatorApp::Common::Automation +namespace CalculatorApp::ViewModel::Common::Automation { namespace CalculatorActivityIds { diff --git a/src/CalcViewModel/Common/Automation/NarratorAnnouncement.h b/src/CalcViewModel/Common/Automation/NarratorAnnouncement.h index d996a082..da323e5f 100644 --- a/src/CalcViewModel/Common/Automation/NarratorAnnouncement.h +++ b/src/CalcViewModel/Common/Automation/NarratorAnnouncement.h @@ -3,7 +3,7 @@ #pragma once -namespace CalculatorApp::Common::Automation +namespace CalculatorApp::ViewModel::Common::Automation { public ref class NarratorAnnouncement sealed @@ -28,25 +28,23 @@ public static bool IsValid(NarratorAnnouncement ^ announcement); private: - // Make CalculatorAnnouncement a friend class so it is the only - // class that can access the private constructor. - friend class CalculatorAnnouncement; + Platform::String ^ m_announcement; + Platform::String ^ m_activityId; + Windows::UI::Xaml::Automation::Peers::AutomationNotificationKind m_kind; + Windows::UI::Xaml::Automation::Peers::AutomationNotificationProcessing m_processing; + internal: NarratorAnnouncement( Platform::String ^ announcement, Platform::String ^ activityId, Windows::UI::Xaml::Automation::Peers::AutomationNotificationKind kind, Windows::UI::Xaml::Automation::Peers::AutomationNotificationProcessing processing); - - Platform::String ^ m_announcement; - Platform::String ^ m_activityId; - Windows::UI::Xaml::Automation::Peers::AutomationNotificationKind m_kind; - Windows::UI::Xaml::Automation::Peers::AutomationNotificationProcessing m_processing; }; // CalculatorAnnouncement is intended to contain only static methods // that return announcements made for the Calculator app. - class CalculatorAnnouncement +public + ref class CalculatorAnnouncement sealed { public: static NarratorAnnouncement ^ GetDisplayUpdatedAnnouncement(Platform::String ^ announcement); diff --git a/src/CalcViewModel/Common/Automation/NarratorAnnouncementHostFactory.cpp b/src/CalcViewModel/Common/Automation/NarratorAnnouncementHostFactory.cpp index a103c7e7..6e8254b1 100644 --- a/src/CalcViewModel/Common/Automation/NarratorAnnouncementHostFactory.cpp +++ b/src/CalcViewModel/Common/Automation/NarratorAnnouncementHostFactory.cpp @@ -6,7 +6,7 @@ #include "NotificationHost.h" #include "LiveRegionHost.h" -using namespace CalculatorApp::Common::Automation; +using namespace CalculatorApp::ViewModel::Common::Automation; using namespace std; INarratorAnnouncementHost ^ NarratorAnnouncementHostFactory::s_hostProducer; diff --git a/src/CalcViewModel/Common/Automation/NarratorAnnouncementHostFactory.h b/src/CalcViewModel/Common/Automation/NarratorAnnouncementHostFactory.h index 4b739a79..d6579617 100644 --- a/src/CalcViewModel/Common/Automation/NarratorAnnouncementHostFactory.h +++ b/src/CalcViewModel/Common/Automation/NarratorAnnouncementHostFactory.h @@ -9,7 +9,7 @@ // Depending on the version of the OS the app is running on, the factory will return // an announcement host appropriate for that version. -namespace CalculatorApp::Common::Automation +namespace CalculatorApp::ViewModel::Common::Automation { class NarratorAnnouncementHostFactory { diff --git a/src/CalcViewModel/Common/Automation/NarratorNotifier.cpp b/src/CalcViewModel/Common/Automation/NarratorNotifier.cpp index 89fa0c0b..4ac4600e 100644 --- a/src/CalcViewModel/Common/Automation/NarratorNotifier.cpp +++ b/src/CalcViewModel/Common/Automation/NarratorNotifier.cpp @@ -6,7 +6,7 @@ #include "pch.h" #include "NarratorNotifier.h" -using namespace CalculatorApp::Common::Automation; +using namespace CalculatorApp::ViewModel::Common::Automation; using namespace Platform; using namespace Windows::UI::Xaml; using namespace Windows::UI::Xaml::Automation; diff --git a/src/CalcViewModel/Common/Automation/NarratorNotifier.h b/src/CalcViewModel/Common/Automation/NarratorNotifier.h index 359bb09e..f3d82eaa 100644 --- a/src/CalcViewModel/Common/Automation/NarratorNotifier.h +++ b/src/CalcViewModel/Common/Automation/NarratorNotifier.h @@ -6,7 +6,7 @@ #pragma once #include "NarratorAnnouncement.h" -namespace CalculatorApp::Common::Automation +namespace CalculatorApp::ViewModel::Common::Automation { public ref class NarratorNotifier sealed : public Windows::UI::Xaml::DependencyObject diff --git a/src/CalcViewModel/Common/Automation/NotificationHost.cpp b/src/CalcViewModel/Common/Automation/NotificationHost.cpp index 92bf846e..d5bc1d45 100644 --- a/src/CalcViewModel/Common/Automation/NotificationHost.cpp +++ b/src/CalcViewModel/Common/Automation/NotificationHost.cpp @@ -4,7 +4,7 @@ #include "pch.h" #include "NotificationHost.h" -using namespace CalculatorApp::Common::Automation; +using namespace CalculatorApp::ViewModel::Common::Automation; using namespace Windows::Foundation::Metadata; using namespace Windows::UI::Xaml::Automation; using namespace Windows::UI::Xaml::Automation::Peers; diff --git a/src/CalcViewModel/Common/Automation/NotificationHost.h b/src/CalcViewModel/Common/Automation/NotificationHost.h index d0a929c6..b0e86787 100644 --- a/src/CalcViewModel/Common/Automation/NotificationHost.h +++ b/src/CalcViewModel/Common/Automation/NotificationHost.h @@ -8,7 +8,7 @@ // This class announces NarratorAnnouncements using the RaiseNotification API // available in RS3. -namespace CalculatorApp::Common::Automation +namespace CalculatorApp::ViewModel::Common::Automation { public ref class NotificationHost sealed : public INarratorAnnouncementHost @@ -23,10 +23,10 @@ public private: static Windows::UI::Xaml::Automation::Peers::AutomationNotificationKind - GetWindowsNotificationKind(CalculatorApp::Common::Automation::AutomationNotificationKind customKindType); + GetWindowsNotificationKind(CalculatorApp::ViewModel::Common::Automation::AutomationNotificationKind customKindType); static Windows::UI::Xaml::Automation::Peers::AutomationNotificationProcessing - GetWindowsNotificationProcessing(CalculatorApp::Common::Automation::AutomationNotificationProcessing customProcessingType); + GetWindowsNotificationProcessing(CalculatorApp::ViewModel::Common::Automation::AutomationNotificationProcessing customProcessingType); private: Windows::UI::Xaml::UIElement ^ m_host; diff --git a/src/CalcViewModel/Common/BitLength.h b/src/CalcViewModel/Common/BitLength.h index 8c38e7e4..065bd25e 100644 --- a/src/CalcViewModel/Common/BitLength.h +++ b/src/CalcViewModel/Common/BitLength.h @@ -1,6 +1,6 @@ #pragma once -namespace CalculatorApp +namespace CalculatorApp::ViewModel { namespace Common { diff --git a/src/CalcViewModel/Common/CalculatorButtonPressedEventArgs.cpp b/src/CalcViewModel/Common/CalculatorButtonPressedEventArgs.cpp index 76c0d4c0..899af3ec 100644 --- a/src/CalcViewModel/Common/CalculatorButtonPressedEventArgs.cpp +++ b/src/CalcViewModel/Common/CalculatorButtonPressedEventArgs.cpp @@ -5,7 +5,8 @@ #include "CalculatorButtonPressedEventArgs.h" using namespace CalculatorApp; -using namespace CalculatorApp::Common; +using namespace CalculatorApp::ViewModel; +using namespace CalculatorApp::ViewModel::Common; using namespace Platform; NumbersAndOperatorsEnum CalculatorButtonPressedEventArgs::GetOperationFromCommandParameter(_In_ Object ^ commandParameter) diff --git a/src/CalcViewModel/Common/CalculatorButtonPressedEventArgs.h b/src/CalcViewModel/Common/CalculatorButtonPressedEventArgs.h index 27624987..58192d41 100644 --- a/src/CalcViewModel/Common/CalculatorButtonPressedEventArgs.h +++ b/src/CalcViewModel/Common/CalculatorButtonPressedEventArgs.h @@ -6,7 +6,7 @@ #include "CalculatorButtonUser.h" #include "Utils.h" -namespace CalculatorApp +namespace CalculatorApp::ViewModel { namespace Common { @@ -15,15 +15,15 @@ namespace CalculatorApp { public: PROPERTY_R(Platform::String ^, AuditoryFeedback); - PROPERTY_R(CalculatorApp::NumbersAndOperatorsEnum, Operation); + PROPERTY_R(CalculatorApp::ViewModel::Common::NumbersAndOperatorsEnum, Operation); - CalculatorButtonPressedEventArgs(Platform::String ^ feedback, CalculatorApp::NumbersAndOperatorsEnum operation) + CalculatorButtonPressedEventArgs(Platform::String ^ feedback, CalculatorApp::ViewModel::Common::NumbersAndOperatorsEnum operation) : m_AuditoryFeedback(feedback) , m_Operation(operation) { } - static CalculatorApp::NumbersAndOperatorsEnum GetOperationFromCommandParameter(_In_ Platform::Object ^ commandParameter); + static CalculatorApp::ViewModel::Common::NumbersAndOperatorsEnum GetOperationFromCommandParameter(_In_ Platform::Object ^ commandParameter); static Platform::String ^ GetAuditoryFeedbackFromCommandParameter(_In_ Platform::Object ^ commandParameter); }; } diff --git a/src/CalcViewModel/Common/CalculatorButtonUser.h b/src/CalcViewModel/Common/CalculatorButtonUser.h index 0d09de6e..4885e488 100644 --- a/src/CalcViewModel/Common/CalculatorButtonUser.h +++ b/src/CalcViewModel/Common/CalculatorButtonUser.h @@ -5,12 +5,11 @@ #include "CalcManager/Command.h" -namespace CalculatorApp +namespace CalculatorApp::ViewModel::Common { namespace CM = CalculationManager; -public - enum class NumbersAndOperatorsEnum + public enum class NumbersAndOperatorsEnum { Zero = (int)CM::Command::Command0, One = (int)CM::Command::Command1, diff --git a/src/CalcViewModel/Common/CalculatorDisplay.cpp b/src/CalcViewModel/Common/CalculatorDisplay.cpp index 5cf8afbc..afd42a0c 100644 --- a/src/CalcViewModel/Common/CalculatorDisplay.cpp +++ b/src/CalcViewModel/Common/CalculatorDisplay.cpp @@ -8,143 +8,149 @@ #include "StandardCalculatorViewModel.h" using namespace CalculatorApp; +using namespace CalculatorApp::ViewModel; +using namespace CalculatorApp::ViewModel::Common; using namespace CalculationManager; using namespace Platform; using namespace std; -CalculatorDisplay::CalculatorDisplay() +namespace CalculatorApp::ViewModel::Common { -} - -void CalculatorDisplay::SetCallback(Platform::WeakReference callbackReference) -{ - m_callbackReference = callbackReference; -} - -void CalculatorDisplay::SetHistoryCallback(Platform::WeakReference callbackReference) -{ - m_historyCallbackReference = callbackReference; -} - -void CalculatorDisplay::SetPrimaryDisplay(_In_ const wstring& displayStringValue, _In_ bool isError) -{ - if (m_callbackReference) + CalculatorDisplay::CalculatorDisplay() { - if (auto calcVM = m_callbackReference.Resolve()) + } + + void CalculatorDisplay::SetCallback(Platform::WeakReference callbackReference) + { + m_callbackReference = callbackReference; + } + + void CalculatorDisplay::SetHistoryCallback(Platform::WeakReference callbackReference) + { + m_historyCallbackReference = callbackReference; + } + + void CalculatorDisplay::SetPrimaryDisplay(_In_ const wstring& displayStringValue, _In_ bool isError) + { + if (m_callbackReference) { - calcVM->SetPrimaryDisplay(StringReference(displayStringValue.c_str()), isError); + if (auto calcVM = m_callbackReference.Resolve()) + { + calcVM->SetPrimaryDisplay(StringReference(displayStringValue.c_str()), isError); + } + } + } + + void CalculatorDisplay::SetParenthesisNumber(_In_ unsigned int parenthesisCount) + { + if (m_callbackReference != nullptr) + { + if (auto calcVM = m_callbackReference.Resolve()) + { + calcVM->SetParenthesisCount(parenthesisCount); + } + } + } + + void CalculatorDisplay::OnNoRightParenAdded() + { + if (m_callbackReference != nullptr) + { + if (auto calcVM = m_callbackReference.Resolve()) + { + calcVM->OnNoRightParenAdded(); + } + } + } + + void CalculatorDisplay::SetIsInError(bool isError) + { + if (m_callbackReference != nullptr) + { + if (auto calcVM = m_callbackReference.Resolve()) + { + calcVM->IsInError = isError; + } + } + } + + void CalculatorDisplay::SetExpressionDisplay( + _Inout_ std::shared_ptr>> const& tokens, + _Inout_ std::shared_ptr>> const& commands) + { + if (m_callbackReference != nullptr) + { + if (auto calcVM = m_callbackReference.Resolve()) + { + calcVM->SetExpressionDisplay(tokens, commands); + } + } + } + + void CalculatorDisplay::SetMemorizedNumbers(_In_ const vector& newMemorizedNumbers) + { + if (m_callbackReference != nullptr) + { + if (auto calcVM = m_callbackReference.Resolve()) + { + calcVM->SetMemorizedNumbers(newMemorizedNumbers); + } + } + } + + void CalculatorDisplay::OnHistoryItemAdded(_In_ unsigned int addedItemIndex) + { + if (m_historyCallbackReference != nullptr) + { + if (auto historyVM = m_historyCallbackReference.Resolve()) + { + historyVM->OnHistoryItemAdded(addedItemIndex); + } + } + } + + void CalculatorDisplay::MaxDigitsReached() + { + if (m_callbackReference != nullptr) + { + if (auto calcVM = m_callbackReference.Resolve()) + { + calcVM->OnMaxDigitsReached(); + } + } + } + + void CalculatorDisplay::BinaryOperatorReceived() + { + if (m_callbackReference != nullptr) + { + if (auto calcVM = m_callbackReference.Resolve()) + { + calcVM->OnBinaryOperatorReceived(); + } + } + } + + void CalculatorDisplay::MemoryItemChanged(unsigned int indexOfMemory) + { + if (m_callbackReference != nullptr) + { + if (auto calcVM = m_callbackReference.Resolve()) + { + calcVM->OnMemoryItemChanged(indexOfMemory); + } + } + } + + void CalculatorDisplay::InputChanged() + { + if (m_callbackReference != nullptr) + { + if (auto calcVM = m_callbackReference.Resolve()) + { + calcVM->OnInputChanged(); + } } } } -void CalculatorDisplay::SetParenthesisNumber(_In_ unsigned int parenthesisCount) -{ - if (m_callbackReference != nullptr) - { - if (auto calcVM = m_callbackReference.Resolve()) - { - calcVM->SetParenthesisCount(parenthesisCount); - } - } -} - -void CalculatorDisplay::OnNoRightParenAdded() -{ - if (m_callbackReference != nullptr) - { - if (auto calcVM = m_callbackReference.Resolve()) - { - calcVM->OnNoRightParenAdded(); - } - } -} - -void CalculatorDisplay::SetIsInError(bool isError) -{ - if (m_callbackReference != nullptr) - { - if (auto calcVM = m_callbackReference.Resolve()) - { - calcVM->IsInError = isError; - } - } -} - -void CalculatorDisplay::SetExpressionDisplay( - _Inout_ std::shared_ptr>> const& tokens, - _Inout_ std::shared_ptr>> const& commands) -{ - if (m_callbackReference != nullptr) - { - if (auto calcVM = m_callbackReference.Resolve()) - { - calcVM->SetExpressionDisplay(tokens, commands); - } - } -} - -void CalculatorDisplay::SetMemorizedNumbers(_In_ const vector& newMemorizedNumbers) -{ - if (m_callbackReference != nullptr) - { - if (auto calcVM = m_callbackReference.Resolve()) - { - calcVM->SetMemorizedNumbers(newMemorizedNumbers); - } - } -} - -void CalculatorDisplay::OnHistoryItemAdded(_In_ unsigned int addedItemIndex) -{ - if (m_historyCallbackReference != nullptr) - { - if (auto historyVM = m_historyCallbackReference.Resolve()) - { - historyVM->OnHistoryItemAdded(addedItemIndex); - } - } -} - -void CalculatorDisplay::MaxDigitsReached() -{ - if (m_callbackReference != nullptr) - { - if (auto calcVM = m_callbackReference.Resolve()) - { - calcVM->OnMaxDigitsReached(); - } - } -} - -void CalculatorDisplay::BinaryOperatorReceived() -{ - if (m_callbackReference != nullptr) - { - if (auto calcVM = m_callbackReference.Resolve()) - { - calcVM->OnBinaryOperatorReceived(); - } - } -} - -void CalculatorDisplay::MemoryItemChanged(unsigned int indexOfMemory) -{ - if (m_callbackReference != nullptr) - { - if (auto calcVM = m_callbackReference.Resolve()) - { - calcVM->OnMemoryItemChanged(indexOfMemory); - } - } -} - -void CalculatorDisplay::InputChanged() -{ - if (m_callbackReference != nullptr) - { - if (auto calcVM = m_callbackReference.Resolve()) - { - calcVM->OnInputChanged(); - } - } -} diff --git a/src/CalcViewModel/Common/CalculatorDisplay.h b/src/CalcViewModel/Common/CalculatorDisplay.h index 921260da..f6c45ae0 100644 --- a/src/CalcViewModel/Common/CalculatorDisplay.h +++ b/src/CalcViewModel/Common/CalculatorDisplay.h @@ -5,7 +5,7 @@ #include "CalcManager/Header Files/ICalcDisplay.h" -namespace CalculatorApp +namespace CalculatorApp::ViewModel::Common { // Callback interface to be implemented by the CalculatorManager class CalculatorDisplay : public ICalcDisplay diff --git a/src/CalcViewModel/Common/CopyPasteManager.cpp b/src/CalcViewModel/Common/CopyPasteManager.cpp index 8f84eead..44ae1ac2 100644 --- a/src/CalcViewModel/Common/CopyPasteManager.cpp +++ b/src/CalcViewModel/Common/CopyPasteManager.cpp @@ -9,7 +9,8 @@ using namespace std; using namespace concurrency; using namespace CalculatorApp; -using namespace CalculatorApp::Common; +using namespace CalculatorApp::ViewModel::Common; +using namespace CalculatorApp::ViewModel; using namespace Platform; using namespace Platform::Collections; using namespace Windows::Foundation; @@ -116,7 +117,7 @@ String } // Get english translated expression - String ^ englishString = LocalizationSettings::GetInstance().GetEnglishValueFromLocalizedDigits(pastedText); + String ^ englishString = LocalizationSettings::GetInstance()->GetEnglishValueFromLocalizedDigits(pastedText); // Removing the spaces, comma separator from the pasteExpression to allow pasting of expressions like 1 + 2+1,333 auto pasteExpression = wstring(RemoveUnwantedCharsFromString(englishString)->Data()); @@ -614,7 +615,7 @@ ULONG32 CopyPasteManager::ProgrammerOperandLength(Platform::String ^ operand, Nu Platform::String ^ CopyPasteManager::RemoveUnwantedCharsFromString(Platform::String ^ input) { constexpr wchar_t unWantedChars[] = { L' ', L',', L'"', 165, 164, 8373, 36, 8353, 8361, 8362, 8358, 8377, 163, 8364, 8234, 8235, 8236, 8237, 160 }; - input = CalculatorApp::Common::LocalizationSettings::GetInstance().RemoveGroupSeparators(input); + input = CalculatorApp::ViewModel::Common::LocalizationSettings::GetInstance()->RemoveGroupSeparators(input); return ref new String(Utils::RemoveUnwantedCharsFromString(input->Data(), unWantedChars).c_str()); } diff --git a/src/CalcViewModel/Common/CopyPasteManager.h b/src/CalcViewModel/Common/CopyPasteManager.h index ae59a4db..1153d81b 100644 --- a/src/CalcViewModel/Common/CopyPasteManager.h +++ b/src/CalcViewModel/Common/CopyPasteManager.h @@ -13,10 +13,9 @@ namespace CalculatorUnitTests class CopyPasteManagerTest; } -namespace CalculatorApp +namespace CalculatorApp::ViewModel::Common { -public - value struct CopyPasteMaxOperandLengthAndValue + public value struct CopyPasteMaxOperandLengthAndValue { unsigned int maxLength; unsigned long long maxValue; @@ -26,9 +25,11 @@ public { public: static void CopyToClipboard(Platform::String ^ stringToCopy); - static Windows::Foundation::IAsyncOperation< - Platform::String - ^> ^ GetStringToPaste(CalculatorApp::Common::ViewMode mode, CalculatorApp::Common::CategoryGroupType modeType, CalculatorApp::Common::NumberBase programmerNumberBase, CalculatorApp::Common::BitLength bitLengthType); + static Windows::Foundation::IAsyncOperation ^ GetStringToPaste( + CalculatorApp::ViewModel::Common::ViewMode mode, + CalculatorApp::ViewModel::Common::CategoryGroupType modeType, + CalculatorApp::ViewModel::Common::NumberBase programmerNumberBase, + CalculatorApp::ViewModel::Common::BitLength bitLengthType); static bool HasStringToPaste(); static bool IsErrorMessage(Platform::String ^ message); static property unsigned int MaxPasteableLength @@ -87,39 +88,39 @@ public static Platform::String ^ ValidatePasteExpression( Platform::String ^ pastedText, - CalculatorApp::Common::ViewMode mode, - CalculatorApp::Common::NumberBase programmerNumberBase, - CalculatorApp::Common::BitLength bitLengthType); + CalculatorApp::ViewModel::Common::ViewMode mode, + CalculatorApp::ViewModel::Common::NumberBase programmerNumberBase, + CalculatorApp::ViewModel::Common::BitLength bitLengthType); static Platform::String ^ ValidatePasteExpression( Platform::String ^ pastedText, - CalculatorApp::Common::ViewMode mode, - CalculatorApp::Common::CategoryGroupType modeType, - CalculatorApp::Common::NumberBase programmerNumberBase, - CalculatorApp::Common::BitLength bitLengthType); + CalculatorApp::ViewModel::Common::ViewMode mode, + CalculatorApp::ViewModel::Common::CategoryGroupType modeType, + CalculatorApp::ViewModel::Common::NumberBase programmerNumberBase, + CalculatorApp::ViewModel::Common::BitLength bitLengthType); static CopyPasteMaxOperandLengthAndValue GetMaxOperandLengthAndValue( - CalculatorApp::Common::ViewMode mode, - CalculatorApp::Common::CategoryGroupType modeType, - CalculatorApp::Common::NumberBase programmerNumberBase, - CalculatorApp::Common::BitLength bitLengthType); + CalculatorApp::ViewModel::Common::ViewMode mode, + CalculatorApp::ViewModel::Common::CategoryGroupType modeType, + CalculatorApp::ViewModel::Common::NumberBase programmerNumberBase, + CalculatorApp::ViewModel::Common::BitLength bitLengthType); static Windows::Foundation::Collections::IVector< - Platform::String ^> ^ ExtractOperands(Platform::String ^ pasteExpression, CalculatorApp::Common::ViewMode mode); + Platform::String ^> ^ ExtractOperands(Platform::String ^ pasteExpression, CalculatorApp::ViewModel::Common::ViewMode mode); static bool ExpressionRegExMatch( Windows::Foundation::Collections::IVector ^ operands, - CalculatorApp::Common::ViewMode mode, - CalculatorApp::Common::CategoryGroupType modeType, - CalculatorApp::Common::NumberBase programmerNumberBase, - CalculatorApp::Common::BitLength bitLengthType); + CalculatorApp::ViewModel::Common::ViewMode mode, + CalculatorApp::ViewModel::Common::CategoryGroupType modeType, + CalculatorApp::ViewModel::Common::NumberBase programmerNumberBase, + CalculatorApp::ViewModel::Common::BitLength bitLengthType); static Platform::String ^ SanitizeOperand(Platform::String ^ operand); static Platform::String ^ RemoveUnwantedCharsFromString(Platform::String ^ input); - static Platform::IBox ^ TryOperandToULL(Platform::String ^ operand, CalculatorApp::Common::NumberBase numberBase); + static Platform::IBox ^ TryOperandToULL(Platform::String ^ operand, CalculatorApp::ViewModel::Common::NumberBase numberBase); static ULONG32 StandardScientificOperandLength(Platform::String ^ operand); static ULONG32 OperandLength( Platform::String ^ operand, - CalculatorApp::Common::ViewMode mode, - CalculatorApp::Common::CategoryGroupType modeType, - CalculatorApp::Common::NumberBase programmerNumberBase); - static ULONG32 ProgrammerOperandLength(Platform::String ^ operand, CalculatorApp::Common::NumberBase numberBase); + CalculatorApp::ViewModel::Common::ViewMode mode, + CalculatorApp::ViewModel::Common::CategoryGroupType modeType, + CalculatorApp::ViewModel::Common::NumberBase programmerNumberBase); + static ULONG32 ProgrammerOperandLength(Platform::String ^ operand, CalculatorApp::ViewModel::Common::NumberBase numberBase); private: static constexpr size_t MaxStandardOperandLengthValue = 16; diff --git a/src/CalcViewModel/Common/DateCalculator.cpp b/src/CalcViewModel/Common/DateCalculator.cpp index 35df7231..0b417387 100644 --- a/src/CalcViewModel/Common/DateCalculator.cpp +++ b/src/CalcViewModel/Common/DateCalculator.cpp @@ -7,7 +7,7 @@ using namespace Platform; using namespace Windows::Foundation; using namespace Windows::Globalization; -using namespace CalculatorApp::Common::DateCalculation; +using namespace CalculatorApp::ViewModel::Common::DateCalculation; bool operator==(const DateDifference& l, const DateDifference& r) { diff --git a/src/CalcViewModel/Common/DateCalculator.h b/src/CalcViewModel/Common/DateCalculator.h index 7c9b6c4d..89275b1f 100644 --- a/src/CalcViewModel/Common/DateCalculator.h +++ b/src/CalcViewModel/Common/DateCalculator.h @@ -13,7 +13,7 @@ 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 +namespace CalculatorApp::ViewModel { namespace Common { @@ -68,4 +68,4 @@ namespace CalculatorApp } } -bool operator==(const CalculatorApp::Common::DateCalculation::DateDifference& l, const CalculatorApp::Common::DateCalculation::DateDifference& r); +bool operator==(const CalculatorApp::ViewModel::Common::DateCalculation::DateDifference& l, const CalculatorApp::ViewModel::Common::DateCalculation::DateDifference& r); diff --git a/src/CalcViewModel/Common/DelegateCommand.h b/src/CalcViewModel/Common/DelegateCommand.h index 3a341287..6a0151a1 100644 --- a/src/CalcViewModel/Common/DelegateCommand.h +++ b/src/CalcViewModel/Common/DelegateCommand.h @@ -3,22 +3,18 @@ #pragma once -namespace CalculatorApp +namespace CalculatorApp::ViewModel { namespace Common { - template - ref class DelegateCommand : public Windows::UI::Xaml::Input::ICommand + public delegate void DelegateCommandHandler(Platform::Object ^ parameter); + + public ref class DelegateCommand sealed : public Windows::UI::Xaml::Input::ICommand { - internal : - - typedef void (TTarget::*CommandHandlerFunc)(Platform::Object ^); - - DelegateCommand(TTarget ^ target, CommandHandlerFunc func) - : m_weakTarget(target) - , m_function(func) - { - } + public: + DelegateCommand(DelegateCommandHandler ^ handler) + : m_handler(handler) + {} private: // Explicit, and private, implementation of ICommand, this way of programming makes it so @@ -27,11 +23,7 @@ namespace CalculatorApp // code in the app calling Execute. virtual void ExecuteImpl(Platform::Object ^ parameter) sealed = Windows::UI::Xaml::Input::ICommand::Execute { - TTarget ^ target = m_weakTarget.Resolve(); - if (target) - { - (target->*m_function)(parameter); - } + m_handler->Invoke(parameter); } virtual bool CanExecuteImpl(Platform::Object ^ parameter) sealed = Windows::UI::Xaml::Input::ICommand::CanExecute @@ -39,9 +31,9 @@ namespace CalculatorApp return true; } - virtual event Windows::Foundation::EventHandler^ CanExecuteChangedImpl + virtual event Windows::Foundation::EventHandler ^ CanExecuteChangedImpl { - virtual Windows::Foundation::EventRegistrationToken add(Windows::Foundation::EventHandler^ handler) sealed = Windows::UI::Xaml::Input::ICommand::CanExecuteChanged::add + virtual Windows::Foundation::EventRegistrationToken add(Windows::Foundation::EventHandler ^ handler) sealed = Windows::UI::Xaml::Input::ICommand::CanExecuteChanged::add { return m_canExecuteChanged += handler; } @@ -52,17 +44,25 @@ namespace CalculatorApp } private: + DelegateCommandHandler ^ m_handler; - event Windows::Foundation::EventHandler^ m_canExecuteChanged; - - CommandHandlerFunc m_function; - Platform::WeakReference m_weakTarget; + event Windows::Foundation::EventHandler ^ m_canExecuteChanged; }; template - DelegateCommand ^ MakeDelegate(TTarget ^ target, TFuncPtr&& function) { - return ref new DelegateCommand(target, std::forward(function)); - } - + DelegateCommandHandler ^ MakeDelegateCommandHandler(TTarget ^ target, TFuncPtr&& function) + { + Platform::WeakReference weakTarget(target); + return ref new DelegateCommandHandler([weakTarget, function=std::forward(function)](Platform::Object ^ param) + { + TTarget ^ thatTarget = weakTarget.Resolve(); + if (nullptr != thatTarget) + { + (thatTarget->*function)(param); + } + } + ); + } } } + diff --git a/src/CalcViewModel/Common/DisplayExpressionToken.h b/src/CalcViewModel/Common/DisplayExpressionToken.h index aaaaf37c..c53c4857 100644 --- a/src/CalcViewModel/Common/DisplayExpressionToken.h +++ b/src/CalcViewModel/Common/DisplayExpressionToken.h @@ -5,7 +5,7 @@ #include "Utils.h" -namespace CalculatorApp::Common +namespace CalculatorApp::ViewModel::Common { public enum class TokenType @@ -33,6 +33,7 @@ public OBSERVABLE_PROPERTY_RW(int, TokenPosition); OBSERVABLE_PROPERTY_RW(bool, IsTokenEditable); OBSERVABLE_PROPERTY_RW(int, CommandIndex); + OBSERVABLE_PROPERTY_RW(TokenType, Type); OBSERVABLE_PROPERTY_R(Platform::String ^, OriginalToken); property bool IsTokenInEditMode @@ -50,7 +51,6 @@ public m_InEditMode = val; } } - internal : OBSERVABLE_PROPERTY_RW(TokenType, Type); private: bool m_InEditMode; diff --git a/src/CalcViewModel/Common/EngineResourceProvider.cpp b/src/CalcViewModel/Common/EngineResourceProvider.cpp index 05faff9f..ff274d1d 100644 --- a/src/CalcViewModel/Common/EngineResourceProvider.cpp +++ b/src/CalcViewModel/Common/EngineResourceProvider.cpp @@ -5,7 +5,7 @@ #include "EngineResourceProvider.h" #include "Common/LocalizationSettings.h" -using namespace CalculatorApp::Common; +using namespace CalculatorApp::ViewModel::Common; using namespace Platform; using namespace Windows::ApplicationModel::Resources; using namespace std; @@ -19,16 +19,16 @@ namespace CalculatorApp wstring EngineResourceProvider::GetCEngineString(wstring_view id) { - const auto& localizationSettings = LocalizationSettings::GetInstance(); + LocalizationSettings^ localizationSettings = LocalizationSettings::GetInstance(); if (id.compare(L"sDecimal") == 0) { - return localizationSettings.GetDecimalSeparatorStr(); + return localizationSettings->GetDecimalSeparatorStr(); } if (id.compare(L"sThousand") == 0) { - return localizationSettings.GetNumberGroupingSeparatorStr(); + return localizationSettings->GetNumberGroupingSeparatorStr(); } if (id.compare(L"sGrouping") == 0) @@ -39,7 +39,7 @@ namespace CalculatorApp // 3;2;0 0x023 - group 1st 3 and then every 2 digits // 4;0 0x004 - group every 4 digits // 5;3;2;0 0x235 - group 5, then 3, then every 2 - wstring numberGroupingString = localizationSettings.GetNumberGroupingStr(); + wstring numberGroupingString = localizationSettings->GetNumberGroupingStr(); return numberGroupingString; } diff --git a/src/CalcViewModel/Common/EngineResourceProvider.h b/src/CalcViewModel/Common/EngineResourceProvider.h index f4620c5c..524b7a9b 100644 --- a/src/CalcViewModel/Common/EngineResourceProvider.h +++ b/src/CalcViewModel/Common/EngineResourceProvider.h @@ -5,7 +5,7 @@ #include "CalcManager/CalculatorResource.h" -namespace CalculatorApp +namespace CalculatorApp::ViewModel::Common { class EngineResourceProvider : public CalculationManager::IResourceProvider { diff --git a/src/CalcViewModel/Common/ExpressionCommandDeserializer.cpp b/src/CalcViewModel/Common/ExpressionCommandDeserializer.cpp index 509a1659..a91d2d35 100644 --- a/src/CalcViewModel/Common/ExpressionCommandDeserializer.cpp +++ b/src/CalcViewModel/Common/ExpressionCommandDeserializer.cpp @@ -4,7 +4,7 @@ #include "pch.h" #include "ExpressionCommandDeserializer.h" -using namespace CalculatorApp::Common; +using namespace CalculatorApp::ViewModel::Common; using namespace Windows::Storage::Streams; CommandDeserializer::CommandDeserializer(_In_ DataReader ^ dataReader) diff --git a/src/CalcViewModel/Common/ExpressionCommandDeserializer.h b/src/CalcViewModel/Common/ExpressionCommandDeserializer.h index 833b6bf6..aed9afe2 100644 --- a/src/CalcViewModel/Common/ExpressionCommandDeserializer.h +++ b/src/CalcViewModel/Common/ExpressionCommandDeserializer.h @@ -5,7 +5,7 @@ #include "CalcManager/ExpressionCommand.h" -namespace CalculatorApp +namespace CalculatorApp::ViewModel { namespace Common { diff --git a/src/CalcViewModel/Common/ExpressionCommandSerializer.cpp b/src/CalcViewModel/Common/ExpressionCommandSerializer.cpp index fb0cd83a..464bc023 100644 --- a/src/CalcViewModel/Common/ExpressionCommandSerializer.cpp +++ b/src/CalcViewModel/Common/ExpressionCommandSerializer.cpp @@ -4,7 +4,7 @@ #include "pch.h" #include "Common/ExpressionCommandSerializer.h" -using namespace CalculatorApp::Common; +using namespace CalculatorApp::ViewModel::Common; using namespace Windows::Storage::Streams; SerializeCommandVisitor::SerializeCommandVisitor(_In_ DataWriter ^ dataWriter) diff --git a/src/CalcViewModel/Common/ExpressionCommandSerializer.h b/src/CalcViewModel/Common/ExpressionCommandSerializer.h index 23303fe7..d64b19b7 100644 --- a/src/CalcViewModel/Common/ExpressionCommandSerializer.h +++ b/src/CalcViewModel/Common/ExpressionCommandSerializer.h @@ -5,7 +5,7 @@ #include "CalcManager/ExpressionCommand.h" -namespace CalculatorApp +namespace CalculatorApp::ViewModel { namespace Common { diff --git a/src/CalcViewModel/Common/LocalizationService.cpp b/src/CalcViewModel/Common/LocalizationService.cpp index 0e1cb317..5c28e42d 100644 --- a/src/CalcViewModel/Common/LocalizationService.cpp +++ b/src/CalcViewModel/Common/LocalizationService.cpp @@ -6,8 +6,9 @@ #include "LocalizationSettings.h" #include "AppResourceProvider.h" -using namespace CalculatorApp::Common; -using namespace CalculatorApp::Common::LocalizationServiceProperties; +using namespace CalculatorApp::ViewModel::Common; +using namespace CalculatorApp::ViewModel::Common::LocalizationServiceProperties; +using namespace CalculatorApp::ViewModel; using namespace Concurrency; using namespace Platform; using namespace Platform::Collections; @@ -371,7 +372,7 @@ 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() const +DecimalFormatter ^ LocalizationService::GetRegionalSettingsAwareDecimalFormatter() { IIterable ^ languageIdentifiers = LocalizationService::GetLanguageIdentifiers(); if (languageIdentifiers != nullptr) @@ -386,7 +387,7 @@ 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) const +DateTimeFormatter ^ LocalizationService::GetRegionalSettingsAwareDateTimeFormatter(_In_ String ^ format) { IIterable ^ languageIdentifiers = LocalizationService::GetLanguageIdentifiers(); if (languageIdentifiers == nullptr) @@ -399,7 +400,7 @@ DateTimeFormatter ^ LocalizationService::GetRegionalSettingsAwareDateTimeFormatt // 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) const +DateTimeFormatter ^ LocalizationService::GetRegionalSettingsAwareDateTimeFormatter(_In_ String ^ format, _In_ String ^ calendarIdentifier, _In_ String ^ clockIdentifier) { IIterable ^ languageIdentifiers = LocalizationService::GetLanguageIdentifiers(); if (languageIdentifiers == nullptr) @@ -410,7 +411,7 @@ DateTimeFormatter ^ LocalizationService::GetRegionalSettingsAwareDateTimeFormatt return ref new DateTimeFormatter(format, languageIdentifiers, GlobalizationPreferences::HomeGeographicRegion, calendarIdentifier, clockIdentifier); } -CurrencyFormatter ^ LocalizationService::GetRegionalSettingsAwareCurrencyFormatter() const +CurrencyFormatter ^ LocalizationService::GetRegionalSettingsAwareCurrencyFormatter() { String ^ userCurrency = (GlobalizationPreferences::Currencies->Size > 0) ? GlobalizationPreferences::Currencies->GetAt(0) : StringReference(DefaultCurrencyCode.data()); @@ -423,7 +424,7 @@ CurrencyFormatter ^ LocalizationService::GetRegionalSettingsAwareCurrencyFormatt auto currencyFormatter = ref new CurrencyFormatter(userCurrency, languageIdentifiers, GlobalizationPreferences::HomeGeographicRegion); - int fractionDigits = LocalizationSettings::GetInstance().GetCurrencyTrailingDigits(); + int fractionDigits = LocalizationSettings::GetInstance()->GetCurrencyTrailingDigits(); currencyFormatter->FractionDigits = fractionDigits; return currencyFormatter; diff --git a/src/CalcViewModel/Common/LocalizationService.h b/src/CalcViewModel/Common/LocalizationService.h index d6921371..ae7a513e 100644 --- a/src/CalcViewModel/Common/LocalizationService.h +++ b/src/CalcViewModel/Common/LocalizationService.h @@ -5,7 +5,7 @@ #include "Utils.h" -namespace CalculatorApp +namespace CalculatorApp::ViewModel { namespace Common { @@ -30,10 +30,7 @@ namespace CalculatorApp 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(); @@ -42,7 +39,17 @@ namespace CalculatorApp Platform::String ^ GetFontFamilyOverride(); Windows::UI::Text::FontWeight GetFontWeightOverride(); double GetFontScaleFactorOverride(LanguageFontType fontType); + Windows::Globalization::NumberFormatting::DecimalFormatter ^ GetRegionalSettingsAwareDecimalFormatter(); + Windows::Globalization::DateTimeFormatting::DateTimeFormatter ^ GetRegionalSettingsAwareDateTimeFormatter(_In_ Platform::String ^ format); + Windows::Globalization::DateTimeFormatting::DateTimeFormatter + ^ GetRegionalSettingsAwareDateTimeFormatter( + _In_ Platform::String ^ format, + _In_ Platform::String ^ calendarIdentifier, + _In_ Platform::String ^ clockIdentifier); + Windows::Globalization::NumberFormatting::CurrencyFormatter ^ GetRegionalSettingsAwareCurrencyFormatter(); + internal: + static void OverrideWithLanguage(_In_ const wchar_t* const language); void Sort(std::vector& source); template @@ -56,16 +63,6 @@ namespace CalculatorApp }); } - 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; - - Windows::Globalization::NumberFormatting::CurrencyFormatter ^ GetRegionalSettingsAwareCurrencyFormatter() const; - static Platform::String ^ GetNarratorReadableToken(Platform::String ^ rawToken); static Platform::String ^ GetNarratorReadableString(Platform::String ^ rawString); @@ -101,6 +98,5 @@ namespace CalculatorApp double m_uiCaptionFontScaleFactorOverride; std::locale m_locale; }; - } } diff --git a/src/CalcViewModel/Common/LocalizationSettings.h b/src/CalcViewModel/Common/LocalizationSettings.h index 799e6438..0c1db651 100644 --- a/src/CalcViewModel/Common/LocalizationSettings.h +++ b/src/CalcViewModel/Common/LocalizationSettings.h @@ -6,22 +6,191 @@ #include -namespace CalculatorApp +namespace CalculatorApp::ViewModel { namespace Common { - class LocalizationSettings + public ref class LocalizationSettings sealed { private: LocalizationSettings() // Use DecimalFormatter as it respects the locale and the user setting - : LocalizationSettings(LocalizationService::GetInstance()->GetRegionalSettingsAwareDecimalFormatter()) { + Initialize(LocalizationService::GetInstance()->GetRegionalSettingsAwareDecimalFormatter()); } public: // This is only public for unit testing purposes. LocalizationSettings(Windows::Globalization::NumberFormatting::DecimalFormatter ^ formatter) + { + Initialize(formatter); + } + + // Provider of the singleton LocalizationSettings instance. + static LocalizationSettings^ GetInstance() + { + static LocalizationSettings^ localizationSettings = ref new LocalizationSettings(); + return localizationSettings; + } + + Platform::String ^ GetLocaleName() + { + return m_resolvedName; + } + + bool IsDigitEnUsSetting() + { + return (this->GetDigitSymbolFromEnUsDigit('0') == L'0'); + } + + Platform::String ^ GetEnglishValueFromLocalizedDigits(Platform::String ^ localizedString) + { + if (m_resolvedName == L"en-US") + { + return localizedString; + } + + std::wstring englishString; + englishString.reserve(localizedString->Length()); + + for (wchar_t ch : localizedString) + { + if (!IsEnUsDigit(ch)) + { + auto it = std::find(m_digitSymbols.begin(), m_digitSymbols.end(), ch); + + if (it != m_digitSymbols.end()) + { + auto index = std::distance(m_digitSymbols.begin(), it); + ch = index.ToString()->Data()[0]; + } + } + if (ch == m_decimalSeparator) + { + ch = L'.'; + } + englishString += ch; + } + + return ref new Platform::String(englishString.c_str()); + } + + Platform::String ^ RemoveGroupSeparators(Platform::String ^ source) + { + std::wstring destination; + std::copy_if( + begin(source), end(source), std::back_inserter(destination), [this](auto const c) { return c != L' ' && c != m_numberGroupSeparator; }); + + return ref new Platform::String(destination.c_str()); + } + + Platform::String ^ GetCalendarIdentifier() + { + return m_calendarIdentifier; + } + + Windows::Globalization::DayOfWeek GetFirstDayOfWeek() + { + return m_firstDayOfWeek; + } + + int GetCurrencyTrailingDigits() + { + return m_currencyTrailingDigits; + } + + int GetCurrencySymbolPrecedence() + { + return m_currencySymbolPrecedence; + } + + wchar_t GetDecimalSeparator() + { + return m_decimalSeparator; + } + + wchar_t GetDigitSymbolFromEnUsDigit(wchar_t digitSymbol) + { + assert(digitSymbol >= L'0' && digitSymbol <= L'9'); + int digit = digitSymbol - L'0'; + return m_digitSymbols.at(digit); // throws on out of range + } + + wchar_t GetNumberGroupSeparator() + { + return m_numberGroupSeparator; + } + + bool IsEnUsDigit(wchar_t digit) + { + return (digit >= L'0' && digit <= L'9'); + } + + bool IsLocalizedDigit(wchar_t digit) + { + return std::find(m_digitSymbols.begin(), m_digitSymbols.end(), digit) != m_digitSymbols.end(); + } + + bool IsLocalizedHexDigit(wchar_t digit) + { + if (IsLocalizedDigit(digit)) + { + return true; + } + + return std::find(s_hexSymbols.begin(), s_hexSymbols.end(), digit) != s_hexSymbols.end(); + } + + Platform::String ^ GetListSeparatorWinRT() + { + return ref new Platform::String(GetListSeparator().c_str()); + } + + Platform::String ^ GetDecimalSeparatorStrWinRT() + { + return ref new Platform::String(GetDecimalSeparatorStr().c_str()); + } + + internal: + void LocalizeDisplayValue(_Inout_ std::wstring* stringToLocalize) + { + if (IsDigitEnUsSetting()) + { + return; + } + + for (wchar_t& ch : *stringToLocalize) + { + if (IsEnUsDigit(ch)) + { + ch = GetDigitSymbolFromEnUsDigit(ch); + } + } + } + + std::wstring GetDecimalSeparatorStr() + { + return std::wstring(1, m_decimalSeparator); + } + + std::wstring GetNumberGroupingSeparatorStr() + { + return std::wstring(1, m_numberGroupSeparator); + } + + std::wstring GetNumberGroupingStr() + { + return m_numberGrouping; + } + + std::wstring GetListSeparator() + { + return m_listSeparator; + } + + + private: + void Initialize(Windows::Globalization::NumberFormatting::DecimalFormatter ^ formatter) { formatter->FractionDigits = 0; formatter->IsDecimalPointAlwaysDisplayed = false; @@ -125,167 +294,6 @@ namespace CalculatorApp m_firstDayOfWeek = static_cast((_wtoi(day) + 1) % 7); // static cast int to DayOfWeek enum } - // A LocalizationSettings object is not copyable. - LocalizationSettings(const LocalizationSettings&) = delete; - LocalizationSettings& operator=(const LocalizationSettings&) = delete; - - // A LocalizationSettings object is not moveable. - LocalizationSettings(LocalizationSettings&&) = delete; - LocalizationSettings& operator=(LocalizationSettings&&) = delete; - - // Provider of the singleton LocalizationSettings instance. - static const LocalizationSettings& GetInstance() - { - static const LocalizationSettings localizationSettings; - - return localizationSettings; - } - - Platform::String ^ GetLocaleName() const - { - return m_resolvedName; - } - - bool IsDigitEnUsSetting() const - { - return (this->GetDigitSymbolFromEnUsDigit('0') == L'0'); - } - - void LocalizeDisplayValue(_Inout_ std::wstring* stringToLocalize) const - { - if (IsDigitEnUsSetting()) - { - return; - } - - for (wchar_t& ch : *stringToLocalize) - { - if (IsEnUsDigit(ch)) - { - ch = GetDigitSymbolFromEnUsDigit(ch); - } - } - } - - Platform::String ^ GetEnglishValueFromLocalizedDigits(Platform::String ^ localizedString) const - { - if (m_resolvedName == L"en-US") - { - return localizedString; - } - - std::wstring englishString; - englishString.reserve(localizedString->Length()); - - for (wchar_t ch : localizedString) - { - if (!IsEnUsDigit(ch)) - { - auto it = std::find(m_digitSymbols.begin(), m_digitSymbols.end(), ch); - - if (it != m_digitSymbols.end()) - { - auto index = std::distance(m_digitSymbols.begin(), it); - ch = index.ToString()->Data()[0]; - } - } - if (ch == m_decimalSeparator) - { - ch = L'.'; - } - englishString += ch; - } - - return ref new Platform::String(englishString.c_str()); - } - - bool IsEnUsDigit(const wchar_t digit) const - { - return (digit >= L'0' && digit <= L'9'); - } - - bool IsLocalizedDigit(const wchar_t digit) const - { - return std::find(m_digitSymbols.begin(), m_digitSymbols.end(), digit) != m_digitSymbols.end(); - } - - bool IsLocalizedHexDigit(const wchar_t digit) const - { - if (IsLocalizedDigit(digit)) - { - return true; - } - - return std::find(s_hexSymbols.begin(), s_hexSymbols.end(), digit) != s_hexSymbols.end(); - } - - wchar_t GetDigitSymbolFromEnUsDigit(wchar_t digitSymbol) const - { - assert(digitSymbol >= L'0' && digitSymbol <= L'9'); - int digit = digitSymbol - L'0'; - return m_digitSymbols.at(digit); // throws on out of range - } - - wchar_t GetDecimalSeparator() const - { - return m_decimalSeparator; - } - - wchar_t GetNumberGroupSeparator() const - { - return m_numberGroupSeparator; - } - - std::wstring GetDecimalSeparatorStr() const - { - return std::wstring(1, m_decimalSeparator); - } - - std::wstring GetNumberGroupingSeparatorStr() const - { - return std::wstring(1, m_numberGroupSeparator); - } - - std::wstring GetNumberGroupingStr() const - { - return m_numberGrouping; - } - - Platform::String ^ RemoveGroupSeparators(Platform::String ^ source) const - { - std::wstring destination; - std::copy_if( - begin(source), end(source), std::back_inserter(destination), [this](auto const c) { return c != L' ' && c != m_numberGroupSeparator; }); - - return ref new Platform::String(destination.c_str()); - } - - Platform::String ^ GetCalendarIdentifier() const - { - return m_calendarIdentifier; - } - - std::wstring GetListSeparator() const - { - return m_listSeparator; - } - - Windows::Globalization::DayOfWeek GetFirstDayOfWeek() const - { - return m_firstDayOfWeek; - } - - int GetCurrencyTrailingDigits() const - { - return m_currencyTrailingDigits; - } - - int GetCurrencySymbolPrecedence() const - { - return m_currencySymbolPrecedence; - } - - private: static Platform::String^ GetCalendarIdentifierFromCalid(CALID calId) { switch (calId) diff --git a/src/CalcViewModel/Common/LocalizationStringUtil.h b/src/CalcViewModel/Common/LocalizationStringUtil.h index 73da6d0d..33aa482d 100644 --- a/src/CalcViewModel/Common/LocalizationStringUtil.h +++ b/src/CalcViewModel/Common/LocalizationStringUtil.h @@ -5,7 +5,7 @@ #include "AppResourceProvider.h" -namespace CalculatorApp +namespace CalculatorApp::ViewModel { namespace Common { diff --git a/src/CalcViewModel/Common/MyVirtualKey.h b/src/CalcViewModel/Common/MyVirtualKey.h index c530e816..071b4183 100644 --- a/src/CalcViewModel/Common/MyVirtualKey.h +++ b/src/CalcViewModel/Common/MyVirtualKey.h @@ -3,7 +3,7 @@ #pragma once -namespace CalculatorApp +namespace CalculatorApp::ViewModel { namespace Common { diff --git a/src/CalcViewModel/Common/NavCategory.cpp b/src/CalcViewModel/Common/NavCategory.cpp index 6a3c21b9..32bc3877 100644 --- a/src/CalcViewModel/Common/NavCategory.cpp +++ b/src/CalcViewModel/Common/NavCategory.cpp @@ -8,7 +8,8 @@ #include using namespace CalculatorApp; -using namespace CalculatorApp::Common; +using namespace CalculatorApp::ViewModel::Common; +using namespace CalculatorApp::ViewModel; using namespace Concurrency; using namespace Platform; using namespace Platform::Collections; @@ -480,18 +481,19 @@ ViewMode NavCategory::GetViewModeForVirtualKey(MyVirtualKey virtualKey) return (iter != s_categoryManifest.end()) ? iter->viewMode : ViewMode::None; } -vector NavCategory::GetCategoryAcceleratorKeys() +void NavCategory::GetCategoryAcceleratorKeys(IVector ^ accelerators) { - vector accelerators{}; - for (auto category : s_categoryManifest) + if (accelerators != nullptr) { - if (category.virtualKey != MyVirtualKey::None) + accelerators->Clear(); + for (auto category : s_categoryManifest) { - accelerators.push_back(category.virtualKey); + if (category.virtualKey != MyVirtualKey::None) + { + accelerators->Append(category.virtualKey); + } } } - - return accelerators; } NavCategoryGroup::NavCategoryGroup(const NavCategoryGroupInitializer& groupInitializer) @@ -550,3 +552,4 @@ NavCategoryGroup ^ NavCategoryGroup::CreateConverterCategory() return ref new NavCategoryGroup( NavCategoryGroupInitializer{ CategoryGroupType::Converter, L"ConverterModeTextCaps", L"ConverterModeText", L"ConverterModePluralText" }); } + diff --git a/src/CalcViewModel/Common/NavCategory.h b/src/CalcViewModel/Common/NavCategory.h index c0ce95f0..1af04676 100644 --- a/src/CalcViewModel/Common/NavCategory.h +++ b/src/CalcViewModel/Common/NavCategory.h @@ -17,7 +17,7 @@ #include "Utils.h" #include "MyVirtualKey.h" -namespace CalculatorApp +namespace CalculatorApp::ViewModel { namespace Common { @@ -153,6 +153,7 @@ namespace CalculatorApp static int GetPosition(ViewMode mode); static ViewMode GetViewModeForVirtualKey(MyVirtualKey virtualKey); + static void GetCategoryAcceleratorKeys(Windows::Foundation::Collections::IVector ^ resutls); internal : NavCategory( Platform::String ^ name, @@ -174,8 +175,6 @@ namespace CalculatorApp { } - static std::vector GetCategoryAcceleratorKeys(); - private: static bool IsModeInCategoryGroup(ViewMode mode, CategoryGroupType groupType); @@ -193,7 +192,7 @@ namespace CalculatorApp static Windows::Foundation::Collections::IObservableVector ^ CreateMenuOptions(); - internal : static NavCategoryGroup ^ CreateCalculatorCategory(); + static NavCategoryGroup ^ CreateCalculatorCategory(); static NavCategoryGroup ^ CreateConverterCategory(); private: diff --git a/src/CalcViewModel/Common/NetworkManager.cpp b/src/CalcViewModel/Common/NetworkManager.cpp index 8bf3835a..4f032d96 100644 --- a/src/CalcViewModel/Common/NetworkManager.cpp +++ b/src/CalcViewModel/Common/NetworkManager.cpp @@ -5,6 +5,8 @@ #include "NetworkManager.h" using namespace CalculatorApp; +using namespace CalculatorApp::ViewModel; +using namespace CalculatorApp::ViewModel::Common; using namespace Platform; using namespace Windows::Networking::Connectivity; diff --git a/src/CalcViewModel/Common/NetworkManager.h b/src/CalcViewModel/Common/NetworkManager.h index 51903d94..6bf7b7c1 100644 --- a/src/CalcViewModel/Common/NetworkManager.h +++ b/src/CalcViewModel/Common/NetworkManager.h @@ -3,7 +3,7 @@ #pragma once -namespace CalculatorApp +namespace CalculatorApp::ViewModel::Common { public enum class NetworkAccessBehavior diff --git a/src/CalcViewModel/Common/NumberBase.h b/src/CalcViewModel/Common/NumberBase.h index 4e15efa1..6efb323b 100644 --- a/src/CalcViewModel/Common/NumberBase.h +++ b/src/CalcViewModel/Common/NumberBase.h @@ -2,7 +2,7 @@ // Licensed under the MIT License. #pragma once -namespace CalculatorApp::Common +namespace CalculatorApp::ViewModel::Common { public enum class NumberBase diff --git a/src/CalcViewModel/Common/RadixType.cpp b/src/CalcViewModel/Common/RadixType.cpp new file mode 100644 index 00000000..12b45371 --- /dev/null +++ b/src/CalcViewModel/Common/RadixType.cpp @@ -0,0 +1,8 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#include "pch.h" +#include "RadixType.h" + +// export enum RadixType + diff --git a/src/CalcViewModel/Common/RadixType.h b/src/CalcViewModel/Common/RadixType.h new file mode 100644 index 00000000..de4bc8a8 --- /dev/null +++ b/src/CalcViewModel/Common/RadixType.h @@ -0,0 +1,19 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once + +namespace CalculatorApp::ViewModel +{ + namespace Common + { + // This is expected to be in same order as IDM_HEX, IDM_DEC, IDM_OCT, IDM_BIN + public enum class RadixType + { + Hex, + Decimal, + Octal, + Binary + }; + } +} diff --git a/src/CalcViewModel/Common/TraceLogger.cpp b/src/CalcViewModel/Common/TraceLogger.cpp index f58513de..d19f4e01 100644 --- a/src/CalcViewModel/Common/TraceLogger.cpp +++ b/src/CalcViewModel/Common/TraceLogger.cpp @@ -7,7 +7,8 @@ #include "CalculatorButtonUser.h" using namespace CalculatorApp; -using namespace CalculatorApp::Common; +using namespace CalculatorApp::ViewModel::Common; +using namespace CalculatorApp::ViewModel; using namespace TraceLogging; using namespace Concurrency; using namespace std; @@ -147,16 +148,21 @@ namespace CalculatorApp TraceLoggingCommon::GetInstance()->LogLevel2Event(StringReference(EVENT_NAME_EXCEPTION), fields); } - void TraceLogger::LogPlatformException(ViewMode mode, wstring_view functionName, Platform::Exception ^ e) + void TraceLogger::LogPlatformExceptionInfo(CalculatorApp::ViewModel::Common::ViewMode mode, Platform::String ^ functionName, Platform::String^ message, int hresult) { auto fields = ref new LoggingFields(); fields->AddString(StringReference(CALC_MODE), NavCategory::GetFriendlyName(mode)); - fields->AddString(StringReference(L"FunctionName"), StringReference(functionName.data())); - fields->AddString(StringReference(L"Message"), e->Message); - fields->AddInt32(StringReference(L"HRESULT"), e->HResult); + fields->AddString(StringReference(L"FunctionName"), functionName); + fields->AddString(StringReference(L"Message"), message); + fields->AddInt32(StringReference(L"HRESULT"), hresult); TraceLoggingCommon::GetInstance()->LogLevel2Event(StringReference(EVENT_NAME_EXCEPTION), fields); } + void TraceLogger::LogPlatformException(ViewMode mode, Platform::String ^ functionName, Platform::Exception ^ e) + { + LogPlatformExceptionInfo(mode, functionName, e->Message, e->HResult); + } + void TraceLogger::UpdateButtonUsage(NumbersAndOperatorsEnum button, ViewMode mode) { // IsProgrammerMode, IsScientificMode, IsStandardMode and None are not actual buttons, so ignore them diff --git a/src/CalcViewModel/Common/TraceLogger.h b/src/CalcViewModel/Common/TraceLogger.h index cef592e8..e82d3645 100644 --- a/src/CalcViewModel/Common/TraceLogger.h +++ b/src/CalcViewModel/Common/TraceLogger.h @@ -8,15 +8,15 @@ // A trace logging provider can only be instantiated and registered once per module. // This class implements a singleton model ensure that only one instance is created. -namespace CalculatorApp +namespace CalculatorApp::ViewModel::Common { struct ButtonLog { public: int count; - CalculatorApp::NumbersAndOperatorsEnum button; - CalculatorApp::Common::ViewMode mode; - ButtonLog(CalculatorApp::NumbersAndOperatorsEnum btn, CalculatorApp::Common::ViewMode vMode) + CalculatorApp::ViewModel::Common::NumbersAndOperatorsEnum button; + CalculatorApp::ViewModel::Common::ViewMode mode; + ButtonLog(CalculatorApp::ViewModel::Common::NumbersAndOperatorsEnum btn, CalculatorApp::ViewModel::Common::ViewMode vMode) { button = btn; mode = vMode; @@ -62,20 +62,20 @@ namespace CalculatorApp public: static TraceLogger ^ GetInstance(); - void LogModeChange(CalculatorApp::Common::ViewMode mode); - void LogHistoryItemLoad(CalculatorApp::Common::ViewMode mode, int historyListSize, int loadedIndex); - void LogMemoryItemLoad(CalculatorApp::Common::ViewMode mode, int memoryListSize, int loadedIndex); - void UpdateButtonUsage(CalculatorApp::NumbersAndOperatorsEnum button, CalculatorApp::Common::ViewMode mode); + void LogModeChange(CalculatorApp::ViewModel::Common::ViewMode mode); + void LogHistoryItemLoad(CalculatorApp::ViewModel::Common::ViewMode mode, int historyListSize, int loadedIndex); + void LogMemoryItemLoad(CalculatorApp::ViewModel::Common::ViewMode mode, int memoryListSize, int loadedIndex); + void UpdateButtonUsage(CalculatorApp::ViewModel::Common::NumbersAndOperatorsEnum button, CalculatorApp::ViewModel::Common::ViewMode mode); void LogButtonUsage(); void LogDateCalculationModeUsed(bool AddSubtractMode); void UpdateWindowCount(uint64 windowCount); void DecreaseWindowCount(); bool IsWindowIdInLog(int windowId); - void LogVisualStateChanged(CalculatorApp::Common::ViewMode mode, Platform::String ^ state, bool isAlwaysOnTop); - void LogWindowCreated(CalculatorApp::Common::ViewMode mode, int windowId); - void LogConverterInputReceived(CalculatorApp::Common::ViewMode mode); + void LogVisualStateChanged(CalculatorApp::ViewModel::Common::ViewMode mode, Platform::String ^ state, bool isAlwaysOnTop); + void LogWindowCreated(CalculatorApp::ViewModel::Common::ViewMode mode, int windowId); + void LogConverterInputReceived(CalculatorApp::ViewModel::Common::ViewMode mode); void LogNavBarOpened(); - void LogError(CalculatorApp::Common::ViewMode mode, Platform::String ^ functionName, Platform::String ^ errorString); + void LogError(CalculatorApp::ViewModel::Common::ViewMode mode, Platform::String ^ functionName, Platform::String ^ errorString); void LogShowHideButtonClicked(bool isHideButton); void LogGraphButtonClicked(GraphButton buttonName, GraphButtonValue buttonValue); void LogGraphLineStyleChanged(LineStyleType style); @@ -83,10 +83,12 @@ namespace CalculatorApp void LogVariableSettingsChanged(Platform::String ^ setting); void LogGraphSettingsChanged(GraphSettingsType settingsType, Platform::String ^ settingValue); void LogGraphTheme(Platform::String ^ graphTheme); + void LogInputPasted(CalculatorApp::ViewModel::Common::ViewMode mode); + void LogPlatformExceptionInfo(CalculatorApp::ViewModel::Common::ViewMode mode, Platform::String ^ functionName, Platform::String ^ message, int hresult); + internal: - void LogStandardException(CalculatorApp::Common::ViewMode mode, std::wstring_view functionName, _In_ const std::exception& e); - void LogPlatformException(CalculatorApp::Common::ViewMode mode, std::wstring_view functionName, _In_ Platform::Exception ^ e); - void LogInputPasted(CalculatorApp::Common::ViewMode mode); + void LogPlatformException(CalculatorApp::ViewModel::Common::ViewMode mode, Platform::String ^ functionName, Platform::Exception ^ e); + void LogStandardException(CalculatorApp::ViewModel::Common::ViewMode mode, std::wstring_view functionName, _In_ const std::exception& e); private: // Create an instance of TraceLogger diff --git a/src/CalcViewModel/Common/Utils.cpp b/src/CalcViewModel/Common/Utils.cpp index 6bcc527d..8715cea1 100644 --- a/src/CalcViewModel/Common/Utils.cpp +++ b/src/CalcViewModel/Common/Utils.cpp @@ -6,13 +6,17 @@ // #include "pch.h" + +#include + #include "Utils.h" #include "Common/AppResourceProvider.h" #include "Common/ExpressionCommandSerializer.h" #include "Common/ExpressionCommandDeserializer.h" +#include "CalcManager/NumberFormattingUtils.h" using namespace CalculatorApp; -using namespace CalculatorApp::Common; +using namespace CalculatorApp::ViewModel::Common; using namespace concurrency; using namespace Graphing::Renderer; using namespace Platform; @@ -168,18 +172,20 @@ void Utils::TrimBack(wstring& value) }).base(), value.end()); } -String^ Utils::EscapeHtmlSpecialCharacters(String^ originalString, shared_ptr> specialCharacters) +bool operator==(const Color& color1, const Color& color2) +{ + return equal_to()(color1, color2); +} + +bool operator!=(const Color& color1, const Color& color2) +{ + return !(color1 == color2); +} + +String^ CalculatorApp::ViewModel::Common::Utilities::EscapeHtmlSpecialCharacters(String^ originalString) { // Construct a default special characters if not provided. - if (specialCharacters == nullptr) - { - specialCharacters = make_shared>(); - specialCharacters->push_back(L'&'); - specialCharacters->push_back(L'\"'); - specialCharacters->push_back(L'\''); - specialCharacters->push_back(L'<'); - specialCharacters->push_back(L'>'); - } + const std::vector specialCharacters {L'&', L'\"', L'\'', L'<', L'>'}; bool replaceCharacters = false; const wchar_t* pCh; @@ -189,7 +195,7 @@ String^ Utils::EscapeHtmlSpecialCharacters(String^ originalString, shared_ptrData(); *pCh; pCh++) { - if (std::find(specialCharacters->begin(), specialCharacters->end(), *pCh) != specialCharacters->end()) + if (std::find(specialCharacters.begin(), specialCharacters.end(), *pCh) != specialCharacters.end()) { replaceCharacters = true; break; @@ -233,20 +239,22 @@ String^ Utils::EscapeHtmlSpecialCharacters(String^ originalString, shared_ptr()(color1, color2); + std::wstring tmp(input->Data()); + CalcManager::NumberFormattingUtils::TrimTrailingZeros(tmp); + return ref new Platform::String(tmp.c_str()); } -bool operator!=(const Color& color1, const Color& color2) +bool CalculatorApp::ViewModel::Common::Utilities::AreColorsEqual(Windows::UI::Color color1, Windows::UI::Color color2) { - return !(color1 == color2); + return Utils::AreColorsEqual(color1, color2); } // This method calculates the luminance ratio between White and the given background color. // The luminance is calculate using the RGB values and does not use the A value. // White or Black is returned -SolidColorBrush ^ Utils::GetContrastColor(Color backgroundColor) +SolidColorBrush ^ CalculatorApp::ViewModel::Common::Utilities::GetContrastColor(Color backgroundColor) { auto luminance = 0.2126 * backgroundColor.R + 0.7152 * backgroundColor.G + 0.0722 * backgroundColor.B; @@ -257,3 +265,21 @@ SolidColorBrush ^ Utils::GetContrastColor(Color backgroundColor) return static_cast(Application::Current->Resources->Lookup(L"BlackBrush")); } + +int CalculatorApp::ViewModel::Common::Utilities::GetWindowId() +{ + return Utils::GetWindowId(); +} + +long long CalculatorApp::ViewModel::Common::Utilities::GetConst_WINEVENT_KEYWORD_RESPONSE_TIME() +{ + return WINEVENT_KEYWORD_RESPONSE_TIME; +} + +bool CalculatorApp::ViewModel::Common::Utilities::GetIntegratedDisplaySize(double* size) +{ + if (SUCCEEDED(::GetIntegratedDisplaySize(size))) + return true; + return false; +} + diff --git a/src/CalcViewModel/Common/Utils.h b/src/CalcViewModel/Common/Utils.h index 701969ea..cd04350d 100644 --- a/src/CalcViewModel/Common/Utils.h +++ b/src/CalcViewModel/Common/Utils.h @@ -168,11 +168,22 @@ public: // 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 {\ - 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; \ + property Windows::UI::Xaml::Input::ICommand ^ p \ + { \ + Windows::UI::Xaml::Input::ICommand ^ get() \ + { \ + if (!donotuse_##p) \ + { \ + donotuse_##p = ref new CalculatorApp::ViewModel::Common::DelegateCommand( \ + CalculatorApp::ViewModel::Common::MakeDelegateCommandHandler(this, &m) \ + ); \ + } \ + return donotuse_##p; \ + } \ + } \ + \ +private: \ + Windows::UI::Xaml::Input::ICommand ^ donotuse_##p; \ \ public: @@ -398,10 +409,6 @@ namespace Utils void Trim(std::wstring& value); void TrimFront(std::wstring& value); void TrimBack(std::wstring& value); - - Platform::String ^ EscapeHtmlSpecialCharacters(Platform::String ^ originalString, std::shared_ptr> specialCharacters = nullptr); - - Windows::UI::Xaml::Media::SolidColorBrush ^ GetContrastColor(Windows::UI::Color backgroundColor); } // This goes into the header to define the property, in the public: section of the class @@ -697,6 +704,23 @@ namespace CalculatorApp return to; } + + namespace ViewModel::Common + { + // below utilities are intended to support interops between C# and C++/CX + // they can be removed if the entire codebase has been migrated to C# + public ref class Utilities sealed + { + public: + static Platform::String ^ EscapeHtmlSpecialCharacters(Platform::String ^ originalString); + static Platform::String^ TrimTrailingZeros(Platform::String^ input); + static bool AreColorsEqual(Windows::UI::Color color1, Windows::UI::Color color2); + static Windows::UI::Xaml::Media::SolidColorBrush ^ GetContrastColor(Windows::UI::Color backgroundColor); + static int GetWindowId(); + static long long GetConst_WINEVENT_KEYWORD_RESPONSE_TIME(); + static bool GetIntegratedDisplaySize(double* size); + }; + } } // There's no standard definition of equality for Windows::UI::Color structs. diff --git a/src/CalcViewModel/DataLoaders/CurrencyDataLoader.cpp b/src/CalcViewModel/DataLoaders/CurrencyDataLoader.cpp index 5aa6a708..0eb32714 100644 --- a/src/CalcViewModel/DataLoaders/CurrencyDataLoader.cpp +++ b/src/CalcViewModel/DataLoaders/CurrencyDataLoader.cpp @@ -11,11 +11,11 @@ #include "UnitConverterDataConstants.h" using namespace CalculatorApp; -using namespace CalculatorApp::Common; -using namespace CalculatorApp::Common::LocalizationServiceProperties; -using namespace CalculatorApp::DataLoaders; +using namespace CalculatorApp::ViewModel::Common; +using namespace CalculatorApp::ViewModel::Common::LocalizationServiceProperties; +using namespace CalculatorApp::ViewModel::DataLoaders; using namespace CalculatorApp::ViewModel; -using namespace CalculatorApp::ViewModel::CurrencyDataLoaderConstants; +using namespace CalculatorApp::ViewModel::DataLoaders::CurrencyDataLoaderConstants; using namespace concurrency; using namespace Platform; using namespace std; @@ -69,7 +69,7 @@ static constexpr auto DEFAULT_TO_CURRENCY = L"EUR"; namespace CalculatorApp { - namespace ViewModel + namespace ViewModel::DataLoaders { namespace UnitConverterResourceKeys { @@ -300,7 +300,7 @@ pair CurrencyDataLoader::GetCurrencyRatioEquality(_In_ const U double ratio = (iter2->second).ratio; double rounded = RoundCurrencyRatio(ratio); - auto digit = LocalizationSettings::GetInstance().GetDigitSymbolFromEnUsDigit(L'1'); + auto digit = LocalizationSettings::GetInstance()->GetDigitSymbolFromEnUsDigit(L'1'); auto digitSymbol = ref new String(&digit, 1); auto roundedFormat = m_ratioFormatter->Format(rounded); diff --git a/src/CalcViewModel/DataLoaders/CurrencyDataLoader.h b/src/CalcViewModel/DataLoaders/CurrencyDataLoader.h index 3216d63e..6ee878be 100644 --- a/src/CalcViewModel/DataLoaders/CurrencyDataLoader.h +++ b/src/CalcViewModel/DataLoaders/CurrencyDataLoader.h @@ -9,7 +9,7 @@ namespace CalculatorApp { - namespace ViewModel + namespace ViewModel::DataLoaders { public enum class CurrencyLoadStatus @@ -54,7 +54,9 @@ namespace CalculatorApp class CurrencyDataLoader : public UCM::IConverterDataLoader, public UCM::ICurrencyConverterDataLoader { public: - CurrencyDataLoader(_In_ std::unique_ptr client, const wchar_t* overrideLanguage = nullptr); + CurrencyDataLoader( + _In_ std::unique_ptr client, + const wchar_t* overrideLanguage = nullptr); ~CurrencyDataLoader(); bool LoadFinished(); @@ -82,7 +84,7 @@ namespace CalculatorApp std::future TryLoadDataFromWebOverrideAsync() override; // ICurrencyConverterDataLoader - void OnNetworkBehaviorChanged(CalculatorApp::NetworkAccessBehavior newBehavior); + void OnNetworkBehaviorChanged(CalculatorApp::ViewModel::Common::NetworkAccessBehavior newBehavior); private: void ResetLoadStatus(); @@ -112,7 +114,7 @@ namespace CalculatorApp private: Platform::String ^ m_responseLanguage; - std::unique_ptr m_client; + std::unique_ptr m_client; bool m_isRtlLanguage; @@ -130,8 +132,8 @@ namespace CalculatorApp CurrencyLoadStatus m_loadStatus; - CalculatorApp::NetworkManager ^ m_networkManager; - CalculatorApp::NetworkAccessBehavior m_networkAccessBehavior; + CalculatorApp::ViewModel::Common::NetworkManager ^ m_networkManager; + CalculatorApp::ViewModel::Common::NetworkAccessBehavior m_networkAccessBehavior; Windows::Foundation::EventRegistrationToken m_networkBehaviorToken; bool m_meteredOverrideSet; }; diff --git a/src/CalcViewModel/DataLoaders/CurrencyHttpClient.cpp b/src/CalcViewModel/DataLoaders/CurrencyHttpClient.cpp index e9d42c6c..39786f32 100644 --- a/src/CalcViewModel/DataLoaders/CurrencyHttpClient.cpp +++ b/src/CalcViewModel/DataLoaders/CurrencyHttpClient.cpp @@ -11,6 +11,7 @@ #endif using namespace CalculatorApp::DataLoaders; +using namespace CalculatorApp::ViewModel::DataLoaders; using namespace Platform; using namespace std; using namespace Windows::Foundation; diff --git a/src/CalcViewModel/DataLoaders/CurrencyHttpClient.h b/src/CalcViewModel/DataLoaders/CurrencyHttpClient.h index cfd10e7d..8f667c7c 100644 --- a/src/CalcViewModel/DataLoaders/CurrencyHttpClient.h +++ b/src/CalcViewModel/DataLoaders/CurrencyHttpClient.h @@ -7,7 +7,7 @@ namespace CalculatorApp { - namespace DataLoaders + namespace ViewModel::DataLoaders { class CurrencyHttpClient : public ICurrencyHttpClient { diff --git a/src/CalcViewModel/DataLoaders/ICurrencyHttpClient.h b/src/CalcViewModel/DataLoaders/ICurrencyHttpClient.h index 69f23f52..84104b7b 100644 --- a/src/CalcViewModel/DataLoaders/ICurrencyHttpClient.h +++ b/src/CalcViewModel/DataLoaders/ICurrencyHttpClient.h @@ -5,7 +5,7 @@ namespace CalculatorApp { - namespace DataLoaders + namespace ViewModel::DataLoaders { class ICurrencyHttpClient { diff --git a/src/CalcViewModel/DataLoaders/UnitConverterDataConstants.h b/src/CalcViewModel/DataLoaders/UnitConverterDataConstants.h index 0d22a14a..099b3b1f 100644 --- a/src/CalcViewModel/DataLoaders/UnitConverterDataConstants.h +++ b/src/CalcViewModel/DataLoaders/UnitConverterDataConstants.h @@ -3,7 +3,7 @@ namespace CalculatorApp { - namespace ViewModel + namespace ViewModel::Common { private enum UnitConverterUnits diff --git a/src/CalcViewModel/DataLoaders/UnitConverterDataLoader.cpp b/src/CalcViewModel/DataLoaders/UnitConverterDataLoader.cpp index 601b0112..564bf314 100644 --- a/src/CalcViewModel/DataLoaders/UnitConverterDataLoader.cpp +++ b/src/CalcViewModel/DataLoaders/UnitConverterDataLoader.cpp @@ -7,8 +7,8 @@ #include "UnitConverterDataConstants.h" #include "CurrencyDataLoader.h" -using namespace CalculatorApp::Common; -using namespace CalculatorApp::DataLoaders; +using namespace CalculatorApp::ViewModel::Common; +using namespace CalculatorApp::ViewModel::DataLoaders; using namespace CalculatorApp::ViewModel; using namespace Platform; using namespace std; diff --git a/src/CalcViewModel/DataLoaders/UnitConverterDataLoader.h b/src/CalcViewModel/DataLoaders/UnitConverterDataLoader.h index 0011fdb6..beb5be63 100644 --- a/src/CalcViewModel/DataLoaders/UnitConverterDataLoader.h +++ b/src/CalcViewModel/DataLoaders/UnitConverterDataLoader.h @@ -8,7 +8,7 @@ namespace CalculatorApp { - namespace ViewModel + namespace ViewModel::Common { struct OrderedUnit : UnitConversionManager::Unit { @@ -34,7 +34,7 @@ namespace CalculatorApp struct UnitData { - CalculatorApp::Common::ViewMode categoryId; + CalculatorApp::ViewModel::Common::ViewMode categoryId; int unitId; double factor; }; @@ -45,7 +45,7 @@ namespace CalculatorApp { } ExplicitUnitConversionData( - CalculatorApp::Common::ViewMode categoryId, + CalculatorApp::ViewModel::Common::ViewMode categoryId, int parentUnitId, int unitId, double ratio, @@ -58,7 +58,7 @@ namespace CalculatorApp { } - CalculatorApp::Common::ViewMode categoryId; + CalculatorApp::ViewModel::Common::ViewMode categoryId; int parentUnitId; int unitId; }; @@ -79,10 +79,9 @@ namespace CalculatorApp // IConverterDataLoader void GetCategories(_In_ std::shared_ptr> categoriesList); - void GetUnits(_In_ std::unordered_map>& unitMap); - void GetConversionData(_In_ std::unordered_map>& categoryToUnitConversionMap); - void - GetExplicitConversionData(_In_ std::unordered_map>& unitToUnitConversionList); + void GetUnits(_In_ std::unordered_map>& unitMap); + void GetConversionData(_In_ std::unordered_map>& categoryToUnitConversionMap); + void GetExplicitConversionData(_In_ std::unordered_map>& unitToUnitConversionList); std::wstring GetLocalizedStringName(_In_ Platform::String ^ stringId); diff --git a/src/CalcViewModel/DateCalculatorViewModel.cpp b/src/CalcViewModel/DateCalculatorViewModel.cpp index a34c1288..ff8e0d9c 100644 --- a/src/CalcViewModel/DateCalculatorViewModel.cpp +++ b/src/CalcViewModel/DateCalculatorViewModel.cpp @@ -10,8 +10,8 @@ #include "Common/CopyPasteManager.h" using namespace CalculatorApp; -using namespace CalculatorApp::Common; -using namespace CalculatorApp::Common::DateCalculation; +using namespace CalculatorApp::ViewModel::Common; +using namespace CalculatorApp::ViewModel::Common::DateCalculation; using namespace CalculatorApp::ViewModel; using namespace Platform; using namespace Platform::Collections; @@ -45,13 +45,13 @@ DateCalculatorViewModel::DateCalculatorViewModel() , m_StrDateResult(L"") , m_StrDateResultAutomationName(L"") { - const auto & localizationSettings = LocalizationSettings::GetInstance(); + LocalizationSettings^ localizationSettings = LocalizationSettings::GetInstance(); // Initialize Date Output format instances - InitializeDateOutputFormats(localizationSettings.GetCalendarIdentifier()); + InitializeDateOutputFormats(localizationSettings->GetCalendarIdentifier()); // Initialize Date Calc engine - m_dateCalcEngine = ref new DateCalculationEngine(localizationSettings.GetCalendarIdentifier()); + m_dateCalcEngine = ref new DateCalculationEngine(localizationSettings->GetCalendarIdentifier()); // 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 @@ -68,7 +68,7 @@ DateCalculatorViewModel::DateCalculatorViewModel() // Initialize the list separator delimiter appended with a space at the end, e.g. ", " // This will be used for date difference formatting: Y years, M months, W weeks, D days - m_listSeparator = localizationSettings.GetListSeparator() + L" "; + m_listSeparator = localizationSettings->GetListSeparator() + L" "; // Initialize the output results UpdateDisplayResult(); @@ -77,7 +77,7 @@ DateCalculatorViewModel::DateCalculatorViewModel() for (int i = 0; i <= c_maxOffsetValue; i++) { wstring numberStr(to_wstring(i)); - localizationSettings.LocalizeDisplayValue(&numberStr); + localizationSettings->LocalizeDisplayValue(&numberStr); m_offsetValues->Append(ref new String(numberStr.c_str())); } @@ -378,7 +378,7 @@ void DateCalculatorViewModel::OnCopyCommand(Platform::Object ^ parameter) String ^ DateCalculatorViewModel::GetLocalizedNumberString(int value) const { wstring numberStr(to_wstring(value)); - LocalizationSettings::GetInstance().LocalizeDisplayValue(&numberStr); + LocalizationSettings::GetInstance()->LocalizeDisplayValue(&numberStr); return ref new String(numberStr.c_str()); } diff --git a/src/CalcViewModel/DateCalculatorViewModel.h b/src/CalcViewModel/DateCalculatorViewModel.h index 48573784..7d9ff0ab 100644 --- a/src/CalcViewModel/DateCalculatorViewModel.h +++ b/src/CalcViewModel/DateCalculatorViewModel.h @@ -125,26 +125,26 @@ namespace CalculatorApp } } - property CalculatorApp::Common::DateCalculation::DateDifference DateDiffResult + property CalculatorApp::ViewModel::Common::DateCalculation::DateDifference DateDiffResult { - CalculatorApp::Common::DateCalculation::DateDifference get() + CalculatorApp::ViewModel::Common::DateCalculation::DateDifference get() { return m_dateDiffResult; } - void set(CalculatorApp::Common::DateCalculation::DateDifference value) + void set(CalculatorApp::ViewModel::Common::DateCalculation::DateDifference value) { m_dateDiffResult = value; UpdateDisplayResult(); } } - property CalculatorApp::Common::DateCalculation::DateDifference DateDiffResultInDays + property CalculatorApp::ViewModel::Common::DateCalculation::DateDifference DateDiffResultInDays { - CalculatorApp::Common::DateCalculation::DateDifference get() + CalculatorApp::ViewModel::Common::DateCalculation::DateDifference get() { return m_dateDiffResultInDays; } - void set(CalculatorApp::Common::DateCalculation::DateDifference value) + void set(CalculatorApp::ViewModel::Common::DateCalculation::DateDifference value) { m_dateDiffResultInDays = value; UpdateDisplayResult(); @@ -172,13 +172,13 @@ namespace CalculatorApp Windows::Foundation::DateTime m_toDate; Windows::Foundation::DateTime m_startDate; Windows::Foundation::DateTime m_dateResult; - CalculatorApp::Common::DateCalculation::DateDifference m_dateDiffResult; - CalculatorApp::Common::DateCalculation::DateDifference m_dateDiffResultInDays; + CalculatorApp::ViewModel::Common::DateCalculation::DateDifference m_dateDiffResult; + CalculatorApp::ViewModel::Common::DateCalculation::DateDifference m_dateDiffResultInDays; // Private members - CalculatorApp::Common::DateCalculation::DateCalculationEngine ^ m_dateCalcEngine; - CalculatorApp::Common::DateCalculation::DateUnit m_daysOutputFormat; - CalculatorApp::Common::DateCalculation::DateUnit m_allDateUnitsOutputFormat; + CalculatorApp::ViewModel::Common::DateCalculation::DateCalculationEngine ^ m_dateCalcEngine; + CalculatorApp::ViewModel::Common::DateCalculation::DateUnit m_daysOutputFormat; + CalculatorApp::ViewModel::Common::DateCalculation::DateUnit m_allDateUnitsOutputFormat; Windows::Globalization::DateTimeFormatting::DateTimeFormatter ^ m_dateTimeFormatter; std::wstring m_listSeparator; }; diff --git a/src/CalcViewModel/GraphingCalculator/EquationViewModel.cpp b/src/CalcViewModel/GraphingCalculator/EquationViewModel.cpp index 50592aa4..e7829c75 100644 --- a/src/CalcViewModel/GraphingCalculator/EquationViewModel.cpp +++ b/src/CalcViewModel/GraphingCalculator/EquationViewModel.cpp @@ -6,7 +6,7 @@ #include "CalcViewModel\Common\LocalizationSettings.h" #include "CalcViewModel\GraphingCalculatorEnums.h" -using namespace CalculatorApp::Common; +using namespace CalculatorApp::ViewModel::Common; using namespace Graphing; using namespace Platform; using namespace Platform::Collections; @@ -245,7 +245,7 @@ namespace CalculatorApp::ViewModel return; } - Platform::String ^ separator = ref new String(LocalizationSettings::GetInstance().GetListSeparator().c_str()); + Platform::String ^ separator = ref new String(LocalizationSettings::GetInstance()->GetListSeparator().c_str()); wstring error; if ((graphEquation->TooComplexFeatures & KeyGraphFeaturesFlag::Domain) == KeyGraphFeaturesFlag::Domain) diff --git a/src/CalcViewModel/GraphingCalculator/GraphingSettingsViewModel.cpp b/src/CalcViewModel/GraphingCalculator/GraphingSettingsViewModel.cpp index 3c7de353..8bb0d7f8 100644 --- a/src/CalcViewModel/GraphingCalculator/GraphingSettingsViewModel.cpp +++ b/src/CalcViewModel/GraphingCalculator/GraphingSettingsViewModel.cpp @@ -6,6 +6,7 @@ #include using namespace CalculatorApp::ViewModel; +using namespace CalculatorApp::ViewModel::Common; using namespace CalcManager::NumberFormattingUtils; using namespace GraphControl; using namespace std; @@ -102,7 +103,7 @@ void GraphingSettingsViewModel::UpdateDisplayRange() m_Graph->SetDisplayRanges(m_XMinValue, m_XMaxValue, m_YMinValue, m_YMaxValue); - TraceLogger::GetInstance()->LogGraphSettingsChanged(GraphSettingsType::Grid, L""); + CalculatorApp::ViewModel::Common::TraceLogger::GetInstance()->LogGraphSettingsChanged(GraphSettingsType::Grid, L""); } bool GraphingSettingsViewModel::HasError() diff --git a/src/CalcViewModel/GraphingCalculator/GraphingSettingsViewModel.h b/src/CalcViewModel/GraphingCalculator/GraphingSettingsViewModel.h index 6d6045c0..77f1dda1 100644 --- a/src/CalcViewModel/GraphingCalculator/GraphingSettingsViewModel.h +++ b/src/CalcViewModel/GraphingCalculator/GraphingSettingsViewModel.h @@ -232,7 +232,7 @@ namespace CalculatorApp::ViewModel RaisePropertyChanged(L"TrigModeDegrees"); RaisePropertyChanged(L"TrigModeGradians"); - TraceLogger::GetInstance()->LogGraphSettingsChanged(GraphSettingsType::TrigUnits, L"Radians"); + CalculatorApp::ViewModel::Common::TraceLogger::GetInstance()->LogGraphSettingsChanged(CalculatorApp::ViewModel::Common::GraphSettingsType::TrigUnits, L"Radians"); } } } @@ -253,7 +253,7 @@ namespace CalculatorApp::ViewModel RaisePropertyChanged(L"TrigModeRadians"); RaisePropertyChanged(L"TrigModeGradians"); - TraceLogger::GetInstance()->LogGraphSettingsChanged(GraphSettingsType::TrigUnits, L"Degrees"); + CalculatorApp::ViewModel::Common::TraceLogger::GetInstance()->LogGraphSettingsChanged(CalculatorApp::ViewModel::Common::GraphSettingsType::TrigUnits, L"Degrees"); } } } @@ -274,7 +274,7 @@ namespace CalculatorApp::ViewModel RaisePropertyChanged(L"TrigModeDegrees"); RaisePropertyChanged(L"TrigModeRadians"); - TraceLogger::GetInstance()->LogGraphSettingsChanged(GraphSettingsType::TrigUnits, L"Gradians"); + CalculatorApp::ViewModel::Common::TraceLogger::GetInstance()->LogGraphSettingsChanged(CalculatorApp::ViewModel::Common::GraphSettingsType::TrigUnits, L"Gradians"); } } } diff --git a/src/CalcViewModel/GraphingCalculator/VariableViewModel.h b/src/CalcViewModel/GraphingCalculator/VariableViewModel.h index 151499ec..6c15fba3 100644 --- a/src/CalcViewModel/GraphingCalculator/VariableViewModel.h +++ b/src/CalcViewModel/GraphingCalculator/VariableViewModel.h @@ -127,8 +127,8 @@ public { Platform::String ^ get() { - return CalculatorApp::Common::LocalizationStringUtil::GetLocalizedString( - CalculatorApp::AppResourceProvider::GetInstance()->GetResourceString(L"VariableListViewItem"), Name); + return CalculatorApp::ViewModel::Common::LocalizationStringUtil::GetLocalizedString( + CalculatorApp::ViewModel::Common::AppResourceProvider::GetInstance()->GetResourceString(L"VariableListViewItem"), Name); } } diff --git a/src/CalcViewModel/HistoryItemViewModel.cpp b/src/CalcViewModel/HistoryItemViewModel.cpp index 95775bb9..023ab643 100644 --- a/src/CalcViewModel/HistoryItemViewModel.cpp +++ b/src/CalcViewModel/HistoryItemViewModel.cpp @@ -5,7 +5,7 @@ #include "HistoryItemViewModel.h" #include "Common/LocalizationService.h" -using namespace CalculatorApp::Common; +using namespace CalculatorApp::ViewModel::Common; using namespace CalculatorApp::ViewModel; using namespace std; using namespace Platform; diff --git a/src/CalcViewModel/HistoryViewModel.cpp b/src/CalcViewModel/HistoryViewModel.cpp index 8235c93a..0953486d 100644 --- a/src/CalcViewModel/HistoryViewModel.cpp +++ b/src/CalcViewModel/HistoryViewModel.cpp @@ -9,8 +9,8 @@ #include "StandardCalculatorViewModel.h" using namespace CalculatorApp; -using namespace CalculatorApp::Common; -using namespace CalculatorApp::Common::Automation; +using namespace CalculatorApp::ViewModel::Common; +using namespace CalculatorApp::ViewModel::Common::Automation; using namespace CalculatorApp::ViewModel; using namespace Platform; using namespace std; @@ -57,15 +57,15 @@ void HistoryViewModel::ReloadHistory(_In_ ViewMode currentMode) auto historyListModel = m_calculatorManager->GetHistoryItems(m_currentMode); auto historyListVM = ref new Platform::Collections::Vector(); - const auto& localizer = LocalizationSettings::GetInstance(); + LocalizationSettings^ localizer = LocalizationSettings::GetInstance(); if (historyListModel.size() > 0) { for (auto ritr = historyListModel.rbegin(); ritr != historyListModel.rend(); ++ritr) { wstring expression = (*ritr)->historyItemVector.expression; wstring result = (*ritr)->historyItemVector.result; - localizer.LocalizeDisplayValue(&expression); - localizer.LocalizeDisplayValue(&result); + localizer->LocalizeDisplayValue(&expression); + localizer->LocalizeDisplayValue(&result); auto item = ref new HistoryItemViewModel( ref new Platform::String(expression.c_str()), @@ -83,11 +83,11 @@ void HistoryViewModel::ReloadHistory(_In_ ViewMode currentMode) void HistoryViewModel::OnHistoryItemAdded(_In_ unsigned int addedItemIndex) { auto newItem = m_calculatorManager->GetHistoryItem(addedItemIndex); - const auto& localizer = LocalizationSettings::GetInstance(); + LocalizationSettings^ localizer = LocalizationSettings::GetInstance(); wstring expression = newItem->historyItemVector.expression; wstring result = newItem->historyItemVector.result; - localizer.LocalizeDisplayValue(&expression); - localizer.LocalizeDisplayValue(&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()), @@ -133,7 +133,7 @@ void HistoryViewModel::DeleteItem(_In_ HistoryItemViewModel ^ e) } // Adding 1 to the history item index to provide 1-based numbering on announcements. wstring localizedIndex = to_wstring(itemIndex + 1); - LocalizationSettings::GetInstance().LocalizeDisplayValue(&localizedIndex); + LocalizationSettings::GetInstance()->LocalizeDisplayValue(&localizedIndex); m_localizedHistorySlotCleared = AppResourceProvider::GetInstance()->GetResourceString(HistoryResourceKeys::HistorySlotCleared); String ^ announcement = LocalizationStringUtil::GetLocalizedString(m_localizedHistorySlotCleared, StringReference(localizedIndex.c_str())); HistoryAnnouncement = CalculatorAnnouncement::GetHistorySlotClearedAnnouncement(announcement); diff --git a/src/CalcViewModel/HistoryViewModel.h b/src/CalcViewModel/HistoryViewModel.h index d7c7874e..a09360ed 100644 --- a/src/CalcViewModel/HistoryViewModel.h +++ b/src/CalcViewModel/HistoryViewModel.h @@ -28,7 +28,7 @@ namespace CalculatorApp OBSERVABLE_OBJECT(); OBSERVABLE_PROPERTY_R(Windows::Foundation::Collections::IObservableVector ^, Items); OBSERVABLE_PROPERTY_RW(bool, AreHistoryShortcutsEnabled); - OBSERVABLE_PROPERTY_R(CalculatorApp::Common::Automation::NarratorAnnouncement ^, HistoryAnnouncement); + OBSERVABLE_PROPERTY_R(CalculatorApp::ViewModel::Common::Automation::NarratorAnnouncement ^, HistoryAnnouncement); property int ItemsCount { int get() @@ -48,17 +48,17 @@ namespace CalculatorApp event HideHistoryClickedHandler ^ HideHistoryClicked; event HistoryItemClickedHandler ^ HistoryItemClicked; void ShowItem(_In_ CalculatorApp::ViewModel::HistoryItemViewModel ^ e); + void DeleteItem(_In_ CalculatorApp::ViewModel::HistoryItemViewModel ^ e); + void ReloadHistory(_In_ CalculatorApp::ViewModel::Common::ViewMode currentMode); internal : HistoryViewModel(_In_ CalculationManager::CalculatorManager* calculatorManager); - void SetCalculatorDisplay(CalculatorDisplay& calculatorDisplay); - void ReloadHistory(_In_ CalculatorApp::Common::ViewMode currentMode); + void SetCalculatorDisplay(Common::CalculatorDisplay& calculatorDisplay); unsigned long long GetMaxItemSize(); - void DeleteItem(_In_ CalculatorApp::ViewModel::HistoryItemViewModel ^ e); private: CalculationManager::CalculatorManager* const m_calculatorManager; - CalculatorDisplay m_calculatorDisplay; + Common::CalculatorDisplay m_calculatorDisplay; CalculationManager::CalculatorMode m_currentMode; Platform::String ^ m_localizedHistoryCleared; Platform::String ^ m_localizedHistorySlotCleared; diff --git a/src/CalcViewModel/MemoryItemViewModel.cpp b/src/CalcViewModel/MemoryItemViewModel.cpp index b7d21649..9600e773 100644 --- a/src/CalcViewModel/MemoryItemViewModel.cpp +++ b/src/CalcViewModel/MemoryItemViewModel.cpp @@ -6,8 +6,8 @@ #include "StandardCalculatorViewModel.h" using namespace CalculatorApp; -using namespace CalculatorApp::Common; -using namespace CalculatorApp::Common::Automation; +using namespace CalculatorApp::ViewModel::Common; +using namespace CalculatorApp::ViewModel::Common::Automation; using namespace CalculatorApp::ViewModel; using namespace Platform; using namespace std; diff --git a/src/CalcViewModel/StandardCalculatorViewModel.cpp b/src/CalcViewModel/StandardCalculatorViewModel.cpp index 56f2bda4..aaf6fb6d 100644 --- a/src/CalcViewModel/StandardCalculatorViewModel.cpp +++ b/src/CalcViewModel/StandardCalculatorViewModel.cpp @@ -10,8 +10,8 @@ #include "Common/TraceLogger.h" using namespace CalculatorApp; -using namespace CalculatorApp::Common; -using namespace CalculatorApp::Common::Automation; +using namespace CalculatorApp::ViewModel::Common; +using namespace CalculatorApp::ViewModel::Common::Automation; using namespace CalculatorApp::ViewModel; using namespace CalculationManager; using namespace concurrency; @@ -25,7 +25,6 @@ using namespace Windows::UI::Core; using namespace Windows::UI::Popups; using namespace Windows::Storage::Streams; using namespace Windows::Foundation::Collections; -using namespace Utils; using namespace concurrency; constexpr int StandardModePrecision = 16; @@ -118,7 +117,7 @@ StandardCalculatorViewModel::StandardCalculatorViewModel() m_HistoryVM = ref new HistoryViewModel(&m_standardCalculatorManager); m_HistoryVM->SetCalculatorDisplay(m_calculatorDisplay); - m_decimalSeparator = LocalizationSettings::GetInstance().GetDecimalSeparator(); + m_decimalSeparator = LocalizationSettings::GetInstance()->GetDecimalSeparator(); if (CoreWindow::GetForCurrentThread() != nullptr) { @@ -138,7 +137,7 @@ StandardCalculatorViewModel::StandardCalculatorViewModel() String ^ StandardCalculatorViewModel::LocalizeDisplayValue(_In_ wstring const& displayValue) { wstring result(displayValue); - LocalizationSettings::GetInstance().LocalizeDisplayValue(&result); + LocalizationSettings::GetInstance()->LocalizeDisplayValue(&result); return ref new Platform::String(result.c_str()); } @@ -170,13 +169,13 @@ String ^ StandardCalculatorViewModel::CalculateNarratorDisplayValue(_In_ wstring String ^ StandardCalculatorViewModel::GetNarratorStringReadRawNumbers(_In_ String ^ localizedDisplayValue) { wstring ws; - const auto& locSettings = LocalizationSettings::GetInstance(); + LocalizationSettings^ locSettings = LocalizationSettings::GetInstance(); // Insert a space after each digit in the string, to force Narrator to read them as separate numbers. for (const wchar_t& c : localizedDisplayValue) { ws += c; - if (locSettings.IsLocalizedHexDigit(c)) + if (locSettings->IsLocalizedHexDigit(c)) { ws += L' '; } @@ -230,7 +229,7 @@ void StandardCalculatorViewModel::SetParenthesisCount(_In_ unsigned int parenthe void StandardCalculatorViewModel::SetOpenParenthesisCountNarratorAnnouncement() { wstring localizedParenthesisCount = to_wstring(m_OpenParenthesisCount).c_str(); - LocalizationSettings::GetInstance().LocalizeDisplayValue(&localizedParenthesisCount); + LocalizationSettings::GetInstance()->LocalizeDisplayValue(&localizedParenthesisCount); if (m_localizedOpenParenthesisCountChangedAutomationFormat == nullptr) { @@ -329,7 +328,7 @@ void StandardCalculatorViewModel::SetTokens(_Inout_ shared_ptrLocalizeDisplayValue(&(currentToken.first)); if (!isEditable) { @@ -392,7 +391,7 @@ String ^ StandardCalculatorViewModel::GetCalculatorExpressionAutomationName() void StandardCalculatorViewModel::SetMemorizedNumbers(const vector& newMemorizedNumbers) { - const auto& localizer = LocalizationSettings::GetInstance(); + LocalizationSettings^ localizer = LocalizationSettings::GetInstance(); if (newMemorizedNumbers.size() == 0) // Memory has been cleared { MemorizedNumbers->Clear(); @@ -408,7 +407,7 @@ void StandardCalculatorViewModel::SetMemorizedNumbers(const vector& new MemoryItemViewModel ^ memorySlot = ref new MemoryItemViewModel(this); memorySlot->Position = 0; - localizer.LocalizeDisplayValue(&stringValue); + localizer->LocalizeDisplayValue(&stringValue); memorySlot->Value = ref new String(stringValue.c_str()); MemorizedNumbers->InsertAt(0, memorySlot); @@ -426,7 +425,7 @@ void StandardCalculatorViewModel::SetMemorizedNumbers(const vector& new for (unsigned int i = 0; i < MemorizedNumbers->Size; i++) { auto newStringValue = newMemorizedNumbers.at(i); - localizer.LocalizeDisplayValue(&newStringValue); + localizer->LocalizeDisplayValue(&newStringValue); // If the value is different, update the value if (MemorizedNumbers->GetAt(i)->Value != StringReference(newStringValue.c_str())) @@ -1001,10 +1000,10 @@ ButtonInfo StandardCalculatorViewModel::MapCharacterToButtonId(char16 ch) if (result.buttonId == NumbersAndOperatorsEnum::None) { - if (LocalizationSettings::GetInstance().IsLocalizedDigit(ch)) + if (LocalizationSettings::GetInstance()->IsLocalizedDigit(ch)) { result.buttonId = - NumbersAndOperatorsEnum::Zero + static_cast(ch - LocalizationSettings::GetInstance().GetDigitSymbolFromEnUsDigit('0')); + NumbersAndOperatorsEnum::Zero + static_cast(ch - LocalizationSettings::GetInstance()->GetDigitSymbolFromEnUsDigit('0')); result.canSendNegate = true; } } @@ -1044,7 +1043,7 @@ void StandardCalculatorViewModel::OnMemoryItemChanged(unsigned int indexOfMemory String ^ localizedValue = memSlot->Value; wstring localizedIndex = to_wstring(indexOfMemory + 1); - LocalizationSettings::GetInstance().LocalizeDisplayValue(&localizedIndex); + LocalizationSettings::GetInstance()->LocalizeDisplayValue(&localizedIndex); if (m_localizedMemoryItemChangedAutomationFormat == nullptr) { @@ -1116,7 +1115,7 @@ void StandardCalculatorViewModel::OnMemoryClear(_In_ Object ^ memoryItemPosition TraceLogger::GetInstance()->UpdateButtonUsage(NumbersAndOperatorsEnum::MemoryClear, GetCalculatorMode()); wstring localizedIndex = to_wstring(boxedPosition->Value + 1); - LocalizationSettings::GetInstance().LocalizeDisplayValue(&localizedIndex); + LocalizationSettings::GetInstance()->LocalizeDisplayValue(&localizedIndex); if (m_localizedMemoryItemClearedAutomationFormat == nullptr) { @@ -1216,7 +1215,7 @@ String ^ StandardCalculatorViewModel::GetRawDisplayValue() } else { - return LocalizationSettings::GetInstance().RemoveGroupSeparators(DisplayValue); + return LocalizationSettings::GetInstance()->RemoveGroupSeparators(DisplayValue); } } @@ -1535,7 +1534,7 @@ size_t StandardCalculatorViewModel::LengthWithoutPadding(wstring str) wstring StandardCalculatorViewModel::AddPadding(wstring binaryString) { - if (LocalizationSettings::GetInstance().GetEnglishValueFromLocalizedDigits(StringReference(binaryString.c_str())) == L"0") + if (LocalizationSettings::GetInstance()->GetEnglishValueFromLocalizedDigits(StringReference(binaryString.c_str())) == L"0") { return binaryString; } @@ -1571,13 +1570,13 @@ void StandardCalculatorViewModel::UpdateProgrammerPanelDisplay() binaryDisplayString = m_standardCalculatorManager.GetResultForRadix(2, precision, true); } } - const auto& localizer = LocalizationSettings::GetInstance(); + LocalizationSettings^ localizer = LocalizationSettings::GetInstance(); binaryDisplayString = AddPadding(binaryDisplayString); - localizer.LocalizeDisplayValue(&hexDisplayString); - localizer.LocalizeDisplayValue(&decimalDisplayString); - localizer.LocalizeDisplayValue(&octalDisplayString); - localizer.LocalizeDisplayValue(&binaryDisplayString); + localizer->LocalizeDisplayValue(&hexDisplayString); + localizer->LocalizeDisplayValue(&decimalDisplayString); + localizer->LocalizeDisplayValue(&octalDisplayString); + localizer->LocalizeDisplayValue(&binaryDisplayString); HexDisplayValue = ref new Platform::String(hexDisplayString.c_str()); DecimalDisplayValue = ref new Platform::String(decimalDisplayString.c_str()); @@ -1609,7 +1608,7 @@ void StandardCalculatorViewModel::UpdateOperand(int pos, String ^ text) { pair p = m_tokens->at(pos); - String ^ englishString = LocalizationSettings::GetInstance().GetEnglishValueFromLocalizedDigits(text); + String ^ englishString = LocalizationSettings::GetInstance()->GetEnglishValueFromLocalizedDigits(text); p.first = englishString->Data(); int commandPos = p.second; @@ -1719,7 +1718,7 @@ ViewMode StandardCalculatorViewModel::GetCalculatorMode() return ViewMode::Programmer; } -void StandardCalculatorViewModel::ValueBitLength::set(CalculatorApp::Common::BitLength value) +void StandardCalculatorViewModel::ValueBitLength::set(CalculatorApp::ViewModel::Common::BitLength value) { if (m_valueBitLength != value) { diff --git a/src/CalcViewModel/StandardCalculatorViewModel.h b/src/CalcViewModel/StandardCalculatorViewModel.h index d60122bf..ac5e877b 100644 --- a/src/CalcViewModel/StandardCalculatorViewModel.h +++ b/src/CalcViewModel/StandardCalculatorViewModel.h @@ -29,7 +29,7 @@ namespace CalculatorApp public value struct ButtonInfo { - NumbersAndOperatorsEnum buttonId; + CalculatorApp::ViewModel::Common::NumbersAndOperatorsEnum buttonId; bool canSendNegate; }; @@ -73,12 +73,12 @@ namespace CalculatorApp OBSERVABLE_PROPERTY_R(Platform::String ^, CalculationResultAutomationName); OBSERVABLE_PROPERTY_R(Platform::String ^, CalculationExpressionAutomationName); OBSERVABLE_PROPERTY_R(bool, IsShiftProgrammerChecked); - OBSERVABLE_PROPERTY_R(CalculatorApp::Common::NumberBase, CurrentRadixType); + OBSERVABLE_PROPERTY_R(CalculatorApp::ViewModel::Common::NumberBase, CurrentRadixType); OBSERVABLE_PROPERTY_R(bool, AreTokensUpdated); OBSERVABLE_PROPERTY_R(bool, AreAlwaysOnTopResultsUpdated); OBSERVABLE_PROPERTY_R(bool, AreProgrammerRadixOperatorsVisible); OBSERVABLE_PROPERTY_R(bool, IsInputEmpty); - OBSERVABLE_PROPERTY_R(CalculatorApp::Common::Automation::NarratorAnnouncement ^, Announcement); + OBSERVABLE_PROPERTY_R(CalculatorApp::ViewModel::Common::Automation::NarratorAnnouncement ^, Announcement); OBSERVABLE_PROPERTY_R(unsigned int, OpenParenthesisCount); COMMAND_FOR_METHOD(CopyCommand, StandardCalculatorViewModel::OnCopyCommand); @@ -111,13 +111,13 @@ namespace CalculatorApp static property Platform::String ^ IsBitFlipCheckedPropertyName { Platform::String ^ get() { return Platform::StringReference(L"IsBitFlipChecked"); } } - property CalculatorApp::Common::BitLength ValueBitLength + property CalculatorApp::ViewModel::Common::BitLength ValueBitLength { - CalculatorApp::Common::BitLength get() + CalculatorApp::ViewModel::Common::BitLength get() { return m_valueBitLength; } - void set(CalculatorApp::Common::BitLength value); + void set(CalculatorApp::ViewModel::Common::BitLength value); } property bool IsStandard @@ -244,6 +244,21 @@ namespace CalculatorApp void ResetCalcManager(bool clearMemory); void SendCommandToCalcManager(int command); + public: + // Memory feature related methods. + void OnMemoryButtonPressed(); + void OnMemoryItemPressed(Platform::Object ^ memoryItemPosition); + void OnMemoryAdd(Platform::Object ^ memoryItemPosition); + void OnMemorySubtract(Platform::Object ^ memoryItemPosition); + void OnMemoryClear(_In_ Platform::Object ^ memoryItemPosition); + + void SelectHistoryItem(HistoryItemViewModel ^ item); + void SwitchProgrammerModeBase(CalculatorApp::ViewModel::Common::NumberBase calculatorBase); + void SetBitshiftRadioButtonCheckedAnnouncement(Platform::String ^ announcement); + void SetOpenParenthesisCountNarratorAnnouncement(); + void SwitchAngleType(CalculatorApp::ViewModel::Common::NumbersAndOperatorsEnum num); + void FtoEButtonToggled(); + internal: void OnPaste(Platform::String ^ pastedString); void OnCopyCommand(Platform::Object ^ parameter); @@ -251,35 +266,23 @@ namespace CalculatorApp ButtonInfo MapCharacterToButtonId(char16 ch); - // 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 OnInputChanged(); void DisplayPasteError(); void SetParenthesisCount(_In_ unsigned int parenthesisCount); - void SetOpenParenthesisCountNarratorAnnouncement(); void OnNoRightParenAdded(); void SetNoParenAddedNarratorAnnouncement(); void OnMaxDigitsReached(); void OnBinaryOperatorReceived(); void OnMemoryItemChanged(unsigned int indexOfMemory); - void SetBitshiftRadioButtonCheckedAnnouncement(Platform::String ^ announcement); Platform::String ^ GetLocalizedStringFormat(Platform::String ^ format, Platform::String ^ displayValue); void OnPropertyChanged(Platform::String ^ propertyname); - void SetCalculatorType(CalculatorApp::Common::ViewMode targetState); + void SetCalculatorType(CalculatorApp::ViewModel::Common::ViewMode targetState); Platform::String ^ GetRawDisplayValue(); void Recalculate(bool fromHistory = false); bool IsOperator(CalculationManager::Command cmdenum); - void FtoEButtonToggled(); - void SwitchProgrammerModeBase(CalculatorApp::Common::NumberBase calculatorBase); - void SetMemorizedNumbersString(); - void SwitchAngleType(NumbersAndOperatorsEnum num); + void SetMemorizedNumbersString(); void ResetDisplay(); void SetPrecision(int32_t precision); @@ -287,11 +290,11 @@ namespace CalculatorApp { m_standardCalculatorManager.UpdateMaxIntDigits(); } - NumbersAndOperatorsEnum GetCurrentAngleType() + CalculatorApp::ViewModel::Common::NumbersAndOperatorsEnum GetCurrentAngleType() { return m_CurrentAngleType; } - void SelectHistoryItem(HistoryItemViewModel ^ item); + private: void SetMemorizedNumbers(const std::vector& memorizedNumbers); void UpdateProgrammerPanelDisplay(); @@ -304,12 +307,12 @@ namespace CalculatorApp _Inout_ std::shared_ptr>> const& tokens, _Inout_ std::shared_ptr>> const& commands); void SetTokens(_Inout_ std::shared_ptr>> const& tokens); - NumbersAndOperatorsEnum ConvertIntegerToNumbersAndOperatorsEnum(unsigned int parameter); - static RadixType GetRadixTypeFromNumberBase(CalculatorApp::Common::NumberBase base); - NumbersAndOperatorsEnum m_CurrentAngleType; + CalculatorApp::ViewModel::Common::NumbersAndOperatorsEnum ConvertIntegerToNumbersAndOperatorsEnum(unsigned int parameter); + static RadixType GetRadixTypeFromNumberBase(CalculatorApp::ViewModel::Common::NumberBase base); + CalculatorApp::ViewModel::Common::NumbersAndOperatorsEnum m_CurrentAngleType; wchar_t m_decimalSeparator; - CalculatorDisplay m_calculatorDisplay; - CalculatorApp::EngineResourceProvider m_resourceProvider; + CalculatorApp::ViewModel::Common::CalculatorDisplay m_calculatorDisplay; + CalculatorApp::ViewModel::Common::EngineResourceProvider m_resourceProvider; CalculationManager::CalculatorManager m_standardCalculatorManager; Platform::String ^ m_expressionAutomationNameFormat; Platform::String ^ m_localizedCalculationResultAutomationFormat; @@ -336,18 +339,18 @@ namespace CalculatorApp bool m_isRtlLanguage; bool m_operandUpdated; bool m_isLastOperationHistoryLoad; - CalculatorApp::Common::BitLength m_valueBitLength; + CalculatorApp::ViewModel::Common::BitLength m_valueBitLength; Platform::String ^ m_selectedExpressionLastData; Common::DisplayExpressionToken ^ m_selectedExpressionToken; Platform::String ^ LocalizeDisplayValue(_In_ std::wstring const& displayValue); Platform::String ^ CalculateNarratorDisplayValue(_In_ std::wstring const& displayValue, _In_ Platform::String ^ localizedDisplayValue); - CalculatorApp::Common::Automation::NarratorAnnouncement ^ GetDisplayUpdatedNarratorAnnouncement(); + CalculatorApp::ViewModel::Common::Automation::NarratorAnnouncement ^ GetDisplayUpdatedNarratorAnnouncement(); Platform::String ^ GetCalculatorExpressionAutomationName(); Platform::String ^ GetNarratorStringReadRawNumbers(_In_ Platform::String ^ localizedDisplayValue); - CalculationManager::Command ConvertToOperatorsEnum(NumbersAndOperatorsEnum operation); + CalculationManager::Command ConvertToOperatorsEnum(CalculatorApp::ViewModel::Common::NumbersAndOperatorsEnum operation); void DisableButtons(CalculationManager::CommandType selectedExpressionCommandType); Platform::String ^ m_feedbackForButtonPress; @@ -368,9 +371,9 @@ namespace CalculatorApp void SaveEditedCommand(_In_ unsigned int index, _In_ CalculationManager::Command command); - CalculatorApp::Common::ViewMode GetCalculatorMode(); + CalculatorApp::ViewModel::Common::ViewMode GetCalculatorMode(); - friend class CalculatorDisplay; + friend class CalculatorApp::ViewModel::Common::CalculatorDisplay; friend class CalculatorUnitTests::MultiWindowUnitTests; }; } diff --git a/src/CalcViewModel/UnitConverterViewModel.cpp b/src/CalcViewModel/UnitConverterViewModel.cpp index 90960eb8..17466237 100644 --- a/src/CalcViewModel/UnitConverterViewModel.cpp +++ b/src/CalcViewModel/UnitConverterViewModel.cpp @@ -15,9 +15,10 @@ #include "DataLoaders/UnitConverterDataLoader.h" using namespace CalculatorApp; -using namespace CalculatorApp::Common; -using namespace CalculatorApp::Common::Automation; using namespace CalculatorApp::ViewModel; +using namespace CalculatorApp::ViewModel::Common; +using namespace CalculatorApp::ViewModel::Common::Automation; +using namespace CalculatorApp::ViewModel::DataLoaders; using namespace concurrency; using namespace Platform; using namespace Platform::Collections; @@ -75,7 +76,7 @@ namespace StringReference SupplementaryVisibilityPropertyName(L"SupplementaryVisibility"); } -namespace CalculatorApp::ViewModel::UnitConverterResourceKeys +namespace CalculatorApp::ViewModel::DataLoaders::UnitConverterResourceKeys { StringReference ValueFromFormat(L"Format_ValueFrom"); StringReference ValueFromDecimalFormat(L"Format_ValueFrom_Decimal"); @@ -128,7 +129,7 @@ UnitConverterViewModel::UnitConverterViewModel(const shared_ptrGetRegionalSettingsAwareDecimalFormatter(); m_decimalFormatter->FractionDigits = 0; m_decimalFormatter->IsGrouped = true; - m_decimalSeparator = LocalizationSettings::GetInstance().GetDecimalSeparator(); + m_decimalSeparator = LocalizationSettings::GetInstance()->GetDecimalSeparator(); m_currencyFormatter = localizationService->GetRegionalSettingsAwareCurrencyFormatter(); m_currencyFormatter->IsGrouped = true; @@ -922,10 +923,10 @@ NumbersAndOperatorsEnum UnitConverterViewModel::MapCharacterToButtonId(const wch if (mappedValue == NumbersAndOperatorsEnum::None) { - if (LocalizationSettings::GetInstance().IsLocalizedDigit(ch)) + if (LocalizationSettings::GetInstance()->IsLocalizedDigit(ch)) { mappedValue = NumbersAndOperatorsEnum::Zero - + static_cast(ch - LocalizationSettings::GetInstance().GetDigitSymbolFromEnUsDigit(L'0')); + + static_cast(ch - LocalizationSettings::GetInstance()->GetDigitSymbolFromEnUsDigit(L'0')); canSendNegate = true; } } diff --git a/src/CalcViewModel/UnitConverterViewModel.h b/src/CalcViewModel/UnitConverterViewModel.h index b48c1c3b..594742ec 100644 --- a/src/CalcViewModel/UnitConverterViewModel.h +++ b/src/CalcViewModel/UnitConverterViewModel.h @@ -35,6 +35,11 @@ namespace CalculatorApp } } + int GetModelCategoryId() + { + return GetModelCategory().id; + } + internal : const UnitConversionManager::Category& GetModelCategory() const { return m_original; @@ -70,38 +75,51 @@ namespace CalculatorApp return AccessibleName; } - internal : const UnitConversionManager::Unit& GetModelUnit() const + public: + bool IsModelUnitWhimsical() { - return m_original; + return m_original.isWhimsical; } + int ModelUnitID() + { + return m_original.id; + } + + 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 { - internal : SupplementaryResult(Platform::String ^ value, Unit ^ unit) + internal: + SupplementaryResult(Platform::String ^ value, Unit ^ unit) : m_Value(value) , m_Unit(unit) { } - bool IsWhimsical() const + public: + bool IsWhimsical() { return m_Unit->GetModelUnit().isWhimsical; } Platform::String ^ GetLocalizedAutomationName(); - public: OBSERVABLE_OBJECT(); OBSERVABLE_PROPERTY_R(Platform::String ^, Value); OBSERVABLE_PROPERTY_R(CalculatorApp::ViewModel::Unit ^, Unit); }; - interface class IActivatable + public interface class IActivatable { virtual property bool IsActive; }; @@ -143,7 +161,7 @@ namespace CalculatorApp OBSERVABLE_OBJECT_CALLBACK(OnPropertyChanged); OBSERVABLE_PROPERTY_R(Windows::Foundation::Collections::IObservableVector ^, Categories); - OBSERVABLE_PROPERTY_RW(CalculatorApp::Common::ViewMode, Mode); + OBSERVABLE_PROPERTY_RW(CalculatorApp::ViewModel::Common::ViewMode, Mode); OBSERVABLE_PROPERTY_R(Windows::Foundation::Collections::IObservableVector ^, Units); OBSERVABLE_PROPERTY_RW(Platform::String ^, CurrencySymbol1); OBSERVABLE_PROPERTY_RW(Unit ^, Unit1); @@ -158,7 +176,7 @@ namespace CalculatorApp 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(CalculatorApp::ViewModel::Common::Automation::NarratorAnnouncement ^, Announcement); OBSERVABLE_PROPERTY_RW(bool, IsDecimalEnabled); OBSERVABLE_PROPERTY_RW(bool, IsDropDownOpen); OBSERVABLE_PROPERTY_RW(bool, IsDropDownEnabled); @@ -167,7 +185,7 @@ namespace CalculatorApp 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(CalculatorApp::ViewModel::Common::NetworkAccessBehavior, NetworkBehavior); OBSERVABLE_NAMED_PROPERTY_RW(bool, CurrencyDataLoadFailed); OBSERVABLE_NAMED_PROPERTY_RW(bool, CurrencyDataIsWeekOld); @@ -185,7 +203,7 @@ namespace CalculatorApp if (value != nullptr) { auto currentCategory = value->GetModelCategory(); - IsCurrencyCurrentCategory = currentCategory.id == CalculatorApp::Common::NavCategory::Serialize(CalculatorApp::Common::ViewMode::Currency); + IsCurrencyCurrentCategory = currentCategory.id == CalculatorApp::ViewModel::Common::NavCategory::Serialize(CalculatorApp::ViewModel::Common::ViewMode::Currency); } RaisePropertyChanged("CurrentCategory"); } @@ -217,12 +235,14 @@ namespace CalculatorApp void AnnounceConversionResult(); + void OnPaste(Platform::String ^ stringToPaste); + void RefreshCurrencyRatios(); + void OnValueActivated(IActivatable ^ control); + internal : void ResetView(); void PopulateData(); - NumbersAndOperatorsEnum MapCharacterToButtonId(const wchar_t ch, bool& canSendNegate); + CalculatorApp::ViewModel::Common::NumbersAndOperatorsEnum MapCharacterToButtonId(const wchar_t ch, bool& canSendNegate); void DisplayPasteError(); - void OnValueActivated(IActivatable ^ control); - void OnPaste(Platform::String ^ stringToPaste); void OnCopyCommand(Platform::Object ^ parameter); void OnPasteCommand(Platform::Object ^ parameter); @@ -255,8 +275,7 @@ namespace CalculatorApp void OnCurrencyDataLoadFinished(bool didLoad); void OnCurrencyTimestampUpdated(_In_ const std::wstring& timestamp, bool isWeekOld); - void RefreshCurrencyRatios(); - void OnNetworkBehaviorChanged(_In_ CalculatorApp::NetworkAccessBehavior newBehavior); + void OnNetworkBehaviorChanged(_In_ CalculatorApp::ViewModel::Common::NetworkAccessBehavior newBehavior); const std::wstring& GetValueFromUnlocalized() const { @@ -282,7 +301,7 @@ namespace CalculatorApp void OnCategoryChanged(Platform::Object ^ unused); void OnUnitChanged(Platform::Object ^ unused); void OnSwitchActive(Platform::Object ^ unused); - UnitConversionManager::Command CommandFromButtonId(CalculatorApp::NumbersAndOperatorsEnum button); + UnitConversionManager::Command CommandFromButtonId(CalculatorApp::ViewModel::Common::NumbersAndOperatorsEnum button); void SupplementaryResultsTimerTick(Windows::System::Threading::ThreadPoolTimer ^ timer); void SupplementaryResultsTimerCancel(Windows::System::Threading::ThreadPoolTimer ^ timer); void RefreshSupplementaryResults(); @@ -449,7 +468,7 @@ namespace CalculatorApp void NetworkBehaviorChanged(_In_ int newBehavior) override { - m_viewModel->OnNetworkBehaviorChanged(static_cast(newBehavior)); + m_viewModel->OnNetworkBehaviorChanged(static_cast(newBehavior)); } private: diff --git a/src/CalcViewModel/ViewState.cpp b/src/CalcViewModel/ViewState.cpp deleted file mode 100644 index 63a5d30e..00000000 --- a/src/CalcViewModel/ViewState.cpp +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -#include "pch.h" -#include "ViewState.h" - -namespace CalculatorApp -{ - namespace ViewState - { - Platform::StringReference Snap(L"Snap"); - Platform::StringReference DockedView(L"DockedView"); - - bool IsValidViewState(Platform::String ^ viewState) - { - return viewState->Equals(ViewState::Snap) || viewState->Equals(ViewState::DockedView); - } - } -} diff --git a/src/CalcViewModel/ViewState.h b/src/CalcViewModel/ViewState.h deleted file mode 100644 index 0a103d09..00000000 --- a/src/CalcViewModel/ViewState.h +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -#pragma once - -namespace CalculatorApp -{ - namespace ViewState - { - extern Platform::StringReference Snap; - extern Platform::StringReference DockedView; - - bool IsValidViewState(Platform::String ^ viewState); - } -} diff --git a/src/CalcViewModel/pch.h b/src/CalcViewModel/pch.h index da6ea470..6d4cd9c2 100644 --- a/src/CalcViewModel/pch.h +++ b/src/CalcViewModel/pch.h @@ -49,7 +49,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::ViewModel::Common::Automation { } -namespace CustomPeers = CalculatorApp::Common::Automation; +namespace CustomPeers = CalculatorApp::ViewModel::Common::Automation; diff --git a/src/CalcViewModelCopyForUT/CalcViewModelCopyForUT.vcxproj b/src/CalcViewModelCopyForUT/CalcViewModelCopyForUT.vcxproj new file mode 100644 index 00000000..ffee7eed --- /dev/null +++ b/src/CalcViewModelCopyForUT/CalcViewModelCopyForUT.vcxproj @@ -0,0 +1,414 @@ + + + + + Debug + ARM + + + Debug + ARM64 + + + Debug + Win32 + + + Debug + x64 + + + Release + ARM + + + Release + ARM64 + + + Release + Win32 + + + Release + x64 + + + + {cc9b4fa7-d746-4f52-9401-0ad1b4d6b16d} + StaticLibrary + CalcViewModelCopyForUT + en-US + 14.0 + true + Windows Store + 10.0.18362.0 + 10.0.17134.0 + 10.0 + + + + StaticLibrary + true + v142 + + + StaticLibrary + true + v142 + + + StaticLibrary + true + v142 + + + StaticLibrary + true + v142 + + + StaticLibrary + false + true + v142 + + + StaticLibrary + false + true + v142 + + + StaticLibrary + false + true + v142 + + + StaticLibrary + false + true + v142 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + false + true + + + + Use + true + true + $(SolutionDir)..\src\;$(SolutionDir)CalcViewModel\;%(AdditionalIncludeDirectories) + 4453 + /bigobj /await /std:c++17 /utf-8 %(AdditionalOptions) + Level4 + true + + + Console + false + false + + + /ignore:4264 %(AdditionalOptions) + + + + + Use + true + true + $(SolutionDir)..\src\;$(SolutionDir)CalcViewModel\;%(AdditionalIncludeDirectories) + 4453 + /bigobj /await /std:c++17 /utf-8 %(AdditionalOptions) + Level4 + true + + + Console + false + false + + + /ignore:4264 %(AdditionalOptions) + + + + + Use + true + true + $(SolutionDir)..\src\;$(SolutionDir)CalcViewModel\;%(AdditionalIncludeDirectories) + 4453 + /bigobj /await /std:c++17 /utf-8 %(AdditionalOptions) + Level4 + true + + + Console + false + false + + + /ignore:4264 %(AdditionalOptions) + + + + + Use + true + true + $(SolutionDir)..\src\;$(SolutionDir)CalcViewModel\;%(AdditionalIncludeDirectories) + 4453 + /bigobj /await /std:c++17 /utf-8 %(AdditionalOptions) + Level4 + true + + + Console + false + false + + + /ignore:4264 %(AdditionalOptions) + + + + + Use + true + true + $(SolutionDir);$(SolutionDir)CalcViewModel\;%(AdditionalIncludeDirectories) + 4453 + /bigobj /await /std:c++17 /utf-8 %(AdditionalOptions) + Level4 + true + + + Console + false + false + + + /ignore:4264 %(AdditionalOptions) + + + + + Use + true + true + $(SolutionDir)..\src\;$(SolutionDir)CalcViewModel\;%(AdditionalIncludeDirectories) + 4453 + /bigobj /await /std:c++17 /utf-8 %(AdditionalOptions) + Level4 + true + + + Console + false + false + + + /ignore:4264 %(AdditionalOptions) + + + + + Use + true + true + $(SolutionDir)..\src\;$(SolutionDir)CalcViewModel\;%(AdditionalIncludeDirectories) + 4453 + /bigobj /await /std:c++17 /utf-8 %(AdditionalOptions) + Level4 + true + + + Console + false + false + + + /ignore:4264 %(AdditionalOptions) + + + + + Use + true + true + $(SolutionDir)..\src\;$(SolutionDir)CalcViewModel\;%(AdditionalIncludeDirectories) + 4453 + /bigobj /await /std:c++17 /utf-8 %(AdditionalOptions) + Level4 + true + + + Console + false + false + + + /ignore:4264 %(AdditionalOptions) + + + + + /DSEND_DIAGNOSTICS %(AdditionalOptions) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Create + Create + Create + Create + Create + Create + Create + Create + + + + + + + {311e866d-8b93-4609-a691-265941fee101} + + + {e727a92b-f149-492c-8117-c039a298719b} + + + {fc81ff41-02cd-4cd9-9bc5-45a1e39ac6ed} + + + + + /DUSE_MOCK_DATA %(AdditionalOptions) + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/CalcViewModelCopyForUT/CalcViewModelCopyForUT.vcxproj.filters b/src/CalcViewModelCopyForUT/CalcViewModelCopyForUT.vcxproj.filters new file mode 100644 index 00000000..19ca2cee --- /dev/null +++ b/src/CalcViewModelCopyForUT/CalcViewModelCopyForUT.vcxproj.filters @@ -0,0 +1,213 @@ + + + + + {2c2762e9-7673-4c4e-bf31-9513125dfc00} + + + {8f48b19f-14df-421f-bcc6-ef908f9dcff0} + + + {6811c769-d698-4add-b477-794316d39c66} + + + {da163ad4-d001-45eb-b4b3-6e9e17d22077} + + + + + Common + + + Common\Automation + + + Common\Automation + + + + + + + + + + + Common + + + Common + + + Common + + + Common + + + Common + + + Common + + + Common + + + Common + + + Common + + + Common + + + Common + + + Common + + + DataLoaders + + + DataLoaders + + + DataLoaders + + + GraphingCalculator + + + GraphingCalculator + + + GraphingCalculator + + + + + + Common + + + Common\Automation + + + Common\Automation + + + + + + + + + + + + Common + + + Common + + + Common + + + Common + + + Common + + + Common + + + Common + + + Common + + + Common + + + Common + + + Common + + + Common + + + Common + + + Common + + + Common + + + Common + + + Common + + + Common + + + Common + + + Common + + + Common + + + DataLoaders + + + DataLoaders + + + DataLoaders + + + DataLoaders + + + DataLoaders + + + DataLoaders + + + GraphingCalculator + + + GraphingCalculator + + + GraphingCalculator + + + GraphingCalculator + + + + Common + + + + + DataLoaders + + + \ No newline at end of file diff --git a/src/Calculator.sln b/src/Calculator.sln index 09fc81fd..312f0d43 100644 --- a/src/Calculator.sln +++ b/src/Calculator.sln @@ -9,11 +9,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution nuget.config = nuget.config EndProjectSection EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Calculator", "Calculator\Calculator.vcxproj", "{9447424A-0E05-4911-BEB8-E0354405F39A}" -EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CalcManager", "CalcManager\CalcManager.vcxproj", "{311E866D-8B93-4609-A691-265941FEE101}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CalcViewModel", "CalcViewModel\CalcViewModel.vcxproj", "{90E9761D-9262-4773-942D-CAEAE75D7140}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CalcViewModel", "CalcViewModel\CalcViewModel.vcxproj", "{812D1A7B-B8AC-49E4-8E6D-AF5D59500D56}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CalculatorUnitTests", "CalculatorUnitTests\CalculatorUnitTests.vcxproj", "{D3BAED2C-4B07-4E1D-8807-9D6499450349}" EndProject @@ -27,6 +25,10 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GraphControl", "GraphContro EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TraceLogging", "TraceLogging\TraceLogging.vcxproj", "{FC81FF41-02CD-4CD9-9BC5-45A1E39AC6ED}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Calculator", "Calculator\Calculator.csproj", "{3B773403-B0D6-4F9A-948E-512A7A5FB315}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CalcViewModelCopyForUT", "CalcViewModelCopyForUT\CalcViewModelCopyForUT.vcxproj", "{CC9B4FA7-D746-4F52-9401-0AD1B4D6B16D}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|ARM = Debug|ARM @@ -39,30 +41,6 @@ Global Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {9447424A-0E05-4911-BEB8-E0354405F39A}.Debug|ARM.ActiveCfg = Debug|ARM - {9447424A-0E05-4911-BEB8-E0354405F39A}.Debug|ARM.Build.0 = Debug|ARM - {9447424A-0E05-4911-BEB8-E0354405F39A}.Debug|ARM.Deploy.0 = Debug|ARM - {9447424A-0E05-4911-BEB8-E0354405F39A}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {9447424A-0E05-4911-BEB8-E0354405F39A}.Debug|ARM64.Build.0 = Debug|ARM64 - {9447424A-0E05-4911-BEB8-E0354405F39A}.Debug|ARM64.Deploy.0 = Debug|ARM64 - {9447424A-0E05-4911-BEB8-E0354405F39A}.Debug|x64.ActiveCfg = Debug|x64 - {9447424A-0E05-4911-BEB8-E0354405F39A}.Debug|x64.Build.0 = Debug|x64 - {9447424A-0E05-4911-BEB8-E0354405F39A}.Debug|x64.Deploy.0 = Debug|x64 - {9447424A-0E05-4911-BEB8-E0354405F39A}.Debug|x86.ActiveCfg = Debug|Win32 - {9447424A-0E05-4911-BEB8-E0354405F39A}.Debug|x86.Build.0 = Debug|Win32 - {9447424A-0E05-4911-BEB8-E0354405F39A}.Debug|x86.Deploy.0 = Debug|Win32 - {9447424A-0E05-4911-BEB8-E0354405F39A}.Release|ARM.ActiveCfg = Release|ARM - {9447424A-0E05-4911-BEB8-E0354405F39A}.Release|ARM.Build.0 = Release|ARM - {9447424A-0E05-4911-BEB8-E0354405F39A}.Release|ARM.Deploy.0 = Release|ARM - {9447424A-0E05-4911-BEB8-E0354405F39A}.Release|ARM64.ActiveCfg = Release|ARM64 - {9447424A-0E05-4911-BEB8-E0354405F39A}.Release|ARM64.Build.0 = Release|ARM64 - {9447424A-0E05-4911-BEB8-E0354405F39A}.Release|ARM64.Deploy.0 = Release|ARM64 - {9447424A-0E05-4911-BEB8-E0354405F39A}.Release|x64.ActiveCfg = Release|x64 - {9447424A-0E05-4911-BEB8-E0354405F39A}.Release|x64.Build.0 = Release|x64 - {9447424A-0E05-4911-BEB8-E0354405F39A}.Release|x64.Deploy.0 = Release|x64 - {9447424A-0E05-4911-BEB8-E0354405F39A}.Release|x86.ActiveCfg = Release|Win32 - {9447424A-0E05-4911-BEB8-E0354405F39A}.Release|x86.Build.0 = Release|Win32 - {9447424A-0E05-4911-BEB8-E0354405F39A}.Release|x86.Deploy.0 = Release|Win32 {311E866D-8B93-4609-A691-265941FEE101}.Debug|ARM.ActiveCfg = Debug|ARM {311E866D-8B93-4609-A691-265941FEE101}.Debug|ARM.Build.0 = Debug|ARM {311E866D-8B93-4609-A691-265941FEE101}.Debug|ARM64.ActiveCfg = Debug|ARM64 @@ -79,22 +57,22 @@ Global {311E866D-8B93-4609-A691-265941FEE101}.Release|x64.Build.0 = Release|x64 {311E866D-8B93-4609-A691-265941FEE101}.Release|x86.ActiveCfg = Release|Win32 {311E866D-8B93-4609-A691-265941FEE101}.Release|x86.Build.0 = Release|Win32 - {90E9761D-9262-4773-942D-CAEAE75D7140}.Debug|ARM.ActiveCfg = Debug|ARM - {90E9761D-9262-4773-942D-CAEAE75D7140}.Debug|ARM.Build.0 = Debug|ARM - {90E9761D-9262-4773-942D-CAEAE75D7140}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {90E9761D-9262-4773-942D-CAEAE75D7140}.Debug|ARM64.Build.0 = Debug|ARM64 - {90E9761D-9262-4773-942D-CAEAE75D7140}.Debug|x64.ActiveCfg = Debug|x64 - {90E9761D-9262-4773-942D-CAEAE75D7140}.Debug|x64.Build.0 = Debug|x64 - {90E9761D-9262-4773-942D-CAEAE75D7140}.Debug|x86.ActiveCfg = Debug|Win32 - {90E9761D-9262-4773-942D-CAEAE75D7140}.Debug|x86.Build.0 = Debug|Win32 - {90E9761D-9262-4773-942D-CAEAE75D7140}.Release|ARM.ActiveCfg = Release|ARM - {90E9761D-9262-4773-942D-CAEAE75D7140}.Release|ARM.Build.0 = Release|ARM - {90E9761D-9262-4773-942D-CAEAE75D7140}.Release|ARM64.ActiveCfg = Release|ARM64 - {90E9761D-9262-4773-942D-CAEAE75D7140}.Release|ARM64.Build.0 = Release|ARM64 - {90E9761D-9262-4773-942D-CAEAE75D7140}.Release|x64.ActiveCfg = Release|x64 - {90E9761D-9262-4773-942D-CAEAE75D7140}.Release|x64.Build.0 = Release|x64 - {90E9761D-9262-4773-942D-CAEAE75D7140}.Release|x86.ActiveCfg = Release|Win32 - {90E9761D-9262-4773-942D-CAEAE75D7140}.Release|x86.Build.0 = Release|Win32 + {812D1A7B-B8AC-49E4-8E6D-AF5D59500D56}.Debug|ARM.ActiveCfg = Debug|ARM + {812D1A7B-B8AC-49E4-8E6D-AF5D59500D56}.Debug|ARM.Build.0 = Debug|ARM + {812D1A7B-B8AC-49E4-8E6D-AF5D59500D56}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {812D1A7B-B8AC-49E4-8E6D-AF5D59500D56}.Debug|ARM64.Build.0 = Debug|ARM64 + {812D1A7B-B8AC-49E4-8E6D-AF5D59500D56}.Debug|x64.ActiveCfg = Debug|x64 + {812D1A7B-B8AC-49E4-8E6D-AF5D59500D56}.Debug|x64.Build.0 = Debug|x64 + {812D1A7B-B8AC-49E4-8E6D-AF5D59500D56}.Debug|x86.ActiveCfg = Debug|Win32 + {812D1A7B-B8AC-49E4-8E6D-AF5D59500D56}.Debug|x86.Build.0 = Debug|Win32 + {812D1A7B-B8AC-49E4-8E6D-AF5D59500D56}.Release|ARM.ActiveCfg = Release|ARM + {812D1A7B-B8AC-49E4-8E6D-AF5D59500D56}.Release|ARM.Build.0 = Release|ARM + {812D1A7B-B8AC-49E4-8E6D-AF5D59500D56}.Release|ARM64.ActiveCfg = Release|ARM64 + {812D1A7B-B8AC-49E4-8E6D-AF5D59500D56}.Release|ARM64.Build.0 = Release|ARM64 + {812D1A7B-B8AC-49E4-8E6D-AF5D59500D56}.Release|x64.ActiveCfg = Release|x64 + {812D1A7B-B8AC-49E4-8E6D-AF5D59500D56}.Release|x64.Build.0 = Release|x64 + {812D1A7B-B8AC-49E4-8E6D-AF5D59500D56}.Release|x86.ActiveCfg = Release|Win32 + {812D1A7B-B8AC-49E4-8E6D-AF5D59500D56}.Release|x86.Build.0 = Release|Win32 {D3BAED2C-4B07-4E1D-8807-9D6499450349}.Debug|ARM.ActiveCfg = Debug|ARM {D3BAED2C-4B07-4E1D-8807-9D6499450349}.Debug|ARM64.ActiveCfg = Debug|ARM64 {D3BAED2C-4B07-4E1D-8807-9D6499450349}.Debug|x64.ActiveCfg = Debug|x64 @@ -191,6 +169,44 @@ Global {FC81FF41-02CD-4CD9-9BC5-45A1E39AC6ED}.Release|x64.Build.0 = Release|x64 {FC81FF41-02CD-4CD9-9BC5-45A1E39AC6ED}.Release|x86.ActiveCfg = Release|Win32 {FC81FF41-02CD-4CD9-9BC5-45A1E39AC6ED}.Release|x86.Build.0 = Release|Win32 + {3B773403-B0D6-4F9A-948E-512A7A5FB315}.Debug|ARM.ActiveCfg = Debug|ARM + {3B773403-B0D6-4F9A-948E-512A7A5FB315}.Debug|ARM.Build.0 = Debug|ARM + {3B773403-B0D6-4F9A-948E-512A7A5FB315}.Debug|ARM.Deploy.0 = Debug|ARM + {3B773403-B0D6-4F9A-948E-512A7A5FB315}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {3B773403-B0D6-4F9A-948E-512A7A5FB315}.Debug|ARM64.Build.0 = Debug|ARM64 + {3B773403-B0D6-4F9A-948E-512A7A5FB315}.Debug|ARM64.Deploy.0 = Debug|ARM64 + {3B773403-B0D6-4F9A-948E-512A7A5FB315}.Debug|x64.ActiveCfg = Debug|x64 + {3B773403-B0D6-4F9A-948E-512A7A5FB315}.Debug|x64.Build.0 = Debug|x64 + {3B773403-B0D6-4F9A-948E-512A7A5FB315}.Debug|x64.Deploy.0 = Debug|x64 + {3B773403-B0D6-4F9A-948E-512A7A5FB315}.Debug|x86.ActiveCfg = Debug|x86 + {3B773403-B0D6-4F9A-948E-512A7A5FB315}.Debug|x86.Build.0 = Debug|x86 + {3B773403-B0D6-4F9A-948E-512A7A5FB315}.Debug|x86.Deploy.0 = Debug|x86 + {3B773403-B0D6-4F9A-948E-512A7A5FB315}.Release|ARM.ActiveCfg = Release|ARM + {3B773403-B0D6-4F9A-948E-512A7A5FB315}.Release|ARM.Build.0 = Release|ARM + {3B773403-B0D6-4F9A-948E-512A7A5FB315}.Release|ARM.Deploy.0 = Release|ARM + {3B773403-B0D6-4F9A-948E-512A7A5FB315}.Release|ARM64.ActiveCfg = Release|ARM64 + {3B773403-B0D6-4F9A-948E-512A7A5FB315}.Release|ARM64.Build.0 = Release|ARM64 + {3B773403-B0D6-4F9A-948E-512A7A5FB315}.Release|ARM64.Deploy.0 = Release|ARM64 + {3B773403-B0D6-4F9A-948E-512A7A5FB315}.Release|x64.ActiveCfg = Release|x64 + {3B773403-B0D6-4F9A-948E-512A7A5FB315}.Release|x64.Build.0 = Release|x64 + {3B773403-B0D6-4F9A-948E-512A7A5FB315}.Release|x64.Deploy.0 = Release|x64 + {3B773403-B0D6-4F9A-948E-512A7A5FB315}.Release|x86.ActiveCfg = Release|x86 + {3B773403-B0D6-4F9A-948E-512A7A5FB315}.Release|x86.Build.0 = Release|x86 + {3B773403-B0D6-4F9A-948E-512A7A5FB315}.Release|x86.Deploy.0 = Release|x86 + {CC9B4FA7-D746-4F52-9401-0AD1B4D6B16D}.Debug|ARM.ActiveCfg = Debug|ARM + {CC9B4FA7-D746-4F52-9401-0AD1B4D6B16D}.Debug|ARM.Build.0 = Debug|ARM + {CC9B4FA7-D746-4F52-9401-0AD1B4D6B16D}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {CC9B4FA7-D746-4F52-9401-0AD1B4D6B16D}.Debug|x64.ActiveCfg = Debug|x64 + {CC9B4FA7-D746-4F52-9401-0AD1B4D6B16D}.Debug|x64.Build.0 = Debug|x64 + {CC9B4FA7-D746-4F52-9401-0AD1B4D6B16D}.Debug|x86.ActiveCfg = Debug|Win32 + {CC9B4FA7-D746-4F52-9401-0AD1B4D6B16D}.Debug|x86.Build.0 = Debug|Win32 + {CC9B4FA7-D746-4F52-9401-0AD1B4D6B16D}.Release|ARM.ActiveCfg = Release|ARM + {CC9B4FA7-D746-4F52-9401-0AD1B4D6B16D}.Release|ARM.Build.0 = Release|ARM + {CC9B4FA7-D746-4F52-9401-0AD1B4D6B16D}.Release|ARM64.ActiveCfg = Release|ARM64 + {CC9B4FA7-D746-4F52-9401-0AD1B4D6B16D}.Release|x64.ActiveCfg = Release|x64 + {CC9B4FA7-D746-4F52-9401-0AD1B4D6B16D}.Release|x64.Build.0 = Release|x64 + {CC9B4FA7-D746-4F52-9401-0AD1B4D6B16D}.Release|x86.ActiveCfg = Release|Win32 + {CC9B4FA7-D746-4F52-9401-0AD1B4D6B16D}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/src/Calculator/AboutFlyout.xaml b/src/Calculator/AboutFlyout.xaml index b83dfd83..e9b16a61 100644 --- a/src/Calculator/AboutFlyout.xaml +++ b/src/Calculator/AboutFlyout.xaml @@ -82,11 +82,13 @@ FontSize="{ThemeResource BodyFontSize}" TextWrapping="Wrap"> - + - + + diff --git a/src/Calculator/AboutFlyout.xaml.cpp b/src/Calculator/AboutFlyout.xaml.cpp deleted file mode 100644 index c89c7df5..00000000 --- a/src/Calculator/AboutFlyout.xaml.cpp +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -#include "pch.h" -#include "AboutFlyout.xaml.h" -#include "CalcViewModel/Common/AppResourceProvider.h" -#include "CalcViewModel/Common/LocalizationService.h" -#include "CalcViewModel/Common/LocalizationStringUtil.h" -#include "CalcViewModel/Common/TraceLogger.h" - -using namespace std; -using namespace CalculatorApp; -using namespace CalculatorApp::Common; -using namespace Platform; -using namespace Windows::ApplicationModel; -using namespace Windows::Foundation; -using namespace Windows::System; -using namespace Windows::UI::Xaml; -using namespace Windows::UI::Xaml::Controls; -using namespace Windows::UI::Xaml::Controls::Primitives; -using namespace Windows::UI::Xaml::Data; - -#ifndef BUILD_YEAR -#define BUILD_YEAR 2021 -#endif - -AboutFlyout::AboutFlyout() -{ - auto locService = LocalizationService::GetInstance(); - auto resourceLoader = AppResourceProvider::GetInstance(); - - InitializeComponent(); - - Language = locService->GetLanguage(); - - this->SetVersionString(); - - Header->Text = resourceLoader->GetResourceString("AboutButton/Content"); - - auto copyrightText = - LocalizationStringUtil::GetLocalizedString(resourceLoader->GetResourceString("AboutControlCopyright"), StringReference(to_wstring(BUILD_YEAR).c_str())); - AboutControlCopyrightRun->Text = copyrightText; - - InitializeContributeTextBlock(); -} - -void AboutFlyout::FeedbackButton_Click(_In_ Object ^ sender, _In_ RoutedEventArgs ^ e) -{ - PackageVersion version = Package::Current->Id->Version; - String ^ versionNumber = ref new String(L"Version "); - versionNumber = versionNumber + version.Major + "." + version.Minor + "." + version.Build + "." + version.Revision; - Launcher::LaunchUriAsync(ref new Uri("windows-feedback:?contextid=130&metadata=%7B%22Metadata%22:[%7B%22AppBuild%22:%22" + versionNumber + "%22%7D]%7D")); -} - -void AboutFlyout::SetVersionString() -{ - PackageVersion version = Package::Current->Id->Version; - String ^ appName = AppResourceProvider::GetInstance()->GetResourceString(L"AppName"); - AboutFlyoutVersion->Text = appName + L" " + version.Major + L"." + version.Minor + L"." + version.Build + L"." + version.Revision; -} - -void AboutFlyout::SetDefaultFocus() -{ - AboutFlyoutEULA->Focus(::FocusState::Programmatic); -} - -void AboutFlyout::InitializeContributeTextBlock() -{ - auto resProvider = AppResourceProvider::GetInstance(); - std::wstring contributeHyperlinkText = resProvider->GetResourceString(L"AboutFlyoutContribute")->Data(); - - // The resource string has the 'GitHub' hyperlink wrapped with '%HL%'. - // Break the string and assign pieces appropriately. - static const std::wstring delimiter{ L"%HL%" }; - static const size_t delimiterLength{ delimiter.length() }; - - // Find the delimiters. - size_t firstSplitPosition = contributeHyperlinkText.find(delimiter, 0); - assert(firstSplitPosition != std::wstring::npos); - size_t secondSplitPosition = contributeHyperlinkText.find(delimiter, firstSplitPosition + 1); - assert(secondSplitPosition != std::wstring::npos); - size_t hyperlinkTextLength = secondSplitPosition - (firstSplitPosition + delimiterLength); - - // Assign pieces. - auto contributeTextBeforeHyperlink = ref new String(contributeHyperlinkText.substr(0, firstSplitPosition).c_str()); - auto contributeTextLink = ref new String(contributeHyperlinkText.substr(firstSplitPosition + delimiterLength, hyperlinkTextLength).c_str()); - auto contributeTextAfterHyperlink = ref new String(contributeHyperlinkText.substr(secondSplitPosition + delimiterLength).c_str()); - - ContributeRunBeforeLink->Text = contributeTextBeforeHyperlink; - ContributeRunLink->Text = contributeTextLink; - ContributeRunAfterLink->Text = contributeTextAfterHyperlink; -} diff --git a/src/Calculator/AboutFlyout.xaml.cs b/src/Calculator/AboutFlyout.xaml.cs new file mode 100644 index 00000000..34508206 --- /dev/null +++ b/src/Calculator/AboutFlyout.xaml.cs @@ -0,0 +1,86 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using CalculatorApp.ViewModel.Common; +using System; +using System.Diagnostics; +using Windows.ApplicationModel; +using Windows.System; +using Windows.UI.Xaml; + +namespace CalculatorApp +{ + public sealed partial class AboutFlyout + { + // CSHARP_MIGRATION: TODO: + // BUILD_YEAR was a C++/CX macro and may update the value from the pipeline + private const string BUILD_YEAR = "2021"; + + public AboutFlyout() + { + var locService = LocalizationService.GetInstance(); + var resourceLoader = AppResourceProvider.GetInstance(); + + InitializeComponent(); + + Language = locService.GetLanguage(); + + SetVersionString(); + + Header.Text = resourceLoader.GetResourceString("AboutButton/Content"); + + var copyrightText = + LocalizationStringUtil.GetLocalizedString(resourceLoader.GetResourceString("AboutControlCopyright"), BUILD_YEAR); + AboutControlCopyrightRun.Text = copyrightText; + + InitializeContributeTextBlock(); + } + + public void SetDefaultFocus() + { + AboutFlyoutEULA.Focus(FocusState.Programmatic); + } + + private void FeedbackButton_Click(object sender, RoutedEventArgs e) + { + PackageVersion version = Package.Current.Id.Version; + string versionNumber = "Version "; + versionNumber = versionNumber + version.Major + "." + version.Minor + "." + version.Build + "." + version.Revision; + _ = Launcher.LaunchUriAsync(new Uri("windows-feedback:?contextid=130&metadata=%7B%22Metadata%22:[%7B%22AppBuild%22:%22" + versionNumber + "%22%7D]%7D")); + } + + private void SetVersionString() + { + PackageVersion version = Package.Current.Id.Version; + string appName = AppResourceProvider.GetInstance().GetResourceString("AppName"); + AboutFlyoutVersion.Text = appName + " " + version.Major + "." + version.Minor + "." + version.Build + "." + version.Revision; + } + + private void InitializeContributeTextBlock() + { + var resProvider = AppResourceProvider.GetInstance(); + string contributeHyperlinkText = resProvider.GetResourceString("AboutFlyoutContribute"); + + // The resource string has the 'GitHub' hyperlink wrapped with '%HL%'. + // Break the string and assign pieces appropriately. + string delimiter = "%HL%"; + int delimiterLength = delimiter.Length; + + // Find the delimiters. + int firstSplitPosition = contributeHyperlinkText.IndexOf(delimiter, 0); + Debug.Assert(firstSplitPosition != -1); + int secondSplitPosition = contributeHyperlinkText.IndexOf(delimiter, firstSplitPosition + 1); + Debug.Assert(secondSplitPosition != -1); + int hyperlinkTextLength = secondSplitPosition - (firstSplitPosition + delimiterLength); + + // Assign pieces. + var contributeTextBeforeHyperlink = contributeHyperlinkText.Substring(0, firstSplitPosition); + var contributeTextLink = contributeHyperlinkText.Substring(firstSplitPosition + delimiterLength, hyperlinkTextLength); + var contributeTextAfterHyperlink = contributeHyperlinkText.Substring(secondSplitPosition + delimiterLength); + + ContributeRunBeforeLink.Text = contributeTextBeforeHyperlink; + ContributeRunLink.Text = contributeTextLink; + ContributeRunAfterLink.Text = contributeTextAfterHyperlink; + } + } +} diff --git a/src/Calculator/AboutFlyout.xaml.h b/src/Calculator/AboutFlyout.xaml.h deleted file mode 100644 index f4e47a36..00000000 --- a/src/Calculator/AboutFlyout.xaml.h +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -#pragma once - -#include "AboutFlyout.g.h" - -namespace CalculatorApp -{ -public - ref class AboutFlyout sealed - { - public: - AboutFlyout(); - - void SetDefaultFocus(); - - private: - void FeedbackButton_Click(_In_ Platform::Object ^ sender, _In_ Windows::UI::Xaml::RoutedEventArgs ^ e); - void SetVersionString(); - void InitializeContributeTextBlock(); - }; -} /* namespace CalculatorApp */ diff --git a/src/Calculator/App.xaml.cpp b/src/Calculator/App.xaml.cpp deleted file mode 100644 index 938b5d23..00000000 --- a/src/Calculator/App.xaml.cpp +++ /dev/null @@ -1,439 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -// -// App.xaml.cpp -// Implementation of the App class. -// - -#include "pch.h" -#include "App.xaml.h" -#include "CalcViewModel/Common/TraceLogger.h" -#include "CalcViewModel/Common/Automation/NarratorNotifier.h" -#include "CalcViewModel/Common/AppResourceProvider.h" -#include "CalcViewModel/Common/LocalizationSettings.h" -#include "Views/MainPage.xaml.h" - -using namespace CalculatorApp; -using namespace CalculatorApp::Common; -using namespace CalculatorApp::Common::Automation; - -using namespace Concurrency; -using namespace Microsoft::WRL; -using namespace Platform; -using namespace Windows::ApplicationModel; -using namespace Windows::ApplicationModel::Activation; -using namespace Windows::ApplicationModel::Core; -using namespace Windows::ApplicationModel::Resources; -using namespace Windows::Foundation; -using namespace Windows::Foundation::Collections; -using namespace Windows::Storage; -using namespace Windows::System; -using namespace Windows::UI::Core; -using namespace Windows::UI::Popups; -using namespace Windows::UI::StartScreen; -using namespace Windows::UI::ViewManagement; -using namespace Windows::UI::Xaml; -using namespace Windows::UI::Xaml::Controls; -using namespace Windows::UI::Xaml::Controls::Primitives; -using namespace Windows::UI::Xaml::Data; -using namespace Windows::UI::Xaml::Input; -using namespace Windows::UI::Xaml::Interop; -using namespace Windows::UI::Xaml::Media; -using namespace Windows::UI::Xaml::Media::Animation; -using namespace Windows::UI::Xaml::Navigation; -using namespace Windows::ApplicationModel::Activation; - -namespace CalculatorApp -{ - namespace ApplicationResourceKeys - { - StringReference AppMinWindowHeight(L"AppMinWindowHeight"); - StringReference AppMinWindowWidth(L"AppMinWindowWidth"); - } -} - -/// -/// Initializes the singleton application object. This is the first line of authored code -/// executed, and as such is the logical equivalent of main() or WinMain(). -/// -App::App() -{ - InitializeComponent(); - - m_preLaunched = false; - - RegisterDependencyProperties(); - - // TODO: MSFT 14645325: Set this directly from XAML. - // Currently this is bugged so the property is only respected from code-behind. - this->HighContrastAdjustment = ApplicationHighContrastAdjustment::None; - - this->Suspending += ref new SuspendingEventHandler(this, &App::OnSuspending); - -#if _DEBUG - this->DebugSettings->IsBindingTracingEnabled = true; - this->DebugSettings->BindingFailed += ref new BindingFailedEventHandler([](_In_ Object ^ /*sender*/, _In_ BindingFailedEventArgs ^ e) { - if (IsDebuggerPresent()) - { - ::Platform::String ^ errorMessage = e->Message; - __debugbreak(); - } - }); -#endif -} - -void App::AddWindowToMap(_In_ WindowFrameService ^ frameService) -{ - reader_writer_lock::scoped_lock lock(m_windowsMapLock); - m_secondaryWindows[frameService->GetViewId()] = frameService; - TraceLogger::GetInstance()->UpdateWindowCount(m_secondaryWindows.size()); -} - -WindowFrameService ^ App::GetWindowFromMap(int viewId) -{ - reader_writer_lock::scoped_lock_read lock(m_windowsMapLock); - auto windowMapEntry = m_secondaryWindows.find(viewId); - if (windowMapEntry != m_secondaryWindows.end()) - { - return windowMapEntry->second; - } - return nullptr; -} - -void App::RemoveWindowFromMap(int viewId) -{ - reader_writer_lock::scoped_lock lock(m_windowsMapLock); - auto iter = m_secondaryWindows.find(viewId); - assert(iter != m_secondaryWindows.end() && "Window does not exist in the list"); - m_secondaryWindows.erase(viewId); -} - -void App::RemoveWindow(_In_ WindowFrameService ^ frameService) -{ - // Shell does not allow killing the main window. - if (m_mainViewId != frameService->GetViewId()) - { - HandleViewReleaseAndRemoveWindowFromMap(frameService); - } -} - -task App::HandleViewReleaseAndRemoveWindowFromMap(_In_ WindowFrameService ^ frameService) -{ - WeakReference weak(this); - - // Unregister the event handler of the Main Page - auto frame = safe_cast(Window::Current->Content); - auto mainPage = safe_cast(frame->Content); - mainPage->UnregisterEventHandlers(); - - return frameService->HandleViewRelease().then( - [weak, frameService]() { - auto that = weak.Resolve(); - that->RemoveWindowFromMap(frameService->GetViewId()); - }, - task_continuation_context::use_arbitrary()); -} - -#pragma optimize("", off) // Turn off optimizations to work around coroutine optimization bug -task App::SetupJumpList() -{ - try - { - auto calculatorOptions = NavCategoryGroup::CreateCalculatorCategory(); - - auto jumpList = co_await JumpList::LoadCurrentAsync(); - jumpList->SystemGroupKind = JumpListSystemGroupKind::None; - jumpList->Items->Clear(); - - for (NavCategory ^ option : calculatorOptions->Categories) - { - if (!option->IsEnabled) - { - continue; - } - ViewMode mode = option->Mode; - auto item = JumpListItem::CreateWithArguments(((int)mode).ToString(), L"ms-resource:///Resources/" + NavCategory::GetNameResourceKey(mode)); - item->Description = L"ms-resource:///Resources/" + NavCategory::GetNameResourceKey(mode); - item->Logo = ref new Uri("ms-appx:///Assets/" + mode.ToString() + ".png"); - - jumpList->Items->Append(item); - } - - co_await jumpList->SaveAsync(); - } - catch (...) - { - } -}; -#pragma optimize("", on) - -void App::RemoveSecondaryWindow(_In_ WindowFrameService ^ frameService) -{ - // Shell does not allow killing the main window. - if (m_mainViewId != frameService->GetViewId()) - { - RemoveWindowFromMap(frameService->GetViewId()); - } -} - -Frame ^ App::CreateFrame() -{ - auto frame = ref new Frame(); - frame->FlowDirection = LocalizationService::GetInstance()->GetFlowDirection(); - - return frame; -} - -/// -/// Invoked when the application is launched normally by the end user. Other entry points -/// will be used when the application is launched to open a specific file, to display -/// search results, and so forth. -/// -/// Details about the launch request and process. -void App::OnLaunched(LaunchActivatedEventArgs ^ args) -{ - if (args->PrelaunchActivated) - { - // If the app got pre-launch activated, then save that state in a flag - m_preLaunched = true; - } - NavCategory::InitializeCategoryManifest(args->User); - OnAppLaunch(args, args->Arguments); -} - -void App::OnAppLaunch(IActivatedEventArgs ^ args, String ^ argument) -{ - // Uncomment the following lines to display frame-rate and per-frame CPU usage info. - //#if _DEBUG - // if (IsDebuggerPresent()) - // { - // DebugSettings->EnableFrameRateCounter = true; - // } - //#endif - - args->SplashScreen->Dismissed += ref new TypedEventHandler(this, &App::DismissedEventHandler); - - auto rootFrame = dynamic_cast(Window::Current->Content); - WeakReference weak(this); - - float minWindowWidth = static_cast(static_cast(this->Resources->Lookup(ApplicationResourceKeys::AppMinWindowWidth))); - float minWindowHeight = static_cast(static_cast(this->Resources->Lookup(ApplicationResourceKeys::AppMinWindowHeight))); - Size minWindowSize = SizeHelper::FromDimensions(minWindowWidth, minWindowHeight); - - ApplicationView ^ appView = ApplicationView::GetForCurrentView(); - ApplicationDataContainer ^ localSettings = ApplicationData::Current->LocalSettings; - // For very first launch, set the size of the calc as size of the default standard mode - if (!localSettings->Values->HasKey(L"VeryFirstLaunch")) - { - localSettings->Values->Insert(ref new String(L"VeryFirstLaunch"), false); - appView->SetPreferredMinSize(minWindowSize); - appView->TryResizeView(minWindowSize); - } - else - { - appView->PreferredLaunchWindowingMode = ApplicationViewWindowingMode::Auto; - } - - // Do not repeat app initialization when the Window already has content, - // just ensure that the window is active - if (rootFrame == nullptr) - { - if (!Windows::Foundation::Metadata::ApiInformation::IsTypePresent("Windows.Phone.UI.Input.HardwareButtons")) // PC Family - { - // Disable the system view activation policy during the first launch of the app - // only for PC family devices and not for phone family devices - try - { - ApplicationViewSwitcher::DisableSystemViewActivationPolicy(); - } - catch (Exception ^ e) - { - // Log that DisableSystemViewActionPolicy didn't work - } - } - - // Create a Frame to act as the navigation context - rootFrame = App::CreateFrame(); - - // When the navigation stack isn't restored navigate to the first page, - // configuring the new page by passing required information as a navigation - // parameter - if (!rootFrame->Navigate(MainPage::typeid, argument)) - { - // We couldn't navigate to the main page, kill the app so we have a good - // stack to debug - throw std::bad_exception(); - } - - SetMinWindowSizeAndActivate(rootFrame, minWindowSize); - m_mainViewId = ApplicationView::GetForCurrentView()->Id; - AddWindowToMap(WindowFrameService::CreateNewWindowFrameService(rootFrame, false, weak)); - } - else - { - // For first launch, LaunchStart is logged in constructor, this is for subsequent launches. - - // !Phone check is required because even in continuum mode user interaction mode is Mouse not Touch - if ((UIViewSettings::GetForCurrentView()->UserInteractionMode == UserInteractionMode::Mouse) - && (!Windows::Foundation::Metadata::ApiInformation::IsTypePresent("Windows.Phone.UI.Input.HardwareButtons"))) - { - // If the pre-launch hasn't happened then allow for the new window/view creation - if (!m_preLaunched) - { - auto newCoreAppView = CoreApplication::CreateNewView(); - newCoreAppView->Dispatcher->RunAsync( - CoreDispatcherPriority::Normal, ref new DispatchedHandler([args, argument, minWindowSize, weak]() { - auto that = weak.Resolve(); - if (that != nullptr) - { - auto rootFrame = App::CreateFrame(); - SetMinWindowSizeAndActivate(rootFrame, minWindowSize); - - if (!rootFrame->Navigate(MainPage::typeid, argument)) - { - // We couldn't navigate to the main page, kill the app so we have a good - // stack to debug - throw std::bad_exception(); - } - - auto frameService = WindowFrameService::CreateNewWindowFrameService(rootFrame, true, weak); - that->AddWindowToMap(frameService); - - auto dispatcher = CoreWindow::GetForCurrentThread()->Dispatcher; - auto safeFrameServiceCreation = std::make_shared(frameService, that); - int newWindowId = ApplicationView::GetApplicationViewIdForWindow(CoreWindow::GetForCurrentThread()); - - ActivationViewSwitcher ^ activationViewSwitcher; - auto activateEventArgs = dynamic_cast(args); - if (activateEventArgs != nullptr) - { - activationViewSwitcher = activateEventArgs->ViewSwitcher; - } - - if (activationViewSwitcher != nullptr) - { - activationViewSwitcher->ShowAsStandaloneAsync(newWindowId, ViewSizePreference::Default); - safeFrameServiceCreation->SetOperationSuccess(true); - } - else - { - auto activatedEventArgs = dynamic_cast(args); - if ((activatedEventArgs != nullptr) && (activatedEventArgs->CurrentlyShownApplicationViewId != 0)) - { - create_task(ApplicationViewSwitcher::TryShowAsStandaloneAsync( - frameService->GetViewId(), - ViewSizePreference::Default, - activatedEventArgs->CurrentlyShownApplicationViewId, - ViewSizePreference::Default)) - .then( - [safeFrameServiceCreation](bool viewShown) { - // SafeFrameServiceCreation is used to automatically remove the frame - // from the list of frames if something goes bad. - safeFrameServiceCreation->SetOperationSuccess(viewShown); - }, - task_continuation_context::use_current()); - } - } - } - })); - } - else - { - ActivationViewSwitcher ^ activationViewSwitcher; - auto activateEventArgs = dynamic_cast(args); - if (activateEventArgs != nullptr) - { - activationViewSwitcher = activateEventArgs->ViewSwitcher; - } - - if (activationViewSwitcher != nullptr) - { - activationViewSwitcher->ShowAsStandaloneAsync( - ApplicationView::GetApplicationViewIdForWindow(CoreWindow::GetForCurrentThread()), ViewSizePreference::Default); - } - else - { - TraceLogger::GetInstance()->LogError(ViewMode::None, L"App::OnAppLaunch", L"Null_ActivationViewSwitcher"); - } - } - // Set the preLaunched flag to false - m_preLaunched = false; - } - else // for touch devices - { - if (rootFrame->Content == nullptr) - { - // When the navigation stack isn't restored navigate to the first page, - // configuring the new page by passing required information as a navigation - // parameter - if (!rootFrame->Navigate(MainPage::typeid, argument)) - { - // We couldn't navigate to the main page, - // kill the app so we have a good stack to debug - throw std::bad_exception(); - } - } - if (ApplicationView::GetForCurrentView()->ViewMode != ApplicationViewMode::CompactOverlay) - { - if (!Windows::Foundation::Metadata::ApiInformation::IsTypePresent("Windows.Phone.UI.Input.HardwareButtons")) - { - // for tablet mode: since system view activation policy is disabled so do ShowAsStandaloneAsync if activationViewSwitcher exists in - // activationArgs - ActivationViewSwitcher ^ activationViewSwitcher; - auto activateEventArgs = dynamic_cast(args); - if (activateEventArgs != nullptr) - { - activationViewSwitcher = activateEventArgs->ViewSwitcher; - } - if (activationViewSwitcher != nullptr) - { - auto viewId = safe_cast(args)->CurrentlyShownApplicationViewId; - if (viewId != 0) - { - activationViewSwitcher->ShowAsStandaloneAsync(viewId); - } - } - } - // Ensure the current window is active - Window::Current->Activate(); - } - } - } -} - -void App::SetMinWindowSizeAndActivate(Frame ^ rootFrame, Size minWindowSize) -{ - // SetPreferredMinSize should always be called before Window::Activate - ApplicationView ^ appView = ApplicationView::GetForCurrentView(); - appView->SetPreferredMinSize(minWindowSize); - - // Place the frame in the current Window - Window::Current->Content = rootFrame; - Window::Current->Activate(); -} - -void App::RegisterDependencyProperties() -{ - NarratorNotifier::RegisterDependencyProperties(); -} - -void App::OnActivated(IActivatedEventArgs ^ args) -{ - if (args->Kind == ActivationKind::Protocol) - { - // We currently don't pass the uri as an argument, - // and handle any protocol launch as a normal app launch. - OnAppLaunch(args, nullptr); - } -} - -void CalculatorApp::App::OnSuspending(Object ^ sender, SuspendingEventArgs ^ args) -{ - TraceLogger::GetInstance()->LogButtonUsage(); -} - -void App::DismissedEventHandler(SplashScreen ^ sender, Object ^ e) -{ - SetupJumpList(); -} diff --git a/src/Calculator/App.xaml.cs b/src/Calculator/App.xaml.cs new file mode 100644 index 00000000..73046d99 --- /dev/null +++ b/src/Calculator/App.xaml.cs @@ -0,0 +1,504 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// +// App.xaml.h +// Declaration of the App class. +// + +using CalculatorApp.ViewModel.Common; +using CalculatorApp.ViewModel.Common.Automation; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Threading; +using System.Threading.Tasks; + +using Windows.ApplicationModel; +using Windows.ApplicationModel.Activation; +using Windows.ApplicationModel.Core; +using Windows.Foundation; +using Windows.Storage; +using Windows.UI.Core; +using Windows.UI.StartScreen; +using Windows.UI.ViewManagement; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; + +namespace CalculatorApp +{ + namespace ApplicationResourceKeys + { + static public partial class Globals + { + public static readonly string AppMinWindowHeight = "AppMinWindowHeight"; + public static readonly string AppMinWindowWidth = "AppMinWindowWidth"; + } + } + + /// + /// Provides application-specific behavior to supplement the default Application class. + /// + sealed partial class App + { + /// + /// Initializes the singleton application object. This is the first line of authored code + /// executed, and as such is the logical equivalent of main() or WinMain(). + /// + public App() + { + InitializeComponent(); + + m_preLaunched = false; + + RegisterDependencyProperties(); + + // TODO: MSFT 14645325: Set this directly from XAML. + // Currently this is bugged so the property is only respected from code-behind. + HighContrastAdjustment = ApplicationHighContrastAdjustment.None; + + Suspending += OnSuspending; + +#if DEBUG + DebugSettings.IsBindingTracingEnabled = true; + DebugSettings.BindingFailed += (sender, args) => + { + if (Debugger.IsAttached) + { + string errorMessage = args.Message; + Debugger.Break(); + } + }; +#endif + } + + /// + /// Invoked when the application is launched normally by the end user. Other entry points + /// will be used when the application is launched to open a specific file, to display + /// search results, and so forth. + /// + /// Details about the launch request and process. + protected override void OnLaunched(LaunchActivatedEventArgs args) + { + if (args.PrelaunchActivated) + { + // If the app got pre-launch activated, then save that state in a flag + m_preLaunched = true; + } + NavCategory.InitializeCategoryManifest(args.User); + OnAppLaunch(args, args.Arguments); + } + + protected override void OnActivated(IActivatedEventArgs args) + { + if (args.Kind == ActivationKind.Protocol) + { + // We currently don't pass the uri as an argument, + // and handle any protocol launch as a normal app launch. + OnAppLaunch(args, null); + } + } + + internal void RemoveWindow(WindowFrameService frameService) + { + // Shell does not allow killing the main window. + if (m_mainViewId != frameService.GetViewId()) + { + _ = HandleViewReleaseAndRemoveWindowFromMap(frameService); + } + } + + internal void RemoveSecondaryWindow(WindowFrameService frameService) + { + // Shell does not allow killing the main window. + if (m_mainViewId != frameService.GetViewId()) + { + RemoveWindowFromMap(frameService.GetViewId()); + } + } + + private static Frame CreateFrame() + { + var frame = new Frame(); + frame.FlowDirection = LocalizationService.GetInstance().GetFlowDirection(); + return frame; + } + + private static void SetMinWindowSizeAndActivate(Frame rootFrame, Size minWindowSize) + { + // SetPreferredMinSize should always be called before Window.Activate + ApplicationView appView = ApplicationView.GetForCurrentView(); + appView.SetPreferredMinSize(minWindowSize); + + // Place the frame in the current Window + Window.Current.Content = rootFrame; + Window.Current.Activate(); + } + + private void OnAppLaunch(IActivatedEventArgs args, string argument) + { + // Uncomment the following lines to display frame-rate and per-frame CPU usage info. + //#if _DEBUG + // if (IsDebuggerPresent()) + // { + // DebugSettings->EnableFrameRateCounter = true; + // } + //#endif + + args.SplashScreen.Dismissed += DismissedEventHandler; + + var rootFrame = (Window.Current.Content as Frame); + WeakReference weak = new WeakReference(this); + + float minWindowWidth = (float)((double)Resources[ApplicationResourceKeys.Globals.AppMinWindowWidth]); + float minWindowHeight = (float)((double)Resources[ApplicationResourceKeys.Globals.AppMinWindowHeight]); + Size minWindowSize = SizeHelper.FromDimensions(minWindowWidth, minWindowHeight); + + ApplicationView appView = ApplicationView.GetForCurrentView(); + ApplicationDataContainer localSettings = ApplicationData.Current.LocalSettings; + // For very first launch, set the size of the calc as size of the default standard mode + if (!localSettings.Values.ContainsKey("VeryFirstLaunch")) + { + localSettings.Values["VeryFirstLaunch"] = false; + appView.SetPreferredMinSize(minWindowSize); + appView.TryResizeView(minWindowSize); + } + else + { + ApplicationView.PreferredLaunchWindowingMode = ApplicationViewWindowingMode.Auto; + } + + // Do not repeat app initialization when the Window already has content, + // just ensure that the window is active + if (rootFrame == null) + { + if (!Windows.Foundation.Metadata.ApiInformation.IsTypePresent("Windows.Phone.UI.Input.HardwareButtons")) // PC Family + { + // Disable the system view activation policy during the first launch of the app + // only for PC family devices and not for phone family devices + try + { + ApplicationViewSwitcher.DisableSystemViewActivationPolicy(); + } + catch (Exception) + { + // Log that DisableSystemViewActionPolicy didn't work + } + } + + // Create a Frame to act as the navigation context + rootFrame = App.CreateFrame(); + + // When the navigation stack isn't restored navigate to the first page, + // configuring the new page by passing required information as a navigation + // parameter + if (!rootFrame.Navigate(typeof(MainPage), argument)) + { + // We couldn't navigate to the main page, kill the app so we have a good + // stack to debug + throw new SystemException(); + } + + SetMinWindowSizeAndActivate(rootFrame, minWindowSize); + m_mainViewId = ApplicationView.GetForCurrentView().Id; + AddWindowToMap(WindowFrameService.CreateNewWindowFrameService(rootFrame, false, weak)); + } + else + { + // For first launch, LaunchStart is logged in constructor, this is for subsequent launches. + + // !Phone check is required because even in continuum mode user interaction mode is Mouse not Touch + if ((UIViewSettings.GetForCurrentView().UserInteractionMode == UserInteractionMode.Mouse) + && (!Windows.Foundation.Metadata.ApiInformation.IsTypePresent("Windows.Phone.UI.Input.HardwareButtons"))) + { + // If the pre-launch hasn't happened then allow for the new window/view creation + if (!m_preLaunched) + { + var newCoreAppView = CoreApplication.CreateNewView(); + _ = newCoreAppView.Dispatcher.RunAsync( + CoreDispatcherPriority.Normal, async () => + { + var that = weak.Target as App; + if (that != null) + { + var newRootFrame = App.CreateFrame(); + + SetMinWindowSizeAndActivate(newRootFrame, minWindowSize); + + if (!newRootFrame.Navigate(typeof(MainPage), argument)) + { + // We couldn't navigate to the main page, kill the app so we have a good + // stack to debug + throw new SystemException(); + } + + var frameService = WindowFrameService.CreateNewWindowFrameService(newRootFrame, true, weak); + that.AddWindowToMap(frameService); + + var dispatcher = CoreWindow.GetForCurrentThread().Dispatcher; + + // CSHARP_MIGRATION_ANNOTATION: + // class SafeFrameWindowCreation is being interpreted into a IDisposable class + // in order to enhance its RAII capability that was written in C++/CX + using (var safeFrameServiceCreation = new SafeFrameWindowCreation(frameService, that)) + { + int newWindowId = ApplicationView.GetApplicationViewIdForWindow(CoreWindow.GetForCurrentThread()); + + ActivationViewSwitcher activationViewSwitcher = null; + var activateEventArgs = (args as IViewSwitcherProvider); + if (activateEventArgs != null) + { + activationViewSwitcher = activateEventArgs.ViewSwitcher; + } + + if (activationViewSwitcher != null) + { + _ = activationViewSwitcher.ShowAsStandaloneAsync(newWindowId, ViewSizePreference.Default); + safeFrameServiceCreation.SetOperationSuccess(true); + } + else + { + var activatedEventArgs = (args as IApplicationViewActivatedEventArgs); + if ((activatedEventArgs != null) && (activatedEventArgs.CurrentlyShownApplicationViewId != 0)) + { + // CSHARP_MIGRATION_ANNOTATION: + // here we don't use ContinueWith() to interpret origin code because we would like to + // pursue the design of class SafeFrameWindowCreate whichi was using RAII to ensure + // some states get handled properly when its instance is being destructed. + // + // To achieve that, SafeFrameWindowCreate has been reinterpreted using IDisposable + // pattern, which forces we use below way to keep async works being controlled within + // a same code block. + var viewShown = await ApplicationViewSwitcher.TryShowAsStandaloneAsync( + frameService.GetViewId(), + ViewSizePreference.Default, + activatedEventArgs.CurrentlyShownApplicationViewId, + ViewSizePreference.Default); + // SafeFrameServiceCreation is used to automatically remove the frame + // from the list of frames if something goes bad. + safeFrameServiceCreation.SetOperationSuccess(viewShown); + } + } + } + } + }); + } + else + { + ActivationViewSwitcher activationViewSwitcher = null; + var activateEventArgs = (args as IViewSwitcherProvider); + if (activateEventArgs != null) + { + activationViewSwitcher = activateEventArgs.ViewSwitcher; + } + + if (activationViewSwitcher != null) + { + _ = activationViewSwitcher.ShowAsStandaloneAsync( + ApplicationView.GetApplicationViewIdForWindow(CoreWindow.GetForCurrentThread()), ViewSizePreference.Default); + } + else + { + TraceLogger.GetInstance().LogError(ViewMode.None, "App.OnAppLaunch", "Null_ActivationViewSwitcher"); + } + } + // Set the preLaunched flag to false + m_preLaunched = false; + } + else // for touch devices + { + if (rootFrame.Content == null) + { + // When the navigation stack isn't restored navigate to the first page, + // configuring the new page by passing required information as a navigation + // parameter + if (!rootFrame.Navigate(typeof(MainPage), argument)) + { + // We couldn't navigate to the main page, + // kill the app so we have a good stack to debug + throw new SystemException(); + } + } + if (ApplicationView.GetForCurrentView().ViewMode != ApplicationViewMode.CompactOverlay) + { + if (!Windows.Foundation.Metadata.ApiInformation.IsTypePresent("Windows.Phone.UI.Input.HardwareButtons")) + { + // for tablet mode: since system view activation policy is disabled so do ShowAsStandaloneAsync if activationViewSwitcher exists in + // activationArgs + ActivationViewSwitcher activationViewSwitcher = null; + var activateEventArgs = (args as IViewSwitcherProvider); + if (activateEventArgs != null) + { + activationViewSwitcher = activateEventArgs.ViewSwitcher; + } + if (activationViewSwitcher != null) + { + var viewId = (args as IApplicationViewActivatedEventArgs).CurrentlyShownApplicationViewId; + if (viewId != 0) + { + _ = activationViewSwitcher.ShowAsStandaloneAsync(viewId); + } + } + } + // Ensure the current window is active + Window.Current.Activate(); + } + } + } + } + + private void DismissedEventHandler(SplashScreen sender, object e) + { + _ = SetupJumpList(); + } + + private void RegisterDependencyProperties() + { + NarratorNotifier.RegisterDependencyProperties(); + } + + private void OnSuspending(object sender, SuspendingEventArgs args) + { + TraceLogger.GetInstance().LogButtonUsage(); + } + + private sealed class SafeFrameWindowCreation : IDisposable + { + public SafeFrameWindowCreation(WindowFrameService frameService, App parent) + { + m_frameService = frameService; + m_frameOpenedInWindow = false; + m_parent = parent; + } + + public void SetOperationSuccess(bool success) + { + m_frameOpenedInWindow = success; + } + + public void Dispose() + { + if (!m_frameOpenedInWindow) + { + // Close the window as the navigation to the window didn't succeed + // and this is not visible to the user. + m_parent.RemoveWindowFromMap(m_frameService.GetViewId()); + } + + GC.SuppressFinalize(this); + } + + ~SafeFrameWindowCreation() + { + Dispose(); + } + + private WindowFrameService m_frameService; + private bool m_frameOpenedInWindow; + private App m_parent; + }; + + private async Task SetupJumpList() + { + try + { + var calculatorOptions = NavCategoryGroup.CreateCalculatorCategory(); + + var jumpList = await JumpList.LoadCurrentAsync(); + jumpList.SystemGroupKind = JumpListSystemGroupKind.None; + jumpList.Items.Clear(); + + foreach (NavCategory option in calculatorOptions.Categories) + { + if (!option.IsEnabled) + { + continue; + } + ViewMode mode = option.Mode; + var item = JumpListItem.CreateWithArguments(((int)mode).ToString(), "ms-resource:///Resources/" + NavCategory.GetNameResourceKey(mode)); + item.Description = "ms-resource:///Resources/" + NavCategory.GetNameResourceKey(mode); + item.Logo = new Uri("ms-appx:///Assets/" + mode.ToString() + ".png"); + + jumpList.Items.Add(item); + } + + await jumpList.SaveAsync(); + } + catch + { + } + } + + private async Task HandleViewReleaseAndRemoveWindowFromMap(WindowFrameService frameService) + { + WeakReference weak = new WeakReference(this); + + // Unregister the event handler of the Main Page + var frame = (Window.Current.Content as Frame); + var mainPage = (frame.Content as MainPage); + + mainPage.UnregisterEventHandlers(); + + await frameService.HandleViewRelease(); + await Task.Run(() => + { + var that = weak.Target as App; + that.RemoveWindowFromMap(frameService.GetViewId()); + }).ConfigureAwait(false /* task_continuation_context::use_arbitrary() */); + } + + private void AddWindowToMap(WindowFrameService frameService) + { + m_windowsMapLock.EnterWriteLock(); + try + { + m_secondaryWindows[frameService.GetViewId()] = frameService; + TraceLogger.GetInstance().UpdateWindowCount(Convert.ToUInt64(m_secondaryWindows.Count)); + } + finally + { + m_windowsMapLock.ExitWriteLock(); + } + } + + private WindowFrameService GetWindowFromMap(int viewId) + { + m_windowsMapLock.EnterReadLock(); + try + { + if (m_secondaryWindows.TryGetValue(viewId, out var windowMapEntry)) + { + return windowMapEntry; + } + else + { + return null; + } + } + finally + { + m_windowsMapLock.ExitReadLock(); + } + } + + private void RemoveWindowFromMap(int viewId) + { + m_windowsMapLock.EnterWriteLock(); + try + { + bool removed = m_secondaryWindows.Remove(viewId); + Debug.Assert(removed != false, "Window does not exist in the list"); + } + finally + { + m_windowsMapLock.ExitWriteLock(); + } + } + + private readonly ReaderWriterLockSlim m_windowsMapLock = new ReaderWriterLockSlim(); + private Dictionary m_secondaryWindows = new Dictionary(); + private int m_mainViewId; + private bool m_preLaunched; + } +} + diff --git a/src/Calculator/App.xaml.h b/src/Calculator/App.xaml.h deleted file mode 100644 index f11ebef6..00000000 --- a/src/Calculator/App.xaml.h +++ /dev/null @@ -1,91 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -// -// App.xaml.h -// Declaration of the App class. -// - -#pragma once - -#include "App.g.h" -#include "WindowFrameService.h" - -namespace CalculatorApp -{ - namespace ApplicationResourceKeys - { - extern Platform::StringReference AppMinWindowHeight; - extern Platform::StringReference AppMinWindowWidth; - } - - /// - /// Provides application-specific behavior to supplement the default Application class. - /// - ref class App sealed - { - public: - App(); - virtual void OnLaunched(Windows::ApplicationModel::Activation::LaunchActivatedEventArgs ^ args) override; - virtual void OnActivated(Windows::ApplicationModel::Activation::IActivatedEventArgs ^ args) override; - - internal: - void RemoveWindow(_In_ WindowFrameService ^ frameService); - void RemoveSecondaryWindow(_In_ WindowFrameService ^ frameService); - - private: - static Windows::UI::Xaml::Controls::Frame ^ CreateFrame(); - static void SetMinWindowSizeAndActivate(Windows::UI::Xaml::Controls::Frame ^ rootFrame, Windows::Foundation::Size minWindowSize); - - void OnAppLaunch(Windows::ApplicationModel::Activation::IActivatedEventArgs ^ args, Platform::String ^ argument); - void DismissedEventHandler(Windows::ApplicationModel::Activation::SplashScreen ^ sender, Platform::Object ^ e); - void RegisterDependencyProperties(); - void OnSuspending(Platform::Object ^ sender, Windows::ApplicationModel::SuspendingEventArgs ^ args); - - - class SafeFrameWindowCreation final - { - public: - SafeFrameWindowCreation(_In_ WindowFrameService ^ frameService, App ^ parent) - : m_frameService(frameService) - , m_frameOpenedInWindow(false) - , m_parent(parent) - { - } - - void SetOperationSuccess(bool success) - { - m_frameOpenedInWindow = success; - } - - ~SafeFrameWindowCreation() - { - if (!m_frameOpenedInWindow) - { - // Close the window as the navigation to the window didn't succeed - // and this is not visible to the user. - m_parent->RemoveWindowFromMap(m_frameService->GetViewId()); - } - } - - private: - WindowFrameService ^ m_frameService; - bool m_frameOpenedInWindow; - App ^ m_parent; - }; - - private: - concurrency::reader_writer_lock m_windowsMapLock; - std::unordered_map m_secondaryWindows; - - concurrency::task SetupJumpList(); - concurrency::task HandleViewReleaseAndRemoveWindowFromMap(_In_ WindowFrameService ^ frameService); - void AddWindowToMap(_In_ WindowFrameService ^ frameService); - WindowFrameService ^ GetWindowFromMap(int viewId); - void RemoveWindowFromMap(int viewId); - int m_mainViewId; - bool m_preLaunched; - - Windows::UI::Xaml::Controls::Primitives::Popup ^ m_aboutPopup; - }; -} diff --git a/src/Calculator/Calculator.csproj b/src/Calculator/Calculator.csproj new file mode 100644 index 00000000..75c53533 --- /dev/null +++ b/src/Calculator/Calculator.csproj @@ -0,0 +1,837 @@ + + + + + Debug + x86 + {3B773403-B0D6-4F9A-948E-512A7A5FB315} + AppContainerExe + Properties + CalculatorApp + CalculatorApp + Windows Store + true + en-US + UAP + 10.0.19041.0 + 10.0.17134.0 + + false + false + 14 + 10.0 + black + 512 + {A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + true + True + WindowsDev_TemporaryKey.pfx + False + Always + true + False + SHA256 + False + True + $(Platform) + 0 + + + + true + ..\x86\Debug\Calculator\ + DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP + ;2008 + full + x86 + false + prompt + true + + + ..\x86\Release\Calculator\ + TRACE;NETFX_CORE;WINDOWS_UWP + true + ;2008 + pdbonly + x86 + false + prompt + true + true + + + true + ..\ARM\Debug\Calculator\ + DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP + ;2008 + full + ARM + false + prompt + true + + + ..\ARM\Release\Calculator\ + TRACE;NETFX_CORE;WINDOWS_UWP + true + ;2008 + pdbonly + ARM + false + prompt + true + true + + + true + ..\ARM64\Debug\Calculator\ + DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP + ;2008 + full + ARM64 + false + prompt + true + true + + + ..\ARM64\Release\Calculator\ + TRACE;NETFX_CORE;WINDOWS_UWP + true + ;2008 + pdbonly + ARM64 + false + prompt + true + true + + + true + ..\x64\Debug\Calculator\ + DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP + ;2008 + full + x64 + false + prompt + true + + + ..\x64\Release\Calculator\ + TRACE;NETFX_CORE;WINDOWS_UWP + true + ;2008 + pdbonly + x64 + false + prompt + true + true + + + $(DefineConstants);SEND_DIAGNOSTICS;IS_STORE_BUILD + + + PackageReference + + + + AboutFlyout.xaml + + + App.xaml + + + + + + + + + + + + + + + + + + + + + + + + + + + EquationStylePanelControl.xaml + + + + + Calculator.xaml + + + CalculatorProgrammerBitFlipPanel.xaml + + + CalculatorProgrammerOperators.xaml + + + CalculatorProgrammerRadixOperators.xaml + + + CalculatorScientificAngleButtons.xaml + + + CalculatorScientificOperators.xaml + + + CalculatorStandardOperators.xaml + + + DateCalculator.xaml + + + EquationInputArea.xaml + + + GraphingCalculator.xaml + + + GraphingNumPad.xaml + + + GraphingSettings.xaml + + + KeyGraphFeaturesPanel.xaml + + + HistoryList.xaml + + + MainPage.xaml + + + + + + Memory.xaml + + + MemoryListItem.xaml + + + NumberPad.xaml + + + OperatorsPanel.xaml + + + + CalculatorProgrammerDisplayPanel.xaml + + + + SupplementaryResults.xaml + + + TitleBar.xaml + + + UnitConverter.xaml + + + + + + Designer + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Designer + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + MSBuild:Compile + Designer + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + MSBuild:Compile + Designer + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + MSBuild:Compile + Designer + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + MSBuild:Compile + Designer + + + + + 6.2.10 + + + + + + {812d1a7b-b8ac-49e4-8e6d-af5d59500d56} + CalcViewModel + + + {e727a92b-f149-492c-8117-c039a298719b} + GraphControl + + + {fc81ff41-02cd-4cd9-9bc5-45a1e39ac6ed} + TraceLogging + + + + + + + + 14.0 + + + + + <_IntermediateFrameworkSdkReference Include="@(AppxPackageRegistration)" Condition="'@(AppxPackageRegistration)' != '' AND ('$(Configuration)' == '%(AppxPackageRegistration.Configuration)' OR '%(AppxPackageRegistration.Configuration)' == '') AND ('$(PlatformTarget)' == '%(AppxPackageRegistration.Architecture)' OR '%(AppxPackageRegistration.Configuration)' == '')"> + %(AppxPackageRegistration.Name) + %(AppxPackageRegistration.Filename) + %(AppxPackageRegistration.Configuration) + %(AppxPackageRegistration.Architecture) + %(AppxPackageRegistration.Identity) + + + Name = %(_IntermediateFrameworkSdkReference.SDKName), MinVersion = %(_IntermediateFrameworkSdkReference.Version), Publisher = %(_IntermediateFrameworkSdkReference.Publisher) + + + + + + + \ No newline at end of file diff --git a/src/Calculator/Calculator.vcxproj b/src/Calculator/Calculator.vcxproj deleted file mode 100644 index 4724d1fc..00000000 --- a/src/Calculator/Calculator.vcxproj +++ /dev/null @@ -1,969 +0,0 @@ - - - - {9447424a-0e05-4911-beb8-e0354405f39a} - CalculatorApp - en-US - 15.0 - true - Windows Store - 10.0.18362.0 - 10.0.17134.0 - - false - false - 10.0 - black - Always - WindowsDev_TemporaryKey.pfx - True - False - - - - - x64 - - - - Debug - ARM - - - Debug - ARM64 - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - ARM64 - - - Release - Win32 - - - Release - x64 - - - - Application - true - v142 - - - Application - true - v142 - - - Application - true - v142 - - - Application - true - v142 - - - Application - false - true - v142 - - - Application - false - true - v142 - - - Application - false - true - v142 - - - Application - false - true - v142 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - /bigobj /await /std:c++17 /utf-8 %(AdditionalOptions) - 4453;28204 - $(SolutionDir)..\src\;%(AdditionalIncludeDirectories) - Level4 - true - - - - - /bigobj /await /std:c++17 /utf-8 %(AdditionalOptions) - 4453;28204 - $(SolutionDir)..\src\;%(AdditionalIncludeDirectories) - Level4 - true - - - - - /bigobj /await /std:c++17 /utf-8 %(AdditionalOptions) - 4453;28204 - $(SolutionDir)..\src\;%(AdditionalIncludeDirectories) - Level4 - true - - - WindowsApp.lib;$(VC_ReferencesPath_VC_ARM)\pgort.lib;%(AdditionalDependencies) - - - - - /bigobj /await /std:c++17 /utf-8 %(AdditionalOptions) - 4453;28204 - $(SolutionDir)..\src\;%(AdditionalIncludeDirectories) - Level4 - true - - - WindowsApp.lib;$(VC_ReferencesPath_VC_ARM)\pgort.lib;%(AdditionalDependencies) - - - - - /bigobj /await /std:c++17 /utf-8 %(AdditionalOptions) - 4453;28204 - $(SolutionDir)..\src\;%(AdditionalIncludeDirectories) - Level4 - true - - - - - /bigobj /await /std:c++17 /utf-8 %(AdditionalOptions) - 4453;28204 - $(SolutionDir)..\src\;%(AdditionalIncludeDirectories) - Level4 - true - - - WindowsApp.lib;$(VC_ReferencesPath_VC_x86)\pgort.lib;%(AdditionalDependencies) - - - - - /bigobj /await /std:c++17 /utf-8 %(AdditionalOptions) - 4453;28204 - $(SolutionDir)..\src\;%(AdditionalIncludeDirectories) - Level4 - true - - - - - /bigobj /await /std:c++17 /utf-8 %(AdditionalOptions) - 4453;28204 - $(SolutionDir)..\src\;%(AdditionalIncludeDirectories) - Level4 - true - - - WindowsApp.lib;$(VC_ReferencesPath_VC_x64)\pgort.lib;%(AdditionalDependencies) - - - - - /DSEND_DIAGNOSTICS /DIS_STORE_BUILD %(AdditionalOptions) - - - - 0.0.0.0 - - - true - - - - - - - AboutFlyout.xaml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - App.xaml - - - EquationStylePanelControl.xaml - - - - - Views\Calculator.xaml - - - Views\CalculatorProgrammerBitFlipPanel.xaml - - - Views\CalculatorProgrammerDisplayPanel.xaml - - - Views\CalculatorProgrammerOperators.xaml - - - Views\CalculatorProgrammerRadixOperators.xaml - - - Views\CalculatorScientificAngleButtons.xaml - - - Views\CalculatorScientificOperators.xaml - - - Views\CalculatorStandardOperators.xaml - - - Views\GraphingCalculator\EquationInputArea.xaml - - - Views\GraphingCalculator\GraphingCalculator.xaml - - - Views\GraphingCalculator\GraphingSettings.xaml - - - Views\GraphingCalculator\KeyGraphFeaturesPanel.xaml - - - Views\GraphingCalculator\GraphingNumPad.xaml - - - Views\HistoryList.xaml - - - Views\MainPage.xaml - - - Views\Memory.xaml - - - Views\MemoryListItem.xaml - - - Views\NumberPad.xaml - - - Views\OperatorsPanel.xaml - - - - - Views\SupplementaryResults.xaml - - - Views\DateCalculator.xaml - - - Views\TitleBar.xaml - - - Views\UnitConverter.xaml - - - - - - Designer - - - - Designer - - - Designer - - - Designer - - - - - Designer - - - - Designer - - - - - - - - - - - - - - - - - - - - - - Designer - - - Designer - - - - - - AboutFlyout.xaml - - - App.xaml - - - - - - - - - - - - - - - - - - - - - - - - - - Create - Create - Create - Create - Create - Create - Create - Create - - - EquationStylePanelControl.xaml - - - - - Views\Calculator.xaml - - - Views\CalculatorProgrammerBitFlipPanel.xaml - - - Views\CalculatorProgrammerDisplayPanel.xaml - - - Views\CalculatorProgrammerOperators.xaml - - - Views\CalculatorProgrammerRadixOperators.xaml - - - Views\CalculatorScientificAngleButtons.xaml - - - Views\CalculatorScientificOperators.xaml - - - Views\CalculatorStandardOperators.xaml - - - Views\GraphingCalculator\EquationInputArea.xaml - - - Views\GraphingCalculator\GraphingCalculator.xaml - - - Views\GraphingCalculator\GraphingSettings.xaml - - - Views\GraphingCalculator\KeyGraphFeaturesPanel.xaml - - - Views\GraphingCalculator\GraphingNumPad.xaml - - - Views\HistoryList.xaml - - - Views\MainPage.xaml - - - Views\Memory.xaml - - - Views\MemoryListItem.xaml - - - Views\NumberPad.xaml - - - Views\OperatorsPanel.xaml - - - - - Views\SupplementaryResults.xaml - - - Views\DateCalculator.xaml - - - Views\TitleBar.xaml - - - Views\UnitConverter.xaml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Designer - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - true - - - - - {90e9761d-9262-4773-942d-caeae75d7140} - - - {e727a92b-f149-492c-8117-c039a298719b} - - - - - - - <_IntermediateFrameworkSdkReference Include="@(AppxPackageRegistration)" Condition="'@(AppxPackageRegistration)' != '' AND ('$(Configuration)' == '%(AppxPackageRegistration.Configuration)' OR '%(AppxPackageRegistration.Configuration)' == '') AND ('$(PlatformTarget)' == '%(AppxPackageRegistration.Architecture)' OR '%(AppxPackageRegistration.Configuration)' == '')"> - %(AppxPackageRegistration.Name) - %(AppxPackageRegistration.Filename) - %(AppxPackageRegistration.Configuration) - %(AppxPackageRegistration.Architecture) - %(AppxPackageRegistration.Identity) - - - Name = %(_IntermediateFrameworkSdkReference.SDKName), MinVersion = %(_IntermediateFrameworkSdkReference.Version), Publisher = %(_IntermediateFrameworkSdkReference.Publisher) - - - - - - - - - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see https://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - \ No newline at end of file diff --git a/src/Calculator/Calculator.vcxproj.filters b/src/Calculator/Calculator.vcxproj.filters deleted file mode 100644 index 790f6623..00000000 --- a/src/Calculator/Calculator.vcxproj.filters +++ /dev/null @@ -1,1569 +0,0 @@ - - - - - 9447424a-0e05-4911-beb8-e0354405f39a - - - c853ff75-910d-48f0-ac19-d5fd57622aba - bmp;fbx;gif;jpg;jpeg;tga;tiff;tif;png - - - {21d65f04-31c9-4c70-8511-1c65b894ac8b} - - - {5a666ef7-54fb-46cc-9588-5cbcfaed3465} - - - {f9b88d9e-918b-49ac-869b-a1a380ec3201} - - - {6c2951d4-aa9a-44ce-88c5-28fe11b4e7f7} - - - {7794e615-088b-412c-88bf-f045788ca81f} - - - {72128df8-67df-4d34-934d-14896720e153} - - - {9dd1aaa8-31a9-43b3-b224-77293910f109} - - - {4fc9f4fc-51a7-4348-881b-efe9b32cd0bc} - - - {c883c196-cbc3-437f-8dbd-92f3009479c1} - - - {399ad3d6-a676-45a5-ad0e-8bf796ecfea8} - - - {ad7f2c92-59aa-4720-96af-fccfa1530b25} - - - {b5e4250c-03cf-4cef-ae64-67205e3cdca7} - - - {7ca47758-c39c-40f9-8cbb-7fc2fb627c9e} - - - {65e8bdb6-ca86-43b8-a335-ee406bffe79b} - - - {f47b0870-721f-4646-8b9f-2e55613bcbcc} - - - {9ba8ec65-5ba8-4499-add4-b085710f5ef4} - - - {55225802-0eb4-4d30-91ba-025ac695c7b2} - - - {582f1542-e30b-461d-bf1e-33af9cbd2241} - - - {1fa74901-4f66-4eb1-8d17-fa46debcf314} - - - {2a4bc64b-d709-46a1-9913-006dbf545ff3} - - - {05ba3255-5c3f-4a1f-a8a2-8984cd7826f0} - - - {dc6243aa-fe4d-46e3-9c31-f8461e7bb007} - - - {5dc497d8-4b4d-4851-a721-e37585fcb4ed} - - - {8945e63d-27c4-4407-81bb-993f78b583d8} - - - {a3c3e799-4fff-4795-9ef7-ee2237c4c190} - - - {41958465-ab1b-4450-a688-c2a49a476ad3} - - - {3cb02368-06c6-46b2-a2b3-be916140f2df} - - - {f9dede5d-08b1-4c18-8967-2bf6e0eab10a} - - - {a1cd3ced-b21b-47a1-9dad-5f9a3bcb0653} - - - {99bbda66-7ed8-48e4-bc8b-9285d9c22fb0} - - - {7d443f1c-4e49-4379-bd5c-dd156a73bbb7} - - - {7353aa9e-8f6d-4b11-885b-cb41e8deeb55} - - - {7737b4aa-a25f-464d-8f41-4c7420363963} - - - {a4f2f71c-0707-44df-a8d7-8bf085fc4ace} - - - {16a3847d-fcd8-48ec-af99-0eba690b3389} - - - {decf69bc-1143-4e7e-bf8c-a78201f541c0} - - - {c511e187-9ffa-40ec-8d8b-7d89048ed33e} - - - {9d8d84e4-347a-40d6-bea7-82919c544cdc} - - - {50aa51a9-ac6a-4f46-9920-4fcbb34cab31} - - - {35d8beb6-382f-4e05-a3f0-e21555076168} - - - {cfd9f17a-dcf5-4ab7-9a4d-f66b0a89a21b} - - - {1c96ea43-c29b-4d91-905f-9a80fe3a8ce3} - - - {be692687-c3d8-4ebf-9200-2325a2a7f5c1} - - - {6edbff29-bb0a-4a31-9d21-ac4904cf15db} - - - {38c626d1-54b4-4162-9650-755fb95da2e7} - - - {7caf3ffa-9430-49d4-86da-ef6fd3b952ec} - - - {ea5e3c91-ae7b-4984-8f67-a287dc4e985d} - - - {b8904687-7060-450e-8ac6-22b409acb0ff} - - - {bde6a2ee-9103-45ad-a03c-840405419d96} - - - {2ecb3b06-467c-4872-9df9-910752d5a0e5} - - - {75c19928-73ca-4451-ac27-7c87df9f5add} - - - {6623c7a9-1632-4776-bd26-e924d8bdc032} - - - {392e6638-a46c-463f-a76c-d80ea6dafb76} - - - {f5b473d1-ff89-4278-bc40-f842a5f25b31} - - - {90ffae6c-249f-40bb-b817-857136971b44} - - - {cada420a-1c49-4446-972e-b3e099773c53} - - - {f829702a-28db-47eb-95ca-c424ec052101} - - - {1b77ab20-2528-42c9-931b-4de4d6b872fb} - - - {c3930ca9-93d7-401c-898f-523590a400c9} - - - {aa0bf861-fe20-4cad-b78b-cf037bcb1f2c} - - - {d429fed0-d5d8-49a3-a7c8-2f7c45cf789f} - - - {d81d9186-d538-4a6e-95aa-1c84bbd0c2a4} - - - {8647b869-c857-4e75-97ab-726cf7e041c5} - - - {d443fa37-c49e-47d2-9697-928617752438} - - - {c83b2fa0-f69b-40e7-90e2-1a9c02ed2681} - - - {2075e31f-992a-4ec5-8671-2c4e244f1285} - - - {d9d114cf-2268-4954-93f8-97a9dad6bdd4} - - - {3cb2e2cf-48be-4c9c-96b8-0c843c73e0fa} - - - {fb46a60d-1f3a-4818-aefd-cba41e514245} - - - {0120c344-0bc0-4a1d-b82c-df7945f46189} - - - {e23e2a6e-491b-4200-9bf7-d355a1ee695b} - - - {b491a249-26b8-4814-9f50-2c3a57018c56} - - - - - - - - - - Controls - - - Controls - - - Controls - - - Converters - - - Converters - - - Converters - - - Converters - - - Converters - - - Converters - - - - - - - - - - - - - - - - Controls - - - - - Controls - - - - - Controls - - - Controls - - - Views\StateTriggers - - - - - Controls - - - Common - - - Controls - - - - Views\StateTriggers - - - Controls - - - Controls - - - - - Controls - - - - Views\GraphingCalculator - - - - Utils - - - Common - - - - - - - - - Common - - - Controls - - - Controls - - - Controls - - - Converters - - - Converters - - - Converters - - - Converters - - - Converters - - - Converters - - - - - - - - - - - - - - - - Controls - - - - - Controls - - - - - Controls - - - Controls - - - Views\StateTriggers - - - - - Controls - - - Common - - - Controls - - - Views\StateTriggers - - - - Controls - - - Controls - - - - - Controls - - - - Views\GraphingCalculator - - - - Utils - - - Common - - - Common - - - - - - - - - - - - - - Views - - - Views - - - Views - - - Views - - - Views - - - Views - - - Views - - - Views - - - Views - - - Views - - - Views - - - Views - - - Views - - - - Views - - - Views - - - Views - - - Views - - - Views - - - Views\GraphingCalculator - - - Views\GraphingCalculator - - - Views - - - Views\GraphingCalculator - - - Views\GraphingCalculator - - - Views\GraphingCalculator - - - - Views\StateTriggers - - - - - Resources\en-US - - - Resources\en-US - - - Resources\az-Latn-az - - - Resources\af-za - - - Resources\uk-ua - - - Resources\ar-sa - - - Resources\vi-vn - - - Resources\am-et - - - Resources\tr-tr - - - Resources\zh-tw - - - Resources\bg-bg - - - Resources\ca-es - - - Resources\cs-cz - - - Resources\da-dk - - - Resources\zh-cn - - - Resources\ta-in - - - Resources\sv-se - - - Resources\te-in - - - Resources\th-th - - - Resources\et-ee - - - Resources\es-mx - - - Resources\sk-sk - - - Resources\el-gr - - - Resources\en-gb - - - Resources\de-de - - - Resources\sr-latn-rs - - - Resources\es-es - - - Resources\sq-al - - - Resources\fil-ph - - - Resources\ru-ru - - - Resources\fr-ca - - - Resources\sl-sI - - - Resources\nl-nl - - - Resources\nb-no - - - Resources\eu-es - - - Resources\fa-ir - - - Resources\fi-fi - - - Resources\ro-ro - - - Resources\he-il - - - Resources\fr-fr - - - Resources\gl-es - - - Resources\pl-pl - - - Resources\pt-pt - - - Resources\hi-in - - - Resources\pt-br - - - Resources\lt-lt - - - Resources\ms-my - - - Resources\it-it - - - Resources\mk-mk - - - Resources\lv-lv - - - Resources\ja-jp - - - Resources\id-id - - - Resources\ml-in - - - Resources\hr-hr - - - Resources\kn-in - - - Resources\hu-hu - - - Resources\is-is - - - Resources\ko-kr - - - Resources\lo-la - - - Resources\km-kh - - - Resources\kk-kz - - - Resources\es-mx - - - Resources\fr-ca - - - Resources\is-is - - - Resources\km-kh - - - Resources\id-id - - - Resources\it-it - - - Resources\ms-my - - - Resources\hr-hr - - - Resources\mk-mk - - - Resources\ml-in - - - Resources\lv-lv - - - Resources\fr-fr - - - Resources\hi-in - - - Resources\lt-lt - - - Resources\hu-hu - - - Resources\he-il - - - Resources\pt-pt - - - Resources\gl-es - - - Resources\pt-br - - - Resources\eu-es - - - Resources\fa-ir - - - Resources\nb-no - - - Resources\pl-pl - - - Resources\nl-nl - - - Resources\et-ee - - - Resources\sq-al - - - Resources\ro-ro - - - Resources\ru-ru - - - Resources\lo-la - - - Resources\fil-ph - - - Resources\sk-sk - - - Resources\fi-fi - - - Resources\de-de - - - Resources\sr-latn-rs - - - Resources\en-gb - - - Resources\te-in - - - Resources\kn-in - - - Resources\th-th - - - Resources\ta-in - - - Resources\es-es - - - Resources\sv-se - - - Resources\el-gr - - - Resources\uk-ua - - - Resources\zh-cn - - - Resources\vi-vn - - - Resources\tr-tr - - - Resources\sl-sI - - - Resources\zh-tw - - - Resources\cs-cz - - - Resources\da-dk - - - Resources\bg-bg - - - Resources\ca-es - - - Resources\az-Latn-az - - - Resources\af-za - - - Resources\ar-sa - - - Resources\kk-kz - - - Resources\am-et - - - Resources\ja-jp - - - Resources\ko-kr - - - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - - - Assets - - - - - - - - - - \ No newline at end of file diff --git a/src/Calculator/Common/AlwaysSelectedCollectionView.cs b/src/Calculator/Common/AlwaysSelectedCollectionView.cs new file mode 100644 index 00000000..0847a5ab --- /dev/null +++ b/src/Calculator/Common/AlwaysSelectedCollectionView.cs @@ -0,0 +1,260 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Collections; +using System.Collections.Generic; +using Windows.Foundation; +using Windows.Foundation.Collections; +using Windows.UI.Xaml.Data; + +namespace CalculatorApp +{ + namespace Common + { + sealed class AlwaysSelectedCollectionView : Windows.UI.Xaml.DependencyObject, Windows.UI.Xaml.Data.ICollectionView + { + internal AlwaysSelectedCollectionView(IList source) + { + m_currentPosition = -1; + m_source = source; + + var observable = source as Windows.UI.Xaml.Interop.IBindableObservableVector; + if (observable != null) + { + observable.VectorChanged += OnSourceBindableVectorChanged; + } + } + + public bool MoveCurrentTo(object item) + { + if (item != null) + { + int newCurrentPosition = m_source.IndexOf(item); + if (newCurrentPosition != -1) + { + m_currentPosition = newCurrentPosition; + CurrentChanged?.Invoke(this, null); + 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 < m_source.Count) + { + Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, new Windows.UI.Core.DispatchedHandler(() => + { + CurrentChanged?.Invoke(this, null); + })).AsTask().Wait(); + } + return false; + } + + public bool MoveCurrentToPosition(int index) + { + if (index < 0 || index >= m_source.Count) + { + return false; + } + + m_currentPosition = index; + CurrentChanged?.Invoke(this, null); + return true; + } + + #region no implementations + + public bool MoveCurrentToFirst() + { + throw new NotImplementedException(); + } + + public bool MoveCurrentToLast() + { + throw new NotImplementedException(); + } + + public bool MoveCurrentToNext() + { + throw new NotImplementedException(); + } + + public bool MoveCurrentToPrevious() + { + throw new NotImplementedException(); + } + + public IAsyncOperation LoadMoreItemsAsync(uint count) + { + throw new NotImplementedException(); + } + + public void Insert(int index, object item) + { + throw new NotImplementedException(); + } + + public void RemoveAt(int index) + { + throw new NotImplementedException(); + } + + public void Add(object item) + { + throw new NotImplementedException(); + } + + public void Clear() + { + throw new NotImplementedException(); + } + + public bool Contains(object item) + { + throw new NotImplementedException(); + } + + public void CopyTo(object[] array, int arrayIndex) + { + throw new NotImplementedException(); + } + + public bool Remove(object item) + { + throw new NotImplementedException(); + } + + public bool IsReadOnly => throw new NotImplementedException(); + + #endregion no implementations + + public object this[int index] + { + get + { + return m_source[index]; + } + + set => throw new NotImplementedException(); + } + + public int Count + { + get + { + return m_source.Count; + } + } + + public IObservableVector CollectionGroups + { + get + { + return (IObservableVector)new List(); + } + } + + public object CurrentItem + { + get + { + if (m_currentPosition >= 0 && m_currentPosition < m_source.Count) + { + return m_source[m_currentPosition]; + } + return null; + } + } + + public int CurrentPosition + { + get + { + return m_currentPosition; + } + } + + public bool HasMoreItems + { + get + { + return false; + } + } + + public bool IsCurrentAfterLast + { + get + { + return m_currentPosition >= m_source.Count; + } + } + + public bool IsCurrentBeforeFirst + { + get + { + return m_currentPosition < 0; + } + } + + public int IndexOf(object item) + { + return m_source.IndexOf(item); + } + + public IEnumerator GetEnumerator() + { + throw new NotImplementedException(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + throw new NotImplementedException(); + } + + // Event handlers + void OnSourceBindableVectorChanged(Windows.UI.Xaml.Interop.IBindableObservableVector source, object e) + { + Windows.Foundation.Collections.IVectorChangedEventArgs args = (Windows.Foundation.Collections.IVectorChangedEventArgs)e; + VectorChanged?.Invoke(this, args); + } + + public event EventHandler CurrentChanged; + public event VectorChangedEventHandler VectorChanged; + public event CurrentChangingEventHandler CurrentChanging + { + add => throw new NotImplementedException(); + remove => throw new NotImplementedException(); + } + + IList m_source; + int m_currentPosition; + } + + public sealed class AlwaysSelectedCollectionViewConverter : Windows.UI.Xaml.Data.IValueConverter + { + public AlwaysSelectedCollectionViewConverter() + { + } + + public object Convert(object value, Type targetType, object parameter, string language) + { + var result = value as IList; + if (result != null) + { + return new AlwaysSelectedCollectionView(result); + } + return Windows.UI.Xaml.DependencyProperty.UnsetValue; // Can't convert + } + + public object ConvertBack(object value, Type targetType, object parameter, string language) + { + return Windows.UI.Xaml.DependencyProperty.UnsetValue; + } + } + } +} + diff --git a/src/Calculator/Common/AlwaysSelectedCollectionView.h b/src/Calculator/Common/AlwaysSelectedCollectionView.h deleted file mode 100644 index 35d40095..00000000 --- a/src/Calculator/Common/AlwaysSelectedCollectionView.h +++ /dev/null @@ -1,293 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -#pragma once - -namespace CalculatorApp -{ - namespace Common - { - ref class AlwaysSelectedCollectionView sealed : public Windows::UI::Xaml::DependencyObject, public Windows::UI::Xaml::Data::ICollectionView - { - internal : AlwaysSelectedCollectionView(Windows::UI::Xaml::Interop::IBindableVector ^ source) - : m_currentPosition(-1) - { - m_source = source; - - Windows::UI::Xaml::Interop::IBindableObservableVector ^ observable = - dynamic_cast(source); - if (observable) - { - observable->VectorChanged += ref new Windows::UI::Xaml::Interop::BindableVectorChangedEventHandler( - this, &AlwaysSelectedCollectionView::OnSourceBindableVectorChanged); - } - } - - private: - // ICollectionView - // Not implemented methods - virtual Windows::Foundation::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 ^ CollectionGroups { - virtual Windows::Foundation::Collections::IObservableVector< - Platform::Object ^> ^ get() = Windows::UI::Xaml::Data::ICollectionView::CollectionGroups::get - { - return ref new Platform::Collections::Vector(); - } - } property bool HasMoreItems - { - virtual bool get() = Windows::UI::Xaml::Data::ICollectionView::HasMoreItems::get - { - return false; - } - } - - // Implementented 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(m_source->Size)) - { - this->Dispatcher->RunAsync(Windows::UI::Core::CoreDispatcherPriority::Normal, ref new Windows::UI::Core::DispatchedHandler([this]() { - m_currentChanged(this, nullptr); - })); - } - return false; - } - - virtual bool MoveCurrentToPosition(int index) = Windows::UI::Xaml::Data::ICollectionView::MoveCurrentToPosition - { - if (index < 0 || index >= static_cast(m_source->Size)) - { - return false; - } - - m_currentPosition = index; - m_currentChanged(this, nullptr); - return true; - } - - property Platform::Object^ CurrentItem - { - virtual Platform::Object^ get() = Windows::UI::Xaml::Data::ICollectionView::CurrentItem::get - { - if (m_currentPosition >= 0 && m_currentPosition < static_cast(m_source->Size)) - { - return m_source->GetAt(m_currentPosition); - } - return nullptr; - } - } - - property int 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 - { - return m_currentPosition >= static_cast(m_source->Size); - } - } - - property bool IsCurrentBeforeFirst - { - virtual bool get() = Windows::UI::Xaml::Data::ICollectionView::IsCurrentBeforeFirst::get - { - return m_currentPosition < 0; - } - } - - event Windows::Foundation::EventHandler^ CurrentChanged - { - virtual Windows::Foundation::EventRegistrationToken add(Windows::Foundation::EventHandler^ handler) = Windows::UI::Xaml::Data::ICollectionView::CurrentChanged::add - { - return m_currentChanged += handler; - } - virtual void remove(Windows::Foundation::EventRegistrationToken token) = Windows::UI::Xaml::Data::ICollectionView::CurrentChanged::remove - { - m_currentChanged -= token; - } - } - event Windows::UI::Xaml::Data::CurrentChangingEventHandler^ CurrentChanging - { - virtual Windows::Foundation::EventRegistrationToken add(Windows::UI::Xaml::Data::CurrentChangingEventHandler^ handler) = Windows::UI::Xaml::Data::ICollectionView::CurrentChanging::add - { - return m_currentChanging += handler; - } - virtual void remove(Windows::Foundation::EventRegistrationToken token) = Windows::UI::Xaml::Data::ICollectionView::CurrentChanging::remove - { - m_currentChanging -= token; - } - } - - // IVector - // Not implemented methods - virtual void Append(Platform::Object^ /*item*/) = Windows::Foundation::Collections::IVector::Append - { - throw ref new Platform::NotImplementedException(); - } - virtual void Clear() = Windows::Foundation::Collections::IVector::Clear - { - throw ref new Platform::NotImplementedException(); - } - virtual unsigned int GetMany( - unsigned int /*startIndex*/, - Platform::WriteOnlyArray ^ /*items*/) = Windows::Foundation::Collections::IVector::GetMany - { - throw ref new Platform::NotImplementedException(); - } - virtual Windows::Foundation::Collections::IVectorView ^ 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::InsertAt - { - throw ref new Platform::NotImplementedException(); - } - virtual void RemoveAt(unsigned int /*index*/) = Windows::Foundation::Collections::IVector::RemoveAt - { - throw ref new Platform::NotImplementedException(); - } - virtual void RemoveAtEnd() = Windows::Foundation::Collections::IVector::RemoveAtEnd - { - throw ref new Platform::NotImplementedException(); - } - virtual void - ReplaceAll(const Platform::Array ^ /*items*/) = Windows::Foundation::Collections::IVector::ReplaceAll - { - throw ref new Platform::NotImplementedException(); - } - virtual void SetAt(unsigned int /*index*/, Platform::Object ^ /*item*/) = Windows::Foundation::Collections::IVector::SetAt - { - throw ref new Platform::NotImplementedException(); - } - - // Implemented methods - virtual Platform::Object ^ GetAt(unsigned int index) = Windows::Foundation::Collections::IVector::GetAt - { - return m_source->GetAt(index); - } - - virtual bool IndexOf(Platform::Object ^ item, unsigned int* index) = Windows::Foundation::Collections::IVector::IndexOf - { - return m_source->IndexOf(item, index); - } - - property unsigned int Size - { - virtual unsigned int get() = Windows::Foundation::Collections::IVector::Size::get - { - return m_source->Size; - } - } - - // IObservableVector - event Windows::Foundation::Collections::VectorChangedEventHandler^ VectorChanged - { - virtual Windows::Foundation::EventRegistrationToken add(Windows::Foundation::Collections::VectorChangedEventHandler^ handler) = Windows::Foundation::Collections::IObservableVector::VectorChanged::add - { - return m_vectorChanged += handler; - } - virtual void remove(Windows::Foundation::EventRegistrationToken token) = Windows::Foundation::Collections::IObservableVector::VectorChanged::remove - { - m_vectorChanged -= token; - } - } - - // IIterable - // Not implemented - virtual Windows::Foundation::Collections::IIterator^ First() = Windows::Foundation::Collections::IIterable::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(e); - m_vectorChanged(this, args); - } - - Windows::UI::Xaml::Interop::IBindableVector ^ m_source; - int m_currentPosition; - event Windows::Foundation::EventHandler ^ m_currentChanged; - event Windows::UI::Xaml::Data::CurrentChangingEventHandler ^ m_currentChanging; - event Windows::Foundation::Collections::VectorChangedEventHandler ^ 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(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; - } - }; - } -} diff --git a/src/Calculator/Common/AppLifecycleLogger.cpp b/src/Calculator/Common/AppLifecycleLogger.cpp deleted file mode 100644 index 78d21e39..00000000 --- a/src/Calculator/Common/AppLifecycleLogger.cpp +++ /dev/null @@ -1,149 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -#include "pch.h" -#include "AppLifecycleLogger.h" -#include - -using namespace std; -using namespace winrt; -using namespace winrt::Windows::ApplicationModel; -using namespace winrt::Windows::ApplicationModel::Background; -using namespace winrt::Windows::ApplicationModel::Core; -using namespace winrt::Windows::Foundation::Diagnostics; -using namespace winrt::Windows::UI::ViewManagement; - -namespace CalculatorApp -{ -#ifdef SEND_DIAGNOSTICS - // c.f. WINEVENT_KEYWORD_RESERVED_63-56 0xFF00000000000000 // Bits 63-56 - channel keywords - // c.f. WINEVENT_KEYWORD_* 0x00FF000000000000 // Bits 55-48 - system-reserved keywords - constexpr int64_t MICROSOFT_KEYWORD_LEVEL_1 = 0x0000800000000000; // Bit 47 - constexpr int64_t MICROSOFT_KEYWORD_LEVEL_2 = 0x0000400000000000; // Bit 46 - constexpr int64_t MICROSOFT_KEYWORD_LEVEL_3 = 0x0000200000000000; // Bit 45 - 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 diagnostics - constexpr int64_t MICROSOFT_KEYWORD_LEVEL_1 = 0; - constexpr int64_t MICROSOFT_KEYWORD_LEVEL_2 = 0; - constexpr int64_t MICROSOFT_KEYWORD_LEVEL_3 = 0; - constexpr int64_t MICROSOFT_KEYWORD_RESERVED_44 = 0; -#endif - -#pragma region TraceLogger setup and cleanup - - AppLifecycleLogger::AppLifecycleLogger() - : m_appLifecycleProvider( - L"Microsoft.Windows.AppLifeCycle", - LoggingChannelOptions(GUID{ 0x4f50731a, 0x89cf, 0x4782, 0xb3, 0xe0, 0xdc, 0xe8, 0xc9, 0x4, 0x76, 0xba }), - GUID{ 0xef00584a, 0x2655, 0x462c, 0xbc, 0x24, 0xe7, 0xde, 0x63, 0xe, 0x7f, 0xbf }) // Unique provider ID {EF00584A-2655-462C-BC24-E7DE630E7FBF} - { - } - - AppLifecycleLogger::~AppLifecycleLogger() - { - } - - AppLifecycleLogger& AppLifecycleLogger::GetInstance() - { - static AppLifecycleLogger s_selfInstance; - return s_selfInstance; - } - - bool AppLifecycleLogger::GetTraceLoggingProviderEnabled() const - { - return m_appLifecycleProvider.Enabled(); - } - -#pragma region Tracing methods - void AppLifecycleLogger::LogAppLifecycleEvent(hstring const& eventName, LoggingFields const& fields) const - { - m_appLifecycleProvider.LogEvent( - eventName, fields, LoggingLevel::Information, LoggingOptions(MICROSOFT_KEYWORD_LEVEL_3 | WINEVENT_KEYWORD_RESPONSE_TIME)); - } -#pragma endregion - - void AppLifecycleLogger::LaunchUIResponsive() const - { - if (!GetTraceLoggingProviderEnabled()) - return; - - LoggingFields fields{}; - PopulateAppInfo(fields); - LogAppLifecycleEvent(L"ModernAppLaunch_UIResponsive", fields); - } - - void AppLifecycleLogger::LaunchVisibleComplete() const - { - if (!GetTraceLoggingProviderEnabled()) - return; - - LoggingFields fields{}; - PopulateAppInfo(fields); - LogAppLifecycleEvent(L"ModernAppLaunch_VisibleComplete", fields); - } - - void AppLifecycleLogger::ResumeUIResponsive() const - { - if (!GetTraceLoggingProviderEnabled()) - return; - - LoggingFields fields{}; - PopulateAppInfo(fields); - LogAppLifecycleEvent(L"ModernAppResume_UIResponsive", fields); - } - - void AppLifecycleLogger::ResumeVisibleComplete() const - { - if (!GetTraceLoggingProviderEnabled()) - return; - - LoggingFields fields{}; - PopulateAppInfo(fields); - LogAppLifecycleEvent(L"ModernAppResume_VisibleComplete", fields); - } - - void AppLifecycleLogger::ResizeUIResponsive() const - { - ResizeUIResponsive(ApplicationView::GetForCurrentView().Id()); - } - - void AppLifecycleLogger::ResizeUIResponsive(int32_t viewId) const - { - if (!GetTraceLoggingProviderEnabled()) - return; - - LoggingFields fields{}; - PopulateAppInfo(fields); - fields.AddInt32(L"ViewId", viewId); - LogAppLifecycleEvent(L"ModernAppResize_UIResponsive", fields); - } - - void AppLifecycleLogger::ResizeVisibleComplete() const - { - ResizeVisibleComplete(ApplicationView::GetForCurrentView().Id()); - } - - void AppLifecycleLogger::ResizeVisibleComplete(int32_t viewId) const - { - if (!GetTraceLoggingProviderEnabled()) - return; - - LoggingFields fields{}; - PopulateAppInfo(fields); - fields.AddInt32(L"ViewId", viewId); - LogAppLifecycleEvent(L"ModernAppResize_VisibleComplete", fields); - } - - void AppLifecycleLogger::PopulateAppInfo(LoggingFields& fields) const - { - auto appId = CoreApplication::Id(); - auto aumId = Package::Current().Id().FamilyName() + L"!" + appId; - auto packageFullName = Package::Current().Id().FullName(); - auto psmKey = Package::Current().Id().FullName() + L"+" + appId; - - fields.AddString(L"AumId", aumId); - fields.AddString(L"PackageFullName", packageFullName); - fields.AddString(L"PsmKey", psmKey); - } -} diff --git a/src/Calculator/Common/AppLifecycleLogger.cs b/src/Calculator/Common/AppLifecycleLogger.cs new file mode 100644 index 00000000..dff96f33 --- /dev/null +++ b/src/Calculator/Common/AppLifecycleLogger.cs @@ -0,0 +1,152 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; + +using CalculatorApp.ViewModel.Common; +using Windows.ApplicationModel; +using Windows.ApplicationModel.Core; +using Windows.Foundation.Diagnostics; +using Windows.UI.ViewManagement; + +namespace CalculatorApp +{ + static public partial class Globals + { +#if SEND_DIAGNOSTICS + // c.f. WINEVENT_KEYWORD_RESERVED_63-56 0xFF00000000000000 // Bits 63-56 - channel keywords + // c.f. WINEVENT_KEYWORD_* 0x00FF000000000000 // Bits 55-48 - system-reserved keywords + public const long MICROSOFT_KEYWORD_LEVEL_1 = 0x0000800000000000; // Bit 47 + public const long MICROSOFT_KEYWORD_LEVEL_2 = 0x0000400000000000; // Bit 46 + public const long MICROSOFT_KEYWORD_LEVEL_3 = 0x0000200000000000; // Bit 45 + public const long 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 diagnostics + public const long MICROSOFT_KEYWORD_LEVEL_1 = 0; + public const long MICROSOFT_KEYWORD_LEVEL_2 = 0; + public const long MICROSOFT_KEYWORD_LEVEL_3 = 0; + public const long MICROSOFT_KEYWORD_RESERVED_44 = 0; +#endif + } + + class AppLifecycleLogger + { + public static AppLifecycleLogger GetInstance() + { + return s_selfInstance.Value; + } + + public bool GetTraceLoggingProviderEnabled() + { + return m_appLifecycleProvider.Enabled; + } + + public void LaunchUIResponsive() + { + if (!GetTraceLoggingProviderEnabled()) + return; + + LoggingFields fields = new LoggingFields(); + PopulateAppInfo(fields); + LogAppLifecycleEvent("ModernAppLaunch_UIResponsive", fields); + } + + public void LaunchVisibleComplete() + { + if (!GetTraceLoggingProviderEnabled()) + return; + + LoggingFields fields = new LoggingFields(); + PopulateAppInfo(fields); + LogAppLifecycleEvent("ModernAppLaunch_VisibleComplete", fields); + } + + public void ResumeUIResponsive() + { + if (!GetTraceLoggingProviderEnabled()) + return; + + LoggingFields fields = new LoggingFields(); + PopulateAppInfo(fields); + LogAppLifecycleEvent("ModernAppResume_UIResponsive", fields); + } + + public void ResumeVisibleComplete() + { + if (!GetTraceLoggingProviderEnabled()) + return; + + LoggingFields fields = new LoggingFields(); + PopulateAppInfo(fields); + LogAppLifecycleEvent("ModernAppResume_VisibleComplete", fields); + } + + public void ResizeUIResponsive() + { + ResizeUIResponsive(ApplicationView.GetForCurrentView().Id); + } + + public void ResizeVisibleComplete() + { + ResizeVisibleComplete(ApplicationView.GetForCurrentView().Id); + } + + public void ResizeUIResponsive(int viewId) + { + if (!GetTraceLoggingProviderEnabled()) + return; + + LoggingFields fields = new LoggingFields(); + PopulateAppInfo(fields); + fields.AddInt32("ViewId", viewId); + LogAppLifecycleEvent("ModernAppResize_UIResponsive", fields); + } + + public void ResizeVisibleComplete(int viewId) + { + if (!GetTraceLoggingProviderEnabled()) + return; + + LoggingFields fields = new LoggingFields(); + PopulateAppInfo(fields); + fields.AddInt32("ViewId", viewId); + LogAppLifecycleEvent("ModernAppResize_VisibleComplete", fields); + } + + // Make the object construction private to allow singleton access to this class + private AppLifecycleLogger() + { + m_appLifecycleProvider = new LoggingChannel( + "Microsoft.Windows.AppLifeCycle", + new LoggingChannelOptions(new Guid(0x4f50731a, 0x89cf, 0x4782, 0xb3, 0xe0, 0xdc, 0xe8, 0xc9, 0x4, 0x76, 0xba)), + new Guid(0xef00584a, 0x2655, 0x462c, 0xbc, 0x24, 0xe7, 0xde, 0x63, 0xe, 0x7f, 0xbf)); + } + + // 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 diagnostics and pass + // TraceLoggingKeyword(MICROSOFT_KEYWORD_LEVEL_3) accordingly c) Should accept a variable number of additional data arguments if needed + private void LogAppLifecycleEvent(string eventName, LoggingFields fields) + { + m_appLifecycleProvider.LogEvent( + eventName, fields, LoggingLevel.Information, new LoggingOptions(Globals.MICROSOFT_KEYWORD_LEVEL_3 | Utilities.GetConst_WINEVENT_KEYWORD_RESPONSE_TIME())); + } + + private void PopulateAppInfo(LoggingFields fields) + { + var appId = CoreApplication.Id; + var aumId = Package.Current.Id.FamilyName + "!" + appId; + var packageFullName = Package.Current.Id.FullName; + var psmKey = Package.Current.Id.FullName + "+" + appId; + + fields.AddString("AumId", aumId); + fields.AddString("PackageFullName", packageFullName); + fields.AddString("PsmKey", psmKey); + } + + private LoggingChannel m_appLifecycleProvider; + private static readonly Lazy s_selfInstance = new Lazy(() => new AppLifecycleLogger(), true); + } +} + diff --git a/src/Calculator/Common/AppLifecycleLogger.h b/src/Calculator/Common/AppLifecycleLogger.h deleted file mode 100644 index fdb8702e..00000000 --- a/src/Calculator/Common/AppLifecycleLogger.h +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -#pragma once - -namespace CalculatorApp -{ - class AppLifecycleLogger - { - public: - AppLifecycleLogger(AppLifecycleLogger const&) = delete; - AppLifecycleLogger const& operator=(AppLifecycleLogger const&) = delete; - ~AppLifecycleLogger(); - static AppLifecycleLogger& GetInstance(); - bool GetTraceLoggingProviderEnabled() const; - - void LaunchUIResponsive() const; - void LaunchVisibleComplete() const; - void ResumeUIResponsive() const; - void ResumeVisibleComplete() const; - - void ResizeUIResponsive() const; - void ResizeVisibleComplete() const; - void ResizeUIResponsive(int32_t viewId) const; - void ResizeVisibleComplete(int32_t viewId) const; - - private: - // Make the object construction private to allow singleton access to this class - AppLifecycleLogger(); - - // 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 diagnostics and pass - // TraceLoggingKeyword(MICROSOFT_KEYWORD_LEVEL_3) accordingly c) Should accept a variable number of additional data arguments if needed - void LogAppLifecycleEvent(winrt::hstring const& eventName, winrt::Windows::Foundation::Diagnostics::LoggingFields const& fields) const; - void PopulateAppInfo(winrt::Windows::Foundation::Diagnostics::LoggingFields& fields) const; - - winrt::Windows::Foundation::Diagnostics::LoggingChannel m_appLifecycleProvider; - }; -} diff --git a/src/Calculator/Common/KeyboardShortcuManager.cs b/src/Calculator/Common/KeyboardShortcuManager.cs new file mode 100644 index 00000000..d6579767 --- /dev/null +++ b/src/Calculator/Common/KeyboardShortcuManager.cs @@ -0,0 +1,832 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using CalculatorApp.ViewModel; +using CalculatorApp.ViewModel.Common; +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Diagnostics; +using System.Linq; +using Windows.Foundation.Collections; +using Windows.UI.Core; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; +using Windows.UI.Xaml.Controls.Primitives; +using MUXC = Microsoft.UI.Xaml.Controls; + +namespace CalculatorApp +{ + namespace Common + { + static partial class KeyboardShortcutManagerLocals + { + // Lights up all of the buttons in the given range + // The range is defined by a pair of iterators + static public void LightUpButtons(IEnumerable buttons) + { + foreach (var button in buttons) + { + var btn = button.Target as ButtonBase; + if (btn != null && btn.IsEnabled) + { + LightUpButton(btn); + } + } + } + + static public void LightUpButton(ButtonBase button) + { + // If the button is a toggle button then we don't need + // to change the UI of the button + if (button is ToggleButton) + { + return; + } + + // The button will go into the visual Pressed state with this call + VisualStateManager.GoToState(button, "Pressed", true); + + // 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 + var timer = new DispatcherTimer(); + TimeSpan lightUpTime = TimeSpan.FromMilliseconds(50); // 5e5 100-ns + timer.Interval = lightUpTime; + + var timerWeakReference = new WeakReference(timer); + var buttonWeakReference = new WeakReference(button); + timer.Tick += (sender, args) => + { + var btn = buttonWeakReference.Target as ButtonBase; + if (btn != null) + { + VisualStateManager.GoToState(button, "Normal", true); + } + + var tmr = timerWeakReference.Target as DispatcherTimer; + if (tmr != null) + { + tmr.Stop(); + } + }; + timer.Start(); + } + + // Looks for the first button reference that it can resolve + // and execute its command. + // NOTE: It is assumed that all buttons associated with a particular + // key have the same command + static public void RunFirstEnabledButtonCommand(IEnumerable buttons) + { + foreach (var button in buttons) + { + var btn = button.Target as ButtonBase; + if (btn != null && btn.IsEnabled) + { + RunButtonCommand(btn); + break; + } + } + } + + static public void RunButtonCommand(ButtonBase button) + { + if (button.IsEnabled) + { + var command = button.Command; + var parameter = button.CommandParameter; + if (command != null && command.CanExecute(parameter)) + { + command.Execute(parameter); + } + + var radio = (button as RadioButton); + if (radio != null) + { + radio.IsChecked = true; + return; + } + + var toggle = (button as ToggleButton); + if (toggle != null) + { + toggle.IsChecked = !(toggle.IsChecked != null && toggle.IsChecked.Value); + return; + } + } + } + } + + public sealed class KeyboardShortcutManager : DependencyObject + { + public KeyboardShortcutManager() + { + } + + public static readonly DependencyProperty CharacterProperty = + DependencyProperty.RegisterAttached( + "Character", + typeof(string), + typeof(KeyboardShortcutManager), + new PropertyMetadata(string.Empty, (sender, args) => + { + OnCharacterPropertyChanged(sender, (string)args.OldValue, (string)args.NewValue); + })); + + public static string GetCharacter(DependencyObject target) + { + return (string)target.GetValue(CharacterProperty); + } + + public static void SetCharacter(DependencyObject target, string value) + { + target.SetValue(CharacterProperty, value); + } + + public static readonly DependencyProperty VirtualKeyProperty = + DependencyProperty.RegisterAttached( + "VirtualKey", + typeof(MyVirtualKey), + typeof(KeyboardShortcutManager), + new PropertyMetadata(default(MyVirtualKey), (sender, args) => + { + OnVirtualKeyPropertyChanged(sender, (MyVirtualKey)args.OldValue, (MyVirtualKey)args.NewValue); + })); + + public static MyVirtualKey GetVirtualKey(DependencyObject target) + { + return (MyVirtualKey)target.GetValue(VirtualKeyProperty); + } + + public static void SetVirtualKey(DependencyObject target, MyVirtualKey value) + { + target.SetValue(VirtualKeyProperty, value); + } + + public static readonly DependencyProperty VirtualKeyControlChordProperty = + DependencyProperty.RegisterAttached( + "VirtualKey", + typeof(MyVirtualKey), + typeof(KeyboardShortcutManager), + new PropertyMetadata(default(MyVirtualKey), (sender, args) => + { + OnVirtualKeyControlChordPropertyChanged(sender, (MyVirtualKey)args.OldValue, (MyVirtualKey)args.NewValue); + })); + + public static MyVirtualKey GetVirtualKeyControlChord(DependencyObject target) + { + return (MyVirtualKey)target.GetValue(VirtualKeyControlChordProperty); + } + + public static void SetVirtualKeyControlChord(DependencyObject target, MyVirtualKey value) + { + target.SetValue(VirtualKeyControlChordProperty, value); + } + + public static readonly DependencyProperty VirtualKeyShiftChordProperty = + DependencyProperty.RegisterAttached( + "VirtualKey", + typeof(MyVirtualKey), + typeof(KeyboardShortcutManager), + new PropertyMetadata(default(MyVirtualKey), (sender, args) => + { + OnVirtualKeyShiftChordPropertyChanged(sender, (MyVirtualKey)args.OldValue, (MyVirtualKey)args.NewValue); + })); + + public static MyVirtualKey GetVirtualKeyShiftChord(DependencyObject target) + { + return (MyVirtualKey)target.GetValue(VirtualKeyShiftChordProperty); + } + + public static void SetVirtualKeyShiftChord(DependencyObject target, MyVirtualKey value) + { + target.SetValue(VirtualKeyShiftChordProperty, value); + } + + public static readonly DependencyProperty VirtualKeyAltChordProperty = + DependencyProperty.RegisterAttached( + "VirtualKey", + typeof(MyVirtualKey), + typeof(KeyboardShortcutManager), + new PropertyMetadata(default(MyVirtualKey), (sender, args) => + { + OnVirtualKeyAltChordPropertyChanged(sender, (MyVirtualKey)args.OldValue, (MyVirtualKey)args.NewValue); + })); + + public static MyVirtualKey GetVirtualKeyAltChord(DependencyObject target) + { + return (MyVirtualKey)target.GetValue(VirtualKeyAltChordProperty); + } + + public static void SetVirtualKeyAltChord(DependencyObject target, MyVirtualKey value) + { + target.SetValue(VirtualKeyAltChordProperty, value); + } + + public static readonly DependencyProperty VirtualKeyControlShiftChordProperty = + DependencyProperty.RegisterAttached( + "VirtualKey", + typeof(MyVirtualKey), + typeof(KeyboardShortcutManager), + new PropertyMetadata(default(MyVirtualKey), (sender, args) => + { + OnVirtualKeyControlShiftChordPropertyChanged(sender, (MyVirtualKey)args.OldValue, (MyVirtualKey)args.NewValue); + })); + + public static MyVirtualKey GetVirtualKeyControlShiftChord(DependencyObject target) + { + return (MyVirtualKey)target.GetValue(VirtualKeyControlShiftChordProperty); + } + + public static void SetVirtualKeyControlShiftChord(DependencyObject target, MyVirtualKey value) + { + target.SetValue(VirtualKeyControlShiftChordProperty, value); + } + + internal static void Initialize() + { + var coreWindow = Window.Current.CoreWindow; + coreWindow.CharacterReceived += OnCharacterReceivedHandler; + coreWindow.KeyDown += OnKeyDownHandler; + coreWindow.Dispatcher.AcceleratorKeyActivated += OnAcceleratorKeyActivated; + KeyboardShortcutManager.RegisterNewAppViewId(); + } + + // 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 + // we need to be able to ignore it (looking at e->Handled isn't sufficient + // because that always returns true). + // The onlyOnce flag is used to indicate whether we should only ignore the + // next escape, or keep ignoring until you explicitly HonorEscape. + public static void IgnoreEscape(bool onlyOnce) + { + // Writer lock for the static maps + lock (s_keyboardShortcutMapLockMutex) + { + int viewId = Utilities.GetWindowId(); + + if (s_ignoreNextEscape.ContainsKey(viewId)) + { + s_ignoreNextEscape[viewId] = true; + } + + if (s_keepIgnoringEscape.ContainsKey(viewId)) + { + s_keepIgnoringEscape[viewId] = !onlyOnce; + } + } + } + + public static void HonorEscape() + { + // Writer lock for the static maps + lock (s_keyboardShortcutMapLockMutex) + { + int viewId = Utilities.GetWindowId(); + + if (s_ignoreNextEscape.ContainsKey(viewId)) + { + s_ignoreNextEscape[viewId] = false; + } + + if (s_keepIgnoringEscape.ContainsKey(viewId)) + { + s_keepIgnoringEscape[viewId] = false; + } + } + } + + public static void HonorShortcuts(bool allow) + { + // Writer lock for the static maps + lock (s_keyboardShortcutMapLockMutex) + { + int viewId = Utilities.GetWindowId(); + + if (s_fHonorShortcuts.ContainsKey(viewId)) + { + if (s_fDisableShortcuts.ContainsKey(viewId)) + { + if (s_fDisableShortcuts[viewId]) + { + s_fHonorShortcuts[viewId] = false; + return; + } + } + + s_fHonorShortcuts[viewId] = allow; + } + } + } + + public static void DisableShortcuts(bool disable) + { + int viewId = Utilities.GetWindowId(); + + if (s_fDisableShortcuts.ContainsKey(viewId)) + { + s_fDisableShortcuts[viewId] = disable; + } + + HonorShortcuts(!disable); + } + + public static void UpdateDropDownState(bool isOpen) + { + int viewId = Utilities.GetWindowId(); + + if (s_IsDropDownOpen.ContainsKey(viewId)) + { + s_IsDropDownOpen[viewId] = isOpen; + } + } + + public static void RegisterNewAppViewId() + { + // Writer lock for the static maps + lock (s_keyboardShortcutMapLockMutex) + { + int appViewId = Utilities.GetWindowId(); + + // Check if the View Id has already been registered + if (!s_characterForButtons.ContainsKey(appViewId)) + { + s_characterForButtons.Add(appViewId, new SortedDictionary>()); + } + + if (!s_virtualKey.ContainsKey(appViewId)) + { + s_virtualKey.Add(appViewId, new SortedDictionary>()); + } + + if (!s_VirtualKeyControlChordsForButtons.ContainsKey(appViewId)) + { + s_VirtualKeyControlChordsForButtons.Add(appViewId, new SortedDictionary>()); + } + + if (!s_VirtualKeyShiftChordsForButtons.ContainsKey(appViewId)) + { + s_VirtualKeyShiftChordsForButtons.Add(appViewId, new SortedDictionary>()); + } + + if (!s_VirtualKeyAltChordsForButtons.ContainsKey(appViewId)) + { + s_VirtualKeyAltChordsForButtons.Add(appViewId, new SortedDictionary>()); + } + + if (!s_VirtualKeyControlShiftChordsForButtons.ContainsKey(appViewId)) + { + s_VirtualKeyControlShiftChordsForButtons.Add(appViewId, new SortedDictionary>()); + } + + s_IsDropDownOpen[appViewId] = false; + s_ignoreNextEscape[appViewId] = false; + s_keepIgnoringEscape[appViewId] = false; + s_fHonorShortcuts[appViewId] = true; + s_fDisableShortcuts[appViewId] = false; + } + } + + public static void OnWindowClosed(int viewId) + { + // Writer lock for the static maps + lock (s_keyboardShortcutMapLockMutex) + { + s_characterForButtons.Remove(viewId); + + s_virtualKey.Remove(viewId); + s_VirtualKeyControlChordsForButtons.Remove(viewId); + s_VirtualKeyShiftChordsForButtons.Remove(viewId); + s_VirtualKeyAltChordsForButtons.Remove(viewId); + s_VirtualKeyControlShiftChordsForButtons.Remove(viewId); + + s_IsDropDownOpen.Remove(viewId); + s_ignoreNextEscape.Remove(viewId); + s_keepIgnoringEscape.Remove(viewId); + s_fHonorShortcuts.Remove(viewId); + s_fDisableShortcuts.Remove(viewId); + } + } + + private static void OnCharacterPropertyChanged(DependencyObject target, string oldValue, string newValue) + { + // Writer lock for the static maps + lock (s_keyboardShortcutMapLockMutex) + { + var button = (target as ButtonBase); + + int viewId = Utilities.GetWindowId(); + if (s_characterForButtons.TryGetValue(viewId, out var iterViewMap)) + { + if (!string.IsNullOrEmpty(oldValue)) + { + iterViewMap.Remove(oldValue[0]); + } + + if (!string.IsNullOrEmpty(newValue)) + { + if (newValue == ".") + { + char decSep = LocalizationSettings.GetInstance().GetDecimalSeparator(); + Insert(iterViewMap, decSep, new WeakReference(button)); + } + else + { + Insert(iterViewMap, newValue[0], new WeakReference(button)); + } + } + } + else + { + s_characterForButtons.Add(viewId, new SortedDictionary>()); + + if (newValue == ".") + { + char decSep = LocalizationSettings.GetInstance().GetDecimalSeparator(); + Insert(s_characterForButtons[viewId], decSep, new WeakReference(button)); + } + else + { + Insert(s_characterForButtons[viewId], newValue[0], new WeakReference(button)); + } + } + } + } + + private static void OnVirtualKeyPropertyChanged(DependencyObject target, MyVirtualKey oldValue, MyVirtualKey newValue) + { + // Writer lock for the static maps + lock (s_keyboardShortcutMapLockMutex) + { + var button = ((ButtonBase)target); + + int viewId = Utilities.GetWindowId(); + + // Check if the View Id has already been registered + if (s_virtualKey.TryGetValue(viewId, out var iterViewMap)) + { + Insert(iterViewMap, newValue, new WeakReference(button)); + } + else + { + // If the View Id is not already registered, then register it and make the entry + s_virtualKey.Add(viewId, new SortedDictionary>()); + Insert(s_virtualKey[viewId], newValue, new WeakReference(button)); + } + } + } + + private static void OnVirtualKeyControlChordPropertyChanged(DependencyObject target, MyVirtualKey oldValue, MyVirtualKey newValue) + { + // Writer lock for the static maps + lock (s_keyboardShortcutMapLockMutex) + { + Control control = (target as ButtonBase); + + if (control == null) + { + // Handling Ctrl+E shortcut for Date Calc, target would be NavigationView^ in that case + control = (target as MUXC.NavigationView); + } + + int viewId = Utilities.GetWindowId(); + + // Check if the View Id has already been registered + if (s_VirtualKeyControlChordsForButtons.TryGetValue(viewId, out var iterViewMap)) + { + Insert(iterViewMap, newValue, new WeakReference(control)); + } + else + { + // If the View Id is not already registered, then register it and make the entry + s_VirtualKeyControlChordsForButtons.Add(viewId, new SortedDictionary>()); + Insert(s_VirtualKeyControlChordsForButtons[viewId], newValue, new WeakReference(control)); + } + } + } + + private static void OnVirtualKeyShiftChordPropertyChanged(DependencyObject target, MyVirtualKey oldValue, MyVirtualKey newValue) + { + // Writer lock for the static maps + lock (s_keyboardShortcutMapLockMutex) + { + var button = (target as ButtonBase); + + int viewId = Utilities.GetWindowId(); + + // Check if the View Id has already been registered + if (s_VirtualKeyShiftChordsForButtons.TryGetValue(viewId, out var iterViewMap)) + { + Insert(iterViewMap, newValue, new WeakReference(button)); + } + else + { + // If the View Id is not already registered, then register it and make the entry + s_VirtualKeyShiftChordsForButtons.Add(viewId, new SortedDictionary>()); + Insert(s_VirtualKeyShiftChordsForButtons[viewId], newValue, new WeakReference(button)); + } + } + } + + private static void OnVirtualKeyAltChordPropertyChanged(DependencyObject target, MyVirtualKey oldValue, MyVirtualKey newValue) + { + // Writer lock for the static maps + lock (s_keyboardShortcutMapLockMutex) + { + MUXC.NavigationView navView = (target as MUXC.NavigationView); + + int viewId = Utilities.GetWindowId(); + + // Check if the View Id has already been registered + if (s_VirtualKeyAltChordsForButtons.TryGetValue(viewId, out var iterViewMap)) + { + Insert(iterViewMap, newValue, new WeakReference(navView)); + } + else + { + // If the View Id is not already registered, then register it and make the entry + s_VirtualKeyAltChordsForButtons.Add(viewId, new SortedDictionary>()); + Insert(s_VirtualKeyAltChordsForButtons[viewId], newValue, new WeakReference(navView)); + } + } + } + + private static void OnVirtualKeyControlShiftChordPropertyChanged(DependencyObject target, MyVirtualKey oldValue, MyVirtualKey newValue) + { + // Writer lock for the static maps + lock (s_keyboardShortcutMapLockMutex) + { + var button = (target as ButtonBase); + + int viewId = Utilities.GetWindowId(); + + // Check if the View Id has already been registered + if (s_VirtualKeyControlShiftChordsForButtons.TryGetValue(viewId, out var iterViewMap)) + { + Insert(iterViewMap, newValue, new WeakReference(button)); + } + else + { + // If the View Id is not already registered, then register it and make the entry + s_VirtualKeyControlShiftChordsForButtons.Add(viewId, new SortedDictionary>()); + Insert(s_VirtualKeyControlShiftChordsForButtons[viewId], newValue, new WeakReference(button)); + } + } + } + + // 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. + private static void OnCharacterReceivedHandler(CoreWindow sender, CharacterReceivedEventArgs args) + { + int viewId = Utilities.GetWindowId(); + bool hit = s_fHonorShortcuts.TryGetValue(viewId, out var currentHonorShortcuts); + + if (!hit || currentHonorShortcuts) + { + char character = ((char)args.KeyCode); + var buttons = EqualRange(s_characterForButtons[viewId], character); + KeyboardShortcutManagerLocals.RunFirstEnabledButtonCommand(buttons); + + KeyboardShortcutManagerLocals.LightUpButtons(buttons); + } + } + + private static void OnKeyDownHandler(CoreWindow sender, KeyEventArgs args) + { + if (args.Handled) + { + return; + } + + var key = args.VirtualKey; + int viewId = Utilities.GetWindowId(); + + bool isControlKeyPressed = (Window.Current.CoreWindow.GetKeyState(Windows.System.VirtualKey.Control) & CoreVirtualKeyStates.Down) == CoreVirtualKeyStates.Down; + bool isShiftKeyPressed = (Window.Current.CoreWindow.GetKeyState(Windows.System.VirtualKey.Shift) & CoreVirtualKeyStates.Down) == CoreVirtualKeyStates.Down; + bool isAltKeyPressed = (Window.Current.CoreWindow.GetKeyState(Windows.System.VirtualKey.Menu) & CoreVirtualKeyStates.Down) == CoreVirtualKeyStates.Down; + + // Handle Ctrl + E for DateCalculator + if ((key == Windows.System.VirtualKey.E) && isControlKeyPressed && !isShiftKeyPressed && !isAltKeyPressed) + { + var lookupMap = GetCurrentKeyDictionary(isControlKeyPressed, isShiftKeyPressed, false); + if (lookupMap == null) + { + return; + } + + var buttons = EqualRange(lookupMap, (MyVirtualKey)key); + var navView = buttons.ElementAt(0).Target as MUXC.NavigationView; + var appViewModel = (navView.DataContext as ApplicationViewModel); + appViewModel.Mode = ViewMode.Date; + var categoryName = AppResourceProvider.GetInstance().GetResourceString("DateCalculationModeText"); + appViewModel.CategoryName = categoryName; + + var menuItems = ((ObservableCollection)navView.MenuItemsSource); + var flatIndex = NavCategory.GetFlatIndex(ViewMode.Date); + navView.SelectedItem = menuItems[flatIndex]; + return; + } + + if (s_ignoreNextEscape.TryGetValue(viewId, out var currentIgnoreNextEscape)) + { + if (currentIgnoreNextEscape && key == Windows.System.VirtualKey.Escape) + { + if (s_keepIgnoringEscape.TryGetValue(viewId, out var currentKeepIgnoringEscape)) + { + if (!currentKeepIgnoringEscape) + { + HonorEscape(); + } + return; + } + } + } + + if (s_fHonorShortcuts.TryGetValue(viewId, out var currentHonorShortcuts)) + { + if (currentHonorShortcuts) + { + var myVirtualKey = key; + var lookupMap = GetCurrentKeyDictionary(isControlKeyPressed, isShiftKeyPressed, isAltKeyPressed); + if (lookupMap == null) + { + return; + } + + var buttons = EqualRange(lookupMap, (MyVirtualKey)myVirtualKey); + if (buttons.Count() <= 0) + { + return; + } + + KeyboardShortcutManagerLocals.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 + //var currentIsDropDownOpen = s_IsDropDownOpen.find(viewId); + if (!s_IsDropDownOpen.TryGetValue(viewId, out var currentIsDropDownOpen) || !currentIsDropDownOpen) + { + // Do not Light Up Buttons when Ctrl+C, Ctrl+V, Ctrl+Insert or Shift+Insert is pressed + if (!(isControlKeyPressed && (key == Windows.System.VirtualKey.C || key == Windows.System.VirtualKey.V || key == Windows.System.VirtualKey.Insert)) + & !(isShiftKeyPressed && (key == Windows.System.VirtualKey.Insert))) + { + KeyboardShortcutManagerLocals.LightUpButtons(buttons); + } + } + } + } + } + + private static void OnAcceleratorKeyActivated(CoreDispatcher dispatcher, AcceleratorKeyEventArgs args) + { + if (args.KeyStatus.IsKeyReleased) + { + var key = args.VirtualKey; + bool altPressed = args.KeyStatus.IsMenuKeyDown; + + // If the Alt/Menu key is not pressed then we don't care about the key anymore + if (!altPressed) + { + return; + } + + bool controlKeyPressed = (Window.Current.CoreWindow.GetKeyState(Windows.System.VirtualKey.Control) & CoreVirtualKeyStates.Down) == CoreVirtualKeyStates.Down; + // Ctrl is pressed in addition to alt, this means Alt Gr is intended. do not navigate. + if (controlKeyPressed) + { + return; + } + + bool shiftKeyPressed = (Window.Current.CoreWindow.GetKeyState(Windows.System.VirtualKey.Shift) & CoreVirtualKeyStates.Down) == CoreVirtualKeyStates.Down; + var lookupMap = GetCurrentKeyDictionary(controlKeyPressed, shiftKeyPressed, altPressed); + if (lookupMap != null) + { + var listItems = EqualRange(lookupMap, (MyVirtualKey)key); + foreach (var itemRef in listItems) + { + var item = itemRef.Target as MUXC.NavigationView; + if (item != null) + { + var navView = (MUXC.NavigationView)item; + + var menuItems = ((ObservableCollection)navView.MenuItemsSource); + if (menuItems != null) + { + var vm = (navView.DataContext as ApplicationViewModel); + if (null != vm) + { + ViewMode toMode = NavCategory.GetViewModeForVirtualKey(((MyVirtualKey)key)); + var nvi = (menuItems[NavCategory.GetFlatIndex(toMode)] as MUXC.NavigationViewItem); + if (nvi != null && nvi.IsEnabled && NavCategory.IsValidViewMode(toMode)) + { + vm.Mode = toMode; + navView.SelectedItem = nvi; + } + } + } + break; + } + } + } + } + } + + private static SortedDictionary> GetCurrentKeyDictionary(bool controlKeyPressed, bool shiftKeyPressed, bool altPressed) + { + int viewId = Utilities.GetWindowId(); + + if (controlKeyPressed) + { + if (altPressed) + { + return null; + } + else + { + if (shiftKeyPressed) + { + return s_VirtualKeyControlShiftChordsForButtons[viewId]; + } + else + { + return s_VirtualKeyControlChordsForButtons[viewId]; + } + } + } + else + { + if (altPressed) + { + if (!shiftKeyPressed) + { + return s_VirtualKeyAltChordsForButtons[viewId]; + } + else + { + return null; + } + } + else + { + if (shiftKeyPressed) + { + return s_VirtualKeyShiftChordsForButtons[viewId]; + } + else + { + return s_virtualKey[viewId]; + } + } + } + } + + // EqualRange is a helper function to pick a range from std::multimap. + private static IEnumerable EqualRange(SortedDictionary> source, TKey key) + { + Debug.Assert(source != null); + if (source.TryGetValue(key, out List items)) + { + return items; + } + else + { + return Enumerable.Empty(); + } + } + + // Insert is a helper function to insert a pair into std::multimap. + private static void Insert(SortedDictionary> dest, Tkey key, TValue value) + { + if (dest.TryGetValue(key, out List items)) + { + items.Add(value); + } + else + { + items = new List { value }; + dest.Add(key, items); + } + } + + private static SortedDictionary>> s_characterForButtons = new SortedDictionary>>(); + private static SortedDictionary>> s_virtualKey = new SortedDictionary>>(); + private static SortedDictionary>> s_VirtualKeyControlChordsForButtons = new SortedDictionary>>(); + private static SortedDictionary>> s_VirtualKeyShiftChordsForButtons = new SortedDictionary>>(); + private static SortedDictionary>> s_VirtualKeyAltChordsForButtons = new SortedDictionary>>(); + private static SortedDictionary>> s_VirtualKeyControlShiftChordsForButtons = new SortedDictionary>>(); + + private static SortedDictionary s_IsDropDownOpen = new SortedDictionary(); + private static SortedDictionary s_ignoreNextEscape = new SortedDictionary(); + private static SortedDictionary s_keepIgnoringEscape = new SortedDictionary(); + private static SortedDictionary s_fHonorShortcuts = new SortedDictionary(); + private static SortedDictionary s_fDisableShortcuts = new SortedDictionary(); + + //private static Concurrency.reader_writer_lock s_keyboardShortcutMapLock; + private static readonly object s_keyboardShortcutMapLockMutex = new object(); + } + } +} + diff --git a/src/Calculator/Common/KeyboardShortcutManager.cpp b/src/Calculator/Common/KeyboardShortcutManager.cpp deleted file mode 100644 index 96e5e8f4..00000000 --- a/src/Calculator/Common/KeyboardShortcutManager.cpp +++ /dev/null @@ -1,692 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -#include "pch.h" -#include "KeyboardShortcutManager.h" -#include "CalcViewModel/Common/AppResourceProvider.h" -#include "CalcViewModel/ApplicationViewModel.h" -#include "CalcViewModel/Common/LocalizationSettings.h" - -using namespace Concurrency; -using namespace Platform; -using namespace std; -using namespace chrono; -using namespace Windows::ApplicationModel::Resources; -using namespace Windows::UI::Xaml; -using namespace Windows::UI::Xaml::Controls; -using namespace Windows::Foundation; -using namespace Windows::Foundation::Collections; -using namespace Windows::UI::Core; -using namespace Windows::UI::Xaml::Controls::Primitives; -using namespace Windows::System; -using namespace Utils; -using namespace CalculatorApp; -using namespace CalculatorApp::Common; -using namespace CalculatorApp::ViewModel; - -namespace MUXC = Microsoft::UI::Xaml::Controls; - -DEPENDENCY_PROPERTY_INITIALIZATION(KeyboardShortcutManager, Character); -DEPENDENCY_PROPERTY_INITIALIZATION(KeyboardShortcutManager, VirtualKey); -DEPENDENCY_PROPERTY_INITIALIZATION(KeyboardShortcutManager, VirtualKeyControlChord); -DEPENDENCY_PROPERTY_INITIALIZATION(KeyboardShortcutManager, VirtualKeyShiftChord); -DEPENDENCY_PROPERTY_INITIALIZATION(KeyboardShortcutManager, VirtualKeyAltChord); -DEPENDENCY_PROPERTY_INITIALIZATION(KeyboardShortcutManager, VirtualKeyControlShiftChord); - -map> KeyboardShortcutManager::s_characterForButtons; -map> KeyboardShortcutManager::s_virtualKey; -map> KeyboardShortcutManager::s_VirtualKeyControlChordsForButtons; -map> KeyboardShortcutManager::s_VirtualKeyShiftChordsForButtons; -map> KeyboardShortcutManager::s_VirtualKeyAltChordsForButtons; -map> KeyboardShortcutManager::s_VirtualKeyControlShiftChordsForButtons; - -map KeyboardShortcutManager::s_IsDropDownOpen; -map KeyboardShortcutManager::s_ignoreNextEscape; -map KeyboardShortcutManager::s_keepIgnoringEscape; -map KeyboardShortcutManager::s_fHonorShortcuts; -map KeyboardShortcutManager::s_fDisableShortcuts; -reader_writer_lock KeyboardShortcutManager::s_keyboardShortcutMapLock; - -namespace CalculatorApp -{ - namespace Common - { - // Lights up all of the buttons in the given range - // The range is defined by a pair of iterators - template - void LightUpButtons(const T& buttons) - { - auto iterator = buttons.first; - for (; iterator != buttons.second; ++iterator) - { - auto button = iterator->second.Resolve(); - if (button && button->IsEnabled) - { - LightUpButton(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(button)) - { - return; - } - - // The button will go into the visual Pressed state with this call - VisualStateManager::GoToState(button, "Pressed", true); - - // 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; - - WeakReference timerWeakReference(timer); - WeakReference buttonWeakReference(button); - timer->Tick += ref new EventHandler([buttonWeakReference, timerWeakReference](Object ^, Object ^) { - auto button = buttonWeakReference.Resolve(); - if (button) - { - VisualStateManager::GoToState(button, "Normal", true); - } - - // Cancel the timer after we're done so it only fires once - auto timer = timerWeakReference.Resolve(); - if (timer) - { - timer->Stop(); - } - }); - timer->Start(); - } - - // Looks for the first button reference that it can resolve - // and execute its command. - // NOTE: It is assumed that all buttons associated with a particular - // key have the same command - template - void RunFirstEnabledButtonCommand(const T& buttons) - { - auto buttonIterator = buttons.first; - for (; buttonIterator != buttons.second; ++buttonIterator) - { - auto button = buttonIterator->second.Resolve(); - if (button && button->IsEnabled) - { - RunButtonCommand(button); - break; - } - } - } - - void RunButtonCommand(ButtonBase ^ button) - { - if (button->IsEnabled) - { - auto command = button->Command; - auto parameter = button->CommandParameter; - if (command && command->CanExecute(parameter)) - { - command->Execute(parameter); - } - - auto radio = dynamic_cast(button); - if (radio) - { - radio->IsChecked = true; - return; - } - - auto toggle = dynamic_cast(button); - if (toggle) - { - toggle->IsChecked = !(toggle->IsChecked != nullptr && toggle->IsChecked->Value); - return; - } - } - } - } -} - -void KeyboardShortcutManager::IgnoreEscape(bool onlyOnce) -{ - // Writer lock for the static maps - reader_writer_lock::scoped_lock lock(s_keyboardShortcutMapLock); - - int viewId = Utils::GetWindowId(); - - if (s_ignoreNextEscape.find(viewId) != s_ignoreNextEscape.end()) - { - s_ignoreNextEscape[viewId] = true; - } - - if (s_keepIgnoringEscape.find(viewId) != s_keepIgnoringEscape.end()) - { - s_keepIgnoringEscape[viewId] = !onlyOnce; - } -} - -void KeyboardShortcutManager::HonorEscape() -{ - // Writer lock for the static maps - reader_writer_lock::scoped_lock lock(s_keyboardShortcutMapLock); - - int viewId = Utils::GetWindowId(); - - if (s_ignoreNextEscape.find(viewId) != s_ignoreNextEscape.end()) - { - s_ignoreNextEscape[viewId] = false; - } - - if (s_keepIgnoringEscape.find(viewId) != s_keepIgnoringEscape.end()) - { - s_keepIgnoringEscape[viewId] = false; - } -} - -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(target); - - int viewId = Utils::GetWindowId(); - auto iterViewMap = s_characterForButtons.find(viewId); - - if (iterViewMap != s_characterForButtons.end()) - { - if (oldValue) - { - iterViewMap->second.erase(oldValue->Data()[0]); - } - - if (newValue) - { - if (newValue == L".") - { - wchar_t decSep = LocalizationSettings::GetInstance().GetDecimalSeparator(); - iterViewMap->second.insert(make_pair(decSep, WeakReference(button))); - } - else - { - iterViewMap->second.insert(make_pair(newValue->Data()[0], WeakReference(button))); - } - } - } - else - { - s_characterForButtons.insert(make_pair(viewId, multimap())); - - if (newValue == L".") - { - wchar_t decSep = LocalizationSettings::GetInstance().GetDecimalSeparator(); - s_characterForButtons.find(viewId)->second.insert(make_pair(decSep, WeakReference(button))); - } - else - { - s_characterForButtons.find(viewId)->second.insert(make_pair(newValue->Data()[0], WeakReference(button))); - } - } -} - -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(target); - - int viewId = Utils::GetWindowId(); - auto iterViewMap = s_virtualKey.find(viewId); - - // Check if the View Id has already been registered - if (iterViewMap != s_virtualKey.end()) - { - iterViewMap->second.insert(make_pair(newValue, WeakReference(button))); - } - else - { - // If the View Id is not already registered, then register it and make the entry - s_virtualKey.insert(make_pair(viewId, multimap())); - s_virtualKey.find(viewId)->second.insert(make_pair(newValue, WeakReference(button))); - } -} - -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(target); - - if (control == nullptr) - { - // Handling Ctrl+E shortcut for Date Calc, target would be NavigationView^ in that case - control = safe_cast(target); - } - - int viewId = Utils::GetWindowId(); - auto iterViewMap = s_VirtualKeyControlChordsForButtons.find(viewId); - - // Check if the View Id has already been registered - if (iterViewMap != s_VirtualKeyControlChordsForButtons.end()) - { - iterViewMap->second.insert(make_pair(newValue, WeakReference(control))); - } - else - { - // If the View Id is not already registered, then register it and make the entry - s_VirtualKeyControlChordsForButtons.insert(make_pair(viewId, multimap())); - s_VirtualKeyControlChordsForButtons.find(viewId)->second.insert(make_pair(newValue, WeakReference(control))); - } -} - -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(target); - - int viewId = Utils::GetWindowId(); - auto iterViewMap = s_VirtualKeyShiftChordsForButtons.find(viewId); - - // Check if the View Id has already been registered - if (iterViewMap != s_VirtualKeyShiftChordsForButtons.end()) - { - iterViewMap->second.insert(make_pair(newValue, WeakReference(button))); - } - else - { - // If the View Id is not already registered, then register it and make the entry - s_VirtualKeyShiftChordsForButtons.insert(make_pair(viewId, multimap())); - s_VirtualKeyShiftChordsForButtons.find(viewId)->second.insert(make_pair(newValue, WeakReference(button))); - } -} - -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(target); - - int viewId = Utils::GetWindowId(); - auto iterViewMap = s_VirtualKeyAltChordsForButtons.find(viewId); - - // Check if the View Id has already been registered - if (iterViewMap != s_VirtualKeyAltChordsForButtons.end()) - { - iterViewMap->second.insert(make_pair(newValue, WeakReference(navView))); - } - else - { - // If the View Id is not already registered, then register it and make the entry - s_VirtualKeyAltChordsForButtons.insert(make_pair(viewId, multimap())); - s_VirtualKeyAltChordsForButtons.find(viewId)->second.insert(make_pair(newValue, WeakReference(navView))); - } -} - -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(target); - - int viewId = Utils::GetWindowId(); - auto iterViewMap = s_VirtualKeyControlShiftChordsForButtons.find(viewId); - - // Check if the View Id has already been registered - if (iterViewMap != s_VirtualKeyControlShiftChordsForButtons.end()) - { - iterViewMap->second.insert(make_pair(newValue, WeakReference(button))); - } - else - { - // If the View Id is not already registered, then register it and make the entry - s_VirtualKeyControlShiftChordsForButtons.insert(make_pair(viewId, multimap())); - s_VirtualKeyControlShiftChordsForButtons.find(viewId)->second.insert(make_pair(newValue, WeakReference(button))); - } -} - -// 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) -{ - int viewId = Utils::GetWindowId(); - auto currentHonorShortcuts = s_fHonorShortcuts.find(viewId); - - if (currentHonorShortcuts == s_fHonorShortcuts.end() || currentHonorShortcuts->second) - { - wchar_t character = static_cast(args->KeyCode); - auto buttons = s_characterForButtons.find(viewId)->second.equal_range(character); - RunFirstEnabledButtonCommand(buttons); - - LightUpButtons(buttons); - } -} - -const multimap* KeyboardShortcutManager::GetCurrentKeyDictionary(bool controlKeyPressed, bool shiftKeyPressed, bool altPressed) -{ - int viewId = Utils::GetWindowId(); - - if (controlKeyPressed) - { - if (altPressed) - { - return nullptr; - } - else - { - if (shiftKeyPressed) - { - return &s_VirtualKeyControlShiftChordsForButtons.find(viewId)->second; - } - else - { - return &s_VirtualKeyControlChordsForButtons.find(viewId)->second; - } - } - } - else - { - if (altPressed) - { - if (!shiftKeyPressed) - { - return &s_VirtualKeyAltChordsForButtons.find(viewId)->second; - } - else - { - return nullptr; - } - } - else - { - if (shiftKeyPressed) - { - return &s_VirtualKeyShiftChordsForButtons.find(viewId)->second; - } - else - { - return &s_virtualKey.find(viewId)->second; - } - } - } -} - -void KeyboardShortcutManager::OnKeyDownHandler(CoreWindow ^ sender, KeyEventArgs ^ args) -{ - if (args->Handled) - { - return; - } - - auto key = args->VirtualKey; - int viewId = Utils::GetWindowId(); - - const bool isControlKeyPressed = (Window::Current->CoreWindow->GetKeyState(VirtualKey::Control) & CoreVirtualKeyStates::Down) == CoreVirtualKeyStates::Down; - const bool isShiftKeyPressed = (Window::Current->CoreWindow->GetKeyState(VirtualKey::Shift) & CoreVirtualKeyStates::Down) == CoreVirtualKeyStates::Down; - const bool isAltKeyPressed = (Window::Current->CoreWindow->GetKeyState(VirtualKey::Menu) & CoreVirtualKeyStates::Down) == CoreVirtualKeyStates::Down; - - // Handle Ctrl + E for DateCalculator - if ((key == VirtualKey::E) && isControlKeyPressed && !isShiftKeyPressed && !isAltKeyPressed) - { - const auto lookupMap = GetCurrentKeyDictionary(isControlKeyPressed, isShiftKeyPressed, false); - if (lookupMap == nullptr) - { - return; - } - - auto buttons = lookupMap->equal_range(static_cast(key)); - auto navView = buttons.first->second.Resolve(); - auto appViewModel = safe_cast(navView->DataContext); - appViewModel->Mode = ViewMode::Date; - auto categoryName = AppResourceProvider::GetInstance()->GetResourceString(L"DateCalculationModeText"); - appViewModel->CategoryName = categoryName; - - auto menuItems = static_cast ^>(navView->MenuItemsSource); - auto flatIndex = NavCategory::GetFlatIndex(ViewMode::Date); - navView->SelectedItem = menuItems->GetAt(flatIndex); - return; - } - - auto currentIgnoreNextEscape = s_ignoreNextEscape.find(viewId); - if (currentIgnoreNextEscape != s_ignoreNextEscape.end()) - { - if (currentIgnoreNextEscape->second && key == VirtualKey::Escape) - { - auto currentKeepIgnoringEscape = s_keepIgnoringEscape.find(viewId); - - if (currentKeepIgnoringEscape != s_keepIgnoringEscape.end()) - { - if (!currentKeepIgnoringEscape->second) - { - HonorEscape(); - } - return; - } - } - } - - auto currentHonorShortcuts = s_fHonorShortcuts.find(viewId); - if (currentHonorShortcuts != s_fHonorShortcuts.end()) - { - if (currentHonorShortcuts->second) - { - const auto myVirtualKey = static_cast(key); - const auto lookupMap = GetCurrentKeyDictionary(isControlKeyPressed, isShiftKeyPressed, isAltKeyPressed); - if (lookupMap == nullptr) - { - return; - } - - auto buttons = lookupMap->equal_range(myVirtualKey); - if (buttons.first == buttons.second) - { - return; - } - - 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 - auto currentIsDropDownOpen = s_IsDropDownOpen.find(viewId); - if (currentIsDropDownOpen == s_IsDropDownOpen.end() || !currentIsDropDownOpen->second) - { - // Do not Light Up Buttons when Ctrl+C, Ctrl+V, Ctrl+Insert or Shift+Insert is pressed - if (!(isControlKeyPressed && (key == VirtualKey::C || key == VirtualKey::V || key == VirtualKey::Insert)) - && !(isShiftKeyPressed && (key == VirtualKey::Insert))) - { - LightUpButtons(buttons); - } - } - } - } -} - -void KeyboardShortcutManager::OnAcceleratorKeyActivated(CoreDispatcher ^, AcceleratorKeyEventArgs ^ args) -{ - if (args->KeyStatus.IsKeyReleased) - { - auto key = args->VirtualKey; - const bool altPressed = args->KeyStatus.IsMenuKeyDown; - - // If the Alt/Menu key is not pressed then we don't care about the key anymore - if (!altPressed) - { - return; - } - - const bool controlKeyPressed = - (Window::Current->CoreWindow->GetKeyState(VirtualKey::Control) & CoreVirtualKeyStates::Down) == CoreVirtualKeyStates::Down; - // Ctrl is pressed in addition to alt, this means Alt Gr is intended. do not navigate. - if (controlKeyPressed) - { - return; - } - - const bool shiftKeyPressed = (Window::Current->CoreWindow->GetKeyState(VirtualKey::Shift) & CoreVirtualKeyStates::Down) == CoreVirtualKeyStates::Down; - const auto lookupMap = GetCurrentKeyDictionary(controlKeyPressed, shiftKeyPressed, altPressed); - if (lookupMap != nullptr) - { - auto listItems = lookupMap->equal_range(static_cast(key)); - for (auto listIterator = listItems.first; listIterator != listItems.second; ++listIterator) - { - auto item = listIterator->second.Resolve(); - if (item != nullptr) - { - auto navView = safe_cast(item); - - auto menuItems = static_cast ^>(navView->MenuItemsSource); - if (menuItems != nullptr) - { - auto vm = safe_cast(navView->DataContext); - if (nullptr != vm) - { - ViewMode toMode = NavCategory::GetViewModeForVirtualKey(static_cast(key)); - auto nvi = dynamic_cast(menuItems->GetAt(NavCategory::GetFlatIndex(toMode))); - if (nvi && nvi->IsEnabled && NavCategory::IsValidViewMode(toMode)) - { - vm->Mode = toMode; - navView->SelectedItem = nvi; - } - } - } - break; - } - } - } - } -} - -void KeyboardShortcutManager::Initialize() -{ - auto coreWindow = Window::Current->CoreWindow; - coreWindow->CharacterReceived += - ref new TypedEventHandler(&KeyboardShortcutManager::OnCharacterReceivedHandler); - coreWindow->KeyDown += ref new TypedEventHandler(&KeyboardShortcutManager::OnKeyDownHandler); - coreWindow->Dispatcher->AcceleratorKeyActivated += - ref new TypedEventHandler(&KeyboardShortcutManager::OnAcceleratorKeyActivated); - - KeyboardShortcutManager::RegisterNewAppViewId(); -} - -void KeyboardShortcutManager::UpdateDropDownState(bool isOpen) -{ - int viewId = Utils::GetWindowId(); - - if (s_IsDropDownOpen.find(viewId) != s_IsDropDownOpen.end()) - { - s_IsDropDownOpen[viewId] = isOpen; - } -} - -void KeyboardShortcutManager::HonorShortcuts(bool allow) -{ - // Writer lock for the static maps - reader_writer_lock::scoped_lock lock(s_keyboardShortcutMapLock); - - int viewId = Utils::GetWindowId(); - - if (s_fHonorShortcuts.find(viewId) != s_fHonorShortcuts.end()) - { - if (s_fDisableShortcuts.find(viewId) != s_fDisableShortcuts.end()) - { - if (s_fDisableShortcuts[viewId]) - { - s_fHonorShortcuts[viewId] = false; - return; - } - } - - s_fHonorShortcuts[viewId] = allow; - } -} - -void KeyboardShortcutManager::RegisterNewAppViewId() -{ - // Writer lock for the static maps - reader_writer_lock::scoped_lock lock(s_keyboardShortcutMapLock); - - int appViewId = Utils::GetWindowId(); - - // Check if the View Id has already been registered - if (s_characterForButtons.find(appViewId) == s_characterForButtons.end()) - { - s_characterForButtons.insert(make_pair(appViewId, multimap())); - } - - if (s_virtualKey.find(appViewId) == s_virtualKey.end()) - { - s_virtualKey.insert(make_pair(appViewId, multimap())); - } - - if (s_VirtualKeyControlChordsForButtons.find(appViewId) == s_VirtualKeyControlChordsForButtons.end()) - { - s_VirtualKeyControlChordsForButtons.insert(make_pair(appViewId, multimap())); - } - - if (s_VirtualKeyShiftChordsForButtons.find(appViewId) == s_VirtualKeyShiftChordsForButtons.end()) - { - s_VirtualKeyShiftChordsForButtons.insert(make_pair(appViewId, multimap())); - } - - if (s_VirtualKeyAltChordsForButtons.find(appViewId) == s_VirtualKeyAltChordsForButtons.end()) - { - s_VirtualKeyAltChordsForButtons.insert(make_pair(appViewId, multimap())); - } - - if (s_VirtualKeyControlShiftChordsForButtons.find(appViewId) == s_VirtualKeyControlShiftChordsForButtons.end()) - { - s_VirtualKeyControlShiftChordsForButtons.insert(make_pair(appViewId, multimap())); - } - - s_IsDropDownOpen[appViewId] = false; - s_ignoreNextEscape[appViewId] = false; - s_keepIgnoringEscape[appViewId] = false; - s_fHonorShortcuts[appViewId] = true; - s_fDisableShortcuts[appViewId] = false; -} - -void KeyboardShortcutManager::OnWindowClosed(int viewId) -{ - // Writer lock for the static maps - reader_writer_lock::scoped_lock lock(s_keyboardShortcutMapLock); - - s_characterForButtons.erase(viewId); - - s_virtualKey.erase(viewId); - s_VirtualKeyControlChordsForButtons.erase(viewId); - s_VirtualKeyShiftChordsForButtons.erase(viewId); - s_VirtualKeyAltChordsForButtons.erase(viewId); - s_VirtualKeyControlShiftChordsForButtons.erase(viewId); - - s_IsDropDownOpen.erase(viewId); - s_ignoreNextEscape.erase(viewId); - s_keepIgnoringEscape.erase(viewId); - s_fHonorShortcuts.erase(viewId); - s_fDisableShortcuts.erase(viewId); -} - -void KeyboardShortcutManager::DisableShortcuts(bool disable) -{ - int viewId = Utils::GetWindowId(); - - if (s_fDisableShortcuts.find(viewId) != s_fDisableShortcuts.end()) - { - s_fDisableShortcuts[viewId] = disable; - } - - HonorShortcuts(!disable); -} diff --git a/src/Calculator/Common/KeyboardShortcutManager.h b/src/Calculator/Common/KeyboardShortcutManager.h deleted file mode 100644 index 1ca7e487..00000000 --- a/src/Calculator/Common/KeyboardShortcutManager.h +++ /dev/null @@ -1,87 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -#pragma once - -#include "CalcViewModel/Common/Utils.h" -#include "CalcViewModel/Common/MyVirtualKey.h" - -namespace CalculatorApp -{ - namespace Common - { - public - ref class KeyboardShortcutManager sealed - { - public: - KeyboardShortcutManager() - { - } - - DEPENDENCY_PROPERTY_OWNER(KeyboardShortcutManager); - - 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); - DEPENDENCY_PROPERTY_ATTACHED_WITH_CALLBACK(MyVirtualKey, VirtualKeyAltChord); - DEPENDENCY_PROPERTY_ATTACHED_WITH_CALLBACK(MyVirtualKey, VirtualKeyControlShiftChord); - - internal : - - 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 - // we need to be able to ignore it (looking at e->Handled isn't sufficient - // because that always returns true). - // The onlyOnce flag is used to indicate whether we should only ignore the - // next escape, or keep ignoring until you explicitly HonorEscape. - static void IgnoreEscape(bool onlyOnce); - static void HonorEscape(); - static void HonorShortcuts(bool allow); - static void DisableShortcuts(bool disable); - static void UpdateDropDownState(bool); - - 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 OnVirtualKeyPropertyChanged(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 OnVirtualKeyAltChordPropertyChanged(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 OnAcceleratorKeyActivated(Windows::UI::Core::CoreDispatcher ^, Windows::UI::Core::AcceleratorKeyEventArgs ^ args); - static const std::multimap* - KeyboardShortcutManager::GetCurrentKeyDictionary(bool controlKeyPressed, bool shiftKeyPressed, bool altPressed); - - private: - static std::map> s_characterForButtons; - static std::map> s_virtualKey; - static std::map> s_VirtualKeyControlChordsForButtons; - static std::map> s_VirtualKeyShiftChordsForButtons; - static std::map> s_VirtualKeyAltChordsForButtons; - static std::map> s_VirtualKeyControlShiftChordsForButtons; - - static std::map s_IsDropDownOpen; - static std::map s_ignoreNextEscape; - static std::map s_keepIgnoringEscape; - static std::map s_fHonorShortcuts; - static std::map s_fDisableShortcuts; - - static Concurrency::reader_writer_lock s_keyboardShortcutMapLock; - }; - } -} diff --git a/src/Calculator/Common/ValidatingConverters.cs b/src/Calculator/Common/ValidatingConverters.cs new file mode 100644 index 00000000..32d3ce0f --- /dev/null +++ b/src/Calculator/Common/ValidatingConverters.cs @@ -0,0 +1,65 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +using System; + +namespace CalculatorApp +{ + namespace Common + { + public sealed class ValidSelectedItemConverter : Windows.UI.Xaml.Data.IValueConverter + { + public ValidSelectedItemConverter() + { } + + public object Convert(object value, Type targetType, object parameter, string language) + { + // Pass through as we don't want to change the value from the source + return value; + } + + public object ConvertBack(object value, Type targetType, object parameter, string language) + { + if (value != null) + { + return value; + } + + // Stop the binding if the object is nullptr + return Windows.UI.Xaml.DependencyProperty.UnsetValue; + } + } + + public sealed class ValidSelectedIndexConverter : Windows.UI.Xaml.Data.IValueConverter + { + public ValidSelectedIndexConverter() + { } + + public object Convert(object value, Type targetType, object parameter, string language) + { + // Pass through as we don't want to change the value from the source + return value; + } + + public object ConvertBack(object value, Type targetType, object parameter, string language) + { + // The value to be valid has to be a boxed int32 value + // extract that value and ensure it is valid, ie >= 0 + if (value != null) + { + var box = value as Windows.Foundation.IPropertyValue; + if (box != null && box.Type == Windows.Foundation.PropertyType.Int32) + { + 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; + } + } + } +} + diff --git a/src/Calculator/Common/ValidatingConverters.h b/src/Calculator/Common/ValidatingConverters.h deleted file mode 100644 index bc168502..00000000 --- a/src/Calculator/Common/ValidatingConverters.h +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -#pragma once - -namespace CalculatorApp -{ - namespace Common - { - public - ref class ValidSelectedItemConverter sealed : public Windows::UI::Xaml::Data::IValueConverter - { - 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; - } - - 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) - { - 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(value); - if (box && box->Type == Windows::Foundation::PropertyType::Int32) - { - 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; - } - }; - } -} diff --git a/src/Calculator/Common/ViewState.cpp b/src/Calculator/Common/ViewState.cpp deleted file mode 100644 index 63a5d30e..00000000 --- a/src/Calculator/Common/ViewState.cpp +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -#include "pch.h" -#include "ViewState.h" - -namespace CalculatorApp -{ - namespace ViewState - { - Platform::StringReference Snap(L"Snap"); - Platform::StringReference DockedView(L"DockedView"); - - bool IsValidViewState(Platform::String ^ viewState) - { - return viewState->Equals(ViewState::Snap) || viewState->Equals(ViewState::DockedView); - } - } -} diff --git a/src/Calculator/Common/ViewState.cs b/src/Calculator/Common/ViewState.cs new file mode 100644 index 00000000..20eb41e9 --- /dev/null +++ b/src/Calculator/Common/ViewState.cs @@ -0,0 +1,17 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +namespace CalculatorApp +{ + static class ViewState + { + public static readonly string Snap = "Snap"; + public static readonly string DockedView = "DockedView"; + + public static bool IsValidViewState(string viewState) + { + return (viewState == Snap) || (viewState == DockedView); + } + } +} + diff --git a/src/Calculator/Common/ViewState.h b/src/Calculator/Common/ViewState.h deleted file mode 100644 index 0a103d09..00000000 --- a/src/Calculator/Common/ViewState.h +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -#pragma once - -namespace CalculatorApp -{ - namespace ViewState - { - extern Platform::StringReference Snap; - extern Platform::StringReference DockedView; - - bool IsValidViewState(Platform::String ^ viewState); - } -} diff --git a/src/Calculator/Controls/CalculationResult.cpp b/src/Calculator/Controls/CalculationResult.cpp deleted file mode 100644 index c2542f10..00000000 --- a/src/Calculator/Controls/CalculationResult.cpp +++ /dev/null @@ -1,419 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -#include "pch.h" -#include "CalculationResult.h" -#include "CalculationResultAutomationPeer.h" -#include "CalcViewModel/Common/LocalizationSettings.h" - -using namespace CalculatorApp; -using namespace CalculatorApp::Controls; -using namespace CalculatorApp::Common; - -using namespace Platform; -using namespace Windows::Devices::Input; -using namespace Windows::Foundation; -using namespace Windows::Foundation::Collections; -using namespace Windows::UI::Xaml; -using namespace Windows::UI::Xaml::Controls; -using namespace Windows::UI::Xaml::Controls::Primitives; -using namespace Windows::UI::Xaml::Data; -using namespace Windows::UI::Xaml::Input; -using namespace Windows::UI::Xaml::Media; -using namespace Windows::UI::Xaml::Navigation; -using namespace Windows::UI::Xaml::Automation; -using namespace Windows::UI::Xaml::Automation::Peers; -using namespace std; - -DEPENDENCY_PROPERTY_INITIALIZATION(CalculationResult, IsActive); -DEPENDENCY_PROPERTY_INITIALIZATION(CalculationResult, MinFontSize); -DEPENDENCY_PROPERTY_INITIALIZATION(CalculationResult, MaxFontSize); -DEPENDENCY_PROPERTY_INITIALIZATION(CalculationResult, DisplayMargin); -DEPENDENCY_PROPERTY_INITIALIZATION(CalculationResult, DisplayValue); -DEPENDENCY_PROPERTY_INITIALIZATION(CalculationResult, IsInError); -DEPENDENCY_PROPERTY_INITIALIZATION(CalculationResult, IsOperatorCommand); - -#define SCALEFACTOR 0.357143 -#define SMALLHEIGHTSCALEFACTOR 0 -#define HEIGHTCUTOFF 100 -#define INCREMENTOFFSET 1 -#define MAXFONTINCREMENT 5 -#define WIDTHTOFONTSCALAR 0.0556513 -#define WIDTHTOFONTOFFSET 3 -#define WIDTHCUTOFF 50 -#define FONTTOLERANCE 0.001 -#define SCROLL_RATIO 0.7 - -// We need a safety margin to guarantee we correctly always show/hide ScrollLeft and ScrollRight buttons when necessary. -// In rare cases, ScrollViewer::HorizontalOffset is a little low by a few (sub)pixels when users scroll to one of the extremity -// and no events are launched when they scroll again in the same direction -#define SCROLL_BUTTONS_APPROXIMATION_RANGE 4 - -CalculationResult::CalculationResult() - : m_isScalingText(false) - , m_haveCalculatedMax(false) -{ -} - -Platform::String ^ CalculationResult::GetRawDisplayValue() -{ - return LocalizationSettings::GetInstance().RemoveGroupSeparators(DisplayValue); -} - -void CalculationResult::OnApplyTemplate() -{ - if (m_textContainer) - { - if (m_textContainerLayoutChangedToken.Value != 0) - { - m_textContainer->LayoutUpdated -= m_textContainerLayoutChangedToken; - m_textContainerLayoutChangedToken.Value = 0; - } - if (m_textContainerSizeChangedToken.Value != 0) - { - m_textContainer->SizeChanged -= m_textContainerSizeChangedToken; - m_textContainerSizeChangedToken.Value = 0; - } - if (m_textContainerViewChangedToken.Value != 0) - { - m_textContainer->ViewChanged -= m_textContainerViewChangedToken; - m_textContainerViewChangedToken.Value = 0; - } - } - - if (m_textBlock != nullptr && m_textBlockSizeChangedToken.Value != 0) - { - m_textBlock->SizeChanged -= m_textBlockSizeChangedToken; - m_textBlockSizeChangedToken.Value = 0; - } - - if (m_scrollLeft != nullptr && m_scrollLeftClickToken.Value != 0) - { - m_scrollLeft->Click -= m_scrollLeftClickToken; - m_scrollLeftClickToken.Value = 0; - } - - if (m_scrollRight != nullptr && m_scrollRightClickToken.Value != 0) - { - m_scrollRight->Click -= m_scrollRightClickToken; - m_scrollRightClickToken.Value = 0; - } - - m_textContainer = dynamic_cast(GetTemplateChild("TextContainer")); - if (m_textContainer) - { - // We want to know when the size of the container changes so - // we can rescale the textbox - m_textContainerSizeChangedToken = m_textContainer->SizeChanged += ref new SizeChangedEventHandler(this, &CalculationResult::OnTextContainerSizeChanged); - - m_textContainerViewChangedToken = m_textContainer->ViewChanged += - ref new Windows::Foundation::EventHandler( - this, &CalculatorApp::Controls::CalculationResult::OnTextContainerOnViewChanged); - - m_textContainerLayoutChangedToken = m_textContainer->LayoutUpdated += - ref new EventHandler(this, &CalculationResult::OnTextContainerLayoutUpdated); - - m_textContainer->ChangeView(m_textContainer->ExtentWidth - m_textContainer->ViewportWidth, nullptr, nullptr); - m_scrollLeft = dynamic_cast(GetTemplateChild("ScrollLeft")); - if (m_scrollLeft) - { - m_scrollLeftClickToken = m_scrollLeft->Click += ref new RoutedEventHandler(this, &CalculationResult::OnScrollLeftClick); - } - m_scrollRight = dynamic_cast(GetTemplateChild("ScrollRight")); - if (m_scrollRight) - { - m_scrollRightClickToken = m_scrollRight->Click += ref new RoutedEventHandler(this, &CalculationResult::OnScrollRightClick); - } - m_textBlock = dynamic_cast(GetTemplateChild("NormalOutput")); - if (m_textBlock) - { - m_textBlock->Visibility = ::Visibility::Visible; - m_textBlockSizeChangedToken = m_textBlock->SizeChanged += ref new SizeChangedEventHandler(this, &CalculationResult::OnTextBlockSizeChanged); - } - } - UpdateVisualState(); - UpdateTextState(); -} - -void CalculationResult::OnTextContainerLayoutUpdated(Object ^ /*sender*/, Object ^ /*e*/) -{ - if (m_isScalingText) - { - UpdateTextState(); - } -} - -void CalculationResult::OnTextContainerSizeChanged(Object ^ /*sender*/, SizeChangedEventArgs ^ /*e*/) -{ - UpdateTextState(); -} - -void CalculationResult::OnIsActivePropertyChanged(bool /*oldValue*/, bool /*newValue */) -{ - UpdateVisualState(); -} - -void CalculationResult::OnDisplayValuePropertyChanged(String ^ /*oldValue*/, String ^ /*newValue*/) -{ - UpdateTextState(); -} - -void CalculationResult::OnMinFontSizePropertyChanged(double /*oldValue*/, double /*newValue*/) -{ - UpdateTextState(); -} - -void CalculationResult::OnMaxFontSizePropertyChanged(double /*oldValue*/, double /*newValue*/) -{ - UpdateTextState(); -} - -void CalculationResult::OnIsInErrorPropertyChanged(bool /*oldValue*/, bool newValue) -{ - // We need to have a good template for this to work - if (m_textBlock == nullptr) - { - return; - } - - if (newValue) - { - // If there's an error message we need to override the normal display font - // with the font appropriate for this language. This is because the error - // message is localized and therefore can contain characters that are not - // available in the normal font. - // We use UIText as the font type because this is the most common font type to use - m_textBlock->FontFamily = LocalizationService::GetInstance()->GetLanguageFontFamilyForType(LanguageFontType::UIText); - } - else - { - // The error result is no longer an error so we will restore the - // value to FontFamily property to the value provided in the style - // for the TextBlock in the template. - m_textBlock->ClearValue(TextBlock::FontFamilyProperty); - } -} - -void CalculationResult::UpdateVisualState() -{ - if (IsActive) - { - VisualStateManager::GoToState(this, "Active", true); - } - else - { - VisualStateManager::GoToState(this, "Normal", true); - } -} - -void CalculationResult::UpdateTextState() -{ - if ((m_textContainer == nullptr) || (m_textBlock == nullptr)) - { - return; - } - - auto containerSize = m_textContainer->ActualWidth; - String ^ oldText = m_textBlock->Text; - String ^ newText = DisplayValue; - - // Initiate the scaling operation - // UpdateLayout will keep calling us until we make it through the below 2 if-statements - if (!m_isScalingText || oldText != newText) - { - m_textBlock->Text = newText; - - m_isScalingText = true; - m_haveCalculatedMax = false; - m_textBlock->InvalidateArrange(); - return; - } - if (containerSize > 0) - { - double widthDiff = abs(m_textBlock->ActualWidth - containerSize); - double fontSizeChange = INCREMENTOFFSET; - - if (widthDiff > WIDTHCUTOFF) - { - fontSizeChange = min(max(floor(WIDTHTOFONTSCALAR * widthDiff) - WIDTHTOFONTOFFSET, INCREMENTOFFSET), MAXFONTINCREMENT); - } - if (m_textBlock->ActualWidth < containerSize && abs(m_textBlock->FontSize - MaxFontSize) > FONTTOLERANCE && !m_haveCalculatedMax) - { - ModifyFontAndMargin(m_textBlock, fontSizeChange); - m_textBlock->InvalidateArrange(); - return; - } - if (fontSizeChange < 5) - { - m_haveCalculatedMax = true; - } - if (m_textBlock->ActualWidth >= containerSize && abs(m_textBlock->FontSize - MinFontSize) > FONTTOLERANCE) - { - ModifyFontAndMargin(m_textBlock, -1 * fontSizeChange); - m_textBlock->InvalidateArrange(); - return; - } - assert(m_textBlock->FontSize >= MinFontSize && m_textBlock->FontSize <= MaxFontSize); - m_isScalingText = false; - if (IsOperatorCommand) - { - m_textContainer->ChangeView(0.0, nullptr, nullptr); - } - else - { - m_textContainer->ChangeView(m_textContainer->ExtentWidth - m_textContainer->ViewportWidth, nullptr, nullptr); - } - } -} - -void CalculationResult::ScrollLeft() -{ - if (m_textContainer == nullptr) - { - return; - } - if (m_textContainer->HorizontalOffset > 0) - { - double offset = m_textContainer->HorizontalOffset - (SCROLL_RATIO * m_textContainer->ViewportWidth); - m_textContainer->ChangeView(offset, nullptr, nullptr); - } -} - -void CalculationResult::ScrollRight() -{ - if (m_textContainer == nullptr) - { - return; - } - - if (m_textContainer->HorizontalOffset < m_textContainer->ExtentWidth - m_textContainer->ViewportWidth) - { - double offset = m_textContainer->HorizontalOffset + (SCROLL_RATIO * m_textContainer->ViewportWidth); - m_textContainer->ChangeView(offset, nullptr, nullptr); - } -} - -void CalculationResult::OnKeyDown(KeyRoutedEventArgs ^ e) -{ - switch (e->Key) - { - case Windows::System::VirtualKey::Left: - this->ScrollLeft(); - break; - case Windows::System::VirtualKey::Right: - this->ScrollRight(); - break; - } -} - -void CalculationResult::OnScrollLeftClick(Object ^ sender, RoutedEventArgs ^ /*e*/) -{ - ScrollLeft(); -} - -void CalculationResult::OnScrollRightClick(Object ^ sender, RoutedEventArgs ^ /*e*/) -{ - ScrollRight(); -} - -void CalculationResult::UpdateScrollButtons() -{ - if (m_textContainer == nullptr) - { - return; - } - - bool shouldTryFocusScrollRight = false; - if (m_scrollLeft != nullptr) - { - auto scrollLeftVisibility = m_textContainer->HorizontalOffset > SCROLL_BUTTONS_APPROXIMATION_RANGE ? ::Visibility::Visible : ::Visibility::Collapsed; - - if (scrollLeftVisibility == ::Visibility::Collapsed) - { - shouldTryFocusScrollRight = m_scrollLeft->Equals(FocusManager::GetFocusedElement()); - } - - m_scrollLeft->Visibility = scrollLeftVisibility; - } - - if (m_scrollRight != nullptr) - { - auto scrollRightVisibility = - m_textContainer->HorizontalOffset + m_textContainer->ViewportWidth + SCROLL_BUTTONS_APPROXIMATION_RANGE < m_textContainer->ExtentWidth - ? ::Visibility::Visible - : ::Visibility::Collapsed; - - if (scrollRightVisibility == ::Visibility::Collapsed && m_scrollLeft != nullptr && m_scrollLeft->Visibility == ::Visibility::Visible - && m_scrollRight->Equals(FocusManager::GetFocusedElement())) - { - // ScrollRight had the focus and will be collapsed, ScrollLeft should get the focus - m_scrollLeft->Focus(::FocusState::Programmatic); - } - m_scrollRight->Visibility = scrollRightVisibility; - - if (shouldTryFocusScrollRight && scrollRightVisibility == ::Visibility::Visible) - { - m_scrollRight->Focus(::FocusState::Programmatic); - } - } -} - -void CalculationResult::ModifyFontAndMargin(TextBlock ^ textBox, double fontChange) -{ - double cur = textBox->FontSize; - double newFontSize = 0.0; - double scaleFactor = SCALEFACTOR; - if (m_textContainer->ActualHeight <= HEIGHTCUTOFF) - { - scaleFactor = SMALLHEIGHTSCALEFACTOR; - } - - newFontSize = min(max(cur + fontChange, MinFontSize), MaxFontSize); - m_textContainer->Padding = Thickness(0, 0, 0, scaleFactor * abs(cur - newFontSize)); - textBox->FontSize = newFontSize; -} - -void CalculationResult::OnTapped(TappedRoutedEventArgs ^ e) -{ - this->Focus(::FocusState::Programmatic); - RaiseSelectedEvent(); -} - -void CalculationResult::OnRightTapped(RightTappedRoutedEventArgs ^ e) -{ - auto requestedElement = e->OriginalSource; - - if (requestedElement->Equals(dynamic_cast(m_textBlock))) - { - m_textBlock->Focus(::FocusState::Programmatic); - } - else - { - this->Focus(::FocusState::Programmatic); - } -} - -AutomationPeer ^ CalculationResult::OnCreateAutomationPeer() -{ - return ref new CalculationResultAutomationPeer(this); -} - -void CalculationResult::ProgrammaticSelect() -{ - RaiseSelectedEvent(); -} - -void CalculationResult::RaiseSelectedEvent() -{ - Selected(this); -} - -void CalculationResult::OnTextContainerOnViewChanged(Object ^ /*sender*/, ScrollViewerViewChangedEventArgs ^ e) -{ - UpdateScrollButtons(); -} - -void CalculationResult::OnTextBlockSizeChanged(Object ^ /*sender*/, SizeChangedEventArgs ^ /*e*/) -{ - UpdateScrollButtons(); -} diff --git a/src/Calculator/Controls/CalculationResult.cs b/src/Calculator/Controls/CalculationResult.cs new file mode 100644 index 00000000..5dd577b4 --- /dev/null +++ b/src/Calculator/Controls/CalculationResult.cs @@ -0,0 +1,500 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using System.Diagnostics; +using CalculatorApp; +using CalculatorApp.Controls; +using CalculatorApp.ViewModel.Common; + +using Windows.Devices.Input; +using Windows.Foundation; +using Windows.Foundation.Collections; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; +using Windows.UI.Xaml.Controls.Primitives; +using Windows.UI.Xaml.Data; +using Windows.UI.Xaml.Input; +using Windows.UI.Xaml.Media; +using Windows.UI.Xaml.Navigation; +using Windows.UI.Xaml.Automation; +using Windows.UI.Xaml.Automation.Peers; +using System.Reflection; + +namespace CalculatorApp +{ + namespace Controls + { + public delegate void SelectedEventHandler(object sender); + + public sealed class CalculationResult : Windows.UI.Xaml.Controls.Control + { + public CalculationResult() + { + m_isScalingText = false; + m_haveCalculatedMax = false; + } + + public double MinFontSize + { + get { return (double)GetValue(MinFontSizeProperty); } + set { SetValue(MinFontSizeProperty, value); } + } + + // Using a DependencyProperty as the backing store for MinFontSize. This enables animation, styling, binding, etc... + public static readonly DependencyProperty MinFontSizeProperty = + DependencyProperty.Register(nameof(MinFontSize), typeof(double), typeof(CalculationResult), new PropertyMetadata(0.0, new PropertyChangedCallback((sender, args) => + { + var self = (CalculationResult)sender; + self.OnMinFontSizePropertyChanged((double)args.OldValue, (double)args.NewValue); + }))); + + public double MaxFontSize + { + get { return (double)GetValue(MaxFontSizeProperty); } + set { SetValue(MaxFontSizeProperty, value); } + } + + // Using a DependencyProperty as the backing store for MaxFontSize. This enables animation, styling, binding, etc... + public static readonly DependencyProperty MaxFontSizeProperty = + DependencyProperty.Register(nameof(MaxFontSize), typeof(double), typeof(CalculationResult), new PropertyMetadata(30.0, new PropertyChangedCallback((sender, args) => + { + var self = (CalculationResult)sender; + self.OnMaxFontSizePropertyChanged((double)args.OldValue, (double)args.NewValue); + }))); + + public Thickness DisplayMargin + { + get { return (Thickness)GetValue(DisplayMarginProperty); } + set { SetValue(DisplayMarginProperty, value); } + } + + // Using a DependencyProperty as the backing store for DisplayMargin. This enables animation, styling, binding, etc... + public static readonly DependencyProperty DisplayMarginProperty = + DependencyProperty.Register(nameof(DisplayMargin), typeof(Thickness), typeof(CalculationResult), new PropertyMetadata(default(Thickness))); + + public bool IsActive + { + get { return (bool)GetValue(IsActiveProperty); } + set { SetValue(IsActiveProperty, value); } + } + + // Using a DependencyProperty as the backing store for IsActive. This enables animation, styling, binding, etc... + public static readonly DependencyProperty IsActiveProperty = + DependencyProperty.Register(nameof(IsActive), typeof(bool), typeof(CalculationResult), new PropertyMetadata(default(bool), new PropertyChangedCallback((sender, args) => + { + var self = (CalculationResult)sender; + self.OnIsActivePropertyChanged((bool)args.OldValue, (bool)args.NewValue); + }))); + + public string DisplayValue + { + get { return (string)GetValue(DisplayValueProperty); } + set { SetValue(DisplayValueProperty, value); } + } + + // Using a DependencyProperty as the backing store for DisplayValue. This enables animation, styling, binding, etc... + public static readonly DependencyProperty DisplayValueProperty = + DependencyProperty.Register(nameof(DisplayValue), typeof(string), typeof(CalculationResult), new PropertyMetadata(string.Empty, new PropertyChangedCallback((sender, args) => + { + var self = (CalculationResult)sender; + self.OnDisplayValuePropertyChanged((string)args.OldValue, (string)args.NewValue); + }))); + + public bool IsInError + { + get { return (bool)GetValue(IsInErrorProperty); } + set { SetValue(IsInErrorProperty, value); } + } + + // Using a DependencyProperty as the backing store for IsInError. This enables animation, styling, binding, etc... + public static readonly DependencyProperty IsInErrorProperty = + DependencyProperty.Register(nameof(IsInError), typeof(bool), typeof(CalculationResult), new PropertyMetadata(default(bool), new PropertyChangedCallback((sender, args) => + { + var self = (CalculationResult)sender; + self.OnIsInErrorPropertyChanged((bool)args.OldValue, (bool)args.NewValue); + }))); + + public bool IsOperatorCommand + { + get { return (bool)GetValue(IsOperatorCommandProperty); } + set { SetValue(IsOperatorCommandProperty, value); } + } + + // Using a DependencyProperty as the backing store for IsOperatorCommand. This enables animation, styling, binding, etc... + public static readonly DependencyProperty IsOperatorCommandProperty = + DependencyProperty.Register(nameof(IsOperatorCommand), typeof(bool), typeof(CalculationResult), new PropertyMetadata(false)); + + public event SelectedEventHandler Selected; + + public void ProgrammaticSelect() + { + RaiseSelectedEvent(); + } + + internal void UpdateTextState() + { + if ((m_textContainer == null) || (m_textBlock == null)) + { + return; + } + + var containerSize = m_textContainer.ActualWidth; + string oldText = m_textBlock.Text; + string newText = DisplayValue; + + // Initiate the scaling operation + // UpdateLayout will keep calling us until we make it through the below 2 if-statements + if (!m_isScalingText || oldText != newText) + { + m_textBlock.Text = newText; + + m_isScalingText = true; + m_haveCalculatedMax = false; + m_textBlock.InvalidateArrange(); + return; + } + if (containerSize > 0) + { + double widthDiff = Math.Abs(m_textBlock.ActualWidth - containerSize); + double fontSizeChange = INCREMENTOFFSET; + + if (widthDiff > WIDTHCUTOFF) + { + fontSizeChange = Math.Min((double)Math.Max((double)Math.Floor(WIDTHTOFONTSCALAR * widthDiff) - WIDTHTOFONTOFFSET, INCREMENTOFFSET), MAXFONTINCREMENT); + } + if (m_textBlock.ActualWidth < containerSize && Math.Abs(m_textBlock.FontSize - MaxFontSize) > FONTTOLERANCE && !m_haveCalculatedMax) + { + ModifyFontAndMargin(m_textBlock, fontSizeChange); + m_textBlock.InvalidateArrange(); + return; + } + if (fontSizeChange < 5) + { + m_haveCalculatedMax = true; + } + if (m_textBlock.ActualWidth >= containerSize && Math.Abs(m_textBlock.FontSize - MinFontSize) > FONTTOLERANCE) + { + ModifyFontAndMargin(m_textBlock, -1 * fontSizeChange); + m_textBlock.InvalidateArrange(); + return; + } + Debug.Assert(m_textBlock.FontSize >= MinFontSize && m_textBlock.FontSize <= MaxFontSize); + m_isScalingText = false; + if (IsOperatorCommand) + { + m_textContainer.ChangeView(0.0, null, null); + } + else + { + m_textContainer.ChangeView(m_textContainer.ExtentWidth - m_textContainer.ViewportWidth, null, null); + } + } + } + public string GetRawDisplayValue() + { + return LocalizationSettings.GetInstance().RemoveGroupSeparators(DisplayValue); + } + + protected override void OnKeyDown(KeyRoutedEventArgs e) + { + switch (e.Key) + { + case Windows.System.VirtualKey.Left: + this.ScrollLeft(); + break; + case Windows.System.VirtualKey.Right: + this.ScrollRight(); + break; + } + } + + protected override void OnApplyTemplate() + { + if (m_textContainer != null) + { + m_textContainer.LayoutUpdated -= OnTextContainerLayoutUpdated; + m_textContainer.SizeChanged -= OnTextContainerSizeChanged; + m_textContainer.ViewChanged -= OnTextContainerOnViewChanged; + } + + if (m_textBlock != null) + { + m_textBlock.SizeChanged -= OnTextBlockSizeChanged; + } + + if (m_scrollLeft != null) + { + m_scrollLeft.Click -= OnScrollLeftClick; + } + + if (m_scrollRight != null) + { + m_scrollRight.Click -= OnScrollRightClick; + } + + m_textContainer = GetTemplateChild("TextContainer") as ScrollViewer; + if (m_textContainer != null) + { + // We want to know when the size of the container changes so + // we can rescale the textbox + m_textContainer.SizeChanged += OnTextContainerSizeChanged; + + m_textContainer.ViewChanged += OnTextContainerOnViewChanged; + + m_textContainer.LayoutUpdated += OnTextContainerLayoutUpdated; + + m_textContainer.ChangeView(m_textContainer.ExtentWidth - m_textContainer.ViewportWidth, null, null); + m_scrollLeft = GetTemplateChild("ScrollLeft") as HyperlinkButton; + if (m_scrollLeft != null) + { + m_scrollLeft.Click += OnScrollLeftClick; + } + m_scrollRight = GetTemplateChild("ScrollRight") as HyperlinkButton; + if (m_scrollRight != null) + { + m_scrollRight.Click += OnScrollRightClick; + } + m_textBlock = GetTemplateChild("NormalOutput") as TextBlock; + if (m_textBlock != null) + { + m_textBlock.Visibility = Visibility.Visible; + m_textBlock.SizeChanged += OnTextBlockSizeChanged; + } + } + UpdateVisualState(); + UpdateTextState(); + } + + protected override void OnTapped(TappedRoutedEventArgs e) + { + this.Focus(FocusState.Programmatic); + RaiseSelectedEvent(); + } + + protected override void OnRightTapped(RightTappedRoutedEventArgs e) + { + var requestedElement = e.OriginalSource; + + if (requestedElement.Equals(m_textBlock as object)) + { + m_textBlock.Focus(FocusState.Programmatic); + } + else + { + this.Focus(FocusState.Programmatic); + } + } + + protected override AutomationPeer OnCreateAutomationPeer() + { + return new CalculationResultAutomationPeer(this); + } + + private void OnIsActivePropertyChanged(bool oldValue, bool newValue) + { + UpdateVisualState(); + } + + private void OnDisplayValuePropertyChanged(string oldValue, string newValue) + { + UpdateTextState(); + } + + private void OnIsInErrorPropertyChanged(bool oldValue, bool newValue) + { + // We need to have a good template for this to work + if (m_textBlock == null) + { + return; + } + + if (newValue) + { + // If there's an error message we need to override the normal display font + // with the font appropriate for this language. This is because the error + // message is localized and therefore can contain characters that are not + // available in the normal font. + // We use UIText as the font type because this is the most common font type to use + m_textBlock.FontFamily = LocalizationService.GetInstance().GetLanguageFontFamilyForType(LanguageFontType.UIText); + } + else + { + // The error result is no longer an error so we will restore the + // value to FontFamily property to the value provided in the style + // for the TextBlock in the template. + m_textBlock.ClearValue(TextBlock.FontFamilyProperty); + } + } + + private void OnMinFontSizePropertyChanged(double oldValue, double newValue) + { + UpdateTextState(); + } + + private void OnMaxFontSizePropertyChanged(double oldValue, double newValue) + { + UpdateTextState(); + } + + private void OnTextContainerSizeChanged(object sender, SizeChangedEventArgs e) + { + UpdateTextState(); + } + + private void OnTextBlockSizeChanged(object sender, SizeChangedEventArgs e) + { + UpdateScrollButtons(); + } + + private void OnTextContainerLayoutUpdated(object sender, object e) + { + if (m_isScalingText) + { + UpdateTextState(); + } + } + + private void OnTextContainerOnViewChanged(object sender, ScrollViewerViewChangedEventArgs e) + { + UpdateScrollButtons(); + } + + private void UpdateVisualState() + { + if (IsActive) + { + VisualStateManager.GoToState(this, "Active", true); + } + else + { + VisualStateManager.GoToState(this, "Normal", true); + } + } + + private void OnScrollLeftClick(object sender, RoutedEventArgs e) + { + ScrollLeft(); + } + + private void OnScrollRightClick(object sender, RoutedEventArgs e) + { + ScrollRight(); + } + + private void ModifyFontAndMargin(TextBlock textBox, double fontChange) + { + double cur = textBox.FontSize; + double newFontSize = 0.0; + double scaleFactor = SCALEFACTOR; + if (m_textContainer.ActualHeight <= HEIGHTCUTOFF) + { + scaleFactor = SMALLHEIGHTSCALEFACTOR; + } + + newFontSize = Math.Min(Math.Max(cur + fontChange, MinFontSize), MaxFontSize); + m_textContainer.Padding = new Thickness(0, 0, 0, scaleFactor * Math.Abs(cur - newFontSize)); + textBox.FontSize = newFontSize; + } + + private void UpdateScrollButtons() + { + if (m_textContainer == null) + { + return; + } + + bool shouldTryFocusScrollRight = false; + if (m_scrollLeft != null) + { + var scrollLeftVisibility = m_textContainer.HorizontalOffset > SCROLL_BUTTONS_APPROXIMATION_RANGE ? Visibility.Visible : Visibility.Collapsed; + + if (scrollLeftVisibility == Visibility.Collapsed) + { + shouldTryFocusScrollRight = m_scrollLeft.Equals(FocusManager.GetFocusedElement()); + } + + m_scrollLeft.Visibility = scrollLeftVisibility; + } + + if (m_scrollRight != null) + { + var scrollRightVisibility = + m_textContainer.HorizontalOffset + m_textContainer.ViewportWidth + SCROLL_BUTTONS_APPROXIMATION_RANGE < m_textContainer.ExtentWidth + ? Visibility.Visible + : Visibility.Collapsed; + + if (scrollRightVisibility == Visibility.Collapsed && m_scrollLeft != null && m_scrollLeft.Visibility == Visibility.Visible + && m_scrollRight.Equals(FocusManager.GetFocusedElement())) + { + // ScrollRight had the focus and will be collapsed, ScrollLeft should get the focus + m_scrollLeft.Focus(FocusState.Programmatic); + } + m_scrollRight.Visibility = scrollRightVisibility; + + if (shouldTryFocusScrollRight && scrollRightVisibility == Visibility.Visible) + { + m_scrollRight.Focus(FocusState.Programmatic); + } + } + } + + private void ScrollLeft() + { + if (m_textContainer == null) + { + return; + } + if (m_textContainer.HorizontalOffset > 0) + { + double offset = m_textContainer.HorizontalOffset - (SCROLL_RATIO * m_textContainer.ViewportWidth); + m_textContainer.ChangeView(offset, null, null); + } + } + + private void ScrollRight() + { + if (m_textContainer == null) + { + return; + } + + if (m_textContainer.HorizontalOffset < m_textContainer.ExtentWidth - m_textContainer.ViewportWidth) + { + double offset = m_textContainer.HorizontalOffset + (SCROLL_RATIO * m_textContainer.ViewportWidth); + m_textContainer.ChangeView(offset, null, null); + } + } + + private void RaiseSelectedEvent() + { + Selected?.Invoke(this); + } + + private const double SCALEFACTOR = 0.357143; + private const double SMALLHEIGHTSCALEFACTOR = 0; + private const double HEIGHTCUTOFF = 100; + private const double INCREMENTOFFSET = 1; + private const double MAXFONTINCREMENT = 5; + private const double WIDTHTOFONTSCALAR = 0.0556513; + private const double WIDTHTOFONTOFFSET = 3; + private const double WIDTHCUTOFF = 50; + private const double FONTTOLERANCE = 0.001; + private const double SCROLL_RATIO = 0.7; + + // We need a safety margin to guarantee we correctly always show/hide ScrollLeft and ScrollRight buttons when necessary. + // In rare cases, ScrollViewer::HorizontalOffset is a little low by a few (sub)pixels when users scroll to one of the extremity + // and no events are launched when they scroll again in the same direction + private const double SCROLL_BUTTONS_APPROXIMATION_RANGE = 4; + + private Windows.UI.Xaml.Controls.ScrollViewer m_textContainer; + private Windows.UI.Xaml.Controls.TextBlock m_textBlock; + private Windows.UI.Xaml.Controls.HyperlinkButton m_scrollLeft; + private Windows.UI.Xaml.Controls.HyperlinkButton m_scrollRight; + private bool m_isScalingText; + private bool m_haveCalculatedMax; + } + } +} diff --git a/src/Calculator/Controls/CalculationResult.h b/src/Calculator/Controls/CalculationResult.h deleted file mode 100644 index fb6a0d9a..00000000 --- a/src/Calculator/Controls/CalculationResult.h +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -#pragma once - -#include "CalcViewModel/Common/Utils.h" - -namespace CalculatorApp -{ - namespace Controls - { - public - delegate void SelectedEventHandler(Platform::Object ^ sender); - - public - ref class CalculationResult sealed : public Windows::UI::Xaml::Controls::Control - { - public: - CalculationResult(); - - DEPENDENCY_PROPERTY_OWNER(CalculationResult); - - DEPENDENCY_PROPERTY_WITH_DEFAULT_AND_CALLBACK(double, MinFontSize, 0.0); - DEPENDENCY_PROPERTY_WITH_DEFAULT_AND_CALLBACK(double, MaxFontSize, 30.0); - DEPENDENCY_PROPERTY(Windows::UI::Xaml::Thickness, DisplayMargin); - DEPENDENCY_PROPERTY_WITH_CALLBACK(bool, IsActive); - DEPENDENCY_PROPERTY_WITH_CALLBACK(Platform::String ^, DisplayValue); - DEPENDENCY_PROPERTY_WITH_CALLBACK(bool, IsInError); - DEPENDENCY_PROPERTY_WITH_DEFAULT(bool, IsOperatorCommand, false); - - event SelectedEventHandler ^ Selected; - void ProgrammaticSelect(); - - internal : void UpdateTextState(); - Platform::String ^ GetRawDisplayValue(); - - protected: - virtual void OnKeyDown(Windows::UI::Xaml::Input::KeyRoutedEventArgs ^ e) override; - virtual void OnApplyTemplate() override; - virtual void OnTapped(Windows::UI::Xaml::Input::TappedRoutedEventArgs ^ e) override; - virtual void OnRightTapped(Windows::UI::Xaml::Input::RightTappedRoutedEventArgs ^ e) override; - - virtual Windows::UI::Xaml::Automation::Peers::AutomationPeer ^ OnCreateAutomationPeer() override; - - private: - void OnIsActivePropertyChanged(bool oldValue, bool newValue); - void OnDisplayValuePropertyChanged(Platform::String ^ oldValue, Platform::String ^ newValue); - void OnIsInErrorPropertyChanged(bool oldValue, bool newValue); - void OnMinFontSizePropertyChanged(double oldValue, double newValue); - void OnMaxFontSizePropertyChanged(double oldValue, double newValue); - void OnTextContainerSizeChanged(Object ^ sender, Windows::UI::Xaml::SizeChangedEventArgs ^ e); - void OnTextBlockSizeChanged(Object ^ sender, Windows::UI::Xaml::SizeChangedEventArgs ^ e); - void OnTextContainerLayoutUpdated(Object ^ sender, Object ^ e); - void OnTextContainerOnViewChanged(Object ^ sender, Windows::UI::Xaml::Controls::ScrollViewerViewChangedEventArgs ^ e); - void UpdateVisualState(); - void UpdateAllState(); - void OnScrollLeftClick(Platform::Object ^ sender, Windows::UI::Xaml::RoutedEventArgs ^ e); - void OnScrollRightClick(Platform::Object ^ sender, Windows::UI::Xaml::RoutedEventArgs ^ e); - void OnPointerEntered(Platform::Object ^ sender, Windows::UI::Xaml::Input::PointerRoutedEventArgs ^ e); - void OnPointerExited(Platform::Object ^ sender, Windows::UI::Xaml::Input::PointerRoutedEventArgs ^ e); - void ModifyFontAndMargin(Windows::UI::Xaml::Controls::TextBlock ^ textBlock, double fontChange); - void UpdateScrollButtons(); - void ScrollLeft(); - void ScrollRight(); - void RaiseSelectedEvent(); - - Windows::UI::Xaml::Controls::ScrollViewer ^ m_textContainer; - Windows::UI::Xaml::Controls::TextBlock ^ m_textBlock; - Windows::UI::Xaml::Controls::HyperlinkButton ^ m_scrollLeft; - Windows::UI::Xaml::Controls::HyperlinkButton ^ m_scrollRight; - bool m_isScalingText; - bool m_haveCalculatedMax; - Windows::Foundation::EventRegistrationToken m_textContainerLayoutChangedToken; - Windows::Foundation::EventRegistrationToken m_textContainerViewChangedToken; - Windows::Foundation::EventRegistrationToken m_textContainerSizeChangedToken; - Windows::Foundation::EventRegistrationToken m_scrollRightClickToken; - Windows::Foundation::EventRegistrationToken m_scrollLeftClickToken; - Windows::Foundation::EventRegistrationToken m_textBlockSizeChangedToken; - }; - } -} diff --git a/src/Calculator/Controls/CalculationResultAutomationPeer.cpp b/src/Calculator/Controls/CalculationResultAutomationPeer.cpp deleted file mode 100644 index 6f381e28..00000000 --- a/src/Calculator/Controls/CalculationResultAutomationPeer.cpp +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -#include "pch.h" -#include "CalculationResultAutomationPeer.h" - -using namespace Windows::UI::Xaml; -using namespace Windows::UI::Xaml::Automation::Peers; - -namespace CalculatorApp::Controls -{ - CalculationResultAutomationPeer::CalculationResultAutomationPeer(FrameworkElement ^ owner) - : FrameworkElementAutomationPeer(owner) - { - } - - AutomationControlType CalculationResultAutomationPeer::GetAutomationControlTypeCore() - { - return AutomationControlType::Text; - } - - Platform::Object ^ CalculationResultAutomationPeer::GetPatternCore(PatternInterface pattern) - { - if (pattern == PatternInterface::Invoke) - { - return this; - } - - return FrameworkElementAutomationPeer::GetPatternCore(pattern); - } - - void CalculationResultAutomationPeer::Invoke() - { - auto owner = static_cast(this->Owner); - owner->ProgrammaticSelect(); - } -} diff --git a/src/Calculator/Controls/CalculationResultAutomationPeer.cs b/src/Calculator/Controls/CalculationResultAutomationPeer.cs new file mode 100644 index 00000000..36d1f37a --- /dev/null +++ b/src/Calculator/Controls/CalculationResultAutomationPeer.cs @@ -0,0 +1,44 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using System.Diagnostics; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Automation.Peers; + +namespace CalculatorApp +{ + namespace Controls + { + public sealed class CalculationResultAutomationPeer : Windows.UI.Xaml.Automation.Peers.FrameworkElementAutomationPeer, + Windows.UI.Xaml.Automation.Provider.IInvokeProvider + { + public CalculationResultAutomationPeer(FrameworkElement owner) : base(owner) + { + } + + protected override AutomationControlType GetAutomationControlTypeCore() + { + return AutomationControlType.Text; + } + + protected override object GetPatternCore(PatternInterface pattern) + { + if (pattern == PatternInterface.Invoke) + { + return this; + } + + return base.GetPatternCore(pattern); + } + + public void Invoke() + { + var owner = (CalculationResult)this.Owner; + owner.ProgrammaticSelect(); + } + } + } +} diff --git a/src/Calculator/Controls/CalculationResultAutomationPeer.h b/src/Calculator/Controls/CalculationResultAutomationPeer.h deleted file mode 100644 index ec75320c..00000000 --- a/src/Calculator/Controls/CalculationResultAutomationPeer.h +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -#pragma once - -#include "Controls/CalculationResult.h" - -namespace CalculatorApp -{ - namespace Controls - { - public - ref class CalculationResultAutomationPeer sealed : Windows::UI::Xaml::Automation::Peers::FrameworkElementAutomationPeer, - Windows::UI::Xaml::Automation::Provider::IInvokeProvider - { - public: - CalculationResultAutomationPeer(Windows::UI::Xaml::FrameworkElement ^ owner); - - virtual Windows::UI::Xaml::Automation::Peers::AutomationControlType GetAutomationControlTypeCore() override; - virtual Platform::Object ^ GetPatternCore(Windows::UI::Xaml::Automation::Peers::PatternInterface pattern) override; - virtual void Invoke(); - }; - } -} diff --git a/src/Calculator/Controls/CalculatorButton.cpp b/src/Calculator/Controls/CalculatorButton.cpp deleted file mode 100644 index 2377a9a7..00000000 --- a/src/Calculator/Controls/CalculatorButton.cpp +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -#include "pch.h" -#include "CalculatorButton.h" -#include "CalcViewModel/Common/CalculatorButtonPressedEventArgs.h" - -using namespace CalculatorApp; -using namespace CalculatorApp::Common; -using namespace CalculatorApp::Controls; -using namespace Windows::System; -using namespace Windows::UI::Xaml; -using namespace Windows::UI::Xaml::Input; -using namespace Windows::UI::Xaml::Data; -using namespace Platform; -using namespace Windows::Foundation::Collections; - -DEPENDENCY_PROPERTY_INITIALIZATION(CalculatorButton, ButtonId); -DEPENDENCY_PROPERTY_INITIALIZATION(CalculatorButton, AuditoryFeedback); -DEPENDENCY_PROPERTY_INITIALIZATION(CalculatorButton, HoverBackground); -DEPENDENCY_PROPERTY_INITIALIZATION(CalculatorButton, HoverForeground); -DEPENDENCY_PROPERTY_INITIALIZATION(CalculatorButton, PressBackground); -DEPENDENCY_PROPERTY_INITIALIZATION(CalculatorButton, PressForeground); - -CalculatorButton::CalculatorButton() -{ - // Set the default bindings for this button, these can be overwritten by Xaml if needed - // These are a replacement for binding in styles - Binding ^ commandBinding = ref new Binding(); - commandBinding->Path = ref new PropertyPath("ButtonPressed"); - this->SetBinding(Button::CommandProperty, commandBinding); -} - -void CalculatorButton::OnKeyDown(KeyRoutedEventArgs ^ e) -{ - // Ignore the Enter key - if (e->Key == VirtualKey::Enter) - { - return; - } - - Button::OnKeyDown(e); -} - -void CalculatorButton::OnKeyUp(KeyRoutedEventArgs ^ e) -{ - // Ignore the Enter key - if (e->Key == VirtualKey::Enter) - { - return; - } - - Button::OnKeyUp(e); -} - -void CalculatorButton::OnButtonIdPropertyChanged(NumbersAndOperatorsEnum /*oldValue*/, NumbersAndOperatorsEnum newValue) -{ - this->CommandParameter = ref new CalculatorButtonPressedEventArgs(AuditoryFeedback, newValue); -} - -void CalculatorButton::OnAuditoryFeedbackPropertyChanged(String ^ /*oldValue*/, String ^ newValue) -{ - this->CommandParameter = ref new CalculatorButtonPressedEventArgs(newValue, ButtonId); -} diff --git a/src/Calculator/Controls/CalculatorButton.cs b/src/Calculator/Controls/CalculatorButton.cs new file mode 100644 index 00000000..d24bafb7 --- /dev/null +++ b/src/Calculator/Controls/CalculatorButton.cs @@ -0,0 +1,134 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using System.Diagnostics; +using CalculatorApp; +using CalculatorApp.Controls; +using CalculatorApp.ViewModel.Common; +using Windows.System; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Input; +using Windows.UI.Xaml.Data; +using Windows.Foundation.Collections; +using Windows.Storage.Pickers; + +namespace CalculatorApp +{ + namespace Controls + { + public sealed class CalculatorButton : Windows.UI.Xaml.Controls.Button + { + public CalculatorButton() + { + // Set the default bindings for this button, these can be overwritten by Xaml if needed + // These are a replacement for binding in styles + Binding commandBinding = new Binding(); + commandBinding.Path = new PropertyPath("ButtonPressed"); + this.SetBinding(CommandProperty, commandBinding); + } + + public NumbersAndOperatorsEnum ButtonId + { + get { return (NumbersAndOperatorsEnum)GetValue(ButtonIdProperty); } + set { SetValue(ButtonIdProperty, value); } + } + + // Using a DependencyProperty as the backing store for ButtonId. This enables animation, styling, binding, etc... + public static readonly DependencyProperty ButtonIdProperty = + DependencyProperty.Register(nameof(ButtonId), typeof(NumbersAndOperatorsEnum), typeof(CalculatorButton), new PropertyMetadata(default(NumbersAndOperatorsEnum), new PropertyChangedCallback((sender, args) => + { + var self = (CalculatorButton)sender; + self.OnButtonIdPropertyChanged((NumbersAndOperatorsEnum)args.OldValue, (NumbersAndOperatorsEnum)args.NewValue); + }))); + + public string AuditoryFeedback + { + get { return (string)GetValue(AuditoryFeedbackProperty); } + set { SetValue(AuditoryFeedbackProperty, value); } + } + + // Using a DependencyProperty as the backing store for AuditoryFeedback. This enables animation, styling, binding, etc... + public static readonly DependencyProperty AuditoryFeedbackProperty = + DependencyProperty.Register(nameof(AuditoryFeedback), typeof(string), typeof(CalculatorButton), new PropertyMetadata(string.Empty, new PropertyChangedCallback((sender, args) => + { + var self = (CalculatorButton)sender; + self.OnAuditoryFeedbackPropertyChanged((string)args.OldValue, (string)args.NewValue); + }))); + + public Windows.UI.Xaml.Media.Brush HoverBackground + { + get { return (Windows.UI.Xaml.Media.Brush)GetValue(HoverBackgroundProperty); } + set { SetValue(HoverBackgroundProperty, value); } + } + + // Using a DependencyProperty as the backing store for HoverBackground. This enables animation, styling, binding, etc... + public static readonly DependencyProperty HoverBackgroundProperty = + DependencyProperty.Register(nameof(HoverBackground), typeof(Windows.UI.Xaml.Media.Brush), typeof(CalculatorButton), new PropertyMetadata(default(Windows.UI.Xaml.Media.Brush))); + + public Windows.UI.Xaml.Media.Brush HoverForeground + { + get { return (Windows.UI.Xaml.Media.Brush)GetValue(HoverForegroundProperty); } + set { SetValue(HoverForegroundProperty, value); } + } + + // Using a DependencyProperty as the backing store for HoverForeground. This enables animation, styling, binding, etc... + public static readonly DependencyProperty HoverForegroundProperty = + DependencyProperty.Register(nameof(HoverForeground), typeof(Windows.UI.Xaml.Media.Brush), typeof(CalculatorButton), new PropertyMetadata(default(Windows.UI.Xaml.Media.Brush))); + + public Windows.UI.Xaml.Media.Brush PressBackground + { + get { return (Windows.UI.Xaml.Media.Brush)GetValue(PressBackgroundProperty); } + set { SetValue(PressBackgroundProperty, value); } + } + + // Using a DependencyProperty as the backing store for PressBackground. This enables animation, styling, binding, etc... + public static readonly DependencyProperty PressBackgroundProperty = + DependencyProperty.Register(nameof(PressBackground), typeof(Windows.UI.Xaml.Media.Brush), typeof(CalculatorButton), new PropertyMetadata(default(Windows.UI.Xaml.Media.Brush))); + + public Windows.UI.Xaml.Media.Brush PressForeground + { + get { return (Windows.UI.Xaml.Media.Brush)GetValue(PressForegroundProperty); } + set { SetValue(PressForegroundProperty, value); } + } + + // Using a DependencyProperty as the backing store for PressForeground. This enables animation, styling, binding, etc... + public static readonly DependencyProperty PressForegroundProperty = + DependencyProperty.Register(nameof(PressForeground), typeof(Windows.UI.Xaml.Media.Brush), typeof(CalculatorButton), new PropertyMetadata(default(Windows.UI.Xaml.Media.Brush))); + + protected override void OnKeyDown(KeyRoutedEventArgs e) + { + // Ignore the Enter key + if (e.Key == VirtualKey.Enter) + { + return; + } + + base.OnKeyDown(e); + } + + protected override void OnKeyUp(KeyRoutedEventArgs e) + { + // Ignore the Enter key + if (e.Key == VirtualKey.Enter) + { + return; + } + + base.OnKeyUp(e); + } + + private void OnButtonIdPropertyChanged(NumbersAndOperatorsEnum oldValue, NumbersAndOperatorsEnum newValue) + { + this.CommandParameter = new CalculatorButtonPressedEventArgs(AuditoryFeedback, newValue); + } + + private void OnAuditoryFeedbackPropertyChanged(string oldValue, string newValue) + { + this.CommandParameter = new CalculatorButtonPressedEventArgs(newValue, ButtonId); + } + } + } +} diff --git a/src/Calculator/Controls/CalculatorButton.h b/src/Calculator/Controls/CalculatorButton.h deleted file mode 100644 index 8a780700..00000000 --- a/src/Calculator/Controls/CalculatorButton.h +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -#pragma once - -#include "CalcViewModel/Common/Utils.h" -#include "CalcViewModel/Common/CalculatorButtonUser.h" - -namespace CalculatorApp -{ - namespace Controls - { - public - ref class CalculatorButton sealed : Windows::UI::Xaml::Controls::Button - { - public: - CalculatorButton(); - DEPENDENCY_PROPERTY_OWNER(CalculatorButton); - - DEPENDENCY_PROPERTY_WITH_CALLBACK(NumbersAndOperatorsEnum, ButtonId); - DEPENDENCY_PROPERTY_WITH_CALLBACK(Platform::String ^, AuditoryFeedback); - DEPENDENCY_PROPERTY(Windows::UI::Xaml::Media::Brush ^, HoverBackground); - DEPENDENCY_PROPERTY(Windows::UI::Xaml::Media::Brush ^, HoverForeground); - DEPENDENCY_PROPERTY(Windows::UI::Xaml::Media::Brush ^, PressBackground); - DEPENDENCY_PROPERTY(Windows::UI::Xaml::Media::Brush ^, PressForeground); - - protected: - virtual void OnKeyDown(Windows::UI::Xaml::Input::KeyRoutedEventArgs ^ e) override; - virtual void OnKeyUp(Windows::UI::Xaml::Input::KeyRoutedEventArgs ^ e) override; - - private: - void OnButtonIdPropertyChanged(NumbersAndOperatorsEnum oldValue, NumbersAndOperatorsEnum newValue); - void OnAuditoryFeedbackPropertyChanged(Platform::String ^ oldValue, Platform::String ^ newValue); - }; - } -} diff --git a/src/Calculator/Controls/EquationTextBox.cpp b/src/Calculator/Controls/EquationTextBox.cpp deleted file mode 100644 index a0d65298..00000000 --- a/src/Calculator/Controls/EquationTextBox.cpp +++ /dev/null @@ -1,507 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -#include "pch.h" -#include "CalcViewModel/Common/AppResourceProvider.h" -#include "CalcViewModel/Common/LocalizationStringUtil.h" -#include "EquationTextBox.h" - -using namespace std; -using namespace Platform; -using namespace CalculatorApp; -using namespace CalculatorApp::Common; -using namespace CalculatorApp::Controls; -using namespace Windows::System; -using namespace Windows::Foundation; -using namespace Windows::ApplicationModel; -using namespace Windows::UI::Text; -using namespace Windows::UI::Xaml; -using namespace Windows::UI::Xaml::Automation; -using namespace Windows::UI::Xaml::Controls; -using namespace Windows::UI::Xaml::Input; -using namespace Windows::UI::Xaml::Controls::Primitives; -using namespace Windows::UI::Xaml::Media; - -DEPENDENCY_PROPERTY_INITIALIZATION(EquationTextBox, EquationColor); -DEPENDENCY_PROPERTY_INITIALIZATION(EquationTextBox, EquationButtonForegroundColor); -DEPENDENCY_PROPERTY_INITIALIZATION(EquationTextBox, ColorChooserFlyout); -DEPENDENCY_PROPERTY_INITIALIZATION(EquationTextBox, EquationButtonContentIndex); -DEPENDENCY_PROPERTY_INITIALIZATION(EquationTextBox, HasError); -DEPENDENCY_PROPERTY_INITIALIZATION(EquationTextBox, IsAddEquationMode); -DEPENDENCY_PROPERTY_INITIALIZATION(EquationTextBox, MathEquation); -DEPENDENCY_PROPERTY_INITIALIZATION(EquationTextBox, ErrorText); -DEPENDENCY_PROPERTY_INITIALIZATION(EquationTextBox, IsEquationLineDisabled); - -EquationTextBox::EquationTextBox() -{ -} - -void EquationTextBox::OnApplyTemplate() -{ - m_equationButton = dynamic_cast(GetTemplateChild("EquationButton")); - m_richEditBox = dynamic_cast(GetTemplateChild("MathRichEditBox")); - m_deleteButton = dynamic_cast