Add canvas tool service boundary

This commit is contained in:
2026-06-03 13:42:34 +02:00
parent 45a7d49d40
commit 9c7c89fed4
6 changed files with 309 additions and 50 deletions

View File

@@ -1,8 +1,55 @@
#include "app_core/canvas_tool_ui.h"
#include "test_harness.h"
#include <string>
namespace {
class FakeCanvasToolServices final : public pp::app::CanvasToolServices {
public:
void select_toolbar_button(pp::app::CanvasToolMode mode) override
{
toolbar_selections += 1;
last_mode = mode;
call_order += "select;";
}
void set_transform_action(pp::app::CanvasToolTransformAction action) override
{
transform_sets += 1;
last_transform_action = action;
call_order += "transform;";
}
void set_canvas_mode(pp::app::CanvasToolMode mode) override
{
mode_sets += 1;
last_mode = mode;
call_order += "mode;";
}
void toggle_picking() override
{
picking_toggles += 1;
call_order += "pick;";
}
void toggle_touch_lock() override
{
touch_lock_toggles += 1;
call_order += "touch;";
}
int toolbar_selections = 0;
int transform_sets = 0;
int mode_sets = 0;
int picking_toggles = 0;
int touch_lock_toggles = 0;
pp::app::CanvasToolMode last_mode = pp::app::CanvasToolMode::draw;
pp::app::CanvasToolTransformAction last_transform_action = pp::app::CanvasToolTransformAction::none;
std::string call_order;
};
void selection_plans_canvas_modes(pp::tests::Harness& harness)
{
const auto draw = pp::app::plan_canvas_tool_select(pp::app::CanvasToolMode::draw);
@@ -81,6 +128,74 @@ void button_state_tracks_active_mode_and_toggles(pp::tests::Harness& harness)
PP_EXPECT(harness, !bucket.mask_line_active);
}
void executor_dispatches_tool_actions(pp::tests::Harness& harness)
{
FakeCanvasToolServices services;
PP_EXPECT(harness, pp::app::execute_canvas_tool_plan(
pp::app::plan_canvas_tool_select(pp::app::CanvasToolMode::copy),
services).ok());
PP_EXPECT(harness, pp::app::execute_canvas_tool_plan(
pp::app::plan_canvas_tool_pick_toggle(true),
services).ok());
PP_EXPECT(harness, pp::app::execute_canvas_tool_plan(
pp::app::plan_canvas_tool_touch_lock_toggle(),
services).ok());
PP_EXPECT(harness, services.toolbar_selections == 1);
PP_EXPECT(harness, services.transform_sets == 1);
PP_EXPECT(harness, services.mode_sets == 1);
PP_EXPECT(harness, services.picking_toggles == 1);
PP_EXPECT(harness, services.touch_lock_toggles == 1);
PP_EXPECT(harness, services.last_mode == pp::app::CanvasToolMode::copy);
PP_EXPECT(harness, services.last_transform_action == pp::app::CanvasToolTransformAction::copy);
PP_EXPECT(harness, services.call_order == "select;transform;mode;pick;touch;");
}
void executor_no_ops_pick_when_not_in_draw_mode(pp::tests::Harness& harness)
{
FakeCanvasToolServices services;
PP_EXPECT(harness, pp::app::execute_canvas_tool_plan(
pp::app::plan_canvas_tool_pick_toggle(false),
services).ok());
PP_EXPECT(harness, services.toolbar_selections == 0);
PP_EXPECT(harness, services.mode_sets == 0);
PP_EXPECT(harness, services.picking_toggles == 0);
PP_EXPECT(harness, services.call_order.empty());
}
void executor_rejects_malformed_plans(pp::tests::Harness& harness)
{
FakeCanvasToolServices services;
auto select = pp::app::plan_canvas_tool_select(pp::app::CanvasToolMode::copy);
select.transform_action = pp::app::CanvasToolTransformAction::cut;
PP_EXPECT(harness, !pp::app::execute_canvas_tool_plan(select, services).ok());
auto missing_update = pp::app::plan_canvas_tool_select(pp::app::CanvasToolMode::draw);
missing_update.updates_canvas_mode = false;
PP_EXPECT(harness, !pp::app::execute_canvas_tool_plan(missing_update, services).ok());
pp::app::CanvasToolPlan pick;
pick.operation = pp::app::CanvasToolOperation::toggle_picking;
pick.requires_draw_mode = false;
pick.toggles_picking = true;
PP_EXPECT(harness, !pp::app::execute_canvas_tool_plan(pick, services).ok());
pp::app::CanvasToolPlan touch;
touch.operation = pp::app::CanvasToolOperation::toggle_touch_lock;
touch.toggles_touch_lock = false;
PP_EXPECT(harness, !pp::app::execute_canvas_tool_plan(touch, services).ok());
PP_EXPECT(harness, services.toolbar_selections == 0);
PP_EXPECT(harness, services.transform_sets == 0);
PP_EXPECT(harness, services.mode_sets == 0);
PP_EXPECT(harness, services.picking_toggles == 0);
PP_EXPECT(harness, services.touch_lock_toggles == 0);
}
} // namespace
int main()
@@ -90,5 +205,8 @@ int main()
harness.run("transform tools plan copy and cut actions", transform_tools_plan_copy_and_cut_actions);
harness.run("pick and touch lock toggle state", pick_and_touch_lock_toggle_state);
harness.run("button state tracks active mode and toggles", button_state_tracks_active_mode_and_toggles);
harness.run("executor dispatches tool actions", executor_dispatches_tool_actions);
harness.run("executor no-ops pick when not in draw mode", executor_no_ops_pick_when_not_in_draw_mode);
harness.run("executor rejects malformed plans", executor_rejects_malformed_plans);
return harness.finish();
}