diff --git a/src/CalcViewModel/StandardCalculatorViewModel.cpp b/src/CalcViewModel/StandardCalculatorViewModel.cpp index b915f950..6bf064e5 100644 --- a/src/CalcViewModel/StandardCalculatorViewModel.cpp +++ b/src/CalcViewModel/StandardCalculatorViewModel.cpp @@ -78,7 +78,7 @@ StandardCalculatorViewModel::StandardCalculatorViewModel() , m_IsShiftProgrammerChecked(false) , m_valueBitLength(BitLength::BitLengthQWord) , m_isBitFlipChecked(false) - , m_isBinaryBitFlippingEnabled(false) + , m_IsBinaryBitFlippingEnabled(false) , m_CurrentRadixType(NumberBase::DecBase) , m_CurrentAngleType(NumbersAndOperatorsEnum::Degree) , m_Announcement(nullptr) @@ -93,6 +93,8 @@ StandardCalculatorViewModel::StandardCalculatorViewModel() , m_localizedMemoryCleared(nullptr) , m_localizedOpenParenthesisCountChangedAutomationFormat(nullptr) , m_localizedNoRightParenthesisAddedFormat(nullptr) + , m_TokenPosition(-1) + , m_isLastOperationHistoryLoad(false) { WeakReference calculatorViewModel(this); auto appResourceProvider = AppResourceProvider::GetInstance(); @@ -130,9 +132,6 @@ StandardCalculatorViewModel::StandardCalculatorViewModel() IsDecimalEnabled = true; AreHistoryShortcutsEnabled = true; AreProgrammerRadixOperatorsEnabled = false; - - m_tokenPosition = -1; - m_isLastOperationHistoryLoad = false; } String ^ StandardCalculatorViewModel::LocalizeDisplayValue(_In_ wstring const& displayValue, _In_ bool isError) @@ -455,7 +454,7 @@ void StandardCalculatorViewModel::FtoEButtonToggled() void StandardCalculatorViewModel::HandleUpdatedOperandData(Command cmdenum) { - DisplayExpressionToken ^ displayExpressionToken = ExpressionTokens->GetAt(m_tokenPosition); + DisplayExpressionToken ^ displayExpressionToken = ExpressionTokens->GetAt(m_TokenPosition); if (displayExpressionToken == nullptr) { return; @@ -583,7 +582,7 @@ void StandardCalculatorViewModel::HandleUpdatedOperandData(Command cmdenum) } String ^ updatedData = ref new String(temp); - UpdateOperand(m_tokenPosition, updatedData); + UpdateOperand(m_TokenPosition, updatedData); displayExpressionToken->Token = updatedData; IsOperandUpdatedUsingViewModel = true; displayExpressionToken->CommandIndex = commandIndex; @@ -622,7 +621,7 @@ void StandardCalculatorViewModel::OnButtonPressed(Object ^ parameter) && numOpEnum != NumbersAndOperatorsEnum::IsProgrammerMode && numOpEnum != NumbersAndOperatorsEnum::FToE && (numOpEnum != NumbersAndOperatorsEnum::Degree) && (numOpEnum != NumbersAndOperatorsEnum::Radians) && (numOpEnum != NumbersAndOperatorsEnum::Grads)) { - if (!m_keyPressed) + if (!m_KeyPressed) { SaveEditedCommand(m_selectedExpressionToken->TokenPosition, cmdenum); } @@ -765,9 +764,10 @@ void StandardCalculatorViewModel::OnPaste(String ^ pastedString) while (it != pastedString->End()) { bool sendCommand = true; - bool canSendNegate = false; + auto buttonInfo = MapCharacterToButtonId(*it); - NumbersAndOperatorsEnum mappedNumOp = MapCharacterToButtonId(*it, canSendNegate); + NumbersAndOperatorsEnum mappedNumOp = buttonInfo.buttonId; + bool canSendNegate = buttonInfo.canSendNegate; if (mappedNumOp == NumbersAndOperatorsEnum::None) { @@ -869,7 +869,7 @@ void StandardCalculatorViewModel::OnPaste(String ^ pastedString) if (mappedNumOp == NumbersAndOperatorsEnum::Exp) { // Check the following item - switch (MapCharacterToButtonId(*(it + 1), canSendNegate)) + switch (MapCharacterToButtonId(*(it + 1)).buttonId) { case NumbersAndOperatorsEnum::Subtract: { @@ -919,10 +919,11 @@ void StandardCalculatorViewModel::SetViewPinnedState(bool pinned) IsCurrentViewPinned = pinned; } -NumbersAndOperatorsEnum StandardCalculatorViewModel::MapCharacterToButtonId(const wchar_t ch, bool& canSendNegate) +ButtonInfo StandardCalculatorViewModel::MapCharacterToButtonId(char16 ch) { - NumbersAndOperatorsEnum mappedValue = NumbersAndOperatorsEnum::None; - canSendNegate = false; + ButtonInfo result; + result.buttonId = NumbersAndOperatorsEnum::None; + result.canSendNegate = false; switch (ch) { @@ -936,112 +937,111 @@ NumbersAndOperatorsEnum StandardCalculatorViewModel::MapCharacterToButtonId(cons case '7': case '8': case '9': - mappedValue = NumbersAndOperatorsEnum::Zero + static_cast(ch - L'0'); - canSendNegate = true; + result.buttonId = NumbersAndOperatorsEnum::Zero + static_cast(ch - L'0'); + result.canSendNegate = true; break; case '*': - mappedValue = NumbersAndOperatorsEnum::Multiply; + result.buttonId = NumbersAndOperatorsEnum::Multiply; break; case '+': - mappedValue = NumbersAndOperatorsEnum::Add; + result.buttonId = NumbersAndOperatorsEnum::Add; break; case '-': - mappedValue = NumbersAndOperatorsEnum::Subtract; + result.buttonId = NumbersAndOperatorsEnum::Subtract; break; case '/': - mappedValue = NumbersAndOperatorsEnum::Divide; + result.buttonId = NumbersAndOperatorsEnum::Divide; break; case '^': if (IsScientific) { - mappedValue = NumbersAndOperatorsEnum::XPowerY; + result.buttonId = NumbersAndOperatorsEnum::XPowerY; } break; case '%': if (IsScientific || IsProgrammer) { - mappedValue = NumbersAndOperatorsEnum::Mod; + result.buttonId = NumbersAndOperatorsEnum::Mod; } break; case '=': - mappedValue = NumbersAndOperatorsEnum::Equals; + result.buttonId = NumbersAndOperatorsEnum::Equals; break; case '(': - mappedValue = NumbersAndOperatorsEnum::OpenParenthesis; + result.buttonId = NumbersAndOperatorsEnum::OpenParenthesis; break; case ')': - mappedValue = NumbersAndOperatorsEnum::CloseParenthesis; + result.buttonId = NumbersAndOperatorsEnum::CloseParenthesis; break; case 'a': case 'A': - mappedValue = NumbersAndOperatorsEnum::A; + result.buttonId = NumbersAndOperatorsEnum::A; break; case 'b': case 'B': - mappedValue = NumbersAndOperatorsEnum::B; + result.buttonId = NumbersAndOperatorsEnum::B; break; case 'c': case 'C': - mappedValue = NumbersAndOperatorsEnum::C; + result.buttonId = NumbersAndOperatorsEnum::C; break; case 'd': case 'D': - mappedValue = NumbersAndOperatorsEnum::D; + result.buttonId = NumbersAndOperatorsEnum::D; break; case 'e': case 'E': // Only allow scientific notation in scientific mode if (IsProgrammer) { - mappedValue = NumbersAndOperatorsEnum::E; + result.buttonId = NumbersAndOperatorsEnum::E; } else { - mappedValue = NumbersAndOperatorsEnum::Exp; + result.buttonId = NumbersAndOperatorsEnum::Exp; } break; case 'f': case 'F': - mappedValue = NumbersAndOperatorsEnum::F; + result.buttonId = NumbersAndOperatorsEnum::F; break; default: // For the decimalSeparator, we need to respect the user setting. if (ch == m_decimalSeparator) { - mappedValue = NumbersAndOperatorsEnum::Decimal; + result.buttonId = NumbersAndOperatorsEnum::Decimal; } break; } - if (mappedValue == NumbersAndOperatorsEnum::None) + if (result.buttonId == NumbersAndOperatorsEnum::None) { if (LocalizationSettings::GetInstance().IsLocalizedDigit(ch)) { - mappedValue = - NumbersAndOperatorsEnum::Zero + static_cast(ch - LocalizationSettings::GetInstance().GetDigitSymbolFromEnUsDigit('0')); - canSendNegate = true; + result.buttonId = NumbersAndOperatorsEnum::Zero + + static_cast(ch - LocalizationSettings::GetInstance().GetDigitSymbolFromEnUsDigit('0')); + result.canSendNegate = true; } } // Negate cannot be sent for leading zeroes - if (NumbersAndOperatorsEnum::Zero == mappedValue) + if (NumbersAndOperatorsEnum::Zero == result.buttonId) { - canSendNegate = false; + result.canSendNegate = false; } - return mappedValue; + return result; } - void StandardCalculatorViewModel::OnInputChanged() { IsInputEmpty = m_standardCalculatorManager.IsInputEmpty(); diff --git a/src/CalcViewModel/StandardCalculatorViewModel.h b/src/CalcViewModel/StandardCalculatorViewModel.h index c6a60e8b..fcd808d5 100644 --- a/src/CalcViewModel/StandardCalculatorViewModel.h +++ b/src/CalcViewModel/StandardCalculatorViewModel.h @@ -20,7 +20,6 @@ namespace CalculatorFunctionalTests namespace CalculatorUnitTests { class MultiWindowUnitTests; - class TimerTests; } namespace CalculatorApp @@ -31,8 +30,13 @@ namespace CalculatorApp namespace ViewModel { #define ASCII_0 48 - public - delegate void HideMemoryClickedHandler(); + public delegate void HideMemoryClickedHandler(); + + public value struct ButtonInfo + { + NumbersAndOperatorsEnum buttonId; + bool canSendNegate; + }; [Windows::UI::Xaml::Data::Bindable] public ref class StandardCalculatorViewModel sealed : public Windows::UI::Xaml::Data::INotifyPropertyChanged { @@ -43,40 +47,47 @@ namespace CalculatorApp OBSERVABLE_OBJECT_CALLBACK(OnPropertyChanged); OBSERVABLE_PROPERTY_RW(Platform::String ^, DisplayValue); - OBSERVABLE_PROPERTY_RW(HistoryViewModel ^, HistoryVM); - OBSERVABLE_NAMED_PROPERTY_RW(bool, IsInError); - OBSERVABLE_PROPERTY_RW(bool, IsOperatorCommand); - OBSERVABLE_PROPERTY_RW(Platform::String ^, DisplayStringExpression); + OBSERVABLE_PROPERTY_R(HistoryViewModel ^, HistoryVM); + OBSERVABLE_PROPERTY_RW(bool, IsAlwaysOnTop); + OBSERVABLE_PROPERTY_R(bool, IsBinaryBitFlippingEnabled); + PROPERTY_R(bool, IsOperandUpdatedUsingViewModel); + PROPERTY_R(int, TokenPosition); + PROPERTY_R(bool, IsOperandTextCompletelySelected); + PROPERTY_R(bool, KeyPressed); + PROPERTY_R(Platform::String ^, SelectedExpressionLastData); + OBSERVABLE_NAMED_PROPERTY_R(bool, IsInError); + OBSERVABLE_PROPERTY_R(bool, IsOperatorCommand); + OBSERVABLE_PROPERTY_R(Platform::String ^, DisplayStringExpression); OBSERVABLE_PROPERTY_R(Windows::Foundation::Collections::IObservableVector ^, ExpressionTokens); - OBSERVABLE_PROPERTY_RW(Platform::String ^, DecimalDisplayValue); - OBSERVABLE_PROPERTY_RW(Platform::String ^, HexDisplayValue); - OBSERVABLE_PROPERTY_RW(Platform::String ^, OctalDisplayValue); - OBSERVABLE_NAMED_PROPERTY_RW(Platform::String ^, BinaryDisplayValue); + OBSERVABLE_PROPERTY_R(Platform::String ^, DecimalDisplayValue); + OBSERVABLE_PROPERTY_R(Platform::String ^, HexDisplayValue); + OBSERVABLE_PROPERTY_R(Platform::String ^, OctalDisplayValue); + OBSERVABLE_NAMED_PROPERTY_R(Platform::String ^, BinaryDisplayValue); OBSERVABLE_NAMED_PROPERTY_R(Windows::Foundation::Collections::IVector ^, BinaryDigits); - OBSERVABLE_PROPERTY_RW(Platform::String ^, HexDisplayValue_AutomationName); - OBSERVABLE_PROPERTY_RW(Platform::String ^, DecDisplayValue_AutomationName); - OBSERVABLE_PROPERTY_RW(Platform::String ^, OctDisplayValue_AutomationName); - OBSERVABLE_PROPERTY_RW(Platform::String ^, BinDisplayValue_AutomationName); - OBSERVABLE_PROPERTY_RW(bool, IsBinaryOperatorEnabled); - OBSERVABLE_PROPERTY_RW(bool, IsUnaryOperatorEnabled); - OBSERVABLE_PROPERTY_RW(bool, IsNegateEnabled); + OBSERVABLE_PROPERTY_R(Platform::String ^, HexDisplayValue_AutomationName); + OBSERVABLE_PROPERTY_R(Platform::String ^, DecDisplayValue_AutomationName); + OBSERVABLE_PROPERTY_R(Platform::String ^, OctDisplayValue_AutomationName); + OBSERVABLE_PROPERTY_R(Platform::String ^, BinDisplayValue_AutomationName); + OBSERVABLE_PROPERTY_R(bool, IsBinaryOperatorEnabled); + OBSERVABLE_PROPERTY_R(bool, IsUnaryOperatorEnabled); + OBSERVABLE_PROPERTY_R(bool, IsNegateEnabled); OBSERVABLE_PROPERTY_RW(bool, IsDecimalEnabled); - OBSERVABLE_PROPERTY_RW(bool, IsCurrentViewPinned); - OBSERVABLE_PROPERTY_RW(Windows::Foundation::Collections::IVector ^, MemorizedNumbers); + OBSERVABLE_PROPERTY_R(bool, IsCurrentViewPinned); + OBSERVABLE_PROPERTY_R(Windows::Foundation::Collections::IVector ^, MemorizedNumbers); OBSERVABLE_NAMED_PROPERTY_RW(bool, IsMemoryEmpty); - OBSERVABLE_PROPERTY_RW(bool, IsFToEChecked); + OBSERVABLE_PROPERTY_R(bool, IsFToEChecked); OBSERVABLE_PROPERTY_R(bool, IsFToEEnabled); - OBSERVABLE_PROPERTY_RW(bool, AreHEXButtonsEnabled); - OBSERVABLE_PROPERTY_RW(Platform::String ^, CalculationResultAutomationName); - OBSERVABLE_PROPERTY_RW(Platform::String ^, CalculationExpressionAutomationName); - OBSERVABLE_PROPERTY_RW(bool, IsShiftProgrammerChecked); - OBSERVABLE_PROPERTY_RW(CalculatorApp::Common::NumberBase, CurrentRadixType); - OBSERVABLE_PROPERTY_RW(bool, AreTokensUpdated); - OBSERVABLE_PROPERTY_RW(bool, AreAlwaysOnTopResultsUpdated); + OBSERVABLE_PROPERTY_R(bool, AreHEXButtonsEnabled); + 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(bool, AreTokensUpdated); + OBSERVABLE_PROPERTY_R(bool, AreAlwaysOnTopResultsUpdated); OBSERVABLE_PROPERTY_RW(bool, AreHistoryShortcutsEnabled); - OBSERVABLE_PROPERTY_RW(bool, AreProgrammerRadixOperatorsEnabled); - OBSERVABLE_PROPERTY_RW(bool, IsInputEmpty); - OBSERVABLE_PROPERTY_RW(CalculatorApp::Common::Automation::NarratorAnnouncement ^, Announcement); + OBSERVABLE_PROPERTY_R(bool, AreProgrammerRadixOperatorsEnabled); + OBSERVABLE_PROPERTY_R(bool, IsInputEmpty); + OBSERVABLE_PROPERTY_R(CalculatorApp::Common::Automation::NarratorAnnouncement ^, Announcement); OBSERVABLE_PROPERTY_R(unsigned int, OpenParenthesisCount); COMMAND_FOR_METHOD(CopyCommand, StandardCalculatorViewModel::OnCopyCommand); @@ -109,22 +120,6 @@ namespace CalculatorApp static property Platform::String ^ IsBitFlipCheckedPropertyName { Platform::String ^ get() { return Platform::StringReference(L"IsBitFlipChecked"); } } - property bool IsBinaryBitFlippingEnabled - { - bool get() - { - return m_isBinaryBitFlippingEnabled; - } - void set(bool value) - { - if (m_isBinaryBitFlippingEnabled != value) - { - m_isBinaryBitFlippingEnabled = value; - RaisePropertyChanged(L"IsBinaryBitFlippingEnabled"); - } - } - } - property CalculatorApp::Common::BitLength ValueBitLength { CalculatorApp::Common::BitLength get() @@ -205,22 +200,6 @@ namespace CalculatorApp static property Platform::String ^ IsProgrammerPropertyName { Platform::String ^ get() { return Platform::StringReference(L"IsProgrammer"); } } - property bool IsAlwaysOnTop - { - bool get() - { - return m_isAlwaysOnTop; - } - void set(bool value) - { - if (m_isAlwaysOnTop != value) - { - m_isAlwaysOnTop = value; - RaisePropertyChanged(L"IsAlwaysOnTop"); - } - } - } - property bool IsEditingEnabled { bool get() @@ -271,65 +250,12 @@ namespace CalculatorApp } } - property int TokenPosition - { - int get() - { - return m_tokenPosition; - } - void set(int value) - { - m_tokenPosition = value; - } - } - - property Platform::String^ SelectedExpressionLastData - { - Platform::String^ get() { return m_selectedExpressionLastData; } - void set(Platform::String^ value) { m_selectedExpressionLastData = value; } - } - - property bool KeyPressed - { - bool get() - { - return m_keyPressed; - } - void set(bool value) - { - m_keyPressed = value; - } - } - - property bool IsOperandUpdatedUsingViewModel - { - bool get() - { - return m_operandUpdated; - } - void set(bool value) - { - m_operandUpdated = value; - } - } - - property bool IsOperandTextCompletelySelected - { - bool get() - { - return m_completeTextSelection; - } - void set(bool value) - { - m_completeTextSelection = value; - } - } - - internal : void OnPaste(Platform::String ^ pastedString); + internal : + void OnPaste(Platform::String ^ pastedString); void OnCopyCommand(Platform::Object ^ parameter); void OnPasteCommand(Platform::Object ^ parameter); - NumbersAndOperatorsEnum MapCharacterToButtonId(const wchar_t ch, bool& canSendNegate); + ButtonInfo MapCharacterToButtonId(char16 ch); // Memory feature related methods. They are internal because they need to called from the MainPage code-behind void OnMemoryButtonPressed(); @@ -413,14 +339,9 @@ namespace CalculatorApp bool m_isStandard; bool m_isScientific; bool m_isProgrammer; - bool m_isAlwaysOnTop; - bool m_isBinaryBitFlippingEnabled; bool m_isBitFlipChecked; bool m_isRtlLanguage; - int m_tokenPosition; - bool m_keyPressed; bool m_operandUpdated; - bool m_completeTextSelection; bool m_isLastOperationHistoryLoad; CalculatorApp::Common::BitLength m_valueBitLength; Platform::String ^ m_selectedExpressionLastData; @@ -463,7 +384,6 @@ namespace CalculatorApp friend class CalculatorDisplay; friend class CalculatorFunctionalTests::HistoryTests; friend class CalculatorUnitTests::MultiWindowUnitTests; - friend class CalculatorUnitTests::TimerTests; }; } } diff --git a/src/CalculatorUnitTests/StandardViewModelUnitTests.cpp b/src/CalculatorUnitTests/StandardViewModelUnitTests.cpp index d1ddf30e..6bf7dff8 100644 --- a/src/CalculatorUnitTests/StandardViewModelUnitTests.cpp +++ b/src/CalculatorUnitTests/StandardViewModelUnitTests.cpp @@ -373,27 +373,25 @@ namespace CalculatorUnitTests /// Low-level test of character mapping TEST_METHOD(VerifyCorrectCharacterMapping) { - bool canSendNegate = false; - // Valid numbers - NumbersAndOperatorsEnum n = m_viewModel->MapCharacterToButtonId(L'0', canSendNegate); + NumbersAndOperatorsEnum n = m_viewModel->MapCharacterToButtonId(L'0').buttonId; ValidateNumbersAndOperatorsAreEqual(n, NumbersAndOperatorsEnum::Zero); - n = m_viewModel->MapCharacterToButtonId(L'1', canSendNegate); + n = m_viewModel->MapCharacterToButtonId(L'1').buttonId; ValidateNumbersAndOperatorsAreEqual(n, NumbersAndOperatorsEnum::One); // Valid operators - n = m_viewModel->MapCharacterToButtonId(L'+', canSendNegate); + n = m_viewModel->MapCharacterToButtonId(L'+').buttonId; ValidateNumbersAndOperatorsAreEqual(n, NumbersAndOperatorsEnum::Add); - n = m_viewModel->MapCharacterToButtonId(L'=', canSendNegate); + n = m_viewModel->MapCharacterToButtonId(L'=').buttonId; ValidateNumbersAndOperatorsAreEqual(n, NumbersAndOperatorsEnum::Equals); - n = m_viewModel->MapCharacterToButtonId(L'a', canSendNegate); + n = m_viewModel->MapCharacterToButtonId(L'a').buttonId; ValidateNumbersAndOperatorsAreEqual(n, NumbersAndOperatorsEnum::A); // Invalid character - n = m_viewModel->MapCharacterToButtonId(L'$', canSendNegate); + n = m_viewModel->MapCharacterToButtonId(L'$').buttonId; ValidateNumbersAndOperatorsAreEqual(n, NumbersAndOperatorsEnum::None); }