浏览代码

fix sliver_traversal

/siyaoH-1.17-PlatformMessage
Shiyun Wen 4 年前
当前提交
456e8c67
共有 12 个文件被更改,包括 1130 次插入597 次删除
  1. 30
      com.unity.uiwidgets/Runtime/foundation/diagnostics.cs
  2. 31
      com.unity.uiwidgets/Runtime/rendering/proxy_box.cs
  3. 13
      com.unity.uiwidgets/Runtime/rendering/proxy_sliver.cs
  4. 63
      com.unity.uiwidgets/Runtime/rendering/sliver.cs
  5. 642
      com.unity.uiwidgets/Runtime/widgets/focus_manager.cs
  6. 472
      com.unity.uiwidgets/Runtime/widgets/focus_traversal.cs
  7. 6
      com.unity.uiwidgets/Runtime/widgets/scroll_notification.mixin.njk
  8. 6
      com.unity.uiwidgets/Runtime/widgets/selectable_text.cs
  9. 13
      com.unity.uiwidgets/Runtime/widgets/transitions.cs
  10. 72
      com.unity.uiwidgets/Runtime/widgets/DiagnosticableTree.mixin.gen.cs
  11. 69
      com.unity.uiwidgets/Runtime/widgets/DiagnosticableTree.mixin.njk
  12. 310
      com.unity.uiwidgets/Runtime/widgets/DirectionalFocusTraversalPolicy.mixin.njk

30
com.unity.uiwidgets/Runtime/foundation/diagnostics.cs


}
}
class DiagnosticableTreeNode : DiagnosticableNode<DiagnosticableTree> {
class DiagnosticableTreeNode : DiagnosticableNode<DiagnosticableTreeMixin> {
DiagnosticableTree value,
DiagnosticableTreeMixin value,
DiagnosticsTreeStyle style
) : base(
name: name,

}
public override List<DiagnosticsNode> getChildren() {
if (value != null) {

public virtual void debugFillProperties(DiagnosticPropertiesBuilder properties) {
}
}
public abstract class DiagnosticableTree : Diagnosticable {
public interface DiagnosticableTreeMixin : IDiagnosticable{
public string toString(DiagnosticLevel minLevel = DiagnosticLevel.info);
public string toStringShallow(
string joiner = ", ",
DiagnosticLevel minLevel = DiagnosticLevel.debug
);
public string toStringDeep(
string prefixLineOne = "",
string prefixOtherLines = null,
DiagnosticLevel minLevel = DiagnosticLevel.debug);
public string toStringShort();
public DiagnosticsNode toDiagnosticsNode(string name = null, DiagnosticsTreeStyle style = DiagnosticsTreeStyle.sparse);
public List<DiagnosticsNode> debugDescribeChildren();
public void debugFillProperties(DiagnosticPropertiesBuilder properties);
}
public abstract class DiagnosticableTree : Diagnosticable,DiagnosticableTreeMixin {
protected DiagnosticableTree() {
}

31
com.unity.uiwidgets/Runtime/rendering/proxy_box.cs


translucent,
}
public interface RenderAnimatedOpacityMixin<T> : RenderObjectWithChildMixin<T> where T : RenderObject {
int _alpha { get; }
public new bool alwaysNeedsCompositing {
get;
}
bool _currentlyNeedsCompositing { get; }
public Animation<float> opacity {
get;
set;
}
Animation<float> _opacity { get; }
public bool alwaysIncludeSemantics {
get;
set;
}
bool _alwaysIncludeSemantics { get; }
public void attach(PipelineOwner owner);
public void detach();
public void _updateOpacity();
public void paint(PaintingContext context, Offset offset);
public void visitChildrenForSemantics(RenderObjectVisitor visitor);
public void debugFillProperties(DiagnosticPropertiesBuilder properties);
}
public abstract class RenderProxyBoxWithHitTestBehavior : RenderProxyBox {
protected RenderProxyBoxWithHitTestBehavior(
HitTestBehavior behavior = HitTestBehavior.deferToChild,

13
com.unity.uiwidgets/Runtime/rendering/proxy_sliver.cs


set { child = (RenderSliver) value; }
}
}
public class RenderSliverAnimatedOpacity : RenderProxySliver , RenderAnimatedOpacityMixin<RenderSliver>{
public RenderSliverAnimatedOpacity(
Animation<float> opacity ,
RenderSliver sliver = null,
bool alwaysIncludeSemantics = false
) {
D.assert(opacity != null);
D.assert(alwaysIncludeSemantics != null);
this.opacity = opacity;
this.alwaysIncludeSemantics = alwaysIncludeSemantics;
child = sliver;
}
}
public class RenderSliverOpacity : RenderProxySliver {
public RenderSliverOpacity(
RenderSliver sliver = null,

63
com.unity.uiwidgets/Runtime/rendering/sliver.cs


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Unity.UIWidgets.foundation;
using Unity.UIWidgets.gestures;

hasErrors = true;
errorMessage.AppendLine($" {message}");
});
void verifyFloat(float property, string name, bool mustBePositive = false, bool mustBeNegative = false) {
verify(property != null, $"The \"{name}\" is null.");
if (property.isNaN()) {
string additional = ".";
if (mustBePositive) {
additional = ", expected greater than or equal to zero.";
} else if (mustBeNegative) {
additional = ", expected less than or equal to zero.";
}
verify(false, $"The \"{name}\" is NaN" + $"{additional}");
} else if (mustBePositive) {
verify(property >= 0.0, $"The \"{name}\" is negative.");
} else if (mustBeNegative) {
verify(property <= 0.0, $"The \"{name}\" is positive.");
}
}
verify(axis != null, "The \"axis\" is null.");
verify(growthDirection != null, "The \"growthDirection\" is null.");
verifyFloat(scrollOffset, "scrollOffset");
verifyFloat(overlap, "overlap");
verifyFloat(crossAxisExtent, "crossAxisExtent");
verifyFloat(scrollOffset, "scrollOffset", mustBePositive: true);
verify(crossAxisDirection != null, "The \"crossAxisDirection\" is null.");
verify(AxisUtils.axisDirectionToAxis(axisDirection) != AxisUtils.axisDirectionToAxis(crossAxisDirection), "The \"axisDirection\" and the \"crossAxisDirection\" are along the same axis.");
verifyFloat(viewportMainAxisExtent, "viewportMainAxisExtent", mustBePositive: true);
verifyFloat(remainingPaintExtent, "remainingPaintExtent", mustBePositive: true);
verifyFloat(remainingCacheExtent, "remainingCacheExtent", mustBePositive: true);
verifyFloat(cacheOrigin, "cacheOrigin", mustBeNegative: true);
verifyFloat(precedingScrollExtent, "precedingScrollExtent", mustBePositive: true);
verify(isNormalized, "The constraints are not normalized."); // should be redundant with earlier checks
verify(scrollOffset >= 0.0f, "The \"scrollOffset\" is negative.");
verify(crossAxisExtent >= 0.0f, "The \"crossAxisExtent\" is negative.");
verify(
AxisUtils.axisDirectionToAxis(axisDirection) !=
AxisUtils.axisDirectionToAxis(crossAxisDirection),
"The \"axisDirection\" and the \"crossAxisDirection\" are along the same axis.");
verify(viewportMainAxisExtent >= 0.0f, "The \"viewportMainAxisExtent\" is negative.");
verify(remainingPaintExtent >= 0.0f, "The \"remainingPaintExtent\" is negative.");
verify(remainingCacheExtent >= 0.0f, "The \"remainingCacheExtent\" is negative.");
verify(cacheOrigin <= 0.0f, "The \"cacheOrigin\" is positive.");
verify(isNormalized, "The constraints are not normalized.");
if (hasErrors) {
List<DiagnosticsNode> diagnosticInfo = new List<DiagnosticsNode>();
diagnosticInfo.Add(new ErrorSummary($"{GetType()} is not valid: {errorMessage}"));

}
public override string ToString() {
string result = "";
result += ($"{axisDirection}") +" , ";
result +=($"{growthDirection}")+" , ";
result +=($"{userScrollDirection}")+" , ";
result +=($"scrollOffset: {scrollOffset : F1}")+" , ";
result +=($"remainingPaintExtent: {remainingPaintExtent : F1}")+" , ";
if (overlap != 0.0)
result +=($"overlap: {overlap: F1}")+" , ";
result +=($"crossAxisExtent: {crossAxisExtent : F1}")+" , ";
result +=($"crossAxisDirection: crossAxisDirection")+" , ";
result +=($"viewportMainAxisExtent: {viewportMainAxisExtent : F1}")+" , ";
result +=($"remainingCacheExtent: {remainingCacheExtent : F1}")+" , ";
result +=($"cacheOrigin: {cacheOrigin : F1}");
return $"SliverConstraints({result})";
return
$"SliverConstraints({axisDirection}, {growthDirection}, {userScrollDirection}, scrollOffset: {scrollOffset:F1}, remainingPaintExtent: {remainingCacheExtent:F1}, " +
$"{(overlap != 0.0f ? "overlap: " + overlap.ToString("F1") + ", " : "")}crossAxisExtent: {crossAxisExtent:F1}, crossAxisDirection: {crossAxisDirection}, " +

if (layoutOffset == null)
return "layoutOffset = None";
else {
return layoutOffset.ToString(); // toStringAsFixed(3); // 1.000
return $"layoutOffset = {layoutOffset:F}";
// 1.000
}
}
}

642
com.unity.uiwidgets/Runtime/widgets/focus_manager.cs


}
/*string debugDescribeFocusTree() {
public static string debugDescribeFocusTree() {
}());
});
}*/
}
/*void debugDumpFocusTree() {
public static void debugDumpFocusTree() {
}*/
}
}
public class FocusAttachment {

}
}
public class FocusNode : ChangeNotifier {
//DiagnosticableTreeMixin,
public class FocusNode : DiagnosticableTreeMixinChangeNotifier{
public FocusNode(
string debugLabel = "",
FocusOnKeyCallback onKey = null,

D.assert(canRequestFocus != null);
_skipTraversal = skipTraversal;
_canRequestFocus = canRequestFocus;
/*_onKey = onKey {
this.debugLabel = debugLabel; ///????
}*/
_onKey = onKey;
this.debugLabel = debugLabel;
}
public bool skipTraversal {

BuildContext _context;
FocusOnKeyCallback onKey {
public FocusOnKeyCallback onKey {
get { return _onKey; }
}

List<FocusNode> _descendants;
bool _hasKeyboardToken = false;
FocusNode parent {
public FocusNode parent {
get { return _parent; }
}

}
/*bool nextFocus() {
public bool nextFocus() {
}*
}
bool previousFocus() {
public bool previousFocus() {
bool focusInDirection(TraversalDirection direction) {
public bool focusInDirection(TraversalDirection direction) {
}*/
}
/*public override void debugFillProperties(DiagnosticPropertiesBuilder properties) {
public override void debugFillProperties(DiagnosticPropertiesBuilder properties) {
}*/
}
/*public override List<DiagnosticsNode> debugDescribeChildren() {
public override List<DiagnosticsNode> debugDescribeChildren() {
return _children.map<DiagnosticsNode>((FocusNode child) {
return _children.Select((FocusNode child)=> {
}).toList();
}*/
}).ToList();
}
/*public string toStringShort() {//override
public override string toStringShort() {//override
bool hasDebugLabel = debugLabel != null && debugLabel.isNotEmpty();
string nullStr = "";
string extraData = $"{(hasDebugLabel ? debugLabel : nullStr)} " +

return $"{describeIdentity(this)}" + $"{(extraData.isNotEmpty() ? extraData : nullStr)}";
return $"{foundation_.describeIdentity(this)}" + $"{(extraData.isNotEmpty() ? extraData : nullStr)}";
}*/
}
}
public class FocusScopeNode : FocusNode {

primaryFocus._doRequestFocus(findFirstFocus: findFirstFocus);
}
}
/*public override void debugFillProperties(DiagnosticPropertiesBuilder properties) {
base.debugFillProperties(properties);
if (_focusedChildren.isEmpty()) {
return;
}
List<string> childList = _focusedChildren.reversed.map<string>((FocusNode child) {
return child.toStringShort();
}).toList();
properties.add(new IEnumerableProperty<string>("focusedChildren", childList, defaultValue: new List<string>()));
}*/
public override void debugFillProperties(DiagnosticPropertiesBuilder properties) {
base.debugFillProperties(properties);
if (_focusedChildren.isEmpty()) {
return;
}
List<string> childList = new List<string>();
_focusedChildren.Reverse();
childList = _focusedChildren.Select((FocusNode child)=> {
return child.toStringShort();
}).ToList();
// properties.add(new IEnumerableProperty<string>("focusedChildren", childList, defaultValue: new List<string>()));
}
public class FocusManager : ChangeNotifier {//DiagnosticableTreeMixin,
public class FocusManager : DiagnosticableTreeMixinChangeNotifier{
//RawKeyboard.instance.addListener(_handleRawKeyEvent);
RawKeyboard.instance.addListener(_handleRawKeyEvent);
GestureBinding.instance.pointerRouter.addGlobalRoute(_handlePointerEvent);
}
public static FocusManager instance {

}
if (newMode != _highlightMode) {
_highlightMode = newMode;
//_notifyHighlightModeListeners();
_notifyHighlightModeListeners();
}
}

