Extract app frame and export dialog helpers

This commit is contained in:
2026-06-16 11:58:22 +02:00
parent d2a841f348
commit 01854f9b10
9 changed files with 786 additions and 584 deletions

View File

@@ -0,0 +1,164 @@
#include "pch.h"
#include "app.h"
#include "app_core/app_frame.h"
#include "app_core/canvas_tool_ui.h"
#include "legacy_ui_gl_dispatch.h"
#include "renderer_gl/opengl_capabilities.h"
namespace {
pp::app::CanvasToolMode canvas_tool_mode_from_canvas_mode(kCanvasMode mode) noexcept
{
switch (mode) {
case kCanvasMode::Draw:
return pp::app::CanvasToolMode::draw;
case kCanvasMode::Erase:
return pp::app::CanvasToolMode::erase;
case kCanvasMode::Line:
return pp::app::CanvasToolMode::line;
case kCanvasMode::Camera:
return pp::app::CanvasToolMode::camera;
case kCanvasMode::Grid:
return pp::app::CanvasToolMode::grid;
case kCanvasMode::Copy:
return pp::app::CanvasToolMode::copy;
case kCanvasMode::Cut:
return pp::app::CanvasToolMode::cut;
case kCanvasMode::Fill:
return pp::app::CanvasToolMode::fill;
case kCanvasMode::MaskFree:
return pp::app::CanvasToolMode::mask_free;
case kCanvasMode::MaskLine:
return pp::app::CanvasToolMode::mask_line;
case kCanvasMode::FloodFill:
return pp::app::CanvasToolMode::flood_fill;
default:
return pp::app::CanvasToolMode::draw;
}
}
void apply_legacy_app_scissor(pp::renderer::gl::OpenGlScissorRect scissor)
{
const auto status = pp::renderer::gl::apply_opengl_scissor_rect(
scissor,
pp::renderer::gl::OpenGlScissorDispatch {
.enable = pp::legacy::ui_gl::enable_opengl_state,
.disable = pp::legacy::ui_gl::disable_opengl_state,
.scissor = pp::legacy::ui_gl::set_opengl_scissor,
});
if (!status.ok())
LOG("OpenGL scissor failed: %s", status.message);
}
void watch_layout_children(LayoutManager* layout, uint16_t main_id, int start_index, const std::function<bool(Node*)>& observer)
{
if (!layout)
return;
if (auto* root = layout->get(main_id)) {
for (int i = start_index; i < static_cast<int>(root->m_children.size()); ++i)
root->m_children[i]->watch(observer);
}
}
}
namespace pp::panopainter
{
bool update_legacy_app_ui_observer(App& app, Node* n)
{
std::vector<pp::app::AppUiObserverParentClip> parent_clips;
if (n) {
for (Node* p = n->m_parent; p; p = p->m_parent) {
parent_clips.push_back(pp::app::AppUiObserverParentClip {
.clip = pp::app::AppUiObserverRect {
.x = p->m_clip_uncut.x,
.y = p->m_clip_uncut.y,
.width = p->m_clip_uncut.z,
.height = p->m_clip_uncut.w,
},
.padding_top = YGNodeLayoutGetPadding(p->y_node, YGEdgeTop),
.padding_right = YGNodeLayoutGetPadding(p->y_node, YGEdgeRight),
.padding_bottom = YGNodeLayoutGetPadding(p->y_node, YGEdgeBottom),
.padding_left = YGNodeLayoutGetPadding(p->y_node, YGEdgeLeft),
});
}
}
const auto plan = pp::app::plan_app_ui_observer(
n != nullptr,
n && n->m_display,
n && n->m_on_screen,
n
? pp::app::AppUiObserverRect {
.x = n->m_clip_uncut.x,
.y = n->m_clip_uncut.y,
.width = n->m_clip_uncut.z,
.height = n->m_clip_uncut.w,
}
: pp::app::AppUiObserverRect {},
parent_clips,
app.height,
app.zoom,
app.off_x,
app.off_y);
if (!plan) {
LOG("UI observer plan failed: %s", plan.status().message);
return false;
}
if (!n)
return false;
if (plan.value().notify_leave_screen)
n->handle_on_screen(true, false);
if (plan.value().notify_enter_screen)
n->handle_on_screen(false, true);
n->m_on_screen = plan.value().next_on_screen;
if (!plan.value().draw_node)
return false;
apply_legacy_app_scissor(pp::renderer::gl::OpenGlScissorRect {
.enabled = 1U,
.x = plan.value().scissor_x,
.y = plan.value().scissor_y,
.width = plan.value().scissor_width,
.height = plan.value().scissor_height,
});
n->draw();
return true;
}
void watch_legacy_app_ui_children(App& app, const std::function<bool(Node*)>& observer, bool skip_first_main_child)
{
watch_layout_children(&app.layout, app.main_id, skip_first_main_child ? 1 : 0, observer);
watch_layout_children(&app.layout_designer, app.main_id, 0, observer);
}
void update_legacy_canvas_toolbar(App& app)
{
const auto mode = Canvas::I->m_current_mode;
auto* pm = app.canvas->m_canvas->get_mode<CanvasModePen>();
const auto toolbar = pp::app::plan_canvas_tool_button_state(
canvas_tool_mode_from_canvas_mode(mode),
pm && pm->m_picking,
app.canvas->m_canvas->m_touch_lock);
app.layout[app.main_id]->find<NodeButtonCustom>("btn-pick")->set_active(toolbar.pick_active);
app.layout[app.main_id]->find<NodeButtonCustom>("btn-touchlock")->set_active(toolbar.touch_lock_active);
app.layout[app.main_id]->find<NodeButtonCustom>("btn-pen")->set_active(toolbar.pen_active);
app.layout[app.main_id]->find<NodeButtonCustom>("btn-erase")->set_active(toolbar.erase_active);
app.layout[app.main_id]->find<NodeButton>("btn-cam")->set_active(toolbar.camera_active);
app.layout[app.main_id]->find<NodeButtonCustom>("btn-line")->set_active(toolbar.line_active);
app.layout[app.main_id]->find<NodeButton>("btn-grid")->set_active(toolbar.grid_active);
app.layout[app.main_id]->find<NodeButton>("btn-copy")->set_active(toolbar.copy_active);
app.layout[app.main_id]->find<NodeButton>("btn-cut")->set_active(toolbar.cut_active);
app.layout[app.main_id]->find<NodeButtonCustom>("btn-mask-free")->set_active(toolbar.mask_free_active);
app.layout[app.main_id]->find<NodeButtonCustom>("btn-mask-line")->set_active(toolbar.mask_line_active);
app.layout[app.main_id]->find<NodeButtonCustom>("btn-bucket")->set_active(toolbar.flood_fill_active);
}
}