Centralize legacy document session bridge

This commit is contained in:
2026-06-04 13:30:22 +02:00
parent d980b81bd7
commit 4528edfb2c
10 changed files with 437 additions and 64 deletions

View File

@@ -11,6 +11,7 @@
#include "app_core/document_route.h"
#include "app_core/document_session.h"
#include "legacy_document_open_services.h"
#include "legacy_document_session_services.h"
#include "legacy_recording_services.h"
#include "platform_api/platform_services.h"
#include "renderer_gl/opengl_capabilities.h"
@@ -208,26 +209,14 @@ bool App::request_close()
const auto close_decision = pp::app::plan_close_request(
Canvas::I->m_unsaved,
dialog_already_opened);
if (close_decision == pp::app::CloseRequestDecision::close_now)
return true;
if (close_decision == pp::app::CloseRequestDecision::show_unsaved_prompt)
{
auto* m = layout[main_id]->add_child<NodeMessageBox>();
m->m_title->set_text("Unsaved document");
m->m_message->set_text("Do you want to close without saving?");
m->btn_ok->m_text->set_text("Yes");
m->btn_ok->on_click = [this](Node*) {
request_app_close();
Canvas::I->m_unsaved = false;
};
m->btn_cancel->m_text->set_text("No");
m->btn_cancel->on_click = [this,m](Node*) {
m->destroy();
dialog_already_opened = false;
};
dialog_already_opened = true;
}
return false;
const auto status = pp::panopainter::execute_legacy_close_request_decision(
*this,
close_decision,
dialog_already_opened);
if (!status.ok())
LOG("Close request action failed: %s", status.message);
return close_decision == pp::app::CloseRequestDecision::close_now;
}
void App::clear()

View File

