A minor improvement for the Viewport with setScrollOnDragEnabled


#1

Hi,
With Viewport::setScrollOnDragEnabled enabled there is a nice inertial movement of the viewport when we lift the finger or the mouse after dragging. It is very nice, except when the movement is close to stopping, at which point one notices that the animation is no more a 60 fps animation. This is when the speed is lower than 60 px / sec, because of the rounding of the viewport position to the nearest int. For example, if the speed is 6 pixels / second, the viewport position will be changed only 10 times per second, which appears “non-smooth” . The best solution would probably be to have the viewport position defined as a float instead of an int, but I guess this would be a large change. Another possibility is to just stop the inertial movement when the (rounded to int) position does not change between two consecutive frames.

For example we can acheive that by adding a minimum speed to the juce inertial animated position:

--- a/juce-git/modules/juce_gui_basics/layout/juce_AnimatedPositionBehaviours.h
+++ b/juce-git/modules/juce_gui_basics/layout/juce_AnimatedPositionBehaviours.h
@@ -56,6 +56,11 @@
             damping = 1.0 - newFriction;
         }

+        void setMinimumSpeed (double newMinimumSpeed) noexcept^M
+        {^M
+            minimumSpeed = newMinimumSpeed;^M
+        }^M
+^M
         /** Called by the AnimatedPosition class. This tells us the position and
             velocity at which the user is about to release the object.
             The velocity is measured in units/second.
@@ -72,7 +77,7 @@
         {
             velocity *= damping;

-            if (std::abs (velocity) < 0.05)^M
+            if (std::abs (velocity) < minimumSpeed)^M
                 velocity = 0;

             return oldPos + velocity * elapsedSeconds;
@@ -88,6 +93,7 @@

     private:
         double velocity = 0, damping = 0.92;
+        double minimumSpeed = 0.05;^M
     };

     //==============================================================================
diff --git a/juce-git/modules/juce_gui_basics/layout/juce_Viewport.cpp b/juce-git/modules/juce_gui_basics/layout/juce_Viewport.cpp
--- a/juce-git/modules/juce_gui_basics/layout/juce_Viewport.cpp
+++ b/juce-git/modules/juce_gui_basics/layout/juce_Viewport.cpp
@@ -191,6 +191,8 @@
         viewport.contentHolder.addMouseListener (this, true);
         offsetX.addListener (this);
         offsetY.addListener (this);
+        offsetX.behaviour.setMinimumSpeed(60);^M
+        offsetY.behaviour.setMinimumSpeed(60);^M
     }

     ~DragToScrollListener()

Another small improvement is to stop any previous inertial scrolling when the user puts his finger on the viewport:

@@ -208,7 +216,7 @@
     void mouseDown (const MouseEvent& e) override
     {
         if (doesMouseEventComponentBlockViewportDrag (e.eventComponent))
             isViewportDragBlocked = true;
-^M
+        offsetX.setPosition(offsetX.getPosition());^M
+        offsetY.setPosition(offsetY.getPosition());^M
         ++numTouches;
     }

#2

Sounds like a reasonable request. I’ve added this to develop with commit d105d94.