From 944f97684fd438a181d0a230b86ca2bb32e5a5c2 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Fri, 27 Nov 2015 19:57:50 +0100 Subject: [PATCH] Make Carousel transitions more intelligent. In the face of multiple rapid changes. Fixes #212. --- .../Presenters/CarouselPresenter.cs | 80 +++++++++++++------ 1 file changed, 56 insertions(+), 24 deletions(-) diff --git a/src/Perspex.Controls/Presenters/CarouselPresenter.cs b/src/Perspex.Controls/Presenters/CarouselPresenter.cs index 7af2416b9a..e130936d29 100644 --- a/src/Perspex.Controls/Presenters/CarouselPresenter.cs +++ b/src/Perspex.Controls/Presenters/CarouselPresenter.cs @@ -55,6 +55,8 @@ namespace Perspex.Controls.Presenters private int _selectedIndex = -1; private bool _createdPanel; private IItemContainerGenerator _generator; + private Task _currentTransition; + private int _queuedTransitionIndex = -1; /// /// Initializes static members of the class. @@ -187,35 +189,39 @@ namespace Perspex.Controls.Presenters /// A task tracking the animation. private async Task MoveToPage(int fromIndex, int toIndex) { - var generator = ItemContainerGenerator; - IControl from = null; - IControl to = null; - - if (fromIndex != -1) + if (fromIndex != toIndex) { - from = generator.ContainerFromIndex(fromIndex); - } + var generator = ItemContainerGenerator; + IControl from = null; + IControl to = null; - if (toIndex != -1) - { - var item = Items.Cast().ElementAt(toIndex); - to = generator.Materialize(toIndex, new[] { item }, MemberSelector).FirstOrDefault(); + if (fromIndex != -1) + { + from = generator.ContainerFromIndex(fromIndex); + } - if (to != null) + if (toIndex != -1) { - Panel.Children.Add(to); + var item = Items.Cast().ElementAt(toIndex); + to = generator.ContainerFromIndex(toIndex) ?? + generator.Materialize(toIndex, new[] { item }, MemberSelector).FirstOrDefault(); + + if (to != null) + { + Panel.Children.Add(to); + } } - } - if (Transition != null && (from != null || to != null)) - { - await Transition.Start((Visual)from, (Visual)to, fromIndex < toIndex); - } + if (Transition != null && (from != null || to != null)) + { + await Transition.Start((Visual)from, (Visual)to, fromIndex < toIndex); + } - if (from != null) - { - Panel.Children.Remove(from); - generator.Dematerialize(fromIndex, 1); + if (from != null) + { + Panel.Children.Remove(from); + generator.Dematerialize(fromIndex, 1); + } } } @@ -223,11 +229,37 @@ namespace Perspex.Controls.Presenters /// Called when the property changes. /// /// The event args. - private void SelectedIndexChanged(PerspexPropertyChangedEventArgs e) + private async void SelectedIndexChanged(PerspexPropertyChangedEventArgs e) { if (Panel != null) { - var task = MoveToPage((int)e.OldValue, (int)e.NewValue); + if (_currentTransition == null) + { + int fromIndex = (int)e.OldValue; + int toIndex = (int)e.NewValue; + + for (;;) + { + _currentTransition = MoveToPage(fromIndex, toIndex); + await _currentTransition; + + if (_queuedTransitionIndex != -1) + { + fromIndex = toIndex; + toIndex = _queuedTransitionIndex; + _queuedTransitionIndex = -1; + } + else + { + _currentTransition = null; + break; + } + } + } + else + { + _queuedTransitionIndex = (int)e.NewValue; + } } } }