From fdae1000fcc1ef56c6acb9ee2ebdc0ab9062b5f2 Mon Sep 17 00:00:00 2001 From: Tian L <60599517+tian-lt@users.noreply.github.com> Date: Thu, 15 Jul 2021 17:12:38 +0800 Subject: [PATCH] Hello C# - Migrating the codebase from C++/CX to C# (Phase 1) (#1598) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Hello C# - Going to an official feature branch (#1544) * change CalcViewModel into a WindowsRuntimeComponent project (#5) * change CalcViewModel into a WindowsRuntimeComponent project * remove the old UI codebase (#6) * initially migrated C# codebase by tian (#7) * initial migrated C# codebase by tian * format the codebase * resolve comments * undo: modifications on UI test project * Remove the blocks that have more than 1 empty line. * Register DP using keyword 'nameof' * C# Migration: Initially migrated C# codebase by Han (#8) * C# Migration: Initially migrated C# codebase by Han * Resolved comments and misssing asset * Added three files to Calculator project * Added TODO comment and updated Object * NavCategory: temporary resolution of the hang issue (#9) * Updated CalcViewModel and missing files (#10) * Updated CalcViewModel and WinMeta * Added Calculator.rc * Resolved comment for InitializeLocalizationSettings * add: views/unitconverter.xaml (#11) * add: views/unitconverter.xaml * format the code * remove the extra empty line * add an empty line * check null before invoking event handlers (#12) * fix problems of the migration of OBSERVABLE_PROPERTY_RW (#13) * fixes crash in MathRichEditBox.ctor() (#14) * fixes crash in MathRichEditBox.ctor() * typo * Update azure-pipelines.ci.yaml for Azure Pipelines * Added a link copy of CalcViewModel to temporarily pass Unit Tests (#16) * Updated CalcViewModelCopyForUT configuration (#17) * changes output path of the UI project to align with other projects (#15) * fixes EETypeLoadException issue: export class DelegateCommand (#18) * fixes EETypeLoadException issue: export class DelegateCommand * weak-reference in C++/CX * WeakRef in C# codebase * UTF-8-BOM * spaces in macro * resolve some comments from the offline review * format * rename file * fixes the memory list issue (#20) * fixes a wrongly migrated property * UTF-8-BOM * fixes up the crash of type casting (#21) * Update localized strings 2021-01-04 (#1458) (#23) (cherry picked from commit cdcb95656df0e5336d2cefe3e57afe0e58dc031a) Co-authored-by: Matt Cooley * Fixup tests (#1429) (#24) - Removed unneeded "ToString" calls - Fixed typos - Renamed "fEButtonState" to "FEButtonState" (cherry picked from commit 66ad328d0018c360c1a0dc766f994c7fdb7d4a3f) Co-authored-by: N <71219152+PokeCodec@users.noreply.github.com> * Update graph internal engine verseion (#1466) (#25) (cherry picked from commit 0048dcb50031a2e94cd041282ed9a3511b4143b4) Co-authored-by: Quentin Al-Timimi <27322516+quentin987@users.noreply.github.com> * Turn off DFS file shares in internal build system (#1470) (#26) (cherry picked from commit 885fa23a898e8f029c4b21af5a6a9e6b2982722a) Co-authored-by: Matt Cooley * Improve clarity of math expressions in history for Standard Calculator (feature #138) (#1453) (#27) * Implemented feature & added unit tests * Fixed more unit/ui tests * Refactored tests * Update HistoryTests.cpp * Update HistoryTests.cpp * Update HistoryTests.cpp * Update HistoryTests.cpp * Update HistoryTests.cpp * Update HistoryTests.cpp * Update HistoryTests.cpp * Update HistoryTests.cpp (cherry picked from commit 565e3e2714ceb45ae7f2e860a319ea790ab24cef) Co-authored-by: Wei (Waley) Zhang * Adds unit-test cases for NarratorAnnouncement after fixing issue #1386 (#1469) (#28) * fix bug: No confirmation is announced by the narrator after activating 'Remove equation' button #1386 * Unit Test: Add NarratorAnnouncementUnitTests Co-authored-by: tain (cherry picked from commit 9d8e2ad18c472fb9a511d67cb9430e8a7732552a) Co-authored-by: Tian L <60599517+MSFT-Tilia@users.noreply.github.com> * Move localization pipeline sync schedule to the YAML file (#1478) (#30) (cherry picked from commit 007eccd9408c80f8b60a947af03be934e8a99319) Co-authored-by: Matt Cooley * remove the strong reference carried from delegate (#32) * Remove the finalizer of ControlSizeTrigger (#31) * Normalize the namespace of CalcViewModel (#33) * ViewMode: arrange namespaces * UI build pass * run release * UT build pass * pass build * resolve comment: make the diff results cleaner * resolve comment: make the diff results cleaner (2) * resolve comment: make the diff results cleaner (3) * resolve comment: move impl into a namespace * update: spaces * update: CalculatorButtonUser.h * UTF-8 to UTF-8-BOM * remove ViewState.h/.cpp from CalcViewModel path * revert changes for NavCategory.cpp * remove extra space * remove UCM * remove BOM * Fixed a graphing calculator "permissions" bug caused by PR #1426 (#1471) (#34) - The PR #1426 can cause a crash when no users are returned via `User::FindAllAsync(UserType::LocalUser)` when subsequently trying to access the first user. The existing code also does not guarantee that the returned user is the currently active user. - This fix retrieves the user that opened the app and passes this user into a function to check if this user has the proper permissions to access the graphing mode. This makes sense since the active user is indistinguishable (at least from the app's perspective) to the user who opened the app. This user's permissions are then propagated downwards to properly set up the navigation menu of the app. - Implementation detail worth pointing out: `s_categoryManifest` is what is used to populate the navigation menu of the app, but this variable is static by design, so a separate function was written to override the appropriate `isEnabled` value in `s_categoryManifest`. This function is called by `onLaunched`. - Manual testing Co-authored-by: Wei (Waley) Zhang * fixes up a bug (#35) * fix csproj (#37) Co-authored-by: hanzhang54 Co-authored-by: Matt Cooley Co-authored-by: N <71219152+PokeCodec@users.noreply.github.com> Co-authored-by: Quentin Al-Timimi <27322516+quentin987@users.noreply.github.com> Co-authored-by: Wei (Waley) Zhang Co-authored-by: Tian L <60599517+MSFT-Tilia@users.noreply.github.com> * **BYPASS_SECRET_SCANNING** (#1546) * Fixes a bug about the UI of expression tokens (#1547) * fix * [FeatureBranch] Fixes x86/ARM/ARM64 builds for the CI-Pipeline (#1550) * **BYPASS_SECRET_SCANNING** * fix * fixes x86/ARM/ARM64 builds for CI-Pipeline * Add headers missing for compilation with GCC (#1468) (#1551) Things that required such update included: * `wstringstream` * `setprecision` * `SCODE_CODE`, `E_BOUNDS` * Various SAL macros Co-authored-by: Michał Janiszewski * Update nuget.config file (#1486) (#1552) Co-authored-by: Matt Cooley * Fixes up some simple miscellaneous TODO items (#1556) * #DEBUG is a known C# preprocessor directive * So far, we haven't observed the problem described in the comment from C# async * fixes misc TODO items * resolve some warnings (#1564) * Add internal CI pipeline (#1553) (#1565) * Add CI-internal pipeline * No ARM64, to match release Co-authored-by: Matt Cooley * Temporarily disable PGO NuGet package (#1510) (#1566) Co-authored-by: Matt Cooley * [C# Calc]Removes WinMeta.cs (#1567) * remove WinMeta.cs * undo a trivial change * UTF-8 BOM * [C# Calc] Reverts some changes for Currency constants (#1570) * Update2108release - experimental (#1572) * adjusts Calculator.csproj (#1571) * fixes BinSkim problems (#1573) * fixes an issue around line style (#1575) * fixes the missed NULLs (#1576) (#1578) * Fix the Missing Part in Unit Converter Constructor (#1579) * fixes: calculator doesn't remember its previous mode (#1580) * Fixes: GraphingNumber doesn't work correctly (#1585) * fixes: GraphingNumber doesn't work correctly * Avoid crashing * fixes binding (#1586) * resolve TODO items (#1589) * Improving keyboard support in VariableValueSlider (#1559) (#1595) Co-authored-by: Dave Grochocki * [C# Calc] Fixes: Keep the value away from getting rounded in Graphing Mode (#1596) * keep the value away from getting rounded * set the display precision to 6 to align with C++ impl * fixes the button-light-up time (#1597) * fixes up merging flaws * Update2108release * fixes (#1599) * keep master for ci pipeline * remove the Resources filter from CalcViewModel project * removes `that` since `this` can be captured automatically * AppxBundlePlatforms * StampAssemblyInfo * removes PreferredToolArchitecture * Change the arg AppVersion into Version * Change the arg AppVersion into Version * from Calculator.rc to AssemblyInfo.cs * Adds assembly-info Co-authored-by: hanzhang54 Co-authored-by: Matt Cooley Co-authored-by: N <71219152+PokeCodec@users.noreply.github.com> Co-authored-by: Quentin Al-Timimi <27322516+quentin987@users.noreply.github.com> Co-authored-by: Wei (Waley) Zhang Co-authored-by: Tian L <60599517+MSFT-Tilia@users.noreply.github.com> Co-authored-by: Michał Janiszewski Co-authored-by: Dave Grochocki --- build/pipelines/azure-pipelines.release.yaml | 4 +- .../templates/build-app-internal.yaml | 19 +- .../templates/build-single-architecture.yaml | 2 +- src/CalcViewModel/ApplicationViewModel.cpp | 4 +- src/CalcViewModel/ApplicationViewModel.h | 22 +- .../CalcViewModel.rc} | 4 +- src/CalcViewModel/CalcViewModel.vcxproj | 265 +-- .../CalcViewModel.vcxproj.filters | 91 +- .../Common/AppResourceProvider.cpp | 1 + .../Common/AppResourceProvider.h | 2 +- .../Automation/INarratorAnnouncementHost.h | 2 +- .../Common/Automation/LiveRegionHost.cpp | 2 +- .../Common/Automation/LiveRegionHost.h | 2 +- .../Automation/NarratorAnnouncement.cpp | 4 +- .../Common/Automation/NarratorAnnouncement.h | 18 +- .../NarratorAnnouncementHostFactory.cpp | 2 +- .../NarratorAnnouncementHostFactory.h | 2 +- .../Common/Automation/NarratorNotifier.cpp | 2 +- .../Common/Automation/NarratorNotifier.h | 2 +- .../Common/Automation/NotificationHost.cpp | 2 +- .../Common/Automation/NotificationHost.h | 6 +- src/CalcViewModel/Common/BitLength.h | 2 +- .../CalculatorButtonPressedEventArgs.cpp | 3 +- .../Common/CalculatorButtonPressedEventArgs.h | 8 +- .../Common/CalculatorButtonUser.h | 5 +- .../Common/CalculatorDisplay.cpp | 264 +-- src/CalcViewModel/Common/CalculatorDisplay.h | 2 +- src/CalcViewModel/Common/CopyPasteManager.cpp | 7 +- src/CalcViewModel/Common/CopyPasteManager.h | 55 +- src/CalcViewModel/Common/DateCalculator.cpp | 2 +- src/CalcViewModel/Common/DateCalculator.h | 4 +- src/CalcViewModel/Common/DelegateCommand.h | 54 +- .../Common/DisplayExpressionToken.h | 4 +- .../Common/EngineResourceProvider.cpp | 10 +- .../Common/EngineResourceProvider.h | 2 +- .../Common/ExpressionCommandDeserializer.cpp | 2 +- .../Common/ExpressionCommandDeserializer.h | 2 +- .../Common/ExpressionCommandSerializer.cpp | 2 +- .../Common/ExpressionCommandSerializer.h | 2 +- .../Common/LocalizationService.cpp | 15 +- .../Common/LocalizationService.h | 26 +- .../Common/LocalizationSettings.h | 336 ++-- .../Common/LocalizationStringUtil.h | 2 +- src/CalcViewModel/Common/MyVirtualKey.h | 2 +- src/CalcViewModel/Common/NavCategory.cpp | 19 +- src/CalcViewModel/Common/NavCategory.h | 7 +- src/CalcViewModel/Common/NetworkManager.cpp | 2 + src/CalcViewModel/Common/NetworkManager.h | 2 +- src/CalcViewModel/Common/NumberBase.h | 2 +- src/CalcViewModel/Common/RadixType.cpp | 8 + src/CalcViewModel/Common/RadixType.h | 19 + src/CalcViewModel/Common/TraceLogger.cpp | 16 +- src/CalcViewModel/Common/TraceLogger.h | 32 +- src/CalcViewModel/Common/Utils.cpp | 60 +- src/CalcViewModel/Common/Utils.h | 42 +- .../DataLoaders/CurrencyDataLoader.cpp | 12 +- .../DataLoaders/CurrencyDataLoader.h | 14 +- .../DataLoaders/CurrencyHttpClient.cpp | 1 + .../DataLoaders/CurrencyHttpClient.h | 2 +- .../DataLoaders/ICurrencyHttpClient.h | 2 +- .../DataLoaders/UnitConverterDataConstants.h | 2 +- .../DataLoaders/UnitConverterDataLoader.cpp | 4 +- .../DataLoaders/UnitConverterDataLoader.h | 15 +- src/CalcViewModel/DateCalculatorViewModel.cpp | 16 +- src/CalcViewModel/DateCalculatorViewModel.h | 22 +- .../GraphingCalculator/EquationViewModel.cpp | 4 +- .../GraphingSettingsViewModel.cpp | 3 +- .../GraphingSettingsViewModel.h | 6 +- .../GraphingCalculator/VariableViewModel.h | 4 +- src/CalcViewModel/HistoryItemViewModel.cpp | 2 +- src/CalcViewModel/HistoryViewModel.cpp | 18 +- src/CalcViewModel/HistoryViewModel.h | 10 +- src/CalcViewModel/MemoryItemViewModel.cpp | 4 +- .../StandardCalculatorViewModel.cpp | 51 +- .../StandardCalculatorViewModel.h | 67 +- src/CalcViewModel/UnitConverterViewModel.cpp | 13 +- src/CalcViewModel/UnitConverterViewModel.h | 53 +- src/CalcViewModel/ViewState.cpp | 19 - src/CalcViewModel/ViewState.h | 15 - src/CalcViewModel/pch.h | 4 +- .../CalcViewModelCopyForUT.vcxproj | 414 +++++ .../CalcViewModelCopyForUT.vcxproj.filters | 213 +++ src/Calculator.sln | 102 +- src/Calculator/AboutFlyout.xaml | 6 +- src/Calculator/AboutFlyout.xaml.cpp | 92 - src/Calculator/AboutFlyout.xaml.cs | 86 + src/Calculator/AboutFlyout.xaml.h | 23 - src/Calculator/App.xaml.cpp | 439 ----- src/Calculator/App.xaml.cs | 504 ++++++ src/Calculator/App.xaml.h | 91 - src/Calculator/Calculator.csproj | 837 +++++++++ src/Calculator/Calculator.vcxproj | 969 ---------- src/Calculator/Calculator.vcxproj.filters | 1569 ----------------- .../Common/AlwaysSelectedCollectionView.cs | 260 +++ .../Common/AlwaysSelectedCollectionView.h | 293 --- src/Calculator/Common/AppLifecycleLogger.cpp | 149 -- src/Calculator/Common/AppLifecycleLogger.cs | 152 ++ src/Calculator/Common/AppLifecycleLogger.h | 41 - .../Common/KeyboardShortcuManager.cs | 832 +++++++++ .../Common/KeyboardShortcutManager.cpp | 692 -------- .../Common/KeyboardShortcutManager.h | 87 - src/Calculator/Common/ValidatingConverters.cs | 65 + src/Calculator/Common/ValidatingConverters.h | 92 - src/Calculator/Common/ViewState.cpp | 19 - src/Calculator/Common/ViewState.cs | 17 + src/Calculator/Common/ViewState.h | 15 - src/Calculator/Controls/CalculationResult.cpp | 419 ----- src/Calculator/Controls/CalculationResult.cs | 500 ++++++ src/Calculator/Controls/CalculationResult.h | 81 - .../CalculationResultAutomationPeer.cpp | 37 - .../CalculationResultAutomationPeer.cs | 44 + .../CalculationResultAutomationPeer.h | 24 - src/Calculator/Controls/CalculatorButton.cpp | 64 - src/Calculator/Controls/CalculatorButton.cs | 134 ++ src/Calculator/Controls/CalculatorButton.h | 36 - src/Calculator/Controls/EquationTextBox.cpp | 507 ------ src/Calculator/Controls/EquationTextBox.cs | 626 +++++++ src/Calculator/Controls/EquationTextBox.h | 105 -- src/Calculator/Controls/FlipButtons.cpp | 47 - src/Calculator/Controls/FlipButtons.cs | 93 + src/Calculator/Controls/FlipButtons.h | 33 - .../HorizontalNoOverflowStackPanel.cpp | 73 - .../HorizontalNoOverflowStackPanel.cs | 83 + .../Controls/HorizontalNoOverflowStackPanel.h | 31 - src/Calculator/Controls/MathRichEditBox.cpp | 229 --- src/Calculator/Controls/MathRichEditBox.cs | 260 +++ src/Calculator/Controls/MathRichEditBox.h | 74 - .../Controls/OperatorPanelButton.cpp | 44 - .../Controls/OperatorPanelButton.cs | 102 ++ src/Calculator/Controls/OperatorPanelButton.h | 36 - .../Controls/OperatorPanelListView.cpp | 147 -- .../Controls/OperatorPanelListView.cs | 164 ++ .../Controls/OperatorPanelListView.h | 43 - src/Calculator/Controls/OverflowTextBlock.cpp | 240 --- src/Calculator/Controls/OverflowTextBlock.cs | 332 ++++ src/Calculator/Controls/OverflowTextBlock.h | 74 - .../OverflowTextBlockAutomationPeer.cpp | 27 - .../OverflowTextBlockAutomationPeer.cs | 32 + .../OverflowTextBlockAutomationPeer.h | 22 - src/Calculator/Controls/RadixButton.cpp | 23 - src/Calculator/Controls/RadixButton.cs | 22 + src/Calculator/Controls/RadixButton.h | 18 - .../Controls/SupplementaryItemsControl.cpp | 40 - .../Controls/SupplementaryItemsControl.cs | 78 + .../Controls/SupplementaryItemsControl.h | 54 - .../Converters/BooleanNegationConverter.cpp | 33 - .../Converters/BooleanNegationConverter.cs | 32 + .../Converters/BooleanNegationConverter.h | 26 - .../BooleanToVisibilityConverter.cpp | 59 - .../BooleanToVisibilityConverter.cs | 57 + .../Converters/BooleanToVisibilityConverter.h | 52 - .../ExpressionItemTemplateSelector.cpp | 38 - .../ExpressionItemTemplateSelector.cs | 83 + .../ExpressionItemTemplateSelector.h | 57 - .../ItemSizeToVisibilityConverter.cpp | 44 - .../ItemSizeToVisibilityConverter.cs | 42 + .../ItemSizeToVisibilityConverter.h | 37 - .../Converters/RadixToStringConverter.cpp | 61 - .../Converters/RadixToStringConverter.cs | 58 + .../Converters/RadixToStringConverter.h | 26 - .../VisibilityNegationConverter.cpp | 31 - .../Converters/VisibilityNegationConverter.cs | 33 + .../Converters/VisibilityNegationConverter.h | 26 - src/Calculator/EquationStylePanelControl.xaml | 2 +- .../EquationStylePanelControl.xaml.cpp | 283 --- .../EquationStylePanelControl.xaml.cs | 325 ++++ .../EquationStylePanelControl.xaml.h | 40 - .../KeyGraphFeaturesTemplateSelector.cs | 47 + src/Calculator/Properties/AssemblyInfo.cs | 16 + src/Calculator/Properties/Default.rd.xml | 31 + src/Calculator/Resources/ko-KR/Resources.resw | 2 +- src/Calculator/Resources/lo-LA/Resources.resw | 2 +- src/Calculator/Resources/zh-CN/Resources.resw | 2 +- .../KeyGraphFeaturesTemplateSelector.cpp | 36 - .../KeyGraphFeaturesTemplateSelector.h | 25 - src/Calculator/Utils/DelegateCommandUtils.cs | 26 + .../Utils/DispatcherTimerDelayer.cpp | 39 - .../Utils/DispatcherTimerDelayer.cs | 45 + src/Calculator/Utils/DispatcherTimerDelayer.h | 26 - src/Calculator/Utils/VisualTree.cpp | 102 -- src/Calculator/Utils/VisualTree.cs | 134 ++ src/Calculator/Utils/VisualTree.h | 50 - src/Calculator/Views/Calculator.xaml | 4 +- src/Calculator/Views/Calculator.xaml.cpp | 733 -------- src/Calculator/Views/Calculator.xaml.cs | 874 +++++++++ src/Calculator/Views/Calculator.xaml.h | 156 -- .../CalculatorProgrammerBitFlipPanel.xaml | 224 +-- .../CalculatorProgrammerBitFlipPanel.xaml.cpp | 276 --- .../CalculatorProgrammerBitFlipPanel.xaml.cs | 283 +++ .../CalculatorProgrammerBitFlipPanel.xaml.h | 50 - .../CalculatorProgrammerDisplayPanel.xaml.cpp | 78 - .../CalculatorProgrammerDisplayPanel.xaml.h | 37 - .../CalculatorProgrammerOperators.xaml.cpp | 109 -- .../CalculatorProgrammerOperators.xaml.cs | 120 ++ .../CalculatorProgrammerOperators.xaml.h | 37 - .../CalculatorProgrammerRadixOperators.xaml | 4 +- ...alculatorProgrammerRadixOperators.xaml.cpp | 232 --- ...CalculatorProgrammerRadixOperators.xaml.cs | 252 +++ .../CalculatorProgrammerRadixOperators.xaml.h | 61 - .../CalculatorScientificAngleButtons.xaml | 8 +- .../CalculatorScientificAngleButtons.xaml.cpp | 85 - .../CalculatorScientificAngleButtons.xaml.cs | 113 ++ .../CalculatorScientificAngleButtons.xaml.h | 41 - .../CalculatorScientificOperators.xaml.cpp | 158 -- .../CalculatorScientificOperators.xaml.cs | 175 ++ .../CalculatorScientificOperators.xaml.h | 49 - .../CalculatorStandardOperators.xaml.cpp | 48 - .../Views/CalculatorStandardOperators.xaml.cs | 52 + .../Views/CalculatorStandardOperators.xaml.h | 32 - src/Calculator/Views/DateCalculator.xaml.cpp | 261 --- src/Calculator/Views/DateCalculator.xaml.cs | 267 +++ src/Calculator/Views/DateCalculator.xaml.h | 56 - .../GraphingCalculator/EquationInputArea.xaml | 2 +- .../EquationInputArea.xaml.cpp | 579 ------ .../EquationInputArea.xaml.cs | 652 +++++++ .../EquationInputArea.xaml.h | 90 - .../GraphingCalculator.xaml.cpp | 839 --------- .../GraphingCalculator.xaml.cs | 902 ++++++++++ .../GraphingCalculator.xaml.h | 113 -- .../GraphingNumPad.xaml.cpp | 275 --- .../GraphingCalculator/GraphingNumPad.xaml.cs | 283 +++ .../GraphingCalculator/GraphingNumPad.xaml.h | 40 - .../GraphingSettings.xaml.cpp | 101 -- .../GraphingSettings.xaml.cs | 138 ++ .../GraphingSettings.xaml.h | 56 - .../KeyGraphFeaturesPanel.xaml.cpp | 30 - .../KeyGraphFeaturesPanel.xaml.cs | 67 + .../KeyGraphFeaturesPanel.xaml.h | 35 - src/Calculator/Views/HistoryList.xaml | 7 +- src/Calculator/Views/HistoryList.xaml.cpp | 92 - src/Calculator/Views/HistoryList.xaml.cs | 85 + src/Calculator/Views/HistoryList.xaml.h | 41 - src/Calculator/Views/MainPage.xaml | 2 +- src/Calculator/Views/MainPage.xaml.cpp | 598 ------- src/Calculator/Views/MainPage.xaml.cs | 573 ++++++ src/Calculator/Views/MainPage.xaml.h | 92 - src/Calculator/Views/Memory.xaml | 2 +- src/Calculator/Views/Memory.xaml.cpp | 104 -- src/Calculator/Views/Memory.xaml.cs | 100 ++ src/Calculator/Views/Memory.xaml.h | 50 - src/Calculator/Views/MemoryListItem.xaml | 3 +- src/Calculator/Views/MemoryListItem.xaml.cpp | 81 - src/Calculator/Views/MemoryListItem.xaml.cs | 76 + src/Calculator/Views/MemoryListItem.xaml.h | 34 - src/Calculator/Views/NumberPad.xaml.cpp | 99 -- src/Calculator/Views/NumberPad.xaml.cs | 102 ++ src/Calculator/Views/NumberPad.xaml.h | 39 - src/Calculator/Views/OperatorsPanel.xaml | 2 +- src/Calculator/Views/OperatorsPanel.xaml.cpp | 84 - src/Calculator/Views/OperatorsPanel.xaml.cs | 99 ++ src/Calculator/Views/OperatorsPanel.xaml.h | 33 - .../StateTriggers/AspectRatioTrigger.cpp | 86 - .../Views/StateTriggers/AspectRatioTrigger.cs | 145 ++ .../Views/StateTriggers/AspectRatioTrigger.h | 58 - .../CalculatorProgrammerDisplayPanel.xaml | 4 +- .../CalculatorProgrammerDisplayPanel.xaml.cs | 102 ++ .../StateTriggers/ControlSizeTrigger.cpp | 72 - .../Views/StateTriggers/ControlSizeTrigger.cs | 100 ++ .../Views/StateTriggers/ControlSizeTrigger.h | 37 - .../Views/SupplementaryResults.xaml.cpp | 85 - .../Views/SupplementaryResults.xaml.cs | 115 ++ .../Views/SupplementaryResults.xaml.h | 87 - src/Calculator/Views/TitleBar.xaml | 11 +- src/Calculator/Views/TitleBar.xaml.cpp | 200 --- src/Calculator/Views/TitleBar.xaml.cs | 210 +++ src/Calculator/Views/TitleBar.xaml.h | 48 - src/Calculator/Views/UnitConverter.xaml | 4 +- src/Calculator/Views/UnitConverter.xaml.cpp | 383 ---- src/Calculator/Views/UnitConverter.xaml.cs | 411 +++++ src/Calculator/Views/UnitConverter.xaml.h | 93 - src/Calculator/WindowFrameService.cpp | 178 -- src/Calculator/WindowFrameService.cs | 188 ++ src/Calculator/WindowFrameService.h | 60 - src/Calculator/pch.cpp | 9 - src/Calculator/pch.h | 49 - src/CalculatorUnitTests/CalcEngineTests.cpp | 1 + .../CalculatorManagerTest.cpp | 2 +- .../CalculatorUnitTests.vcxproj | 4 +- .../CopyPasteManagerTest.cpp | 2 +- .../CurrencyConverterUnitTests.cpp | 8 +- .../DateCalculatorUnitTests.cpp | 2 +- src/CalculatorUnitTests/Helpers.h | 2 +- src/CalculatorUnitTests/HistoryTests.cpp | 2 +- .../LocalizationServiceUnitTests.cpp | 2 +- .../LocalizationSettingsUnitTests.cpp | 16 +- .../Mocks/CurrencyHttpClient.cpp | 2 +- .../Mocks/CurrencyHttpClient.h | 2 +- .../MultiWindowUnitTests.cpp | 2 +- .../NarratorAnnouncementUnitTests.cpp | 4 +- .../NavCategoryUnitTests.cpp | 2 +- .../StandardViewModelUnitTests.cpp | 2 +- .../UnitConverterViewModelUnitTests.cpp | 2 +- src/CalculatorUnitTests/UnitTestApp.xaml.cpp | 2 +- src/GraphControl/GraphControl.rc | 10 + src/GraphControl/GraphControl.vcxproj | 10 + src/GraphingImpl/GraphingImpl.rc | 10 + src/GraphingImpl/GraphingImpl.vcxproj | 6 + src/TraceLogging/TraceLogging.rc | 10 + src/TraceLogging/TraceLogging.vcxproj | 10 + .../Calculator.StampAssemblyInfo.targets | 29 + 300 files changed, 14563 insertions(+), 16717 deletions(-) rename src/{Calculator/Calculator.rc => CalcViewModel/CalcViewModel.rc} (74%) create mode 100644 src/CalcViewModel/Common/RadixType.cpp create mode 100644 src/CalcViewModel/Common/RadixType.h delete mode 100644 src/CalcViewModel/ViewState.cpp delete mode 100644 src/CalcViewModel/ViewState.h create mode 100644 src/CalcViewModelCopyForUT/CalcViewModelCopyForUT.vcxproj create mode 100644 src/CalcViewModelCopyForUT/CalcViewModelCopyForUT.vcxproj.filters delete mode 100644 src/Calculator/AboutFlyout.xaml.cpp create mode 100644 src/Calculator/AboutFlyout.xaml.cs delete mode 100644 src/Calculator/AboutFlyout.xaml.h delete mode 100644 src/Calculator/App.xaml.cpp create mode 100644 src/Calculator/App.xaml.cs delete mode 100644 src/Calculator/App.xaml.h create mode 100644 src/Calculator/Calculator.csproj delete mode 100644 src/Calculator/Calculator.vcxproj delete mode 100644 src/Calculator/Calculator.vcxproj.filters create mode 100644 src/Calculator/Common/AlwaysSelectedCollectionView.cs delete mode 100644 src/Calculator/Common/AlwaysSelectedCollectionView.h delete mode 100644 src/Calculator/Common/AppLifecycleLogger.cpp create mode 100644 src/Calculator/Common/AppLifecycleLogger.cs delete mode 100644 src/Calculator/Common/AppLifecycleLogger.h create mode 100644 src/Calculator/Common/KeyboardShortcuManager.cs delete mode 100644 src/Calculator/Common/KeyboardShortcutManager.cpp delete mode 100644 src/Calculator/Common/KeyboardShortcutManager.h create mode 100644 src/Calculator/Common/ValidatingConverters.cs delete mode 100644 src/Calculator/Common/ValidatingConverters.h delete mode 100644 src/Calculator/Common/ViewState.cpp create mode 100644 src/Calculator/Common/ViewState.cs delete mode 100644 src/Calculator/Common/ViewState.h delete mode 100644 src/Calculator/Controls/CalculationResult.cpp create mode 100644 src/Calculator/Controls/CalculationResult.cs delete mode 100644 src/Calculator/Controls/CalculationResult.h delete mode 100644 src/Calculator/Controls/CalculationResultAutomationPeer.cpp create mode 100644 src/Calculator/Controls/CalculationResultAutomationPeer.cs delete mode 100644 src/Calculator/Controls/CalculationResultAutomationPeer.h delete mode 100644 src/Calculator/Controls/CalculatorButton.cpp create mode 100644 src/Calculator/Controls/CalculatorButton.cs delete mode 100644 src/Calculator/Controls/CalculatorButton.h delete mode 100644 src/Calculator/Controls/EquationTextBox.cpp create mode 100644 src/Calculator/Controls/EquationTextBox.cs delete mode 100644 src/Calculator/Controls/EquationTextBox.h delete mode 100644 src/Calculator/Controls/FlipButtons.cpp create mode 100644 src/Calculator/Controls/FlipButtons.cs delete mode 100644 src/Calculator/Controls/FlipButtons.h delete mode 100644 src/Calculator/Controls/HorizontalNoOverflowStackPanel.cpp create mode 100644 src/Calculator/Controls/HorizontalNoOverflowStackPanel.cs delete mode 100644 src/Calculator/Controls/HorizontalNoOverflowStackPanel.h delete mode 100644 src/Calculator/Controls/MathRichEditBox.cpp create mode 100644 src/Calculator/Controls/MathRichEditBox.cs delete mode 100644 src/Calculator/Controls/MathRichEditBox.h delete mode 100644 src/Calculator/Controls/OperatorPanelButton.cpp create mode 100644 src/Calculator/Controls/OperatorPanelButton.cs delete mode 100644 src/Calculator/Controls/OperatorPanelButton.h delete mode 100644 src/Calculator/Controls/OperatorPanelListView.cpp create mode 100644 src/Calculator/Controls/OperatorPanelListView.cs delete mode 100644 src/Calculator/Controls/OperatorPanelListView.h delete mode 100644 src/Calculator/Controls/OverflowTextBlock.cpp create mode 100644 src/Calculator/Controls/OverflowTextBlock.cs delete mode 100644 src/Calculator/Controls/OverflowTextBlock.h delete mode 100644 src/Calculator/Controls/OverflowTextBlockAutomationPeer.cpp create mode 100644 src/Calculator/Controls/OverflowTextBlockAutomationPeer.cs delete mode 100644 src/Calculator/Controls/OverflowTextBlockAutomationPeer.h delete mode 100644 src/Calculator/Controls/RadixButton.cpp create mode 100644 src/Calculator/Controls/RadixButton.cs delete mode 100644 src/Calculator/Controls/RadixButton.h delete mode 100644 src/Calculator/Controls/SupplementaryItemsControl.cpp create mode 100644 src/Calculator/Controls/SupplementaryItemsControl.cs delete mode 100644 src/Calculator/Controls/SupplementaryItemsControl.h delete mode 100644 src/Calculator/Converters/BooleanNegationConverter.cpp create mode 100644 src/Calculator/Converters/BooleanNegationConverter.cs delete mode 100644 src/Calculator/Converters/BooleanNegationConverter.h delete mode 100644 src/Calculator/Converters/BooleanToVisibilityConverter.cpp create mode 100644 src/Calculator/Converters/BooleanToVisibilityConverter.cs delete mode 100644 src/Calculator/Converters/BooleanToVisibilityConverter.h delete mode 100644 src/Calculator/Converters/ExpressionItemTemplateSelector.cpp create mode 100644 src/Calculator/Converters/ExpressionItemTemplateSelector.cs delete mode 100644 src/Calculator/Converters/ExpressionItemTemplateSelector.h delete mode 100644 src/Calculator/Converters/ItemSizeToVisibilityConverter.cpp create mode 100644 src/Calculator/Converters/ItemSizeToVisibilityConverter.cs delete mode 100644 src/Calculator/Converters/ItemSizeToVisibilityConverter.h delete mode 100644 src/Calculator/Converters/RadixToStringConverter.cpp create mode 100644 src/Calculator/Converters/RadixToStringConverter.cs delete mode 100644 src/Calculator/Converters/RadixToStringConverter.h delete mode 100644 src/Calculator/Converters/VisibilityNegationConverter.cpp create mode 100644 src/Calculator/Converters/VisibilityNegationConverter.cs delete mode 100644 src/Calculator/Converters/VisibilityNegationConverter.h delete mode 100644 src/Calculator/EquationStylePanelControl.xaml.cpp create mode 100644 src/Calculator/EquationStylePanelControl.xaml.cs delete mode 100644 src/Calculator/EquationStylePanelControl.xaml.h create mode 100644 src/Calculator/KeyGraphFeaturesTemplateSelector.cs create mode 100644 src/Calculator/Properties/AssemblyInfo.cs create mode 100644 src/Calculator/Properties/Default.rd.xml delete mode 100644 src/Calculator/TemplateSelectors/KeyGraphFeaturesTemplateSelector.cpp delete mode 100644 src/Calculator/TemplateSelectors/KeyGraphFeaturesTemplateSelector.h create mode 100644 src/Calculator/Utils/DelegateCommandUtils.cs delete mode 100644 src/Calculator/Utils/DispatcherTimerDelayer.cpp create mode 100644 src/Calculator/Utils/DispatcherTimerDelayer.cs delete mode 100644 src/Calculator/Utils/DispatcherTimerDelayer.h delete mode 100644 src/Calculator/Utils/VisualTree.cpp create mode 100644 src/Calculator/Utils/VisualTree.cs delete mode 100644 src/Calculator/Utils/VisualTree.h delete mode 100644 src/Calculator/Views/Calculator.xaml.cpp create mode 100644 src/Calculator/Views/Calculator.xaml.cs delete mode 100644 src/Calculator/Views/Calculator.xaml.h delete mode 100644 src/Calculator/Views/CalculatorProgrammerBitFlipPanel.xaml.cpp create mode 100644 src/Calculator/Views/CalculatorProgrammerBitFlipPanel.xaml.cs delete mode 100644 src/Calculator/Views/CalculatorProgrammerBitFlipPanel.xaml.h delete mode 100644 src/Calculator/Views/CalculatorProgrammerDisplayPanel.xaml.cpp delete mode 100644 src/Calculator/Views/CalculatorProgrammerDisplayPanel.xaml.h delete mode 100644 src/Calculator/Views/CalculatorProgrammerOperators.xaml.cpp create mode 100644 src/Calculator/Views/CalculatorProgrammerOperators.xaml.cs delete mode 100644 src/Calculator/Views/CalculatorProgrammerOperators.xaml.h delete mode 100644 src/Calculator/Views/CalculatorProgrammerRadixOperators.xaml.cpp create mode 100644 src/Calculator/Views/CalculatorProgrammerRadixOperators.xaml.cs delete mode 100644 src/Calculator/Views/CalculatorProgrammerRadixOperators.xaml.h delete mode 100644 src/Calculator/Views/CalculatorScientificAngleButtons.xaml.cpp create mode 100644 src/Calculator/Views/CalculatorScientificAngleButtons.xaml.cs delete mode 100644 src/Calculator/Views/CalculatorScientificAngleButtons.xaml.h delete mode 100644 src/Calculator/Views/CalculatorScientificOperators.xaml.cpp create mode 100644 src/Calculator/Views/CalculatorScientificOperators.xaml.cs delete mode 100644 src/Calculator/Views/CalculatorScientificOperators.xaml.h delete mode 100644 src/Calculator/Views/CalculatorStandardOperators.xaml.cpp create mode 100644 src/Calculator/Views/CalculatorStandardOperators.xaml.cs delete mode 100644 src/Calculator/Views/CalculatorStandardOperators.xaml.h delete mode 100644 src/Calculator/Views/DateCalculator.xaml.cpp create mode 100644 src/Calculator/Views/DateCalculator.xaml.cs delete mode 100644 src/Calculator/Views/DateCalculator.xaml.h delete mode 100644 src/Calculator/Views/GraphingCalculator/EquationInputArea.xaml.cpp create mode 100644 src/Calculator/Views/GraphingCalculator/EquationInputArea.xaml.cs delete mode 100644 src/Calculator/Views/GraphingCalculator/EquationInputArea.xaml.h delete mode 100644 src/Calculator/Views/GraphingCalculator/GraphingCalculator.xaml.cpp create mode 100644 src/Calculator/Views/GraphingCalculator/GraphingCalculator.xaml.cs delete mode 100644 src/Calculator/Views/GraphingCalculator/GraphingCalculator.xaml.h delete mode 100644 src/Calculator/Views/GraphingCalculator/GraphingNumPad.xaml.cpp create mode 100644 src/Calculator/Views/GraphingCalculator/GraphingNumPad.xaml.cs delete mode 100644 src/Calculator/Views/GraphingCalculator/GraphingNumPad.xaml.h delete mode 100644 src/Calculator/Views/GraphingCalculator/GraphingSettings.xaml.cpp create mode 100644 src/Calculator/Views/GraphingCalculator/GraphingSettings.xaml.cs delete mode 100644 src/Calculator/Views/GraphingCalculator/GraphingSettings.xaml.h delete mode 100644 src/Calculator/Views/GraphingCalculator/KeyGraphFeaturesPanel.xaml.cpp create mode 100644 src/Calculator/Views/GraphingCalculator/KeyGraphFeaturesPanel.xaml.cs delete mode 100644 src/Calculator/Views/GraphingCalculator/KeyGraphFeaturesPanel.xaml.h delete mode 100644 src/Calculator/Views/HistoryList.xaml.cpp create mode 100644 src/Calculator/Views/HistoryList.xaml.cs delete mode 100644 src/Calculator/Views/HistoryList.xaml.h delete mode 100644 src/Calculator/Views/MainPage.xaml.cpp create mode 100644 src/Calculator/Views/MainPage.xaml.cs delete mode 100644 src/Calculator/Views/MainPage.xaml.h delete mode 100644 src/Calculator/Views/Memory.xaml.cpp create mode 100644 src/Calculator/Views/Memory.xaml.cs delete mode 100644 src/Calculator/Views/Memory.xaml.h delete mode 100644 src/Calculator/Views/MemoryListItem.xaml.cpp create mode 100644 src/Calculator/Views/MemoryListItem.xaml.cs delete mode 100644 src/Calculator/Views/MemoryListItem.xaml.h delete mode 100644 src/Calculator/Views/NumberPad.xaml.cpp create mode 100644 src/Calculator/Views/NumberPad.xaml.cs delete mode 100644 src/Calculator/Views/NumberPad.xaml.h delete mode 100644 src/Calculator/Views/OperatorsPanel.xaml.cpp create mode 100644 src/Calculator/Views/OperatorsPanel.xaml.cs delete mode 100644 src/Calculator/Views/OperatorsPanel.xaml.h delete mode 100644 src/Calculator/Views/StateTriggers/AspectRatioTrigger.cpp create mode 100644 src/Calculator/Views/StateTriggers/AspectRatioTrigger.cs delete mode 100644 src/Calculator/Views/StateTriggers/AspectRatioTrigger.h rename src/Calculator/Views/{ => StateTriggers}/CalculatorProgrammerDisplayPanel.xaml (97%) create mode 100644 src/Calculator/Views/StateTriggers/CalculatorProgrammerDisplayPanel.xaml.cs delete mode 100644 src/Calculator/Views/StateTriggers/ControlSizeTrigger.cpp create mode 100644 src/Calculator/Views/StateTriggers/ControlSizeTrigger.cs delete mode 100644 src/Calculator/Views/StateTriggers/ControlSizeTrigger.h delete mode 100644 src/Calculator/Views/SupplementaryResults.xaml.cpp create mode 100644 src/Calculator/Views/SupplementaryResults.xaml.cs delete mode 100644 src/Calculator/Views/SupplementaryResults.xaml.h delete mode 100644 src/Calculator/Views/TitleBar.xaml.cpp create mode 100644 src/Calculator/Views/TitleBar.xaml.cs delete mode 100644 src/Calculator/Views/TitleBar.xaml.h delete mode 100644 src/Calculator/Views/UnitConverter.xaml.cpp create mode 100644 src/Calculator/Views/UnitConverter.xaml.cs delete mode 100644 src/Calculator/Views/UnitConverter.xaml.h delete mode 100644 src/Calculator/WindowFrameService.cpp create mode 100644 src/Calculator/WindowFrameService.cs delete mode 100644 src/Calculator/WindowFrameService.h delete mode 100644 src/Calculator/pch.cpp delete mode 100644 src/Calculator/pch.h create mode 100644 src/GraphControl/GraphControl.rc create mode 100644 src/GraphingImpl/GraphingImpl.rc create mode 100644 src/TraceLogging/TraceLogging.rc create mode 100644 src/build/Calculator.StampAssemblyInfo.targets 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