stash changes

This commit is contained in:
Tian Liao 2024-10-16 14:20:29 +08:00
commit ff9d026ea7
8 changed files with 686 additions and 542 deletions

View file

@ -38,445 +38,445 @@ namespace
StringReference CategoriesPropertyName(L"Categories"); StringReference CategoriesPropertyName(L"Categories");
StringReference ClearMemoryVisibilityPropertyName(L"ClearMemoryVisibility"); StringReference ClearMemoryVisibilityPropertyName(L"ClearMemoryVisibility");
struct SnapshotHelper //struct SnapshotHelper
{ //{
static constexpr int SnapshotVersion = 0; // static constexpr int SnapshotVersion = 0;
static Windows::Data::Json::JsonObject ^ SaveSnapshotToJson(const ApplicationSnapshot& value) // static Windows::Data::Json::JsonObject ^ SaveSnapshotToJson(const ApplicationSnapshot& value)
{ // {
auto jsonObject = ref new Windows::Data::Json::JsonObject(); // auto jsonObject = ref new Windows::Data::Json::JsonObject();
jsonObject->SetNamedValue(L"SnapshotVersion", Windows::Data::Json::JsonValue::CreateNumberValue(value.SnapshotVersion)); // jsonObject->SetNamedValue(L"SnapshotVersion", Windows::Data::Json::JsonValue::CreateNumberValue(value.SnapshotVersion));
jsonObject->SetNamedValue(L"Mode", Windows::Data::Json::JsonValue::CreateNumberValue(value.Mode)); // jsonObject->SetNamedValue(L"Mode", Windows::Data::Json::JsonValue::CreateNumberValue(value.Mode));
if (value.StandardCalc.has_value()) // if (value.StandardCalc.has_value())
{ // {
jsonObject->SetNamedValue(L"StandardCalculatorSnapshot", SaveSnapshotToJson(*value.StandardCalc)); // jsonObject->SetNamedValue(L"StandardCalculatorSnapshot", SaveSnapshotToJson(*value.StandardCalc));
} // }
return jsonObject; // return jsonObject;
} // }
static Windows::Data::Json::JsonObject ^ SaveSnapshotToJson(const StandardCalculatorSnapshot& value) // static Windows::Data::Json::JsonObject ^ SaveSnapshotToJson(const StandardCalculatorSnapshot& value)
{ // {
auto jsonObject = ref new Windows::Data::Json::JsonObject(); // auto jsonObject = ref new Windows::Data::Json::JsonObject();
jsonObject->SetNamedValue(L"CalculatorManagerSnapshot", SaveSnapshotToJson(value.CalcManager)); // jsonObject->SetNamedValue(L"CalculatorManagerSnapshot", SaveSnapshotToJson(value.CalcManager));
jsonObject->SetNamedValue(L"PrimaryDisplay", SaveSnapshotToJson(value.PrimaryDisplay)); // jsonObject->SetNamedValue(L"PrimaryDisplay", SaveSnapshotToJson(value.PrimaryDisplay));
if (value.ExpressionDisplay.has_value()) // if (value.ExpressionDisplay.has_value())
{ // {
jsonObject->SetNamedValue(L"ExpressionDisplay", SaveSnapshotToJson(*value.ExpressionDisplay)); // jsonObject->SetNamedValue(L"ExpressionDisplay", SaveSnapshotToJson(*value.ExpressionDisplay));
} // }
auto commandsJsonArray = ref new Windows::Data::Json::JsonArray(); // auto commandsJsonArray = ref new Windows::Data::Json::JsonArray();
for (const auto& command : value.DisplayCommands) // for (const auto& command : value.DisplayCommands)
{ // {
commandsJsonArray->Append(SaveSnapshotToJson(command)); // commandsJsonArray->Append(SaveSnapshotToJson(command));
} // }
jsonObject->SetNamedValue(L"DisplayCommands", commandsJsonArray); // jsonObject->SetNamedValue(L"DisplayCommands", commandsJsonArray);
return jsonObject; // return jsonObject;
} // }
static Windows::Data::Json::JsonObject ^ SaveSnapshotToJson(const PrimaryDisplaySnapshot& value) // static Windows::Data::Json::JsonObject ^ SaveSnapshotToJson(const PrimaryDisplaySnapshot& value)
{ // {
auto jsonObject = ref new Windows::Data::Json::JsonObject(); // auto jsonObject = ref new Windows::Data::Json::JsonObject();
jsonObject->SetNamedValue(L"DisplayValue", Windows::Data::Json::JsonValue::CreateStringValue(value.DisplayValue)); // jsonObject->SetNamedValue(L"DisplayValue", Windows::Data::Json::JsonValue::CreateStringValue(value.DisplayValue));
jsonObject->SetNamedValue(L"IsError", Windows::Data::Json::JsonValue::CreateBooleanValue(value.IsError)); // jsonObject->SetNamedValue(L"IsError", Windows::Data::Json::JsonValue::CreateBooleanValue(value.IsError));
return jsonObject; // return jsonObject;
} // }
static Windows::Data::Json::JsonObject ^ SaveSnapshotToJson(const ExpressionDisplaySnapshot& value) // static Windows::Data::Json::JsonObject ^ SaveSnapshotToJson(const ExpressionDisplaySnapshot& value)
{ // {
auto jsonObject = ref new Windows::Data::Json::JsonObject(); // auto jsonObject = ref new Windows::Data::Json::JsonObject();
auto tokensJsonArray = ref new Windows::Data::Json::JsonArray(); // auto tokensJsonArray = ref new Windows::Data::Json::JsonArray();
for (const auto& token : value.Tokens) // for (const auto& token : value.Tokens)
{ // {
auto tokenJsonArray = ref new Windows::Data::Json::JsonArray(); // auto tokenJsonArray = ref new Windows::Data::Json::JsonArray();
tokenJsonArray->Append(Windows::Data::Json::JsonValue::CreateStringValue(ref new Platform::String(token.first.c_str()))); // tokenJsonArray->Append(Windows::Data::Json::JsonValue::CreateStringValue(ref new Platform::String(token.first.c_str())));
tokenJsonArray->Append(Windows::Data::Json::JsonValue::CreateNumberValue(token.second)); // tokenJsonArray->Append(Windows::Data::Json::JsonValue::CreateNumberValue(token.second));
tokensJsonArray->Append(tokenJsonArray); // tokensJsonArray->Append(tokenJsonArray);
} // }
jsonObject->SetNamedValue(L"Tokens", tokensJsonArray); // jsonObject->SetNamedValue(L"Tokens", tokensJsonArray);
auto commandsJsonArray = ref new Windows::Data::Json::JsonArray(); // auto commandsJsonArray = ref new Windows::Data::Json::JsonArray();
for (const auto& command : value.Commands) // for (const auto& command : value.Commands)
{ // {
commandsJsonArray->Append(SaveSnapshotToJson(command)); // commandsJsonArray->Append(SaveSnapshotToJson(command));
} // }
jsonObject->SetNamedValue(L"Commands", commandsJsonArray); // jsonObject->SetNamedValue(L"Commands", commandsJsonArray);
return jsonObject; // return jsonObject;
} // }
static Windows::Data::Json::JsonObject ^ SaveSnapshotToJson(const CalculatorManagerSnapshot& value) // static Windows::Data::Json::JsonObject ^ SaveSnapshotToJson(const CalculatorManagerSnapshot& value)
{ // {
auto jsonObject = ref new Windows::Data::Json::JsonObject(); // auto jsonObject = ref new Windows::Data::Json::JsonObject();
if (value.HistoryItems.has_value()) // if (value.HistoryItems.has_value())
{ // {
auto historyJsonArray = ref new Windows::Data::Json::JsonArray(); // auto historyJsonArray = ref new Windows::Data::Json::JsonArray();
for (const auto& item : *value.HistoryItems) // for (const auto& item : *value.HistoryItems)
{ // {
historyJsonArray->Append(SaveSnapshotToJson(*item)); // historyJsonArray->Append(SaveSnapshotToJson(*item));
} // }
jsonObject->SetNamedValue(L"HistoryItems", historyJsonArray); // jsonObject->SetNamedValue(L"HistoryItems", historyJsonArray);
} // }
return jsonObject; // return jsonObject;
} // }
static Windows::Data::Json::JsonObject ^ SaveSnapshotToJson(const CalculationManager::HISTORYITEM& value) // static Windows::Data::Json::JsonObject ^ SaveSnapshotToJson(const CalculationManager::HISTORYITEM& value)
{ // {
auto jsonObject = ref new Windows::Data::Json::JsonObject(); // auto jsonObject = ref new Windows::Data::Json::JsonObject();
jsonObject->SetNamedValue(L"Expression", Windows::Data::Json::JsonValue::CreateStringValue(ref new Platform::String(value.historyItemVector.expression.c_str()))); // jsonObject->SetNamedValue(L"Expression", Windows::Data::Json::JsonValue::CreateStringValue(ref new Platform::String(value.historyItemVector.expression.c_str())));
jsonObject->SetNamedValue(L"Result", Windows::Data::Json::JsonValue::CreateStringValue(ref new Platform::String(value.historyItemVector.result.c_str()))); // jsonObject->SetNamedValue(L"Result", Windows::Data::Json::JsonValue::CreateStringValue(ref new Platform::String(value.historyItemVector.result.c_str())));
auto tokensJsonArray = ref new Windows::Data::Json::JsonArray(); // auto tokensJsonArray = ref new Windows::Data::Json::JsonArray();
for (const auto& token : *value.historyItemVector.spTokens) // for (const auto& token : *value.historyItemVector.spTokens)
{ // {
auto tokenJsonArray = ref new Windows::Data::Json::JsonArray(); // auto tokenJsonArray = ref new Windows::Data::Json::JsonArray();
tokenJsonArray->Append(Windows::Data::Json::JsonValue::CreateStringValue(ref new Platform::String(token.first.c_str()))); // tokenJsonArray->Append(Windows::Data::Json::JsonValue::CreateStringValue(ref new Platform::String(token.first.c_str())));
tokenJsonArray->Append(Windows::Data::Json::JsonValue::CreateNumberValue(token.second)); // tokenJsonArray->Append(Windows::Data::Json::JsonValue::CreateNumberValue(token.second));
tokensJsonArray->Append(tokenJsonArray); // tokensJsonArray->Append(tokenJsonArray);
} // }
jsonObject->SetNamedValue(L"Tokens", tokensJsonArray); // jsonObject->SetNamedValue(L"Tokens", tokensJsonArray);
auto commandsJsonArray = ref new Windows::Data::Json::JsonArray(); // auto commandsJsonArray = ref new Windows::Data::Json::JsonArray();
for (const auto& command : *value.historyItemVector.spCommands) // for (const auto& command : *value.historyItemVector.spCommands)
{ // {
commandsJsonArray->Append(SaveSnapshotToJson(command)); // commandsJsonArray->Append(SaveSnapshotToJson(command));
} // }
jsonObject->SetNamedValue(L"Commands", commandsJsonArray); // jsonObject->SetNamedValue(L"Commands", commandsJsonArray);
return jsonObject; // return jsonObject;
} // }
static Windows::Data::Json::JsonObject ^ SaveSnapshotToJson(const std::shared_ptr<IExpressionCommand>& value) // static Windows::Data::Json::JsonObject ^ SaveSnapshotToJson(const std::shared_ptr<IExpressionCommand>& value)
{ // {
auto jsonObject = ref new Windows::Data::Json::JsonObject(); // auto jsonObject = ref new Windows::Data::Json::JsonObject();
auto opndCommand = dynamic_cast<COpndCommand*>(value.get()); // auto opndCommand = dynamic_cast<COpndCommand*>(value.get());
if (opndCommand != nullptr) // if (opndCommand != nullptr)
{ // {
jsonObject = SaveSnapshotToJson(*opndCommand); // jsonObject = SaveSnapshotToJson(*opndCommand);
} // }
auto unaryCommand = dynamic_cast<CUnaryCommand*>(value.get()); // auto unaryCommand = dynamic_cast<CUnaryCommand*>(value.get());
if (unaryCommand != nullptr) // if (unaryCommand != nullptr)
{ // {
jsonObject = SaveSnapshotToJson(*unaryCommand); // jsonObject = SaveSnapshotToJson(*unaryCommand);
} // }
auto binaryCommand = dynamic_cast<CBinaryCommand*>(value.get()); // auto binaryCommand = dynamic_cast<CBinaryCommand*>(value.get());
if (binaryCommand != nullptr) // if (binaryCommand != nullptr)
{ // {
jsonObject = SaveSnapshotToJson(*binaryCommand); // jsonObject = SaveSnapshotToJson(*binaryCommand);
} // }
auto parenthesesCommand = dynamic_cast<CParentheses*>(value.get()); // auto parenthesesCommand = dynamic_cast<CParentheses*>(value.get());
if (parenthesesCommand != nullptr) // if (parenthesesCommand != nullptr)
{ // {
jsonObject = SaveSnapshotToJson(*parenthesesCommand); // jsonObject = SaveSnapshotToJson(*parenthesesCommand);
} // }
return jsonObject; // return jsonObject;
} // }
static Windows::Data::Json::JsonObject ^ SaveSnapshotToJson(const COpndCommand& value) // static Windows::Data::Json::JsonObject ^ SaveSnapshotToJson(const COpndCommand& value)
{ // {
auto jsonObject = ref new Windows::Data::Json::JsonObject(); // auto jsonObject = ref new Windows::Data::Json::JsonObject();
jsonObject->SetNamedValue(L"CommandType", Windows::Data::Json::JsonValue::CreateNumberValue(static_cast<double>(value.GetCommandType()))); // jsonObject->SetNamedValue(L"CommandType", Windows::Data::Json::JsonValue::CreateNumberValue(static_cast<double>(value.GetCommandType())));
jsonObject->SetNamedValue(L"IsNegative", Windows::Data::Json::JsonValue::CreateBooleanValue(value.IsNegative())); // jsonObject->SetNamedValue(L"IsNegative", Windows::Data::Json::JsonValue::CreateBooleanValue(value.IsNegative()));
jsonObject->SetNamedValue(L"IsDecimalPresent", Windows::Data::Json::JsonValue::CreateBooleanValue(value.IsDecimalPresent())); // jsonObject->SetNamedValue(L"IsDecimalPresent", Windows::Data::Json::JsonValue::CreateBooleanValue(value.IsDecimalPresent()));
jsonObject->SetNamedValue(L"IsSciFmt", Windows::Data::Json::JsonValue::CreateBooleanValue(value.IsSciFmt())); // jsonObject->SetNamedValue(L"IsSciFmt", Windows::Data::Json::JsonValue::CreateBooleanValue(value.IsSciFmt()));
auto commandsJsonArray = ref new Windows::Data::Json::JsonArray(); // auto commandsJsonArray = ref new Windows::Data::Json::JsonArray();
for (const auto& command : *value.GetCommands()) // for (const auto& command : *value.GetCommands())
{ // {
commandsJsonArray->Append(Windows::Data::Json::JsonValue::CreateNumberValue(command)); // commandsJsonArray->Append(Windows::Data::Json::JsonValue::CreateNumberValue(command));
} // }
jsonObject->SetNamedValue(L"Commands", commandsJsonArray); // jsonObject->SetNamedValue(L"Commands", commandsJsonArray);
return jsonObject; // return jsonObject;
} // }
static Windows::Data::Json::JsonObject ^ SaveSnapshotToJson(const CUnaryCommand& value) // static Windows::Data::Json::JsonObject ^ SaveSnapshotToJson(const CUnaryCommand& value)
{ // {
auto jsonObject = ref new Windows::Data::Json::JsonObject(); // auto jsonObject = ref new Windows::Data::Json::JsonObject();
jsonObject->SetNamedValue(L"CommandType", Windows::Data::Json::JsonValue::CreateNumberValue(static_cast<double>(value.GetCommandType()))); // jsonObject->SetNamedValue(L"CommandType", Windows::Data::Json::JsonValue::CreateNumberValue(static_cast<double>(value.GetCommandType())));
auto commandsJsonArray = ref new Windows::Data::Json::JsonArray(); // auto commandsJsonArray = ref new Windows::Data::Json::JsonArray();
for (const auto& command : *value.GetCommands()) // for (const auto& command : *value.GetCommands())
{ // {
commandsJsonArray->Append(Windows::Data::Json::JsonValue::CreateNumberValue(command)); // commandsJsonArray->Append(Windows::Data::Json::JsonValue::CreateNumberValue(command));
} // }
jsonObject->SetNamedValue(L"Commands", commandsJsonArray); // jsonObject->SetNamedValue(L"Commands", commandsJsonArray);
return jsonObject; // return jsonObject;
} // }
static Windows::Data::Json::JsonObject ^ SaveSnapshotToJson(const CBinaryCommand& value) // static Windows::Data::Json::JsonObject ^ SaveSnapshotToJson(const CBinaryCommand& value)
{ // {
auto jsonObject = ref new Windows::Data::Json::JsonObject(); // auto jsonObject = ref new Windows::Data::Json::JsonObject();
jsonObject->SetNamedValue(L"CommandType", Windows::Data::Json::JsonValue::CreateNumberValue(static_cast<double>(value.GetCommandType()))); // jsonObject->SetNamedValue(L"CommandType", Windows::Data::Json::JsonValue::CreateNumberValue(static_cast<double>(value.GetCommandType())));
jsonObject->SetNamedValue(L"Command", Windows::Data::Json::JsonValue::CreateNumberValue(value.GetCommand())); // jsonObject->SetNamedValue(L"Command", Windows::Data::Json::JsonValue::CreateNumberValue(value.GetCommand()));
return jsonObject; // return jsonObject;
} // }
static Windows::Data::Json::JsonObject ^ SaveSnapshotToJson(const CParentheses& value) // static Windows::Data::Json::JsonObject ^ SaveSnapshotToJson(const CParentheses& value)
{ // {
auto jsonObject = ref new Windows::Data::Json::JsonObject(); // auto jsonObject = ref new Windows::Data::Json::JsonObject();
jsonObject->SetNamedValue(L"CommandType", Windows::Data::Json::JsonValue::CreateNumberValue(static_cast<double>(value.GetCommandType()))); // jsonObject->SetNamedValue(L"CommandType", Windows::Data::Json::JsonValue::CreateNumberValue(static_cast<double>(value.GetCommandType())));
jsonObject->SetNamedValue(L"Command", Windows::Data::Json::JsonValue::CreateNumberValue(value.GetCommand())); // jsonObject->SetNamedValue(L"Command", Windows::Data::Json::JsonValue::CreateNumberValue(value.GetCommand()));
return jsonObject; // return jsonObject;
} // }
static void RestoreJsonToSnapshot(Windows::Data::Json::JsonObject ^ jsonObject, std::optional<ApplicationSnapshot>& value) // static void RestoreJsonToSnapshot(Windows::Data::Json::JsonObject ^ jsonObject, std::optional<ApplicationSnapshot>& value)
{ // {
ApplicationSnapshot applicationSnapshot; // ApplicationSnapshot applicationSnapshot;
applicationSnapshot.SnapshotVersion = static_cast<int>(jsonObject->GetNamedNumber(L"SnapshotVersion")); // applicationSnapshot.SnapshotVersion = static_cast<int>(jsonObject->GetNamedNumber(L"SnapshotVersion"));
if (applicationSnapshot.SnapshotVersion > SnapshotVersion) // if (applicationSnapshot.SnapshotVersion > SnapshotVersion)
{ // {
return; // return;
} // }
applicationSnapshot.Mode = static_cast<int>(jsonObject->GetNamedNumber(L"Mode")); // applicationSnapshot.Mode = static_cast<int>(jsonObject->GetNamedNumber(L"Mode"));
if (jsonObject->HasKey(L"StandardCalculatorSnapshot")) // if (jsonObject->HasKey(L"StandardCalculatorSnapshot"))
{ // {
std::optional<StandardCalculatorSnapshot> standardCalculatorSnapshot; // std::optional<StandardCalculatorSnapshot> standardCalculatorSnapshot;
RestoreJsonToSnapshot(jsonObject->GetNamedObject(L"StandardCalculatorSnapshot"), standardCalculatorSnapshot); // RestoreJsonToSnapshot(jsonObject->GetNamedObject(L"StandardCalculatorSnapshot"), standardCalculatorSnapshot);
if (standardCalculatorSnapshot.has_value()) // if (standardCalculatorSnapshot.has_value())
{ // {
applicationSnapshot.StandardCalc = std::move(*standardCalculatorSnapshot); // applicationSnapshot.StandardCalc = std::move(*standardCalculatorSnapshot);
} // }
else // else
{ // {
return; // return;
} // }
} // }
value = std::move(applicationSnapshot); // value = std::move(applicationSnapshot);
} // }
static void RestoreJsonToSnapshot(Windows::Data::Json::JsonObject ^ jsonObject, std::optional<StandardCalculatorSnapshot>& value) // static void RestoreJsonToSnapshot(Windows::Data::Json::JsonObject ^ jsonObject, std::optional<StandardCalculatorSnapshot>& value)
{ // {
StandardCalculatorSnapshot standardCalculatorSnapshot; // StandardCalculatorSnapshot standardCalculatorSnapshot;
std::optional<CalculatorManagerSnapshot> calcManagerSnapshot; // std::optional<CalculatorManagerSnapshot> calcManagerSnapshot;
RestoreJsonToSnapshot(jsonObject->GetNamedObject(L"CalculatorManagerSnapshot"), calcManagerSnapshot); // RestoreJsonToSnapshot(jsonObject->GetNamedObject(L"CalculatorManagerSnapshot"), calcManagerSnapshot);
if (calcManagerSnapshot.has_value()) // if (calcManagerSnapshot.has_value())
{ // {
standardCalculatorSnapshot.CalcManager = std::move(*calcManagerSnapshot); // standardCalculatorSnapshot.CalcManager = std::move(*calcManagerSnapshot);
} // }
else // else
{ // {
return; // return;
} // }
std::optional<PrimaryDisplaySnapshot> primaryDisplaySnapshot; // std::optional<PrimaryDisplaySnapshot> primaryDisplaySnapshot;
RestoreJsonToSnapshot(jsonObject->GetNamedObject(L"PrimaryDisplay"), primaryDisplaySnapshot); // RestoreJsonToSnapshot(jsonObject->GetNamedObject(L"PrimaryDisplay"), primaryDisplaySnapshot);
if (primaryDisplaySnapshot.has_value()) // if (primaryDisplaySnapshot.has_value())
{ // {
standardCalculatorSnapshot.PrimaryDisplay = std::move(*primaryDisplaySnapshot); // standardCalculatorSnapshot.PrimaryDisplay = std::move(*primaryDisplaySnapshot);
} // }
else // else
{ // {
return; // return;
} // }
if (jsonObject->HasKey(L"ExpressionDisplay")) // if (jsonObject->HasKey(L"ExpressionDisplay"))
{ // {
std::optional<ExpressionDisplaySnapshot> expressionDisplaySnapshot; // std::optional<ExpressionDisplaySnapshot> expressionDisplaySnapshot;
RestoreJsonToSnapshot(jsonObject->GetNamedObject(L"ExpressionDisplay"), expressionDisplaySnapshot); // RestoreJsonToSnapshot(jsonObject->GetNamedObject(L"ExpressionDisplay"), expressionDisplaySnapshot);
if (expressionDisplaySnapshot.has_value()) // if (expressionDisplaySnapshot.has_value())
{ // {
standardCalculatorSnapshot.ExpressionDisplay = std::move(*expressionDisplaySnapshot); // standardCalculatorSnapshot.ExpressionDisplay = std::move(*expressionDisplaySnapshot);
} // }
else // else
{ // {
return; // return;
} // }
} // }
standardCalculatorSnapshot.DisplayCommands = RestoreExpressionCommandsFromJsonArray(jsonObject->GetNamedArray(L"DisplayCommands")); // standardCalculatorSnapshot.DisplayCommands = RestoreExpressionCommandsFromJsonArray(jsonObject->GetNamedArray(L"DisplayCommands"));
value = std::move(standardCalculatorSnapshot); // value = std::move(standardCalculatorSnapshot);
} // }
static void RestoreJsonToSnapshot(Windows::Data::Json::JsonObject ^ jsonObject, std::optional<PrimaryDisplaySnapshot>& value) // static void RestoreJsonToSnapshot(Windows::Data::Json::JsonObject ^ jsonObject, std::optional<PrimaryDisplaySnapshot>& value)
{ // {
value = PrimaryDisplaySnapshot{ jsonObject->GetNamedString(L"DisplayValue"), jsonObject->GetNamedBoolean(L"IsError") }; // value = PrimaryDisplaySnapshot{ jsonObject->GetNamedString(L"DisplayValue"), jsonObject->GetNamedBoolean(L"IsError") };
} // }
static void RestoreJsonToSnapshot(Windows::Data::Json::JsonObject ^ jsonObject, std::optional<ExpressionDisplaySnapshot>& value) // static void RestoreJsonToSnapshot(Windows::Data::Json::JsonObject ^ jsonObject, std::optional<ExpressionDisplaySnapshot>& value)
{ // {
ExpressionDisplaySnapshot expressionDisplaySnapshot; // ExpressionDisplaySnapshot expressionDisplaySnapshot;
expressionDisplaySnapshot.Tokens = RestoreExpressionTokensFromJsonArray(jsonObject->GetNamedArray(L"Tokens")); // expressionDisplaySnapshot.Tokens = RestoreExpressionTokensFromJsonArray(jsonObject->GetNamedArray(L"Tokens"));
if (expressionDisplaySnapshot.Tokens.empty()) // if (expressionDisplaySnapshot.Tokens.empty())
{ // {
return; // return;
} // }
expressionDisplaySnapshot.Commands = RestoreExpressionCommandsFromJsonArray(jsonObject->GetNamedArray(L"Commands")); // expressionDisplaySnapshot.Commands = RestoreExpressionCommandsFromJsonArray(jsonObject->GetNamedArray(L"Commands"));
if (expressionDisplaySnapshot.Commands.empty()) // if (expressionDisplaySnapshot.Commands.empty())
{ // {
return; // return;
} // }
value = std::move(expressionDisplaySnapshot); // value = std::move(expressionDisplaySnapshot);
} // }
static void RestoreJsonToSnapshot(Windows::Data::Json::JsonObject ^ jsonObject, std::optional<CalculatorManagerSnapshot>& value) // static void RestoreJsonToSnapshot(Windows::Data::Json::JsonObject ^ jsonObject, std::optional<CalculatorManagerSnapshot>& value)
{ // {
CalculatorManagerSnapshot calcManagerSnapshot; // CalculatorManagerSnapshot calcManagerSnapshot;
if (jsonObject->HasKey(L"HistoryItems")) // if (jsonObject->HasKey(L"HistoryItems"))
{ // {
std::vector<std::shared_ptr<CalculationManager::HISTORYITEM>> historyItems; // std::vector<std::shared_ptr<CalculationManager::HISTORYITEM>> historyItems;
auto historyJsonArray = jsonObject->GetNamedArray(L"HistoryItems"); // auto historyJsonArray = jsonObject->GetNamedArray(L"HistoryItems");
for (uint32_t i = 0; i < historyJsonArray->Size; ++i) // for (uint32_t i = 0; i < historyJsonArray->Size; ++i)
{ // {
std::optional<CalculationManager::HISTORYITEM> historyItem; // std::optional<CalculationManager::HISTORYITEM> historyItem;
RestoreJsonToSnapshot(historyJsonArray->GetObjectAt(i), historyItem); // RestoreJsonToSnapshot(historyJsonArray->GetObjectAt(i), historyItem);
if (historyItem.has_value()) // if (historyItem.has_value())
{ // {
historyItems.push_back(std::make_shared<CalculationManager::HISTORYITEM>(*historyItem)); // historyItems.push_back(std::make_shared<CalculationManager::HISTORYITEM>(*historyItem));
} // }
else // else
{ // {
return; // return;
} // }
} // }
calcManagerSnapshot.HistoryItems = std::move(historyItems); // calcManagerSnapshot.HistoryItems = std::move(historyItems);
} // }
value = std::move(calcManagerSnapshot); // value = std::move(calcManagerSnapshot);
} // }
static void RestoreJsonToSnapshot(Windows::Data::Json::JsonObject ^ jsonObject, std::optional<CalculationManager::HISTORYITEM>& value) // static void RestoreJsonToSnapshot(Windows::Data::Json::JsonObject ^ jsonObject, std::optional<CalculationManager::HISTORYITEM>& value)
{ // {
CalculationManager::HISTORYITEM historyItem; // CalculationManager::HISTORYITEM historyItem;
historyItem.historyItemVector.expression = std::wstring(jsonObject->GetNamedString(L"Expression")->Data()); // historyItem.historyItemVector.expression = std::wstring(jsonObject->GetNamedString(L"Expression")->Data());
historyItem.historyItemVector.result = std::wstring(jsonObject->GetNamedString(L"Result")->Data()); // historyItem.historyItemVector.result = std::wstring(jsonObject->GetNamedString(L"Result")->Data());
historyItem.historyItemVector.spTokens = // historyItem.historyItemVector.spTokens =
std::make_shared<std::vector<std::pair<std::wstring, int>>>(RestoreExpressionTokensFromJsonArray(jsonObject->GetNamedArray(L"Tokens"))); // std::make_shared<std::vector<std::pair<std::wstring, int>>>(RestoreExpressionTokensFromJsonArray(jsonObject->GetNamedArray(L"Tokens")));
if (historyItem.historyItemVector.spTokens->empty()) // if (historyItem.historyItemVector.spTokens->empty())
{ // {
return; // return;
} // }
historyItem.historyItemVector.spCommands = std::make_shared<std::vector<std::shared_ptr<IExpressionCommand>>>( // historyItem.historyItemVector.spCommands = std::make_shared<std::vector<std::shared_ptr<IExpressionCommand>>>(
RestoreExpressionCommandsFromJsonArray(jsonObject->GetNamedArray(L"Commands"))); // RestoreExpressionCommandsFromJsonArray(jsonObject->GetNamedArray(L"Commands")));
if (historyItem.historyItemVector.spCommands->empty()) // if (historyItem.historyItemVector.spCommands->empty())
{ // {
return; // return;
} // }
value = std::move(historyItem); // value = std::move(historyItem);
} // }
static void RestoreJsonToSnapshot(Windows::Data::Json::JsonObject ^ jsonObject, std::optional<std::shared_ptr<IExpressionCommand>>& value) // static void RestoreJsonToSnapshot(Windows::Data::Json::JsonObject ^ jsonObject, std::optional<std::shared_ptr<IExpressionCommand>>& value)
{ // {
auto commandType = static_cast<CalculationManager::CommandType>(jsonObject->GetNamedNumber(L"CommandType")); // auto commandType = static_cast<CalculationManager::CommandType>(jsonObject->GetNamedNumber(L"CommandType"));
switch (commandType) // switch (commandType)
{ // {
case CalculationManager::CommandType::OperandCommand: // case CalculationManager::CommandType::OperandCommand:
{ // {
std::optional<COpndCommand> opndCommand; // std::optional<COpndCommand> opndCommand;
RestoreJsonToSnapshot(jsonObject, opndCommand); // RestoreJsonToSnapshot(jsonObject, opndCommand);
if (opndCommand.has_value()) // if (opndCommand.has_value())
{ // {
value = std::make_shared<COpndCommand>(*opndCommand); // value = std::make_shared<COpndCommand>(*opndCommand);
} // }
break; // break;
} // }
case CalculationManager::CommandType::UnaryCommand: // case CalculationManager::CommandType::UnaryCommand:
{ // {
std::optional<CUnaryCommand> unaryCommand; // std::optional<CUnaryCommand> unaryCommand;
RestoreJsonToSnapshot(jsonObject, unaryCommand); // RestoreJsonToSnapshot(jsonObject, unaryCommand);
if (unaryCommand.has_value()) // if (unaryCommand.has_value())
{ // {
value = std::make_shared<CUnaryCommand>(*unaryCommand); // value = std::make_shared<CUnaryCommand>(*unaryCommand);
} // }
break; // break;
} // }
case CalculationManager::CommandType::BinaryCommand: // case CalculationManager::CommandType::BinaryCommand:
{ // {
std::optional<CBinaryCommand> binaryCommand; // std::optional<CBinaryCommand> binaryCommand;
RestoreJsonToSnapshot(jsonObject, binaryCommand); // RestoreJsonToSnapshot(jsonObject, binaryCommand);
if (binaryCommand.has_value()) // if (binaryCommand.has_value())
{ // {
value = std::make_shared<CBinaryCommand>(*binaryCommand); // value = std::make_shared<CBinaryCommand>(*binaryCommand);
} // }
break; // break;
} // }
case CalculationManager::CommandType::Parentheses: // case CalculationManager::CommandType::Parentheses:
{ // {
std::optional<CParentheses> parenthesesCommand; // std::optional<CParentheses> parenthesesCommand;
RestoreJsonToSnapshot(jsonObject, parenthesesCommand); // RestoreJsonToSnapshot(jsonObject, parenthesesCommand);
if (parenthesesCommand.has_value()) // if (parenthesesCommand.has_value())
{ // {
value = std::make_shared<CParentheses>(*parenthesesCommand); // value = std::make_shared<CParentheses>(*parenthesesCommand);
} // }
break; // break;
} // }
default: // default:
throw std::logic_error{ "c8cba597-dfec-447a-bd1c-e78a9ffaad95" }; // throw std::logic_error{ "c8cba597-dfec-447a-bd1c-e78a9ffaad95" };
} // }
} // }
static void RestoreJsonToSnapshot(Windows::Data::Json::JsonObject ^ jsonObject, std::optional<COpndCommand>& value) // static void RestoreJsonToSnapshot(Windows::Data::Json::JsonObject ^ jsonObject, std::optional<COpndCommand>& value)
{ // {
auto isNegative = jsonObject->GetNamedBoolean(L"IsNegative"); // auto isNegative = jsonObject->GetNamedBoolean(L"IsNegative");
auto isDecimalPresent = jsonObject->GetNamedBoolean(L"IsDecimalPresent"); // auto isDecimalPresent = jsonObject->GetNamedBoolean(L"IsDecimalPresent");
auto isSciFmt = jsonObject->GetNamedBoolean(L"IsSciFmt"); // auto isSciFmt = jsonObject->GetNamedBoolean(L"IsSciFmt");
std::vector<int> commands; // std::vector<int> commands;
auto commandsJsonArray = jsonObject->GetNamedArray(L"Commands"); // auto commandsJsonArray = jsonObject->GetNamedArray(L"Commands");
for (uint32_t i = 0; i < commandsJsonArray->Size; ++i) // for (uint32_t i = 0; i < commandsJsonArray->Size; ++i)
{ // {
commands.push_back(static_cast<int>(commandsJsonArray->GetNumberAt(i))); // commands.push_back(static_cast<int>(commandsJsonArray->GetNumberAt(i)));
} // }
value = COpndCommand(std::make_shared<std::vector<int>>(std::move(commands)), isNegative, isDecimalPresent, isSciFmt); // value = COpndCommand(std::make_shared<std::vector<int>>(std::move(commands)), isNegative, isDecimalPresent, isSciFmt);
} // }
static void RestoreJsonToSnapshot(Windows::Data::Json::JsonObject ^ jsonObject, std::optional<CUnaryCommand>& value) // static void RestoreJsonToSnapshot(Windows::Data::Json::JsonObject ^ jsonObject, std::optional<CUnaryCommand>& value)
{ // {
std::vector<int> commands; // std::vector<int> commands;
auto commandsJsonArray = jsonObject->GetNamedArray(L"Commands"); // auto commandsJsonArray = jsonObject->GetNamedArray(L"Commands");
if (commandsJsonArray->Size == 1) // if (commandsJsonArray->Size == 1)
{ // {
value = CUnaryCommand(static_cast<int>(commandsJsonArray->GetNumberAt(0))); // value = CUnaryCommand(static_cast<int>(commandsJsonArray->GetNumberAt(0)));
} // }
else if (commandsJsonArray->Size == 2) // else if (commandsJsonArray->Size == 2)
{ // {
value = CUnaryCommand(static_cast<int>(commandsJsonArray->GetNumberAt(0)), static_cast<int>(commandsJsonArray->GetNumberAt(1))); // value = CUnaryCommand(static_cast<int>(commandsJsonArray->GetNumberAt(0)), static_cast<int>(commandsJsonArray->GetNumberAt(1)));
} // }
} // }
static void RestoreJsonToSnapshot(Windows::Data::Json::JsonObject ^ jsonObject, std::optional<CBinaryCommand>& value) // static void RestoreJsonToSnapshot(Windows::Data::Json::JsonObject ^ jsonObject, std::optional<CBinaryCommand>& value)
{ // {
value = CBinaryCommand(static_cast<int>(jsonObject->GetNamedNumber(L"Command"))); // value = CBinaryCommand(static_cast<int>(jsonObject->GetNamedNumber(L"Command")));
} // }
static void RestoreJsonToSnapshot(Windows::Data::Json::JsonObject ^ jsonObject, std::optional<CParentheses>& value) // static void RestoreJsonToSnapshot(Windows::Data::Json::JsonObject ^ jsonObject, std::optional<CParentheses>& value)
{ // {
value = CParentheses(static_cast<int>(jsonObject->GetNamedNumber(L"Command"))); // value = CParentheses(static_cast<int>(jsonObject->GetNamedNumber(L"Command")));
} // }
static std::vector<std::pair<std::wstring, int>> RestoreExpressionTokensFromJsonArray(Windows::Data::Json::JsonArray ^ jsonArray) // static std::vector<std::pair<std::wstring, int>> RestoreExpressionTokensFromJsonArray(Windows::Data::Json::JsonArray ^ jsonArray)
{ // {
std::vector<std::pair<std::wstring, int>> tokens; // std::vector<std::pair<std::wstring, int>> tokens;
for (uint32_t i = 0; i < jsonArray->Size; ++i) // for (uint32_t i = 0; i < jsonArray->Size; ++i)
{ // {
auto tokenJsonArray = jsonArray->GetArrayAt(i); // auto tokenJsonArray = jsonArray->GetArrayAt(i);
if (tokenJsonArray->Size == 2 && tokenJsonArray->GetAt(0)->ValueType == Windows::Data::Json::JsonValueType::String // if (tokenJsonArray->Size == 2 && tokenJsonArray->GetAt(0)->ValueType == Windows::Data::Json::JsonValueType::String
&& tokenJsonArray->GetAt(1)->ValueType == Windows::Data::Json::JsonValueType::Number) // && tokenJsonArray->GetAt(1)->ValueType == Windows::Data::Json::JsonValueType::Number)
{ // {
tokens.emplace_back(std::wstring(tokenJsonArray->GetAt(0)->GetString()->Data()), static_cast<int>(tokenJsonArray->GetAt(1)->GetNumber())); // tokens.emplace_back(std::wstring(tokenJsonArray->GetAt(0)->GetString()->Data()), static_cast<int>(tokenJsonArray->GetAt(1)->GetNumber()));
} // }
else // else
{ // {
return {}; // return {};
} // }
} // }
return tokens; // return tokens;
} // }
static std::vector<std::shared_ptr<IExpressionCommand>> RestoreExpressionCommandsFromJsonArray(Windows::Data::Json::JsonArray ^ jsonArray) // static std::vector<std::shared_ptr<IExpressionCommand>> RestoreExpressionCommandsFromJsonArray(Windows::Data::Json::JsonArray ^ jsonArray)
{ // {
std::vector<std::shared_ptr<IExpressionCommand>> commands; // std::vector<std::shared_ptr<IExpressionCommand>> commands;
for (uint32_t i = 0; i < jsonArray->Size; ++i) // for (uint32_t i = 0; i < jsonArray->Size; ++i)
{ // {
std::optional<std::shared_ptr<IExpressionCommand>> command; // std::optional<std::shared_ptr<IExpressionCommand>> command;
RestoreJsonToSnapshot(jsonArray->GetObjectAt(i), command); // RestoreJsonToSnapshot(jsonArray->GetObjectAt(i), command);
if (command.has_value()) // if (command.has_value())
{ // {
commands.push_back(*command); // commands.push_back(*command);
} // }
else // else
{ // {
return {}; // return {};
} // }
} // }
return commands; // return commands;
} // }
static bool IsJsonParsingException(Platform::COMException ^ e) // static bool IsJsonParsingException(Platform::COMException ^ e)
{ // {
return e->HResult == WEB_E_JSON_VALUE_NOT_FOUND || e->HResult == E_ILLEGAL_METHOD_CALL; // return e->HResult == WEB_E_JSON_VALUE_NOT_FOUND || e->HResult == E_ILLEGAL_METHOD_CALL;
} // }
}; //};
} }
ApplicationViewModel::ApplicationViewModel() ApplicationViewModel::ApplicationViewModel()
@ -712,47 +712,47 @@ void ApplicationViewModel::SetDisplayNormalAlwaysOnTopOption()
m_mode == ViewMode::Standard && ApplicationView::GetForCurrentView()->IsViewModeSupported(ApplicationViewMode::CompactOverlay) && !IsAlwaysOnTop; m_mode == ViewMode::Standard && ApplicationView::GetForCurrentView()->IsViewModeSupported(ApplicationViewMode::CompactOverlay) && !IsAlwaysOnTop;
} }
Windows::Data::Json::JsonObject ^ ApplicationViewModel::SaveApplicationSnapshot() //Windows::Data::Json::JsonObject ^ ApplicationViewModel::SaveApplicationSnapshot()
{ //{
ApplicationSnapshot applicationSnapshot; // ApplicationSnapshot applicationSnapshot;
applicationSnapshot.SnapshotVersion = SnapshotHelper::SnapshotVersion; // applicationSnapshot.SnapshotVersion = SnapshotHelper::SnapshotVersion;
applicationSnapshot.Mode = static_cast<int>(Mode); // applicationSnapshot.Mode = static_cast<int>(Mode);
if (m_CalculatorViewModel != nullptr && m_mode == ViewMode::Standard) // if (m_CalculatorViewModel != nullptr && m_mode == ViewMode::Standard)
{ // {
// Standard calculator is the only supported mode so far. // // Standard calculator is the only supported mode so far.
applicationSnapshot.StandardCalc = m_CalculatorViewModel->GetStandardCalculatorSnapshot(); // applicationSnapshot.StandardCalc = m_CalculatorViewModel->GetStandardCalculatorSnapshot();
} // }
return SnapshotHelper::SaveSnapshotToJson(applicationSnapshot); // return SnapshotHelper::SaveSnapshotToJson(applicationSnapshot);
} //}
//
bool ApplicationViewModel::TryRestoreFromSnapshot(Windows::Data::Json::JsonObject ^ jsonObject) //bool ApplicationViewModel::TryRestoreFromSnapshot(Windows::Data::Json::JsonObject ^ jsonObject)
{ //{
std::optional<ApplicationSnapshot> applicationSnapshot; // std::optional<ApplicationSnapshot> applicationSnapshot;
try // try
{ // {
SnapshotHelper::RestoreJsonToSnapshot(jsonObject, applicationSnapshot); // SnapshotHelper::RestoreJsonToSnapshot(jsonObject, applicationSnapshot);
} // }
catch (Platform::COMException ^ e) // catch (Platform::COMException ^ e)
{ // {
if (SnapshotHelper::IsJsonParsingException(e)) // if (SnapshotHelper::IsJsonParsingException(e))
{ // {
return false; // return false;
} // }
throw; // throw;
} // }
//
if (applicationSnapshot.has_value()) // if (applicationSnapshot.has_value())
{ // {
Mode = static_cast<ViewMode>(applicationSnapshot->Mode); // Mode = static_cast<ViewMode>(applicationSnapshot->Mode);
if (applicationSnapshot->StandardCalc.has_value()) // if (applicationSnapshot->StandardCalc.has_value())
{ // {
if (m_CalculatorViewModel == nullptr) // if (m_CalculatorViewModel == nullptr)
{ // {
m_CalculatorViewModel = ref new StandardCalculatorViewModel(); // m_CalculatorViewModel = ref new StandardCalculatorViewModel();
} // }
m_CalculatorViewModel->SetStandardCalculatorSnapshot(applicationSnapshot->StandardCalc.value()); // m_CalculatorViewModel->SetStandardCalculatorSnapshot(applicationSnapshot->StandardCalc.value());
} // }
return true; // return true;
} // }
return false; // return false;
} //}

