Extract tools menu planning

This commit is contained in:
2026-06-03 12:15:57 +02:00
parent fb844f79fd
commit c640519772
8 changed files with 651 additions and 51 deletions

View File

@@ -18,6 +18,7 @@
#include "app_core/grid_ui.h"
#include "app_core/history_ui.h"
#include "app_core/quick_ui.h"
#include "app_core/tools_menu.h"
#include "assets/image_format.h"
#include "assets/image_metadata.h"
#include "assets/image_pixels.h"
@@ -341,6 +342,16 @@ struct PlanQuickOperationArgs {
bool fire_event = false;
};
struct PlanToolsMenuArgs {
std::string command = "shortcuts";
bool sonarpen_available = false;
};
struct PlanToolsPanelArgs {
std::string panel = "layers";
bool already_visible = false;
};
struct SimulateAppSessionArgs {
bool has_canvas = true;
bool new_document = false;
@@ -650,6 +661,135 @@ const char* file_menu_action_name(pp::app::FileMenuAction action) noexcept
return "show-new-document-dialog";
}
const char* tools_menu_command_name(pp::app::ToolsMenuCommand command) noexcept
{
switch (command) {
case pp::app::ToolsMenuCommand::panels:
return "panels";
case pp::app::ToolsMenuCommand::options:
return "options";
case pp::app::ToolsMenuCommand::clear_grids:
return "clear-grids";
case pp::app::ToolsMenuCommand::reset_camera:
return "reset-camera";
case pp::app::ToolsMenuCommand::shortcuts:
return "shortcuts";
case pp::app::ToolsMenuCommand::sonarpen:
return "sonarpen";
}
return "shortcuts";
}
const char* tools_menu_action_name(pp::app::ToolsMenuAction action) noexcept
{
switch (action) {
case pp::app::ToolsMenuAction::show_panels_submenu:
return "show-panels-submenu";
case pp::app::ToolsMenuAction::show_options_submenu:
return "show-options-submenu";
case pp::app::ToolsMenuAction::clear_grid_overlays:
return "clear-grid-overlays";
case pp::app::ToolsMenuAction::reset_camera:
return "reset-camera";
case pp::app::ToolsMenuAction::show_shortcuts_dialog:
return "show-shortcuts-dialog";
case pp::app::ToolsMenuAction::start_sonarpen:
return "start-sonarpen";
case pp::app::ToolsMenuAction::no_op_unavailable:
return "no-op-unavailable";
}
return "no-op-unavailable";
}
const char* tools_panel_name(pp::app::ToolsPanel panel) noexcept
{
switch (panel) {
case pp::app::ToolsPanel::presets:
return "presets";
case pp::app::ToolsPanel::color:
return "color";
case pp::app::ToolsPanel::color_advanced:
return "color-advanced";
case pp::app::ToolsPanel::layers:
return "layers";
case pp::app::ToolsPanel::brush:
return "brush";
case pp::app::ToolsPanel::grids:
return "grids";
case pp::app::ToolsPanel::animation:
return "animation";
}
return "layers";
}
const char* tools_panel_action_name(pp::app::ToolsPanelAction action) noexcept
{
switch (action) {
case pp::app::ToolsPanelAction::open_floating_panel:
return "open-floating-panel";
case pp::app::ToolsPanelAction::no_op_already_visible:
return "no-op-already-visible";
}
return "no-op-already-visible";
}
pp::foundation::Result<pp::app::ToolsMenuCommand> parse_tools_menu_command(std::string_view command)
{
if (command == "panels") {
return pp::foundation::Result<pp::app::ToolsMenuCommand>::success(pp::app::ToolsMenuCommand::panels);
}
if (command == "options") {
return pp::foundation::Result<pp::app::ToolsMenuCommand>::success(pp::app::ToolsMenuCommand::options);
}
if (command == "clear-grids") {
return pp::foundation::Result<pp::app::ToolsMenuCommand>::success(pp::app::ToolsMenuCommand::clear_grids);
}
if (command == "reset-camera") {
return pp::foundation::Result<pp::app::ToolsMenuCommand>::success(pp::app::ToolsMenuCommand::reset_camera);
}
if (command == "shortcuts") {
return pp::foundation::Result<pp::app::ToolsMenuCommand>::success(pp::app::ToolsMenuCommand::shortcuts);
}
if (command == "sonarpen") {
return pp::foundation::Result<pp::app::ToolsMenuCommand>::success(pp::app::ToolsMenuCommand::sonarpen);
}
return pp::foundation::Result<pp::app::ToolsMenuCommand>::failure(
pp::foundation::Status::invalid_argument("unknown tools menu command"));
}
pp::foundation::Result<pp::app::ToolsPanel> parse_tools_panel(std::string_view panel)
{
if (panel == "presets") {
return pp::foundation::Result<pp::app::ToolsPanel>::success(pp::app::ToolsPanel::presets);
}
if (panel == "color") {
return pp::foundation::Result<pp::app::ToolsPanel>::success(pp::app::ToolsPanel::color);
}
if (panel == "color-advanced" || panel == "advanced-color") {
return pp::foundation::Result<pp::app::ToolsPanel>::success(pp::app::ToolsPanel::color_advanced);
}
if (panel == "layers") {
return pp::foundation::Result<pp::app::ToolsPanel>::success(pp::app::ToolsPanel::layers);
}
if (panel == "brush") {
return pp::foundation::Result<pp::app::ToolsPanel>::success(pp::app::ToolsPanel::brush);
}
if (panel == "grids" || panel == "grid") {
return pp::foundation::Result<pp::app::ToolsPanel>::success(pp::app::ToolsPanel::grids);
}
if (panel == "animation") {
return pp::foundation::Result<pp::app::ToolsPanel>::success(pp::app::ToolsPanel::animation);
}
return pp::foundation::Result<pp::app::ToolsPanel>::failure(
pp::foundation::Status::invalid_argument("unknown tools panel"));
}
const char* document_layer_rename_action_name(pp::app::DocumentLayerRenameAction action) noexcept
{
switch (action) {
@@ -1264,6 +1404,8 @@ void print_help()
<< " plan-recording-session [--running] [--frame-count N] [--platform-deletes-recorded-files]\n"
<< " plan-app-preferences [--ui-scale N] [--display-density N] [--current-scale N] [--scale-option N] [--viewport-scale N] [--rtl] [--timelapse-disabled] [--recording-running] [--vr-controllers-disabled] [--cursor-mode 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-panel --panel presets|color|color-advanced|layers|brush|grids|animation [--already-visible]\n"
<< " plan-canvas-clear [--no-canvas] [--r N] [--g N] [--b N] [--a N]\n"
<< " plan-image-import --width N --height N\n"
<< " plan-document-resize [--current-resolution N] [--selected-resolution-index N]\n"
@@ -2816,6 +2958,111 @@ int plan_app_preferences(int argc, char** argv)
return 0;
}
pp::foundation::Status parse_plan_tools_menu_args(
int argc,
char** argv,
PlanToolsMenuArgs& 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 == "--sonarpen-available") {
args.sonarpen_available = true;
} else {
return pp::foundation::Status::invalid_argument("unknown option");
}
}
return pp::foundation::Status::success();
}
int plan_tools_menu(int argc, char** argv)
{
PlanToolsMenuArgs args;
const auto status = parse_plan_tools_menu_args(argc, argv, args);
if (!status.ok()) {
print_error("plan-tools-menu", status.message);
return 2;
}
const auto command = parse_tools_menu_command(args.command);
if (!command) {
print_error("plan-tools-menu", command.status().message);
return 2;
}
const auto plan = pp::app::plan_tools_menu_command(command.value(), args.sonarpen_available);
std::cout << "{\"ok\":true,\"command\":\"plan-tools-menu\""
<< ",\"state\":{\"command\":\"" << json_escape(args.command)
<< "\",\"sonarpenAvailable\":" << json_bool(args.sonarpen_available)
<< "},\"plan\":{\"command\":\"" << tools_menu_command_name(plan.command)
<< "\",\"action\":\"" << tools_menu_action_name(plan.action)
<< "\",\"label\":\"" << json_escape(std::string(plan.label))
<< "\",\"closesRootPopup\":" << json_bool(plan.closes_root_popup)
<< "}}\n";
return 0;
}
pp::foundation::Status parse_plan_tools_panel_args(
int argc,
char** argv,
PlanToolsPanelArgs& args)
{
for (int i = 2; i < argc; ++i) {
const std::string_view key(argv[i]);
if (key == "--panel") {
if (i + 1 >= argc) {
return pp::foundation::Status::invalid_argument("missing value for option");
}
args.panel = argv[++i];
} else if (key == "--already-visible") {
args.already_visible = true;
} else {
return pp::foundation::Status::invalid_argument("unknown option");
}
}
return pp::foundation::Status::success();
}
int plan_tools_panel(int argc, char** argv)
{
PlanToolsPanelArgs args;
const auto status = parse_plan_tools_panel_args(argc, argv, args);
if (!status.ok()) {
print_error("plan-tools-panel", status.message);
return 2;
}
const auto panel = parse_tools_panel(args.panel);
if (!panel) {
print_error("plan-tools-panel", panel.status().message);
return 2;
}
const auto plan = pp::app::plan_tools_panel(panel.value(), args.already_visible);
std::cout << "{\"ok\":true,\"command\":\"plan-tools-panel\""
<< ",\"state\":{\"panel\":\"" << json_escape(args.panel)
<< "\",\"alreadyVisible\":" << json_bool(args.already_visible)
<< "},\"plan\":{\"panel\":\"" << tools_panel_name(plan.panel)
<< "\",\"action\":\"" << tools_panel_action_name(plan.action)
<< "\",\"title\":\"" << json_escape(std::string(plan.title))
<< "\",\"width\":" << plan.width
<< ",\"height\":" << plan.height
<< ",\"minWidth\":" << plan.min_width
<< ",\"minHeight\":" << plan.min_height
<< ",\"droppable\":" << json_bool(plan.droppable)
<< ",\"hidesEmbeddedTitle\":" << json_bool(plan.hides_embedded_title)
<< "}}\n";
return 0;
}
pp::foundation::Status parse_plan_app_status_args(
int argc,
char** argv,
@@ -6579,6 +6826,14 @@ int main(int argc, char** argv)
return plan_app_status(argc, argv);
}
if (command == "plan-tools-menu") {
return plan_tools_menu(argc, argv);
}
if (command == "plan-tools-panel") {
return plan_tools_panel(argc, argv);
}
if (command == "plan-document-resize") {
return plan_document_resize(argc, argv);
}