#include <cstring> // for strcmp
#include <dali/public-api/animation/constraints.h>
#include <dali/public-api/common/stage.h>
-#include <dali/public-api/events/mouse-wheel-event.h>
+#include <dali/public-api/events/wheel-event.h>
#include <dali/public-api/events/touch-event.h>
#include <dali/public-api/object/type-registry.h>
#include <dali/devel-api/object/type-registry-helper.h>
const float FREE_FLICK_SPEED_THRESHOLD = 200.0f; ///< Free-Flick threshold in pixels/ms
const float AUTOLOCK_AXIS_MINIMUM_DISTANCE2 = 100.0f; ///< Auto-lock axis after minimum distance squared.
const float FLICK_ORTHO_ANGLE_RANGE = 75.0f; ///< degrees. (if >45, then supports diagonal flicking)
-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 Vector2 DEFAULT_WHEEL_SCROLL_DISTANCE_STEP_PROPORTION = Vector2(0.17f, 0.1f); ///< The step of horizontal scroll distance in the proportion of stage size for each wheel event received.
const unsigned long MINIMUM_TIME_BETWEEN_DOWN_AND_UP_FOR_RESET( 150u );
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
*/
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 )
if(!mWasPanning)
{
mPrePosition = scrollPostPosition;
+ mStartPosition = mPrePosition;
mCurrentPanMask = mInitialPanMask;
mWasPanning = true;
}
}
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 );
+ }
+ }
}
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;
};
/**
}
ScrollView::ScrollView()
-: ScrollBase( ControlBehaviour( REQUIRES_MOUSE_WHEEL_EVENTS ) ), // Enable size negotiation
+: ScrollBase( ControlBehaviour( REQUIRES_WHEEL_EVENTS ) ), // Enable size negotiation
mTouchDownTime(0u),
mGestureStackDepth(0),
mScrollStateFlags(0),
mFrictionCoefficient(DEFAULT_FRICTION_COEFFICIENT),
mFlickSpeedCoefficient(DEFAULT_FLICK_SPEED_COEFFICIENT),
mMaxFlickSpeed(DEFAULT_MAX_FLICK_SPEED),
- mMouseWheelScrollDistanceStep(Vector2::ZERO),
+ mWheelScrollDistanceStep(Vector2::ZERO),
mInAccessibilityPan(false),
- mInitialized(false),
mScrolling(false),
mScrollInterrupted(false),
mPanning(false),
// Internal Actor, used to hide actors from enumerations.
// Also actors added to Internal actor appear as overlays e.g. ScrollBar components.
mInternalActor = Actor::New();
- mInternalActor.SetDrawMode(DrawMode::OVERLAY);
self.Add(mInternalActor);
mInternalActor.SetParentOrigin(ParentOrigin::CENTER);
mScrollPostPosition = mScrollPrePosition = Vector2::ZERO;
- mMouseWheelScrollDistanceStep = Stage::GetCurrent().GetSize() * DEFAULT_MOUSE_WHEEL_SCROLL_DISTANCE_STEP_PROPORTION;
-
- mInitialized = true;
+ mWheelScrollDistanceStep = Stage::GetCurrent().GetSize() * DEFAULT_WHEEL_SCROLL_DISTANCE_STEP_PROPORTION;
mGestureStackDepth = 0;
mRulerX = ruler;
mRulerY = ruler;
- SetOvershootEnabled(true);
-
self.SetProperty(Toolkit::Scrollable::Property::CAN_SCROLL_VERTICAL, mCanScrollVertical);
self.SetProperty(Toolkit::Scrollable::Property::CAN_SCROLL_HORIZONTAL, mCanScrollHorizontal);
SetInternalConstraints();
}
-void ScrollView::OnControlStageConnection()
+void ScrollView::OnStageConnection( int depth )
{
DALI_LOG_SCROLL_STATE("[0x%X]", this);
}
}
-void ScrollView::OnControlStageDisconnection()
+void ScrollView::OnStageDisconnection()
{
DALI_LOG_SCROLL_STATE("[0x%X]", this);
mMaxFlickSpeed = speed;
}
-void ScrollView::SetMouseWheelScrollDistanceStep(Vector2 step)
+void ScrollView::SetWheelScrollDistanceStep(Vector2 step)
{
- mMouseWheelScrollDistanceStep = step;
+ mWheelScrollDistanceStep = step;
}
-Vector2 ScrollView::GetMouseWheelScrollDistanceStep() const
+Vector2 ScrollView::GetWheelScrollDistanceStep() const
{
- return mMouseWheelScrollDistanceStep;
+ return mWheelScrollDistanceStep;
}
unsigned int ScrollView::GetCurrentPage() const
return -GetPropertyPosition();
}
-void ScrollView::SetScrollPosition(const Vector2& position)
-{
- mScrollPrePosition = position;
-}
-
Vector2 ScrollView::GetDomainSize() const
{
Vector3 size = Self().GetCurrentSize();
void ScrollView::EnableScrollOvershoot(bool enable)
{
- if(enable && !mOvershootIndicator)
- {
- mOvershootIndicator = ScrollOvershootIndicator::New();
- }
- if( enable )
+ if (enable)
{
+ if (!mOvershootIndicator)
+ {
+ mOvershootIndicator = ScrollOvershootIndicator::New();
+ }
+
mOvershootIndicator->AttachToScrollable(*this);
}
else
{
mMaxOvershoot = mUserMaxOvershoot;
- mOvershootIndicator->DetachFromScrollable(*this);
+
+ if (mOvershootIndicator)
+ {
+ mOvershootIndicator->DetachFromScrollable(*this);
+ }
}
+
UpdateMainInternalConstraint();
}
void ScrollView::AddOverlay(Actor actor)
{
+ actor.SetDrawMode( DrawMode::OVERLAY_2D );
mInternalActor.Add( actor );
}
UpdatePropertyDomain();
}
-void ScrollView::OnControlSizeSet( const Vector3& size )
+void ScrollView::OnSizeSet( const Vector3& size )
{
// need to update domain properties for new size
if( mDefaultMaxOvershoot )
return true;
}
-bool ScrollView::OnMouseWheelEvent(const MouseWheelEvent& event)
+bool ScrollView::OnWheelEvent(const WheelEvent& event)
{
if(!mSensitive)
{
- // Ignore this mouse wheel event, if scrollview is insensitive.
+ // Ignore this wheel event, if scrollview is insensitive.
return false;
}
if(mRulerX->GetType() == Ruler::Free)
{
// Free panning mode
- targetScrollPosition.x += event.z * mMouseWheelScrollDistanceStep.x;
+ targetScrollPosition.x += event.z * mWheelScrollDistanceStep.x;
ClampPosition(targetScrollPosition);
ScrollTo(-targetScrollPosition);
}
if(mRulerY->GetType() == Ruler::Free)
{
// Free panning mode
- targetScrollPosition.y += event.z * mMouseWheelScrollDistanceStep.y;
+ targetScrollPosition.y += event.z * mWheelScrollDistanceStep.y;
ClampPosition(targetScrollPosition);
ScrollTo(-targetScrollPosition);
}
{
mScrollMainInternalPrePositionConstraint.Remove();
}
-
- if( mOvershootIndicator )
- {
- mOvershootIndicator->ClearOvershoot();
- }
}
else
{
mAxisAutoLockGradient,
mLockAxis,
mMaxOvershoot,
- mRulerX->GetDomain(),
- mRulerY->GetDomain() ) );
+ mRulerX,
+ mRulerY ) );
mScrollMainInternalPrePositionConstraint.AddSource( Source( detector, PanGestureDetector::Property::LOCAL_POSITION ) );
mScrollMainInternalPrePositionConstraint.AddSource( Source( self, Actor::Property::SIZE ) );
mScrollMainInternalPrePositionConstraint.Apply();