WheelEvent class pimpling
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / controls / scrollable / scroll-view / scroll-view-impl.cpp
index 0d8becc..a4ebfa9 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2020 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.
 // EXTERNAL INCLUDES
 #include <cstring> // for strcmp
 #include <dali/public-api/animation/constraints.h>
-#include <dali/public-api/common/stage.h>
+#include <dali/devel-api/common/stage.h>
 #include <dali/public-api/events/wheel-event.h>
-#include <dali/public-api/events/touch-data.h>
+#include <dali/public-api/events/touch-event.h>
 #include <dali/public-api/object/type-registry.h>
 #include <dali/public-api/object/type-registry-helper.h>
+#include <dali/public-api/object/property-map.h>
+#include <dali/devel-api/object/property-helper-devel.h>
 #include <dali/integration-api/debug.h>
 
 // INTERNAL INCLUDES
-#include <dali-toolkit/public-api/controls/scroll-bar/scroll-bar.h>
+#include <dali-toolkit/devel-api/controls/scroll-bar/scroll-bar.h>
 #include <dali-toolkit/public-api/controls/scrollable/scroll-view/scroll-view.h>
 #include <dali-toolkit/public-api/controls/scrollable/scroll-view/scroll-view-constraints.h>
+#include <dali-toolkit/public-api/controls/scrollable/scroll-view/scroll-mode.h>
 #include <dali-toolkit/internal/controls/scrollable/scroll-view/scroll-overshoot-indicator-impl.h>
 #include <dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-effect-impl.h>
 
 //#define ENABLED_SCROLL_STATE_LOGGING
 
 #ifdef ENABLED_SCROLL_STATE_LOGGING
-#define DALI_LOG_SCROLL_STATE(format, args...) Dali::Integration::Log::LogMessage(Dali::Integration::Log::DebugInfo, "%s:%d " format "\n", __PRETTY_FUNCTION__, __LINE__, ## args)
+#define DALI_LOG_SCROLL_STATE(format, ...) Dali::Integration::Log::LogMessage(Dali::Integration::Log::DebugInfo, "%s:%d " format "\n", __PRETTY_FUNCTION__, __LINE__, ## __VA_ARGS__)
 #else
-#define DALI_LOG_SCROLL_STATE(format, args...)
+#define DALI_LOG_SCROLL_STATE(format, ...)
 #endif
 
 // TODO: Change to two class system:
@@ -142,9 +145,9 @@ float VectorInDomain(float a, float b, float start, float end, Dali::Toolkit::Di
  */
 Vector3 GetPositionOfAnchor(Actor &actor, const Vector3 &anchor)
 {
-  Vector3 childPosition = actor.GetCurrentPosition();
-  Vector3 childAnchor = - actor.GetCurrentAnchorPoint() + anchor;
-  Vector3 childSize = actor.GetCurrentSize();
+  Vector3 childPosition = actor.GetCurrentProperty< Vector3 >( Actor::Property::POSITION );
+  Vector3 childAnchor = - actor.GetCurrentProperty< Vector3 >( Actor::Property::ANCHOR_POINT ) + anchor;
+  Vector3 childSize = actor.GetCurrentProperty< Vector3 >( Actor::Property::SIZE );
 
   return childPosition + childAnchor * childSize;
 }
@@ -248,6 +251,7 @@ DALI_PROPERTY_REGISTRATION( Toolkit, ScrollView, "wrapEnabled",                B
 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_PROPERTY_REGISTRATION( Toolkit, ScrollView, "scrollMode",                 MAP,       SCROLL_MODE )
 
 DALI_ANIMATABLE_PROPERTY_REGISTRATION( Toolkit, ScrollView, "scrollPosition",  VECTOR2, SCROLL_POSITION)
 DALI_ANIMATABLE_PROPERTY_REGISTRATION( Toolkit, ScrollView, "scrollPrePosition",   VECTOR2, SCROLL_PRE_POSITION)
@@ -424,9 +428,9 @@ struct InternalPrePositionConstraint
         // 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 );
+        Vector2 viewPageSizeLimit( size.x - ( 1.0f + 1.0f ), size.y - ( 1.0f - 1.0f ) );
+        Vector2 minPosition( mStartPosition.x - viewPageSizeLimit.x, mStartPosition.y - viewPageSizeLimit.y );
+        Vector2 maxPosition( mStartPosition.x + viewPageSizeLimit.x, mStartPosition.y + viewPageSizeLimit.y );
 
         if( mFixedRulerX )
         {
@@ -658,7 +662,8 @@ ScrollView::ScrollView()
   mAlterChild(false),
   mDefaultMaxOvershoot(true),
   mCanScrollHorizontal(true),
-  mCanScrollVertical(true)
+  mCanScrollVertical(true),
+  mTransientScrollBar(true)
 {
 }
 
@@ -671,8 +676,8 @@ void ScrollView::OnInitialize()
   mInternalActor = Actor::New();
   self.Add(mInternalActor);
 
-  mInternalActor.SetParentOrigin(ParentOrigin::CENTER);
-  mInternalActor.SetAnchorPoint(AnchorPoint::CENTER);
+  mInternalActor.SetProperty( Actor::Property::PARENT_ORIGIN,ParentOrigin::CENTER );
+  mInternalActor.SetProperty( Actor::Property::ANCHOR_POINT,AnchorPoint::CENTER);
   mInternalActor.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS );
 
   mAlterChild = true;
@@ -699,10 +704,8 @@ void ScrollView::OnInitialize()
   SetInternalConstraints();
 }
 
-void ScrollView::OnStageConnection( int depth )
+void ScrollView::OnSceneConnection( int depth )
 {
-  ScrollBase::OnStageConnection( depth );
-
   DALI_LOG_SCROLL_STATE("[0x%X]", this);
 
   if ( mSensitive )
@@ -710,20 +713,23 @@ void ScrollView::OnStageConnection( int depth )
     SetScrollSensitive( false );
     SetScrollSensitive( true );
   }
+
   if(IsOvershootEnabled())
   {
     // try and make sure property notifications are set
     EnableScrollOvershoot(true);
   }
+
+  ScrollBase::OnSceneConnection( depth );
 }
 
