Extract main toolbar action planning

This commit is contained in:
2026-06-03 12:37:32 +02:00
parent b5bd6d42f7
commit 62561624ed
8 changed files with 536 additions and 15 deletions

146
src/app_core/main_toolbar.h Normal file
View File

@@ -0,0 +1,146 @@
#pragma once
#include "app_core/document_canvas.h"
#include "app_core/history_ui.h"
#include "foundation/result.h"
#include <string>
namespace pp::app {
enum class MainToolbarCommand {
open_document,
save_document,
undo,
redo,
clear_history,
clear_canvas,
show_message_box,
show_settings,
};
enum class MainToolbarAction {
show_open_dialog,
show_save_dialog,
invoke_undo,
invoke_redo,
clear_history,
clear_canvas,
show_message_box,
show_settings_dialog,
no_op_unavailable,
};
struct MainToolbarPlan {
MainToolbarCommand command = MainToolbarCommand::open_document;
MainToolbarAction action = MainToolbarAction::show_open_dialog;
std::string label;
bool requires_canvas = false;
bool updates_memory_label = false;
bool updates_title = false;
bool records_undo = false;
bool marks_unsaved = false;
bool no_op = false;
};
[[nodiscard]] inline pp::foundation::Result<MainToolbarPlan> plan_main_toolbar_command(
MainToolbarCommand command,
int undo_count = 0,
int redo_count = 0,
int memory_bytes = 0,
bool has_canvas = true)
{
MainToolbarPlan plan;
plan.command = command;
switch (command) {
case MainToolbarCommand::open_document:
plan.action = MainToolbarAction::show_open_dialog;
plan.label = "Open";
return pp::foundation::Result<MainToolbarPlan>::success(plan);
case MainToolbarCommand::save_document:
plan.action = MainToolbarAction::show_save_dialog;
plan.label = "Save";
return pp::foundation::Result<MainToolbarPlan>::success(plan);
case MainToolbarCommand::undo:
{
const auto history = plan_history_undo(undo_count);
if (!history) {
return pp::foundation::Result<MainToolbarPlan>::failure(history.status());
}
plan.action = history.value().invokes_undo
? MainToolbarAction::invoke_undo
: MainToolbarAction::no_op_unavailable;
plan.label = history.value().invokes_undo ? "Undo" : "Undo (No history)";
plan.updates_memory_label = history.value().updates_memory_label;
plan.updates_title = history.value().updates_title;
plan.no_op = history.value().no_op;
return pp::foundation::Result<MainToolbarPlan>::success(plan);
}
case MainToolbarCommand::redo:
{
const auto history = plan_history_redo(redo_count);
if (!history) {
return pp::foundation::Result<MainToolbarPlan>::failure(history.status());
}
plan.action = history.value().invokes_redo
? MainToolbarAction::invoke_redo
: MainToolbarAction::no_op_unavailable;
plan.label = history.value().invokes_redo ? "Redo" : "Redo (No history)";
plan.updates_memory_label = history.value().updates_memory_label;
plan.updates_title = history.value().updates_title;
plan.no_op = history.value().no_op;
return pp::foundation::Result<MainToolbarPlan>::success(plan);
}
case MainToolbarCommand::clear_history:
{
const auto history = plan_history_clear(undo_count, redo_count, memory_bytes);
if (!history) {
return pp::foundation::Result<MainToolbarPlan>::failure(history.status());
}
plan.action = history.value().clears_history
? MainToolbarAction::clear_history
: MainToolbarAction::no_op_unavailable;
plan.label = history.value().clears_history ? "Clear History" : "Clear History (Empty)";
plan.updates_memory_label = history.value().updates_memory_label;
plan.no_op = history.value().no_op;
return pp::foundation::Result<MainToolbarPlan>::success(plan);
}
case MainToolbarCommand::clear_canvas:
{
const auto clear = plan_document_canvas_clear(has_canvas);
if (!clear) {
return pp::foundation::Result<MainToolbarPlan>::failure(clear.status());
}
plan.action = clear.value().clears_canvas
? MainToolbarAction::clear_canvas
: MainToolbarAction::no_op_unavailable;
plan.label = clear.value().clears_canvas ? "Clear Canvas" : "Clear Canvas (No canvas)";
plan.requires_canvas = true;
plan.records_undo = clear.value().records_undo;
plan.marks_unsaved = clear.value().marks_unsaved;
plan.no_op = clear.value().no_op;
return pp::foundation::Result<MainToolbarPlan>::success(plan);
}
case MainToolbarCommand::show_message_box:
plan.action = MainToolbarAction::show_message_box;
plan.label = "Show Message Box";
return pp::foundation::Result<MainToolbarPlan>::success(plan);
case MainToolbarCommand::show_settings:
plan.action = MainToolbarAction::show_settings_dialog;
plan.label = "Settings";
return pp::foundation::Result<MainToolbarPlan>::success(plan);
}
return pp::foundation::Result<MainToolbarPlan>::failure(
pp::foundation::Status::invalid_argument("unknown main toolbar command"));
}
} // namespace pp::app