View file

@ -16,7 +16,7 @@ namespace CalculatorApp
{ {
int SnapshotVersion; int SnapshotVersion;
int Mode; int Mode;
std::optional<StandardCalculatorSnapshot> StandardCalc; //std::optional<StandardCalculatorSnapshot> StandardCalc;
}; };
[Windows::UI::Xaml::Data::Bindable] public ref class ApplicationViewModel sealed : public Windows::UI::Xaml::Data::INotifyPropertyChanged [Windows::UI::Xaml::Data::Bindable] public ref class ApplicationViewModel sealed : public Windows::UI::Xaml::Data::INotifyPropertyChanged
@ -103,8 +103,8 @@ namespace CalculatorApp
void ToggleAlwaysOnTop(float width, float height); void ToggleAlwaysOnTop(float width, float height);
Windows::Data::Json::JsonObject ^ SaveApplicationSnapshot(); //Windows::Data::Json::JsonObject ^ SaveApplicationSnapshot();
bool TryRestoreFromSnapshot(Windows::Data::Json::JsonObject ^ jsonObject); //bool TryRestoreFromSnapshot(Windows::Data::Json::JsonObject ^ jsonObject);
private: private:
bool TryRecoverFromNavigationModeFailure(); bool TryRecoverFromNavigationModeFailure();

