diff --git a/src/CalcViewModel/ApplicationViewModel.cpp b/src/CalcViewModel/ApplicationViewModel.cpp deleted file mode 100644 index 62035c97..00000000 --- a/src/CalcViewModel/ApplicationViewModel.cpp +++ /dev/null @@ -1,293 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -#include "pch.h" -#include "ApplicationViewModel.h" -#include "Common/TraceLogger.h" -#include "Common/AppResourceProvider.h" -#include "StandardCalculatorViewModel.h" -#include "DateCalculatorViewModel.h" -#include "DataLoaders/CurrencyHttpClient.h" -#include "DataLoaders/CurrencyDataLoader.h" -#include "DataLoaders/UnitConverterDataLoader.h" - -using namespace CalculatorApp; -using namespace CalculatorApp::ViewModel::Common; -using namespace CalculatorApp::ViewModel::DataLoaders; -using namespace CalculatorApp::ViewModel; -using namespace CalculationManager; -using namespace Platform; -using namespace Platform::Collections; -using namespace Windows::System; -using namespace Windows::Storage; -using namespace Utils; -using namespace Windows::Foundation::Collections; -using namespace Windows::Globalization; -using namespace Windows::UI::ViewManagement; -using namespace Windows::UI::Core; -using namespace Windows::UI::Xaml::Automation; -using namespace Windows::UI::Xaml::Controls; -using namespace Windows::UI::Xaml::Data; -using namespace Windows::UI::Xaml::Input; -using namespace Windows::UI::Xaml::Media; -using namespace Windows::Foundation; -using namespace Concurrency; - -namespace -{ - StringReference CategoriesPropertyName(L"Categories"); - StringReference ClearMemoryVisibilityPropertyName(L"ClearMemoryVisibility"); -} - -ApplicationViewModel::ApplicationViewModel() - : m_CalculatorViewModel(nullptr) - , m_DateCalcViewModel(nullptr) - , m_GraphingCalcViewModel(nullptr) - , m_ConverterViewModel(nullptr) - , m_PreviousMode(ViewMode::None) - , m_mode(ViewMode::None) - , m_categories(nullptr) -{ - SetMenuCategories(); -} - -void ApplicationViewModel::Mode::set(ViewMode value) -{ - if (m_mode != value) - { - PreviousMode = m_mode; - m_mode = value; - SetDisplayNormalAlwaysOnTopOption(); - OnModeChanged(); - RaisePropertyChanged(ModePropertyName); - } -} - -void ApplicationViewModel::Categories::set(IObservableVector ^ value) -{ - if (m_categories != value) - { - m_categories = value; - RaisePropertyChanged(CategoriesPropertyName); - } -} - -CalculatorApp::ViewModel::Snapshot::ApplicationSnapshot ^ ApplicationViewModel::Snapshot::get() -{ - auto snapshot = ref new CalculatorApp::ViewModel::Snapshot::ApplicationSnapshot(); - snapshot->Mode = static_cast(Mode); - if (m_CalculatorViewModel != nullptr && m_mode == ViewMode::Standard) - { - snapshot->StandardCalculator = m_CalculatorViewModel->Snapshot; - } - return snapshot; -} - -void ApplicationViewModel::Initialize(ViewMode mode) -{ - if (!NavCategoryStates::IsValidViewMode(mode) || !NavCategoryStates::IsViewModeEnabled(mode)) - { - mode = ViewMode::Standard; - } - - try - { - Mode = mode; - } - catch (const std::exception& e) - { - TraceLogger::GetInstance()->LogStandardException(mode, __FUNCTIONW__, e); - if (!TryRecoverFromNavigationModeFailure()) - { - // Could not navigate to standard mode either. - // Throw the original exception so we have a good stack to debug. - throw; - } - } - catch (Exception ^ e) - { - TraceLogger::GetInstance()->LogPlatformException(mode, __FUNCTIONW__, e); - if (!TryRecoverFromNavigationModeFailure()) - { - // Could not navigate to standard mode either. - // Throw the original exception so we have a good stack to debug. - throw; - } - } -} - -void ApplicationViewModel::RestoreFromSnapshot(CalculatorApp::ViewModel::Snapshot::ApplicationSnapshot ^ snapshot) -{ - Mode = static_cast(snapshot->Mode); - if (snapshot->StandardCalculator != nullptr) - { - m_CalculatorViewModel->Snapshot = snapshot->StandardCalculator; - } -} - -bool ApplicationViewModel::TryRecoverFromNavigationModeFailure() -{ - // Here we are simply trying to recover from being unable to navigate to a mode. - // Try falling back to standard mode and if there are *any* exceptions, we should - // fail because something is seriously wrong. - try - { - Mode = ViewMode::Standard; - return true; - } - catch (...) - { - return false; - } -} - -void ApplicationViewModel::OnModeChanged() -{ - assert(NavCategoryStates::IsValidViewMode(m_mode)); - if (NavCategory::IsCalculatorViewMode(m_mode)) - { - if (!m_CalculatorViewModel) - { - m_CalculatorViewModel = ref new StandardCalculatorViewModel(); - } - m_CalculatorViewModel->SetCalculatorType(m_mode); - } - else if (NavCategory::IsGraphingCalculatorViewMode(m_mode)) - { - if (!m_GraphingCalcViewModel) - { - m_GraphingCalcViewModel = ref new GraphingCalculatorViewModel(); - } - } - else if (NavCategory::IsDateCalculatorViewMode(m_mode)) - { - if (!m_DateCalcViewModel) - { - m_DateCalcViewModel = ref new DateCalculatorViewModel(); - } - } - else if (NavCategory::IsConverterViewMode(m_mode)) - { - if (!m_ConverterViewModel) - { - auto dataLoader = std::make_shared(ref new GeographicRegion()); - m_ConverterViewModel = - ref new UnitConverterViewModel(std::make_shared(dataLoader, std::make_shared())); - } - - m_ConverterViewModel->Mode = m_mode; - } - - auto resProvider = AppResourceProvider::GetInstance(); - CategoryName = resProvider->GetResourceString(NavCategoryStates::GetNameResourceKey(m_mode)); - - // Cast mode to an int in order to save it to app data. - // Save the changed mode, so that the new window launches in this mode. - // Don't save until after we have adjusted to the new mode, so we don't save a mode that fails to load. - ApplicationData::Current->LocalSettings->Values->Insert(ModePropertyName, NavCategoryStates::Serialize(m_mode)); - - // Log ModeChange event when not first launch, log WindowCreated on first launch - if (NavCategoryStates::IsValidViewMode(m_PreviousMode)) - { - TraceLogger::GetInstance()->LogModeChange(m_mode); - } - else - { - TraceLogger::GetInstance()->LogWindowCreated(m_mode, ApplicationView::GetApplicationViewIdForWindow(CoreWindow::GetForCurrentThread())); - } - - RaisePropertyChanged(ClearMemoryVisibilityPropertyName); -} - -void ApplicationViewModel::OnCopyCommand(Object ^ parameter) -{ - if (NavCategory::IsConverterViewMode(m_mode)) - { - ConverterViewModel->OnCopyCommand(parameter); - } - else if (NavCategory::IsDateCalculatorViewMode(m_mode)) - { - DateCalcViewModel->OnCopyCommand(parameter); - } - else if (NavCategory::IsCalculatorViewMode(m_mode)) - { - CalculatorViewModel->OnCopyCommand(parameter); - } -} - -void ApplicationViewModel::OnPasteCommand(Object ^ parameter) -{ - if (NavCategory::IsConverterViewMode(m_mode)) - { - ConverterViewModel->OnPasteCommand(parameter); - } - else if (NavCategory::IsCalculatorViewMode(m_mode)) - { - CalculatorViewModel->OnPasteCommand(parameter); - } -} - -void ApplicationViewModel::SetMenuCategories() -{ - // Use the Categories property instead of the backing variable - // because we want to take advantage of binding updates and - // property setter logic. - Categories = NavCategoryStates::CreateMenuOptions(); -} - -void ApplicationViewModel::ToggleAlwaysOnTop(float width, float height) -{ - HandleToggleAlwaysOnTop(width, height); -} - -#pragma optimize("", off) -task ApplicationViewModel::HandleToggleAlwaysOnTop(float width, float height) -{ - if (ApplicationView::GetForCurrentView()->ViewMode == ApplicationViewMode::CompactOverlay) - { - ApplicationDataContainer ^ localSettings = ApplicationData::Current->LocalSettings; - localSettings->Values->Insert(WidthLocalSettings, width); - localSettings->Values->Insert(HeightLocalSettings, height); - - bool success = co_await ApplicationView::GetForCurrentView()->TryEnterViewModeAsync(ApplicationViewMode::Default); - CalculatorViewModel->HistoryVM->AreHistoryShortcutsEnabled = success; - CalculatorViewModel->IsAlwaysOnTop = !success; - IsAlwaysOnTop = !success; - } - else - { - ApplicationDataContainer ^ localSettings = ApplicationData::Current->LocalSettings; - ViewModePreferences ^ compactOptions = ViewModePreferences::CreateDefault(ApplicationViewMode::CompactOverlay); - if (!localSettings->Values->GetView()->HasKey(LaunchedLocalSettings)) - { - compactOptions->CustomSize = Size(320, 394); - localSettings->Values->Insert(LaunchedLocalSettings, true); - } - else - { - if (localSettings->Values->GetView()->HasKey(WidthLocalSettings) && localSettings->Values->GetView()->HasKey(HeightLocalSettings)) - { - float oldWidth = safe_cast(localSettings->Values->GetView()->Lookup(WidthLocalSettings))->GetSingle(); - float oldHeight = safe_cast(localSettings->Values->GetView()->Lookup(HeightLocalSettings))->GetSingle(); - compactOptions->CustomSize = Size(oldWidth, oldHeight); - } - else - { - compactOptions->CustomSize = Size(320, 394); - } - } - - bool success = co_await ApplicationView::GetForCurrentView()->TryEnterViewModeAsync(ApplicationViewMode::CompactOverlay, compactOptions); - CalculatorViewModel->HistoryVM->AreHistoryShortcutsEnabled = !success; - CalculatorViewModel->IsAlwaysOnTop = success; - IsAlwaysOnTop = success; - } - SetDisplayNormalAlwaysOnTopOption(); -}; -#pragma optimize("", on) - -void ApplicationViewModel::SetDisplayNormalAlwaysOnTopOption() -{ - DisplayNormalAlwaysOnTopOption = - m_mode == ViewMode::Standard && ApplicationView::GetForCurrentView()->IsViewModeSupported(ApplicationViewMode::CompactOverlay) && !IsAlwaysOnTop; -} diff --git a/src/CalcViewModel/ApplicationViewModel.h b/src/CalcViewModel/ApplicationViewModel.h deleted file mode 100644 index afb67eb6..00000000 --- a/src/CalcViewModel/ApplicationViewModel.h +++ /dev/null @@ -1,122 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -#pragma once - -#include "Snapshots.h" -#include "StandardCalculatorViewModel.h" -#include "DateCalculatorViewModel.h" -#include "GraphingCalculator/GraphingCalculatorViewModel.h" -#include "UnitConverterViewModel.h" - -namespace CalculatorApp -{ - namespace ViewModel - { - [Windows::UI::Xaml::Data::Bindable] public ref class ApplicationViewModel sealed : public Windows::UI::Xaml::Data::INotifyPropertyChanged - { - public: - ApplicationViewModel(); - - void Initialize(CalculatorApp::ViewModel::Common::ViewMode mode); // Use for first init, use deserialize for rehydration - void RestoreFromSnapshot(CalculatorApp::ViewModel::Snapshot::ApplicationSnapshot^ snapshot); - - 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::ViewModel::Common::ViewMode, PreviousMode); - OBSERVABLE_PROPERTY_R(bool, IsAlwaysOnTop); - OBSERVABLE_NAMED_PROPERTY_RW(Platform::String ^, CategoryName); - - // Indicates whether calculator is currently in standard mode _and_ supports CompactOverlay _and_ is not in Always-on-Top mode - OBSERVABLE_PROPERTY_R(bool, DisplayNormalAlwaysOnTopOption); - - COMMAND_FOR_METHOD(CopyCommand, ApplicationViewModel::OnCopyCommand); - COMMAND_FOR_METHOD(PasteCommand, ApplicationViewModel::OnPasteCommand); - - property CalculatorApp::ViewModel::Common::ViewMode Mode - { - CalculatorApp::ViewModel::Common::ViewMode get() - { - return m_mode; - } - - void set(CalculatorApp::ViewModel::Common::ViewMode value); - } - static property Platform::String^ ModePropertyName - { - Platform::String^ get() - { - return Platform::StringReference(L"Mode"); - } - } - - property Windows::Foundation::Collections::IObservableVector^ Categories - { - Windows::Foundation::Collections::IObservableVector^ get() - { - return m_categories; - } - - void set(Windows::Foundation::Collections::IObservableVector^ value); - } - - property Windows::UI::Xaml::Visibility ClearMemoryVisibility - { - Windows::UI::Xaml::Visibility get() - { - return CalculatorApp::ViewModel::Common::NavCategory::IsCalculatorViewMode(Mode) ? Windows::UI::Xaml::Visibility::Visible - : Windows::UI::Xaml::Visibility::Collapsed; - } - } - - property CalculatorApp::ViewModel::Snapshot::ApplicationSnapshot ^ Snapshot - { - CalculatorApp::ViewModel::Snapshot::ApplicationSnapshot ^ get(); - } - - static property Platform::String ^ LaunchedLocalSettings - { - Platform::String ^ get() - { - return Platform::StringReference(L"calculatorAlwaysOnTopLaunched"); - } - } - - static property Platform::String ^ WidthLocalSettings - { - Platform::String ^ get() - { - return Platform::StringReference(L"calculatorAlwaysOnTopLastWidth"); - } - } - - static property Platform::String ^ HeightLocalSettings - { - Platform::String ^ get() - { - return Platform::StringReference(L"calculatorAlwaysOnTopLastHeight"); - } - } - - void ToggleAlwaysOnTop(float width, float height); - - private: - bool TryRecoverFromNavigationModeFailure(); - - void OnModeChanged(); - - void OnCopyCommand(Platform::Object ^ parameter); - void OnPasteCommand(Platform::Object ^ parameter); - - void SetMenuCategories(); - - 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/CalcViewModel/CalcViewModel.vcxproj b/src/CalcViewModel/CalcViewModel.vcxproj index a16a37d8..b4c50741 100644 --- a/src/CalcViewModel/CalcViewModel.vcxproj +++ b/src/CalcViewModel/CalcViewModel.vcxproj @@ -314,7 +314,6 @@ - @@ -359,7 +358,6 @@ - diff --git a/src/CalcViewModel/CalcViewModel.vcxproj.filters b/src/CalcViewModel/CalcViewModel.vcxproj.filters index 8dd500c0..39619363 100644 --- a/src/CalcViewModel/CalcViewModel.vcxproj.filters +++ b/src/CalcViewModel/CalcViewModel.vcxproj.filters @@ -82,7 +82,6 @@ GraphingCalculator - @@ -189,7 +188,6 @@ GraphingCalculator - diff --git a/src/CalcViewModel/Common/NavCategory.cpp b/src/CalcViewModel/Common/NavCategory.cpp index c8e5185e..b7d673ca 100644 --- a/src/CalcViewModel/Common/NavCategory.cpp +++ b/src/CalcViewModel/Common/NavCategory.cpp @@ -306,7 +306,7 @@ void NavCategoryStates::SetCurrentUser(Platform::String^ userId) CurrentUserId = userId; } -IObservableVector ^ NavCategoryStates::CreateMenuOptions() +IVector ^ NavCategoryStates::CreateMenuOptions() { auto menuOptions = ref new Vector(); menuOptions->Append(CreateCalculatorCategoryGroup()); diff --git a/src/CalcViewModel/Common/NavCategory.h b/src/CalcViewModel/Common/NavCategory.h index 810ccbed..c4104d91 100644 --- a/src/CalcViewModel/Common/NavCategory.h +++ b/src/CalcViewModel/Common/NavCategory.h @@ -146,14 +146,14 @@ namespace CalculatorApp::ViewModel OBSERVABLE_PROPERTY_R(Platform::String ^, Name); OBSERVABLE_PROPERTY_R(Platform::String ^, AutomationName); OBSERVABLE_PROPERTY_R(CategoryGroupType, GroupType); - OBSERVABLE_PROPERTY_R(Windows::Foundation::Collections::IObservableVector ^, Categories); + OBSERVABLE_PROPERTY_R(Windows::Foundation::Collections::IVector ^, Categories); }; public ref class NavCategoryStates sealed { public: static void SetCurrentUser(Platform::String^ user); - static Windows::Foundation::Collections::IObservableVector ^ CreateMenuOptions(); + static Windows::Foundation::Collections::IVector ^ CreateMenuOptions(); static NavCategoryGroup ^ CreateCalculatorCategoryGroup(); static NavCategoryGroup ^ CreateConverterCategoryGroup(); diff --git a/src/CalcViewModel/StandardCalculatorViewModel.h b/src/CalcViewModel/StandardCalculatorViewModel.h index 65cf7eb6..6deb0f30 100644 --- a/src/CalcViewModel/StandardCalculatorViewModel.h +++ b/src/CalcViewModel/StandardCalculatorViewModel.h @@ -40,6 +40,7 @@ namespace CalculatorApp [Windows::UI::Xaml::Data::Bindable] public ref class StandardCalculatorViewModel sealed : public Windows::UI::Xaml::Data::INotifyPropertyChanged { public: + StandardCalculatorViewModel(); void UpdateOperand(int pos, Platform::String ^ text); OBSERVABLE_OBJECT_CALLBACK(OnPropertyChanged); @@ -267,9 +268,11 @@ namespace CalculatorApp void SwitchAngleType(CalculatorApp::ViewModel::Common::NumbersAndOperatorsEnum num); void FtoEButtonToggled(); - internal : void OnPaste(Platform::String ^ pastedString); void OnCopyCommand(Platform::Object ^ parameter); void OnPasteCommand(Platform::Object ^ parameter); + void SetCalculatorType(CalculatorApp::ViewModel::Common::ViewMode targetState); + + internal : void OnPaste(Platform::String ^ pastedString); ButtonInfo MapCharacterToButtonId(char16 ch); @@ -284,7 +287,6 @@ namespace CalculatorApp Platform::String ^ GetLocalizedStringFormat(Platform::String ^ format, Platform::String ^ displayValue); void OnPropertyChanged(Platform::String ^ propertyname); - void SetCalculatorType(CalculatorApp::ViewModel::Common::ViewMode targetState); Platform::String ^ GetRawDisplayValue(); void Recalculate(bool fromHistory = false); @@ -302,9 +304,6 @@ namespace CalculatorApp return m_CurrentAngleType; } - internal :; - explicit StandardCalculatorViewModel(); - private: void SetMemorizedNumbers(const std::vector& memorizedNumbers); void UpdateProgrammerPanelDisplay(); diff --git a/src/CalcViewModel/UnitConverterViewModel.cpp b/src/CalcViewModel/UnitConverterViewModel.cpp index 47848538..4eba27af 100644 --- a/src/CalcViewModel/UnitConverterViewModel.cpp +++ b/src/CalcViewModel/UnitConverterViewModel.cpp @@ -152,6 +152,13 @@ UnitConverterViewModel::UnitConverterViewModel(const shared_ptr( // + std::make_shared(ref new Windows::Globalization::GeographicRegion()), // + std::make_shared())) +{ +} + void UnitConverterViewModel::ResetView() { m_model->SendCommand(UCM::Command::Reset); diff --git a/src/CalcViewModel/UnitConverterViewModel.h b/src/CalcViewModel/UnitConverterViewModel.h index 64c75162..a201b757 100644 --- a/src/CalcViewModel/UnitConverterViewModel.h +++ b/src/CalcViewModel/UnitConverterViewModel.h @@ -158,6 +158,11 @@ namespace CalculatorApp internal : UnitConverterViewModel(const std::shared_ptr& model); public: + UnitConverterViewModel(); + virtual ~UnitConverterViewModel() + { + } + OBSERVABLE_OBJECT_CALLBACK(OnPropertyChanged); OBSERVABLE_PROPERTY_R(Windows::Foundation::Collections::IObservableVector ^, Categories); @@ -238,15 +243,14 @@ namespace CalculatorApp void OnPaste(Platform::String ^ stringToPaste); void RefreshCurrencyRatios(); void OnValueActivated(IActivatable ^ control); + void OnCopyCommand(Platform::Object ^ parameter); + void OnPasteCommand(Platform::Object ^ parameter); internal : void ResetView(); void PopulateData(); CalculatorApp::ViewModel::Common::NumbersAndOperatorsEnum MapCharacterToButtonId(const wchar_t ch, bool& canSendNegate); void DisplayPasteError(); - void OnCopyCommand(Platform::Object ^ parameter); - void OnPasteCommand(Platform::Object ^ parameter); - enum class CurrencyFormatterParameter { Default, diff --git a/src/CalcViewModelCopyForUT/CalcViewModelCopyForUT.vcxproj b/src/CalcViewModelCopyForUT/CalcViewModelCopyForUT.vcxproj index 510e7677..42807796 100644 --- a/src/CalcViewModelCopyForUT/CalcViewModelCopyForUT.vcxproj +++ b/src/CalcViewModelCopyForUT/CalcViewModelCopyForUT.vcxproj @@ -300,7 +300,6 @@ - @@ -345,7 +344,6 @@ - diff --git a/src/CalcViewModelCopyForUT/CalcViewModelCopyForUT.vcxproj.filters b/src/CalcViewModelCopyForUT/CalcViewModelCopyForUT.vcxproj.filters index d2091270..21c3ed73 100644 --- a/src/CalcViewModelCopyForUT/CalcViewModelCopyForUT.vcxproj.filters +++ b/src/CalcViewModelCopyForUT/CalcViewModelCopyForUT.vcxproj.filters @@ -24,7 +24,6 @@ Common\Automation - @@ -71,9 +70,6 @@ DataLoaders - - DataLoaders - DataLoaders @@ -88,6 +84,7 @@ + @@ -99,7 +96,6 @@ Common\Automation - @@ -174,9 +170,6 @@ DataLoaders - - DataLoaders - DataLoaders diff --git a/src/Calculator.ManagedViewModels/ApplicationViewModel.cs b/src/Calculator.ManagedViewModels/ApplicationViewModel.cs new file mode 100644 index 00000000..df7b7a0c --- /dev/null +++ b/src/Calculator.ManagedViewModels/ApplicationViewModel.cs @@ -0,0 +1,384 @@ +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Diagnostics; +using System.Runtime.CompilerServices; +using System.Threading.Tasks; +using System.Windows.Input; + +using Windows.Foundation; +using Windows.Storage; +using Windows.UI.Core; +using Windows.UI.ViewManagement; +using Windows.UI.Xaml; + +using CalculatorApp.ViewModel; +using CalculatorApp.ViewModel.Common; +using CalculatorApp.ViewModel.Snapshot; + +namespace CalculatorApp.ManagedViewModels +{ + public class ApplicationViewModel : INotifyPropertyChanged + { + private StandardCalculatorViewModel _calcVm; + private DateCalculatorViewModel _dateVm; + private GraphingCalculatorViewModel _graphVm; + private UnitConverterViewModel _unitVm; + private ViewMode _mode = ViewMode.None; + private ViewMode _previousMode = ViewMode.None; + private bool _isAlwaysOnTop = false; + private bool _displayNormalAlwaysOnTopOption; + private string _categoryName; + private IList _categories = NavCategoryStates.CreateMenuOptions(); + + public const string WidthLocalSettingsKey = "calculatorAlwaysOnTopLastWidth"; + public const string HeightLocalSettingsKey = "calculatorAlwaysOnTopLastHeight"; + + public event PropertyChangedEventHandler PropertyChanged; + + public ViewMode Mode + { + get => _mode; + set + { + if (_mode != value) + { + PreviousMode = _mode; + _mode = value; + SetDisplayNormalAlwaysOnTopOption(); + OnModeChanged(); + RaisePropertyChanged(); + } + } + } + + public ICommand CopyCommand => new RelayCommand(OnCopyCommand); + + public ICommand PasteCommand => new RelayCommand(OnPasteCommand); + + public Visibility ClearMemoryVisibility + { + get => NavCategory.IsCalculatorViewMode(_mode) ? + Visibility.Visible : Visibility.Collapsed; + } + + public ApplicationSnapshot Snapshot + { + get + { + var snapshot = new ApplicationSnapshot(); + snapshot.Mode = (int)_mode; + if (_calcVm != null) + { + snapshot.StandardCalculator = _calcVm.Snapshot; + } + return snapshot; + } + } + + public StandardCalculatorViewModel CalculatorViewModel + { + get => _calcVm; + set + { + if (_calcVm != value) + { + _calcVm = value; + RaisePropertyChanged(); + } + } + } + + public DateCalculatorViewModel DateCalcViewModel + { + get => _dateVm; + set + { + if (_dateVm != value) + { + _dateVm = value; + RaisePropertyChanged(); + } + } + } + + public GraphingCalculatorViewModel GraphingCalcViewModel + { + get => _graphVm; + set + { + if (_graphVm != value) + { + _graphVm = value; + RaisePropertyChanged(); + } + } + } + + public UnitConverterViewModel ConverterViewModel + { + get => _unitVm; + set + { + if (_unitVm != value) + { + _unitVm = value; + RaisePropertyChanged(); + } + } + } + + public ViewMode PreviousMode + { + get => _previousMode; + set + { + if (_previousMode != value) + { + _previousMode = value; + RaisePropertyChanged(); + } + } + } + + public bool IsAlwaysOnTop + { + get => _isAlwaysOnTop; + private set + { + if (_isAlwaysOnTop != value) + { + _isAlwaysOnTop = value; + RaisePropertyChanged(); + } + } + } + + // Indicates whether calculator is currently in standard mode _and_ supports CompactOverlay _and_ is not in Always-on-Top mode + public bool DisplayNormalAlwaysOnTopOption + { + get => _displayNormalAlwaysOnTopOption; + private set + { + if (_displayNormalAlwaysOnTopOption != value) + { + _displayNormalAlwaysOnTopOption = value; + RaisePropertyChanged(); + } + } + } + + public string CategoryName + { + get => _categoryName; + set + { + if (_categoryName != value) + { + _categoryName = value; + RaisePropertyChanged(); + } + } + } + + public IList Categories + { + get => _categories; + set + { + if (_categories != value) + { + _categories = value; + RaisePropertyChanged(); + } + } + } + + public async Task ToggleAlwaysOnTop(float width, float height) + { + var DefaultSize = new Size(320, 394); + const string LaunchedSettingsKey = "calculatorAlwaysOnTopLaunched"; + var settings = ApplicationData.Current.LocalSettings; + if (ApplicationView.GetForCurrentView().ViewMode == ApplicationViewMode.CompactOverlay) + { + settings.Values[WidthLocalSettingsKey] = width; + settings.Values[HeightLocalSettingsKey] = height; + bool success = await ApplicationView.GetForCurrentView().TryEnterViewModeAsync(ApplicationViewMode.Default); + _calcVm.HistoryVM.AreHistoryShortcutsEnabled = success; + _calcVm.IsAlwaysOnTop = !success; + IsAlwaysOnTop = !success; + } + else + { + var compactOptions = ViewModePreferences.CreateDefault(ApplicationViewMode.CompactOverlay); + if (!settings.Values.ContainsKey(LaunchedSettingsKey)) + { + compactOptions.CustomSize = DefaultSize; + settings.Values[LaunchedSettingsKey] = true; + } + else + { + if (settings.Values.TryGetValue(WidthLocalSettingsKey, out var oldWidth) && + settings.Values.TryGetValue(HeightLocalSettingsKey, out var oldHeight)) + { + compactOptions.CustomSize = new Size((float)oldWidth, (float)oldHeight); + } + else + { + compactOptions.CustomSize = DefaultSize; + } + } + bool success = await ApplicationView.GetForCurrentView().TryEnterViewModeAsync(ApplicationViewMode.CompactOverlay, compactOptions); + _calcVm.HistoryVM.AreHistoryShortcutsEnabled = !success; + _calcVm.IsAlwaysOnTop = success; + IsAlwaysOnTop = success; + } + SetDisplayNormalAlwaysOnTopOption(); + } + + public void Initialize(ViewMode mode) + { + if (!NavCategoryStates.IsValidViewMode(mode) || !NavCategoryStates.IsViewModeEnabled(mode)) + { + mode = ViewMode.Standard; + } + try + { + Mode = mode; + } + catch (Exception e) + { + TraceLogger.GetInstance().LogError(mode, nameof(Initialize), e.Message); + if (!TryRecoverFromNavigationModeFailure()) + { + // Could not navigate to standard mode either. + // Throw the original exception so we have a good stack to debug. + throw; + } + } + } + + public void RestoreFromSnapshot(ApplicationSnapshot snapshot) + { + Mode = (ViewMode)snapshot.Mode; + if (snapshot.StandardCalculator != null) + { + _calcVm.Snapshot = snapshot.StandardCalculator; + } + } + + private void OnModeChanged() + { + Debug.Assert(NavCategoryStates.IsValidViewMode(_mode)); + if (NavCategory.IsCalculatorViewMode(_mode)) + { + if (_calcVm == null) + { + _calcVm = new StandardCalculatorViewModel(); + } + _calcVm.SetCalculatorType(_mode); + } + else if (NavCategory.IsGraphingCalculatorViewMode(_mode)) + { + if (_graphVm == null) + { + _graphVm = new GraphingCalculatorViewModel(); + } + } + else if (NavCategory.IsDateCalculatorViewMode(_mode)) + { + if (_dateVm == null) + { + _dateVm = new DateCalculatorViewModel(); + } + } + else if (NavCategory.IsConverterViewMode(_mode)) + { + if (_unitVm == null) + { + _unitVm = new UnitConverterViewModel(); + } + _unitVm.Mode = _mode; + } + + var resProvider = AppResourceProvider.GetInstance(); + CategoryName = resProvider.GetResourceString(NavCategoryStates.GetNameResourceKey(_mode)); + + // Cast mode to an int in order to save it to app data. + // Save the changed mode, so that the new window launches in this mode. + // Don't save until after we have adjusted to the new mode, so we don't save a mode that fails to load. + ApplicationData.Current.LocalSettings.Values[nameof(Mode)] = NavCategoryStates.Serialize(_mode); + + // Log ModeChange event when not first launch, log WindowCreated on first launch + if (NavCategoryStates.IsValidViewMode(_previousMode)) + { + TraceLogger.GetInstance().LogModeChange(_mode); + } + else + { + TraceLogger.GetInstance().LogWindowCreated( + _mode, + ApplicationView.GetApplicationViewIdForWindow(CoreWindow.GetForCurrentThread())); + } + RaisePropertyChanged(nameof(ClearMemoryVisibility)); + } + + private void OnCopyCommand(object param) + { + if (NavCategory.IsConverterViewMode(_mode)) + { + _unitVm.OnCopyCommand(param); + } + else if (NavCategory.IsDateCalculatorViewMode(_mode)) + { + _dateVm.OnCopyCommand(param); + } + else if (NavCategory.IsCalculatorViewMode(_mode)) + { + _calcVm.OnCopyCommand(param); + } + } + + private void OnPasteCommand(object param) + { + if (NavCategory.IsConverterViewMode(_mode)) + { + _unitVm.OnPasteCommand(param); + } + else if (NavCategory.IsCalculatorViewMode(_mode)) + { + _calcVm.OnPasteCommand(param); + } + } + + private void SetDisplayNormalAlwaysOnTopOption() + { + DisplayNormalAlwaysOnTopOption = _mode == ViewMode.Standard && + ApplicationView.GetForCurrentView().IsViewModeSupported(ApplicationViewMode.CompactOverlay) && + !_isAlwaysOnTop; + } + + private bool TryRecoverFromNavigationModeFailure() + { + // Here we are simply trying to recover from being unable to navigate to a mode. + // Try falling back to standard mode and if there are *any* exceptions, we should + // fail because something is seriously wrong. + try + { + Mode = ViewMode.Standard; + return true; + } + catch + { + return false; + } + } + + private void RaisePropertyChanged([CallerMemberName] string propertyName = null) + { + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + } + } +} diff --git a/src/Calculator.ManagedViewModels/Calculator.ManagedViewModels.csproj b/src/Calculator.ManagedViewModels/Calculator.ManagedViewModels.csproj new file mode 100644 index 00000000..23ff71e6 --- /dev/null +++ b/src/Calculator.ManagedViewModels/Calculator.ManagedViewModels.csproj @@ -0,0 +1,150 @@ + + + + + Debug + AnyCPU + {2179CFDE-CDED-4DF0-8C24-A0EF6B425771} + Library + Properties + Calculator.ManagedViewModels + Calculator.ManagedViewModels + en-US + UAP + 10.0.22000.0 + 10.0.17763.0 + 14 + 512 + {A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE;NETFX_CORE;WINDOWS_UWP + prompt + 4 + + + x86 + true + bin\x86\Debug\ + DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP + ;2008 + full + false + prompt + + + x86 + bin\x86\Release\ + TRACE;NETFX_CORE;WINDOWS_UWP + true + ;2008 + pdbonly + false + prompt + + + ARM + true + bin\ARM\Debug\ + DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP + ;2008 + full + false + prompt + + + ARM + bin\ARM\Release\ + TRACE;NETFX_CORE;WINDOWS_UWP + true + ;2008 + pdbonly + false + prompt + + + ARM64 + true + bin\ARM64\Debug\ + DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP + ;2008 + full + false + prompt + + + ARM64 + bin\ARM64\Release\ + TRACE;NETFX_CORE;WINDOWS_UWP + true + ;2008 + pdbonly + false + prompt + + + x64 + true + bin\x64\Debug\ + DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP + ;2008 + full + false + prompt + + + x64 + bin\x64\Release\ + TRACE;NETFX_CORE;WINDOWS_UWP + true + ;2008 + pdbonly + false + prompt + + + PackageReference + + + + + + + + + + 6.2.14 + + + + + {812d1a7b-b8ac-49e4-8e6d-af5d59500d56} + CalcViewModel + + + + 14.0 + + + + \ No newline at end of file diff --git a/src/Calculator.ManagedViewModels/Properties/AssemblyInfo.cs b/src/Calculator.ManagedViewModels/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..bfe8e0f4 --- /dev/null +++ b/src/Calculator.ManagedViewModels/Properties/AssemblyInfo.cs @@ -0,0 +1,8 @@ +using System.Reflection; +using System.Runtime.InteropServices; + +[assembly: AssemblyTitle("Calculator.ManagedViewModels")] +[assembly: AssemblyCompany("Microsoft Corporation")] +[assembly: AssemblyProduct("Microsoft Windows Calculator")] +[assembly: AssemblyCopyright("Copyright © 2025")] +[assembly: ComVisible(false)] diff --git a/src/Calculator.ManagedViewModels/Properties/Calculator.ManagedViewModels.rd.xml b/src/Calculator.ManagedViewModels/Properties/Calculator.ManagedViewModels.rd.xml new file mode 100644 index 00000000..aad8b7c7 --- /dev/null +++ b/src/Calculator.ManagedViewModels/Properties/Calculator.ManagedViewModels.rd.xml @@ -0,0 +1,33 @@ + + + + + + + + + diff --git a/src/Calculator.ManagedViewModels/RelayCommand.cs b/src/Calculator.ManagedViewModels/RelayCommand.cs new file mode 100644 index 00000000..4692dd77 --- /dev/null +++ b/src/Calculator.ManagedViewModels/RelayCommand.cs @@ -0,0 +1,36 @@ +// Licensed under the MIT License. + +using System; +using System.Windows.Input; + +namespace CalculatorApp.ManagedViewModels +{ + public class RelayCommand: ICommand + { + private readonly Action _execute; + private readonly Func _canExecute; + + public RelayCommand(Action execute, Func canExecute = null) + { + _execute = execute ?? throw new ArgumentNullException(nameof(execute)); + _canExecute = canExecute; + } + + public event EventHandler CanExecuteChanged; + + public bool CanExecute(object parameter) + { + return _canExecute == null || _canExecute(parameter); + } + + public void Execute(object parameter) + { + _execute(parameter); + } + + public void RaiseCanExecuteChanged() + { + CanExecuteChanged?.Invoke(this, EventArgs.Empty); + } + } +} diff --git a/src/Calculator.sln b/src/Calculator.sln index 9458f929..4e53844c 100644 --- a/src/Calculator.sln +++ b/src/Calculator.sln @@ -29,6 +29,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TraceLogging", "TraceLoggin EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CalcViewModelCopyForUT", "CalcViewModelCopyForUT\CalcViewModelCopyForUT.vcxproj", "{CC9B4FA7-D746-4F52-9401-0AD1B4D6B16D}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Calculator.ManagedViewModels", "Calculator.ManagedViewModels\Calculator.ManagedViewModels.csproj", "{2179CFDE-CDED-4DF0-8C24-A0EF6B425771}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|ARM = Debug|ARM @@ -41,6 +43,30 @@ Global Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution + {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 {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 @@ -169,30 +195,6 @@ 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 @@ -207,6 +209,22 @@ Global {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 + {2179CFDE-CDED-4DF0-8C24-A0EF6B425771}.Debug|ARM.ActiveCfg = Debug|ARM + {2179CFDE-CDED-4DF0-8C24-A0EF6B425771}.Debug|ARM.Build.0 = Debug|ARM + {2179CFDE-CDED-4DF0-8C24-A0EF6B425771}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {2179CFDE-CDED-4DF0-8C24-A0EF6B425771}.Debug|ARM64.Build.0 = Debug|ARM64 + {2179CFDE-CDED-4DF0-8C24-A0EF6B425771}.Debug|x64.ActiveCfg = Debug|x64 + {2179CFDE-CDED-4DF0-8C24-A0EF6B425771}.Debug|x64.Build.0 = Debug|x64 + {2179CFDE-CDED-4DF0-8C24-A0EF6B425771}.Debug|x86.ActiveCfg = Debug|x86 + {2179CFDE-CDED-4DF0-8C24-A0EF6B425771}.Debug|x86.Build.0 = Debug|x86 + {2179CFDE-CDED-4DF0-8C24-A0EF6B425771}.Release|ARM.ActiveCfg = Release|ARM + {2179CFDE-CDED-4DF0-8C24-A0EF6B425771}.Release|ARM.Build.0 = Release|ARM + {2179CFDE-CDED-4DF0-8C24-A0EF6B425771}.Release|ARM64.ActiveCfg = Release|ARM64 + {2179CFDE-CDED-4DF0-8C24-A0EF6B425771}.Release|ARM64.Build.0 = Release|ARM64 + {2179CFDE-CDED-4DF0-8C24-A0EF6B425771}.Release|x64.ActiveCfg = Release|x64 + {2179CFDE-CDED-4DF0-8C24-A0EF6B425771}.Release|x64.Build.0 = Release|x64 + {2179CFDE-CDED-4DF0-8C24-A0EF6B425771}.Release|x86.ActiveCfg = Release|x86 + {2179CFDE-CDED-4DF0-8C24-A0EF6B425771}.Release|x86.Build.0 = Release|x86 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/src/Calculator/Calculator.csproj b/src/Calculator/Calculator.csproj index 00bdc954..004d36a6 100644 --- a/src/Calculator/Calculator.csproj +++ b/src/Calculator/Calculator.csproj @@ -806,6 +806,10 @@ + + {2179cfde-cded-4df0-8c24-a0ef6b425771} + Calculator.ManagedViewModels + {812d1a7b-b8ac-49e4-8e6d-af5d59500d56} CalcViewModel diff --git a/src/Calculator/Common/KeyboardShortcutManager.cs b/src/Calculator/Common/KeyboardShortcutManager.cs index 141298bb..22494bfa 100644 --- a/src/Calculator/Common/KeyboardShortcutManager.cs +++ b/src/Calculator/Common/KeyboardShortcutManager.cs @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -using CalculatorApp.ViewModel; +using CalculatorApp.ManagedViewModels; using CalculatorApp.ViewModel.Common; using System; diff --git a/src/Calculator/Views/MainPage.xaml.cs b/src/Calculator/Views/MainPage.xaml.cs index 32bfdb26..078cabd6 100644 --- a/src/Calculator/Views/MainPage.xaml.cs +++ b/src/Calculator/Views/MainPage.xaml.cs @@ -19,7 +19,7 @@ using Microsoft.UI.Xaml.Controls; using CalculatorApp.Common; using CalculatorApp.Converters; using CalculatorApp.JsonUtils; -using CalculatorApp.ViewModel; +using CalculatorApp.ManagedViewModels; using CalculatorApp.ViewModel.Common; using CalculatorApp.ViewModel.Common.Automation; @@ -159,9 +159,9 @@ namespace CalculatorApp { var initialMode = ViewMode.Standard; var localSettings = ApplicationData.Current.LocalSettings; - if (localSettings.Values.ContainsKey(ApplicationViewModel.ModePropertyName)) + if (localSettings.Values.ContainsKey(nameof(ApplicationViewModel.Mode))) { - initialMode = NavCategoryStates.Deserialize(localSettings.Values[ApplicationViewModel.ModePropertyName]); + initialMode = NavCategoryStates.Deserialize(localSettings.Values[nameof(ApplicationViewModel.Mode)]); } if (e.Parameter == null) @@ -202,12 +202,6 @@ namespace CalculatorApp private void InitializeNavViewCategoriesSource() { NavViewCategoriesSource = ExpandNavViewCategoryGroups(Model.Categories); - Model.Categories.VectorChanged += (sender, args) => - { - NavViewCategoriesSource.Clear(); - NavViewCategoriesSource = ExpandNavViewCategoryGroups(Model.Categories); - }; - _ = Window.Current.Dispatcher.RunAsync(CoreDispatcherPriority.Low, () => { var graphCategory = (NavCategory)NavViewCategoriesSource.Find(x => @@ -258,7 +252,7 @@ namespace CalculatorApp private void OnAppPropertyChanged(object sender, PropertyChangedEventArgs e) { string propertyName = e.PropertyName; - if (propertyName == ApplicationViewModel.ModePropertyName) + if (propertyName == nameof(ApplicationViewModel.Mode)) { ViewMode newValue = Model.Mode; ViewMode previousMode = Model.PreviousMode; @@ -324,7 +318,7 @@ namespace CalculatorApp UpdateViewState(); SetDefaultFocus(); } - else if (propertyName == ApplicationViewModel.CategoryNamePropertyName) + else if (propertyName == nameof(ApplicationViewModel.CategoryName)) { SetHeaderAutomationName(); AnnounceCategoryName(); @@ -541,8 +535,8 @@ namespace CalculatorApp if (Model.IsAlwaysOnTop) { ApplicationDataContainer localSettings = ApplicationData.Current.LocalSettings; - localSettings.Values[ApplicationViewModel.WidthLocalSettings] = ActualWidth; - localSettings.Values[ApplicationViewModel.HeightLocalSettings] = ActualHeight; + localSettings.Values[ApplicationViewModel.WidthLocalSettingsKey] = ActualWidth; + localSettings.Values[ApplicationViewModel.HeightLocalSettingsKey] = ActualHeight; } } diff --git a/src/CalculatorUnitTests/NavCategoryUnitTests.cpp b/src/CalculatorUnitTests/NavCategoryUnitTests.cpp index bdcb9d71..c38c1feb 100644 --- a/src/CalculatorUnitTests/NavCategoryUnitTests.cpp +++ b/src/CalculatorUnitTests/NavCategoryUnitTests.cpp @@ -98,14 +98,14 @@ namespace CalculatorUnitTests public: TEST_METHOD(CreateNavCategoryGroup) { - IObservableVector ^ menuOptions = NavCategoryStates::CreateMenuOptions(); + IVector ^ menuOptions = NavCategoryStates::CreateMenuOptions(); VERIFY_ARE_EQUAL(2, menuOptions->Size); NavCategoryGroup ^ calculatorGroup = menuOptions->GetAt(0); VERIFY_ARE_EQUAL(CategoryGroupType::Calculator, calculatorGroup->GroupType); - IObservableVector ^ calculatorCategories = calculatorGroup->Categories; + IVector ^ calculatorCategories = calculatorGroup->Categories; ValidateNavCategory(calculatorCategories, 0u, ViewMode::Standard); ValidateNavCategory(calculatorCategories, 1u, ViewMode::Scientific); ValidateNavCategory(calculatorCategories, 2u, ViewMode::Graphing); @@ -116,7 +116,7 @@ namespace CalculatorUnitTests NavCategoryGroup ^ converterGroup = menuOptions->GetAt(1); VERIFY_ARE_EQUAL(CategoryGroupType::Converter, converterGroup->GroupType); - IObservableVector ^ converterCategories = converterGroup->Categories; + IVector ^ converterCategories = converterGroup->Categories; VERIFY_ARE_EQUAL(13, converterCategories->Size); ValidateNavCategory(converterCategories, 0u, ViewMode::Currency); ValidateNavCategory(converterCategories, 1u, ViewMode::Volume); @@ -134,7 +134,7 @@ namespace CalculatorUnitTests } private: - void ValidateNavCategory(IObservableVector ^ categories, unsigned int index, ViewMode expectedMode) + void ValidateNavCategory(IVector ^ categories, unsigned int index, ViewMode expectedMode) { VERIFY_IS_LESS_THAN(0u, categories->Size); VERIFY_IS_GREATER_THAN(categories->Size, index);