public void removeHighlightModeListener(ValueChanged<FocusHighlightMode> listener) => _listeners?.Remove(listener);
/*void _notifyHighlightModeListeners() {
void _notifyHighlightModeListeners() {
List<ValueChanged<FocusHighlightMode>> localListeners = List<ValueChanged<FocusHighlightMode>>.from(_listeners);
List<ValueChanged<FocusHighlightMode>> localListeners = new List<ValueChanged<FocusHighlightMode>>();
foreach (var listener in _listeners) {
localListeners.Add(listener);
}
try {
listener(_highlightMode);
listener(_highlightMode);
} catch (exception, stack) {
InformationCollector collector;
D.assert(() =>{
collector = () sync* {
yield DiagnosticsProperty<FocusManager>(
"The $runtimeType sending notification was",
this,
style: DiagnosticsTreeStyle.errorProperty,
);
};
return true;
}());
FlutterError.reportError(FlutterErrorDetails(
exception: exception,
stack: stack,
library: "widgets library",
context: ErrorDescription("while dispatching notifications for $runtimeType"),
informationCollector: collector,
));
}
}*/
}
public readonly FocusScopeNode rootScope = new FocusScopeNode(debugLabel: "Root Focus Scope");

}
}
/*void _handleRawKeyEvent(RawKeyEvent Event) {
void _handleRawKeyEvent(RawKeyEvent Event) {
if (_lastInteractionWasTouch) {
_lastInteractionWasTouch = false;

D.assert(FocusManagerUtils._focusDebug($"Received key event {Event.logicalKey}"));
//D.assert(FocusManagerUtils._focusDebug($"Received key event {Event.logicalKey}"));
if (_primaryFocus == null) {
D.assert(FocusManagerUtils._focusDebug($"No primary focus for key event, ignored: {Event}"));

bool handled = false;
foreach (FocusNode node in List < FocusNode >{
_primaryFocus, ..._primaryFocus.ancestors
}) {
List<FocusNode> nodes = new List<FocusNode>();
nodes.Add(_primaryFocus);
foreach (var node in _primaryFocus.ancestors) {
nodes.Add(node);
}
foreach (FocusNode node in nodes) {
if (node.onKey != null && node.onKey(node, Event)) {
D.assert(FocusManagerUtils._focusDebug($"Node {node} handled key event {Event}."));
handled = true;

if (!handled) {
D.assert(FocusManagerUtils._focusDebug($"Key event not handled by anyone: {Event}."));
}
}*/
}
public FocusNode primaryFocus {

public FocusNode _markedForFocus;
public void _markDetached(FocusNode node) {
D.assert(FocusManagerUtils._focusDebug($"Node was detached: {node}"));
if (_primaryFocus == node) {
_primaryFocus = null;
}
_dirtyNodes?.Remove(node);
D.assert(FocusManagerUtils._focusDebug($"Node was detached: {node}"));
if (_primaryFocus == node) {
_primaryFocus = null;
}
_dirtyNodes?.Remove(node);
}
public void _markPropertiesChanged(FocusNode node) {

}
}
public void _markNextFocus(FocusNode node) {
public void _markNextFocus(FocusNode node) {
_markedForFocus = null;
_markedForFocus = null;
} else {
_markedForFocus = node;
_markNeedsUpdate();

return;
}
_haveScheduledUpdate = true;
//scheduleMicrotask(_applyFocusChange);
async_.scheduleMicrotask(()=> {
_applyFocusChange();
return null;
});
/*public void reparentIfNeeded(FocusNode node) {
D.assert(node != null);
if (node._parent == null || node._parent == this) {
return;
}
node.unfocus();
D.assert(node._parent == null);
if (_focus == null) {
_setFocus(node);
}
}*/
/*void _applyFocusChange() {
void _applyFocusChange() {
_markedForFocus = rootScope;
_markedForFocus = rootScope;
HashSet<FocusNode> previousPath = previousFocus?.ancestors?.toSet() ?? new HashSet<FocusNode>();
HashSet<FocusNode> nextPath = _markedForFocus.ancestors.toSet();
// Notify nodes that are newly focused.
_dirtyNodes.addAll(nextPath.difference(previousPath));
// Notify nodes that are no longer focused
_dirtyNodes.addAll(previousPath.difference(nextPath));
HashSet<FocusNode> previousPath = new HashSet<FocusNode>(previousFocus?.ancestors) ?? new HashSet<FocusNode>();
HashSet<FocusNode> nextPath = new HashSet<FocusNode>(_markedForFocus.ancestors);
_primaryFocus = _markedForFocus;
_markedForFocus = null;
foreach(FocusNode node in FocusTravesalUtils.difference(nextPath,previousPath)) {
_dirtyNodes.Add(node);
}
foreach(FocusNode node in FocusTravesalUtils.difference(previousPath,nextPath)) {
_dirtyNodes.Add(node);
}
_primaryFocus = _markedForFocus;
_markedForFocus = null;
D.assert(FocusManagerUtils._focusDebug("Updating focus from $previousFocus to $_primaryFocus"));
if (previousFocus != null) {
_dirtyNodes.Add(previousFocus);
}
if (_primaryFocus != null) {
_dirtyNodes.Add(_primaryFocus);
}
D.assert(FocusManagerUtils._focusDebug($"Updating focus from {previousFocus} to {_primaryFocus}"));
if (previousFocus != null) {
_dirtyNodes.Add(previousFocus);
}
if (_primaryFocus != null) {
_dirtyNodes.Add(_primaryFocus);
}
D.assert(FocusManagerUtils._focusDebug("Notifying ${_dirtyNodes.length} dirty nodes:", _dirtyNodes.toList().map<String>((FocusNode node) => node.toString())));
D.assert(FocusManagerUtils._focusDebug($"Notifying {_dirtyNodes.Count} dirty nodes:",
_dirtyNodes.ToList().Select((FocusNode node) => {
return node.toString();
}).ToList()));
node._notify();
node._notify();
notifyListeners();
notifyListeners();
if (_kDebugFocus) {
debugDumpFocusTree();
}
return true;
if (FocusManagerUtils._kDebugFocus) {
FocusManagerUtils.debugDumpFocusTree();
}
return true;
}*/
}
/*public override List<DiagnosticsNode> debugDescribeChildren() {
public override List<DiagnosticsNode> debugDescribeChildren() {
}*/
}
/*public void debugFillProperties(DiagnosticPropertiesBuilder properties) {
public override void debugFillProperties(DiagnosticPropertiesBuilder properties) {
properties.add(new FlagProperty("haveScheduledUpdate", value: _haveScheduledUpdate, ifTrue: "UPDATE SCHEDULED"));
properties.add(new DiagnosticsProperty<FocusNode>("primaryFocus", primaryFocus, defaultValue: null));
properties.add(new DiagnosticsProperty<FocusNode>("nextFocus", _markedForFocus, defaultValue: null));

}
}*/
}
}
/*
public class FocusNode : ChangeNotifier {
internal FocusScopeNode _parent;
internal FocusManager _manager;
internal bool _hasKeyboardToken = false;
public bool hasFocus {
get {
FocusNode node = null;
if (_manager != null) {
node = _manager._currentFocus;
}
return node == this;
}
}
public bool consumeKeyboardToken() {
if (!_hasKeyboardToken) {
return false;
}
_hasKeyboardToken = false;
return true;
}
public void unfocus() {
if (_parent != null) {
_parent._resignFocus(this);
}
D.assert(_parent == null);
D.assert(_manager == null);
}
public override void dispose() {
if (_manager != null) {
_manager._willDisposeFocusNode(this);
}
if (_parent != null) {
_parent._resignFocus(this);
}
D.assert(_parent == null);
D.assert(_manager == null);
base.dispose();
}
internal void _notify() {
notifyListeners();
}
public override string ToString() {
return $"{foundation_.describeIdentity(this)} hasFocus: {hasFocus}";
public class FocusScopeNode : DiagnosticableTree {
internal FocusManager _manager;
internal FocusScopeNode _parent;
internal FocusScopeNode _nextSibling;
internal FocusScopeNode _previousSibling;
internal FocusScopeNode _firstChild;
internal FocusScopeNode _lastChild;
internal FocusNode _focus;
internal List<FocusScopeNode> _focusPath;
public bool isFirstFocus {
get { return _parent == null || _parent._firstChild == this; }
}
internal List<FocusScopeNode> _getFocusPath() {
List<FocusScopeNode> nodes = new List<FocusScopeNode> {this};
FocusScopeNode node = _parent;
while (node != null && node != _manager?.rootScope) {
nodes.Add(node);
node = node._parent;
}
return nodes;
}
internal void _prepend(FocusScopeNode child) {
D.assert(child != this);
D.assert(child != _firstChild);
D.assert(child != _lastChild);
D.assert(child._parent == null);
D.assert(child._manager == null);
D.assert(child._nextSibling == null);
D.assert(child._previousSibling == null);
D.assert(() => {
var node = this;
while (node._parent != null) {
node = node._parent;
}
D.assert(node != child);
return true;
});
child._parent = this;
child._nextSibling = _firstChild;
if (_firstChild != null) {
_firstChild._previousSibling = child;
}
_firstChild = child;
_lastChild = _lastChild ?? child;
child._updateManager(_manager);
}
void _updateManager(FocusManager manager) {
Action<FocusScopeNode> update = null;
update = (child) => {
if (child._manager == manager) {
return;
}
child._manager = manager;
// We don"t proactively null out the manager for FocusNodes because the
// manager holds the currently active focus node until the end of the
// microtask, even if that node is detached from the focus tree.
if (manager != null && child._focus != null) {
child._focus._manager = manager;
}
child._visitChildren(update);
};
update(this);
}
void _visitChildren(Action<FocusScopeNode> vistor) {
FocusScopeNode child = _firstChild;
while (child != null) {
vistor.Invoke(child);
child = child._nextSibling;
}
}
bool _debugUltimatePreviousSiblingOf(FocusScopeNode child, FocusScopeNode equals) {
while (child._previousSibling != null) {
D.assert(child._previousSibling != child);
child = child._previousSibling;
}
return child == equals;
}
bool _debugUltimateNextSiblingOf(FocusScopeNode child, FocusScopeNode equals) {
while (child._nextSibling != null) {
D.assert(child._nextSibling != child);
child = child._nextSibling;
}
return child == equals;
}
internal void _remove(FocusScopeNode child) {
D.assert(child._parent == this);
D.assert(child._manager == _manager);
D.assert(_debugUltimatePreviousSiblingOf(child, equals: _firstChild));
D.assert(_debugUltimateNextSiblingOf(child, equals: _lastChild));
if (child._previousSibling == null) {
D.assert(_firstChild == child);
_firstChild = child._nextSibling;
}
else {
child._previousSibling._nextSibling = child._nextSibling;
}
if (child._nextSibling == null) {
D.assert(_lastChild == child);
_lastChild = child._previousSibling;
}
else {
child._nextSibling._previousSibling = child._previousSibling;
}
child._previousSibling = null;
child._nextSibling = null;
child._parent = null;
child._updateManager(null);
}
internal void _didChangeFocusChain() {
if (isFirstFocus && _manager != null) {
_manager._markNeedsUpdate();
}
}
// TODO: need update
public void requestFocus(FocusNode node = null) {
// D.assert(node != null);
var focusPath = _manager?._getCurrentFocusPath();
if (_focus == node &&
(_focusPath == focusPath || (focusPath != null && _focusPath != null &&
_focusPath.SequenceEqual(focusPath)))) {
return;
}
if (_focus != null) {
_focus.unfocus();
}
node._hasKeyboardToken = true;
_setFocus(node);
}
public void autofocus(FocusNode node) {
D.assert(node != null);
if (_focus == null) {
node._hasKeyboardToken = true;
_setFocus(node);
}
}
public void reparentIfNeeded(FocusNode node) {
D.assert(node != null);
if (node._parent == null || node._parent == this) {
return;
}
node.unfocus();
D.assert(node._parent == null);
if (_focus == null) {
_setFocus(node);
}
}
internal void _setFocus(FocusNode node) {
D.assert(node != null);
D.assert(node._parent == null);
D.assert(_focus == null);
_focus = node;
_focus._parent = this;
_focus._manager = _manager;
_focus._hasKeyboardToken = true;
_didChangeFocusChain();
_focusPath = _getFocusPath();
}
internal void _resignFocus(FocusNode node) {
D.assert(node != null);
if (_focus != node) {
return;
}
_focus._parent = null;
_focus._manager = null;
_focus = null;
_didChangeFocusChain();
}
public void setFirstFocus(FocusScopeNode child) {
D.assert(child != null);
D.assert(child._parent == null || child._parent == this);
if (_firstChild == child) {
return;
}
child.detach();
_prepend(child);
D.assert(child._parent == this);
_didChangeFocusChain();
}
public void reparentScopeIfNeeded(FocusScopeNode child) {
D.assert(child != null);
if (child._parent == null || child._parent == this) {
return;
}
if (child.isFirstFocus) {
setFirstFocus(child);
}
else {
child.detach();
}
}
public void detach() {
_didChangeFocusChain();
if (_parent != null) {
_parent._remove(this);
}
D.assert(_parent == null);
}
public override void debugFillProperties(DiagnosticPropertiesBuilder properties) {
base.debugFillProperties(properties);
if (_focus != null) {
properties.add(new DiagnosticsProperty<FocusNode>("focus", _focus));
}
}
public override List<DiagnosticsNode> debugDescribeChildren() {
var children = new List<DiagnosticsNode>();
if (_firstChild != null) {
FocusScopeNode child = _firstChild;
int count = 1;
while (true) {
children.Add(child.toDiagnosticsNode(name: $"child {count}"));
if (child == _lastChild) {
break;
}
child = child._nextSibling;
count += 1;
}
}
return children;
}
}
public class FocusManager {
public FocusManager() {
rootScope._manager = this;
D.assert(rootScope._firstChild == null);
D.assert(rootScope._lastChild == null);
}
public readonly FocusScopeNode rootScope = new FocusScopeNode();
internal readonly FocusScopeNode _noneScope = new FocusScopeNode();
public FocusNode currentFocus {
get { return _currentFocus; }
}
internal FocusNode _currentFocus;
internal void _willDisposeFocusNode(FocusNode node) {
D.assert(node != null);
if (_currentFocus == node) {
_currentFocus = null;
}
}
bool _haveScheduledUpdate = false;
internal void _markNeedsUpdate() {
if (_haveScheduledUpdate) {
return;
}
_haveScheduledUpdate = true;
async_.scheduleMicrotask(() => {
_update();
return null;
});
}
internal FocusNode _findNextFocus() {
FocusScopeNode scope = rootScope;
while (scope._firstChild != null) {
scope = scope._firstChild;
}
return scope._focus;
}
internal void _update() {
_haveScheduledUpdate = false;
var nextFocus = _findNextFocus();
if (_currentFocus == nextFocus) {
return;
}
var previousFocus = _currentFocus;
_currentFocus = nextFocus;
if (previousFocus != null) {
previousFocus._notify();
}
if (_currentFocus != null) {
_currentFocus._notify();
}
}
internal List<FocusScopeNode> _getCurrentFocusPath() {
return _currentFocus?._parent?._getFocusPath();
}
public void focusNone(bool focus) {
if (focus) {
if (_noneScope._parent != null && _noneScope.isFirstFocus) {
return;
}
rootScope.setFirstFocus(_noneScope);
}
else {
if (_noneScope._parent == null) {
return;
}
_noneScope.detach();
}
}
public override string ToString() {
var status = _haveScheduledUpdate ? " UPDATE SCHEDULED" : "";
var indent = " ";
return string.Format("{1}{2}\n{0}currentFocus: {3}\n{4}", indent, foundation_.describeIdentity(this),
status, _currentFocus,
rootScope.toStringDeep(prefixLineOne: indent, prefixOtherLines: indent));
}
}*/

