Example #1
0
        float _calculateScrollIncrement(ScrollableState state, ScrollIncrementType type = ScrollIncrementType.line)
        {
            D.assert(state.position != null);
            D.assert(state.position.havePixels);
            D.assert(state.widget.physics == null || state.widget.physics.shouldAcceptUserOffset(state.position));

            if (state.widget.incrementCalculator != null)
            {
                return(state.widget.incrementCalculator(
                           new ScrollIncrementDetails(
                               type: type,
                               metrics: state.position
                               )
                           ));
            }

            switch (type)
            {
            case ScrollIncrementType.line:
                return(50.0f);

            case ScrollIncrementType.page:
                return(0.8f * state.position.viewportDimension);
            }

            return(0.0f);
        }
Example #2
0
 internal _ScrollableScope(
     Key key = null,
     ScrollableState scrollable = null,
     ScrollPosition position    = null,
     Widget child = null
     ) : base(key: key, child: child)
 {
     D.assert(scrollable != null);
     D.assert(child != null);
     this.scrollable = scrollable;
     this.position   = position;
 }
Example #3
0
        public static Future ensureVisible(
            BuildContext context,
            float alignment   = 0.0f,
            TimeSpan?duration = null,
            Curve curve       = null,
            ScrollPositionAlignmentPolicy alignmentPolicy = ScrollPositionAlignmentPolicy.explicitPolicy
            )
        {
            duration = duration ?? TimeSpan.Zero;
            curve    = curve ?? Curves.ease;
            List <Future> futures = new List <Future>();

            ScrollableState scrollable = of(context);

            while (scrollable != null)
            {
                futures.Add(scrollable.position.ensureVisible(
                                context.findRenderObject(),
                                alignment: alignment,
                                duration: duration,
                                curve: curve,
                                alignmentPolicy: alignmentPolicy
                                ));
                context    = scrollable.context;
                scrollable = of(context);
            }

            if (futures.isEmpty() || duration == TimeSpan.Zero)
            {
                return(Future.value());
            }

            if (futures.Count == 1)
            {
                return(futures.Single());
            }

            return(Future.wait <object>(futures));
        }
Example #4
0
        public override void invoke(FocusNode node, Intent intent)
        {
            ScrollableState state = Scrollable.of(node.context);

            D.assert(state != null, () => "ScrollAction was invoked on a context that has no scrollable parent");
            D.assert(state.position.havePixels, () => "Scrollable must be laid out before it can be scrolled via a ScrollAction");
            if (state.widget.physics != null && !state.widget.physics.shouldAcceptUserOffset(state.position))
            {
                return;
            }
            float increment = _getIncrement(state, intent as ScrollIntent);

            if (increment == 0.0f)
            {
                return;
            }
            state.position.moveTo(
                state.position.pixels + increment,
                duration: TimeSpan.FromMilliseconds(100),
                curve: Curves.easeInOut
                );
        }
Example #5
0
        public static IPromise ensureVisible(BuildContext context,
                                             float alignment   = 0.0f,
                                             TimeSpan?duration = null,
                                             Curve curve       = null
                                             )
        {
            duration = duration ?? TimeSpan.Zero;
            curve    = curve ?? Curves.ease;
            List <IPromise> futures = new List <IPromise>();

            ScrollableState scrollable = of(context);

            while (scrollable != null)
            {
                futures.Add(scrollable.position.ensureVisible(
                                context.findRenderObject(),
                                alignment: alignment,
                                duration: duration,
                                curve: curve
                                ));
                context    = scrollable.context;
                scrollable = of(context);
            }

            if (futures.isEmpty() || duration == TimeSpan.Zero)
            {
                return(Promise.Resolved());
            }

            if (futures.Count == 1)
            {
                return(futures.Single());
            }

            return(Promise.All(futures));
        }
Example #6
0
        float _getIncrement(ScrollableState state, ScrollIntent intent)
        {
            float increment = _calculateScrollIncrement(state, type: intent.type);

            switch (intent.direction)
            {
            case AxisDirection.down:
                switch (state.axisDirection)
                {
                case AxisDirection.up:
                    return(-increment);

                case AxisDirection.down:
                    return(increment);

                case AxisDirection.right:
                case AxisDirection.left:
                    return(0.0f);
                }
                break;

            case AxisDirection.up:
                switch (state.axisDirection)
                {
                case AxisDirection.up:
                    return(increment);

                case AxisDirection.down:
                    return(-increment);

                case AxisDirection.right:
                case AxisDirection.left:
                    return(0.0f);
                }
                break;

            case AxisDirection.left:
                switch (state.axisDirection)
                {
                case AxisDirection.right:
                    return(-increment);

                case AxisDirection.left:
                    return(increment);

                case AxisDirection.up:
                case AxisDirection.down:
                    return(0.0f);
                }
                break;

            case AxisDirection.right:
                switch (state.axisDirection)
                {
                case AxisDirection.right:
                    return(increment);

                case AxisDirection.left:
                    return(-increment);

                case AxisDirection.up:
                case AxisDirection.down:
                    return(0.0f);
                }
                break;
            }
            return(0.0f);
        }
Example #7
0
        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 = LinqUtils <FocusNode> .WhereList(eligibleNodes, ((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 = LinqUtils <FocusNode> .WhereList(sorted, ((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 = LinqUtils <FocusNode> .WhereList(eligibleNodes, ((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 = LinqUtils <FocusNode> .WhereList(sorted, ((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);
        }