@@ -65,6 +65,31 @@ public:
virtual void prompt_discard_unsaved_project(const DocumentOpenRoute& route) = 0;
};
class CloseRequestServices {
public:
virtual ~CloseRequestServices() = default;
virtual void request_close_now() = 0;
virtual void show_unsaved_close_prompt() = 0;
};
class DocumentSaveServices {
public:
virtual ~DocumentSaveServices() = default;
virtual void show_save_dialog() = 0;
virtual void save_existing_document() = 0;
virtual void save_document_version() = 0;
};
class DocumentWorkflowServices {
public:
virtual ~DocumentWorkflowServices() = default;
virtual void continue_workflow_now() = 0;
virtual void prompt_save_before_continue() = 0;
};
struct DocumentFileTarget {
std::string name;
std::string directory;
@@ -160,6 +185,24 @@ struct NewDocumentPlan {
: CloseRequestDecision::show_unsaved_prompt;
}
[[nodiscard]] inline pp::foundation::Status execute_close_request_decision(
CloseRequestDecision decision,
CloseRequestServices& services)
{
switch (decision) {
case CloseRequestDecision::close_now:
services.request_close_now();
return pp::foundation::Status::success();
case CloseRequestDecision::show_unsaved_prompt:
services.show_unsaved_close_prompt();
return pp::foundation::Status::success();
case CloseRequestDecision::wait_for_existing_prompt:
return pp::foundation::Status::success();
}
return pp::foundation::Status::invalid_argument("unknown close request decision");
}
[[nodiscard]] constexpr DocumentSaveDecision plan_document_save(
bool is_new_document,
bool has_unsaved_changes,
@@ -191,6 +234,27 @@ struct NewDocumentPlan {
return DocumentSaveDecision::no_op;
}
[[nodiscard]] inline pp::foundation::Status execute_document_save_decision(
DocumentSaveDecision decision,
DocumentSaveServices& services)
{
switch (decision) {
case DocumentSaveDecision::no_op:
return pp::foundation::Status::success();
case DocumentSaveDecision::show_save_dialog:
services.show_save_dialog();
return pp::foundation::Status::success();
case DocumentSaveDecision::save_existing:
services.save_existing_document();
return pp::foundation::Status::success();
case DocumentSaveDecision::save_version:
services.save_document_version();
return pp::foundation::Status::success();
}
return pp::foundation::Status::invalid_argument("unknown document save decision");
}
[[nodiscard]] constexpr DocumentWorkflowDecision plan_document_workflow(
bool has_canvas,
bool has_unsaved_changes) noexcept
@@ -204,6 +268,24 @@ struct NewDocumentPlan {
: DocumentWorkflowDecision::continue_now;
}
[[nodiscard]] inline pp::foundation::Status execute_document_workflow_decision(
DocumentWorkflowDecision decision,
DocumentWorkflowServices& services)
{
switch (decision) {
case DocumentWorkflowDecision::unavailable:
return pp::foundation::Status::success();
case DocumentWorkflowDecision::continue_now:
services.continue_workflow_now();
return pp::foundation::Status::success();
case DocumentWorkflowDecision::prompt_save_before_continue:
services.prompt_save_before_continue();
return pp::foundation::Status::success();
}
return pp::foundation::Status::invalid_argument("unknown document workflow decision");
}
[[nodiscard]] inline pp::foundation::Result<DocumentFileTarget> make_document_file_target(
std::string_view work_directory,
std::string_view document_name)

View File

@@ -6,6 +6,7 @@
#include "app_core/document_session.h"
#include "legacy_document_canvas_services.h"
#include "legacy_document_layer_services.h"
#include "legacy_document_session_services.h"
#include "legacy_history_services.h"
#include "settings.h"
#include "node_dialog_open.h"
@@ -23,6 +24,8 @@
#define MP4V2_NO_STDINT_DEFS
#include <mp4v2/mp4v2.h>
#include <utility>
#ifdef __QUEST__
#include "oculus_vr.h"
#elif __WEB__
@@ -138,34 +141,12 @@ void App::continue_document_workflow_after_optional_save(std::function<void()> a
const bool has_canvas = canvas != nullptr;
const bool has_unsaved_changes = has_canvas && Canvas::I->m_unsaved;
const auto decision = pp::app::plan_document_workflow(has_canvas, has_unsaved_changes);
switch (decision) {
case pp::app::DocumentWorkflowDecision::unavailable:
return;
case pp::app::DocumentWorkflowDecision::continue_now:
action();
return;
case pp::app::DocumentWorkflowDecision::prompt_save_before_continue:
break;
}
auto m = layout[main_id]->add_child<NodeMessageBox>();
m->m_title->set_text("Unsaved document");
m->m_message->set_text("Would you like to save this document before closing?");
m->btn_ok->m_text->set_text("Yes");
m->btn_cancel->m_text->set_text("No");
m->btn_ok->on_click = [this, m, action](Node*) {
Canvas::I->project_save([this, m, action](bool success) {
if (success)
action();
else
message_box("Saving Error", "There was a problem saving the document");
});
m->destroy();
};
m->btn_cancel->on_click = [m, action](Node*) {
action();
m->destroy();
};
const auto status = pp::panopainter::execute_legacy_document_workflow_decision(
*this,
decision,
std::move(action));
if (!status.ok())
LOG("Document workflow action failed: %s", status.message);
}
void App::dialog_newdoc()
@@ -350,19 +331,9 @@ void App::save_document(pp::app::DocumentSaveIntent intent)
Canvas::I->m_newdoc,
Canvas::I->m_unsaved,
intent);
switch (decision) {
case pp::app::DocumentSaveDecision::show_save_dialog:
dialog_save();
break;
case pp::app::DocumentSaveDecision::save_existing:
Canvas::I->project_save();
break;
case pp::app::DocumentSaveDecision::save_version:
dialog_save_ver();
break;
case pp::app::DocumentSaveDecision::no_op:
break;
}
const auto status = pp::panopainter::execute_legacy_document_save_decision(*this, decision);
if (!status.ok())
LOG("Document save action failed: %s", status.message);
}
void App::dialog_save()

View File

