Extract app menu binding services
This commit is contained in:
@@ -94,6 +94,8 @@ set(PP_LEGACY_APP_SOURCES
|
|||||||
src/legacy_canvas_mode_transform.cpp
|
src/legacy_canvas_mode_transform.cpp
|
||||||
src/legacy_app_shell_services.cpp
|
src/legacy_app_shell_services.cpp
|
||||||
src/legacy_app_shell_services.h
|
src/legacy_app_shell_services.h
|
||||||
|
src/legacy_about_menu_binding_services.cpp
|
||||||
|
src/legacy_about_menu_binding_services.h
|
||||||
src/legacy_app_shell_performance_test_services.cpp
|
src/legacy_app_shell_performance_test_services.cpp
|
||||||
src/legacy_app_shell_performance_test_services.h
|
src/legacy_app_shell_performance_test_services.h
|
||||||
src/legacy_canvas_tool_services.cpp
|
src/legacy_canvas_tool_services.cpp
|
||||||
@@ -157,9 +159,15 @@ set(PP_PANOPAINTER_APP_SOURCES
|
|||||||
src/app_layout_edit_menu.cpp
|
src/app_layout_edit_menu.cpp
|
||||||
src/app_layout_about_layer_menu.cpp
|
src/app_layout_about_layer_menu.cpp
|
||||||
src/app_layout_file_menu.cpp
|
src/app_layout_file_menu.cpp
|
||||||
|
src/legacy_file_menu_binding_services.cpp
|
||||||
|
src/legacy_file_menu_binding_services.h
|
||||||
src/app_layout_tools_menu.cpp
|
src/app_layout_tools_menu.cpp
|
||||||
|
src/legacy_tools_menu_binding_services.cpp
|
||||||
|
src/legacy_tools_menu_binding_services.h
|
||||||
src/app_shaders.cpp
|
src/app_shaders.cpp
|
||||||
src/app_vr.cpp
|
src/app_vr.cpp
|
||||||
|
src/legacy_main_toolbar_binding_services.cpp
|
||||||
|
src/legacy_main_toolbar_binding_services.h
|
||||||
src/legacy_app_runtime_shell_services.cpp
|
src/legacy_app_runtime_shell_services.cpp
|
||||||
src/legacy_app_frame_services.cpp
|
src/legacy_app_frame_services.cpp
|
||||||
src/legacy_app_dialog_services.cpp
|
src/legacy_app_dialog_services.cpp
|
||||||
|
|||||||
@@ -25,6 +25,29 @@ agent or engineer to remove them without reconstructing context from chat.
|
|||||||
owns that document-open handoff inline while retained dialog creation,
|
owns that document-open handoff inline while retained dialog creation,
|
||||||
unsaved-project prompting, project-open execution, and title/layer refresh
|
unsaved-project prompting, project-open execution, and title/layer refresh
|
||||||
still remain.
|
still remain.
|
||||||
|
- 2026-06-17: `DEBT-0035` was narrowed again.
|
||||||
|
`src/app_layout_main_toolbar.cpp` no longer owns the retained main-toolbar
|
||||||
|
button wiring inline; `src/legacy_main_toolbar_binding_services.*` now owns
|
||||||
|
the per-button bindings behind explicit `App&` plus toolbar-root
|
||||||
|
dependencies, while the app-layout file remains a thin layout-root adapter
|
||||||
|
and retained toolbar execution still lives in
|
||||||
|
`src/legacy_app_shell_services.*`.
|
||||||
|
- 2026-06-17: `DEBT-0031`/`DEBT-0030` were narrowed again.
|
||||||
|
`src/app_layout_file_menu.cpp` no longer owns the retained File-menu popup,
|
||||||
|
export-submenu popup, or button wiring inline; that binding now lives in
|
||||||
|
`src/legacy_file_menu_binding_services.*`, while retained file/export command
|
||||||
|
execution still lives in `src/legacy_app_shell_services.*`.
|
||||||
|
- 2026-06-17: `DEBT-0034` was narrowed again.
|
||||||
|
`src/app_layout_about_layer_menu.cpp` no longer owns the retained About-menu
|
||||||
|
popup creation, version-label setup, or button wiring inline; that binding
|
||||||
|
now lives in `src/legacy_about_menu_binding_services.*`, while retained About
|
||||||
|
command execution and diagnostics still live in
|
||||||
|
`src/legacy_app_shell_services.*`.
|
||||||
|
- 2026-06-17: `DEBT-0033` was narrowed again.
|
||||||
|
`src/app_layout_tools_menu.cpp` no longer owns the retained Tools > Panels
|
||||||
|
submenu popup flow or panel-item wiring inline; that binding now lives in
|
||||||
|
`src/legacy_tools_menu_binding_services.*`, while retained Tools command
|
||||||
|
execution and options-menu preference wiring still remain in the app shell.
|
||||||
- 2026-06-17: `DEBT-0038` was narrowed again. The retained cloud upload and
|
- 2026-06-17: `DEBT-0038` was narrowed again. The retained cloud upload and
|
||||||
download background execution in `src/legacy_cloud_services.cpp` now routes
|
download background execution in `src/legacy_cloud_services.cpp` now routes
|
||||||
through `AppRuntime::canvas_async_task` instead of a file-static worker
|
through `AppRuntime::canvas_async_task` instead of a file-static worker
|
||||||
|
|||||||
@@ -83,6 +83,10 @@ Current conclusion:
|
|||||||
`src/legacy_document_open_services.*`, and retained cloud upload/download,
|
`src/legacy_document_open_services.*`, and retained cloud upload/download,
|
||||||
brush-package import, and timelapse-export async paths now use
|
brush-package import, and timelapse-export async paths now use
|
||||||
`AppRuntime::canvas_async_task` instead of file-static worker singletons.
|
`AppRuntime::canvas_async_task` instead of file-static worker singletons.
|
||||||
|
- Main-toolbar, File-menu, About-menu, and Tools > Panels binding ownership now
|
||||||
|
lives in dedicated `legacy_*_binding_services.*` helpers, so the
|
||||||
|
corresponding `app_layout_*` files are thinner adapters even though retained
|
||||||
|
execution still lives in the app shell.
|
||||||
- Platform extraction improved substantially and the root app source group no
|
- Platform extraction improved substantially and the root app source group no
|
||||||
longer compiles Web platform sources directly, but broader CMake and
|
longer compiles Web platform sources directly, but broader CMake and
|
||||||
entrypoint cleanup are not complete.
|
entrypoint cleanup are not complete.
|
||||||
|
|||||||
@@ -65,6 +65,25 @@ Key facts:
|
|||||||
- `App::dialog_browse()` no longer owns browse-dialog button wiring inline; the
|
- `App::dialog_browse()` no longer owns browse-dialog button wiring inline; the
|
||||||
retained document-open bridge now owns that handoff in
|
retained document-open bridge now owns that handoff in
|
||||||
`src/legacy_document_open_services.*`.
|
`src/legacy_document_open_services.*`.
|
||||||
|
- `App::init_toolbar_main()` now delegates retained main-toolbar button wiring
|
||||||
|
through `src/legacy_main_toolbar_binding_services.*`, so
|
||||||
|
`src/app_layout_main_toolbar.cpp` is down to a thin root lookup and adapter
|
||||||
|
call while retained toolbar execution still lives in
|
||||||
|
`src/legacy_app_shell_services.*`.
|
||||||
|
- `App::init_menu_file()` now delegates retained File-menu popup and export
|
||||||
|
submenu wiring through `src/legacy_file_menu_binding_services.*`, so
|
||||||
|
`src/app_layout_file_menu.cpp` is down to a thin trigger lookup and adapter
|
||||||
|
call while retained file/export execution still lives in
|
||||||
|
`src/legacy_app_shell_services.*`.
|
||||||
|
- `App::init_menu_about()` now delegates retained About-menu popup wiring
|
||||||
|
through `src/legacy_about_menu_binding_services.*`, so
|
||||||
|
`src/app_layout_about_layer_menu.cpp` no longer owns the About callback body
|
||||||
|
inline while retained About execution still lives in
|
||||||
|
`src/legacy_app_shell_services.*`.
|
||||||
|
- `App::init_menu_tools()` now delegates the retained Tools > Panels submenu
|
||||||
|
wiring through `src/legacy_tools_menu_binding_services.*`, so
|
||||||
|
`src/app_layout_tools_menu.cpp` no longer owns that floating-panel submenu
|
||||||
|
body inline while retained Tools execution and options wiring remain.
|
||||||
|
|
||||||
## Parallel Assignment Rules
|
## Parallel Assignment Rules
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
#include "app.h"
|
#include "app.h"
|
||||||
#include "app_core/about_menu.h"
|
|
||||||
#include "app_core/document_layer.h"
|
#include "app_core/document_layer.h"
|
||||||
#include "legacy_app_shell_services.h"
|
#include "legacy_about_menu_binding_services.h"
|
||||||
#include "legacy_document_layer_services.h"
|
#include "legacy_document_layer_services.h"
|
||||||
#include "legacy_ui_overlay_services.h"
|
#include "legacy_ui_overlay_services.h"
|
||||||
#include "node_button_custom.h"
|
#include "node_button_custom.h"
|
||||||
@@ -70,11 +69,6 @@ pp::app::DocumentLayerMenuPlan make_layer_menu_plan(
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void execute_about_menu_plan(App& app, const pp::app::AboutMenuPlan& plan)
|
|
||||||
{
|
|
||||||
pp::panopainter::execute_legacy_about_menu_plan(app, plan);
|
|
||||||
}
|
|
||||||
|
|
||||||
void execute_document_layer_menu_plan(App& app, const pp::app::DocumentLayerMenuPlan& plan)
|
void execute_document_layer_menu_plan(App& app, const pp::app::DocumentLayerMenuPlan& plan)
|
||||||
{
|
{
|
||||||
const auto status = pp::panopainter::execute_legacy_document_layer_menu_plan(app, plan);
|
const auto status = pp::panopainter::execute_legacy_document_layer_menu_plan(app, plan);
|
||||||
@@ -92,110 +86,18 @@ void bind_legacy_about_menu(App& app)
|
|||||||
|
|
||||||
if (auto* menu_file = main->find<NodeButtonCustom>("menu-about"))
|
if (auto* menu_file = main->find<NodeButtonCustom>("menu-about"))
|
||||||
{
|
{
|
||||||
menu_file->on_click = [&app, menu_file](Node*) {
|
auto* popup_root = app.layout[app.main_id];
|
||||||
auto* popup_root = app.layout[app.main_id];
|
if (!popup_root) {
|
||||||
if (!popup_root) {
|
return;
|
||||||
return;
|
}
|
||||||
}
|
pp::panopainter::bind_legacy_about_menu_popup(
|
||||||
glm::vec2 pos = menu_file->m_pos + glm::vec2(0, menu_file->m_size.y);
|
app,
|
||||||
auto popup = add_menu_popup(app, "about-menu", pos, menu_file->m_size.x);
|
*popup_root,
|
||||||
if (!popup)
|
*menu_file,
|
||||||
return;
|
g_version_major,
|
||||||
pp::panopainter::detach_legacy_node_from_parent(*popup);
|
g_version_minor,
|
||||||
auto popup_overlay = pp::panopainter::open_legacy_overlay_node_with_handle(*popup_root, popup);
|
g_version_fix,
|
||||||
if (!popup_overlay) {
|
app.canvas && app.canvas->m_canvas);
|
||||||
pp::panopainter::destroy_legacy_node(*popup);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
auto popup_handle = popup_overlay.value();
|
|
||||||
|
|
||||||
popup->find<NodeButtonCustom>("about-app")->on_click = [&app, popup_root, popup_handle](Node*) {
|
|
||||||
const auto plan = pp::app::plan_about_menu_command(
|
|
||||||
pp::app::AboutMenuCommand::about_app,
|
|
||||||
g_version_major,
|
|
||||||
g_version_minor,
|
|
||||||
g_version_fix);
|
|
||||||
execute_about_menu_plan(app, plan);
|
|
||||||
if (plan.closes_root_popup)
|
|
||||||
{
|
|
||||||
close_legacy_overlay_handle_ignoring_status(*popup_root, popup_handle);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
popup->find<NodeButtonCustom>("about-doc")->on_click = [&app, 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(
|
|
||||||
pp::app::AboutMenuCommand::help_guide,
|
|
||||||
g_version_major,
|
|
||||||
g_version_minor,
|
|
||||||
g_version_fix);
|
|
||||||
execute_about_menu_plan(app, plan);
|
|
||||||
if (plan.closes_root_popup)
|
|
||||||
{
|
|
||||||
close_legacy_overlay_handle_ignoring_status(*popup_root, popup_handle);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if (auto item = popup->find<NodeButtonCustom>("about-news"))
|
|
||||||
{
|
|
||||||
if (auto text = item->find<NodeText>("menu-label"))
|
|
||||||
{
|
|
||||||
const auto plan = pp::app::plan_about_menu_command(
|
|
||||||
pp::app::AboutMenuCommand::whats_new,
|
|
||||||
g_version_major,
|
|
||||||
g_version_minor,
|
|
||||||
g_version_fix);
|
|
||||||
text->set_text(plan.label.c_str());
|
|
||||||
}
|
|
||||||
item->on_click = [&app, popup_root, popup_handle](Node*) {
|
|
||||||
const auto plan = pp::app::plan_about_menu_command(
|
|
||||||
pp::app::AboutMenuCommand::whats_new,
|
|
||||||
g_version_major,
|
|
||||||
g_version_minor,
|
|
||||||
g_version_fix);
|
|
||||||
execute_about_menu_plan(app, plan);
|
|
||||||
if (plan.closes_root_popup)
|
|
||||||
{
|
|
||||||
close_legacy_overlay_handle_ignoring_status(*popup_root, popup_handle);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (auto b = popup->find<NodeButtonCustom>("about-crash"))
|
|
||||||
{
|
|
||||||
b->on_click = [&app, popup_root, popup_handle](Node*) {
|
|
||||||
const auto plan = pp::app::plan_about_menu_command(
|
|
||||||
pp::app::AboutMenuCommand::induce_crash,
|
|
||||||
g_version_major,
|
|
||||||
g_version_minor,
|
|
||||||
g_version_fix);
|
|
||||||
execute_about_menu_plan(app, plan);
|
|
||||||
if (plan.closes_root_popup)
|
|
||||||
{
|
|
||||||
close_legacy_overlay_handle_ignoring_status(*popup_root, popup_handle);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (auto b = popup->find<NodeButtonCustom>("about-perf"))
|
|
||||||
{
|
|
||||||
b->on_click = [&app, popup_root, popup_handle](Node*) {
|
|
||||||
const auto plan = pp::app::plan_about_menu_command(
|
|
||||||
pp::app::AboutMenuCommand::performance_test,
|
|
||||||
g_version_major,
|
|
||||||
g_version_minor,
|
|
||||||
g_version_fix,
|
|
||||||
true,
|
|
||||||
Canvas::I != nullptr);
|
|
||||||
execute_about_menu_plan(app, plan);
|
|
||||||
if (plan.closes_root_popup)
|
|
||||||
{
|
|
||||||
close_legacy_overlay_handle_ignoring_status(*popup_root, popup_handle);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,51 +1,7 @@
|
|||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
#include "app.h"
|
#include "app.h"
|
||||||
#include "app_core/document_export.h"
|
#include "legacy_file_menu_binding_services.h"
|
||||||
#include "app_core/file_menu.h"
|
|
||||||
#include "legacy_app_shell_services.h"
|
|
||||||
#include "legacy_ui_overlay_services.h"
|
|
||||||
#include "node_button_custom.h"
|
#include "node_button_custom.h"
|
||||||
#include "node_popup_menu.h"
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
void apply_document_export_menu_plan(App& app, pp::app::DocumentExportMenuKind kind)
|
|
||||||
{
|
|
||||||
(void)pp::panopainter::apply_legacy_document_export_menu_plan(app, kind);
|
|
||||||
}
|
|
||||||
|
|
||||||
void apply_file_menu_plan(App& app, pp::app::FileMenuCommand command)
|
|
||||||
{
|
|
||||||
pp::panopainter::apply_legacy_file_menu_command(app, command);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<NodePopupMenu> add_menu_popup(
|
|
||||||
App& app,
|
|
||||||
const char* template_id,
|
|
||||||
glm::vec2 position,
|
|
||||||
float rtl_anchor_width)
|
|
||||||
{
|
|
||||||
const auto popup = pp::panopainter::add_legacy_popup_menu(
|
|
||||||
app,
|
|
||||||
template_id,
|
|
||||||
position.x,
|
|
||||||
position.y,
|
|
||||||
rtl_anchor_width);
|
|
||||||
if (!popup) {
|
|
||||||
LOG("Popup menu '%s' failed: %s", template_id ? template_id : "<null>", popup.status().message);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
namespace pp::panopainter {
|
namespace pp::panopainter {
|
||||||
|
|
||||||
@@ -55,135 +11,7 @@ void bind_legacy_file_menu(App& app)
|
|||||||
|
|
||||||
if (auto* menu_file = main->find<NodeButtonCustom>("menu-file"))
|
if (auto* menu_file = main->find<NodeButtonCustom>("menu-file"))
|
||||||
{
|
{
|
||||||
menu_file->on_click = [&app, menu_file](Node*) {
|
bind_legacy_file_menu_popup(app, *menu_file, *main);
|
||||||
auto* popup_root = app.layout[app.main_id];
|
|
||||||
if (!popup_root) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const auto open_checked_menu_popup = [popup_root](App& app_ref, const char* id, glm::vec2 pos, float width)
|
|
||||||
-> std::pair<std::shared_ptr<NodePopupMenu>, pp::ui::NodeHandle>
|
|
||||||
{
|
|
||||||
auto popup = add_menu_popup(app_ref, 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);
|
|
||||||
const auto [popup, popup_handle] = open_checked_menu_popup(app, "file-menu", pos, menu_file->m_size.x);
|
|
||||||
if (!popup)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (auto b = popup->find<NodeButtonCustom>("file-newdoc"))
|
|
||||||
b->on_click = [&app, popup_root, popup_handle](Node*) {
|
|
||||||
apply_file_menu_plan(app, pp::app::FileMenuCommand::new_document);
|
|
||||||
close_legacy_overlay_handle_ignoring_status(*popup_root, popup_handle);
|
|
||||||
};
|
|
||||||
if (auto b = popup->find<NodeButtonCustom>("file-import"))
|
|
||||||
b->on_click = [&app, popup_root, popup_handle](Node*) {
|
|
||||||
apply_file_menu_plan(app, pp::app::FileMenuCommand::import_image);
|
|
||||||
close_legacy_overlay_handle_ignoring_status(*popup_root, popup_handle);
|
|
||||||
};
|
|
||||||
if (auto b = popup->find<NodeButtonCustom>("file-open"))
|
|
||||||
b->on_click = [&app, popup_root, popup_handle](Node*) {
|
|
||||||
apply_file_menu_plan(app, pp::app::FileMenuCommand::open_project);
|
|
||||||
close_legacy_overlay_handle_ignoring_status(*popup_root, popup_handle);
|
|
||||||
};
|
|
||||||
if (auto b = popup->find<NodeButtonCustom>("file-browse"))
|
|
||||||
b->on_click = [&app, popup_root, popup_handle](Node*) {
|
|
||||||
apply_file_menu_plan(app, pp::app::FileMenuCommand::browse_cloud);
|
|
||||||
close_legacy_overlay_handle_ignoring_status(*popup_root, popup_handle);
|
|
||||||
};
|
|
||||||
if (auto b = popup->find<NodeButtonCustom>("file-save"))
|
|
||||||
b->on_click = [&app, popup_root, popup_handle](Node*) {
|
|
||||||
apply_file_menu_plan(app, pp::app::FileMenuCommand::save);
|
|
||||||
close_legacy_overlay_handle_ignoring_status(*popup_root, popup_handle);
|
|
||||||
};
|
|
||||||
if (auto b = popup->find<NodeButtonCustom>("file-save-as"))
|
|
||||||
b->on_click = [&app, popup_root, popup_handle](Node*) {
|
|
||||||
apply_file_menu_plan(app, pp::app::FileMenuCommand::save_as);
|
|
||||||
close_legacy_overlay_handle_ignoring_status(*popup_root, popup_handle);
|
|
||||||
};
|
|
||||||
if (auto b = popup->find<NodeButtonCustom>("file-save-ver"))
|
|
||||||
b->on_click = [&app, popup_root, popup_handle](Node*) {
|
|
||||||
apply_file_menu_plan(app, pp::app::FileMenuCommand::save_version);
|
|
||||||
close_legacy_overlay_handle_ignoring_status(*popup_root, popup_handle);
|
|
||||||
};
|
|
||||||
if (auto b = popup->find<NodeButtonCustom>("file-export"))
|
|
||||||
b->on_click = [&app, popup_root, popup_handle](Node*) {
|
|
||||||
apply_file_menu_plan(app, pp::app::FileMenuCommand::export_jpeg);
|
|
||||||
close_legacy_overlay_handle_ignoring_status(*popup_root, popup_handle);
|
|
||||||
};
|
|
||||||
if (auto b = popup->find<NodeButtonCustom>("file-export-tick"))
|
|
||||||
b->on_click = [&app, b, popup_root, popup_handle, open_checked_menu_popup](Node*) {
|
|
||||||
glm::vec2 pos = b->m_pos + glm::vec2(b->m_size.x, 0);
|
|
||||||
const auto [subpopup, subpopup_handle] = open_checked_menu_popup(app, "file-submenu-export", pos, b->m_size.x);
|
|
||||||
if (!subpopup)
|
|
||||||
return;
|
|
||||||
subpopup->find<NodeButtonCustom>("file-submenu-export-png")->on_click = [&app, popup_root, popup_handle, subpopup_handle](Node*) {
|
|
||||||
apply_document_export_menu_plan(app, pp::app::DocumentExportMenuKind::png);
|
|
||||||
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 = [&app, popup_root, popup_handle, subpopup_handle](Node*) {
|
|
||||||
apply_document_export_menu_plan(app, pp::app::DocumentExportMenuKind::layers);
|
|
||||||
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 = [&app, popup_root, popup_handle, subpopup_handle](Node*) {
|
|
||||||
apply_document_export_menu_plan(app, pp::app::DocumentExportMenuKind::cube_faces);
|
|
||||||
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 = [&app, popup_root, popup_handle, subpopup_handle](Node*) {
|
|
||||||
apply_document_export_menu_plan(app, pp::app::DocumentExportMenuKind::depth);
|
|
||||||
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 = [&app, popup_root, popup_handle, subpopup_handle](Node*) {
|
|
||||||
apply_document_export_menu_plan(app, pp::app::DocumentExportMenuKind::animation_frames);
|
|
||||||
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 = [&app, popup_root, popup_handle, subpopup_handle](Node*) {
|
|
||||||
apply_document_export_menu_plan(app, pp::app::DocumentExportMenuKind::animation_mp4);
|
|
||||||
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 = [&app, popup_root, popup_handle, subpopup_handle](Node*) {
|
|
||||||
apply_document_export_menu_plan(app, pp::app::DocumentExportMenuKind::timelapse);
|
|
||||||
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 = [&app, popup_root, popup_handle](Node*) {
|
|
||||||
apply_file_menu_plan(app, pp::app::FileMenuCommand::share);
|
|
||||||
close_legacy_overlay_handle_ignoring_status(*popup_root, popup_handle);
|
|
||||||
};
|
|
||||||
if (auto b = popup->find<NodeButtonCustom>("file-resize"))
|
|
||||||
b->on_click = [&app, popup_root, popup_handle](Node*) {
|
|
||||||
apply_file_menu_plan(app, pp::app::FileMenuCommand::resize);
|
|
||||||
close_legacy_overlay_handle_ignoring_status(*popup_root, popup_handle);
|
|
||||||
};
|
|
||||||
if (auto b = popup->find<NodeButtonCustom>("file-cloud-upload"))
|
|
||||||
b->on_click = [&app, popup_root, popup_handle](Node*) {
|
|
||||||
apply_file_menu_plan(app, pp::app::FileMenuCommand::cloud_upload);
|
|
||||||
close_legacy_overlay_handle_ignoring_status(*popup_root, popup_handle);
|
|
||||||
};
|
|
||||||
if (auto b = popup->find<NodeButtonCustom>("file-cloud-browse"))
|
|
||||||
b->on_click = [&app, popup_root, popup_handle](Node*) {
|
|
||||||
apply_file_menu_plan(app, pp::app::FileMenuCommand::cloud_browse);
|
|
||||||
close_legacy_overlay_handle_ignoring_status(*popup_root, popup_handle);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,118 +1,12 @@
|
|||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
#include "app.h"
|
#include "app.h"
|
||||||
#include "app_core/main_toolbar.h"
|
#include "legacy_main_toolbar_binding_services.h"
|
||||||
#include "legacy_app_shell_services.h"
|
|
||||||
#include "legacy_history_services.h"
|
|
||||||
#include "node_button.h"
|
|
||||||
#include "node_button_custom.h"
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
void execute_main_toolbar_plan(App& app, const pp::app::MainToolbarPlan& plan)
|
|
||||||
{
|
|
||||||
pp::panopainter::execute_legacy_main_toolbar_plan(app, plan);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
namespace pp::panopainter {
|
namespace pp::panopainter {
|
||||||
|
|
||||||
void bind_legacy_main_toolbar(App& app)
|
void bind_legacy_main_toolbar(App& app)
|
||||||
{
|
{
|
||||||
if (auto* button = app.layout[app.main_id]->find<NodeButton>("btn-anim"))
|
pp::panopainter::bind_legacy_main_toolbar_buttons(app, *app.layout[app.main_id]);
|
||||||
{
|
|
||||||
button->on_click = [&app, button](Node*) {
|
|
||||||
if (app.canvas)
|
|
||||||
{
|
|
||||||
//app.canvas->m_canvas->export_anim();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
if (auto* button = app.layout[app.main_id]->find<NodeButton>("btn-open"))
|
|
||||||
{
|
|
||||||
button->on_click = [&app, button](Node*) {
|
|
||||||
const auto plan = pp::app::plan_main_toolbar_command(
|
|
||||||
pp::app::MainToolbarCommand::open_document);
|
|
||||||
if (plan)
|
|
||||||
execute_main_toolbar_plan(app, plan.value());
|
|
||||||
};
|
|
||||||
}
|
|
||||||
if (auto* button = app.layout[app.main_id]->find<NodeButton>("btn-save"))
|
|
||||||
{
|
|
||||||
button->on_click = [&app, button](Node*) {
|
|
||||||
const auto plan = pp::app::plan_main_toolbar_command(
|
|
||||||
pp::app::MainToolbarCommand::save_document);
|
|
||||||
if (plan)
|
|
||||||
execute_main_toolbar_plan(app, plan.value());
|
|
||||||
};
|
|
||||||
}
|
|
||||||
if (auto* button = app.layout[app.main_id]->find<NodeButtonCustom>("btn-undo"))
|
|
||||||
{
|
|
||||||
button->on_click = [&app, button](Node*) {
|
|
||||||
const auto history = pp::panopainter::legacy_history_snapshot();
|
|
||||||
const auto plan = pp::app::plan_main_toolbar_command(
|
|
||||||
pp::app::MainToolbarCommand::undo,
|
|
||||||
history.undo_count);
|
|
||||||
if (plan)
|
|
||||||
execute_main_toolbar_plan(app, plan.value());
|
|
||||||
};
|
|
||||||
}
|
|
||||||
if (auto* button = app.layout[app.main_id]->find<NodeButtonCustom>("btn-redo"))
|
|
||||||
{
|
|
||||||
button->on_click = [&app, button](Node*) {
|
|
||||||
const auto history = pp::panopainter::legacy_history_snapshot();
|
|
||||||
const auto plan = pp::app::plan_main_toolbar_command(
|
|
||||||
pp::app::MainToolbarCommand::redo,
|
|
||||||
0,
|
|
||||||
history.redo_count);
|
|
||||||
if (plan)
|
|
||||||
execute_main_toolbar_plan(app, plan.value());
|
|
||||||
};
|
|
||||||
}
|
|
||||||
if (auto* button = app.layout[app.main_id]->find<NodeButtonCustom>("btn-clean-memory"))
|
|
||||||
{
|
|
||||||
button->on_click = [&app](Node*) {
|
|
||||||
const auto history = pp::panopainter::legacy_history_snapshot();
|
|
||||||
const auto plan = pp::app::plan_main_toolbar_command(
|
|
||||||
pp::app::MainToolbarCommand::clear_history,
|
|
||||||
history.undo_count,
|
|
||||||
history.redo_count,
|
|
||||||
history.memory_bytes);
|
|
||||||
if (plan)
|
|
||||||
execute_main_toolbar_plan(app, plan.value());
|
|
||||||
};
|
|
||||||
}
|
|
||||||
if (auto* button = app.layout[app.main_id]->find<NodeButton>("btn-clear"))
|
|
||||||
{
|
|
||||||
button->on_click = [&app](Node*) {
|
|
||||||
const auto plan = pp::app::plan_main_toolbar_command(
|
|
||||||
pp::app::MainToolbarCommand::clear_canvas,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
static_cast<bool>(app.canvas));
|
|
||||||
if (plan)
|
|
||||||
execute_main_toolbar_plan(app, plan.value());
|
|
||||||
};
|
|
||||||
}
|
|
||||||
if (auto* button = app.layout[app.main_id]->find<NodeButton>("btn-popup"))
|
|
||||||
{
|
|
||||||
button->on_click = [&app](Node*) {
|
|
||||||
const auto plan = pp::app::plan_main_toolbar_command(
|
|
||||||
pp::app::MainToolbarCommand::show_message_box);
|
|
||||||
if (plan)
|
|
||||||
execute_main_toolbar_plan(app, plan.value());
|
|
||||||
};
|
|
||||||
}
|
|
||||||
if (auto* button = app.layout[app.main_id]->find<NodeButtonCustom>("btn-settings"))
|
|
||||||
{
|
|
||||||
button->on_click = [&app](Node*) {
|
|
||||||
const auto plan = pp::app::plan_main_toolbar_command(
|
|
||||||
pp::app::MainToolbarCommand::show_settings);
|
|
||||||
if (plan)
|
|
||||||
execute_main_toolbar_plan(app, plan.value());
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace pp::panopainter
|
} // namespace pp::panopainter
|
||||||
|
|||||||
@@ -1,53 +1,21 @@
|
|||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
#include "app.h"
|
#include "app.h"
|
||||||
#include "app_core/app_preferences.h"
|
#include "app_core/app_preferences.h"
|
||||||
#include "app_core/brush_ui.h"
|
|
||||||
#include "app_core/tools_menu.h"
|
#include "app_core/tools_menu.h"
|
||||||
#include "legacy_brush_ui_services.h"
|
|
||||||
#include "legacy_app_preference_services.h"
|
#include "legacy_app_preference_services.h"
|
||||||
#include "legacy_app_shell_services.h"
|
#include "legacy_app_shell_services.h"
|
||||||
#include "legacy_preference_storage.h"
|
#include "legacy_preference_storage.h"
|
||||||
|
#include "legacy_tools_menu_binding_services.h"
|
||||||
#include "legacy_ui_overlay_services.h"
|
#include "legacy_ui_overlay_services.h"
|
||||||
#include "node_button_custom.h"
|
#include "node_button_custom.h"
|
||||||
#include "node_checkbox.h"
|
#include "node_checkbox.h"
|
||||||
#include "node_combobox.h"
|
#include "node_combobox.h"
|
||||||
#include "node_dialog_picker.h"
|
|
||||||
#include "node_panel_animation.h"
|
|
||||||
#include "node_panel_brush.h"
|
|
||||||
#include "node_panel_color.h"
|
|
||||||
#include "node_panel_floating.h"
|
|
||||||
#include "node_panel_grid.h"
|
|
||||||
#include "node_panel_layer.h"
|
|
||||||
#include "node_panel_stroke.h"
|
|
||||||
#include "node_popup_menu.h"
|
#include "node_popup_menu.h"
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
[[nodiscard]] bool should_open_tools_panel(const pp::app::ToolsPanelPlan& plan) noexcept
|
|
||||||
{
|
|
||||||
return plan.action == pp::app::ToolsPanelAction::open_floating_panel;
|
|
||||||
}
|
|
||||||
|
|
||||||
void apply_tools_panel_chrome(NodePanelFloating& panel, const pp::app::ToolsPanelPlan& plan)
|
|
||||||
{
|
|
||||||
if (plan.width > 0 && plan.height > 0) {
|
|
||||||
panel.SetSize(static_cast<float>(plan.width), static_cast<float>(plan.height));
|
|
||||||
} else {
|
|
||||||
if (plan.width > 0)
|
|
||||||
panel.SetWidth(static_cast<float>(plan.width));
|
|
||||||
if (plan.height > 0)
|
|
||||||
panel.SetHeight(static_cast<float>(plan.height));
|
|
||||||
}
|
|
||||||
if (plan.min_width > 0)
|
|
||||||
panel.SetMinWidth(static_cast<float>(plan.min_width));
|
|
||||||
if (plan.min_height > 0)
|
|
||||||
panel.SetMinHeight(static_cast<float>(plan.min_height));
|
|
||||||
panel.m_title->set_text(plan.title.data());
|
|
||||||
panel.m_droppable = plan.droppable;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<NodePopupMenu> add_menu_popup(
|
std::shared_ptr<NodePopupMenu> add_menu_popup(
|
||||||
App& app,
|
App& app,
|
||||||
const char* template_id,
|
const char* template_id,
|
||||||
@@ -83,201 +51,13 @@ void bind_legacy_tools_menu(App& app)
|
|||||||
if (!popup_exp)
|
if (!popup_exp)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (auto tick = popup_exp->find<NodeButtonCustom>("tools-panels")) tick->on_click = [&app, popup_exp, main](Node* b)
|
if (auto tick = popup_exp->find<NodeButtonCustom>("tools-panels")) tick->on_click = [&app, popup_exp, main, tick](Node*)
|
||||||
{
|
{
|
||||||
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);
|
pp::panopainter::bind_legacy_tools_panels_submenu(app, *main, popup_exp, *tick);
|
||||||
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(app, "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 = [&app](Node* panel) {
|
|
||||||
if (!panel)
|
|
||||||
return false;
|
|
||||||
for (auto& c : app.floatings_container->m_children)
|
|
||||||
{
|
|
||||||
if (auto fp = std::static_pointer_cast<NodePanelFloating>(c))
|
|
||||||
{
|
|
||||||
if (fp->m_container->is_child(panel))
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
|
|
||||||
popup_time->find<NodeButtonCustom>("panel-presets")->on_click = [&app, close_panel_popups, visible](Node*) {
|
|
||||||
const auto plan = pp::app::plan_tools_panel(
|
|
||||||
pp::app::ToolsPanel::presets,
|
|
||||||
visible(app.floating_presets.get()));
|
|
||||||
if (!should_open_tools_panel(plan))
|
|
||||||
return;
|
|
||||||
auto fpanel = app.floatings_container->add_child<NodePanelFloating>();
|
|
||||||
fpanel->m_class = NodePanelFloating::kClass::Presets;
|
|
||||||
apply_tools_panel_chrome(*fpanel, plan);
|
|
||||||
if (!app.floating_presets)
|
|
||||||
{
|
|
||||||
app.floating_presets = fpanel->m_container->add_child_ref<NodePanelBrushPreset>();
|
|
||||||
app.floating_presets->SetHeightP(100);
|
|
||||||
app.floating_presets->on_brush_changed = [&app](Node*, std::shared_ptr<Brush>& b) {
|
|
||||||
(void)pp::panopainter::apply_legacy_brush_preset_plan(app, b);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
fpanel->m_container->add_child(app.floating_presets);
|
|
||||||
}
|
|
||||||
close_panel_popups();
|
|
||||||
};
|
|
||||||
|
|
||||||
popup_time->find<NodeButtonCustom>("panel-color")->on_click = [&app, close_panel_popups, visible](Node*) {
|
|
||||||
const auto plan = pp::app::plan_tools_panel(
|
|
||||||
pp::app::ToolsPanel::color,
|
|
||||||
visible(app.floating_color.get()));
|
|
||||||
if (!should_open_tools_panel(plan))
|
|
||||||
return;
|
|
||||||
auto fpanel = app.floatings_container->add_child<NodePanelFloating>();
|
|
||||||
fpanel->m_class = NodePanelFloating::kClass::Color;
|
|
||||||
apply_tools_panel_chrome(*fpanel, plan);
|
|
||||||
if (!app.floating_color)
|
|
||||||
{
|
|
||||||
app.floating_color = fpanel->m_container->add_child_ref<NodePanelColor>();
|
|
||||||
app.floating_color->SetHeightP(100);
|
|
||||||
if (plan.hides_embedded_title)
|
|
||||||
app.floating_color->find("title")->SetVisibility(false);
|
|
||||||
app.floating_color->on_color_changed = [&app](Node*, glm::vec4 color) {
|
|
||||||
(void)pp::panopainter::apply_legacy_brush_color_plan(app, color, false, false);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
fpanel->m_container->add_child(app.floating_color);
|
|
||||||
}
|
|
||||||
close_panel_popups();
|
|
||||||
};
|
|
||||||
popup_time->find<NodeButtonCustom>("panel-color-adv")->on_click = [&app, close_panel_popups, visible](Node*) {
|
|
||||||
const auto plan = pp::app::plan_tools_panel(
|
|
||||||
pp::app::ToolsPanel::color_advanced,
|
|
||||||
visible(app.floating_picker.get()));
|
|
||||||
if (!should_open_tools_panel(plan))
|
|
||||||
return;
|
|
||||||
auto fpanel = app.floatings_container->add_child<NodePanelFloating>();
|
|
||||||
fpanel->m_class = NodePanelFloating::kClass::ColorAdv;
|
|
||||||
apply_tools_panel_chrome(*fpanel, plan);
|
|
||||||
if (!app.floating_picker)
|
|
||||||
{
|
|
||||||
app.floating_picker = fpanel->m_container->add_child_ref<NodeColorPicker>();
|
|
||||||
app.floating_picker->m_autohide = false;
|
|
||||||
app.floating_picker->on_color_change = [&app](Node*, glm::vec3 color) {
|
|
||||||
(void)pp::panopainter::apply_legacy_brush_color_plan(app, glm::vec4(color, 1.f), false, false);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
fpanel->m_container->add_child(app.floating_picker);
|
|
||||||
}
|
|
||||||
close_panel_popups();
|
|
||||||
};
|
|
||||||
popup_time->find<NodeButtonCustom>("panel-layers")->on_click = [&app, close_panel_popups, visible](Node*) {
|
|
||||||
const auto plan = pp::app::plan_tools_panel(
|
|
||||||
pp::app::ToolsPanel::layers,
|
|
||||||
visible(app.layers.get()));
|
|
||||||
if (!should_open_tools_panel(plan))
|
|
||||||
return;
|
|
||||||
auto fpanel = app.floatings_container->add_child<NodePanelFloating>();
|
|
||||||
fpanel->m_class = NodePanelFloating::kClass::Layers;
|
|
||||||
apply_tools_panel_chrome(*fpanel, plan);
|
|
||||||
fpanel->m_container->add_child(app.layers);
|
|
||||||
app.layers->SetPositioning(YGPositionTypeRelative);
|
|
||||||
app.layers->SetPosition(0, 0);
|
|
||||||
app.layers->SetWidthP(100);
|
|
||||||
app.layers->SetHeightP(100);
|
|
||||||
app.layers->SetFlexShrink(0);
|
|
||||||
if (plan.hides_embedded_title)
|
|
||||||
app.layers->find("title")->SetVisibility(false);
|
|
||||||
|
|
||||||
close_panel_popups();
|
|
||||||
};
|
|
||||||
popup_time->find<NodeButtonCustom>("panel-brush")->on_click = [&app, close_panel_popups, visible](Node*) {
|
|
||||||
const auto plan = pp::app::plan_tools_panel(
|
|
||||||
pp::app::ToolsPanel::brush,
|
|
||||||
visible(app.stroke.get()));
|
|
||||||
if (!should_open_tools_panel(plan))
|
|
||||||
return;
|
|
||||||
auto fpanel = app.floatings_container->add_child<NodePanelFloating>();
|
|
||||||
fpanel->m_class = NodePanelFloating::kClass::Brush;
|
|
||||||
fpanel->m_container->add_child(app.stroke);
|
|
||||||
apply_tools_panel_chrome(*fpanel, plan);
|
|
||||||
app.stroke->SetPositioning(YGPositionTypeRelative);
|
|
||||||
app.stroke->SetPosition(0, 0);
|
|
||||||
app.stroke->SetWidthP(100);
|
|
||||||
app.stroke->SetHeightP(100);
|
|
||||||
if (plan.hides_embedded_title)
|
|
||||||
app.stroke->find("title")->SetVisibility(false);
|
|
||||||
|
|
||||||
close_panel_popups();
|
|
||||||
};
|
|
||||||
popup_time->find<NodeButtonCustom>("panel-grids")->on_click = [&app, close_panel_popups, visible](Node*) {
|
|
||||||
const auto plan = pp::app::plan_tools_panel(
|
|
||||||
pp::app::ToolsPanel::grids,
|
|
||||||
visible(app.grid.get()));
|
|
||||||
if (!should_open_tools_panel(plan))
|
|
||||||
return;
|
|
||||||
auto fpanel = app.floatings_container->add_child<NodePanelFloating>();
|
|
||||||
fpanel->m_class = NodePanelFloating::kClass::Grids;
|
|
||||||
fpanel->m_container->add_child(app.grid);
|
|
||||||
apply_tools_panel_chrome(*fpanel, plan);
|
|
||||||
app.grid->SetPositioning(YGPositionTypeRelative);
|
|
||||||
app.grid->SetPosition(0, 0);
|
|
||||||
app.grid->SetWidthP(100);
|
|
||||||
app.grid->SetHeightP(100);
|
|
||||||
if (plan.hides_embedded_title)
|
|
||||||
app.grid->find("title")->SetVisibility(false);
|
|
||||||
|
|
||||||
close_panel_popups();
|
|
||||||
};
|
|
||||||
popup_time->find<NodeButtonCustom>("panel-animation")->on_click = [&app, close_panel_popups, visible](Node*) {
|
|
||||||
const auto plan = pp::app::plan_tools_panel(
|
|
||||||
pp::app::ToolsPanel::animation,
|
|
||||||
visible(app.animation.get()));
|
|
||||||
if (!should_open_tools_panel(plan))
|
|
||||||
return;
|
|
||||||
auto fpanel = app.floatings_container->add_child<NodePanelFloating>();
|
|
||||||
fpanel->m_class = NodePanelFloating::kClass::Animation;
|
|
||||||
fpanel->m_container->add_child(app.animation);
|
|
||||||
apply_tools_panel_chrome(*fpanel, plan);
|
|
||||||
app.animation->SetPositioning(YGPositionTypeRelative);
|
|
||||||
app.animation->SetPosition(0, 0);
|
|
||||||
app.animation->SetWidthP(100);
|
|
||||||
app.animation->SetHeightP(100);
|
|
||||||
|
|
||||||
close_panel_popups();
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if (auto options = popup_exp->find<NodeButtonCustom>("tools-options")) options->on_click = [&app, options, main](Node* b)
|
if (auto options = popup_exp->find<NodeButtonCustom>("tools-options")) options->on_click = [&app, options, main](Node* b)
|
||||||
|
|||||||
166
src/legacy_about_menu_binding_services.cpp
Normal file
166
src/legacy_about_menu_binding_services.cpp
Normal file
@@ -0,0 +1,166 @@
|
|||||||
|
#include "pch.h"
|
||||||
|
|
||||||
|
#include "legacy_about_menu_binding_services.h"
|
||||||
|
|
||||||
|
#include "app.h"
|
||||||
|
#include "legacy_app_shell_services.h"
|
||||||
|
#include "legacy_ui_overlay_services.h"
|
||||||
|
#include "node_button_custom.h"
|
||||||
|
#include "node_popup_menu.h"
|
||||||
|
#include "node_text.h"
|
||||||
|
|
||||||
|
namespace pp::panopainter {
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
std::shared_ptr<NodePopupMenu> add_menu_popup(
|
||||||
|
App& app,
|
||||||
|
const char* template_id,
|
||||||
|
glm::vec2 position,
|
||||||
|
float rtl_anchor_width)
|
||||||
|
{
|
||||||
|
const auto popup = pp::panopainter::add_legacy_popup_menu(
|
||||||
|
app,
|
||||||
|
template_id,
|
||||||
|
position.x,
|
||||||
|
position.y,
|
||||||
|
rtl_anchor_width);
|
||||||
|
if (!popup) {
|
||||||
|
LOG("Popup menu '%s' failed: %s", template_id ? template_id : "<null>", popup.status().message);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
void bind_about_menu_action(
|
||||||
|
App& app,
|
||||||
|
Node& popup_root,
|
||||||
|
pp::ui::NodeHandle popup_handle,
|
||||||
|
NodeButtonCustom& button,
|
||||||
|
pp::app::AboutMenuCommand command,
|
||||||
|
int version_major,
|
||||||
|
int version_minor,
|
||||||
|
int version_fix,
|
||||||
|
bool has_canvas) noexcept
|
||||||
|
{
|
||||||
|
button.on_click = [&app, &popup_root, popup_handle, command, version_major, version_minor, version_fix, has_canvas](Node*) {
|
||||||
|
const auto plan = pp::app::plan_about_menu_command(
|
||||||
|
command,
|
||||||
|
version_major,
|
||||||
|
version_minor,
|
||||||
|
version_fix,
|
||||||
|
true,
|
||||||
|
has_canvas);
|
||||||
|
execute_legacy_about_menu_plan(app, plan);
|
||||||
|
if (plan.closes_root_popup) {
|
||||||
|
close_legacy_overlay_handle_ignoring_status(popup_root, popup_handle);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
void bind_legacy_about_menu_popup(
|
||||||
|
App& app,
|
||||||
|
Node& popup_root,
|
||||||
|
NodeButtonCustom& trigger_button,
|
||||||
|
int version_major,
|
||||||
|
int version_minor,
|
||||||
|
int version_fix,
|
||||||
|
bool has_canvas) noexcept
|
||||||
|
{
|
||||||
|
trigger_button.on_click = [&app, &popup_root, &trigger_button, version_major, version_minor, version_fix, has_canvas](Node*) {
|
||||||
|
const glm::vec2 pos = trigger_button.m_pos + glm::vec2(0, trigger_button.m_size.y);
|
||||||
|
auto popup = add_menu_popup(app, "about-menu", pos, trigger_button.m_size.x);
|
||||||
|
if (!popup) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto popup_handle = popup_overlay.value();
|
||||||
|
|
||||||
|
bind_about_menu_action(
|
||||||
|
app,
|
||||||
|
popup_root,
|
||||||
|
popup_handle,
|
||||||
|
*popup->find<NodeButtonCustom>("about-app"),
|
||||||
|
pp::app::AboutMenuCommand::about_app,
|
||||||
|
version_major,
|
||||||
|
version_minor,
|
||||||
|
version_fix,
|
||||||
|
has_canvas);
|
||||||
|
|
||||||
|
bind_about_menu_action(
|
||||||
|
app,
|
||||||
|
popup_root,
|
||||||
|
popup_handle,
|
||||||
|
*popup->find<NodeButtonCustom>("about-doc"),
|
||||||
|
pp::app::AboutMenuCommand::help_guide,
|
||||||
|
version_major,
|
||||||
|
version_minor,
|
||||||
|
version_fix,
|
||||||
|
has_canvas);
|
||||||
|
|
||||||
|
if (auto item = popup->find<NodeButtonCustom>("about-news")) {
|
||||||
|
if (auto text = item->find<NodeText>("menu-label")) {
|
||||||
|
const auto plan = pp::app::plan_about_menu_command(
|
||||||
|
pp::app::AboutMenuCommand::whats_new,
|
||||||
|
version_major,
|
||||||
|
version_minor,
|
||||||
|
version_fix);
|
||||||
|
text->set_text(plan.label.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
bind_about_menu_action(
|
||||||
|
app,
|
||||||
|
popup_root,
|
||||||
|
popup_handle,
|
||||||
|
*item,
|
||||||
|
pp::app::AboutMenuCommand::whats_new,
|
||||||
|
version_major,
|
||||||
|
version_minor,
|
||||||
|
version_fix,
|
||||||
|
has_canvas);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (auto b = popup->find<NodeButtonCustom>("about-crash")) {
|
||||||
|
bind_about_menu_action(
|
||||||
|
app,
|
||||||
|
popup_root,
|
||||||
|
popup_handle,
|
||||||
|
*b,
|
||||||
|
pp::app::AboutMenuCommand::induce_crash,
|
||||||
|
version_major,
|
||||||
|
version_minor,
|
||||||
|
version_fix,
|
||||||
|
has_canvas);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (auto b = popup->find<NodeButtonCustom>("about-perf")) {
|
||||||
|
bind_about_menu_action(
|
||||||
|
app,
|
||||||
|
popup_root,
|
||||||
|
popup_handle,
|
||||||
|
*b,
|
||||||
|
pp::app::AboutMenuCommand::performance_test,
|
||||||
|
version_major,
|
||||||
|
version_minor,
|
||||||
|
version_fix,
|
||||||
|
has_canvas);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace pp::panopainter
|
||||||
20
src/legacy_about_menu_binding_services.h
Normal file
20
src/legacy_about_menu_binding_services.h
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "app_core/about_menu.h"
|
||||||
|
|
||||||
|
class App;
|
||||||
|
class Node;
|
||||||
|
class NodeButtonCustom;
|
||||||
|
|
||||||
|
namespace pp::panopainter {
|
||||||
|
|
||||||
|
void bind_legacy_about_menu_popup(
|
||||||
|
App& app,
|
||||||
|
Node& popup_root,
|
||||||
|
NodeButtonCustom& trigger_button,
|
||||||
|
int version_major,
|
||||||
|
int version_minor,
|
||||||
|
int version_fix,
|
||||||
|
bool has_canvas) noexcept;
|
||||||
|
|
||||||
|
} // namespace pp::panopainter
|
||||||
286
src/legacy_file_menu_binding_services.cpp
Normal file
286
src/legacy_file_menu_binding_services.cpp
Normal file
@@ -0,0 +1,286 @@
|
|||||||
|
#include "pch.h"
|
||||||
|
|
||||||
|
#include "legacy_file_menu_binding_services.h"
|
||||||
|
|
||||||
|
#include "app.h"
|
||||||
|
#include "app_core/document_export.h"
|
||||||
|
#include "app_core/file_menu.h"
|
||||||
|
#include "legacy_app_shell_services.h"
|
||||||
|
#include "legacy_ui_overlay_services.h"
|
||||||
|
#include "node_button_custom.h"
|
||||||
|
#include "node_popup_menu.h"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
std::shared_ptr<NodePopupMenu> add_menu_popup(
|
||||||
|
App& app,
|
||||||
|
const char* template_id,
|
||||||
|
glm::vec2 position,
|
||||||
|
float rtl_anchor_width)
|
||||||
|
{
|
||||||
|
const auto popup = pp::panopainter::add_legacy_popup_menu(
|
||||||
|
app,
|
||||||
|
template_id,
|
||||||
|
position.x,
|
||||||
|
position.y,
|
||||||
|
rtl_anchor_width);
|
||||||
|
if (!popup) {
|
||||||
|
LOG("Popup menu '%s' failed: %s", template_id ? template_id : "<null>", popup.status().message);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
namespace pp::panopainter {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
class LegacyFileMenuBindingServices final {
|
||||||
|
public:
|
||||||
|
LegacyFileMenuBindingServices(App& app, Node& popup_root) noexcept
|
||||||
|
: app_(app)
|
||||||
|
, popup_root_(popup_root)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void bind_menu_button(NodeButtonCustom& menu_file)
|
||||||
|
{
|
||||||
|
menu_file.on_click = [this, &menu_file](Node*) {
|
||||||
|
open_file_menu_popup(menu_file);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void open_file_menu_popup(NodeButtonCustom& menu_file)
|
||||||
|
{
|
||||||
|
const glm::vec2 pos = menu_file.m_pos + glm::vec2(0, menu_file.m_size.y);
|
||||||
|
const auto popup = add_menu_popup(app_, "file-menu", pos, menu_file.m_size.x);
|
||||||
|
if (!popup) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
pp::panopainter::detach_legacy_node_from_parent(*popup);
|
||||||
|
const auto popup_overlay = pp::panopainter::open_legacy_overlay_node_with_handle(popup_root_, popup);
|
||||||
|
if (!popup_overlay) {
|
||||||
|
pp::panopainter::destroy_legacy_node(*popup);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bind_popup_wiring(*popup, popup_overlay.value());
|
||||||
|
}
|
||||||
|
|
||||||
|
void bind_popup_wiring(
|
||||||
|
NodePopupMenu& popup,
|
||||||
|
pp::ui::NodeHandle popup_handle)
|
||||||
|
{
|
||||||
|
if (auto* b = popup.find<NodeButtonCustom>("file-newdoc")) {
|
||||||
|
b->on_click = [this, popup_handle](Node*) {
|
||||||
|
apply_file_menu_command(pp::app::FileMenuCommand::new_document);
|
||||||
|
close_popup(popup_handle);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (auto* b = popup.find<NodeButtonCustom>("file-import")) {
|
||||||
|
b->on_click = [this, popup_handle](Node*) {
|
||||||
|
apply_file_menu_command(pp::app::FileMenuCommand::import_image);
|
||||||
|
close_popup(popup_handle);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (auto* b = popup.find<NodeButtonCustom>("file-open")) {
|
||||||
|
b->on_click = [this, popup_handle](Node*) {
|
||||||
|
apply_file_menu_command(pp::app::FileMenuCommand::open_project);
|
||||||
|
close_popup(popup_handle);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (auto* b = popup.find<NodeButtonCustom>("file-browse")) {
|
||||||
|
b->on_click = [this, popup_handle](Node*) {
|
||||||
|
apply_file_menu_command(pp::app::FileMenuCommand::browse_cloud);
|
||||||
|
close_popup(popup_handle);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (auto* b = popup.find<NodeButtonCustom>("file-save")) {
|
||||||
|
b->on_click = [this, popup_handle](Node*) {
|
||||||
|
apply_file_menu_command(pp::app::FileMenuCommand::save);
|
||||||
|
close_popup(popup_handle);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (auto* b = popup.find<NodeButtonCustom>("file-save-as")) {
|
||||||
|
b->on_click = [this, popup_handle](Node*) {
|
||||||
|
apply_file_menu_command(pp::app::FileMenuCommand::save_as);
|
||||||
|
close_popup(popup_handle);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (auto* b = popup.find<NodeButtonCustom>("file-save-ver")) {
|
||||||
|
b->on_click = [this, popup_handle](Node*) {
|
||||||
|
apply_file_menu_command(pp::app::FileMenuCommand::save_version);
|
||||||
|
close_popup(popup_handle);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (auto* b = popup.find<NodeButtonCustom>("file-export")) {
|
||||||
|
b->on_click = [this, popup_handle](Node*) {
|
||||||
|
apply_file_menu_command(pp::app::FileMenuCommand::export_jpeg);
|
||||||
|
close_popup(popup_handle);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (auto* b = popup.find<NodeButtonCustom>("file-export-tick")) {
|
||||||
|
b->on_click = [this, b, popup_handle](Node*) {
|
||||||
|
open_export_submenu(*b, popup_handle);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (auto* b = popup.find<NodeButtonCustom>("file-share")) {
|
||||||
|
b->on_click = [this, popup_handle](Node*) {
|
||||||
|
apply_file_menu_command(pp::app::FileMenuCommand::share);
|
||||||
|
close_popup(popup_handle);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (auto* b = popup.find<NodeButtonCustom>("file-resize")) {
|
||||||
|
b->on_click = [this, popup_handle](Node*) {
|
||||||
|
apply_file_menu_command(pp::app::FileMenuCommand::resize);
|
||||||
|
close_popup(popup_handle);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (auto* b = popup.find<NodeButtonCustom>("file-cloud-upload")) {
|
||||||
|
b->on_click = [this, popup_handle](Node*) {
|
||||||
|
apply_file_menu_command(pp::app::FileMenuCommand::cloud_upload);
|
||||||
|
close_popup(popup_handle);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (auto* b = popup.find<NodeButtonCustom>("file-cloud-browse")) {
|
||||||
|
b->on_click = [this, popup_handle](Node*) {
|
||||||
|
apply_file_menu_command(pp::app::FileMenuCommand::cloud_browse);
|
||||||
|
close_popup(popup_handle);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void open_export_submenu(
|
||||||
|
NodeButtonCustom& export_button,
|
||||||
|
pp::ui::NodeHandle popup_handle)
|
||||||
|
{
|
||||||
|
const glm::vec2 pos = export_button.m_pos + glm::vec2(export_button.m_size.x, 0);
|
||||||
|
const auto subpopup = add_menu_popup(
|
||||||
|
app_,
|
||||||
|
"file-submenu-export",
|
||||||
|
pos,
|
||||||
|
export_button.m_size.x);
|
||||||
|
if (!subpopup) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
pp::panopainter::detach_legacy_node_from_parent(*subpopup);
|
||||||
|
const auto subpopup_overlay = pp::panopainter::open_legacy_overlay_node_with_handle(popup_root_, subpopup);
|
||||||
|
if (!subpopup_overlay) {
|
||||||
|
pp::panopainter::destroy_legacy_node(*subpopup);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bind_export_submenu_wiring(
|
||||||
|
*subpopup,
|
||||||
|
popup_handle,
|
||||||
|
subpopup_overlay.value());
|
||||||
|
}
|
||||||
|
|
||||||
|
void bind_export_submenu_wiring(
|
||||||
|
NodePopupMenu& subpopup,
|
||||||
|
pp::ui::NodeHandle popup_handle,
|
||||||
|
pp::ui::NodeHandle subpopup_handle)
|
||||||
|
{
|
||||||
|
bind_export_submenu_button(
|
||||||
|
subpopup,
|
||||||
|
"file-submenu-export-png",
|
||||||
|
pp::app::DocumentExportMenuKind::png,
|
||||||
|
popup_handle,
|
||||||
|
subpopup_handle);
|
||||||
|
bind_export_submenu_button(
|
||||||
|
subpopup,
|
||||||
|
"file-submenu-export-layers",
|
||||||
|
pp::app::DocumentExportMenuKind::layers,
|
||||||
|
popup_handle,
|
||||||
|
subpopup_handle);
|
||||||
|
bind_export_submenu_button(
|
||||||
|
subpopup,
|
||||||
|
"file-submenu-export-cube",
|
||||||
|
pp::app::DocumentExportMenuKind::cube_faces,
|
||||||
|
popup_handle,
|
||||||
|
subpopup_handle);
|
||||||
|
bind_export_submenu_button(
|
||||||
|
subpopup,
|
||||||
|
"file-submenu-export-depth",
|
||||||
|
pp::app::DocumentExportMenuKind::depth,
|
||||||
|
popup_handle,
|
||||||
|
subpopup_handle);
|
||||||
|
bind_export_submenu_button(
|
||||||
|
subpopup,
|
||||||
|
"file-submenu-export-anim",
|
||||||
|
pp::app::DocumentExportMenuKind::animation_frames,
|
||||||
|
popup_handle,
|
||||||
|
subpopup_handle);
|
||||||
|
bind_export_submenu_button(
|
||||||
|
subpopup,
|
||||||
|
"file-submenu-export-anim-mp4",
|
||||||
|
pp::app::DocumentExportMenuKind::animation_mp4,
|
||||||
|
popup_handle,
|
||||||
|
subpopup_handle);
|
||||||
|
bind_export_submenu_button(
|
||||||
|
subpopup,
|
||||||
|
"file-submenu-export-timelapse",
|
||||||
|
pp::app::DocumentExportMenuKind::timelapse,
|
||||||
|
popup_handle,
|
||||||
|
subpopup_handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
void bind_export_submenu_button(
|
||||||
|
NodePopupMenu& subpopup,
|
||||||
|
const char* button_id,
|
||||||
|
pp::app::DocumentExportMenuKind kind,
|
||||||
|
pp::ui::NodeHandle popup_handle,
|
||||||
|
pp::ui::NodeHandle subpopup_handle)
|
||||||
|
{
|
||||||
|
if (auto* b = subpopup.find<NodeButtonCustom>(button_id)) {
|
||||||
|
b->on_click = [this, kind, popup_handle, subpopup_handle](Node*) {
|
||||||
|
apply_document_export_menu(kind);
|
||||||
|
close_popup(popup_handle);
|
||||||
|
close_popup(subpopup_handle);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void apply_file_menu_command(pp::app::FileMenuCommand command)
|
||||||
|
{
|
||||||
|
pp::panopainter::apply_legacy_file_menu_command(app_, command);
|
||||||
|
}
|
||||||
|
|
||||||
|
void apply_document_export_menu(pp::app::DocumentExportMenuKind kind)
|
||||||
|
{
|
||||||
|
(void)pp::panopainter::apply_legacy_document_export_menu_plan(app_, kind);
|
||||||
|
}
|
||||||
|
|
||||||
|
void close_popup(pp::ui::NodeHandle overlay) noexcept
|
||||||
|
{
|
||||||
|
close_legacy_overlay_handle_ignoring_status(popup_root_, overlay);
|
||||||
|
}
|
||||||
|
|
||||||
|
App& app_;
|
||||||
|
Node& popup_root_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
void bind_legacy_file_menu_popup(
|
||||||
|
App& app,
|
||||||
|
NodeButtonCustom& menu_file,
|
||||||
|
Node& popup_root)
|
||||||
|
{
|
||||||
|
LegacyFileMenuBindingServices services(app, popup_root);
|
||||||
|
services.bind_menu_button(menu_file);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace pp::panopainter
|
||||||
14
src/legacy_file_menu_binding_services.h
Normal file
14
src/legacy_file_menu_binding_services.h
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
class App;
|
||||||
|
class Node;
|
||||||
|
class NodeButtonCustom;
|
||||||
|
|
||||||
|
namespace pp::panopainter {
|
||||||
|
|
||||||
|
void bind_legacy_file_menu_popup(
|
||||||
|
App& app,
|
||||||
|
NodeButtonCustom& menu_file,
|
||||||
|
Node& popup_root);
|
||||||
|
|
||||||
|
} // namespace pp::panopainter
|
||||||
112
src/legacy_main_toolbar_binding_services.cpp
Normal file
112
src/legacy_main_toolbar_binding_services.cpp
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
#include "pch.h"
|
||||||
|
|
||||||
|
#include "legacy_main_toolbar_binding_services.h"
|
||||||
|
|
||||||
|
#include "app.h"
|
||||||
|
#include "app_core/main_toolbar.h"
|
||||||
|
#include "legacy_app_shell_services.h"
|
||||||
|
#include "legacy_history_services.h"
|
||||||
|
#include "node_button.h"
|
||||||
|
#include "node_button_custom.h"
|
||||||
|
|
||||||
|
namespace pp::panopainter {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
template <class ButtonT, class Handler>
|
||||||
|
void bind_legacy_main_toolbar_click(Node& toolbar_root, const char* button_id, Handler&& handler)
|
||||||
|
{
|
||||||
|
if (auto* button = toolbar_root.find<ButtonT>(button_id)) {
|
||||||
|
button->on_click = std::forward<Handler>(handler);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void execute_main_toolbar_plan(App& app, const pp::app::MainToolbarPlan& plan)
|
||||||
|
{
|
||||||
|
pp::panopainter::execute_legacy_main_toolbar_plan(app, plan);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
void bind_legacy_main_toolbar_buttons(App& app, Node& toolbar_root)
|
||||||
|
{
|
||||||
|
bind_legacy_main_toolbar_click<NodeButton>(toolbar_root, "btn-anim", [&app](Node*) {
|
||||||
|
if (app.canvas) {
|
||||||
|
//app.canvas->m_canvas->export_anim();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
bind_legacy_main_toolbar_click<NodeButton>(toolbar_root, "btn-open", [&app](Node*) {
|
||||||
|
const auto plan = pp::app::plan_main_toolbar_command(
|
||||||
|
pp::app::MainToolbarCommand::open_document);
|
||||||
|
if (plan)
|
||||||
|
execute_main_toolbar_plan(app, plan.value());
|
||||||
|
});
|
||||||
|
|
||||||
|
bind_legacy_main_toolbar_click<NodeButton>(toolbar_root, "btn-save", [&app](Node*) {
|
||||||
|
const auto plan = pp::app::plan_main_toolbar_command(
|
||||||
|
pp::app::MainToolbarCommand::save_document);
|
||||||
|
if (plan)
|
||||||
|
execute_main_toolbar_plan(app, plan.value());
|
||||||
|
});
|
||||||
|
|
||||||
|
bind_legacy_main_toolbar_click<NodeButtonCustom>(toolbar_root, "btn-undo", [&app](Node*) {
|
||||||
|
const auto history = pp::panopainter::legacy_history_snapshot();
|
||||||
|
const auto plan = pp::app::plan_main_toolbar_command(
|
||||||
|
pp::app::MainToolbarCommand::undo,
|
||||||
|
history.undo_count);
|
||||||
|
if (plan)
|
||||||
|
execute_main_toolbar_plan(app, plan.value());
|
||||||
|
});
|
||||||
|
|
||||||
|
bind_legacy_main_toolbar_click<NodeButtonCustom>(toolbar_root, "btn-redo", [&app](Node*) {
|
||||||
|
const auto history = pp::panopainter::legacy_history_snapshot();
|
||||||
|
const auto plan = pp::app::plan_main_toolbar_command(
|
||||||
|
pp::app::MainToolbarCommand::redo,
|
||||||
|
0,
|
||||||
|
history.redo_count);
|
||||||
|
if (plan)
|
||||||
|
execute_main_toolbar_plan(app, plan.value());
|
||||||
|
});
|
||||||
|
|
||||||
|
bind_legacy_main_toolbar_click<NodeButtonCustom>(
|
||||||
|
toolbar_root,
|
||||||
|
"btn-clean-memory",
|
||||||
|
[&app](Node*) {
|
||||||
|
const auto history = pp::panopainter::legacy_history_snapshot();
|
||||||
|
const auto plan = pp::app::plan_main_toolbar_command(
|
||||||
|
pp::app::MainToolbarCommand::clear_history,
|
||||||
|
history.undo_count,
|
||||||
|
history.redo_count,
|
||||||
|
history.memory_bytes);
|
||||||
|
if (plan)
|
||||||
|
execute_main_toolbar_plan(app, plan.value());
|
||||||
|
});
|
||||||
|
|
||||||
|
bind_legacy_main_toolbar_click<NodeButton>(toolbar_root, "btn-clear", [&app](Node*) {
|
||||||
|
const auto plan = pp::app::plan_main_toolbar_command(
|
||||||
|
pp::app::MainToolbarCommand::clear_canvas,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
static_cast<bool>(app.canvas));
|
||||||
|
if (plan)
|
||||||
|
execute_main_toolbar_plan(app, plan.value());
|
||||||
|
});
|
||||||
|
|
||||||
|
bind_legacy_main_toolbar_click<NodeButton>(toolbar_root, "btn-popup", [&app](Node*) {
|
||||||
|
const auto plan = pp::app::plan_main_toolbar_command(
|
||||||
|
pp::app::MainToolbarCommand::show_message_box);
|
||||||
|
if (plan)
|
||||||
|
execute_main_toolbar_plan(app, plan.value());
|
||||||
|
});
|
||||||
|
|
||||||
|
bind_legacy_main_toolbar_click<NodeButtonCustom>(toolbar_root, "btn-settings", [&app](Node*) {
|
||||||
|
const auto plan = pp::app::plan_main_toolbar_command(
|
||||||
|
pp::app::MainToolbarCommand::show_settings);
|
||||||
|
if (plan)
|
||||||
|
execute_main_toolbar_plan(app, plan.value());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace pp::panopainter
|
||||||
10
src/legacy_main_toolbar_binding_services.h
Normal file
10
src/legacy_main_toolbar_binding_services.h
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
class App;
|
||||||
|
class Node;
|
||||||
|
|
||||||
|
namespace pp::panopainter {
|
||||||
|
|
||||||
|
void bind_legacy_main_toolbar_buttons(App& app, Node& toolbar_root);
|
||||||
|
|
||||||
|
} // namespace pp::panopainter
|
||||||
296
src/legacy_tools_menu_binding_services.cpp
Normal file
296
src/legacy_tools_menu_binding_services.cpp
Normal file
@@ -0,0 +1,296 @@
|
|||||||
|
#include "pch.h"
|
||||||
|
|
||||||
|
#include "legacy_tools_menu_binding_services.h"
|
||||||
|
|
||||||
|
#include "app.h"
|
||||||
|
#include "app_core/brush_ui.h"
|
||||||
|
#include "app_core/tools_menu.h"
|
||||||
|
#include "legacy_brush_ui_services.h"
|
||||||
|
#include "legacy_ui_overlay_services.h"
|
||||||
|
#include "node_button_custom.h"
|
||||||
|
#include "node_dialog_picker.h"
|
||||||
|
#include "node_panel_animation.h"
|
||||||
|
#include "node_panel_brush.h"
|
||||||
|
#include "node_panel_color.h"
|
||||||
|
#include "node_panel_floating.h"
|
||||||
|
#include "node_panel_grid.h"
|
||||||
|
#include "node_panel_layer.h"
|
||||||
|
#include "node_panel_stroke.h"
|
||||||
|
#include "node_popup_menu.h"
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
[[nodiscard]] bool should_open_tools_panel(const pp::app::ToolsPanelPlan& plan) noexcept
|
||||||
|
{
|
||||||
|
return plan.action == pp::app::ToolsPanelAction::open_floating_panel;
|
||||||
|
}
|
||||||
|
|
||||||
|
void apply_tools_panel_chrome(NodePanelFloating& panel, const pp::app::ToolsPanelPlan& plan)
|
||||||
|
{
|
||||||
|
if (plan.width > 0 && plan.height > 0) {
|
||||||
|
panel.SetSize(static_cast<float>(plan.width), static_cast<float>(plan.height));
|
||||||
|
} else {
|
||||||
|
if (plan.width > 0)
|
||||||
|
panel.SetWidth(static_cast<float>(plan.width));
|
||||||
|
if (plan.height > 0)
|
||||||
|
panel.SetHeight(static_cast<float>(plan.height));
|
||||||
|
}
|
||||||
|
if (plan.min_width > 0)
|
||||||
|
panel.SetMinWidth(static_cast<float>(plan.min_width));
|
||||||
|
if (plan.min_height > 0)
|
||||||
|
panel.SetMinHeight(static_cast<float>(plan.min_height));
|
||||||
|
panel.m_title->set_text(plan.title.data());
|
||||||
|
panel.m_droppable = plan.droppable;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] std::shared_ptr<NodePopupMenu> add_menu_popup(
|
||||||
|
App& app,
|
||||||
|
const char* template_id,
|
||||||
|
glm::vec2 position,
|
||||||
|
float rtl_anchor_width)
|
||||||
|
{
|
||||||
|
const auto popup = pp::panopainter::add_legacy_popup_menu(
|
||||||
|
app,
|
||||||
|
template_id,
|
||||||
|
position.x,
|
||||||
|
position.y,
|
||||||
|
rtl_anchor_width);
|
||||||
|
if (!popup) {
|
||||||
|
LOG("Popup menu '%s' failed: %s", template_id ? template_id : "<null>", popup.status().message);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto make_panel_visibility_checker(App& app)
|
||||||
|
{
|
||||||
|
return [&app](Node* panel) {
|
||||||
|
if (!panel)
|
||||||
|
return false;
|
||||||
|
for (auto& c : app.floatings_container->m_children)
|
||||||
|
{
|
||||||
|
if (auto fp = std::static_pointer_cast<NodePanelFloating>(c))
|
||||||
|
{
|
||||||
|
if (fp->m_container->is_child(panel))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void bind_panel_handlers(
|
||||||
|
App& app,
|
||||||
|
NodePopupMenu& panels_popup,
|
||||||
|
const std::function<void()>& close_panel_popups,
|
||||||
|
const std::function<bool(Node*)>& visible)
|
||||||
|
{
|
||||||
|
panels_popup.find<NodeButtonCustom>("panel-presets")->on_click = [&app, close_panel_popups, visible](Node*) {
|
||||||
|
const auto plan = pp::app::plan_tools_panel(
|
||||||
|
pp::app::ToolsPanel::presets,
|
||||||
|
visible(app.floating_presets.get()));
|
||||||
|
if (!should_open_tools_panel(plan))
|
||||||
|
return;
|
||||||
|
auto fpanel = app.floatings_container->add_child<NodePanelFloating>();
|
||||||
|
fpanel->m_class = NodePanelFloating::kClass::Presets;
|
||||||
|
apply_tools_panel_chrome(*fpanel, plan);
|
||||||
|
if (!app.floating_presets)
|
||||||
|
{
|
||||||
|
app.floating_presets = fpanel->m_container->add_child_ref<NodePanelBrushPreset>();
|
||||||
|
app.floating_presets->SetHeightP(100);
|
||||||
|
app.floating_presets->on_brush_changed = [&app](Node*, std::shared_ptr<Brush>& b) {
|
||||||
|
(void)pp::panopainter::apply_legacy_brush_preset_plan(app, b);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fpanel->m_container->add_child(app.floating_presets);
|
||||||
|
}
|
||||||
|
close_panel_popups();
|
||||||
|
};
|
||||||
|
|
||||||
|
panels_popup.find<NodeButtonCustom>("panel-color")->on_click = [&app, close_panel_popups, visible](Node*) {
|
||||||
|
const auto plan = pp::app::plan_tools_panel(
|
||||||
|
pp::app::ToolsPanel::color,
|
||||||
|
visible(app.floating_color.get()));
|
||||||
|
if (!should_open_tools_panel(plan))
|
||||||
|
return;
|
||||||
|
auto fpanel = app.floatings_container->add_child<NodePanelFloating>();
|
||||||
|
fpanel->m_class = NodePanelFloating::kClass::Color;
|
||||||
|
apply_tools_panel_chrome(*fpanel, plan);
|
||||||
|
if (!app.floating_color)
|
||||||
|
{
|
||||||
|
app.floating_color = fpanel->m_container->add_child_ref<NodePanelColor>();
|
||||||
|
app.floating_color->SetHeightP(100);
|
||||||
|
if (plan.hides_embedded_title)
|
||||||
|
app.floating_color->find("title")->SetVisibility(false);
|
||||||
|
app.floating_color->on_color_changed = [&app](Node*, glm::vec4 color) {
|
||||||
|
(void)pp::panopainter::apply_legacy_brush_color_plan(app, color, false, false);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fpanel->m_container->add_child(app.floating_color);
|
||||||
|
}
|
||||||
|
close_panel_popups();
|
||||||
|
};
|
||||||
|
|
||||||
|
panels_popup.find<NodeButtonCustom>("panel-color-adv")->on_click = [&app, close_panel_popups, visible](Node*) {
|
||||||
|
const auto plan = pp::app::plan_tools_panel(
|
||||||
|
pp::app::ToolsPanel::color_advanced,
|
||||||
|
visible(app.floating_picker.get()));
|
||||||
|
if (!should_open_tools_panel(plan))
|
||||||
|
return;
|
||||||
|
auto fpanel = app.floatings_container->add_child<NodePanelFloating>();
|
||||||
|
fpanel->m_class = NodePanelFloating::kClass::ColorAdv;
|
||||||
|
apply_tools_panel_chrome(*fpanel, plan);
|
||||||
|
if (!app.floating_picker)
|
||||||
|
{
|
||||||
|
app.floating_picker = fpanel->m_container->add_child_ref<NodeColorPicker>();
|
||||||
|
app.floating_picker->m_autohide = false;
|
||||||
|
app.floating_picker->on_color_change = [&app](Node*, glm::vec3 color) {
|
||||||
|
(void)pp::panopainter::apply_legacy_brush_color_plan(app, glm::vec4(color, 1.f), false, false);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fpanel->m_container->add_child(app.floating_picker);
|
||||||
|
}
|
||||||
|
close_panel_popups();
|
||||||
|
};
|
||||||
|
|
||||||
|
panels_popup.find<NodeButtonCustom>("panel-layers")->on_click = [&app, close_panel_popups, visible](Node*) {
|
||||||
|
const auto plan = pp::app::plan_tools_panel(
|
||||||
|
pp::app::ToolsPanel::layers,
|
||||||
|
visible(app.layers.get()));
|
||||||
|
if (!should_open_tools_panel(plan))
|
||||||
|
return;
|
||||||
|
auto fpanel = app.floatings_container->add_child<NodePanelFloating>();
|
||||||
|
fpanel->m_class = NodePanelFloating::kClass::Layers;
|
||||||
|
apply_tools_panel_chrome(*fpanel, plan);
|
||||||
|
fpanel->m_container->add_child(app.layers);
|
||||||
|
app.layers->SetPositioning(YGPositionTypeRelative);
|
||||||
|
app.layers->SetPosition(0, 0);
|
||||||
|
app.layers->SetWidthP(100);
|
||||||
|
app.layers->SetHeightP(100);
|
||||||
|
app.layers->SetFlexShrink(0);
|
||||||
|
if (plan.hides_embedded_title)
|
||||||
|
app.layers->find("title")->SetVisibility(false);
|
||||||
|
|
||||||
|
close_panel_popups();
|
||||||
|
};
|
||||||
|
|
||||||
|
panels_popup.find<NodeButtonCustom>("panel-brush")->on_click = [&app, close_panel_popups, visible](Node*) {
|
||||||
|
const auto plan = pp::app::plan_tools_panel(
|
||||||
|
pp::app::ToolsPanel::brush,
|
||||||
|
visible(app.stroke.get()));
|
||||||
|
if (!should_open_tools_panel(plan))
|
||||||
|
return;
|
||||||
|
auto fpanel = app.floatings_container->add_child<NodePanelFloating>();
|
||||||
|
fpanel->m_class = NodePanelFloating::kClass::Brush;
|
||||||
|
fpanel->m_container->add_child(app.stroke);
|
||||||
|
apply_tools_panel_chrome(*fpanel, plan);
|
||||||
|
app.stroke->SetPositioning(YGPositionTypeRelative);
|
||||||
|
app.stroke->SetPosition(0, 0);
|
||||||
|
app.stroke->SetWidthP(100);
|
||||||
|
app.stroke->SetHeightP(100);
|
||||||
|
if (plan.hides_embedded_title)
|
||||||
|
app.stroke->find("title")->SetVisibility(false);
|
||||||
|
|
||||||
|
close_panel_popups();
|
||||||
|
};
|
||||||
|
|
||||||
|
panels_popup.find<NodeButtonCustom>("panel-grids")->on_click = [&app, close_panel_popups, visible](Node*) {
|
||||||
|
const auto plan = pp::app::plan_tools_panel(
|
||||||
|
pp::app::ToolsPanel::grids,
|
||||||
|
visible(app.grid.get()));
|
||||||
|
if (!should_open_tools_panel(plan))
|
||||||
|
return;
|
||||||
|
auto fpanel = app.floatings_container->add_child<NodePanelFloating>();
|
||||||
|
fpanel->m_class = NodePanelFloating::kClass::Grids;
|
||||||
|
fpanel->m_container->add_child(app.grid);
|
||||||
|
apply_tools_panel_chrome(*fpanel, plan);
|
||||||
|
app.grid->SetPositioning(YGPositionTypeRelative);
|
||||||
|
app.grid->SetPosition(0, 0);
|
||||||
|
app.grid->SetWidthP(100);
|
||||||
|
app.grid->SetHeightP(100);
|
||||||
|
if (plan.hides_embedded_title)
|
||||||
|
app.grid->find("title")->SetVisibility(false);
|
||||||
|
|
||||||
|
close_panel_popups();
|
||||||
|
};
|
||||||
|
|
||||||
|
panels_popup.find<NodeButtonCustom>("panel-animation")->on_click = [&app, close_panel_popups, visible](Node*) {
|
||||||
|
const auto plan = pp::app::plan_tools_panel(
|
||||||
|
pp::app::ToolsPanel::animation,
|
||||||
|
visible(app.animation.get()));
|
||||||
|
if (!should_open_tools_panel(plan))
|
||||||
|
return;
|
||||||
|
auto fpanel = app.floatings_container->add_child<NodePanelFloating>();
|
||||||
|
fpanel->m_class = NodePanelFloating::kClass::Animation;
|
||||||
|
fpanel->m_container->add_child(app.animation);
|
||||||
|
apply_tools_panel_chrome(*fpanel, plan);
|
||||||
|
app.animation->SetPositioning(YGPositionTypeRelative);
|
||||||
|
app.animation->SetPosition(0, 0);
|
||||||
|
app.animation->SetWidthP(100);
|
||||||
|
app.animation->SetHeightP(100);
|
||||||
|
|
||||||
|
close_panel_popups();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
namespace pp::panopainter {
|
||||||
|
|
||||||
|
void bind_legacy_tools_panels_submenu(
|
||||||
|
App& app,
|
||||||
|
Node& main,
|
||||||
|
std::shared_ptr<NodePopupMenu> root_popup,
|
||||||
|
NodeButtonCustom& panels_button)
|
||||||
|
{
|
||||||
|
panels_button.on_click = [&app, &main, root_popup = std::move(root_popup), &panels_button](Node*) mutable {
|
||||||
|
pp::panopainter::detach_legacy_node_from_parent(*root_popup);
|
||||||
|
const auto root_popup_overlay = pp::panopainter::open_legacy_overlay_node_with_handle(main, root_popup);
|
||||||
|
if (!root_popup_overlay)
|
||||||
|
return;
|
||||||
|
const auto root_popup_handle = root_popup_overlay.value();
|
||||||
|
|
||||||
|
glm::vec2 pos = panels_button.m_pos + glm::vec2(panels_button.m_size.x, 0);
|
||||||
|
auto panels_popup = add_menu_popup(app, "panels-menu", pos, panels_button.m_size.x);
|
||||||
|
if (!panels_popup)
|
||||||
|
{
|
||||||
|
close_legacy_overlay_handle_ignoring_status(main, root_popup_handle);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
pp::panopainter::detach_legacy_node_from_parent(*panels_popup);
|
||||||
|
const auto panels_popup_overlay = pp::panopainter::open_legacy_overlay_node_with_handle(main, panels_popup);
|
||||||
|
if (!panels_popup_overlay)
|
||||||
|
{
|
||||||
|
close_legacy_overlay_handle_ignoring_status(main, root_popup_handle);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto panels_popup_handle = panels_popup_overlay.value();
|
||||||
|
|
||||||
|
const auto close_panel_popups = [root_popup_handle, panels_popup_handle, &main]()
|
||||||
|
{
|
||||||
|
close_legacy_overlay_handle_ignoring_status(main, root_popup_handle);
|
||||||
|
close_legacy_overlay_handle_ignoring_status(main, panels_popup_handle);
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto visible = make_panel_visibility_checker(app);
|
||||||
|
bind_panel_handlers(app, *panels_popup, close_panel_popups, visible);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace pp::panopainter
|
||||||
18
src/legacy_tools_menu_binding_services.h
Normal file
18
src/legacy_tools_menu_binding_services.h
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
class App;
|
||||||
|
class Node;
|
||||||
|
class NodeButtonCustom;
|
||||||
|
class NodePopupMenu;
|
||||||
|
|
||||||
|
namespace pp::panopainter {
|
||||||
|
|
||||||
|
void bind_legacy_tools_panels_submenu(
|
||||||
|
App& app,
|
||||||
|
Node& main,
|
||||||
|
std::shared_ptr<NodePopupMenu> root_popup,
|
||||||
|
NodeButtonCustom& panels_button);
|
||||||
|
|
||||||
|
} // namespace pp::panopainter
|
||||||
Reference in New Issue
Block a user