const float TOUCH_DOWN_TIMER_INTERVAL = 100.0f;
const float DEFAULT_SCROLL_UPDATE_DISTANCE( 30.0f ); ///< Default distance to travel in pixels for scroll update signal
-const std::string INTERNAL_MAX_POSITION_PROPERTY_NAME( "internal-max-position" );
+const std::string INTERNAL_MAX_POSITION_PROPERTY_NAME( "internalMaxPosition" );
// Helpers ////////////////////////////////////////////////////////////////////////////////////////
// Setup properties, signals and actions using the type-registry.
DALI_TYPE_REGISTRATION_BEGIN( Toolkit::ScrollView, Toolkit::Scrollable, Create )
-DALI_ANIMATABLE_PROPERTY_REGISTRATION( Toolkit, ScrollView, "scroll-position", VECTOR2, SCROLL_POSITION)
-DALI_ANIMATABLE_PROPERTY_REGISTRATION( Toolkit, ScrollView, "scroll-pre-position", VECTOR2, SCROLL_PRE_POSITION)
-DALI_ANIMATABLE_PROPERTY_COMPONENT_REGISTRATION( Toolkit, ScrollView, "scroll-pre-position-x", SCROLL_PRE_POSITION_X, SCROLL_PRE_POSITION, 0)
-DALI_ANIMATABLE_PROPERTY_COMPONENT_REGISTRATION( Toolkit, ScrollView, "scroll-pre-position-y", SCROLL_PRE_POSITION_Y, SCROLL_PRE_POSITION, 1)
-DALI_ANIMATABLE_PROPERTY_REGISTRATION( Toolkit, ScrollView, "scroll-pre-position-max", VECTOR2, SCROLL_PRE_POSITION_MAX)
-DALI_ANIMATABLE_PROPERTY_COMPONENT_REGISTRATION( Toolkit, ScrollView, "scroll-pre-position-max-x", SCROLL_PRE_POSITION_MAX_X, SCROLL_PRE_POSITION_MAX, 0)
-DALI_ANIMATABLE_PROPERTY_COMPONENT_REGISTRATION( Toolkit, ScrollView, "scroll-pre-position-max-y", SCROLL_PRE_POSITION_MAX_Y, SCROLL_PRE_POSITION_MAX, 1)
-DALI_ANIMATABLE_PROPERTY_REGISTRATION( Toolkit, ScrollView, "overshoot-x", FLOAT, OVERSHOOT_X)
-DALI_ANIMATABLE_PROPERTY_REGISTRATION( Toolkit, ScrollView, "overshoot-y", FLOAT, OVERSHOOT_Y)
-DALI_ANIMATABLE_PROPERTY_REGISTRATION( Toolkit, ScrollView, "scroll-final", VECTOR2, SCROLL_FINAL)
-DALI_ANIMATABLE_PROPERTY_COMPONENT_REGISTRATION( Toolkit, ScrollView, "scroll-final-x", SCROLL_FINAL_X, SCROLL_FINAL,0)
-DALI_ANIMATABLE_PROPERTY_COMPONENT_REGISTRATION( Toolkit, ScrollView, "scroll-final-y", SCROLL_FINAL_Y, SCROLL_FINAL,1)
+DALI_ANIMATABLE_PROPERTY_REGISTRATION( Toolkit, ScrollView, "scrollPosition", VECTOR2, SCROLL_POSITION)
+DALI_ANIMATABLE_PROPERTY_REGISTRATION( Toolkit, ScrollView, "scrollPrePosition", VECTOR2, SCROLL_PRE_POSITION)
+DALI_ANIMATABLE_PROPERTY_COMPONENT_REGISTRATION( Toolkit, ScrollView, "scrollPrePositionX", SCROLL_PRE_POSITION_X, SCROLL_PRE_POSITION, 0)
+DALI_ANIMATABLE_PROPERTY_COMPONENT_REGISTRATION( Toolkit, ScrollView, "scrollPrePositionY", SCROLL_PRE_POSITION_Y, SCROLL_PRE_POSITION, 1)
+DALI_ANIMATABLE_PROPERTY_REGISTRATION( Toolkit, ScrollView, "scrollPrePositionMax", VECTOR2, SCROLL_PRE_POSITION_MAX)
+DALI_ANIMATABLE_PROPERTY_COMPONENT_REGISTRATION( Toolkit, ScrollView, "scrollPrePositionMaxX", SCROLL_PRE_POSITION_MAX_X, SCROLL_PRE_POSITION_MAX, 0)
+DALI_ANIMATABLE_PROPERTY_COMPONENT_REGISTRATION( Toolkit, ScrollView, "scrollPrePositionMaxY", SCROLL_PRE_POSITION_MAX_Y, SCROLL_PRE_POSITION_MAX, 1)
+DALI_ANIMATABLE_PROPERTY_REGISTRATION( Toolkit, ScrollView, "overshootX", FLOAT, OVERSHOOT_X)
+DALI_ANIMATABLE_PROPERTY_REGISTRATION( Toolkit, ScrollView, "overshootY", FLOAT, OVERSHOOT_Y)
+DALI_ANIMATABLE_PROPERTY_REGISTRATION( Toolkit, ScrollView, "scrollFinal", VECTOR2, SCROLL_FINAL)
+DALI_ANIMATABLE_PROPERTY_COMPONENT_REGISTRATION( Toolkit, ScrollView, "scrollFinalX", SCROLL_FINAL_X, SCROLL_FINAL,0)
+DALI_ANIMATABLE_PROPERTY_COMPONENT_REGISTRATION( Toolkit, ScrollView, "scrollFinalY", SCROLL_FINAL_Y, SCROLL_FINAL,1)
DALI_ANIMATABLE_PROPERTY_REGISTRATION( Toolkit, ScrollView, "wrap", BOOLEAN, WRAP)
DALI_ANIMATABLE_PROPERTY_REGISTRATION( Toolkit, ScrollView, "panning", BOOLEAN, PANNING)
DALI_ANIMATABLE_PROPERTY_REGISTRATION( Toolkit, ScrollView, "scrolling", BOOLEAN, SCROLLING)
-DALI_ANIMATABLE_PROPERTY_REGISTRATION( Toolkit, ScrollView, "scroll-domain-size", VECTOR2, SCROLL_DOMAIN_SIZE)
-DALI_ANIMATABLE_PROPERTY_COMPONENT_REGISTRATION( Toolkit, ScrollView, "scroll-domain-size-x", SCROLL_DOMAIN_SIZE_X, SCROLL_DOMAIN_SIZE, 0)
-DALI_ANIMATABLE_PROPERTY_COMPONENT_REGISTRATION( Toolkit, ScrollView, "scroll-domain-size-y", SCROLL_DOMAIN_SIZE_Y, SCROLL_DOMAIN_SIZE, 1)
-DALI_ANIMATABLE_PROPERTY_REGISTRATION( Toolkit, ScrollView, "scroll-domain-offset", VECTOR2, SCROLL_DOMAIN_OFFSET)
-DALI_ANIMATABLE_PROPERTY_REGISTRATION( Toolkit, ScrollView, "scroll-position-delta", VECTOR2, SCROLL_POSITION_DELTA)
-DALI_ANIMATABLE_PROPERTY_REGISTRATION( Toolkit, ScrollView, "start-page-position", VECTOR3, START_PAGE_POSITION)
+DALI_ANIMATABLE_PROPERTY_REGISTRATION( Toolkit, ScrollView, "scrollDomainSize", VECTOR2, SCROLL_DOMAIN_SIZE)
+DALI_ANIMATABLE_PROPERTY_COMPONENT_REGISTRATION( Toolkit, ScrollView, "scrollDomainSizeX", SCROLL_DOMAIN_SIZE_X, SCROLL_DOMAIN_SIZE, 0)
+DALI_ANIMATABLE_PROPERTY_COMPONENT_REGISTRATION( Toolkit, ScrollView, "scrollDomainSizeY", SCROLL_DOMAIN_SIZE_Y, SCROLL_DOMAIN_SIZE, 1)
+DALI_ANIMATABLE_PROPERTY_REGISTRATION( Toolkit, ScrollView, "scrollDomainOffset", VECTOR2, SCROLL_DOMAIN_OFFSET)
+DALI_ANIMATABLE_PROPERTY_REGISTRATION( Toolkit, ScrollView, "scrollPositionDelta", VECTOR2, SCROLL_POSITION_DELTA)
+DALI_ANIMATABLE_PROPERTY_REGISTRATION( Toolkit, ScrollView, "startPagePosition", VECTOR3, START_PAGE_POSITION)
-DALI_SIGNAL_REGISTRATION( Toolkit, ScrollView, "value-changed", SIGNAL_SNAP_STARTED )
+DALI_SIGNAL_REGISTRATION( Toolkit, ScrollView, "valueChanged", SIGNAL_SNAP_STARTED )
DALI_TYPE_REGISTRATION_END()
*/
struct InternalPrePositionConstraint
{
- InternalPrePositionConstraint(const Vector2& initialPanPosition,
- const Vector2& initialPanMask,
- bool axisAutoLock,
- float axisAutoLockGradient,
- ScrollView::LockAxis initialLockAxis,
- const Vector2& maxOvershoot,
- const RulerDomain& domainX, const RulerDomain& domainY)
- : mLocalStart(initialPanPosition),
- mInitialPanMask(initialPanMask),
- mDomainMin( -domainX.min, -domainY.min ),
- mDomainMax( -domainX.max, -domainY.max ),
- mMaxOvershoot(maxOvershoot),
- mAxisAutoLockGradient(axisAutoLockGradient),
- mLockAxis(initialLockAxis),
- mAxisAutoLock(axisAutoLock),
- mWasPanning(false),
- mClampX( domainX.enabled ),
- mClampY( domainY.enabled )
- {
+ InternalPrePositionConstraint( const Vector2& initialPanPosition,
+ const Vector2& initialPanMask,
+ bool axisAutoLock,
+ float axisAutoLockGradient,
+ ScrollView::LockAxis initialLockAxis,
+ const Vector2& maxOvershoot,
+ const RulerPtr& rulerX, const RulerPtr& rulerY )
+ : mLocalStart( initialPanPosition ),
+ mInitialPanMask( initialPanMask ),
+ mMaxOvershoot( maxOvershoot ),
+ mAxisAutoLockGradient( axisAutoLockGradient ),
+ mLockAxis( initialLockAxis ),
+ mAxisAutoLock( axisAutoLock ),
+ mWasPanning( false )
+ {
+ const RulerDomain& rulerDomainX = rulerX->GetDomain();
+ const RulerDomain& rulerDomainY = rulerY->GetDomain();
+ mDomainMin = Vector2( rulerDomainX.min, -rulerDomainY.min );
+ mDomainMax = Vector2( -rulerDomainX.max, -rulerDomainY.max );
+ mClampX = rulerDomainX.enabled;
+ mClampY = rulerDomainY.enabled;
+ mFixedRulerX = rulerX->GetType() == Ruler::Fixed;
+ mFixedRulerY = rulerY->GetType() == Ruler::Fixed;
}
void operator()( Vector2& scrollPostPosition, const PropertyInputContainer& inputs )
{
const Vector2& panPosition = inputs[0]->GetVector2();
+ const bool& inGesture = inputs[1]->GetBoolean();
- if(!mWasPanning)
- {
- mPrePosition = scrollPostPosition;
- mCurrentPanMask = mInitialPanMask;
- mWasPanning = true;
- }
-
- // Calculate Deltas...
- const Vector2& currentPosition = panPosition;
- Vector2 panDelta( currentPosition - mLocalStart );
-
- // Axis Auto Lock - locks the panning to the horizontal or vertical axis if the pan
- // appears mostly horizontal or mostly vertical respectively...
- if( mAxisAutoLock )
+ // First check if we are within a gesture.
+ // The ScrollView may have received a start gesture from ::OnPan()
+ // while the finish gesture is received now in this constraint.
+ // This gesture must then be rejected as the value will be "old".
+ // Typically the last value from the end of the last gesture.
+ // If we are rejecting the gesture, we simply don't modify the constraint target.
+ if( inGesture )
{
- mLockAxis = GetLockAxis(panDelta, mLockAxis, mAxisAutoLockGradient);
- if( mLockAxis == ScrollView::LockVertical )
+ if( !mWasPanning )
{
- mCurrentPanMask.y = 0.0f;
+ mPrePosition = scrollPostPosition;
+ mStartPosition = mPrePosition;
+ mCurrentPanMask = mInitialPanMask;
+ mWasPanning = true;
}
- else if( mLockAxis == ScrollView::LockHorizontal )
+
+ // Calculate Deltas...
+ const Vector2& currentPosition = panPosition;
+ Vector2 panDelta( currentPosition - mLocalStart );
+
+ // Axis Auto Lock - locks the panning to the horizontal or vertical axis if the pan
+ // appears mostly horizontal or mostly vertical respectively...
+ if( mAxisAutoLock )
{
- mCurrentPanMask.x = 0.0f;
+ mLockAxis = GetLockAxis( panDelta, mLockAxis, mAxisAutoLockGradient );
+ if( mLockAxis == ScrollView::LockVertical )
+ {
+ mCurrentPanMask.y = 0.0f;
+ }
+ else if( mLockAxis == ScrollView::LockHorizontal )
+ {
+ mCurrentPanMask.x = 0.0f;
+ }
}
- }
- // Restrict deltas based on ruler enable/disable and axis-lock state...
- panDelta *= mCurrentPanMask;
+ // Restrict deltas based on ruler enable/disable and axis-lock state...
+ panDelta *= mCurrentPanMask;
- // Perform Position transform based on input deltas...
- scrollPostPosition = mPrePosition;
- scrollPostPosition += panDelta;
+ // Perform Position transform based on input deltas...
+ scrollPostPosition = mPrePosition;
+ scrollPostPosition += panDelta;
- // if no wrapping then clamp preposition to maximum overshoot amount
- const Vector3& size = inputs[1]->GetVector3();
- if( mClampX )
- {
- float newXPosition = Clamp(scrollPostPosition.x, (mDomainMax.x + size.x) - mMaxOvershoot.x, mDomainMin.x + mMaxOvershoot.x );
- if( (newXPosition < scrollPostPosition.x - Math::MACHINE_EPSILON_1)
- || (newXPosition > scrollPostPosition.x + Math::MACHINE_EPSILON_1) )
+ // if no wrapping then clamp preposition to maximum overshoot amount
+ const Vector3& size = inputs[2]->GetVector3();
+ if( mClampX )
{
- mPrePosition.x = newXPosition;
- mLocalStart.x = panPosition.x;
+ float newXPosition = Clamp( scrollPostPosition.x, ( mDomainMax.x + size.x ) - mMaxOvershoot.x, mDomainMin.x + mMaxOvershoot.x );
+ if( (newXPosition < scrollPostPosition.x - Math::MACHINE_EPSILON_1)
+ || (newXPosition > scrollPostPosition.x + Math::MACHINE_EPSILON_1) )
+ {
+ mPrePosition.x = newXPosition;
+ mLocalStart.x = panPosition.x;
+ }
+ scrollPostPosition.x = newXPosition;
}
- scrollPostPosition.x = newXPosition;
- }
- if( mClampY )
- {
- float newYPosition = Clamp(scrollPostPosition.y, (mDomainMax.y + size.y) - mMaxOvershoot.y, mDomainMin.y + mMaxOvershoot.y );
- if( (newYPosition < scrollPostPosition.y - Math::MACHINE_EPSILON_1)
- || (newYPosition > scrollPostPosition.y + Math::MACHINE_EPSILON_1) )
+ if( mClampY )
{
- mPrePosition.y = newYPosition;
- mLocalStart.y = panPosition.y;
+ float newYPosition = Clamp( scrollPostPosition.y, ( mDomainMax.y + size.y ) - mMaxOvershoot.y, mDomainMin.y + mMaxOvershoot.y );
+ if( ( newYPosition < scrollPostPosition.y - Math::MACHINE_EPSILON_1 )
+ || ( newYPosition > scrollPostPosition.y + Math::MACHINE_EPSILON_1 ) )
+ {
+ mPrePosition.y = newYPosition;
+ mLocalStart.y = panPosition.y;
+ }
+ scrollPostPosition.y = newYPosition;
+ }
+
+ // If we are using a fixed ruler in a particular axis, limit the maximum pages scrolled on that axis.
+ if( mFixedRulerX || mFixedRulerY )
+ {
+ // Here we limit the maximum amount that can be moved from the starting position of the gesture to one page.
+ // We do this only if we have a fixed ruler (on that axis) and the mode is enabled.
+ // Note: 1.0f is subtracted to keep the value within one page size (otherwise we stray on to the page after).
+ // Note: A further 1.0f is subtracted to handle a compensation that happens later within the flick handling code in SnapWithVelocity().
+ // When a flick is completed, an adjustment of 1.0f is sometimes made to allow for the scenario where:
+ // A flick finishes before the update thread has advanced the scroll position past the previous snap point.
+ Vector2 pageSizeLimit( size.x - ( 1.0f + 1.0f ), size.y - ( 1.0f - 1.0f ) );
+ Vector2 minPosition( mStartPosition.x - pageSizeLimit.x, mStartPosition.y - pageSizeLimit.y );
+ Vector2 maxPosition( mStartPosition.x + pageSizeLimit.x, mStartPosition.y + pageSizeLimit.y );
+
+ if( mFixedRulerX )
+ {
+ scrollPostPosition.x = Clamp( scrollPostPosition.x, minPosition.x, maxPosition.x );
+ }
+ if( mFixedRulerY )
+ {
+ scrollPostPosition.y = Clamp( scrollPostPosition.y, minPosition.y, maxPosition.y );
+ }
}
- scrollPostPosition.y = newYPosition;
}
}
Vector2 mPrePosition;
Vector2 mLocalStart;
- Vector2 mInitialPanMask; ///< Initial pan mask (based on ruler settings)
+ Vector2 mStartPosition; ///< The start position of the gesture - used to limit scroll amount (not modified by clamping).
+ Vector2 mInitialPanMask; ///< Initial pan mask (based on ruler settings).
Vector2 mCurrentPanMask; ///< Current pan mask that can be altered by axis lock mode.
Vector2 mDomainMin;
Vector2 mDomainMax;
float mAxisAutoLockGradient; ///< Set by ScrollView
ScrollView::LockAxis mLockAxis;
- bool mAxisAutoLock:1; ///< Set by ScrollView
+ bool mAxisAutoLock:1; ///< Set by ScrollView
bool mWasPanning:1;
bool mClampX:1;
bool mClampY:1;
+ bool mFixedRulerX:1;
+ bool mFixedRulerY:1;
};
/**
mMaxFlickSpeed(DEFAULT_MAX_FLICK_SPEED),
mWheelScrollDistanceStep(Vector2::ZERO),
mInAccessibilityPan(false),
- mInitialized(false),
mScrolling(false),
mScrollInterrupted(false),
mPanning(false),
mWheelScrollDistanceStep = Stage::GetCurrent().GetSize() * DEFAULT_WHEEL_SCROLL_DISTANCE_STEP_PROPORTION;
- mInitialized = true;
-
mGestureStackDepth = 0;
EnableGestureDetection( Gesture::Type( Gesture::Pan ) );
void ScrollView::OnStageConnection( int depth )
{
+ ScrollBase::OnStageConnection( depth );
+
DALI_LOG_SCROLL_STATE("[0x%X]", this);
if ( mSensitive )
DALI_LOG_SCROLL_STATE("[0x%X]", this);
StopAnimation();
+
+ ScrollBase::OnStageDisconnection();
}
ScrollView::~ScrollView()
mAxisAutoLockGradient,
mLockAxis,
mMaxOvershoot,
- mRulerX->GetDomain(),
- mRulerY->GetDomain() ) );
+ mRulerX,
+ mRulerY ) );
mScrollMainInternalPrePositionConstraint.AddSource( Source( detector, PanGestureDetector::Property::LOCAL_POSITION ) );
+ mScrollMainInternalPrePositionConstraint.AddSource( Source( detector, PanGestureDetector::Property::PANNING ) );
mScrollMainInternalPrePositionConstraint.AddSource( Source( self, Actor::Property::SIZE ) );
mScrollMainInternalPrePositionConstraint.Apply();
}