X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=blobdiff_plain;f=base%2Fdali-toolkit%2Finternal%2Fcontrols%2Fscrollable%2Fscroll-view%2Fscroll-view-impl.cpp;h=dca4aabcbd41c1875e2dce702026781a7a476957;hp=395a3cb8771adfa766ce41c4323a512b327387e8;hb=45e0dfb55809cde34b3913b0b16f18e79c14775c;hpb=30f6ca1e541089b19f2b349a8a12d8a5bcaf2f9e diff --git a/base/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-impl.cpp b/base/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-impl.cpp index 395a3cb..dca4aab 100644 --- a/base/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-impl.cpp +++ b/base/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-impl.cpp @@ -44,7 +44,8 @@ const float AUTOLOCK_AXIS_MINIMUM_DISTANCE2 = 100.0f; const float FLICK_ORTHO_ANGLE_RANGE = 60.0f; ///< degrees. (if >45, then supports diagonal flicking) const unsigned int MAXIMUM_NUMBER_OF_VALUES = 5; ///< Number of values to use for weighted pan calculation. const Vector2 DEFAULT_MOUSE_WHEEL_SCROLL_DISTANCE_STEP_PROPORTION = Vector2(0.17f, 0.1f); ///< The step of horizontal scroll distance in the proportion of stage size for each mouse wheel event received. -const unsigned long MINIMUM_TIME_BETWEEN_DOWN_AND_UP_FOR_RESET( 150u ); +const unsigned long MINIMUM_TIME_BETWEEN_DOWN_AND_UP_FOR_RESET( 150u ); ///< Determines whether velocity is reset after tap interrupts snap animation +const float TOUCH_DOWN_TIMER_INTERVAL = 100.0f; ///< After this time interval with touch-down, the snap animation will be interrupted (if no gesture has started). // predefined effect values const Vector3 ANGLE_CAROUSEL_ROTATE(Math::PI * 0.5f, Math::PI * 0.5f, 0.0f); @@ -518,7 +519,7 @@ ScrollView::ScrollView() mRotationDelta(0.0f), mScrollPreRotation(0.0f), mScrollPostRotation(0.0f), - mTouchDownReceived(false), + mTouchDownTimeoutReached(false), mActorAutoSnapEnabled(false), mAutoResizeContainerEnabled(false), mWrapMode(false), @@ -540,7 +541,8 @@ ScrollView::ScrollView() mAxisAutoLockGradient(Toolkit::ScrollView::DEFAULT_AXIS_AUTO_LOCK_GRADIENT), mFrictionCoefficient(Toolkit::ScrollView::DEFAULT_FRICTION_COEFFICIENT), mFlickSpeedCoefficient(Toolkit::ScrollView::DEFAULT_FLICK_SPEED_COEFFICIENT), - mMaxFlickSpeed(Toolkit::ScrollView::DEFAULT_MAX_FLICK_SPEED) + mMaxFlickSpeed(Toolkit::ScrollView::DEFAULT_MAX_FLICK_SPEED), + mInAccessibilityPan(false) { SetRequiresMouseWheelEvents(true); } @@ -1357,21 +1359,32 @@ bool ScrollView::SnapWithVelocity(Vector2 velocity) const float orthoAngleRange = FLICK_ORTHO_ANGLE_RANGE * M_PI / 180.0f; const float flickSpeedThreshold2 = FLICK_SPEED_THRESHOLD*FLICK_SPEED_THRESHOLD; + Vector3 positionSnap = mScrollPostPosition; + // Flick logic X Axis if(mRulerX->IsEnabled()) { horizontal = All; - if(speed2 > flickSpeedThreshold2) // exceeds flick threshold + if( speed2 > flickSpeedThreshold2 || // exceeds flick threshold + mInAccessibilityPan ) // With AccessibilityPan its easier to move between snap positions { if((angle >= -orthoAngleRange) && (angle < orthoAngleRange)) // Swiping East { biasX = 0.0f, horizontal = Left; + + // This guards against an error where no movement occurs, due to the flick finishing + // before the update-thread has advanced mScrollPostPosition past the the previous snap point. + positionSnap.x += 1.0f; } else if((angle >= M_PI-orthoAngleRange) || (angle < -M_PI+orthoAngleRange)) // Swiping West { biasX = 1.0f, horizontal = Right; + + // This guards against an error where no movement occurs, due to the flick finishing + // before the update-thread has advanced mScrollPostPosition past the the previous snap point. + positionSnap.x -= 1.0f; } } } @@ -1382,7 +1395,8 @@ bool ScrollView::SnapWithVelocity(Vector2 velocity) { vertical = All; - if(speed2 > flickSpeedThreshold2) // exceeds flick threshold + if( speed2 > flickSpeedThreshold2 || // exceeds flick threshold + mInAccessibilityPan ) // With AccessibilityPan its easier to move between snap positions { if((angle >= M_PI_2-orthoAngleRange) && (angle < M_PI_2+orthoAngleRange)) // Swiping South { @@ -1406,8 +1420,7 @@ bool ScrollView::SnapWithVelocity(Vector2 velocity) alphaFunction = mFlickAlphaFunction; } - // Position Snap //////////////////////////////////////////////////////////// - Vector3 positionSnap = mScrollPostPosition; + // Calculate next positionSnap //////////////////////////////////////////////////////////// if(mActorAutoSnapEnabled) { @@ -1866,6 +1879,49 @@ void ScrollView::OnChildRemove(Actor& child) UnbindActor(child); } +void ScrollView::StartTouchDownTimer() +{ + if ( !mTouchDownTimer ) + { + mTouchDownTimer = Timer::New( TOUCH_DOWN_TIMER_INTERVAL ); + mTouchDownTimer.TickSignal().Connect( this, &ScrollView::OnTouchDownTimeout ); + } + + mTouchDownTimer.Start(); +} + +void ScrollView::StopTouchDownTimer() +{ + if ( mTouchDownTimer ) + { + mTouchDownTimer.Stop(); + } +} + +bool ScrollView::OnTouchDownTimeout() +{ + mTouchDownTimeoutReached = true; + + if( mSnapAnimation || mSnapXAnimation || mSnapYAnimation || mSnapOvershootAnimation ) + { + mScrollInterrupted = true; + StopAnimation(); + } + + if(mScrolling) // are we interrupting a current scroll? + { + // reset domain offset as scrolling from original plane. + mDomainOffset = Vector3::ZERO; + Self().SetProperty(mPropertyDomainOffset, Vector3::ZERO); + + mScrolling = false; + Vector3 currentScrollPosition = GetCurrentScrollPosition(); + mScrollCompletedSignalV2.Emit( currentScrollPosition ); + } + + return false; +} + bool ScrollView::OnTouchEvent(const TouchEvent& event) { if(!mSensitive) @@ -1882,33 +1938,23 @@ bool ScrollView::OnTouchEvent(const TouchEvent& event) if (event.GetPoint(0).state == TouchPoint::Down) { - mTouchDownTime = event.time; - mTouchDownReceived = true; - mTouchDownPosition = event.GetPoint(0).local; - - if( mSnapAnimation || mSnapXAnimation || mSnapYAnimation || mSnapOvershootAnimation ) - { - mScrollInterrupted = true; - StopAnimation(); - } - - if(mScrolling) // are we interrupting a current scroll? + if(mGestureStackDepth==0) { - // reset domain offset as scrolling from original plane. - mDomainOffset = Vector3::ZERO; - Self().SetProperty(mPropertyDomainOffset, Vector3::ZERO); + mTouchDownTime = event.time; - mScrolling = false; - Vector3 currentScrollPosition = GetCurrentScrollPosition(); - mScrollCompletedSignalV2.Emit( currentScrollPosition ); + // This allows time for a pan-gesture to start, to avoid breaking snap-animation behavior with fast flicks. + // If touch-down does not become a pan (after timeout interval), then snap-animation can be interrupted. + StartTouchDownTimer(); } } else if(event.GetPoint(0).state == TouchPoint::Up) { + StopTouchDownTimer(); + // if the user touches and releases without enough movement to go // into a gesture state, then we should snap to nearest point. // otherwise our scroll could be stopped (interrupted) half way through an animation. - if(mGestureStackDepth==0 && mTouchDownReceived) + if(mGestureStackDepth==0 && mTouchDownTimeoutReached) { unsigned timeDelta( event.time - mTouchDownTime ); if ( timeDelta >= MINIMUM_TIME_BETWEEN_DOWN_AND_UP_FOR_RESET ) @@ -1916,11 +1962,6 @@ bool ScrollView::OnTouchEvent(const TouchEvent& event) // Reset the velocity only if down was received a while ago mLastVelocity = Vector2( 0.0f, 0.0f ); } - else - { - Vector2 positionDelta( mTouchDownPosition - event.GetPoint(0).local ); - mLastVelocity = positionDelta / timeDelta; - } // Only finish the transform if scrolling was interrupted on down or if we are scrolling if ( mSnapAnimation || mSnapXAnimation || mSnapYAnimation || mSnapOvershootAnimation || mScrollInterrupted || mScrolling ) @@ -1928,7 +1969,7 @@ bool ScrollView::OnTouchEvent(const TouchEvent& event) FinishTransform(); } } - mTouchDownReceived = false; + mTouchDownTimeoutReached = false; mScrollInterrupted = false; } @@ -2046,6 +2087,7 @@ void ScrollView::GestureStarted() // we continue and combine the effects of the gesture instead of reseting. if(mGestureStackDepth++==0) { + StopTouchDownTimer(); StopAnimation(); mPanDelta = Vector3::ZERO; mScaleDelta = Vector3::ONE; @@ -2131,17 +2173,23 @@ void ScrollView::OnPan(PanGesture gesture) self.SetProperty( mPropertyScrollStartPagePosition, GetCurrentScrollPosition() ); // Update property: X & Y = Position (only when in panning mode - in snapping mode, X & Y are animated). - Constraint constraint = Constraint::New( mPropertyX, - LocalSource( mPropertyPosition ), - Source( self, mPropertyPanning ), - InternalXConstraint ); - mScrollMainInternalXConstraint = self.ApplyConstraint(constraint); + if( ! mScrollMainInternalXConstraint ) + { + Constraint constraint = Constraint::New( mPropertyX, + LocalSource( mPropertyPosition ), + Source( self, mPropertyPanning ), + InternalXConstraint ); + mScrollMainInternalXConstraint = self.ApplyConstraint( constraint ); + } + if( ! mScrollMainInternalYConstraint ) + { + Constraint constraint = Constraint::New( mPropertyY, + LocalSource( mPropertyPosition ), + Source( self, mPropertyPanning ), + InternalYConstraint ); + mScrollMainInternalYConstraint = self.ApplyConstraint( constraint ); + } - constraint = Constraint::New( mPropertyY, - LocalSource( mPropertyPosition ), - Source( self, mPropertyPanning ), - InternalYConstraint ); - mScrollMainInternalYConstraint = self.ApplyConstraint(constraint); // When panning we want to make sure overshoot values are affected by pre position and post position SetOvershootConstraintsEnabled(true); break; @@ -2162,6 +2210,8 @@ void ScrollView::OnPan(PanGesture gesture) // Remove X & Y position constraints as they are not required when we are not panning. self.RemoveConstraint(mScrollMainInternalXConstraint); self.RemoveConstraint(mScrollMainInternalYConstraint); + mScrollMainInternalXConstraint.Reset(); + mScrollMainInternalYConstraint.Reset(); break; } @@ -2276,7 +2326,11 @@ Vector3 ScrollView::GetOvershoot(Vector3& position) const bool ScrollView::OnAccessibilityPan(PanGesture gesture) { + // Keep track of whether this is an AccessibilityPan + mInAccessibilityPan = true; OnPan(gesture); + mInAccessibilityPan = false; + return true; }