diff --git a/src/CalcManager/CEngine/History.cpp b/src/CalcManager/CEngine/History.cpp index f45ff090..e0cb5337 100644 --- a/src/CalcManager/CEngine/History.cpp +++ b/src/CalcManager/CEngine/History.cpp @@ -3,7 +3,6 @@ #include "Header Files/CalcEngine.h" #include "Command.h" -#include "ExpressionCommand.h" #include "winerror_cross_platform.h" constexpr int ASCII_0 = 48; @@ -66,47 +65,7 @@ CHistoryCollector::~CHistoryCollector() void CHistoryCollector::AddOpndToHistory(wstring_view numStr, Rational const& rat, bool fRepetition) { - std::shared_ptr> commands = std::make_shared>(); - // Check for negate - bool fNegative = (numStr[0] == L'-'); - bool fSciFmt = false; - bool fDecimal = false; - - for (size_t i = (fNegative ? 1 : 0); i < numStr.length(); i++) - { - if (numStr[i] == m_decimalSymbol) - { - commands->push_back(IDC_PNT); - if (!fSciFmt) - { - fDecimal = true; - } - } - else if (numStr[i] == L'e') - { - commands->push_back(IDC_EXP); - fSciFmt = true; - } - else if (numStr[i] == L'-') - { - commands->push_back(IDC_SIGN); - } - else if (numStr[i] == L'+') - { - // Ignore. - } - // Number - else - { - int num = static_cast(numStr[i]) - ASCII_0; - num += IDC_0; - commands->push_back(num); - } - } - - auto operandCommand = std::make_shared(commands, fNegative, fDecimal, fSciFmt); - operandCommand->Initialize(rat); - int iCommandEnd = AddCommand(operandCommand); + int iCommandEnd = AddCommand(GetOperandCommandsFromString(numStr, rat)); m_lastOpStartIndex = IchAddSzToEquationSz(numStr, iCommandEnd); if (fRepetition) @@ -201,7 +160,7 @@ void CHistoryCollector::EnclosePrecInversionBrackets() IchAddSzToEquationSz(CCalcEngine::OpCodeToString(IDC_CLOSEP), -1); } -bool CHistoryCollector::FOpndAddedToHistory() +bool CHistoryCollector::FOpndAddedToHistory() const { return (-1 != m_lastOpStartIndex); } @@ -465,7 +424,7 @@ void CHistoryCollector::SetDecimalSymbol(wchar_t decimalSymbol) } // Update the commands corresponding to the passed string Number -std::shared_ptr> CHistoryCollector::GetOperandCommandsFromString(wstring_view numStr) +std::shared_ptr> CHistoryCollector::GetOperandCommandsFromString(wstring_view numStr) const { std::shared_ptr> commands = std::make_shared>(); // Check for negate @@ -505,3 +464,58 @@ std::shared_ptr> CHistoryCollector::GetOperandCommandsFromStrin } return commands; } + +std::shared_ptr CHistoryCollector::GetOperandCommandsFromString(std::wstring_view numStr, Rational const& rat) const +{ + std::shared_ptr> commands = std::make_shared>(); + // Check for negate + bool fNegative = (numStr[0] == L'-'); + bool fSciFmt = false; + bool fDecimal = false; + + for (size_t i = (fNegative ? 1 : 0); i < numStr.length(); i++) + { + if (numStr[i] == m_decimalSymbol) + { + commands->push_back(IDC_PNT); + if (!fSciFmt) + { + fDecimal = true; + } + } + else if (numStr[i] == L'e') + { + commands->push_back(IDC_EXP); + fSciFmt = true; + } + else if (numStr[i] == L'-') + { + commands->push_back(IDC_SIGN); + } + else if (numStr[i] == L'+') + { + // Ignore. + } + // Number + else + { + int num = static_cast(numStr[i]) - ASCII_0; + num += IDC_0; + commands->push_back(num); + } + } + + auto operandCommand = std::make_shared(commands, fNegative, fDecimal, fSciFmt); + operandCommand->Initialize(rat); + return operandCommand; +} + +std::vector> CHistoryCollector::GetCommands() const +{ + std::vector> commands; + if (m_spCommands != nullptr) + { + commands = *m_spCommands; + } + return commands; +} diff --git a/src/CalcManager/CEngine/calc.cpp b/src/CalcManager/CEngine/calc.cpp index 713a661c..7ef2acb7 100644 --- a/src/CalcManager/CEngine/calc.cpp +++ b/src/CalcManager/CEngine/calc.cpp @@ -202,3 +202,13 @@ wchar_t CCalcEngine::DecimalSeparator() const { return m_decimalSeparator; } + +std::vector> CCalcEngine::GetHistoryCollectorCommandsSnapshot() const +{ + auto commands = m_HistoryCollector.GetCommands(); + if (!m_HistoryCollector.FOpndAddedToHistory() && m_bRecord) + { + commands.push_back(m_HistoryCollector.GetOperandCommandsFromString(m_numberString, m_currentVal)); + } + return commands; +} diff --git a/src/CalcManager/CalculatorManager.cpp b/src/CalcManager/CalculatorManager.cpp index c32a027d..e2d6a802 100644 --- a/src/CalcManager/CalculatorManager.cpp +++ b/src/CalcManager/CalculatorManager.cpp @@ -597,4 +597,9 @@ namespace CalculationManager { m_inHistoryItemLoadMode = isHistoryItemLoadMode; } + + std::vector> CalculatorManager::GetDisplayCommandsSnapshot() const + { + return m_currentCalculatorEngine->GetHistoryCollectorCommandsSnapshot(); + } } diff --git a/src/CalcManager/CalculatorManager.h b/src/CalcManager/CalculatorManager.h index 5db70b65..035c5a64 100644 --- a/src/CalcManager/CalculatorManager.h +++ b/src/CalcManager/CalculatorManager.h @@ -119,5 +119,6 @@ namespace CalculationManager } CalculationManager::Command GetCurrentDegreeMode(); void SetInHistoryItemLoadMode(_In_ bool isHistoryItemLoadMode); + std::vector> GetDisplayCommandsSnapshot() const; }; } diff --git a/src/CalcManager/Header Files/CalcEngine.h b/src/CalcManager/Header Files/CalcEngine.h index f387c020..eaa2956b 100644 --- a/src/CalcManager/Header Files/CalcEngine.h +++ b/src/CalcManager/Header Files/CalcEngine.h @@ -89,6 +89,8 @@ public: void UpdateMaxIntDigits(); wchar_t DecimalSeparator() const; + std::vector> GetHistoryCollectorCommandsSnapshot() const; + // Static methods for the instance static void InitialOneTimeOnlySetup(CalculationManager::IResourceProvider& resourceProvider); // Once per load time to call to initialize all shared global variables diff --git a/src/CalcManager/Header Files/History.h b/src/CalcManager/Header Files/History.h index 9eb0bd71..a437a975 100644 --- a/src/CalcManager/Header Files/History.h +++ b/src/CalcManager/Header Files/History.h @@ -4,10 +4,13 @@ #pragma once #include +#include "ExpressionCommand.h" #include "ICalcDisplay.h" #include "IHistoryDisplay.h" #include "Rational.h" +class COpndCommand; + // maximum depth you can get by precedence. It is just an array's size limit. static constexpr size_t MAXPRECDEPTH = 25; @@ -29,13 +32,15 @@ public: void PushLastOpndStart(int ichOpndStart = -1); void PopLastOpndStart(); void EnclosePrecInversionBrackets(); - bool FOpndAddedToHistory(); + bool FOpndAddedToHistory() const; void CompleteHistoryLine(std::wstring_view numStr); void CompleteEquation(std::wstring_view numStr); void ClearHistoryLine(std::wstring_view errStr); int AddCommand(_In_ const std::shared_ptr& spCommand); void UpdateHistoryExpression(uint32_t radix, int32_t precision); void SetDecimalSymbol(wchar_t decimalSymbol); + std::shared_ptr GetOperandCommandsFromString(std::wstring_view numStr, CalcEngine::Rational const& rat) const; + std::vector> GetCommands() const; private: std::shared_ptr m_pHistoryDisplay; @@ -60,5 +65,5 @@ private: void TruncateEquationSzFromIch(int ich); void SetExpressionDisplay(); void InsertSzInEquationSz(std::wstring_view str, int icommandIndex, int ich); - std::shared_ptr> GetOperandCommandsFromString(std::wstring_view numStr); + std::shared_ptr> GetOperandCommandsFromString(std::wstring_view numStr) const; }; diff --git a/src/CalcViewModel/ApplicationViewModel.cpp b/src/CalcViewModel/ApplicationViewModel.cpp index 3b831645..7a54182d 100644 --- a/src/CalcViewModel/ApplicationViewModel.cpp +++ b/src/CalcViewModel/ApplicationViewModel.cpp @@ -63,6 +63,12 @@ namespace { jsonObject->SetNamedValue(L"ExpressionDisplay", SaveSnapshotToJson(*value.ExpressionDisplay)); } + auto commandsJsonArray = ref new Windows::Data::Json::JsonArray(); + for (const auto& command : value.DisplayCommands) + { + commandsJsonArray->Append(SaveSnapshotToJson(command)); + } + jsonObject->SetNamedValue(L"DisplayCommands", commandsJsonArray); return jsonObject; } @@ -270,6 +276,7 @@ namespace return; } } + standardCalculatorSnapshot.DisplayCommands = RestoreExpressionCommandsFromJsonArray(jsonObject->GetNamedArray(L"DisplayCommands")); value = std::move(standardCalculatorSnapshot); } diff --git a/src/CalcViewModel/StandardCalculatorViewModel.cpp b/src/CalcViewModel/StandardCalculatorViewModel.cpp index 42546906..04735680 100644 --- a/src/CalcViewModel/StandardCalculatorViewModel.cpp +++ b/src/CalcViewModel/StandardCalculatorViewModel.cpp @@ -42,6 +42,57 @@ namespace StringReference IsBitFlipCheckedPropertyName(L"IsBitFlipChecked"); StringReference CalcAlwaysOnTop(L"CalcAlwaysOnTop"); StringReference CalcBackToFullView(L"CalcBackToFullView"); + + std::vector GetCommandsFromExpressionCommands(const std::vector>& expressionCommands) + { + vector commands; + for (const auto& command : expressionCommands) + { + CommandType commandType = command->GetCommandType(); + + if (commandType == CommandType::UnaryCommand) + { + shared_ptr spCommand = dynamic_pointer_cast(command); + const shared_ptr>& unaryCommands = spCommand->GetCommands(); + + for (int nUCode : *unaryCommands) + { + commands.push_back(nUCode); + } + } + + if (commandType == CommandType::BinaryCommand) + { + shared_ptr spCommand = dynamic_pointer_cast(command); + commands.push_back(spCommand->GetCommand()); + } + + if (commandType == CommandType::Parentheses) + { + shared_ptr spCommand = dynamic_pointer_cast(command); + commands.push_back(spCommand->GetCommand()); + } + + if (commandType == CommandType::OperandCommand) + { + shared_ptr spCommand = dynamic_pointer_cast(command); + const shared_ptr>& opndCommands = spCommand->GetCommands(); + bool fNeedIDCSign = spCommand->IsNegative(); + + for (int nOCode : *opndCommands) + { + commands.push_back(nOCode); + + if (fNeedIDCSign && nOCode != IDC_0) + { + commands.push_back(static_cast(CalculationManager::Command::CommandSIGN)); + fNeedIDCSign = false; + } + } + } + } + return commands; + } } namespace CalculatorResourceKeys @@ -1388,55 +1439,8 @@ void StandardCalculatorViewModel::Recalculate(bool fromHistory) { // Recalculate Command currentDegreeMode = m_standardCalculatorManager.GetCurrentDegreeMode(); - shared_ptr>> savedCommands = make_shared>>(); - vector currentCommands; - - for (const auto& command : *m_commands) - { - savedCommands->push_back(command); - CommandType commandType = command->GetCommandType(); - - if (commandType == CommandType::UnaryCommand) - { - shared_ptr spCommand = dynamic_pointer_cast(command); - const shared_ptr>& unaryCommands = spCommand->GetCommands(); - - for (int nUCode : *unaryCommands) - { - currentCommands.push_back(nUCode); - } - } - - if (commandType == CommandType::BinaryCommand) - { - shared_ptr spCommand = dynamic_pointer_cast(command); - currentCommands.push_back(spCommand->GetCommand()); - } - - if (commandType == CommandType::Parentheses) - { - shared_ptr spCommand = dynamic_pointer_cast(command); - currentCommands.push_back(spCommand->GetCommand()); - } - - if (commandType == CommandType::OperandCommand) - { - shared_ptr spCommand = dynamic_pointer_cast(command); - const shared_ptr>& opndCommands = spCommand->GetCommands(); - bool fNeedIDCSign = spCommand->IsNegative(); - - for (int nOCode : *opndCommands) - { - currentCommands.push_back(nOCode); - - if (fNeedIDCSign && nOCode != IDC_0) - { - currentCommands.push_back(static_cast(CalculationManager::Command::CommandSIGN)); - fNeedIDCSign = false; - } - } - } - } + shared_ptr>> savedCommands = std::make_shared>>(*m_commands); + vector currentCommands = GetCommandsFromExpressionCommands(*m_commands); shared_ptr>> savedTokens = make_shared>>(); @@ -1796,6 +1800,7 @@ StandardCalculatorSnapshot StandardCalculatorViewModel::GetStandardCalculatorSna { snapshot.ExpressionDisplay = { *m_tokens, *m_commands }; } + snapshot.DisplayCommands = m_standardCalculatorManager.GetDisplayCommandsSnapshot(); return snapshot; } @@ -1805,11 +1810,26 @@ void StandardCalculatorViewModel::SetStandardCalculatorSnapshot(const StandardCa { m_standardCalculatorManager.SetHistoryItems(snapshot.CalcManager.HistoryItems.value()); } - SetPrimaryDisplay(snapshot.PrimaryDisplay.DisplayValue, snapshot.PrimaryDisplay.IsError); + + std::vector commands; + if (snapshot.ExpressionDisplay.has_value() && snapshot.ExpressionDisplay->Tokens.back().first == L"=") + { + commands = GetCommandsFromExpressionCommands(snapshot.ExpressionDisplay->Commands); + } + if (commands.empty() && !snapshot.DisplayCommands.empty()) + { + commands = GetCommandsFromExpressionCommands(snapshot.DisplayCommands); + } + for (const auto& command : commands) + { + m_standardCalculatorManager.SendCommand(static_cast(command)); + } + if (snapshot.ExpressionDisplay.has_value()) { SetExpressionDisplay( std::make_shared>>(snapshot.ExpressionDisplay->Tokens), std::make_shared>>(snapshot.ExpressionDisplay->Commands)); } + SetPrimaryDisplay(snapshot.PrimaryDisplay.DisplayValue, snapshot.PrimaryDisplay.IsError); } diff --git a/src/CalcViewModel/StandardCalculatorViewModel.h b/src/CalcViewModel/StandardCalculatorViewModel.h index dd5c102c..160a7fe8 100644 --- a/src/CalcViewModel/StandardCalculatorViewModel.h +++ b/src/CalcViewModel/StandardCalculatorViewModel.h @@ -55,6 +55,7 @@ namespace CalculatorApp CalculatorManagerSnapshot CalcManager; PrimaryDisplaySnapshot PrimaryDisplay; std::optional ExpressionDisplay; + std::vector> DisplayCommands; }; [Windows::UI::Xaml::Data::Bindable] public ref class StandardCalculatorViewModel sealed : public Windows::UI::Xaml::Data::INotifyPropertyChanged