Move retained popups to checked handles

This commit is contained in:
2026-06-15 19:33:06 +02:00
parent 168404433c
commit ce169a3fd6
6 changed files with 397 additions and 142 deletions

View File

@@ -18,6 +18,15 @@ agent or engineer to remove them without reconstructing context from chat.
## Recent Reductions ## Recent Reductions
- 2026-06-15: `DEBT-0063` was narrowed again. Sidebar stroke/color/layer/grid
popups, file/about/layer menu popups in `src/app_layout.cpp`, quick
brush/color popup+ticker overlays in `src/legacy_quick_ui_services.cpp`,
combo-box popup open/close in `src/node_combobox.cpp`, and picker
outside-click teardown in `src/node_dialog_picker.cpp` now route through
checked overlay handles or explicit handle-safe close callbacks instead of
raw attach-and-destroy popup ownership; remaining popup families still stay
open under the same debt until the last retained dialog/menu surfaces are
converted.
- 2026-06-15: `DEBT-0058`/`DEBT-0063` were narrowed again. App-owned About, - 2026-06-15: `DEBT-0058`/`DEBT-0063` were narrowed again. App-owned About,
Changelog, User Manual, New Document, Open, Browse, Save, Resize, Layer Changelog, User Manual, New Document, Open, Browse, Save, Resize, Layer
Rename, and PPBR Export dialogs now open and close through checked overlay Rename, and PPBR Export dialogs now open and close through checked overlay

View File

