From 52ed7ddeb0131ea66f911e09a82a5f5f4bb95aea Mon Sep 17 00:00:00 2001 From: omigamedev Date: Wed, 17 Jun 2026 19:26:42 +0200 Subject: [PATCH] Extract app frame and ui state services --- cmake/PanoPainterSources.cmake | 4 + docs/modernization/debt.md | 24 +++ docs/modernization/roadmap.md | 5 + docs/modernization/tasks.md | 17 ++ src/app_events.cpp | 35 +--- src/app_layout_sidebar.cpp | 33 +--- src/app_layout_ui_state.cpp | 181 +------------------ src/legacy_app_frame_services.cpp | 59 ++++++ src/legacy_app_frame_services.h | 24 +++ src/legacy_app_runtime_shell_services.cpp | 22 +-- src/legacy_app_ui_state_services.cpp | 187 ++++++++++++++++++++ src/legacy_app_ui_state_services.h | 25 +++ src/legacy_sidebar_color_popup_services.cpp | 57 ++++++ src/legacy_sidebar_color_popup_services.h | 16 ++ 14 files changed, 435 insertions(+), 254 deletions(-) create mode 100644 src/legacy_app_frame_services.h create mode 100644 src/legacy_app_ui_state_services.cpp create mode 100644 src/legacy_app_ui_state_services.h create mode 100644 src/legacy_sidebar_color_popup_services.cpp create mode 100644 src/legacy_sidebar_color_popup_services.h diff --git a/cmake/PanoPainterSources.cmake b/cmake/PanoPainterSources.cmake index d43ca0d0..a00fab13 100644 --- a/cmake/PanoPainterSources.cmake +++ b/cmake/PanoPainterSources.cmake @@ -94,6 +94,8 @@ 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_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 @@ -155,6 +157,8 @@ set(PP_PANOPAINTER_APP_SOURCES src/app_layout_draw_toolbar.cpp src/app_layout_ui_state.cpp src/app_layout_sidebar.cpp + src/legacy_sidebar_color_popup_services.cpp + src/legacy_sidebar_color_popup_services.h src/app_layout_main_toolbar.cpp src/app_layout_edit_menu.cpp src/app_layout_about_layer_menu.cpp diff --git a/docs/modernization/debt.md b/docs/modernization/debt.md index 2121c921..c4dbf0e1 100644 --- a/docs/modernization/debt.md +++ b/docs/modernization/debt.md @@ -25,6 +25,24 @@ agent or engineer to remove them without reconstructing context from chat. owns that document-open handoff inline while retained dialog creation, unsaved-project prompting, project-open execution, and title/layer refresh still remain. +- 2026-06-17: `DEBT-0003` was narrowed again. `App::update()` in + `src/legacy_app_runtime_shell_services.cpp` no longer owns retained + app-frame layout-update and canvas-toolbar refresh execution inline; + `src/legacy_app_frame_services.*` now owns that frame-update execution + behind an explicit `App&` plus `AppFrameUpdatePlan` seam, while draw-time + execution, UI observer walking, and broader app-frame ownership still + remain. +- 2026-06-17: `DEBT-0003` was narrowed again. `App::tick()` and + `App::resize()` in `src/app_events.cpp` no longer own retained app-frame + tick and surface-resize execution inline; `src/legacy_app_frame_services.*` + now owns the tick/resize execution against explicit `App&` plus frame plans, + while broader event dispatch and runtime/platform frame ownership still + remain. +- 2026-06-17: `DEBT-0045` was narrowed again. + `src/app_layout_ui_state.cpp` no longer owns retained floating/docked panel + save/restore serialization inline; that panel-persistence family now lives in + `src/legacy_app_ui_state_services.*`, while RTL direction execution and + broader preference/runtime ownership still remain. - 2026-06-17: `DEBT-0035` was narrowed again. `src/app_layout_main_toolbar.cpp` no longer owns the retained main-toolbar button wiring inline; `src/legacy_main_toolbar_binding_services.*` now owns @@ -48,6 +66,12 @@ agent or engineer to remove them without reconstructing context from chat. submenu popup flow or panel-item wiring inline; that binding now lives in `src/legacy_tools_menu_binding_services.*`, while retained Tools command execution and options-menu preference wiring still remain in the app shell. +- 2026-06-17: `DEBT-0063` was narrowed again. + `src/app_layout_sidebar.cpp` no longer owns the retained color-popup open / + close wiring inline; that binding now lives in + `src/legacy_sidebar_color_popup_services.*` with explicit `App&`, + popup-root, trigger-button, and panel dependencies, while retained + stroke/grid/layer popup families still remain on the sidebar shell. - 2026-06-17: `DEBT-0038` was narrowed again. The retained cloud upload and download background execution in `src/legacy_cloud_services.cpp` now routes through `AppRuntime::canvas_async_task` instead of a file-static worker diff --git a/docs/modernization/roadmap.md b/docs/modernization/roadmap.md index 5985206f..9afa28b6 100644 --- a/docs/modernization/roadmap.md +++ b/docs/modernization/roadmap.md @@ -87,6 +87,11 @@ Current conclusion: lives in dedicated `legacy_*_binding_services.*` helpers, so the corresponding `app_layout_*` files are thinner adapters even though retained execution still lives in the app shell. +- App-frame update, tick, and resize execution now route through + `src/legacy_app_frame_services.*`, and floating/docked panel persistence now + 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. - 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 8a876126..0633b75c 100644 --- a/docs/modernization/tasks.md +++ b/docs/modernization/tasks.md @@ -84,6 +84,23 @@ Key facts: wiring through `src/legacy_tools_menu_binding_services.*`, so `src/app_layout_tools_menu.cpp` no longer owns that floating-panel submenu body inline while retained Tools execution and options wiring remain. +- `App::update()` now delegates retained app-frame layout update and + canvas-toolbar refresh execution through `src/legacy_app_frame_services.*`, + so `src/legacy_app_runtime_shell_services.cpp` is thinner at the frame + update seam while draw-time execution still remains there. +- `App::tick()` and `App::resize()` now delegate retained app-frame tick and + surface-resize execution through `src/legacy_app_frame_services.*`, so + `src/app_events.cpp` is thinner at the frame-execution seam while broader + input/platform dispatch still remains there. +- `App::ui_save()` and `App::ui_restore()` now delegate retained floating and + docked panel persistence through `src/legacy_app_ui_state_services.*`, so + `src/app_layout_ui_state.cpp` is down to thin preference adapters while RTL + direction execution stays local. +- `App::init_sidebar()` now delegates the retained color-popup open/close + wiring through `src/legacy_sidebar_color_popup_services.*` with explicit + `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. ## Parallel Assignment Rules diff --git a/src/app_events.cpp b/src/app_events.cpp index 8a4f3910..d19e660f 100644 --- a/src/app_events.cpp +++ b/src/app_events.cpp @@ -1,9 +1,9 @@ #include "pch.h" #include "app.h" -#include "app_core/app_frame.h" #include "app_core/app_input.h" #include "app_core/document_platform_io.h" #include "app_core/document_sharing.h" +#include "legacy_app_frame_services.h" #include "platform_api/platform_services.h" #include @@ -14,15 +14,9 @@ #ifdef _WIN32 #include "platform_windows/windows_platform_services.h" #endif -#include "renderer_gl/opengl_capabilities.h" namespace { -[[nodiscard]] GLint rgba8_internal_format() noexcept -{ - return static_cast(pp::renderer::gl::rgba8_internal_format()); -} - [[nodiscard]] bool should_dispatch_keyboard_visibility(bool visible) noexcept { const auto action = pp::app::plan_virtual_keyboard(visible); @@ -97,35 +91,12 @@ void App::crash_test() void App::tick(float dt) { - const auto tick_plan = pp::app::plan_app_frame_tick( - layout_designer.get(main_id) != nullptr, - layout.get(main_id) != nullptr); - if (auto* main = layout_designer[main_id]; tick_plan.tick_designer_layout && main) - main->tick(dt); - if (auto* main = layout[main_id]; tick_plan.tick_main_layout && main) - main->tick(dt); + pp::panopainter::execute_legacy_app_frame_tick(*this, dt); } void App::resize(float w, float h) { - LOG("App::resize %d %d", (int)w, (int)h); - const auto resize_plan = pp::app::plan_app_resize(w, h); - if (!resize_plan) { - LOG("App resize plan failed: %s", resize_plan.status().message); - return; - } - - if (resize_plan.value().recreate_ui_render_target) { - uirtt.create( - resize_plan.value().render_target_width, - resize_plan.value().render_target_height, - -1, - rgba8_internal_format(), - true); - } - redraw = resize_plan.value().request_redraw; - width = resize_plan.value().width; - height = resize_plan.value().height; + pp::panopainter::execute_legacy_app_frame_resize(*this, w, h); } void App::show_cursor() diff --git a/src/app_layout_sidebar.cpp b/src/app_layout_sidebar.cpp index 49834f18..05d2e16d 100644 --- a/src/app_layout_sidebar.cpp +++ b/src/app_layout_sidebar.cpp @@ -4,6 +4,7 @@ #include "node_panel_floating.h" #include "app_core/brush_ui.h" #include "app_core/document_layer.h" +#include "legacy_sidebar_color_popup_services.h" #include "legacy_brush_ui_services.h" #include "legacy_document_layer_services.h" #include "legacy_ui_overlay_services.h" @@ -297,37 +298,7 @@ void App::init_sidebar() if (!popup_root) { return; } - glm::vec2 pos = button->m_pos + glm::vec2(button->m_size.x * 0.5f, button->m_size.y); - const auto popup_overlay = pp::panopainter::open_legacy_overlay_node_with_handle(*popup_root, color); - if (!popup_overlay) - { - LOG("Color popup overlay failed: %s", popup_overlay.status().message); - return; - } - color->find("title")->SetVisibility(true); - color->SetSize(350, 350); - auto tick = pp::panopainter::make_legacy_overlay_node_for_anchor(*layout[main_id]); - 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(); - - color->SetPosition(pos.x - color->m_size.x / 2.f, pos.y + 16); - color->SetPositioning(YGPositionTypeAbsolute); - pp::panopainter::activate_legacy_popup_overlay(*color); - color->on_popup_close = [popup_root, popup_handle, tick_handle](Node*) { - close_legacy_overlay_handle_ignoring_status(*popup_root, popup_handle); - close_legacy_overlay_handle_ignoring_status(*popup_root, tick_handle); - }; + pp::panopainter::open_legacy_sidebar_color_popup(*this, *popup_root, *button, *color); }; } if (auto* button = layout[main_id]->find("btn-layer")) diff --git a/src/app_layout_ui_state.cpp b/src/app_layout_ui_state.cpp index 09c4b33d..310ab1fb 100644 --- a/src/app_layout_ui_state.cpp +++ b/src/app_layout_ui_state.cpp @@ -1,161 +1,8 @@ #include "pch.h" #include "app.h" #include "app_core/app_preferences.h" -#include "legacy_brush_ui_services.h" -#include "legacy_ui_overlay_services.h" +#include "legacy_app_ui_state_services.h" #include "legacy_preference_storage.h" -#include "node_dialog_picker.h" -#include "node_panel_brush.h" -#include "node_panel_color.h" -#include "node_panel_grid.h" -#include "node_panel_floating.h" -#include "serializer.h" - -namespace { - -bool apply_brush_color_plan(App& app, glm::vec4 color, bool update_quick, bool update_color_panel) -{ - return pp::panopainter::apply_legacy_brush_color_plan(app, color, update_quick, update_color_panel); -} - -bool apply_brush_preset_plan(App& app, const std::shared_ptr& brush) -{ - return pp::panopainter::apply_legacy_brush_preset_plan(app, brush); -} - -void save_floating_panel_state(Serializer::List& list, const std::shared_ptr& child) -{ - if (auto const& f = std::dynamic_pointer_cast(child)) - { - auto fd = list.add(); - fd->class_id = "ui-flt"; - fd->set("pos", Serializer::Vec2(f->GetPosition())); - fd->set("size", Serializer::Vec2(f->m_size)); - fd->set("class", Serializer::Integer((int)f->m_class)); - fd->set("title", Serializer::CString(f->m_title->m_text)); - } -} - -void save_docked_panel_state(Serializer::List& list, const std::shared_ptr& child, const char* class_id) -{ - if (auto const& f = std::dynamic_pointer_cast(child)) - { - auto fd = list.add(); - fd->class_id = class_id; - fd->set("size", Serializer::Vec2(f->m_size)); - fd->set("class", Serializer::Integer((int)f->m_class)); - fd->set("title", Serializer::CString(f->m_title->m_text)); - } -} - -template -void restore_panel_children( - App& app, - std::shared_ptr container, - const TList& items, - bool docked) -{ - for (auto const& l : items) - { - auto ld = std::static_pointer_cast(l); - auto size = ld->value("size"); - auto cls = static_cast(ld->value("class")); - auto f = container->add_child(); - std::string title = "Floating Panel"; - ld->value("title", title); - f->m_title->set_text(title.c_str()); - switch (cls) - { - case NodePanelFloating::kClass::Presets: - { - auto floating_presets = f->m_container->add_child_ref(); - if (!docked) - app.floating_presets = floating_presets; - floating_presets->SetHeightP(100); - floating_presets->on_brush_changed = [&app](Node*, std::shared_ptr& b) { - apply_brush_preset_plan(app, b); - }; - break; - } - case NodePanelFloating::kClass::Color: - { - auto floating_color = f->m_container->add_child_ref(); - if (!docked) - app.floating_color = floating_color; - floating_color->SetHeightP(100); - if (docked) - pp::panopainter::destroy_legacy_node(*floating_color->find("title")); - else - floating_color->find("title")->SetVisibility(false); - floating_color->on_color_changed = [&app](Node*, glm::vec4 color) { - apply_brush_color_plan(app, color, false, false); - }; - break; - } - case NodePanelFloating::kClass::ColorAdv: - { - app.floating_picker = f->m_container->add_child_ref(); - app.floating_picker->m_autohide = false; - app.floating_picker->on_color_change = [&app](Node*, glm::vec3 color) { - apply_brush_color_plan(app, glm::vec4(color, 1.f), false, false); - }; - break; - } - case NodePanelFloating::kClass::Layers: - f->m_container->add_child(app.layers); - if (!docked) - f->SetMinHeight(100); - if (!docked) - f->SetHeight(300); - if (!docked) - app.layers->find("title")->SetVisibility(false); - app.layers->SetPositioning(YGPositionTypeRelative); - app.layers->SetPosition(0, 0); - app.layers->SetWidthP(100); - app.layers->SetHeightP(100); - app.layers->SetFlexShrink(0); - break; - case NodePanelFloating::kClass::Brush: - f->m_container->add_child(app.stroke); - if (!docked) - app.stroke->find("title")->SetVisibility(false); - app.stroke->SetPositioning(YGPositionTypeRelative); - app.stroke->SetPosition(0, 0); - app.stroke->SetWidthP(100); - app.stroke->SetHeightP(100); - break; - case NodePanelFloating::kClass::Grids: - f->m_container->add_child(app.grid); - if (!docked) - app.grid->find("title")->SetVisibility(false); - app.grid->SetPositioning(YGPositionTypeRelative); - app.grid->SetPosition(0, 0); - app.grid->SetWidthP(100); - app.grid->SetHeightP(100); - break; - case NodePanelFloating::kClass::Animation: - f->m_container->add_child(app.animation); - f->m_droppable = false; - app.animation->SetPositioning(YGPositionTypeRelative); - app.animation->SetPosition(0, 0); - app.animation->SetWidthP(100); - app.animation->SetHeightP(100); - break; - case NodePanelFloating::kClass::Generic: - default: - f->m_container->add_child(); - break; - } - f->m_class = cls; - if (docked) - f->m_dock = container; - f->SetPositioning(docked ? YGPositionTypeRelative : YGPositionTypeAbsolute); - f->SetPosition(0, 0); - f->SetSize(size); - } -} - -} // namespace void App::set_ui_rtl(bool rtl) { @@ -173,23 +20,11 @@ bool App::get_ui_rtl() const void App::ui_save() { Serializer::Descriptor d; - d.class_id = "ui-state"; - - Serializer::List list_floatings; - for (auto const& c : layout[main_id]->find("floatings")->m_children) - save_floating_panel_state(list_floatings, c); - d.set("floatings", list_floatings); - - Serializer::List list_drop_left; - for (auto const& c : layout[main_id]->find("drop-left")->m_children) - save_docked_panel_state(list_drop_left, c, "ui-dpl"); - d.set("drop-left", list_drop_left); - - Serializer::List list_drop_right; - for (auto const& c : layout[main_id]->find("drop-right")->m_children) - save_docked_panel_state(list_drop_right, c, "ui-dpr"); - d.set("drop-right", list_drop_right); - + pp::panopainter::save_legacy_ui_panel_state( + d, + layout[main_id]->find_ref("floatings"), + layout[main_id]->find_ref("drop-left"), + layout[main_id]->find_ref("drop-right")); pp::panopainter::set_legacy_ui_state_preferences(d, ui_rtl); save_platform_ui_state(); @@ -210,7 +45,5 @@ void App::ui_restore() auto drop_right = layout[main_id]->find_ref("drop-right"); auto d = preferences.state; - restore_panel_children(*this, floatings, d->get("floatings")->items, false); - restore_panel_children(*this, drop_left, d->get("drop-left")->items, true); - restore_panel_children(*this, drop_right, d->get("drop-right")->items, true); + pp::panopainter::restore_legacy_ui_panel_state(*this, floatings, drop_left, drop_right, *d); } diff --git a/src/legacy_app_frame_services.cpp b/src/legacy_app_frame_services.cpp index 3ee01a25..a7ffe7f8 100644 --- a/src/legacy_app_frame_services.cpp +++ b/src/legacy_app_frame_services.cpp @@ -1,5 +1,7 @@ #include "pch.h" +#include "legacy_app_frame_services.h" + #include "app.h" #include "app_core/app_frame.h" #include "app_core/canvas_tool_ui.h" @@ -62,6 +64,11 @@ void watch_layout_children(LayoutManager* layout, uint16_t main_id, int start_in } } +[[nodiscard]] GLint rgba8_internal_format() noexcept +{ + return static_cast(pp::renderer::gl::rgba8_internal_format()); +} + } namespace pp::panopainter @@ -161,4 +168,56 @@ void update_legacy_canvas_toolbar(App& app) app.layout[app.main_id]->find("btn-bucket")->set_active(toolbar.flood_fill_active); } +void execute_legacy_app_frame_update( + App& app, + const pp::app::AppFrameUpdatePlan& plan) +{ + if (!plan.update_frame) + return; + + if (auto* main = app.layout[app.main_id]; plan.update_layouts && main) + main->update(app.width, app.height, app.zoom); + + if (auto* main = app.layout_designer[app.main_id]; plan.update_layouts && main) + main->update(app.width, app.height, app.zoom); + + if (!plan.refresh_canvas_toolbar) + return; + + update_legacy_canvas_toolbar(app); +} + +void execute_legacy_app_frame_tick(App& app, float dt) +{ + const auto tick_plan = pp::app::plan_app_frame_tick( + app.layout_designer.get(app.main_id) != nullptr, + app.layout.get(app.main_id) != nullptr); + if (auto* main = app.layout_designer[app.main_id]; tick_plan.tick_designer_layout && main) + main->tick(dt); + if (auto* main = app.layout[app.main_id]; tick_plan.tick_main_layout && main) + main->tick(dt); +} + +void execute_legacy_app_frame_resize(App& app, float width, float height) +{ + LOG("App::resize %d %d", (int)width, (int)height); + const auto resize_plan = pp::app::plan_app_resize(width, height); + if (!resize_plan) { + LOG("App resize plan failed: %s", resize_plan.status().message); + return; + } + + if (resize_plan.value().recreate_ui_render_target) { + app.uirtt.create( + resize_plan.value().render_target_width, + resize_plan.value().render_target_height, + -1, + rgba8_internal_format(), + true); + } + app.redraw = resize_plan.value().request_redraw; + app.width = resize_plan.value().width; + app.height = resize_plan.value().height; +} + } diff --git a/src/legacy_app_frame_services.h b/src/legacy_app_frame_services.h new file mode 100644 index 00000000..34546807 --- /dev/null +++ b/src/legacy_app_frame_services.h @@ -0,0 +1,24 @@ +#pragma once + +#include "app_core/app_frame.h" + +class App; +class Node; + +#include + +namespace pp::panopainter { + +[[nodiscard]] bool update_legacy_app_ui_observer(App& app, Node* n); +void watch_legacy_app_ui_children( + App& app, + const std::function& observer, + bool skip_first_main_child); +void update_legacy_canvas_toolbar(App& app); +void execute_legacy_app_frame_update( + App& app, + const pp::app::AppFrameUpdatePlan& plan); +void execute_legacy_app_frame_tick(App& app, float dt); +void execute_legacy_app_frame_resize(App& app, float width, float height); + +} // namespace pp::panopainter diff --git a/src/legacy_app_runtime_shell_services.cpp b/src/legacy_app_runtime_shell_services.cpp index bfc54f53..4f61c159 100644 --- a/src/legacy_app_runtime_shell_services.cpp +++ b/src/legacy_app_runtime_shell_services.cpp @@ -7,6 +7,7 @@ #include "app_core/app_shutdown.h" #include "app_core/app_status.h" #include "app_core/document_session.h" +#include "legacy_app_frame_services.h" #include "legacy_document_session_services.h" #include "legacy_recording_services.h" #include "legacy_ui_gl_dispatch.h" @@ -42,9 +43,6 @@ void apply_app_scissor_test(bool enabled) namespace pp::panopainter { bool process_legacy_recording_worker_iteration(App& app); void update_legacy_recording_frame_label(App& app); -bool update_legacy_app_ui_observer(App& app, Node* n); -void watch_legacy_app_ui_children(App& app, const std::function& observer, bool skip_first_main_child); -void update_legacy_canvas_toolbar(App& app); bool execute_legacy_app_request_close(App& app) { @@ -158,20 +156,10 @@ void App::draw(float dt) void App::update(float dt) { - const auto update_plan = pp::app::plan_app_frame_update(redraw, animate); - if (!update_plan.update_frame) - return; - - if (auto* main = layout[main_id]; update_plan.update_layouts && main) - main->update(width, height, zoom); - - if (auto* main = layout_designer[main_id]; update_plan.update_layouts && main) - main->update(width, height, zoom); - - if (!update_plan.refresh_canvas_toolbar) - return; - - pp::panopainter::update_legacy_canvas_toolbar(*this); + (void)dt; + pp::panopainter::execute_legacy_app_frame_update( + *this, + pp::app::plan_app_frame_update(redraw, animate)); } void App::clear() diff --git a/src/legacy_app_ui_state_services.cpp b/src/legacy_app_ui_state_services.cpp new file mode 100644 index 00000000..d191e32a --- /dev/null +++ b/src/legacy_app_ui_state_services.cpp @@ -0,0 +1,187 @@ +#include "pch.h" + +#include "legacy_app_ui_state_services.h" + +#include "app.h" +#include "legacy_brush_ui_services.h" +#include "legacy_ui_overlay_services.h" +#include "node_dialog_picker.h" +#include "node_panel_brush.h" +#include "node_panel_color.h" +#include "node_panel_grid.h" +#include "node_panel_floating.h" + +namespace pp::panopainter { +namespace { + +void save_floating_panel_state(Serializer::List& list, const std::shared_ptr& child) +{ + if (auto const& f = std::dynamic_pointer_cast(child)) + { + auto fd = list.add(); + fd->class_id = "ui-flt"; + fd->set("pos", Serializer::Vec2(f->GetPosition())); + fd->set("size", Serializer::Vec2(f->m_size)); + fd->set("class", Serializer::Integer((int)f->m_class)); + fd->set("title", Serializer::CString(f->m_title->m_text)); + } +} + +void save_docked_panel_state(Serializer::List& list, const std::shared_ptr& child, const char* class_id) +{ + if (auto const& f = std::dynamic_pointer_cast(child)) + { + auto fd = list.add(); + fd->class_id = class_id; + fd->set("size", Serializer::Vec2(f->m_size)); + fd->set("class", Serializer::Integer((int)f->m_class)); + fd->set("title", Serializer::CString(f->m_title->m_text)); + } +} + +template +void restore_panel_children( + App& app, + std::shared_ptr container, + const TList& items, + bool docked) +{ + for (auto const& l : items) + { + auto ld = std::static_pointer_cast(l); + auto size = ld->value("size"); + auto cls = static_cast(ld->value("class")); + auto f = container->add_child(); + std::string title = "Floating Panel"; + ld->value("title", title); + f->m_title->set_text(title.c_str()); + switch (cls) + { + case NodePanelFloating::kClass::Presets: + { + auto floating_presets = f->m_container->add_child_ref(); + if (!docked) + app.floating_presets = floating_presets; + floating_presets->SetHeightP(100); + floating_presets->on_brush_changed = [&app](Node*, std::shared_ptr& b) { + (void)apply_legacy_brush_preset_plan(app, b); + }; + break; + } + case NodePanelFloating::kClass::Color: + { + auto floating_color = f->m_container->add_child_ref(); + if (!docked) + app.floating_color = floating_color; + floating_color->SetHeightP(100); + if (docked) + destroy_legacy_node(*floating_color->find("title")); + else + floating_color->find("title")->SetVisibility(false); + floating_color->on_color_changed = [&app](Node*, glm::vec4 color) { + (void)apply_legacy_brush_color_plan(app, color, false, false); + }; + break; + } + case NodePanelFloating::kClass::ColorAdv: + { + app.floating_picker = f->m_container->add_child_ref(); + app.floating_picker->m_autohide = false; + app.floating_picker->on_color_change = [&app](Node*, glm::vec3 color) { + (void)apply_legacy_brush_color_plan(app, glm::vec4(color, 1.f), false, false); + }; + break; + } + case NodePanelFloating::kClass::Layers: + f->m_container->add_child(app.layers); + if (!docked) + f->SetMinHeight(100); + if (!docked) + f->SetHeight(300); + if (!docked) + app.layers->find("title")->SetVisibility(false); + app.layers->SetPositioning(YGPositionTypeRelative); + app.layers->SetPosition(0, 0); + app.layers->SetWidthP(100); + app.layers->SetHeightP(100); + app.layers->SetFlexShrink(0); + break; + case NodePanelFloating::kClass::Brush: + f->m_container->add_child(app.stroke); + if (!docked) + app.stroke->find("title")->SetVisibility(false); + app.stroke->SetPositioning(YGPositionTypeRelative); + app.stroke->SetPosition(0, 0); + app.stroke->SetWidthP(100); + app.stroke->SetHeightP(100); + break; + case NodePanelFloating::kClass::Grids: + f->m_container->add_child(app.grid); + if (!docked) + app.grid->find("title")->SetVisibility(false); + app.grid->SetPositioning(YGPositionTypeRelative); + app.grid->SetPosition(0, 0); + app.grid->SetWidthP(100); + app.grid->SetHeightP(100); + break; + case NodePanelFloating::kClass::Animation: + f->m_container->add_child(app.animation); + f->m_droppable = false; + app.animation->SetPositioning(YGPositionTypeRelative); + app.animation->SetPosition(0, 0); + app.animation->SetWidthP(100); + app.animation->SetHeightP(100); + break; + case NodePanelFloating::kClass::Generic: + default: + f->m_container->add_child(); + break; + } + f->m_class = cls; + if (docked) + f->m_dock = container; + f->SetPositioning(docked ? YGPositionTypeRelative : YGPositionTypeAbsolute); + f->SetPosition(0, 0); + f->SetSize(size); + } +} + +} // namespace + +void save_legacy_ui_panel_state( + Serializer::Descriptor& state, + const std::shared_ptr& floatings, + const std::shared_ptr& drop_left, + const std::shared_ptr& drop_right) +{ + state.class_id = "ui-state"; + + Serializer::List list_floatings; + for (const auto& c : floatings->m_children) + save_floating_panel_state(list_floatings, c); + state.set("floatings", list_floatings); + + Serializer::List list_drop_left; + for (const auto& c : drop_left->m_children) + save_docked_panel_state(list_drop_left, c, "ui-dpl"); + state.set("drop-left", list_drop_left); + + Serializer::List list_drop_right; + for (const auto& c : drop_right->m_children) + save_docked_panel_state(list_drop_right, c, "ui-dpr"); + state.set("drop-right", list_drop_right); +} + +void restore_legacy_ui_panel_state( + App& app, + const std::shared_ptr& floatings, + const std::shared_ptr& drop_left, + const std::shared_ptr& drop_right, + const Serializer::Descriptor& state) +{ + restore_panel_children(app, floatings, state.get("floatings")->items, false); + restore_panel_children(app, drop_left, state.get("drop-left")->items, true); + restore_panel_children(app, drop_right, state.get("drop-right")->items, true); +} + +} // namespace pp::panopainter diff --git a/src/legacy_app_ui_state_services.h b/src/legacy_app_ui_state_services.h new file mode 100644 index 00000000..6af7cda4 --- /dev/null +++ b/src/legacy_app_ui_state_services.h @@ -0,0 +1,25 @@ +#pragma once + +#include "serializer.h" + +#include + +class App; +class Node; + +namespace pp::panopainter { + +void save_legacy_ui_panel_state( + Serializer::Descriptor& state, + const std::shared_ptr& floatings, + const std::shared_ptr& drop_left, + const std::shared_ptr& drop_right); + +void restore_legacy_ui_panel_state( + App& app, + const std::shared_ptr& floatings, + const std::shared_ptr& drop_left, + const std::shared_ptr& drop_right, + const Serializer::Descriptor& state); + +} // namespace pp::panopainter diff --git a/src/legacy_sidebar_color_popup_services.cpp b/src/legacy_sidebar_color_popup_services.cpp new file mode 100644 index 00000000..4fff176c --- /dev/null +++ b/src/legacy_sidebar_color_popup_services.cpp @@ -0,0 +1,57 @@ +#include "pch.h" +#include "legacy_sidebar_color_popup_services.h" + +#include "app.h" +#include "legacy_ui_overlay_services.h" +#include "node_button_custom.h" +#include "node_image.h" +#include "node_panel_color.h" + +namespace pp::panopainter { + +void open_legacy_sidebar_color_popup( + App& app, + Node& popup_root, + NodeButtonCustom& trigger_button, + NodePanelColor& popup_panel) +{ + const glm::vec2 pos = trigger_button.m_pos + glm::vec2(trigger_button.m_size.x * 0.5f, trigger_button.m_size.y); + const auto popup_overlay = open_legacy_overlay_node_with_handle( + popup_root, + std::static_pointer_cast(popup_panel.shared_from_this())); + if (!popup_overlay) + { + LOG("Color popup overlay failed: %s", popup_overlay.status().message); + return; + } + + popup_panel.find("title")->SetVisibility(true); + popup_panel.SetSize(350, 350); + + 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) + { + pp::panopainter::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); + popup_panel.on_popup_close = [&popup_root, popup_handle, tick_handle](Node*) { + pp::panopainter::close_legacy_overlay_handle_ignoring_status(popup_root, popup_handle); + pp::panopainter::close_legacy_overlay_handle_ignoring_status(popup_root, tick_handle); + }; +} + +} // namespace pp::panopainter diff --git a/src/legacy_sidebar_color_popup_services.h b/src/legacy_sidebar_color_popup_services.h new file mode 100644 index 00000000..b2025662 --- /dev/null +++ b/src/legacy_sidebar_color_popup_services.h @@ -0,0 +1,16 @@ +#pragma once + +class App; +class NodeButtonCustom; +class NodePanelColor; +class Node; + +namespace pp::panopainter { + +void open_legacy_sidebar_color_popup( + App& app, + Node& popup_root, + NodeButtonCustom& trigger_button, + NodePanelColor& popup_panel); + +} // namespace pp::panopainter