|
|
|
|
|
|
using System; |
|
|
|
using System.Collections.Generic; |
|
|
|
using System.Linq; |
|
|
|
using System.Runtime.CompilerServices; |
|
|
|
using JetBrains.Annotations; |
|
|
|
using Unity.UIWidgets.external; |
|
|
|
using Unity.UIWidgets.external; |
|
|
|
using Unity.UIWidgets.scheduler; |
|
|
|
using Unity.UIWidgets.ui; |
|
|
|
using UnityEngine; |
|
|
|
|
|
|
Widget build(BuildContext context, int index); |
|
|
|
Widget build(BuildContext context, int index); |
|
|
|
public readonly List<Widget> children; |
|
|
|
|
|
|
|
public ListWheelChildListDelegate( |
|
|
|
List<Widget> children |
|
|
|
) { |
|
|
|
|
|
|
|
|
|
|
public readonly List<Widget> children; |
|
|
|
|
|
|
|
public int? estimatedChildCount { |
|
|
|
get { return children.Count; } |
|
|
|
|
|
|
return null; |
|
|
|
} |
|
|
|
|
|
|
|
return new IndexedSemantics(child: children[index], index: index); |
|
|
|
return new IndexedSemantics(child: children[index: index], index: index); |
|
|
|
} |
|
|
|
|
|
|
|
public int trueIndexOf(int index) { |
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
public class ListWheelChildLoopingListDelegate : ListWheelChildDelegate { |
|
|
|
public readonly List<Widget> children; |
|
|
|
|
|
|
|
public ListWheelChildLoopingListDelegate( |
|
|
|
List<Widget> children |
|
|
|
) { |
|
|
|
|
|
|
|
|
|
|
public readonly List<Widget> children; |
|
|
|
|
|
|
|
public int? estimatedChildCount { |
|
|
|
get { return null; } |
|
|
|
|
|
|
var result = index; |
|
|
|
if (index < 0) { |
|
|
|
if (index % children.Count == 0) |
|
|
|
if (index % children.Count == 0) { |
|
|
|
} |
|
|
|
else |
|
|
|
else { |
|
|
|
} |
|
|
|
|
|
|
|
return result; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return new IndexedSemantics(child: children[Mathf.Abs(index % children.Count)]); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
public class ListWheelChildBuilderDelegate : ListWheelChildDelegate { |
|
|
|
public readonly IndexedWidgetBuilder builder; |
|
|
|
|
|
|
|
public readonly int? childCount; |
|
|
|
|
|
|
|
public ListWheelChildBuilderDelegate( |
|
|
|
IndexedWidgetBuilder builder, |
|
|
|
int? childCount = null |
|
|
|
|
|
|
this.childCount = childCount; |
|
|
|
} |
|
|
|
|
|
|
|
public readonly IndexedWidgetBuilder builder; |
|
|
|
|
|
|
|
public readonly int? childCount; |
|
|
|
|
|
|
|
public int? estimatedChildCount { |
|
|
|
get { return childCount; } |
|
|
|
|
|
|
if (childCount == null) { |
|
|
|
Widget child = builder(context, index); |
|
|
|
var child = builder(context: context, index: index); |
|
|
|
return child == null ? null : new IndexedSemantics(child: child); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return new IndexedSemantics(child: builder(context, index)); |
|
|
|
return new IndexedSemantics(child: builder(context: context, index: index)); |
|
|
|
} |
|
|
|
|
|
|
|
public int trueIndexOf(int index) { |
|
|
|
|
|
|
|
|
|
|
class ListWheelScrollViewUtils { |
|
|
|
public static int _getItemFromOffset( |
|
|
|
float offset , |
|
|
|
float itemExtent , |
|
|
|
float minScrollExtent , |
|
|
|
float maxScrollExtent |
|
|
|
float offset, |
|
|
|
float itemExtent, |
|
|
|
float minScrollExtent, |
|
|
|
float maxScrollExtent |
|
|
|
return (_clipOffsetToScrollableRange(offset, minScrollExtent, maxScrollExtent) / itemExtent).round(); |
|
|
|
return (_clipOffsetToScrollableRange(offset: offset, minScrollExtent: minScrollExtent, |
|
|
|
maxScrollExtent: maxScrollExtent) / itemExtent).round(); |
|
|
|
|
|
|
|
return Mathf.Min(Mathf.Max(offset, minScrollExtent), maxScrollExtent); |
|
|
|
return Mathf.Min(Mathf.Max(a: offset, b: minScrollExtent), b: maxScrollExtent); |
|
|
|
public readonly int initialItem; |
|
|
|
|
|
|
|
|
|
|
|
public readonly int initialItem; |
|
|
|
|
|
|
|
public int selectedItem { |
|
|
|
get { |
|
|
|
|
|
|
() => |
|
|
|
"The selectedItem property cannot be read when multiple scroll views are attached to the same FixedExtentScrollController." |
|
|
|
); |
|
|
|
_FixedExtentScrollPosition position = (_FixedExtentScrollPosition) this.position; |
|
|
|
var position = (_FixedExtentScrollPosition) this.position; |
|
|
|
return position.itemIndex; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
if (!hasClients) { |
|
|
|
return null; |
|
|
|
} |
|
|
|
List<Future> futures = new List<Future>(); |
|
|
|
|
|
|
|
foreach (_FixedExtentScrollPosition position in positions.Cast<_FixedExtentScrollPosition>()) { |
|
|
|
|
|
|
|
var futures = new List<Future>(); |
|
|
|
|
|
|
|
foreach (var position in positions.Cast<_FixedExtentScrollPosition>()) { |
|
|
|
futures.Add(position.animateTo( |
|
|
|
itemIndex * position.itemExtent, |
|
|
|
duration: duration, |
|
|
|
|
|
|
return Future.wait<object>(futures); |
|
|
|
|
|
|
|
return Future.wait<object>(futures: futures); |
|
|
|
foreach (_FixedExtentScrollPosition position in positions.Cast<_FixedExtentScrollPosition>()) { |
|
|
|
foreach (var position in positions.Cast<_FixedExtentScrollPosition>()) { |
|
|
|
ScrollPhysics physics, |
|
|
|
ScrollPhysics physics, |
|
|
|
ScrollContext context, |
|
|
|
ScrollPosition oldPosition) { |
|
|
|
return new _FixedExtentScrollPosition( |
|
|
|
|
|
|
|
|
|
|
public class FixedExtentMetrics : FixedScrollMetrics, IFixedExtentMetrics { |
|
|
|
public FixedExtentMetrics( |
|
|
|
float minScrollExtent , |
|
|
|
float minScrollExtent, |
|
|
|
float pixels , |
|
|
|
float viewportDimension , |
|
|
|
AxisDirection axisDirection , |
|
|
|
int itemIndex |
|
|
|
float pixels, |
|
|
|
float viewportDimension, |
|
|
|
AxisDirection axisDirection, |
|
|
|
int itemIndex |
|
|
|
minScrollExtent: minScrollExtent , |
|
|
|
maxScrollExtent: maxScrollExtent , |
|
|
|
pixels: pixels , |
|
|
|
viewportDimension: viewportDimension , |
|
|
|
minScrollExtent: minScrollExtent, |
|
|
|
maxScrollExtent: maxScrollExtent, |
|
|
|
pixels: pixels, |
|
|
|
viewportDimension: viewportDimension, |
|
|
|
axisDirection: axisDirection |
|
|
|
) { |
|
|
|
this.itemIndex = itemIndex; |
|
|
|
|
|
|
int? itemIndex = null |
|
|
|
) { |
|
|
|
return new FixedExtentMetrics( |
|
|
|
minScrollExtent: minScrollExtent ?? this.minScrollExtent, |
|
|
|
maxScrollExtent: maxScrollExtent ?? this.maxScrollExtent, |
|
|
|
pixels: pixels ?? this.pixels, |
|
|
|
viewportDimension: viewportDimension ?? this.viewportDimension, |
|
|
|
axisDirection: axisDirection ?? this.axisDirection, |
|
|
|
itemIndex: itemIndex ?? this.itemIndex |
|
|
|
minScrollExtent ?? this.minScrollExtent, |
|
|
|
maxScrollExtent ?? this.maxScrollExtent, |
|
|
|
pixels ?? this.pixels, |
|
|
|
viewportDimension ?? this.viewportDimension, |
|
|
|
axisDirection ?? this.axisDirection, |
|
|
|
itemIndex ?? this.itemIndex |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
class _FixedExtentScrollPosition : ScrollPositionWithSingleContext, IFixedExtentMetrics { |
|
|
|
|
|
|
) : base( |
|
|
|
physics: physics, |
|
|
|
context: context, |
|
|
|
initialPixels: _getItemExtentFromScrollContext(context) * (initialItem ?? 0.0f), |
|
|
|
_getItemExtentFromScrollContext(context: context) * (initialItem ?? 0.0f), |
|
|
|
keepScrollOffset: keepScrollOffset, |
|
|
|
oldPosition: oldPosition, |
|
|
|
debugLabel: debugLabel |
|
|
|
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
static float _getItemExtentFromScrollContext(ScrollContext context) { |
|
|
|
_FixedExtentScrollableState scrollable = (_FixedExtentScrollableState) context; |
|
|
|
return scrollable.itemExtent; |
|
|
|
} |
|
|
|
|
|
|
|
get { return _getItemExtentFromScrollContext(context); } |
|
|
|
get { return _getItemExtentFromScrollContext(context: context); } |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int? itemIndex = null |
|
|
|
) { |
|
|
|
return new FixedExtentMetrics( |
|
|
|
minScrollExtent: minScrollExtent ?? this.minScrollExtent, |
|
|
|
maxScrollExtent: maxScrollExtent ?? this.maxScrollExtent, |
|
|
|
pixels: pixels ?? this.pixels, |
|
|
|
viewportDimension: viewportDimension ?? this.viewportDimension, |
|
|
|
axisDirection: axisDirection ?? this.axisDirection, |
|
|
|
itemIndex: itemIndex ?? this.itemIndex |
|
|
|
minScrollExtent ?? this.minScrollExtent, |
|
|
|
maxScrollExtent ?? this.maxScrollExtent, |
|
|
|
pixels ?? this.pixels, |
|
|
|
viewportDimension ?? this.viewportDimension, |
|
|
|
axisDirection ?? this.axisDirection, |
|
|
|
itemIndex ?? this.itemIndex |
|
|
|
|
|
|
|
static float _getItemExtentFromScrollContext(ScrollContext context) { |
|
|
|
var scrollable = (_FixedExtentScrollableState) context; |
|
|
|
return scrollable.itemExtent; |
|
|
|
} |
|
|
|
public readonly float itemExtent; |
|
|
|
|
|
|
|
ScrollPhysics physics = null, |
|
|
|
ScrollPhysics physics = null, |
|
|
|
|
|
|
|
) : base( |
|
|
|
key: key, |
|
|
|
axisDirection: axisDirection, |
|
|
|
|
|
|
) { |
|
|
|
this.itemExtent = itemExtent; |
|
|
|
} |
|
|
|
|
|
|
|
public readonly float itemExtent; |
|
|
|
|
|
|
|
public override State createState() { |
|
|
|
return new _FixedExtentScrollableState(); |
|
|
|
|
|
|
class _FixedExtentScrollableState : ScrollableState { |
|
|
|
public float itemExtent { |
|
|
|
get { |
|
|
|
_FixedExtentScrollable actualWidget = (_FixedExtentScrollable) widget; |
|
|
|
var actualWidget = (_FixedExtentScrollable) widget; |
|
|
|
return actualWidget.itemExtent; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
public class FixedExtentScrollPhysics : ScrollPhysics { |
|
|
|
public FixedExtentScrollPhysics( |
|
|
|
ScrollPhysics parent = null |
|
|
|
) : base(parent: parent) { } |
|
|
|
) : base(parent: parent) { |
|
|
|
} |
|
|
|
return new FixedExtentScrollPhysics(parent: buildParent(ancestor)); |
|
|
|
return new FixedExtentScrollPhysics(buildParent(ancestor: ancestor)); |
|
|
|
} |
|
|
|
|
|
|
|
public override Simulation createBallisticSimulation(ScrollMetrics position, float velocity) { |
|
|
|
|
|
|
"the FixedExtentScrollController" |
|
|
|
); |
|
|
|
|
|
|
|
_FixedExtentScrollPosition metrics = (_FixedExtentScrollPosition) position; |
|
|
|
var metrics = (_FixedExtentScrollPosition) position; |
|
|
|
if ((velocity <= 0.0f && metrics.pixels <= metrics.minScrollExtent) || |
|
|
|
(velocity >= 0.0f && metrics.pixels >= metrics.maxScrollExtent)) { |
|
|
|
return base.createBallisticSimulation(metrics, velocity); |
|
|
|
if (velocity <= 0.0f && metrics.pixels <= metrics.minScrollExtent || |
|
|
|
velocity >= 0.0f && metrics.pixels >= metrics.maxScrollExtent) { |
|
|
|
return base.createBallisticSimulation(position: metrics, velocity: velocity); |
|
|
|
Simulation testFrictionSimulation = |
|
|
|
base.createBallisticSimulation(metrics, velocity); |
|
|
|
var testFrictionSimulation = |
|
|
|
base.createBallisticSimulation(position: metrics, velocity: velocity); |
|
|
|
&& (testFrictionSimulation.x(float.PositiveInfinity) == metrics.minScrollExtent |
|
|
|
|| testFrictionSimulation.x(float.PositiveInfinity) == metrics.maxScrollExtent)) { |
|
|
|
return base.createBallisticSimulation(metrics, velocity); |
|
|
|
&& (testFrictionSimulation.x(time: float.PositiveInfinity) == metrics.minScrollExtent |
|
|
|
|| testFrictionSimulation.x(time: float.PositiveInfinity) == metrics.maxScrollExtent)) { |
|
|
|
return base.createBallisticSimulation(position: metrics, velocity: velocity); |
|
|
|
int settlingItemIndex = ListWheelScrollViewUtils._getItemFromOffset( |
|
|
|
offset: testFrictionSimulation?.x(float.PositiveInfinity) ?? metrics.pixels, |
|
|
|
var settlingItemIndex = ListWheelScrollViewUtils._getItemFromOffset( |
|
|
|
testFrictionSimulation?.x(time: float.PositiveInfinity) ?? metrics.pixels, |
|
|
|
float settlingPixels = settlingItemIndex * metrics.itemExtent; |
|
|
|
var settlingPixels = settlingItemIndex * metrics.itemExtent; |
|
|
|
|
|
|
|
if (velocity.abs() < tolerance.velocity |
|
|
|
&& (settlingPixels - metrics.pixels).abs() < tolerance.distance) { |
|
|
|
|
|
|
if (settlingItemIndex == metrics.itemIndex) { |
|
|
|
return new SpringSimulation( |
|
|
|
spring, |
|
|
|
metrics.pixels, |
|
|
|
settlingPixels, |
|
|
|
velocity, |
|
|
|
spring: spring, |
|
|
|
start: metrics.pixels, |
|
|
|
end: settlingPixels, |
|
|
|
velocity: velocity, |
|
|
|
metrics.pixels, |
|
|
|
settlingPixels, |
|
|
|
velocity, |
|
|
|
startPosition: metrics.pixels, |
|
|
|
endPosition: settlingPixels, |
|
|
|
startVelocity: velocity, |
|
|
|
tolerance.velocity * velocity.sign() |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
public readonly bool clipToSize; |
|
|
|
|
|
|
|
public readonly ScrollController controller; |
|
|
|
public readonly float diameterRatio; |
|
|
|
public readonly float itemExtent; |
|
|
|
public readonly float magnification; |
|
|
|
public readonly float offAxisFraction; |
|
|
|
public readonly ValueChanged<int> onSelectedItemChanged; |
|
|
|
public readonly float overAndUnderCenterOpacity; |
|
|
|
public readonly float perspective; |
|
|
|
public readonly ScrollPhysics physics; |
|
|
|
public readonly bool renderChildrenOutsideViewport; |
|
|
|
public readonly float squeeze; |
|
|
|
public readonly bool useMagnifier; |
|
|
|
public ListWheelChildDelegate childDelegate; |
|
|
|
|
|
|
|
public ListWheelScrollView( |
|
|
|
List<Widget> children, |
|
|
|
float itemExtent, |
|
|
|
|
|
|
this.renderChildrenOutsideViewport = renderChildrenOutsideViewport; |
|
|
|
} |
|
|
|
|
|
|
|
public ListWheelScrollView ( |
|
|
|
public ListWheelScrollView( |
|
|
|
float itemExtent, |
|
|
|
Key key = null, |
|
|
|
ScrollController controller = null, |
|
|
|
|
|
|
ListWheelChildDelegate childDelegate = null |
|
|
|
) : base(key: key) { |
|
|
|
D.assert(childDelegate != null); |
|
|
|
D.assert(diameterRatio > 0.0, ()=>RenderListWheelViewport.diameterRatioZeroMessage); |
|
|
|
D.assert(diameterRatio > 0.0, () => RenderListWheelViewport.diameterRatioZeroMessage); |
|
|
|
D.assert(perspective <= 0.01,()=> RenderListWheelViewport.perspectiveTooHighMessage); |
|
|
|
D.assert(perspective <= 0.01, () => RenderListWheelViewport.perspectiveTooHighMessage); |
|
|
|
D.assert(magnification > 0); |
|
|
|
D.assert(overAndUnderCenterOpacity >= 0 && overAndUnderCenterOpacity <= 1); |
|
|
|
D.assert(itemExtent != null); |
|
|
|
|
|
|
!renderChildrenOutsideViewport || !clipToSize,()=> |
|
|
|
RenderListWheelViewport.clipToSizeAndRenderChildrenOutsideViewportConflict |
|
|
|
!renderChildrenOutsideViewport || !clipToSize, () => |
|
|
|
RenderListWheelViewport.clipToSizeAndRenderChildrenOutsideViewportConflict |
|
|
|
); |
|
|
|
this.controller = controller; |
|
|
|
this.physics = physics; |
|
|
|
|
|
|
this.childDelegate = childDelegate; |
|
|
|
} |
|
|
|
|
|
|
|
public readonly ScrollController controller; |
|
|
|
public readonly ScrollPhysics physics; |
|
|
|
public readonly float diameterRatio; |
|
|
|
public readonly float perspective; |
|
|
|
public readonly float offAxisFraction; |
|
|
|
public readonly bool useMagnifier; |
|
|
|
public readonly float magnification; |
|
|
|
public readonly float itemExtent; |
|
|
|
public readonly float overAndUnderCenterOpacity; |
|
|
|
public readonly float squeeze; |
|
|
|
public readonly ValueChanged<int> onSelectedItemChanged; |
|
|
|
public readonly bool clipToSize; |
|
|
|
public readonly bool renderChildrenOutsideViewport; |
|
|
|
public ListWheelChildDelegate childDelegate; |
|
|
|
|
|
|
|
public override State createState() { |
|
|
|
return new _ListWheelScrollViewState(); |
|
|
|
} |
|
|
|
|
|
|
int _lastReportedItemIndex = 0; |
|
|
|
int _lastReportedItemIndex; |
|
|
|
ScrollController scrollController; |
|
|
|
|
|
|
|
public override void initState() { |
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
public override void didUpdateWidget(StatefulWidget oldWidget) { |
|
|
|
base.didUpdateWidget(oldWidget); |
|
|
|
base.didUpdateWidget(oldWidget: oldWidget); |
|
|
|
ScrollController oldScrollController = scrollController; |
|
|
|
SchedulerBinding.instance.addPostFrameCallback((_) => { oldScrollController.dispose(); }); |
|
|
|
var oldScrollController = scrollController; |
|
|
|
SchedulerBinding.instance.addPostFrameCallback(_ => { oldScrollController.dispose(); }); |
|
|
|
scrollController = widget.controller; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
onNotification: (ScrollNotification notification) => { |
|
|
|
onNotification: notification => { |
|
|
|
int currentItemIndex = metrics.itemIndex; |
|
|
|
var currentItemIndex = metrics.itemIndex; |
|
|
|
int trueIndex = widget.childDelegate.trueIndexOf(currentItemIndex); |
|
|
|
widget.onSelectedItemChanged(trueIndex); |
|
|
|
var trueIndex = widget.childDelegate.trueIndexOf(index: currentItemIndex); |
|
|
|
widget.onSelectedItemChanged(value: trueIndex); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
controller: scrollController, |
|
|
|
physics: widget.physics, |
|
|
|
itemExtent: widget.itemExtent, |
|
|
|
viewportBuilder: (BuildContext _context, ViewportOffset _offset) => { |
|
|
|
viewportBuilder: (_context, _offset) => { |
|
|
|
return new ListWheelViewport( |
|
|
|
diameterRatio: widget.diameterRatio, |
|
|
|
perspective: widget.perspective, |
|
|
|
|
|
|
overAndUnderCenterOpacity: widget.overAndUnderCenterOpacity, |
|
|
|
itemExtent: widget.itemExtent , |
|
|
|
itemExtent: widget.itemExtent, |
|
|
|
squeeze: widget.squeeze, |
|
|
|
clipToSize: widget.clipToSize, |
|
|
|
renderChildrenOutsideViewport: widget.renderChildrenOutsideViewport, |
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
public class ListWheelElement : RenderObjectElement, IListWheelChildManager { |
|
|
|
public ListWheelElement(ListWheelViewport widget) : base(widget) { } |
|
|
|
readonly SplayTree<int, Element> _childElements = new SplayTree<int, Element>(); |
|
|
|
|
|
|
|
|
|
|
|
readonly Dictionary<int, Widget> _childWidgets = new Dictionary<int, Widget>(); |
|
|
|
|
|
|
|
public ListWheelElement(ListWheelViewport widget) : base(widget: widget) { |
|
|
|
} |
|
|
|
|
|
|
|
public new ListWheelViewport widget { |
|
|
|
get { return (ListWheelViewport) base.widget; } |
|
|
|
|
|
|
get { return (RenderListWheelViewport)base.renderObject; } |
|
|
|
get { return (RenderListWheelViewport) base.renderObject; } |
|
|
|
public int? childCount { |
|
|
|
get { return widget.childDelegate.estimatedChildCount; } |
|
|
|
} |
|
|
|
readonly Dictionary<int, Widget> _childWidgets = new Dictionary<int, Widget>(); |
|
|
|
public bool childExistsAt(int index) { |
|
|
|
return retrieveWidget(index: index) != null; |
|
|
|
} |
|
|
|
readonly SplayTree<int, Element> _childElements = new SplayTree<int, Element>(); |
|
|
|
public void createChild(int index, RenderBox after) { |
|
|
|
owner.buildScope(this, () => { |
|
|
|
var insertFirst = after == null; |
|
|
|
D.assert(insertFirst || _childElements.getOrDefault(index - 1) != null); |
|
|
|
var newChild = updateChild(_childElements.getOrDefault(key: index), retrieveWidget(index: index), |
|
|
|
newSlot: index); |
|
|
|
if (newChild != null) { |
|
|
|
_childElements[key: index] = newChild; |
|
|
|
} |
|
|
|
else { |
|
|
|
_childElements.Remove(key: index); |
|
|
|
} |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
public void removeChild(RenderBox child) { |
|
|
|
var index = renderObject.indexOf(child: child); |
|
|
|
owner.buildScope(this, () => { |
|
|
|
D.assert(_childElements.ContainsKey(key: index)); |
|
|
|
var result = updateChild(_childElements[key: index], null, newSlot: index); |
|
|
|
D.assert(result == null); |
|
|
|
_childElements.Remove(key: index); |
|
|
|
D.assert(!_childElements.ContainsKey(key: index)); |
|
|
|
}); |
|
|
|
} |
|
|
|
ListWheelViewport oldWidget = widget; |
|
|
|
base.update(newWidget); |
|
|
|
ListWheelChildDelegate newDelegate = ((ListWheelViewport) newWidget).childDelegate; |
|
|
|
ListWheelChildDelegate oldDelegate = oldWidget.childDelegate; |
|
|
|
var oldWidget = widget; |
|
|
|
base.update(newWidget: newWidget); |
|
|
|
var newDelegate = ((ListWheelViewport) newWidget).childDelegate; |
|
|
|
var oldDelegate = oldWidget.childDelegate; |
|
|
|
(newDelegate.GetType() != oldDelegate.GetType() || newDelegate.shouldRebuild(oldDelegate))) { |
|
|
|
(newDelegate.GetType() != oldDelegate.GetType() || |
|
|
|
newDelegate.shouldRebuild(oldDelegate: oldDelegate))) { |
|
|
|
} |
|
|
|
|
|
|
|
public int? childCount { |
|
|
|
get { return widget.childDelegate.estimatedChildCount; } |
|
|
|
} |
|
|
|
|
|
|
|
protected override void performRebuild() { |
|
|
|
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
int firstIndex = _childElements.First()?.Key ?? 0; |
|
|
|
int lastIndex = _childElements.Last()?.Key ?? _childElements.Count; |
|
|
|
var firstIndex = _childElements.First()?.Key ?? 0; |
|
|
|
var lastIndex = _childElements.Last()?.Key ?? _childElements.Count; |
|
|
|
for (int index = firstIndex; index <= lastIndex; ++index) { |
|
|
|
Element newChild = updateChild(_childElements[index], retrieveWidget(index), index); |
|
|
|
for (var index = firstIndex; index <= lastIndex; ++index) { |
|
|
|
var newChild = updateChild(_childElements[key: index], retrieveWidget(index: index), newSlot: index); |
|
|
|
_childElements[index] = newChild; |
|
|
|
_childElements[key: index] = newChild; |
|
|
|
_childElements.Remove(index); |
|
|
|
_childElements.Remove(key: index); |
|
|
|
return _childWidgets.putIfAbsent(index, |
|
|
|
() => { return widget.childDelegate.build(this, index); }); |
|
|
|
} |
|
|
|
|
|
|
|
public bool childExistsAt(int index) { |
|
|
|
return retrieveWidget(index) != null; |
|
|
|
} |
|
|
|
|
|
|
|
public void createChild(int index, RenderBox after) { |
|
|
|
owner.buildScope(this, () => { |
|
|
|
bool insertFirst = after == null; |
|
|
|
D.assert(insertFirst || _childElements.getOrDefault(index - 1) != null); |
|
|
|
Element newChild = updateChild(_childElements.getOrDefault(index), retrieveWidget(index), index); |
|
|
|
if (newChild != null) { |
|
|
|
_childElements[index] = newChild; |
|
|
|
} |
|
|
|
else { |
|
|
|
_childElements.Remove(index); |
|
|
|
} |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
public void removeChild(RenderBox child) { |
|
|
|
int index = renderObject.indexOf(child); |
|
|
|
owner.buildScope(this, () => { |
|
|
|
D.assert(_childElements.ContainsKey(index)); |
|
|
|
Element result = updateChild(_childElements[index], null, index); |
|
|
|
D.assert(result == null); |
|
|
|
_childElements.Remove(index); |
|
|
|
D.assert(!_childElements.ContainsKey(index)); |
|
|
|
}); |
|
|
|
return _childWidgets.putIfAbsent(key: index, |
|
|
|
() => { return widget.childDelegate.build(this, index: index); }); |
|
|
|
ListWheelParentData oldParentData = (ListWheelParentData) child?.renderObject?.parentData; |
|
|
|
Element newChild = base.updateChild(child, newWidget, newSlot); |
|
|
|
ListWheelParentData newParentData = (ListWheelParentData) newChild?.renderObject?.parentData; |
|
|
|
var oldParentData = (ListWheelParentData) child?.renderObject?.parentData; |
|
|
|
var newChild = base.updateChild(child: child, newWidget: newWidget, newSlot: newSlot); |
|
|
|
var newParentData = (ListWheelParentData) newChild?.renderObject?.parentData; |
|
|
|
if (newParentData != null) { |
|
|
|
newParentData.index = (int) newSlot; |
|
|
|
if (oldParentData != null) { |
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
protected override void insertChildRenderObject(RenderObject child, object slot) { |
|
|
|
RenderListWheelViewport renderObject = this.renderObject; |
|
|
|
D.assert(renderObject.debugValidateChild(child)); |
|
|
|
int slotNum = (int) slot; |
|
|
|
renderObject.insert(child as RenderBox, after: _childElements.getOrDefault(slotNum - 1)?.renderObject as RenderBox); |
|
|
|
var renderObject = this.renderObject; |
|
|
|
D.assert(renderObject.debugValidateChild(child: child)); |
|
|
|
var slotNum = (int) slot; |
|
|
|
renderObject.insert(child as RenderBox, |
|
|
|
_childElements.getOrDefault(slotNum - 1)?.renderObject as RenderBox); |
|
|
|
protected override void moveChildRenderObject(RenderObject child, dynamic slot) { |
|
|
|
string moveChildRenderObjectErrorMessage = |
|
|
|
protected override void moveChildRenderObject(RenderObject child, dynamic slot) { |
|
|
|
var moveChildRenderObjectErrorMessage = |
|
|
|
"Currently we maintain the list in contiguous increasing order, so " + |
|
|
|
"moving children around is not allowed."; |
|
|
|
D.assert(false, () => moveChildRenderObjectErrorMessage); |
|
|
|
|
|
|
|
|
|
|
public override void visitChildren(ElementVisitor visitor) { |
|
|
|
foreach (var item in _childElements) { |
|
|
|
visitor(item.Value); |
|
|
|
visitor(element: item.Value); |
|
|
|
_childElements.Remove((int) (child.slot)); |
|
|
|
base.forgetChild(child); |
|
|
|
_childElements.Remove((int) child.slot); |
|
|
|
base.forgetChild(child: child); |
|
|
|
public readonly ListWheelChildDelegate childDelegate; |
|
|
|
public readonly bool clipToSize; |
|
|
|
|
|
|
|
public readonly float diameterRatio; |
|
|
|
public readonly float? itemExtent; |
|
|
|
public readonly float magnification; |
|
|
|
public readonly float offAxisFraction; |
|
|
|
public readonly ViewportOffset offset; |
|
|
|
public readonly float overAndUnderCenterOpacity; |
|
|
|
public readonly float perspective; |
|
|
|
public readonly bool renderChildrenOutsideViewport; |
|
|
|
public readonly float squeeze; |
|
|
|
public readonly bool useMagnifier; |
|
|
|
|
|
|
|
public ListWheelViewport( |
|
|
|
Key key = null, |
|
|
|
float diameterRatio = RenderListWheelViewport.defaultDiameterRatio, |
|
|
|
|
|
|
this.childDelegate = childDelegate; |
|
|
|
} |
|
|
|
|
|
|
|
public readonly float diameterRatio; |
|
|
|
public readonly float perspective; |
|
|
|
public readonly float offAxisFraction; |
|
|
|
public readonly bool useMagnifier; |
|
|
|
public readonly float magnification; |
|
|
|
public readonly float overAndUnderCenterOpacity; |
|
|
|
public readonly float? itemExtent; |
|
|
|
public readonly float squeeze; |
|
|
|
public readonly bool clipToSize; |
|
|
|
public readonly bool renderChildrenOutsideViewport; |
|
|
|
public readonly ViewportOffset offset; |
|
|
|
public readonly ListWheelChildDelegate childDelegate; |
|
|
|
|
|
|
|
ListWheelElement childManager = (ListWheelElement) context; |
|
|
|
var childManager = (ListWheelElement) context; |
|
|
|
return new RenderListWheelViewport( |
|
|
|
childManager: childManager, |
|
|
|
offset: offset, |
|
|
|
|
|
|
useMagnifier: useMagnifier, |
|
|
|
magnification: magnification, |
|
|
|
overAndUnderCenterOpacity: overAndUnderCenterOpacity, |
|
|
|
itemExtent: itemExtent ?? 1.0f , |
|
|
|
itemExtent: itemExtent ?? 1.0f, |
|
|
|
squeeze: squeeze, |
|
|
|
clipToSize: clipToSize, |
|
|
|
renderChildrenOutsideViewport: renderChildrenOutsideViewport |
|
|
|