472
com.unity.uiwidgets/Runtime/widgets/focus_traversal.cs


}
public class FocusTravesalUtils {
public static void _focusAndEnsureVisible(
FocusNode node,

}
return result;
}
static int _MERGE_SORT_LIMIT = 32;
/// as they started in.
public static void insertionSort<T>(List<T> list,
Comparator<T> compare = null, int start = 0, int end =0) {
//compare ??= defaultCompare<T>();
end = end == 0 ?list.Count : end;
for (int pos = start + 1; pos < end; pos++) {
int min = start;
int max = pos;
var element = list[pos];
while (min < max) {
int mid = min + ((max - min) >> 1);
int comparison = compare(element, list[mid]);
if (comparison < 0) {
max = mid;
} else {
min = mid + 1;
}
}
setRange(list,min + 1, pos + 1, list, min);
list[min] = element;
}
}
public delegate int Comparator<T>(T a, T b);
//public Comparator<T> defaultCompare<T>() => (value1, value2) => value1 ;
public static void mergeSort<T>(
List<T> list,
int? start = null , int? end = null, Comparator<T> compare = null) {
int _start = start ?? 0;
int _end = end ?? list.Count;
compare = compare ;//?? <T>();
int length = _end - _start;
if (length < 2) return;
if (length < _MERGE_SORT_LIMIT) {
insertionSort(list, compare: compare, start: _start, end: _end);
return;
}
int middle = _start + ((_end - _start) >> 1);
int firstLength = middle - _start;
int secondLength = _end - middle;
// secondLength is always the same as firstLength, or one greater.
var scratchSpace = new List<T>(secondLength);
_mergeSort(list, compare, middle, _end, scratchSpace, 0);
int firstTarget = _end - firstLength;
_mergeSort(list, compare, _start, middle, list, firstTarget);
_merge(compare, list, firstTarget, _end, scratchSpace, 0, secondLength, list,
_start);
}
public static void _mergeSort<T>(List<T> list, Comparator<T> compare, int start, int end,
List<T> target, int targetOffset) {
int length = end - start;
if (length < _MERGE_SORT_LIMIT) {
_movingInsertionSort(list, compare, start, end, target, targetOffset);
return;
}
int middle = start + (length >> 1);
int firstLength = middle - start;
int secondLength = end - middle;
int targetMiddle = targetOffset + firstLength;
_mergeSort(list, compare, middle, end, target, targetMiddle);
_mergeSort(list, compare, start, middle, list, middle);
_merge(compare, list, middle, middle + firstLength, target, targetMiddle,
targetMiddle + secondLength, target, targetOffset);
}
public static void _movingInsertionSort<T>(List<T> list, Comparator<T> compare, int start,
int end, List<T> target, int targetOffset) {
int length = end - start;
if (length == 0) return;
target[targetOffset] = list[start];
for (int i = 1; i < length; i++) {
var element = list[start + i];
int min = targetOffset;
int max = targetOffset + i;
while (min < max) {
int mid = min + ((max - min) >> 1);
if (compare(element, target[mid]) < 0) {
max = mid;
} else {
min = mid + 1;
}
}
setRange(target,min + 1, targetOffset + i + 1, target, min);
target[min] = element;
}
}
public static List<T>setRange<T>(List<T> alist, int start, int end, List<T> blist, int skipConut = 0 ) {
List<T> copyList = new List<T>();
List<T> resultList = new List<T>();
for (int i = skipConut; i < blist.Count; i++) {
copyList.Add(blist[i]);
}
for (int i = 0; i < start; i++) {
resultList.Add(alist[i]);
}
for (int i = 0; i < copyList.Count; i++) {
resultList.Add(blist[i]);
}
for (int i = start + copyList.Count - 1; i < alist.Count; i++) {
resultList.Add(alist[i]);
}
return resultList;
}
public static void _merge<T>(
Comparator<T> compare,
List<T> firstList,
int firstStart,
int firstEnd,
List<T> secondList,
int secondStart,
int secondEnd,
List<T> target,
int targetOffset) {
// No empty lists reaches here.
D.assert(firstStart < firstEnd);
D.assert(secondStart < secondEnd);
int cursor1 = firstStart;
int cursor2 = secondStart;
var firstElement = firstList[cursor1++];
var secondElement = secondList[cursor2++];
while (true) {
if (compare(firstElement, secondElement) <= 0) {
target[targetOffset++] = firstElement;
if (cursor1 == firstEnd) break; // Flushing second list after loop.
firstElement = firstList[cursor1++];
} else {
target[targetOffset++] = secondElement;
if (cursor2 != secondEnd) {
secondElement = secondList[cursor2++];
continue;
}
target[targetOffset++] = firstElement;
setRange(target,targetOffset, targetOffset + (firstEnd - cursor1),
firstList, cursor1);
return;
}
}
// First list empties first. Reached by break above.
target[targetOffset++] = secondElement;
setRange(target
,targetOffset, targetOffset + (secondEnd - cursor2), secondList, cursor2);
}
public class FocusTraversalGroup : StatefulWidget {
public FocusTraversalGroup(

) : base(key: key) {
policy = policy ;//?? new ReadingOrderTraversalPolicy();
policy = policy ?? new ReadingOrderTraversalPolicy();
this.child = child;
}

List<FocusNode> members = null
) {
groupNode = marker?.focusNode;
policy = marker?.policy ?? defaultPolicy ;//?? new ReadingOrderTraversalPolicy();
policy = marker?.policy ?? defaultPolicy ?? new ReadingOrderTraversalPolicy();
members = members ?? new List<FocusNode>();
}
public readonly FocusNode groupNode;

