// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. #pragma once #include "Common/Automation/NarratorAnnouncement.h" #include "Common/DisplayExpressionToken.h" #include "Common/CalculatorDisplay.h" #include "Common/EngineResourceProvider.h" #include "Common/CalculatorButtonUser.h" #include "HistoryViewModel.h" #include "MemoryItemViewModel.h" namespace CalculatorFunctionalTests { class HistoryTests; } namespace CalculatorUnitTests { class MultiWindowUnitTests; class TimerTests; } namespace CalculatorApp { namespace WS = Windows::System; namespace CM = CalculationManager; namespace ViewModel { #define ASCII_0 48 public delegate void HideMemoryClickedHandler(); public delegate void ProgModeRadixChangeHandler(); [Windows::UI::Xaml::Data::Bindable] public ref class StandardCalculatorViewModel sealed : public Windows::UI::Xaml::Data::INotifyPropertyChanged { public: StandardCalculatorViewModel(); void UpdateOperand(int pos, Platform::String ^ text); void UpdatecommandsInRecordingMode(); int GetBitLengthType(); int GetNumberBase(); 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(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_RW(Platform::String ^, HexDisplayValue_AutomationName); OBSERVABLE_PROPERTY_RW(Platform::String ^, DecDisplayValue_AutomationName); OBSERVABLE_PROPERTY_RW(Platform::String ^, OctDisplayValue_AutomationName); OBSERVABLE_PROPERTY_RW(Platform::String ^, BinDisplayValue_AutomationName); OBSERVABLE_PROPERTY_RW(bool, IsBinaryOperatorEnabled); OBSERVABLE_PROPERTY_RW(bool, IsUnaryOperatorEnabled); OBSERVABLE_PROPERTY_RW(bool, IsNegateEnabled); OBSERVABLE_PROPERTY_RW(bool, IsDecimalEnabled); OBSERVABLE_PROPERTY_RW(bool, IsCurrentViewPinned); OBSERVABLE_PROPERTY_RW(Windows::Foundation::Collections::IVector ^, MemorizedNumbers); OBSERVABLE_NAMED_PROPERTY_RW(bool, IsMemoryEmpty); OBSERVABLE_PROPERTY_RW(bool, IsFToEChecked); OBSERVABLE_PROPERTY_RW(bool, IsFToEEnabled); OBSERVABLE_PROPERTY_RW(bool, IsHyperbolicChecked); OBSERVABLE_PROPERTY_RW(bool, AreHEXButtonsEnabled); OBSERVABLE_PROPERTY_RW(Platform::String ^, CalculationResultAutomationName); OBSERVABLE_PROPERTY_RW(Platform::String ^, CalculationExpressionAutomationName); OBSERVABLE_PROPERTY_RW(bool, IsShiftProgrammerChecked); OBSERVABLE_PROPERTY_RW(bool, IsQwordEnabled); OBSERVABLE_PROPERTY_RW(bool, IsDwordEnabled); OBSERVABLE_PROPERTY_RW(bool, IsWordEnabled); OBSERVABLE_PROPERTY_RW(bool, IsByteEnabled); OBSERVABLE_PROPERTY_RW(int, CurrentRadixType); OBSERVABLE_PROPERTY_RW(bool, AreTokensUpdated); OBSERVABLE_PROPERTY_RW(bool, AreAlwaysOnTopResultsUpdated); OBSERVABLE_PROPERTY_RW(bool, AreHistoryShortcutsEnabled); OBSERVABLE_PROPERTY_RW(bool, AreProgrammerRadixOperatorsEnabled); OBSERVABLE_PROPERTY_RW(CalculatorApp::Common::Automation::NarratorAnnouncement ^, Announcement); OBSERVABLE_PROPERTY_R(unsigned int, OpenParenthesisCount); COMMAND_FOR_METHOD(CopyCommand, StandardCalculatorViewModel::OnCopyCommand); COMMAND_FOR_METHOD(PasteCommand, StandardCalculatorViewModel::OnPasteCommand); COMMAND_FOR_METHOD(ButtonPressed, StandardCalculatorViewModel::OnButtonPressed); COMMAND_FOR_METHOD(ClearMemoryCommand, StandardCalculatorViewModel::OnClearMemoryCommand); COMMAND_FOR_METHOD(MemoryItemPressed, StandardCalculatorViewModel::OnMemoryItemPressed); COMMAND_FOR_METHOD(MemoryAdd, StandardCalculatorViewModel::OnMemoryAdd); COMMAND_FOR_METHOD(MemorySubtract, StandardCalculatorViewModel::OnMemorySubtract); event HideMemoryClickedHandler ^ HideMemoryClicked; event ProgModeRadixChangeHandler ^ ProgModeRadixChange; property bool IsShiftChecked { bool get() { return m_isShiftChecked; } void set(bool value) { if (m_isShiftChecked != value) { m_isShiftChecked = value; RaisePropertyChanged(L"IsShiftChecked"); } } } property bool IsBitFlipChecked { bool get() { return m_isBitFlipChecked; } void set(bool value) { if (m_isBitFlipChecked != value) { m_isBitFlipChecked = value; IsBinaryBitFlippingEnabled = IsProgrammer && m_isBitFlipChecked; AreProgrammerRadixOperatorsEnabled = IsProgrammer && !m_isBitFlipChecked; RaisePropertyChanged(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 bool IsStandard { bool get() { return m_isStandard; } void set(bool value) { if (m_isStandard != value) { m_isStandard = value; if (value) { IsScientific = false; IsProgrammer = false; } RaisePropertyChanged(L"IsStandard"); } } } property bool IsScientific { bool get() { return m_isScientific; } void set(bool value) { if (m_isScientific != value) { m_isScientific = value; if (value) { IsStandard = false; IsProgrammer = false; } RaisePropertyChanged(L"IsScientific"); } } } property bool IsProgrammer { bool get() { return m_isProgrammer; } void set(bool value) { if (m_isProgrammer != value) { m_isProgrammer = value; if (!m_isProgrammer) { IsBitFlipChecked = false; } IsBinaryBitFlippingEnabled = m_isProgrammer && IsBitFlipChecked; AreProgrammerRadixOperatorsEnabled = m_isProgrammer && !IsBitFlipChecked; if (value) { IsStandard = false; IsScientific = false; } RaisePropertyChanged(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() { return m_isEditingEnabled; } void set(bool value) { if (m_isEditingEnabled != value) { // Numbers::Common::KeyboardShortcutManager::IsCalculatorInEditingMode = value; m_isEditingEnabled = value; bool currentEditToggleValue = !m_isEditingEnabled; IsBinaryOperatorEnabled = currentEditToggleValue; IsUnaryOperatorEnabled = currentEditToggleValue; IsOperandEnabled = currentEditToggleValue; IsNegateEnabled = currentEditToggleValue; IsDecimalEnabled = currentEditToggleValue; RaisePropertyChanged(L"IsEditingEnabled"); } } } property bool IsEngineRecording { bool get() { return m_standardCalculatorManager.IsEngineRecording(); } } property bool IsOperandEnabled { bool get() { return m_isOperandEnabled; } void set(bool value) { if (m_isOperandEnabled != value) { m_isOperandEnabled = value; IsDecimalEnabled = value; AreHEXButtonsEnabled = IsProgrammer; IsFToEEnabled = value; RaisePropertyChanged(L"IsOperandEnabled"); } } } 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); void OnCopyCommand(Platform::Object ^ parameter); void OnPasteCommand(Platform::Object ^ parameter); NumbersAndOperatorsEnum MapCharacterToButtonId(const wchar_t ch, bool& canSendNegate); // Memory feature related methods. They are internal because they need to called from the MainPage code-behind void OnMemoryButtonPressed(); void OnMemoryItemPressed(Platform::Object ^ memoryItemPosition); void OnMemoryAdd(Platform::Object ^ memoryItemPosition); void OnMemorySubtract(Platform::Object ^ memoryItemPosition); void OnMemoryClear(_In_ Platform::Object ^ memoryItemPosition); void OnPinUnpinCommand(Platform::Object ^ parameter); void SetPrimaryDisplay(_In_ std::wstring const& displayString, _In_ bool isError); void DisplayPasteError(); void SetTokens(_Inout_ std::shared_ptr>> const& tokens); void SetExpressionDisplay( _Inout_ std::shared_ptr>> const& tokens, _Inout_ std::shared_ptr>> const& commands); void SetHistoryExpressionDisplay( _Inout_ std::shared_ptr>> const& tokens, _Inout_ std::shared_ptr>> const& commands); void SetParenthesisCount(_In_ unsigned int parenthesisCount); void SetOpenParenthesisCountNarratorAnnouncement(); void OnNoRightParenAdded(); void SetNoParenAddedNarratorAnnouncement(); void OnMaxDigitsReached(); void OnBinaryOperatorReceived(); void OnMemoryItemChanged(unsigned int indexOfMemory); Platform::String ^ GetLocalizedStringFormat(Platform::String ^ format, Platform::String ^ displayValue); void OnPropertyChanged(Platform::String ^ propertyname); void SetCalculatorType(CalculatorApp::Common::ViewMode targetState); Platform::String ^ GetRawDisplayValue(); void Recalculate(bool fromHistory = false); bool IsOperator(CalculationManager::Command cmdenum); void FtoEButtonToggled(); void SwitchProgrammerModeBase(RADIX_TYPE calculatorBase); void SetMemorizedNumbersString(); void SwitchAngleType(NumbersAndOperatorsEnum num); void ResetDisplay(); RADIX_TYPE GetCurrentRadixType() { return (RADIX_TYPE)m_CurrentRadixType; } void SetPrecision(int32_t precision); void UpdateMaxIntDigits() { m_standardCalculatorManager.UpdateMaxIntDigits(); } NumbersAndOperatorsEnum GetCurrentAngleType() { return m_CurrentAngleType; } private: void SetMemorizedNumbers(const std::vector& memorizedNumbers); void UpdateProgrammerPanelDisplay(); void HandleUpdatedOperandData(CalculationManager::Command cmdenum); NumbersAndOperatorsEnum ConvertIntegerToNumbersAndOperatorsEnum(unsigned int parameter); NumbersAndOperatorsEnum m_CurrentAngleType; wchar_t m_decimalSeparator; CalculatorDisplay m_calculatorDisplay; CalculatorApp::EngineResourceProvider m_resourceProvider; CalculationManager::CalculatorManager m_standardCalculatorManager; Platform::String ^ m_expressionAutomationNameFormat; Platform::String ^ m_localizedCalculationResultAutomationFormat; Platform::String ^ m_localizedCalculationResultDecimalAutomationFormat; Platform::String ^ m_localizedHexaDecimalAutomationFormat; Platform::String ^ m_localizedDecimalAutomationFormat; Platform::String ^ m_localizedOctalAutomationFormat; Platform::String ^ m_localizedBinaryAutomationFormat; Platform::String ^ m_localizedMaxDigitsReachedAutomationFormat; Platform::String ^ m_localizedButtonPressFeedbackAutomationFormat; Platform::String ^ m_localizedMemorySavedAutomationFormat; Platform::String ^ m_localizedMemoryItemChangedAutomationFormat; Platform::String ^ m_localizedMemoryItemClearedAutomationFormat; Platform::String ^ m_localizedMemoryCleared; Platform::String ^ m_localizedOpenParenthesisCountChangedAutomationFormat; Platform::String ^ m_localizedNoRightParenthesisAddedFormat; bool m_pinned; bool m_isOperandEnabled; bool m_isEditingEnabled; bool m_isStandard; bool m_isScientific; bool m_isProgrammer; bool m_isAlwaysOnTop; bool m_isBinaryBitFlippingEnabled; bool m_isBitFlipChecked; bool m_isShiftChecked; bool m_isRtlLanguage; int m_tokenPosition; bool m_keyPressed; bool m_operandUpdated; bool m_completeTextSelection; bool m_isLastOperationHistoryLoad; Platform::String ^ m_selectedExpressionLastData; Common::DisplayExpressionToken ^ m_selectedExpressionToken; Platform::String ^ LocalizeDisplayValue(_In_ std::wstring const& displayValue, _In_ bool isError); Platform::String ^ CalculateNarratorDisplayValue(_In_ std::wstring const& displayValue, _In_ Platform::String ^ localizedDisplayValue, _In_ bool isError); CalculatorApp::Common::Automation::NarratorAnnouncement ^ GetDisplayUpdatedNarratorAnnouncement(); Platform::String ^ GetCalculatorExpressionAutomationName(); Platform::String ^ GetNarratorStringReadRawNumbers(_In_ Platform::String ^ localizedDisplayValue); CalculationManager::Command ConvertToOperatorsEnum(NumbersAndOperatorsEnum operation); void DisableButtons(CalculationManager::CommandType selectedExpressionCommandType); Platform::String ^ m_feedbackForButtonPress; void OnButtonPressed(Platform::Object ^ parameter); void OnClearMemoryCommand(Platform::Object ^ parameter); std::wstring AddPadding(std::wstring); size_t LengthWithoutPadding(std::wstring); std::shared_ptr>> m_tokens; std::shared_ptr>> m_commands; // Token types bool IsUnaryOp(int nOpCode); bool IsBinOp(int nOpcode); bool IsTrigOp(int nOpCode); bool IsOpnd(int nOpCode); bool IsRecoverableCommand(int nOpCode); CalculationManager::CommandType GetSelectedTokenType(_In_ unsigned int); void SaveEditedCommand(_In_ unsigned int index, _In_ CalculationManager::Command command); bool IsViewPinned(); void SetViewPinnedState(bool pinned); CalculatorApp::Common::ViewMode GetCalculatorMode(); friend class CalculatorDisplay; friend class CalculatorFunctionalTests::HistoryTests; friend class CalculatorUnitTests::MultiWindowUnitTests; friend class CalculatorUnitTests::TimerTests; }; } }