summaryrefslogtreecommitdiffstats
path: root/carousel/java
diff options
context:
space:
mode:
authorJim Miller <jaggies@google.com>2010-09-26 18:59:34 -0700
committerJim Miller <jaggies@google.com>2010-09-26 18:59:34 -0700
commita3cb716626b477c98ba912698c765eab20f27286 (patch)
treed82b5c0cdab7b8642e8d28767439ab55a74b6dae /carousel/java
parent7867abe6e7af226fc29285890d6decb0ce3daa0f (diff)
downloadandroid_frameworks_ex-a3cb716626b477c98ba912698c765eab20f27286.tar.gz
android_frameworks_ex-a3cb716626b477c98ba912698c765eab20f27286.tar.bz2
android_frameworks_ex-a3cb716626b477c98ba912698c765eab20f27286.zip
Major improvements to Carousel.
Added CarouselViewHelper class to simplify writing applications that use the widged. Updated examples to use new CarouselViewHelper class. Added sample "lighting" to CarouselTestActivity. Change-Id: I1b4a7e0d79f94781add16e1d2e7ec8b4657744d8
Diffstat (limited to 'carousel/java')
-rw-r--r--carousel/java/com/android/ex/carousel/CarouselRS.java7
-rw-r--r--carousel/java/com/android/ex/carousel/CarouselView.java59
-rw-r--r--carousel/java/com/android/ex/carousel/CarouselViewHelper.java260
-rw-r--r--carousel/java/com/android/ex/carousel/CarouselViewUtilities.java39
4 files changed, 309 insertions, 56 deletions
diff --git a/carousel/java/com/android/ex/carousel/CarouselRS.java b/carousel/java/com/android/ex/carousel/CarouselRS.java
index e6433d2..f9fbadf 100644
--- a/carousel/java/com/android/ex/carousel/CarouselRS.java
+++ b/carousel/java/com/android/ex/carousel/CarouselRS.java
@@ -296,7 +296,7 @@ public class CarouselRS {
programStoreBuilder.setDepthFunc(ProgramStore.DepthFunc.LESS);
programStoreBuilder.setBlendFunc(ProgramStore.BlendSrcFunc.SRC_ALPHA,
ProgramStore.BlendDstFunc.ONE_MINUS_SRC_ALPHA);
- programStoreBuilder.setDitherEnable(false);
+ programStoreBuilder.setDitherEnable(true);
programStoreBuilder.setDepthMask(true);
mProgramStore = programStoreBuilder.create();
mScript.set_programStore(mProgramStore);
@@ -363,7 +363,7 @@ public class CarouselRS {
{
if (bitmap == null) return null;
Allocation allocation = Allocation.createFromBitmap(mRS, bitmap,
- elementForBitmap(bitmap, Bitmap.Config.RGB_565), mipmap);
+ elementForBitmap(bitmap, Bitmap.Config.ARGB_4444), mipmap);
allocation.uploadToTexture(0);
return allocation;
}
@@ -380,7 +380,8 @@ public class CarouselRS {
}
if (bitmap != null) {
if (DBG) Log.v(TAG, "creating new bitmap");
- item.texture = Allocation.createFromBitmap(mRS, bitmap, RGB_565(mRS), MIPMAP);
+ item.texture = Allocation.createFromBitmap(mRS, bitmap,
+ elementForBitmap(bitmap, Bitmap.Config.ARGB_4444), MIPMAP);
if (DBG) Log.v(TAG, "uploadToTexture(" + n + ")");
item.texture.uploadToTexture(0);
if (DBG) Log.v(TAG, "done...");
diff --git a/carousel/java/com/android/ex/carousel/CarouselView.java b/carousel/java/com/android/ex/carousel/CarouselView.java
index 92e870e..740c4b9 100644
--- a/carousel/java/com/android/ex/carousel/CarouselView.java
+++ b/carousel/java/com/android/ex/carousel/CarouselView.java
@@ -21,6 +21,7 @@ import com.android.ex.carousel.CarouselRS.CarouselCallback;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
+import android.graphics.PixelFormat;
import android.graphics.Bitmap.Config;
import android.renderscript.FileA3D;
import android.renderscript.Float4;
@@ -80,6 +81,7 @@ public abstract class CarouselView extends RSSurfaceView {
private float mAt[] = { 14.7255f, -3.40001f, -1.30184f };
private float mUp[] = { 0.0f, 1.0f, 0.0f };
private Float4 mBackgroundColor = new Float4(0.0f, 0.0f, 0.0f, 1.0f);
+ private CarouselCallback mCarouselCallback;
public static class Info {
public Info(int _resId) { resId = _resId; }
@@ -243,6 +245,10 @@ public abstract class CarouselView extends RSSurfaceView {
}
}
+ public int getCardCount() {
+ return mCardCount;
+ }
+
/**
* This sets the texture on card n. It should only be called in response to
* {@link CarouselCallback#onRequestTexture(int)}. Since there's no guarantee
@@ -504,57 +510,4 @@ public abstract class CarouselView extends RSSurfaceView {
return true;
}
-
- private final CarouselCallback DEBUG_CALLBACK = new CarouselCallback() {
- @Override
- public void onAnimationStarted() {
- if (DBG) Log.v(TAG, "onAnimationStarted()");
- }
-
- @Override
- public void onAnimationFinished() {
- if (DBG) Log.v(TAG, "onAnimationFinished()");
- }
-
- @Override
- public void onCardSelected(int n) {
- if (DBG) Log.v(TAG, "onCardSelected(" + n + ")");
- }
-
- @Override
- public void onRequestGeometry(int n) {
- if (DBG) Log.v(TAG, "onRequestGeometry(" + n + ")");
- }
-
- @Override
- public void onInvalidateGeometry(int n) {
- if (DBG) Log.v(TAG, "onInvalidateGeometry(" + n + ")");
- }
-
- @Override
- public void onRequestTexture(int n) {
- if (DBG) Log.v(TAG, "onRequestTexture(" + n + ")");
- }
-
- @Override
- public void onInvalidateTexture(int n) {
- if (DBG) Log.v(TAG, "onInvalidateTexture(" + n + ")");
- }
-
- public void onRequestDetailTexture(int n) {
- if (DBG) Log.v(TAG, "onRequestDetailTexture(" + n + ")");
- }
-
- public void onInvalidateDetailTexture(int n) {
- if (DBG) Log.v(TAG, "onInvalidateDetailTexture(" + n + ")");
- }
-
- @Override
- public void onReportFirstCardPosition(int n) {
- Log.v(TAG, "onReportFirstCardPosition(" + n + ")");
- }
- };
-
- private CarouselCallback mCarouselCallback = DEBUG_CALLBACK;
-
}
diff --git a/carousel/java/com/android/ex/carousel/CarouselViewHelper.java b/carousel/java/com/android/ex/carousel/CarouselViewHelper.java
new file mode 100644
index 0000000..55feb09
--- /dev/null
+++ b/carousel/java/com/android/ex/carousel/CarouselViewHelper.java
@@ -0,0 +1,260 @@
+package com.android.ex.carousel;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Matrix;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Looper;
+import android.os.Message;
+import android.renderscript.Mesh;
+import android.util.Log;
+
+import com.android.ex.carousel.CarouselRS.CarouselCallback;
+
+/**
+ * CarouselViewHelper wraps all of the threading and event handling of the CarouselView,
+ * providing a simpler interface. Most users will just need to implement a handful of
+ * methods to get an application working.
+ *
+ */
+public class CarouselViewHelper implements CarouselCallback {
+ private static final String TAG = "CarouselViewHelper";
+ private static final int SET_TEXTURE_N = 1;
+ private static final int SET_DETAIL_TEXTURE_N = 2;
+ private static final int SET_GEOMETRY_N = 3;
+
+ // This is an ordered list of base message ids to allow removal of a single item from the
+ // list for a particular card. The implementation currently supports up to a million cards.
+ private static final int REQUEST_TEXTURE_N = 1000000;
+ private static final int REQUEST_DETAIL_TEXTURE_N = 2000000;
+ private static final int REQUEST_GEOMETRY_N = 3000000;
+ private static final int REQUEST_END = 4000000;
+
+ private HandlerThread mHandlerThread;
+ private Context mContext;
+ private CarouselView mCarouselView;
+ private boolean DBG = true;
+ private long HOLDOFF_DELAY = 100;
+ private Handler mAsyncHandler; // Background thread handler for reading textures, geometry, etc.
+ private Handler mSyncHandler; // Synchronous handler for interacting with UI elements.
+
+ public class TextureParameters {
+ public TextureParameters(Matrix _matrix) { matrix = _matrix; }
+ public Matrix matrix;
+ };
+
+ public class DetailTextureParameters {
+ public DetailTextureParameters(float offX, float offY) {
+ offsetX = offX;
+ offsetY = offY;
+ }
+ public float offsetX;
+ public float offsetY;
+ };
+
+ public void setCarouselView(CarouselView carouselView) {
+ mCarouselView = carouselView;
+ mCarouselView.setCallback(this);
+ }
+
+ public CarouselViewHelper(Context context, CarouselView carouselView) {
+ this(context);
+ setCarouselView(carouselView);
+ }
+
+ public CarouselViewHelper(Context context) {
+ mContext = context;
+
+ mHandlerThread = new HandlerThread(TAG + ".handler");
+ mHandlerThread.start();
+
+ mAsyncHandler = new AsyncHandler(mHandlerThread.getLooper());
+ mSyncHandler = new SyncHandler(); // runs in calling thread
+ }
+
+ class AsyncHandler extends Handler {
+ AsyncHandler(Looper looper) {
+ super(looper);
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ int id = msg.arg1;
+ if (id >= mCarouselView.getCardCount()) {
+ Log.e(TAG, "Index out of range for get, card:" + id);
+ return;
+ }
+ if (msg.what < REQUEST_TEXTURE_N || msg.what > REQUEST_END) {
+ Log.e(TAG, "Unknown message: " + id);
+ return;
+ }
+ if (msg.what < REQUEST_DETAIL_TEXTURE_N) {
+ // REQUEST_TEXTURE_N
+ final Bitmap bitmap = getTexture(id);
+ if (bitmap != null) {
+ mSyncHandler.obtainMessage(SET_TEXTURE_N, id, 0, bitmap).sendToTarget();
+ }
+ } else if (msg.what < REQUEST_GEOMETRY_N) {
+ // REQUEST_DETAIL_TEXTURE_N
+ final Bitmap bitmap = getDetailTexture(id);
+ if (bitmap != null) {
+ mSyncHandler.obtainMessage(SET_DETAIL_TEXTURE_N, id, 0, bitmap).sendToTarget();
+ }
+ } else if (msg.what < REQUEST_END) {
+ // REQUEST_GEOMETRY_N
+ Mesh mesh = getGeometry(id);
+ if (mesh != null) {
+ mSyncHandler.obtainMessage(SET_GEOMETRY_N, id, 0, mesh).sendToTarget();
+ }
+ }
+ }
+ };
+
+ class SyncHandler extends Handler {
+ @Override
+ public void handleMessage(Message msg) {
+ int id = msg.arg1;
+ if (id >= mCarouselView.getCardCount()) {
+ Log.e(TAG, "Index out of range for set, card:" + id);
+ return;
+ }
+
+ switch (msg.what) {
+ case SET_TEXTURE_N:
+ mCarouselView.setTextureForItem(id, (Bitmap) msg.obj);
+ break;
+
+ case SET_DETAIL_TEXTURE_N:
+ DetailTextureParameters params = getDetailTextureParameters(id);
+ float x = params != null ? params.offsetX : 0.0f;
+ float y = params != null ? params.offsetY : 0.0f;
+ mCarouselView.setDetailTextureForItem(id, x, y, (Bitmap) msg.obj);
+ break;
+
+ case SET_GEOMETRY_N:
+ mCarouselView.setGeometryForItem(id, (Mesh) msg.obj);
+ break;
+ }
+ }
+ };
+
+ /**
+ * Implement this method if you want to load a texture for
+ * the given card. Most subclasses will implement this. Note: this will generally
+ * <b>not</b> be called in the UI thread, so proper locking should be ensured.
+ *
+ * @param id of the texture to load
+ * @return a valid bitmap
+ */
+ public Bitmap getTexture(int id) {
+ return null;
+ }
+
+ /**
+ * Implement this method if you want to load a detail texture for
+ * the given card. Most subclasses will implement this. Note: this will generally
+ * <b>not</b> be called in the UI thread, so proper locking should be ensured.
+ *
+ * @param id
+ * @return
+ */
+ public Bitmap getDetailTexture(int id) {
+ return null;
+ }
+
+ /**
+ * Implement this method if you want to load geometry for the given card. Most subclasses
+ * will implement this. Note: this will generally <b>not</b> be called in the UI thread,
+ * so proper locking should be ensured.
+ *
+ * @param id
+ * @return
+ */
+ private Mesh getGeometry(int id) {
+ return null;
+ }
+
+ /**
+ * Implement this method if you want custom texture parameters for
+ * the given id. Note: this will generally
+ * <b>not</b> be called in the UI thread, so proper locking should be ensured.
+ *
+ * @param id
+ * @return texture parameters
+ */
+ public TextureParameters getTextureParameters(int id) {
+ return null;
+ }
+
+ /**
+ * Implement this method if you want custom detail texture parameters for
+ * the given id. Note: this will generally
+ * <b>not</b> be called in the UI thread, so proper locking should be ensured.
+ *
+ * @param id the id of the texture being requested
+ * @return detail texture parameters
+ */
+ public DetailTextureParameters getDetailTextureParameters(int id) {
+ return null;
+ }
+
+ public void onRequestTexture(int id) {
+ if (DBG) Log.v(TAG, "onRequestTexture(" + id + ")" );
+ mAsyncHandler.removeMessages(REQUEST_TEXTURE_N + id);
+ Message message = mAsyncHandler.obtainMessage(REQUEST_TEXTURE_N + id, id, 0);
+ mAsyncHandler.sendMessageDelayed(message, HOLDOFF_DELAY);
+ }
+
+ public void onInvalidateTexture(final int id) {
+ if (DBG) Log.v(TAG, "onInvalidateTexture(" + id + ")");
+ mAsyncHandler.removeMessages(REQUEST_TEXTURE_N + id);
+ }
+
+ public void onRequestGeometry(int id) {
+ if (DBG) Log.v(TAG, "onRequestGeometry(" + id + ")");
+ mAsyncHandler.removeMessages(REQUEST_GEOMETRY_N + id);
+ mAsyncHandler.sendMessage(mAsyncHandler.obtainMessage(REQUEST_GEOMETRY_N + id, id, 0));
+ }
+
+ public void onInvalidateGeometry(int id) {
+ if (DBG) Log.v(TAG, "onInvalidateGeometry(" + id + ")");
+ mAsyncHandler.removeMessages(REQUEST_GEOMETRY_N + id);
+ }
+
+ public void onRequestDetailTexture(int id) {
+ if (DBG) Log.v(TAG, "onRequestDetailTexture(" + id + ")" );
+ mAsyncHandler.removeMessages(REQUEST_DETAIL_TEXTURE_N + id);
+ Message message = mAsyncHandler.obtainMessage(REQUEST_DETAIL_TEXTURE_N + id, id, 0);
+ mAsyncHandler.sendMessageDelayed(message, HOLDOFF_DELAY);
+ }
+
+ public void onInvalidateDetailTexture(int id) {
+ if (DBG) Log.v(TAG, "onInvalidateDetailTexture(" + id + ")");
+ mAsyncHandler.removeMessages(REQUEST_DETAIL_TEXTURE_N + id);
+ }
+
+ public void onCardSelected(int n) {
+ if (DBG) Log.v(TAG, "onCardSelected(" + n + ")");
+ }
+
+ public void onAnimationStarted() {
+
+ }
+
+ public void onAnimationFinished() {
+
+ }
+
+ public void onReportFirstCardPosition(int n) {
+
+ }
+
+ public void onResume() {
+ mCarouselView.onResume();
+ }
+
+ public void onPause() {
+ mCarouselView.onPause();
+ }
+}
diff --git a/carousel/java/com/android/ex/carousel/CarouselViewUtilities.java b/carousel/java/com/android/ex/carousel/CarouselViewUtilities.java
new file mode 100644
index 0000000..8b53734
--- /dev/null
+++ b/carousel/java/com/android/ex/carousel/CarouselViewUtilities.java
@@ -0,0 +1,39 @@
+package com.android.ex.carousel;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.media.MediaScannerConnection;
+import android.os.Environment;
+import android.util.Log;
+
+public class CarouselViewUtilities {
+ /**
+ * Debug utility to write the given bitmap to a file.
+ *
+ * @param context calling context
+ * @param bitmap the bitmap to write
+ * @param filename the name of the file to write
+ * @return
+ */
+ public static boolean writeBitmapToFile(Context context, Bitmap bitmap, String filename) {
+ File path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
+ File file = new File(path, filename);
+ boolean result = false;
+ try {
+ path.mkdirs();
+ OutputStream os = new FileOutputStream(file);
+ MediaScannerConnection.scanFile(context, new String[] { file.toString() }, null, null);
+ bitmap.compress(Bitmap.CompressFormat.PNG, 100, os);
+ result = true;
+ } catch (IOException e) {
+ Log.w("ExternalStorage", "Error writing " + file, e);
+ }
+ return result;
+ }
+
+}