return childPosition + childAnchor * childSize;
}
+/**
+ * Returns the closest actor to the given position
+ * @param[in] actor The scrollview actor
+ * @param[in] internalActor The internal actor (to ignore)
+ * @param[in] position The given position
+ * @param[in] dirX Direction to search in
+ * @param[in] dirY Direction to search in
+ * @param[in] dirZ Direction to search in
+ * @return the closest child actor
+ */
+using FindDirection = Dali::Toolkit::Internal::ScrollView::FindDirection;
+
+Actor FindClosestActorToPosition(
+ CustomActor actor, Actor internalActor, const Vector3& position, FindDirection dirX, FindDirection dirY, FindDirection dirZ)
+{
+ Actor closestChild;
+ float closestDistance2 = 0.0f;
+ Vector3 actualPosition = position;
+
+ unsigned int numChildren = actor.GetChildCount();
+
+ for(unsigned int i = 0; i < numChildren; ++i)
+ {
+ Actor child = actor.GetChildAt(i);
+
+ if(internalActor == child) // ignore internal actor.
+ {
+ continue;
+ }
+
+ Vector3 childPosition = GetPositionOfAnchor(child, AnchorPoint::CENTER);
+
+ Vector3 delta = childPosition - actualPosition;
+
+ // X-axis checking (only find Actors to the [dirX] of actualPosition)
+ if(dirX > FindDirection::All) // != All,None
+ {
+ FindDirection deltaH = delta.x > 0 ? FindDirection::Right : FindDirection::Left;
+ if(dirX != deltaH)
+ {
+ continue;
+ }
+ }
+
+ // Y-axis checking (only find Actors to the [dirY] of actualPosition)
+ if(dirY > FindDirection::All) // != All,None
+ {
+ FindDirection deltaV = delta.y > 0 ? FindDirection::Down : FindDirection::Up;
+ if(dirY != deltaV)
+ {
+ continue;
+ }
+ }
+
+ // Z-axis checking (only find Actors to the [dirZ] of actualPosition)
+ if(dirZ > FindDirection::All) // != All,None
+ {
+ FindDirection deltaV = delta.y > 0 ? FindDirection::In : FindDirection::Out;
+ if(dirZ != deltaV)
+ {
+ continue;
+ }
+ }
+
+ // compare child to closest child in terms of distance.
+ float distance2 = 0.0f;
+
+ // distance2 = the Square of the relevant dimensions of delta
+ if(dirX != FindDirection::None)
+ {
+ distance2 += delta.x * delta.x;
+ }
+
+ if(dirY != FindDirection::None)
+ {
+ distance2 += delta.y * delta.y;
+ }
+
+ if(dirZ != FindDirection::None)
+ {
+ distance2 += delta.z * delta.z;
+ }
+
+ if(closestChild) // Next time.
+ {
+ if(distance2 < closestDistance2)
+ {
+ closestChild = child;
+ closestDistance2 = distance2;
+ }
+ }
+ else // First time.
+ {
+ closestChild = child;
+ closestDistance2 = distance2;
+ }
+ }
+
+ return closestChild;
+}
+
// AlphaFunctions /////////////////////////////////////////////////////////////////////////////////
float FinalDefaultAlphaFunction(float offset)
scrollMax = max - size.GetVectorXY();
}
+/**
+ * Clamp a position
+ * @param[in] size The size to clamp to
+ * @param[in] rulerX The horizontal ruler
+ * @param[in] rulerY The vertical ruler
+ * @param[in,out] position The position to clamp
+ * @param[out] clamped the clamped state
+ */
+void ClampPosition(const Vector3& size, Dali::Toolkit::RulerPtr rulerX, Dali::Toolkit::RulerPtr rulerY, Vector2& position, Dali::Toolkit::ClampState2D& clamped)
+{
+ position.x = -rulerX->Clamp(-position.x, size.width, 1.0f, clamped.x); // NOTE: X & Y rulers think in -ve coordinate system.
+ position.y = -rulerY->Clamp(-position.y, size.height, 1.0f, clamped.y); // That is scrolling RIGHT (e.g. 100.0, 0.0) means moving LEFT.
+}
+
+/**
+ * TODO: In situations where axes are different (X snap, Y free)
+ * Each axis should really have their own independent animation (time and equation)
+ * Consider, X axis snapping to nearest grid point (EaseOut over fixed time)
+ * Consider, Y axis simulating physics to arrive at a point (Physics equation over variable time)
+ * Currently, the axes have been split however, they both use the same EaseOut equation.
+ *
+ * @param[in] scrollView The main scrollview
+ * @param[in] rulerX The X ruler
+ * @param[in] rulerY The Y ruler
+ * @param[in] lockAxis Which axis (if any) is locked.
+ * @param[in] velocity Current pan velocity
+ * @param[in] maxOvershoot Maximum overshoot
+ * @param[in] inAcessibilityPan True if we are currently panning with accessibility
+ * @param[out] positionSnap The target position of snap animation
+ * @param[out] positionDuration The duration of the snap animation
+ * @param[out] alphaFunction The snap animation alpha function
+ * @param[out] isFlick if we are flicking or not
+ * @param[out] isFreeFlick if we are free flicking or not
+ */
+void SnapWithVelocity(
+ Dali::Toolkit::Internal::ScrollView& scrollView,
+ Dali::Toolkit::RulerPtr rulerX,
+ Dali::Toolkit::RulerPtr rulerY,
+ Dali::Toolkit::Internal::ScrollView::LockAxis lockAxis,
+ Vector2 velocity,
+ Vector2 maxOvershoot,
+ Vector2& positionSnap,
+ Vector2& positionDuration,
+ AlphaFunction& alphaFunction,
+ bool inAccessibilityPan,
+ bool& isFlick,
+ bool& isFreeFlick)
+{
+ // Animator takes over now, touches are assumed not to interfere.
+ // And if touches do interfere, then we'll stop animation, update PrePosition
+ // to current mScroll's properties, and then resume.
+ // Note: For Flicking this may work a bit different...
+
+ float angle = atan2(velocity.y, velocity.x);
+ float speed2 = velocity.LengthSquared();
+ float biasX = 0.5f;
+ float biasY = 0.5f;
+ FindDirection horizontal = FindDirection::None;
+ FindDirection vertical = FindDirection::None;
+
+ using LockAxis = Dali::Toolkit::Internal::ScrollView::LockAxis;
+
+ // orthoAngleRange = Angle tolerance within the Exact N,E,S,W direction
+ // that will be accepted as a general N,E,S,W flick direction.
+
+ const float orthoAngleRange = FLICK_ORTHO_ANGLE_RANGE * M_PI / 180.0f;
+ const float flickSpeedThreshold2 = scrollView.GetMinimumSpeedForFlick() * scrollView.GetMinimumSpeedForFlick();
+
+ // Flick logic X Axis
+
+ if(rulerX->IsEnabled() && lockAxis != LockAxis::LockHorizontal)
+ {
+ horizontal = FindDirection::All;
+
+ if(speed2 > flickSpeedThreshold2 || // exceeds flick threshold
+ inAccessibilityPan) // With AccessibilityPan its easier to move between snap positions
+ {
+ if((angle >= -orthoAngleRange) && (angle < orthoAngleRange)) // Swiping East
+ {
+ biasX = 0.0f, horizontal = FindDirection::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 = FindDirection::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;
+ }
+ }
+ }
+
+ // Flick logic Y Axis
+
+ if(rulerY->IsEnabled() && lockAxis != LockAxis::LockVertical)
+ {
+ vertical = FindDirection::All;
+
+ if(speed2 > flickSpeedThreshold2 || // exceeds flick threshold
+ inAccessibilityPan) // With AccessibilityPan its easier to move between snap positions
+ {
+ if((angle >= M_PI_2 - orthoAngleRange) && (angle < M_PI_2 + orthoAngleRange)) // Swiping South
+ {
+ biasY = 0.0f, vertical = FindDirection::Up;
+ }
+ else if((angle >= -M_PI_2 - orthoAngleRange) && (angle < -M_PI_2 + orthoAngleRange)) // Swiping North
+ {
+ biasY = 1.0f, vertical = FindDirection::Down;
+ }
+ }
+ }
+
+ // isFlick: Whether this gesture is a flick or not.
+ isFlick = (horizontal != FindDirection::All || vertical != FindDirection::All);
+ // isFreeFlick: Whether this gesture is a flick under free panning criteria.
+ isFreeFlick = velocity.LengthSquared() > (FREE_FLICK_SPEED_THRESHOLD * FREE_FLICK_SPEED_THRESHOLD);
+
+ if(isFlick || isFreeFlick)
+ {
+ positionDuration = Vector2::ONE * scrollView.GetScrollFlickDuration();
+ alphaFunction = scrollView.GetScrollFlickAlphaFunction();
+ }
+
+ // Calculate next positionSnap ////////////////////////////////////////////////////////////
+
+ if(scrollView.GetActorAutoSnap())
+ {
+ Vector3 size = scrollView.Self().GetCurrentProperty<Vector3>(Actor::Property::SIZE);
+
+ Actor child = scrollView.FindClosestActorToPosition(Vector3(size.width * 0.5f, size.height * 0.5f, 0.0f), horizontal, vertical);
+
+ if(!child && isFlick)
+ {
+ // If we conducted a direction limited search and found no actor, then just snap to the closest actor.
+ child = scrollView.FindClosestActorToPosition(Vector3(size.width * 0.5f, size.height * 0.5f, 0.0f));
+ }
+
+ if(child)
+ {
+ Vector2 position = scrollView.Self().GetCurrentProperty<Vector2>(Toolkit::ScrollView::Property::SCROLL_POSITION);
+
+ // Get center-point of the Actor.
+ Vector3 childPosition = GetPositionOfAnchor(child, AnchorPoint::CENTER);
+
+ if(rulerX->IsEnabled())
+ {
+ positionSnap.x = position.x - childPosition.x + size.width * 0.5f;
+ }
+ if(rulerY->IsEnabled())
+ {
+ positionSnap.y = position.y - childPosition.y + size.height * 0.5f;
+ }
+ }
+ }
+
+ Vector2 startPosition = positionSnap;
+ positionSnap.x = -rulerX->Snap(-positionSnap.x, biasX); // NOTE: X & Y rulers think in -ve coordinate system.
+ positionSnap.y = -rulerY->Snap(-positionSnap.y, biasY); // That is scrolling RIGHT (e.g. 100.0, 0.0) means moving LEFT.
+
+ Dali::Toolkit::ClampState2D clamped;
+ Vector3 size = scrollView.Self().GetCurrentProperty<Vector3>(Actor::Property::SIZE);
+ Vector2 clampDelta(Vector2::ZERO);
+ ClampPosition(size, rulerX, rulerY, positionSnap, clamped);
+
+ if((rulerX->GetType() == Dali::Toolkit::Ruler::FREE || rulerY->GetType() == Dali::Toolkit::Ruler::FREE) &&
+ isFreeFlick && !scrollView.GetActorAutoSnap())
+ {
+ // Calculate target position based on velocity of flick.
+
+ // a = Deceleration (Set to diagonal stage length * friction coefficient)
+ // u = Initial Velocity (Flick velocity)
+ // v = 0 (Final Velocity)
+ // t = Time (Velocity / Deceleration)
+ Vector2 stageSize = Stage::GetCurrent().GetSize();
+ float stageLength = Vector3(stageSize.x, stageSize.y, 0.0f).Length();
+ float a = (stageLength * scrollView.GetFrictionCoefficient());
+ Vector3 u = Vector3(velocity.x, velocity.y, 0.0f) * scrollView.GetFlickSpeedCoefficient();
+ float speed = u.Length();
+ u /= speed;
+
+ // TODO: Change this to a decay function. (faster you flick, the slower it should be)
+ speed = std::min(speed, stageLength * scrollView.GetMaxFlickSpeed());
+ u *= speed;
+ alphaFunction = ConstantDecelerationAlphaFunction;
+
+ float t = speed / a;
+
+ if(rulerX->IsEnabled() && rulerX->GetType() == Dali::Toolkit::Ruler::FREE)
+ {
+ positionSnap.x += t * u.x * 0.5f;
+ }
+
+ if(rulerY->IsEnabled() && rulerY->GetType() == Dali::Toolkit::Ruler::FREE)
+ {
+ positionSnap.y += t * u.y * 0.5f;
+ }
+
+ clampDelta = positionSnap;
+ ClampPosition(size, rulerX, rulerY, positionSnap, clamped);
+
+ if((positionSnap - startPosition).LengthSquared() > Math::MACHINE_EPSILON_0)
+ {
+ clampDelta -= positionSnap;
+ clampDelta.x = clampDelta.x > 0.0f ? std::min(clampDelta.x, maxOvershoot.x) : std::max(clampDelta.x, -maxOvershoot.x);
+ clampDelta.y = clampDelta.y > 0.0f ? std::min(clampDelta.y, maxOvershoot.y) : std::max(clampDelta.y, -maxOvershoot.y);
+ }
+ else
+ {
+ clampDelta = Vector2::ZERO;
+ }
+
+ // If Axis is Free and has velocity, then calculate time taken
+ // to reach target based on velocity in axis.
+ if(rulerX->IsEnabled() && rulerX->GetType() == Dali::Toolkit::Ruler::FREE)
+ {
+ float deltaX = fabsf(startPosition.x - positionSnap.x);
+
+ if(fabsf(u.x) > Math::MACHINE_EPSILON_1)
+ {
+ positionDuration.x = fabsf(deltaX / u.x);
+ }
+ else
+ {
+ positionDuration.x = 0;
+ }
+ }
+
+ if(rulerY->IsEnabled() && rulerY->GetType() == Dali::Toolkit::Ruler::FREE)
+ {
+ float deltaY = fabsf(startPosition.y - positionSnap.y);
+
+ if(fabsf(u.y) > Math::MACHINE_EPSILON_1)
+ {
+ positionDuration.y = fabsf(deltaY / u.y);
+ }
+ else
+ {
+ positionDuration.y = 0;
+ }
+ }
+ }
+
+ if(scrollView.IsOvershootEnabled())
+ {
+ // Scroll to the end of the overshoot only when overshoot is enabled.
+ positionSnap += clampDelta;
+ }
+}
+
} // unnamed namespace
namespace Dali
Actor ScrollView::FindClosestActorToPosition(const Vector3& position, FindDirection dirX, FindDirection dirY, FindDirection dirZ)
{
- Actor closestChild;
- float closestDistance2 = 0.0f;
- Vector3 actualPosition = position;
-
- unsigned int numChildren = Self().GetChildCount();
-
- for(unsigned int i = 0; i < numChildren; ++i)
- {
- Actor child = Self().GetChildAt(i);
-
- if(mInternalActor == child) // ignore internal actor.
- {
- continue;
- }
-
- Vector3 childPosition = GetPositionOfAnchor(child, AnchorPoint::CENTER);
-
- Vector3 delta = childPosition - actualPosition;
-
- // X-axis checking (only find Actors to the [dirX] of actualPosition)
- if(dirX > All) // != All,None
- {
- FindDirection deltaH = delta.x > 0 ? Right : Left;
- if(dirX != deltaH)
- {
- continue;
- }
- }
-
- // Y-axis checking (only find Actors to the [dirY] of actualPosition)
- if(dirY > All) // != All,None
- {
- FindDirection deltaV = delta.y > 0 ? Down : Up;
- if(dirY != deltaV)
- {
- continue;
- }
- }
-
- // Z-axis checking (only find Actors to the [dirZ] of actualPosition)
- if(dirZ > All) // != All,None
- {
- FindDirection deltaV = delta.y > 0 ? In : Out;
- if(dirZ != deltaV)
- {
- continue;
- }
- }
-
- // compare child to closest child in terms of distance.
- float distance2 = 0.0f;
-
- // distance2 = the Square of the relevant dimensions of delta
- if(dirX != None)
- {
- distance2 += delta.x * delta.x;
- }
-
- if(dirY != None)
- {
- distance2 += delta.y * delta.y;
- }
-
- if(dirZ != None)
- {
- distance2 += delta.z * delta.z;
- }
-
- if(closestChild) // Next time.
- {
- if(distance2 < closestDistance2)
- {
- closestChild = child;
- closestDistance2 = distance2;
- }
- }
- else // First time.
- {
- closestChild = child;
- closestDistance2 = distance2;
- }
- }
-
- return closestChild;
+ return ::FindClosestActorToPosition(Self(), mInternalActor, position, dirX, dirY, dirZ);
}
bool ScrollView::ScrollToSnapPoint()
return SnapWithVelocity(stationaryVelocity);
}
-// TODO: In situations where axes are different (X snap, Y free)
-// Each axis should really have their own independent animation (time and equation)
-// Consider, X axis snapping to nearest grid point (EaseOut over fixed time)
-// Consider, Y axis simulating physics to arrive at a point (Physics equation over variable time)
-// Currently, the axes have been split however, they both use the same EaseOut equation.
bool ScrollView::SnapWithVelocity(Vector2 velocity)
{
- // Animator takes over now, touches are assumed not to interfere.
- // And if touches do interfere, then we'll stop animation, update PrePosition
- // to current mScroll's properties, and then resume.
- // Note: For Flicking this may work a bit different...
-
- float angle = atan2(velocity.y, velocity.x);
- float speed2 = velocity.LengthSquared();
- AlphaFunction alphaFunction = mSnapAlphaFunction;
+ Vector2 positionSnap = mScrollPrePosition;
Vector2 positionDuration = Vector2::ONE * mSnapDuration;
- float biasX = 0.5f;
- float biasY = 0.5f;
- FindDirection horizontal = None;
- FindDirection vertical = None;
-
- // orthoAngleRange = Angle tolerance within the Exact N,E,S,W direction
- // that will be accepted as a general N,E,S,W flick direction.
-
- const float orthoAngleRange = FLICK_ORTHO_ANGLE_RANGE * M_PI / 180.0f;
- const float flickSpeedThreshold2 = mFlickSpeedThreshold * mFlickSpeedThreshold;
-
- Vector2 positionSnap = mScrollPrePosition;
-
- // Flick logic X Axis
-
- if(mRulerX->IsEnabled() && mLockAxis != LockHorizontal)
- {
- horizontal = All;
-
- 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;
- }
- }
- }
-
- // Flick logic Y Axis
-
- if(mRulerY->IsEnabled() && mLockAxis != LockVertical)
- {
- vertical = All;
-
- 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
- {
- biasY = 0.0f, vertical = Up;
- }
- else if((angle >= -M_PI_2 - orthoAngleRange) && (angle < -M_PI_2 + orthoAngleRange)) // Swiping North
- {
- biasY = 1.0f, vertical = Down;
- }
- }
- }
-
- // isFlick: Whether this gesture is a flick or not.
- bool isFlick = (horizontal != All || vertical != All);
- // isFreeFlick: Whether this gesture is a flick under free panning criteria.
- bool isFreeFlick = velocity.LengthSquared() > (FREE_FLICK_SPEED_THRESHOLD * FREE_FLICK_SPEED_THRESHOLD);
-
- if(isFlick || isFreeFlick)
- {
- positionDuration = Vector2::ONE * mFlickDuration;
- alphaFunction = mFlickAlphaFunction;
- }
-
- // Calculate next positionSnap ////////////////////////////////////////////////////////////
-
- if(mActorAutoSnapEnabled)
- {
- Vector3 size = Self().GetCurrentProperty<Vector3>(Actor::Property::SIZE);
-
- Actor child = FindClosestActorToPosition(Vector3(size.width * 0.5f, size.height * 0.5f, 0.0f), horizontal, vertical);
-
- if(!child && isFlick)
- {
- // If we conducted a direction limited search and found no actor, then just snap to the closest actor.
- child = FindClosestActorToPosition(Vector3(size.width * 0.5f, size.height * 0.5f, 0.0f));
- }
-
- if(child)
- {
- Vector2 position = Self().GetCurrentProperty<Vector2>(Toolkit::ScrollView::Property::SCROLL_POSITION);
-
- // Get center-point of the Actor.
- Vector3 childPosition = GetPositionOfAnchor(child, AnchorPoint::CENTER);
-
- if(mRulerX->IsEnabled())
- {
- positionSnap.x = position.x - childPosition.x + size.width * 0.5f;
- }
- if(mRulerY->IsEnabled())
- {
- positionSnap.y = position.y - childPosition.y + size.height * 0.5f;
- }
- }
- }
-
- Vector2 startPosition = positionSnap;
- positionSnap.x = -mRulerX->Snap(-positionSnap.x, biasX); // NOTE: X & Y rulers think in -ve coordinate system.
- positionSnap.y = -mRulerY->Snap(-positionSnap.y, biasY); // That is scrolling RIGHT (e.g. 100.0, 0.0) means moving LEFT.
-
- Vector2 clampDelta(Vector2::ZERO);
- ClampPosition(positionSnap);
-
- if((mRulerX->GetType() == Ruler::FREE || mRulerY->GetType() == Ruler::FREE) && isFreeFlick && !mActorAutoSnapEnabled)
- {
- // Calculate target position based on velocity of flick.
-
- // a = Deceleration (Set to diagonal stage length * friction coefficient)
- // u = Initial Velocity (Flick velocity)
- // v = 0 (Final Velocity)
- // t = Time (Velocity / Deceleration)
- Vector2 stageSize = Stage::GetCurrent().GetSize();
- float stageLength = Vector3(stageSize.x, stageSize.y, 0.0f).Length();
- float a = (stageLength * mFrictionCoefficient);
- Vector3 u = Vector3(velocity.x, velocity.y, 0.0f) * mFlickSpeedCoefficient;
- float speed = u.Length();
- u /= speed;
-
- // TODO: Change this to a decay function. (faster you flick, the slower it should be)
- speed = std::min(speed, stageLength * mMaxFlickSpeed);
- u *= speed;
- alphaFunction = ConstantDecelerationAlphaFunction;
-
- float t = speed / a;
-
- if(mRulerX->IsEnabled() && mRulerX->GetType() == Ruler::FREE)
- {
- positionSnap.x += t * u.x * 0.5f;
- }
-
- if(mRulerY->IsEnabled() && mRulerY->GetType() == Ruler::FREE)
- {
- positionSnap.y += t * u.y * 0.5f;
- }
-
- clampDelta = positionSnap;
- ClampPosition(positionSnap);
- if((positionSnap - startPosition).LengthSquared() > Math::MACHINE_EPSILON_0)
- {
- clampDelta -= positionSnap;
- clampDelta.x = clampDelta.x > 0.0f ? std::min(clampDelta.x, mMaxOvershoot.x) : std::max(clampDelta.x, -mMaxOvershoot.x);
- clampDelta.y = clampDelta.y > 0.0f ? std::min(clampDelta.y, mMaxOvershoot.y) : std::max(clampDelta.y, -mMaxOvershoot.y);
- }
- else
- {
- clampDelta = Vector2::ZERO;
- }
-
- // If Axis is Free and has velocity, then calculate time taken
- // to reach target based on velocity in axis.
- if(mRulerX->IsEnabled() && mRulerX->GetType() == Ruler::FREE)
- {
- float deltaX = fabsf(startPosition.x - positionSnap.x);
-
- if(fabsf(u.x) > Math::MACHINE_EPSILON_1)
- {
- positionDuration.x = fabsf(deltaX / u.x);
- }
- else
- {
- positionDuration.x = 0;
- }
- }
-
- if(mRulerY->IsEnabled() && mRulerY->GetType() == Ruler::FREE)
- {
- float deltaY = fabsf(startPosition.y - positionSnap.y);
-
- if(fabsf(u.y) > Math::MACHINE_EPSILON_1)
- {
- positionDuration.y = fabsf(deltaY / u.y);
- }
- else
- {
- positionDuration.y = 0;
- }
- }
- }
+ AlphaFunction alphaFunction = mSnapAlphaFunction;
+ bool isFlick;
+ bool isFreeFlick;
- if(IsOvershootEnabled())
- {
- // Scroll to the end of the overshoot only when overshoot is enabled.
- positionSnap += clampDelta;
- }
+ ::SnapWithVelocity(*this, mRulerX, mRulerY, mLockAxis, velocity, mMaxOvershoot, positionSnap, positionDuration, alphaFunction, mInAccessibilityPan, isFlick, isFreeFlick);
bool animating = AnimateTo(positionSnap, positionDuration, alphaFunction, false, DIRECTION_BIAS_NONE, DIRECTION_BIAS_NONE, isFlick || isFreeFlick ? FLICK : SNAP);
return mSnapStartedSignal;
}
-void ScrollView::AccessibleImpl::EnsureChildVisible(Actor child)
+bool ScrollView::AccessibleImpl::ScrollToChild(Actor child)
{
- auto scrollView = Dali::Toolkit::ScrollView::DownCast(self);
- scrollView.ScrollTo(child);
+ auto scrollView = Dali::Toolkit::ScrollView::DownCast(Self());
+ if(Toolkit::GetImpl(scrollView).FindClosestActor() == child)
+ {
+ return false;
+ }
+
+ // FIXME: ScrollTo does not work (snaps back to original position)
+ scrollView.ScrollTo(child, scrollView.GetScrollFlickDuration());
+ return true;
}
void ScrollView::FindAndUnbindActor(Actor child)
{
Vector3 size = Self().GetCurrentProperty<Vector3>(Actor::Property::SIZE);
- position.x = -mRulerX->Clamp(-position.x, size.width, 1.0f, clamped.x); // NOTE: X & Y rulers think in -ve coordinate system.
- position.y = -mRulerY->Clamp(-position.y, size.height, 1.0f, clamped.y); // That is scrolling RIGHT (e.g. 100.0, 0.0) means moving LEFT.
+ ::ClampPosition(size, mRulerX, mRulerY, position, clamped);
}
void ScrollView::WrapPosition(Vector2& position) const