您最多选择25个主题 主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 
 
 
 

431 行
16 KiB

using System.Collections.Generic;
using System.Linq;
using Unity.UIWidgets.foundation;
using Unity.UIWidgets.gestures;
using Unity.UIWidgets.painting;
using Unity.UIWidgets.ui;
namespace Unity.UIWidgets.rendering {
public interface RenderSliverBoxChildManager {
void createChild(int index, RenderBox after = null);
void removeChild(RenderBox child);
float estimateMaxScrollOffset(
SliverConstraints constraints,
int firstIndex = 0,
int lastIndex = 0,
float leadingScrollOffset = 0,
float trailingScrollOffset = 0);
int? childCount { get; }
void didAdoptChild(RenderBox child);
void setDidUnderflow(bool value);
void didStartLayout();
void didFinishLayout();
bool debugAssertChildListLocked();
}
public class SliverMultiBoxAdaptorParentData : ContainerParentDataMixinSliverLogicalParentData<RenderBox> {
public int index;
public bool keepAlive = false;
public bool keptAlive {
get { return _keptAlive; }
}
internal bool _keptAlive = false;
public override string ToString() {
return $"index={index}; {(keepAlive ? "keeyAlive; " : "")}{base.ToString()}";
}
}
public abstract class RenderSliverMultiBoxAdaptor
: ContainerRenderObjectMixinRenderSliver<RenderBox, SliverMultiBoxAdaptorParentData> {
public RenderSliverMultiBoxAdaptor(
RenderSliverBoxChildManager childManager = null
) {
D.assert(childManager != null);
_childManager = childManager;
}
public override void setupParentData(RenderObject child) {
if (!(child.parentData is SliverMultiBoxAdaptorParentData)) {
child.parentData = new SliverMultiBoxAdaptorParentData();
}
}
protected RenderSliverBoxChildManager childManager {
get { return _childManager; }
}
readonly RenderSliverBoxChildManager _childManager;
readonly Dictionary<int, RenderBox> _keepAliveBucket = new Dictionary<int, RenderBox>();
protected override void adoptChild(AbstractNodeMixinDiagnosticableTree childNode) {
base.adoptChild(childNode);
var child = (RenderBox) childNode;
var childParentData = (SliverMultiBoxAdaptorParentData) child.parentData;
if (!childParentData._keptAlive) {
childManager.didAdoptChild(child);
}
}
bool _debugAssertChildListLocked() {
return childManager.debugAssertChildListLocked();
}
public override void insert(RenderBox child, RenderBox after = null) {
D.assert(!_keepAliveBucket.ContainsValue(value: child));
base.insert(child, after: after);
D.assert(firstChild != null);
D.assert(() => {
int index = indexOf(firstChild);
RenderBox childAfter = this.childAfter(firstChild);
while (childAfter != null) {
D.assert(indexOf(childAfter) > index);
index = indexOf(childAfter);
childAfter = this.childAfter(childAfter);
}
return true;
});
}
public override void remove(RenderBox child) {
var childParentData = (SliverMultiBoxAdaptorParentData) child.parentData;
if (!childParentData._keptAlive) {
base.remove(child);
return;
}
D.assert(_keepAliveBucket[childParentData.index] == child);
_keepAliveBucket.Remove(childParentData.index);
dropChild(child);
}
public override void removeAll() {
base.removeAll();
foreach (var child in _keepAliveBucket.Values) {
dropChild(child);
}
_keepAliveBucket.Clear();
}
void _createOrObtainChild(int index, RenderBox after = null) {
invokeLayoutCallback<SliverConstraints>(constraints => {
D.assert(constraints == this.constraints);
if (_keepAliveBucket.ContainsKey(index)) {
RenderBox child = _keepAliveBucket[index];
_keepAliveBucket.Remove(index);
var childParentData = (SliverMultiBoxAdaptorParentData) child.parentData;
D.assert(childParentData._keptAlive);
dropChild(child);
child.parentData = childParentData;
insert(child, after: after);
childParentData._keptAlive = false;
}
else {
_childManager.createChild(index, after: after);
}
});
}
public void _destroyOrCacheChild(RenderBox child) {
var childParentData = (SliverMultiBoxAdaptorParentData) child.parentData;
if (childParentData.keepAlive) {
D.assert(!childParentData._keptAlive);
remove(child);
_keepAliveBucket[childParentData.index] = child;
child.parentData = childParentData;
base.adoptChild(child);
childParentData._keptAlive = true;
}
else {
D.assert(child.parent == this);
_childManager.removeChild(child);
D.assert(child.parent == null);
}
}
public override void attach(object owner) {
base.attach(owner);
foreach (RenderBox child in _keepAliveBucket.Values) {
child.attach(owner);
}
}
public override void detach() {
base.detach();
foreach (RenderBox child in _keepAliveBucket.Values) {
child.detach();
}
}
public override void redepthChildren() {
base.redepthChildren();
foreach (var child in _keepAliveBucket.Values) {
redepthChild(child);
}
}
public override void visitChildren(RenderObjectVisitor visitor) {
base.visitChildren(visitor);
foreach (var child in _keepAliveBucket.Values) {
visitor(child);
}
}
protected bool addInitialChild(int index = 0, float layoutOffset = 0.0f) {
D.assert(_debugAssertChildListLocked());
D.assert(firstChild == null);
_createOrObtainChild(index, after: null);
if (firstChild != null) {
D.assert(firstChild == lastChild);
D.assert(indexOf(firstChild) == index);
var firstChildParentData = (SliverMultiBoxAdaptorParentData) firstChild.parentData;
firstChildParentData.layoutOffset = layoutOffset;
return true;
}
childManager.setDidUnderflow(true);
return false;
}
protected RenderBox insertAndLayoutLeadingChild(BoxConstraints childConstraints, bool parentUsesSize = false) {
D.assert(_debugAssertChildListLocked());
int index = indexOf(firstChild) - 1;
_createOrObtainChild(index, after: null);
if (indexOf(firstChild) == index) {
firstChild.layout(childConstraints, parentUsesSize: parentUsesSize);
return firstChild;
}
childManager.setDidUnderflow(true);
return null;
}
protected RenderBox insertAndLayoutChild(
BoxConstraints childConstraints,
RenderBox after = null,
bool parentUsesSize = false
) {
D.assert(_debugAssertChildListLocked());
D.assert(after != null);
int index = indexOf(after) + 1;
_createOrObtainChild(index, after: after);
RenderBox child = childAfter(after);
if (child != null && indexOf(child) == index) {
child.layout(childConstraints, parentUsesSize: parentUsesSize);
return child;
}
childManager.setDidUnderflow(true);
return null;
}
protected void collectGarbage(int leadingGarbage, int trailingGarbage) {
D.assert(_debugAssertChildListLocked());
D.assert(childCount >= leadingGarbage + trailingGarbage);
invokeLayoutCallback<SliverConstraints>(constraints => {
while (leadingGarbage > 0) {
_destroyOrCacheChild(firstChild);
leadingGarbage -= 1;
}
while (trailingGarbage > 0) {
_destroyOrCacheChild(lastChild);
trailingGarbage -= 1;
}
_keepAliveBucket.Values.Where(child => {
var childParentData = (SliverMultiBoxAdaptorParentData) child.parentData;
return !childParentData.keepAlive;
}).ToList().ForEach(_childManager.removeChild);
D.assert(_keepAliveBucket.Values.Where(child => {
var childParentData = (SliverMultiBoxAdaptorParentData) child.parentData;
return !childParentData.keepAlive;
}).ToList().isEmpty());
});
}
public int indexOf(RenderBox child) {
D.assert(child != null);
var childParentData = (SliverMultiBoxAdaptorParentData) child.parentData;
return childParentData.index;
}
protected float paintExtentOf(RenderBox child) {
D.assert(child != null);
D.assert(child.hasSize);
switch (constraints.axis) {
case Axis.horizontal:
return child.size.width;
case Axis.vertical:
return child.size.height;
}
return 0.0f;
}
protected override bool hitTestChildren(SliverHitTestResult result, float mainAxisPosition = 0.0f,
float crossAxisPosition = 0.0f) {
RenderBox child = lastChild;
BoxHitTestResult boxResult = new BoxHitTestResult(result);
while (child != null) {
if (this.hitTestBoxChild(boxResult, child, mainAxisPosition: mainAxisPosition,
crossAxisPosition: crossAxisPosition)) {
return true;
}
child = childBefore(child);
}
return false;
}
public override float childMainAxisPosition(RenderObject child) {
return childScrollOffset(child) - constraints.scrollOffset;
}
public override float childScrollOffset(RenderObject child) {
D.assert(child != null);
D.assert(child.parent == this);
var childParentData = (SliverMultiBoxAdaptorParentData) child.parentData;
return childParentData.layoutOffset;
}
public override void applyPaintTransform(RenderObject child, Matrix4 transform) {
this.applyPaintTransformForBoxChild((RenderBox) child, transform);
}
public override void paint(PaintingContext context, Offset offset) {
if (firstChild == null) {
return;
}
Offset mainAxisUnit = null, crossAxisUnit = null, originOffset = null;
bool addExtent = false;
switch (GrowthDirectionUtils.applyGrowthDirectionToAxisDirection(constraints.axisDirection,
constraints.growthDirection)) {
case AxisDirection.up:
mainAxisUnit = new Offset(0.0f, -1.0f);
crossAxisUnit = new Offset(1.0f, 0.0f);
originOffset = offset + new Offset(0.0f, geometry.paintExtent);
addExtent = true;
break;
case AxisDirection.right:
mainAxisUnit = new Offset(1.0f, 0.0f);
crossAxisUnit = new Offset(0.0f, 1.0f);
originOffset = offset;
addExtent = false;
break;
case AxisDirection.down:
mainAxisUnit = new Offset(0.0f, 1.0f);
crossAxisUnit = new Offset(1.0f, 0.0f);
originOffset = offset;
addExtent = false;
break;
case AxisDirection.left:
mainAxisUnit = new Offset(-1.0f, 0.0f);
crossAxisUnit = new Offset(0.0f, 1.0f);
originOffset = offset + new Offset(geometry.paintExtent, 0.0f);
addExtent = true;
break;
}
RenderBox child = firstChild;
while (child != null) {
float mainAxisDelta = childMainAxisPosition(child);
float crossAxisDelta = childCrossAxisPosition(child);
Offset childOffset = new Offset(
originOffset.dx + mainAxisUnit.dx * mainAxisDelta + crossAxisUnit.dx * crossAxisDelta,
originOffset.dy + mainAxisUnit.dy * mainAxisDelta + crossAxisUnit.dy * crossAxisDelta
);
if (addExtent) {
childOffset += mainAxisUnit * paintExtentOf(child);
}
if (mainAxisDelta < constraints.remainingPaintExtent &&
mainAxisDelta + paintExtentOf(child) > 0) {
context.paintChild(child, childOffset);
}
child = childAfter(child);
}
}
public override void debugFillProperties(DiagnosticPropertiesBuilder properties) {
base.debugFillProperties(properties);
properties.add(DiagnosticsNode.message(firstChild != null
? "currently live children: " + indexOf(firstChild) + " to " + indexOf(lastChild)
: "no children current live"));
}
public bool debugAssertChildListIsNonEmptyAndContiguous() {
D.assert(() => {
D.assert(firstChild != null);
int index = indexOf(firstChild);
RenderBox child = childAfter(firstChild);
while (child != null) {
index += 1;
D.assert(indexOf(child) == index);
child = childAfter(child);
}
return true;
});
return true;
}
public override List<DiagnosticsNode> debugDescribeChildren() {
var children = new List<DiagnosticsNode>();
if (firstChild != null) {
RenderBox child = firstChild;
while (true) {
var childParentData = (SliverMultiBoxAdaptorParentData) child.parentData;
children.Add(child.toDiagnosticsNode(name: "child with index " + childParentData.index));
if (child == lastChild) {
break;
}
child = childParentData.nextSibling;
}
}
if (_keepAliveBucket.isNotEmpty()) {
List<int> indices = _keepAliveBucket.Keys.ToList();
indices.Sort();
foreach (int index in indices) {
children.Add(_keepAliveBucket[index].toDiagnosticsNode(
name: "child with index " + index + " (kept alive but not laid out)",
style: DiagnosticsTreeStyle.offstage
));
}
}
return children;
}
}
}