candidate = sorted.isNotEmpty() ? sorted.First() : null;
}
candidate ??= currentNode;
candidate = candidate ?? currentNode;
public abstract void invalidateScopeData(FocusScopeNode node);
public virtual void invalidateScopeData(FocusScopeNode node) {
}
public abstract void changedScope(FocusNode node = null, FocusScopeNode oldScope = null);
bool next(FocusNode currentNode) => _moveFocus(currentNode, forward: true);
public virtual void changedScope(FocusNode node = null, FocusScopeNode oldScope = null) {
}
public bool next(FocusNode currentNode) => _moveFocus(currentNode, forward: true);
bool previous(FocusNode currentNode) => _moveFocus(currentNode, forward: false);
public bool previous(FocusNode currentNode) => _moveFocus(currentNode, forward: false);
public abstract bool inDirection(FocusNode currentNode, TraversalDirection direction);

public List<FocusNode> _sortAllDescendants(FocusScopeNode scope) {
D.assert(scope != null);
_FocusTraversalGroupMarker scopeGroupMarker = _getMarker(scope.context);
FocusTraversalPolicy defaultPolicy = scopeGroupMarker?.policy ;//?? new ReadingOrderTraversalPolicy();
FocusTraversalPolicy defaultPolicy = scopeGroupMarker?.policy ?? new ReadingOrderTraversalPolicy();
Dictionary<FocusNode, _FocusTraversalGroupInfo> groups = new Dictionary<FocusNode, _FocusTraversalGroupInfo>();
foreach(FocusNode node in scope.descendants) {
_FocusTraversalGroupMarker groupMarker = _getMarker(node.context);

_FocusTraversalGroupMarker parentMarker = _getMarker(parentContext);
FocusNode parentNode = parentMarker?.focusNode;
groups[parentNode] ??= new _FocusTraversalGroupInfo(parentMarker, members: new List<FocusNode>(), defaultPolicy: defaultPolicy);
FocusNode parentNode = parentMarker?.focusNode;
groups[groupNode] = groups.getOrDefault(parentNode) ?? new _FocusTraversalGroupInfo(parentMarker, members: new List<FocusNode>(), defaultPolicy: defaultPolicy);
groups[groupNode] ??= new _FocusTraversalGroupInfo(groupMarker, members: new List<FocusNode>(), defaultPolicy: defaultPolicy);
groups[groupNode] = groups.getOrDefault(groupNode) ?? new _FocusTraversalGroupInfo(groupMarker, members: new List<FocusNode>(), defaultPolicy: defaultPolicy);
D.assert(!groups[groupNode].members.Contains(node));
groups[groupNode].members.Add(node);
}

return false;
}
}
public class _DirectionalPolicyDataEntry {
public _DirectionalPolicyDataEntry(
TraversalDirection direction ,

public readonly TraversalDirection direction;
public readonly FocusNode node;
}
public class WidgetOrderTraversalPolicy : DirectionalFocusTraversalPolicyMixinFocusTraversalPolicy {
public override IEnumerable<FocusNode> sortDescendants(IEnumerable<FocusNode> descendants) {
return descendants;
}
}
public class _DirectionalPolicyData {
public _DirectionalPolicyData(List<_DirectionalPolicyDataEntry> history) {
D.assert(history != null);
}
public readonly List<_DirectionalPolicyDataEntry> history;
}
public class _ReadingOrderSortData : Diagnosticable {
public _ReadingOrderSortData(FocusNode node) {
D.assert(node != null);

IEnumerable<HashSet<Directionality>> allAncestors = list.Select((_ReadingOrderSortData member) => new HashSet<Directionality>(member.directionalAncestors));
HashSet<Directionality> common = null;
foreach ( HashSet<Directionality> ancestorSet in allAncestors) {
common ??= ancestorSet;
common = common ?? ancestorSet;
common = FocusTravesalUtils.intersaction(common,ancestorSet);
}
if (common.isEmpty()) {

}
return common.First().textDirection;
}
/*public static void sortWithDirectionality(List<_ReadingOrderSortData> list, TextDirection directionality) {
mergeSort<_ReadingOrderSortData>(list, compare: (_ReadingOrderSortData a, _ReadingOrderSortData b)=> {
public static void sortWithDirectionality(List<_ReadingOrderSortData> list, TextDirection directionality) {
FocusTravesalUtils.mergeSort<_ReadingOrderSortData>(list,
compare: (_ReadingOrderSortData a, _ReadingOrderSortData b)=> {
switch (directionality) {
case TextDirection.ltr:
return a.rect.left.CompareTo(b.rect.left);

D.assert(false, ()=>"Unhandled directionality $directionality");
return 0;
});
}*/
}
public IEnumerable<Directionality> directionalAncestors {
get {

}
return result;
}
_directionalAncestors ??= getDirectionalityAncestors(node.context);
_directionalAncestors = _directionalAncestors ?? getDirectionalityAncestors(node.context);
return _directionalAncestors;
}
}