-void ScrollView::OnStageDisconnection()
+void ScrollView::OnSceneDisconnection()
 {
   DALI_LOG_SCROLL_STATE("[0x%X]", this);
 
   StopAnimation();
 
-  ScrollBase::OnStageDisconnection();
+  ScrollBase::OnSceneDisconnection();
 }
 
 ScrollView::~ScrollView()
@@ -1315,8 +1321,8 @@ void ScrollView::ScrollTo(Actor &actor, float duration)
   DALI_ASSERT_ALWAYS(actor.GetParent() == Self());
 
   Actor self = Self();
-  Vector3 size = self.GetCurrentSize();
-  Vector3 position = actor.GetCurrentPosition();
+  Vector3 size = self.GetCurrentProperty< Vector3 >( Actor::Property::SIZE );
+  Vector3 position = actor.GetCurrentProperty< Vector3 >( Actor::Property::POSITION );
   Vector2 prePosition = GetPropertyPrePosition();
   position.GetVectorXY() -= prePosition;
 
@@ -1326,7 +1332,7 @@ void ScrollView::ScrollTo(Actor &actor, float duration)
 Actor ScrollView::FindClosestActor()
 {
   Actor self = Self();
-  Vector3 size = self.GetCurrentSize();
+  Vector3 size = self.GetCurrentProperty< Vector3 >( Actor::Property::SIZE );
 
   return FindClosestActorToPosition(Vector3(size.width * 0.5f,size.height * 0.5f,0.0f));
 }