@@ -0,0 +1,143 @@
#include "pch.h"
#include "legacy_document_session_services.h"
#include "app.h"
namespace pp::panopainter {
namespace {
class LegacyCloseRequestServices final : public pp::app::CloseRequestServices {
public:
LegacyCloseRequestServices(App& app, bool& dialog_already_opened) noexcept
: app_(app)
, dialog_already_opened_(dialog_already_opened)
{
}
void request_close_now() override
{
}
void show_unsaved_close_prompt() override
{
auto* app = &app_;
auto* dialog_already_opened = &dialog_already_opened_;
auto* m = app_.layout[app_.main_id]->add_child<NodeMessageBox>();
m->m_title->set_text("Unsaved document");
m->m_message->set_text("Do you want to close without saving?");
m->btn_ok->m_text->set_text("Yes");
m->btn_ok->on_click = [app](Node*) {
app->request_app_close();
Canvas::I->m_unsaved = false;
};
m->btn_cancel->m_text->set_text("No");
m->btn_cancel->on_click = [dialog_already_opened, m](Node*) {
m->destroy();
*dialog_already_opened = false;
};
dialog_already_opened_ = true;
}
private:
App& app_;
bool& dialog_already_opened_;
};
class LegacyDocumentSaveServices final : public pp::app::DocumentSaveServices {
public:
explicit LegacyDocumentSaveServices(App& app) noexcept
: app_(app)
{
}
void show_save_dialog() override
{
app_.dialog_save();
}
void save_existing_document() override
{
Canvas::I->project_save();
}
void save_document_version() override
{
app_.dialog_save_ver();
}
private:
App& app_;
};
class LegacyDocumentWorkflowServices final : public pp::app::DocumentWorkflowServices {
public:
LegacyDocumentWorkflowServices(App& app, std::function<void()> action) noexcept
: app_(app)
, action_(std::move(action))
{
}
void continue_workflow_now() override
{
action_();
}
void prompt_save_before_continue() override
{
auto m = app_.layout[app_.main_id]->add_child<NodeMessageBox>();
m->m_title->set_text("Unsaved document");
m->m_message->set_text("Would you like to save this document before closing?");
m->btn_ok->m_text->set_text("Yes");
m->btn_cancel->m_text->set_text("No");
auto* app = &app_;
auto action = action_;
m->btn_ok->on_click = [app, m, action](Node*) {
Canvas::I->project_save([app, m, action](bool success) {
if (success)
action();
else
app->message_box("Saving Error", "There was a problem saving the document");
});
m->destroy();
};
m->btn_cancel->on_click = [m, action](Node*) {
action();
m->destroy();
};
}
private:
App& app_;
std::function<void()> action_;
};
} // namespace
pp::foundation::Status execute_legacy_close_request_decision(
App& app,
pp::app::CloseRequestDecision decision,
bool& dialog_already_opened)
{
LegacyCloseRequestServices services(app, dialog_already_opened);
return pp::app::execute_close_request_decision(decision, services);
}
pp::foundation::Status execute_legacy_document_save_decision(
App& app,
pp::app::DocumentSaveDecision decision)
{
LegacyDocumentSaveServices services(app);
return pp::app::execute_document_save_decision(decision, services);
}
pp::foundation::Status execute_legacy_document_workflow_decision(
App& app,
pp::app::DocumentWorkflowDecision decision,
std::function<void()> action)
{
LegacyDocumentWorkflowServices services(app, std::move(action));
return pp::app::execute_document_workflow_decision(decision, services);
}
} // namespace pp::panopainter

View File

@@ -0,0 +1,26 @@
#pragma once
#include "app_core/document_session.h"
#include "foundation/result.h"
#include <functional>
class App;
namespace pp::panopainter {
[[nodiscard]] pp::foundation::Status execute_legacy_close_request_decision(
App& app,
pp::app::CloseRequestDecision decision,
bool& dialog_already_opened);
[[nodiscard]] pp::foundation::Status execute_legacy_document_save_decision(
App& app,
pp::app::DocumentSaveDecision decision);
[[nodiscard]] pp::foundation::Status execute_legacy_document_workflow_decision(
App& app,
pp::app::DocumentWorkflowDecision decision,
std::function<void()> action);
} // namespace pp::panopainter