public static FocusTraversalPolicy of(BuildContext context, bool nullOk = false) { D.assert(context != null); _FocusTraversalGroupMarker inherited = context?.dependOnInheritedWidgetOfExactType <_FocusTraversalGroupMarker>(); D.assert(() => { if (nullOk) { return(true); } if (inherited == null) { throw new UIWidgetsError( "Unable to find a FocusTraversalGroup widget in the context.\n" + "FocusTraversalGroup.of() was called with a context that does not contain a " + "FocusTraversalGroup.\n" + "No FocusTraversalGroup ancestor could be found starting from the context that was " + "passed to FocusTraversalGroup.of(). This can happen because there is not a " + "WidgetsApp or MaterialApp widget (those widgets introduce a FocusTraversalGroup), " + "or it can happen if the context comes from a widget above those widgets.\n" + "The context used was:\n" + $" {context}" ); } return(true); }); return(inherited?.policy); }
public _FocusTraversalGroupInfo( _FocusTraversalGroupMarker marker, FocusTraversalPolicy defaultPolicy = null, List <FocusNode> members = null ) { groupNode = marker?.focusNode; policy = marker?.policy ?? defaultPolicy ?? new ReadingOrderTraversalPolicy(); this.members = members ?? new List <FocusNode>(); }
public List <FocusNode> _sortAllDescendants(FocusScopeNode scope) { D.assert(scope != null); _FocusTraversalGroupMarker scopeGroupMarker = _getMarker(scope.context); 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); FocusNode groupNode = groupMarker?.focusNode; if (node == groupNode) { BuildContext parentContext = FocusTravesalUtils._getAncestor(groupNode.context, count: 2); _FocusTraversalGroupMarker parentMarker = _getMarker(parentContext); FocusNode parentNode = parentMarker?.focusNode; groups[groupNode] = groups.getOrDefault(parentNode) ?? new _FocusTraversalGroupInfo(parentMarker, members: new List <FocusNode>(), defaultPolicy: defaultPolicy); D.assert(!groups[parentNode].members.Contains(node)); groups[parentNode].members.Add(groupNode); continue; } if (node.canRequestFocus && !node.skipTraversal) { 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); } } HashSet <FocusNode> groupKeys = new HashSet <FocusNode>(groups.Keys); foreach (FocusNode key in groups.Keys) { List <FocusNode> sortedMembers = groups.getOrDefault(key).policy.sortDescendants(groups.getOrDefault(key).members).ToList(); groups[key].members.Clear(); groups[key].members.AddRange(sortedMembers); } List <FocusNode> sortedDescendants = new List <FocusNode>(); void visitGroups(_FocusTraversalGroupInfo info) { foreach (FocusNode node in info.members) { if (groupKeys.Contains(node)) { visitGroups(groups[node]); } else { sortedDescendants.Add(node); } } } visitGroups(groups[scopeGroupMarker?.focusNode]); D.assert( FocusTravesalUtils.difference(new HashSet <FocusNode>(sortedDescendants), (new HashSet <FocusNode>(scope.traversalDescendants))).isEmpty(), () => $"sorted descendants contains more nodes than it should: ({FocusTravesalUtils.difference(new HashSet<FocusNode>(sortedDescendants),(new HashSet<FocusNode>(scope.traversalDescendants)))})" ); D.assert( FocusTravesalUtils.difference(new HashSet <FocusNode>(scope.traversalDescendants), new HashSet <FocusNode>(sortedDescendants)).isEmpty(), () => $"sorted descendants are missing some nodes: ({FocusTravesalUtils.difference(new HashSet<FocusNode>(scope.traversalDescendants),new HashSet<FocusNode>(sortedDescendants))})" ); return(sortedDescendants); }