Allow configurable speed factor when ItemView is being swiped.
[platform/core/uifw/dali-toolkit.git] / base / dali-toolkit / internal / controls / scrollable / item-view / item-view-impl.cpp
index 001291f..55f87ad 100644 (file)
@@ -1,18 +1,19 @@
-//
-// Copyright (c) 2014 Samsung Electronics Co., Ltd.
-//
-// Licensed under the Flora License, Version 1.0 (the License);
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://floralicense.org/license/
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an AS IS BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
+/*
+ * Copyright (c) 2014 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
 
 // CLASS HEADER
 #include <dali-toolkit/internal/controls/scrollable/item-view/item-view-impl.h>
@@ -24,6 +25,7 @@
 #include <dali/public-api/events/mouse-wheel-event.h>
 #include <dali-toolkit/public-api/controls/scrollable/item-view/item-factory.h>
 #include <dali-toolkit/internal/controls/scrollable/scroll-connector-impl.h>
+#include <dali-toolkit/public-api/controls/default-controls/solid-color-actor.h>
 
 using namespace std;
 using namespace Dali;
@@ -46,7 +48,6 @@ const float DEFAULT_COLOR_VISIBILITY_REMOVE_TIME = 0.5f; // 0.5 second
 
 const float MILLISECONDS_PER_SECONDS = 1000.0f;
 
-const char* OVERSHOOT_OVERLAY_RIPPLE_IMAGE_PATH = DALI_IMAGE_DIR "overshoot_ripple.png";
 const Rect<int> OVERSHOOT_BOUNCE_IMAGE_1_PIXEL_AREA( 0, 0, 720, 58 );
 const Vector4 OVERSHOOT_OVERLAY_NINE_PATCH_BORDER(0.0f, 0.0f, 1.0f, 12.0f);
 const float MAXIMUM_OVERSHOOT_HEIGHT = 36.0f;  // 36 pixels
@@ -411,7 +412,9 @@ ItemView::ItemView(ItemFactory& factory)
   mIsFlicking(false),
   mGestureState(Gesture::Clear),
   mAddingItems(false),
-  mRefreshEnabled(true)
+  mRefreshEnabled(true),
+  mItemsParentOrigin( ParentOrigin::CENTER),
+  mItemsAnchorPoint( AnchorPoint::CENTER)
 {
   SetRequiresMouseWheelEvents(true);
   SetKeyboardNavigationSupport(true);
@@ -425,16 +428,6 @@ void ItemView::OnInitialize()
 
   Actor self = Self();
 
-  mOvershootEffect = OvershootRippleEffect::New();
-  Image overshootImage = Image::New( OVERSHOOT_OVERLAY_RIPPLE_IMAGE_PATH );
-  mOvershootOverlay = ImageActor::New( overshootImage );
-  mOvershootOverlay.SetParentOrigin(ParentOrigin::TOP_LEFT);
-  mOvershootOverlay.SetAnchorPoint(AnchorPoint::TOP_LEFT);
-  mOvershootOverlay.SetDrawMode(DrawMode::OVERLAY);
-  mOvershootOverlay.SetShaderEffect(mOvershootEffect);
-  mOvershootOverlay.SetPixelArea(OVERSHOOT_BOUNCE_IMAGE_1_PIXEL_AREA);
-  self.Add(mOvershootOverlay);
-
   mScrollConnector = Dali::Toolkit::ScrollConnector::New();
   mScrollPositionObject = mScrollConnector.GetScrollPositionObject();
 
@@ -442,7 +435,7 @@ void ItemView::OnInitialize()
   mPropertyPosition = self.RegisterProperty(POSITION_PROPERTY_NAME, 0.0f);
   mPropertyScrollSpeed = self.RegisterProperty(SCROLL_SPEED_PROPERTY_NAME, 0.0f);
 
-  ApplyOvershootOverlayConstraints();
+  EnableScrollComponent(Toolkit::Scrollable::OvershootIndicator);
 
   Constraint constraint = Constraint::New<Vector3>(mPropertyRelativePosition,
                                                    LocalSource(mPropertyPosition),
@@ -592,7 +585,7 @@ void ItemView::ActivateLayout(unsigned int layoutIndex, const Vector3& targetSiz
   if (scrollAnimationNeeded)
   {
     RemoveAnimation(mScrollAnimation);
-    mScrollAnimation = Animation::New(mAnchoringDuration);
+    mScrollAnimation = Animation::New(durationSeconds);
     mScrollAnimation.AnimateTo( Property( mScrollPositionObject, ScrollConnector::SCROLL_POSITION ), firstItemScrollPosition, AlphaFunctions::EaseOut );
     mScrollAnimation.AnimateTo( Property(self, mPropertyPosition), GetScrollPosition(firstItemScrollPosition, targetSize), AlphaFunctions::EaseOut );
     mScrollAnimation.Play();
@@ -903,7 +896,8 @@ bool ItemView::RemoveActor(unsigned int itemId)
 
   if( removeIter != mItemPool.end() )
   {
-    Self().Remove( removeIter->second );
+    ReleaseActor(itemId, removeIter->second);
+
     removed = true;
 
     // Adjust the remaining item IDs, for example if item 2 is removed:
@@ -939,7 +933,7 @@ void ItemView::ReplaceItem( Item replacementItem, float durationSeconds )
   const ItemPoolIter iter = mItemPool.find( replacementItem.first );
   if( mItemPool.end() != iter )
   {
-    Self().Remove( iter->second );
+    ReleaseActor(iter->first, iter->second);
     iter->second = replacementItem.second;
   }
   else
@@ -969,7 +963,7 @@ void ItemView::RemoveActorsOutsideRange( ItemRange range )
 
     if( ! range.Within( current ) )
     {
-      Self().Remove( iter->second );
+      ReleaseActor(iter->first, iter->second);
 
       mItemPool.erase( iter++ ); // erase invalidates the return value of post-increment; iter remains valid
     }
@@ -1029,8 +1023,8 @@ void ItemView::AddNewActor( unsigned int itemId, float durationSeconds )
 
 void ItemView::SetupActor( Item item, float durationSeconds )
 {
-  item.second.SetParentOrigin( ParentOrigin::CENTER );
-  item.second.SetAnchorPoint( AnchorPoint::CENTER );
+  item.second.SetParentOrigin( mItemsParentOrigin );
+  item.second.SetAnchorPoint( mItemsAnchorPoint );
 
   if( mActiveLayout )
   {
@@ -1044,6 +1038,12 @@ void ItemView::SetupActor( Item item, float durationSeconds )
   }
 }
 
+void ItemView::ReleaseActor( ItemId item, Actor actor )
+{
+  Self().Remove( actor );
+  mItemFactory.ItemReleased(item, actor);
+}
+
 ItemRange ItemView::GetItemRange(ItemLayout& layout, const Vector3& layoutSize, float layoutPosition, bool reserveExtra)
 {
   unsigned int itemCount = mItemFactory.GetNumberOfItems();
@@ -1112,7 +1112,7 @@ bool ItemView::OnMouseWheelEvent(const MouseWheelEvent& event)
   {
     Actor self = Self();
     const Vector3 layoutSize = Self().GetCurrentSize();
-    float layoutPositionDelta = GetCurrentLayoutPosition(0) + (event.z * mMouseWheelScrollDistanceStep * mActiveLayout->GetScrollSpeedFactor());
+    float layoutPositionDelta = GetCurrentLayoutPosition(0) - (event.z * mMouseWheelScrollDistanceStep * mActiveLayout->GetScrollSpeedFactor());
     float firstItemScrollPosition = ClampFirstItemPosition(layoutPositionDelta, layoutSize, *mActiveLayout);
 
     mScrollPositionObject.SetProperty( ScrollConnector::SCROLL_POSITION, firstItemScrollPosition );
@@ -1349,16 +1349,11 @@ void ItemView::OnPan(PanGesture gesture)
     case Gesture::Continuing:
     {
       mScrollDistance = CalculateScrollDistance(gesture.displacement, *mActiveLayout);
-      mScrollSpeed = Clamp((gesture.GetSpeed() * mActiveLayout->GetScrollSpeedFactor() * MILLISECONDS_PER_SECONDS), 0.0f, mActiveLayout->GetMaximumSwipeSpeed());
+      mScrollSpeed = Clamp((gesture.GetSpeed() * mActiveLayout->GetFlickSpeedFactor() * MILLISECONDS_PER_SECONDS), 0.0f, mActiveLayout->GetMaximumSwipeSpeed());
 
       // Refresh order depends on the direction of the scroll; negative is towards the last item.
       mRefreshOrderHint = mScrollDistance < 0.0f;
 
-      RemoveAnimation(mScrollSpeedAnimation);
-      mScrollSpeedAnimation = Animation::New(0.3f);
-      mScrollSpeedAnimation.AnimateTo( Property(self, mPropertyScrollSpeed), mScrollSpeed, AlphaFunctions::Linear );
-      mScrollSpeedAnimation.Play();
-
       float layoutPositionDelta = GetCurrentLayoutPosition(0) + (mScrollDistance * mActiveLayout->GetScrollSpeedFactor());
 
       float firstItemScrollPosition = ClampFirstItemPosition(layoutPositionDelta, layoutSize, *mActiveLayout);
@@ -1407,7 +1402,7 @@ bool ItemView::OnAccessibilityPan(PanGesture gesture)
   return true;
 }
 
-Actor ItemView::GetNextKeyboardFocusableActor(Actor actor, Control::KeyboardFocusNavigationDirection direction, bool loopEnabled)
+Actor ItemView::GetNextKeyboardFocusableActor(Actor actor, Toolkit::Control::KeyboardFocusNavigationDirection direction, bool loopEnabled)
 {
   Actor nextFocusActor;
   if(mActiveLayout)
@@ -1672,40 +1667,60 @@ void ItemView::ScrollTo(const Vector3& position, float duration)
   mScrollStartedSignalV2.Emit(GetCurrentScrollPosition());
 }
 
-void ItemView::ApplyOvershootOverlayConstraints()
+void ItemView::SetOvershootEnabled( bool enable )
 {
-  Constraint constraint = Constraint::New<float>( Actor::SIZE_WIDTH,
-                                                    ParentSource( mPropertyScrollDirection ),
-                                                    Source( mScrollPositionObject, ScrollConnector::OVERSHOOT ),
-                                                    ParentSource( Actor::SIZE ),
-                                                    OvershootOverlaySizeConstraint() );
-  mOvershootOverlay.ApplyConstraint(constraint);
-  mOvershootOverlay.SetSize(OVERSHOOT_BOUNCE_IMAGE_1_PIXEL_AREA.width, OVERSHOOT_BOUNCE_IMAGE_1_PIXEL_AREA.height);
-
-  constraint = Constraint::New<Quaternion>( Actor::ROTATION,
-                                            ParentSource( mPropertyScrollDirection ),
-                                            Source( mScrollPositionObject, ScrollConnector::OVERSHOOT ),
-                                            OvershootOverlayRotationConstraint() );
-  mOvershootOverlay.ApplyConstraint(constraint);
-
-  constraint = Constraint::New<Vector3>( Actor::POSITION,
-                                         ParentSource( Actor::SIZE ),
-                                         ParentSource( mPropertyScrollDirection ),
-                                         Source( mScrollPositionObject, ScrollConnector::OVERSHOOT ),
-                                         OvershootOverlayPositionConstraint() );
-  mOvershootOverlay.ApplyConstraint(constraint);
-
-  constraint = Constraint::New<bool>( Actor::VISIBLE,
-                                      ParentSource( mPropertyCanScrollVertical ),
-                                      OvershootOverlayVisibilityConstraint() );
-  mOvershootOverlay.ApplyConstraint(constraint);
-
-  int effectOvershootPropertyIndex = mOvershootEffect.GetPropertyIndex(mOvershootEffect.GetOvershootPropertyName());
   Actor self = Self();
-  constraint = Constraint::New<float>( effectOvershootPropertyIndex,
-                                       Source( mScrollPositionObject, ScrollConnector::OVERSHOOT ),
-                                       EqualToConstraint() );
-  mOvershootEffect.ApplyConstraint(constraint);
+  if( enable )
+  {
+    mOvershootEffect = BouncingEffect::New(Scrollable::DEFAULT_OVERSHOOT_COLOUR);
+    mOvershootOverlay = CreateSolidColorActor(Vector4::ONE);
+    mOvershootOverlay.SetParentOrigin(ParentOrigin::TOP_LEFT);
+    mOvershootOverlay.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+    mOvershootOverlay.SetDrawMode(DrawMode::OVERLAY);
+    mOvershootOverlay.SetShaderEffect(mOvershootEffect);
+    self.Add(mOvershootOverlay);
+    Constraint constraint = Constraint::New<float>( Actor::SIZE_WIDTH,
+                                                      ParentSource( mPropertyScrollDirection ),
+                                                      Source( mScrollPositionObject, ScrollConnector::OVERSHOOT ),
+                                                      ParentSource( Actor::SIZE ),
+                                                      OvershootOverlaySizeConstraint() );
+    mOvershootOverlay.ApplyConstraint(constraint);
+    mOvershootOverlay.SetSize(OVERSHOOT_BOUNCE_IMAGE_1_PIXEL_AREA.width, OVERSHOOT_BOUNCE_IMAGE_1_PIXEL_AREA.height);
+
+    constraint = Constraint::New<Quaternion>( Actor::ROTATION,
+                                              ParentSource( mPropertyScrollDirection ),
+                                              Source( mScrollPositionObject, ScrollConnector::OVERSHOOT ),
+                                              OvershootOverlayRotationConstraint() );
+    mOvershootOverlay.ApplyConstraint(constraint);
+
+    constraint = Constraint::New<Vector3>( Actor::POSITION,
+                                           ParentSource( Actor::SIZE ),
+                                           ParentSource( mPropertyScrollDirection ),
+                                           Source( mScrollPositionObject, ScrollConnector::OVERSHOOT ),
+                                           OvershootOverlayPositionConstraint() );
+    mOvershootOverlay.ApplyConstraint(constraint);
+
+    constraint = Constraint::New<bool>( Actor::VISIBLE,
+                                        ParentSource( mPropertyCanScrollVertical ),
+                                        OvershootOverlayVisibilityConstraint() );
+    mOvershootOverlay.ApplyConstraint(constraint);
+
+    int effectOvershootPropertyIndex = mOvershootEffect.GetPropertyIndex(mOvershootEffect.GetProgressRatePropertyName());
+    Actor self = Self();
+    constraint = Constraint::New<float>( effectOvershootPropertyIndex,
+                                         Source( mScrollPositionObject, ScrollConnector::OVERSHOOT ),
+                                         EqualToConstraint() );
+    mOvershootEffect.ApplyConstraint(constraint);
+  }
+  else
+  {
+    if( mOvershootOverlay )
+    {
+      self.Remove(mOvershootOverlay);
+      mOvershootOverlay.Reset();
+    }
+    mOvershootEffect.Reset();
+  }
 }
 
 float ItemView::CalculateScrollOvershoot()
@@ -1754,6 +1769,46 @@ void ItemView::AnimateScrollOvershoot(float overshootAmount, bool animateBack)
   mAnimatingOvershootOn = animatingOn;
 }
 
+void ItemView::SetItemsParentOrigin( const Vector3& parentOrigin )
+{
+  if( parentOrigin != mItemsParentOrigin )
+  {
+    mItemsParentOrigin = parentOrigin;
+    for (ItemPoolIter iter = mItemPool.begin(); iter != mItemPool.end(); ++iter)
+    {
+      iter->second.SetParentOrigin(parentOrigin);
+    }
+  }
+}
+
+Vector3 ItemView::GetItemsParentOrigin() const
+{
+  return mItemsParentOrigin;
+}
+
+void ItemView::SetItemsAnchorPoint( const Vector3& anchorPoint )
+{
+  if( anchorPoint != mItemsAnchorPoint )
+  {
+    mItemsAnchorPoint = anchorPoint;
+    for (ItemPoolIter iter = mItemPool.begin(); iter != mItemPool.end(); ++iter)
+    {
+      iter->second.SetAnchorPoint(anchorPoint);
+    }
+  }
+}
+
+Vector3 ItemView::GetItemsAnchorPoint() const
+{
+  return mItemsAnchorPoint;
+}
+
+void ItemView::GetItemsRange(ItemRange& range)
+{
+  range.begin = mItemPool.begin()->first;
+  range.end = mItemPool.rbegin()->first + 1;
+}
+
 } // namespace Internal
 
 } // namespace Toolkit