View file

@ -338,6 +338,7 @@
<ClInclude Include="HistoryViewModel.h" /> <ClInclude Include="HistoryViewModel.h" />
<ClInclude Include="MemoryItemViewModel.h" /> <ClInclude Include="MemoryItemViewModel.h" />
<ClInclude Include="pch.h" /> <ClInclude Include="pch.h" />
<ClInclude Include="Snapshots.h" />
<ClInclude Include="StandardCalculatorViewModel.h" /> <ClInclude Include="StandardCalculatorViewModel.h" />
<ClInclude Include="targetver.h" /> <ClInclude Include="targetver.h" />
<ClInclude Include="UnitConverterViewModel.h" /> <ClInclude Include="UnitConverterViewModel.h" />
@ -380,6 +381,7 @@
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader> <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader> <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
</ClCompile> </ClCompile>
<ClCompile Include="Snapshots.cpp" />
<ClCompile Include="StandardCalculatorViewModel.cpp" /> <ClCompile Include="StandardCalculatorViewModel.cpp" />
<ClCompile Include="UnitConverterViewModel.cpp" /> <ClCompile Include="UnitConverterViewModel.cpp" />
</ItemGroup> </ItemGroup>

View file

@ -89,6 +89,7 @@
<ClCompile Include="MemoryItemViewModel.cpp" /> <ClCompile Include="MemoryItemViewModel.cpp" />
<ClCompile Include="StandardCalculatorViewModel.cpp" /> <ClCompile Include="StandardCalculatorViewModel.cpp" />
<ClCompile Include="UnitConverterViewModel.cpp" /> <ClCompile Include="UnitConverterViewModel.cpp" />
<ClCompile Include="Snapshots.cpp" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="pch.h" /> <ClInclude Include="pch.h" />
@ -203,6 +204,7 @@
<ClInclude Include="StandardCalculatorViewModel.h" /> <ClInclude Include="StandardCalculatorViewModel.h" />
<ClInclude Include="targetver.h" /> <ClInclude Include="targetver.h" />
<ClInclude Include="UnitConverterViewModel.h" /> <ClInclude Include="UnitConverterViewModel.h" />
<ClInclude Include="Snapshots.h" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="DataLoaders\DefaultFromToCurrency.json"> <None Include="DataLoaders\DefaultFromToCurrency.json">

