Browse Source

Touch scroll in ScrollView / ListView. Deceleration is instant for now. Closes #332.

Lasse Öörni 11 years ago
parent
commit
40028ccc71
2 changed files with 71 additions and 0 deletions
  1. 65 0
      Source/Engine/UI/ScrollView.cpp
  2. 6 0
      Source/Engine/UI/ScrollView.h

+ 65 - 0
Source/Engine/UI/ScrollView.cpp

@@ -26,6 +26,8 @@
 #include "InputEvents.h"
 #include "InputEvents.h"
 #include "ScrollBar.h"
 #include "ScrollBar.h"
 #include "ScrollView.h"
 #include "ScrollView.h"
+#include "Slider.h"
+#include "UI.h"
 #include "UIEvents.h"
 #include "UIEvents.h"
 
 
 #include "DebugNew.h"
 #include "DebugNew.h"
@@ -42,6 +44,7 @@ ScrollView::ScrollView(Context* context) :
     viewPosition_(IntVector2::ZERO),
     viewPosition_(IntVector2::ZERO),
     viewSize_(IntVector2::ZERO),
     viewSize_(IntVector2::ZERO),
     viewPositionAttr_(IntVector2::ZERO),
     viewPositionAttr_(IntVector2::ZERO),
+    touchScrollSpeed_(IntVector2::ZERO),
     pageStep_(1.0f),
     pageStep_(1.0f),
     scrollBarsAutoVisible_(true),
     scrollBarsAutoVisible_(true),
     ignoreEvents_(false),
     ignoreEvents_(false),
@@ -68,6 +71,7 @@ ScrollView::ScrollView(Context* context) :
     SubscribeToEvent(horizontalScrollBar_, E_VISIBLECHANGED, HANDLER(ScrollView, HandleScrollBarVisibleChanged));
     SubscribeToEvent(horizontalScrollBar_, E_VISIBLECHANGED, HANDLER(ScrollView, HandleScrollBarVisibleChanged));
     SubscribeToEvent(verticalScrollBar_, E_SCROLLBARCHANGED, HANDLER(ScrollView, HandleScrollBarChanged));
     SubscribeToEvent(verticalScrollBar_, E_SCROLLBARCHANGED, HANDLER(ScrollView, HandleScrollBarChanged));
     SubscribeToEvent(verticalScrollBar_, E_VISIBLECHANGED, HANDLER(ScrollView, HandleScrollBarVisibleChanged));
     SubscribeToEvent(verticalScrollBar_, E_VISIBLECHANGED, HANDLER(ScrollView, HandleScrollBarVisibleChanged));
+    SubscribeToEvent(E_TOUCHMOVE, HANDLER(ScrollView, HandleTouchMove));
 }
 }
 
 
 ScrollView::~ScrollView()
 ScrollView::~ScrollView()
@@ -88,6 +92,54 @@ void ScrollView::RegisterObject(Context* context)
     ACCESSOR_ATTRIBUTE(ScrollView, VAR_BOOL, "Auto Show/Hide Scrollbars", GetScrollBarsAutoVisible, SetScrollBarsAutoVisible, bool, true, AM_FILE);
     ACCESSOR_ATTRIBUTE(ScrollView, VAR_BOOL, "Auto Show/Hide Scrollbars", GetScrollBarsAutoVisible, SetScrollBarsAutoVisible, bool, true, AM_FILE);
 }
 }
 
 
