Exemple #1
0
        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(LinqUtils <FocusNode, _OrderedFocusInfo> .SelectList(ordered, ((_OrderedFocusInfo info) => info.node)).Concat(unordered));
        }
Exemple #2
0
 public FocusTraversalGroup(
     Key key = null,
     FocusTraversalPolicy policy = null,
     Widget child = null
     ) : base(key: key)
 {
     this.policy = policy ?? new ReadingOrderTraversalPolicy();
     this.child  = child;
 }
Exemple #3
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>();
 }
Exemple #4
0
 public _FocusTraversalGroupMarker(
     FocusTraversalPolicy policy = null,
     FocusNode focusNode         = null,
     Widget child = null
     )  : base(child: child)
 {
     D.assert(policy != null);
     D.assert(focusNode != null);
     this.policy    = policy;
     this.focusNode = focusNode;
 }
Exemple #5
0
 public OrderedTraversalPolicy(FocusTraversalPolicy secondary)
 {
     this.secondary = secondary;
 }
Exemple #6
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);
        }