View file

@ -0,0 +1,59 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
#include "pch.h"
#include <cassert>
#include "Snapshots.h"
namespace CalculatorApp::ViewModel
{
CalcEngineHistoryToken::CalcEngineHistoryToken(Platform::String ^ opCodeName, int cmdIndex)
{
assert(opCodeName != nullptr && "opCodeName is mandatory.");
OpCodeName = opCodeName;
CommandIndex = cmdIndex;
}
CalcEnginHistoryItem::CalcEnginHistoryItem(const CalculationManager::HISTORYITEM& item)
{
Tokens = ref new Platform::Collections::Vector<CalcEngineHistoryToken ^>();
if (item.historyItemVector.spTokens != nullptr)
{
for (auto& [opCode, cmdIdx] : *item.historyItemVector.spTokens)
{
Tokens->Append(ref new CalcEngineHistoryToken(ref new Platform::String(opCode.c_str()), cmdIdx));
}
}
Expression = ref new Platform::String(item.historyItemVector.expression.c_str());
Result = ref new Platform::String(item.historyItemVector.result.c_str());
}
CalcManagerSnapshot::CalcManagerSnapshot(const CalculationManager::CalculatorManager& calcMgr)
{
auto& items = calcMgr.GetHistoryItems();
if (!items.empty())
{
for (auto& item : items)
{
HistoryItems->Append(ref new CalcEnginHistoryItem(*item));
}
}
}
PrimaryDisplaySnapshot::PrimaryDisplaySnapshot(Platform::String ^ display, bool isError)
{
assert(display != nullptr && "display is mandatory");
DisplayValue = display;
IsError = isError;
}
ExpressionDisplaySnapshot::ExpressionDisplaySnapshot(const std::vector<CalcHistoryToken>& tokens)
{
Tokens = ref new Platform::Collections::Vector<CalcEngineHistoryToken ^>();
for (auto& [opCode, cmdIdx] : tokens)
{
Tokens->Append(ref new CalcEngineHistoryToken(ref new Platform::String(opCode.c_str()), cmdIdx));
}
}
}