+void ScrollView::Update(float timeStep)
+{
+    // Update touch scrolling here if necessary
+    if (touchScrollSpeed_ == IntVector2::ZERO)
+        return;
+    
+    // Check if we should not scroll:
+    // - ScrollView is not visible, is not enabled, or doesn't have focus
+    // - The element being dragged is not a child of the ScrollView, or is one of our scrollbars
+    if (!IsVisible() || !IsEnabled() || !HasFocus())
+    {
+        touchScrollSpeed_ = IntVector2::ZERO;
+        return;
+    }
+    
+    UIElement* dragElement = GetSubsystem<UI>()->GetDragElement();
+    if (dragElement)
+    {
+        UIElement* dragParent = dragElement->GetParent();
+        bool dragElementIsChild = false;
+        
+        while (dragParent)
+        {
+            if (dragParent == this)
+            {
+                dragElementIsChild = true;
+                break;
+            }
+            dragParent = dragParent->GetParent();
+        }
+        
+        if (!dragElementIsChild || dragElement == horizontalScrollBar_->GetSlider() || dragElement == verticalScrollBar_->GetSlider())
+        {
+            touchScrollSpeed_ = IntVector2::ZERO;
+            return;
+        }
+    }
+    
+    // Update view position, reset speed accumulation for next frame
+    IntVector2 newPosition = viewPosition_;
+    newPosition.x_ += touchScrollSpeed_.x_;
+    newPosition.y_ += touchScrollSpeed_.y_;
+    SetViewPosition(newPosition);
+    
+    /// \todo Could have smooth deceleration
+    touchScrollSpeed_ = IntVector2::ZERO;
+}
+
 void ScrollView::ApplyAttributes()
 void ScrollView::ApplyAttributes()
 {
 {
     UIElement::ApplyAttributes();
     UIElement::ApplyAttributes();
@@ -444,4 +496,17 @@ void ScrollView::HandleElementResized(StringHash eventType, VariantMap& eventDat
         OnResize();
         OnResize();
 }
 }
 
 
+void ScrollView::HandleTouchMove(StringHash eventType, VariantMap& eventData)
+{
+    using namespace TouchMove;
+    
+    // Take new scrolling speed if it's faster than the current accumulated value
+    int dX = -eventData[P_DX].GetInt();
+    int dY = -eventData[P_DY].GetInt();
+    if (Abs(dX) > Abs(touchScrollSpeed_.x_))
+        touchScrollSpeed_.x_ = dX;
+    if (Abs(dY) > Abs(touchScrollSpeed_.y_))
+        touchScrollSpeed_.y_ = dY;
+}
+
 }
 }

+ 6 - 0
Source/Engine/UI/ScrollView.h

@@ -43,6 +43,8 @@ public:
     /// Register object factory.
     /// Register object factory.
     static void RegisterObject(Context* context);
     static void RegisterObject(Context* context);
 
 
+    /// Perform UI element update.
+    virtual void Update(float timeStep);
     /// Apply attribute changes that can not be applied immediately.
     /// Apply attribute changes that can not be applied immediately.
     virtual void ApplyAttributes();
     virtual void ApplyAttributes();
     /// React to mouse wheel.
     /// React to mouse wheel.
@@ -115,6 +117,8 @@ protected:
     IntVector2 viewSize_;
     IntVector2 viewSize_;
     /// View offset attribute.
     /// View offset attribute.
     IntVector2 viewPositionAttr_;
     IntVector2 viewPositionAttr_;
+    /// Accumulated touch scroll speed.
+    IntVector2 touchScrollSpeed_;
     /// Arrow key page step.
     /// Arrow key page step.
     float pageStep_;
     float pageStep_;
     /// Automatically show/hide scrollbars flag.
     /// Automatically show/hide scrollbars flag.
@@ -131,6 +135,8 @@ private:
     void HandleScrollBarVisibleChanged(StringHash eventType, VariantMap& eventData);
     void HandleScrollBarVisibleChanged(StringHash eventType, VariantMap& eventData);
     /// Handle content element resized.
     /// Handle content element resized.
     void HandleElementResized(StringHash eventType, VariantMap& eventData);
     void HandleElementResized(StringHash eventType, VariantMap& eventData);
+    /// Handle touch move event for scrolling.
+    void HandleTouchMove(StringHash eventType, VariantMap& eventData);
 };
 };
 
 
 }
 }