示例#1
0
        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);
        }
示例#2
0
 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>();
 }
示例#3
0
        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);
        }