Browse Source

Handle element constrains to the target's border area instead of its margin area

Michael Ragazzon 1 year ago
parent
commit
5187e16232

+ 11 - 5
Source/Core/ElementHandle.cpp

@@ -84,9 +84,13 @@ public:
 		data.top_left.x = (!data.bottom_right.x || computed.left().type != Left::Auto);
 		data.top_left.y = (!data.bottom_right.y || computed.top().type != Top::Auto);
 
-		drag_delta_min = Math::Max(drag_delta_min, Vector2f{resolved_edge_margin[LEFT], resolved_edge_margin[TOP]} - data.original_position_top_left);
-		drag_delta_max =
-			Math::Min(drag_delta_max, Vector2f{-resolved_edge_margin[RIGHT], -resolved_edge_margin[BOTTOM]} + data.original_position_bottom_right);
+		const Vector2f top_left_margin = {box.GetEdge(BoxArea::Margin, BoxEdge::Left), box.GetEdge(BoxArea::Margin, BoxEdge::Top)};
+		const Vector2f bottom_right_margin = {box.GetEdge(BoxArea::Margin, BoxEdge::Right), box.GetEdge(BoxArea::Margin, BoxEdge::Bottom)};
+
+		drag_delta_min = Math::Max(drag_delta_min,
+			Vector2f{resolved_edge_margin[LEFT], resolved_edge_margin[TOP]} - data.original_position_top_left - top_left_margin);
+		drag_delta_max = Math::Min(drag_delta_max,
+			Vector2f{-resolved_edge_margin[RIGHT], -resolved_edge_margin[BOTTOM]} + data.original_position_bottom_right + bottom_right_margin);
 
 		return data;
 	}
@@ -112,10 +116,12 @@ public:
 			ResolveValueOr(computed.max_width(), containing_block.x, FLT_MAX),
 			ResolveValueOr(computed.max_height(), containing_block.y, FLT_MAX),
 		};
+		const Vector2f bottom_right_margin = {box.GetEdge(BoxArea::Margin, BoxEdge::Right), box.GetEdge(BoxArea::Margin, BoxEdge::Bottom)};
+
 		drag_delta_min = Math::Max(drag_delta_min, min_size - data.original_size);
 		drag_delta_max = Math::Min(drag_delta_max, max_size - data.original_size);
-		drag_delta_max =
-			Math::Min(drag_delta_max, Vector2f{-resolved_edge_margin[RIGHT], -resolved_edge_margin[BOTTOM]} + data.original_position_bottom_right);
+		drag_delta_max = Math::Min(drag_delta_max,
+			Vector2f{-resolved_edge_margin[RIGHT], -resolved_edge_margin[BOTTOM]} + data.original_position_bottom_right + bottom_right_margin);
 
 		return data;
 	}

+ 1 - 1
Tests/Data/VisualTests/handle_target_anchor.rml

@@ -36,7 +36,7 @@
 			min-width: 100dp;
 			min-height: 50dp;
 			border-width: 0;
-			margin: 0;
+			margin: 30dp 20dp;
 		}
 		.top_left {
 			top: 25px;

+ 101 - 0
Tests/Source/UnitTests/ElementHandle.cpp

@@ -313,6 +313,107 @@ TEST_CASE("ElementHandle")
 		CHECK(target->GetBox().GetSize() == Vector2f(200, 200));
 	}
 
