Add long-press support to carousel

Change-Id: I65f468d4d0104bac2e98a8e97ec3ba49db42c7d5
diff --git a/carousel/java/com/android/ex/carousel/CarouselController.java b/carousel/java/com/android/ex/carousel/CarouselController.java
index 2d7a4f6..545b25c 100644
--- a/carousel/java/com/android/ex/carousel/CarouselController.java
+++ b/carousel/java/com/android/ex/carousel/CarouselController.java
@@ -393,6 +393,13 @@
     }
 
     /**
+     * Gets the callback for receiving events from Renderscript.
+     */
+    public CarouselCallback getCallback() {
+        return mCarouselCallback;
+    }
+
+    /**
      * Sets the startAngle for the Carousel. The start angle is the first position of the first
      * slot draw.  Cards will be drawn from this angle in a counter-clockwise manner around the
      * Carousel.
@@ -514,6 +521,13 @@
     }
 
     /**
+     * Tells the carousel that the user has long-pressed.
+     */
+    public void onLongPress() {
+        mRenderScript.doLongPress();
+    }
+
+    /**
      * Tells the carousel that a touch event has stopped at the designated location.
      * @param x The number of pixels from the left edge that the event occurred
      * @param y The number of pixels from the top edge that the event occurred
diff --git a/carousel/java/com/android/ex/carousel/CarouselRS.java b/carousel/java/com/android/ex/carousel/CarouselRS.java
index 66ff5d6..cbb6714 100644
--- a/carousel/java/com/android/ex/carousel/CarouselRS.java
+++ b/carousel/java/com/android/ex/carousel/CarouselRS.java
@@ -42,6 +42,7 @@
 
     // Client messages *** THIS LIST MUST MATCH THOSE IN carousel.rs ***
     public static final int CMD_CARD_SELECTED = 100;
+    public static final int CMD_CARD_LONGPRESS = 110;
     public static final int CMD_REQUEST_TEXTURE = 200;
     public static final int CMD_INVALIDATE_TEXTURE = 210;
     public static final int CMD_REQUEST_GEOMETRY = 300;
@@ -97,6 +98,12 @@
         void onCardSelected(int n);
 
         /**
+         * Called when a card is long-pressed
+         * @param n the id of the card
+         */
+        void onCardLongPress(int n);
+
+        /**
          * Called when texture is needed for card n.  This happens when the given card becomes
          * visible.
          * @param n the id of the card
@@ -161,6 +168,10 @@
                     mCallback.onCardSelected(mData[0]);
                     break;
 
+                case CMD_CARD_LONGPRESS:
+                    mCallback.onCardLongPress(mData[0]);
+                    break;
+
                 case CMD_REQUEST_TEXTURE:
                     mCallback.onRequestTexture(mData[0]);
                     break;
@@ -535,6 +546,10 @@
         mRS.contextBindRootScript(mScript);
     }
 
+    public void doLongPress() {
+        mScript.invoke_doLongPress();
+    }
+
     public void doMotion(float x, float y) {
         mScript.invoke_doMotion(x,y);
     }
diff --git a/carousel/java/com/android/ex/carousel/CarouselView.java b/carousel/java/com/android/ex/carousel/CarouselView.java
index e8f40f8..ee21a51 100644
--- a/carousel/java/com/android/ex/carousel/CarouselView.java
+++ b/carousel/java/com/android/ex/carousel/CarouselView.java
@@ -16,6 +16,7 @@
 
 package com.android.ex.carousel;
 
+import android.view.View;
 import com.android.ex.carousel.CarouselRS.CarouselCallback;
 
 import android.content.Context;
@@ -108,6 +109,17 @@
         boolean useDepthBuffer = true;
         ensureRenderScript();
         // TODO: add parameters to layout
+
+        setOnLongClickListener(new OnLongClickListener() {
+            public boolean onLongClick(View v) {
+                if (interpretLongPressEvents()) {
+                    mRenderScript.doLongPress();
+                    return true;
+                } else {
+                    return false;
+                }
+            }
+        });
     }
 
     private void ensureRenderScript() {
@@ -154,6 +166,17 @@
     }
 
     /**
+     * Do I want to interpret the long-press gesture? If so, long-presses will cancel the
+     * current selection and call the appropriate callbacks. Otherwise, a long press will
+     * not be handled any way other than as a continued drag.
+     *
+     * @return True if we interpret long-presses
+     */
+    public boolean interpretLongPressEvents() {
+        return false;
+    }
+
+    /**
      * Loads geometry from a resource id.
      *
      * @param resId
@@ -549,6 +572,7 @@
 
     @Override
     public boolean onTouchEvent(MotionEvent event) {
+        super.onTouchEvent(event);
         final int action = event.getAction();
         final float x = event.getX();
         final float y = event.getY();
diff --git a/carousel/java/com/android/ex/carousel/CarouselViewHelper.java b/carousel/java/com/android/ex/carousel/CarouselViewHelper.java
index de1718e..927db93 100644
--- a/carousel/java/com/android/ex/carousel/CarouselViewHelper.java
+++ b/carousel/java/com/android/ex/carousel/CarouselViewHelper.java
@@ -252,6 +252,10 @@
         if (DBG) Log.v(TAG, "onCardSelected(" + n + ")");
     }
 
+    public void onCardLongPress(int n) {
+        if (DBG) Log.v(TAG, "onCardLongPress(" + n + ")");
+    }
+
     public void onAnimationStarted() {
 
     }
diff --git a/carousel/java/com/android/ex/carousel/MVCCarouselView.java b/carousel/java/com/android/ex/carousel/MVCCarouselView.java
index f1e0def..9a57f55 100644
--- a/carousel/java/com/android/ex/carousel/MVCCarouselView.java
+++ b/carousel/java/com/android/ex/carousel/MVCCarouselView.java
@@ -16,6 +16,7 @@
 
 package com.android.ex.carousel;
 
+import android.view.View;
 import com.android.ex.carousel.CarouselRS.CarouselCallback;
 
 import android.content.Context;
@@ -81,6 +82,17 @@
         boolean useDepthBuffer = true;
         ensureRenderScript();
         // TODO: add parameters to layout
+
+        setOnLongClickListener(new View.OnLongClickListener() {
+            public boolean onLongClick(View v) {
+                if (interpretLongPressEvents()) {
+                    mController.onLongPress();
+                    return true;
+                } else {
+                    return false;
+                }
+            }
+        });
     }
 
     private void ensureRenderScript() {
@@ -111,6 +123,17 @@
     }
 
     /**
+     * Do I want to interpret the long-press gesture? If so, long-presses will cancel the
+     * current selection and call the appropriate callbacks. Otherwise, a long press will
+     * not be handled any way other than as a continued drag.
+     *
+     * @return True if we interpret long-presses
+     */
+    public boolean interpretLongPressEvents() {
+        return false;
+    }
+
+    /**
      * Loads geometry from a resource id.
      *
      * @param resId
@@ -409,6 +432,7 @@
 
     @Override
     public boolean onTouchEvent(MotionEvent event) {
+        super.onTouchEvent(event);
         final int action = event.getAction();
         final float x = event.getX();
         final float y = event.getY();
diff --git a/carousel/java/com/android/ex/carousel/MVCCarouselViewHelper.java b/carousel/java/com/android/ex/carousel/MVCCarouselViewHelper.java
index 239e5a2..30aec51 100644
--- a/carousel/java/com/android/ex/carousel/MVCCarouselViewHelper.java
+++ b/carousel/java/com/android/ex/carousel/MVCCarouselViewHelper.java
@@ -252,6 +252,10 @@
         if (DBG) Log.v(TAG, "onCardSelected(" + n + ")");
     }
 
+    public void onCardLongPress(int n) {
+        if (DBG) Log.v(TAG, "onCardLongPress(" + n + ")");
+    }
+
     public void onAnimationStarted() {
 
     }
diff --git a/carousel/java/com/android/ex/carousel/carousel.rs b/carousel/java/com/android/ex/carousel/carousel.rs
index 6890120..c265383 100644
--- a/carousel/java/com/android/ex/carousel/carousel.rs
+++ b/carousel/java/com/android/ex/carousel/carousel.rs
@@ -66,6 +66,7 @@
 
 // Client messages *** THIS LIST MUST MATCH THOSE IN CarouselRS.java. ***
 static const int CMD_CARD_SELECTED = 100;
+static const int CMD_CARD_LONGPRESS = 110;
 static const int CMD_REQUEST_TEXTURE = 200;
 static const int CMD_INVALIDATE_TEXTURE = 210;
 static const int CMD_REQUEST_GEOMETRY = 300;
@@ -135,7 +136,8 @@
 #pragma rs export_var(linearClamp, shaderConstants)
 #pragma rs export_var(startAngle, defaultTexture, loadingTexture, defaultGeometry, loadingGeometry)
 #pragma rs export_var(fadeInDuration, rezInCardCount)
-#pragma rs export_func(createCards, copyCards, lookAt, doStart, doStop, doMotion, doSelection)
+#pragma rs export_func(createCards, copyCards, lookAt)
+#pragma rs export_func(doStart, doStop, doMotion, doLongPress, doSelection)
 #pragma rs export_func(setTexture, setGeometry, setDetailTexture, debugCamera, debugPicking)
 #pragma rs export_func(requestFirstCardPosition)
 
@@ -802,6 +804,20 @@
     lastTime = rsUptimeMillis();
 }
 
+void doLongPress()
+{
+    int64_t currentTime = rsUptimeMillis();
+    updateAllocationVars(cards);
+    if (currentSelection != -1) {
+        // rsDebug("HIT!", currentSelection);
+        int data[1];
+        data[0] = currentSelection;
+        rsSendToClientBlocking(CMD_CARD_LONGPRESS, data, sizeof(data));
+    }
+    currentSelection = -1;
+    lastTime = rsUptimeMillis();
+}
+
 void doMotion(float x, float y)
 {
     int64_t currentTime = rsUptimeMillis();