Dispatch layer operations through app core
This commit is contained in:
@@ -31,6 +31,110 @@ public:
|
||||
int last_to_index = -1;
|
||||
};
|
||||
|
||||
class FakeDocumentLayerOperationServices final : public pp::app::DocumentLayerOperationServices {
|
||||
public:
|
||||
void add_layer(std::string_view name, int insert_index) override
|
||||
{
|
||||
add_calls += 1;
|
||||
last_name = std::string(name);
|
||||
last_insert_index = insert_index;
|
||||
}
|
||||
|
||||
void duplicate_layer(int source_index, int insert_index) override
|
||||
{
|
||||
duplicate_calls += 1;
|
||||
last_source_index = source_index;
|
||||
last_insert_index = insert_index;
|
||||
}
|
||||
|
||||
void select_layer(int index) override
|
||||
{
|
||||
select_calls += 1;
|
||||
last_index = index;
|
||||
}
|
||||
|
||||
void reorder_layer(int from_index, int to_index) override
|
||||
{
|
||||
reorder_calls += 1;
|
||||
last_from_index = from_index;
|
||||
last_to_index = to_index;
|
||||
}
|
||||
|
||||
void remove_layer(int index) override
|
||||
{
|
||||
remove_calls += 1;
|
||||
last_index = index;
|
||||
}
|
||||
|
||||
void set_layer_opacity(int index, float opacity) override
|
||||
{
|
||||
opacity_calls += 1;
|
||||
last_index = index;
|
||||
last_opacity = opacity;
|
||||
}
|
||||
|
||||
void set_layer_visibility(int index, bool visible) override
|
||||
{
|
||||
visibility_calls += 1;
|
||||
last_index = index;
|
||||
last_flag = visible;
|
||||
}
|
||||
|
||||
void set_layer_alpha_lock(int index, bool locked) override
|
||||
{
|
||||
alpha_lock_calls += 1;
|
||||
last_index = index;
|
||||
last_flag = locked;
|
||||
}
|
||||
|
||||
void set_layer_blend_mode(int index, int blend_mode) override
|
||||
{
|
||||
blend_mode_calls += 1;
|
||||
last_index = index;
|
||||
last_blend_mode = blend_mode;
|
||||
}
|
||||
|
||||
void set_layer_highlight(int index, bool highlighted) override
|
||||
{
|
||||
highlight_calls += 1;
|
||||
last_index = index;
|
||||
last_flag = highlighted;
|
||||
}
|
||||
|
||||
void mark_unsaved() override { unsaved_marks += 1; }
|
||||
void reload_animation_layers() override { animation_reloads += 1; }
|
||||
void update_title() override { title_updates += 1; }
|
||||
|
||||
[[nodiscard]] int mutation_calls() const noexcept
|
||||
{
|
||||
return add_calls + duplicate_calls + reorder_calls + remove_calls + opacity_calls
|
||||
+ visibility_calls + alpha_lock_calls + blend_mode_calls;
|
||||
}
|
||||
|
||||
int add_calls = 0;
|
||||
int duplicate_calls = 0;
|
||||
int select_calls = 0;
|
||||
int reorder_calls = 0;
|
||||
int remove_calls = 0;
|
||||
int opacity_calls = 0;
|
||||
int visibility_calls = 0;
|
||||
int alpha_lock_calls = 0;
|
||||
int blend_mode_calls = 0;
|
||||
int highlight_calls = 0;
|
||||
int unsaved_marks = 0;
|
||||
int animation_reloads = 0;
|
||||
int title_updates = 0;
|
||||
int last_index = -1;
|
||||
int last_from_index = -1;
|
||||
int last_to_index = -1;
|
||||
int last_insert_index = -1;
|
||||
int last_source_index = -1;
|
||||
int last_blend_mode = -1;
|
||||
float last_opacity = -1.0F;
|
||||
bool last_flag = false;
|
||||
std::string last_name;
|
||||
};
|
||||
|
||||
void layer_rename_records_changed_name(pp::tests::Harness& harness)
|
||||
{
|
||||
const auto plan = pp::app::plan_document_layer_rename("Base", "Paint");
|
||||
@@ -203,6 +307,162 @@ void layer_highlight_is_transient(pp::tests::Harness& harness)
|
||||
PP_EXPECT(harness, !pp::app::plan_document_layer_highlight(2, 2, true));
|
||||
}
|
||||
|
||||
void layer_operation_executor_dispatches_document_mutations(pp::tests::Harness& harness)
|
||||
{
|
||||
FakeDocumentLayerOperationServices services;
|
||||
|
||||
const auto add = pp::app::plan_document_layer_add(2, 1, "Paint");
|
||||
PP_EXPECT(harness, add);
|
||||
if (add) {
|
||||
PP_EXPECT(harness, pp::app::execute_document_layer_operation_plan(add.value(), services).ok());
|
||||
PP_EXPECT(harness, services.add_calls == 1);
|
||||
PP_EXPECT(harness, services.last_name == "Paint");
|
||||
PP_EXPECT(harness, services.last_insert_index == 1);
|
||||
PP_EXPECT(harness, services.unsaved_marks == 1);
|
||||
PP_EXPECT(harness, services.animation_reloads == 1);
|
||||
PP_EXPECT(harness, services.title_updates == 1);
|
||||
}
|
||||
|
||||
const auto duplicate = pp::app::plan_document_layer_duplicate(3, 1);
|
||||
PP_EXPECT(harness, duplicate);
|
||||
if (duplicate) {
|
||||
PP_EXPECT(harness, pp::app::execute_document_layer_operation_plan(duplicate.value(), services).ok());
|
||||
PP_EXPECT(harness, services.duplicate_calls == 1);
|
||||
PP_EXPECT(harness, services.last_source_index == 1);
|
||||
PP_EXPECT(harness, services.last_insert_index == 2);
|
||||
PP_EXPECT(harness, services.unsaved_marks == 2);
|
||||
PP_EXPECT(harness, services.animation_reloads == 2);
|
||||
PP_EXPECT(harness, services.title_updates == 2);
|
||||
}
|
||||
|
||||
const auto reorder = pp::app::plan_document_layer_reorder(3, 2, 0);
|
||||
PP_EXPECT(harness, reorder);
|
||||
if (reorder) {
|
||||
PP_EXPECT(harness, pp::app::execute_document_layer_operation_plan(reorder.value(), services).ok());
|
||||
PP_EXPECT(harness, services.reorder_calls == 1);
|
||||
PP_EXPECT(harness, services.last_from_index == 2);
|
||||
PP_EXPECT(harness, services.last_to_index == 0);
|
||||
PP_EXPECT(harness, services.unsaved_marks == 3);
|
||||
PP_EXPECT(harness, services.animation_reloads == 3);
|
||||
PP_EXPECT(harness, services.title_updates == 3);
|
||||
}
|
||||
|
||||
const auto remove = pp::app::plan_document_layer_remove(3, 1);
|
||||
PP_EXPECT(harness, remove);
|
||||
if (remove) {
|
||||
PP_EXPECT(harness, pp::app::execute_document_layer_operation_plan(remove.value(), services).ok());
|
||||
PP_EXPECT(harness, services.remove_calls == 1);
|
||||
PP_EXPECT(harness, services.last_index == 1);
|
||||
PP_EXPECT(harness, services.unsaved_marks == 4);
|
||||
PP_EXPECT(harness, services.animation_reloads == 4);
|
||||
PP_EXPECT(harness, services.title_updates == 4);
|
||||
}
|
||||
}
|
||||
|
||||
void layer_operation_executor_dispatches_selection_and_metadata(pp::tests::Harness& harness)
|
||||
{
|
||||
FakeDocumentLayerOperationServices services;
|
||||
|
||||
const auto select = pp::app::plan_document_layer_select(3, 2);
|
||||
PP_EXPECT(harness, select);
|
||||
if (select) {
|
||||
PP_EXPECT(harness, pp::app::execute_document_layer_operation_plan(select.value(), services).ok());
|
||||
PP_EXPECT(harness, services.select_calls == 1);
|
||||
PP_EXPECT(harness, services.last_index == 2);
|
||||
PP_EXPECT(harness, services.unsaved_marks == 0);
|
||||
PP_EXPECT(harness, services.animation_reloads == 1);
|
||||
PP_EXPECT(harness, services.title_updates == 0);
|
||||
}
|
||||
|
||||
const auto opacity = pp::app::plan_document_layer_opacity(3, 1, 0.25F);
|
||||
PP_EXPECT(harness, opacity);
|
||||
if (opacity) {
|
||||
PP_EXPECT(harness, pp::app::execute_document_layer_operation_plan(opacity.value(), services).ok());
|
||||
PP_EXPECT(harness, services.opacity_calls == 1);
|
||||
PP_EXPECT(harness, services.last_index == 1);
|
||||
PP_EXPECT(harness, services.last_opacity == 0.25F);
|
||||
PP_EXPECT(harness, services.unsaved_marks == 1);
|
||||
PP_EXPECT(harness, services.animation_reloads == 1);
|
||||
PP_EXPECT(harness, services.title_updates == 1);
|
||||
}
|
||||
|
||||
const auto visibility = pp::app::plan_document_layer_visibility(3, 1, false);
|
||||
PP_EXPECT(harness, visibility);
|
||||
if (visibility) {
|
||||
PP_EXPECT(harness, pp::app::execute_document_layer_operation_plan(visibility.value(), services).ok());
|
||||
PP_EXPECT(harness, services.visibility_calls == 1);
|
||||
PP_EXPECT(harness, !services.last_flag);
|
||||
PP_EXPECT(harness, services.unsaved_marks == 2);
|
||||
PP_EXPECT(harness, services.animation_reloads == 2);
|
||||
PP_EXPECT(harness, services.title_updates == 2);
|
||||
}
|
||||
|
||||
const auto alpha_lock = pp::app::plan_document_layer_alpha_lock(3, 1, true);
|
||||
PP_EXPECT(harness, alpha_lock);
|
||||
if (alpha_lock) {
|
||||
PP_EXPECT(harness, pp::app::execute_document_layer_operation_plan(alpha_lock.value(), services).ok());
|
||||
PP_EXPECT(harness, services.alpha_lock_calls == 1);
|
||||
PP_EXPECT(harness, services.last_flag);
|
||||
PP_EXPECT(harness, services.unsaved_marks == 3);
|
||||
PP_EXPECT(harness, services.animation_reloads == 2);
|
||||
PP_EXPECT(harness, services.title_updates == 3);
|
||||
}
|
||||
|
||||
const auto blend = pp::app::plan_document_layer_blend_mode(3, 1, 4);
|
||||
PP_EXPECT(harness, blend);
|
||||
if (blend) {
|
||||
PP_EXPECT(harness, pp::app::execute_document_layer_operation_plan(blend.value(), services).ok());
|
||||
PP_EXPECT(harness, services.blend_mode_calls == 1);
|
||||
PP_EXPECT(harness, services.last_blend_mode == 4);
|
||||
PP_EXPECT(harness, services.unsaved_marks == 4);
|
||||
PP_EXPECT(harness, services.title_updates == 4);
|
||||
}
|
||||
}
|
||||
|
||||
void layer_operation_executor_preserves_no_op_and_transient_actions(pp::tests::Harness& harness)
|
||||
{
|
||||
FakeDocumentLayerOperationServices services;
|
||||
|
||||
const auto no_op_reorder = pp::app::plan_document_layer_reorder(3, 1, 1);
|
||||
PP_EXPECT(harness, no_op_reorder);
|
||||
if (no_op_reorder) {
|
||||
PP_EXPECT(harness, pp::app::execute_document_layer_operation_plan(no_op_reorder.value(), services).ok());
|
||||
PP_EXPECT(harness, services.reorder_calls == 0);
|
||||
PP_EXPECT(harness, services.mutation_calls() == 0);
|
||||
PP_EXPECT(harness, services.unsaved_marks == 0);
|
||||
PP_EXPECT(harness, services.animation_reloads == 0);
|
||||
PP_EXPECT(harness, services.title_updates == 0);
|
||||
}
|
||||
|
||||
const auto highlight = pp::app::plan_document_layer_highlight(3, 1, true);
|
||||
PP_EXPECT(harness, highlight);
|
||||
if (highlight) {
|
||||
PP_EXPECT(harness, pp::app::execute_document_layer_operation_plan(highlight.value(), services).ok());
|
||||
PP_EXPECT(harness, services.highlight_calls == 1);
|
||||
PP_EXPECT(harness, services.last_index == 1);
|
||||
PP_EXPECT(harness, services.last_flag);
|
||||
PP_EXPECT(harness, services.unsaved_marks == 0);
|
||||
PP_EXPECT(harness, services.animation_reloads == 0);
|
||||
PP_EXPECT(harness, services.title_updates == 0);
|
||||
}
|
||||
}
|
||||
|
||||
void layer_operation_executor_rejects_malformed_mutation_plans(pp::tests::Harness& harness)
|
||||
{
|
||||
FakeDocumentLayerOperationServices services;
|
||||
|
||||
pp::app::DocumentLayerOperationPlan malformed;
|
||||
malformed.operation = pp::app::DocumentLayerOperation::add;
|
||||
malformed.insert_index = 1;
|
||||
malformed.mutates_document = true;
|
||||
|
||||
const auto status = pp::app::execute_document_layer_operation_plan(malformed, services);
|
||||
PP_EXPECT(harness, !status.ok());
|
||||
PP_EXPECT(harness, status.code == pp::foundation::StatusCode::invalid_argument);
|
||||
PP_EXPECT(harness, services.add_calls == 0);
|
||||
PP_EXPECT(harness, services.unsaved_marks == 0);
|
||||
}
|
||||
|
||||
void layer_menu_labels_selected_layer_commands(pp::tests::Harness& harness)
|
||||
{
|
||||
const auto clear = pp::app::plan_document_layer_menu(
|
||||
@@ -418,6 +678,10 @@ int main()
|
||||
harness.run("layer remove keeps at least one layer", layer_remove_keeps_at_least_one_layer);
|
||||
harness.run("layer metadata plans validate values", layer_metadata_plans_validate_values);
|
||||
harness.run("layer highlight is transient", layer_highlight_is_transient);
|
||||
harness.run("layer operation executor dispatches document mutations", layer_operation_executor_dispatches_document_mutations);
|
||||
harness.run("layer operation executor dispatches selection and metadata", layer_operation_executor_dispatches_selection_and_metadata);
|
||||
harness.run("layer operation executor preserves no op and transient actions", layer_operation_executor_preserves_no_op_and_transient_actions);
|
||||
harness.run("layer operation executor rejects malformed mutation plans", layer_operation_executor_rejects_malformed_mutation_plans);
|
||||
harness.run("layer menu labels selected layer commands", layer_menu_labels_selected_layer_commands);
|
||||
harness.run("layer menu plans merge down or blocks it", layer_menu_plans_merge_down_or_blocks_it);
|
||||
harness.run("layer menu handles missing selection and bad state", layer_menu_handles_missing_selection_and_bad_state);
|
||||
|
||||
Reference in New Issue
Block a user