From c3d85074acf24d0bcfed510127871106bc29ca04 Mon Sep 17 00:00:00 2001 From: omigamedev Date: Thu, 4 Jun 2026 11:59:20 +0200 Subject: [PATCH] Centralize legacy canvas tool bridge --- cmake/PanoPainterSources.cmake | 2 + docs/modernization/build-inventory.md | 6 + docs/modernization/debt.md | 2 +- docs/modernization/roadmap.md | 21 +-- src/app_layout.cpp | 127 +-------------- src/legacy_canvas_tool_services.cpp | 224 ++++++++++++++++++++++++++ src/legacy_canvas_tool_services.h | 21 +++ src/node_canvas.cpp | 79 +-------- 8 files changed, 273 insertions(+), 209 deletions(-) create mode 100644 src/legacy_canvas_tool_services.cpp create mode 100644 src/legacy_canvas_tool_services.h diff --git a/cmake/PanoPainterSources.cmake b/cmake/PanoPainterSources.cmake index 5d1cbdb..0883436 100644 --- a/cmake/PanoPainterSources.cmake +++ b/cmake/PanoPainterSources.cmake @@ -60,6 +60,8 @@ set(PP_LEGACY_APP_SOURCES src/canvas_modes.cpp src/legacy_app_shell_services.cpp src/legacy_app_shell_services.h + src/legacy_canvas_tool_services.cpp + src/legacy_canvas_tool_services.h src/legacy_document_canvas_services.cpp src/legacy_document_canvas_services.h src/legacy_document_layer_services.cpp diff --git a/docs/modernization/build-inventory.md b/docs/modernization/build-inventory.md index 936714c..e354628 100644 --- a/docs/modernization/build-inventory.md +++ b/docs/modernization/build-inventory.md @@ -167,6 +167,12 @@ Known local toolchain state: Tools, About, history, canvas-clear, and settings execution remain tracked by `DEBT-0029`, `DEBT-0030`, `DEBT-0031`, `DEBT-0033`, `DEBT-0034`, and `DEBT-0035`. +- `src/legacy_canvas_tool_services.*` is the current app-shell bridge for + canvas toolbar tool selection, NodeCanvas stylus/input mode switching, and + canvas hotkey/touch execution. It keeps those live paths on the `pp_app_core` + contracts while legacy `Canvas` mode state, transform actions, picking, + touch-lock, save/UI/cursor calls, brush-size controls, and history execution + remain tracked by `DEBT-0027`. - `pano_cli simulate-image-import` decodes an embedded tiny PNG through `pp_assets`, attaches it to `pp_document`, and is covered by `pano_cli_simulate_image_import_smoke`. diff --git a/docs/modernization/debt.md b/docs/modernization/debt.md index 93a30a7..ebf6a88 100644 --- a/docs/modernization/debt.md +++ b/docs/modernization/debt.md @@ -44,7 +44,7 @@ agent or engineer to remove them without reconstructing context from chat. | DEBT-0024 | Open | Modernization | Grid/heightmap/lightmap UI planning now consumes pure `pp_app_core` through `NodePanelGrid` and `pano_cli plan-grid-operation`, but live execution still performs legacy image loading, OpenGL texture updates, nanort lightmap baking, progress UI, and `Canvas::draw_objects` commit directly | Preserve grid/lightmap behavior while moving renderable grid commands toward app/renderer/document boundaries | `pp_app_core_grid_ui_tests`; `pano_cli plan-grid-operation --kind render --float32 --texture-resolution 1024 --samples 32`; `ctest --preset desktop-fast --build-config Debug` | Grid heightmap/lightmap execution is owned by app/renderer/document services with `NodePanelGrid` acting only as UI adapter | | DEBT-0025 | Open | Modernization | Quick brush/color slot and mini-state planning and execution dispatch now consume pure `pp_app_core` through `NodePanelQuick`, `pano_cli plan-quick-operation`, and the `QuickUiServices` boundary, but the live adapter still mutates legacy quick UI widgets, `Brush` previews, color picker popup state, and preset popup state | Preserve quick-panel behavior while quick brush/color commands move toward a brush/app command boundary with safer automation coverage | `pp_app_core_quick_ui_tests`; `pano_cli plan-quick-operation --kind brush --current-index 0 --slot-index 2`; `pano_cli plan-quick-operation --kind restore --brush-index 2 --color-index 1 --fire-event`; `ctest --preset desktop-fast --build-config Debug` | Quick-panel selection, popup, restore, reset, brush preview, and color execution are owned by injected app/brush/UI services with no legacy quick-panel adapter | | DEBT-0026 | Open | Modernization | Toolbar history command planning and canvas hotkey history dispatch now consume pure `pp_app_core` through `App::init_toolbar_main`, `NodeCanvas`, `pano_cli plan-history-operation`, and the `HistoryUiServices` boundary, and both live callers share `src/legacy_history_services.*` for saturated legacy history metrics and execution, but the shared live bridge still mutates legacy `ActionManager` stacks directly | Preserve undo/redo/clear behavior while moving action history toward document/app command services | `pp_app_core_history_ui_tests`; `pano_cli plan-history-operation --kind undo --undo-count 2`; `pano_cli plan-history-operation --kind clear --undo-count 2 --redo-count 1 --memory-bytes 4096`; `ctest --preset desktop-fast --build-config Debug` | Undo/redo/clear execution is owned by injected document/app history services with no legacy `ActionManager` adapter | -| DEBT-0027 | Open | Modernization | Canvas draw-tool toolbar command, canvas input mode switching, active-state planning/execution dispatch, and canvas keyboard/touch command planning now consume pure `pp_app_core` through `App::init_toolbar_draw`, `App::update`, `NodeCanvas`, `pano_cli plan-canvas-tool`, `pano_cli plan-canvas-tool-state`, `pano_cli plan-canvas-hotkey`, `CanvasToolServices`, and `CanvasHotkeyServices`, but live adapters still mutate or read legacy `Canvas` mode state, pen picking state, touch-lock state, transform copy/cut action objects, `ActionManager`, legacy save UI, legacy stroke size controls, and cursor/UI singletons | Preserve current toolbar, stylus eraser, keyboard, and touch command behavior while canvas input/tools move toward an app/document command boundary | `pp_app_core_canvas_tool_ui_tests`; `pp_app_core_canvas_hotkey_tests`; `pano_cli plan-canvas-tool --kind copy`; `pano_cli plan-canvas-tool-state --mode draw --picking --touch-lock`; `pano_cli plan-canvas-hotkey --event key-up --key z --ctrl --undo-count 2`; `pano_cli plan-canvas-hotkey --event key-up --key s --ctrl --shift`; `ctest --preset desktop-fast --build-config Debug` | Canvas tool selection, toolbar state refresh, picking, touch lock, stylus eraser/key mode switching, hotkey/touch command dispatch, save hotkeys, history hotkeys, brush-size hotkeys, and transform action execution are owned by injected app/document/canvas services with no legacy toolbar/canvas adapter | +| DEBT-0027 | Open | Modernization | Canvas draw-tool toolbar command, canvas input mode switching, active-state planning/execution dispatch, and canvas keyboard/touch command planning now consume pure `pp_app_core` through `App::init_toolbar_draw`, `App::update`, `NodeCanvas`, `pano_cli plan-canvas-tool`, `pano_cli plan-canvas-tool-state`, `pano_cli plan-canvas-hotkey`, `CanvasToolServices`, and `CanvasHotkeyServices`, and live toolbar/input/hotkey execution is centralized in `src/legacy_canvas_tool_services.*`, but the bridge still mutates or reads legacy `Canvas` mode state, pen picking state, touch-lock state, transform copy/cut action objects, `ActionManager`, legacy save UI, legacy stroke size controls, and cursor/UI singletons | Preserve current toolbar, stylus eraser, keyboard, and touch command behavior while canvas input/tools move toward an app/document command boundary | `pp_app_core_canvas_tool_ui_tests`; `pp_app_core_canvas_hotkey_tests`; `pano_cli plan-canvas-tool --kind copy`; `pano_cli plan-canvas-tool-state --mode draw --picking --touch-lock`; `pano_cli plan-canvas-hotkey --event key-up --key z --ctrl --undo-count 2`; `pano_cli plan-canvas-hotkey --event key-up --key s --ctrl --shift`; `ctest --preset desktop-fast --build-config Debug` | Canvas tool selection, toolbar state refresh, picking, touch lock, stylus eraser/key mode switching, hotkey/touch command dispatch, save hotkeys, history hotkeys, brush-size hotkeys, and transform action execution are owned by injected app/document/canvas services with no legacy toolbar/canvas adapter | | DEBT-0028 | Open | Modernization | Canvas clear command planning and execution dispatch now consume pure `pp_app_core` through `App::init_toolbar_main`, Layer menu clear, `pano_cli plan-canvas-clear`, and the `DocumentCanvasClearServices` boundary, and toolbar/Layer-menu clear share `src/legacy_document_canvas_services.*`, but the shared live bridge still calls legacy `Canvas::clear`, which records `ActionLayerClear`, clears the current layer/frame, and marks legacy `Canvas::I` unsaved | Preserve clear-current-layer behavior while canvas/document commands move toward document/app command services | `pp_app_core_document_canvas_tests`; `pano_cli plan-canvas-clear --r 0 --g 0.1 --b 0.2 --a 0.3`; `pano_cli plan-canvas-clear --no-canvas`; `pano_cli plan-layer-menu --command clear --current-index 1 --current-name Paint`; `ctest --preset desktop-fast --build-config Debug` | Canvas clear execution, undo recording, dirty-state updates, and clear color handling are owned by injected document/app services with no legacy canvas-clear adapter | | DEBT-0029 | Open | Modernization | Image import route planning and execution dispatch now consume pure `pp_app_core` through the File menu, `pano_cli plan-image-import`, and the `DocumentImageImportServices` boundary, and live File-menu import execution is centralized in `src/legacy_app_shell_services.*`, but the bridge still loads images with legacy `Image`, calls legacy `Canvas::import_equirectangular`, or configures legacy import transform mode directly | Preserve current File > Import behavior while image import moves toward document/app/asset command services | `pp_app_core_document_import_tests`; `pano_cli plan-image-import --width 4096 --height 2048`; `pano_cli plan-image-import --width 1024 --height 1024`; `ctest --preset desktop-fast --build-config Debug` | Image loading, equirectangular import, transform-placement import, and failure reporting are owned by injected document/app/asset services with File-menu callbacks acting only as adapters and no legacy image-import adapter | | DEBT-0030 | Open | Modernization | File export menu action planning and execution dispatch now consume pure `pp_app_core` through the File menu, `pano_cli plan-export-menu`, and the `DocumentExportMenuServices` boundary, and live execution is centralized in `src/legacy_app_shell_services.*`, but the bridge still opens legacy export dialogs and then reaches legacy canvas/render/video export code | Preserve current export menu behavior while export command execution moves toward document/app/renderer/video services | `pp_app_core_document_export_tests`; `pano_cli plan-export-menu --kind png`; `pano_cli plan-export-menu --kind animation-mp4 --demo`; `pano_cli plan-export-menu --kind layers --no-canvas`; `ctest --preset desktop-fast --build-config Debug` | Export menu routing, license gating, target creation, image/layer/cube/depth/animation/timelapse execution, and error reporting are owned by injected document/app/renderer/video services with File-menu callbacks acting only as UI adapters and no legacy export adapter | diff --git a/docs/modernization/roadmap.md b/docs/modernization/roadmap.md index 87a39ee..094e38a 100644 --- a/docs/modernization/roadmap.md +++ b/docs/modernization/roadmap.md @@ -533,16 +533,17 @@ adapter continues. `pano_cli plan-canvas-tool` exposes app-core planning for draw/erase/line, camera, grid, copy, cut, fill, mask, flood-fill, pick, and touch-lock toolbar commands. Canvas tool execution now dispatches through `CanvasToolServices` -before legacy toolbar selection, `Canvas` mode, pen picking, touch-lock, and -transform state adapters continue. `pano_cli plan-canvas-tool-state` exposes -the matching toolbar active-state refresh used by `App::update` before legacy -`Canvas` mode state remains the source of truth. `NodeCanvas` stylus eraser -mode switching consumes the same app-core executor before legacy canvas mode -execution continues. `NodeCanvas` keyboard and touch command handling now -consumes `pp_app_core` canvas-hotkey planning for E draw/erase, Ctrl+Z, -Ctrl+Shift+Z, Ctrl+S, Ctrl+Shift+S, Tab UI toggle, brush-size brackets, -Android back, Alt cursor reveal, and two-finger undo before legacy UI/canvas -adapters execute the command. +through `src/legacy_canvas_tool_services.*` before legacy toolbar selection, +`Canvas` mode, pen picking, touch-lock, and transform state adapters continue. +`pano_cli plan-canvas-tool-state` exposes the matching toolbar active-state +refresh used by `App::update` before legacy `Canvas` mode state remains the +source of truth. `NodeCanvas` stylus eraser mode switching consumes the same +shared bridge through its input-only path before legacy canvas mode execution +continues. `NodeCanvas` keyboard and touch command handling now consumes +`pp_app_core` canvas-hotkey planning for E draw/erase, Ctrl+Z, Ctrl+Shift+Z, +Ctrl+S, Ctrl+Shift+S, Tab UI toggle, brush-size brackets, Android back, Alt +cursor reveal, and two-finger undo before the shared bridge delegates to legacy +UI/canvas/history adapters. `pano_cli plan-canvas-clear` exposes app-core planning for the main toolbar clear-current-layer command, including clear color validation, no-canvas handling, undo recording intent, and dirty-state intent; live toolbar execution diff --git a/src/app_layout.cpp b/src/app_layout.cpp index 30f0a98..f30c344 100644 --- a/src/app_layout.cpp +++ b/src/app_layout.cpp @@ -18,6 +18,7 @@ #include "app_core/main_toolbar.h" #include "app_core/tools_menu.h" #include "legacy_app_shell_services.h" +#include "legacy_canvas_tool_services.h" #include "legacy_document_layer_services.h" #include "legacy_history_services.h" #include "settings.h" @@ -685,126 +686,11 @@ void App::init_sidebar() }; } } -void set_canvas_tool_button_active(Node* button, bool active) -{ - if (auto* custom = dynamic_cast(button)) { - custom->set_active(active); - return; - } - if (auto* regular = dynamic_cast(button)) { - regular->set_active(active); - } -} - -void select_canvas_tool_button(Node* main, Node* button) -{ - main->find("btn-pen")->set_active(false); - main->find("btn-erase")->set_active(false); - main->find("btn-line")->set_active(false); - main->find("btn-cam")->set_active(false); - main->find("btn-grid")->set_active(false); - main->find("btn-copy")->set_active(false); - main->find("btn-cut")->set_active(false); - main->find("btn-mask-free")->set_active(false); - main->find("btn-mask-line")->set_active(false); - main->find("btn-bucket")->set_active(false); - set_canvas_tool_button_active(button, false); -} - -kCanvasMode canvas_mode_from_tool(pp::app::CanvasToolMode mode) -{ - switch (mode) { - case pp::app::CanvasToolMode::draw: - return kCanvasMode::Draw; - case pp::app::CanvasToolMode::erase: - return kCanvasMode::Erase; - case pp::app::CanvasToolMode::line: - return kCanvasMode::Line; - case pp::app::CanvasToolMode::camera: - return kCanvasMode::Camera; - case pp::app::CanvasToolMode::grid: - return kCanvasMode::Grid; - case pp::app::CanvasToolMode::copy: - return kCanvasMode::Copy; - case pp::app::CanvasToolMode::cut: - return kCanvasMode::Cut; - case pp::app::CanvasToolMode::fill: - return kCanvasMode::Fill; - case pp::app::CanvasToolMode::mask_free: - return kCanvasMode::MaskFree; - case pp::app::CanvasToolMode::mask_line: - return kCanvasMode::MaskLine; - case pp::app::CanvasToolMode::flood_fill: - return kCanvasMode::FloodFill; - } - return kCanvasMode::Draw; -} - -class LegacyCanvasToolServices final : public pp::app::CanvasToolServices { -public: - LegacyCanvasToolServices(App& app, Node* toolbar_button = nullptr) noexcept - : app_(app) - , toolbar_button_(toolbar_button) - { - } - - void select_toolbar_button(pp::app::CanvasToolMode) override - { - if (toolbar_button_) - select_canvas_tool_button(app_.layout[app_.main_id], toolbar_button_); - } - - void set_transform_action(pp::app::CanvasToolTransformAction action) override - { - if (!app_.canvas || !app_.canvas->m_canvas) - return; - - if (action == pp::app::CanvasToolTransformAction::copy) { - auto* transform = static_cast( - app_.canvas->m_canvas->modes[(int)kCanvasMode::Copy][0]); - transform->m_action = CanvasModeTransform::ActionType::Copy; - } else if (action == pp::app::CanvasToolTransformAction::cut) { - auto* transform = static_cast( - app_.canvas->m_canvas->modes[(int)kCanvasMode::Cut][0]); - transform->m_action = CanvasModeTransform::ActionType::Cut; - } - } - - void set_canvas_mode(pp::app::CanvasToolMode mode) override - { - Canvas::set_mode(canvas_mode_from_tool(mode)); - } - - void toggle_picking() override - { - if (!app_.canvas || !app_.canvas->m_canvas) - return; - - auto* mode = static_cast( - app_.canvas->m_canvas->modes[(int)kCanvasMode::Draw][0]); - if (mode) - mode->m_picking = !mode->m_picking; - } - - void toggle_touch_lock() override - { - if (!app_.canvas || !app_.canvas->m_canvas) - return; - - app_.canvas->m_canvas->m_touch_lock = !app_.canvas->m_canvas->m_touch_lock; - } - -private: - App& app_; - Node* toolbar_button_ = nullptr; -}; - template void apply_canvas_tool_select(App& app, T* button, pp::app::CanvasToolMode mode) { const auto plan = pp::app::plan_canvas_tool_select(mode); - LegacyCanvasToolServices services(app, button); - const auto status = pp::app::execute_canvas_tool_plan(plan, services); + const auto status = pp::panopainter::execute_legacy_canvas_tool_plan(app, plan, button); if (!status.ok()) LOG("Canvas tool select action failed: %s", status.message); } @@ -818,8 +704,7 @@ void App::init_toolbar_draw() }; //button->set_active(true); const auto plan = pp::app::plan_canvas_tool_select(pp::app::CanvasToolMode::draw); - LegacyCanvasToolServices services(*this); - const auto status = pp::app::execute_canvas_tool_plan(plan, services); + const auto status = pp::panopainter::execute_legacy_canvas_tool_plan(*this, plan); if (!status.ok()) LOG("Canvas default tool action failed: %s", status.message); } @@ -828,8 +713,7 @@ void App::init_toolbar_draw() button->on_click = [this](Node*) { const auto plan = pp::app::plan_canvas_tool_pick_toggle( canvas->m_canvas->m_current_mode == kCanvasMode::Draw); - LegacyCanvasToolServices services(*this); - const auto status = pp::app::execute_canvas_tool_plan(plan, services); + const auto status = pp::panopainter::execute_legacy_canvas_tool_plan(*this, plan); if (!status.ok()) LOG("Canvas pick action failed: %s", status.message); }; @@ -838,8 +722,7 @@ void App::init_toolbar_draw() { button->on_click = [this](Node*) { const auto plan = pp::app::plan_canvas_tool_touch_lock_toggle(); - LegacyCanvasToolServices services(*this); - const auto status = pp::app::execute_canvas_tool_plan(plan, services); + const auto status = pp::panopainter::execute_legacy_canvas_tool_plan(*this, plan); if (!status.ok()) LOG("Canvas touch-lock action failed: %s", status.message); }; diff --git a/src/legacy_canvas_tool_services.cpp b/src/legacy_canvas_tool_services.cpp new file mode 100644 index 0000000..92224b9 --- /dev/null +++ b/src/legacy_canvas_tool_services.cpp @@ -0,0 +1,224 @@ +#include "pch.h" + +#include "legacy_canvas_tool_services.h" + +#include "app.h" +#include "legacy_history_services.h" + +namespace pp::panopainter { +namespace { + +void set_canvas_tool_button_active(Node* button, bool active) +{ + if (auto* custom = dynamic_cast(button)) { + custom->set_active(active); + return; + } + if (auto* regular = dynamic_cast(button)) { + regular->set_active(active); + } +} + +void select_canvas_tool_button(Node* main, Node* button) +{ + main->find("btn-pen")->set_active(false); + main->find("btn-erase")->set_active(false); + main->find("btn-line")->set_active(false); + main->find("btn-cam")->set_active(false); + main->find("btn-grid")->set_active(false); + main->find("btn-copy")->set_active(false); + main->find("btn-cut")->set_active(false); + main->find("btn-mask-free")->set_active(false); + main->find("btn-mask-line")->set_active(false); + main->find("btn-bucket")->set_active(false); + set_canvas_tool_button_active(button, false); +} + +kCanvasMode canvas_mode_from_tool(pp::app::CanvasToolMode mode) +{ + switch (mode) { + case pp::app::CanvasToolMode::draw: + return kCanvasMode::Draw; + case pp::app::CanvasToolMode::erase: + return kCanvasMode::Erase; + case pp::app::CanvasToolMode::line: + return kCanvasMode::Line; + case pp::app::CanvasToolMode::camera: + return kCanvasMode::Camera; + case pp::app::CanvasToolMode::grid: + return kCanvasMode::Grid; + case pp::app::CanvasToolMode::copy: + return kCanvasMode::Copy; + case pp::app::CanvasToolMode::cut: + return kCanvasMode::Cut; + case pp::app::CanvasToolMode::fill: + return kCanvasMode::Fill; + case pp::app::CanvasToolMode::mask_free: + return kCanvasMode::MaskFree; + case pp::app::CanvasToolMode::mask_line: + return kCanvasMode::MaskLine; + case pp::app::CanvasToolMode::flood_fill: + return kCanvasMode::FloodFill; + } + return kCanvasMode::Draw; +} + +class LegacyCanvasToolServices final : public pp::app::CanvasToolServices { +public: + LegacyCanvasToolServices(App* app, Node* toolbar_button = nullptr) noexcept + : app_(app) + , toolbar_button_(toolbar_button) + { + } + + void select_toolbar_button(pp::app::CanvasToolMode) override + { + if (app_ && toolbar_button_) + select_canvas_tool_button(app_->layout[app_->main_id], toolbar_button_); + } + + void set_transform_action(pp::app::CanvasToolTransformAction action) override + { + if (!app_ || !app_->canvas || !app_->canvas->m_canvas) + return; + + if (action == pp::app::CanvasToolTransformAction::copy) { + auto* transform = static_cast( + app_->canvas->m_canvas->modes[(int)kCanvasMode::Copy][0]); + transform->m_action = CanvasModeTransform::ActionType::Copy; + } else if (action == pp::app::CanvasToolTransformAction::cut) { + auto* transform = static_cast( + app_->canvas->m_canvas->modes[(int)kCanvasMode::Cut][0]); + transform->m_action = CanvasModeTransform::ActionType::Cut; + } + } + + void set_canvas_mode(pp::app::CanvasToolMode mode) override + { + Canvas::set_mode(canvas_mode_from_tool(mode)); + } + + void toggle_picking() override + { + if (!app_ || !app_->canvas || !app_->canvas->m_canvas) + return; + + auto* mode = static_cast( + app_->canvas->m_canvas->modes[(int)kCanvasMode::Draw][0]); + if (mode) + mode->m_picking = !mode->m_picking; + } + + void toggle_touch_lock() override + { + if (!app_ || !app_->canvas || !app_->canvas->m_canvas) + return; + + app_->canvas->m_canvas->m_touch_lock = !app_->canvas->m_canvas->m_touch_lock; + } + +private: + App* app_ = nullptr; + Node* toolbar_button_ = nullptr; +}; + +class LegacyCanvasInputToolServices final : public pp::app::CanvasToolServices { +public: + void select_toolbar_button(pp::app::CanvasToolMode) override + { + } + + void set_transform_action(pp::app::CanvasToolTransformAction) override + { + } + + void set_canvas_mode(pp::app::CanvasToolMode mode) override + { + switch (mode) { + case pp::app::CanvasToolMode::draw: + Canvas::set_mode(kCanvasMode::Draw); + return; + case pp::app::CanvasToolMode::erase: + Canvas::set_mode(kCanvasMode::Erase); + return; + default: + return; + } + } + + void toggle_picking() override + { + } + + void toggle_touch_lock() override + { + } +}; + +class LegacyCanvasHotkeyServices final : public pp::app::CanvasHotkeyServices { +public: + pp::foundation::Status execute_tool(const pp::app::CanvasToolPlan& plan) override + { + return execute_legacy_canvas_input_tool_plan(plan); + } + + pp::foundation::Status execute_history(const pp::app::HistoryUiPlan& plan) override + { + return execute_legacy_history_plan(plan); + } + + void save_document(pp::app::DocumentSaveIntent intent) override + { + if (App::I) + App::I->save_document(intent); + } + + void toggle_ui() override + { + if (App::I) + App::I->toggle_ui(); + } + + void adjust_brush_size(float delta) override + { + if (!App::I || !App::I->stroke || !App::I->stroke->m_tip_size) + return; + + const float value = App::I->stroke->m_tip_size->get_value(); + const float next_value = glm::clamp(value + delta, 0.0F, 1.0F); + App::I->stroke->set_size(next_value, true, true); + } + + void show_cursor() override + { + if (App::I) + App::I->show_cursor(); + } +}; + +} // namespace + +pp::foundation::Status execute_legacy_canvas_tool_plan( + App& app, + const pp::app::CanvasToolPlan& plan, + Node* toolbar_button) +{ + LegacyCanvasToolServices services(&app, toolbar_button); + return pp::app::execute_canvas_tool_plan(plan, services); +} + +pp::foundation::Status execute_legacy_canvas_input_tool_plan( + const pp::app::CanvasToolPlan& plan) +{ + LegacyCanvasInputToolServices services; + return pp::app::execute_canvas_tool_plan(plan, services); +} + +pp::foundation::Status execute_legacy_canvas_hotkey_plan( + const pp::app::CanvasHotkeyPlan& plan) +{ + LegacyCanvasHotkeyServices services; + return pp::app::execute_canvas_hotkey_plan(plan, services); +} + +} // namespace pp::panopainter diff --git a/src/legacy_canvas_tool_services.h b/src/legacy_canvas_tool_services.h new file mode 100644 index 0000000..4c4c042 --- /dev/null +++ b/src/legacy_canvas_tool_services.h @@ -0,0 +1,21 @@ +#pragma once + +#include "app_core/canvas_hotkey.h" +#include "app_core/canvas_tool_ui.h" +#include "foundation/result.h" + +class App; +class Node; + +namespace pp::panopainter { + +[[nodiscard]] pp::foundation::Status execute_legacy_canvas_tool_plan( + App& app, + const pp::app::CanvasToolPlan& plan, + Node* toolbar_button = nullptr); +[[nodiscard]] pp::foundation::Status execute_legacy_canvas_input_tool_plan( + const pp::app::CanvasToolPlan& plan); +[[nodiscard]] pp::foundation::Status execute_legacy_canvas_hotkey_plan( + const pp::app::CanvasHotkeyPlan& plan); + +} // namespace pp::panopainter diff --git a/src/node_canvas.cpp b/src/node_canvas.cpp index a1263c9..53e2e51 100644 --- a/src/node_canvas.cpp +++ b/src/node_canvas.cpp @@ -8,6 +8,7 @@ #include "app_core/canvas_hotkey.h" #include "app_core/canvas_tool_ui.h" #include "app.h" +#include "legacy_canvas_tool_services.h" #include "legacy_history_services.h" #include "log.h" #include "node_canvas.h" @@ -70,78 +71,6 @@ pp::paint_renderer::CanvasBlendGatePlan node_canvas_blend_gate_plan( return fallback; } -class LegacyNodeCanvasToolServices final : public pp::app::CanvasToolServices { -public: - void select_toolbar_button(pp::app::CanvasToolMode) override - { - } - - void set_transform_action(pp::app::CanvasToolTransformAction) override - { - } - - void set_canvas_mode(pp::app::CanvasToolMode mode) override - { - switch (mode) { - case pp::app::CanvasToolMode::draw: - Canvas::set_mode(kCanvasMode::Draw); - return; - case pp::app::CanvasToolMode::erase: - Canvas::set_mode(kCanvasMode::Erase); - return; - default: - return; - } - } - - void toggle_picking() override - { - } - - void toggle_touch_lock() override - { - } -}; - -class LegacyNodeCanvasHotkeyServices final : public pp::app::CanvasHotkeyServices { -public: - pp::foundation::Status execute_tool(const pp::app::CanvasToolPlan& plan) override - { - LegacyNodeCanvasToolServices services; - return pp::app::execute_canvas_tool_plan(plan, services); - } - - pp::foundation::Status execute_history(const pp::app::HistoryUiPlan& plan) override - { - return pp::panopainter::execute_legacy_history_plan(plan); - } - - void save_document(pp::app::DocumentSaveIntent intent) override - { - App::I->save_document(intent); - } - - void toggle_ui() override - { - App::I->toggle_ui(); - } - - void adjust_brush_size(float delta) override - { - if (!App::I || !App::I->stroke || !App::I->stroke->m_tip_size) - return; - - const float value = App::I->stroke->m_tip_size->get_value(); - const float next_value = glm::clamp(value + delta, 0.0F, 1.0F); - App::I->stroke->set_size(next_value, true, true); - } - - void show_cursor() override - { - App::I->show_cursor(); - } -}; - pp::app::CanvasHotkeyKey canvas_hotkey_key(kKey key) noexcept { switch (key) { @@ -181,8 +110,7 @@ pp::app::CanvasHotkeyState canvas_hotkey_state(bool mouse_focused, int touch_fin void execute_canvas_hotkey_plan(const pp::app::CanvasHotkeyPlan& plan) { - LegacyNodeCanvasHotkeyServices services; - const auto status = pp::app::execute_canvas_hotkey_plan(plan, services); + const auto status = pp::panopainter::execute_legacy_canvas_hotkey_plan(plan); if (!status.ok()) LOG("Canvas hotkey action failed: %s", status.message); } @@ -206,8 +134,7 @@ void run_canvas_hotkey( void run_canvas_tool_mode(pp::app::CanvasToolMode mode) { const auto plan = pp::app::plan_canvas_tool_select(mode); - LegacyNodeCanvasToolServices services; - const auto status = pp::app::execute_canvas_tool_plan(plan, services); + const auto status = pp::panopainter::execute_legacy_canvas_input_tool_plan(plan); if (!status.ok()) LOG("Canvas input tool action failed: %s", status.message); }