@@ -1518,7 +1524,7 @@ bool ScrollView::SnapWithVelocity(Vector2 velocity)
 
   if(mActorAutoSnapEnabled)
   {
-    Vector3 size = Self().GetCurrentSize();
+    Vector3 size = Self().GetCurrentProperty< Vector3 >( Actor::Property::SIZE );
 
     Actor child = FindClosestActorToPosition( Vector3(size.width * 0.5f,size.height * 0.5f,0.0f), horizontal, vertical );
 
@@ -1530,7 +1536,7 @@ bool ScrollView::SnapWithVelocity(Vector2 velocity)
 
     if(child)
     {
-      Vector2 position = Self().GetProperty<Vector2>(Toolkit::ScrollView::Property::SCROLL_POSITION);
+      Vector2 position = Self().GetCurrentProperty<Vector2>( Toolkit::ScrollView::Property::SCROLL_POSITION );
 
       // Get center-point of the Actor.
       Vector3 childPosition = GetPositionOfAnchor(child, AnchorPoint::CENTER);
@@ -1728,7 +1734,7 @@ bool ScrollView::AnimateTo(const Vector2& position, const Vector2& positionDurat
     }
 
     DALI_LOG_SCROLL_STATE("[0x%X] position-changed, mScrollTargetPosition[%.2f, %.2f], mScrollPrePosition[%.2f, %.2f], mScrollPostPosition[%.2f, %.2f]", this, mScrollTargetPosition.x, mScrollTargetPosition.y, mScrollPrePosition.x, mScrollPrePosition.y, mScrollPostPosition.x, mScrollPostPosition.y );
-    DALI_LOG_SCROLL_STATE("[0x%X] SCROLL_PRE_POSITION[%.2f, %.2f], SCROLL_POSITION[%.2f, %.2f]", this, self.GetProperty( Toolkit::ScrollView::Property::SCROLL_PRE_POSITION ).Get<Vector2>().x, self.GetProperty( Toolkit::ScrollView::Property::SCROLL_PRE_POSITION ).Get<Vector2>().y, self.GetProperty( Toolkit::ScrollView::Property::SCROLL_POSITION ).Get<Vector2>().x, self.GetProperty( Toolkit::ScrollView::Property::SCROLL_POSITION ).Get<Vector2>().y );
+    DALI_LOG_SCROLL_STATE("[0x%X] SCROLL_PRE_POSITION[%.2f, %.2f], SCROLL_POSITION[%.2f, %.2f]", this, self.GetCurrentProperty( Toolkit::ScrollView::Property::SCROLL_PRE_POSITION ).Get<Vector2>().x, self.GetCurrentProperty( Toolkit::ScrollView::Property::SCROLL_PRE_POSITION ).Get<Vector2>().y, self.GetCurrentProperty( Toolkit::ScrollView::Property::SCROLL_POSITION ).Get<Vector2>().x, self.GetCurrentProperty( Toolkit::ScrollView::Property::SCROLL_POSITION ).Get<Vector2>().y );
   }
 
   SetScrollUpdateNotification(true);
@@ -1771,7 +1777,7 @@ void ScrollView::EnableScrollOvershoot(bool enable)
 
 void ScrollView::AddOverlay(Actor actor)
 {
-  actor.SetDrawMode( DrawMode::OVERLAY_2D );
+  actor.SetProperty( Actor::Property::DRAW_MODE, DrawMode::OVERLAY_2D );
   mInternalActor.Add( actor );
 }
 
@@ -1780,6 +1786,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;
@@ -1816,14 +1831,14 @@ void ScrollView::FindAndUnbindActor(Actor child)
 
 Vector2 ScrollView::GetPropertyPrePosition() const
 {
-  Vector2 position = Self().GetProperty<Vector2>(Toolkit::ScrollView::Property::SCROLL_PRE_POSITION);
+  Vector2 position = Self().GetCurrentProperty< Vector2 >( Toolkit::ScrollView::Property::SCROLL_PRE_POSITION );
   WrapPosition(position);
   return position;
 }
 
 Vector2 ScrollView::GetPropertyPosition() const
 {
-  Vector2 position = Self().GetProperty<Vector2>(Toolkit::ScrollView::Property::SCROLL_POSITION);
+  Vector2 position = Self().GetCurrentProperty< Vector2 >( Toolkit::ScrollView::Property::SCROLL_POSITION );
   WrapPosition(position);
 
   return position;
@@ -1941,6 +1956,8 @@ void ScrollView::OnSizeSet( const Vector3& size )
   {
     mOvershootIndicator->Reset();
   }
+
+  ScrollBase::OnSizeSet( size );
 }
 
 void ScrollView::OnChildAdd(Actor& child)
@@ -1948,24 +1965,34 @@ 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.SetProperty( Dali::Actor::Property::NAME,"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)
@@ -2032,7 +2059,7 @@ bool ScrollView::OnTouchDownTimeout()
   return false;
 }
 
-bool ScrollView::OnTouch( Actor actor, const TouchData& touch )
+bool ScrollView::OnTouch( Actor actor, const TouchEvent& touch )
 {
   if(!mSensitive)
   {
@@ -2098,7 +2125,7 @@ bool ScrollView::OnTouch( Actor actor, const TouchData& touch )
     mScrollInterrupted = false;
   }
 
-  return true;
+  return false;
 }
 
 bool ScrollView::OnWheelEvent(const WheelEvent& event)
@@ -2117,14 +2144,14 @@ bool ScrollView::OnWheelEvent(const WheelEvent& event)
     if(mRulerX->GetType() == Ruler::Free)
     {
       // Free panning mode
-      targetScrollPosition.x += event.z * mWheelScrollDistanceStep.x;
+      targetScrollPosition.x += event.GetDelta() * mWheelScrollDistanceStep.x;
       ClampPosition(targetScrollPosition);
       ScrollTo(-targetScrollPosition);
     }
     else if(!mScrolling)
     {
       // Snap mode, only respond to the event when the previous snap animation is finished.
-      ScrollTo(GetCurrentPage() - event.z);
+      ScrollTo(GetCurrentPage() - event.GetDelta());
     }
   }
   else
