162 lines
4.9 KiB
C++
162 lines
4.9 KiB
C++
#pragma once
|
|
|
|
#include "foundation/result.h"
|
|
|
|
namespace pp::app {
|
|
|
|
enum class HistoryUiOperation {
|
|
undo,
|
|
redo,
|
|
clear,
|
|
};
|
|
|
|
struct HistoryUiPlan {
|
|
HistoryUiOperation operation = HistoryUiOperation::undo;
|
|
int undo_count = 0;
|
|
int redo_count = 0;
|
|
int memory_bytes = 0;
|
|
bool invokes_undo = false;
|
|
bool invokes_redo = false;
|
|
bool clears_history = false;
|
|
bool updates_memory_label = false;
|
|
bool updates_title = false;
|
|
bool no_op = false;
|
|
};
|
|
|
|
class HistoryUiServices {
|
|
public:
|
|
virtual ~HistoryUiServices() = default;
|
|
|
|
virtual void invoke_undo() = 0;
|
|
virtual void invoke_redo() = 0;
|
|
virtual void clear_history() = 0;
|
|
};
|
|
|
|
[[nodiscard]] inline pp::foundation::Status validate_history_metric(int value, const char* message) noexcept
|
|
{
|
|
if (value < 0) {
|
|
return pp::foundation::Status::out_of_range(message);
|
|
}
|
|
|
|
return pp::foundation::Status::success();
|
|
}
|
|
|
|
[[nodiscard]] inline pp::foundation::Result<HistoryUiPlan> plan_history_undo(int undo_count)
|
|
{
|
|
const auto count_status = validate_history_metric(undo_count, "undo action count must not be negative");
|
|
if (!count_status.ok()) {
|
|
return pp::foundation::Result<HistoryUiPlan>::failure(count_status);
|
|
}
|
|
|
|
HistoryUiPlan plan;
|
|
plan.operation = HistoryUiOperation::undo;
|
|
plan.undo_count = undo_count;
|
|
if (undo_count == 0) {
|
|
plan.no_op = true;
|
|
return pp::foundation::Result<HistoryUiPlan>::success(plan);
|
|
}
|
|
|
|
plan.invokes_undo = true;
|
|
plan.updates_memory_label = true;
|
|
plan.updates_title = true;
|
|
return pp::foundation::Result<HistoryUiPlan>::success(plan);
|
|
}
|
|
|
|
[[nodiscard]] inline pp::foundation::Result<HistoryUiPlan> plan_history_redo(int redo_count)
|
|
{
|
|
const auto count_status = validate_history_metric(redo_count, "redo action count must not be negative");
|
|
if (!count_status.ok()) {
|
|
return pp::foundation::Result<HistoryUiPlan>::failure(count_status);
|
|
}
|
|
|
|
HistoryUiPlan plan;
|
|
plan.operation = HistoryUiOperation::redo;
|
|
plan.redo_count = redo_count;
|
|
if (redo_count == 0) {
|
|
plan.no_op = true;
|
|
return pp::foundation::Result<HistoryUiPlan>::success(plan);
|
|
}
|
|
|
|
plan.invokes_redo = true;
|
|
plan.updates_memory_label = true;
|
|
plan.updates_title = true;
|
|
return pp::foundation::Result<HistoryUiPlan>::success(plan);
|
|
}
|
|
|
|
[[nodiscard]] inline pp::foundation::Result<HistoryUiPlan> plan_history_clear(
|
|
int undo_count,
|
|
int redo_count,
|
|
int memory_bytes)
|
|
{
|
|
const auto undo_status = validate_history_metric(undo_count, "undo action count must not be negative");
|
|
if (!undo_status.ok()) {
|
|
return pp::foundation::Result<HistoryUiPlan>::failure(undo_status);
|
|
}
|
|
const auto redo_status = validate_history_metric(redo_count, "redo action count must not be negative");
|
|
if (!redo_status.ok()) {
|
|
return pp::foundation::Result<HistoryUiPlan>::failure(redo_status);
|
|
}
|
|
const auto memory_status = validate_history_metric(memory_bytes, "history memory bytes must not be negative");
|
|
if (!memory_status.ok()) {
|
|
return pp::foundation::Result<HistoryUiPlan>::failure(memory_status);
|
|
}
|
|
|
|
HistoryUiPlan plan;
|
|
plan.operation = HistoryUiOperation::clear;
|
|
plan.undo_count = undo_count;
|
|
plan.redo_count = redo_count;
|
|
plan.memory_bytes = memory_bytes;
|
|
if (undo_count == 0 && redo_count == 0 && memory_bytes == 0) {
|
|
plan.no_op = true;
|
|
return pp::foundation::Result<HistoryUiPlan>::success(plan);
|
|
}
|
|
|
|
plan.clears_history = true;
|
|
plan.updates_memory_label = true;
|
|
return pp::foundation::Result<HistoryUiPlan>::success(plan);
|
|
}
|
|
|
|
[[nodiscard]] inline pp::foundation::Status execute_history_ui_plan(
|
|
const HistoryUiPlan& plan,
|
|
HistoryUiServices& services)
|
|
{
|
|
const auto undo_status = validate_history_metric(plan.undo_count, "undo action count must not be negative");
|
|
if (!undo_status.ok()) {
|
|
return undo_status;
|
|
}
|
|
const auto redo_status = validate_history_metric(plan.redo_count, "redo action count must not be negative");
|
|
if (!redo_status.ok()) {
|
|
return redo_status;
|
|
}
|
|
const auto memory_status = validate_history_metric(plan.memory_bytes, "history memory bytes must not be negative");
|
|
if (!memory_status.ok()) {
|
|
return memory_status;
|
|
}
|
|
|
|
if (plan.no_op) {
|
|
return pp::foundation::Status::success();
|
|
}
|
|
|
|
switch (plan.operation) {
|
|
case HistoryUiOperation::undo:
|
|
if (plan.invokes_undo) {
|
|
services.invoke_undo();
|
|
}
|
|
return pp::foundation::Status::success();
|
|
case HistoryUiOperation::redo:
|
|
if (plan.invokes_redo) {
|
|
services.invoke_redo();
|
|
}
|
|
return pp::foundation::Status::success();
|
|
case HistoryUiOperation::clear:
|
|
if (plan.clears_history) {
|
|
services.clear_history();
|
|
}
|
|
return pp::foundation::Status::success();
|
|
}
|
|
|
|
return pp::foundation::Status::invalid_argument("unknown history operation");
|
|
}
|
|
|
|
} // namespace pp::app
|