X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=blobdiff_plain;f=dali-toolkit%2Finternal%2Fcontrols%2Fscrollable%2Fscroll-view%2Fscroll-view-impl.cpp;h=3063cbcf57f4f9f8f9cf15115543e9cc46e04ace;hp=86e9173baa8602108479ceff4e9c87db36e76c99;hb=95afb515eab9557a404015e26a210c07889f53b9;hpb=906b5eed2f9ddd8c03ac4b7b4b6aee7547bab42d diff --git a/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-impl.cpp b/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-impl.cpp index 86e9173..3063cbc 100644 --- a/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-impl.cpp +++ b/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-impl.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * Copyright (c) 2017 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. @@ -23,9 +23,10 @@ #include #include #include -#include +#include #include -#include +#include +#include #include // INTERNAL INCLUDES @@ -74,7 +75,7 @@ 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 -const std::string INTERNAL_MAX_POSITION_PROPERTY_NAME( "internal-max-position" ); +const std::string INTERNAL_MAX_POSITION_PROPERTY_NAME( "internalMaxPosition" ); // Helpers //////////////////////////////////////////////////////////////////////////////////////// @@ -244,29 +245,34 @@ BaseHandle Create() // 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_PROPERTY_REGISTRATION( Toolkit, ScrollView, "wrapEnabled", BOOLEAN, WRAP_ENABLED ) +DALI_PROPERTY_REGISTRATION( Toolkit, ScrollView, "panningEnabled", BOOLEAN, PANNING_ENABLED ) +DALI_PROPERTY_REGISTRATION( Toolkit, ScrollView, "axisAutoLockEnabled", BOOLEAN, AXIS_AUTO_LOCK_ENABLED ) +DALI_PROPERTY_REGISTRATION( Toolkit, ScrollView, "wheelScrollDistanceStep", VECTOR2, WHEEL_SCROLL_DISTANCE_STEP ) + +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() @@ -313,93 +319,132 @@ ScrollView::LockAxis GetLockAxis(const Vector2& panDelta, ScrollView::LockAxis c */ 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 ) + { + 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 ) { - mPrePosition.y = newYPosition; - mLocalStart.y = panPosition.y; + // 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; @@ -408,10 +453,12 @@ struct InternalPrePositionConstraint 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; }; /** @@ -578,7 +625,7 @@ Dali::Toolkit::ScrollView ScrollView::New() } ScrollView::ScrollView() -: ScrollBase( ControlBehaviour( REQUIRES_WHEEL_EVENTS ) ), // Enable size negotiation +: ScrollBase( ControlBehaviour( REQUIRES_WHEEL_EVENTS | DISABLE_STYLE_CHANGE_SIGNALS ) ), // Enable size negotiation mTouchDownTime(0u), mGestureStackDepth(0), mScrollStateFlags(0), @@ -600,7 +647,6 @@ ScrollView::ScrollView() mMaxFlickSpeed(DEFAULT_MAX_FLICK_SPEED), mWheelScrollDistanceStep(Vector2::ZERO), mInAccessibilityPan(false), - mInitialized(false), mScrolling(false), mScrollInterrupted(false), mPanning(false), @@ -613,7 +659,8 @@ ScrollView::ScrollView() mAlterChild(false), mDefaultMaxOvershoot(true), mCanScrollHorizontal(true), - mCanScrollVertical(true) + mCanScrollVertical(true), + mTransientScrollBar(true) { } @@ -636,10 +683,9 @@ void ScrollView::OnInitialize() mWheelScrollDistanceStep = Stage::GetCurrent().GetSize() * DEFAULT_WHEEL_SCROLL_DISTANCE_STEP_PROPORTION; - mInitialized = true; - mGestureStackDepth = 0; + self.TouchSignal().Connect( this, &ScrollView::OnTouch ); EnableGestureDetection( Gesture::Type( Gesture::Pan ) ); // By default we'll allow the user to freely drag the scroll view, @@ -648,8 +694,6 @@ void ScrollView::OnInitialize() mRulerX = ruler; mRulerY = ruler; - SetOvershootEnabled(true); - self.SetProperty(Toolkit::Scrollable::Property::CAN_SCROLL_VERTICAL, mCanScrollVertical); self.SetProperty(Toolkit::Scrollable::Property::CAN_SCROLL_HORIZONTAL, mCanScrollHorizontal); @@ -666,11 +710,14 @@ void ScrollView::OnStageConnection( int depth ) SetScrollSensitive( false ); SetScrollSensitive( true ); } + if(IsOvershootEnabled()) { // try and make sure property notifications are set EnableScrollOvershoot(true); } + + ScrollBase::OnStageConnection( depth ); } void ScrollView::OnStageDisconnection() @@ -678,6 +725,8 @@ void ScrollView::OnStageDisconnection() DALI_LOG_SCROLL_STATE("[0x%X]", this); StopAnimation(); + + ScrollBase::OnStageDisconnection(); } ScrollView::~ScrollView() @@ -926,6 +975,11 @@ void ScrollView::UpdatePropertyDomain() } } +bool ScrollView::GetScrollSensitive() +{ + return mSensitive; +} + void ScrollView::SetScrollSensitive(bool sensitive) { Actor self = Self(); @@ -971,11 +1025,21 @@ void ScrollView::SetSnapOvershootAlphaFunction(AlphaFunction alpha) mSnapOvershootAlphaFunction = alpha; } +float ScrollView::GetSnapOvershootDuration() +{ + return mSnapOvershootDuration; +} + void ScrollView::SetSnapOvershootDuration(float duration) { mSnapOvershootDuration = duration; } +bool ScrollView::GetActorAutoSnap() +{ + return mActorAutoSnapEnabled; +} + void ScrollView::SetActorAutoSnap(bool enable) { mActorAutoSnapEnabled = enable; @@ -1115,19 +1179,6 @@ Vector2 ScrollView::GetCurrentScrollPosition() const return -GetPropertyPosition(); } -Vector2 ScrollView::GetDomainSize() const -{ - Vector3 size = Self().GetCurrentSize(); - - const RulerDomain& xDomain = GetRulerX()->GetDomain(); - const RulerDomain& yDomain = GetRulerY()->GetDomain(); - - Vector2 domainSize; - domainSize.x = xDomain.max - xDomain.min - size.x; - domainSize.y = yDomain.max - yDomain.min - size.y; - return domainSize; -} - void ScrollView::TransformTo(const Vector2& position, DirectionBias horizontalBias, DirectionBias verticalBias) { @@ -1645,6 +1696,7 @@ bool ScrollView::AnimateTo(const Vector2& position, const Vector2& positionDurat // Position Delta /////////////////////////////////////////////////////// if(positionChanged) { + UpdateMainInternalConstraint(); if(mWrapMode && findShortcuts) { // In Wrap Mode, the shortest distance is a little less intuitive... @@ -1698,19 +1750,25 @@ bool ScrollView::AnimateTo(const Vector2& position, const Vector2& positionDurat 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(); } @@ -1725,6 +1783,15 @@ void ScrollView::RemoveOverlay(Actor actor) mInternalActor.Remove( actor ); } +void ScrollView::SetOvershootSize( const Vector2& size ) +{ + mOvershootSize = size; + if( IsOvershootEnabled() && mOvershootIndicator ) + { + mOvershootIndicator->AttachToScrollable(*this); + } +} + void ScrollView::SetOvershootEffectColor( const Vector4& color ) { mOvershootEffectColor = color; @@ -1886,29 +1953,43 @@ void ScrollView::OnSizeSet( const Vector3& size ) { mOvershootIndicator->Reset(); } + + ScrollBase::OnSizeSet( size ); } void ScrollView::OnChildAdd(Actor& child) { + ScrollBase::OnChildAdd( child ); + Dali::Toolkit::ScrollBar scrollBar = Dali::Toolkit::ScrollBar::DownCast(child); - if(scrollBar) + if( scrollBar ) { - mInternalActor.Add(scrollBar); - if(scrollBar.GetScrollDirection() == Toolkit::ScrollBar::Horizontal) + mScrollBar = scrollBar; + scrollBar.SetName("ScrollBar"); + + mInternalActor.Add( scrollBar ); + if( scrollBar.GetScrollDirection() == Toolkit::ScrollBar::Horizontal ) { - scrollBar.SetScrollPropertySource(Self(), - Toolkit::ScrollView::Property::SCROLL_PRE_POSITION_X, - Toolkit::Scrollable::Property::SCROLL_POSITION_MIN_X, - Toolkit::ScrollView::Property::SCROLL_PRE_POSITION_MAX_X, - Toolkit::ScrollView::Property::SCROLL_DOMAIN_SIZE_X); + scrollBar.SetScrollPropertySource( Self(), + Toolkit::ScrollView::Property::SCROLL_PRE_POSITION_X, + Toolkit::Scrollable::Property::SCROLL_POSITION_MIN_X, + Toolkit::ScrollView::Property::SCROLL_PRE_POSITION_MAX_X, + Toolkit::ScrollView::Property::SCROLL_DOMAIN_SIZE_X ); } else { - scrollBar.SetScrollPropertySource(Self(), - Toolkit::ScrollView::Property::SCROLL_PRE_POSITION_Y, - Toolkit::Scrollable::Property::SCROLL_POSITION_MIN_Y, - Toolkit::ScrollView::Property::SCROLL_PRE_POSITION_MAX_Y, - Toolkit::ScrollView::Property::SCROLL_DOMAIN_SIZE_Y); + scrollBar.SetScrollPropertySource( Self(), + Toolkit::ScrollView::Property::SCROLL_PRE_POSITION_Y, + Toolkit::Scrollable::Property::SCROLL_POSITION_MIN_Y, + Toolkit::ScrollView::Property::SCROLL_PRE_POSITION_MAX_Y, + Toolkit::ScrollView::Property::SCROLL_DOMAIN_SIZE_Y ); + } + + if( mTransientScrollBar ) + { + // Show the scroll-indicator for a brief period + Property::Map emptyMap; + scrollBar.DoAction( "ShowTransientIndicator", emptyMap ); } } else if(mAlterChild) @@ -1921,6 +2002,8 @@ void ScrollView::OnChildRemove(Actor& child) { // TODO: Actor needs a RemoveConstraint method to take out an individual constraint. UnbindActor(child); + + ScrollBase::OnChildRemove( child ); } void ScrollView::StartTouchDownTimer() @@ -1973,7 +2056,7 @@ bool ScrollView::OnTouchDownTimeout() return false; } -bool ScrollView::OnTouchEvent(const TouchEvent& event) +bool ScrollView::OnTouch( Actor actor, const TouchData& touch ) { if(!mSensitive) { @@ -1984,21 +2067,21 @@ bool ScrollView::OnTouchEvent(const TouchEvent& event) } // Ignore events with multiple-touch points - if (event.GetPointCount() != 1) + if (touch.GetPointCount() != 1) { DALI_LOG_SCROLL_STATE("[0x%X], multiple touch, ignoring", this); return false; } - const TouchPoint::State pointState = event.GetPoint(0).state; - if( pointState == TouchPoint::Down ) + const PointState::Type pointState = touch.GetState( 0 ); + if( pointState == PointState::DOWN ) { DALI_LOG_SCROLL_STATE("[0x%X] Down", this); if(mGestureStackDepth==0) { - mTouchDownTime = event.time; + mTouchDownTime = touch.GetTime(); // 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. @@ -2007,8 +2090,8 @@ bool ScrollView::OnTouchEvent(const TouchEvent& event) StartTouchDownTimer(); } } - else if( ( pointState == TouchPoint::Up ) || - ( ( pointState == TouchPoint::Interrupted ) && ( event.GetPoint(0).hitActor == Self() ) ) ) + else if( ( pointState == PointState::UP ) || + ( ( pointState == PointState::INTERRUPTED ) && ( touch.GetHitActor( 0 )== Self() ) ) ) { DALI_LOG_SCROLL_STATE("[0x%X] %s", this, ( ( pointState == TouchPoint::Up ) ? "Up" : "Interrupted" ) ); @@ -2019,8 +2102,8 @@ bool ScrollView::OnTouchEvent(const TouchEvent& event) // otherwise our scroll could be stopped (interrupted) half way through an animation. if(mGestureStackDepth==0 && mTouchDownTimeoutReached) { - if( ( event.GetPoint(0).state == TouchPoint::Interrupted ) || - ( ( event.time - mTouchDownTime ) >= MINIMUM_TIME_BETWEEN_DOWN_AND_UP_FOR_RESET ) ) + if( ( pointState == PointState::INTERRUPTED ) || + ( ( touch.GetTime() - mTouchDownTime ) >= 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 ); @@ -2405,6 +2488,18 @@ void ScrollView::OnPan( const PanGesture& gesture ) self.SetProperty( Toolkit::ScrollView::Property::START_PAGE_POSITION, Vector3(gesture.position.x, gesture.position.y, 0.0f) ); UpdateMainInternalConstraint(); + Toolkit::ScrollBar scrollBar = mScrollBar.GetHandle(); + if( scrollBar && mTransientScrollBar ) + { + Vector3 size = Self().GetCurrentSize(); + const Toolkit::RulerDomain& rulerDomainX = mRulerX->GetDomain(); + const Toolkit::RulerDomain& rulerDomainY = mRulerY->GetDomain(); + + if( ( rulerDomainX.max > size.width ) || ( rulerDomainY.max > size.height ) ) + { + scrollBar.ShowIndicator(); + } + } break; } @@ -2440,9 +2535,10 @@ void ScrollView::OnPan( const PanGesture& gesture ) mScrollMainInternalPrePositionConstraint.Remove(); } - if( mOvershootIndicator ) + Toolkit::ScrollBar scrollBar = mScrollBar.GetHandle(); + if( scrollBar && mTransientScrollBar ) { - mOvershootIndicator->ClearOvershoot(); + scrollBar.HideIndicator(); } } else @@ -2662,9 +2758,10 @@ void ScrollView::UpdateMainInternalConstraint() 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(); } @@ -2779,6 +2876,76 @@ void ScrollView::SetInternalConstraints() ApplyConstraintToBoundActors(constraint); } +void ScrollView::SetProperty( BaseObject* object, Property::Index index, const Property::Value& value ) +{ + Toolkit::ScrollView scrollView = Toolkit::ScrollView::DownCast( Dali::BaseHandle( object ) ); + + if( scrollView ) + { + ScrollView& scrollViewImpl( GetImpl( scrollView ) ); + switch( index ) + { + case Toolkit::ScrollView::Property::WRAP_ENABLED: + { + scrollViewImpl.SetWrapMode( value.Get() ); + break; + } + case Toolkit::ScrollView::Property::PANNING_ENABLED: + { + scrollViewImpl.SetScrollSensitive( value.Get() ); + break; + } + case Toolkit::ScrollView::Property::AXIS_AUTO_LOCK_ENABLED: + { + scrollViewImpl.SetAxisAutoLock( value.Get() ); + break; + } + case Toolkit::ScrollView::Property::WHEEL_SCROLL_DISTANCE_STEP: + { + scrollViewImpl.SetWheelScrollDistanceStep( value.Get() ); + break; + } + } + } +} + +Property::Value ScrollView::GetProperty( BaseObject* object, Property::Index index ) +{ + Property::Value value; + + Toolkit::ScrollView scrollView = Toolkit::ScrollView::DownCast( Dali::BaseHandle( object ) ); + + if( scrollView ) + { + ScrollView& scrollViewImpl( GetImpl( scrollView ) ); + switch( index ) + { + case Toolkit::ScrollView::Property::WRAP_ENABLED: + { + value = scrollViewImpl.GetWrapMode(); + break; + } + case Toolkit::ScrollView::Property::PANNING_ENABLED: + { + value = scrollViewImpl.GetScrollSensitive(); + break; + } + case Toolkit::ScrollView::Property::AXIS_AUTO_LOCK_ENABLED: + { + value = scrollViewImpl.GetAxisAutoLock(); + break; + } + case Toolkit::ScrollView::Property::WHEEL_SCROLL_DISTANCE_STEP: + { + value = scrollViewImpl.GetWheelScrollDistanceStep(); + break; + } + } + } + + return value; +} + } // namespace Internal } // namespace Toolkit