浏览代码

scroll updates

/main
kg 6 年前
当前提交
9ad18499
共有 40 个文件被更改,包括 1361 次插入225 次删除
  1. 14
      Assets/UIWidgets/Tests/Gestures.cs
  2. 8
      Assets/UIWidgets/Tests/Paragraph.cs
  3. 12
      Assets/UIWidgets/Tests/RenderBoxes.cs
  4. 16
      Assets/UIWidgets/Tests/RenderEditable.cs
  5. 8
      Assets/UIWidgets/Tests/Widgets.cs
  6. 85
      Assets/UIWidgets/editor/editor_window.cs
  7. 7
      Assets/UIWidgets/gestures/arena.cs
  8. 15
      Assets/UIWidgets/gestures/binding.cs
  9. 4
      Assets/UIWidgets/gestures/long_press.cs
  10. 16
      Assets/UIWidgets/gestures/monodrag.cs
  11. 21
      Assets/UIWidgets/gestures/multitap.cs
  12. 21
      Assets/UIWidgets/gestures/recognizer.cs
  13. 4
      Assets/UIWidgets/gestures/tap.cs
  14. 27
      Assets/UIWidgets/rendering/binding.cs
  15. 5
      Assets/UIWidgets/rendering/editable.cs
  16. 11
      Assets/UIWidgets/rendering/proxy_box.cs
  17. 33
      Assets/UIWidgets/rendering/sliver_fixed_extent_list.cs
  18. 4
      Assets/UIWidgets/rendering/sliver_list.cs
  19. 6
      Assets/UIWidgets/rendering/sliver_multi_box_adaptor.cs
  20. 6
      Assets/UIWidgets/rendering/sliver_padding.cs
  21. 2
      Assets/UIWidgets/rendering/view.cs
  22. 32
      Assets/UIWidgets/scheduler/binding.cs
  23. 6
      Assets/UIWidgets/scheduler/ticker.cs
  24. 20
      Assets/UIWidgets/ui/window.cs
  25. 53
      Assets/UIWidgets/widgets/basic.cs
  26. 23
      Assets/UIWidgets/widgets/binding.cs
  27. 6
      Assets/UIWidgets/widgets/framework.cs
  28. 1
      Assets/UIWidgets/widgets/primary_scroll_controller.cs
  29. 2
      Assets/UIWidgets/widgets/scroll_activity.cs
  30. 2
      Assets/UIWidgets/widgets/scroll_configuration.cs
  31. 9
      Assets/UIWidgets/widgets/scroll_position.cs
  32. 2
      Assets/UIWidgets/widgets/scroll_position_with_single_context.cs
  33. 320
      Assets/UIWidgets/widgets/scroll_view.cs
  34. 20
      Assets/UIWidgets/widgets/scrollable.cs
  35. 21
      Assets/UIWidgets/widgets/ticker_provider.cs
  36. 13
      Assets/UIWidgets/widgets/viewport.cs
  37. 206
      Assets/UIWidgets/rendering/automatic_keep_alive.cs
  38. 3
      Assets/UIWidgets/rendering/automatic_keep_alive.cs.meta
  39. 519
      Assets/UIWidgets/widgets/sliver.cs
  40. 3
      Assets/UIWidgets/widgets/sliver.cs.meta

14
Assets/UIWidgets/Tests/Gestures.cs


private WindowAdapter windowAdapter;
private RendererBindings rendererBindings;
[NonSerialized] private bool hasInvoked = false;
void OnGUI() {

this.hasInvoked = true;
var renderBox = this._options[this._selected]();
this.rendererBindings.setRoot(renderBox);
if (this.windowAdapter != null) {
this.windowAdapter.attachRootRenderBox(renderBox);
}
}
if (this.windowAdapter != null) {

private void OnEnable() {
this.windowAdapter = new WindowAdapter(this);
this.rendererBindings = new RendererBindings(this.windowAdapter);
this._tapRecognizer = new TapGestureRecognizer(this.rendererBindings.rendererBinding);
this._tapRecognizer = new TapGestureRecognizer();
this._panRecognizer = new PanGestureRecognizer(this.rendererBindings.rendererBinding);
this._panRecognizer = new PanGestureRecognizer();
this._doubleTapGesture = new DoubleTapGestureRecognizer(this.rendererBindings.rendererBinding);
this._doubleTapGesture = new DoubleTapGestureRecognizer();
this.rendererBindings = null;
}
TapGestureRecognizer _tapRecognizer;

8
Assets/UIWidgets/Tests/Paragraph.cs


private WindowAdapter windowAdapter;
private RendererBindings rendererBindings;
[NonSerialized] private bool hasInvoked = false;
void OnGUI() {

this.hasInvoked = true;
var renderBox = this._options[this._selected]();
this.rendererBindings.setRoot(renderBox);
if (this.windowAdapter != null) {
this.windowAdapter.attachRootRenderBox(renderBox);
}
}
if (this.windowAdapter != null) {

private void OnEnable() {
this.windowAdapter = new WindowAdapter(this);
this.rendererBindings = new RendererBindings(this.windowAdapter);
this.rendererBindings = null;
}
RenderBox none() {

12
Assets/UIWidgets/Tests/RenderBoxes.cs


private WindowAdapter windowAdapter;
private RendererBindings rendererBindings;
[NonSerialized] private bool hasInvoked = false;
void OnGUI() {

this.hasInvoked = true;
var renderBox = this._options[this._selected]();
this.rendererBindings.setRoot(renderBox);
if (this.windowAdapter != null) {
this.windowAdapter.attachRootRenderBox(renderBox);
}
}
void Update() {

private void OnEnable() {
this.windowAdapter = new WindowAdapter(this);
this.rendererBindings = new RendererBindings(this.windowAdapter);
this.rendererBindings = null;
}
RenderBox none() {

color: new Color(0xFF00FFFF)
)
)));
flexbox.add(new RenderConstrainedBox(
additionalConstraints: new BoxConstraints(minWidth: 50, minHeight: 100),
child: new RenderDecoratedBox(

)));
return flexbox;
}

16
Assets/UIWidgets/Tests/RenderEditable.cs


using UIWidgets.rendering;
using UIWidgets.service;
using UIWidgets.ui;
using UnityEditor;
using FontStyle = UIWidgets.ui.FontStyle;
namespace UIWidgets.Tests
{

private WindowAdapter windowAdapter;
private RendererBindings rendererBindings;
[NonSerialized] private bool hasInvoked = false;
void OnGUI() {

this.hasInvoked = true;
var renderBox = this._options[this._selected]();
this.rendererBindings.setRoot(renderBox);
if (this.windowAdapter != null) {
this.windowAdapter.attachRootRenderBox(renderBox);
}
}
if (this.windowAdapter != null) {

private void OnEnable() {
this.windowAdapter = new WindowAdapter(this);
this.rendererBindings = new RendererBindings(this.windowAdapter);
this.rendererBindings = null;
}
private RenderBox box(RenderBox p, int width = 400, int height = 400)

flexbox.add(flexItemBox(
new rendering.RenderEditable(span, TextDirection.ltr,
new _FixedViewportOffset(0.0), new ValueNotifier<bool>(true), this.rendererBindings.rendererBinding,
new _FixedViewportOffset(0.0), new ValueNotifier<bool>(true),
onSelectionChanged: selectionChanged, cursorColor: Color.fromARGB(255, 0, 0, 0),
maxLines: 100,
selectionColor: Color.fromARGB(255, 255, 0, 0))

}, style:new painting.TextStyle(height:1.0));
flexbox.add(flexItemBox(
new rendering.RenderEditable(span, TextDirection.ltr,
new _FixedViewportOffset(0.0), new ValueNotifier<bool>(true), this.rendererBindings.rendererBinding,
new _FixedViewportOffset(0.0), new ValueNotifier<bool>(true),
onSelectionChanged: selectionChanged, cursorColor: Color.fromARGB(255, 0, 0, 0),
maxLines: 100,
selectionColor: Color.fromARGB(255, 255, 0, 0))

}, style:new painting.TextStyle(height:1.0));
flexbox.add(flexItemBox(
new rendering.RenderEditable(span, TextDirection.ltr,
new _FixedViewportOffset(0.0), new ValueNotifier<bool>(true), this.rendererBindings.rendererBinding,
new _FixedViewportOffset(0.0), new ValueNotifier<bool>(true),
onSelectionChanged: selectionChanged, cursorColor: Color.fromARGB(255, 0, 0, 0),
selectionColor: Color.fromARGB(255, 255, 0, 0))
, width:300));

8
Assets/UIWidgets/Tests/Widgets.cs


public class Widgets : EditorWindow {
private WindowAdapter windowAdapter;
private WidgetsBindings widgetsBindings;
private PaintingBinding paintingBinding;
private Widget root;

this.paintingBinding = new PaintingBinding(null);
paintingBinding.initInstances();
this.windowAdapter = new WindowAdapter(this);
this.widgetsBindings = new WidgetsBindings(windowAdapter);
if (widgetsBindings != null) {
widgetsBindings.attachRootWidget(root);
}
this.windowAdapter.attachRootWidget(root);
this.widgetsBindings = null;
}
}
}

