Home | History | Annotate | Download | only in carousel
      1 package com.android.ex.carousel;
      2 
      3 import android.content.Context;
      4 import android.graphics.Bitmap;
      5 import android.graphics.Matrix;
      6 import android.graphics.Rect;
      7 import android.os.Handler;
      8 import android.os.HandlerThread;
      9 import android.os.Looper;
     10 import android.os.Message;
     11 import android.renderscript.Matrix4f;
     12 import android.renderscript.Mesh;
     13 import android.util.Log;
     14 
     15 import com.android.ex.carousel.CarouselRS.CarouselCallback;
     16 
     17 /**
     18  * CarouselViewHelper wraps all of the threading and event handling of the CarouselView,
     19  * providing a simpler interface.  Most users will just need to implement a handful of
     20  * methods to get an application working.
     21  *
     22  */
     23 public class CarouselViewHelper implements CarouselCallback {
     24     private static final String TAG = "CarouselViewHelper";
     25     private static final int SET_TEXTURE_N = 1;
     26     private static final int SET_DETAIL_TEXTURE_N = 2;
     27     private static final int SET_GEOMETRY_N = 3;
     28     private static final int SET_MATRIX_N = 4;
     29 
     30     // This is an ordered list of base message ids to allow removal of a single item from the
     31     // list for a particular card. The implementation currently supports up to a million cards.
     32     private static final int REQUEST_TEXTURE_N = 1000000;
     33     private static final int REQUEST_DETAIL_TEXTURE_N = 2000000;
     34     private static final int REQUEST_GEOMETRY_N = 3000000;
     35     private static final int REQUEST_END = 4000000;
     36 
     37     private HandlerThread mHandlerThread;
     38     private Context mContext;
     39     private CarouselView mCarouselView;
     40     private boolean DBG = false;
     41     private long HOLDOFF_DELAY = 100;
     42     private Handler mAsyncHandler; // Background thread handler for reading textures, geometry, etc.
     43     private Handler mSyncHandler; // Synchronous handler for interacting with UI elements.
     44 
     45     public static class TextureParameters {
     46         public TextureParameters() { matrix = new Matrix4f(); }
     47         public TextureParameters(Matrix4f _matrix) { matrix = _matrix; }
     48         public Matrix4f matrix;
     49     };
     50 
     51     public static class DetailTextureParameters {
     52         public DetailTextureParameters(float textureOffsetX, float textureOffsetY) {
     53             this.textureOffsetX = textureOffsetX;
     54             this.textureOffsetY = textureOffsetY;
     55             this.lineOffsetX = 0.0f;
     56             this.lineOffsetY = 0.0f;
     57         }
     58         public DetailTextureParameters(
     59                 float textureOffsetX, float textureOffsetY,
     60                 float lineOffsetX, float lineOffsetY) {
     61             this.textureOffsetX = textureOffsetX;
     62             this.textureOffsetY = textureOffsetY;
     63             this.lineOffsetX = lineOffsetX;
     64             this.lineOffsetY = lineOffsetY;
     65         }
     66         public float textureOffsetX;
     67         public float textureOffsetY;
     68         public float lineOffsetX;
     69         public float lineOffsetY;
     70     };
     71 
     72     public void setCarouselView(CarouselView carouselView) {
     73         mCarouselView = carouselView;
     74         mCarouselView.setCallback(this);
     75     }
     76 
     77     public CarouselViewHelper(Context context, CarouselView carouselView) {
     78         this(context);
     79         setCarouselView(carouselView);
     80     }
     81 
     82     public CarouselViewHelper(Context context) {
     83         mContext = context;
     84 
     85         mHandlerThread = new HandlerThread(TAG + ".handler");
     86         mHandlerThread.start();
     87 
     88         mAsyncHandler = new AsyncHandler(mHandlerThread.getLooper());
     89         mSyncHandler = new SyncHandler(); // runs in calling thread
     90     }
     91 
     92     class AsyncHandler extends Handler {
     93         AsyncHandler(Looper looper) {
     94             super(looper);
     95         }
     96 
     97         @Override
     98         public void handleMessage(Message msg) {
     99             int id = msg.arg1;
    100             if (id >= mCarouselView.getCardCount()) {
    101                 Log.e(TAG, "Index out of range for get, card:" + id);
    102                 return;
    103             }
    104             if (msg.what < REQUEST_TEXTURE_N || msg.what > REQUEST_END) {
    105                 Log.e(TAG, "Unknown message: " + id);
    106                 return;
    107             }
    108             if (msg.what < REQUEST_DETAIL_TEXTURE_N) {
    109                 // REQUEST_TEXTURE_N
    110                 final Bitmap bitmap = getTexture(id);
    111                 if (bitmap != null) {
    112                     mSyncHandler.obtainMessage(SET_TEXTURE_N, id, 0, bitmap).sendToTarget();
    113                 }
    114 
    115                 TextureParameters params = getTextureParameters(id);
    116                 if (params != null) {
    117                     mSyncHandler.obtainMessage(SET_MATRIX_N, id, 0,
    118                             params.matrix.getArray()).sendToTarget();
    119                 }
    120             } else if (msg.what < REQUEST_GEOMETRY_N) {
    121                 // REQUEST_DETAIL_TEXTURE_N
    122                 final Bitmap bitmap = getDetailTexture(id);
    123                 if (bitmap != null) {
    124                     mSyncHandler.obtainMessage(SET_DETAIL_TEXTURE_N, id, 0, bitmap).sendToTarget();
    125                 }
    126             } else if (msg.what < REQUEST_END) {
    127                 // REQUEST_GEOMETRY_N
    128                 Mesh mesh = getGeometry(id);
    129                 if (mesh != null) {
    130                     mSyncHandler.obtainMessage(SET_GEOMETRY_N, id, 0, mesh).sendToTarget();
    131                 }
    132             }
    133         }
    134     };
    135 
    136     class SyncHandler extends Handler {
    137         @Override
    138         public void handleMessage(Message msg) {
    139             int id = msg.arg1;
    140             if (id >= mCarouselView.getCardCount()) {
    141                 Log.e(TAG, "Index out of range for set, card:" + id);
    142                 return;
    143             }
    144 
    145             switch (msg.what) {
    146                 case SET_TEXTURE_N:
    147                     mCarouselView.setTextureForItem(id, (Bitmap) msg.obj);
    148                     break;
    149 
    150                 case SET_DETAIL_TEXTURE_N:
    151                     DetailTextureParameters params = getDetailTextureParameters(id);
    152                     float x = params != null ? params.textureOffsetX : 0.0f;
    153                     float y = params != null ? params.textureOffsetY : 0.0f;
    154                     float lx = params != null ? params.lineOffsetX : 0.0f;
    155                     float ly = params != null ? params.lineOffsetY : 0.0f;
    156                     mCarouselView.setDetailTextureForItem(id, x, y, lx, ly, (Bitmap) msg.obj);
    157                     break;
    158 
    159                 case SET_GEOMETRY_N:
    160                     mCarouselView.setGeometryForItem(id, (Mesh) msg.obj);
    161                     break;
    162 
    163                 case SET_MATRIX_N:
    164                     mCarouselView.setMatrixForItem(id, (float[]) msg.obj);
    165                     break;
    166             }
    167         }
    168     };
    169 
    170     /**
    171      * Implement this method if you want to load a texture for
    172      * the given card.  Most subclasses will implement this. Note: this will generally
    173      * <b>not</b> be called in the UI thread, so proper locking should be ensured.
    174      *
    175      * @param id of the texture to load
    176      * @return a valid bitmap
    177      */
    178     public Bitmap getTexture(int id) {
    179         return null;
    180     }
    181 
    182     /**
    183      * Implement this method if you want to load a detail texture for
    184      * the given card.  Most subclasses will implement this. Note: this will generally
    185      * <b>not</b> be called in the UI thread, so proper locking should be ensured.
    186      *
    187      * @param id
    188      * @return
    189      */
    190     public Bitmap getDetailTexture(int id) {
    191         return null;
    192     }
    193 
    194     /**
    195      * Implement this method if you want to load geometry for the given card.  Most subclasses
    196      * will implement this. Note: this will generally <b>not</b> be called in the UI thread,
    197      * so proper locking should be ensured.
    198      *
    199      * @param id
    200      * @return
    201      */
    202     public Mesh getGeometry(int id) {
    203         return null;
    204     }
    205 
    206     /**
    207      * Implement this method if you want custom texture parameters for
    208      * the given id. Note: this will generally
    209      * <b>not</b> be called in the UI thread, so proper locking should be ensured.
    210      *
    211      * @param id
    212      * @return texture parameters
    213      */
    214     public TextureParameters getTextureParameters(int id) {
    215         return null;
    216     }
    217 
    218     /**
    219      * Implement this method if you want custom detail texture parameters for
    220      * the given id. Note: this will generally
    221      * <b>not</b> be called in the UI thread, so proper locking should be ensured.
    222      *
    223      * @param id the id of the texture being requested
    224      * @return detail texture parameters
    225      */
    226     public DetailTextureParameters getDetailTextureParameters(int id) {
    227         return null;
    228     }
    229 
    230     public void onRequestTexture(int id) {
    231         if (DBG) Log.v(TAG, "onRequestTexture(" + id + ")" );
    232         mAsyncHandler.removeMessages(REQUEST_TEXTURE_N + id);
    233         Message message = mAsyncHandler.obtainMessage(REQUEST_TEXTURE_N + id, id, 0);
    234         mAsyncHandler.sendMessageDelayed(message, HOLDOFF_DELAY);
    235     }
    236 
    237     public void onInvalidateTexture(final int id) {
    238         if (DBG) Log.v(TAG, "onInvalidateTexture(" + id + ")");
    239         mAsyncHandler.removeMessages(REQUEST_TEXTURE_N + id);
    240     }
    241 
    242     public void onRequestGeometry(int id) {
    243         if (DBG) Log.v(TAG, "onRequestGeometry(" + id + ")");
    244         mAsyncHandler.removeMessages(REQUEST_GEOMETRY_N + id);
    245         mAsyncHandler.sendMessage(mAsyncHandler.obtainMessage(REQUEST_GEOMETRY_N + id, id, 0));
    246     }
    247 
    248     public void onInvalidateGeometry(int id) {
    249         if (DBG) Log.v(TAG, "onInvalidateGeometry(" + id + ")");
    250         mAsyncHandler.removeMessages(REQUEST_GEOMETRY_N + id);
    251     }
    252 
    253     public void onRequestDetailTexture(int id) {
    254         if (DBG) Log.v(TAG, "onRequestDetailTexture(" + id + ")" );
    255         mAsyncHandler.removeMessages(REQUEST_DETAIL_TEXTURE_N + id);
    256         Message message = mAsyncHandler.obtainMessage(REQUEST_DETAIL_TEXTURE_N + id, id, 0);
    257         mAsyncHandler.sendMessageDelayed(message, HOLDOFF_DELAY);
    258     }
    259 
    260     public void onInvalidateDetailTexture(int id) {
    261         if (DBG) Log.v(TAG, "onInvalidateDetailTexture(" + id + ")");
    262         mAsyncHandler.removeMessages(REQUEST_DETAIL_TEXTURE_N + id);
    263     }
    264 
    265     public void onCardSelected(int n) {
    266         if (DBG) Log.v(TAG, "onCardSelected(" + n + ")");
    267     }
    268 
    269     public void onDetailSelected(int n, int x, int y) {
    270         if (DBG) Log.v(TAG, "onDetailSelected(" + n + ", " + x + ", " + y + ")");
    271     }
    272 
    273     public void onCardLongPress(int n, int touchPosition[], Rect detailCoordinates) {
    274         if (DBG) Log.v(TAG, "onCardLongPress(" + n + ", (" + touchPosition + "), (" +
    275                 detailCoordinates +") )");
    276     }
    277 
    278     public void onAnimationStarted() {
    279 
    280     }
    281 
    282     public void onAnimationFinished(float carouselRotationAngle) {
    283 
    284     }
    285 
    286     public void onResume() {
    287         mCarouselView.resume();
    288     }
    289 
    290     public void onPause() {
    291         mCarouselView.pause();
    292     }
    293 
    294     public void onDestroy() {
    295         mHandlerThread.quit();
    296     }
    297 
    298     protected Handler getAsyncHandler() {
    299         return mAsyncHandler;
    300     }
    301 
    302     protected CarouselView getCarouselView() {
    303         return mCarouselView;
    304     }
    305 }
    306