View file

@ -0,0 +1,69 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
#pragma once
#include "CalcManager/CalculatorManager.h"
namespace CalculatorApp::ViewModel
{
public
ref struct CalcEngineHistoryToken sealed
{
property Platform::String ^ OpCodeName; // mandatory
property int CommandIndex;
internal :;
explicit CalcEngineHistoryToken(Platform::String ^ opCodeName, int cmdIndex);
};
public
ref struct CalcEnginHistoryItem sealed
{
property Windows::Foundation::Collections::IVector<CalcEngineHistoryToken ^> ^ Tokens; // mandatory
// TODO: commands
property Platform::String ^ Expression; // mandatory
property Platform::String ^ Result; // mandatory
internal :;
explicit CalcEnginHistoryItem(const CalculationManager::HISTORYITEM& item);
};
public
ref struct CalcManagerSnapshot sealed
{
property Windows::Foundation::Collections::IVector<CalcEnginHistoryItem ^> ^ HistoryItems; // optional
internal :;
explicit CalcManagerSnapshot(const CalculationManager::CalculatorManager& calcMgr);
};
public
ref struct PrimaryDisplaySnapshot sealed
{
property Platform::String ^ DisplayValue; // mandatory
property bool IsError;
internal :;
explicit PrimaryDisplaySnapshot(Platform::String ^ display, bool isError);
};
public
ref struct ExpressionDisplaySnapshot sealed
{
property Windows::Foundation::Collections::IVector<CalcEngineHistoryToken ^> ^ Tokens;
// TODO: commands
internal :;
using CalcHistoryToken = std::pair<std::wstring, int>;
explicit ExpressionDisplaySnapshot(const std::vector<CalcHistoryToken>& tokens);
};
public
ref struct StandardCalculatorSnapshot sealed
{
property CalcManagerSnapshot ^ CalcManager; // mandatory
property PrimaryDisplaySnapshot ^ PrimaryDisplay; // mandatory
property ExpressionDisplaySnapshot ^ ExpressionDisplay; // optional
// TODO: commands
};
}