@@ -2133,14 +2160,14 @@ bool ScrollView::OnWheelEvent(const WheelEvent& event)
     if(mRulerY->GetType() == Ruler::Free)
     {
       // Free panning mode
-      targetScrollPosition.y += event.z * mWheelScrollDistanceStep.y;
+      targetScrollPosition.y += event.GetDelta() * mWheelScrollDistanceStep.y;
       ClampPosition(targetScrollPosition);
       ScrollTo(-targetScrollPosition);
     }
     else if(!mScrolling)
     {
       // Snap mode, only respond to the event when the previous snap animation is finished.
-      ScrollTo(GetCurrentPage() - event.z * mRulerX->GetTotalPages());
+      ScrollTo(GetCurrentPage() - event.GetDelta() * mRulerX->GetTotalPages());
     }
   }
 
@@ -2150,7 +2177,7 @@ bool ScrollView::OnWheelEvent(const WheelEvent& event)
 void ScrollView::ResetScrolling()
 {
   Actor self = Self();
-  self.GetProperty(Toolkit::ScrollView::Property::SCROLL_POSITION).Get(mScrollPostPosition);
+  self.GetCurrentProperty( Toolkit::ScrollView::Property::SCROLL_POSITION ).Get( mScrollPostPosition );
   mScrollPrePosition = mScrollPostPosition;
   DALI_LOG_SCROLL_STATE("[0x%X] Setting SCROLL_PRE_POSITION To[%.2f, %.2f]", this, mScrollPostPosition.x, mScrollPostPosition.y );
   self.SetProperty(Toolkit::ScrollView::Property::SCROLL_PRE_POSITION, mScrollPostPosition);
@@ -2159,8 +2186,8 @@ void ScrollView::ResetScrolling()
 void ScrollView::UpdateLocalScrollProperties()
 {
   Actor self = Self();
-  self.GetProperty(Toolkit::ScrollView::Property::SCROLL_PRE_POSITION).Get(mScrollPrePosition);
-  self.GetProperty(Toolkit::ScrollView::Property::SCROLL_POSITION).Get(mScrollPostPosition);
+  self.GetCurrentProperty( Toolkit::ScrollView::Property::SCROLL_PRE_POSITION ).Get( mScrollPrePosition );
+  self.GetCurrentProperty( Toolkit::ScrollView::Property::SCROLL_POSITION ).Get( mScrollPostPosition );
 }
 
 // private functions
@@ -2206,7 +2233,7 @@ void ScrollView::AnimateInternalXTo( float position, float duration, AlphaFuncti
   if( duration > Math::MACHINE_EPSILON_10 )
   {
     Actor self = Self();
-    DALI_LOG_SCROLL_STATE("[0x%X], Animating from[%.2f] to[%.2f]", this, self.GetProperty(Toolkit::ScrollView::Property::SCROLL_PRE_POSITION).Get<Vector2>().x, position );
+    DALI_LOG_SCROLL_STATE("[0x%X], Animating from[%.2f] to[%.2f]", this, self.GetCurrentProperty(  Toolkit::ScrollView::Property::SCROLL_PRE_POSITION ).Get< Vector2 >().x, position );
     mInternalXAnimation = Animation::New(duration);
     DALI_LOG_SCROLL_STATE("[0x%X], mInternalXAnimation[0x%X]", this, mInternalXAnimation.GetObjectPtr() );
     mInternalXAnimation.FinishedSignal().Connect(this, &ScrollView::OnScrollAnimationFinished);
@@ -2227,7 +2254,7 @@ void ScrollView::AnimateInternalYTo( float position, float duration, AlphaFuncti
   if( duration > Math::MACHINE_EPSILON_10 )
   {
     Actor self = Self();
-    DALI_LOG_SCROLL_STATE("[0x%X], Animating from[%.2f] to[%.2f]", this, self.GetProperty(Toolkit::ScrollView::Property::SCROLL_PRE_POSITION).Get<Vector2>().y, position );
+    DALI_LOG_SCROLL_STATE("[0x%X], Animating from[%.2f] to[%.2f]", this, self.GetCurrentProperty(  Toolkit::ScrollView::Property::SCROLL_PRE_POSITION ).Get< Vector2 >().y, position );
     mInternalYAnimation = Animation::New(duration);
     DALI_LOG_SCROLL_STATE("[0x%X], mInternalYAnimation[0x%X]", this, mInternalYAnimation.GetObjectPtr() );
     mInternalYAnimation.FinishedSignal().Connect(this, &ScrollView::OnScrollAnimationFinished);
@@ -2254,7 +2281,7 @@ void ScrollView::OnScrollAnimationFinished( Animation& source )
 
   if( source == mInternalXAnimation )
   {
-    DALI_LOG_SCROLL_STATE("[0x%X] mInternalXAnimation[0x%X], expected[%.2f], actual[%.2f], post[%.2f]", this, mInternalXAnimation.GetObjectPtr(), mScrollTargetPosition.x, Self().GetProperty(SCROLL_PRE_POSITION).Get<Vector2>().x, mScrollPostPosition.x );
+    DALI_LOG_SCROLL_STATE("[0x%X] mInternalXAnimation[0x%X], expected[%.2f], actual[%.2f], post[%.2f]", this, mInternalXAnimation.GetObjectPtr(), mScrollTargetPosition.x, Self().GetCurrentProperty( SCROLL_PRE_POSITION ).Get< Vector2 >().x, mScrollPostPosition.x );
 
     if( !(mScrollStateFlags & AnimatingInternalY) )
     {
@@ -2274,7 +2301,7 @@ void ScrollView::OnScrollAnimationFinished( Animation& source )
 
   if( source == mInternalYAnimation )
   {
-    DALI_LOG_SCROLL_STATE("[0x%X] mInternalYAnimation[0x%X], expected[%.2f], actual[%.2f], post[%.2f]", this, mInternalYAnimation.GetObjectPtr(), mScrollTargetPosition.y, Self().GetProperty(SCROLL_PRE_POSITION).Get<Vector2>().y, mScrollPostPosition.y );
+    DALI_LOG_SCROLL_STATE("[0x%X] mInternalYAnimation[0x%X], expected[%.2f], actual[%.2f], post[%.2f]", this, mInternalYAnimation.GetObjectPtr(), mScrollTargetPosition.y, DevelHandle::GetProperty( Self(), SCROLL_PRE_POSITION ).Get< Vector2 >().y, mScrollPostPosition.y );
 
     if( !(mScrollStateFlags & AnimatingInternalX) )
     {
@@ -2464,6 +2491,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().GetCurrentProperty< Vector3 >( Actor::Property::SIZE );
+        const Toolkit::RulerDomain& rulerDomainX = mRulerX->GetDomain();
+        const Toolkit::RulerDomain& rulerDomainY = mRulerY->GetDomain();
+
+        if( ( rulerDomainX.max > size.width ) || ( rulerDomainY.max > size.height ) )
+        {
+          scrollBar.ShowIndicator();
+        }
+      }
       break;
     }
 
@@ -2498,6 +2537,12 @@ void ScrollView::OnPan( const PanGesture& gesture )
         {
           mScrollMainInternalPrePositionConstraint.Remove();
         }
+
+        Toolkit::ScrollBar scrollBar = mScrollBar.GetHandle();
+        if( scrollBar && mTransientScrollBar )
+        {
+          scrollBar.HideIndicator();
+        }
       }
       else
       {
@@ -2590,7 +2635,7 @@ void ScrollView::FinishTransform()
 
 Vector2 ScrollView::GetOvershoot(Vector2& position) const
 {
-  Vector3 size = Self().GetCurrentSize();
+  Vector3 size = Self().GetCurrentProperty< Vector3 >( Actor::Property::SIZE );
   Vector2 overshoot;
 
   const RulerDomain rulerDomainX = mRulerX->GetDomain();
@@ -2645,7 +2690,7 @@ void ScrollView::ClampPosition(Vector2& position) const
 
 void ScrollView::ClampPosition(Vector2& position, ClampState2D &clamped) const
 {
-  Vector3 size = Self().GetCurrentSize();
+  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.
@@ -2863,6 +2908,14 @@ void ScrollView::SetProperty( BaseObject* object, Property::Index index, const P
         scrollViewImpl.SetWheelScrollDistanceStep( value.Get<Vector2>() );
         break;
       }
+      case Toolkit::ScrollView::Property::SCROLL_MODE:
+      {
+        Property::Map* map = value.GetMap();
+        if( map )
+        {
+          scrollViewImpl.SetScrollMode( *map );
+        }
+      }
     }
   }
 }
@@ -2904,6 +2957,90 @@ Property::Value ScrollView::GetProperty( BaseObject* object, Property::Index ind
   return value;
 }
 
+void ScrollView::SetScrollMode( const Property::Map& scrollModeMap )
+{
+  Toolkit::RulerPtr rulerX, rulerY;
+
+  // Check the scroll mode in the X axis
+  bool xAxisScrollEnabled = true;
+  Property::Value* valuePtr = scrollModeMap.Find( Toolkit::ScrollMode::X_AXIS_SCROLL_ENABLED, "xAxisScrollEnabled" );
+  if( valuePtr && valuePtr->GetType() == Property::BOOLEAN )
+  {
+    valuePtr->Get( xAxisScrollEnabled );
+  }
+
+  if( !xAxisScrollEnabled )
+  {
+    // Default ruler and disabled
+    rulerX = new Toolkit::DefaultRuler();
+    rulerX->Disable();
+  }
+  else
+  {
+    valuePtr = scrollModeMap.Find( Toolkit::ScrollMode::X_AXIS_SNAP_TO_INTERVAL, "xAxisSnapToInterval" );
+    float xAxisSnapToInterval = 0.0f;
+    if( valuePtr && valuePtr->Get( xAxisSnapToInterval ) )
+    {
+      // Fixed ruler and enabled
+      rulerX = new Toolkit::FixedRuler( xAxisSnapToInterval );
+    }
+    else
+    {
+      // Default ruler and enabled
+      rulerX = new Toolkit::DefaultRuler();
+    }
+
+    valuePtr = scrollModeMap.Find( Toolkit::ScrollMode::X_AXIS_SCROLL_BOUNDARY, "xAxisScrollBoundary" );
+    float xAxisScrollBoundary = 0.0f;
+    if( valuePtr && valuePtr->Get( xAxisScrollBoundary ) )
+    {
+      // By default ruler domain is disabled unless set
+      rulerX->SetDomain( Toolkit::RulerDomain( 0, xAxisScrollBoundary, true ) );
+    }
+  }
+
+  // Check the scroll mode in the Y axis
+  bool yAxisScrollEnabled = true;
+  valuePtr = scrollModeMap.Find( Toolkit::ScrollMode::Y_AXIS_SCROLL_ENABLED, "yAxisScrollEnabled" );
+  if( valuePtr && valuePtr->GetType() == Property::BOOLEAN )
+  {
+    valuePtr->Get( yAxisScrollEnabled );
+  }
+
+  if( !yAxisScrollEnabled )
+  {
+    // Default ruler and disabled
+    rulerY = new Toolkit::DefaultRuler();
+    rulerY->Disable();
+  }
+  else
+  {
+    valuePtr = scrollModeMap.Find( Toolkit::ScrollMode::Y_AXIS_SNAP_TO_INTERVAL, "yAxisSnapToInterval" );
+    float yAxisSnapToInterval = 0.0f;
+    if( valuePtr && valuePtr->Get( yAxisSnapToInterval ) )
+    {
+      // Fixed ruler and enabled
+      rulerY = new Toolkit::FixedRuler(yAxisSnapToInterval);
+    }
+    else
+    {
+      // Default ruler and enabled
+      rulerY = new Toolkit::DefaultRuler();
+    }
+
+    valuePtr = scrollModeMap.Find( Toolkit::ScrollMode::Y_AXIS_SCROLL_BOUNDARY, "yAxisScrollBoundary" );
+    float yAxisScrollBoundary = 0.0f;
+    if( valuePtr && valuePtr->Get( yAxisScrollBoundary ) )
+    {
+      // By default ruler domain is disabled unless set
+      rulerY->SetDomain( Toolkit::RulerDomain( 0, yAxisScrollBoundary, true ) );
+    }
+  }
+
+  SetRulerX(rulerX);
+  SetRulerY(rulerY);
+}
+
 } // namespace Internal
 
 } // namespace Toolkit