From d2c0a6de37f0166a6a4a9bd1b1017ffcc8f545cc Mon Sep 17 00:00:00 2001 From: Richard Huang Date: Wed, 25 Jun 2014 18:33:38 +0100 Subject: [PATCH] Prevent fighting of setting scroll position property by ItemView and ScrollBar [problem] When ItemView is still scrolling, touch and drag the fast scroll bar, the fast scroll bar is not responsive for some time and ItemView scrolls to the wrong position sometimes. [cause] When scroll position property is being animated by ItemView, if something else (e.g. ScrollBar) tries to modify the scroll position property at the same time, there is a fighting of setting the same property between the two. [solution] Cancel scroll animation when it is in fast scroll mode. Change-Id: I3de03d7b21b929fe527b907e58464896b774c489 Signed-off-by: Adeel Kazmi --- .../controls/scroll-bar/scroll-bar-impl.cpp | 23 ++++++++------ .../scrollable/item-view/item-view-impl.cpp | 12 ++++++- .../controls/scrollable/item-view/item-view-impl.h | 6 ++++ .../controls/scrollable/scroll-connector-impl.cpp | 6 ++++ .../controls/scrollable/scroll-connector-impl.h | 23 ++++++++++++++ .../controls/scrollable/scroll-connector.cpp | 16 ++++++++++ .../controls/scrollable/scroll-connector.h | 37 ++++++++++++++++++---- 7 files changed, 105 insertions(+), 18 deletions(-) diff --git a/base/dali-toolkit/internal/controls/scroll-bar/scroll-bar-impl.cpp b/base/dali-toolkit/internal/controls/scroll-bar/scroll-bar-impl.cpp index 2a4db69..6298e7d 100755 --- a/base/dali-toolkit/internal/controls/scroll-bar/scroll-bar-impl.cpp +++ b/base/dali-toolkit/internal/controls/scroll-bar/scroll-bar-impl.cpp @@ -284,7 +284,7 @@ void ScrollBar::SetPositionNotifications( const std::vector& positions ) void ScrollBar::OnScrollPositionNotified(PropertyNotification& source) { // Emit the signal to notify the scroll position crossing - mScrollPositionNotifiedSignal.Emit(mScrollPositionObject.GetProperty( Toolkit::ScrollConnector::SCROLL_POSITION )); + mScrollPositionNotifiedSignal.Emit(mScrollConnector.GetScrollPosition()); } void ScrollBar::Show() @@ -318,13 +318,9 @@ void ScrollBar::Hide() bool ScrollBar::OnPanGestureProcessTick() { // Update the scroll position property. - mScrollPositionObject.SetProperty( Toolkit::ScrollConnector::SCROLL_POSITION, mCurrentScrollPosition ); - - Dali::Toolkit::ItemView itemView = Dali::Toolkit::ItemView::DownCast(Self().GetParent()); - if(itemView) + if( mScrollConnector ) { - // Refresh ItemView immediately when the scroll position is changed. - GetImpl(itemView).DoRefresh(mCurrentScrollPosition, false); // No need to cache extra items. + mScrollConnector.SetScrollPosition(mCurrentScrollPosition); } return true; @@ -332,8 +328,10 @@ bool ScrollBar::OnPanGestureProcessTick() void ScrollBar::OnPan( PanGesture gesture ) { - if(mScrollPositionObject) + if(mScrollConnector) { + Dali::Toolkit::ItemView itemView = Dali::Toolkit::ItemView::DownCast(Self().GetParent()); + switch(gesture.state) { case Gesture::Started: @@ -347,7 +345,7 @@ void ScrollBar::OnPan( PanGesture gesture ) } Show(); - mScrollStart = mScrollPositionObject.GetProperty( Toolkit::ScrollConnector::SCROLL_POSITION ); + mScrollStart = mScrollConnector.GetScrollPosition(); mGestureDisplacement = Vector3::ZERO; mIsPanning = true; @@ -377,11 +375,16 @@ void ScrollBar::OnPan( PanGesture gesture ) mTimer.Reset(); } + if(itemView) + { + // Refresh the ItemView cache with extra items + GetImpl(itemView).DoRefresh(mCurrentScrollPosition, true); + } + break; } } - Dali::Toolkit::ItemView itemView = Dali::Toolkit::ItemView::DownCast(Self().GetParent()); if(itemView) { // Disable automatic refresh in ItemView during fast scrolling diff --git a/base/dali-toolkit/internal/controls/scrollable/item-view/item-view-impl.cpp b/base/dali-toolkit/internal/controls/scrollable/item-view/item-view-impl.cpp index 14bd8fc..fdb1d88 100644 --- a/base/dali-toolkit/internal/controls/scrollable/item-view/item-view-impl.cpp +++ b/base/dali-toolkit/internal/controls/scrollable/item-view/item-view-impl.cpp @@ -433,6 +433,7 @@ void ItemView::OnInitialize() mScrollConnector = Dali::Toolkit::ScrollConnector::New(); mScrollPositionObject = mScrollConnector.GetScrollPositionObject(); + mScrollConnector.ScrollPositionChangedSignal().Connect( this, &ItemView::OnScrollPositionChanged ); mPropertyMinimumLayoutPosition = self.RegisterProperty(MINIMUM_LAYOUT_POSITION_PROPERTY_NAME, 0.0f); mPropertyPosition = self.RegisterProperty(POSITION_PROPERTY_NAME, 0.0f); @@ -502,7 +503,7 @@ ItemLayoutPtr ItemView::GetActiveLayout() const float ItemView::GetCurrentLayoutPosition(unsigned int itemId) const { - return mScrollPositionObject.GetProperty( ScrollConnector::SCROLL_POSITION ) + static_cast( itemId ); + return mScrollConnector.GetScrollPosition() + static_cast( itemId ); } void ItemView::ActivateLayout(unsigned int layoutIndex, const Vector3& targetSize, float durationSeconds) @@ -1836,6 +1837,15 @@ void ItemView::GetItemsRange(ItemRange& range) range.end = mItemPool.rbegin()->first + 1; } +void ItemView::OnScrollPositionChanged( float position ) +{ + // Cancel scroll animation to prevent any fighting of setting the scroll position property. + RemoveAnimation(mScrollAnimation); + + // Refresh the cache immediately when the scroll position is changed. + DoRefresh(position, false); // No need to cache extra items. +} + } // namespace Internal } // namespace Toolkit diff --git a/base/dali-toolkit/internal/controls/scrollable/item-view/item-view-impl.h b/base/dali-toolkit/internal/controls/scrollable/item-view/item-view-impl.h index 1f33626..442d760 100644 --- a/base/dali-toolkit/internal/controls/scrollable/item-view/item-view-impl.h +++ b/base/dali-toolkit/internal/controls/scrollable/item-view/item-view-impl.h @@ -548,6 +548,12 @@ private: */ void OnRefreshNotification(PropertyNotification& source); + /** + * This is called when scroll position has been changed by ScrollConnector::SetScrollPosition. + * @param[in] position The new scroll position + */ + void OnScrollPositionChanged( float position ); + private: ItemFactory& mItemFactory; diff --git a/base/dali-toolkit/internal/controls/scrollable/scroll-connector-impl.cpp b/base/dali-toolkit/internal/controls/scrollable/scroll-connector-impl.cpp index 659e67b..a84a419 100644 --- a/base/dali-toolkit/internal/controls/scrollable/scroll-connector-impl.cpp +++ b/base/dali-toolkit/internal/controls/scrollable/scroll-connector-impl.cpp @@ -47,6 +47,12 @@ void ScrollConnector::SetScrollDomain( float min, float max, float length ) mDomainChangedSignal.Emit( mMinLimit, mMaxLimit, mContentLength ); } +void ScrollConnector::SetScrollPosition( float position ) +{ + mScrollPositionObject.SetProperty( Toolkit::ScrollConnector::SCROLL_POSITION, position ); + mScrollPositionChangedSignal.Emit( position ); +} + ScrollConnector::ScrollConnector() : mMinLimit( 0.0f ), mMaxLimit( 0.0f ), diff --git a/base/dali-toolkit/internal/controls/scrollable/scroll-connector-impl.h b/base/dali-toolkit/internal/controls/scrollable/scroll-connector-impl.h index 45616f4..e9d8679 100644 --- a/base/dali-toolkit/internal/controls/scrollable/scroll-connector-impl.h +++ b/base/dali-toolkit/internal/controls/scrollable/scroll-connector-impl.h @@ -38,6 +38,7 @@ class ScrollConnector : public Dali::BaseObject public: typedef Toolkit::ScrollConnector::DomainChangedSignalType DomainChangedSignalType; + typedef Toolkit::ScrollConnector::ScrollPositionChangedSignalType ScrollPositionChangedSignalType; static const Property::Index SCROLL_POSITION; static const Property::Index OVERSHOOT; @@ -78,6 +79,27 @@ public: } /** + * @copydoc Toolkit::ScrollConnector::SetScrollPosition() + */ + void SetScrollPosition( float position ); + + /** + * @copydoc Toolkit::ScrollConnector::GetScrollPosition() + */ + float GetScrollPosition() const + { + return mScrollPositionObject.GetProperty( Toolkit::ScrollConnector::SCROLL_POSITION ); + } + + /** + * Signal emitted after the SetScrollPosition() method has been called. + */ + ScrollPositionChangedSignalType& ScrollPositionChangedSignal() + { + return mScrollPositionChangedSignal; + } + + /** * Signal emitted after the SetScrollDomain() method has been called. */ DomainChangedSignalType& DomainChangedSignal() @@ -117,6 +139,7 @@ private: Constrainable mScrollPositionObject; DomainChangedSignalType mDomainChangedSignal; + ScrollPositionChangedSignalType mScrollPositionChangedSignal; float mMinLimit; float mMaxLimit; diff --git a/base/dali-toolkit/public-api/controls/scrollable/scroll-connector.cpp b/base/dali-toolkit/public-api/controls/scrollable/scroll-connector.cpp index 8827738..c89dfab 100644 --- a/base/dali-toolkit/public-api/controls/scrollable/scroll-connector.cpp +++ b/base/dali-toolkit/public-api/controls/scrollable/scroll-connector.cpp @@ -33,6 +33,7 @@ const Property::Index ScrollConnector::SCROLL_POSITION = Internal::ScrollConnect const Property::Index ScrollConnector::OVERSHOOT = Internal::ScrollConnector::OVERSHOOT; const char* const ScrollConnector::DOMAIN_CHANGED_SIGNAL_NAME = "domain-changed"; +const char* const ScrollConnector::SCROLL_POSITION_CHANGED_SIGNAL_NAME = "scroll-position-changed"; ScrollConnector ScrollConnector::New() { @@ -82,6 +83,21 @@ Constrainable ScrollConnector::GetScrollPositionObject() const return GetImpl(*this).GetScrollPositionObject(); } +void ScrollConnector::SetScrollPosition( float position ) +{ + GetImpl(*this).SetScrollPosition( position ); +} + +float ScrollConnector::GetScrollPosition() const +{ + return GetImpl(*this).GetScrollPosition(); +} + +ScrollConnector::ScrollPositionChangedSignalType& ScrollConnector::ScrollPositionChangedSignal() +{ + return GetImpl(*this).ScrollPositionChangedSignal(); +} + ScrollConnector::DomainChangedSignalType& ScrollConnector::DomainChangedSignal() { return GetImpl(*this).DomainChangedSignal(); diff --git a/capi/dali-toolkit/public-api/controls/scrollable/scroll-connector.h b/capi/dali-toolkit/public-api/controls/scrollable/scroll-connector.h index 6960b4b..1e64e7e 100644 --- a/capi/dali-toolkit/public-api/controls/scrollable/scroll-connector.h +++ b/capi/dali-toolkit/public-api/controls/scrollable/scroll-connector.h @@ -70,6 +70,9 @@ public: static const char* const DOMAIN_CHANGED_SIGNAL_NAME; ///< "domain-changed" signal name typedef SignalV2< void ( float min, float max, float size ) > DomainChangedSignalType; + static const char* const SCROLL_POSITION_CHANGED_SIGNAL_NAME; ///< "scroll-position-changed" signal name + typedef SignalV2< void ( float position ) > ScrollPositionChangedSignalType; + /** * Create a ScrollConnector. * @return A handle to a newly allocated ScrollConnector. @@ -100,13 +103,13 @@ public: ~ScrollConnector(); /** - * Downcast a BaseHandle to ScrollConnector handle. + * @brief Downcast a BaseHandle to ScrollConnector handle. * @return A handle to a ScrollConnector or an empty handle. */ static ScrollConnector DownCast( BaseHandle handle ); /** - * Set the scroll domain, corresponding to the start & end position, and size of the scrollable content in actor coordinates. + * @brief Set the scroll domain, corresponding to the start & end position, and size of the scrollable content in actor coordinates. * @param[in] min The minimum scroll position limit. * @param[in] max The maximum scroll position limit. * @param[in] length The length of the scrollable content in actor coordinates. @@ -114,30 +117,50 @@ public: void SetScrollDomain( float min, float max, float length ); /** - * Retrieve the min limit. + * @brief Retrieve the min limit. * @return The minimum value. */ float GetMinLimit() const; /** - * Retrieve the max limit. + * @brief Retrieve the max limit. * @return The maximum value. */ float GetMaxLimit() const; /** - * Retrieve the length of the scrollable content in actor coordinates. + * @brief Retrieve the length of the scrollable content in actor coordinates. * @return The length of the scrollable content. */ float GetContentLength() const; /** - * Signal emitted after the SetScrollDomain() method has been called. + * @brief Set the scroll position. + * + * This will set the "scroll-position" property and emit the ScrollPositionChanged signal. + * + * @param[in] position The scroll position. + */ + void SetScrollPosition( float position ); + + /** + * @brief Retrieve the scroll position. + * @return The scroll position. + */ + float GetScrollPosition() const; + + /** + * @brief Signal emitted after the SetScrollPosition() method has been called. + */ + ScrollConnector::ScrollPositionChangedSignalType& ScrollPositionChangedSignal(); + + /** + * @brief Signal emitted after the SetScrollDomain() method has been called. */ ScrollConnector::DomainChangedSignalType& DomainChangedSignal(); /** - * Retrieve the object which provides the "scroll-position" property. + * @brief Retrieve the object which provides the "scroll-position" property. * @return The scroll-position object. */ Constrainable GetScrollPositionObject() const; -- 2.7.4