-//
-// Copyright (c) 2014 Samsung Electronics Co., Ltd.
-//
-// Licensed under the Flora License, Version 1.0 (the License);
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://floralicense.org/license/
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an AS IS BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
// INTERNAL INCLUDES
#include <dali/public-api/events/mouse-wheel-event.h>
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);
mRotationDelta(0.0f),
mScrollPreRotation(0.0f),
mScrollPostRotation(0.0f),
- mTouchDownReceived(false),
+ mTouchDownTimeoutReached(false),
mActorAutoSnapEnabled(false),
mAutoResizeContainerEnabled(false),
mWrapMode(false),
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)
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 )
// 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 )
FinishTransform();
}
}
- mTouchDownReceived = false;
+ mTouchDownTimeoutReached = false;
mScrollInterrupted = false;
}
// we continue and combine the effects of the gesture instead of reseting.
if(mGestureStackDepth++==0)
{
+ StopTouchDownTimer();
StopAnimation();
mPanDelta = Vector3::ZERO;
mScaleDelta = Vector3::ONE;
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<float>( mPropertyX,
- LocalSource( mPropertyPosition ),
- Source( self, mPropertyPanning ),
- InternalXConstraint );
- mScrollMainInternalXConstraint = self.ApplyConstraint(constraint);
+ if( ! mScrollMainInternalXConstraint )
+ {
+ Constraint constraint = Constraint::New<float>( mPropertyX,
+ LocalSource( mPropertyPosition ),
+ Source( self, mPropertyPanning ),
+ InternalXConstraint );
+ mScrollMainInternalXConstraint = self.ApplyConstraint( constraint );
+ }
+ if( ! mScrollMainInternalYConstraint )
+ {
+ Constraint constraint = Constraint::New<float>( mPropertyY,
+ LocalSource( mPropertyPosition ),
+ Source( self, mPropertyPanning ),
+ InternalYConstraint );
+ mScrollMainInternalYConstraint = self.ApplyConstraint( constraint );
+ }
- constraint = Constraint::New<float>( 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;
// 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;
}