• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 {
TextureParameters()46         public TextureParameters() { matrix = new Matrix4f(); }
TextureParameters(Matrix4f _matrix)47         public TextureParameters(Matrix4f _matrix) { matrix = _matrix; }
48         public Matrix4f matrix;
49     };
50 
51     public static class DetailTextureParameters {
DetailTextureParameters(float textureOffsetX, float textureOffsetY)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         }
DetailTextureParameters( float textureOffsetX, float textureOffsetY, float lineOffsetX, float lineOffsetY)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 
setCarouselView(CarouselView carouselView)72     public void setCarouselView(CarouselView carouselView) {
73         mCarouselView = carouselView;
74         mCarouselView.setCallback(this);
75     }
76 
CarouselViewHelper(Context context, CarouselView carouselView)77     public CarouselViewHelper(Context context, CarouselView carouselView) {
78         this(context);
79         setCarouselView(carouselView);
80     }
81 
CarouselViewHelper(Context context)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 {
AsyncHandler(Looper looper)93         AsyncHandler(Looper looper) {
94             super(looper);
95         }
96 
97         @Override
handleMessage(Message msg)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
handleMessage(Message msg)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      */
getTexture(int id)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      */
getDetailTexture(int id)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      */
getGeometry(int id)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      */
getTextureParameters(int id)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      */
getDetailTextureParameters(int id)226     public DetailTextureParameters getDetailTextureParameters(int id) {
227         return null;
228     }
229 
onRequestTexture(int id)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 
onInvalidateTexture(final int id)237     public void onInvalidateTexture(final int id) {
238         if (DBG) Log.v(TAG, "onInvalidateTexture(" + id + ")");
239         mAsyncHandler.removeMessages(REQUEST_TEXTURE_N + id);
240     }
241 
onRequestGeometry(int id)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 
onInvalidateGeometry(int id)248     public void onInvalidateGeometry(int id) {
249         if (DBG) Log.v(TAG, "onInvalidateGeometry(" + id + ")");
250         mAsyncHandler.removeMessages(REQUEST_GEOMETRY_N + id);
251     }
252 
onRequestDetailTexture(int id)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 
onInvalidateDetailTexture(int id)260     public void onInvalidateDetailTexture(int id) {
261         if (DBG) Log.v(TAG, "onInvalidateDetailTexture(" + id + ")");
262         mAsyncHandler.removeMessages(REQUEST_DETAIL_TEXTURE_N + id);
263     }
264 
onCardSelected(int n)265     public void onCardSelected(int n) {
266         if (DBG) Log.v(TAG, "onCardSelected(" + n + ")");
267     }
268 
onDetailSelected(int n, int x, int y)269     public void onDetailSelected(int n, int x, int y) {
270         if (DBG) Log.v(TAG, "onDetailSelected(" + n + ", " + x + ", " + y + ")");
271     }
272 
onCardLongPress(int n, int touchPosition[], Rect detailCoordinates)273     public void onCardLongPress(int n, int touchPosition[], Rect detailCoordinates) {
274         if (DBG) Log.v(TAG, "onCardLongPress(" + n + ", (" + touchPosition + "), (" +
275                 detailCoordinates +") )");
276     }
277 
onAnimationStarted()278     public void onAnimationStarted() {
279 
280     }
281 
onAnimationFinished(float carouselRotationAngle)282     public void onAnimationFinished(float carouselRotationAngle) {
283 
284     }
285 
onResume()286     public void onResume() {
287         mCarouselView.resume();
288     }
289 
onPause()290     public void onPause() {
291         mCarouselView.pause();
292     }
293 
onDestroy()294     public void onDestroy() {
295         mHandlerThread.quit();
296     }
297 
getAsyncHandler()298     protected Handler getAsyncHandler() {
299         return mAsyncHandler;
300     }
301 
getCarouselView()302     protected CarouselView getCarouselView() {
303         return mCarouselView;
304     }
305 }
306