View File

@@ -17,6 +17,7 @@
#include "app_core/file_menu.h"
#include "app_core/app_status.h"
#include "app_core/history_ui.h"
#include "app_core/main_toolbar.h"
#include "app_core/tools_menu.h"
#include "settings.h"
#include "serializer.h"
@@ -281,39 +282,51 @@ void App::init_toolbar_main()
if (auto* button = layout[main_id]->find<NodeButton>("btn-open"))
{
button->on_click = [this, button](Node*) {
dialog_open();
const auto plan = pp::app::plan_main_toolbar_command(
pp::app::MainToolbarCommand::open_document);
if (plan && plan.value().action == pp::app::MainToolbarAction::show_open_dialog)
dialog_open();
};
}
if (auto* button = layout[main_id]->find<NodeButton>("btn-save"))
{
button->on_click = [this, button](Node*) {
dialog_save();
const auto plan = pp::app::plan_main_toolbar_command(
pp::app::MainToolbarCommand::save_document);
if (plan && plan.value().action == pp::app::MainToolbarAction::show_save_dialog)
dialog_save();
};
}
if (auto* button = layout[main_id]->find<NodeButtonCustom>("btn-undo"))
{
button->on_click = [this, button](Node*) {
const auto plan = pp::app::plan_history_undo(static_cast<int>(ActionManager::I.m_actions.size()));
if (plan && plan.value().invokes_undo)
const auto plan = pp::app::plan_main_toolbar_command(
pp::app::MainToolbarCommand::undo,
static_cast<int>(ActionManager::I.m_actions.size()));
if (plan && plan.value().action == pp::app::MainToolbarAction::invoke_undo)
ActionManager::undo();
};
}
if (auto* button = layout[main_id]->find<NodeButtonCustom>("btn-redo"))
{
button->on_click = [this, button](Node*) {
const auto plan = pp::app::plan_history_redo(static_cast<int>(ActionManager::I.m_redos.size()));
if (plan && plan.value().invokes_redo)
const auto plan = pp::app::plan_main_toolbar_command(
pp::app::MainToolbarCommand::redo,
0,
static_cast<int>(ActionManager::I.m_redos.size()));
if (plan && plan.value().action == pp::app::MainToolbarAction::invoke_redo)
ActionManager::redo();
};
}
if (auto* button = layout[main_id]->find<NodeButtonCustom>("btn-clean-memory"))
{
button->on_click = [this](Node*) {
const auto plan = pp::app::plan_history_clear(
const auto plan = pp::app::plan_main_toolbar_command(
pp::app::MainToolbarCommand::clear_history,
static_cast<int>(ActionManager::I.m_actions.size()),
static_cast<int>(ActionManager::I.m_redos.size()),
static_cast<int>(ActionManager::I.m_memory));
if (plan && plan.value().clears_history)
if (plan && plan.value().action == pp::app::MainToolbarAction::clear_history)
ActionManager::clear();
};
}
@@ -321,18 +334,27 @@ void App::init_toolbar_main()
{
button->on_click = [this](Node*) {
//exit(0);
const auto plan = pp::app::plan_document_canvas_clear(static_cast<bool>(canvas));
if (plan && plan.value().clears_canvas)
const auto plan = pp::app::plan_main_toolbar_command(
pp::app::MainToolbarCommand::clear_canvas,
0,
0,
0,
static_cast<bool>(canvas));
if (plan && plan.value().action == pp::app::MainToolbarAction::clear_canvas)
canvas->m_canvas->clear({
plan.value().r,
plan.value().g,
plan.value().b,
plan.value().a });
0.0F,
0.0F,
0.0F,
0.0F });
};
}
if (auto* button = layout[main_id]->find<NodeButton>("btn-popup"))
{
button->on_click = [this](Node*) {
const auto plan = pp::app::plan_main_toolbar_command(
pp::app::MainToolbarCommand::show_message_box);
if (!plan || plan.value().action != pp::app::MainToolbarAction::show_message_box)
return;
msgbox = new NodeMessageBox();
msgbox->set_manager(&layout);
msgbox->init();
@@ -342,6 +364,10 @@ void App::init_toolbar_main()
if (auto* button = layout[main_id]->find<NodeButtonCustom>("btn-settings"))
{
button->on_click = [this](Node*) {
const auto plan = pp::app::plan_main_toolbar_command(
pp::app::MainToolbarCommand::show_settings);
if (!plan || plan.value().action != pp::app::MainToolbarAction::show_settings_dialog)
return;
settings = new NodeSettings();
settings->set_manager(&layout);
settings->init();