get {if (_rect == null) {
foreach(Rect rect in members.Select(
(_ReadingOrderSortData data) => data.rect)){
_rect ??= rect;
_rect = _rect ?? rect;
_rect = _rect.expandToInclude(rect);
}
}

}
List<Directionality> _memberAncestors;
/*public static void sortWithDirectionality(List<_ReadingOrderDirectionalGroupData> list, TextDirection directionality) {
mergeSort<_ReadingOrderDirectionalGroupData>(list, compare: (_ReadingOrderDirectionalGroupData a, _ReadingOrderDirectionalGroupData b) =>{
public static void sortWithDirectionality(List<_ReadingOrderDirectionalGroupData> list, TextDirection directionality) {
FocusTravesalUtils.mergeSort<_ReadingOrderDirectionalGroupData>(list, compare: (_ReadingOrderDirectionalGroupData a, _ReadingOrderDirectionalGroupData b) =>{
switch (directionality) {
case TextDirection.ltr:
return a.rect.left.CompareTo(b.rect.left);

D.assert(false, ()=>"Unhandled directionality $directionality");
return 0;
});
}*/
}
public override void debugFillProperties(DiagnosticPropertiesBuilder properties) {
base.debugFillProperties(properties);
properties.add(new DiagnosticsProperty<TextDirection>("directionality", directionality));

//})));
}
}
/*public class ReadingOrderTraversalPolicy : FocusTraversalPolicy , DirectionalFocusTraversalPolicyMixin
public interface DirectionalFocusTraversalPolicyMixin {
//Dictionary<FocusScopeNode, _DirectionalPolicyData> _policyData = new Dictionary<FocusScopeNode, _DirectionalPolicyData>();
void invalidateScopeData(FocusScopeNode node);
void changedScope(FocusNode node = null, FocusScopeNode oldScope = null);
FocusNode findFirstFocusInDirection(FocusNode currentNode, TraversalDirection direction);
FocusNode _sortAndFindInitial(FocusNode currentNode, bool vertical = false, bool first = false);
IEnumerable<FocusNode> _sortAndFilterHorizontally(
TraversalDirection direction,
Rect target,
FocusNode nearestScope);
IEnumerable<FocusNode> _sortAndFilterVertically(
TraversalDirection direction,
Rect target,
IEnumerable<FocusNode> nodes);
bool _popPolicyDataIfNeeded(TraversalDirection direction, FocusScopeNode nearestScope, FocusNode focusedChild);
void _pushPolicyData(TraversalDirection direction, FocusScopeNode nearestScope, FocusNode focusedChild);
bool inDirection(FocusNode currentNode, TraversalDirection direction);
}
public class ReadingOrderTraversalPolicy : DirectionalFocusTraversalPolicyMixinFocusTraversalPolicy
{
public List<_ReadingOrderDirectionalGroupData> _collectDirectionalityGroups(IEnumerable<_ReadingOrderSortData> candidates) {
TextDirection currentDirection = candidates.First().directionality;

if (bandGroup.members.Count == 1) {
continue;
}
// _ReadingOrderSortData.sortWithDirectionality(bandGroup.members, bandGroup.directionality);
_ReadingOrderSortData.sortWithDirectionality(bandGroup.members, bandGroup.directionality);
}*/
/*public _ReadingOrderSortData _pickNext(List<_ReadingOrderSortData> candidates) {
}
public _ReadingOrderSortData _pickNext(List<_ReadingOrderSortData> candidates) {
MERGESORT<_ReadingOrderSortData>(candidates, compare: (_ReadingOrderSortData a, _ReadingOrderSortData b) => a.rect.top.CompareTo(b.rect.top));
FocusTravesalUtils.mergeSort<_ReadingOrderSortData>(candidates, compare: (_ReadingOrderSortData a, _ReadingOrderSortData b) => a.rect.top.CompareTo(b.rect.top));
_ReadingOrderSortData topmost = candidates.First();
List<_ReadingOrderSortData> inBand(_ReadingOrderSortData current, IEnumerable<_ReadingOrderSortData> candidates) {

}
_ReadingOrderDirectionalGroupData.sortWithDirectionality(bandGroups, nearestCommonDirectionality);
return bandGroups.First().members.First();
}*/
}
/*public override IEnumerable<FocusNode> sortDescendants(IEnumerable<FocusNode> descendants) {
public override IEnumerable<FocusNode> sortDescendants(IEnumerable<FocusNode> descendants) {
D.assert(descendants != null);
if (descendants.Count() <= 1) {
return descendants;

unplaced.Remove(current);
}
return sortedList;
}*/
// }
}
}
public interface Comparable<T> {
public int compareTo(T other);
int compare(Comparable<T> a, T b);
}
public abstract class FocusOrder : Diagnosticable , Comparable<FocusOrder> {
public FocusOrder() {
}
public int compareTo(FocusOrder other) {
D.assert(
GetType() == other.GetType(),()=>
"The sorting algorithm must not compare incomparable keys, since they don't "+
$"know how to order themselves relative to each other. Comparing {this} with {other}");
return doCompare(other);
}
public int compare(Comparable<FocusOrder> a, FocusOrder b) {
//throw new NotImplementedException();
return a.compareTo(b);
}
protected abstract int doCompare(FocusOrder other);
}
public class NumericFocusOrder : FocusOrder {
public NumericFocusOrder(float order) {
D.assert(order != null);
this.order = order;
}
public readonly float order;
public override void debugFillProperties(DiagnosticPropertiesBuilder properties) {
base.debugFillProperties(properties);
properties.add(new FloatProperty("order", order));
}
protected override int doCompare(FocusOrder other) {
other = (NumericFocusOrder) other;
return order.CompareTo(((NumericFocusOrder) other).order);
}
}
class LexicalFocusOrder : FocusOrder {
public LexicalFocusOrder(string order) {
D.assert(order != null);
this.order = order;
}
public readonly string order;
public override void debugFillProperties(DiagnosticPropertiesBuilder properties) {
base.debugFillProperties(properties);
properties.add(new StringProperty("order", order));
}
protected override int doCompare(FocusOrder other) {
other = (LexicalFocusOrder) other;
return order.CompareTo(((LexicalFocusOrder) other).order);
}
}
class _OrderedFocusInfo {
public _OrderedFocusInfo(
FocusNode node = null,
FocusOrder order = null) {
D.assert(node != null);
D.assert(order != null);
this.order = order;
this.node = node;
}
public readonly FocusNode node;
public readonly FocusOrder order;
}
public class OrderedTraversalPolicy : DirectionalFocusTraversalPolicyMixinFocusTraversalPolicy {
public OrderedTraversalPolicy(FocusTraversalPolicy secondary) {
}
public readonly FocusTraversalPolicy secondary;
public override IEnumerable<FocusNode> sortDescendants(IEnumerable<FocusNode> descendants) {
FocusTraversalPolicy secondaryPolicy = secondary ?? new ReadingOrderTraversalPolicy();
IEnumerable<FocusNode> sortedDescendants = secondaryPolicy.sortDescendants(descendants);
List<FocusNode> unordered = new List<FocusNode>();
List<_OrderedFocusInfo> ordered = new List<_OrderedFocusInfo>();
foreach( FocusNode node in sortedDescendants) {
FocusOrder order = FocusTraversalOrder.of(node.context, nullOk: true);
if (order != null) {
ordered.Add(new _OrderedFocusInfo(node: node, order: order));
} else {
unordered.Add(node);
}
}
FocusTravesalUtils.mergeSort<_OrderedFocusInfo>(ordered, compare: (_OrderedFocusInfo a, _OrderedFocusInfo b)=> {
D.assert(
a.order.GetType() == b.order.GetType(),()=>
$"When sorting nodes for determining focus order, the order ({a.order}) of " +
$"node {a.node}, isn't the same type as the order ({b.order}) of {b.node}. " +
"Incompatible order types can't be compared. Use a FocusTraversalGroup to group " +
"similar orders together."
);
return a.order.compareTo(b.order);
});
return ordered.Select((_OrderedFocusInfo info) => info.node).Concat(unordered);
}
}
public class FocusTraversalOrder : InheritedWidget {
public FocusTraversalOrder(Key key = null, FocusOrder order = null, Widget child = null)
: base(key: key, child: child) {
}
public readonly FocusOrder order;
public static FocusOrder of(BuildContext context, bool nullOk = false) {
D.assert(context != null);
D.assert(nullOk != null);
FocusTraversalOrder marker = context.getElementForInheritedWidgetOfExactType<FocusTraversalOrder>()?.widget as FocusTraversalOrder;
FocusOrder order = marker?.order;
if (order == null && !nullOk) {
throw new UIWidgetsError("FocusTraversalOrder.of() was called with a context that "+
"does not contain a TraversalOrder widget. No TraversalOrder widget " +
"ancestor could be found starting from the context that was passed to " +
"FocusTraversalOrder.of().\n" +
"The context used was:\n" +
$" {context}");
}
return order;
}
public override bool updateShouldNotify(InheritedWidget oldWidget) => false;
public override void debugFillProperties(DiagnosticPropertiesBuilder properties) {
base.debugFillProperties(properties);
properties.add(new DiagnosticsProperty<FocusOrder>("order", order));
}
}
public class _RequestFocusActionBase : UiWidgetAction {
public _RequestFocusActionBase(LocalKey name) : base(name) {
}
FocusNode _previousFocus;
public override void invoke(FocusNode node, Intent intent) {
_previousFocus = FocusManagerUtils.primaryFocus;
node.requestFocus();
}
public override void debugFillProperties(DiagnosticPropertiesBuilder properties) {
base.debugFillProperties(properties);
properties.add(new DiagnosticsProperty<FocusNode>("previous", _previousFocus));
}
}
public class NextFocusAction : _RequestFocusActionBase {
public NextFocusAction() : base(key) {
}
public readonly static LocalKey key = new ValueKey<Type>(typeof(NextFocusAction));
public override void invoke(FocusNode node, Intent intent) {
node.nextFocus();
}
}
public class PreviousFocusAction : _RequestFocusActionBase {
public PreviousFocusAction() : base(key) {
}
public readonly static LocalKey key = new ValueKey<Type>(typeof(PreviousFocusAction));
public override void invoke(FocusNode node, Intent intent) => node.previousFocus();
}
public class DirectionalFocusIntent : Intent {
public DirectionalFocusIntent(TraversalDirection direction = TraversalDirection.up, bool ignoreTextFields = true)
:base(DirectionalFocusAction.key) {
this.ignoreTextFields = ignoreTextFields;
this.direction = direction;
}
public readonly TraversalDirection direction;
public readonly bool ignoreTextFields;
}
public class DirectionalFocusAction : _RequestFocusActionBase {
public DirectionalFocusAction() : base(key) {
}
public readonly static LocalKey key = new ValueKey<Type>(typeof(DirectionalFocusAction));
public override void invoke(FocusNode node, Intent intent) {
intent = (DirectionalFocusIntent) intent;
if (!((DirectionalFocusIntent)intent).ignoreTextFields || !(node.context.widget is EditableText)) {
node.focusInDirection(((DirectionalFocusIntent) intent).direction);
}
}
}
}

