Unverified Commit 8eadbb31 authored by LongCatIsLooong's avatar LongCatIsLooong Committed by GitHub

Revert "Add CompositedTransformFollower.{followerAnchor, leaderAnchor} for...

Revert "Add CompositedTransformFollower.{followerAnchor, leaderAnchor} for custom anchoring (#64930)" (#65871)

This reverts commit 2fbb529d.
parent 7948a786
......@@ -3,6 +3,7 @@
// found in the LICENSE file.
import 'dart:async';
import 'dart:collection';
import 'dart:ui' as ui;
import 'package:flutter/foundation.dart';
......@@ -2027,14 +2028,6 @@ class LayerLink {
LeaderLayer? get leader => _leader;
LeaderLayer? _leader;
/// The total size of [leader]'s contents.
///
/// Generally this should be set by the [RenderObject] that paints on the
/// registered [leader] layer (for instance a [RenderLeaderLayer] that shares
/// this link with its followers). This size may be outdated before and during
/// layout.
Size? leaderSize;
@override
String toString() => '${describeIdentity(this)}(${ _leader != null ? "<linked>" : "<dangling>" })';
}
......@@ -2273,91 +2266,59 @@ class FollowerLayer extends ContainerLayer {
/// treated as the child of the second, and so forth. The first layer in the
/// list won't have [applyTransform] called on it. The first layer may be
/// null.
static Matrix4 _collectTransformForLayerChain(List<ContainerLayer?> layers) {
Matrix4 _collectTransformForLayerChain(List<ContainerLayer?> layers) {
// Initialize our result matrix.
final Matrix4 result = Matrix4.identity();
// Apply each layer to the matrix in turn, starting from the last layer,
// and providing the previous layer as the child.
for (int index = layers.length - 1; index > 0; index -= 1)
layers[index]?.applyTransform(layers[index - 1], result);
layers[index]!.applyTransform(layers[index - 1], result);
return result;
}
/// Find the common ancestor of two layers [a] and [b] by searching towards
/// the root of the tree, and append each ancestor of [a] or [b] visited along
/// the path to [ancestorsA] and [ancestorsB] respectively.
///
/// Returns null if [a] [b] do not share a common ancestor, in which case the
/// results in [ancestorsA] and [ancestorsB] are undefined.
static Layer? _pathsToCommonAncestor(
Layer? a, Layer? b,
List<ContainerLayer?> ancestorsA, List<ContainerLayer?> ancestorsB,
) {
// No common ancestor found.
if (a == null || b == null)
return null;
if (identical(a, b))
return a;
if (a.depth < b.depth) {
ancestorsB.add(b.parent);
return _pathsToCommonAncestor(a, b.parent, ancestorsA, ancestorsB);
} else if (a.depth > b.depth){
ancestorsA.add(a.parent);
return _pathsToCommonAncestor(a.parent, b, ancestorsA, ancestorsB);
}
ancestorsA.add(a.parent);
ancestorsB.add(b.parent);
return _pathsToCommonAncestor(a.parent, b.parent, ancestorsA, ancestorsB);
}
/// Populate [_lastTransform] given the current state of the tree.
void _establishTransform() {
assert(link != null);
_lastTransform = null;
final LeaderLayer? leader = link.leader;
// Check to see if we are linked.
if (leader == null)
if (link.leader == null)
return;
// If we're linked, check the link is valid.
assert(
leader.owner == owner,
'Linked LeaderLayer anchor is not in the same layer tree as the FollowerLayer.',
);
assert(
leader._lastOffset != null,
'LeaderLayer anchor must come before FollowerLayer in paint order, but the reverse was true.',
);
// Stores [leader, ..., commonAncestor] after calling _pathsToCommonAncestor.
final List<ContainerLayer?> forwardLayers = <ContainerLayer>[leader];
// Stores [this (follower), ..., commonAncestor] after calling
// _pathsToCommonAncestor.
final List<ContainerLayer?> inverseLayers = <ContainerLayer>[this];
final Layer? ancestor = _pathsToCommonAncestor(
leader, this,
forwardLayers, inverseLayers,
);
assert(ancestor != null);
assert(link.leader!.owner == owner, 'Linked LeaderLayer anchor is not in the same layer tree as the FollowerLayer.');
assert(link.leader!._lastOffset != null, 'LeaderLayer anchor must come before FollowerLayer in paint order, but the reverse was true.');
// Collect all our ancestors into a Set so we can recognize them.
final Set<Layer> ancestors = HashSet<Layer>();
Layer? ancestor = parent;
while (ancestor != null) {
ancestors.add(ancestor);
ancestor = ancestor.parent;
}
// Collect all the layers from a hypothetical child (null) of the target
// layer up to the common ancestor layer.
ContainerLayer? layer = link.leader;
final List<ContainerLayer?> forwardLayers = <ContainerLayer?>[null, layer];
do {
layer = layer!.parent;
forwardLayers.add(layer);
} while (!ancestors.contains(layer)); // ignore: iterable_contains_unrelated_type
ancestor = layer;
// Collect all the layers from this layer up to the common ancestor layer.
layer = this;
final List<ContainerLayer> inverseLayers = <ContainerLayer>[layer];
do {
layer = layer!.parent;
inverseLayers.add(layer!);
} while (layer != ancestor);
// Establish the forward and backward matrices given these lists of layers.
final Matrix4 forwardTransform = _collectTransformForLayerChain(forwardLayers);
// Further transforms the coordinate system to a hypothetical child (null)
// of the leader layer, to account for the leader's additional paint offset
// and layer offset (LeaderLayer._lastOffset).
leader.applyTransform(null, forwardTransform);
forwardTransform.translate(linkedOffset!.dx, linkedOffset!.dy);
final Matrix4 inverseTransform = _collectTransformForLayerChain(inverseLayers);
if (inverseTransform.invert() == 0.0) {
// We are in a degenerate transform, so there's not much we can do.
return;
}
// Combine the matrices and store the result.
inverseTransform.multiply(forwardTransform);
inverseTransform.translate(linkedOffset!.dx, linkedOffset!.dy);
_lastTransform = inverseTransform;
_inverseDirty = true;
}
......
......@@ -4826,37 +4826,28 @@ class RenderLeaderLayer extends RenderProxyBox {
required LayerLink link,
RenderBox? child,
}) : assert(link != null),
_link = link,
super(child);
super(child) {
this.link = link;
}
/// The link object that connects this [RenderLeaderLayer] with one or more
/// [RenderFollowerLayer]s.
///
/// This property must not be null. The object must not be associated with
/// another [RenderLeaderLayer] that is also being painted.
LayerLink get link => _link;
LayerLink _link;
LayerLink get link => _link!;
LayerLink? _link;
set link(LayerLink value) {
assert(value != null);
if (_link == value)
return;
_link.leaderSize = null;
_link = value;
if (hasSize) {
_link.leaderSize = size;
}
markNeedsPaint();
}
@override
bool get alwaysNeedsCompositing => true;
@override
void performLayout() {
super.performLayout();
link.leaderSize = size;
}
@override
void paint(PaintingContext context, Offset offset) {
if (layer == null) {
......@@ -4899,8 +4890,6 @@ class RenderFollowerLayer extends RenderProxyBox {
required LayerLink link,
bool showWhenUnlinked = true,
Offset offset = Offset.zero,
Alignment leaderAnchor = Alignment.topLeft,
Alignment followerAnchor = Alignment.topLeft,
RenderBox? child,
}) : assert(link != null),
assert(showWhenUnlinked != null),
......@@ -4908,8 +4897,6 @@ class RenderFollowerLayer extends RenderProxyBox {
_link = link,
_showWhenUnlinked = showWhenUnlinked,
_offset = offset,
_leaderAnchor = leaderAnchor,
_followerAnchor = followerAnchor,
super(child);
/// The link object that connects this [RenderFollowerLayer] with a
......@@ -4955,46 +4942,6 @@ class RenderFollowerLayer extends RenderProxyBox {
markNeedsPaint();
}
/// The anchor point on the linked [RenderLeaderLayer] that [followerAnchor]
/// will line up with.
///
/// {@template flutter.rendering.followerLayer.anchor}
/// For example, when [leaderAnchor] and [followerAnchor] are both
/// [Alignment.topLeft], this [RenderFollowerLayer] will be top left aligned
/// with the linked [RenderLeaderLayer]. When [leaderAnchor] is
/// [Alignment.bottomLeft] and [followerAnchor] is [Alignment.topLeft], this
/// [RenderFollowerLayer] will be left aligned with the linked
/// [RenderLeaderLayer], and its top edge will line up with the
/// [RenderLeaderLayer]'s bottom edge.
/// {@endtemplate}
///
/// Defaults to [Alignment.topLeft].
Alignment get leaderAnchor => _leaderAnchor;
Alignment _leaderAnchor;
set leaderAnchor(Alignment value) {
assert(value != null);
if (_leaderAnchor == value)
return;
_leaderAnchor = value;
markNeedsPaint();
}
/// The anchor point on this [RenderFollowerLayer] that will line up with
/// [followerAnchor] on the linked [RenderLeaderLayer].
///
/// {@macro flutter.rendering.followerLayer.anchor}
///
/// Defaults to [Alignment.topLeft].
Alignment get followerAnchor => _followerAnchor;
Alignment _followerAnchor;
set followerAnchor(Alignment value) {
assert(value != null);
if (_followerAnchor == value)
return;
_followerAnchor = value;
markNeedsPaint();
}
@override
void detach() {
layer = null;
......@@ -5043,29 +4990,19 @@ class RenderFollowerLayer extends RenderProxyBox {
@override
void paint(PaintingContext context, Offset offset) {
final Size? leaderSize = link.leaderSize;
assert(
link.leaderSize != null || (link.leader == null || leaderAnchor == Alignment.topLeft),
'$link: layer is linked to ${link.leader} but a valid leaderSize is not set. '
'leaderSize is required when leaderAnchor is not Alignment.topLeft'
'(current value is $leaderAnchor).',
);
final Offset effectiveLinkedOffset = leaderSize == null
? this.offset
: leaderAnchor.alongSize(leaderSize) - followerAnchor.alongSize(size) + this.offset;
assert(showWhenUnlinked != null);
if (layer == null) {
layer = FollowerLayer(
link: link,
showWhenUnlinked: showWhenUnlinked,
linkedOffset: effectiveLinkedOffset,
linkedOffset: this.offset,
unlinkedOffset: offset,
);
} else {
layer
?..link = link
layer!
..link = link
..showWhenUnlinked = showWhenUnlinked
..linkedOffset = effectiveLinkedOffset
..linkedOffset = this.offset
..unlinkedOffset = offset;
}
context.pushLayer(
......
......@@ -1327,11 +1327,9 @@ class CompositedTransformTarget extends SingleChildRenderObjectWidget {
///
/// When this widget is composited during the compositing phase (which comes
/// after the paint phase, as described in [WidgetsBinding.drawFrame]), it
/// applies a transformation that brings [targetAnchor] of the linked
/// [CompositedTransformTarget] and [followerAnchor] of this widget together.
/// The two anchor points will have the same global coordinates, unless [offset]
/// is not [Offset.zero], in which case [followerAnchor] will be offset by
/// [offset] in the linked [CompositedTransformTarget]'s coordinate space.
/// applies a transformation that causes it to provide its child with a
/// coordinate space that matches that of the linked [CompositedTransformTarget]
/// widget, offset by [offset].
///
/// The [LayerLink] object used as the [link] must be the same object as that
/// provided to the matching [CompositedTransformTarget].
......@@ -1363,14 +1361,10 @@ class CompositedTransformFollower extends SingleChildRenderObjectWidget {
required this.link,
this.showWhenUnlinked = true,
this.offset = Offset.zero,
this.targetAnchor = Alignment.topLeft,
this.followerAnchor = Alignment.topLeft,
Widget? child,
}) : assert(link != null),
assert(showWhenUnlinked != null),
assert(offset != null),
assert(targetAnchor != null),
assert(followerAnchor != null),
super(key: key, child: child);
/// The link object that connects this [CompositedTransformFollower] with a
......@@ -1390,33 +1384,8 @@ class CompositedTransformFollower extends SingleChildRenderObjectWidget {
/// hidden.
final bool showWhenUnlinked;
/// The anchor point on the linked [CompositedTransformTarget] that
/// [followerAnchor] will line up with.
///
/// {@template flutter.widgets.followerLayer.anchor}
/// For example, when [targetAnchor] and [followerAnchor] are both
/// [Alignment.topLeft], this widget will be top left aligned with the linked
/// [CompositedTransformTarget]. When [targetAnchor] is
/// [Alignment.bottomLeft] and [followerAnchor] is [Alignment.topLeft], this
/// widget will be left aligned with the linked [CompositedTransformTarget],
/// and its top edge will line up with the [CompositedTransformTarget]'s
/// bottom edge.
/// {@endtemplate}
///
/// Defaults to [Alignment.topLeft].
final Alignment targetAnchor;
/// The anchor point on this widget that will line up with [followerAnchor] on
/// the linked [CompositedTransformTarget].
///
/// {@macro flutter.widgets.followerLayer.anchor}
///
/// Defaults to [Alignment.topLeft].
final Alignment followerAnchor;
/// The additional offset to apply to the [targetAnchor] of the linked
/// [CompositedTransformTarget] to obtain this widget's [followerAnchor]
/// position.
/// The offset to apply to the origin of the linked
/// [CompositedTransformTarget] to obtain this widget's origin.
final Offset offset;
@override
......@@ -1425,8 +1394,6 @@ class CompositedTransformFollower extends SingleChildRenderObjectWidget {
link: link,
showWhenUnlinked: showWhenUnlinked,
offset: offset,
leaderAnchor: targetAnchor,
followerAnchor: followerAnchor,
);
}
......@@ -1435,9 +1402,7 @@ class CompositedTransformFollower extends SingleChildRenderObjectWidget {
renderObject
..link = link
..showWhenUnlinked = showWhenUnlinked
..offset = offset
..leaderAnchor = targetAnchor
..followerAnchor = followerAnchor;
..offset = offset;
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment