Extract about menu action planning
This commit is contained in:
@@ -223,6 +223,7 @@ target_link_libraries(pp_platform_api
|
|||||||
pp_project_warnings)
|
pp_project_warnings)
|
||||||
|
|
||||||
add_library(pp_app_core STATIC
|
add_library(pp_app_core STATIC
|
||||||
|
src/app_core/about_menu.h
|
||||||
src/app_core/app_preferences.h
|
src/app_core/app_preferences.h
|
||||||
src/app_core/app_status.h
|
src/app_core/app_status.h
|
||||||
src/app_core/brush_ui.h
|
src/app_core/brush_ui.h
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -545,6 +545,11 @@ grid-clear, and platform-only SonarPen gating before legacy UI/panel/canvas
|
|||||||
execution continues. The live animation panel route now also checks animation
|
execution continues. The live animation panel route now also checks animation
|
||||||
panel visibility and applies animation panel layout state instead of using the
|
panel visibility and applies animation panel layout state instead of using the
|
||||||
grid panel by mistake.
|
grid panel by mistake.
|
||||||
|
`pano_cli plan-about-menu` exposes app-core planning for About menu help,
|
||||||
|
about, what's-new, crash-test, and performance-test commands, including
|
||||||
|
versioned what's-new labels, diagnostic gating, and no-canvas performance-test
|
||||||
|
blocking before legacy dialogs, platform crash hooks, and Canvas performance
|
||||||
|
strokes continue.
|
||||||
`pp_platform_api` now owns a headless `PlatformServices` interface for
|
`pp_platform_api` now owns a headless `PlatformServices` interface for
|
||||||
startup storage path preparation, clipboard text, cursor visibility,
|
startup storage path preparation, clipboard text, cursor visibility,
|
||||||
virtual-keyboard visibility, UI-thread lifecycle hooks, render-context
|
virtual-keyboard visibility, UI-thread lifecycle hooks, render-context
|
||||||
@@ -1273,6 +1278,14 @@ Results:
|
|||||||
`pano_cli_plan_tools_panel_visible_noop_smoke`, and
|
`pano_cli_plan_tools_panel_visible_noop_smoke`, and
|
||||||
`pano_cli_plan_tools_panel_rejects_unknown` passed and expose live Tools
|
`pano_cli_plan_tools_panel_rejects_unknown` passed and expose live Tools
|
||||||
menu/panel planning as JSON automation.
|
menu/panel planning as JSON automation.
|
||||||
|
- `pp_app_core_about_menu_tests` passed, covering About/help/what's-new dialog
|
||||||
|
routing, versioned what's-new labels, crash diagnostic gating, performance
|
||||||
|
workload metadata, and no-canvas performance-test blocking.
|
||||||
|
- `pano_cli_plan_about_menu_news_smoke`,
|
||||||
|
`pano_cli_plan_about_menu_performance_no_canvas_smoke`,
|
||||||
|
`pano_cli_plan_about_menu_crash_disabled_smoke`, and
|
||||||
|
`pano_cli_plan_about_menu_rejects_unknown` passed and expose live About menu
|
||||||
|
planning as JSON automation.
|
||||||
- `pp_app_core_document_sharing_tests` passed, covering saved-path gating before
|
- `pp_app_core_document_sharing_tests` passed, covering saved-path gating before
|
||||||
platform share execution.
|
platform share execution.
|
||||||
- `pano_cli_plan_share_file_unsaved_smoke` and
|
- `pano_cli_plan_share_file_unsaved_smoke` and
|
||||||
|
|||||||
86
src/app_core/about_menu.h
Normal file
86
src/app_core/about_menu.h
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace pp::app {
|
||||||
|
|
||||||
|
enum class AboutMenuCommand {
|
||||||
|
help_guide,
|
||||||
|
about_app,
|
||||||
|
whats_new,
|
||||||
|
induce_crash,
|
||||||
|
performance_test,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class AboutMenuAction {
|
||||||
|
show_user_manual,
|
||||||
|
show_about_dialog,
|
||||||
|
show_whats_new_dialog,
|
||||||
|
trigger_crash_test,
|
||||||
|
run_performance_test,
|
||||||
|
no_op_unavailable,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct AboutMenuPlan {
|
||||||
|
AboutMenuCommand command = AboutMenuCommand::help_guide;
|
||||||
|
AboutMenuAction action = AboutMenuAction::show_user_manual;
|
||||||
|
std::string label;
|
||||||
|
bool closes_root_popup = true;
|
||||||
|
bool requires_canvas = false;
|
||||||
|
int performance_iterations = 0;
|
||||||
|
int performance_updates_per_iteration = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
[[nodiscard]] inline AboutMenuPlan plan_about_menu_command(
|
||||||
|
AboutMenuCommand command,
|
||||||
|
int version_major,
|
||||||
|
int version_minor,
|
||||||
|
int version_fix,
|
||||||
|
bool diagnostics_available = true,
|
||||||
|
bool has_canvas = true)
|
||||||
|
{
|
||||||
|
AboutMenuPlan plan;
|
||||||
|
plan.command = command;
|
||||||
|
|
||||||
|
switch (command) {
|
||||||
|
case AboutMenuCommand::help_guide:
|
||||||
|
plan.action = AboutMenuAction::show_user_manual;
|
||||||
|
plan.label = "Help Guide";
|
||||||
|
break;
|
||||||
|
case AboutMenuCommand::about_app:
|
||||||
|
plan.action = AboutMenuAction::show_about_dialog;
|
||||||
|
plan.label = "About PanoPainter";
|
||||||
|
break;
|
||||||
|
case AboutMenuCommand::whats_new:
|
||||||
|
plan.action = AboutMenuAction::show_whats_new_dialog;
|
||||||
|
plan.label = "What's new in "
|
||||||
|
+ std::to_string(version_major)
|
||||||
|
+ "."
|
||||||
|
+ std::to_string(version_minor)
|
||||||
|
+ "."
|
||||||
|
+ std::to_string(version_fix)
|
||||||
|
+ "?";
|
||||||
|
break;
|
||||||
|
case AboutMenuCommand::induce_crash:
|
||||||
|
plan.label = "Induce crash";
|
||||||
|
plan.action = diagnostics_available
|
||||||
|
? AboutMenuAction::trigger_crash_test
|
||||||
|
: AboutMenuAction::no_op_unavailable;
|
||||||
|
plan.closes_root_popup = diagnostics_available;
|
||||||
|
break;
|
||||||
|
case AboutMenuCommand::performance_test:
|
||||||
|
plan.label = has_canvas ? "Performance test" : "Performance test (No canvas)";
|
||||||
|
plan.requires_canvas = true;
|
||||||
|
plan.performance_iterations = 100;
|
||||||
|
plan.performance_updates_per_iteration = 10;
|
||||||
|
plan.action = has_canvas
|
||||||
|
? AboutMenuAction::run_performance_test
|
||||||
|
: AboutMenuAction::no_op_unavailable;
|
||||||
|
plan.closes_root_popup = has_canvas;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return plan;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -6,6 +6,7 @@
|
|||||||
#include "node_progress_bar.h"
|
#include "node_progress_bar.h"
|
||||||
#include "node_dialog_picker.h"
|
#include "node_dialog_picker.h"
|
||||||
#include "node_panel_floating.h"
|
#include "node_panel_floating.h"
|
||||||
|
#include "app_core/about_menu.h"
|
||||||
#include "app_core/app_preferences.h"
|
#include "app_core/app_preferences.h"
|
||||||
#include "app_core/brush_ui.h"
|
#include "app_core/brush_ui.h"
|
||||||
#include "app_core/canvas_tool_ui.h"
|
#include "app_core/canvas_tool_ui.h"
|
||||||
@@ -1495,54 +1496,105 @@ void App::init_menu_about()
|
|||||||
layout[main_id]->add_child(popup);
|
layout[main_id]->add_child(popup);
|
||||||
|
|
||||||
popup->find<NodeButtonCustom>("about-app")->on_click = [this, popup](Node*) {
|
popup->find<NodeButtonCustom>("about-app")->on_click = [this, popup](Node*) {
|
||||||
|
const auto plan = pp::app::plan_about_menu_command(
|
||||||
|
pp::app::AboutMenuCommand::about_app,
|
||||||
|
g_version_major,
|
||||||
|
g_version_minor,
|
||||||
|
g_version_fix);
|
||||||
|
if (plan.action == pp::app::AboutMenuAction::show_about_dialog)
|
||||||
dialog_about();
|
dialog_about();
|
||||||
|
if (plan.closes_root_popup)
|
||||||
|
{
|
||||||
popup->mouse_release();
|
popup->mouse_release();
|
||||||
popup->destroy();
|
popup->destroy();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
popup->find<NodeButtonCustom>("about-doc")->on_click = [this, popup](Node*) {
|
popup->find<NodeButtonCustom>("about-doc")->on_click = [this, popup](Node*) {
|
||||||
// auto path = Asset::absolute("data/doc/test.pdf");
|
// auto path = Asset::absolute("data/doc/test.pdf");
|
||||||
// display_file(path);
|
// 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);
|
||||||
|
if (plan.action == pp::app::AboutMenuAction::show_user_manual)
|
||||||
dialog_usermanual();
|
dialog_usermanual();
|
||||||
|
if (plan.closes_root_popup)
|
||||||
|
{
|
||||||
popup->mouse_release();
|
popup->mouse_release();
|
||||||
popup->destroy();
|
popup->destroy();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (auto item = popup->find<NodeButtonCustom>("about-news"))
|
if (auto item = popup->find<NodeButtonCustom>("about-news"))
|
||||||
{
|
{
|
||||||
if (auto text = item->find<NodeText>("menu-label"))
|
if (auto text = item->find<NodeText>("menu-label"))
|
||||||
{
|
{
|
||||||
static char label[128];
|
const auto plan = pp::app::plan_about_menu_command(
|
||||||
sprintf(label, "What's new in %d.%d.%d?", g_version_major, g_version_minor, g_version_fix);
|
pp::app::AboutMenuCommand::whats_new,
|
||||||
text->set_text(label);
|
g_version_major,
|
||||||
|
g_version_minor,
|
||||||
|
g_version_fix);
|
||||||
|
text->set_text(plan.label.c_str());
|
||||||
}
|
}
|
||||||
item->on_click = [this, popup](Node*) {
|
item->on_click = [this, popup](Node*) {
|
||||||
|
const auto plan = pp::app::plan_about_menu_command(
|
||||||
|
pp::app::AboutMenuCommand::whats_new,
|
||||||
|
g_version_major,
|
||||||
|
g_version_minor,
|
||||||
|
g_version_fix);
|
||||||
|
if (plan.action == pp::app::AboutMenuAction::show_whats_new_dialog)
|
||||||
dialog_whatsnew(true);
|
dialog_whatsnew(true);
|
||||||
|
if (plan.closes_root_popup)
|
||||||
|
{
|
||||||
popup->mouse_release();
|
popup->mouse_release();
|
||||||
popup->destroy();
|
popup->destroy();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (auto b = popup->find<NodeButtonCustom>("about-crash"))
|
if (auto b = popup->find<NodeButtonCustom>("about-crash"))
|
||||||
{
|
{
|
||||||
b->on_click = [this, popup](Node*) {
|
b->on_click = [this, popup](Node*) {
|
||||||
|
const auto plan = pp::app::plan_about_menu_command(
|
||||||
|
pp::app::AboutMenuCommand::induce_crash,
|
||||||
|
g_version_major,
|
||||||
|
g_version_minor,
|
||||||
|
g_version_fix);
|
||||||
|
if (plan.action == pp::app::AboutMenuAction::trigger_crash_test)
|
||||||
|
{
|
||||||
LOG("crashing");
|
LOG("crashing");
|
||||||
crash_test();
|
crash_test();
|
||||||
|
}
|
||||||
|
if (plan.closes_root_popup)
|
||||||
|
{
|
||||||
popup->mouse_release();
|
popup->mouse_release();
|
||||||
popup->destroy();
|
popup->destroy();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (auto b = popup->find<NodeButtonCustom>("about-perf"))
|
if (auto b = popup->find<NodeButtonCustom>("about-perf"))
|
||||||
{
|
{
|
||||||
b->on_click = [this, popup](Node*) {
|
b->on_click = [this, popup](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);
|
||||||
|
if (plan.action == pp::app::AboutMenuAction::run_performance_test)
|
||||||
|
{
|
||||||
LOG("perf");
|
LOG("perf");
|
||||||
static char str[256];
|
std::string message;
|
||||||
|
const int performance_iterations = plan.performance_iterations;
|
||||||
render_task([&]
|
render_task([&]
|
||||||
{
|
{
|
||||||
auto start = std::chrono::high_resolution_clock::now();
|
auto start = std::chrono::high_resolution_clock::now();
|
||||||
Canvas::I->stroke_start({ 0, 0, 0 }, 0.9f);
|
Canvas::I->stroke_start({ 0, 0, 0 }, 0.9f);
|
||||||
for (int i = 0; i < 100; i++)
|
for (int i = 0; i < performance_iterations; i++)
|
||||||
{
|
{
|
||||||
Canvas::I->stroke_update({ 100, 100, 0 }, 0.9f);
|
Canvas::I->stroke_update({ 100, 100, 0 }, 0.9f);
|
||||||
Canvas::I->stroke_update({ 200, 200, 0 }, 0.9f);
|
Canvas::I->stroke_update({ 200, 200, 0 }, 0.9f);
|
||||||
@@ -1560,11 +1612,15 @@ void App::init_menu_about()
|
|||||||
auto diff = std::chrono::high_resolution_clock::now() - start;
|
auto diff = std::chrono::high_resolution_clock::now() - start;
|
||||||
auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(diff).count();
|
auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(diff).count();
|
||||||
LOG("%lld ms", ms);
|
LOG("%lld ms", ms);
|
||||||
sprintf(str, "Time %lld ms", ms);
|
message = "Time " + std::to_string(ms) + " ms";
|
||||||
});
|
});
|
||||||
message_box("Performance test", str);
|
message_box("Performance test", message);
|
||||||
|
}
|
||||||
|
if (plan.closes_root_popup)
|
||||||
|
{
|
||||||
popup->mouse_release();
|
popup->mouse_release();
|
||||||
popup->destroy();
|
popup->destroy();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -268,6 +268,16 @@ add_test(NAME pp_ui_core_layout_xml_tests COMMAND pp_ui_core_layout_xml_tests)
|
|||||||
set_tests_properties(pp_ui_core_layout_xml_tests PROPERTIES
|
set_tests_properties(pp_ui_core_layout_xml_tests PROPERTIES
|
||||||
LABELS "ui;desktop-fast;fuzz")
|
LABELS "ui;desktop-fast;fuzz")
|
||||||
|
|
||||||
|
add_executable(pp_app_core_about_menu_tests
|
||||||
|
app_core/about_menu_tests.cpp)
|
||||||
|
target_link_libraries(pp_app_core_about_menu_tests PRIVATE
|
||||||
|
pp_app_core
|
||||||
|
pp_test_harness)
|
||||||
|
|
||||||
|
add_test(NAME pp_app_core_about_menu_tests COMMAND pp_app_core_about_menu_tests)
|
||||||
|
set_tests_properties(pp_app_core_about_menu_tests PROPERTIES
|
||||||
|
LABELS "app;ui;desktop-fast;fuzz")
|
||||||
|
|
||||||
add_executable(pp_app_core_brush_ui_tests
|
add_executable(pp_app_core_brush_ui_tests
|
||||||
app_core/brush_ui_tests.cpp)
|
app_core/brush_ui_tests.cpp)
|
||||||
target_link_libraries(pp_app_core_brush_ui_tests PRIVATE
|
target_link_libraries(pp_app_core_brush_ui_tests PRIVATE
|
||||||
@@ -851,6 +861,30 @@ if(TARGET pano_cli)
|
|||||||
LABELS "app;ui;integration;desktop-fast;fuzz"
|
LABELS "app;ui;integration;desktop-fast;fuzz"
|
||||||
WILL_FAIL TRUE)
|
WILL_FAIL TRUE)
|
||||||
|
|
||||||
|
add_test(NAME pano_cli_plan_about_menu_news_smoke
|
||||||
|
COMMAND pano_cli plan-about-menu --command news --version-major 2 --version-minor 5 --version-fix 7)
|
||||||
|
set_tests_properties(pano_cli_plan_about_menu_news_smoke PROPERTIES
|
||||||
|
LABELS "app;ui;integration;desktop-fast"
|
||||||
|
PASS_REGULAR_EXPRESSION "\"command\":\"plan-about-menu\".*\"command\":\"news\".*\"versionMajor\":2.*\"action\":\"show-whats-new-dialog\".*\"label\":\"What's new in 2.5.7\\?\".*\"closesRootPopup\":true")
|
||||||
|
|
||||||
|
add_test(NAME pano_cli_plan_about_menu_performance_no_canvas_smoke
|
||||||
|
COMMAND pano_cli plan-about-menu --command performance --no-canvas)
|
||||||
|
set_tests_properties(pano_cli_plan_about_menu_performance_no_canvas_smoke PROPERTIES
|
||||||
|
LABELS "app;ui;integration;desktop-fast;fuzz"
|
||||||
|
PASS_REGULAR_EXPRESSION "\"command\":\"plan-about-menu\".*\"hasCanvas\":false.*\"action\":\"no-op-unavailable\".*\"label\":\"Performance test \\(No canvas\\)\".*\"closesRootPopup\":false.*\"requiresCanvas\":true")
|
||||||
|
|
||||||
|
add_test(NAME pano_cli_plan_about_menu_crash_disabled_smoke
|
||||||
|
COMMAND pano_cli plan-about-menu --command crash --no-diagnostics)
|
||||||
|
set_tests_properties(pano_cli_plan_about_menu_crash_disabled_smoke PROPERTIES
|
||||||
|
LABELS "app;ui;integration;desktop-fast;fuzz"
|
||||||
|
PASS_REGULAR_EXPRESSION "\"command\":\"plan-about-menu\".*\"diagnosticsAvailable\":false.*\"action\":\"no-op-unavailable\".*\"closesRootPopup\":false")
|
||||||
|
|
||||||
|
add_test(NAME pano_cli_plan_about_menu_rejects_unknown
|
||||||
|
COMMAND pano_cli plan-about-menu --command missing)
|
||||||
|
set_tests_properties(pano_cli_plan_about_menu_rejects_unknown PROPERTIES
|
||||||
|
LABELS "app;ui;integration;desktop-fast;fuzz"
|
||||||
|
WILL_FAIL TRUE)
|
||||||
|
|
||||||
add_test(NAME pano_cli_plan_app_status_smoke
|
add_test(NAME pano_cli_plan_app_status_smoke
|
||||||
COMMAND pano_cli plan-app-status
|
COMMAND pano_cli plan-app-status
|
||||||
--doc-name demo
|
--doc-name demo
|
||||||
|
|||||||
81
tests/app_core/about_menu_tests.cpp
Normal file
81
tests/app_core/about_menu_tests.cpp
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
#include "app_core/about_menu.h"
|
||||||
|
#include "test_harness.h"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
void about_menu_maps_user_facing_dialog_actions(pp::tests::Harness& harness)
|
||||||
|
{
|
||||||
|
const auto help = pp::app::plan_about_menu_command(pp::app::AboutMenuCommand::help_guide, 1, 2, 3);
|
||||||
|
const auto about = pp::app::plan_about_menu_command(pp::app::AboutMenuCommand::about_app, 1, 2, 3);
|
||||||
|
const auto news = pp::app::plan_about_menu_command(pp::app::AboutMenuCommand::whats_new, 1, 2, 3);
|
||||||
|
|
||||||
|
PP_EXPECT(harness, help.action == pp::app::AboutMenuAction::show_user_manual);
|
||||||
|
PP_EXPECT(harness, help.label == "Help Guide");
|
||||||
|
PP_EXPECT(harness, help.closes_root_popup);
|
||||||
|
PP_EXPECT(harness, about.action == pp::app::AboutMenuAction::show_about_dialog);
|
||||||
|
PP_EXPECT(harness, about.label == "About PanoPainter");
|
||||||
|
PP_EXPECT(harness, news.action == pp::app::AboutMenuAction::show_whats_new_dialog);
|
||||||
|
PP_EXPECT(harness, news.label == "What's new in 1.2.3?");
|
||||||
|
}
|
||||||
|
|
||||||
|
void about_menu_gates_diagnostic_crash_action(pp::tests::Harness& harness)
|
||||||
|
{
|
||||||
|
const auto enabled = pp::app::plan_about_menu_command(
|
||||||
|
pp::app::AboutMenuCommand::induce_crash,
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
3,
|
||||||
|
true);
|
||||||
|
const auto disabled = pp::app::plan_about_menu_command(
|
||||||
|
pp::app::AboutMenuCommand::induce_crash,
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
3,
|
||||||
|
false);
|
||||||
|
|
||||||
|
PP_EXPECT(harness, enabled.action == pp::app::AboutMenuAction::trigger_crash_test);
|
||||||
|
PP_EXPECT(harness, enabled.closes_root_popup);
|
||||||
|
PP_EXPECT(harness, disabled.action == pp::app::AboutMenuAction::no_op_unavailable);
|
||||||
|
PP_EXPECT(harness, !disabled.closes_root_popup);
|
||||||
|
}
|
||||||
|
|
||||||
|
void about_menu_performance_test_declares_workload_and_canvas_requirement(pp::tests::Harness& harness)
|
||||||
|
{
|
||||||
|
const auto available = pp::app::plan_about_menu_command(
|
||||||
|
pp::app::AboutMenuCommand::performance_test,
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
3,
|
||||||
|
true,
|
||||||
|
true);
|
||||||
|
const auto no_canvas = pp::app::plan_about_menu_command(
|
||||||
|
pp::app::AboutMenuCommand::performance_test,
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
3,
|
||||||
|
true,
|
||||||
|
false);
|
||||||
|
|
||||||
|
PP_EXPECT(harness, available.action == pp::app::AboutMenuAction::run_performance_test);
|
||||||
|
PP_EXPECT(harness, available.requires_canvas);
|
||||||
|
PP_EXPECT(harness, available.performance_iterations == 100);
|
||||||
|
PP_EXPECT(harness, available.performance_updates_per_iteration == 10);
|
||||||
|
PP_EXPECT(harness, available.closes_root_popup);
|
||||||
|
PP_EXPECT(harness, no_canvas.action == pp::app::AboutMenuAction::no_op_unavailable);
|
||||||
|
PP_EXPECT(harness, no_canvas.label == "Performance test (No canvas)");
|
||||||
|
PP_EXPECT(harness, no_canvas.requires_canvas);
|
||||||
|
PP_EXPECT(harness, !no_canvas.closes_root_popup);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
pp::tests::Harness harness;
|
||||||
|
harness.run("about menu maps user facing dialog actions", about_menu_maps_user_facing_dialog_actions);
|
||||||
|
harness.run("about menu gates diagnostic crash action", about_menu_gates_diagnostic_crash_action);
|
||||||
|
harness.run(
|
||||||
|
"about menu performance test declares workload and canvas requirement",
|
||||||
|
about_menu_performance_test_declares_workload_and_canvas_requirement);
|
||||||
|
return harness.finish();
|
||||||
|
}
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
#include "app_core/about_menu.h"
|
||||||
#include "app_core/app_preferences.h"
|
#include "app_core/app_preferences.h"
|
||||||
#include "app_core/app_status.h"
|
#include "app_core/app_status.h"
|
||||||
#include "app_core/brush_ui.h"
|
#include "app_core/brush_ui.h"
|
||||||
@@ -352,6 +353,15 @@ struct PlanToolsPanelArgs {
|
|||||||
bool already_visible = false;
|
bool already_visible = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct PlanAboutMenuArgs {
|
||||||
|
std::string command = "news";
|
||||||
|
int version_major = 1;
|
||||||
|
int version_minor = 0;
|
||||||
|
int version_fix = 0;
|
||||||
|
bool diagnostics_available = true;
|
||||||
|
bool has_canvas = true;
|
||||||
|
};
|
||||||
|
|
||||||
struct SimulateAppSessionArgs {
|
struct SimulateAppSessionArgs {
|
||||||
bool has_canvas = true;
|
bool has_canvas = true;
|
||||||
bool new_document = false;
|
bool new_document = false;
|
||||||
@@ -737,6 +747,44 @@ const char* tools_panel_action_name(pp::app::ToolsPanelAction action) noexcept
|
|||||||
return "no-op-already-visible";
|
return "no-op-already-visible";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char* about_menu_command_name(pp::app::AboutMenuCommand command) noexcept
|
||||||
|
{
|
||||||
|
switch (command) {
|
||||||
|
case pp::app::AboutMenuCommand::help_guide:
|
||||||
|
return "help";
|
||||||
|
case pp::app::AboutMenuCommand::about_app:
|
||||||
|
return "about";
|
||||||
|
case pp::app::AboutMenuCommand::whats_new:
|
||||||
|
return "news";
|
||||||
|
case pp::app::AboutMenuCommand::induce_crash:
|
||||||
|
return "crash";
|
||||||
|
case pp::app::AboutMenuCommand::performance_test:
|
||||||
|
return "performance";
|
||||||
|
}
|
||||||
|
|
||||||
|
return "help";
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* about_menu_action_name(pp::app::AboutMenuAction action) noexcept
|
||||||
|
{
|
||||||
|
switch (action) {
|
||||||
|
case pp::app::AboutMenuAction::show_user_manual:
|
||||||
|
return "show-user-manual";
|
||||||
|
case pp::app::AboutMenuAction::show_about_dialog:
|
||||||
|
return "show-about-dialog";
|
||||||
|
case pp::app::AboutMenuAction::show_whats_new_dialog:
|
||||||
|
return "show-whats-new-dialog";
|
||||||
|
case pp::app::AboutMenuAction::trigger_crash_test:
|
||||||
|
return "trigger-crash-test";
|
||||||
|
case pp::app::AboutMenuAction::run_performance_test:
|
||||||
|
return "run-performance-test";
|
||||||
|
case pp::app::AboutMenuAction::no_op_unavailable:
|
||||||
|
return "no-op-unavailable";
|
||||||
|
}
|
||||||
|
|
||||||
|
return "no-op-unavailable";
|
||||||
|
}
|
||||||
|
|
||||||
pp::foundation::Result<pp::app::ToolsMenuCommand> parse_tools_menu_command(std::string_view command)
|
pp::foundation::Result<pp::app::ToolsMenuCommand> parse_tools_menu_command(std::string_view command)
|
||||||
{
|
{
|
||||||
if (command == "panels") {
|
if (command == "panels") {
|
||||||
@@ -790,6 +838,33 @@ pp::foundation::Result<pp::app::ToolsPanel> parse_tools_panel(std::string_view p
|
|||||||
pp::foundation::Status::invalid_argument("unknown tools panel"));
|
pp::foundation::Status::invalid_argument("unknown tools panel"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pp::foundation::Result<pp::app::AboutMenuCommand> parse_about_menu_command(std::string_view command)
|
||||||
|
{
|
||||||
|
if (command == "help" || command == "help-guide" || command == "manual") {
|
||||||
|
return pp::foundation::Result<pp::app::AboutMenuCommand>::success(
|
||||||
|
pp::app::AboutMenuCommand::help_guide);
|
||||||
|
}
|
||||||
|
if (command == "about" || command == "about-app") {
|
||||||
|
return pp::foundation::Result<pp::app::AboutMenuCommand>::success(
|
||||||
|
pp::app::AboutMenuCommand::about_app);
|
||||||
|
}
|
||||||
|
if (command == "news" || command == "whats-new") {
|
||||||
|
return pp::foundation::Result<pp::app::AboutMenuCommand>::success(
|
||||||
|
pp::app::AboutMenuCommand::whats_new);
|
||||||
|
}
|
||||||
|
if (command == "crash" || command == "induce-crash") {
|
||||||
|
return pp::foundation::Result<pp::app::AboutMenuCommand>::success(
|
||||||
|
pp::app::AboutMenuCommand::induce_crash);
|
||||||
|
}
|
||||||
|
if (command == "performance" || command == "perf") {
|
||||||
|
return pp::foundation::Result<pp::app::AboutMenuCommand>::success(
|
||||||
|
pp::app::AboutMenuCommand::performance_test);
|
||||||
|
}
|
||||||
|
|
||||||
|
return pp::foundation::Result<pp::app::AboutMenuCommand>::failure(
|
||||||
|
pp::foundation::Status::invalid_argument("unknown about menu command"));
|
||||||
|
}
|
||||||
|
|
||||||
const char* document_layer_rename_action_name(pp::app::DocumentLayerRenameAction action) noexcept
|
const char* document_layer_rename_action_name(pp::app::DocumentLayerRenameAction action) noexcept
|
||||||
{
|
{
|
||||||
switch (action) {
|
switch (action) {
|
||||||
@@ -1406,6 +1481,7 @@ void print_help()
|
|||||||
<< " plan-app-status [--doc-name NAME] [--unsaved] [--resolution N] [--resolution-index N] [--zoom N] [--history-bytes N] [--recording-running] [--encoder-available] [--encoded-frames N]\n"
|
<< " plan-app-status [--doc-name NAME] [--unsaved] [--resolution N] [--resolution-index N] [--zoom N] [--history-bytes N] [--recording-running] [--encoder-available] [--encoded-frames N]\n"
|
||||||
<< " plan-tools-menu --command panels|options|clear-grids|reset-camera|shortcuts|sonarpen [--sonarpen-available]\n"
|
<< " plan-tools-menu --command panels|options|clear-grids|reset-camera|shortcuts|sonarpen [--sonarpen-available]\n"
|
||||||
<< " plan-tools-panel --panel presets|color|color-advanced|layers|brush|grids|animation [--already-visible]\n"
|
<< " plan-tools-panel --panel presets|color|color-advanced|layers|brush|grids|animation [--already-visible]\n"
|
||||||
|
<< " plan-about-menu --command help|about|news|crash|performance [--version-major N] [--version-minor N] [--version-fix N] [--no-diagnostics] [--no-canvas]\n"
|
||||||
<< " plan-canvas-clear [--no-canvas] [--r N] [--g N] [--b N] [--a N]\n"
|
<< " plan-canvas-clear [--no-canvas] [--r N] [--g N] [--b N] [--a N]\n"
|
||||||
<< " plan-image-import --width N --height N\n"
|
<< " plan-image-import --width N --height N\n"
|
||||||
<< " plan-document-resize [--current-resolution N] [--selected-resolution-index N]\n"
|
<< " plan-document-resize [--current-resolution N] [--selected-resolution-index N]\n"
|
||||||
@@ -3063,6 +3139,86 @@ int plan_tools_panel(int argc, char** argv)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pp::foundation::Status parse_plan_about_menu_args(
|
||||||
|
int argc,
|
||||||
|
char** argv,
|
||||||
|
PlanAboutMenuArgs& args)
|
||||||
|
{
|
||||||
|
for (int i = 2; i < argc; ++i) {
|
||||||
|
const std::string_view key(argv[i]);
|
||||||
|
if (key == "--command") {
|
||||||
|
if (i + 1 >= argc) {
|
||||||
|
return pp::foundation::Status::invalid_argument("missing value for option");
|
||||||
|
}
|
||||||
|
args.command = argv[++i];
|
||||||
|
} else if (key == "--version-major" || key == "--version-minor" || key == "--version-fix") {
|
||||||
|
if (i + 1 >= argc) {
|
||||||
|
return pp::foundation::Status::invalid_argument("missing value for option");
|
||||||
|
}
|
||||||
|
const auto value = parse_i32_arg(argv[++i]);
|
||||||
|
if (!value) {
|
||||||
|
return value.status();
|
||||||
|
}
|
||||||
|
if (key == "--version-major") {
|
||||||
|
args.version_major = value.value();
|
||||||
|
} else if (key == "--version-minor") {
|
||||||
|
args.version_minor = value.value();
|
||||||
|
} else {
|
||||||
|
args.version_fix = value.value();
|
||||||
|
}
|
||||||
|
} else if (key == "--no-diagnostics") {
|
||||||
|
args.diagnostics_available = false;
|
||||||
|
} else if (key == "--no-canvas") {
|
||||||
|
args.has_canvas = false;
|
||||||
|
} else {
|
||||||
|
return pp::foundation::Status::invalid_argument("unknown option");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return pp::foundation::Status::success();
|
||||||
|
}
|
||||||
|
|
||||||
|
int plan_about_menu(int argc, char** argv)
|
||||||
|
{
|
||||||
|
PlanAboutMenuArgs args;
|
||||||
|
const auto status = parse_plan_about_menu_args(argc, argv, args);
|
||||||
|
if (!status.ok()) {
|
||||||
|
print_error("plan-about-menu", status.message);
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto command = parse_about_menu_command(args.command);
|
||||||
|
if (!command) {
|
||||||
|
print_error("plan-about-menu", command.status().message);
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto plan = pp::app::plan_about_menu_command(
|
||||||
|
command.value(),
|
||||||
|
args.version_major,
|
||||||
|
args.version_minor,
|
||||||
|
args.version_fix,
|
||||||
|
args.diagnostics_available,
|
||||||
|
args.has_canvas);
|
||||||
|
|
||||||
|
std::cout << "{\"ok\":true,\"command\":\"plan-about-menu\""
|
||||||
|
<< ",\"state\":{\"command\":\"" << json_escape(args.command)
|
||||||
|
<< "\",\"versionMajor\":" << args.version_major
|
||||||
|
<< ",\"versionMinor\":" << args.version_minor
|
||||||
|
<< ",\"versionFix\":" << args.version_fix
|
||||||
|
<< ",\"diagnosticsAvailable\":" << json_bool(args.diagnostics_available)
|
||||||
|
<< ",\"hasCanvas\":" << json_bool(args.has_canvas)
|
||||||
|
<< "},\"plan\":{\"command\":\"" << about_menu_command_name(plan.command)
|
||||||
|
<< "\",\"action\":\"" << about_menu_action_name(plan.action)
|
||||||
|
<< "\",\"label\":\"" << json_escape(plan.label)
|
||||||
|
<< "\",\"closesRootPopup\":" << json_bool(plan.closes_root_popup)
|
||||||
|
<< ",\"requiresCanvas\":" << json_bool(plan.requires_canvas)
|
||||||
|
<< ",\"performanceIterations\":" << plan.performance_iterations
|
||||||
|
<< ",\"performanceUpdatesPerIteration\":" << plan.performance_updates_per_iteration
|
||||||
|
<< "}}\n";
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
pp::foundation::Status parse_plan_app_status_args(
|
pp::foundation::Status parse_plan_app_status_args(
|
||||||
int argc,
|
int argc,
|
||||||
char** argv,
|
char** argv,
|
||||||
@@ -6834,6 +6990,10 @@ int main(int argc, char** argv)
|
|||||||
return plan_tools_panel(argc, argv);
|
return plan_tools_panel(argc, argv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (command == "plan-about-menu") {
|
||||||
|
return plan_about_menu(argc, argv);
|
||||||
|
}
|
||||||
|
|
||||||
if (command == "plan-document-resize") {
|
if (command == "plan-document-resize") {
|
||||||
return plan_document_resize(argc, argv);
|
return plan_document_resize(argc, argv);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user