6
com.unity.uiwidgets/Runtime/widgets/scroll_notification.mixin.njk


{% macro ViewportNotificationMixin(with) %}
public abstract class ViewportNotificationMixin{{with}} : {{with}} {
public int depth {
get { return this._depth; }
get { return _depth; }
}
int _depth = 0;

this._depth += 1;
_depth += 1;
}
return base.visitAncestor(element);

base.debugFillDescription(description);
description.Add(string.Format("depth: {0} ({1})",
this._depth, this._depth == 0 ? "local" : "remote"));
_depth, _depth == 0 ? "local" : "remote"));
}
}
{% endmacro %}

6
com.unity.uiwidgets/Runtime/widgets/selectable_text.cs


}
void _handleDragUpdate(DragUpdateDetails details) {
_lastDragUpdateDetails = details;
_dragUpdateThrottleTimer = _dragUpdateThrottleTimer ??
Timer.create(TextSelectionUtils._kDragSelectionUpdateThrottle,
_handleDragUpdateThrottled);
_lastDragUpdateDetails = details;
_dragUpdateThrottleTimer = _dragUpdateThrottleTimer ?? Timer.create(TextSelectionUtils._kDragSelectionUpdateThrottle, _handleDragUpdateThrottled);
}
object _handleDragUpdateThrottled() {

13
com.unity.uiwidgets/Runtime/widgets/transitions.cs


}
}
/*public class SliverFadeTransition : SingleChildRenderObjectWidget {
public class SliverFadeTransition : SingleChildRenderObjectWidget {
public SliverFadeTransition(
Animation<float> opacity ,
Key key = null,

alwaysIncludeSemantics: alwaysIncludeSemantics
);
}
public override void updateRenderObject(BuildContext context, RenderSliverAnimatedOpacity renderObject) {
renderObject = (RenderSliverAnimatedOpacity) renderObject;
((RenderSliverAnimatedOpacity) renderObject).opacity = opacity;
((RenderSliverAnimatedOpacity) renderObject).alwaysIncludeSemantics = alwaysIncludeSemantics;
public override void updateRenderObject(BuildContext context, RenderObject renderObject) {
renderObject = (RenderSliverAnimatedOpacity)renderObject;
((RenderSliverAnimatedOpacity)renderObject).opacity = opacity;
((RenderSliverAnimatedOpacity)renderObject).alwaysIncludeSemantics = alwaysIncludeSemantics;
}
public override void debugFillProperties(DiagnosticPropertiesBuilder properties) {

}
}*/
}
public class RelativeRectTween : Tween<RelativeRect> {
public RelativeRectTween(
RelativeRect begin = null,

72
com.unity.uiwidgets/Runtime/widgets/DiagnosticableTree.mixin.gen.cs


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Unity.UIWidgets.ui;
using UnityEngine;
namespace Unity.UIWidgets.foundation {
public class DiagnosticableTreeMixinChangeNotifier : ChangeNotifier, DiagnosticableTreeMixin {
protected DiagnosticableTreeMixinChangeNotifier() {
}
public virtual string toString( DiagnosticLevel minLevel = DiagnosticLevel.info ) {
return toDiagnosticsNode(style: DiagnosticsTreeStyle.singleLine).toString(minLevel: minLevel);
}
public virtual string toStringShallow(
string joiner = ", ",
DiagnosticLevel minLevel = DiagnosticLevel.debug
) {
if (foundation_.kReleaseMode) {
return toString();
}
string shallowString = "";
D.assert(() => {
var result = new StringBuilder();
result.Append(toString());
result.Append(joiner);
DiagnosticPropertiesBuilder builder = new DiagnosticPropertiesBuilder();
debugFillProperties(builder);
result.Append(string.Join(joiner,
builder.properties.Where(n => !n.isFiltered(minLevel)).Select(n => n.ToString()).ToArray())
);
shallowString = result.ToString();
return true;
});
return shallowString;
}
public virtual string toStringDeep(
string prefixLineOne = "",
string prefixOtherLines = null,
DiagnosticLevel minLevel = DiagnosticLevel.debug
) {
return toDiagnosticsNode().toStringDeep(prefixLineOne: prefixLineOne, prefixOtherLines: prefixOtherLines, minLevel: minLevel);
}
public virtual string toStringShort() {
return foundation_.describeIdentity(this);
}
public virtual DiagnosticsNode toDiagnosticsNode(
string name = null,
DiagnosticsTreeStyle style = DiagnosticsTreeStyle.sparse) {
return new DiagnosticableTreeNode(
name: name,
value: this,
style: style
);
}
public virtual List<DiagnosticsNode> debugDescribeChildren()
{
return new List<DiagnosticsNode>();
}
public virtual void debugFillProperties(DiagnosticPropertiesBuilder properties) { }
}
}

69
com.unity.uiwidgets/Runtime/widgets/DiagnosticableTree.mixin.njk


namespace Unity.UIWidgets.foundation {
{% macro DiagnosticableTreeMixin(with) %}
{% set className = 'DiagnosticableTreeMixin' + with %}
public class {{className}} : {{with}}, DiagnosticableTreeMixin {
protected {{className}}() {
}
public virtual string toString( DiagnosticLevel minLevel = DiagnosticLevel.info ) {
return toDiagnosticsNode(style: DiagnosticsTreeStyle.singleLine).toString(minLevel: minLevel);
}
public virtual string toStringShallow(
string joiner = ", ",
DiagnosticLevel minLevel = DiagnosticLevel.debug
) {
if (foundation_.kReleaseMode) {
return toString();
}
string shallowString = "";
D.assert(() => {
var result = new StringBuilder();
result.Append(toString());
result.Append(joiner);
DiagnosticPropertiesBuilder builder = new DiagnosticPropertiesBuilder();
debugFillProperties(builder);
result.Append(string.Join(joiner,
builder.properties.Where(n => !n.isFiltered(minLevel)).Select(n => n.ToString()).ToArray())
);
shallowString = result.ToString();
return true;
});
return shallowString;
}
public virtual string toStringDeep(
string prefixLineOne = "",
string prefixOtherLines = null,
DiagnosticLevel minLevel = DiagnosticLevel.debug
) {
return toDiagnosticsNode().toStringDeep(prefixLineOne: prefixLineOne, prefixOtherLines: prefixOtherLines, minLevel: minLevel);
}
public virtual string toStringShort() {
return foundation_.describeIdentity(this);
}
public virtual DiagnosticsNode toDiagnosticsNode(
string name = null,
DiagnosticsTreeStyle style = DiagnosticsTreeStyle.sparse) {
return new DiagnosticableTreeNode(
name: name,
value: this,
style: style
);
}
public virtual List<DiagnosticsNode> debugDescribeChildren()
{
return new List<DiagnosticsNode>();
}
public virtual void debugFillProperties(DiagnosticPropertiesBuilder properties) { }
}
{% endmacro %}
{{ DiagnosticableTreeMixin('ChangeNotifier') }}
}

310
com.unity.uiwidgets/Runtime/widgets/DirectionalFocusTraversalPolicy.mixin.njk


namespace Unity.UIWidgets.widgets {
{% macro DirectionalFocusTraversalPolicyMixin(with) %}
{% set className = 'DirectionalFocusTraversalPolicyMixin' + with %}
public class {{className}} : {{with}}, DirectionalFocusTraversalPolicyMixin {
protected {{className}}() {
}
public readonly Dictionary<FocusScopeNode, _DirectionalPolicyData> _policyData = new Dictionary<FocusScopeNode, _DirectionalPolicyData>();
public override void invalidateScopeData(FocusScopeNode node) {
base.invalidateScopeData(node);
_policyData.Remove(node);
}
public override void changedScope(FocusNode node = null, FocusScopeNode oldScope = null) {
base.changedScope(node: node, oldScope: oldScope);
if (oldScope != null) {
var delEntries = _policyData[oldScope]?.history?.Where((_DirectionalPolicyDataEntry entry)=> {
return entry.node == node;
});
foreach (var delEntry in delEntries) {
_policyData[oldScope]?.history?.Remove(delEntry);
}
}
}
public override FocusNode findFirstFocusInDirection(FocusNode currentNode, TraversalDirection direction) {
D.assert(direction != null);
D.assert(currentNode != null);
switch (direction) {
case TraversalDirection.up:
return _sortAndFindInitial(currentNode, vertical: true, first: false);
case TraversalDirection.down:
return _sortAndFindInitial(currentNode, vertical: true, first: true);
case TraversalDirection.left:
return _sortAndFindInitial(currentNode, vertical: false, first: false);
case TraversalDirection.right:
return _sortAndFindInitial(currentNode, vertical: false, first: true);
}
return null;
}
public FocusNode _sortAndFindInitial(FocusNode currentNode, bool vertical = false, bool first = false) {
IEnumerable<FocusNode> nodes = currentNode.nearestScope.traversalDescendants;
List<FocusNode> sorted = nodes.ToList();
FocusTravesalUtils.mergeSort<FocusNode>(sorted, compare: (FocusNode a, FocusNode b)=> {
if (vertical) {
if (first) {
return a.rect.top.CompareTo(b.rect.top);
} else {
return b.rect.bottom.CompareTo(a.rect.bottom);
}
} else {
if (first) {
return a.rect.left.CompareTo(b.rect.left);
} else {
return b.rect.right.CompareTo(a.rect.right);
}
}
});
if (sorted.isNotEmpty()) {
return sorted.First();
}
return null;
}
public IEnumerable<FocusNode> _sortAndFilterHorizontally(
TraversalDirection direction,
Rect target,
FocusNode nearestScope)
{
D.assert(direction == TraversalDirection.left || direction == TraversalDirection.right);
IEnumerable<FocusNode> nodes = nearestScope.traversalDescendants;
D.assert(!nodes.Contains(nearestScope));
List<FocusNode> sorted = nodes.ToList();
FocusTravesalUtils.mergeSort<FocusNode>(sorted, compare: (FocusNode a, FocusNode b) => a.rect.center.dx.CompareTo(b.rect.center.dx));
IEnumerable<FocusNode> result = new List<FocusNode>();
switch (direction) {
case TraversalDirection.left:
result = sorted.Where((FocusNode node) => node.rect != target && node.rect.center.dx <= target.left);
break;
case TraversalDirection.right:
result = sorted.Where((FocusNode node) => node.rect != target && node.rect.center.dx >= target.right);
break;
case TraversalDirection.up:
case TraversalDirection.down:
break;
}
return result;
}
public IEnumerable<FocusNode> _sortAndFilterVertically(
TraversalDirection direction,
Rect target,
IEnumerable<FocusNode> nodes)
{
List<FocusNode> sorted = nodes.ToList();
FocusTravesalUtils.mergeSort<FocusNode>(sorted, compare: (FocusNode a, FocusNode b) => a.rect.center.dy.CompareTo(b.rect.center.dy));
switch (direction) {
case TraversalDirection.up:
return sorted.Where((FocusNode node) => node.rect != target && node.rect.center.dy <= target.top);
case TraversalDirection.down:
return sorted.Where((FocusNode node) => node.rect != target && node.rect.center.dy >= target.bottom);
case TraversalDirection.left:
case TraversalDirection.right:
break;
}
D.assert(direction == TraversalDirection.up || direction == TraversalDirection.down);
return null;
}
public bool _popPolicyDataIfNeeded(TraversalDirection direction, FocusScopeNode nearestScope, FocusNode focusedChild) {
_DirectionalPolicyData policyData = _policyData[nearestScope];
if (policyData != null && policyData.history.isNotEmpty() && policyData.history.First().direction != direction) {
if (policyData.history.Last().node.parent == null) {
invalidateScopeData(nearestScope);
return false;
}
bool popOrInvalidate(TraversalDirection direction) {
FocusNode lastNode = policyData.history.removeLast().node;
if (Scrollable.of(lastNode.context) != Scrollable.of(FocusManagerUtils.primaryFocus.context)) {
invalidateScopeData(nearestScope);
return false;
}
ScrollPositionAlignmentPolicy alignmentPolicy = ScrollPositionAlignmentPolicy.explicitPolicy;
switch (direction) {
case TraversalDirection.up:
case TraversalDirection.left:
alignmentPolicy = ScrollPositionAlignmentPolicy.keepVisibleAtStart;
break;
case TraversalDirection.right:
case TraversalDirection.down:
alignmentPolicy = ScrollPositionAlignmentPolicy.keepVisibleAtEnd;
break;
}
FocusTravesalUtils._focusAndEnsureVisible(
lastNode,
alignmentPolicy: alignmentPolicy
);
return true;
}
switch (direction) {
case TraversalDirection.down:
case TraversalDirection.up:
switch (policyData.history.First().direction) {
case TraversalDirection.left:
case TraversalDirection.right:
invalidateScopeData(nearestScope);
break;
case TraversalDirection.up:
case TraversalDirection.down:
if (popOrInvalidate(direction)) {
return true;
}
break;
}
break;
case TraversalDirection.left:
case TraversalDirection.right:
switch (policyData.history.First().direction) {
case TraversalDirection.left:
case TraversalDirection.right:
if (popOrInvalidate(direction)) {
return true;
}
break;
case TraversalDirection.up:
case TraversalDirection.down:
invalidateScopeData(nearestScope);
break;
}
break;
}
}
if (policyData != null && policyData.history.isEmpty()) {
invalidateScopeData(nearestScope);
}
return false;
}
public void _pushPolicyData(TraversalDirection direction, FocusScopeNode nearestScope, FocusNode focusedChild) {
_DirectionalPolicyData policyData = _policyData[nearestScope];
if (policyData != null && !(policyData is _DirectionalPolicyData)) {
return;
}
_DirectionalPolicyDataEntry newEntry = new _DirectionalPolicyDataEntry(node: focusedChild, direction: direction);
if (policyData != null) {
policyData.history.Add(newEntry);
} else {
_policyData[nearestScope] = new _DirectionalPolicyData(history: new List<_DirectionalPolicyDataEntry>(){newEntry});
}
}
public override bool inDirection(FocusNode currentNode, TraversalDirection direction) {
FocusScopeNode nearestScope = currentNode.nearestScope;
FocusNode focusedChild = nearestScope.focusedChild;
if (focusedChild == null) {
FocusNode firstFocus = findFirstFocusInDirection(currentNode, direction) ?? currentNode;
switch (direction) {
case TraversalDirection.up:
case TraversalDirection.left:
FocusTravesalUtils._focusAndEnsureVisible(
firstFocus,
alignmentPolicy: ScrollPositionAlignmentPolicy.keepVisibleAtStart
);
break;
case TraversalDirection.right:
case TraversalDirection.down:
FocusTravesalUtils._focusAndEnsureVisible(
firstFocus,
alignmentPolicy: ScrollPositionAlignmentPolicy.keepVisibleAtEnd
);
break;
}
return true;
}
if (_popPolicyDataIfNeeded(direction, nearestScope, focusedChild)) {
return true;
}
FocusNode found = null;
ScrollableState focusedScrollable = Scrollable.of(focusedChild.context);
switch (direction) {
case TraversalDirection.down:
case TraversalDirection.up:
IEnumerable<FocusNode> eligibleNodes = _sortAndFilterVertically(
direction,
focusedChild.rect,
nearestScope.traversalDescendants
);
if (focusedScrollable != null && !focusedScrollable.position.atEdge()) {
IEnumerable<FocusNode> filteredEligibleNodes = eligibleNodes.Where((FocusNode node) => Scrollable.of(node.context) == focusedScrollable);
if (filteredEligibleNodes.Count() !=0) {
eligibleNodes = filteredEligibleNodes;
}
}
if (eligibleNodes.Count() == 0) {
break;
}
List<FocusNode> sorted = eligibleNodes.ToList();
if (direction == TraversalDirection.up) {
//sorted = sorted.reversed.toList();
sorted.Reverse();
sorted = sorted.ToList();
}
Rect band = Rect.fromLTRB(focusedChild.rect.left, float.NegativeInfinity, focusedChild.rect.right, float.PositiveInfinity);
IEnumerable<FocusNode> inBand = sorted.Where((FocusNode node) => !node.rect.intersect(band).isEmpty);
if (inBand.Count() !=0) {
found = inBand.First();
break;
}
FocusTravesalUtils.mergeSort<FocusNode>(sorted, compare: (FocusNode a, FocusNode b)=> {
return (a.rect.center.dx - focusedChild.rect.center.dx).abs().CompareTo((b.rect.center.dx - focusedChild.rect.center.dx).abs());
});
found = sorted.First();
break;
case TraversalDirection.right:
case TraversalDirection.left:
eligibleNodes = _sortAndFilterHorizontally(direction, focusedChild.rect, nearestScope);
if (focusedScrollable != null && !focusedScrollable.position.atEdge()) {
IEnumerable<FocusNode> filteredEligibleNodes = eligibleNodes.Where((FocusNode node) => Scrollable.of(node.context) == focusedScrollable);
if (filteredEligibleNodes.Count()!=0) {
eligibleNodes = filteredEligibleNodes;
}
}
if (eligibleNodes.Count() == 0) {
break;
}
sorted = eligibleNodes.ToList();
if (direction == TraversalDirection.left) {
sorted.Reverse();
sorted = sorted.ToList();
//sorted = sorted.reversed.toList();
}
band = Rect.fromLTRB(float.NegativeInfinity, focusedChild.rect.top, float.PositiveInfinity, focusedChild.rect.bottom);
inBand = sorted.Where((FocusNode node) => !node.rect.intersect(band).isEmpty);
if (inBand.Count()!=0) {
found = inBand.First();
break;
}
FocusTravesalUtils.mergeSort<FocusNode>(sorted, compare: (FocusNode a, FocusNode b) =>{
return (a.rect.center.dy - focusedChild.rect.center.dy).abs().CompareTo((b.rect.center.dy - focusedChild.rect.center.dy).abs());
});
found = sorted.First();
break;
}
if (found != null) {
_pushPolicyData(direction, nearestScope, focusedChild);
switch (direction) {
case TraversalDirection.up:
case TraversalDirection.left:
FocusTravesalUtils._focusAndEnsureVisible(
found,
alignmentPolicy: ScrollPositionAlignmentPolicy.keepVisibleAtStart
);
break;
case TraversalDirection.down:
case TraversalDirection.right:
FocusTravesalUtils._focusAndEnsureVisible(
found,
alignmentPolicy: ScrollPositionAlignmentPolicy.keepVisibleAtEnd
);
break;
}
return true;
}
return false;
}
public override IEnumerable<FocusNode> sortDescendants(IEnumerable<FocusNode> descendants) {
return null;
}
}
{% endmacro %}
{{ DirectionalFocusTraversalPolicyMixin('FocusTraversalPolicy') }}
}
正在加载...
取消
保存