From b505d9f727e92b0aec0ebfa087f2f2fcad943173 Mon Sep 17 00:00:00 2001 From: omigamedev Date: Wed, 17 Jun 2026 19:37:58 +0200 Subject: [PATCH] Extract app dialog and binding service seams --- cmake/PanoPainterSources.cmake | 8 ++ docs/modernization/debt.md | 21 ++++ docs/modernization/roadmap.md | 7 ++ docs/modernization/tasks.md | 23 ++++ src/app_dialogs_info_openers.cpp | 38 +++---- src/app_dialogs_workflow.cpp | 108 +------------------ src/app_layout.cpp | 17 +-- src/app_layout_draw_toolbar.cpp | 64 +---------- src/app_layout_sidebar.cpp | 41 +------ src/legacy_app_status_services.cpp | 28 +++++ src/legacy_app_status_services.h | 9 ++ src/legacy_document_session_services.cpp | 92 ++++++++++++++++ src/legacy_document_session_services.h | 4 + src/legacy_draw_toolbar_binding_services.cpp | 62 +++++++++++ src/legacy_draw_toolbar_binding_services.h | 10 ++ src/legacy_info_dialog_services.cpp | 52 +++++++++ src/legacy_info_dialog_services.h | 12 +++ src/legacy_sidebar_stroke_popup_services.cpp | 68 ++++++++++++ src/legacy_sidebar_stroke_popup_services.h | 16 +++ 19 files changed, 432 insertions(+), 248 deletions(-) create mode 100644 src/legacy_app_status_services.cpp create mode 100644 src/legacy_app_status_services.h create mode 100644 src/legacy_draw_toolbar_binding_services.cpp create mode 100644 src/legacy_draw_toolbar_binding_services.h create mode 100644 src/legacy_info_dialog_services.cpp create mode 100644 src/legacy_info_dialog_services.h create mode 100644 src/legacy_sidebar_stroke_popup_services.cpp create mode 100644 src/legacy_sidebar_stroke_popup_services.h diff --git a/cmake/PanoPainterSources.cmake b/cmake/PanoPainterSources.cmake index a00fab13..ba1d63c9 100644 --- a/cmake/PanoPainterSources.cmake +++ b/cmake/PanoPainterSources.cmake @@ -94,12 +94,16 @@ set(PP_LEGACY_APP_SOURCES src/legacy_canvas_mode_transform.cpp src/legacy_app_shell_services.cpp src/legacy_app_shell_services.h + src/legacy_app_status_services.cpp + src/legacy_app_status_services.h src/legacy_app_ui_state_services.cpp src/legacy_app_ui_state_services.h src/legacy_about_menu_binding_services.cpp src/legacy_about_menu_binding_services.h src/legacy_app_shell_performance_test_services.cpp src/legacy_app_shell_performance_test_services.h + src/legacy_info_dialog_services.cpp + src/legacy_info_dialog_services.h src/legacy_canvas_tool_services.cpp src/legacy_canvas_tool_services.h src/legacy_canvas_view_services.cpp @@ -155,8 +159,12 @@ set(PP_PANOPAINTER_APP_SOURCES src/app_layout_bootstrap.cpp src/app_layout_brush.cpp src/app_layout_draw_toolbar.cpp + src/legacy_draw_toolbar_binding_services.cpp + src/legacy_draw_toolbar_binding_services.h src/app_layout_ui_state.cpp src/app_layout_sidebar.cpp + src/legacy_sidebar_stroke_popup_services.cpp + src/legacy_sidebar_stroke_popup_services.h src/legacy_sidebar_color_popup_services.cpp src/legacy_sidebar_color_popup_services.h src/app_layout_main_toolbar.cpp diff --git a/docs/modernization/debt.md b/docs/modernization/debt.md index c4dbf0e1..195da7b6 100644 --- a/docs/modernization/debt.md +++ b/docs/modernization/debt.md @@ -791,6 +791,27 @@ agent or engineer to remove them without reconstructing context from chat. no longer self-destroy their cancel/OK buttons through `bind_legacy_click_destroys_node(...)`; menu/layout-owned popup families still remain on separate retained cleanup paths. +- 2026-06-17: `DEBT-0058`/`DEBT-0063` were narrowed again. The retained + usermanual, changelog, and about openers in `src/app_dialogs_info_openers.cpp` + now delegate retained dialog construction and overlay close wiring through + `src/legacy_info_dialog_services.*` with explicit `App&` plus overlay-anchor + dependencies, so the app dialog shell no longer owns that info-dialog family + inline while `open_whatsnew_dialog()` still owns the retained whats-new flow + inline. +- 2026-06-17: `DEBT-0058`/`DEBT-0063` were narrowed again. The retained New + Document and Save dialog openers in `src/app_dialogs_workflow.cpp` now + delegate retained dialog construction and button wiring through + `src/legacy_document_session_services.*` with explicit `App&` ownership, so + the app dialog shell no longer owns that document-session dialog family + inline while browse, open, and resize flows still remain there. +- 2026-06-17: `DEBT-0035` was narrowed again. `App::title_update()` and the + draw-toolbar/stroke-popup binding families now delegate through + `src/legacy_app_status_services.*`, + `src/legacy_draw_toolbar_binding_services.*`, and + `src/legacy_sidebar_stroke_popup_services.*`, so + `src/app_layout.cpp`, `src/app_layout_draw_toolbar.cpp`, and part of + `src/app_layout_sidebar.cpp` are thinner adapters while retained app-shell + execution and remaining popup families still stay open under the same debt. - 2026-06-15: `DEBT-0036` was narrowed again. `NodeStrokePreview` now drops the retained pass-sequence, mix-execution, final-composite-request, background capture, and preview-copy wrapper structs/functions in favor of direct diff --git a/docs/modernization/roadmap.md b/docs/modernization/roadmap.md index 9afa28b6..bc441042 100644 --- a/docs/modernization/roadmap.md +++ b/docs/modernization/roadmap.md @@ -92,6 +92,13 @@ Current conclusion: routes through `src/legacy_app_ui_state_services.*`, so more of the retained app shell is down to adapter calls even though runtime draw/event/sidebar execution still remains. +- New-document/save dialog session wiring, app-title rendering, draw-toolbar + binding, sidebar stroke-popup binding, and usermanual/changelog/about opener + wiring now live in dedicated `legacy_*services.*` seams, so + `src/app_dialogs_workflow.cpp`, `src/app_layout.cpp`, + `src/app_layout_draw_toolbar.cpp`, `src/app_layout_sidebar.cpp`, and + `src/app_dialogs_info_openers.cpp` are thinner adapters even though broader + retained dialog/sidebar execution still remains. - Platform extraction improved substantially and the root app source group no longer compiles Web platform sources directly, but broader CMake and entrypoint cleanup are not complete. diff --git a/docs/modernization/tasks.md b/docs/modernization/tasks.md index 0633b75c..4e6ff2a6 100644 --- a/docs/modernization/tasks.md +++ b/docs/modernization/tasks.md @@ -101,6 +101,29 @@ Key facts: `App&`, popup-root, trigger-button, and panel dependencies, so `src/app_layout_sidebar.cpp` is thinner while the retained stroke/grid/layer popup families still remain inline. +- `App::dialog_usermanual()`, `App::dialog_changelog()`, and + `App::dialog_about()` now delegate the retained info-dialog construction and + overlay close wiring through `src/legacy_info_dialog_services.*` with + explicit `App&` plus overlay-anchor dependencies, so + `src/app_dialogs_info_openers.cpp` is thinner while `open_whatsnew_dialog()` + still owns the retained whats-new flow inline. +- `App::dialog_newdoc()` and `App::dialog_save()` now delegate retained dialog + construction and button wiring through `src/legacy_document_session_services.*`, + so `src/app_dialogs_workflow.cpp` is thinner at the document-session seam + while browse, open, and resize retained workflows still remain there. +- `App::title_update()` now delegates retained document-title and DPI-label + rendering through `src/legacy_app_status_services.*`, so + `src/app_layout.cpp` no longer owns that app-status family inline. +- `App::init_toolbar_draw()` now delegates retained draw-toolbar button lookup, + click wiring, and default-tool application through + `src/legacy_draw_toolbar_binding_services.*`, so + `src/app_layout_draw_toolbar.cpp` is down to a thin adapter while retained + tool execution still flows through `src/legacy_canvas_tool_services.*`. +- `App::init_sidebar()` now delegates the retained stroke-popup open/anchor/tick + wiring through `src/legacy_sidebar_stroke_popup_services.*` with explicit + `App&`, popup-root, trigger-button, and panel dependencies, so + `src/app_layout_sidebar.cpp` is thinner while the retained grid and layer + popup families still remain inline. ## Parallel Assignment Rules diff --git a/src/app_dialogs_info_openers.cpp b/src/app_dialogs_info_openers.cpp index 2f67d685..e8224b9b 100644 --- a/src/app_dialogs_info_openers.cpp +++ b/src/app_dialogs_info_openers.cpp @@ -2,59 +2,45 @@ #include "app.h" #include "legacy_preference_storage.h" #include "legacy_ui_overlay_services.h" -#include "node_about.h" -#include "node_changelog.h" +#include "legacy_info_dialog_services.h" #include "node_remote_page.h" #include "node_shorcuts.h" -#include "node_usermanual.h" #include "version.h" namespace pp::panopainter { namespace { -template -void open_info_dialog(App& app, const char* log_name) +Node* get_legacy_info_dialog_overlay_anchor(App& app, const char* log_name) { auto* overlay_anchor = app.layout[app.main_id]; if (!overlay_anchor) { LOG("%s dialog open failed: main layout anchor is missing", log_name); - return; } - - auto dialog = make_legacy_overlay_node(app); - const auto overlay = open_legacy_overlay_node_with_handle(*overlay_anchor, dialog); - if (!overlay) { - LOG("%s dialog open failed: %s", log_name, overlay.status().message); - return; - } - const auto overlay_handle = overlay.value(); - - const auto close_dialog = [overlay_anchor, overlay_handle]() { - const auto close_status = close_legacy_overlay_node(*overlay_anchor, overlay_handle); - (void)close_status; - }; - - dialog->btn_ok->on_click = [close_dialog](Node*) { - close_dialog(); - }; + return overlay_anchor; } } // namespace void open_usermanual_dialog(App& app) { - open_info_dialog(app, "User manual"); + if (auto* overlay_anchor = get_legacy_info_dialog_overlay_anchor(app, "User manual")) { + pp::panopainter::open_usermanual_dialog(app, *overlay_anchor, "User manual"); + } } void open_changelog_dialog(App& app) { - open_info_dialog(app, "Changelog"); + if (auto* overlay_anchor = get_legacy_info_dialog_overlay_anchor(app, "Changelog")) { + pp::panopainter::open_changelog_dialog(app, *overlay_anchor, "Changelog"); + } } void open_about_dialog(App& app) { - open_info_dialog(app, "About"); + if (auto* overlay_anchor = get_legacy_info_dialog_overlay_anchor(app, "About")) { + pp::panopainter::open_about_dialog(app, *overlay_anchor, "About"); + } } void open_whatsnew_dialog(App& app, bool force_show) diff --git a/src/app_dialogs_workflow.cpp b/src/app_dialogs_workflow.cpp index 0ce9c496..4b54cc03 100644 --- a/src/app_dialogs_workflow.cpp +++ b/src/app_dialogs_workflow.cpp @@ -9,27 +9,6 @@ #include "node_dialog_open.h" #include "node_dialog_resize.h" -namespace { - -void wire_document_save_dialog_buttons( - App& app, - const std::shared_ptr& dialog, - std::function close_dialog) -{ - dialog->btn_ok->on_click = [&app, dialog](Node*) - { - const auto status = pp::panopainter::execute_legacy_document_file_save_dialog(app, dialog); - if (!status.ok()) - LOG("Document file save action failed: %s", status.message); - }; - dialog->btn_cancel->on_click = [close_dialog](Node*) - { - close_dialog(); - }; -} - -} // namespace - void App::continue_document_workflow_after_optional_save(std::function action) { const bool has_canvas = canvas != nullptr; @@ -46,62 +25,7 @@ void App::continue_document_workflow_after_optional_save(std::function a void App::dialog_newdoc() { auto show_dialog = [this] { - auto* overlay_anchor = layout[main_id]; - if (!overlay_anchor) { - LOG("New document dialog open failed: main layout anchor is missing"); - return; - } - - auto dialog = pp::panopainter::make_legacy_overlay_node(*this); - dialog->input->set_text("name"); - - App::I->showKeyboard(); - - const auto overlay = pp::panopainter::open_legacy_overlay_node_with_handle(*overlay_anchor, dialog); - if (!overlay) { - App::I->hideKeyboard(); - LOG("New document dialog open failed: %s", overlay.status().message); - return; - } - const auto overlay_handle = overlay.value(); - - const auto close_dialog = [this, overlay_anchor, overlay_handle]() { - const auto close_status = - pp::panopainter::close_legacy_overlay_node(*overlay_anchor, overlay_handle); - (void)close_status; - App::I->hideKeyboard(); - }; - - dialog->btn_ok->on_click = [this, dialog](Node*) - { - std::string name = dialog->input->m_text; - const auto plan = pp::app::plan_new_document( - work_path, - name, - dialog->m_resolution->m_current_index, - [](const std::string& path) { - return Asset::exist(path); - }); - if (!plan) - { - const bool missing_name = - plan.status().code == pp::foundation::StatusCode::invalid_argument; - message_box( - "Warning", - missing_name ? "You need to specify a name to file." : plan.status().message); - return; - } - - const auto status = - pp::panopainter::execute_legacy_new_document_plan(*this, plan.value(), dialog); - if (!status.ok()) - LOG("New document action failed: %s", status.message); - - }; - dialog->btn_cancel->on_click = [close_dialog](Node*) - { - close_dialog(); - }; + pp::panopainter::open_legacy_new_document_dialog(*this); }; continue_document_workflow_after_optional_save(show_dialog); @@ -219,35 +143,7 @@ void App::dialog_save() } if (canvas) - { - auto* overlay_anchor = layout[main_id]; - if (!overlay_anchor) { - LOG("Save document dialog open failed: main layout anchor is missing"); - return; - } - - auto dialog = pp::panopainter::make_legacy_overlay_node(*this); - dialog->input->set_text(doc_name); - - App::I->showKeyboard(); - - const auto overlay = pp::panopainter::open_legacy_overlay_node_with_handle(*overlay_anchor, dialog); - if (!overlay) { - App::I->hideKeyboard(); - LOG("Save document dialog open failed: %s", overlay.status().message); - return; - } - const auto overlay_handle = overlay.value(); - - const auto close_dialog = [this, overlay_anchor, overlay_handle]() { - const auto close_status = - pp::panopainter::close_legacy_overlay_node(*overlay_anchor, overlay_handle); - (void)close_status; - App::I->hideKeyboard(); - }; - - wire_document_save_dialog_buttons(*this, dialog, close_dialog); - } + pp::panopainter::open_legacy_document_file_save_dialog(*this); } void App::dialog_resize() diff --git a/src/app_layout.cpp b/src/app_layout.cpp index 87c0da71..7a188133 100644 --- a/src/app_layout.cpp +++ b/src/app_layout.cpp @@ -1,13 +1,12 @@ #include "pch.h" #include "app.h" -#include "node_text.h" #include "node_panel_floating.h" #include "app_core/about_menu.h" #include "app_core/app_preferences.h" #include "app_core/document_layer.h" #include "app_core/document_canvas.h" -#include "app_core/app_status.h" #include "app_core/tools_menu.h" +#include "legacy_app_status_services.h" #include "legacy_app_preference_services.h" #include "legacy_app_shell_services.h" #include "legacy_document_layer_services.h" @@ -65,19 +64,7 @@ void execute_document_layer_merge_plan(App& app, const pp::app::DocumentLayerMer void App::title_update() { - if (auto docname = layout[main_id]->find("txt-docname")) - { - const auto title = pp::app::make_document_title( - doc_name, - canvas->m_canvas->m_unsaved, - canvas->m_canvas->m_width); - docname->set_text(title.c_str()); - } - if (auto node = layout[main_id]->find("txt-dpi")) - { - const auto label = pp::app::make_dpi_label(zoom); - node->set_text(label.c_str()); - } + pp::panopainter::update_legacy_app_title(*this); } void App::init_toolbar_main() diff --git a/src/app_layout_draw_toolbar.cpp b/src/app_layout_draw_toolbar.cpp index d3114469..623f6f70 100644 --- a/src/app_layout_draw_toolbar.cpp +++ b/src/app_layout_draw_toolbar.cpp @@ -1,68 +1,8 @@ #include "pch.h" #include "app.h" -#include "app_core/canvas_tool_ui.h" -#include "legacy_canvas_tool_services.h" -#include "node_button.h" -#include "node_button_custom.h" - -namespace { - -[[nodiscard]] bool current_canvas_mode_is_draw(App& app) noexcept -{ - return app.canvas && app.canvas->m_canvas && app.canvas->m_canvas->m_current_mode == kCanvasMode::Draw; -} - -template -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 toolbar action failed: %s", status.message); -} - -template -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); - }; -} - -} // namespace +#include "legacy_draw_toolbar_binding_services.h" void App::init_toolbar_draw() { - 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(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(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); - } + pp::panopainter::bind_legacy_draw_toolbar_buttons(*this, *layout[main_id]); } diff --git a/src/app_layout_sidebar.cpp b/src/app_layout_sidebar.cpp index 05d2e16d..a866d5d9 100644 --- a/src/app_layout_sidebar.cpp +++ b/src/app_layout_sidebar.cpp @@ -5,6 +5,7 @@ #include "app_core/brush_ui.h" #include "app_core/document_layer.h" #include "legacy_sidebar_color_popup_services.h" +#include "legacy_sidebar_stroke_popup_services.h" #include "legacy_brush_ui_services.h" #include "legacy_document_layer_services.h" #include "legacy_ui_overlay_services.h" @@ -234,45 +235,7 @@ void App::init_sidebar() if (!popup_root) { return; } - auto screen = popup_root->m_size; - glm::vec2 pos = button->m_pos + glm::vec2(button->m_size.x * 0.5f, button->m_size.y); - if (stroke->m_parent) - { - if (auto fp = dynamic_cast(stroke->m_parent->m_parent)) - { - pp::panopainter::detach_legacy_node_from_parent(*stroke); - pp::panopainter::close_legacy_dialog_node(*fp); - } - } - const auto popup_overlay = pp::panopainter::open_legacy_overlay_node_with_handle(*popup_root, stroke); - if (!popup_overlay) { - return; - } - stroke->SetSize(350, glm::max(100.f, screen.y - pos.y - 50.f)); - stroke->find("title")->SetVisibility(true); - auto tick = pp::panopainter::make_legacy_overlay_node_for_anchor(*popup_root); - tick->SetPositioning(YGPositionTypeAbsolute); - tick->SetSize(32, 16); - tick->SetPosition(pos.x - 16, pos.y); - tick->set_image("data/ui/popup-tick-up.png"); - auto tick_overlay = pp::panopainter::open_legacy_overlay_node_with_handle(*popup_root, tick); - if (!popup_overlay || !tick_overlay) - { - close_legacy_overlay_handles_if_open(*popup_root, popup_overlay, tick_overlay); - return; - } - const auto popup_handle = popup_overlay.value(); - const auto tick_handle = tick_overlay.value(); - popup_root->update(); - - stroke->SetPosition(pos.x - stroke->m_size.x / 2.f, pos.y + 16); - stroke->SetPositioning(YGPositionTypeAbsolute); - pp::panopainter::activate_legacy_popup_overlay(*stroke); - auto scroll = stroke->find("scroller"); - (void)scroll; - stroke->m_popup_overlay_handle = popup_handle; - stroke->m_tick_overlay_handle = tick_handle; - + pp::panopainter::open_legacy_sidebar_stroke_popup(*this, *popup_root, *button, *stroke); }; } //if (auto* button = layout[main_id]->find("btn-brush")) diff --git a/src/legacy_app_status_services.cpp b/src/legacy_app_status_services.cpp new file mode 100644 index 00000000..9f900c87 --- /dev/null +++ b/src/legacy_app_status_services.cpp @@ -0,0 +1,28 @@ +#include "pch.h" + +#include "legacy_app_status_services.h" + +#include "app.h" +#include "app_core/app_status.h" +#include "node_text.h" + +namespace pp::panopainter { + +void update_legacy_app_title(App& app) +{ + if (auto docname = app.layout[app.main_id]->find("txt-docname")) + { + const auto title = pp::app::make_document_title( + app.doc_name, + app.canvas->m_canvas->m_unsaved, + app.canvas->m_canvas->m_width); + docname->set_text(title.c_str()); + } + if (auto node = app.layout[app.main_id]->find("txt-dpi")) + { + const auto label = pp::app::make_dpi_label(app.zoom); + node->set_text(label.c_str()); + } +} + +} // namespace pp::panopainter diff --git a/src/legacy_app_status_services.h b/src/legacy_app_status_services.h new file mode 100644 index 00000000..78f254c9 --- /dev/null +++ b/src/legacy_app_status_services.h @@ -0,0 +1,9 @@ +#pragma once + +class App; + +namespace pp::panopainter { + +void update_legacy_app_title(App& app); + +} // namespace pp::panopainter diff --git a/src/legacy_document_session_services.cpp b/src/legacy_document_session_services.cpp index f57047e2..8a187f6f 100644 --- a/src/legacy_document_session_services.cpp +++ b/src/legacy_document_session_services.cpp @@ -405,6 +405,88 @@ private: std::function action_; }; +void open_legacy_new_document_dialog_impl(App& app) +{ + auto* overlay_anchor = app.layout[app.main_id]; + if (!overlay_anchor) { + LOG("New document dialog open failed: main layout anchor is missing"); + return; + } + + auto dialog = pp::panopainter::make_legacy_overlay_node(app); + dialog->input->set_text("name"); + + app.showKeyboard(); + + const auto overlay = pp::panopainter::open_legacy_overlay_node_with_handle(*overlay_anchor, dialog); + if (!overlay) { + app.hideKeyboard(); + LOG("New document dialog open failed: %s", overlay.status().message); + return; + } + + dialog->btn_ok->on_click = [&app, dialog](Node*) { + const auto plan = pp::app::plan_new_document( + app.work_path, + dialog->input->m_text, + dialog->m_resolution->m_current_index, + [](const std::string& path) { + return Asset::exist(path); + }); + if (!plan) { + const bool missing_name = + plan.status().code == pp::foundation::StatusCode::invalid_argument; + app.message_box( + "Warning", + missing_name ? "You need to specify a name to file." : plan.status().message); + return; + } + + const auto status = + pp::panopainter::execute_legacy_new_document_plan(app, plan.value(), dialog); + if (!status.ok()) + LOG("New document action failed: %s", status.message); + }; + dialog->btn_cancel->on_click = [&app, dialog](Node*) { + pp::panopainter::close_legacy_dialog_and_hide_keyboard(app, *dialog); + }; +} + +void wire_document_file_save_dialog_buttons(App& app, const std::shared_ptr& dialog) +{ + dialog->btn_ok->on_click = [&app, dialog](Node*) { + const auto status = pp::panopainter::execute_legacy_document_file_save_dialog(app, dialog); + if (!status.ok()) + LOG("Document file save action failed: %s", status.message); + }; + dialog->btn_cancel->on_click = [&app, dialog](Node*) { + pp::panopainter::close_legacy_dialog_and_hide_keyboard(app, *dialog); + }; +} + +void open_legacy_document_file_save_dialog_impl(App& app) +{ + auto* overlay_anchor = app.layout[app.main_id]; + if (!overlay_anchor) { + LOG("Save document dialog open failed: main layout anchor is missing"); + return; + } + + auto dialog = pp::panopainter::make_legacy_overlay_node(app); + dialog->input->set_text(app.doc_name); + + app.showKeyboard(); + + const auto overlay = pp::panopainter::open_legacy_overlay_node_with_handle(*overlay_anchor, dialog); + if (!overlay) { + app.hideKeyboard(); + LOG("Save document dialog open failed: %s", overlay.status().message); + return; + } + + wire_document_file_save_dialog_buttons(app, dialog); +} + } // namespace pp::foundation::Status execute_legacy_close_request_decision( @@ -433,6 +515,11 @@ pp::foundation::Status execute_legacy_document_workflow_decision( return pp::app::execute_document_workflow_decision(decision, services); } +void open_legacy_new_document_dialog(App& app) +{ + open_legacy_new_document_dialog_impl(app); +} + pp::foundation::Status execute_legacy_new_document_plan( App& app, const pp::app::NewDocumentPlan& plan, @@ -469,6 +556,11 @@ pp::foundation::Status execute_legacy_document_file_save_dialog( return execute_legacy_document_file_save_plan(app, plan.value(), std::move(dialog)); } +void open_legacy_document_file_save_dialog(App& app) +{ + open_legacy_document_file_save_dialog_impl(app); +} + pp::foundation::Status execute_legacy_document_version_save( App& app, const pp::app::DocumentVersionTarget& target) diff --git a/src/legacy_document_session_services.h b/src/legacy_document_session_services.h index 0af4993a..b8f0fb32 100644 --- a/src/legacy_document_session_services.h +++ b/src/legacy_document_session_services.h @@ -26,6 +26,8 @@ namespace pp::panopainter { pp::app::DocumentWorkflowDecision decision, std::function action); +void open_legacy_new_document_dialog(App& app); + [[nodiscard]] pp::foundation::Status execute_legacy_new_document_plan( App& app, const pp::app::NewDocumentPlan& plan, @@ -40,6 +42,8 @@ namespace pp::panopainter { App& app, std::shared_ptr dialog); +void open_legacy_document_file_save_dialog(App& app); + [[nodiscard]] pp::foundation::Status execute_legacy_document_version_save( App& app, const pp::app::DocumentVersionTarget& target); diff --git a/src/legacy_draw_toolbar_binding_services.cpp b/src/legacy_draw_toolbar_binding_services.cpp new file mode 100644 index 00000000..a7c7750b --- /dev/null +++ b/src/legacy_draw_toolbar_binding_services.cpp @@ -0,0 +1,62 @@ +#include "pch.h" + +#include "legacy_draw_toolbar_binding_services.h" + +#include "app.h" +#include "app_core/canvas_tool_ui.h" +#include "legacy_canvas_tool_services.h" +#include "node_button.h" +#include "node_button_custom.h" + +namespace pp::panopainter { +namespace { + +[[nodiscard]] bool current_canvas_mode_is_draw(App& app) noexcept +{ + return app.canvas && app.canvas->m_canvas && app.canvas->m_canvas->m_current_mode == kCanvasMode::Draw; +} + +template +void bind_canvas_tool_toolbar_button( + App& app, + Node& toolbar_root, + const pp::app::CanvasToolToolbarBinding& binding) +{ + if (auto* button = toolbar_root.find(binding.button_id.data())) { + button->on_click = [&app, binding, button](Node*) { + 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 toolbar action failed: %s", status.message); + }; + } +} + +} // namespace + +void bind_legacy_draw_toolbar_buttons(App& app, Node& toolbar_root) +{ + const auto toolbar = pp::app::plan_canvas_tool_toolbar(); + bool apply_default_tool = false; + for (const auto& binding : toolbar.bindings) { + if (binding.custom_button) { + bind_canvas_tool_toolbar_button(app, toolbar_root, binding); + } else { + bind_canvas_tool_toolbar_button(app, toolbar_root, binding); + } + 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(app, default_plan); + if (!status.ok()) + LOG("Canvas default tool action failed: %s", status.message); + } +} + +} // namespace pp::panopainter diff --git a/src/legacy_draw_toolbar_binding_services.h b/src/legacy_draw_toolbar_binding_services.h new file mode 100644 index 00000000..0b3b6a64 --- /dev/null +++ b/src/legacy_draw_toolbar_binding_services.h @@ -0,0 +1,10 @@ +#pragma once + +class App; +class Node; + +namespace pp::panopainter { + +void bind_legacy_draw_toolbar_buttons(App& app, Node& toolbar_root); + +} // namespace pp::panopainter diff --git a/src/legacy_info_dialog_services.cpp b/src/legacy_info_dialog_services.cpp new file mode 100644 index 00000000..03a92869 --- /dev/null +++ b/src/legacy_info_dialog_services.cpp @@ -0,0 +1,52 @@ +#include "pch.h" + +#include "legacy_info_dialog_services.h" + +#include "app.h" +#include "legacy_ui_overlay_services.h" +#include "node_about.h" +#include "node_changelog.h" +#include "node_usermanual.h" + +namespace pp::panopainter { +namespace { + +template +void open_legacy_info_dialog(App& app, Node& overlay_anchor, const char* log_name) +{ + auto dialog = make_legacy_overlay_node(app); + const auto overlay = open_legacy_overlay_node_with_handle(overlay_anchor, dialog); + if (!overlay) { + LOG("%s dialog open failed: %s", log_name, overlay.status().message); + return; + } + const auto overlay_handle = overlay.value(); + + const auto close_dialog = [&overlay_anchor, overlay_handle]() { + const auto close_status = close_legacy_overlay_node(overlay_anchor, overlay_handle); + (void)close_status; + }; + + dialog->btn_ok->on_click = [close_dialog](Node*) { + close_dialog(); + }; +} + +} // namespace + +void open_usermanual_dialog(App& app, Node& overlay_anchor, const char* log_name) +{ + open_legacy_info_dialog(app, overlay_anchor, log_name); +} + +void open_changelog_dialog(App& app, Node& overlay_anchor, const char* log_name) +{ + open_legacy_info_dialog(app, overlay_anchor, log_name); +} + +void open_about_dialog(App& app, Node& overlay_anchor, const char* log_name) +{ + open_legacy_info_dialog(app, overlay_anchor, log_name); +} + +} // namespace pp::panopainter diff --git a/src/legacy_info_dialog_services.h b/src/legacy_info_dialog_services.h new file mode 100644 index 00000000..42774230 --- /dev/null +++ b/src/legacy_info_dialog_services.h @@ -0,0 +1,12 @@ +#pragma once + +class App; +class Node; + +namespace pp::panopainter { + +void open_usermanual_dialog(App& app, Node& overlay_anchor, const char* log_name); +void open_changelog_dialog(App& app, Node& overlay_anchor, const char* log_name); +void open_about_dialog(App& app, Node& overlay_anchor, const char* log_name); + +} // namespace pp::panopainter diff --git a/src/legacy_sidebar_stroke_popup_services.cpp b/src/legacy_sidebar_stroke_popup_services.cpp new file mode 100644 index 00000000..7a389292 --- /dev/null +++ b/src/legacy_sidebar_stroke_popup_services.cpp @@ -0,0 +1,68 @@ +#include "pch.h" +#include "legacy_sidebar_stroke_popup_services.h" + +#include "app.h" +#include "legacy_ui_overlay_services.h" +#include "node_button_custom.h" +#include "node_image.h" +#include "node_panel_floating.h" +#include "node_panel_stroke.h" + +namespace pp::panopainter { + +void open_legacy_sidebar_stroke_popup( + App& app, + Node& popup_root, + NodeButtonCustom& trigger_button, + NodePanelStroke& popup_panel) +{ + (void)app; + + const glm::vec2 pos = trigger_button.m_pos + glm::vec2(trigger_button.m_size.x * 0.5f, trigger_button.m_size.y); + + if (popup_panel.m_parent) + { + if (auto fp = dynamic_cast(popup_panel.m_parent->m_parent)) + { + detach_legacy_node_from_parent(popup_panel); + close_legacy_dialog_node(*fp); + } + } + + const auto popup_overlay = open_legacy_overlay_node_with_handle( + popup_root, + std::static_pointer_cast(popup_panel.shared_from_this())); + if (!popup_overlay) { + return; + } + + popup_panel.SetSize(350, glm::max(100.f, popup_root.m_size.y - pos.y - 50.f)); + popup_panel.find("title")->SetVisibility(true); + + auto tick = make_legacy_overlay_node_for_anchor(popup_root); + tick->SetPositioning(YGPositionTypeAbsolute); + tick->SetSize(32, 16); + tick->SetPosition(pos.x - 16, pos.y); + tick->set_image("data/ui/popup-tick-up.png"); + + const auto tick_overlay = open_legacy_overlay_node_with_handle(popup_root, tick); + if (!popup_overlay || !tick_overlay) + { + close_legacy_overlay_handles_if_open(popup_root, popup_overlay, tick_overlay); + return; + } + + const auto popup_handle = popup_overlay.value(); + const auto tick_handle = tick_overlay.value(); + popup_root.update(); + + popup_panel.SetPosition(pos.x - popup_panel.m_size.x / 2.f, pos.y + 16); + popup_panel.SetPositioning(YGPositionTypeAbsolute); + activate_legacy_popup_overlay(popup_panel); + auto scroll = popup_panel.find("scroller"); + (void)scroll; + popup_panel.m_popup_overlay_handle = popup_handle; + popup_panel.m_tick_overlay_handle = tick_handle; +} + +} // namespace pp::panopainter diff --git a/src/legacy_sidebar_stroke_popup_services.h b/src/legacy_sidebar_stroke_popup_services.h new file mode 100644 index 00000000..bc664e2f --- /dev/null +++ b/src/legacy_sidebar_stroke_popup_services.h @@ -0,0 +1,16 @@ +#pragma once + +class App; +class Node; +class NodeButtonCustom; +class NodePanelStroke; + +namespace pp::panopainter { + +void open_legacy_sidebar_stroke_popup( + App& app, + Node& popup_root, + NodeButtonCustom& trigger_button, + NodePanelStroke& popup_panel); + +} // namespace pp::panopainter