Plan canvas toolbar bindings

This commit is contained in:
2026-06-05 07:52:58 +02:00
parent 062fdaa982
commit 5def47cdcc
8 changed files with 241 additions and 97 deletions

View File

@@ -2,7 +2,9 @@
#include "foundation/result.h"
#include <array>
#include <cmath>
#include <string_view>
namespace pp::app {
@@ -32,6 +34,12 @@ enum class CanvasToolTransformAction {
cut,
};
enum class CanvasToolToolbarAction {
select_mode,
toggle_picking,
toggle_touch_lock,
};
enum class CanvasCursorVisibilityMode {
never,
small_brush,
@@ -68,6 +76,19 @@ struct CanvasToolButtonState {
bool flood_fill_active = false;
};
struct CanvasToolToolbarBinding {
std::string_view button_id;
CanvasToolToolbarAction action = CanvasToolToolbarAction::select_mode;
CanvasToolMode mode = CanvasToolMode::draw;
bool custom_button = true;
bool applies_default_on_init = false;
};
struct CanvasToolToolbarPlan {
std::array<CanvasToolToolbarBinding, 13> bindings {};
CanvasToolMode default_mode = CanvasToolMode::draw;
};
struct CanvasCursorVisibilityInput {
CanvasToolMode mode = CanvasToolMode::draw;
CanvasCursorVisibilityMode visibility_mode = CanvasCursorVisibilityMode::never;
@@ -139,6 +160,44 @@ public:
return plan;
}
[[nodiscard]] inline constexpr CanvasToolToolbarPlan plan_canvas_tool_toolbar() noexcept
{
return {
std::array<CanvasToolToolbarBinding, 13> {
CanvasToolToolbarBinding { "btn-pen", CanvasToolToolbarAction::select_mode, CanvasToolMode::draw, true, true },
CanvasToolToolbarBinding { "btn-pick", CanvasToolToolbarAction::toggle_picking, CanvasToolMode::draw, true, false },
CanvasToolToolbarBinding { "btn-touchlock", CanvasToolToolbarAction::toggle_touch_lock, CanvasToolMode::draw, true, false },
CanvasToolToolbarBinding { "btn-erase", CanvasToolToolbarAction::select_mode, CanvasToolMode::erase, true, false },
CanvasToolToolbarBinding { "btn-line", CanvasToolToolbarAction::select_mode, CanvasToolMode::line, true, false },
CanvasToolToolbarBinding { "btn-cam", CanvasToolToolbarAction::select_mode, CanvasToolMode::camera, false, false },
CanvasToolToolbarBinding { "btn-grid", CanvasToolToolbarAction::select_mode, CanvasToolMode::grid, false, false },
CanvasToolToolbarBinding { "btn-copy", CanvasToolToolbarAction::select_mode, CanvasToolMode::copy, false, false },
CanvasToolToolbarBinding { "btn-cut", CanvasToolToolbarAction::select_mode, CanvasToolMode::cut, false, false },
CanvasToolToolbarBinding { "btn-fill", CanvasToolToolbarAction::select_mode, CanvasToolMode::fill, false, false },
CanvasToolToolbarBinding { "btn-mask-free", CanvasToolToolbarAction::select_mode, CanvasToolMode::mask_free, true, false },
CanvasToolToolbarBinding { "btn-mask-line", CanvasToolToolbarAction::select_mode, CanvasToolMode::mask_line, true, false },
CanvasToolToolbarBinding { "btn-bucket", CanvasToolToolbarAction::select_mode, CanvasToolMode::flood_fill, true, false },
},
CanvasToolMode::draw,
};
}
[[nodiscard]] inline constexpr CanvasToolPlan plan_canvas_tool_toolbar_binding_action(
const CanvasToolToolbarBinding& binding,
bool current_mode_is_draw) noexcept
{
switch (binding.action) {
case CanvasToolToolbarAction::select_mode:
return plan_canvas_tool_select(binding.mode);
case CanvasToolToolbarAction::toggle_picking:
return plan_canvas_tool_pick_toggle(current_mode_is_draw);
case CanvasToolToolbarAction::toggle_touch_lock:
return plan_canvas_tool_touch_lock_toggle();
}
return plan_canvas_tool_select(CanvasToolMode::draw);
}
[[nodiscard]] inline constexpr CanvasToolButtonState plan_canvas_tool_button_state(
CanvasToolMode mode,
bool picking,

View File

@@ -590,108 +590,62 @@ void App::init_sidebar()
};
}
}
template<class T>
void apply_canvas_tool_select(App& app, T* button, pp::app::CanvasToolMode mode)
[[nodiscard]] bool current_canvas_mode_is_draw(App& app) noexcept
{
const auto plan = pp::app::plan_canvas_tool_select(mode);
const auto status = pp::panopainter::execute_legacy_canvas_tool_plan(app, plan, button);
return app.canvas && app.canvas->m_canvas && app.canvas->m_canvas->m_current_mode == kCanvasMode::Draw;
}
template<class T>
void execute_canvas_tool_toolbar_binding(
App& app,
const pp::app::CanvasToolToolbarBinding& binding,
T* button)
{
const auto plan = pp::app::plan_canvas_tool_toolbar_binding_action(
binding,
current_canvas_mode_is_draw(app));
const auto status = binding.action == pp::app::CanvasToolToolbarAction::select_mode
? pp::panopainter::execute_legacy_canvas_tool_plan(app, plan, button)
: pp::panopainter::execute_legacy_canvas_tool_plan(app, plan);
if (!status.ok())
LOG("Canvas tool select action failed: %s", status.message);
LOG("Canvas toolbar action failed: %s", status.message);
}
template<class T>
void bind_canvas_tool_toolbar_button(
App& app,
const pp::app::CanvasToolToolbarBinding& binding,
T* button)
{
button->on_click = [&app, binding, button](Node*) {
execute_canvas_tool_toolbar_binding(app, binding, button);
};
}
void App::init_toolbar_draw()
{
if (auto* button = layout[main_id]->find<NodeButtonCustom>("btn-pen"))
{
button->on_click = [this, button](Node*) {
apply_canvas_tool_select(*this, button, pp::app::CanvasToolMode::draw);
};
//button->set_active(true);
const auto plan = pp::app::plan_canvas_tool_select(pp::app::CanvasToolMode::draw);
const auto status = pp::panopainter::execute_legacy_canvas_tool_plan(*this, plan);
const auto toolbar = pp::app::plan_canvas_tool_toolbar();
bool apply_default_tool = false;
for (const auto& binding : toolbar.bindings) {
if (binding.custom_button) {
if (auto* button = layout[main_id]->find<NodeButtonCustom>(binding.button_id.data())) {
bind_canvas_tool_toolbar_button(*this, binding, button);
apply_default_tool = apply_default_tool || binding.applies_default_on_init;
}
} else {
if (auto* button = layout[main_id]->find<NodeButton>(binding.button_id.data())) {
bind_canvas_tool_toolbar_button(*this, binding, button);
apply_default_tool = apply_default_tool || binding.applies_default_on_init;
}
}
}
if (apply_default_tool) {
const auto default_plan = pp::app::plan_canvas_tool_select(toolbar.default_mode);
const auto status = pp::panopainter::execute_legacy_canvas_tool_plan(*this, default_plan);
if (!status.ok())
LOG("Canvas default tool action failed: %s", status.message);
}
if (auto* button = layout[main_id]->find<NodeButtonCustom>("btn-pick"))
{
button->on_click = [this](Node*) {
const auto plan = pp::app::plan_canvas_tool_pick_toggle(
canvas->m_canvas->m_current_mode == kCanvasMode::Draw);
const auto status = pp::panopainter::execute_legacy_canvas_tool_plan(*this, plan);
if (!status.ok())
LOG("Canvas pick action failed: %s", status.message);
};
}
if (auto* button = layout[main_id]->find<NodeButtonCustom>("btn-touchlock"))
{
button->on_click = [this](Node*) {
const auto plan = pp::app::plan_canvas_tool_touch_lock_toggle();
const auto status = pp::panopainter::execute_legacy_canvas_tool_plan(*this, plan);
if (!status.ok())
LOG("Canvas touch-lock action failed: %s", status.message);
};
}
if (auto* button = layout[main_id]->find<NodeButtonCustom>("btn-erase"))
{
button->on_click = [this, button](Node*) {
apply_canvas_tool_select(*this, button, pp::app::CanvasToolMode::erase);
};
}
if (auto* button = layout[main_id]->find<NodeButtonCustom>("btn-line"))
{
button->on_click = [this, button](Node*) {
apply_canvas_tool_select(*this, button, pp::app::CanvasToolMode::line);
};
}
if (auto* button = layout[main_id]->find<NodeButton>("btn-cam"))
{
button->on_click = [this, button](Node*) {
apply_canvas_tool_select(*this, button, pp::app::CanvasToolMode::camera);
};
}
if (auto* button = layout[main_id]->find<NodeButton>("btn-grid"))
{
button->on_click = [this, button](Node*) {
apply_canvas_tool_select(*this, button, pp::app::CanvasToolMode::grid);
};
}
if (auto* button = layout[main_id]->find<NodeButton>("btn-copy"))
{
button->on_click = [this, button](Node*) {
apply_canvas_tool_select(*this, button, pp::app::CanvasToolMode::copy);
};
}
if (auto* button = layout[main_id]->find<NodeButton>("btn-cut"))
{
button->on_click = [this, button](Node*) {
apply_canvas_tool_select(*this, button, pp::app::CanvasToolMode::cut);
};
}
if (auto* button = layout[main_id]->find<NodeButton>("btn-fill"))
{
// polygon fill
button->on_click = [this, button](Node*) {
apply_canvas_tool_select(*this, button, pp::app::CanvasToolMode::fill);
};
}
if (auto* button = layout[main_id]->find<NodeButtonCustom>("btn-mask-free"))
{
button->on_click = [this, button](Node*) {
apply_canvas_tool_select(*this, button, pp::app::CanvasToolMode::mask_free);
};
}
if (auto* button = layout[main_id]->find<NodeButtonCustom>("btn-mask-line"))
{
button->on_click = [this, button](Node*) {
apply_canvas_tool_select(*this, button, pp::app::CanvasToolMode::mask_line);
};
}
if (auto* button = layout[main_id]->find<NodeButtonCustom>("btn-bucket"))
{
button->on_click = [this, button](Node*) {
apply_canvas_tool_select(*this, button, pp::app::CanvasToolMode::flood_fill);
};
}
}
void App::init_menu_file()