+	SUBCASE("AutoMarginMove")
+	{
+		handle->SetAttribute("move_target", "target");
+
+		target->SetProperty(PropertyId::Width, Property(100, Unit::PX));
+		target->SetProperty(PropertyId::Height, Property(100, Unit::PX));
+		target->SetProperty("margin", "auto");
+
+		context->Update();
+		CHECK(target->GetAbsoluteOffset() == Vector2f(200, 200));
+		CHECK(target->GetBox().GetSize() == Vector2f(100, 100));
+
+		dispatch_mouse_event(EventId::Dragstart, handle, {0, 0});
+		dispatch_mouse_event(EventId::Drag, handle, {10, 10});
+
+		CHECK(target->GetProperty(PropertyId::MarginTop)->Get<float>() == 200);
+		CHECK(target->GetProperty(PropertyId::MarginRight)->Get<float>() == 200);
+		CHECK(target->GetProperty(PropertyId::MarginBottom)->Get<float>() == 200);
+		CHECK(target->GetProperty(PropertyId::MarginLeft)->Get<float>() == 200);
+		CHECK(target->GetProperty(PropertyId::Top)->Get<float>() == 10);
+		CHECK(target->GetProperty(PropertyId::Left)->Get<float>() == 10);
+
+		context->Update();
+		CHECK(target->GetAbsoluteOffset() == Vector2f(210, 210));
+		CHECK(target->GetBox().GetSize() == Vector2f(100, 100));
+
+		document_set_size({1000, 1000});
+		CHECK(target->GetAbsoluteOffset() == Vector2f(210, 210));
+		CHECK(target->GetBox().GetSize() == Vector2f(100, 100));
+	}
+
+	SUBCASE("AutoMarginMoveConstraints")
+	{
+		handle->SetAttribute("move_target", "target");
+
+		target->SetProperty(PropertyId::Width, Property(100, Unit::PX));
+		target->SetProperty(PropertyId::Height, Property(100, Unit::PX));
+		target->SetProperty("margin", "auto");
+
+		context->Update();
+		CHECK(target->GetAbsoluteOffset() == Vector2f(200, 200));
+		CHECK(target->GetBox().GetSize() == Vector2f(100, 100));
+
+		dispatch_mouse_event(EventId::Dragstart, handle, {0, 0});
+		dispatch_mouse_event(EventId::Drag, handle, {-1000, -1000});
+
+		CHECK(target->GetProperty(PropertyId::Top)->Get<float>() == -200);
+		CHECK(target->GetProperty(PropertyId::Left)->Get<float>() == -200);
+
+		context->Update();
+		CHECK(target->GetAbsoluteOffset() == Vector2f(0, 0));
+		CHECK(target->GetBox().GetSize() == Vector2f(100, 100));
+	}
+
+	SUBCASE("AutoMarginSize")
+	{
+		handle->SetAttribute("size_target", "target");
+
+		target->SetProperty(PropertyId::Width, Property(100, Unit::PX));
+		target->SetProperty(PropertyId::Height, Property(100, Unit::PX));
+		target->SetProperty("margin", "auto");
+
+		context->Update();
+		CHECK(target->GetAbsoluteOffset() == Vector2f(200, 200));
+		CHECK(target->GetBox().GetSize() == Vector2f(100, 100));
+
+		dispatch_mouse_event(EventId::Dragstart, handle, {0, 0});
+		dispatch_mouse_event(EventId::Drag, handle, {10, 10});
+
+		CHECK(target->GetProperty(PropertyId::MarginTop)->Get<float>() == 200);
+		CHECK(target->GetProperty(PropertyId::MarginRight)->Get<float>() == 200);
+		CHECK(target->GetProperty(PropertyId::MarginBottom)->Get<float>() == 200);
+		CHECK(target->GetProperty(PropertyId::MarginLeft)->Get<float>() == 200);
+		CHECK(target->GetProperty(PropertyId::Width)->Get<float>() == 110);
+		CHECK(target->GetProperty(PropertyId::Height)->Get<float>() == 110);
+
+		context->Update();
+		CHECK(target->GetAbsoluteOffset() == Vector2f(200, 200));
+		CHECK(target->GetBox().GetSize() == Vector2f(110, 110));
+	}
+
+	SUBCASE("AutoMarginSizeConstraints")
+	{
+		handle->SetAttribute("size_target", "target");
+
+		target->SetProperty(PropertyId::Width, Property(100, Unit::PX));
+		target->SetProperty(PropertyId::Height, Property(100, Unit::PX));
+		target->SetProperty("margin", "auto");
+
+		context->Update();
+		CHECK(target->GetAbsoluteOffset() == Vector2f(200, 200));
+		CHECK(target->GetBox().GetSize() == Vector2f(100, 100));
+
+		dispatch_mouse_event(EventId::Dragstart, handle, {0, 0});
+		dispatch_mouse_event(EventId::Drag, handle, {1000, 1000});
+
+		context->Update();
+		CHECK(target->GetAbsoluteOffset() == Vector2f(200, 200));
+		CHECK(target->GetBox().GetSize() == Vector2f(300, 300));
+	}
+
 	TestsShell::RenderLoop();
 
 	document->Close();