Add export menu service boundary
This commit is contained in:
@@ -47,7 +47,7 @@ agent or engineer to remove them without reconstructing context from chat.
|
|||||||
| DEBT-0027 | Open | Modernization | Canvas draw-tool toolbar command, canvas input mode switching, and active-state planning now consume pure `pp_app_core` through `App::init_toolbar_draw`, `App::update`, `NodeCanvas`, `pano_cli plan-canvas-tool`, and `pano_cli plan-canvas-tool-state`, but live execution/state storage still mutates or reads legacy `Canvas` mode state, pen picking state, touch-lock state, and transform copy/cut action objects directly | Preserve current toolbar, stylus eraser, and keyboard draw/erase behavior while canvas input/tools move toward an app/document command boundary | `pp_app_core_canvas_tool_ui_tests`; `pano_cli plan-canvas-tool --kind copy`; `pano_cli plan-canvas-tool-state --mode draw --picking --touch-lock`; `ctest --preset desktop-fast --build-config Debug` | Canvas tool selection, toolbar state refresh, picking, touch lock, stylus eraser/key mode switching, and transform action execution are owned by app/document/canvas services with toolbar/canvas callbacks acting only as adapters |
|
| DEBT-0027 | Open | Modernization | Canvas draw-tool toolbar command, canvas input mode switching, and active-state planning now consume pure `pp_app_core` through `App::init_toolbar_draw`, `App::update`, `NodeCanvas`, `pano_cli plan-canvas-tool`, and `pano_cli plan-canvas-tool-state`, but live execution/state storage still mutates or reads legacy `Canvas` mode state, pen picking state, touch-lock state, and transform copy/cut action objects directly | Preserve current toolbar, stylus eraser, and keyboard draw/erase behavior while canvas input/tools move toward an app/document command boundary | `pp_app_core_canvas_tool_ui_tests`; `pano_cli plan-canvas-tool --kind copy`; `pano_cli plan-canvas-tool-state --mode draw --picking --touch-lock`; `ctest --preset desktop-fast --build-config Debug` | Canvas tool selection, toolbar state refresh, picking, touch lock, stylus eraser/key mode switching, and transform action execution are owned by app/document/canvas services with toolbar/canvas callbacks acting only as adapters |
|
||||||
| DEBT-0028 | Open | Modernization | Canvas clear command planning now consumes pure `pp_app_core` through `App::init_toolbar_main` and `pano_cli plan-canvas-clear`, but live execution still calls legacy `Canvas::clear`, which records `ActionLayerClear`, clears the current layer/frame, and marks legacy `Canvas::I` unsaved directly | Preserve clear-current-layer behavior while canvas/document commands move toward document/app command services | `pp_app_core_document_canvas_tests`; `pano_cli plan-canvas-clear --r 0 --g 0.1 --b 0.2 --a 0.3`; `pano_cli plan-canvas-clear --no-canvas`; `ctest --preset desktop-fast --build-config Debug` | Canvas clear execution, undo recording, dirty-state updates, and clear color handling are owned by document/app services with toolbar callbacks acting only as adapters |
|
| DEBT-0028 | Open | Modernization | Canvas clear command planning now consumes pure `pp_app_core` through `App::init_toolbar_main` and `pano_cli plan-canvas-clear`, but live execution still calls legacy `Canvas::clear`, which records `ActionLayerClear`, clears the current layer/frame, and marks legacy `Canvas::I` unsaved directly | Preserve clear-current-layer behavior while canvas/document commands move toward document/app command services | `pp_app_core_document_canvas_tests`; `pano_cli plan-canvas-clear --r 0 --g 0.1 --b 0.2 --a 0.3`; `pano_cli plan-canvas-clear --no-canvas`; `ctest --preset desktop-fast --build-config Debug` | Canvas clear execution, undo recording, dirty-state updates, and clear color handling are owned by document/app services with toolbar callbacks acting only as adapters |
|
||||||
| DEBT-0029 | Open | Modernization | Image import route planning now consumes pure `pp_app_core` through the File menu and `pano_cli plan-image-import`, but live execution still calls legacy `Canvas::import_equirectangular` or legacy import transform mode setup directly after image loading | Preserve current File > Import behavior while image import moves toward document/app/asset command services | `pp_app_core_document_import_tests`; `pano_cli plan-image-import --width 4096 --height 2048`; `pano_cli plan-image-import --width 1024 --height 1024`; `ctest --preset desktop-fast --build-config Debug` | Image loading, equirectangular import, transform-placement import, and failure reporting are owned by document/app/asset services with File-menu callbacks acting only as adapters |
|
| DEBT-0029 | Open | Modernization | Image import route planning now consumes pure `pp_app_core` through the File menu and `pano_cli plan-image-import`, but live execution still calls legacy `Canvas::import_equirectangular` or legacy import transform mode setup directly after image loading | Preserve current File > Import behavior while image import moves toward document/app/asset command services | `pp_app_core_document_import_tests`; `pano_cli plan-image-import --width 4096 --height 2048`; `pano_cli plan-image-import --width 1024 --height 1024`; `ctest --preset desktop-fast --build-config Debug` | Image loading, equirectangular import, transform-placement import, and failure reporting are owned by document/app/asset services with File-menu callbacks acting only as adapters |
|
||||||
| DEBT-0030 | Open | Modernization | File export menu action planning now consumes pure `pp_app_core` through the File menu and `pano_cli plan-export-menu`, but live execution still opens legacy export dialogs and then reaches legacy canvas/render/video export code | Preserve current export menu behavior while export command execution moves toward document/app/renderer/video services | `pp_app_core_document_export_tests`; `pano_cli plan-export-menu --kind png`; `pano_cli plan-export-menu --kind animation-mp4 --demo`; `pano_cli plan-export-menu --kind layers --no-canvas`; `ctest --preset desktop-fast --build-config Debug` | Export menu routing, license gating, target creation, image/layer/cube/depth/animation/timelapse execution, and error reporting are owned by document/app services with File-menu callbacks acting only as adapters |
|
| DEBT-0030 | Open | Modernization | File export menu action planning and execution dispatch now consume pure `pp_app_core` through the File menu, `pano_cli plan-export-menu`, and the `DocumentExportMenuServices` boundary, but the live adapter still opens legacy export dialogs and then reaches legacy canvas/render/video export code | Preserve current export menu behavior while export command execution moves toward document/app/renderer/video services | `pp_app_core_document_export_tests`; `pano_cli plan-export-menu --kind png`; `pano_cli plan-export-menu --kind animation-mp4 --demo`; `pano_cli plan-export-menu --kind layers --no-canvas`; `ctest --preset desktop-fast --build-config Debug` | Export menu routing, license gating, target creation, image/layer/cube/depth/animation/timelapse execution, and error reporting are owned by injected document/app/renderer/video services with File-menu callbacks acting only as UI adapters and no legacy export adapter |
|
||||||
| DEBT-0031 | Open | Modernization | Top-level File menu command planning and execution dispatch now consume pure `pp_app_core` through `App::init_menu_file`, `pano_cli plan-file-menu`, and the `FileMenuServices` boundary, but the live adapter still invokes legacy dialogs, platform pickers, cloud code, share code, and canvas import/export paths directly | Preserve File menu behavior while app workflows move toward app/document/platform command services | `pp_app_core_file_menu_tests`; `pano_cli plan-file-menu --command save-as`; `pano_cli plan-file-menu --command import`; `pano_cli plan-file-menu --command cloud-upload`; `ctest --preset desktop-fast --build-config Debug` | File menu routing, picker dispatch, save/share/cloud/resize/export execution, and image/project import execution are owned by injected app/document/platform services with `App::init_menu_file` acting only as a UI adapter and no legacy File menu adapter |
|
| DEBT-0031 | Open | Modernization | Top-level File menu command planning and execution dispatch now consume pure `pp_app_core` through `App::init_menu_file`, `pano_cli plan-file-menu`, and the `FileMenuServices` boundary, but the live adapter still invokes legacy dialogs, platform pickers, cloud code, share code, and canvas import/export paths directly | Preserve File menu behavior while app workflows move toward app/document/platform command services | `pp_app_core_file_menu_tests`; `pano_cli plan-file-menu --command save-as`; `pano_cli plan-file-menu --command import`; `pano_cli plan-file-menu --command cloud-upload`; `ctest --preset desktop-fast --build-config Debug` | File menu routing, picker dispatch, save/share/cloud/resize/export execution, and image/project import execution are owned by injected app/document/platform services with `App::init_menu_file` acting only as a UI adapter and no legacy File menu adapter |
|
||||||
| DEBT-0032 | Open | Modernization | Layer menu command planning and execution dispatch now consume pure `pp_app_core` through `App::init_menu_layer`, `pano_cli plan-layer-menu`, and the `DocumentLayerMenuServices` boundary, but the live adapter still calls legacy `Canvas::clear`, `App::dialog_layer_rename`, `NodePanelLayer::merge`, and reads `Canvas::I` animation/layer state directly | Preserve existing Layer menu behavior while layer commands move toward document/app services | `pp_app_core_document_layer_tests`; `pano_cli plan-layer-menu --command merge --current-index 2 --lower-name Paint`; `pano_cli plan-layer-menu --command rename --no-current-layer`; `ctest --preset desktop-fast --build-config Debug` | Layer clear, rename, merge-down execution, animation gating, and selected-layer state are owned by injected document/app services with Layer-menu callbacks acting only as UI adapters and no legacy Layer menu adapter |
|
| DEBT-0032 | Open | Modernization | Layer menu command planning and execution dispatch now consume pure `pp_app_core` through `App::init_menu_layer`, `pano_cli plan-layer-menu`, and the `DocumentLayerMenuServices` boundary, but the live adapter still calls legacy `Canvas::clear`, `App::dialog_layer_rename`, `NodePanelLayer::merge`, and reads `Canvas::I` animation/layer state directly | Preserve existing Layer menu behavior while layer commands move toward document/app services | `pp_app_core_document_layer_tests`; `pano_cli plan-layer-menu --command merge --current-index 2 --lower-name Paint`; `pano_cli plan-layer-menu --command rename --no-current-layer`; `ctest --preset desktop-fast --build-config Debug` | Layer clear, rename, merge-down execution, animation gating, and selected-layer state are owned by injected document/app services with Layer-menu callbacks acting only as UI adapters and no legacy Layer menu adapter |
|
||||||
| DEBT-0033 | Open | Modernization | Tools menu planning and direct command execution dispatch now consume pure `pp_app_core` through `App::init_menu_tools`, `pano_cli plan-tools-menu`, `pano_cli plan-tools-panel`, and the `ToolsMenuServices` boundary, but live adapters still construct legacy `NodePanelFloating` panels, mutate legacy panel nodes, clear `CanvasModeGrid`, reset `NodeCanvas` camera state, open legacy shortcuts UI, and call the iOS SonarPen bridge directly | Preserve current Tools menu behavior while UI shell actions move toward app/UI/platform services | `pp_app_core_tools_menu_tests`; `pano_cli plan-tools-menu --command shortcuts`; `pano_cli plan-tools-panel --panel layers`; `pano_cli plan-tools-panel --panel animation --already-visible`; `ctest --preset desktop-fast --build-config Debug` | Tools panel creation, submenu routing, grid clear, camera reset, shortcuts dialog, and SonarPen dispatch are owned by injected app/UI/platform services with `App::init_menu_tools` acting only as a UI adapter and no legacy Tools adapter |
|
| DEBT-0033 | Open | Modernization | Tools menu planning and direct command execution dispatch now consume pure `pp_app_core` through `App::init_menu_tools`, `pano_cli plan-tools-menu`, `pano_cli plan-tools-panel`, and the `ToolsMenuServices` boundary, but live adapters still construct legacy `NodePanelFloating` panels, mutate legacy panel nodes, clear `CanvasModeGrid`, reset `NodeCanvas` camera state, open legacy shortcuts UI, and call the iOS SonarPen bridge directly | Preserve current Tools menu behavior while UI shell actions move toward app/UI/platform services | `pp_app_core_tools_menu_tests`; `pano_cli plan-tools-menu --command shortcuts`; `pano_cli plan-tools-panel --panel layers`; `pano_cli plan-tools-panel --panel animation --already-visible`; `ctest --preset desktop-fast --build-config Debug` | Tools panel creation, submenu routing, grid clear, camera reset, shortcuts dialog, and SonarPen dispatch are owned by injected app/UI/platform services with `App::init_menu_tools` acting only as a UI adapter and no legacy Tools adapter |
|
||||||
|
|||||||
@@ -527,8 +527,9 @@ commands now dispatch through `FileMenuServices` before legacy dialogs, pickers,
|
|||||||
platform services, cloud code, and canvas workflows continue.
|
platform services, cloud code, and canvas workflows continue.
|
||||||
`pano_cli plan-export-menu` exposes app-core planning for File menu export
|
`pano_cli plan-export-menu` exposes app-core planning for File menu export
|
||||||
choices, including image, layer, cube-face, depth, animation-frame, MP4, and
|
choices, including image, layer, cube-face, depth, animation-frame, MP4, and
|
||||||
timelapse dialog routing plus license/canvas gating before legacy export dialogs
|
timelapse dialog routing plus license/canvas gating. Export menu commands now
|
||||||
and renderer/video execution continue.
|
dispatch through `DocumentExportMenuServices` before legacy export dialogs and
|
||||||
|
renderer/video execution continue.
|
||||||
`pano_cli plan-grid-operation` exposes app-core planning for grid heightmap
|
`pano_cli plan-grid-operation` exposes app-core planning for grid heightmap
|
||||||
pick/load/reload/clear, lightmap render capability/limit checks, and heightmap
|
pick/load/reload/clear, lightmap render capability/limit checks, and heightmap
|
||||||
commit used by the live grid panel before legacy image loading, OpenGL texture
|
commit used by the live grid panel before legacy image loading, OpenGL texture
|
||||||
@@ -1256,7 +1257,8 @@ Results:
|
|||||||
menu routing as JSON automation.
|
menu routing as JSON automation.
|
||||||
- `pp_app_core_document_export_tests` passed, now also covering export menu
|
- `pp_app_core_document_export_tests` passed, now also covering export menu
|
||||||
dialog routing, demo-mode MP4/timelapse license gating, and missing-canvas
|
dialog routing, demo-mode MP4/timelapse license gating, and missing-canvas
|
||||||
handling before legacy export dialogs continue.
|
handling, plus export menu executor dispatch for all dialog, blocked, and
|
||||||
|
unavailable actions before legacy export dialogs continue.
|
||||||
- `pano_cli_plan_export_menu_png_smoke`,
|
- `pano_cli_plan_export_menu_png_smoke`,
|
||||||
`pano_cli_plan_export_menu_mp4_demo_blocked_smoke`,
|
`pano_cli_plan_export_menu_mp4_demo_blocked_smoke`,
|
||||||
`pano_cli_plan_export_menu_no_canvas_smoke`, and
|
`pano_cli_plan_export_menu_no_canvas_smoke`, and
|
||||||
|
|||||||
@@ -62,6 +62,21 @@ struct DocumentExportMenuPlan {
|
|||||||
bool opens_dialog = true;
|
bool opens_dialog = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class DocumentExportMenuServices {
|
||||||
|
public:
|
||||||
|
virtual ~DocumentExportMenuServices() = default;
|
||||||
|
|
||||||
|
virtual void show_jpeg_dialog() = 0;
|
||||||
|
virtual void show_png_dialog() = 0;
|
||||||
|
virtual void show_layers_dialog() = 0;
|
||||||
|
virtual void show_cube_faces_dialog() = 0;
|
||||||
|
virtual void show_depth_dialog() = 0;
|
||||||
|
virtual void show_animation_frames_dialog() = 0;
|
||||||
|
virtual void show_animation_mp4_dialog() = 0;
|
||||||
|
virtual void show_timelapse_dialog() = 0;
|
||||||
|
virtual void show_license_disabled() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
[[nodiscard]] constexpr DocumentExportStartDecision plan_document_export_start(
|
[[nodiscard]] constexpr DocumentExportStartDecision plan_document_export_start(
|
||||||
bool requires_license,
|
bool requires_license,
|
||||||
bool license_valid,
|
bool license_valid,
|
||||||
@@ -226,4 +241,43 @@ struct DocumentExportMenuPlan {
|
|||||||
return pp::foundation::Result<DocumentExportSuggestedName>::success(std::move(target));
|
return pp::foundation::Result<DocumentExportSuggestedName>::success(std::move(target));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] inline pp::foundation::Status execute_document_export_menu_plan(
|
||||||
|
const DocumentExportMenuPlan& plan,
|
||||||
|
DocumentExportMenuServices& services)
|
||||||
|
{
|
||||||
|
switch (plan.action) {
|
||||||
|
case DocumentExportMenuAction::show_jpeg_dialog:
|
||||||
|
services.show_jpeg_dialog();
|
||||||
|
return pp::foundation::Status::success();
|
||||||
|
case DocumentExportMenuAction::show_png_dialog:
|
||||||
|
services.show_png_dialog();
|
||||||
|
return pp::foundation::Status::success();
|
||||||
|
case DocumentExportMenuAction::show_layers_dialog:
|
||||||
|
services.show_layers_dialog();
|
||||||
|
return pp::foundation::Status::success();
|
||||||
|
case DocumentExportMenuAction::show_cube_faces_dialog:
|
||||||
|
services.show_cube_faces_dialog();
|
||||||
|
return pp::foundation::Status::success();
|
||||||
|
case DocumentExportMenuAction::show_depth_dialog:
|
||||||
|
services.show_depth_dialog();
|
||||||
|
return pp::foundation::Status::success();
|
||||||
|
case DocumentExportMenuAction::show_animation_frames_dialog:
|
||||||
|
services.show_animation_frames_dialog();
|
||||||
|
return pp::foundation::Status::success();
|
||||||
|
case DocumentExportMenuAction::show_animation_mp4_dialog:
|
||||||
|
services.show_animation_mp4_dialog();
|
||||||
|
return pp::foundation::Status::success();
|
||||||
|
case DocumentExportMenuAction::show_timelapse_dialog:
|
||||||
|
services.show_timelapse_dialog();
|
||||||
|
return pp::foundation::Status::success();
|
||||||
|
case DocumentExportMenuAction::show_license_disabled:
|
||||||
|
services.show_license_disabled();
|
||||||
|
return pp::foundation::Status::success();
|
||||||
|
case DocumentExportMenuAction::unavailable_no_canvas:
|
||||||
|
return pp::foundation::Status::success();
|
||||||
|
}
|
||||||
|
|
||||||
|
return pp::foundation::Status::invalid_argument("unknown document export menu action");
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -85,46 +85,40 @@ bool apply_brush_preset_plan(App& app, const std::shared_ptr<Brush>& brush)
|
|||||||
|
|
||||||
bool apply_document_export_menu_plan(App& app, pp::app::DocumentExportMenuKind kind)
|
bool apply_document_export_menu_plan(App& app, pp::app::DocumentExportMenuKind kind)
|
||||||
{
|
{
|
||||||
|
class LegacyDocumentExportMenuServices final : public pp::app::DocumentExportMenuServices {
|
||||||
|
public:
|
||||||
|
explicit LegacyDocumentExportMenuServices(App& app) noexcept
|
||||||
|
: app_(app)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void show_jpeg_dialog() override { app_.dialog_export(".jpg"); }
|
||||||
|
void show_png_dialog() override { app_.dialog_export(".png"); }
|
||||||
|
void show_layers_dialog() override { app_.dialog_export_layers(); }
|
||||||
|
void show_cube_faces_dialog() override { app_.dialog_export_cube_faces(); }
|
||||||
|
void show_depth_dialog() override { app_.dialog_export_depth(); }
|
||||||
|
void show_animation_frames_dialog() override { app_.dialog_export_anim_frames(); }
|
||||||
|
void show_animation_mp4_dialog() override { app_.dialog_export_mp4(); }
|
||||||
|
void show_timelapse_dialog() override { app_.dialog_timelapse_export(); }
|
||||||
|
void show_license_disabled() override
|
||||||
|
{
|
||||||
|
app_.message_box("License", "This function is disabled in demo mode.");
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
App& app_;
|
||||||
|
};
|
||||||
|
|
||||||
const auto requires_license = pp::app::document_export_menu_requires_license(kind);
|
const auto requires_license = pp::app::document_export_menu_requires_license(kind);
|
||||||
const auto plan = pp::app::plan_document_export_menu_action(
|
const auto plan = pp::app::plan_document_export_menu_action(
|
||||||
kind,
|
kind,
|
||||||
app.canvas != nullptr,
|
app.canvas != nullptr,
|
||||||
!requires_license || app.check_license());
|
!requires_license || app.check_license());
|
||||||
|
LegacyDocumentExportMenuServices services(app);
|
||||||
switch (plan.action)
|
const auto status = pp::app::execute_document_export_menu_plan(plan, services);
|
||||||
{
|
if (!status.ok())
|
||||||
case pp::app::DocumentExportMenuAction::show_jpeg_dialog:
|
LOG("Document export menu action failed: %s", status.message);
|
||||||
app.dialog_export(".jpg");
|
return status.ok() && plan.opens_dialog;
|
||||||
return true;
|
|
||||||
case pp::app::DocumentExportMenuAction::show_png_dialog:
|
|
||||||
app.dialog_export(".png");
|
|
||||||
return true;
|
|
||||||
case pp::app::DocumentExportMenuAction::show_layers_dialog:
|
|
||||||
app.dialog_export_layers();
|
|
||||||
return true;
|
|
||||||
case pp::app::DocumentExportMenuAction::show_cube_faces_dialog:
|
|
||||||
app.dialog_export_cube_faces();
|
|
||||||
return true;
|
|
||||||
case pp::app::DocumentExportMenuAction::show_depth_dialog:
|
|
||||||
app.dialog_export_depth();
|
|
||||||
return true;
|
|
||||||
case pp::app::DocumentExportMenuAction::show_animation_frames_dialog:
|
|
||||||
app.dialog_export_anim_frames();
|
|
||||||
return true;
|
|
||||||
case pp::app::DocumentExportMenuAction::show_animation_mp4_dialog:
|
|
||||||
app.dialog_export_mp4();
|
|
||||||
return true;
|
|
||||||
case pp::app::DocumentExportMenuAction::show_timelapse_dialog:
|
|
||||||
app.dialog_timelapse_export();
|
|
||||||
return true;
|
|
||||||
case pp::app::DocumentExportMenuAction::show_license_disabled:
|
|
||||||
app.message_box("License", "This function is disabled in demo mode.");
|
|
||||||
return false;
|
|
||||||
case pp::app::DocumentExportMenuAction::unavailable_no_canvas:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class LegacyFileMenuServices final : public pp::app::FileMenuServices {
|
class LegacyFileMenuServices final : public pp::app::FileMenuServices {
|
||||||
|
|||||||
@@ -3,6 +3,36 @@
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
class FakeDocumentExportMenuServices final : public pp::app::DocumentExportMenuServices {
|
||||||
|
public:
|
||||||
|
void show_jpeg_dialog() override { jpeg_dialogs += 1; }
|
||||||
|
void show_png_dialog() override { png_dialogs += 1; }
|
||||||
|
void show_layers_dialog() override { layer_dialogs += 1; }
|
||||||
|
void show_cube_faces_dialog() override { cube_dialogs += 1; }
|
||||||
|
void show_depth_dialog() override { depth_dialogs += 1; }
|
||||||
|
void show_animation_frames_dialog() override { animation_frame_dialogs += 1; }
|
||||||
|
void show_animation_mp4_dialog() override { animation_mp4_dialogs += 1; }
|
||||||
|
void show_timelapse_dialog() override { timelapse_dialogs += 1; }
|
||||||
|
void show_license_disabled() override { license_messages += 1; }
|
||||||
|
|
||||||
|
[[nodiscard]] int total_calls() const noexcept
|
||||||
|
{
|
||||||
|
return jpeg_dialogs + png_dialogs + layer_dialogs + cube_dialogs + depth_dialogs
|
||||||
|
+ animation_frame_dialogs + animation_mp4_dialogs + timelapse_dialogs
|
||||||
|
+ license_messages;
|
||||||
|
}
|
||||||
|
|
||||||
|
int jpeg_dialogs = 0;
|
||||||
|
int png_dialogs = 0;
|
||||||
|
int layer_dialogs = 0;
|
||||||
|
int cube_dialogs = 0;
|
||||||
|
int depth_dialogs = 0;
|
||||||
|
int animation_frame_dialogs = 0;
|
||||||
|
int animation_mp4_dialogs = 0;
|
||||||
|
int timelapse_dialogs = 0;
|
||||||
|
int license_messages = 0;
|
||||||
|
};
|
||||||
|
|
||||||
void equirectangular_export_builds_file_target(pp::tests::Harness& harness)
|
void equirectangular_export_builds_file_target(pp::tests::Harness& harness)
|
||||||
{
|
{
|
||||||
const auto target = pp::app::make_document_export_file_target("D:/Paint", "demo", ".png");
|
const auto target = pp::app::make_document_export_file_target("D:/Paint", "demo", ".png");
|
||||||
@@ -123,6 +153,106 @@ void export_menu_reports_missing_canvas_for_unlicensed_image_exports(pp::tests::
|
|||||||
PP_EXPECT(harness, !plan.opens_dialog);
|
PP_EXPECT(harness, !plan.opens_dialog);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void export_menu_executor_dispatches_all_dialog_actions(pp::tests::Harness& harness)
|
||||||
|
{
|
||||||
|
FakeDocumentExportMenuServices services;
|
||||||
|
|
||||||
|
PP_EXPECT(
|
||||||
|
harness,
|
||||||
|
pp::app::execute_document_export_menu_plan(
|
||||||
|
pp::app::plan_document_export_menu_action(
|
||||||
|
pp::app::DocumentExportMenuKind::jpeg,
|
||||||
|
true,
|
||||||
|
true),
|
||||||
|
services).ok());
|
||||||
|
PP_EXPECT(
|
||||||
|
harness,
|
||||||
|
pp::app::execute_document_export_menu_plan(
|
||||||
|
pp::app::plan_document_export_menu_action(
|
||||||
|
pp::app::DocumentExportMenuKind::png,
|
||||||
|
true,
|
||||||
|
true),
|
||||||
|
services).ok());
|
||||||
|
PP_EXPECT(
|
||||||
|
harness,
|
||||||
|
pp::app::execute_document_export_menu_plan(
|
||||||
|
pp::app::plan_document_export_menu_action(
|
||||||
|
pp::app::DocumentExportMenuKind::layers,
|
||||||
|
true,
|
||||||
|
true),
|
||||||
|
services).ok());
|
||||||
|
PP_EXPECT(
|
||||||
|
harness,
|
||||||
|
pp::app::execute_document_export_menu_plan(
|
||||||
|
pp::app::plan_document_export_menu_action(
|
||||||
|
pp::app::DocumentExportMenuKind::cube_faces,
|
||||||
|
true,
|
||||||
|
true),
|
||||||
|
services).ok());
|
||||||
|
PP_EXPECT(
|
||||||
|
harness,
|
||||||
|
pp::app::execute_document_export_menu_plan(
|
||||||
|
pp::app::plan_document_export_menu_action(
|
||||||
|
pp::app::DocumentExportMenuKind::depth,
|
||||||
|
true,
|
||||||
|
true),
|
||||||
|
services).ok());
|
||||||
|
PP_EXPECT(
|
||||||
|
harness,
|
||||||
|
pp::app::execute_document_export_menu_plan(
|
||||||
|
pp::app::plan_document_export_menu_action(
|
||||||
|
pp::app::DocumentExportMenuKind::animation_frames,
|
||||||
|
true,
|
||||||
|
true),
|
||||||
|
services).ok());
|
||||||
|
PP_EXPECT(
|
||||||
|
harness,
|
||||||
|
pp::app::execute_document_export_menu_plan(
|
||||||
|
pp::app::plan_document_export_menu_action(
|
||||||
|
pp::app::DocumentExportMenuKind::animation_mp4,
|
||||||
|
true,
|
||||||
|
true),
|
||||||
|
services).ok());
|
||||||
|
PP_EXPECT(
|
||||||
|
harness,
|
||||||
|
pp::app::execute_document_export_menu_plan(
|
||||||
|
pp::app::plan_document_export_menu_action(
|
||||||
|
pp::app::DocumentExportMenuKind::timelapse,
|
||||||
|
true,
|
||||||
|
true),
|
||||||
|
services).ok());
|
||||||
|
|
||||||
|
PP_EXPECT(harness, services.jpeg_dialogs == 1);
|
||||||
|
PP_EXPECT(harness, services.png_dialogs == 1);
|
||||||
|
PP_EXPECT(harness, services.layer_dialogs == 1);
|
||||||
|
PP_EXPECT(harness, services.cube_dialogs == 1);
|
||||||
|
PP_EXPECT(harness, services.depth_dialogs == 1);
|
||||||
|
PP_EXPECT(harness, services.animation_frame_dialogs == 1);
|
||||||
|
PP_EXPECT(harness, services.animation_mp4_dialogs == 1);
|
||||||
|
PP_EXPECT(harness, services.timelapse_dialogs == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void export_menu_executor_preserves_blocked_and_unavailable_actions(pp::tests::Harness& harness)
|
||||||
|
{
|
||||||
|
FakeDocumentExportMenuServices services;
|
||||||
|
|
||||||
|
const auto blocked = pp::app::plan_document_export_menu_action(
|
||||||
|
pp::app::DocumentExportMenuKind::animation_mp4,
|
||||||
|
true,
|
||||||
|
false);
|
||||||
|
PP_EXPECT(harness, blocked.action == pp::app::DocumentExportMenuAction::show_license_disabled);
|
||||||
|
PP_EXPECT(harness, pp::app::execute_document_export_menu_plan(blocked, services).ok());
|
||||||
|
PP_EXPECT(harness, services.license_messages == 1);
|
||||||
|
|
||||||
|
const auto unavailable = pp::app::plan_document_export_menu_action(
|
||||||
|
pp::app::DocumentExportMenuKind::png,
|
||||||
|
false,
|
||||||
|
true);
|
||||||
|
PP_EXPECT(harness, unavailable.action == pp::app::DocumentExportMenuAction::unavailable_no_canvas);
|
||||||
|
PP_EXPECT(harness, pp::app::execute_document_export_menu_plan(unavailable, services).ok());
|
||||||
|
PP_EXPECT(harness, services.total_calls() == 1);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
@@ -139,5 +269,7 @@ int main()
|
|||||||
harness.run("export menu routes image dialogs without license", export_menu_routes_image_dialogs_without_license);
|
harness.run("export menu routes image dialogs without license", export_menu_routes_image_dialogs_without_license);
|
||||||
harness.run("export menu blocks video when license is missing", export_menu_blocks_video_when_license_is_missing);
|
harness.run("export menu blocks video when license is missing", export_menu_blocks_video_when_license_is_missing);
|
||||||
harness.run("export menu reports missing canvas for unlicensed image exports", export_menu_reports_missing_canvas_for_unlicensed_image_exports);
|
harness.run("export menu reports missing canvas for unlicensed image exports", export_menu_reports_missing_canvas_for_unlicensed_image_exports);
|
||||||
|
harness.run("export menu executor dispatches all dialog actions", export_menu_executor_dispatches_all_dialog_actions);
|
||||||
|
harness.run("export menu executor preserves blocked and unavailable actions", export_menu_executor_preserves_blocked_and_unavailable_actions);
|
||||||
return harness.finish();
|
return harness.finish();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user