@@ -79,6 +79,27 @@ std::shared_ptr<NodePopupMenu> add_menu_popup(
return popup.value(); return popup.value();
} }
void close_legacy_overlay_handle_ignoring_status(
Node& anchor,
pp::ui::NodeHandle overlay) noexcept
{
(void)pp::panopainter::close_legacy_overlay_node(anchor, overlay);
}
template <typename PopupOverlay, typename TickOverlay>
void close_legacy_overlay_handles_if_open(
Node& anchor,
const PopupOverlay& popup_overlay,
const TickOverlay& tick_overlay) noexcept
{
if (popup_overlay) {
close_legacy_overlay_handle_ignoring_status(anchor, popup_overlay.value());
}
if (tick_overlay) {
close_legacy_overlay_handle_ignoring_status(anchor, tick_overlay.value());
}
}
pp::app::DocumentLayerMenuPlan make_layer_menu_plan( pp::app::DocumentLayerMenuPlan make_layer_menu_plan(
pp::app::DocumentLayerMenuCommand command, pp::app::DocumentLayerMenuCommand command,
App& app) App& app)
@@ -463,7 +484,11 @@ void App::init_sidebar()
if (auto* button = layout[main_id]->find<NodeButtonCustom>("btn-stroke")) if (auto* button = layout[main_id]->find<NodeButtonCustom>("btn-stroke"))
{ {
button->on_click = [this, button](Node*) { button->on_click = [this, button](Node*) {
auto screen = layout[main_id]->m_size; auto* popup_root = layout[main_id];
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); glm::vec2 pos = button->m_pos + glm::vec2(button->m_size.x * 0.5f, button->m_size.y);
if (stroke->m_parent) if (stroke->m_parent)
{ {
@@ -473,24 +498,35 @@ void App::init_sidebar()
pp::panopainter::close_legacy_dialog_node(*fp); pp::panopainter::close_legacy_dialog_node(*fp);
} }
} }
(void)pp::panopainter::attach_legacy_overlay_node(*this, stroke); 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->SetSize(350, glm::max(100.f, screen.y - pos.y - 50.f));
stroke->find("title")->SetVisibility(true); stroke->find("title")->SetVisibility(true);
auto tick = pp::panopainter::make_legacy_overlay_node_for_anchor<NodeImage>(*layout[main_id]); auto tick = pp::panopainter::make_legacy_overlay_node_for_anchor<NodeImage>(*popup_root);
tick->SetPositioning(YGPositionTypeAbsolute); tick->SetPositioning(YGPositionTypeAbsolute);
tick->SetSize(32, 16); tick->SetSize(32, 16);
tick->SetPosition(pos.x - 16, pos.y); tick->SetPosition(pos.x - 16, pos.y);
tick->set_image("data/ui/popup-tick-up.png"); tick->set_image("data/ui/popup-tick-up.png");
(void)pp::panopainter::attach_legacy_overlay_node(*this, tick); auto tick_overlay = pp::panopainter::open_legacy_overlay_node_with_handle(*popup_root, tick);
layout[main_id]->update(); 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->SetPosition(pos.x - stroke->m_size.x / 2.f, pos.y + 16);
stroke->SetPositioning(YGPositionTypeAbsolute); stroke->SetPositioning(YGPositionTypeAbsolute);
pp::panopainter::activate_legacy_popup_overlay(*stroke); pp::panopainter::activate_legacy_popup_overlay(*stroke);
auto scroll = stroke->find<NodeScroll>("scroller"); auto scroll = stroke->find<NodeScroll>("scroller");
//scroll->SetHeight(glm::max(100.f, screen.y - pos.y - 200.f)); //scroll->SetHeight(glm::max(100.f, screen.y - pos.y - 200.f));
stroke->m_popup_overlay_handle = popup_handle;
stroke->m_tick_overlay_handle = tick_handle;
pp::panopainter::bind_legacy_popup_close_destroys_overlay(*stroke, tick);
}; };
} }
//if (auto* button = layout[main_id]->find<NodeButtonCustom>("btn-brush")) //if (auto* button = layout[main_id]->find<NodeButtonCustom>("btn-brush"))
@@ -512,9 +548,17 @@ void App::init_sidebar()
if (auto* button = layout[main_id]->find<NodeButtonCustom>("btn-color")) if (auto* button = layout[main_id]->find<NodeButtonCustom>("btn-color"))
{ {
button->on_click = [this, button](Node*) { button->on_click = [this, button](Node*) {
auto screen = layout[main_id]->m_size; auto* popup_root = layout[main_id];
if (!popup_root) {
return;
}
glm::vec2 pos = button->m_pos + glm::vec2(button->m_size.x * 0.5f, button->m_size.y); glm::vec2 pos = button->m_pos + glm::vec2(button->m_size.x * 0.5f, button->m_size.y);
(void)pp::panopainter::attach_legacy_overlay_node(*this, color); 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->find("title")->SetVisibility(true);
color->SetSize(350, 350); color->SetSize(350, 350);
auto tick = pp::panopainter::make_legacy_overlay_node_for_anchor<NodeImage>(*layout[main_id]); auto tick = pp::panopainter::make_legacy_overlay_node_for_anchor<NodeImage>(*layout[main_id]);
@@ -522,20 +566,33 @@ void App::init_sidebar()
tick->SetSize(32, 16); tick->SetSize(32, 16);
tick->SetPosition(pos.x - 16, pos.y); tick->SetPosition(pos.x - 16, pos.y);
tick->set_image("data/ui/popup-tick-up.png"); tick->set_image("data/ui/popup-tick-up.png");
(void)pp::panopainter::attach_legacy_overlay_node(*this, tick); auto tick_overlay = pp::panopainter::open_legacy_overlay_node_with_handle(*popup_root, tick);
layout[main_id]->update(); 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->SetPosition(pos.x - color->m_size.x / 2.f, pos.y + 16);
color->SetPositioning(YGPositionTypeAbsolute); color->SetPositioning(YGPositionTypeAbsolute);
pp::panopainter::activate_legacy_popup_overlay(*color); pp::panopainter::activate_legacy_popup_overlay(*color);
color->on_popup_close = [popup_root, popup_handle, tick_handle](Node*) {
pp::panopainter::bind_legacy_popup_close_destroys_overlay(*color, tick); close_legacy_overlay_handle_ignoring_status(*popup_root, popup_handle);
close_legacy_overlay_handle_ignoring_status(*popup_root, tick_handle);
};
}; };
} }
if (auto* button = layout[main_id]->find<NodeButtonCustom>("btn-layer")) if (auto* button = layout[main_id]->find<NodeButtonCustom>("btn-layer"))
{ {
button->on_click = [this, button](Node*) { button->on_click = [this, button](Node*) {
auto screen = layout[main_id]->m_size; auto* popup_root = layout[main_id];
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); glm::vec2 pos = button->m_pos + glm::vec2(button->m_size.x * 0.5f, button->m_size.y);
layers->find("title")->SetVisibility(true); layers->find("title")->SetVisibility(true);
layers->SetSize(350, YGUndefined); layers->SetSize(350, YGUndefined);
@@ -547,28 +604,45 @@ void App::init_sidebar()
pp::panopainter::close_legacy_dialog_node(*fp); pp::panopainter::close_legacy_dialog_node(*fp);
} }
} }
(void)pp::panopainter::attach_legacy_overlay_node(*this, layers); const auto popup_overlay = pp::panopainter::open_legacy_overlay_node_with_handle(*popup_root, layers);
auto tick = pp::panopainter::make_legacy_overlay_node_for_anchor<NodeImage>(*layout[main_id]); if (!popup_overlay) {
return;
}
auto tick = pp::panopainter::make_legacy_overlay_node_for_anchor<NodeImage>(*popup_root);
tick->SetPositioning(YGPositionTypeAbsolute); tick->SetPositioning(YGPositionTypeAbsolute);
tick->SetSize(32, 16); tick->SetSize(32, 16);
tick->SetPosition(pos.x - 16, pos.y); tick->SetPosition(pos.x - 16, pos.y);
tick->set_image("data/ui/popup-tick-up.png"); tick->set_image("data/ui/popup-tick-up.png");
(void)pp::panopainter::attach_legacy_overlay_node(*this, tick); auto tick_overlay = pp::panopainter::open_legacy_overlay_node_with_handle(*popup_root, tick);
layout[main_id]->update(); 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();
layers->SetPosition(pos.x - layers->m_size.x / 2.f, pos.y + 16); layers->SetPosition(pos.x - layers->m_size.x / 2.f, pos.y + 16);
layers->SetPositioning(YGPositionTypeAbsolute); layers->SetPositioning(YGPositionTypeAbsolute);
pp::panopainter::activate_legacy_popup_overlay(*layers); pp::panopainter::activate_legacy_popup_overlay(*layers);
auto scroll = layers->find<NodeScroll>("layers-container"); auto scroll = layers->find<NodeScroll>("layers-container");
scroll->SetMaxHeight(glm::max(100.f, screen.y - pos.y - 200.f)); scroll->SetMaxHeight(glm::max(100.f, screen.y - pos.y - 200.f));
layers->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::bind_legacy_popup_close_destroys_overlay(*layers, tick);
}; };
} }
if (auto* button = layout[main_id]->find<NodeButtonCustom>("btn-grids-panel")) if (auto* button = layout[main_id]->find<NodeButtonCustom>("btn-grids-panel"))
{ {
button->on_click = [this, button](Node*) { button->on_click = [this, button](Node*) {
auto screen = layout[main_id]->m_size; auto* popup_root = layout[main_id];
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); glm::vec2 pos = button->m_pos + glm::vec2(button->m_size.x * 0.5f, button->m_size.y);
grid->find("title")->SetVisibility(true); grid->find("title")->SetVisibility(true);
grid->SetSize(350, YGUndefined); grid->SetSize(350, YGUndefined);
@@ -580,14 +654,26 @@ void App::init_sidebar()
pp::panopainter::close_legacy_dialog_node(*fp); pp::panopainter::close_legacy_dialog_node(*fp);
} }
} }
(void)pp::panopainter::attach_legacy_overlay_node(*this, grid); const auto popup_overlay = pp::panopainter::open_legacy_overlay_node_with_handle(*popup_root, grid);
auto tick = pp::panopainter::make_legacy_overlay_node_for_anchor<NodeImage>(*layout[main_id]); if (!popup_overlay)
{
LOG("Grid popup overlay failed: %s", popup_overlay.status().message);
return;
}
auto tick = pp::panopainter::make_legacy_overlay_node_for_anchor<NodeImage>(*popup_root);
tick->SetPositioning(YGPositionTypeAbsolute); tick->SetPositioning(YGPositionTypeAbsolute);
tick->SetSize(32, 16); tick->SetSize(32, 16);
tick->SetPosition(pos.x - 16, pos.y); tick->SetPosition(pos.x - 16, pos.y);
tick->set_image("data/ui/popup-tick-up.png"); tick->set_image("data/ui/popup-tick-up.png");
(void)pp::panopainter::attach_legacy_overlay_node(*this, tick); auto tick_overlay = pp::panopainter::open_legacy_overlay_node_with_handle(*popup_root, tick);
layout[main_id]->update(); 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();
grid->SetPosition(pos.x - grid->m_size.x / 2.f, pos.y + 16); grid->SetPosition(pos.x - grid->m_size.x / 2.f, pos.y + 16);
grid->SetPositioning(YGPositionTypeAbsolute); grid->SetPositioning(YGPositionTypeAbsolute);
@@ -595,7 +681,10 @@ void App::init_sidebar()
auto scroll = grid->find<NodeScroll>("scroller"); auto scroll = grid->find<NodeScroll>("scroller");
scroll->SetMaxHeight(glm::max(100.f, screen.y - pos.y - 250.f)); scroll->SetMaxHeight(glm::max(100.f, screen.y - pos.y - 250.f));
pp::panopainter::bind_legacy_popup_close_destroys_overlay(*grid, tick); grid->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);
};
}; };
} }
} }
@@ -661,113 +750,133 @@ void App::init_menu_file()
{ {
if (auto* menu_file = layout[main_id]->find<NodeButtonCustom>("menu-file")) if (auto* menu_file = layout[main_id]->find<NodeButtonCustom>("menu-file"))
{ {
menu_file->on_click = [=](Node*) { menu_file->on_click = [this, menu_file](Node*) {
auto* popup_root = layout[main_id];
if (!popup_root) {
return;
}
const auto open_checked_menu_popup = [this, popup_root](const char* id, glm::vec2 pos, float width)
-> std::pair<std::shared_ptr<NodePopupMenu>, pp::ui::NodeHandle>
{
auto popup = add_menu_popup(*this, id, pos, width);
if (!popup) {
return {};
}
pp::panopainter::detach_legacy_node_from_parent(*popup);
auto popup_overlay = pp::panopainter::open_legacy_overlay_node_with_handle(*popup_root, popup);
if (!popup_overlay) {
pp::panopainter::destroy_legacy_node(*popup);
return {};
}
return { popup, popup_overlay.value() };
};
glm::vec2 pos = menu_file->m_pos + glm::vec2(0, menu_file->m_size.y); glm::vec2 pos = menu_file->m_pos + glm::vec2(0, menu_file->m_size.y);
auto popup = add_menu_popup(*this, "file-menu", pos, menu_file->m_size.x); const auto [popup, popup_handle] = open_checked_menu_popup("file-menu", pos, menu_file->m_size.x);
if (!popup) if (!popup)
return; return;
if (auto b = popup->find<NodeButtonCustom>("file-newdoc")) if (auto b = popup->find<NodeButtonCustom>("file-newdoc"))
b->on_click = [this, popup](Node*) { b->on_click = [this, popup_root, popup_handle](Node*) {
apply_file_menu_plan(*this, pp::app::FileMenuCommand::new_document); apply_file_menu_plan(*this, pp::app::FileMenuCommand::new_document);
pp::panopainter::close_legacy_popup_overlay(*popup); close_legacy_overlay_handle_ignoring_status(*popup_root, popup_handle);
}; };
if (auto b = popup->find<NodeButtonCustom>("file-import")) if (auto b = popup->find<NodeButtonCustom>("file-import"))
b->on_click = [this, popup](Node*) { b->on_click = [this, popup_root, popup_handle](Node*) {
apply_file_menu_plan(*this, pp::app::FileMenuCommand::import_image); apply_file_menu_plan(*this, pp::app::FileMenuCommand::import_image);
pp::panopainter::close_legacy_popup_overlay(*popup); close_legacy_overlay_handle_ignoring_status(*popup_root, popup_handle);
}; };
if (auto b = popup->find<NodeButtonCustom>("file-open")) if (auto b = popup->find<NodeButtonCustom>("file-open"))
b->on_click = [this, popup](Node*) { b->on_click = [this, popup_root, popup_handle](Node*) {
apply_file_menu_plan(*this, pp::app::FileMenuCommand::open_project); apply_file_menu_plan(*this, pp::app::FileMenuCommand::open_project);
pp::panopainter::close_legacy_popup_overlay(*popup); close_legacy_overlay_handle_ignoring_status(*popup_root, popup_handle);
}; };
if (auto b = popup->find<NodeButtonCustom>("file-browse")) if (auto b = popup->find<NodeButtonCustom>("file-browse"))
b->on_click = [this, popup](Node*) { b->on_click = [this, popup_root, popup_handle](Node*) {
apply_file_menu_plan(*this, pp::app::FileMenuCommand::browse_cloud); apply_file_menu_plan(*this, pp::app::FileMenuCommand::browse_cloud);
pp::panopainter::close_legacy_popup_overlay(*popup); close_legacy_overlay_handle_ignoring_status(*popup_root, popup_handle);
}; };
if (auto b = popup->find<NodeButtonCustom>("file-save")) if (auto b = popup->find<NodeButtonCustom>("file-save"))
b->on_click = [this, popup](Node*) { b->on_click = [this, popup_root, popup_handle](Node*) {
apply_file_menu_plan(*this, pp::app::FileMenuCommand::save); apply_file_menu_plan(*this, pp::app::FileMenuCommand::save);
pp::panopainter::close_legacy_popup_overlay(*popup); close_legacy_overlay_handle_ignoring_status(*popup_root, popup_handle);
}; };
if (auto b = popup->find<NodeButtonCustom>("file-save-as")) if (auto b = popup->find<NodeButtonCustom>("file-save-as"))
b->on_click = [this, popup](Node*) { b->on_click = [this, popup_root, popup_handle](Node*) {
apply_file_menu_plan(*this, pp::app::FileMenuCommand::save_as); apply_file_menu_plan(*this, pp::app::FileMenuCommand::save_as);
pp::panopainter::close_legacy_popup_overlay(*popup); close_legacy_overlay_handle_ignoring_status(*popup_root, popup_handle);
}; };
if (auto b = popup->find<NodeButtonCustom>("file-save-ver")) if (auto b = popup->find<NodeButtonCustom>("file-save-ver"))
b->on_click = [this, popup](Node*) { b->on_click = [this, popup_root, popup_handle](Node*) {
apply_file_menu_plan(*this, pp::app::FileMenuCommand::save_version); apply_file_menu_plan(*this, pp::app::FileMenuCommand::save_version);
pp::panopainter::close_legacy_popup_overlay(*popup); close_legacy_overlay_handle_ignoring_status(*popup_root, popup_handle);
}; };
if (auto b = popup->find<NodeButtonCustom>("file-export")) if (auto b = popup->find<NodeButtonCustom>("file-export"))
b->on_click = [this, popup](Node*) { b->on_click = [this, popup_root, popup_handle](Node*) {
apply_file_menu_plan(*this, pp::app::FileMenuCommand::export_jpeg); apply_file_menu_plan(*this, pp::app::FileMenuCommand::export_jpeg);
pp::panopainter::close_legacy_popup_overlay(*popup); close_legacy_overlay_handle_ignoring_status(*popup_root, popup_handle);
}; };
if (auto b = popup->find<NodeButtonCustom>("file-export-tick")) if (auto b = popup->find<NodeButtonCustom>("file-export-tick"))
b->on_click = [this, b, popup](Node*) { b->on_click = [this, b, popup_root, popup_handle, open_checked_menu_popup](Node*) {
glm::vec2 pos = b->m_pos + glm::vec2(b->m_size.x, 0); glm::vec2 pos = b->m_pos + glm::vec2(b->m_size.x, 0);
auto subpopup = add_menu_popup(*this, "file-submenu-export", pos, b->m_size.x); const auto [subpopup, subpopup_handle] = open_checked_menu_popup("file-submenu-export", pos, b->m_size.x);
if (!subpopup) if (!subpopup)
return; return;
subpopup->find<NodeButtonCustom>("file-submenu-export-png")->on_click = [this, subpopup, popup](Node*) { subpopup->find<NodeButtonCustom>("file-submenu-export-png")->on_click = [this, popup_root, popup_handle, subpopup_handle](Node*) {
apply_document_export_menu_plan(*this, pp::app::DocumentExportMenuKind::png); apply_document_export_menu_plan(*this, pp::app::DocumentExportMenuKind::png);
pp::panopainter::close_legacy_popup_overlay(*popup); close_legacy_overlay_handle_ignoring_status(*popup_root, popup_handle);
pp::panopainter::close_legacy_popup_overlay(*subpopup); close_legacy_overlay_handle_ignoring_status(*popup_root, subpopup_handle);
}; };
subpopup->find<NodeButtonCustom>("file-submenu-export-layers")->on_click = [this, subpopup, popup](Node*) { subpopup->find<NodeButtonCustom>("file-submenu-export-layers")->on_click = [this, popup_root, popup_handle, subpopup_handle](Node*) {
apply_document_export_menu_plan(*this, pp::app::DocumentExportMenuKind::layers); apply_document_export_menu_plan(*this, pp::app::DocumentExportMenuKind::layers);
pp::panopainter::close_legacy_popup_overlay(*popup); close_legacy_overlay_handle_ignoring_status(*popup_root, popup_handle);
pp::panopainter::close_legacy_popup_overlay(*subpopup); close_legacy_overlay_handle_ignoring_status(*popup_root, subpopup_handle);
}; };
subpopup->find<NodeButtonCustom>("file-submenu-export-cube")->on_click = [this, subpopup, popup](Node*) { subpopup->find<NodeButtonCustom>("file-submenu-export-cube")->on_click = [this, popup_root, popup_handle, subpopup_handle](Node*) {
apply_document_export_menu_plan(*this, pp::app::DocumentExportMenuKind::cube_faces); apply_document_export_menu_plan(*this, pp::app::DocumentExportMenuKind::cube_faces);
pp::panopainter::close_legacy_popup_overlay(*popup); close_legacy_overlay_handle_ignoring_status(*popup_root, popup_handle);
pp::panopainter::close_legacy_popup_overlay(*subpopup); close_legacy_overlay_handle_ignoring_status(*popup_root, subpopup_handle);
}; };
subpopup->find<NodeButtonCustom>("file-submenu-export-depth")->on_click = [this, subpopup, popup](Node*) { subpopup->find<NodeButtonCustom>("file-submenu-export-depth")->on_click = [this, popup_root, popup_handle, subpopup_handle](Node*) {
apply_document_export_menu_plan(*this, pp::app::DocumentExportMenuKind::depth); apply_document_export_menu_plan(*this, pp::app::DocumentExportMenuKind::depth);
pp::panopainter::close_legacy_popup_overlay(*popup); close_legacy_overlay_handle_ignoring_status(*popup_root, popup_handle);
pp::panopainter::close_legacy_popup_overlay(*subpopup); close_legacy_overlay_handle_ignoring_status(*popup_root, subpopup_handle);
}; };
subpopup->find<NodeButtonCustom>("file-submenu-export-anim")->on_click = [this, subpopup, popup](Node*) { subpopup->find<NodeButtonCustom>("file-submenu-export-anim")->on_click = [this, popup_root, popup_handle, subpopup_handle](Node*) {
apply_document_export_menu_plan(*this, pp::app::DocumentExportMenuKind::animation_frames); apply_document_export_menu_plan(*this, pp::app::DocumentExportMenuKind::animation_frames);
pp::panopainter::close_legacy_popup_overlay(*popup); close_legacy_overlay_handle_ignoring_status(*popup_root, popup_handle);
pp::panopainter::close_legacy_popup_overlay(*subpopup); close_legacy_overlay_handle_ignoring_status(*popup_root, subpopup_handle);
}; };
subpopup->find<NodeButtonCustom>("file-submenu-export-anim-mp4")->on_click = [this, subpopup, popup](Node*) { subpopup->find<NodeButtonCustom>("file-submenu-export-anim-mp4")->on_click = [this, popup_root, popup_handle, subpopup_handle](Node*) {
apply_document_export_menu_plan(*this, pp::app::DocumentExportMenuKind::animation_mp4); apply_document_export_menu_plan(*this, pp::app::DocumentExportMenuKind::animation_mp4);
pp::panopainter::close_legacy_popup_overlay(*popup); close_legacy_overlay_handle_ignoring_status(*popup_root, popup_handle);
pp::panopainter::close_legacy_popup_overlay(*subpopup); close_legacy_overlay_handle_ignoring_status(*popup_root, subpopup_handle);
}; };
subpopup->find<NodeButtonCustom>("file-submenu-export-timelapse")->on_click = [this, subpopup, popup](Node*) { subpopup->find<NodeButtonCustom>("file-submenu-export-timelapse")->on_click = [this, popup_root, popup_handle, subpopup_handle](Node*) {
apply_document_export_menu_plan(*this, pp::app::DocumentExportMenuKind::timelapse); apply_document_export_menu_plan(*this, pp::app::DocumentExportMenuKind::timelapse);
pp::panopainter::close_legacy_popup_overlay(*popup); close_legacy_overlay_handle_ignoring_status(*popup_root, popup_handle);
pp::panopainter::close_legacy_popup_overlay(*subpopup); close_legacy_overlay_handle_ignoring_status(*popup_root, subpopup_handle);
}; };
}; };
if (auto b = popup->find<NodeButtonCustom>("file-share")) if (auto b = popup->find<NodeButtonCustom>("file-share"))
b->on_click = [this, popup](Node*) { b->on_click = [this, popup_root, popup_handle](Node*) {
apply_file_menu_plan(*this, pp::app::FileMenuCommand::share); apply_file_menu_plan(*this, pp::app::FileMenuCommand::share);
pp::panopainter::close_legacy_popup_overlay(*popup); close_legacy_overlay_handle_ignoring_status(*popup_root, popup_handle);
}; };
if (auto b = popup->find<NodeButtonCustom>("file-resize")) if (auto b = popup->find<NodeButtonCustom>("file-resize"))
b->on_click = [this, popup](Node*) { b->on_click = [this, popup_root, popup_handle](Node*) {
apply_file_menu_plan(*this, pp::app::FileMenuCommand::resize); apply_file_menu_plan(*this, pp::app::FileMenuCommand::resize);
pp::panopainter::close_legacy_popup_overlay(*popup); close_legacy_overlay_handle_ignoring_status(*popup_root, popup_handle);
}; };
if (auto b = popup->find<NodeButtonCustom>("file-cloud-upload")) if (auto b = popup->find<NodeButtonCustom>("file-cloud-upload"))
b->on_click = [this, popup](Node*) { b->on_click = [this, popup_root, popup_handle](Node*) {
apply_file_menu_plan(*this, pp::app::FileMenuCommand::cloud_upload); apply_file_menu_plan(*this, pp::app::FileMenuCommand::cloud_upload);
pp::panopainter::close_legacy_popup_overlay(*popup); close_legacy_overlay_handle_ignoring_status(*popup_root, popup_handle);
}; };
if (auto b = popup->find<NodeButtonCustom>("file-cloud-browse")) if (auto b = popup->find<NodeButtonCustom>("file-cloud-browse"))
b->on_click = [this, popup](Node*) { b->on_click = [this, popup_root, popup_handle](Node*) {
apply_file_menu_plan(*this, pp::app::FileMenuCommand::cloud_browse); apply_file_menu_plan(*this, pp::app::FileMenuCommand::cloud_browse);
pp::panopainter::close_legacy_popup_overlay(*popup); close_legacy_overlay_handle_ignoring_status(*popup_root, popup_handle);
}; };
}; };
} }
@@ -798,16 +907,39 @@ void App::init_menu_tools()
if (!popup_exp) if (!popup_exp)
return; return;
if (auto tick = popup_exp->find<NodeButtonCustom>("tools-panels")) tick->on_click = [this, popup_exp](Node* b) if (auto tick = popup_exp->find<NodeButtonCustom>("tools-panels")) tick->on_click = [this, popup_exp, main](Node* b)
{ {
const auto menu_plan = pp::app::plan_tools_menu_command(pp::app::ToolsMenuCommand::panels); const auto menu_plan = pp::app::plan_tools_menu_command(pp::app::ToolsMenuCommand::panels);
if (menu_plan.action != pp::app::ToolsMenuAction::show_panels_submenu) if (menu_plan.action != pp::app::ToolsMenuAction::show_panels_submenu)
return; return;
pp::panopainter::detach_legacy_node_from_parent(*popup_exp);
const auto popup_exp_overlay = pp::panopainter::open_legacy_overlay_node_with_handle(*main, popup_exp);
if (!popup_exp_overlay)
return;
const auto popup_exp_handle = popup_exp_overlay.value();
glm::vec2 pos = b->m_pos + glm::vec2(b->m_size.x, 0); glm::vec2 pos = b->m_pos + glm::vec2(b->m_size.x, 0);
auto popup_time = add_menu_popup(*this, "panels-menu", pos, b->m_size.x); auto popup_time = add_menu_popup(*this, "panels-menu", pos, b->m_size.x);
if (!popup_time) if (!popup_time)
{
close_legacy_overlay_handle_ignoring_status(*main, popup_exp_handle);
return; return;
}
pp::panopainter::detach_legacy_node_from_parent(*popup_time);
const auto popup_time_overlay = pp::panopainter::open_legacy_overlay_node_with_handle(*main, popup_time);
if (!popup_time_overlay)
{
close_legacy_overlay_handle_ignoring_status(*main, popup_exp_handle);
return;
}
const auto popup_time_handle = popup_time_overlay.value();
const auto close_panel_popups = [main, popup_exp_handle, popup_time_handle]()
{
close_legacy_overlay_handle_ignoring_status(*main, popup_exp_handle);
close_legacy_overlay_handle_ignoring_status(*main, popup_time_handle);
};
auto visible = [this](Node* panel) { auto visible = [this](Node* panel) {
if (!panel) if (!panel)
@@ -823,7 +955,7 @@ void App::init_menu_tools()
return false; return false;
}; };
popup_time->find<NodeButtonCustom>("panel-presets")->on_click = [this, popup_time, popup_exp, visible](Node*) { popup_time->find<NodeButtonCustom>("panel-presets")->on_click = [this, close_panel_popups, visible](Node*) {
const auto plan = pp::app::plan_tools_panel( const auto plan = pp::app::plan_tools_panel(
pp::app::ToolsPanel::presets, pp::app::ToolsPanel::presets,
visible(floating_presets.get())); visible(floating_presets.get()));
@@ -846,11 +978,10 @@ void App::init_menu_tools()
{ {
fpanel->m_container->add_child(floating_presets); fpanel->m_container->add_child(floating_presets);
} }
pp::panopainter::close_legacy_popup_overlay(*popup_exp); close_panel_popups();
pp::panopainter::close_legacy_popup_overlay(*popup_time);
}; };
popup_time->find<NodeButtonCustom>("panel-color")->on_click = [this, popup_time, popup_exp, visible](Node*) { popup_time->find<NodeButtonCustom>("panel-color")->on_click = [this, close_panel_popups, visible](Node*) {
const auto plan = pp::app::plan_tools_panel( const auto plan = pp::app::plan_tools_panel(
pp::app::ToolsPanel::color, pp::app::ToolsPanel::color,
visible(floating_color.get())); visible(floating_color.get()));
@@ -874,10 +1005,9 @@ void App::init_menu_tools()
{ {
fpanel->m_container->add_child(floating_color); fpanel->m_container->add_child(floating_color);
} }
pp::panopainter::close_legacy_popup_overlay(*popup_exp); close_panel_popups();
pp::panopainter::close_legacy_popup_overlay(*popup_time);
}; };
popup_time->find<NodeButtonCustom>("panel-color-adv")->on_click = [this, popup_time, popup_exp, visible](Node*) { popup_time->find<NodeButtonCustom>("panel-color-adv")->on_click = [this, close_panel_popups, visible](Node*) {
const auto plan = pp::app::plan_tools_panel( const auto plan = pp::app::plan_tools_panel(
pp::app::ToolsPanel::color_advanced, pp::app::ToolsPanel::color_advanced,
visible(floating_picker.get())); visible(floating_picker.get()));
@@ -901,10 +1031,9 @@ void App::init_menu_tools()
{ {
fpanel->m_container->add_child(floating_picker); fpanel->m_container->add_child(floating_picker);
} }
pp::panopainter::close_legacy_popup_overlay(*popup_exp); close_panel_popups();
pp::panopainter::close_legacy_popup_overlay(*popup_time);
}; };
popup_time->find<NodeButtonCustom>("panel-layers")->on_click = [this, popup_time, popup_exp, visible](Node*) { popup_time->find<NodeButtonCustom>("panel-layers")->on_click = [this, close_panel_popups, visible](Node*) {
const auto plan = pp::app::plan_tools_panel( const auto plan = pp::app::plan_tools_panel(
pp::app::ToolsPanel::layers, pp::app::ToolsPanel::layers,
visible(layers.get())); visible(layers.get()));
@@ -922,10 +1051,9 @@ void App::init_menu_tools()
if (plan.hides_embedded_title) if (plan.hides_embedded_title)
layers->find("title")->SetVisibility(false); layers->find("title")->SetVisibility(false);
pp::panopainter::close_legacy_popup_overlay(*popup_exp); close_panel_popups();
pp::panopainter::close_legacy_popup_overlay(*popup_time);
}; };
popup_time->find<NodeButtonCustom>("panel-brush")->on_click = [this, popup_time, popup_exp, visible](Node*) { popup_time->find<NodeButtonCustom>("panel-brush")->on_click = [this, close_panel_popups, visible](Node*) {
const auto plan = pp::app::plan_tools_panel( const auto plan = pp::app::plan_tools_panel(
pp::app::ToolsPanel::brush, pp::app::ToolsPanel::brush,
visible(stroke.get())); visible(stroke.get()));
@@ -942,10 +1070,9 @@ void App::init_menu_tools()
if (plan.hides_embedded_title) if (plan.hides_embedded_title)
stroke->find("title")->SetVisibility(false); stroke->find("title")->SetVisibility(false);
pp::panopainter::close_legacy_popup_overlay(*popup_exp); close_panel_popups();
pp::panopainter::close_legacy_popup_overlay(*popup_time);
}; };
popup_time->find<NodeButtonCustom>("panel-grids")->on_click = [this, popup_time, popup_exp, visible](Node*) { popup_time->find<NodeButtonCustom>("panel-grids")->on_click = [this, close_panel_popups, visible](Node*) {
const auto plan = pp::app::plan_tools_panel( const auto plan = pp::app::plan_tools_panel(
pp::app::ToolsPanel::grids, pp::app::ToolsPanel::grids,
visible(grid.get())); visible(grid.get()));
@@ -962,10 +1089,9 @@ void App::init_menu_tools()
if (plan.hides_embedded_title) if (plan.hides_embedded_title)
grid->find("title")->SetVisibility(false); grid->find("title")->SetVisibility(false);
pp::panopainter::close_legacy_popup_overlay(*popup_exp); close_panel_popups();
pp::panopainter::close_legacy_popup_overlay(*popup_time);
}; };
popup_time->find<NodeButtonCustom>("panel-animation")->on_click = [this, popup_time, popup_exp, visible](Node*) { popup_time->find<NodeButtonCustom>("panel-animation")->on_click = [this, close_panel_popups, visible](Node*) {
const auto plan = pp::app::plan_tools_panel( const auto plan = pp::app::plan_tools_panel(
pp::app::ToolsPanel::animation, pp::app::ToolsPanel::animation,
visible(animation.get())); visible(animation.get()));
@@ -980,8 +1106,7 @@ void App::init_menu_tools()
animation->SetWidthP(100); animation->SetWidthP(100);
animation->SetHeightP(100); animation->SetHeightP(100);
pp::panopainter::close_legacy_popup_overlay(*popup_exp); close_panel_popups();
pp::panopainter::close_legacy_popup_overlay(*popup_time);
}; };
}; };
@@ -1143,29 +1268,41 @@ void App::init_menu_tools()
}; };
popup_exp->find<NodeButtonCustom>("clear-grids")->on_click = [this, popup_exp](Node*) { popup_exp->find<NodeButtonCustom>("clear-grids")->on_click = [this, popup_exp](Node*) {
auto popup_exp_overlay = pp::panopainter::open_legacy_overlay_node_with_handle(*popup_exp->root(), popup_exp);
if (!popup_exp_overlay)
return;
const auto popup_exp_handle = popup_exp_overlay.value();
const auto plan = pp::app::plan_tools_menu_command(pp::app::ToolsMenuCommand::clear_grids); const auto plan = pp::app::plan_tools_menu_command(pp::app::ToolsMenuCommand::clear_grids);
execute_tools_menu_plan(*this, plan); execute_tools_menu_plan(*this, plan);
if (plan.closes_root_popup) if (plan.closes_root_popup)
{ {
pp::panopainter::close_legacy_popup_overlay(*popup_exp); close_legacy_overlay_handle_ignoring_status(*popup_exp->root(), popup_exp_handle);
} }
}; };
popup_exp->find<NodeButtonCustom>("camera-reset")->on_click = [this, popup_exp](Node*) { popup_exp->find<NodeButtonCustom>("camera-reset")->on_click = [this, popup_exp](Node*) {
auto popup_exp_overlay = pp::panopainter::open_legacy_overlay_node_with_handle(*popup_exp->root(), popup_exp);
if (!popup_exp_overlay)
return;
const auto popup_exp_handle = popup_exp_overlay.value();
const auto plan = pp::app::plan_tools_menu_command(pp::app::ToolsMenuCommand::reset_camera); const auto plan = pp::app::plan_tools_menu_command(pp::app::ToolsMenuCommand::reset_camera);
execute_tools_menu_plan(*this, plan); execute_tools_menu_plan(*this, plan);
if (plan.closes_root_popup) if (plan.closes_root_popup)
{ {
pp::panopainter::close_legacy_popup_overlay(*popup_exp); close_legacy_overlay_handle_ignoring_status(*popup_exp->root(), popup_exp_handle);
} }
}; };
popup_exp->find<NodeButtonCustom>("shortcuts")->on_click = [this, popup_exp](Node*) { popup_exp->find<NodeButtonCustom>("shortcuts")->on_click = [this, popup_exp](Node*) {
auto popup_exp_overlay = pp::panopainter::open_legacy_overlay_node_with_handle(*popup_exp->root(), popup_exp);
if (!popup_exp_overlay)
return;
const auto popup_exp_handle = popup_exp_overlay.value();
const auto plan = pp::app::plan_tools_menu_command(pp::app::ToolsMenuCommand::shortcuts); const auto plan = pp::app::plan_tools_menu_command(pp::app::ToolsMenuCommand::shortcuts);
execute_tools_menu_plan(*this, plan); execute_tools_menu_plan(*this, plan);
if (plan.closes_root_popup) if (plan.closes_root_popup)
{ {
pp::panopainter::close_legacy_popup_overlay(*popup_exp); close_legacy_overlay_handle_ignoring_status(*popup_exp->root(), popup_exp_handle);
} }
}; };
@@ -1179,13 +1316,17 @@ void App::init_menu_tools()
if (platform_supports_sonarpen()) if (platform_supports_sonarpen())
{ {
popup_exp->find<NodeButtonCustom>("sonarpen")->on_click = [this, popup_exp](Node*) { popup_exp->find<NodeButtonCustom>("sonarpen")->on_click = [this, popup_exp](Node*) {
auto popup_exp_overlay = pp::panopainter::open_legacy_overlay_node_with_handle(*popup_exp->root(), popup_exp);
if (!popup_exp_overlay)
return;
const auto popup_exp_handle = popup_exp_overlay.value();
const auto plan = pp::app::plan_tools_menu_command( const auto plan = pp::app::plan_tools_menu_command(
pp::app::ToolsMenuCommand::sonarpen, pp::app::ToolsMenuCommand::sonarpen,
platform_supports_sonarpen()); platform_supports_sonarpen());
execute_tools_menu_plan(*this, plan); execute_tools_menu_plan(*this, plan);
if (plan.closes_root_popup) if (plan.closes_root_popup)
{ {
pp::panopainter::close_legacy_popup_overlay(*popup_exp); close_legacy_overlay_handle_ignoring_status(*popup_exp->root(), popup_exp_handle);
} }
}; };
} }
@@ -1198,12 +1339,23 @@ void App::init_menu_about()
if (auto* menu_file = layout[main_id]->find<NodeButtonCustom>("menu-about")) if (auto* menu_file = layout[main_id]->find<NodeButtonCustom>("menu-about"))
{ {
menu_file->on_click = [=](Node*) { menu_file->on_click = [=](Node*) {
auto* popup_root = layout[main_id];
if (!popup_root) {
return;
}
glm::vec2 pos = menu_file->m_pos + glm::vec2(0, menu_file->m_size.y); glm::vec2 pos = menu_file->m_pos + glm::vec2(0, menu_file->m_size.y);
auto popup = add_menu_popup(*this, "about-menu", pos, menu_file->m_size.x); auto popup = add_menu_popup(*this, "about-menu", pos, menu_file->m_size.x);
if (!popup) if (!popup)
return; return;
pp::panopainter::detach_legacy_node_from_parent(*popup);
auto popup_overlay = pp::panopainter::open_legacy_overlay_node_with_handle(*popup_root, popup);
if (!popup_overlay) {
pp::panopainter::destroy_legacy_node(*popup);
return;
}
auto popup_handle = popup_overlay.value();
popup->find<NodeButtonCustom>("about-app")->on_click = [this, popup](Node*) { popup->find<NodeButtonCustom>("about-app")->on_click = [this, popup_root, popup_handle](Node*) {
const auto plan = pp::app::plan_about_menu_command( const auto plan = pp::app::plan_about_menu_command(
pp::app::AboutMenuCommand::about_app, pp::app::AboutMenuCommand::about_app,
g_version_major, g_version_major,
@@ -1212,11 +1364,11 @@ void App::init_menu_about()
execute_about_menu_plan(*this, plan); execute_about_menu_plan(*this, plan);
if (plan.closes_root_popup) if (plan.closes_root_popup)
{ {
pp::panopainter::close_legacy_popup_overlay(*popup); close_legacy_overlay_handle_ignoring_status(*popup_root, popup_handle);
} }
}; };
popup->find<NodeButtonCustom>("about-doc")->on_click = [this, popup](Node*) { popup->find<NodeButtonCustom>("about-doc")->on_click = [this, popup_root, popup_handle](Node*) {
// auto path = Asset::absolute("data/doc/test.pdf"); // auto path = Asset::absolute("data/doc/test.pdf");
// display_file(path); // display_file(path);
const auto plan = pp::app::plan_about_menu_command( const auto plan = pp::app::plan_about_menu_command(
@@ -1227,7 +1379,7 @@ void App::init_menu_about()
execute_about_menu_plan(*this, plan); execute_about_menu_plan(*this, plan);
if (plan.closes_root_popup) if (plan.closes_root_popup)
{ {
pp::panopainter::close_legacy_popup_overlay(*popup); close_legacy_overlay_handle_ignoring_status(*popup_root, popup_handle);
} }
}; };
@@ -1242,7 +1394,7 @@ void App::init_menu_about()
g_version_fix); g_version_fix);
text->set_text(plan.label.c_str()); text->set_text(plan.label.c_str());
} }
item->on_click = [this, popup](Node*) { item->on_click = [this, popup_root, popup_handle](Node*) {
const auto plan = pp::app::plan_about_menu_command( const auto plan = pp::app::plan_about_menu_command(
pp::app::AboutMenuCommand::whats_new, pp::app::AboutMenuCommand::whats_new,
g_version_major, g_version_major,
@@ -1251,14 +1403,14 @@ void App::init_menu_about()
execute_about_menu_plan(*this, plan); execute_about_menu_plan(*this, plan);
if (plan.closes_root_popup) if (plan.closes_root_popup)
{ {
pp::panopainter::close_legacy_popup_overlay(*popup); close_legacy_overlay_handle_ignoring_status(*popup_root, popup_handle);
} }
}; };
} }
if (auto b = popup->find<NodeButtonCustom>("about-crash")) if (auto b = popup->find<NodeButtonCustom>("about-crash"))
{ {
b->on_click = [this, popup](Node*) { b->on_click = [this, popup_root, popup_handle](Node*) {
const auto plan = pp::app::plan_about_menu_command( const auto plan = pp::app::plan_about_menu_command(
pp::app::AboutMenuCommand::induce_crash, pp::app::AboutMenuCommand::induce_crash,
g_version_major, g_version_major,
@@ -1267,14 +1419,14 @@ void App::init_menu_about()
execute_about_menu_plan(*this, plan); execute_about_menu_plan(*this, plan);
if (plan.closes_root_popup) if (plan.closes_root_popup)
{ {
pp::panopainter::close_legacy_popup_overlay(*popup); close_legacy_overlay_handle_ignoring_status(*popup_root, popup_handle);
} }
}; };
} }
if (auto b = popup->find<NodeButtonCustom>("about-perf")) if (auto b = popup->find<NodeButtonCustom>("about-perf"))
{ {
b->on_click = [this, popup](Node*) { b->on_click = [this, popup_root, popup_handle](Node*) {
const auto plan = pp::app::plan_about_menu_command( const auto plan = pp::app::plan_about_menu_command(
pp::app::AboutMenuCommand::performance_test, pp::app::AboutMenuCommand::performance_test,
g_version_major, g_version_major,
@@ -1285,7 +1437,7 @@ void App::init_menu_about()
execute_about_menu_plan(*this, plan); execute_about_menu_plan(*this, plan);
if (plan.closes_root_popup) if (plan.closes_root_popup)
{ {
pp::panopainter::close_legacy_popup_overlay(*popup); close_legacy_overlay_handle_ignoring_status(*popup_root, popup_handle);
} }
}; };
} }
@@ -1356,15 +1508,26 @@ void App::init_menu_layer()
if (auto* menu_file = layout[main_id]->find<NodeButtonCustom>("menu-layers")) if (auto* menu_file = layout[main_id]->find<NodeButtonCustom>("menu-layers"))
{ {
menu_file->on_click = [=](Node*) { menu_file->on_click = [=](Node*) {
auto* popup_root = layout[main_id];
if (!popup_root) {
return;
}
glm::vec2 pos = menu_file->m_pos + glm::vec2(0, menu_file->m_size.y); glm::vec2 pos = menu_file->m_pos + glm::vec2(0, menu_file->m_size.y);
auto popup = add_menu_popup(*this, "layers-menu", pos, menu_file->m_size.x); auto popup = add_menu_popup(*this, "layers-menu", pos, menu_file->m_size.x);
if (!popup) if (!popup)
return; return;
pp::panopainter::detach_legacy_node_from_parent(*popup);
auto popup_overlay = pp::panopainter::open_legacy_overlay_node_with_handle(*popup_root, popup);
if (!popup_overlay) {
pp::panopainter::destroy_legacy_node(*popup);
return;
}
auto popup_handle = popup_overlay.value();
popup->find<NodeButtonCustom>("layer-clear")->on_click = [this, popup](Node*) { popup->find<NodeButtonCustom>("layer-clear")->on_click = [this, popup_root, popup_handle](Node*) {
const auto plan = make_layer_menu_plan(pp::app::DocumentLayerMenuCommand::clear, *this); const auto plan = make_layer_menu_plan(pp::app::DocumentLayerMenuCommand::clear, *this);
execute_document_layer_menu_plan(*this, plan); execute_document_layer_menu_plan(*this, plan);
pp::panopainter::close_legacy_popup_overlay(*popup); close_legacy_overlay_handle_ignoring_status(*popup_root, popup_handle);
}; };
{ {
const auto plan = make_layer_menu_plan(pp::app::DocumentLayerMenuCommand::clear, *this); const auto plan = make_layer_menu_plan(pp::app::DocumentLayerMenuCommand::clear, *this);
@@ -1373,10 +1536,10 @@ void App::init_menu_layer()
set_text(plan.label.c_str()); set_text(plan.label.c_str());
} }
popup->find<NodeButtonCustom>("layer-rename")->on_click = [this, popup](Node*) { popup->find<NodeButtonCustom>("layer-rename")->on_click = [this, popup_root, popup_handle](Node*) {
const auto plan = make_layer_menu_plan(pp::app::DocumentLayerMenuCommand::rename, *this); const auto plan = make_layer_menu_plan(pp::app::DocumentLayerMenuCommand::rename, *this);
execute_document_layer_menu_plan(*this, plan); execute_document_layer_menu_plan(*this, plan);
pp::panopainter::close_legacy_popup_overlay(*popup); close_legacy_overlay_handle_ignoring_status(*popup_root, popup_handle);
}; };
{ {
const auto plan = make_layer_menu_plan(pp::app::DocumentLayerMenuCommand::rename, *this); const auto plan = make_layer_menu_plan(pp::app::DocumentLayerMenuCommand::rename, *this);
@@ -1385,10 +1548,10 @@ void App::init_menu_layer()
set_text(plan.label.c_str()); set_text(plan.label.c_str());
} }
popup->find<NodeButtonCustom>("layer-merge")->on_click = [this, popup](Node*) { popup->find<NodeButtonCustom>("layer-merge")->on_click = [this, popup_root, popup_handle](Node*) {
const auto plan = make_layer_menu_plan(pp::app::DocumentLayerMenuCommand::merge_down, *this); const auto plan = make_layer_menu_plan(pp::app::DocumentLayerMenuCommand::merge_down, *this);
execute_document_layer_menu_plan(*this, plan); execute_document_layer_menu_plan(*this, plan);
pp::panopainter::close_legacy_popup_overlay(*popup); close_legacy_overlay_handle_ignoring_status(*popup_root, popup_handle);
}; };
{ {
const auto plan = make_layer_menu_plan(pp::app::DocumentLayerMenuCommand::merge_down, *this); const auto plan = make_layer_menu_plan(pp::app::DocumentLayerMenuCommand::merge_down, *this);

View File

@@ -10,6 +10,75 @@
namespace pp::panopainter { namespace pp::panopainter {
namespace { namespace {
void close_legacy_overlay_handle_ignoring_status(
Node& anchor,
const pp::foundation::Result<pp::ui::NodeHandle>& overlay) noexcept
{
if (!overlay) {
return;
}
(void)close_legacy_overlay_node(anchor, overlay.value());
}
void close_legacy_overlay_handles_if_open(
Node& anchor,
const pp::foundation::Result<pp::ui::NodeHandle>& popup,
const pp::foundation::Result<pp::ui::NodeHandle>& tick) noexcept
{
if (popup) {
close_legacy_overlay_handle_ignoring_status(anchor, popup);
}
if (tick) {
close_legacy_overlay_handle_ignoring_status(anchor, tick);
}
}
struct CheckedPopupAndTickOverlays {
bool opened;
pp::foundation::Result<pp::ui::NodeHandle> popup;
pp::foundation::Result<pp::ui::NodeHandle> tick;
};
template <typename PopupT>
void set_popup_ticker_overlay_close_handler(
Node& anchor,
PopupT& popup,
const CheckedPopupAndTickOverlays& popup_and_tick) noexcept
{
popup.on_popup_close = [&anchor, popup_and_tick](Node*) {
close_legacy_overlay_handles_if_open(anchor, popup_and_tick.popup, popup_and_tick.tick);
};
}
CheckedPopupAndTickOverlays open_checked_popup_and_tick_overlays(
Node& anchor,
const std::shared_ptr<Node>& popup,
const std::shared_ptr<Node>& tick) noexcept
{
auto popup_overlay = open_legacy_overlay_node_with_handle(anchor, popup);
auto tick_overlay = open_legacy_overlay_node_with_handle(anchor, tick);
if (!popup_overlay || !tick_overlay) {
close_legacy_overlay_handles_if_open(anchor, popup_overlay, tick_overlay);
return { false, popup_overlay, tick_overlay };
}
return { true, popup_overlay, tick_overlay };
}
std::shared_ptr<NodeImage> create_checked_popup_tick(
Node& anchor,
const glm::vec2& tick_pos,
float anchor_height,
const glm::vec2& tick_sz) noexcept
{
auto tick = make_legacy_overlay_node_for_anchor<NodeImage>(anchor);
tick->SetPositioning(YGPositionTypeAbsolute);
tick->SetPosition(tick_pos.x, tick_pos.y + (anchor_height - tick_sz.y) * 0.5f);
tick->SetSize(tick_sz);
tick->set_image("data/ui/popup-tick.png");
tick->m_scale = { 1, 1 };
return tick;
}
class LegacyQuickUiServices final : public pp::app::QuickUiServices { class LegacyQuickUiServices final : public pp::app::QuickUiServices {
public: public:
LegacyQuickUiServices(NodePanelQuick& panel, const NodePanelQuick::MiniState* restore_state = nullptr) noexcept LegacyQuickUiServices(NodePanelQuick& panel, const NodePanelQuick::MiniState* restore_state = nullptr) noexcept
@@ -84,20 +153,18 @@ private:
glm::vec2 tick_pos = button->m_pos + glm::vec2(button->m_size.x, 0); glm::vec2 tick_pos = button->m_pos + glm::vec2(button->m_size.x, 0);
glm::vec2 popup_pos = { tick_pos.x + tick_sz.x, tick_pos.y }; glm::vec2 popup_pos = { tick_pos.x + tick_sz.x, tick_pos.y };
auto tick = make_legacy_overlay_node_for_anchor<NodeImage>(panel_); auto tick = create_checked_popup_tick(panel_, tick_pos, button->m_size.y, tick_sz);
tick->SetPositioning(YGPositionTypeAbsolute);
tick->SetPosition(tick_pos.x, tick_pos.y + (button->m_size.y - tick_sz.y) * 0.5f);
tick->SetSize(tick_sz);
tick->set_image("data/ui/popup-tick.png");
tick->m_scale = { 1, 1 };
(void)attach_legacy_overlay_node_to_root(panel_, tick);
float hh = popup->m_container->m_children.size() > 10 ? (screen.y - 90.f) : 400.f; float hh = popup->m_container->m_children.size() > 10 ? (screen.y - 90.f) : 400.f;
popup->SetWidth(350); popup->SetWidth(350);
popup->SetHeight(glm::max(hh, 400.f)); popup->SetHeight(glm::max(hh, 400.f));
popup->SetPositioning(YGPositionTypeAbsolute); popup->SetPositioning(YGPositionTypeAbsolute);
popup->SetPosition(popup_pos); popup->SetPosition(popup_pos);
(void)attach_legacy_overlay_node_to_root(panel_, popup);
const auto popup_overlays = open_checked_popup_and_tick_overlays(panel_, popup, tick);
if (!popup_overlays.opened) {
return;
}
panel_.root()->update(); panel_.root()->update();
popup->tick(0); popup->tick(0);
@@ -115,8 +182,7 @@ private:
popup->update(); popup->update();
activate_legacy_popup_overlay(*popup); activate_legacy_popup_overlay(*popup);
set_popup_ticker_overlay_close_handler(panel_, *popup, popup_overlays);
pp::panopainter::bind_legacy_popup_close_destroys_overlay(*popup, tick);
auto* panel = &panel_; auto* panel = &panel_;
popup->on_brush_changed = [panel, button](Node*, std::shared_ptr<Brush>& b) { popup->on_brush_changed = [panel, button](Node*, std::shared_ptr<Brush>& b) {
@@ -141,17 +207,14 @@ private:
glm::vec2 tick_pos = target->m_pos + glm::vec2(target->m_size.x, 0); glm::vec2 tick_pos = target->m_pos + glm::vec2(target->m_size.x, 0);
glm::vec2 popup_pos = { tick_pos.x + tick_sz.x, tick_pos.y - 140.f }; glm::vec2 popup_pos = { tick_pos.x + tick_sz.x, tick_pos.y - 140.f };
auto tick = make_legacy_overlay_node_for_anchor<NodeImage>(panel_); auto tick = create_checked_popup_tick(panel_, tick_pos, target->m_size.y, tick_sz);
tick->SetPositioning(YGPositionTypeAbsolute);
tick->SetPosition(tick_pos.x, tick_pos.y + (target->m_size.y - tick_sz.y) * 0.5f);
tick->SetSize(tick_sz);
tick->set_image("data/ui/popup-tick.png");
tick->m_scale = { 1, 1 };
(void)attach_legacy_overlay_node_to_root(panel_, tick);
popup->SetPositioning(YGPositionTypeAbsolute); popup->SetPositioning(YGPositionTypeAbsolute);
popup->SetPosition(popup_pos); popup->SetPosition(popup_pos);
(void)attach_legacy_overlay_node_to_root(panel_, popup); const auto popup_overlays = open_checked_popup_and_tick_overlays(panel_, popup, tick);
if (!popup_overlays.opened) {
return;
}
panel_.root()->update(); panel_.root()->update();
popup->tick(0); popup->tick(0);
@@ -172,7 +235,7 @@ private:
auto c = static_cast<NodeBorder*>(target->m_children[0].get()); auto c = static_cast<NodeBorder*>(target->m_children[0].get());
panel_.m_picker->set_color(c->m_color); panel_.m_picker->set_color(c->m_color);
pp::panopainter::bind_legacy_popup_close_destroys_overlay(*panel_.m_picker, tick); set_popup_ticker_overlay_close_handler(panel_, *popup, popup_overlays);
auto* panel = &panel_; auto* panel = &panel_;
panel_.m_picker->on_color_change = [panel, c](Node*, glm::vec3 rgb) { panel_.m_picker->on_color_change = [panel, c](Node*, glm::vec3 rgb) {

View File

@@ -30,8 +30,13 @@ void NodeComboBox::loaded()
popup->init(); popup->init();
popup->create(); popup->create();
popup->loaded(); popup->loaded();
(void)pp::panopainter::attach_legacy_overlay_node_to_root(*this, popup); const auto popup_overlay = pp::panopainter::open_legacy_overlay_node_with_handle(*this, popup);
if (!popup_overlay) {
return;
}
const auto popup_handle = popup_overlay.value();
m_items.clear(); m_items.clear();
int popup_child_index = -1;
for (int i = 0; i < m_data.size(); i++) for (int i = 0; i < m_data.size(); i++)
{ {
if (m_data[i] == "-") if (m_data[i] == "-")
@@ -47,17 +52,21 @@ void NodeComboBox::loaded()
btn->m_text->set_text(m_data[i].c_str()); btn->m_text->set_text(m_data[i].c_str());
btn->m_border->SetWidthP(100.f); btn->m_border->SetWidthP(100.f);
btn->m_border->SetHeight(GetHeight()); btn->m_border->SetHeight(GetHeight());
popup_child_index++;
int index = (int)m_items.size(); int index = (int)m_items.size();
if (index == m_current_index) if (index == m_current_index)
m_selected_child_index = popup->get_child_index(btn); m_selected_child_index = popup_child_index;
m_items.push_back(m_data[i]); m_items.push_back(m_data[i]);
btn->on_click = [this,popup,btn,index](Node* target) { const int clicked_child_index = popup_child_index;
btn->on_click = [this, popup_handle, index, clicked_child_index](Node* target) {
m_current_index = index; m_current_index = index;
m_selected_child_index = popup->get_child_index(target); m_selected_child_index = clicked_child_index;
m_text->set_text(m_items[index].c_str()); m_text->set_text(m_items[index].c_str());
if (on_select) if (on_select)
on_select(btn, index); on_select(target, index);
pp::panopainter::close_legacy_popup_overlay(*popup); const auto close_status =
pp::panopainter::close_legacy_overlay_node(*this, popup_handle);
(void)close_status;
}; };
} }
} }

View File

@@ -54,13 +54,21 @@ kEventResult NodeColorPicker::handle_event(Event* e)
case kEventType::MouseUpL: case kEventType::MouseUpL:
if (!m_mouse_inside) if (!m_mouse_inside)
{ {
pp::panopainter::release_legacy_mouse_capture(*this);
if (m_parent)
{
pp::panopainter::detach_legacy_node_from_parent(*this);
}
if (m_color_cur->m_color != m_color_old->m_color) if (m_color_cur->m_color != m_color_old->m_color)
{ {
m_color_old2->m_color = m_color_old1->m_color; m_color_old2->m_color = m_color_old1->m_color;
m_color_old1->m_color = m_color_old->m_color; m_color_old1->m_color = m_color_old->m_color;
m_color_old->m_color = m_color_cur->m_color; m_color_old->m_color = m_color_cur->m_color;
} }
pp::panopainter::close_legacy_popup_panel(*this, on_popup_close); if (on_popup_close)
{
on_popup_close(this);
}
} }
break; break;
default: default:

View File

@@ -8,6 +8,7 @@
#include "node_button_custom.h" #include "node_button_custom.h"
#include "node_image.h" #include "node_image.h"
#include "node_panel_brush.h" #include "node_panel_brush.h"
#include "ui_core/node_lifetime.h"
namespace pp::app { namespace pp::app {
struct BrushStrokeControlPlan; struct BrushStrokeControlPlan;
@@ -100,7 +101,8 @@ public:
std::function<void(Node* target, const std::string& path, const std::string& thumb)> on_brush_changed; std::function<void(Node* target, const std::string& path, const std::string& thumb)> on_brush_changed;
std::function<void(Node* target, const std::string& path, const std::string& thumb)> on_dual_changed; std::function<void(Node* target, const std::string& path, const std::string& thumb)> on_dual_changed;
//std::function<void(Node* target, const std::string& path, const std::string& thumb)> on_texture_changed; //std::function<void(Node* target, const std::string& path, const std::string& thumb)> on_texture_changed;
std::function<void(Node* target)> on_popup_close; pp::ui::NodeHandle m_popup_overlay_handle {};
pp::ui::NodeHandle m_tick_overlay_handle {};
struct SliderCurve struct SliderCurve
{ {
@@ -130,4 +132,5 @@ public:
void init_checkbox(NodeCheckBox*& slider, const char* id, pp::app::BrushStrokeBoolSetting setting, bool Brush::* prop); void init_checkbox(NodeCheckBox*& slider, const char* id, pp::app::BrushStrokeBoolSetting setting, bool Brush::* prop);
void handle_checkbox(pp::app::BrushStrokeBoolSetting setting, bool value); void handle_checkbox(pp::app::BrushStrokeBoolSetting setting, bool value);
void execute_stroke_control_plan(const pp::app::BrushStrokeControlPlan& plan); void execute_stroke_control_plan(const pp::app::BrushStrokeControlPlan& plan);
void close_popup_overlay_handles() noexcept;
}; };