ScrollView: Avoid unintentional contraints on X/Y properties
[platform/core/uifw/dali-toolkit.git] / base / dali-toolkit / internal / controls / scrollable / scroll-view / scroll-view-impl.cpp
index 4a6bd09..6cd1a37 100644 (file)
@@ -1,19 +1,18 @@
-/*
- * 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.
- *
- */
+//
+// 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.
+//
 
 // INTERNAL INCLUDES
 #include <dali/public-api/events/mouse-wheel-event.h>
@@ -541,7 +540,8 @@ ScrollView::ScrollView()
   mAxisAutoLockGradient(Toolkit::ScrollView::DEFAULT_AXIS_AUTO_LOCK_GRADIENT),
   mFrictionCoefficient(Toolkit::ScrollView::DEFAULT_FRICTION_COEFFICIENT),
   mFlickSpeedCoefficient(Toolkit::ScrollView::DEFAULT_FLICK_SPEED_COEFFICIENT),
-  mMaxFlickSpeed(Toolkit::ScrollView::DEFAULT_MAX_FLICK_SPEED)
+  mMaxFlickSpeed(Toolkit::ScrollView::DEFAULT_MAX_FLICK_SPEED),
+  mInAccessibilityPan(false)
 {
   SetRequiresMouseWheelEvents(true);
 }
@@ -1358,21 +1358,32 @@ bool ScrollView::SnapWithVelocity(Vector2 velocity)
   const float orthoAngleRange = FLICK_ORTHO_ANGLE_RANGE * M_PI / 180.0f;
   const float flickSpeedThreshold2 = FLICK_SPEED_THRESHOLD*FLICK_SPEED_THRESHOLD;
 
+  Vector3 positionSnap = mScrollPostPosition;
+
   // Flick logic X Axis
 
   if(mRulerX->IsEnabled())
   {
     horizontal = All;
 
-    if(speed2 > flickSpeedThreshold2) // exceeds flick threshold
+    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;
       }
     }
   }
@@ -1383,7 +1394,8 @@ bool ScrollView::SnapWithVelocity(Vector2 velocity)
   {
     vertical = All;
 
-    if(speed2 > flickSpeedThreshold2) // exceeds flick threshold
+    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
       {
@@ -1407,8 +1419,7 @@ bool ScrollView::SnapWithVelocity(Vector2 velocity)
     alphaFunction = mFlickAlphaFunction;
   }
 
-  // Position Snap ////////////////////////////////////////////////////////////
-  Vector3 positionSnap = mScrollPostPosition;
+  // Calculate next positionSnap ////////////////////////////////////////////////////////////
 
   if(mActorAutoSnapEnabled)
   {
@@ -2132,17 +2143,23 @@ void ScrollView::OnPan(PanGesture gesture)
       self.SetProperty( mPropertyScrollStartPagePosition, GetCurrentScrollPosition() );
 
       //  Update property: X & Y = Position (only when in panning mode - in snapping mode, X & Y are animated).
-      Constraint constraint = Constraint::New<float>( mPropertyX,
-                                           LocalSource( mPropertyPosition ),
-                                           Source( self, mPropertyPanning ),
-                                           InternalXConstraint );
-      mScrollMainInternalXConstraint = self.ApplyConstraint(constraint);
+      if( ! mScrollMainInternalXConstraint )
+      {
+        Constraint constraint = Constraint::New<float>( mPropertyX,
+                                                        LocalSource( mPropertyPosition ),
+                                                        Source( self, mPropertyPanning ),
+                                                        InternalXConstraint );
+        mScrollMainInternalXConstraint = self.ApplyConstraint( constraint );
+      }
+      if( ! mScrollMainInternalYConstraint )
+      {
+        Constraint constraint = Constraint::New<float>( mPropertyY,
+                                                        LocalSource( mPropertyPosition ),
+                                                        Source( self, mPropertyPanning ),
+                                                        InternalYConstraint );
+        mScrollMainInternalYConstraint = self.ApplyConstraint( constraint );
+      }
 
-      constraint = Constraint::New<float>( mPropertyY,
-                                           LocalSource( mPropertyPosition ),
-                                           Source( self, mPropertyPanning ),
-                                           InternalYConstraint );
-      mScrollMainInternalYConstraint = self.ApplyConstraint(constraint);
       // When panning we want to make sure overshoot values are affected by pre position and post position
       SetOvershootConstraintsEnabled(true);
       break;
@@ -2163,6 +2180,8 @@ void ScrollView::OnPan(PanGesture gesture)
       // Remove X & Y position constraints as they are not required when we are not panning.
       self.RemoveConstraint(mScrollMainInternalXConstraint);
       self.RemoveConstraint(mScrollMainInternalYConstraint);
+      mScrollMainInternalXConstraint.Reset();
+      mScrollMainInternalYConstraint.Reset();
       break;
     }
 
@@ -2277,7 +2296,11 @@ Vector3 ScrollView::GetOvershoot(Vector3& position) const
 
 bool ScrollView::OnAccessibilityPan(PanGesture gesture)
 {
+  // Keep track of whether this is an AccessibilityPan
+  mInAccessibilityPan = true;
   OnPan(gesture);
+  mInAccessibilityPan = false;
+
   return true;
 }