View file

@ -227,7 +227,7 @@ String ^ StandardCalculatorViewModel::CalculateNarratorDisplayValue(_In_ wstring
String ^ StandardCalculatorViewModel::GetNarratorStringReadRawNumbers(_In_ String ^ localizedDisplayValue) String ^ StandardCalculatorViewModel::GetNarratorStringReadRawNumbers(_In_ String ^ localizedDisplayValue)
{ {
wstring ws; wstring ws;
LocalizationSettings^ 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. // Insert a space after each digit in the string, to force Narrator to read them as separate numbers.
for (const wchar_t& c : localizedDisplayValue) for (const wchar_t& c : localizedDisplayValue)
@ -386,7 +386,7 @@ void StandardCalculatorViewModel::SetTokens(_Inout_ shared_ptr<vector<pair<wstri
return; return;
} }
LocalizationSettings^ localizer = LocalizationSettings::GetInstance(); LocalizationSettings ^ localizer = LocalizationSettings::GetInstance();
const wstring separator = L" "; const wstring separator = L" ";
for (unsigned int i = 0; i < nTokens; ++i) for (unsigned int i = 0; i < nTokens; ++i)
@ -449,7 +449,7 @@ String ^ StandardCalculatorViewModel::GetCalculatorExpressionAutomationName()
void StandardCalculatorViewModel::SetMemorizedNumbers(const vector<wstring>& newMemorizedNumbers) void StandardCalculatorViewModel::SetMemorizedNumbers(const vector<wstring>& newMemorizedNumbers)
{ {
LocalizationSettings^ localizer = LocalizationSettings::GetInstance(); LocalizationSettings ^ localizer = LocalizationSettings::GetInstance();
if (newMemorizedNumbers.size() == 0) // Memory has been cleared if (newMemorizedNumbers.size() == 0) // Memory has been cleared
{ {
MemorizedNumbers->Clear(); MemorizedNumbers->Clear();
@ -1060,8 +1060,8 @@ ButtonInfo StandardCalculatorViewModel::MapCharacterToButtonId(char16 ch)
{ {
if (LocalizationSettings::GetInstance()->IsLocalizedDigit(ch)) if (LocalizationSettings::GetInstance()->IsLocalizedDigit(ch))
{ {
result.buttonId = result.buttonId = NumbersAndOperatorsEnum::Zero
NumbersAndOperatorsEnum::Zero + static_cast<NumbersAndOperatorsEnum>(ch - LocalizationSettings::GetInstance()->GetDigitSymbolFromEnUsDigit('0')); + static_cast<NumbersAndOperatorsEnum>(ch - LocalizationSettings::GetInstance()->GetDigitSymbolFromEnUsDigit('0'));
result.canSendNegate = true; result.canSendNegate = true;
} }
} }
@ -1588,7 +1588,7 @@ void StandardCalculatorViewModel::UpdateProgrammerPanelDisplay()
binaryDisplayString = m_standardCalculatorManager.GetResultForRadix(2, precision, true); binaryDisplayString = m_standardCalculatorManager.GetResultForRadix(2, precision, true);
} }
} }
LocalizationSettings^ localizer = LocalizationSettings::GetInstance(); LocalizationSettings ^ localizer = LocalizationSettings::GetInstance();
binaryDisplayString = AddPadding(binaryDisplayString); binaryDisplayString = AddPadding(binaryDisplayString);
localizer->LocalizeDisplayValue(&hexDisplayString); localizer->LocalizeDisplayValue(&hexDisplayString);
@ -1787,49 +1787,57 @@ void StandardCalculatorViewModel::SetBitshiftRadioButtonCheckedAnnouncement(Plat
Announcement = CalculatorAnnouncement::GetBitShiftRadioButtonCheckedAnnouncement(announcement); Announcement = CalculatorAnnouncement::GetBitShiftRadioButtonCheckedAnnouncement(announcement);
} }
StandardCalculatorSnapshot StandardCalculatorViewModel::GetStandardCalculatorSnapshot() const StandardCalculatorSnapshot ^ StandardCalculatorViewModel::GetSnapshot() const
{ {
StandardCalculatorSnapshot snapshot; auto result = ref new StandardCalculatorSnapshot();
auto& historyItems = m_standardCalculatorManager.GetHistoryItems(); result->CalcManager = ref new CalcManagerSnapshot(m_standardCalculatorManager);
if (!historyItems.empty()) result->PrimaryDisplay = ref new PrimaryDisplaySnapshot(m_DisplayValue, m_IsInError);
{ result->ExpressionDisplay = ref new ExpressionDisplaySnapshot(*m_tokens);
snapshot.CalcManager.HistoryItems = std::move(historyItems); return nullptr;
}
snapshot.PrimaryDisplay = PrimaryDisplaySnapshot{ m_DisplayValue, m_IsInError };
if (!m_tokens->empty() && !m_commands->empty())
{
snapshot.ExpressionDisplay = { *m_tokens, *m_commands };
}
snapshot.DisplayCommands = m_standardCalculatorManager.GetDisplayCommandsSnapshot();
return snapshot;
}
void StandardCalculatorViewModel::SetStandardCalculatorSnapshot(const StandardCalculatorSnapshot& snapshot)
{
if (snapshot.CalcManager.HistoryItems.has_value())
{
m_standardCalculatorManager.SetHistoryItems(snapshot.CalcManager.HistoryItems.value());
}
std::vector<int> 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>(command));
}
if (snapshot.ExpressionDisplay.has_value())
{
SetExpressionDisplay(
std::make_shared<std::vector<std::pair<std::wstring, int>>>(snapshot.ExpressionDisplay->Tokens),
std::make_shared<std::vector<std::shared_ptr<IExpressionCommand>>>(snapshot.ExpressionDisplay->Commands));
}
SetPrimaryDisplay(snapshot.PrimaryDisplay.DisplayValue, snapshot.PrimaryDisplay.IsError);
} }
// StandardCalculatorSnapshot StandardCalculatorViewModel::GetStandardCalculatorSnapshot() const
//{
// StandardCalculatorSnapshot snapshot;
// auto& historyItems = m_standardCalculatorManager.GetHistoryItems();
// if (!historyItems.empty())
// {
// snapshot.CalcManager.HistoryItems = std::move(historyItems);
// }
// snapshot.PrimaryDisplay = PrimaryDisplaySnapshot{ m_DisplayValue, m_IsInError };
// if (!m_tokens->empty() && !m_commands->empty())
// {
// snapshot.ExpressionDisplay = { *m_tokens, *m_commands };
// }
// snapshot.DisplayCommands = m_standardCalculatorManager.GetDisplayCommandsSnapshot();
// return snapshot;
// }
//
// void StandardCalculatorViewModel::SetStandardCalculatorSnapshot(const StandardCalculatorSnapshot& snapshot)
//{
// if (snapshot.CalcManager.HistoryItems.has_value())
// {
// m_standardCalculatorManager.SetHistoryItems(snapshot.CalcManager.HistoryItems.value());
// }
//
// std::vector<int> 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>(command));
// }
//
// if (snapshot.ExpressionDisplay.has_value())
// {
// SetExpressionDisplay(
// std::make_shared<std::vector<std::pair<std::wstring, int>>>(snapshot.ExpressionDisplay->Tokens),
// std::make_shared<std::vector<std::shared_ptr<IExpressionCommand>>>(snapshot.ExpressionDisplay->Commands));
// }
// SetPrimaryDisplay(snapshot.PrimaryDisplay.DisplayValue, snapshot.PrimaryDisplay.IsError);
// }

