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

@@ -79,6 +79,27 @@ std::shared_ptr<NodePopupMenu> add_menu_popup(
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::DocumentLayerMenuCommand command,
App& app)
@@ -463,7 +484,11 @@ void App::init_sidebar()
if (auto* button = layout[main_id]->find<NodeButtonCustom>("btn-stroke"))
{
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);
if (stroke->m_parent)
{
@@ -473,24 +498,35 @@ void App::init_sidebar()
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->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->SetSize(32, 16);
tick->SetPosition(pos.x - 16, pos.y);
tick->set_image("data/ui/popup-tick-up.png");
(void)pp::panopainter::attach_legacy_overlay_node(*this, tick);
layout[main_id]->update();
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<NodeScroll>("scroller");
//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"))
@@ -512,9 +548,17 @@ void App::init_sidebar()
if (auto* button = layout[main_id]->find<NodeButtonCustom>("btn-color"))
{
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);
(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->SetSize(350, 350);
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->SetPosition(pos.x - 16, pos.y);
tick->set_image("data/ui/popup-tick-up.png");
(void)pp::panopainter::attach_legacy_overlay_node(*this, tick);
layout[main_id]->update();
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);
pp::panopainter::bind_legacy_popup_close_destroys_overlay(*color, tick);
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);
};
};
}
if (auto* button = layout[main_id]->find<NodeButtonCustom>("btn-layer"))
{
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);
layers->find("title")->SetVisibility(true);
layers->SetSize(350, YGUndefined);
@@ -547,28 +604,45 @@ void App::init_sidebar()
pp::panopainter::close_legacy_dialog_node(*fp);
}
}
(void)pp::panopainter::attach_legacy_overlay_node(*this, layers);
auto tick = pp::panopainter::make_legacy_overlay_node_for_anchor<NodeImage>(*layout[main_id]);
const auto popup_overlay = pp::panopainter::open_legacy_overlay_node_with_handle(*popup_root, layers);
if (!popup_overlay) {
return;
}
auto tick = pp::panopainter::make_legacy_overlay_node_for_anchor<NodeImage>(*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");
(void)pp::panopainter::attach_legacy_overlay_node(*this, tick);
layout[main_id]->update();
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();
layers->SetPosition(pos.x - layers->m_size.x / 2.f, pos.y + 16);
layers->SetPositioning(YGPositionTypeAbsolute);
pp::panopainter::activate_legacy_popup_overlay(*layers);
auto scroll = layers->find<NodeScroll>("layers-container");
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"))
{
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);
grid->find("title")->SetVisibility(true);
grid->SetSize(350, YGUndefined);
@@ -580,14 +654,26 @@ void App::init_sidebar()
pp::panopainter::close_legacy_dialog_node(*fp);
}
}
(void)pp::panopainter::attach_legacy_overlay_node(*this, grid);
auto tick = pp::panopainter::make_legacy_overlay_node_for_anchor<NodeImage>(*layout[main_id]);
const auto popup_overlay = pp::panopainter::open_legacy_overlay_node_with_handle(*popup_root, grid);
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->SetSize(32, 16);
tick->SetPosition(pos.x - 16, pos.y);
tick->set_image("data/ui/popup-tick-up.png");
(void)pp::panopainter::attach_legacy_overlay_node(*this, tick);
layout[main_id]->update();
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();
grid->SetPosition(pos.x - grid->m_size.x / 2.f, pos.y + 16);
grid->SetPositioning(YGPositionTypeAbsolute);
@@ -595,7 +681,10 @@ void App::init_sidebar()
auto scroll = grid->find<NodeScroll>("scroller");
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"))
{
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);
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)
return;
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);
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"))
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);
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"))
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);
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"))
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);
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"))
b->on_click = [this, popup](Node*) {
b->on_click = [this, popup_root, popup_handle](Node*) {
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"))
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);
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"))
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);
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"))
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);
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"))
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);
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)
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);
pp::panopainter::close_legacy_popup_overlay(*popup);
pp::panopainter::close_legacy_popup_overlay(*subpopup);
close_legacy_overlay_handle_ignoring_status(*popup_root, popup_handle);
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);
pp::panopainter::close_legacy_popup_overlay(*popup);
pp::panopainter::close_legacy_popup_overlay(*subpopup);
close_legacy_overlay_handle_ignoring_status(*popup_root, popup_handle);
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);
pp::panopainter::close_legacy_popup_overlay(*popup);
pp::panopainter::close_legacy_popup_overlay(*subpopup);
close_legacy_overlay_handle_ignoring_status(*popup_root, popup_handle);
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);
pp::panopainter::close_legacy_popup_overlay(*popup);
pp::panopainter::close_legacy_popup_overlay(*subpopup);
close_legacy_overlay_handle_ignoring_status(*popup_root, popup_handle);
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);
pp::panopainter::close_legacy_popup_overlay(*popup);
pp::panopainter::close_legacy_popup_overlay(*subpopup);
close_legacy_overlay_handle_ignoring_status(*popup_root, popup_handle);
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);
pp::panopainter::close_legacy_popup_overlay(*popup);
pp::panopainter::close_legacy_popup_overlay(*subpopup);
close_legacy_overlay_handle_ignoring_status(*popup_root, popup_handle);
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);
pp::panopainter::close_legacy_popup_overlay(*popup);
pp::panopainter::close_legacy_popup_overlay(*subpopup);
close_legacy_overlay_handle_ignoring_status(*popup_root, popup_handle);
close_legacy_overlay_handle_ignoring_status(*popup_root, subpopup_handle);
};
};
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);
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"))
b->on_click = [this, popup](Node*) {
b->on_click = [this, popup_root, popup_handle](Node*) {
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"))
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);
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"))
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);
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)
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);
if (menu_plan.action != pp::app::ToolsMenuAction::show_panels_submenu)
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);
auto popup_time = add_menu_popup(*this, "panels-menu", pos, b->m_size.x);
if (!popup_time)
{
close_legacy_overlay_handle_ignoring_status(*main, popup_exp_handle);
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) {
if (!panel)
@@ -823,7 +955,7 @@ void App::init_menu_tools()
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(
pp::app::ToolsPanel::presets,
visible(floating_presets.get()));
@@ -846,11 +978,10 @@ void App::init_menu_tools()
{
fpanel->m_container->add_child(floating_presets);
}
pp::panopainter::close_legacy_popup_overlay(*popup_exp);
pp::panopainter::close_legacy_popup_overlay(*popup_time);
close_panel_popups();
};
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(
pp::app::ToolsPanel::color,
visible(floating_color.get()));
@@ -874,10 +1005,9 @@ void App::init_menu_tools()
{
fpanel->m_container->add_child(floating_color);
}
pp::panopainter::close_legacy_popup_overlay(*popup_exp);
pp::panopainter::close_legacy_popup_overlay(*popup_time);
close_panel_popups();
};
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(
pp::app::ToolsPanel::color_advanced,
visible(floating_picker.get()));
@@ -901,10 +1031,9 @@ void App::init_menu_tools()
{
fpanel->m_container->add_child(floating_picker);
}
pp::panopainter::close_legacy_popup_overlay(*popup_exp);
pp::panopainter::close_legacy_popup_overlay(*popup_time);
close_panel_popups();
};
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(
pp::app::ToolsPanel::layers,
visible(layers.get()));
@@ -922,10 +1051,9 @@ void App::init_menu_tools()
if (plan.hides_embedded_title)
layers->find("title")->SetVisibility(false);
pp::panopainter::close_legacy_popup_overlay(*popup_exp);
pp::panopainter::close_legacy_popup_overlay(*popup_time);
close_panel_popups();
};
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(
pp::app::ToolsPanel::brush,
visible(stroke.get()));
@@ -942,10 +1070,9 @@ void App::init_menu_tools()
if (plan.hides_embedded_title)
stroke->find("title")->SetVisibility(false);
pp::panopainter::close_legacy_popup_overlay(*popup_exp);
pp::panopainter::close_legacy_popup_overlay(*popup_time);
close_panel_popups();
};
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(
pp::app::ToolsPanel::grids,
visible(grid.get()));
@@ -962,10 +1089,9 @@ void App::init_menu_tools()
if (plan.hides_embedded_title)
grid->find("title")->SetVisibility(false);
pp::panopainter::close_legacy_popup_overlay(*popup_exp);
pp::panopainter::close_legacy_popup_overlay(*popup_time);
close_panel_popups();
};
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(
pp::app::ToolsPanel::animation,
visible(animation.get()));
@@ -980,8 +1106,7 @@ void App::init_menu_tools()
animation->SetWidthP(100);
animation->SetHeightP(100);
pp::panopainter::close_legacy_popup_overlay(*popup_exp);
pp::panopainter::close_legacy_popup_overlay(*popup_time);
close_panel_popups();
};
};
@@ -1143,29 +1268,41 @@ void App::init_menu_tools()
};
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);
execute_tools_menu_plan(*this, plan);
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*) {
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);
execute_tools_menu_plan(*this, plan);
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*) {
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);
execute_tools_menu_plan(*this, plan);
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())
{
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(
pp::app::ToolsMenuCommand::sonarpen,
platform_supports_sonarpen());
execute_tools_menu_plan(*this, plan);
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"))
{
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);
auto popup = add_menu_popup(*this, "about-menu", pos, menu_file->m_size.x);
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;
}
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(
pp::app::AboutMenuCommand::about_app,
g_version_major,
@@ -1212,11 +1364,11 @@ void App::init_menu_about()
execute_about_menu_plan(*this, plan);
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");
// display_file(path);
const auto plan = pp::app::plan_about_menu_command(
@@ -1227,7 +1379,7 @@ void App::init_menu_about()
execute_about_menu_plan(*this, plan);
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);
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(
pp::app::AboutMenuCommand::whats_new,
g_version_major,
@@ -1251,14 +1403,14 @@ void App::init_menu_about()
execute_about_menu_plan(*this, plan);
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"))
{
b->on_click = [this, popup](Node*) {
b->on_click = [this, popup_root, popup_handle](Node*) {
const auto plan = pp::app::plan_about_menu_command(
pp::app::AboutMenuCommand::induce_crash,
g_version_major,
@@ -1267,14 +1419,14 @@ void App::init_menu_about()
execute_about_menu_plan(*this, plan);
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"))
{
b->on_click = [this, popup](Node*) {
b->on_click = [this, popup_root, popup_handle](Node*) {
const auto plan = pp::app::plan_about_menu_command(
pp::app::AboutMenuCommand::performance_test,
g_version_major,
@@ -1285,7 +1437,7 @@ void App::init_menu_about()
execute_about_menu_plan(*this, plan);
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"))
{
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);
auto popup = add_menu_popup(*this, "layers-menu", pos, menu_file->m_size.x);
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;
}
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);
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);
@@ -1373,10 +1536,10 @@ void App::init_menu_layer()
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);
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);
@@ -1385,10 +1548,10 @@ void App::init_menu_layer()
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);
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);

View File

@@ -10,6 +10,75 @@
namespace pp::panopainter {
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 {
public:
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 popup_pos = { tick_pos.x + tick_sz.x, tick_pos.y };
auto tick = make_legacy_overlay_node_for_anchor<NodeImage>(panel_);
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);
auto tick = create_checked_popup_tick(panel_, tick_pos, button->m_size.y, tick_sz);
float hh = popup->m_container->m_children.size() > 10 ? (screen.y - 90.f) : 400.f;
popup->SetWidth(350);
popup->SetHeight(glm::max(hh, 400.f));
popup->SetPositioning(YGPositionTypeAbsolute);
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();
popup->tick(0);
@@ -115,8 +182,7 @@ private:
popup->update();
activate_legacy_popup_overlay(*popup);
pp::panopainter::bind_legacy_popup_close_destroys_overlay(*popup, tick);
set_popup_ticker_overlay_close_handler(panel_, *popup, popup_overlays);
auto* panel = &panel_;
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 popup_pos = { tick_pos.x + tick_sz.x, tick_pos.y - 140.f };
auto tick = make_legacy_overlay_node_for_anchor<NodeImage>(panel_);
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);
auto tick = create_checked_popup_tick(panel_, tick_pos, target->m_size.y, tick_sz);
popup->SetPositioning(YGPositionTypeAbsolute);
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();
popup->tick(0);
@@ -172,7 +235,7 @@ private:
auto c = static_cast<NodeBorder*>(target->m_children[0].get());
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_;
panel_.m_picker->on_color_change = [panel, c](Node*, glm::vec3 rgb) {

View File

@@ -30,8 +30,13 @@ void NodeComboBox::loaded()
popup->init();
popup->create();
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();
int popup_child_index = -1;
for (int i = 0; i < m_data.size(); i++)
{
if (m_data[i] == "-")
@@ -47,17 +52,21 @@ void NodeComboBox::loaded()
btn->m_text->set_text(m_data[i].c_str());
btn->m_border->SetWidthP(100.f);
btn->m_border->SetHeight(GetHeight());
popup_child_index++;
int index = (int)m_items.size();
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]);
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_selected_child_index = popup->get_child_index(target);
m_selected_child_index = clicked_child_index;
m_text->set_text(m_items[index].c_str());
if (on_select)
on_select(btn, index);
pp::panopainter::close_legacy_popup_overlay(*popup);
on_select(target, index);
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:
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)
{
m_color_old2->m_color = m_color_old1->m_color;
m_color_old1->m_color = m_color_old->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;
default:

View File

@@ -8,6 +8,7 @@
#include "node_button_custom.h"
#include "node_image.h"
#include "node_panel_brush.h"
#include "ui_core/node_lifetime.h"
namespace pp::app {
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_dual_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
{
@@ -130,4 +132,5 @@ public:
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 execute_stroke_control_plan(const pp::app::BrushStrokeControlPlan& plan);
void close_popup_overlay_handles() noexcept;
};