85
Assets/UIWidgets/editor/editor_window.cs


using System.Diagnostics;
using UIWidgets.async;
using UIWidgets.flow;
using UIWidgets.rendering;
using UIWidgets.widgets;
using UnityEditor;
using UnityEngine;
using Rect = UnityEngine.Rect;

public WindowAdapter(EditorWindow editorWindow) {
this.editorWindow = editorWindow;
this.editorWindow.wantsMouseMove = false;
this.editorWindow.wantsMouseEnterLeaveWindow = false;
this._editorWindow = editorWindow;
this._editorWindow.wantsMouseMove = false;
this._editorWindow.wantsMouseEnterLeaveWindow = false;
this._lastPosition.width * EditorGUIUtility.pixelsPerPoint,
this._lastPosition.width * EditorGUIUtility.pixelsPerPoint,
Window.instance = this;
try {
this._binding = new WidgetsBinding();
}
finally {
Window.instance = null;
}
public readonly EditorWindow editorWindow;
readonly EditorWindow _editorWindow;
readonly WidgetsBinding _binding;
Rect _lastPosition;
readonly DateTime _epoch = new DateTime(Stopwatch.GetTimestamp());
readonly MicrotaskQueue _microtaskQueue = new MicrotaskQueue();

Window.instance = this;
WidgetsBinding.instance = this._binding;
try {
this.doOnGUI();
}
finally {
Window.instance = null;
WidgetsBinding.instance = null;
}
}
private void doOnGUI() {
var evt = Event.current;
if (evt.type == EventType.Repaint) {

}
public void Update() {
Window.instance = this;
WidgetsBinding.instance = this._binding;
try {
this.doUpdate();
}
finally {
Window.instance = null;
WidgetsBinding.instance = null;
}
}
private void doUpdate() {
this.flushMicrotasks();
this._timerProvider.update();

dirty = true;
}
if (this._lastPosition != this.editorWindow.position) {
if (this._lastPosition != this._editorWindow.position) {
this._lastPosition = this.editorWindow.position;
this._lastPosition = this._editorWindow.position;
this._physicalSize = new Size(
this._lastPosition.width * EditorGUIUtility.pixelsPerPoint,
this._lastPosition.height * EditorGUIUtility.pixelsPerPoint);

}
public override void scheduleFrame() {
if (this.editorWindow != null) {
this.editorWindow.Repaint();
if (this._editorWindow != null) {
this._editorWindow.Repaint();
}
}

public override Timer run(TimeSpan duration, Action callback) {
return this._timerProvider.run(duration, callback);
}
public void attachRootRenderBox(RenderBox root) {
Window.instance = this;
WidgetsBinding.instance = this._binding;
try {
this._binding.renderView.child = root;
}
finally {
Window.instance = null;
WidgetsBinding.instance = null;
}
}
public void attachRootWidget(Widget root) {
Window.instance = this;
WidgetsBinding.instance = this._binding;
try {
this._binding.attachRootWidget(root);
}
finally {
Window.instance = null;
WidgetsBinding.instance = null;
}
}
}
}

7
Assets/UIWidgets/gestures/arena.cs


public class GestureArenaManager {
readonly Dictionary<int, _GestureArena> _arenas = new Dictionary<int, _GestureArena>();
readonly Window _window;
public GestureArenaManager(Window window) {
this._window = window;
}
public GestureArenaEntry add(int pointer, GestureArenaMember member) {
_GestureArena state = this._arenas.putIfAbsent(pointer, () => {

D.assert(!state.isOpen);
if (state.members.Count == 1) {
this._window.scheduleMicrotask(() => this._resolveByDefault(pointer, state));
Window.instance.scheduleMicrotask(() => this._resolveByDefault(pointer, state));
} else if (state.members.isEmpty()) {
this._arenas.Remove(pointer);
D.assert(this._debugLogDiagnostic(pointer, "Arena empty."));

15
Assets/UIWidgets/gestures/binding.cs


namespace UIWidgets.gestures {
public class GestureBinding : SchedulerBinding, HitTestable, HitTestDispatcher, HitTestTarget {
public GestureBinding(Window window) : base(window) {
this.window.onPointerEvent += this._handlePointerDataPacket;
public static new GestureBinding instance {
get { return (GestureBinding) SchedulerBinding.instance; }
set { SchedulerBinding.instance = value; }
}
public GestureBinding() {
Window.instance.onPointerEvent += this._handlePointerDataPacket;
this.gestureArena = new GestureArenaManager(window);
this.gestureArena = new GestureArenaManager();
foreach (var pointerEvent in PointerEventConverter.expand(packet.data, this.window.devicePixelRatio)) {
foreach (var pointerEvent in PointerEventConverter.expand(packet.data, Window.instance.devicePixelRatio)) {
this._pendingPointerEvents.Enqueue(pointerEvent);
}

public void cancelPointer(int pointer) {
if (this._pendingPointerEvents.isEmpty()) {
this.window.scheduleMicrotask(this._flushPointerEventQueue);
Window.instance.scheduleMicrotask(this._flushPointerEventQueue);
}
this._pendingPointerEvents.Enqueue(

4
Assets/UIWidgets/gestures/long_press.cs


public delegate void GestureLongPressCallback();
public class LongPressGestureRecognizer : PrimaryPointerGestureRecognizer {
public LongPressGestureRecognizer(GestureBinding binding = null, object debugOwner = null) :
base(binding: binding, deadline: Constants.kLongPressTimeout, debugOwner: debugOwner) {
public LongPressGestureRecognizer(object debugOwner = null) :
base(deadline: Constants.kLongPressTimeout, debugOwner: debugOwner) {
}
public GestureLongPressCallback onLongPress;

16
Assets/UIWidgets/gestures/monodrag.cs


public delegate void GestureDragCancelCallback();
public abstract class DragGestureRecognizer : OneSequenceGestureRecognizer {
public DragGestureRecognizer(GestureBinding binding, object debugOwner = null)
: base(binding: binding, debugOwner: debugOwner) {
public DragGestureRecognizer(object debugOwner = null)
: base(debugOwner: debugOwner) {
}
public GestureDragDownCallback onDown;

}
public class VerticalDragGestureRecognizer : DragGestureRecognizer {
public VerticalDragGestureRecognizer(GestureBinding binding = null, Object debugOwner = null)
: base(binding: binding, debugOwner: debugOwner) {
public VerticalDragGestureRecognizer(Object debugOwner = null)
: base(debugOwner: debugOwner) {
}
protected override bool _isFlingGesture(VelocityEstimate estimate) {

}
public class HorizontalDragGestureRecognizer : DragGestureRecognizer {
public HorizontalDragGestureRecognizer(GestureBinding binding = null, Object debugOwner = null)
: base(binding: binding, debugOwner: debugOwner) {
public HorizontalDragGestureRecognizer(Object debugOwner = null)
: base(debugOwner: debugOwner) {
}
protected override bool _isFlingGesture(VelocityEstimate estimate) {

}
public class PanGestureRecognizer : DragGestureRecognizer {
public PanGestureRecognizer(GestureBinding binding = null, Object debugOwner = null)
: base(binding: binding, debugOwner: debugOwner) {
public PanGestureRecognizer(Object debugOwner = null)
: base(debugOwner: debugOwner) {
}
protected override bool _isFlingGesture(VelocityEstimate estimate) {

21
Assets/UIWidgets/gestures/multitap.cs


class _TapTracker {
internal _TapTracker(
GestureBinding binding = null,
this._binding = binding;
this.pointer = evt.pointer;
this._initialPosition = evt.position;
this.entry = entry;

public readonly GestureArenaEntry entry;
readonly Offset _initialPosition;
readonly GestureBinding _binding;
bool _isTrackingPointer = false;

this._binding.pointerRouter.addRoute(this.pointer, route);
GestureBinding.instance.pointerRouter.addRoute(this.pointer, route);
}
}

this._binding.pointerRouter.removeRoute(this.pointer, route);
GestureBinding.instance.pointerRouter.removeRoute(this.pointer, route);
}
}

}
public class DoubleTapGestureRecognizer : GestureRecognizer {
public DoubleTapGestureRecognizer(
GestureBinding binding = null, object debugOwner = null)
: base(binding: binding, debugOwner: debugOwner) {
public DoubleTapGestureRecognizer(object debugOwner = null)
: base(debugOwner: debugOwner) {
}
public GestureDoubleTapCallback onDoubleTap;

this._stopDoubleTapTimer();
_TapTracker tracker = new _TapTracker(
binding: this._binding,
entry: this._binding.gestureArena.add(evt.pointer, this)
entry: GestureBinding.instance.gestureArena.add(evt.pointer, this)
);
this._trackers[evt.pointer] = tracker;
tracker.startTrackingPointer(this._handleEvent);

_TapTracker tracker = this._firstTap;
this._firstTap = null;
this._reject(tracker);
this._binding.gestureArena.release(tracker.pointer);
GestureBinding.instance.gestureArena.release(tracker.pointer);
}
this._clearTrackers();

this._startDoubleTapTimer();
this._binding.gestureArena.hold(tracker.pointer);
GestureBinding.instance.gestureArena.hold(tracker.pointer);
this._freezeTracker(tracker);
this._trackers.Remove(tracker.pointer);
this._clearTrackers();

void _startDoubleTapTimer() {
this._doubleTapTimer =
this._doubleTapTimer
?? this._binding.window.run(Constants.kDoubleTapTimeout, this._reset);
?? Window.instance.run(Constants.kDoubleTapTimeout, this._reset);
}
void _stopDoubleTapTimer() {

21
Assets/UIWidgets/gestures/recognizer.cs


public delegate T RecognizerCallback<T>();
public abstract class GestureRecognizer : DiagnosticableTree, GestureArenaMember {
protected GestureRecognizer(GestureBinding binding = null, object debugOwner = null) {
this._binding = binding;
protected GestureRecognizer(object debugOwner = null) {
protected readonly GestureBinding _binding;
public readonly object debugOwner;

}
public abstract class OneSequenceGestureRecognizer : GestureRecognizer {
protected OneSequenceGestureRecognizer(
GestureBinding binding = null, object debugOwner = null) : base(binding, debugOwner) {
protected OneSequenceGestureRecognizer(object debugOwner = null) : base(debugOwner) {
}
readonly Dictionary<int, GestureArenaEntry> _entries = new Dictionary<int, GestureArenaEntry>();

public override void dispose() {
this.resolve(GestureDisposition.rejected);
foreach (int pointer in this._trackedPointers) {
this._binding.pointerRouter.removeRoute(pointer, this.handleEvent);
GestureBinding.instance.pointerRouter.removeRoute(pointer, this.handleEvent);
}
this._trackedPointers.Clear();

return this._team.add(pointer, this);
}
return this._binding.gestureArena.add(pointer, this);
return GestureBinding.instance.gestureArena.add(pointer, this);
this._binding.pointerRouter.addRoute(pointer, this.handleEvent);
GestureBinding.instance.pointerRouter.addRoute(pointer, this.handleEvent);
this._trackedPointers.Add(pointer);
D.assert(!this._entries.ContainsKey(pointer));
this._entries[pointer] = this._addPointerToArena(pointer);

if (this._trackedPointers.Contains(pointer)) {
this._binding.pointerRouter.removeRoute(pointer, this.handleEvent);
GestureBinding.instance.pointerRouter.removeRoute(pointer, this.handleEvent);
this._trackedPointers.Remove(pointer);
if (this._trackedPointers.isEmpty()) {
this.didStopTrackingLastPointer(pointer);

public abstract class PrimaryPointerGestureRecognizer : OneSequenceGestureRecognizer {
protected PrimaryPointerGestureRecognizer(
TimeSpan? deadline = null,
GestureBinding binding = null,
) : base(binding: binding, debugOwner: debugOwner) {
) : base(debugOwner: debugOwner) {
this.deadline = deadline;
}

this.primaryPointer = evt.pointer;
this.initialPosition = evt.position;
if (this.deadline != null) {
this._timer = this._binding.window.run(this.deadline.Value, this.didExceedDeadline);
this._timer = Window.instance.run(this.deadline.Value, this.didExceedDeadline);
}
}
}

4
Assets/UIWidgets/gestures/tap.cs


public delegate void GestureTapCancelCallback();
public class TapGestureRecognizer : PrimaryPointerGestureRecognizer {
public TapGestureRecognizer(GestureBinding binding = null, object debugOwner = null)
: base(deadline: Constants.kPressTimeout, binding: binding, debugOwner: debugOwner) {
public TapGestureRecognizer(object debugOwner = null)
: base(deadline: Constants.kPressTimeout, debugOwner: debugOwner) {
}
public GestureTapDownCallback onTapDown;

27
Assets/UIWidgets/rendering/binding.cs


namespace UIWidgets.rendering {
public class RendererBinding : GestureBinding {
public RendererBinding(Window window) : base(window) {
public static new RendererBinding instance {
get { return (RendererBinding) GestureBinding.instance; }
set { GestureBinding.instance = value; }
}
public RendererBinding() {
window.onMetricsChanged += this.handleMetricsChanged;
Window.instance.onMetricsChanged += this.handleMetricsChanged;
this.initRenderView();
D.assert(this.renderView != null);
this.addPersistentFrameCallback(this._handlePersistentFrameCallback);

}
protected virtual ViewConfiguration createViewConfiguration() {
var devicePixelRatio = this.window.devicePixelRatio;
var devicePixelRatio = Window.instance.devicePixelRatio;
size: this.window.physicalSize / devicePixelRatio,
size: Window.instance.physicalSize / devicePixelRatio,
devicePixelRatio: devicePixelRatio
);
}

D.assert(this.renderView != null);
this.renderView.hitTest(result, position: position);
base.hitTest(result, position);
}
}
public class RendererBindings {
public RendererBindings(Window window) {
this.window = window;
this.rendererBinding = new RendererBinding(window);
}
public readonly Window window;
public readonly RendererBinding rendererBinding;
public void setRoot(RenderBox root) {
this.rendererBinding.renderView.child = root;
}
}
}

5
Assets/UIWidgets/rendering/editable.cs


public RenderEditable(TextSpan text, TextDirection textDirection, ViewportOffset offset,
ValueNotifier<bool> showCursor,
GestureBinding binding,
TextAlign textAlign = TextAlign.left, double textScaleFactor = 1.0, Color cursorColor = null,
bool? hasFocus = null, int maxLines = 1, Color selectionColor = null,
TextSelection selection = null, bool obscureText = false, SelectionChangedHandler onSelectionChanged = null,

D.assert(_showCursor != null);
D.assert(!_showCursor.value || cursorColor != null);
_tap = new TapGestureRecognizer(binding, this);
_doubleTap = new DoubleTapGestureRecognizer(binding, this);
_tap = new TapGestureRecognizer(this);
_doubleTap = new DoubleTapGestureRecognizer(this);
_tap.onTapDown = this._handleTapDown;
_tap.onTap = this._handleTap;
_doubleTap.onDoubleTap = this._handleDoubleTap;

11
Assets/UIWidgets/rendering/proxy_box.cs


}
}
public class RenderRepaintBoundary : RenderProxyBox {
public RenderRepaintBoundary(
RenderBox child = null
) : base(child) {
}
public override bool isRepaintBoundary {
get { return true; }
}
}
public class RenderIgnorePointer : RenderProxyBox {
public RenderIgnorePointer(
RenderBox child = null,

33
Assets/UIWidgets/rendering/sliver_fixed_extent_list.cs


namespace UIWidgets.rendering {
public abstract class RenderSliverFixedExtentBoxAdaptor : RenderSliverMultiBoxAdaptor {
RenderSliverFixedExtentBoxAdaptor(
protected RenderSliverFixedExtentBoxAdaptor(
public abstract double itemExtent { get; }
public abstract double itemExtent { get; set; }
public double indexToLayoutOffset(double itemExtent, int index) {
return itemExtent * index;

return itemExtent > 0.0 ? Math.Max(0, (int) Math.Ceiling(scrollOffset / itemExtent) - 1) : 0;
}
public double estimateMaxScrollOffset(SliverConstraints constraints,
public double? estimateMaxScrollOffset(SliverConstraints constraints,
int firstIndex = 0,
int lastIndex = 0,
double leadingScrollOffset = 0.0,

}
public double computeMaxScrollOffset(SliverConstraints constraints, double itemExtent) {
return this.childManager.childCount * itemExtent;
return this.childManager.childCount.Value * itemExtent;
}

lastIndex: lastIndex,
leadingScrollOffset: leadingScrollOffset,
trailingScrollOffset: trailingScrollOffset
);
).Value;
double paintExtent = this.calculatePaintOffset(
this.constraints,

this.childManager.didFinishLayout();
}
}
public class RenderSliverFixedExtentList : RenderSliverFixedExtentBoxAdaptor {
public RenderSliverFixedExtentList(
RenderSliverBoxChildManager childManager = null,
double itemExtent = 0.0
) : base(childManager: childManager) {
this._itemExtent = itemExtent;
}
public override double itemExtent {
get { return this._itemExtent; }
set {
if (this._itemExtent == value) {
return;
}
this._itemExtent = value;
this.markNeedsLayout();
}
}
double _itemExtent;
}
}

4
Assets/UIWidgets/rendering/sliver_list.cs


namespace UIWidgets.rendering {
public class RenderSliverList : RenderSliverMultiBoxAdaptor {
RenderSliverList(
public RenderSliverList(
RenderSliverBoxChildManager childManager = null
) : base(childManager: childManager) {
}

lastIndex: this.indexOf(this.lastChild),
leadingScrollOffset: this.childScrollOffset(this.firstChild),
trailingScrollOffset: endScrollOffset
);
).Value;
}
double paintExtent = this.calculatePaintOffset(

6
Assets/UIWidgets/rendering/sliver_multi_box_adaptor.cs


void removeChild(RenderBox child);
double estimateMaxScrollOffset(
double? estimateMaxScrollOffset(
SliverConstraints constraints,
int firstIndex = 0,
int lastIndex = 0,

int childCount { get; }
int? childCount { get; }
void didAdoptChild(RenderBox child);

void didFinishLayout();
bool debugAssertChildListLocked();
}
public class SliverMultiBoxAdaptorParentData : ContainerParentDataMixinSliverLogicalParentData<RenderBox> {

6
Assets/UIWidgets/rendering/sliver_padding.cs


namespace UIWidgets.rendering {
public class RenderSliverPadding : RenderObjectWithChildMixinRenderSliver<RenderSliver> {
RenderSliverPadding(
EdgeInsets padding,
RenderSliver child
public RenderSliverPadding(
EdgeInsets padding = null,
RenderSliver child = null
) {
this._padding = padding;
this.child = child;

2
Assets/UIWidgets/rendering/view.cs


var builder = new SceneBuilder();
this.layer.addToScene(builder, Offset.zero);
var scene = builder.build();
this.owner.binding.window.render(scene);
Window.instance.render(scene);
}
public override Rect paintBounds {

32
Assets/UIWidgets/scheduler/binding.cs


}
public class SchedulerBinding {
public SchedulerBinding(Window window) {
D.assert(window != null);
this.window = window;
window.onBeginFrame += this._handleBeginFrame;
window.onDrawFrame += this._handleDrawFrame;
public static SchedulerBinding instance {
get {
D.assert(_instance != null, "Binding.instance is null");
return _instance;
}
set {
if (value == null) {
D.assert(_instance != null, "Binding.instance is already cleared.");
_instance = null;
} else {
D.assert(_instance == null, "Binding.instance is already assigned.");
_instance = value;
}
}
public readonly Window window;
static SchedulerBinding _instance;
public SchedulerBinding() {
Window.instance.onBeginFrame += this._handleBeginFrame;
Window.instance.onDrawFrame += this._handleDrawFrame;
}
public double timeDilation {
get { return this._timeDilation; }

return true;
});
this.window.scheduleFrame();
Window.instance.scheduleFrame();
this._hasScheduledFrame = true;
}

return true;
});
this.window.scheduleFrame();
Window.instance.scheduleFrame();
this._hasScheduledFrame = true;
}

6
Assets/UIWidgets/scheduler/ticker.cs


public interface TickerProvider {
Ticker createTicker(TickerCallback onTick);
SchedulerBinding schedulerBinding { get; }
public Ticker(SchedulerBinding binding, TickerCallback onTick, string debugLabel = null) {
public Ticker(TickerCallback onTick, string debugLabel = null) {
D.assert(binding != null);
this._binding = binding;
this._onTick = onTick;
this.debugLabel = debugLabel;
}

20
Assets/UIWidgets/ui/window.cs


using System;
using UIWidgets.async;
using UIWidgets.foundation;
namespace UIWidgets.ui {
public delegate void VoidCallback();

public delegate void PointerDataPacketCallback(PointerDataPacket packet);
public abstract class Window {
public static Window instance {
get {
D.assert(_instance != null, "Window.instance is null");
return _instance;
}
set {
if (value == null) {
D.assert(_instance != null, "Window.instance is already cleared.");
_instance = null;
} else {
D.assert(_instance == null, "Window.instance is already assigned.");
_instance = value;
}
}
}
static Window _instance;
public double devicePixelRatio {
get { return this._devicePixelRatio; }
}

53
Assets/UIWidgets/widgets/basic.cs


}
}
public class SliverPadding : SingleChildRenderObjectWidget {
public SliverPadding(
Key key = null,
EdgeInsets padding = null,
Widget sliver = null
) : base(key: key, child: sliver) {
D.assert(padding != null);
this.padding = padding;
}
public readonly EdgeInsets padding;
public override RenderObject createRenderObject(BuildContext context) {
return new RenderSliverPadding(
padding: this.padding
);
}
public override void updateRenderObject(BuildContext context, RenderObject renderObjectRaw) {
var renderObject = (RenderSliverPadding) renderObjectRaw;
renderObject.padding = this.padding;
}
public override void debugFillProperties(DiagnosticPropertiesBuilder properties) {
base.debugFillProperties(properties);
properties.add(new DiagnosticsProperty<EdgeInsets>("padding", this.padding));
}
}
public class RawImage : LeafRenderObjectWidget {
public RawImage(Key key, ui.Image image, double width, double height, double scale, Color color,
BlendMode colorBlendMode, BoxFit fit, Rect centerSlice, Alignment alignment = null,

}
}
public class RepaintBoundary : SingleChildRenderObjectWidget {
public RepaintBoundary(Key key = null, Widget child = null) : base(key: key, child: child) {
}
public static RepaintBoundary wrap(Widget child, int childIndex) {
D.assert(child != null);
Key key = child.key != null ? (Key) new ValueKey<Key>(child.key) : new ValueKey<int>(childIndex);
return new RepaintBoundary(key: key, child: child);
}
public static List<RepaintBoundary> wrapAll(List<Widget> widgets) {
List<RepaintBoundary> result = new List<RepaintBoundary>(widgets.Count);
for (int i = 0; i < result.Count; ++i) {
result[i] = RepaintBoundary.wrap(widgets[i], i);
}
return result;
}
public override RenderObject createRenderObject(BuildContext context) {
return new RenderRepaintBoundary();
}
}
public class IgnorePointer : SingleChildRenderObjectWidget {
public IgnorePointer(

23
Assets/UIWidgets/widgets/binding.cs


}
public class WidgetsBinding : RendererBinding {
public WidgetsBinding(Window window) : base(window) {
public static new WidgetsBinding instance {
get { return (WidgetsBinding) RendererBinding.instance; }
set { RendererBinding.instance = value; }
}
public WidgetsBinding() {
window.onLocaleChanged += this.handleLocaleChanged;
Window.instance.onLocaleChanged += this.handleLocaleChanged;
}
public BuildOwner buildOwner {

Widget error = ErrorWidget.builder(new UIWidgetsErrorDetails(e));
_child = updateChild(null, error, _rootChildSlot);
}
}
}
public class WidgetsBindings {
public WidgetsBindings(Window window) {
this.window = window;
this.widgetsBinding = new WidgetsBinding(window);
}
public readonly Window window;
public readonly WidgetsBinding widgetsBinding;
public void attachRootWidget(Widget root) {
this.widgetsBinding.attachRootWidget(root);
}
}
}

6
Assets/UIWidgets/widgets/framework.cs


this.visitChildren(visitor);
}
protected Element updateChild(Element child, Widget newWidget, object newSlot) {
protected virtual Element updateChild(Element child, Widget newWidget, object newSlot) {
D.assert(() => {
if (newWidget != null && newWidget.key is GlobalKey) {
GlobalKey key = (GlobalKey) newWidget.key;

internal readonly Dictionary<Element, object> _dependents = new Dictionary<Element, object>();
internal override void _updateInheritance() {
Dictionary<Type, InheritedElement> incomingWidgets = this._parent == null ? null : this._inheritedWidgets;
Dictionary<Type, InheritedElement> incomingWidgets =
this._parent == null ? null : this._parent._inheritedWidgets;
if (incomingWidgets != null) {
this._inheritedWidgets = new Dictionary<Type, InheritedElement>(incomingWidgets);
} else {

1
Assets/UIWidgets/widgets/primary_scroll_controller.cs


Widget child = null
) : base(key: key, child: child) {
D.assert(controller != null);
this.controller = controller;
}
private PrimaryScrollController(

2
Assets/UIWidgets/widgets/scroll_activity.cs


new ScrollEndNotification(
metrics: metrics,
context: context,
dragDetails: lastDetails is DragEndDetails ? (DragEndDetails) lastDetails : null
dragDetails: lastDetails as DragEndDetails
).dispatch(context);
}

2
Assets/UIWidgets/widgets/scroll_configuration.cs


D.assert(this.behavior != null);
return this.behavior.GetType() != oldWidget.behavior.GetType()
|| (this.behavior != oldWidget.behavior && this.behavior.shouldNotify(oldWidget.behavior));
|| this.behavior != oldWidget.behavior && this.behavior.shouldNotify(oldWidget.behavior);
}
public override void debugFillProperties(DiagnosticPropertiesBuilder properties) {

9
Assets/UIWidgets/widgets/scroll_position.cs


double? _maxScrollExtent;
public override double pixels {
get { return this._pixels.Value; }
get {
D.assert(this._pixels != null);
return this._pixels ?? 0.0;
}
}
internal double? _pixels;

public virtual double setPixels(double newPixels) {
D.assert(this._pixels != null);
D.assert(this.context.vsync.schedulerBinding.schedulerPhase <= SchedulerPhase.transientCallbacks);
D.assert(SchedulerBinding.instance.schedulerPhase <= SchedulerPhase.transientCallbacks);
if (newPixels != this.pixels) {
double overscroll = this.applyBoundaryConditions(newPixels);
D.assert(() => {

double oldPixels = this.pixels;
this._pixels = newPixels - overscroll;
if (this._pixels != oldPixels) {
if (this.pixels != oldPixels) {
this.notifyListeners();
this.didUpdateScrollPositionBy(this.pixels - oldPixels);
}

2
Assets/UIWidgets/widgets/scroll_position_with_single_context.cs


if (this.pixels != value) {
double oldPixels = this.pixels;
this.forcePixels(value);
this.notifyListeners();
// this.notifyListeners(); already in forcePixels, no need here.
this.didStartScroll();
this.didUpdateScrollPositionBy(this.pixels - oldPixels);
this.didEndScroll();

320
Assets/UIWidgets/widgets/scroll_view.cs


using System;
using System.Collections.Generic;
using UIWidgets.foundation;
using UIWidgets.painting;

public readonly double? cacheExtent;
protected AxisDirection getDirection(BuildContext context) {
return AxisUtils.getAxisDirectionFromAxisReverseAndDirectionality(context, this.scrollDirection,
this.reverse);
return AxisUtils.getAxisDirectionFromAxisReverseAndDirectionality(
context, this.scrollDirection, this.reverse);
}
protected abstract List<Widget> buildSlivers(BuildContext context);

}
}
public class CustomScrollView : ScrollView {
public CustomScrollView(
Key key = null,
Axis scrollDirection = Axis.vertical,
bool reverse = false,
ScrollController controller = null,
bool? primary = null,
ScrollPhysics physics = null,
bool shrinkWrap = false,
double? cacheExtent = null,
List<Widget> slivers = null
) : base(
key: key,
scrollDirection: scrollDirection,
reverse: reverse,
controller: controller,
primary: primary,
physics: physics,
shrinkWrap: shrinkWrap,
cacheExtent: cacheExtent
) {
this.slivers = slivers ?? new List<Widget>();
}
public readonly List<Widget> slivers;
protected override List<Widget> buildSlivers(BuildContext context) {
return this.slivers;
}
}
public abstract class BoxScrollView : ScrollView {
public BoxScrollView(
Key key = null,

protected override List<Widget> buildSlivers(BuildContext context) {
Widget sliver = this.buildChildLayout(context);
EdgeInsets effectivePadding = this.padding;
if (this.padding == null) {
// final MediaQueryData mediaQuery = MediaQuery.of(context, nullOk: true);
// if (mediaQuery != null) {
// // Automatically pad sliver with padding from MediaQuery.
// final EdgeInsets mediaQueryHorizontalPadding =
// mediaQuery.padding.copyWith(top: 0.0, bottom: 0.0);
// final EdgeInsets mediaQueryVerticalPadding =
// mediaQuery.padding.copyWith(left: 0.0, right: 0.0);
// // Consume the main axis padding with SliverPadding.
// effectivePadding = scrollDirection == Axis.vertical
// ? mediaQueryVerticalPadding
// : mediaQueryHorizontalPadding;
// // Leave behind the cross axis padding.
// sliver = new MediaQuery(
// data: mediaQuery.copyWith(
// padding: scrollDirection == Axis.vertical
// ? mediaQueryHorizontalPadding
// : mediaQueryVerticalPadding,
// ),
// child: sliver,
// );
// }
}
EdgeInsets effectivePadding = this.padding; // no need to check MediaQuery for now.
// sliver = new SliverPadding(padding: effectivePadding, sliver: sliver);
sliver = new SliverPadding(padding: effectivePadding, sliver: sliver);
}
return new List<Widget> {sliver};

public override void debugFillProperties(DiagnosticPropertiesBuilder properties) {
base.debugFillProperties(properties);
properties.add(new DiagnosticsProperty<EdgeInsets>("padding", this.padding,
defaultValue: Diagnostics.kNullDefaultValue));
}
}
public class ListView : BoxScrollView {
public ListView(
Key key = null,
Axis scrollDirection = Axis.vertical,
bool reverse = false,
ScrollController controller = null,
bool? primary = null,
ScrollPhysics physics = null,
bool shrinkWrap = false,
EdgeInsets padding = null,
double? itemExtent = null,
bool addAutomaticKeepAlives = true,
bool addRepaintBoundaries = true,
double? cacheExtent = null,
List<Widget> children = null
) : base(
key: key,
scrollDirection: scrollDirection,
reverse: reverse,
controller: controller,
primary: primary,
physics: physics,
shrinkWrap: shrinkWrap,
padding: padding,
cacheExtent: cacheExtent
) {
this.itemExtent = itemExtent;
this.childrenDelegate = new SliverChildListDelegate(
children,
addAutomaticKeepAlives: addAutomaticKeepAlives,
addRepaintBoundaries: addRepaintBoundaries
);
}
private ListView(
Key key = null,
Axis scrollDirection = Axis.vertical,
bool reverse = false,
ScrollController controller = null,
bool? primary = null,
ScrollPhysics physics = null,
bool shrinkWrap = false,
EdgeInsets padding = null,
double? itemExtent = null,
IndexedWidgetBuilder itemBuilder = null,
int? itemCount = null,
bool addAutomaticKeepAlives = true,
bool addRepaintBoundaries = true,
double? cacheExtent = null
) : base(key: key,
scrollDirection: scrollDirection,
reverse: reverse,
controller: controller,
primary: primary,
physics: physics,
shrinkWrap: shrinkWrap,
padding: padding,
cacheExtent: cacheExtent
) {
this.itemExtent = itemExtent;
this.childrenDelegate = new SliverChildBuilderDelegate(
itemBuilder,
childCount: itemCount,
addAutomaticKeepAlives: addAutomaticKeepAlives,
addRepaintBoundaries: addRepaintBoundaries
);
}
public static ListView builder(
Key key = null,
Axis scrollDirection = Axis.vertical,
bool reverse = false,
ScrollController controller = null,
bool? primary = null,
ScrollPhysics physics = null,
bool shrinkWrap = false,
EdgeInsets padding = null,
double? itemExtent = null,
IndexedWidgetBuilder itemBuilder = null,
int? itemCount = null,
bool addAutomaticKeepAlives = true,
bool addRepaintBoundaries = true,
double? cacheExtent = null
) {
return new ListView(
key,
scrollDirection,
reverse,
controller,
primary,
physics,
shrinkWrap,
padding,
itemExtent,
itemBuilder,
itemCount,
addAutomaticKeepAlives,
addRepaintBoundaries
);
}
private ListView(
Key key = null,
Axis scrollDirection = Axis.vertical,
bool reverse = false,
ScrollController controller = null,
bool? primary = null,
ScrollPhysics physics = null,
bool shrinkWrap = false,
EdgeInsets padding = null,
IndexedWidgetBuilder itemBuilder = null,
IndexedWidgetBuilder separatorBuilder = null,
int itemCount = 0,
bool addAutomaticKeepAlives = true,
bool addRepaintBoundaries = true,
double? cacheExtent = null
) : base(
key: key,
scrollDirection: scrollDirection,
reverse: reverse,
controller: controller,
primary: primary,
physics: physics,
shrinkWrap: shrinkWrap,
padding: padding,
cacheExtent: cacheExtent
) {
D.assert(itemBuilder != null);
D.assert(separatorBuilder != null);
D.assert(itemCount >= 0);
this.itemExtent = null;
this.childrenDelegate = new SliverChildBuilderDelegate(
(context, index) => {
int itemIndex = index / 2;
return index % 2 == 0
? itemBuilder(context, itemIndex)
: separatorBuilder(context, itemIndex);
},
childCount: Math.Max(0, itemCount * 2 - 1),
addAutomaticKeepAlives: addAutomaticKeepAlives,
addRepaintBoundaries: addRepaintBoundaries
);
}
public static ListView seperated(
Key key = null,
Axis scrollDirection = Axis.vertical,
bool reverse = false,
ScrollController controller = null,
bool? primary = null,
ScrollPhysics physics = null,
bool shrinkWrap = false,
EdgeInsets padding = null,
IndexedWidgetBuilder itemBuilder = null,
IndexedWidgetBuilder separatorBuilder = null,
int itemCount = 0,
bool addAutomaticKeepAlives = true,
bool addRepaintBoundaries = true,
double? cacheExtent = null
) {
return new ListView(
key,
scrollDirection,
reverse,
controller,
primary,
physics,
shrinkWrap,
padding,
itemBuilder,
separatorBuilder,
itemCount,
addAutomaticKeepAlives,
addRepaintBoundaries,
cacheExtent
);
}
private ListView(
Key key = null,
Axis scrollDirection = Axis.vertical,
bool reverse = false,
ScrollController controller = null,
bool? primary = null,
ScrollPhysics physics = null,
bool shrinkWrap = false,
EdgeInsets padding = null,
double? itemExtent = null,
SliverChildDelegate childrenDelegate = null,
double? cacheExtent = null
) : base(
key: key,
scrollDirection: scrollDirection,
reverse: reverse,
controller: controller,
primary: primary,
physics: physics,
shrinkWrap: shrinkWrap,
padding: padding,
cacheExtent: cacheExtent
) {
D.assert(childrenDelegate != null);
this.itemExtent = itemExtent;
this.childrenDelegate = childrenDelegate;
}
public static ListView custom(
Key key = null,
Axis scrollDirection = Axis.vertical,
bool reverse = false,
ScrollController controller = null,
bool? primary = null,
ScrollPhysics physics = null,
bool shrinkWrap = false,
EdgeInsets padding = null,
double? itemExtent = null,
SliverChildDelegate childrenDelegate = null,
double? cacheExtent = null
) {
return new ListView(
key,
scrollDirection,
reverse,
controller,
primary,
physics,
shrinkWrap,
padding,
itemExtent,
childrenDelegate,
cacheExtent);
}
public readonly double? itemExtent;
public readonly SliverChildDelegate childrenDelegate;
protected override Widget buildChildLayout(BuildContext context) {
if (this.itemExtent != null) {
return new SliverFixedExtentList(
del: this.childrenDelegate,
itemExtent: this.itemExtent.Value
);
}
return new SliverList(del: this.childrenDelegate);
}
public override void debugFillProperties(DiagnosticPropertiesBuilder properties) {
base.debugFillProperties(properties);
properties.add(new DoubleProperty("itemExtent", this.itemExtent,
defaultValue: Diagnostics.kNullDefaultValue));
}
}

20
Assets/UIWidgets/widgets/scrollable.cs


using UIWidgets.painting;
using UIWidgets.rendering;
using UIWidgets.scheduler;
using UIWidgets.ui;
namespace UIWidgets.widgets {
public delegate Widget ViewportBuilder(BuildContext context, ViewportOffset position);

}
public readonly ScrollableState scrollable;
public readonly ScrollPosition position;
public override bool updateShouldNotify(InheritedWidget old) {

public class ScrollableState : TickerProviderStateMixin<Scrollable>, ScrollContext {
public SchedulerBinding schedulerBinding { get; set; }
public ScrollPosition position {
get { return this._position; }
}

controller.detach(oldPosition);
}
this.schedulerBinding.window.scheduleMicrotask(oldPosition.dispose);
}
if (controller != null) {
this._position = controller.createScrollPosition(this._physics, this, oldPosition);
Window.instance.scheduleMicrotask(oldPosition.dispose);
this._position = controller == null
? null
: controller.createScrollPosition(this._physics, this, oldPosition);
D.assert(this.position != null);
if (controller != null) {
controller.attach(this.position);

}
} while (newPhysics != null || oldPhysics != null);
Type controllerType = widget.controller == null ? null : widget.controller.GetType();
Type controllerType = this.widget.controller == null ? null : this.widget.controller.GetType();
Type oldControllerType = oldWidget.controller == null ? null : oldWidget.controller.GetType();
return controllerType != oldControllerType;
}

base.dispose();
}
GlobalKey<RawGestureDetectorState> _gestureDetectorKey = GlobalKey<RawGestureDetectorState>.key();
GlobalKey _ignorePointerKey = GlobalKey.key();
readonly GlobalKey<RawGestureDetectorState> _gestureDetectorKey = GlobalKey<RawGestureDetectorState>.key();
readonly GlobalKey _ignorePointerKey = GlobalKey.key();
Dictionary<Type, GestureRecognizerFactory> _gestureRecognizers =
new Dictionary<Type, GestureRecognizerFactory>();

21
Assets/UIWidgets/widgets/ticker_provider.cs


namespace UIWidgets.widgets {
public class TickerMode : InheritedWidget {
public TickerMode(Key key = null, bool enabled = true, Widget child = null) : base(key, child) {
public TickerMode(
Key key = null,
bool enabled = true,
Widget child = null)
: base(key, child) {
this.enabled = enabled;
}

}
public abstract class SingleTickerProviderStateMixin<T> : State<T>, TickerProvider where T : StatefulWidget {
public SchedulerBinding schedulerBinding { get; set; }
Ticker _ticker;
public Ticker createTicker(TickerCallback onTick) {

"mixing in a SingleTickerProviderStateMixin, use a regular TickerProviderStateMixin."
);
});
this._ticker = new Ticker(this.schedulerBinding, onTick, debugLabel: "created by " + this);
this._ticker = new Ticker(onTick, debugLabel: "created by " + this);
return this._ticker;
}

if (this._ticker != null) {
if (this._ticker.isActive && this._ticker.muted) {
tickerDescription = "active but muted";
} else if (_ticker.isActive) {
} else if (this._ticker.isActive) {
} else if (_ticker.muted) {
} else if (this._ticker.muted) {
tickerDescription = "inactive and muted";
} else {
tickerDescription = "inactive";

}
public abstract class TickerProviderStateMixin<T> : State<T>, TickerProvider where T : StatefulWidget {
public SchedulerBinding schedulerBinding { get; set; }
var result = new _WidgetTicker<T>(this.schedulerBinding, onTick, this, debugLabel: "created by " + this);
var result = new _WidgetTicker<T>(onTick, this, debugLabel: "created by " + this);
this._tickers.Add(result);
return result;
}

class _WidgetTicker<T> : Ticker where T : StatefulWidget {
internal _WidgetTicker(
SchedulerBinding binding,
base(binding: binding, onTick: onTick, debugLabel: debugLabel) {
base(onTick: onTick, debugLabel: debugLabel) {
this._creator = creator;
}

13
Assets/UIWidgets/widgets/viewport.cs


List<Widget> slivers = null
) : base(key: key, children: slivers) {
D.assert(offset != null);
slivers = slivers ?? new List<Widget>();
D.assert(slivers != null);
D.assert(center == null || slivers.Count(child => child.key == center) == 1);
D.assert(center == null || this.children.Count(child => child.key == center) == 1);
this.axisDirection = axisDirection;
this.crossAxisDirection = crossAxisDirection;

public override RenderObject createRenderObject(BuildContext context) {
return new RenderShrinkWrappingViewport(
axisDirection: this.axisDirection,
crossAxisDirection:
this.crossAxisDirection ?? Viewport.getDefaultCrossAxisDirection(context, this.axisDirection),
crossAxisDirection: this.crossAxisDirection
?? Viewport.getDefaultCrossAxisDirection(context, this.axisDirection),
offset: this.offset
);
}

renderObject.axisDirection = this.axisDirection;
renderObject.crossAxisDirection =
this.crossAxisDirection ?? Viewport.getDefaultCrossAxisDirection(context, this.axisDirection);
renderObject.crossAxisDirection = this.crossAxisDirection
?? Viewport.getDefaultCrossAxisDirection(context, this.axisDirection);
renderObject.offset = this.offset;
}

206
Assets/UIWidgets/rendering/automatic_keep_alive.cs


using System;
using System.Collections.Generic;
using UIWidgets.foundation;
using UIWidgets.scheduler;
using UIWidgets.ui;
using UIWidgets.widgets;
namespace UIWidgets.rendering {
public class AutomaticKeepAlive : StatefulWidget {
public AutomaticKeepAlive(
Key key = null,
Widget child = null
) : base(key: key) {
}
public readonly Widget child;
public override State createState() {
return new _AutomaticKeepAliveState();
}
}
class _AutomaticKeepAliveState : State<AutomaticKeepAlive> {
Dictionary<Listenable, VoidCallback> _handles;
Widget _child;
bool _keepingAlive = false;
public override void initState() {
base.initState();
this._updateChild();
}
public override void didUpdateWidget(StatefulWidget oldWidget) {
base.didUpdateWidget(oldWidget);
this._updateChild();
}
void _updateChild() {
this._child = new NotificationListener<KeepAliveNotification>(
onNotification: this._addClient,
child: this.widget.child
);
}
public override void dispose() {
if (this._handles != null) {
foreach (Listenable handle in this._handles.Keys)
handle.removeListener(this._handles[handle]);
}
base.dispose();
}
bool _addClient(KeepAliveNotification notification) {
Listenable handle = notification.handle;
this._handles = this._handles ?? new Dictionary<Listenable, VoidCallback>();
D.assert(!this._handles.ContainsKey(handle));
this._handles[handle] = this._createCallback(handle);
handle.addListener(this._handles[handle]);
if (!this._keepingAlive) {
this._keepingAlive = true;
ParentDataElement<SliverMultiBoxAdaptorWidget> childElement = this._getChildElement();
if (childElement != null) {
this._updateParentDataOfChild(childElement);
} else {
SchedulerBinding.instance.addPostFrameCallback(timeStamp => {
ParentDataElement<SliverMultiBoxAdaptorWidget> childElement1 = this._getChildElement();
D.assert(childElement1 != null);
this._updateParentDataOfChild(childElement1);
});
}
}
return false;
}
ParentDataElement<SliverMultiBoxAdaptorWidget> _getChildElement() {
Element element = (Element) this.context;
Element childElement = null;
element.visitChildren((Element child) => { childElement = child; });
D.assert(childElement == null || childElement is ParentDataElement<SliverMultiBoxAdaptorWidget>);
return (ParentDataElement<SliverMultiBoxAdaptorWidget>) childElement;
}
void _updateParentDataOfChild(ParentDataElement<SliverMultiBoxAdaptorWidget> childElement) {
childElement.applyWidgetOutOfTurn((ParentDataWidget<SliverMultiBoxAdaptorWidget>) this.build(this.context));
}
VoidCallback _createCallback(Listenable handle) {
return () => {
D.assert(() => {
if (!this.mounted) {
throw new UIWidgetsError(
"AutomaticKeepAlive handle triggered after AutomaticKeepAlive was disposed." +
"Widgets should always trigger their KeepAliveNotification handle when they are " +
"deactivated, so that they (or their handle) do not send spurious events later " +
"when they are no longer in the tree."
);
}
return true;
});
this._handles.Remove(handle);
if (this._handles.isEmpty()) {
if (SchedulerBinding.instance.schedulerPhase < SchedulerPhase.persistentCallbacks) {
this.setState(() => { this._keepingAlive = false; });
} else {
this._keepingAlive = false;
Window.instance.scheduleMicrotask(() => {
if (this.mounted && this._handles.isEmpty()) {
this.setState(() => { D.assert(!this._keepingAlive); });
}
});
}
}
};
}
public override Widget build(BuildContext context) {
D.assert(this._child != null);
return new KeepAlive(
keepAlive: this._keepingAlive,
child: this._child
);
}
public override void debugFillProperties(DiagnosticPropertiesBuilder description) {
base.debugFillProperties(description);
description.add(new FlagProperty("_keepingAlive", value: this._keepingAlive,
ifTrue: "keeping subtree alive"));
description.add(new DiagnosticsProperty<Dictionary<Listenable, VoidCallback>>(
"handles",
this._handles,
description: this._handles != null ? this._handles.Count + " active clients" : null,
ifNull: "no notifications ever received"
));
}
}
public class KeepAliveNotification : Notification {
public KeepAliveNotification(Listenable handle) {
D.assert(handle != null);
this.handle = handle;
}
public readonly Listenable handle;
}
public class KeepAliveHandle : ChangeNotifier {
public void release() {
this.notifyListeners();
}
}
public abstract class AutomaticKeepAliveClientMixin<T> : State<T> where T : StatefulWidget {
KeepAliveHandle _keepAliveHandle;
void _ensureKeepAlive() {
D.assert(this._keepAliveHandle == null);
this._keepAliveHandle = new KeepAliveHandle();
new KeepAliveNotification(this._keepAliveHandle).dispatch(this.context);
}
void _releaseKeepAlive() {
this._keepAliveHandle.release();
this._keepAliveHandle = null;
}
protected abstract bool wantKeepAlive { get; }
protected void updateKeepAlive() {
if (this.wantKeepAlive) {
if (this._keepAliveHandle == null)
this._ensureKeepAlive();
} else {
if (this._keepAliveHandle != null)
this._releaseKeepAlive();
}
}
public override void initState() {
base.initState();
if (this.wantKeepAlive) {
this._ensureKeepAlive();
}
}
public override void deactivate() {
if (this._keepAliveHandle != null) {
this._releaseKeepAlive();
}
base.deactivate();
}
public override Widget build(BuildContext context) {
if (this.wantKeepAlive && this._keepAliveHandle == null) {
this._ensureKeepAlive();
}
return null;
}
}
}

3
Assets/UIWidgets/rendering/automatic_keep_alive.cs.meta


fileFormatVersion: 2
guid: a3c3b140ce174c61bfd25672b4ad6f21
timeCreated: 1537325090

519
Assets/UIWidgets/widgets/sliver.cs


using System;
using System.Collections.Generic;
using System.Linq;
using UIWidgets.foundation;
using UIWidgets.painting;
using UIWidgets.rendering;
namespace UIWidgets.widgets {
public abstract class SliverChildDelegate {
protected SliverChildDelegate() {
}
public abstract Widget build(BuildContext context, int index);
public virtual int? estimatedChildCount {
get { return null; }
}
public virtual double? estimateMaxScrollOffset(
int firstIndex,
int lastIndex,
double leadingScrollOffset,
double trailingScrollOffset
) {
return null;
}
public virtual void didFinishLayout(int firstIndex, int lastIndex) {
}
public abstract bool shouldRebuild(SliverChildDelegate oldDelegate);
public override string ToString() {
var description = new List<string>();
this.debugFillDescription(description);
return string.Format("{0}({1})", Diagnostics.describeIdentity(this),
string.Join(", ", description.ToArray()));
}
protected virtual void debugFillDescription(List<String> description) {
try {
var children = this.estimatedChildCount;
if (children != null) {
description.Add("estimated child count: " + children);
}
}
catch (Exception ex) {
description.Add("estimated child count: EXCEPTION (" + ex.GetType() + ")");
}
}
}
public class SliverChildBuilderDelegate : SliverChildDelegate {
public SliverChildBuilderDelegate(
IndexedWidgetBuilder builder,
int? childCount = null,
bool addAutomaticKeepAlives = true,
bool addRepaintBoundaries = true
) {
D.assert(builder != null);
this.builder = build;
this.childCount = childCount;
this.addAutomaticKeepAlives = addAutomaticKeepAlives;
this.addRepaintBoundaries = addRepaintBoundaries;
}
public readonly IndexedWidgetBuilder builder;
public readonly int? childCount;
public readonly bool addAutomaticKeepAlives;
public readonly bool addRepaintBoundaries;
public override Widget build(BuildContext context, int index) {
D.assert(this.builder != null);
if (index < 0 || (this.childCount != null && index >= this.childCount)) {
return null;
}
Widget child = this.builder(context, index);
if (child == null) {
return null;
}
if (this.addRepaintBoundaries) {
child = RepaintBoundary.wrap(child, index);
}
if (this.addAutomaticKeepAlives) {
child = new AutomaticKeepAlive(child: child);
}
return child;
}
public override int? estimatedChildCount {
get { return this.childCount; }
}
public override bool shouldRebuild(SliverChildDelegate oldDelegate) {
return true;
}
}
public class SliverChildListDelegate : SliverChildDelegate {
public SliverChildListDelegate(
List<Widget> children,
bool addAutomaticKeepAlives = true,
bool addRepaintBoundaries = true
) {
D.assert(children != null);
this.children = children;
this.addAutomaticKeepAlives = addAutomaticKeepAlives;
this.addRepaintBoundaries = addRepaintBoundaries;
}
public readonly bool addAutomaticKeepAlives;
public readonly bool addRepaintBoundaries;
public readonly List<Widget> children;
public override Widget build(BuildContext context, int index) {
D.assert(this.children != null);
if (index < 0 || index >= this.children.Count) {
return null;
}
Widget child = this.children[index];
D.assert(child != null);
if (this.addRepaintBoundaries) {
child = RepaintBoundary.wrap(child, index);
}
if (this.addAutomaticKeepAlives) {
child = new AutomaticKeepAlive(child: child);
}
return child;
}
public override int? estimatedChildCount {
get { return this.children.Count; }
}
public override bool shouldRebuild(SliverChildDelegate oldDelegate) {
return this.children != ((SliverChildListDelegate) oldDelegate).children;
}
}
public abstract class SliverMultiBoxAdaptorWidget : RenderObjectWidget {
protected SliverMultiBoxAdaptorWidget(
Key key = null,
SliverChildDelegate del = null
) : base(key: key) {
D.assert(del != null);
this.del = del;
}
public readonly SliverChildDelegate del;
public override Element createElement() {
return new SliverMultiBoxAdaptorElement(this);
}
public double? estimateMaxScrollOffset(
SliverConstraints constraints,
int firstIndex,
int lastIndex,
double leadingScrollOffset,
double trailingScrollOffset
) {
D.assert(lastIndex >= firstIndex);
return this.del.estimateMaxScrollOffset(
firstIndex,
lastIndex,
leadingScrollOffset,
trailingScrollOffset
);
}
public override void debugFillProperties(DiagnosticPropertiesBuilder properties) {
base.debugFillProperties(properties);
properties.add(new DiagnosticsProperty<SliverChildDelegate>("del", this.del));
}
}
public class SliverList : SliverMultiBoxAdaptorWidget {
public SliverList(
Key key = null,
SliverChildDelegate del = null
) : base(key: key, del: del) {
}
public override RenderObject createRenderObject(BuildContext context) {
SliverMultiBoxAdaptorElement element = (SliverMultiBoxAdaptorElement) context;
return new RenderSliverList(childManager: element);
}
}
public class SliverFixedExtentList : SliverMultiBoxAdaptorWidget {
public SliverFixedExtentList(
Key key = null,
SliverChildDelegate del = null,
double itemExtent = 0
) : base(key: key, del: del) {
this.itemExtent = itemExtent;
}
public readonly double itemExtent;
public override RenderObject createRenderObject(BuildContext context) {
SliverMultiBoxAdaptorElement element = (SliverMultiBoxAdaptorElement) context;
return new RenderSliverFixedExtentList(childManager: element, itemExtent: this.itemExtent);
}
public override void updateRenderObject(BuildContext context, RenderObject renderObjectRaw) {
var renderObject = (RenderSliverFixedExtentList) renderObjectRaw;
renderObject.itemExtent = this.itemExtent;
}
}
public class SliverMultiBoxAdaptorElement : RenderObjectElement, RenderSliverBoxChildManager {
public SliverMultiBoxAdaptorElement(SliverMultiBoxAdaptorWidget widget) : base(widget) {
}
public new SliverMultiBoxAdaptorWidget widget {
get { return (SliverMultiBoxAdaptorWidget) base.widget; }
}
public new RenderSliverMultiBoxAdaptor renderObject {
get { return (RenderSliverMultiBoxAdaptor) base.renderObject; }
}
public override void update(Widget newWidgetRaw) {
var newWidget = (SliverMultiBoxAdaptorWidget) newWidgetRaw;
SliverMultiBoxAdaptorWidget oldWidget = this.widget;
base.update(newWidget);
SliverChildDelegate newDelegate = newWidget.del;
SliverChildDelegate oldDelegate = oldWidget.del;
if (newDelegate != oldDelegate &&
(newDelegate.GetType() != oldDelegate.GetType() || newDelegate.shouldRebuild(oldDelegate))) {
this.performRebuild();
}
}
Dictionary<int, Widget> _childWidgets = new Dictionary<int, Widget>();
SortedDictionary<int, Element> _childElements = new SortedDictionary<int, Element>();
RenderBox _currentBeforeChild;
protected override void performRebuild() {
this._childWidgets.Clear();
base.performRebuild();
this._currentBeforeChild = null;
D.assert(this._currentlyUpdatingChildIndex == null);
try {
int firstIndex = 0;
int lastIndex = 0;
if (!this._childElements.isEmpty()) {
firstIndex = this._childElements.Keys.First();
lastIndex = this._childElements.Keys.Last();
if (this._didUnderflow) {
lastIndex += 1;
}
}
for (int index = firstIndex; index <= lastIndex; ++index) {
this._currentlyUpdatingChildIndex = index;
Element newChild = this.updateChild(this._childElements[index], this._build(index), index);
if (newChild != null) {
this._childElements[index] = newChild;
this._currentBeforeChild = (RenderBox) newChild.renderObject;
} else {
this._childElements.Remove(index);
}
}
}
finally {
this._currentlyUpdatingChildIndex = null;
}
}
Widget _build(int index) {
return this._childWidgets.putIfAbsent(index, () => this.widget.del.build(this, index));
}
public void createChild(int index, RenderBox after = null) {
D.assert(this._currentlyUpdatingChildIndex == null);
this.owner.buildScope(this, () => {
bool insertFirst = after == null;
D.assert(insertFirst || this._childElements[index - 1] != null);
this._currentBeforeChild = insertFirst ? null : (RenderBox) this._childElements[index - 1].renderObject;
Element newChild;
try {
this._currentlyUpdatingChildIndex = index;
newChild = this.updateChild(this._childElements[index], this._build(index), index);
}
finally {
this._currentlyUpdatingChildIndex = null;
}
if (newChild != null) {
this._childElements[index] = newChild;
} else {
this._childElements.Remove(index);
}
});
}
protected override Element updateChild(Element child, Widget newWidget, object newSlot) {
SliverMultiBoxAdaptorParentData oldParentData = null;
if (child != null && child.renderObject != null) {
oldParentData = (SliverMultiBoxAdaptorParentData) child.renderObject.parentData;
}
Element newChild = base.updateChild(child, newWidget, newSlot);
SliverMultiBoxAdaptorParentData newParentData = null;
if (child != null && child.renderObject != null) {
newParentData = (SliverMultiBoxAdaptorParentData) newChild.renderObject.parentData;
}
if (oldParentData != newParentData && oldParentData != null && newParentData != null) {
newParentData.layoutOffset = oldParentData.layoutOffset;
}
return newChild;
}
protected override void forgetChild(Element child) {
D.assert(child != null);
D.assert(child.slot != null);
D.assert(this._childElements.ContainsKey((int) child.slot));
this._childElements.Remove((int) child.slot);
}
public void removeChild(RenderBox child) {
int index = this.renderObject.indexOf(child);
D.assert(this._currentlyUpdatingChildIndex == null);
D.assert(index >= 0);
this.owner.buildScope(this, () => {
D.assert(this._childElements.ContainsKey(index));
try {
this._currentlyUpdatingChildIndex = index;
Element result = this.updateChild(this._childElements[index], null, index);
D.assert(result == null);
}
finally {
this._currentlyUpdatingChildIndex = null;
}
this._childElements.Remove(index);
D.assert(!this._childElements.ContainsKey(index));
});
}
static double _extrapolateMaxScrollOffset(
int firstIndex,
int lastIndex,
double leadingScrollOffset,
double trailingScrollOffset,
int childCount
) {
if (lastIndex == childCount - 1)
return trailingScrollOffset;
int reifiedCount = lastIndex - firstIndex + 1;
double averageExtent = (trailingScrollOffset - leadingScrollOffset) / reifiedCount;
int remainingCount = childCount - lastIndex - 1;
return trailingScrollOffset + averageExtent * remainingCount;
}
public double? estimateMaxScrollOffset(SliverConstraints constraints,
int firstIndex = 0,
int lastIndex = 0,
double leadingScrollOffset = 0,
double trailingScrollOffset = 0
) {
int? childCount = this.childCount;
if (childCount == null) {
return double.PositiveInfinity;
}
return this.widget.estimateMaxScrollOffset(
constraints,
firstIndex,
lastIndex,
leadingScrollOffset,
trailingScrollOffset
) ?? _extrapolateMaxScrollOffset(
firstIndex,
lastIndex,
leadingScrollOffset,
trailingScrollOffset,
childCount.Value
);
}
public int? childCount {
get { return this.widget.del.estimatedChildCount; }
}
public void didStartLayout() {
D.assert(this.debugAssertChildListLocked());
}
public void didFinishLayout() {
D.assert(this.debugAssertChildListLocked());
int firstIndex = this._childElements.Keys.FirstOrDefault();
int lastIndex = this._childElements.Keys.LastOrDefault();
this.widget.del.didFinishLayout(firstIndex, lastIndex);
}
int? _currentlyUpdatingChildIndex;
public bool debugAssertChildListLocked() {
D.assert(this._currentlyUpdatingChildIndex == null);
return true;
}
public void didAdoptChild(RenderBox child) {
D.assert(this._currentlyUpdatingChildIndex != null);
SliverMultiBoxAdaptorParentData childParentData = (SliverMultiBoxAdaptorParentData) child.parentData;
childParentData.index = this._currentlyUpdatingChildIndex.Value;
}
bool _didUnderflow = false;
public void setDidUnderflow(bool value) {
this._didUnderflow = value;
}
protected override void insertChildRenderObject(RenderObject child, object slotRaw) {
D.assert(slotRaw != null);
int slot = (int) slotRaw;
D.assert(this._currentlyUpdatingChildIndex == slot);
D.assert(this.renderObject.debugValidateChild(child));
this.renderObject.insert((RenderBox) child, after: this._currentBeforeChild);
D.assert(() => {
SliverMultiBoxAdaptorParentData childParentData = (SliverMultiBoxAdaptorParentData) child.parentData;
D.assert(slot == childParentData.index);
return true;
});
}
protected override void moveChildRenderObject(RenderObject child, object slotRaw) {
D.assert(false);
}
protected override void removeChildRenderObject(RenderObject child) {
D.assert(this._currentlyUpdatingChildIndex != null);
this.renderObject.remove((RenderBox) child);
}
public override void visitChildren(ElementVisitor visitor) {
D.assert(!this._childElements.Values.Any(child => child == null));
this._childElements.Values.ToList().ForEach(e => visitor(e));
}
public override void debugVisitOnstageChildren(ElementVisitor visitor) {
this._childElements.Values.Where(child => {
SliverMultiBoxAdaptorParentData parentData =
(SliverMultiBoxAdaptorParentData) child.renderObject.parentData;
double itemExtent = 0;
switch (this.renderObject.constraints.axis) {
case Axis.horizontal:
itemExtent = child.renderObject.paintBounds.width;
break;
case Axis.vertical:
itemExtent = child.renderObject.paintBounds.height;
break;
}
return parentData.layoutOffset < this.renderObject.constraints.scrollOffset +
this.renderObject.constraints.remainingPaintExtent &&
parentData.layoutOffset + itemExtent > this.renderObject.constraints.scrollOffset;
}).ToList().ForEach(e => visitor(e));
}
}
public class KeepAlive : ParentDataWidget<SliverMultiBoxAdaptorWidget> {
public KeepAlive(
Key key = null,
bool keepAlive = true,
Widget child = null
) : base(key: key, child: child) {
D.assert(child != null);
this.keepAlive = keepAlive;
}
public readonly bool keepAlive;
public override void applyParentData(RenderObject renderObject) {
D.assert(renderObject.parentData is SliverMultiBoxAdaptorParentData);
SliverMultiBoxAdaptorParentData parentData = (SliverMultiBoxAdaptorParentData) renderObject.parentData;
if (parentData.keepAlive != this.keepAlive) {
parentData.keepAlive = this.keepAlive;
var targetParent = renderObject.parent;
if (targetParent is RenderObject && !this.keepAlive) {
((RenderObject) targetParent).markNeedsLayout();
}
}
}
public override bool debugCanApplyOutOfTurn() {
return this.keepAlive;
}
public override void debugFillProperties(DiagnosticPropertiesBuilder properties) {
base.debugFillProperties(properties);
properties.add(new DiagnosticsProperty<bool>("keepAlive", this.keepAlive));
}
}
}

3
Assets/UIWidgets/widgets/sliver.cs.meta


fileFormatVersion: 2
guid: 657ce5eaa41b4a498591bbb1682d04f4
timeCreated: 1537323273
正在加载...
取消
保存