View file

@ -7,11 +7,13 @@
#include "Common/CalculatorDisplay.h" #include "Common/CalculatorDisplay.h"
#include "Common/EngineResourceProvider.h" #include "Common/EngineResourceProvider.h"
#include "Common/CalculatorButtonUser.h" #include "Common/CalculatorButtonUser.h"
#include "HistoryViewModel.h"
#include "MemoryItemViewModel.h"
#include "Common/BitLength.h" #include "Common/BitLength.h"
#include "Common/NumberBase.h" #include "Common/NumberBase.h"
#include "HistoryViewModel.h"
#include "MemoryItemViewModel.h"
#include "Snapshots.h"
namespace CalculatorUnitTests namespace CalculatorUnitTests
{ {
class MultiWindowUnitTests; class MultiWindowUnitTests;
@ -25,38 +27,40 @@ namespace CalculatorApp
namespace ViewModel namespace ViewModel
{ {
#define ASCII_0 48 #define ASCII_0 48
public delegate void HideMemoryClickedHandler(); public
delegate void HideMemoryClickedHandler();
public value struct ButtonInfo public
value struct ButtonInfo
{ {
CalculatorApp::ViewModel::Common::NumbersAndOperatorsEnum buttonId; CalculatorApp::ViewModel::Common::NumbersAndOperatorsEnum buttonId;
bool canSendNegate; bool canSendNegate;
}; };
struct CalculatorManagerSnapshot // struct CalculatorManagerSnapshot
{ //{
std::optional<std::vector<std::shared_ptr<CalculationManager::HISTORYITEM>>> HistoryItems; // std::optional<std::vector<std::shared_ptr<CalculationManager::HISTORYITEM>>> HistoryItems;
}; // };
struct PrimaryDisplaySnapshot // struct PrimaryDisplaySnapshot
{ //{
Platform::String ^ DisplayValue; // Platform::String ^ DisplayValue;
bool IsError = false; // bool IsError = false;
}; // };
struct ExpressionDisplaySnapshot // struct ExpressionDisplaySnapshot
{ //{
std::vector<std::pair<std::wstring, int>> Tokens; // std::vector<std::pair<std::wstring, int>> Tokens;
std::vector<std::shared_ptr<IExpressionCommand>> Commands; // std::vector<std::shared_ptr<IExpressionCommand>> Commands;
}; // };
struct StandardCalculatorSnapshot // struct StandardCalculatorSnapshot
{ //{
CalculatorManagerSnapshot CalcManager; // CalculatorManagerSnapshot CalcManager;
PrimaryDisplaySnapshot PrimaryDisplay; // PrimaryDisplaySnapshot PrimaryDisplay;
std::optional<ExpressionDisplaySnapshot> ExpressionDisplay; // std::optional<ExpressionDisplaySnapshot> ExpressionDisplay;
std::vector<std::shared_ptr<IExpressionCommand>> DisplayCommands; // std::vector<std::shared_ptr<IExpressionCommand>> DisplayCommands;
}; // };
[Windows::UI::Xaml::Data::Bindable] public ref class StandardCalculatorViewModel sealed : public Windows::UI::Xaml::Data::INotifyPropertyChanged [Windows::UI::Xaml::Data::Bindable] public ref class StandardCalculatorViewModel sealed : public Windows::UI::Xaml::Data::INotifyPropertyChanged
{ {
@ -136,7 +140,7 @@ namespace CalculatorApp
static property Platform::String static property Platform::String
^ IsBitFlipCheckedPropertyName { Platform::String ^ get() { return Platform::StringReference(L"IsBitFlipChecked"); } } ^ IsBitFlipCheckedPropertyName { Platform::String ^ get() { return Platform::StringReference(L"IsBitFlipChecked"); } }
property CalculatorApp::ViewModel::Common::BitLength ValueBitLength property CalculatorApp::ViewModel::Common::BitLength ValueBitLength
{ {
CalculatorApp::ViewModel::Common::BitLength get() CalculatorApp::ViewModel::Common::BitLength get()
{ {
@ -216,7 +220,7 @@ namespace CalculatorApp
static property Platform::String static property Platform::String
^ IsProgrammerPropertyName { Platform::String ^ get() { return Platform::StringReference(L"IsProgrammer"); } } ^ IsProgrammerPropertyName { Platform::String ^ get() { return Platform::StringReference(L"IsProgrammer"); } }
property bool IsEditingEnabled property bool IsEditingEnabled
{ {
bool get() bool get()
{ {
@ -265,6 +269,8 @@ namespace CalculatorApp
} }
} }
property StandardCalculatorSnapshot ^ Snapshot { StandardCalculatorSnapshot ^ get() { return GetSnapshot(); } }
// Used by unit tests // Used by unit tests
void ResetCalcManager(bool clearMemory); void ResetCalcManager(bool clearMemory);
void SendCommandToCalcManager(int command); void SendCommandToCalcManager(int command);
@ -284,8 +290,7 @@ namespace CalculatorApp
void SwitchAngleType(CalculatorApp::ViewModel::Common::NumbersAndOperatorsEnum num); void SwitchAngleType(CalculatorApp::ViewModel::Common::NumbersAndOperatorsEnum num);
void FtoEButtonToggled(); void FtoEButtonToggled();
internal: internal : void OnPaste(Platform::String ^ pastedString);
void OnPaste(Platform::String ^ pastedString);
void OnCopyCommand(Platform::Object ^ parameter); void OnCopyCommand(Platform::Object ^ parameter);
void OnPasteCommand(Platform::Object ^ parameter); void OnPasteCommand(Platform::Object ^ parameter);
@ -320,10 +325,10 @@ namespace CalculatorApp
return m_CurrentAngleType; return m_CurrentAngleType;
} }
StandardCalculatorSnapshot GetStandardCalculatorSnapshot() const; // void SetStandardCalculatorSnapshot(const StandardCalculatorSnapshot& state);
void SetStandardCalculatorSnapshot(const StandardCalculatorSnapshot& state);
private: private:
StandardCalculatorSnapshot ^ GetSnapshot() const;
void SetMemorizedNumbers(const std::vector<std::wstring>& memorizedNumbers); void SetMemorizedNumbers(const std::vector<std::wstring>& memorizedNumbers);
void UpdateProgrammerPanelDisplay(); void UpdateProgrammerPanelDisplay();
void HandleUpdatedOperandData(CalculationManager::Command cmdenum); void HandleUpdatedOperandData(CalculationManager::Command cmdenum);
@ -372,8 +377,7 @@ namespace CalculatorApp
Common::DisplayExpressionToken ^ m_selectedExpressionToken; Common::DisplayExpressionToken ^ m_selectedExpressionToken;
Platform::String ^ LocalizeDisplayValue(_In_ std::wstring const& displayValue); Platform::String ^ LocalizeDisplayValue(_In_ std::wstring const& displayValue);
Platform::String Platform::String ^ CalculateNarratorDisplayValue(_In_ std::wstring const& displayValue, _In_ Platform::String ^ localizedDisplayValue);
^ CalculateNarratorDisplayValue(_In_ std::wstring const& displayValue, _In_ Platform::String ^ localizedDisplayValue);
CalculatorApp::ViewModel::Common::Automation::NarratorAnnouncement ^ GetDisplayUpdatedNarratorAnnouncement(); CalculatorApp::ViewModel::Common::Automation::NarratorAnnouncement ^ GetDisplayUpdatedNarratorAnnouncement();
Platform::String ^ GetCalculatorExpressionAutomationName(); Platform::String ^ GetCalculatorExpressionAutomationName();
Platform::String ^ GetNarratorStringReadRawNumbers(_In_ Platform::String ^ localizedDisplayValue); Platform::String ^ GetNarratorStringReadRawNumbers(_In_ Platform::String ^ localizedDisplayValue);