Browse Source

Handle element: Make edge constraints behave correctly for relative positioning

And allow positioning elements anywhere within scroll containers.
Michael Ragazzon 1 year ago
parent
commit
7a8aceafcc

+ 17 - 9
Source/Core/ElementHandle.cpp

@@ -84,13 +84,11 @@ 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);
 
-		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)};
+		const Vector2f distance_to_top_left = DistanceToTopLeft();
+		const Vector2f distance_to_bottom_right = DistanceToBottomRight(distance_to_top_left);
 
-		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);
+		drag_delta_min = Math::Max(drag_delta_min, Vector2f{resolved_edge_margin[LEFT], resolved_edge_margin[TOP]} - distance_to_top_left);
+		drag_delta_max = Math::Min(drag_delta_max, Vector2f{-resolved_edge_margin[RIGHT], -resolved_edge_margin[BOTTOM]} + distance_to_bottom_right);
 
 		return data;
 	}
@@ -116,12 +114,11 @@ 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)};
+		const Vector2f distance_to_bottom_right = DistanceToBottomRight(DistanceToTopLeft());
 
 		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 + bottom_right_margin);
+		drag_delta_max = Math::Min(drag_delta_max, Vector2f{-resolved_edge_margin[RIGHT], -resolved_edge_margin[BOTTOM]} + distance_to_bottom_right);
 
 		return data;
 	}
@@ -201,6 +198,17 @@ private:
 		});
 	}
 
+	Vector2f DistanceToTopLeft() const
+	{
+		return {target->GetOffsetLeft() - parent_box.GetEdge(BoxArea::Border, BoxEdge::Left),
+			target->GetOffsetTop() - parent_box.GetEdge(BoxArea::Border, BoxEdge::Top)};
+	}
+	Vector2f DistanceToBottomRight(Vector2f distance_to_top_left) const
+	{
+		const Vector2f scroll_size = {target->GetParentNode()->GetScrollWidth(), target->GetParentNode()->GetScrollHeight()};
+		return scroll_size - box.GetSize(BoxArea::Border) - distance_to_top_left;
+	}
+
 	Element* target;
 	const ComputedValues& computed;
 	const Box& box;

+ 3 - 3
Tests/Data/VisualTests/clip_mask.rml

@@ -51,16 +51,16 @@
 <body>
 <div class="box clip">
 	Duck aloft
-	<handle move_target="#self" class="A" edge_margin="-80dp">
+	<handle move_target="#self" class="A" edge_margin="-70%">
 			A
 	</handle>
 	X
 </div>
 <div class="box clip">
 	Y
-	<handle move_target="#self" class="B clip" edge_margin="-80dp">
+	<handle move_target="#self" class="B clip" edge_margin="-70%">
 			C
-		<handle move_target="#self" class="C clip" edge_margin="-90%">
+		<handle move_target="#self" class="C clip" edge_margin="-70%">
 				Some long text
 		</handle>
 			Z

+ 2 - 2
Tests/Data/VisualTests/filter_blur_area.rml

@@ -36,7 +36,7 @@
 </head>
 
 <body>
-	<handle class="background" move_target="#self"/>
-	<handle class="blur" move_target="#self"/>
+	<handle class="background" move_target="#self" edge_margin="-50%"/>
+	<handle class="blur" move_target="#self" edge_margin="-50%"/>
 </body>
 </rml>

+ 2 - 2
Tests/Data/VisualTests/filter_blur_orb.rml

@@ -38,7 +38,7 @@
 </head>
 
 <body>
-	<handle class="background" move_target="#self"/>
-	<handle class="blur" move_target="#self"/>
+	<handle class="background" move_target="#self" edge_margin="-50%"/>
+	<handle class="blur" move_target="#self" edge_margin="-50%"/>
 </body>
 </rml>

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

@@ -2,7 +2,9 @@
 <head>
 	<title>Handle anchor positioning</title>
 	<link type="text/rcss" href="../style.rcss"/>
-	<meta name="Description" content="Handles should respect the target element's anchoring to its parent, determined by its top/right/bottom/left properties. The anchoring should still hold after moving and resizing the target." />
+	<meta name="Description" content="Handles should respect the target element's anchoring to its parent, determined by its top/right/bottom/left properties." />
+	<meta name="Assert" content="The anchoring should still hold after moving and resizing the target." />
+	<meta name="Assert" content="The handles should constrain the movement and sizing such that the target element is located within the edge margin of its containing block." />
 	<style>
 		handle[move_target] {
 			top: 0;