OSDN Git Service

Updated 3D gallery source. Fixes whitespace, several other bugs.
authorDave Sparks <davidsparks@android.com>
Tue, 8 Dec 2009 21:55:22 +0000 (13:55 -0800)
committerDave Sparks <davidsparks@android.com>
Tue, 8 Dec 2009 21:55:22 +0000 (13:55 -0800)
We got out of sync, this is a fresh code drop to resync the trees.

93 files changed:
src/com/cooliris/cache/BootReceiver.java
src/com/cooliris/cache/CacheService.java
src/com/cooliris/media/AdaptiveBackgroundTexture.java
src/com/cooliris/media/ArrayUtils.java
src/com/cooliris/media/BackgroundLayer.java
src/com/cooliris/media/BaseCancelable.java
src/com/cooliris/media/BitmapManager.java
src/com/cooliris/media/BitmapTexture.java
src/com/cooliris/media/Cancelable.java
src/com/cooliris/media/CanvasTexture.java
src/com/cooliris/media/ConcatenatedDataSource.java
src/com/cooliris/media/ContextMenu.java
src/com/cooliris/media/CropImage.java
src/com/cooliris/media/CrossFadingTexture.java
src/com/cooliris/media/DataSource.java
src/com/cooliris/media/Deque.java
src/com/cooliris/media/DetailMode.java
src/com/cooliris/media/DiskCache.java
src/com/cooliris/media/DisplayItem.java
src/com/cooliris/media/DisplaySlot.java
src/com/cooliris/media/FloatAnim.java
src/com/cooliris/media/FloatUtils.java
src/com/cooliris/media/Gallery.java
src/com/cooliris/media/GridCamera.java
src/com/cooliris/media/GridCameraManager.java
src/com/cooliris/media/GridDrawManager.java
src/com/cooliris/media/GridDrawables.java
src/com/cooliris/media/GridInputProcessor.java
src/com/cooliris/media/GridLayer.java
src/com/cooliris/media/GridLayoutInterface.java
src/com/cooliris/media/GridQuad.java
src/com/cooliris/media/GridQuadFrame.java
src/com/cooliris/media/GridQuadMesh.java
src/com/cooliris/media/HighlightView.java
src/com/cooliris/media/HudLayer.java
src/com/cooliris/media/ImageButton.java
src/com/cooliris/media/ImageManager.java
src/com/cooliris/media/ImageViewTouchBase.java
src/com/cooliris/media/Layer.java
src/com/cooliris/media/LayoutInterface.java
src/com/cooliris/media/LoadingLayer.java
src/com/cooliris/media/LocalDataSource.java
src/com/cooliris/media/LocationMediaFilter.java
src/com/cooliris/media/LongSparseArray.java
src/com/cooliris/media/MatrixStack.java
src/com/cooliris/media/MediaBucketList.java
src/com/cooliris/media/MediaClustering.java
src/com/cooliris/media/MediaFeed.java
src/com/cooliris/media/MediaItem.java
src/com/cooliris/media/MediaItemTexture.java
src/com/cooliris/media/MediaSet.java
src/com/cooliris/media/MenuBar.java
src/com/cooliris/media/MonitoredActivity.java
src/com/cooliris/media/MovieView.java
src/com/cooliris/media/MovieViewControl.java
src/com/cooliris/media/PathBarLayer.java
src/com/cooliris/media/PhotoAppWidgetBind.java
src/com/cooliris/media/PhotoAppWidgetConfigure.java
src/com/cooliris/media/PhotoAppWidgetProvider.java
src/com/cooliris/media/Photographs.java
src/com/cooliris/media/PicasaDataSource.java
src/com/cooliris/media/PopupMenu.java
src/com/cooliris/media/RenderView.java
src/com/cooliris/media/ReverseGeocoder.java
src/com/cooliris/media/RootLayer.java
src/com/cooliris/media/RotateBitmap.java
src/com/cooliris/media/Shared.java
src/com/cooliris/media/SimpleStringTexture.java
src/com/cooliris/media/SingleDataSource.java
src/com/cooliris/media/SortCursor.java
src/com/cooliris/media/StringTexture.java
src/com/cooliris/media/Texture.java
src/com/cooliris/media/TimeBar.java
src/com/cooliris/media/UriTexture.java
src/com/cooliris/media/Util.java
src/com/cooliris/media/Utils.java
src/com/cooliris/media/Vector3f.java
src/com/cooliris/media/Wallpaper.java
src/com/cooliris/picasa/AlbumEntry.java
src/com/cooliris/picasa/Entry.java
src/com/cooliris/picasa/EntrySchema.java
src/com/cooliris/picasa/GDataClient.java
src/com/cooliris/picasa/GDataParser.java
src/com/cooliris/picasa/PhotoEntry.java
src/com/cooliris/picasa/PicasaApi.java
src/com/cooliris/picasa/PicasaContentProvider.java
src/com/cooliris/picasa/PicasaReceiver.java
src/com/cooliris/picasa/PicasaService.java
src/com/cooliris/picasa/PicasaSyncAdapter.java
src/com/cooliris/picasa/TableContentProvider.java
src/com/cooliris/picasa/UserEntry.java
src/com/cooliris/wallpaper/RandomDataSource.java
src/com/cooliris/wallpaper/Slideshow.java

index e19aba6..a976326 100644 (file)
@@ -41,7 +41,7 @@ public class BootReceiver extends BroadcastReceiver {
             final ContentObserver localObserver = new ContentObserver(handler) {
                 public void onChange(boolean selfChange) {
                     if (!LocalDataSource.sObserverActive) {
-                       CacheService.senseDirty(context, null);
+                        CacheService.senseDirty(context, null);
                     }
                 }
             };
@@ -52,11 +52,11 @@ public class BootReceiver extends BroadcastReceiver {
             cr.registerContentObserver(uriImages, false, localObserver);
             cr.registerContentObserver(uriVideos, false, localObserver);
         } else if (action.equals(Intent.ACTION_MEDIA_EJECT)) {
-               LocalDataSource.sThumbnailCache.close();
-               LocalDataSource.sThumbnailCacheVideo.close();
-               PicasaDataSource.sThumbnailCache.close();
-               CacheService.sAlbumCache.close();
-               CacheService.sMetaAlbumCache.close();
+            LocalDataSource.sThumbnailCache.close();
+            LocalDataSource.sThumbnailCacheVideo.close();
+            PicasaDataSource.sThumbnailCache.close();
+            CacheService.sAlbumCache.close();
+            CacheService.sMetaAlbumCache.close();
         }
     }
 }
index a3bd75c..00fda9f 100644 (file)
@@ -14,7 +14,6 @@ import java.text.DateFormat;
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Date;
 import java.util.Locale;
 import java.util.concurrent.atomic.AtomicReference;
@@ -55,1168 +54,1200 @@ import com.cooliris.media.UriTexture;
 import com.cooliris.media.Utils;
 
 public final class CacheService extends IntentService {
-       public static final String ACTION_CACHE = "com.cooliris.cache.action.CACHE";
-       public static final DiskCache sAlbumCache = new DiskCache("local-album-cache");
-       public static final DiskCache sMetaAlbumCache = new DiskCache("local-meta-cache");
-
-       private static final String TAG = "CacheService";
-       private static ImageList sList = null;
-
-       // Wait 2 seconds to start the thumbnailer so that the application can load
-       // without any overheads.
-       private static final int THUMBNAILER_WAIT_IN_MS = 2000;
-       private static final int DEFAULT_THUMBNAIL_WIDTH = 128;
-       private static final int DEFAULT_THUMBNAIL_HEIGHT = 96;
-
-       public static final String DEFAULT_IMAGE_SORT_ORDER = Images.ImageColumns.DATE_TAKEN + " ASC";
-       public static final String DEFAULT_VIDEO_SORT_ORDER = Video.VideoColumns.DATE_TAKEN + " ASC";
-       public static final String DEFAULT_BUCKET_SORT_ORDER = "upper(" + Images.ImageColumns.BUCKET_DISPLAY_NAME + ") ASC";
-
-       // Must preserve order between these indices and the order of the terms in
-       // BUCKET_PROJECTION_IMAGES, BUCKET_PROJECTION_VIDEOS.
-       // Not using SortedHashMap for efficieny reasons.
-       public static final int BUCKET_ID_INDEX = 0;
-       public static final int BUCKET_NAME_INDEX = 1;
-       public static final String[] BUCKET_PROJECTION_IMAGES = new String[] { Images.ImageColumns.BUCKET_ID,
-               Images.ImageColumns.BUCKET_DISPLAY_NAME };
-
-       public static final String[] BUCKET_PROJECTION_VIDEOS = new String[] { Video.VideoColumns.BUCKET_ID,
-               Video.VideoColumns.BUCKET_DISPLAY_NAME };
-
-       // Must preserve order between these indices and the order of the terms in
-       // THUMBNAIL_PROJECTION.
-       public static final int THUMBNAIL_ID_INDEX = 0;
-       public static final int THUMBNAIL_DATE_MODIFIED_INDEX = 1;
-       public static final int THUMBNAIL_DATA_INDEX = 2;
-       public static final int THUMBNAIL_ORIENTATION_INDEX = 2;
-       public static final String[] THUMBNAIL_PROJECTION = new String[] { Images.ImageColumns._ID, Images.ImageColumns.DATE_MODIFIED,
-               Images.ImageColumns.DATA, Images.ImageColumns.ORIENTATION };
-
-       public static final String[] SENSE_PROJECTION = new String[] { Images.ImageColumns.BUCKET_ID,
-               "MAX(" + Images.ImageColumns.DATE_ADDED + "), COUNT(*)" };
-
-       // Must preserve order between these indices and the order of the terms in
-       // INITIAL_PROJECTION_IMAGES and
-       // INITIAL_PROJECTION_VIDEOS.
-       public static final int MEDIA_ID_INDEX = 0;
-       public static final int MEDIA_CAPTION_INDEX = 1;
-       public static final int MEDIA_MIME_TYPE_INDEX = 2;
-       public static final int MEDIA_LATITUDE_INDEX = 3;
-       public static final int MEDIA_LONGITUDE_INDEX = 4;
-       public static final int MEDIA_DATE_TAKEN_INDEX = 5;
-       public static final int MEDIA_DATE_ADDED_INDEX = 6;
-       public static final int MEDIA_DATE_MODIFIED_INDEX = 7;
-       public static final int MEDIA_DATA_INDEX = 8;
-       public static final int MEDIA_ORIENTATION_OR_DURATION_INDEX = 9;
-       public static final int MEDIA_BUCKET_ID_INDEX = 10;
-       public static final String[] PROJECTION_IMAGES = new String[] { Images.ImageColumns._ID, Images.ImageColumns.TITLE,
-               Images.ImageColumns.MIME_TYPE, Images.ImageColumns.LATITUDE, Images.ImageColumns.LONGITUDE,
-               Images.ImageColumns.DATE_TAKEN, Images.ImageColumns.DATE_ADDED, Images.ImageColumns.DATE_MODIFIED,
-               Images.ImageColumns.DATA, Images.ImageColumns.ORIENTATION, Images.ImageColumns.BUCKET_ID };
-
-       private static final String[] PROJECTION_VIDEOS = new String[] { Video.VideoColumns._ID, Video.VideoColumns.TITLE,
-               Video.VideoColumns.MIME_TYPE, Video.VideoColumns.LATITUDE, Video.VideoColumns.LONGITUDE, Video.VideoColumns.DATE_TAKEN,
-               Video.VideoColumns.DATE_ADDED, Video.VideoColumns.DATE_MODIFIED, Video.VideoColumns.DATA, Video.VideoColumns.DURATION,
-               Video.VideoColumns.BUCKET_ID };
-
-       public static final String BASE_CONTENT_STRING_IMAGES = (Images.Media.EXTERNAL_CONTENT_URI).toString() + "/";
-       public static final String BASE_CONTENT_STRING_VIDEOS = (Video.Media.EXTERNAL_CONTENT_URI).toString() + "/";
-       private static final AtomicReference<Thread> CACHE_THREAD = new AtomicReference<Thread>();
-       private static final AtomicReference<Thread> THUMBNAIL_THREAD = new AtomicReference<Thread>();
-
-       // Special indices in the Albumcache.
-       private static final int ALBUM_CACHE_METADATA_INDEX = -1;
-       private static final int ALBUM_CACHE_DIRTY_INDEX = -2;
-       private static final int ALBUM_CACHE_INCOMPLETE_INDEX = -3;
-       private static final int ALBUM_CACHE_DIRTY_BUCKET_INDEX = -4;
-       private static final int ALBUM_CACHE_LOCALE_INDEX = -5;
-
-       private static final DateFormat mDateFormat = new SimpleDateFormat("yyyy:MM:dd HH:mm:ss");
-       private static final DateFormat mAltDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
-       private static final byte[] sDummyData = new byte[] { 1 };
-       private static boolean QUEUE_DIRTY_SET;
-       private static boolean QUEUE_DIRTY_ALL;
-       private static boolean QUEUE_DIRTY_SENSE;
-
-       public interface Observer {
-               void onChange(long[] bucketIds);
-       }
-
-       public static final String getCachePath(final String subFolderName) {
-               return Environment.getExternalStorageDirectory() + "/Android/data/com.cooliris.media/cache/" + subFolderName;
-       }
-
-       public static final void startCache(final Context context, final boolean checkthumbnails) {
-               final Locale locale = getLocaleForAlbumCache();
-               final Locale defaultLocale = Locale.getDefault();
-               if (locale == null || !locale.equals(defaultLocale)) {
-                       sAlbumCache.deleteAll();
-                       putLocaleForAlbumCache(defaultLocale);
-               }
-               final Intent intent = new Intent(ACTION_CACHE, null, context, CacheService.class);
-               intent.putExtra("checkthumbnails", checkthumbnails);
-               context.startService(intent);
-       }
-
-       public static final boolean isCacheReady(final boolean onlyMediaSets) {
-               if (onlyMediaSets) {
-                       return (sAlbumCache.get(ALBUM_CACHE_METADATA_INDEX, 0) != null && sAlbumCache.get(ALBUM_CACHE_DIRTY_INDEX, 0) == null);
-               } else {
-                       return (sAlbumCache.get(ALBUM_CACHE_METADATA_INDEX, 0) != null && sAlbumCache.get(ALBUM_CACHE_DIRTY_INDEX, 0) == null && sAlbumCache
-                               .get(ALBUM_CACHE_INCOMPLETE_INDEX, 0) == null);
-               }
-       }
-
-       public static final boolean isCacheReady(final long setId) {
-               final boolean isReady = (sAlbumCache.get(ALBUM_CACHE_METADATA_INDEX, 0) != null
-                       && sAlbumCache.get(ALBUM_CACHE_DIRTY_INDEX, 0) == null && sAlbumCache.get(ALBUM_CACHE_INCOMPLETE_INDEX, 0) == null);
-               if (!isReady) {
-                       return isReady;
-               }
-               // Also, we need to check if this setId is dirty.
-               final byte[] existingData = sAlbumCache.get(ALBUM_CACHE_DIRTY_BUCKET_INDEX, 0);
-               if (existingData != null && existingData.length > 0) {
-                       final long[] ids = toLongArray(existingData);
-                       final int numIds = ids.length;
-                       for (int i = 0; i < numIds; ++i) {
-                               if (ids[i] == setId) {
-                                       return false;
-                               }
-                       }
-               }
-               return true;
-       }
-
-       public static final boolean isPresentInCache(final long setId) {
-               return sAlbumCache.get(setId, 0) != null;
-       }
-
-       public static final void senseDirty(final Context context, final Observer observer) {
-               if (CACHE_THREAD.get() == null) {
-                       QUEUE_DIRTY_SENSE = false;
-                       QUEUE_DIRTY_ALL = false;
-                       QUEUE_DIRTY_SET = false;
-                       restartThread(CACHE_THREAD, "CacheRefresh", new Runnable() {
-                               public void run() {
-                                       try {
-                                               // We sleep for a bit here waiting for the provider database to insert the row(s).
-                                               // This should be unnecessary, and to be fixed in future versions.
-                           Thread.sleep(100);
+    public static final String ACTION_CACHE = "com.cooliris.cache.action.CACHE";
+    public static final DiskCache sAlbumCache = new DiskCache("local-album-cache");
+    public static final DiskCache sMetaAlbumCache = new DiskCache("local-meta-cache");
+
+    private static final String TAG = "CacheService";
+    private static ImageList sList = null;
+
+    // Wait 2 seconds to start the thumbnailer so that the application can load
+    // without any overheads.
+    private static final int THUMBNAILER_WAIT_IN_MS = 2000;
+    private static final int DEFAULT_THUMBNAIL_WIDTH = 128;
+    private static final int DEFAULT_THUMBNAIL_HEIGHT = 96;
+
+    public static final String DEFAULT_IMAGE_SORT_ORDER = Images.ImageColumns.DATE_TAKEN + " ASC";
+    public static final String DEFAULT_VIDEO_SORT_ORDER = Video.VideoColumns.DATE_TAKEN + " ASC";
+    public static final String DEFAULT_BUCKET_SORT_ORDER = "upper(" + Images.ImageColumns.BUCKET_DISPLAY_NAME + ") ASC";
+
+    // Must preserve order between these indices and the order of the terms in
+    // BUCKET_PROJECTION_IMAGES, BUCKET_PROJECTION_VIDEOS.
+    // Not using SortedHashMap for efficieny reasons.
+    public static final int BUCKET_ID_INDEX = 0;
+    public static final int BUCKET_NAME_INDEX = 1;
+    public static final String[] BUCKET_PROJECTION_IMAGES = new String[] { Images.ImageColumns.BUCKET_ID,
+            Images.ImageColumns.BUCKET_DISPLAY_NAME };
+
+    public static final String[] BUCKET_PROJECTION_VIDEOS = new String[] { Video.VideoColumns.BUCKET_ID,
+            Video.VideoColumns.BUCKET_DISPLAY_NAME };
+
+    // Must preserve order between these indices and the order of the terms in
+    // THUMBNAIL_PROJECTION.
+    public static final int THUMBNAIL_ID_INDEX = 0;
+    public static final int THUMBNAIL_DATE_MODIFIED_INDEX = 1;
+    public static final int THUMBNAIL_DATA_INDEX = 2;
+    public static final int THUMBNAIL_ORIENTATION_INDEX = 2;
+    public static final String[] THUMBNAIL_PROJECTION = new String[] { Images.ImageColumns._ID, Images.ImageColumns.DATE_MODIFIED,
+            Images.ImageColumns.DATA, Images.ImageColumns.ORIENTATION };
+
+    public static final String[] SENSE_PROJECTION = new String[] { Images.ImageColumns.BUCKET_ID,
+            "MAX(" + Images.ImageColumns.DATE_ADDED + "), COUNT(*)" };
+
+    // Must preserve order between these indices and the order of the terms in
+    // INITIAL_PROJECTION_IMAGES and
+    // INITIAL_PROJECTION_VIDEOS.
+    public static final int MEDIA_ID_INDEX = 0;
+    public static final int MEDIA_CAPTION_INDEX = 1;
+    public static final int MEDIA_MIME_TYPE_INDEX = 2;
+    public static final int MEDIA_LATITUDE_INDEX = 3;
+    public static final int MEDIA_LONGITUDE_INDEX = 4;
+    public static final int MEDIA_DATE_TAKEN_INDEX = 5;
+    public static final int MEDIA_DATE_ADDED_INDEX = 6;
+    public static final int MEDIA_DATE_MODIFIED_INDEX = 7;
+    public static final int MEDIA_DATA_INDEX = 8;
+    public static final int MEDIA_ORIENTATION_OR_DURATION_INDEX = 9;
+    public static final int MEDIA_BUCKET_ID_INDEX = 10;
+    public static final String[] PROJECTION_IMAGES = new String[] { Images.ImageColumns._ID, Images.ImageColumns.TITLE,
+            Images.ImageColumns.MIME_TYPE, Images.ImageColumns.LATITUDE, Images.ImageColumns.LONGITUDE,
+            Images.ImageColumns.DATE_TAKEN, Images.ImageColumns.DATE_ADDED, Images.ImageColumns.DATE_MODIFIED,
+            Images.ImageColumns.DATA, Images.ImageColumns.ORIENTATION, Images.ImageColumns.BUCKET_ID };
+
+    private static final String[] PROJECTION_VIDEOS = new String[] { Video.VideoColumns._ID, Video.VideoColumns.TITLE,
+            Video.VideoColumns.MIME_TYPE, Video.VideoColumns.LATITUDE, Video.VideoColumns.LONGITUDE, Video.VideoColumns.DATE_TAKEN,
+            Video.VideoColumns.DATE_ADDED, Video.VideoColumns.DATE_MODIFIED, Video.VideoColumns.DATA, Video.VideoColumns.DURATION,
+            Video.VideoColumns.BUCKET_ID };
+
+    public static final String BASE_CONTENT_STRING_IMAGES = (Images.Media.EXTERNAL_CONTENT_URI).toString() + "/";
+    public static final String BASE_CONTENT_STRING_VIDEOS = (Video.Media.EXTERNAL_CONTENT_URI).toString() + "/";
+    private static final AtomicReference<Thread> CACHE_THREAD = new AtomicReference<Thread>();
+    private static final AtomicReference<Thread> THUMBNAIL_THREAD = new AtomicReference<Thread>();
+
+    // Special indices in the Albumcache.
+    private static final int ALBUM_CACHE_METADATA_INDEX = -1;
+    private static final int ALBUM_CACHE_DIRTY_INDEX = -2;
+    private static final int ALBUM_CACHE_INCOMPLETE_INDEX = -3;
+    private static final int ALBUM_CACHE_DIRTY_BUCKET_INDEX = -4;
+    private static final int ALBUM_CACHE_LOCALE_INDEX = -5;
+
+    private static final DateFormat mDateFormat = new SimpleDateFormat("yyyy:MM:dd HH:mm:ss");
+    private static final DateFormat mAltDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
+    private static final byte[] sDummyData = new byte[] { 1 };
+    private static boolean QUEUE_DIRTY_SET;
+    private static boolean QUEUE_DIRTY_ALL;
+    private static boolean QUEUE_DIRTY_SENSE;
+
+    public interface Observer {
+        void onChange(long[] bucketIds);
+    }
+
+    public static final String getCachePath(final String subFolderName) {
+        return Environment.getExternalStorageDirectory() + "/Android/data/com.cooliris.media/cache/" + subFolderName;
+    }
+
+    public static final void startCache(final Context context, final boolean checkthumbnails) {
+        final Locale locale = getLocaleForAlbumCache();
+        final Locale defaultLocale = Locale.getDefault();
+        if (locale == null || !locale.equals(defaultLocale)) {
+            sAlbumCache.deleteAll();
+            putLocaleForAlbumCache(defaultLocale);
+        }
+        final Intent intent = new Intent(ACTION_CACHE, null, context, CacheService.class);
+        intent.putExtra("checkthumbnails", checkthumbnails);
+        context.startService(intent);
+    }
+
+    public static final boolean isCacheReady(final boolean onlyMediaSets) {
+        if (onlyMediaSets) {
+            return (sAlbumCache.get(ALBUM_CACHE_METADATA_INDEX, 0) != null && sAlbumCache.get(ALBUM_CACHE_DIRTY_INDEX, 0) == null);
+        } else {
+            return (sAlbumCache.get(ALBUM_CACHE_METADATA_INDEX, 0) != null && sAlbumCache.get(ALBUM_CACHE_DIRTY_INDEX, 0) == null && sAlbumCache
+                    .get(ALBUM_CACHE_INCOMPLETE_INDEX, 0) == null);
+        }
+    }
+
+    public static final boolean isCacheReady(final long setId) {
+        final boolean isReady = (sAlbumCache.get(ALBUM_CACHE_METADATA_INDEX, 0) != null
+                && sAlbumCache.get(ALBUM_CACHE_DIRTY_INDEX, 0) == null && sAlbumCache.get(ALBUM_CACHE_INCOMPLETE_INDEX, 0) == null);
+        if (!isReady) {
+            return isReady;
+        }
+        // Also, we need to check if this setId is dirty.
+        final byte[] existingData = sAlbumCache.get(ALBUM_CACHE_DIRTY_BUCKET_INDEX, 0);
+        if (existingData != null && existingData.length > 0) {
+            final long[] ids = toLongArray(existingData);
+            final int numIds = ids.length;
+            for (int i = 0; i < numIds; ++i) {
+                if (ids[i] == setId) {
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
+    public static final boolean isPresentInCache(final long setId) {
+        return sAlbumCache.get(setId, 0) != null;
+    }
+
+    public static final void senseDirty(final Context context, final Observer observer) {
+        if (CACHE_THREAD.get() == null) {
+            QUEUE_DIRTY_SENSE = false;
+            QUEUE_DIRTY_ALL = false;
+            QUEUE_DIRTY_SET = false;
+            restartThread(CACHE_THREAD, "CacheRefresh", new Runnable() {
+                public void run() {
+                    try {
+                        // We sleep for a bit here waiting for the provider
+                        // database to insert the row(s).
+                        // This should be unnecessary, and to be fixed in future
+                        // versions.
+                        Thread.sleep(100);
                     } catch (InterruptedException e) {
                     }
-                                       Log.i(TAG, "Computing dirty sets.");
-                                       long ids[] = computeDirtySets(context);
-                                       if (ids != null && observer != null) {
-                                               observer.onChange(ids);
-                                       }
-                                       if (ids != null && ids.length > 0) {
-                                               sList = null;
-                                               Log.i(TAG, "Done computing dirty sets for num " + ids.length);
-                                       }
-                               }
-                       });
-               } else {
-                       QUEUE_DIRTY_SENSE = true;
-               }
-       }
-
-       public static final void markDirty(final Context context) {
-               sList = null;
-               sAlbumCache.put(ALBUM_CACHE_DIRTY_INDEX, sDummyData);
-               if (CACHE_THREAD.get() == null) {
-                       QUEUE_DIRTY_SENSE = false;
-                       QUEUE_DIRTY_ALL = false;
-                       QUEUE_DIRTY_SET = false;
-                       restartThread(CACHE_THREAD, "CacheRefresh", new Runnable() {
-                               public void run() {
-                                       refresh(context);
-                               }
-                       });
-               } else {
-                       QUEUE_DIRTY_ALL = true;
-               }
-       }
-
-       public static final void markDirtyImmediate(final long id) {
-               if (id == Shared.INVALID) {
-                       return;
-               }
-               sList = null;
-               byte[] data = longToByteArray(id);
-               final byte[] existingData = sAlbumCache.get(ALBUM_CACHE_DIRTY_BUCKET_INDEX, 0);
-               if (existingData != null && existingData.length > 0) {
-                       final long[] ids = toLongArray(existingData);
-                       final int numIds = ids.length;
-                       for (int i = 0; i < numIds; ++i) {
-                               if (ids[i] == id) {
-                                       return;
-                               }
-                       }
-                       // Add this to the existing keys and concatenate the byte arrays.
-                       data = concat(data, existingData);
-               }
-               sAlbumCache.put(ALBUM_CACHE_DIRTY_BUCKET_INDEX, data);
-       }
-
-       public static final void markDirty(final Context context, final long id) {
-               markDirtyImmediate(id);
-               if (CACHE_THREAD.get() == null) {
-                       QUEUE_DIRTY_SET = false;
-                       restartThread(CACHE_THREAD, "CacheRefreshDirtySets", new Runnable() {
-                               public void run() {
-                                       refreshDirtySets(context);
-                               }
-                       });
-               } else {
-                       QUEUE_DIRTY_SET = true;
-               }
-       }
-
-       public static final boolean setHasItems(final ContentResolver cr, final long setId) {
-               final Uri uriImages = Images.Media.EXTERNAL_CONTENT_URI;
-               final Uri uriVideos = Video.Media.EXTERNAL_CONTENT_URI;
-               final StringBuffer whereString = new StringBuffer(Images.ImageColumns.BUCKET_ID + "=" + setId);
-               final Cursor cursorImages = cr.query(uriImages, BUCKET_PROJECTION_IMAGES, whereString.toString(), null, null);
-               if (cursorImages != null && cursorImages.getCount() > 0) {
-                       cursorImages.close();
-                       return true;
-               }
-               final Cursor cursorVideos = cr.query(uriVideos, BUCKET_PROJECTION_VIDEOS, whereString.toString(), null, null);
-               if (cursorVideos != null && cursorVideos.getCount() > 0) {
-                       cursorVideos.close();
-                       return true;
-               }
-               return false;
-       }
-
-       public static final void loadMediaSets(final MediaFeed feed, final DataSource source, final boolean includeImages,
-               final boolean includeVideos) {
-               int timeElapsed = 0;
-               while (!isCacheReady(true) && timeElapsed < 10000) {
-                       try {
-                               Thread.sleep(300);
-                       } catch (InterruptedException e) {
-                               return;
-                       }
-                       timeElapsed += 300;
-               }
-               final byte[] albumData = sAlbumCache.get(ALBUM_CACHE_METADATA_INDEX, 0);
-               if (albumData != null && albumData.length > 0) {
-                       final DataInputStream dis = new DataInputStream(new BufferedInputStream(new ByteArrayInputStream(albumData), 256));
-                       try {
-                               final int numAlbums = dis.readInt();
-                               for (int i = 0; i < numAlbums; ++i) {
-                                       final long setId = dis.readLong();
-                                       final String name = Utils.readUTF(dis);
-                                       final boolean hasImages = dis.readBoolean();
-                                       final boolean hasVideos = dis.readBoolean();
-                                       MediaSet mediaSet = feed.getMediaSet(setId);
-                                       if (mediaSet == null) {
-                                               mediaSet = feed.addMediaSet(setId, source);
-                                       }
-                                       if ((includeImages && hasImages) || (includeVideos && hasVideos)) {
-                                               mediaSet.mName = name;
-                                               mediaSet.mHasImages = hasImages;
-                                               mediaSet.mHasVideos = hasVideos;
-                                               mediaSet.mPicasaAlbumId = Shared.INVALID;
-                                               mediaSet.generateTitle(true);
-                                       }
-                               }
-                       } catch (IOException e) {
-                               Log.e(TAG, "Error loading albums.");
-                               sAlbumCache.deleteAll();
-                               putLocaleForAlbumCache(Locale.getDefault());
-                       }
-               } else {
-                       Log.d(TAG, "No albums found.");
-               }
-       }
-
-       public static final void loadMediaSet(final MediaFeed feed, final DataSource source, final long bucketId) {
-               int timeElapsed = 0;
-               while (!isCacheReady(false) && timeElapsed < 10000) {
-                       try {
-                               Thread.sleep(300);
-                       } catch (InterruptedException e) {
-                               return;
-                       }
-                       timeElapsed += 300;
-               }
-               final byte[] albumData = sAlbumCache.get(ALBUM_CACHE_METADATA_INDEX, 0);
-               if (albumData != null && albumData.length > 0) {
-                       DataInputStream dis = new DataInputStream(new BufferedInputStream(new ByteArrayInputStream(albumData), 256));
-                       try {
-                               final int numAlbums = dis.readInt();
-                               for (int i = 0; i < numAlbums; ++i) {
-                                       final long setId = dis.readLong();
-                                       MediaSet mediaSet = null;
-                                       if (setId == bucketId) {
-                                               mediaSet = feed.getMediaSet(setId);
-                                               if (mediaSet == null) {
-                                                       mediaSet = feed.addMediaSet(setId, source);
-                                               }
-                                       } else {
-                                               mediaSet = new MediaSet();
-                                       }
-                                       mediaSet.mName = Utils.readUTF(dis);
-                                       if (setId == bucketId) {
-                                               mediaSet.mPicasaAlbumId = Shared.INVALID;
-                                               mediaSet.generateTitle(true);
-                                               return;
-                                       }
-                               }
-                       } catch (IOException e) {
-                               Log.e(TAG, "Error finding album " + bucketId);
-                               sAlbumCache.deleteAll();
-                               putLocaleForAlbumCache(Locale.getDefault());
-                       }
-               } else {
-                       Log.d(TAG, "No album found for album id " + bucketId);
-               }
-       }
-
-       public static final void loadMediaItemsIntoMediaFeed(final MediaFeed feed, final MediaSet set, final int rangeStart,
-               final int rangeEnd, final boolean includeImages, final boolean includeVideos) {
-               int timeElapsed = 0;
-               byte[] albumData = null;
-               while (!isCacheReady(set.mId) && timeElapsed < 30000) {
-                       try {
-                               Thread.sleep(300);
-                       } catch (InterruptedException e) {
-                               return;
-                       }
-                       timeElapsed += 300;
-               }
-               albumData = sAlbumCache.get(set.mId, 0);
-               if (albumData != null && set.mNumItemsLoaded < set.getNumExpectedItems()) {
-                       final DataInputStream dis = new DataInputStream(new BufferedInputStream(new ByteArrayInputStream(albumData), 256));
-                       try {
-                               final int numItems = dis.readInt();
-                               set.setNumExpectedItems(numItems);
-                               set.mMinTimestamp = dis.readLong();
-                               set.mMaxTimestamp = dis.readLong();
-                               for (int i = 0; i < numItems; ++i) {
-                                       final MediaItem item = new MediaItem();
-                                       // Must preserve order with method that writes to cache.
-                                       item.mId = dis.readLong();
-                                       item.mCaption = Utils.readUTF(dis);
-                                       item.mMimeType = Utils.readUTF(dis);
-                                       item.setMediaType(dis.readInt());
-                                       item.mLatitude = dis.readDouble();
-                                       item.mLongitude = dis.readDouble();
-                                       item.mDateTakenInMs = dis.readLong();
-                                       item.mTriedRetrievingExifDateTaken = dis.readBoolean();
-                                       item.mDateAddedInSec = dis.readLong();
-                                       item.mDateModifiedInSec = dis.readLong();
-                                       item.mDurationInSec = dis.readInt();
-                                       item.mRotation = (float) dis.readInt();
-                                       item.mFilePath = Utils.readUTF(dis);
-                                       int itemMediaType = item.getMediaType();
-                                       if ((itemMediaType == MediaItem.MEDIA_TYPE_IMAGE && includeImages)
-                                               || (itemMediaType == MediaItem.MEDIA_TYPE_VIDEO && includeVideos)) {
-                                               String baseUri = (itemMediaType == MediaItem.MEDIA_TYPE_IMAGE) ? BASE_CONTENT_STRING_IMAGES
-                                                       : BASE_CONTENT_STRING_VIDEOS;
-                                               item.mContentUri = baseUri + item.mId;
-                                               feed.addItemToMediaSet(item, set);
-                                       }
-                               }
-                               dis.close();
-                       } catch (IOException e) {
-                               Log.e(TAG, "Error loading items for album " + set.mName);
-                               sAlbumCache.deleteAll();
-                               putLocaleForAlbumCache(Locale.getDefault());
-                       }
-               } else {
-                       Log.d(TAG, "No items found for album " + set.mName);
-               }
-               set.updateNumExpectedItems();
-               set.generateTitle(true);
-       }
-
-       public static final void populateVideoItemFromCursor(final MediaItem item, final ContentResolver cr, final Cursor cursor,
-               final String baseUri) {
-               item.setMediaType(MediaItem.MEDIA_TYPE_VIDEO);
-               populateMediaItemFromCursor(item, cr, cursor, baseUri);
-       }
-
-       public static final void populateMediaItemFromCursor(final MediaItem item, final ContentResolver cr, final Cursor cursor,
-               final String baseUri) {
-               item.mId = cursor.getLong(CacheService.MEDIA_ID_INDEX);
-               item.mCaption = cursor.getString(CacheService.MEDIA_CAPTION_INDEX);
-               item.mMimeType = cursor.getString(CacheService.MEDIA_MIME_TYPE_INDEX);
-               item.mLatitude = cursor.getDouble(CacheService.MEDIA_LATITUDE_INDEX);
-               item.mLongitude = cursor.getDouble(CacheService.MEDIA_LONGITUDE_INDEX);
-               item.mDateTakenInMs = cursor.getLong(CacheService.MEDIA_DATE_TAKEN_INDEX);
-               item.mDateAddedInSec = cursor.getLong(CacheService.MEDIA_DATE_ADDED_INDEX);
-               item.mDateModifiedInSec = cursor.getLong(CacheService.MEDIA_DATE_MODIFIED_INDEX);
-               if (item.mDateTakenInMs == item.mDateModifiedInSec) {
-                       item.mDateTakenInMs = item.mDateModifiedInSec * 1000;
-               }
-               item.mFilePath = cursor.getString(CacheService.MEDIA_DATA_INDEX);
-               if (baseUri != null)
-                       item.mContentUri = baseUri + item.mId;
-               final int itemMediaType = item.getMediaType();
-               // Check to see if a new date taken is available.
-               final long dateTaken = fetchDateTaken(item);
-               if (dateTaken != -1L && item.mContentUri != null) {
-                       item.mDateTakenInMs = dateTaken;
-                       final ContentValues values = new ContentValues();
-                       if (itemMediaType == MediaItem.MEDIA_TYPE_VIDEO) {
-                               values.put(Video.VideoColumns.DATE_TAKEN, item.mDateTakenInMs);
-                       } else {
-                               values.put(Images.ImageColumns.DATE_TAKEN, item.mDateTakenInMs);
-                       }
-                       cr.update(Uri.parse(item.mContentUri), values, null, null);
-               }
-
-               final int orientationDurationValue = cursor.getInt(CacheService.MEDIA_ORIENTATION_OR_DURATION_INDEX);
-               if (itemMediaType == MediaItem.MEDIA_TYPE_IMAGE) {
-                       item.mRotation = orientationDurationValue;
-               } else {
-                       item.mDurationInSec = orientationDurationValue;
-               }
-       }
-
-       // Returns -1 if we failed to examine EXIF information or EXIF parsing
-       // failed.
-       public static final long fetchDateTaken(final MediaItem item) {
-               if (!item.isDateTakenValid() && !item.mTriedRetrievingExifDateTaken
-                       && (item.mFilePath.endsWith(".jpg") || item.mFilePath.endsWith(".jpeg"))) {
-                       try {
-                               Log.i(TAG, "Parsing date taken from exif");
-                               final ExifInterface exif = new ExifInterface(item.mFilePath);
-                               final String dateTakenStr = exif.getAttribute(ExifInterface.TAG_DATETIME);
-                               if (dateTakenStr != null) {
-                                       try {
-                                               final Date dateTaken = mDateFormat.parse(dateTakenStr);
-                                               return dateTaken.getTime();
-                                       } catch (ParseException pe) {
-                                               try {
-                                                       final Date dateTaken = mAltDateFormat.parse(dateTakenStr);
-                                                       return dateTaken.getTime();
-                                               } catch (ParseException pe2) {
-                                                       Log.i(TAG, "Unable to parse date out of string - " + dateTakenStr);
-                                               }
-                                       }
-                               }
-                       } catch (Exception e) {
-                               Log.i(TAG, "Error reading Exif information, probably not a jpeg.");
-                       }
-
-                       // Ensures that we only try retrieving EXIF date taken once.
-                       item.mTriedRetrievingExifDateTaken = true;
-               }
-               return -1L;
-       }
-
-       public static final byte[] queryThumbnail(final Context context, final long thumbId, final long origId, final boolean isVideo,
-               final long timestamp) {
-               final DiskCache thumbnailCache = (isVideo) ? LocalDataSource.sThumbnailCacheVideo : LocalDataSource.sThumbnailCache;
-               return queryThumbnail(context, thumbId, origId, isVideo, thumbnailCache, timestamp);
-       }
-
-       public static final ImageList getImageList(final Context context) {
-               if (sList != null)
-                       return sList;
-               ImageList list = new ImageList();
-               final Uri uriImages = Images.Media.EXTERNAL_CONTENT_URI;
-               final ContentResolver cr = context.getContentResolver();
-               final Cursor cursorImages = cr.query(uriImages, THUMBNAIL_PROJECTION, null, null, null);
-               if (cursorImages != null && cursorImages.moveToFirst()) {
-                       final int size = cursorImages.getCount();
-                       final long[] ids = new long[size];
-                       final long[] thumbnailIds = new long[size];
-                       final long[] timestamp = new long[size];
-                       final int[] orientation = new int[size];
-                       int ctr = 0;
-                       do {
-                               if (Thread.interrupted()) {
-                                       break;
-                               }
-                               ids[ctr] = cursorImages.getLong(THUMBNAIL_ID_INDEX);
-                               timestamp[ctr] = cursorImages.getLong(THUMBNAIL_DATE_MODIFIED_INDEX);
-                               thumbnailIds[ctr] = Utils.Crc64Long(cursorImages.getString(THUMBNAIL_DATA_INDEX));
-                               orientation[ctr] = cursorImages.getInt(THUMBNAIL_ORIENTATION_INDEX);
-                               ++ctr;
-                       } while (cursorImages.moveToNext());
-                       cursorImages.close();
-                       list.ids = ids;
-                       list.thumbids = thumbnailIds;
-                       list.timestamp = timestamp;
-                       list.orientation = orientation;
-               }
-               if (sList == null) {
-                       sList = list;
-               }
-               return list;
-       }
-
-       private static final byte[] queryThumbnail(final Context context, final long thumbId, final long origId, final boolean isVideo,
-               final DiskCache thumbnailCache, final long timestamp) {
-               if (!((Gallery) context).isPaused()) {
-                       final Thread thumbnailThread = THUMBNAIL_THREAD.getAndSet(null);
-                       if (thumbnailThread != null) {
-                               thumbnailThread.interrupt();
-                       }
-               }
-               byte[] bitmap = thumbnailCache.get(thumbId, timestamp);
-               if (bitmap == null) {
-                       final long time = SystemClock.uptimeMillis();
-                       bitmap = buildThumbnailForId(context, thumbnailCache, thumbId, origId, isVideo, DEFAULT_THUMBNAIL_WIDTH,
-                               DEFAULT_THUMBNAIL_HEIGHT);
-                       Log.i(TAG, "Built thumbnail and screennail for " + origId + " in " + (SystemClock.uptimeMillis() - time));
-               }
-               return bitmap;
-       }
-
-       private static final void buildThumbnails(final Context context) {
-               Log.i(TAG, "Preparing DiskCache for all thumbnails.");
-               ImageList list = getImageList(context);
-               final int size = (list.ids == null) ? 0 : list.ids.length;
-               final long[] ids = list.ids;
-               final long[] timestamp = list.timestamp;
-               final long[] thumbnailIds = list.thumbids;
-               final DiskCache thumbnailCache = LocalDataSource.sThumbnailCache;
-               for (int i = 0; i < size; ++i) {
-                       if (Thread.interrupted()) {
-                               return;
-                       }
-                       final long id = ids[i];
-                       final long timeModifiedInSec = timestamp[i];
-                       final long thumbnailId = thumbnailIds[i];
-                       if (!thumbnailCache.isDataAvailable(thumbnailId, timeModifiedInSec * 1000)) {
-                               buildThumbnailForId(context, thumbnailCache, thumbnailId, id, false, DEFAULT_THUMBNAIL_WIDTH,
-                                       DEFAULT_THUMBNAIL_HEIGHT);
-                       }
-               }
-               Log.i(TAG, "DiskCache ready for all thumbnails.");
-       }
-
-       private static final byte[] buildThumbnailForId(final Context context, final DiskCache thumbnailCache, final long thumbId,
-               final long origId, final boolean isVideo, final int thumbnailWidth, final int thumbnailHeight) {
-               if (origId == Shared.INVALID) {
-                       return null;
-               }
-               try {
-                       Bitmap bitmap = null;
-                       Thread.sleep(1);
-                       if (!isVideo) {
-                               final String uriString = BASE_CONTENT_STRING_IMAGES + origId;
-                               UriTexture.invalidateCache(thumbId, 1024);
-                               try {
-                                       bitmap = UriTexture.createFromUri(context, uriString, 1024, 1024, thumbId, null);
-                               } catch (IOException e) {
-                                       return null;
-                               } catch (URISyntaxException e) {
-                                       return null;
-                               }
-                       } else {
-                               new Thread() {
-                                       public void run() {
-                                               try {
-                                                       Thread.sleep(5000);
-                                               } catch (InterruptedException e) {
-                                                       ;
-                                               }
-                                               try {
-                                                       MediaStore.Video.Thumbnails.cancelThumbnailRequest(context.getContentResolver(), origId);
-                                               } catch (Exception e) {
-                                                       ;
-                                               }
-                                       }
-                               }.start();
-                               bitmap = MediaStore.Video.Thumbnails.getThumbnail(context.getContentResolver(), origId,
-                                       MediaStore.Video.Thumbnails.MICRO_KIND, null);
-                       }
-                       if (bitmap == null) {
-                               return null;
-                       }
-                       final byte[] retVal = writeBitmapToCache(thumbnailCache, thumbId, origId, bitmap, thumbnailWidth, thumbnailHeight);
-                       return retVal;
-               } catch (InterruptedException e) {
-                       return null;
-               }
-       }
-
-       public static final byte[] writeBitmapToCache(final DiskCache thumbnailCache, final long thumbId, final long origId,
-               final Bitmap bitmap, final int thumbnailWidth, final int thumbnailHeight) {
-               final int width = bitmap.getWidth();
-               final int height = bitmap.getHeight();
-               // Detect faces to find the focal point, otherwise fall back to the
-               // image center.
-               int focusX = width / 2;
-               int focusY = height / 2;
-               // We have commented out face detection since it slows down the
-               // generation of the thumbnail and screennail.
-
-               // final FaceDetector faceDetector = new FaceDetector(width, height, 1);
-               // final FaceDetector.Face[] faces = new FaceDetector.Face[1];
-               // final int numFaces = faceDetector.findFaces(bitmap, faces);
-               // if (numFaces > 0 && faces[0].confidence() >=
-               // FaceDetector.Face.CONFIDENCE_THRESHOLD) {
-               // final PointF midPoint = new PointF();
-               // faces[0].getMidPoint(midPoint);
-               // focusX = (int) midPoint.x;
-               // focusY = (int) midPoint.y;
-               // }
-
-               // Crop to thumbnail aspect ratio biased towards the focus point.
-               int cropX;
-               int cropY;
-               int cropWidth;
-               int cropHeight;
-               float scaleFactor;
-               if (thumbnailWidth * height < thumbnailHeight * width) {
-                       // Vertically constrained.
-                       cropWidth = thumbnailWidth * height / thumbnailHeight;
-                       cropX = Math.max(0, Math.min(focusX - cropWidth / 2, width - cropWidth));
-                       cropY = 0;
-                       cropHeight = height;
-                       scaleFactor = (float) thumbnailHeight / height;
-               } else {
-                       // Horizontally constrained.
-                       cropHeight = thumbnailHeight * width / thumbnailWidth;
-                       cropY = Math.max(0, Math.min(focusY - cropHeight / 2, height - cropHeight));
-                       cropX = 0;
-                       cropWidth = width;
-                       scaleFactor = (float) thumbnailWidth / width;
-               }
-               final Bitmap finalBitmap = Bitmap.createBitmap(thumbnailWidth, thumbnailHeight, Bitmap.Config.RGB_565);
-               final Canvas canvas = new Canvas(finalBitmap);
-               final Paint paint = new Paint();
-               paint.setFilterBitmap(true);
-               canvas.drawColor(0);
-               canvas.drawBitmap(bitmap, new Rect(cropX, cropY, cropX + cropWidth, cropY + cropHeight), new Rect(0, 0, thumbnailWidth,
-                       thumbnailHeight), paint);
-               bitmap.recycle();
-
-               // Store (long thumbnailId, short focusX, short focusY, JPEG data).
-               final ByteArrayOutputStream cacheOutput = new ByteArrayOutputStream(16384);
-               final DataOutputStream dataOutput = new DataOutputStream(cacheOutput);
-               byte[] retVal = null;
-               try {
-                       dataOutput.writeLong(origId);
-                       dataOutput.writeShort((int) ((focusX - cropX) * scaleFactor));
-                       dataOutput.writeShort((int) ((focusY - cropY) * scaleFactor));
-                       dataOutput.flush();
-                       finalBitmap.compress(Bitmap.CompressFormat.JPEG, 80, cacheOutput);
-                       retVal = cacheOutput.toByteArray();
-                       synchronized (thumbnailCache) {
-                               thumbnailCache.put(thumbId, retVal);
-                       }
-                       cacheOutput.close();
-               } catch (Exception e) {
-                       ;
-               }
-               return retVal;
-       }
-
-       public CacheService() {
-               super("CacheService");
-       }
-
-       @Override
-       protected void onHandleIntent(final Intent intent) {
-               Log.i(TAG, "Starting CacheService");
-               if (Environment.getExternalStorageState() == Environment.MEDIA_BAD_REMOVAL) {
-                       sAlbumCache.deleteAll();
-                       putLocaleForAlbumCache(Locale.getDefault());
-               }
-               Locale locale = getLocaleForAlbumCache();
-               if (locale != null && locale.equals(Locale.getDefault())) {
-                       // The cache is in the same locale as the system locale.
-                       if (!isCacheReady(false)) {
-                               // The albums and their items have not yet been cached, we need
-                               // to run the service.
-                               startNewCacheThread();
-                       } else {
-                               startNewCacheThreadForDirtySets();
-                       }
-               } else {
-                       // The locale has changed, we need to regenerate the strings.
-                       sAlbumCache.deleteAll();
-                       putLocaleForAlbumCache(Locale.getDefault());
-                       startNewCacheThread();
-               }
-               if (intent.getBooleanExtra("checkthumbnails", false)) {
-                       startNewThumbnailThread(this);
-               } else {
-                       final Thread existingThread = THUMBNAIL_THREAD.getAndSet(null);
-                       if (existingThread != null) {
-                               existingThread.interrupt();
-                       }
-               }
-       }
-
-       private static final void putLocaleForAlbumCache(final Locale locale) {
-               final ByteArrayOutputStream bos = new ByteArrayOutputStream();
-               final DataOutputStream dos = new DataOutputStream(bos);
-               try {
-                       Utils.writeUTF(dos, locale.getCountry());
-                       Utils.writeUTF(dos, locale.getLanguage());
-                       Utils.writeUTF(dos, locale.getVariant());
-                       dos.flush();
-                       bos.flush();
-                       final byte[] data = bos.toByteArray();
-                       sAlbumCache.put(ALBUM_CACHE_LOCALE_INDEX, data);
-                       sAlbumCache.flush();
-                       dos.close();
-                       bos.close();
-               } catch (IOException e) {
-                       // Could not write locale to cache.
-                       Log.i(TAG, "Error writing locale to cache.");
-                       ;
-               }
-       }
-
-       private static final Locale getLocaleForAlbumCache() {
-               final byte[] data = sAlbumCache.get(ALBUM_CACHE_LOCALE_INDEX, 0);
-               if (data != null && data.length > 0) {
-                       ByteArrayInputStream bis = new ByteArrayInputStream(data);
-                       DataInputStream dis = new DataInputStream(bis);
-                       try {
-                               String country = Utils.readUTF(dis);
-                               if (country == null)
-                                       country = "";
-                               String language = Utils.readUTF(dis);
-                               if (language == null)
-                                       language = "";
-                               String variant = Utils.readUTF(dis);
-                               if (variant == null)
-                                       variant = "";
-                               final Locale locale = new Locale(language, country, variant);
-                               dis.close();
-                               bis.close();
-                               return locale;
-                       } catch (IOException e) {
-                               // Could not read locale in cache.
-                               Log.i(TAG, "Error reading locale from cache.");
-                               return null;
-                       }
-               }
-               return null;
-       }
-
-       private static final void restartThread(final AtomicReference<Thread> threadRef, final String name, final Runnable action) {
-               // Create a new thread.
-               final Thread newThread = new Thread() {
-                       public void run() {
-                               try {
-                                       action.run();
-                               } finally {
-                                       threadRef.compareAndSet(this, null);
-                               }
-                       }
-               };
-               newThread.setName(name);
-               newThread.start();
-
-               // Interrupt any existing thread.
-               final Thread existingThread = threadRef.getAndSet(newThread);
-               if (existingThread != null) {
-                       existingThread.interrupt();
-               }
-       }
-
-       public static final void startNewThumbnailThread(final Context context) {
-               restartThread(THUMBNAIL_THREAD, "ThumbnailRefresh", new Runnable() {
-                       public void run() {
-                               Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
-                               try {
-                                       // It is an optimization to prevent the thumbnailer from
-                                       // running while the application loads
-                                       Thread.sleep(THUMBNAILER_WAIT_IN_MS);
-                               } catch (InterruptedException e) {
-                                       return;
-                               }
-                               CacheService.buildThumbnails(context);
-                       }
-               });
-       }
-
-       private void startNewCacheThread() {
-               restartThread(CACHE_THREAD, "CacheRefresh", new Runnable() {
-                       public void run() {
-                               refresh(CacheService.this);
-                       }
-               });
-       }
-
-       private void startNewCacheThreadForDirtySets() {
-               restartThread(CACHE_THREAD, "CacheRefreshDirtySets", new Runnable() {
-                       public void run() {
-                               refreshDirtySets(CacheService.this);
-                       }
-               });
-       }
-
-       private static final byte[] concat(final byte[] A, final byte[] B) {
-               final byte[] C = (byte[]) new byte[A.length + B.length];
-               System.arraycopy(A, 0, C, 0, A.length);
-               System.arraycopy(B, 0, C, A.length, B.length);
-               return C;
-       }
-
-       private static final long[] toLongArray(final byte[] data) {
-               final ByteBuffer bBuffer = ByteBuffer.wrap(data);
-               final LongBuffer lBuffer = bBuffer.asLongBuffer();
-               final int numLongs = lBuffer.capacity();
-               final long[] retVal = new long[numLongs];
-               for (int i = 0; i < numLongs; ++i) {
-                       retVal[i] = lBuffer.get(i);
-               }
-               return retVal;
-       }
-
-       private static final byte[] longToByteArray(final long l) {
-               final byte[] bArray = new byte[8];
-               final ByteBuffer bBuffer = ByteBuffer.wrap(bArray);
-               final LongBuffer lBuffer = bBuffer.asLongBuffer();
-               lBuffer.put(0, l);
-               return bArray;
-       }
-       
-       private static final byte[] longArrayToByteArray(final long[] l) {
-               final byte[] bArray = new byte[8 * l.length];
-               final ByteBuffer bBuffer = ByteBuffer.wrap(bArray);
-               final LongBuffer lBuffer = bBuffer.asLongBuffer();
-               int numLongs = l.length;
-               for (int i = 0; i < numLongs; ++i) {
-                       lBuffer.put(i, l[i]);
-               }
-               return bArray;
-       }
-
-       private final static void refresh(final Context context) {
-               // First we build the album cache.
-               // This is the meta-data about the albums / buckets on the SD card.
-               Log.i(TAG, "Refreshing cache.");
-               sAlbumCache.deleteAll();
-               putLocaleForAlbumCache(Locale.getDefault());
-
-               final ArrayList<MediaSet> sets = new ArrayList<MediaSet>();
-               LongSparseArray<MediaSet> acceleratedSets = new LongSparseArray<MediaSet>();
-               Log.i(TAG, "Building albums.");
-               final Uri uriImages = Images.Media.EXTERNAL_CONTENT_URI.buildUpon().appendQueryParameter("distinct", "true").build();
-               final Uri uriVideos = Video.Media.EXTERNAL_CONTENT_URI.buildUpon().appendQueryParameter("distinct", "true").build();
-               final ContentResolver cr = context.getContentResolver();
-
-               final Cursor cursorImages = cr.query(uriImages, BUCKET_PROJECTION_IMAGES, null, null, DEFAULT_BUCKET_SORT_ORDER);
-               final Cursor cursorVideos = cr.query(uriVideos, BUCKET_PROJECTION_VIDEOS, null, null, DEFAULT_BUCKET_SORT_ORDER);
-               Cursor[] cursors = new Cursor[2];
-               cursors[0] = cursorImages;
-               cursors[1] = cursorVideos;
-               final SortCursor sortCursor = new SortCursor(cursors, Images.ImageColumns.BUCKET_DISPLAY_NAME, SortCursor.TYPE_STRING, true);
-               try {
-                       if (sortCursor != null && sortCursor.moveToFirst()) {
-                               sets.ensureCapacity(sortCursor.getCount());
-                               acceleratedSets = new LongSparseArray<MediaSet>(sortCursor.getCount());
-                               MediaSet cameraSet = new MediaSet();
-                               cameraSet.mId = LocalDataSource.CAMERA_BUCKET_ID;
-                               cameraSet.mName = context.getResources().getString(R.string.camera);
-                               sets.add(cameraSet);
-                               acceleratedSets.put(cameraSet.mId, cameraSet);
-                               do {
-                                       if (Thread.interrupted()) {
-                                               return;
-                                       }
-                                       long setId = sortCursor.getLong(BUCKET_ID_INDEX);
-                                       MediaSet mediaSet = findSet(setId, acceleratedSets);
-                                       if (mediaSet == null) {
-                                               mediaSet = new MediaSet();
-                                               mediaSet.mId = setId;
-                                               mediaSet.mName = sortCursor.getString(BUCKET_NAME_INDEX);
-                                               sets.add(mediaSet);
-                                               acceleratedSets.put(setId, mediaSet);
-                                       }
-                                       mediaSet.mHasImages |= (sortCursor.getCurrentCursorIndex() == 0);
-                                       mediaSet.mHasVideos |= (sortCursor.getCurrentCursorIndex() == 1);
-                               } while (sortCursor.moveToNext());
-                               sortCursor.close();
-                       }
-               } finally {
-                       if (sortCursor != null)
-                               sortCursor.close();
-               }
-
-               sAlbumCache.put(ALBUM_CACHE_INCOMPLETE_INDEX, sDummyData);
-               writeSetsToCache(sets);
-               Log.i(TAG, "Done building albums.");
-               // Now we must cache the items contained in every album / bucket.
-               populateMediaItemsForSets(context, sets, acceleratedSets, false);
-               sAlbumCache.delete(ALBUM_CACHE_INCOMPLETE_INDEX);
-
-               // Complete any queued dirty requests
-               processQueuedDirty(context);
-       }
-
-       private final static void refreshDirtySets(final Context context) {
-               final byte[] existingData = sAlbumCache.get(ALBUM_CACHE_DIRTY_BUCKET_INDEX, 0);
-               if (existingData != null && existingData.length > 0) {
-                       final long[] ids = toLongArray(existingData);
-                       final int numIds = ids.length;
-                       if (numIds > 0) {
-                               final ArrayList<MediaSet> sets = new ArrayList<MediaSet>(numIds);
-                               final LongSparseArray<MediaSet> acceleratedSets = new LongSparseArray<MediaSet>(numIds);
-                               for (int i = 0; i < numIds; ++i) {
-                                       final MediaSet set = new MediaSet();
-                                       set.mId = ids[i];
-                                       sets.add(set);
-                                       acceleratedSets.put(set.mId, set);
-                               }
-                               Log.i(TAG, "Refreshing dirty albums");
-                               populateMediaItemsForSets(context, sets, acceleratedSets, true);
-                       }
-               }
-               processQueuedDirty(context);
-               sAlbumCache.delete(ALBUM_CACHE_DIRTY_BUCKET_INDEX);
-       }
-
-       private static final long[] computeDirtySets(final Context context) {
-               final Uri uriImages = Images.Media.EXTERNAL_CONTENT_URI;
-               final Uri uriVideos = Video.Media.EXTERNAL_CONTENT_URI;
-               final ContentResolver cr = context.getContentResolver();
-               final String where = Images.ImageColumns.BUCKET_ID + "!=0) GROUP BY (" + Images.ImageColumns.BUCKET_ID + " ";
-               final Cursor cursorImages = cr.query(uriImages, SENSE_PROJECTION, where, null, null);
-               final Cursor cursorVideos = cr.query(uriVideos, SENSE_PROJECTION, where, null, null);
-               Cursor[] cursors = new Cursor[2];
-               cursors[0] = cursorImages;
-               cursors[1] = cursorVideos;
-               final MergeCursor cursor = new MergeCursor(cursors);
-               ArrayList<Long> retVal = new ArrayList<Long>();
-               try {
-                       if (cursor.moveToFirst()) {
-                               boolean allDirty = false;
-                               do {
-                                       long setId = cursor.getLong(0);
-                                       if (allDirty) {
-                                               addNoDupe(retVal, setId);
-                                       } else {
-                                               boolean contains = sAlbumCache.isDataAvailable(setId, 0);
-                                               if (!contains) {
-                                                       // We need to refresh everything.
-                                                       markDirty(context);
-                                                       addNoDupe(retVal, setId);
-                                                       allDirty = true;
-                                               }
-                                               if (!allDirty) {
-                                                       long maxAdded = cursor.getLong(1);
-                                                       int count = cursor.getInt(2);
-                                                       byte[] data = sMetaAlbumCache.get(setId, 0);
-                                                       long[] dataLong = new long[2];
-                                                       if (data != null) {
-                                                               dataLong = toLongArray(data);
-                                                       }
-                                                       long oldMaxAdded = dataLong[0];
-                                                       long oldCount = dataLong[1];
-                                                       if (maxAdded > oldMaxAdded || oldCount != count) {
-                                                               markDirty(context, setId);
-                                                               addNoDupe(retVal, setId);
-                                                               dataLong[0] = maxAdded;
-                                                               dataLong[1] = count;
-                                                               sMetaAlbumCache.put(setId, longArrayToByteArray(dataLong));
-                                                       }
-                                               }
-                                       }
-                               } while (cursor.moveToNext());
-                       }
-               } finally {
-                       cursor.close();
-               }
-               sMetaAlbumCache.flush();
-               processQueuedDirty(context);
-               int numIds = retVal.size();
-               long retValIds[] = new long[retVal.size()];
-               for (int i = 0; i < numIds; ++i) {
-                       retValIds[i] = retVal.get(i);
-               }
-               return retValIds;
-       }
-       
-       private static final void addNoDupe(ArrayList<Long> array, long value) {
-               int size = array.size();
-               for (int i = 0; i < size; ++i) {
-                       if (array.get(i).longValue() == value)
-                               return;
-               }
-               array.add(value);
-       }
-
-       private static final void processQueuedDirty(final Context context) {
-               if (QUEUE_DIRTY_SENSE) {
-                       QUEUE_DIRTY_SENSE = false;
-                       QUEUE_DIRTY_ALL = false;
-                       QUEUE_DIRTY_SET = false;
-                       computeDirtySets(context);
-               } else if (QUEUE_DIRTY_ALL) {
-                       QUEUE_DIRTY_ALL = false;
-                       QUEUE_DIRTY_SET = false;
-                       QUEUE_DIRTY_SENSE = false;
-                       refresh(context);
-               } else if (QUEUE_DIRTY_SET) {
-                       QUEUE_DIRTY_SET = false;
-                       // We don't mark QUEUE_DIRTY_SENSE because a set outside the dirty
-                       // sets might have gotten modified.
-                       refreshDirtySets(context);
-               }
-       }
-
-       private final static void populateMediaItemsForSets(final Context context, final ArrayList<MediaSet> sets,
-               final LongSparseArray<MediaSet> acceleratedSets, boolean useWhere) {
-               if (sets == null || sets.size() == 0 || Thread.interrupted()) {
-                       return;
-               }
-               Log.i(TAG, "Building items.");
-               final Uri uriImages = Images.Media.EXTERNAL_CONTENT_URI;
-               final Uri uriVideos = Video.Media.EXTERNAL_CONTENT_URI;
-               final ContentResolver cr = context.getContentResolver();
-
-               String whereClause = null;
-               if (useWhere) {
-                       int numSets = sets.size();
-                       StringBuffer whereString = new StringBuffer(Images.ImageColumns.BUCKET_ID + " in (");
-                       for (int i = 0; i < numSets; ++i) {
-                               whereString.append(sets.get(i).mId);
-                               if (i != numSets - 1) {
-                                       whereString.append(",");
-                               }
-                       }
-                       whereString.append(")");
-                       whereClause = whereString.toString();
-                       Log.i(TAG, "Updating dirty albums where " + whereClause);
-               }
-
-               final Cursor cursorImages = cr.query(uriImages, PROJECTION_IMAGES, whereClause, null, DEFAULT_IMAGE_SORT_ORDER);
-               final Cursor cursorVideos = cr.query(uriVideos, PROJECTION_VIDEOS, whereClause, null, DEFAULT_VIDEO_SORT_ORDER);
-               final Cursor[] cursors = new Cursor[2];
-               cursors[0] = cursorImages;
-               cursors[1] = cursorVideos;
-               final SortCursor sortCursor = new SortCursor(cursors, Images.ImageColumns.DATE_TAKEN, SortCursor.TYPE_NUMERIC, true);
-               if (Thread.interrupted()) {
-                       return;
-               }
-               try {
-                       if (sortCursor != null && sortCursor.moveToFirst()) {
-                               final int count = sortCursor.getCount();
-                               final int numSets = sets.size();
-                               final int approximateCountPerSet = count / numSets;
-                               for (int i = 0; i < numSets; ++i) {
-                                       final MediaSet set = sets.get(i);
-                                       set.setNumExpectedItems(approximateCountPerSet);
-                               }
-                               do {
-                                       if (Thread.interrupted()) {
-                                               return;
-                                       }
-                                       final MediaItem item = new MediaItem();
-                                       final boolean isVideo = (sortCursor.getCurrentCursorIndex() == 1);
-                                       if (isVideo) {
-                                               populateVideoItemFromCursor(item, cr, sortCursor, CacheService.BASE_CONTENT_STRING_VIDEOS);
-                                       } else {
-                                               populateMediaItemFromCursor(item, cr, sortCursor, CacheService.BASE_CONTENT_STRING_IMAGES);
-                                       }
-                                       final long setId = sortCursor.getLong(MEDIA_BUCKET_ID_INDEX);
-                                       final MediaSet set = findSet(setId, acceleratedSets);
-                                       if (set != null) {
-                                               set.addItem(item);
-                                       }
-                               } while (sortCursor.moveToNext());
-                       }
-               } finally {
-                       if (sortCursor != null)
-                               sortCursor.close();
-               }
-               if (sets.size() > 0) {
-                       writeItemsToCache(sets);
-                       Log.i(TAG, "Done building items.");
-               }
-       }
-
-       private static final void writeSetsToCache(final ArrayList<MediaSet> sets) {
-               final ByteArrayOutputStream bos = new ByteArrayOutputStream();
-               final int numSets = sets.size();
-               final DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(bos, 256));
-               try {
-                       dos.writeInt(numSets);
-                       for (int i = 0; i < numSets; ++i) {
-                               if (Thread.interrupted()) {
-                                       return;
-                               }
-                               final MediaSet set = sets.get(i);
-                               dos.writeLong(set.mId);
-                               Utils.writeUTF(dos, set.mName);
-                               dos.writeBoolean(set.mHasImages);
-                               dos.writeBoolean(set.mHasVideos);
-                       }
-                       dos.flush();
-                       sAlbumCache.put(ALBUM_CACHE_METADATA_INDEX, bos.toByteArray());
-                       dos.close();
-                       if (numSets == 0) {
-                               sAlbumCache.deleteAll();
-                               putLocaleForAlbumCache(Locale.getDefault());
-                       }
-                       sAlbumCache.flush();
-               } catch (IOException e) {
-                       Log.e(TAG, "Error writing albums to diskcache.");
-                       sAlbumCache.deleteAll();
-                       putLocaleForAlbumCache(Locale.getDefault());
-               }
-       }
-
-       private static final void writeItemsToCache(final ArrayList<MediaSet> sets) {
-               final int numSets = sets.size();
-               for (int i = 0; i < numSets; ++i) {
-                       if (Thread.interrupted()) {
-                               return;
-                       }
-                       writeItemsForASet(sets.get(i));
-               }
-               sAlbumCache.flush();
-       }
-
-       private static final void writeItemsForASet(final MediaSet set) {
-               final ByteArrayOutputStream bos = new ByteArrayOutputStream();
-               final DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(bos, 256));
-               try {
-                       final ArrayList<MediaItem> items = set.getItems();
-                       final int numItems = items.size();
-                       dos.writeInt(numItems);
-                       dos.writeLong(set.mMinTimestamp);
-                       dos.writeLong(set.mMaxTimestamp);
-                       for (int i = 0; i < numItems; ++i) {
-                               MediaItem item = items.get(i);
-                               if (set.mId == LocalDataSource.CAMERA_BUCKET_ID || set.mId == LocalDataSource.DOWNLOAD_BUCKET_ID) {
-                                       // Reverse the display order for the camera bucket - want
-                                       // the latest first.
-                                       item = items.get(numItems - i - 1);
-                               }
-                               dos.writeLong(item.mId);
-                               Utils.writeUTF(dos, item.mCaption);
-                               Utils.writeUTF(dos, item.mMimeType);
-                               dos.writeInt(item.getMediaType());
-                               dos.writeDouble(item.mLatitude);
-                               dos.writeDouble(item.mLongitude);
-                               dos.writeLong(item.mDateTakenInMs);
-                               dos.writeBoolean(item.mTriedRetrievingExifDateTaken);
-                               dos.writeLong(item.mDateAddedInSec);
-                               dos.writeLong(item.mDateModifiedInSec);
-                               dos.writeInt(item.mDurationInSec);
-                               dos.writeInt((int) item.mRotation);
-                               Utils.writeUTF(dos, item.mFilePath);
-                       }
-                       dos.flush();
-                       sAlbumCache.put(set.mId, bos.toByteArray());
-                       dos.close();
-               } catch (IOException e) {
-                       Log.e(TAG, "Error writing to diskcache for set " + set.mName);
-                       sAlbumCache.deleteAll();
-                       putLocaleForAlbumCache(Locale.getDefault());
-               }
-       }
-
-       private static final MediaSet findSet(final long id, final LongSparseArray<MediaSet> acceleratedTable) {
-               // This is the accelerated lookup table for the MediaSet based on set
-               // id.
-               return acceleratedTable.get(id);
-       }
+                    Log.i(TAG, "Computing dirty sets.");
+                    long ids[] = computeDirtySets(context);
+                    processQueuedDirty(context);
+                    if (ids != null && observer != null) {
+                        observer.onChange(ids);
+                    }
+                    if (ids != null && ids.length > 0) {
+                        sList = null;
+                        Log.i(TAG, "Done computing dirty sets for num " + ids.length);
+                    }
+                }
+            });
+        } else {
+            QUEUE_DIRTY_SENSE = true;
+        }
+    }
+
+    public static final void markDirty(final Context context) {
+        sList = null;
+        sAlbumCache.put(ALBUM_CACHE_DIRTY_INDEX, sDummyData);
+        if (CACHE_THREAD.get() == null) {
+            QUEUE_DIRTY_SENSE = false;
+            QUEUE_DIRTY_ALL = false;
+            QUEUE_DIRTY_SET = false;
+            restartThread(CACHE_THREAD, "CacheRefresh", new Runnable() {
+                public void run() {
+                    refresh(context);
+                    processQueuedDirty(context);
+                }
+            });
+        } else {
+            QUEUE_DIRTY_ALL = true;
+        }
+    }
+
+    public static final void markDirtyImmediate(final long id) {
+        if (id == Shared.INVALID) {
+            return;
+        }
+        sList = null;
+        byte[] data = longToByteArray(id);
+        final byte[] existingData = sAlbumCache.get(ALBUM_CACHE_DIRTY_BUCKET_INDEX, 0);
+        if (existingData != null && existingData.length > 0) {
+            final long[] ids = toLongArray(existingData);
+            final int numIds = ids.length;
+            for (int i = 0; i < numIds; ++i) {
+                if (ids[i] == id) {
+                    return;
+                }
+            }
+            // Add this to the existing keys and concatenate the byte arrays.
+            data = concat(data, existingData);
+        }
+        sAlbumCache.put(ALBUM_CACHE_DIRTY_BUCKET_INDEX, data);
+    }
+
+    public static final void markDirty(final Context context, final long id) {
+        markDirtyImmediate(id);
+        if (CACHE_THREAD.get() == null) {
+            QUEUE_DIRTY_SET = false;
+            restartThread(CACHE_THREAD, "CacheRefreshDirtySets", new Runnable() {
+                public void run() {
+                    refreshDirtySets(context);
+                    processQueuedDirty(context);
+                }
+            });
+        } else {
+            QUEUE_DIRTY_SET = true;
+        }
+    }
+
+    public static final boolean setHasItems(final ContentResolver cr, final long setId) {
+        final Uri uriImages = Images.Media.EXTERNAL_CONTENT_URI;
+        final Uri uriVideos = Video.Media.EXTERNAL_CONTENT_URI;
+        final StringBuffer whereString = new StringBuffer(Images.ImageColumns.BUCKET_ID + "=" + setId);
+        try {
+            final Cursor cursorImages = cr.query(uriImages, BUCKET_PROJECTION_IMAGES, whereString.toString(), null, null);
+            if (cursorImages != null && cursorImages.getCount() > 0) {
+                cursorImages.close();
+                return true;
+            }
+            final Cursor cursorVideos = cr.query(uriVideos, BUCKET_PROJECTION_VIDEOS, whereString.toString(), null, null);
+            if (cursorVideos != null && cursorVideos.getCount() > 0) {
+                cursorVideos.close();
+                return true;
+            }
+        } catch (Exception e) {
+            // If the database query failed for any reason
+            ;
+        }
+        return false;
+    }
+
+    public static final void loadMediaSets(final MediaFeed feed, final DataSource source, final boolean includeImages,
+            final boolean includeVideos) {
+        int timeElapsed = 0;
+        while (!isCacheReady(true) && timeElapsed < 10000) {
+            try {
+                Thread.sleep(300);
+            } catch (InterruptedException e) {
+                return;
+            }
+            timeElapsed += 300;
+        }
+        final byte[] albumData = sAlbumCache.get(ALBUM_CACHE_METADATA_INDEX, 0);
+        if (albumData != null && albumData.length > 0) {
+            final DataInputStream dis = new DataInputStream(new BufferedInputStream(new ByteArrayInputStream(albumData), 256));
+            try {
+                final int numAlbums = dis.readInt();
+                for (int i = 0; i < numAlbums; ++i) {
+                    final long setId = dis.readLong();
+                    final String name = Utils.readUTF(dis);
+                    final boolean hasImages = dis.readBoolean();
+                    final boolean hasVideos = dis.readBoolean();
+                    MediaSet mediaSet = feed.getMediaSet(setId);
+                    if (mediaSet == null) {
+                        mediaSet = feed.addMediaSet(setId, source);
+                    }
+                    if ((includeImages && hasImages) || (includeVideos && hasVideos)) {
+                        mediaSet.mName = name;
+                        mediaSet.mHasImages = hasImages;
+                        mediaSet.mHasVideos = hasVideos;
+                        mediaSet.mPicasaAlbumId = Shared.INVALID;
+                        mediaSet.generateTitle(true);
+                    }
+                }
+            } catch (IOException e) {
+                Log.e(TAG, "Error loading albums.");
+                sAlbumCache.deleteAll();
+                putLocaleForAlbumCache(Locale.getDefault());
+            }
+        } else {
+            Log.d(TAG, "No albums found.");
+        }
+    }
+
+    public static final void loadMediaSet(final MediaFeed feed, final DataSource source, final long bucketId) {
+        int timeElapsed = 0;
+        while (!isCacheReady(false) && timeElapsed < 10000) {
+            try {
+                Thread.sleep(300);
+            } catch (InterruptedException e) {
+                return;
+            }
+            timeElapsed += 300;
+        }
+        final byte[] albumData = sAlbumCache.get(ALBUM_CACHE_METADATA_INDEX, 0);
+        if (albumData != null && albumData.length > 0) {
+            DataInputStream dis = new DataInputStream(new BufferedInputStream(new ByteArrayInputStream(albumData), 256));
+            try {
+                final int numAlbums = dis.readInt();
+                for (int i = 0; i < numAlbums; ++i) {
+                    final long setId = dis.readLong();
+                    MediaSet mediaSet = null;
+                    if (setId == bucketId) {
+                        mediaSet = feed.getMediaSet(setId);
+                        if (mediaSet == null) {
+                            mediaSet = feed.addMediaSet(setId, source);
+                        }
+                    } else {
+                        mediaSet = new MediaSet();
+                    }
+                    mediaSet.mName = Utils.readUTF(dis);
+                    if (setId == bucketId) {
+                        mediaSet.mPicasaAlbumId = Shared.INVALID;
+                        mediaSet.generateTitle(true);
+                        return;
+                    }
+                }
+            } catch (IOException e) {
+                Log.e(TAG, "Error finding album " + bucketId);
+                sAlbumCache.deleteAll();
+                putLocaleForAlbumCache(Locale.getDefault());
+            }
+        } else {
+            Log.d(TAG, "No album found for album id " + bucketId);
+        }
+    }
+
+    public static final void loadMediaItemsIntoMediaFeed(final MediaFeed feed, final MediaSet set, final int rangeStart,
+            final int rangeEnd, final boolean includeImages, final boolean includeVideos) {
+        int timeElapsed = 0;
+        byte[] albumData = null;
+        while (!isCacheReady(set.mId) && timeElapsed < 30000) {
+            try {
+                Thread.sleep(300);
+            } catch (InterruptedException e) {
+                return;
+            }
+            timeElapsed += 300;
+        }
+        albumData = sAlbumCache.get(set.mId, 0);
+        if (albumData != null && set.mNumItemsLoaded < set.getNumExpectedItems()) {
+            final DataInputStream dis = new DataInputStream(new BufferedInputStream(new ByteArrayInputStream(albumData), 256));
+            try {
+                final int numItems = dis.readInt();
+                set.setNumExpectedItems(numItems);
+                set.mMinTimestamp = dis.readLong();
+                set.mMaxTimestamp = dis.readLong();
+                for (int i = 0; i < numItems; ++i) {
+                    final MediaItem item = new MediaItem();
+                    // Must preserve order with method that writes to cache.
+                    item.mId = dis.readLong();
+                    item.mCaption = Utils.readUTF(dis);
+                    item.mMimeType = Utils.readUTF(dis);
+                    item.setMediaType(dis.readInt());
+                    item.mLatitude = dis.readDouble();
+                    item.mLongitude = dis.readDouble();
+                    item.mDateTakenInMs = dis.readLong();
+                    item.mTriedRetrievingExifDateTaken = dis.readBoolean();
+                    item.mDateAddedInSec = dis.readLong();
+                    item.mDateModifiedInSec = dis.readLong();
+                    item.mDurationInSec = dis.readInt();
+                    item.mRotation = (float) dis.readInt();
+                    item.mFilePath = Utils.readUTF(dis);
+                    int itemMediaType = item.getMediaType();
+                    if ((itemMediaType == MediaItem.MEDIA_TYPE_IMAGE && includeImages)
+                            || (itemMediaType == MediaItem.MEDIA_TYPE_VIDEO && includeVideos)) {
+                        String baseUri = (itemMediaType == MediaItem.MEDIA_TYPE_IMAGE) ? BASE_CONTENT_STRING_IMAGES
+                                : BASE_CONTENT_STRING_VIDEOS;
+                        item.mContentUri = baseUri + item.mId;
+                        feed.addItemToMediaSet(item, set);
+                    }
+                }
+                dis.close();
+            } catch (IOException e) {
+                Log.e(TAG, "Error loading items for album " + set.mName);
+                sAlbumCache.deleteAll();
+                putLocaleForAlbumCache(Locale.getDefault());
+            }
+        } else {
+            Log.d(TAG, "No items found for album " + set.mName);
+        }
+        set.updateNumExpectedItems();
+        set.generateTitle(true);
+    }
+
+    public static final void populateVideoItemFromCursor(final MediaItem item, final ContentResolver cr, final Cursor cursor,
+            final String baseUri) {
+        item.setMediaType(MediaItem.MEDIA_TYPE_VIDEO);
+        populateMediaItemFromCursor(item, cr, cursor, baseUri);
+    }
+
+    public static final void populateMediaItemFromCursor(final MediaItem item, final ContentResolver cr, final Cursor cursor,
+            final String baseUri) {
+        item.mId = cursor.getLong(CacheService.MEDIA_ID_INDEX);
+        item.mCaption = cursor.getString(CacheService.MEDIA_CAPTION_INDEX);
+        item.mMimeType = cursor.getString(CacheService.MEDIA_MIME_TYPE_INDEX);
+        item.mLatitude = cursor.getDouble(CacheService.MEDIA_LATITUDE_INDEX);
+        item.mLongitude = cursor.getDouble(CacheService.MEDIA_LONGITUDE_INDEX);
+        item.mDateTakenInMs = cursor.getLong(CacheService.MEDIA_DATE_TAKEN_INDEX);
+        item.mDateAddedInSec = cursor.getLong(CacheService.MEDIA_DATE_ADDED_INDEX);
+        item.mDateModifiedInSec = cursor.getLong(CacheService.MEDIA_DATE_MODIFIED_INDEX);
+        if (item.mDateTakenInMs == item.mDateModifiedInSec) {
+            item.mDateTakenInMs = item.mDateModifiedInSec * 1000;
+        }
+        item.mFilePath = cursor.getString(CacheService.MEDIA_DATA_INDEX);
+        if (baseUri != null)
+            item.mContentUri = baseUri + item.mId;
+        final int itemMediaType = item.getMediaType();
+        // Check to see if a new date taken is available.
+        final long dateTaken = fetchDateTaken(item);
+        if (dateTaken != -1L && item.mContentUri != null) {
+            item.mDateTakenInMs = dateTaken;
+            final ContentValues values = new ContentValues();
+            if (itemMediaType == MediaItem.MEDIA_TYPE_VIDEO) {
+                values.put(Video.VideoColumns.DATE_TAKEN, item.mDateTakenInMs);
+            } else {
+                values.put(Images.ImageColumns.DATE_TAKEN, item.mDateTakenInMs);
+            }
+            try {
+                cr.update(Uri.parse(item.mContentUri), values, null, null);
+            } catch (Exception e) {
+                // If the database operation fails for any reason.
+                ;
+            }
+        }
+
+        final int orientationDurationValue = cursor.getInt(CacheService.MEDIA_ORIENTATION_OR_DURATION_INDEX);
+        if (itemMediaType == MediaItem.MEDIA_TYPE_IMAGE) {
+            item.mRotation = orientationDurationValue;
+        } else {
+            item.mDurationInSec = orientationDurationValue;
+        }
+    }
+
+    // Returns -1 if we failed to examine EXIF information or EXIF parsing
+    // failed.
+    public static final long fetchDateTaken(final MediaItem item) {
+        if (!item.isDateTakenValid() && !item.mTriedRetrievingExifDateTaken
+                && (item.mFilePath.endsWith(".jpg") || item.mFilePath.endsWith(".jpeg"))) {
+            try {
+                Log.i(TAG, "Parsing date taken from exif");
+                final ExifInterface exif = new ExifInterface(item.mFilePath);
+                final String dateTakenStr = exif.getAttribute(ExifInterface.TAG_DATETIME);
+                if (dateTakenStr != null) {
+                    try {
+                        final Date dateTaken = mDateFormat.parse(dateTakenStr);
+                        return dateTaken.getTime();
+                    } catch (ParseException pe) {
+                        try {
+                            final Date dateTaken = mAltDateFormat.parse(dateTakenStr);
+                            return dateTaken.getTime();
+                        } catch (ParseException pe2) {
+                            Log.i(TAG, "Unable to parse date out of string - " + dateTakenStr);
+                        }
+                    }
+                }
+            } catch (Exception e) {
+                Log.i(TAG, "Error reading Exif information, probably not a jpeg.");
+            }
+
+            // Ensures that we only try retrieving EXIF date taken once.
+            item.mTriedRetrievingExifDateTaken = true;
+        }
+        return -1L;
+    }
+
+    public static final byte[] queryThumbnail(final Context context, final long thumbId, final long origId, final boolean isVideo,
+            final long timestamp) {
+        final DiskCache thumbnailCache = (isVideo) ? LocalDataSource.sThumbnailCacheVideo : LocalDataSource.sThumbnailCache;
+        return queryThumbnail(context, thumbId, origId, isVideo, thumbnailCache, timestamp);
+    }
+
+    public static final ImageList getImageList(final Context context) {
+        if (sList != null)
+            return sList;
+        ImageList list = new ImageList();
+        final Uri uriImages = Images.Media.EXTERNAL_CONTENT_URI;
+        final ContentResolver cr = context.getContentResolver();
+        try {
+            final Cursor cursorImages = cr.query(uriImages, THUMBNAIL_PROJECTION, null, null, null);
+            if (cursorImages != null && cursorImages.moveToFirst()) {
+                final int size = cursorImages.getCount();
+                final long[] ids = new long[size];
+                final long[] thumbnailIds = new long[size];
+                final long[] timestamp = new long[size];
+                final int[] orientation = new int[size];
+                int ctr = 0;
+                do {
+                    if (Thread.interrupted()) {
+                        break;
+                    }
+                    ids[ctr] = cursorImages.getLong(THUMBNAIL_ID_INDEX);
+                    timestamp[ctr] = cursorImages.getLong(THUMBNAIL_DATE_MODIFIED_INDEX);
+                    thumbnailIds[ctr] = Utils.Crc64Long(cursorImages.getString(THUMBNAIL_DATA_INDEX));
+                    orientation[ctr] = cursorImages.getInt(THUMBNAIL_ORIENTATION_INDEX);
+                    ++ctr;
+                } while (cursorImages.moveToNext());
+                cursorImages.close();
+                list.ids = ids;
+                list.thumbids = thumbnailIds;
+                list.timestamp = timestamp;
+                list.orientation = orientation;
+            }
+        } catch (Exception e) {
+            // If the database operation failed for any reason
+            ;
+        }
+        if (sList == null) {
+            sList = list;
+        }
+        return list;
+    }
+
+    private static final byte[] queryThumbnail(final Context context, final long thumbId, final long origId, final boolean isVideo,
+            final DiskCache thumbnailCache, final long timestamp) {
+        if (!((Gallery) context).isPaused()) {
+            final Thread thumbnailThread = THUMBNAIL_THREAD.getAndSet(null);
+            if (thumbnailThread != null) {
+                thumbnailThread.interrupt();
+            }
+        }
+        byte[] bitmap = thumbnailCache.get(thumbId, timestamp);
+        if (bitmap == null) {
+            final long time = SystemClock.uptimeMillis();
+            bitmap = buildThumbnailForId(context, thumbnailCache, thumbId, origId, isVideo, DEFAULT_THUMBNAIL_WIDTH,
+                    DEFAULT_THUMBNAIL_HEIGHT);
+            Log.i(TAG, "Built thumbnail and screennail for " + origId + " in " + (SystemClock.uptimeMillis() - time));
+        }
+        return bitmap;
+    }
+
+    private static final void buildThumbnails(final Context context) {
+        Log.i(TAG, "Preparing DiskCache for all thumbnails.");
+        ImageList list = getImageList(context);
+        final int size = (list.ids == null) ? 0 : list.ids.length;
+        final long[] ids = list.ids;
+        final long[] timestamp = list.timestamp;
+        final long[] thumbnailIds = list.thumbids;
+        final DiskCache thumbnailCache = LocalDataSource.sThumbnailCache;
+        for (int i = 0; i < size; ++i) {
+            if (Thread.interrupted()) {
+                return;
+            }
+            final long id = ids[i];
+            final long timeModifiedInSec = timestamp[i];
+            final long thumbnailId = thumbnailIds[i];
+            if (!thumbnailCache.isDataAvailable(thumbnailId, timeModifiedInSec * 1000)) {
+                buildThumbnailForId(context, thumbnailCache, thumbnailId, id, false, DEFAULT_THUMBNAIL_WIDTH,
+                        DEFAULT_THUMBNAIL_HEIGHT);
+            }
+        }
+        Log.i(TAG, "DiskCache ready for all thumbnails.");
+    }
+
+    private static final byte[] buildThumbnailForId(final Context context, final DiskCache thumbnailCache, final long thumbId,
+            final long origId, final boolean isVideo, final int thumbnailWidth, final int thumbnailHeight) {
+        if (origId == Shared.INVALID) {
+            return null;
+        }
+        try {
+            Bitmap bitmap = null;
+            Thread.sleep(1);
+            if (!isVideo) {
+                final String uriString = BASE_CONTENT_STRING_IMAGES + origId;
+                UriTexture.invalidateCache(thumbId, 1024);
+                try {
+                    bitmap = UriTexture.createFromUri(context, uriString, 1024, 1024, thumbId, null);
+                } catch (IOException e) {
+                    return null;
+                } catch (URISyntaxException e) {
+                    return null;
+                }
+            } else {
+                new Thread() {
+                    public void run() {
+                        try {
+                            Thread.sleep(5000);
+                        } catch (InterruptedException e) {
+                            ;
+                        }
+                        try {
+                            MediaStore.Video.Thumbnails.cancelThumbnailRequest(context.getContentResolver(), origId);
+                        } catch (Exception e) {
+                            ;
+                        }
+                    }
+                }.start();
+                bitmap = MediaStore.Video.Thumbnails.getThumbnail(context.getContentResolver(), origId,
+                        MediaStore.Video.Thumbnails.MICRO_KIND, null);
+            }
+            if (bitmap == null) {
+                return null;
+            }
+            final byte[] retVal = writeBitmapToCache(thumbnailCache, thumbId, origId, bitmap, thumbnailWidth, thumbnailHeight);
+            return retVal;
+        } catch (InterruptedException e) {
+            return null;
+        }
+    }
+
+    public static final byte[] writeBitmapToCache(final DiskCache thumbnailCache, final long thumbId, final long origId,
+            final Bitmap bitmap, final int thumbnailWidth, final int thumbnailHeight) {
+        final int width = bitmap.getWidth();
+        final int height = bitmap.getHeight();
+        // Detect faces to find the focal point, otherwise fall back to the
+        // image center.
+        int focusX = width / 2;
+        int focusY = height / 2;
+        // We have commented out face detection since it slows down the
+        // generation of the thumbnail and screennail.
+
+        // final FaceDetector faceDetector = new FaceDetector(width, height, 1);
+        // final FaceDetector.Face[] faces = new FaceDetector.Face[1];
+        // final int numFaces = faceDetector.findFaces(bitmap, faces);
+        // if (numFaces > 0 && faces[0].confidence() >=
+        // FaceDetector.Face.CONFIDENCE_THRESHOLD) {
+        // final PointF midPoint = new PointF();
+        // faces[0].getMidPoint(midPoint);
+        // focusX = (int) midPoint.x;
+        // focusY = (int) midPoint.y;
+        // }
+
+        // Crop to thumbnail aspect ratio biased towards the focus point.
+        int cropX;
+        int cropY;
+        int cropWidth;
+        int cropHeight;
+        float scaleFactor;
+        if (thumbnailWidth * height < thumbnailHeight * width) {
+            // Vertically constrained.
+            cropWidth = thumbnailWidth * height / thumbnailHeight;
+            cropX = Math.max(0, Math.min(focusX - cropWidth / 2, width - cropWidth));
+            cropY = 0;
+            cropHeight = height;
+            scaleFactor = (float) thumbnailHeight / height;
+        } else {
+            // Horizontally constrained.
+            cropHeight = thumbnailHeight * width / thumbnailWidth;
+            cropY = Math.max(0, Math.min(focusY - cropHeight / 2, height - cropHeight));
+            cropX = 0;
+            cropWidth = width;
+            scaleFactor = (float) thumbnailWidth / width;
+        }
+        final Bitmap finalBitmap = Bitmap.createBitmap(thumbnailWidth, thumbnailHeight, Bitmap.Config.RGB_565);
+        final Canvas canvas = new Canvas(finalBitmap);
+        final Paint paint = new Paint();
+        paint.setFilterBitmap(true);
+        canvas.drawColor(0);
+        canvas.drawBitmap(bitmap, new Rect(cropX, cropY, cropX + cropWidth, cropY + cropHeight), new Rect(0, 0, thumbnailWidth,
+                thumbnailHeight), paint);
+        bitmap.recycle();
+
+        // Store (long thumbnailId, short focusX, short focusY, JPEG data).
+        final ByteArrayOutputStream cacheOutput = new ByteArrayOutputStream(16384);
+        final DataOutputStream dataOutput = new DataOutputStream(cacheOutput);
+        byte[] retVal = null;
+        try {
+            dataOutput.writeLong(origId);
+            dataOutput.writeShort((int) ((focusX - cropX) * scaleFactor));
+            dataOutput.writeShort((int) ((focusY - cropY) * scaleFactor));
+            dataOutput.flush();
+            finalBitmap.compress(Bitmap.CompressFormat.JPEG, 80, cacheOutput);
+            retVal = cacheOutput.toByteArray();
+            synchronized (thumbnailCache) {
+                thumbnailCache.put(thumbId, retVal);
+            }
+            cacheOutput.close();
+        } catch (Exception e) {
+            ;
+        }
+        return retVal;
+    }
+
+    public CacheService() {
+        super("CacheService");
+    }
+
+    @Override
+    protected void onHandleIntent(final Intent intent) {
+        Log.i(TAG, "Starting CacheService");
+        if (Environment.getExternalStorageState() == Environment.MEDIA_BAD_REMOVAL) {
+            sAlbumCache.deleteAll();
+            putLocaleForAlbumCache(Locale.getDefault());
+        }
+        Locale locale = getLocaleForAlbumCache();
+        if (locale != null && locale.equals(Locale.getDefault())) {
+            // The cache is in the same locale as the system locale.
+            if (!isCacheReady(false)) {
+                // The albums and their items have not yet been cached, we need
+                // to run the service.
+                startNewCacheThread();
+            } else {
+                startNewCacheThreadForDirtySets();
+            }
+        } else {
+            // The locale has changed, we need to regenerate the strings.
+            sAlbumCache.deleteAll();
+            putLocaleForAlbumCache(Locale.getDefault());
+            startNewCacheThread();
+        }
+        if (intent.getBooleanExtra("checkthumbnails", false)) {
+            startNewThumbnailThread(this);
+        } else {
+            final Thread existingThread = THUMBNAIL_THREAD.getAndSet(null);
+            if (existingThread != null) {
+                existingThread.interrupt();
+            }
+        }
+    }
+
+    private static final void putLocaleForAlbumCache(final Locale locale) {
+        final ByteArrayOutputStream bos = new ByteArrayOutputStream();
+        final DataOutputStream dos = new DataOutputStream(bos);
+        try {
+            Utils.writeUTF(dos, locale.getCountry());
+            Utils.writeUTF(dos, locale.getLanguage());
+            Utils.writeUTF(dos, locale.getVariant());
+            dos.flush();
+            bos.flush();
+            final byte[] data = bos.toByteArray();
+            sAlbumCache.put(ALBUM_CACHE_LOCALE_INDEX, data);
+            sAlbumCache.flush();
+            dos.close();
+            bos.close();
+        } catch (IOException e) {
+            // Could not write locale to cache.
+            Log.i(TAG, "Error writing locale to cache.");
+            ;
+        }
+    }
+
+    private static final Locale getLocaleForAlbumCache() {
+        final byte[] data = sAlbumCache.get(ALBUM_CACHE_LOCALE_INDEX, 0);
+        if (data != null && data.length > 0) {
+            ByteArrayInputStream bis = new ByteArrayInputStream(data);
+            DataInputStream dis = new DataInputStream(bis);
+            try {
+                String country = Utils.readUTF(dis);
+                if (country == null)
+                    country = "";
+                String language = Utils.readUTF(dis);
+                if (language == null)
+                    language = "";
+                String variant = Utils.readUTF(dis);
+                if (variant == null)
+                    variant = "";
+                final Locale locale = new Locale(language, country, variant);
+                dis.close();
+                bis.close();
+                return locale;
+            } catch (IOException e) {
+                // Could not read locale in cache.
+                Log.i(TAG, "Error reading locale from cache.");
+                return null;
+            }
+        }
+        return null;
+    }
+
+    private static final void restartThread(final AtomicReference<Thread> threadRef, final String name, final Runnable action) {
+        // Create a new thread.
+        final Thread newThread = new Thread() {
+            public void run() {
+                try {
+                    action.run();
+                } finally {
+                    threadRef.compareAndSet(this, null);
+                }
+            }
+        };
+        newThread.setName(name);
+        newThread.start();
+
+        // Interrupt any existing thread.
+        final Thread existingThread = threadRef.getAndSet(newThread);
+        if (existingThread != null) {
+            existingThread.interrupt();
+        }
+    }
+
+    public static final void startNewThumbnailThread(final Context context) {
+        restartThread(THUMBNAIL_THREAD, "ThumbnailRefresh", new Runnable() {
+            public void run() {
+                Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
+                try {
+                    // It is an optimization to prevent the thumbnailer from
+                    // running while the application loads
+                    Thread.sleep(THUMBNAILER_WAIT_IN_MS);
+                } catch (InterruptedException e) {
+                    return;
+                }
+                CacheService.buildThumbnails(context);
+            }
+        });
+    }
+
+    private void startNewCacheThread() {
+        restartThread(CACHE_THREAD, "CacheRefresh", new Runnable() {
+            public void run() {
+                refresh(CacheService.this);
+            }
+        });
+    }
+
+    private void startNewCacheThreadForDirtySets() {
+        restartThread(CACHE_THREAD, "CacheRefreshDirtySets", new Runnable() {
+            public void run() {
+                refreshDirtySets(CacheService.this);
+            }
+        });
+    }
+
+    private static final byte[] concat(final byte[] A, final byte[] B) {
+        final byte[] C = (byte[]) new byte[A.length + B.length];
+        System.arraycopy(A, 0, C, 0, A.length);
+        System.arraycopy(B, 0, C, A.length, B.length);
+        return C;
+    }
+
+    private static final long[] toLongArray(final byte[] data) {
+        final ByteBuffer bBuffer = ByteBuffer.wrap(data);
+        final LongBuffer lBuffer = bBuffer.asLongBuffer();
+        final int numLongs = lBuffer.capacity();
+        final long[] retVal = new long[numLongs];
+        for (int i = 0; i < numLongs; ++i) {
+            retVal[i] = lBuffer.get(i);
+        }
+        return retVal;
+    }
+
+    private static final byte[] longToByteArray(final long l) {
+        final byte[] bArray = new byte[8];
+        final ByteBuffer bBuffer = ByteBuffer.wrap(bArray);
+        final LongBuffer lBuffer = bBuffer.asLongBuffer();
+        lBuffer.put(0, l);
+        return bArray;
+    }
+
+    private static final byte[] longArrayToByteArray(final long[] l) {
+        final byte[] bArray = new byte[8 * l.length];
+        final ByteBuffer bBuffer = ByteBuffer.wrap(bArray);
+        final LongBuffer lBuffer = bBuffer.asLongBuffer();
+        int numLongs = l.length;
+        for (int i = 0; i < numLongs; ++i) {
+            lBuffer.put(i, l[i]);
+        }
+        return bArray;
+    }
+
+    private final static void refresh(final Context context) {
+        // First we build the album cache.
+        // This is the meta-data about the albums / buckets on the SD card.
+        Log.i(TAG, "Refreshing cache.");
+        sAlbumCache.deleteAll();
+        putLocaleForAlbumCache(Locale.getDefault());
+
+        final ArrayList<MediaSet> sets = new ArrayList<MediaSet>();
+        LongSparseArray<MediaSet> acceleratedSets = new LongSparseArray<MediaSet>();
+        Log.i(TAG, "Building albums.");
+        final Uri uriImages = Images.Media.EXTERNAL_CONTENT_URI.buildUpon().appendQueryParameter("distinct", "true").build();
+        final Uri uriVideos = Video.Media.EXTERNAL_CONTENT_URI.buildUpon().appendQueryParameter("distinct", "true").build();
+        final ContentResolver cr = context.getContentResolver();
+        try {
+            final Cursor cursorImages = cr.query(uriImages, BUCKET_PROJECTION_IMAGES, null, null, DEFAULT_BUCKET_SORT_ORDER);
+            final Cursor cursorVideos = cr.query(uriVideos, BUCKET_PROJECTION_VIDEOS, null, null, DEFAULT_BUCKET_SORT_ORDER);
+            Cursor[] cursors = new Cursor[2];
+            cursors[0] = cursorImages;
+            cursors[1] = cursorVideos;
+            final SortCursor sortCursor = new SortCursor(cursors, Images.ImageColumns.BUCKET_DISPLAY_NAME, SortCursor.TYPE_STRING,
+                    true);
+            try {
+                if (sortCursor != null && sortCursor.moveToFirst()) {
+                    sets.ensureCapacity(sortCursor.getCount());
+                    acceleratedSets = new LongSparseArray<MediaSet>(sortCursor.getCount());
+                    MediaSet cameraSet = new MediaSet();
+                    cameraSet.mId = LocalDataSource.CAMERA_BUCKET_ID;
+                    cameraSet.mName = context.getResources().getString(R.string.camera);
+                    sets.add(cameraSet);
+                    acceleratedSets.put(cameraSet.mId, cameraSet);
+                    do {
+                        if (Thread.interrupted()) {
+                            return;
+                        }
+                        long setId = sortCursor.getLong(BUCKET_ID_INDEX);
+                        MediaSet mediaSet = findSet(setId, acceleratedSets);
+                        if (mediaSet == null) {
+                            mediaSet = new MediaSet();
+                            mediaSet.mId = setId;
+                            mediaSet.mName = sortCursor.getString(BUCKET_NAME_INDEX);
+                            sets.add(mediaSet);
+                            acceleratedSets.put(setId, mediaSet);
+                        }
+                        mediaSet.mHasImages |= (sortCursor.getCurrentCursorIndex() == 0);
+                        mediaSet.mHasVideos |= (sortCursor.getCurrentCursorIndex() == 1);
+                    } while (sortCursor.moveToNext());
+                    sortCursor.close();
+                }
+            } finally {
+                if (sortCursor != null)
+                    sortCursor.close();
+            }
+
+            sAlbumCache.put(ALBUM_CACHE_INCOMPLETE_INDEX, sDummyData);
+            writeSetsToCache(sets);
+            Log.i(TAG, "Done building albums.");
+            // Now we must cache the items contained in every album / bucket.
+            populateMediaItemsForSets(context, sets, acceleratedSets, false);
+        } catch (Exception e) {
+            // If the database operation failed for any reason.
+            ;
+        }
+        sAlbumCache.delete(ALBUM_CACHE_INCOMPLETE_INDEX);
+    }
+
+    private final static void refreshDirtySets(final Context context) {
+        final byte[] existingData = sAlbumCache.get(ALBUM_CACHE_DIRTY_BUCKET_INDEX, 0);
+        if (existingData != null && existingData.length > 0) {
+            final long[] ids = toLongArray(existingData);
+            final int numIds = ids.length;
+            if (numIds > 0) {
+                final ArrayList<MediaSet> sets = new ArrayList<MediaSet>(numIds);
+                final LongSparseArray<MediaSet> acceleratedSets = new LongSparseArray<MediaSet>(numIds);
+                for (int i = 0; i < numIds; ++i) {
+                    final MediaSet set = new MediaSet();
+                    set.mId = ids[i];
+                    sets.add(set);
+                    acceleratedSets.put(set.mId, set);
+                }
+                Log.i(TAG, "Refreshing dirty albums");
+                populateMediaItemsForSets(context, sets, acceleratedSets, true);
+            }
+        }
+        sAlbumCache.delete(ALBUM_CACHE_DIRTY_BUCKET_INDEX);
+    }
+
+    private static final long[] computeDirtySets(final Context context) {
+        final Uri uriImages = Images.Media.EXTERNAL_CONTENT_URI;
+        final Uri uriVideos = Video.Media.EXTERNAL_CONTENT_URI;
+        final ContentResolver cr = context.getContentResolver();
+        final String where = Images.ImageColumns.BUCKET_ID + "!=0) GROUP BY (" + Images.ImageColumns.BUCKET_ID + " ";
+        ArrayList<Long> retVal = new ArrayList<Long>();
+        try {
+            final Cursor cursorImages = cr.query(uriImages, SENSE_PROJECTION, where, null, null);
+            final Cursor cursorVideos = cr.query(uriVideos, SENSE_PROJECTION, where, null, null);
+            Cursor[] cursors = new Cursor[2];
+            cursors[0] = cursorImages;
+            cursors[1] = cursorVideos;
+            final MergeCursor cursor = new MergeCursor(cursors);
+            try {
+                if (cursor.moveToFirst()) {
+                    boolean allDirty = false;
+                    do {
+                        long setId = cursor.getLong(0);
+                        if (allDirty) {
+                            addNoDupe(retVal, setId);
+                        } else {
+                            boolean contains = sAlbumCache.isDataAvailable(setId, 0);
+                            if (!contains) {
+                                // We need to refresh everything.
+                                markDirty(context);
+                                addNoDupe(retVal, setId);
+                                allDirty = true;
+                            }
+                            if (!allDirty) {
+                                long maxAdded = cursor.getLong(1);
+                                int count = cursor.getInt(2);
+                                byte[] data = sMetaAlbumCache.get(setId, 0);
+                                long[] dataLong = new long[2];
+                                if (data != null) {
+                                    dataLong = toLongArray(data);
+                                }
+                                long oldMaxAdded = dataLong[0];
+                                long oldCount = dataLong[1];
+                                if (maxAdded > oldMaxAdded || oldCount != count) {
+                                    markDirty(context, setId);
+                                    addNoDupe(retVal, setId);
+                                    dataLong[0] = maxAdded;
+                                    dataLong[1] = count;
+                                    sMetaAlbumCache.put(setId, longArrayToByteArray(dataLong));
+                                }
+                            }
+                        }
+                    } while (cursor.moveToNext());
+                }
+            } finally {
+                cursor.close();
+            }
+            sMetaAlbumCache.flush();
+        } catch (Exception e) {
+            // If the database operation failed for any reason.
+            ;
+        }
+        int numIds = retVal.size();
+        long retValIds[] = new long[numIds];
+        for (int i = 0; i < numIds; ++i) {
+            retValIds[i] = retVal.get(i);
+        }
+        return retValIds;
+    }
+
+    private static final void addNoDupe(ArrayList<Long> array, long value) {
+        int size = array.size();
+        for (int i = 0; i < size; ++i) {
+            if (array.get(i).longValue() == value)
+                return;
+        }
+        array.add(value);
+    }
+
+    private static final void processQueuedDirty(final Context context) {
+        do {
+            if (QUEUE_DIRTY_SENSE) {
+                QUEUE_DIRTY_SENSE = false;
+                QUEUE_DIRTY_ALL = false;
+                QUEUE_DIRTY_SET = false;
+                computeDirtySets(context);
+            } else if (QUEUE_DIRTY_ALL) {
+                QUEUE_DIRTY_ALL = false;
+                QUEUE_DIRTY_SET = false;
+                QUEUE_DIRTY_SENSE = false;
+                refresh(context);
+            } else if (QUEUE_DIRTY_SET) {
+                QUEUE_DIRTY_SET = false;
+                // We don't mark QUEUE_DIRTY_SENSE because a set outside the
+                // dirty
+                // sets might have gotten modified.
+                refreshDirtySets(context);
+            }
+        } while (QUEUE_DIRTY_SENSE || QUEUE_DIRTY_SET || QUEUE_DIRTY_ALL);
+    }
+
+    private final static void populateMediaItemsForSets(final Context context, final ArrayList<MediaSet> sets,
+            final LongSparseArray<MediaSet> acceleratedSets, boolean useWhere) {
+        if (sets == null || sets.size() == 0 || Thread.interrupted()) {
+            return;
+        }
+        Log.i(TAG, "Building items.");
+        final Uri uriImages = Images.Media.EXTERNAL_CONTENT_URI;
+        final Uri uriVideos = Video.Media.EXTERNAL_CONTENT_URI;
+        final ContentResolver cr = context.getContentResolver();
+
+        String whereClause = null;
+        if (useWhere) {
+            int numSets = sets.size();
+            StringBuffer whereString = new StringBuffer(Images.ImageColumns.BUCKET_ID + " in (");
+            for (int i = 0; i < numSets; ++i) {
+                whereString.append(sets.get(i).mId);
+                if (i != numSets - 1) {
+                    whereString.append(",");
+                }
+            }
+            whereString.append(")");
+            whereClause = whereString.toString();
+            Log.i(TAG, "Updating dirty albums where " + whereClause);
+        }
+        try {
+            final Cursor cursorImages = cr.query(uriImages, PROJECTION_IMAGES, whereClause, null, DEFAULT_IMAGE_SORT_ORDER);
+            final Cursor cursorVideos = cr.query(uriVideos, PROJECTION_VIDEOS, whereClause, null, DEFAULT_VIDEO_SORT_ORDER);
+            final Cursor[] cursors = new Cursor[2];
+            cursors[0] = cursorImages;
+            cursors[1] = cursorVideos;
+            final SortCursor sortCursor = new SortCursor(cursors, Images.ImageColumns.DATE_TAKEN, SortCursor.TYPE_NUMERIC, true);
+            if (Thread.interrupted()) {
+                return;
+            }
+            try {
+                if (sortCursor != null && sortCursor.moveToFirst()) {
+                    final int count = sortCursor.getCount();
+                    final int numSets = sets.size();
+                    final int approximateCountPerSet = count / numSets;
+                    for (int i = 0; i < numSets; ++i) {
+                        final MediaSet set = sets.get(i);
+                        set.setNumExpectedItems(approximateCountPerSet);
+                    }
+                    do {
+                        if (Thread.interrupted()) {
+                            return;
+                        }
+                        final MediaItem item = new MediaItem();
+                        final boolean isVideo = (sortCursor.getCurrentCursorIndex() == 1);
+                        if (isVideo) {
+                            populateVideoItemFromCursor(item, cr, sortCursor, CacheService.BASE_CONTENT_STRING_VIDEOS);
+                        } else {
+                            populateMediaItemFromCursor(item, cr, sortCursor, CacheService.BASE_CONTENT_STRING_IMAGES);
+                        }
+                        final long setId = sortCursor.getLong(MEDIA_BUCKET_ID_INDEX);
+                        final MediaSet set = findSet(setId, acceleratedSets);
+                        if (set != null) {
+                            set.addItem(item);
+                        }
+                    } while (sortCursor.moveToNext());
+                }
+            } finally {
+                if (sortCursor != null)
+                    sortCursor.close();
+            }
+        } catch (Exception e) {
+            // If the database operation failed for any reason
+            ;
+        }
+        if (sets.size() > 0) {
+            writeItemsToCache(sets);
+            Log.i(TAG, "Done building items.");
+        }
+    }
+
+    private static final void writeSetsToCache(final ArrayList<MediaSet> sets) {
+        final ByteArrayOutputStream bos = new ByteArrayOutputStream();
+        final int numSets = sets.size();
+        final DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(bos, 256));
+        try {
+            dos.writeInt(numSets);
+            for (int i = 0; i < numSets; ++i) {
+                if (Thread.interrupted()) {
+                    return;
+                }
+                final MediaSet set = sets.get(i);
+                dos.writeLong(set.mId);
+                Utils.writeUTF(dos, set.mName);
+                dos.writeBoolean(set.mHasImages);
+                dos.writeBoolean(set.mHasVideos);
+            }
+            dos.flush();
+            sAlbumCache.put(ALBUM_CACHE_METADATA_INDEX, bos.toByteArray());
+            dos.close();
+            if (numSets == 0) {
+                sAlbumCache.deleteAll();
+                putLocaleForAlbumCache(Locale.getDefault());
+            }
+            sAlbumCache.flush();
+        } catch (IOException e) {
+            Log.e(TAG, "Error writing albums to diskcache.");
+            sAlbumCache.deleteAll();
+            putLocaleForAlbumCache(Locale.getDefault());
+        }
+    }
+
+    private static final void writeItemsToCache(final ArrayList<MediaSet> sets) {
+        final int numSets = sets.size();
+        for (int i = 0; i < numSets; ++i) {
+            if (Thread.interrupted()) {
+                return;
+            }
+            writeItemsForASet(sets.get(i));
+        }
+        sAlbumCache.flush();
+    }
+
+    private static final void writeItemsForASet(final MediaSet set) {
+        final ByteArrayOutputStream bos = new ByteArrayOutputStream();
+        final DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(bos, 256));
+        try {
+            final ArrayList<MediaItem> items = set.getItems();
+            final int numItems = items.size();
+            dos.writeInt(numItems);
+            dos.writeLong(set.mMinTimestamp);
+            dos.writeLong(set.mMaxTimestamp);
+            for (int i = 0; i < numItems; ++i) {
+                MediaItem item = items.get(i);
+                if (set.mId == LocalDataSource.CAMERA_BUCKET_ID || set.mId == LocalDataSource.DOWNLOAD_BUCKET_ID) {
+                    // Reverse the display order for the camera bucket - want
+                    // the latest first.
+                    item = items.get(numItems - i - 1);
+                }
+                dos.writeLong(item.mId);
+                Utils.writeUTF(dos, item.mCaption);
+                Utils.writeUTF(dos, item.mMimeType);
+                dos.writeInt(item.getMediaType());
+                dos.writeDouble(item.mLatitude);
+                dos.writeDouble(item.mLongitude);
+                dos.writeLong(item.mDateTakenInMs);
+                dos.writeBoolean(item.mTriedRetrievingExifDateTaken);
+                dos.writeLong(item.mDateAddedInSec);
+                dos.writeLong(item.mDateModifiedInSec);
+                dos.writeInt(item.mDurationInSec);
+                dos.writeInt((int) item.mRotation);
+                Utils.writeUTF(dos, item.mFilePath);
+            }
+            dos.flush();
+            sAlbumCache.put(set.mId, bos.toByteArray());
+            dos.close();
+        } catch (IOException e) {
+            Log.e(TAG, "Error writing to diskcache for set " + set.mName);
+            sAlbumCache.deleteAll();
+            putLocaleForAlbumCache(Locale.getDefault());
+        }
+    }
+
+    private static final MediaSet findSet(final long id, final LongSparseArray<MediaSet> acceleratedTable) {
+        // This is the accelerated lookup table for the MediaSet based on set
+        // id.
+        return acceleratedTable.get(id);
+    }
 }
index deac4e0..4c2fc9e 100644 (file)
@@ -51,7 +51,7 @@ public final class AdaptiveBackgroundTexture extends Texture {
     protected boolean shouldQueue() {
         return true;
     }
-    
+
     @Override
     public boolean isCached() {
         return true;
@@ -59,13 +59,14 @@ public final class AdaptiveBackgroundTexture extends Texture {
 
     @Override
     protected Bitmap load(RenderView view) {
-        // Determine a crop rectangle for the source image that is the aspect ratio of the destination.
+        // Determine a crop rectangle for the source image that is the aspect
+        // ratio of the destination.
         Bitmap source = mSource;
         if (source == null) {
             if (mBaseTexture != null) {
                 source = mBaseTexture.load(view);
                 if (source == null) {
-                       return null;
+                    return null;
                 }
             } else {
                 return null;
@@ -76,8 +77,8 @@ public final class AdaptiveBackgroundTexture extends Texture {
         int sourceHeight = source.getHeight();
         int destWidth = mWidth;
         int destHeight = mHeight;
-        float fitX = (float)sourceWidth / (float)destWidth;
-        float fitY = (float)sourceHeight / (float)destHeight;
+        float fitX = (float) sourceWidth / (float) destWidth;
+        float fitY = (float) sourceHeight / (float) destHeight;
         float scale;
         int cropX;
         int cropY;
@@ -86,7 +87,7 @@ public final class AdaptiveBackgroundTexture extends Texture {
         if (fitX < fitY) {
             // Full width, partial height.
             cropWidth = sourceWidth;
-            cropHeight = (int)(destHeight * fitX);
+            cropHeight = (int) (destHeight * fitX);
             cropX = 0;
             cropY = (sourceHeight - cropHeight) / 2;
             scale = 1.0f / fitX;
@@ -107,9 +108,12 @@ public final class AdaptiveBackgroundTexture extends Texture {
         // Get the source pixels as 32-bit ARGB.
         source.getPixels(in, 0, cropWidth, cropX, cropY, cropWidth, cropHeight);
 
-        // Box blur is a separable kernel, so it is decomposed into a horizontal and vertical pass.
-        // The filter function applies the kernel across each row and transposes the output.
-        // Hence we apply it twice to provide efficient horizontal and vertical convolution.
+        // Box blur is a separable kernel, so it is decomposed into a horizontal
+        // and vertical pass.
+        // The filter function applies the kernel across each row and transposes
+        // the output.
+        // Hence we apply it twice to provide efficient horizontal and vertical
+        // convolution.
         // The filter discards the alpha channel.
         boxBlurFilter(in, tmp, cropWidth, cropHeight, cropWidth);
         boxBlurFilter(tmp, in, cropHeight, cropWidth, START_FADE_X);
@@ -127,7 +131,7 @@ public final class AdaptiveBackgroundTexture extends Texture {
         canvas.scale(scale, scale);
         canvas.drawBitmap(filtered, 0f, 0f, paint);
         filtered.recycle();
-        
+
         // Clear the texture
         mBaseTexture = null;
         return output;
@@ -151,9 +155,10 @@ public final class AdaptiveBackgroundTexture extends Texture {
             int alpha = (y < startFadeX) ? 0xff : ((height - y - 1) * MAX_COLOR_VALUE / (height - startFadeX));
             // Compute output values for the row.
             int outPos = y;
-            for (int x = 0; x != width; ++x) {  // CR: x < width
+            for (int x = 0; x != width; ++x) { // CR: x < width
                 // Output the current pixel.
-                out[outPos] = (alpha << 24) | (KERNEL_NORM[red] << RED_MASK_SHIFT) | (KERNEL_NORM[green] << GREEN_MASK_SHIFT) | KERNEL_NORM[blue];
+                out[outPos] = (alpha << 24) | (KERNEL_NORM[red] << RED_MASK_SHIFT) | (KERNEL_NORM[green] << GREEN_MASK_SHIFT)
+                        | KERNEL_NORM[blue];
                 // Slide to the next pixel, adding the new rightmost pixel and
                 // subtracting the former leftmost.
                 int prevX = FloatUtils.clamp(x - RADIUS, 0, maxX);
index 4f7e11e..297e5de 100644 (file)
@@ -4,8 +4,8 @@ import java.util.ArrayList;
 import java.util.Arrays;
 
 public final class ArrayUtils {
-    public static final void computeSortedIntersection(ArrayList<MediaItem> firstList, final ArrayList<MediaItem> secondList, int maxSize,
-            ArrayList<MediaItem> intersectionList, MediaItem[] hash) {
+    public static final void computeSortedIntersection(ArrayList<MediaItem> firstList, final ArrayList<MediaItem> secondList,
+            int maxSize, ArrayList<MediaItem> intersectionList, MediaItem[] hash) {
         // Assumes that firstList is generally larger than the second list.
         // Build a simple filter to speed up containment testing.
         int mask = hash.length - 1;
@@ -22,9 +22,10 @@ public final class ArrayUtils {
         for (int i = 0; i < firstListSize; ++i) {
             MediaItem firstListItem = firstList.get(i);
             if (firstListItem == null)
-               continue;
+                continue;
             MediaItem hashItem = (hash != null) ? hash[firstListItem.hashCode() & mask] : null;
-            if (hashItem != null && ((hashItem.mId != Shared.INVALID && hashItem.mId == firstListItem.mId) || contains(secondList, firstListItem))) {
+            if (hashItem != null
+                    && ((hashItem.mId != Shared.INVALID && hashItem.mId == firstListItem.mId) || contains(secondList, firstListItem))) {
                 intersectionList.add(firstListItem);
                 if (--maxSize == 0) {
                     break;
@@ -49,12 +50,12 @@ public final class ArrayUtils {
         return false;
     }
 
-       public static void clear(Object[] array) {
-               int length = array.length;
-               for (int i = 0; i < length; i++) {
-                       array[i] = null;
-               }
-       }
+    public static void clear(Object[] array) {
+        int length = array.length;
+        for (int i = 0; i < length; i++) {
+            array[i] = null;
+        }
+    }
 
     public static final boolean contains(ArrayList<MediaItem> items, MediaItem item) {
         final int numItems = items.size();
index fef6bba..08a912c 100644 (file)
@@ -98,24 +98,25 @@ public class BackgroundLayer extends Layer {
                 mFallbackBackground = texture;
             }
         }
-        
-        // We stitch this crossfading texture, and to cover all cases of overlap we need to perform 3 draws.
+
+        // We stitch this crossfading texture, and to cover all cases of overlap
+        // we need to perform 3 draws.
         int cameraPosition = (int) (mGridLayer.getScrollPosition() * PARALLAX);
         int backgroundSpacing = mBackgroundBlitWidth - mBackgroundOverlap;
         int anchorEdge = -cameraPosition % (backgroundSpacing);
         int rightEdge = anchorEdge + backgroundSpacing;
-        
+
         view.draw2D(rightEdge, 0, Z_FAR_PLANE, mBackgroundBlitWidth, mHeight);
 
         view.draw2D(anchorEdge, 0, Z_FAR_PLANE, mBackgroundBlitWidth, mHeight);
 
         int leftEdge = anchorEdge - backgroundSpacing;
         view.draw2D(leftEdge, 0, Z_FAR_PLANE, mBackgroundBlitWidth, mHeight);
-        
+
         if (bind) {
             anchorTexture.unbind(view, gl);
         }
-        
+
         gl.glBlendFunc(GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA);
         gl.glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
     }
index 9741ec9..778589f 100644 (file)
@@ -28,11 +28,13 @@ public abstract class BaseCancelable<T> implements Cancelable<T> {
 
     /**
      * The state of the task, possible transitions are:
+     * 
      * <pre>
-     *     INITIAL -> CANCELED
-     *     EXECUTING -> COMPLETE, CANCELING, ERROR, CANCELED
-     *     CANCELING -> CANCELED
+     *     INITIAL -&gt; CANCELED
+     *     EXECUTING -&gt; COMPLETE, CANCELING, ERROR, CANCELED
+     *     CANCELING -&gt; CANCELED
      * </pre>
+     * 
      * When the task stop, it must be end with one of the following states:
      * COMPLETE, CANCELED, or ERROR;
      */
@@ -69,7 +71,8 @@ public abstract class BaseCancelable<T> implements Cancelable<T> {
         if (mState == STATE_ERROR) {
             throw new ExecutionException(mError);
         }
-        if (mState == STATE_COMPLETE) return mResult;
+        if (mState == STATE_COMPLETE)
+            return mResult;
         throw new IllegalStateException();
     }
 
@@ -102,8 +105,10 @@ public abstract class BaseCancelable<T> implements Cancelable<T> {
             }
         }
         synchronized (this) {
-            if (mState == STATE_CANCELING) mState = STATE_CANCELED;
-            if (mState == STATE_EXECUTING) mState = STATE_COMPLETE;
+            if (mState == STATE_CANCELING)
+                mState = STATE_CANCELED;
+            if (mState == STATE_EXECUTING)
+                mState = STATE_COMPLETE;
             notifyAll();
             if (mState == STATE_CANCELED && mResult != null) {
                 freeCanceledResult(mResult);
@@ -114,9 +119,9 @@ public abstract class BaseCancelable<T> implements Cancelable<T> {
 
     /**
      * Requests the task to be canceled.
-     *
+     * 
      * @return true if the task is running and has not been canceled; false
-     *     otherwise
+     *         otherwise
      */
 
     public synchronized boolean requestCancel() {
@@ -126,11 +131,11 @@ public abstract class BaseCancelable<T> implements Cancelable<T> {
             return false;
         }
         if (mState == STATE_EXECUTING) {
-            if (mCurrentTask != null) mCurrentTask.requestCancel();
+            if (mCurrentTask != null)
+                mCurrentTask.requestCancel();
             mState = STATE_CANCELING;
             return true;
         }
         return false;
     }
 }
-
index 4b7d77c..28e1152 100644 (file)
@@ -26,21 +26,25 @@ import java.util.WeakHashMap;
 
 /**
  * This class provides several utilities to cancel bitmap decoding.
- *
+ * 
  * The function decodeFileDescriptor() is used to decode a bitmap. During
  * decoding if another thread wants to cancel it, it calls the function
  * cancelThreadDecoding() specifying the Thread which is in decoding.
- *
+ * 
  * cancelThreadDecoding() is sticky until allowThreadDecoding() is called.
- *
- * You can also cancel decoding for a set of threads using ThreadSet as
- * the parameter for cancelThreadDecoding. To put a thread into a ThreadSet,
- * use the add() method. A ThreadSet holds (weak) references to the threads,
- * so you don't need to remove Thread from it if some thread dies.
+ * 
+ * You can also cancel decoding for a set of threads using ThreadSet as the
+ * parameter for cancelThreadDecoding. To put a thread into a ThreadSet, use the
+ * add() method. A ThreadSet holds (weak) references to the threads, so you
+ * don't need to remove Thread from it if some thread dies.
  */
 public class BitmapManager {
     private static final String TAG = "BitmapManager";
-    private static enum State {CANCEL, ALLOW}
+
+    private static enum State {
+        CANCEL, ALLOW
+    }
+
     private static class ThreadStatus {
         public State mState = State.ALLOW;
         public BitmapFactory.Options mOptions;
@@ -61,22 +65,22 @@ public class BitmapManager {
     }
 
     public static class ThreadSet implements Iterable<Thread> {
-        private final WeakHashMap<Thread, Object> mWeakCollection =
-                new WeakHashMap<Thread, Object>();
+        private final WeakHashMap<Thread, Object> mWeakCollection = new WeakHashMap<Thread, Object>();
 
         public void add(Thread t) {
             mWeakCollection.put(t, null);
         }
+
         public void remove(Thread t) {
             mWeakCollection.remove(t);
         }
+
         public Iterator<Thread> iterator() {
             return mWeakCollection.keySet().iterator();
         }
     }
 
-    private final WeakHashMap<Thread, ThreadStatus> mThreadStatus =
-            new WeakHashMap<Thread, ThreadStatus>();
+    private final WeakHashMap<Thread, ThreadStatus> mThreadStatus = new WeakHashMap<Thread, ThreadStatus>();
 
     private static BitmapManager sManager = null;
 
@@ -99,8 +103,7 @@ public class BitmapManager {
      * The following three methods are used to keep track of
      * BitmapFaction.Options used for decoding and cancelling.
      */
-    private synchronized void setDecodingOptions(Thread t,
-            BitmapFactory.Options options) {
+    private synchronized void setDecodingOptions(Thread t, BitmapFactory.Options options) {
         getOrCreateThreadStatus(t).mOptions = options;
     }
 
@@ -110,8 +113,8 @@ public class BitmapManager {
     }
 
     /**
-     * The following two methods are used to allow/cancel a set of threads
-     * for bitmap decoding.
+     * The following two methods are used to allow/cancel a set of threads for
+     * bitmap decoding.
      */
     public synchronized void allowThreadDecoding(ThreadSet threads) {
         for (Thread t : threads) {
@@ -126,8 +129,8 @@ public class BitmapManager {
     }
 
     /**
-     * The following three methods are used to keep track of which thread
-     * is being disabled for bitmap decoding.
+     * The following three methods are used to keep track of which thread is
+     * being disabled for bitmap decoding.
      */
     public synchronized boolean canThreadDecoding(Thread t) {
         ThreadStatus status = mThreadStatus.get(t);
@@ -166,8 +169,7 @@ public class BitmapManager {
     /**
      * The real place to delegate bitmap decoding to BitmapFactory.
      */
-    public Bitmap decodeFileDescriptor(FileDescriptor fd,
-                                       BitmapFactory.Options options) {
+    public Bitmap decodeFileDescriptor(FileDescriptor fd, BitmapFactory.Options options) {
         if (options.mCancel) {
             return null;
         }
index a973c18..928752e 100644 (file)
@@ -5,10 +5,11 @@ import android.graphics.Bitmap;
 public class BitmapTexture extends Texture {
     // A simple flexible texture class that enables a Texture from a bitmap.
     final Bitmap mBitmap;
+
     BitmapTexture(Bitmap bitmap) {
         mBitmap = bitmap;
     }
-    
+
     @Override
     protected Bitmap load(RenderView view) {
         return mBitmap;
index 42c61ae..5eb892d 100644 (file)
@@ -16,7 +16,6 @@ package com.cooliris.media;
  * limitations under the License.
  */
 
-
 import java.util.concurrent.ExecutionException;
 
 /**
@@ -27,18 +26,12 @@ public interface Cancelable<T> {
      * Requests this <code>Cancelable</code> to be canceled. This function will
      * return <code>true</code> if and only if the task is originally running
      * and now begin requested for cancel.
-     *
+     * 
      * If subclass need to do more things to cancel the task. It can override
-     * the code like this:
-     * <pre>
-     *     @Override
-     *     public boolean requestCancel() {
-     *         if (super.requestCancel()) {
-     *             // do necessary work to cancel the task
-     *             return true;
-     *         }
-     *         return false;
-     *     }
+     * the code like this: <pre>
+     * 
+     * @Override public boolean requestCancel() { if (super.requestCancel()) {
+     * // do necessary work to cancel the task return true; } return false; }
      * </pre>
      */
     public boolean requestCancel();
@@ -47,9 +40,9 @@ public interface Cancelable<T> {
 
     /**
      * Gets the results of this <code>Cancelable</code> task.
-     *
-     * @throws ExecutionException if exception is thrown during the execution of
-     *         the task
+     * 
+     * @throws ExecutionException
+     *             if exception is thrown during the execution of the task
      */
     public T get() throws InterruptedException, ExecutionException;
 }
\ No newline at end of file
index a881eef..0111d76 100644 (file)
@@ -57,7 +57,8 @@ public abstract class CanvasTexture {
     }
 
     public void resetTexture() {
-        // Happens when restoring the scene. Need to manage this more automatically.
+        // Happens when restoring the scene. Need to manage this more
+        // automatically.
         mTextureId = 0;
         mNeedsResize = true;
     }
index 3a719b3..896065e 100644 (file)
@@ -2,7 +2,6 @@ package com.cooliris.media;
 
 import java.util.ArrayList;
 
-
 import android.util.Log;
 
 public final class ConcatenatedDataSource implements DataSource {
@@ -36,17 +35,17 @@ public final class ConcatenatedDataSource implements DataSource {
         singleBucket.add(null);
         int numBuckets = mediaBuckets.size();
         boolean retVal = true;
-        for (int i = 0; i < numBuckets; ++i) {  // CR: iterator for
+        for (int i = 0; i < numBuckets; ++i) { // CR: iterator for
             MediaBucket bucket = mediaBuckets.get(i);
             MediaSet set = bucket.mediaSet;
             if (set != null) {
-                   DataSource dataSource = set.mDataSource;
-                   if (dataSource != null) {
-                       singleBucket.set(0, bucket);
-                       retVal &= dataSource.performOperation(operation, singleBucket, data);
-                   } else {
-                       Log.e(TAG, "MediaSet was not added to the feed");
-                   }
+                DataSource dataSource = set.mDataSource;
+                if (dataSource != null) {
+                    singleBucket.set(0, bucket);
+                    retVal &= dataSource.performOperation(operation, singleBucket, data);
+                } else {
+                    Log.e(TAG, "MediaSet was not added to the feed");
+                }
             }
         }
         return retVal;
@@ -55,7 +54,7 @@ public final class ConcatenatedDataSource implements DataSource {
     public DiskCache getThumbnailCache() {
         throw new UnsupportedOperationException("ConcatenatedDataSource should not create MediaItems");
     }
-    
+
     public void shutdown() {
         mFirst.shutdown();
         mSecond.shutdown();
index 967326e..bccd88f 100644 (file)
@@ -24,4 +24,4 @@
 //        lists.blendedList.add(this);
 //        lists.hitTestList.add(this);
 //    }
-//}
+// }
index 0e06b2a..3ea0f6b 100644 (file)
@@ -59,9 +59,13 @@ public class CropImage extends MonitoredActivity {
     private static final String TAG = "CropImage";
 
     // These are various options can be specified in the intent.
-    private Bitmap.CompressFormat mOutputFormat = Bitmap.CompressFormat.JPEG; // only used with mSaveUri
+    private Bitmap.CompressFormat mOutputFormat = Bitmap.CompressFormat.JPEG; // only
+                                                                              // used
+                                                                              // with
+                                                                              // mSaveUri
     private Uri mSaveUri = null;
-    private int mAspectX, mAspectY;  // CR: two definitions per line == sad panda.
+    private int mAspectX, mAspectY; // CR: two definitions per line == sad
+                                    // panda.
     private boolean mDoFaceDetection = true;
     private boolean mCircleCrop = false;
     private final Handler mHandler = new Handler();
@@ -93,7 +97,8 @@ public class CropImage extends MonitoredActivity {
         mImageView = (CropImageView) findViewById(R.id.image);
 
         // CR: remove TODO's.
-        // TODO: we may need to show this indicator for the main gallery application
+        // TODO: we may need to show this indicator for the main gallery
+        // application
         // MenuHelper.showStorageToast(this);
 
         Intent intent = getIntent();
@@ -124,32 +129,32 @@ public class CropImage extends MonitoredActivity {
 
         if (mBitmap == null) {
             // Create a MediaItem representing the URI.
-               Uri target = intent.getData();
+            Uri target = intent.getData();
             String targetScheme = target.getScheme();
             int rotation = 0;
-            
+
             if (targetScheme.equals("content")) {
-               mItem = LocalDataSource.createMediaItemFromUri(this, target);
+                mItem = LocalDataSource.createMediaItemFromUri(this, target);
             }
             try {
-               if (mItem != null) {
-                       mBitmap = UriTexture.createFromUri(this, mItem.mContentUri, 1024, 1024, 0, null);
-                       rotation = (int)mItem.mRotation;
-                   } else {
-                       mBitmap = UriTexture.createFromUri(this, target.toString(), 1024, 1024, 0, null);
-                       if (targetScheme.equals("file")) {
-                               ExifInterface exif = new ExifInterface(target.getPath());
-                                       rotation = (int)Shared.exifOrientationToDegrees(exif.getAttributeInt(ExifInterface.TAG_ORIENTATION,
-                                                                       ExifInterface.ORIENTATION_NORMAL));
-                       }
-                   }
+                if (mItem != null) {
+                    mBitmap = UriTexture.createFromUri(this, mItem.mContentUri, 1024, 1024, 0, null);
+                    rotation = (int) mItem.mRotation;
+                } else {
+                    mBitmap = UriTexture.createFromUri(this, target.toString(), 1024, 1024, 0, null);
+                    if (targetScheme.equals("file")) {
+                        ExifInterface exif = new ExifInterface(target.getPath());
+                        rotation = (int) Shared.exifOrientationToDegrees(exif.getAttributeInt(ExifInterface.TAG_ORIENTATION,
+                                ExifInterface.ORIENTATION_NORMAL));
+                    }
+                }
             } catch (IOException e) {
             } catch (URISyntaxException e) {
             }
 
-                       if (mBitmap != null && rotation != 0f) {
-                               mBitmap = Util.rotate(mBitmap, rotation);
-                       }
+            if (mBitmap != null && rotation != 0f) {
+                mBitmap = Util.rotate(mBitmap, rotation);
+            }
         }
 
         if (mBitmap == null) {
@@ -227,7 +232,7 @@ public class CropImage extends MonitoredActivity {
 
         Rect r = mCrop.getCropRect();
 
-        int width = r.width();  // CR: final == happy panda!
+        int width = r.width(); // CR: final == happy panda!
         int height = r.height();
 
         // If we are circle cropping, we want alpha channel, which is the
@@ -264,8 +269,9 @@ public class CropImage extends MonitoredActivity {
             } else {
 
                 /*
-                 * Don't scale the image crop it to the size requested. Create an new image with the cropped image in the center and
-                 * the extra space filled.
+                 * Don't scale the image crop it to the size requested. Create
+                 * an new image with the cropped image in the center and the
+                 * extra space filled.
                  */
 
                 // Don't scale the image but instead fill it so it's the
@@ -343,13 +349,15 @@ public class CropImage extends MonitoredActivity {
                 String fileName = oldPath.getName();
                 fileName = fileName.substring(0, fileName.lastIndexOf("."));
 
-                // Try file-1.jpg, file-2.jpg, ... until we find a filename which
+                // Try file-1.jpg, file-2.jpg, ... until we find a filename
+                // which
                 // does not exist yet.
                 while (true) {
                     x += 1;
                     String candidate = directory.toString() + "/" + fileName + "-" + x + ".jpg";
                     boolean exists = (new File(candidate)).exists();
-                    if (!exists) {  // CR: inline the expression for exists here--it's clear enough.
+                    if (!exists) { // CR: inline the expression for exists
+                                   // here--it's clear enough.
                         break;
                     }
                 }
@@ -358,7 +366,7 @@ public class CropImage extends MonitoredActivity {
                     String finalFileName = fileName + "-" + x + ".jpg";
                     // TODO this is going to cause the orientation to reset.
                     Uri newUri = ImageManager.addImage(mContentResolver, item.mCaption, item.mDateTakenInMs, item.mLatitude,
-                                                       item.mLongitude, 0, directory.toString(), finalFileName);
+                            item.mLongitude, 0, directory.toString(), finalFileName);
                     boolean complete = false;
                     try {
                         String[] projection = new String[] { ImageColumns._ID, ImageColumns.MINI_THUMB_MAGIC };
@@ -394,7 +402,7 @@ public class CropImage extends MonitoredActivity {
                         }
                     }
                     setResult(RESULT_OK, new Intent().setAction(newUri.toString()).putExtras(extras));
-                } catch (Exception e) {  // CR: e.
+                } catch (Exception e) { // CR: e.
                     // CR: sentences!
                     Log.e(TAG, "Store image fail, continue anyway", e);
                 }
@@ -501,7 +509,8 @@ public class CropImage extends MonitoredActivity {
 
             // 256 pixels wide is enough.
             if (mBitmap.getWidth() > 256) {
-                mScale = 256.0F / mBitmap.getWidth();  // CR: F => f (or change all f to F).
+                mScale = 256.0F / mBitmap.getWidth(); // CR: F => f (or change
+                                                      // all f to F).
             }
             Matrix matrix = new Matrix();
             matrix.setScale(mScale, mScale);
@@ -540,7 +549,8 @@ public class CropImage extends MonitoredActivity {
                     }
 
                     if (mNumFaces > 1) {
-                        // CR: no need for the variable t. just do Toast.makeText(...).show().
+                        // CR: no need for the variable t. just do
+                        // Toast.makeText(...).show().
                         Toast t = Toast.makeText(CropImage.this, R.string.multiface_crop_help, Toast.LENGTH_SHORT);
                         t.show();
                     }
@@ -642,11 +652,16 @@ class CropImageView extends ImageViewTouchBase {
         }
 
         switch (event.getAction()) {
-        case MotionEvent.ACTION_DOWN:  // CR: inline case blocks.
+        case MotionEvent.ACTION_DOWN: // CR: inline case blocks.
             if (cropImage.mWaitingToPick) {
                 recomputeFocus(event);
             } else {
-                for (int i = 0; i < mHighlightViews.size(); i++) {  // CR: iterator for; if not, then i++ => ++i.
+                for (int i = 0; i < mHighlightViews.size(); i++) { // CR:
+                                                                   // iterator
+                                                                   // for; if
+                                                                   // not, then
+                                                                   // i++ =>
+                                                                   // ++i.
                     HighlightView hv = mHighlightViews.get(i);
                     int edge = hv.getHit(event.getX(), event.getY());
                     if (edge != HighlightView.GROW_NONE) {
@@ -670,7 +685,8 @@ class CropImageView extends ImageViewTouchBase {
                     if (hv.hasFocus()) {
                         cropImage.mCrop = hv;
                         for (int j = 0; j < mHighlightViews.size(); j++) {
-                            if (j == i) {  // CR: if j != i do your shit; no need for continue.
+                            if (j == i) { // CR: if j != i do your shit; no need
+                                          // for continue.
                                 continue;
                             }
                             mHighlightViews.get(j).setHidden(true);
@@ -763,7 +779,7 @@ class CropImageView extends ImageViewTouchBase {
         if ((Math.abs(zoom - getScale()) / zoom) > .1) {
             float[] coordinates = new float[] { hv.mCropRect.centerX(), hv.mCropRect.centerY() };
             getImageMatrix().mapPoints(coordinates);
-            zoomTo(zoom, coordinates[0], coordinates[1], 300F);  // CR: 300.0f.
+            zoomTo(zoom, coordinates[0], coordinates[1], 300F); // CR: 300.0f.
         }
 
         ensureVisible(hv);
index 0b640b4..6897a00 100644 (file)
@@ -15,8 +15,9 @@ public class CrossFadingTexture {
     private boolean mBind = false;
     private boolean mFadeNecessary = false;
 
-    public CrossFadingTexture() { }
-    
+    public CrossFadingTexture() {
+    }
+
     public CrossFadingTexture(Texture initialTexture) {
         mMixRatio = 1.0f;
         mAnimatedMixRatio = 1.0f;
@@ -43,7 +44,7 @@ public class CrossFadingTexture {
     }
 
     public void setTexture(Texture texture) {
-        if (mTexture == texture || texture == null || (mAnimatedMixRatio > 0.0f && mAnimatedMixRatio < 1.0f)) {
+        if (mTexture == texture || texture == null || mAnimatedMixRatio < 1.0f) {
             return;
         }
         mFadeNecessary = false;
@@ -80,10 +81,10 @@ public class CrossFadingTexture {
             return false;
         }
     }
-    
+
     public boolean bind(RenderView view, GL11 gl) {
         if (mBind) {
-            return true;  // Already bound.
+            return true; // Already bound.
         }
         if (mFadingTexture != null && mFadingTexture.mState == Texture.STATE_ERROR) {
             mFadingTexture = null;
@@ -115,8 +116,8 @@ public class CrossFadingTexture {
         mBind = true;
         if (mAnimatedMixRatio <= 0.0f && fadingTextureLoaded) {
             view.bind(mFadingTexture);
-        } else if (mAnimatedMixRatio >= 1.0f || !fadingTextureLoaded ||
-                view.getAlpha() < mAnimatedMixRatio || mFadingTexture == mTexture) {
+        } else if (mAnimatedMixRatio >= 1.0f || !fadingTextureLoaded || view.getAlpha() < mAnimatedMixRatio
+                || mFadingTexture == mTexture) {
             view.bind(mTexture);
         } else {
             mBindUsingMixed = true;
index 90b6df2..40631fa 100644 (file)
@@ -2,17 +2,16 @@ package com.cooliris.media;
 
 import java.util.ArrayList;
 
-
 public interface DataSource {
     // Load the sets to be displayed.
     void loadMediaSets(final MediaFeed feed);
 
     // Pass in Shared.INFINITY for the rangeEnd to load all items.
     void loadItemsForSet(final MediaFeed feed, final MediaSet parentSet, int rangeStart, int rangeEnd);
-    
+
     // Called when the data source will no longer be used.
     void shutdown();
-    
+
     boolean performOperation(int operation, ArrayList<MediaBucket> mediaBuckets, Object data);
 
     DiskCache getThumbnailCache();
index d7175c5..22540e7 100644 (file)
@@ -23,7 +23,9 @@ public final class Deque<E extends Object> {
     }
 
     public int size() {
-        return (mTail - mHead) & (mArray.length - 1);  // CR: wtf?!? this definitely needs a comment.
+        return (mTail - mHead) & (mArray.length - 1); // CR: wtf?!? this
+                                                      // definitely needs a
+                                                      // comment.
     }
 
     public void clear() {
index 10c06c1..4a1a698 100644 (file)
@@ -5,13 +5,16 @@ import java.util.ArrayList;
 import java.util.Date;
 
 import android.content.Context;
-import android.content.res.Resources;;
+import android.content.res.Resources;
+
+;
 
 public final class DetailMode {
     public static CharSequence[] populateDetailModeStrings(Context context, ArrayList<MediaBucket> buckets) {
         int numBuckets = buckets.size();
         if (MediaBucketList.isSetSelection(buckets) && numBuckets == 1) {
-            // If just 1 set was selected, save the trouble of processing the items in the set again.
+            // If just 1 set was selected, save the trouble of processing the
+            // items in the set again.
             // We have already processed details for that set.
             return populateSetViewDetailModeStrings(context, MediaBucketList.getFirstSetSelection(buckets), 1);
         } else if (MediaBucketList.isSetSelection(buckets) || MediaBucketList.isMultipleItemSelection(buckets)) {
@@ -39,7 +42,7 @@ public final class DetailMode {
             }
             return populateSetViewDetailModeStrings(context, selectedItemsSet, numBuckets);
         } else {
-            return populateItemViewDetailModeStrings(context, MediaBucketList.getFirstItemSelection(buckets)); 
+            return populateItemViewDetailModeStrings(context, MediaBucketList.getFirstItemSelection(buckets));
         }
     }
 
@@ -49,7 +52,7 @@ public final class DetailMode {
         }
         Resources resources = context.getResources();
         ArrayList<CharSequence> strings = new ArrayList<CharSequence>();
-        
+
         // Number of albums selected.
         if (numOriginalSets == 1) {
             strings.add("1 " + resources.getString(R.string.album_selected));
@@ -64,9 +67,9 @@ public final class DetailMode {
         } else {
             strings.add(Integer.toString(numItems) + " " + resources.getString(R.string.items_selected));
         }
-        
-        DateFormat dateTimeFormat = DateFormat.getDateTimeInstance(DateFormat.MEDIUM,DateFormat.SHORT);
-        
+
+        DateFormat dateTimeFormat = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.SHORT);
+
         // Start and end times of the selected items.
         if (selectedItemsSet.areTimestampsAvailable()) {
             long minTimestamp = selectedItemsSet.mMinTimestamp;
@@ -85,7 +88,7 @@ public final class DetailMode {
                 maxTimestamp -= Gallery.CURRENT_TIME_ZONE.getOffset(maxTimestamp);
             }
             strings.add(resources.getString(R.string.start) + ": " + dateTimeFormat.format(new Date(minTimestamp)));
-            strings.add(resources.getString(R.string.end) + ": " + dateTimeFormat.format(new Date(maxTimestamp)));            
+            strings.add(resources.getString(R.string.end) + ": " + dateTimeFormat.format(new Date(maxTimestamp)));
         } else {
             strings.add(resources.getString(R.string.start) + ": " + resources.getString(R.string.date_unknown));
             strings.add(resources.getString(R.string.end) + ": " + resources.getString(R.string.date_unknown));
@@ -102,12 +105,12 @@ public final class DetailMode {
             }
         }
         if (locationString != null && locationString.length() > 0) {
-               strings.add(resources.getString(R.string.location) + ": " + locationString);
+            strings.add(resources.getString(R.string.location) + ": " + locationString);
         }
         int numStrings = strings.size();
         CharSequence[] stringsArr = new CharSequence[numStrings];
         for (int i = 0; i < numStrings; ++i) {
-               stringsArr[i] = strings.get(i);
+            stringsArr[i] = strings.get(i);
         }
         return stringsArr;
     }
@@ -116,13 +119,13 @@ public final class DetailMode {
         if (item == null) {
             return null;
         }
-        Resources resources = context.getResources(); 
+        Resources resources = context.getResources();
         CharSequence[] strings = new CharSequence[5];
         strings[0] = resources.getString(R.string.title) + ": " + item.mCaption;
         strings[1] = resources.getString(R.string.type) + ": " + item.getDisplayMimeType();
-        
-        DateFormat dateTimeFormat = DateFormat.getDateTimeInstance(DateFormat.MEDIUM,DateFormat.SHORT);
-        
+
+        DateFormat dateTimeFormat = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.SHORT);
+
         if (item.isDateTakenValid()) {
             long dateTaken = item.mDateTakenInMs;
             if (item.isPicassaItem()) {
@@ -135,7 +138,8 @@ public final class DetailMode {
                 dateAdded -= Gallery.CURRENT_TIME_ZONE.getOffset(dateAdded);
             }
             // TODO: Make this added_on as soon as translations are ready.
-            //strings[2] = resources.getString(R.string.added_on) + ": " + DateFormat.format("h:mmaa MMM dd yyyy", dateAdded);
+            // strings[2] = resources.getString(R.string.added_on) + ": " +
+            // DateFormat.format("h:mmaa MMM dd yyyy", dateAdded);
             strings[2] = resources.getString(R.string.taken_on) + ": " + dateTimeFormat.format(new Date(dateAdded));
         } else {
             strings[2] = resources.getString(R.string.taken_on) + ": " + resources.getString(R.string.date_unknown);
index 70a884f..a55e137 100644 (file)
@@ -102,7 +102,8 @@ public final class DiskCache {
                     chunkFile.seek(record.offset);
                     chunkFile.write(data);
                     synchronized (mIndexMap) {
-                        mIndexMap.put(key, new Record(currentChunk, record.offset, data.length, record.sizeOnDisk, System.currentTimeMillis()));
+                        mIndexMap.put(key, new Record(currentChunk, record.offset, data.length, record.sizeOnDisk, System
+                                .currentTimeMillis()));
                     }
                     return;
                 }
index 8e50567..a8627c1 100644 (file)
@@ -87,7 +87,7 @@ public final class DisplayItem {
         }
         mTargetPosition.add(mJitteredPosition);
         mStacktopPosition.set(position);
-    } 
+    }
 
     public int getStackIndex() {
         return mStackId;
@@ -116,7 +116,7 @@ public final class DisplayItem {
                 }
             } else {
                 texture = new UriTexture(mItemRef.mScreennailUri);
-                ((UriTexture)texture).setCacheId(Utils.Crc64Long(mItemRef.mFilePath));
+                ((UriTexture) texture).setCacheId(Utils.Crc64Long(mItemRef.mFilePath));
             }
             mScreennailImage = texture;
         }
@@ -144,9 +144,9 @@ public final class DisplayItem {
      * @return true if the display item is animating
      */
     public boolean isAnimating() {
-        return mAlive && (!mAnimatedPosition.equals(mTargetPosition) ||
-                mAnimatedTheta != mTargetTheta || mAnimatedImageTheta != mImageTheta ||
-                mAnimatedPlaceholderFade != 1f);
+        return mAlive
+                && (!mAnimatedPosition.equals(mTargetPosition) || mAnimatedTheta != mTargetTheta
+                        || mAnimatedImageTheta != mImageTheta || mAnimatedPlaceholderFade != 1f);
     }
 
     /**
index ca760d4..1d9f4a0 100644 (file)
@@ -44,6 +44,10 @@ public final class DisplaySlot {
         mTitle = null;
         mTitleImage = null;
         mLocationImage = null;
+        if (set.mReverseGeocodedLocation == null) {
+            set.mReverseGeocodedLocationRequestMade = false;
+            set.mReverseGeocodedLocationComputed = false;
+        }
     }
 
     public MediaSet getMediaSet() {
@@ -58,7 +62,8 @@ public final class DisplaySlot {
         }
     }
 
-    private StringTexture getTextureForString(String string, HashMap<String, StringTexture> textureTable, StringTexture.Config config) {
+    private StringTexture getTextureForString(String string, HashMap<String, StringTexture> textureTable,
+            StringTexture.Config config) {
         StringTexture texture = null;
         if (textureTable != null && textureTable.containsKey(string)) {
             texture = textureTable.get(string);
@@ -79,7 +84,8 @@ public final class DisplaySlot {
         StringTexture texture = mTitleImage;
         String title = mSetRef.mTruncTitleString;
         if (texture == null && title != null && !(title.equals(mTitle))) {
-            texture = getTextureForString(title, textureTable, ((mSetRef.mId != Shared.INVALID && mSetRef.mId != 0) ? CAPTION_STYLE : CLUSTER_STYLE));
+            texture = getTextureForString(title, textureTable, ((mSetRef.mId != Shared.INVALID && mSetRef.mId != 0) ? CAPTION_STYLE
+                    : CLUSTER_STYLE));
             mTitleImage = texture;
             mTitle = title;
         }
@@ -99,7 +105,7 @@ public final class DisplaySlot {
                 String geocodedLocation = mSetRef.mReverseGeocodedLocation;
                 if (geocodedLocation != null) {
                     mLocation = geocodedLocation;
-                    mLocationImage = getTextureForString(mLocation, textureTable, LOCATION_STYLE);                  
+                    mLocationImage = getTextureForString(mLocation, textureTable, LOCATION_STYLE);
                 }
             }
         }
index a99eccf..e6de41e 100644 (file)
@@ -12,14 +12,14 @@ public final class FloatAnim {
         mValue = value;
         mStartTime = 0;
     }
-    
+
     public boolean isAnimating() {
         return mStartTime != 0;
     }
-    
+
     public float getTimeRemaining(long currentTime) {
         float duration = (currentTime - mStartTime) * 0.001f;
-        if (mDuration > duration)  // CR: braces
+        if (mDuration > duration) // CR: braces
             return mDuration - duration;
         else
             return 0.0f;
@@ -51,11 +51,12 @@ public final class FloatAnim {
 
     private float getInterpolatedValue(long currentTime) {
         float ratio = (float) (currentTime - mStartTime) * 0.001f / mDuration;
-        if (ratio >= 1f) {  // CR: 1.0f
+        if (ratio >= 1f) { // CR: 1.0f
             mStartTime = 0;
             return mValue;
         } else {
-            ratio = 0.5f - 0.5f * FloatMath.cos(ratio * 3.14159265f);  // CR: (float)Math.PI
+            ratio = 0.5f - 0.5f * FloatMath.cos(ratio * 3.14159265f); // CR:
+                                                                      // (float)Math.PI
             return mValue + (1f - ratio) * mDelta;
         }
     }
index 51756a4..b61a765 100644 (file)
@@ -6,24 +6,33 @@ package com.cooliris.media;
 
 public class FloatUtils {
     private static final float ANIMATION_SPEED = 4.0f;
-    
+
     /**
      * This function animates a float value to another float value
-     * @param prevVal: The previous value (or the animated value)
-     * @param targetVal: The target value
-     * @param timeElapsed Time elapsed since the last time this function was called
-     * @return The new animated value that is closer to the target value and clamped to the target value
+     * 
+     * @param prevVal
+     *            : The previous value (or the animated value)
+     * @param targetVal
+     *            : The target value
+     * @param timeElapsed
+     *            Time elapsed since the last time this function was called
+     * @return The new animated value that is closer to the target value and
+     *         clamped to the target value
      */
     public static final float animate(float prevVal, float targetVal, float timeElapsed) {
         timeElapsed = timeElapsed * ANIMATION_SPEED;
         return animateAfterFactoringSpeed(prevVal, targetVal, timeElapsed);
     }
-    
+
     /**
      * This function animates a Tuple3f value to another Tuple3f value
-     * @param animVal: The animating Tuple
-     * @param targetVal: The target value for the Tuple
-     * @param timeElapsed: Time elapsed since the last time this function was called
+     * 
+     * @param animVal
+     *            : The animating Tuple
+     * @param targetVal
+     *            : The target value for the Tuple
+     * @param timeElapsed
+     *            : Time elapsed since the last time this function was called
      */
     public static final void animate(Vector3f animVal, Vector3f targetVal, float timeElapsed) {
         timeElapsed = timeElapsed * ANIMATION_SPEED;
@@ -31,24 +40,30 @@ public class FloatUtils {
         animVal.y = animateAfterFactoringSpeed(animVal.y, targetVal.y, timeElapsed);
         animVal.z = animateAfterFactoringSpeed(animVal.z, targetVal.z, timeElapsed);
     }
-    
+
     /**
      * Clamp a float to a lower bound
-     * @param val: the input float value
-     * @param minVal: the minimum value to use to clamp
+     * 
+     * @param val
+     *            : the input float value
+     * @param minVal
+     *            : the minimum value to use to clamp
      * @return the clamped value
      */
     public static final float clampMin(float val, float minVal) {
         if (val < minVal)
-            return minVal;  // CR: braces
+            return minVal; // CR: braces
         else
             return val;
     }
-    
+
     /**
      * Clamp a float to an upper bound
-     * @param val: the input float value
-     * @param maxVal: the maximum value to use to clamp
+     * 
+     * @param val
+     *            : the input float value
+     * @param maxVal
+     *            : the maximum value to use to clamp
      * @return the clamped value
      */
     public static final float clampMax(float val, float maxVal) {
@@ -57,13 +72,18 @@ public class FloatUtils {
         else
             return val;
     }
-    
-    // CR: these comments are barely useful. they mostly just fill space. If anything, a one-liner would be sufficient.
+
+    // CR: these comments are barely useful. they mostly just fill space. If
+    // anything, a one-liner would be sufficient.
     /**
      * Clamp a float to a lower and upper bound
-     * @param val: the input float value
-     * @param minVal: the minimum value to use to clamp
-     * @param maxVal: the maximum value to use to clamp
+     * 
+     * @param val
+     *            : the input float value
+     * @param minVal
+     *            : the minimum value to use to clamp
+     * @param maxVal
+     *            : the maximum value to use to clamp
      * @return the clamped value
      */
     public static final float clamp(float val, float minVal, float maxVal) {
@@ -74,12 +94,16 @@ public class FloatUtils {
         else
             return val;
     }
-    
+
     /**
      * Clamp an integer to a lower and upper bound
-     * @param val: the input float value
-     * @param minVal: the minimum value to use to clamp
-     * @param maxVal: the maximum value to use to clamp
+     * 
+     * @param val
+     *            : the input float value
+     * @param minVal
+     *            : the minimum value to use to clamp
+     * @param maxVal
+     *            : the maximum value to use to clamp
      * @return the clamped value
      */
     public static final int clamp(int val, int minVal, int maxVal) {
@@ -90,19 +114,26 @@ public class FloatUtils {
         else
             return val;
     }
-    
+
     /**
      * Function to check whether a point lies inside a rectangle
-     * @param left: the x coordinate of the left most point
-     * @param right: the x coordinate of the right most point
-     * @param top: the y coordinate of the top most point
-     * @param bottom: the y coordinate of the bottom most point
-     * @param posX: the input point's x coordinate
-     * @param posY: the input point's y coordinate
+     * 
+     * @param left
+     *            : the x coordinate of the left most point
+     * @param right
+     *            : the x coordinate of the right most point
+     * @param top
+     *            : the y coordinate of the top most point
+     * @param bottom
+     *            : the y coordinate of the bottom most point
+     * @param posX
+     *            : the input point's x coordinate
+     * @param posY
+     *            : the input point's y coordinate
      * @return true if point is inside the rectangle else return false
      */
     public static final boolean boundsContainsPoint(float left, float right, float top, float bottom, float posX, float posY) {
-      // CR: return ... (one statement).
+        // CR: return ... (one statement).
         if (posX < left || posX > right || posY < top || posY > bottom)
             return false;
         else
@@ -117,7 +148,8 @@ public class FloatUtils {
             return targetVal;
         if (newVal == prevVal) {
             return targetVal;
-        } else {  // } else if (...) { ... }; no need for a new level of indentation.
+        } else { // } else if (...) { ... }; no need for a new level of
+                 // indentation.
             if (prevVal > targetVal && newVal < targetVal) {
                 return targetVal;
             } else if (prevVal < targetVal && newVal > targetVal) {
index e0a5ab1..7543ebf 100644 (file)
@@ -28,365 +28,366 @@ import com.cooliris.wallpaper.RandomDataSource;
 import com.cooliris.wallpaper.Slideshow;
 
 public final class Gallery extends Activity {
-       public static final TimeZone CURRENT_TIME_ZONE = TimeZone.getDefault();
-       public static float PIXEL_DENSITY = 0.0f;
-       public static final int CROP_MSG_INTERNAL = 100;
+    public static final TimeZone CURRENT_TIME_ZONE = TimeZone.getDefault();
+    public static float PIXEL_DENSITY = 0.0f;
+    public static final int CROP_MSG_INTERNAL = 100;
 
-       private static final String TAG = "Gallery";
-       private static final int CROP_MSG = 10;
-       private RenderView mRenderView = null;
-       private GridLayer mGridLayer;
-       private final Handler mHandler = new Handler();
-       private ReverseGeocoder mReverseGeocoder;
-       private boolean mPause;
-       private MediaScannerConnection mConnection;
-       private WakeLock mWakeLock;
-       private HashMap<String, Boolean> mAccountsEnabled;
-       private static final boolean TEST_WALLPAPER = false;
+    private static final String TAG = "Gallery";
+    private static final int CROP_MSG = 10;
+    private RenderView mRenderView = null;
+    private GridLayer mGridLayer;
+    private final Handler mHandler = new Handler();
+    private ReverseGeocoder mReverseGeocoder;
+    private boolean mPause;
+    private MediaScannerConnection mConnection;
+    private WakeLock mWakeLock;
+    private HashMap<String, Boolean> mAccountsEnabled = new HashMap<String, Boolean>();
 
-       @Override
-       public void onCreate(Bundle savedInstanceState) {
-               super.onCreate(savedInstanceState);
-               final boolean imageManagerHasStorage = ImageManager.quickHasStorage();
-               if (TEST_WALLPAPER || (isViewIntent() && getIntent().getData().equals(Images.Media.EXTERNAL_CONTENT_URI))) {
-                       if (!imageManagerHasStorage) {
-                               Toast.makeText(this, getResources().getString(R.string.no_sd_card), Toast.LENGTH_LONG).show();
-                               finish();
-                       } else {
-                               PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
-                               mWakeLock = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "GridView.Slideshow.All");
-                               mWakeLock.acquire();
-                               Slideshow slideshow = new Slideshow(this);
-                               slideshow.setDataSource(new RandomDataSource());
-                               setContentView(slideshow);
-                       }
-                       return;
-               }
-               final boolean isCacheReady = CacheService.isCacheReady(false);
-               CacheService.startCache(this, false);
-               if (PIXEL_DENSITY == 0.0f) {
-                       DisplayMetrics metrics = new DisplayMetrics();
-                       getWindowManager().getDefaultDisplay().getMetrics(metrics);
-                       PIXEL_DENSITY = metrics.density;
-               }
-               mReverseGeocoder = new ReverseGeocoder(this);
-               mRenderView = new RenderView(this);
-               mGridLayer = new GridLayer(this, (int) (96.0f * PIXEL_DENSITY), (int) (72.0f * PIXEL_DENSITY), new GridLayoutInterface(4),
-                       mRenderView);
-               mRenderView.setRootLayer(mGridLayer);
-               setContentView(mRenderView);
-               
-               // Creating the DataSource objects.
-               final PicasaDataSource picasaDataSource = new PicasaDataSource(this);
-               final LocalDataSource localDataSource = new LocalDataSource(this);
-               final ConcatenatedDataSource combinedDataSource = new ConcatenatedDataSource(localDataSource, picasaDataSource);
-               
-               // Depending upon the intent, we assign the right dataSource.
-               if (!isPickIntent() && !isViewIntent()) {
-                       if (imageManagerHasStorage) {
-                               mGridLayer.setDataSource(combinedDataSource);
-                       } else {
-                               mGridLayer.setDataSource(picasaDataSource);
-                       }
-                       if (!imageManagerHasStorage) {
-                               Toast.makeText(this, getResources().getString(R.string.no_sd_card), Toast.LENGTH_LONG).show();
-                       } else if (!isCacheReady) {
-                               Toast.makeText(this, getResources().getString(R.string.loading_new), Toast.LENGTH_LONG).show();
-                       }
-               } else if (!isViewIntent()) {
-                       final Intent intent = getIntent();
-                       if (intent != null) {
-                               final String type = intent.resolveType(this);
-                               boolean includeImages = isImageType(type);
-                               boolean includeVideos = isVideoType(type);
-                               ((LocalDataSource) localDataSource).setMimeFilter(!includeImages, !includeVideos);
-                               if (includeImages) {
-                                       if (imageManagerHasStorage) {
-                                               mGridLayer.setDataSource(combinedDataSource);
-                                       } else {
-                                               mGridLayer.setDataSource(picasaDataSource);
-                                       }
-                               } else {
-                                       mGridLayer.setDataSource(localDataSource);
-                               }
-                               mGridLayer.setPickIntent(true);
-                               if (!imageManagerHasStorage) {
-                                       Toast.makeText(this, getResources().getString(R.string.no_sd_card), Toast.LENGTH_LONG).show();
-                               } else {
-                                       Toast.makeText(this, getResources().getString(R.string.pick_prompt), Toast.LENGTH_LONG).show();
-                               }
-                       }
-               } else {
-                       // View intent for images.
-                       Uri uri = getIntent().getData();
-                       boolean slideshow = getIntent().getBooleanExtra("slideshow", false);
-                       final SingleDataSource singleDataSource = new SingleDataSource(this, uri.toString(), slideshow);
-                       final ConcatenatedDataSource singleCombinedDataSource = new ConcatenatedDataSource(singleDataSource, picasaDataSource);
-                       mGridLayer.setDataSource(singleCombinedDataSource);
-                       mGridLayer.setViewIntent(true, Utils.getBucketNameFromUri(uri));
-                       if (singleDataSource.isSingleImage()) {
-                               mGridLayer.setSingleImage(false);
-                       } else if (slideshow) {
-                               mGridLayer.setSingleImage(true);
-                               mGridLayer.startSlideshow();
-                       }
-               }
-               // We record the set of enabled accounts for picasa.
-               mAccountsEnabled = PicasaDataSource.getAccountStatus(this);
-               Log.i(TAG, "onCreate");
-       }
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        final boolean imageManagerHasStorage = ImageManager.quickHasStorage();
+        if (isViewIntent() && getIntent().getData().equals(Images.Media.EXTERNAL_CONTENT_URI)
+                && getIntent().getExtras().getBoolean("slideshow", false)) {
+            if (!imageManagerHasStorage) {
+                Toast.makeText(this, getResources().getString(R.string.no_sd_card), Toast.LENGTH_LONG).show();
+                finish();
+            } else {
+                PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
+                mWakeLock = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "GridView.Slideshow.All");
+                mWakeLock.acquire();
+                Slideshow slideshow = new Slideshow(this);
+                slideshow.setDataSource(new RandomDataSource());
+                setContentView(slideshow);
+            }
+            return;
+        }
+        final boolean isCacheReady = CacheService.isCacheReady(false);
+        CacheService.startCache(this, false);
+        if (PIXEL_DENSITY == 0.0f) {
+            DisplayMetrics metrics = new DisplayMetrics();
+            getWindowManager().getDefaultDisplay().getMetrics(metrics);
+            PIXEL_DENSITY = metrics.density;
+        }
+        mReverseGeocoder = new ReverseGeocoder(this);
+        mRenderView = new RenderView(this);
+        mGridLayer = new GridLayer(this, (int) (96.0f * PIXEL_DENSITY), (int) (72.0f * PIXEL_DENSITY), new GridLayoutInterface(4),
+                mRenderView);
+        mRenderView.setRootLayer(mGridLayer);
+        setContentView(mRenderView);
 
-       public ReverseGeocoder getReverseGeocoder() {
-               return mReverseGeocoder;
-       }
+        // Creating the DataSource objects.
+        final PicasaDataSource picasaDataSource = new PicasaDataSource(this);
+        final LocalDataSource localDataSource = new LocalDataSource(this);
+        final ConcatenatedDataSource combinedDataSource = new ConcatenatedDataSource(localDataSource, picasaDataSource);
 
-       public Handler getHandler() {
-               return mHandler;
-       }
+        // Depending upon the intent, we assign the right dataSource.
+        if (!isPickIntent() && !isViewIntent()) {
+            if (imageManagerHasStorage) {
+                mGridLayer.setDataSource(combinedDataSource);
+            } else {
+                mGridLayer.setDataSource(picasaDataSource);
+            }
+            if (!imageManagerHasStorage) {
+                Toast.makeText(this, getResources().getString(R.string.no_sd_card), Toast.LENGTH_LONG).show();
+            } else if (!isCacheReady) {
+                Toast.makeText(this, getResources().getString(R.string.loading_new), Toast.LENGTH_LONG).show();
+            }
+        } else if (!isViewIntent()) {
+            final Intent intent = getIntent();
+            if (intent != null) {
+                final String type = intent.resolveType(this);
+                boolean includeImages = isImageType(type);
+                boolean includeVideos = isVideoType(type);
+                ((LocalDataSource) localDataSource).setMimeFilter(!includeImages, !includeVideos);
+                if (includeImages) {
+                    if (imageManagerHasStorage) {
+                        mGridLayer.setDataSource(combinedDataSource);
+                    } else {
+                        mGridLayer.setDataSource(picasaDataSource);
+                    }
+                } else {
+                    mGridLayer.setDataSource(localDataSource);
+                }
+                mGridLayer.setPickIntent(true);
+                if (!imageManagerHasStorage) {
+                    Toast.makeText(this, getResources().getString(R.string.no_sd_card), Toast.LENGTH_LONG).show();
+                } else {
+                    Toast.makeText(this, getResources().getString(R.string.pick_prompt), Toast.LENGTH_LONG).show();
+                }
+            }
+        } else {
+            // View intent for images.
+            Uri uri = getIntent().getData();
+            boolean slideshow = getIntent().getBooleanExtra("slideshow", false);
+            final SingleDataSource singleDataSource = new SingleDataSource(this, uri.toString(), slideshow);
+            final ConcatenatedDataSource singleCombinedDataSource = new ConcatenatedDataSource(singleDataSource, picasaDataSource);
+            mGridLayer.setDataSource(singleCombinedDataSource);
+            mGridLayer.setViewIntent(true, Utils.getBucketNameFromUri(uri));
+            if (singleDataSource.isSingleImage()) {
+                mGridLayer.setSingleImage(false);
+            } else if (slideshow) {
+                mGridLayer.setSingleImage(true);
+                mGridLayer.startSlideshow();
+            }
+        }
+        // We record the set of enabled accounts for picasa.
+        mAccountsEnabled = PicasaDataSource.getAccountStatus(this);
+        Log.i(TAG, "onCreate");
+    }
 
-       @Override
-       public void onRestart() {
-               super.onRestart();
-       }
+    public ReverseGeocoder getReverseGeocoder() {
+        return mReverseGeocoder;
+    }
 
-       @Override
-       public void onStart() {
-               super.onStart();
-       }
+    public Handler getHandler() {
+        return mHandler;
+    }
 
-       @Override
-       public void onResume() {
-               super.onResume();
-               if (mRenderView != null)
-                       mRenderView.onResume();
-               if (mPause) {
-                       // We check to see if the authenticated accounts have changed, and
-                       // if so, reload the datasource.
-                       HashMap<String, Boolean> accountsEnabled = PicasaDataSource.getAccountStatus(this);
-                       String[] keys = new String[accountsEnabled.size()];
-                       keys = accountsEnabled.keySet().toArray(keys);
-                       int numKeys = keys.length;
-                       for (int i = 0; i < numKeys; ++i) {
-                               String key = keys[i];
-                               boolean newValue = accountsEnabled.get(key).booleanValue();
-                               boolean oldValue = false;
-                               Boolean oldValObj = mAccountsEnabled.get(key);
-                               if (oldValObj != null) {
-                                       oldValue = oldValObj.booleanValue();
-                               }
-                               if (oldValue != newValue) {
-                                       // Reload the datasource.
-                                       mGridLayer.setDataSource(mGridLayer.getDataSource());
-                                       break;
-                               }
-                       }
-                       mAccountsEnabled = accountsEnabled;
-                       mPause = false;
-               }
-       }
+    @Override
+    public void onRestart() {
+        super.onRestart();
+    }
 
-       @Override
-       public void onPause() {
-               super.onPause();
-               if (mRenderView != null)
-                       mRenderView.onPause();
-               mPause = true;
-       }
+    @Override
+    public void onStart() {
+        super.onStart();
+    }
 
-       public boolean isPaused() {
-               return mPause;
-       }
+    @Override
+    public void onResume() {
+        super.onResume();
+        if (mRenderView != null)
+            mRenderView.onResume();
+        if (mPause) {
+            // We check to see if the authenticated accounts have changed, and
+            // if so, reload the datasource.
+            HashMap<String, Boolean> accountsEnabled = PicasaDataSource.getAccountStatus(this);
+            String[] keys = new String[accountsEnabled.size()];
+            keys = accountsEnabled.keySet().toArray(keys);
+            int numKeys = keys.length;
+            for (int i = 0; i < numKeys; ++i) {
+                String key = keys[i];
+                boolean newValue = accountsEnabled.get(key).booleanValue();
+                boolean oldValue = false;
+                Boolean oldValObj = mAccountsEnabled.get(key);
+                if (oldValObj != null) {
+                    oldValue = oldValObj.booleanValue();
+                }
+                if (oldValue != newValue) {
+                    // Reload the datasource.
+                    if (mGridLayer != null)
+                        mGridLayer.setDataSource(mGridLayer.getDataSource());
+                    break;
+                }
+            }
+            mAccountsEnabled = accountsEnabled;
+            mPause = false;
+        }
+    }
 
-       @Override
-       public void onStop() {
-               super.onStop();
-               if (mGridLayer != null)
-                       mGridLayer.stop();
-               if (mReverseGeocoder != null) {
-                       mReverseGeocoder.flushCache();
-               }
-               LocalDataSource.sThumbnailCache.flush();
-               LocalDataSource.sThumbnailCacheVideo.flush();
-               PicasaDataSource.sThumbnailCache.flush();
-               CacheService.startCache(this, true);
-       }
+    @Override
+    public void onPause() {
+        super.onPause();
+        if (mRenderView != null)
+            mRenderView.onPause();
+        mPause = true;
+    }
 
-       @Override
-       public void onDestroy() {
-               // Force GLThread to exit.
-               setContentView(R.layout.main);
-               if (mGridLayer != null) {
-                       DataSource dataSource = mGridLayer.getDataSource();
-                       if (dataSource != null) {
-                               dataSource.shutdown();
-                       }
-                       mGridLayer.shutdown();
-               }
-               if (mWakeLock != null) {
-                       if (mWakeLock.isHeld()) {
-                               mWakeLock.release();
-                       }
-                       mWakeLock = null;
-               }
-               if (mReverseGeocoder != null)
-                       mReverseGeocoder.shutdown();
-               if (mRenderView != null) {
-                       mRenderView.shutdown();
-                       mRenderView = null;
-               }
-               mGridLayer = null;
-               super.onDestroy();
-               Log.i(TAG, "onDestroy");
-       }
+    public boolean isPaused() {
+        return mPause;
+    }
 
-       @Override
-       public void onConfigurationChanged(Configuration newConfig) {
-               super.onConfigurationChanged(newConfig);
-               if (mGridLayer != null) {
-                       mGridLayer.markDirty(30);
-               }
-               if (mRenderView != null)
-                       mRenderView.requestRender();
-               Log.i(TAG, "onConfigurationChanged");
-       }
+    @Override
+    public void onStop() {
+        super.onStop();
+        if (mGridLayer != null)
+            mGridLayer.stop();
+        if (mReverseGeocoder != null) {
+            mReverseGeocoder.flushCache();
+        }
+        LocalDataSource.sThumbnailCache.flush();
+        LocalDataSource.sThumbnailCacheVideo.flush();
+        PicasaDataSource.sThumbnailCache.flush();
+        CacheService.startCache(this, true);
+    }
 
-       @Override
-       public boolean onKeyDown(int keyCode, KeyEvent event) {
-               if (mRenderView != null) {
-                       return mRenderView.onKeyDown(keyCode, event) || super.onKeyDown(keyCode, event);
-               } else {
-                       return super.onKeyDown(keyCode, event);
-               }
-       }
+    @Override
+    public void onDestroy() {
+        // Force GLThread to exit.
+        setContentView(R.layout.main);
+        if (mGridLayer != null) {
+            DataSource dataSource = mGridLayer.getDataSource();
+            if (dataSource != null) {
+                dataSource.shutdown();
+            }
+            mGridLayer.shutdown();
+        }
+        if (mWakeLock != null) {
+            if (mWakeLock.isHeld()) {
+                mWakeLock.release();
+            }
+            mWakeLock = null;
+        }
+        if (mReverseGeocoder != null)
+            mReverseGeocoder.shutdown();
+        if (mRenderView != null) {
+            mRenderView.shutdown();
+            mRenderView = null;
+        }
+        mGridLayer = null;
+        super.onDestroy();
+        Log.i(TAG, "onDestroy");
+    }
 
-       private boolean isPickIntent() {
-               String action = getIntent().getAction();
-               return (Intent.ACTION_PICK.equals(action) || Intent.ACTION_GET_CONTENT.equals(action));
-       }
+    @Override
+    public void onConfigurationChanged(Configuration newConfig) {
+        super.onConfigurationChanged(newConfig);
+        if (mGridLayer != null) {
+            mGridLayer.markDirty(30);
+        }
+        if (mRenderView != null)
+            mRenderView.requestRender();
+        Log.i(TAG, "onConfigurationChanged");
+    }
 
-       private boolean isViewIntent() {
-               String action = getIntent().getAction();
-               return Intent.ACTION_VIEW.equals(action);
-       }
+    @Override
+    public boolean onKeyDown(int keyCode, KeyEvent event) {
+        if (mRenderView != null) {
+            return mRenderView.onKeyDown(keyCode, event) || super.onKeyDown(keyCode, event);
+        } else {
+            return super.onKeyDown(keyCode, event);
+        }
+    }
 
-       private boolean isImageType(String type) {
-               return type.equals("vnd.android.cursor.dir/image") || type.equals("image/*");
-       }
+    private boolean isPickIntent() {
+        String action = getIntent().getAction();
+        return (Intent.ACTION_PICK.equals(action) || Intent.ACTION_GET_CONTENT.equals(action));
+    }
 
-       private boolean isVideoType(String type) {
-               return type.equals("vnd.android.cursor.dir/video") || type.equals("video/*");
-       }
+    private boolean isViewIntent() {
+        String action = getIntent().getAction();
+        return Intent.ACTION_VIEW.equals(action);
+    }
 
-       @Override
-       protected void onActivityResult(int requestCode, int resultCode, Intent data) {
-               switch (requestCode) {
-               case CROP_MSG: {
-                       if (resultCode == RESULT_OK) {
-                               setResult(resultCode, data);
-                               finish();
-                       }
-                       break;
-               }
-               case CROP_MSG_INTERNAL: {
-                       // We cropped an image, we must try to set the focus of the camera
-                       // to that image.
-                       if (resultCode == RESULT_OK) {
-                               String contentUri = data.getAction();
-                               if (mGridLayer != null) {
-                                       mGridLayer.focusItem(contentUri);
-                               }
-                       }
-                       break;
-               }
-               }
-       }
+    private boolean isImageType(String type) {
+        return type.equals("vnd.android.cursor.dir/image") || type.equals("image/*");
+    }
 
-       @Override
-       public void onLowMemory() {
-               if (mRenderView != null) {
-                       mRenderView.handleLowMemory();
-               }
-       }
+    private boolean isVideoType(String type) {
+        return type.equals("vnd.android.cursor.dir/video") || type.equals("video/*");
+    }
 
-       public void launchCropperOrFinish(final MediaItem item) {
-               final Bundle myExtras = getIntent().getExtras();
-               String cropValue = myExtras != null ? myExtras.getString("crop") : null;
-               final String contentUri = item.mContentUri;
-               if (cropValue != null) {
-                       Bundle newExtras = new Bundle();
-                       if (cropValue.equals("circle")) {
-                               newExtras.putString("circleCrop", "true");
-                       }
-                       Intent cropIntent = new Intent();
-                       cropIntent.setData(Uri.parse(contentUri));
-                       cropIntent.setClass(this, CropImage.class);
-                       cropIntent.putExtras(newExtras);
-                       // Pass through any extras that were passed in.
-                       cropIntent.putExtras(myExtras);
-                       startActivityForResult(cropIntent, CROP_MSG);
-               } else {
-                       if (contentUri.startsWith("http://")) {
-                               // This is a http uri, we must save it locally first and
-                               // generate a content uri from it.
-                               final ProgressDialog dialog = ProgressDialog.show(this, this.getResources().getString(R.string.initializing),
-                                       getResources().getString(R.string.running_face_detection), true, false);
-                               if (contentUri != null) {
-                                       MediaScannerConnection.MediaScannerConnectionClient client = new MediaScannerConnection.MediaScannerConnectionClient() {
-                                               public void onMediaScannerConnected() {
-                                                       if (mConnection != null) {
-                                                               try {
-                                                                       final String path = UriTexture.writeHttpDataInDirectory(Gallery.this, contentUri,
-                                                                               LocalDataSource.DOWNLOAD_BUCKET_NAME);
-                                                                       if (path != null) {
-                                                                               mConnection.scanFile(path, item.mMimeType);
-                                                                       } else {
-                                                                               shutdown("");
-                                                                       }
-                                                               } catch (Exception e) {
-                                                                       shutdown("");
-                                                               }
-                                                       }
-                                               }
+    @Override
+    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+        switch (requestCode) {
+        case CROP_MSG: {
+            if (resultCode == RESULT_OK) {
+                setResult(resultCode, data);
+                finish();
+            }
+            break;
+        }
+        case CROP_MSG_INTERNAL: {
+            // We cropped an image, we must try to set the focus of the camera
+            // to that image.
+            if (resultCode == RESULT_OK) {
+                String contentUri = data.getAction();
+                if (mGridLayer != null) {
+                    mGridLayer.focusItem(contentUri);
+                }
+            }
+            break;
+        }
+        }
+    }
 
-                                               public void onScanCompleted(String path, Uri uri) {
-                                                       shutdown(uri.toString());
-                                               }
+    @Override
+    public void onLowMemory() {
+        if (mRenderView != null) {
+            mRenderView.handleLowMemory();
+        }
+    }
 
-                                               public void shutdown(String uri) {
-                                                       dialog.dismiss();
-                                                       performReturn(myExtras, uri.toString());
-                                                       if (mConnection != null) {
-                                                               mConnection.disconnect();
-                                                       }
-                                               }
-                                       };
-                                       MediaScannerConnection connection = new MediaScannerConnection(Gallery.this, client);
-                                       connection.connect();
-                                       mConnection = connection;
-                               }
-                       } else {
-                               performReturn(myExtras, contentUri);
-                       }
-               }
-       }
+    public void launchCropperOrFinish(final MediaItem item) {
+        final Bundle myExtras = getIntent().getExtras();
+        String cropValue = myExtras != null ? myExtras.getString("crop") : null;
+        final String contentUri = item.mContentUri;
+        if (cropValue != null) {
+            Bundle newExtras = new Bundle();
+            if (cropValue.equals("circle")) {
+                newExtras.putString("circleCrop", "true");
+            }
+            Intent cropIntent = new Intent();
+            cropIntent.setData(Uri.parse(contentUri));
+            cropIntent.setClass(this, CropImage.class);
+            cropIntent.putExtras(newExtras);
+            // Pass through any extras that were passed in.
+            cropIntent.putExtras(myExtras);
+            startActivityForResult(cropIntent, CROP_MSG);
+        } else {
+            if (contentUri.startsWith("http://")) {
+                // This is a http uri, we must save it locally first and
+                // generate a content uri from it.
+                final ProgressDialog dialog = ProgressDialog.show(this, this.getResources().getString(R.string.initializing),
+                        getResources().getString(R.string.running_face_detection), true, false);
+                if (contentUri != null) {
+                    MediaScannerConnection.MediaScannerConnectionClient client = new MediaScannerConnection.MediaScannerConnectionClient() {
+                        public void onMediaScannerConnected() {
+                            if (mConnection != null) {
+                                try {
+                                    final String path = UriTexture.writeHttpDataInDirectory(Gallery.this, contentUri,
+                                            LocalDataSource.DOWNLOAD_BUCKET_NAME);
+                                    if (path != null) {
+                                        mConnection.scanFile(path, item.mMimeType);
+                                    } else {
+                                        shutdown("");
+                                    }
+                                } catch (Exception e) {
+                                    shutdown("");
+                                }
+                            }
+                        }
 
-       private void performReturn(Bundle myExtras, String contentUri) {
-               Intent result = new Intent(null, Uri.parse(contentUri));
-               if (myExtras != null && myExtras.getBoolean("return-data")) {
-                       // The size of a transaction should be below 100K.
-                       Bitmap bitmap = null;
-                       try {
-                               bitmap = UriTexture.createFromUri(this, contentUri, 1024, 1024, 0, null);
-                       } catch (IOException e) {
-                               ;
-                       } catch (URISyntaxException e) {
-                               ;
-                       }
-                       if (bitmap != null) {
-                               result.putExtra("data", bitmap);
-                       }
-               }
-               setResult(RESULT_OK, result);
-               finish();
-       }
+                        public void onScanCompleted(String path, Uri uri) {
+                            shutdown(uri.toString());
+                        }
+
+                        public void shutdown(String uri) {
+                            dialog.dismiss();
+                            performReturn(myExtras, uri.toString());
+                            if (mConnection != null) {
+                                mConnection.disconnect();
+                            }
+                        }
+                    };
+                    MediaScannerConnection connection = new MediaScannerConnection(Gallery.this, client);
+                    connection.connect();
+                    mConnection = connection;
+                }
+            } else {
+                performReturn(myExtras, contentUri);
+            }
+        }
+    }
+
+    private void performReturn(Bundle myExtras, String contentUri) {
+        Intent result = new Intent(null, Uri.parse(contentUri));
+        if (myExtras != null && myExtras.getBoolean("return-data")) {
+            // The size of a transaction should be below 100K.
+            Bitmap bitmap = null;
+            try {
+                bitmap = UriTexture.createFromUri(this, contentUri, 1024, 1024, 0, null);
+            } catch (IOException e) {
+                ;
+            } catch (URISyntaxException e) {
+                ;
+            }
+            if (bitmap != null) {
+                result.putExtra("data", bitmap);
+            }
+        }
+        setResult(RESULT_OK, result);
+        finish();
+    }
 }
index a0115dd..23562f9 100644 (file)
@@ -10,7 +10,7 @@ public final class GridCamera {
     public static final float EYE_Z = 8.0f; // Initial z distance.
     private static final float DEFAULT_PORTRAIT_ASPECT = 320.0f / 480.0f;
     private static final float DEFAULT_LANDSCAPE_ASPECT = 1.0f / DEFAULT_PORTRAIT_ASPECT;
-    
+
     public float mEyeX;
     public float mEyeY;
     public float mEyeZ;
@@ -20,7 +20,7 @@ public final class GridCamera {
     public float mUpX;
     public float mUpY;
     public float mUpZ;
-    
+
     // To tilt the wall.
     public float mEyeOffsetX;
     public float mEyeOffsetY;
@@ -28,10 +28,9 @@ public final class GridCamera {
     private float mEyeEdgeOffsetXAnim;
     private float mAmountExceeding;
 
-
     // Animation speed, 1.0f is normal speed.
     public float mConvergenceSpeed;
-    
+
     // Camera field of view and its relation to the grid item width.
     public float mFov;
     public float mScale;
@@ -53,12 +52,12 @@ public final class GridCamera {
     private float mEyeOffsetAnimX;
     private float mEyeOffsetAnimY;
     private float mTargetEyeX;
-    
+
     // Screen width and height.
     private int mWidthBy2;
     private int mHeightBy2;
     private float mTanFovBy2;
-    
+
     public GridCamera(int width, int height, int itemWidth, int itemHeight) {
         reset();
         viewportChanged(width, height, itemWidth, itemHeight);
@@ -108,7 +107,7 @@ public final class GridCamera {
         mHeight = h;
         mWidthBy2 = w >> 1;
         mHeightBy2 = h >> 1;
-        mAspectRatio = (h == 0) ? 1.0f : (float)w / (float)h;
+        mAspectRatio = (h == 0) ? 1.0f : (float) w / (float) h;
         mDefaultAspectRatio = (w > h) ? DEFAULT_LANDSCAPE_ASPECT : DEFAULT_PORTRAIT_ASPECT;
         mTanFovBy2 = (float) Math.tan(Math.toRadians(fov * 0.5f));
         mItemHeight = (int) itemHeight;
@@ -153,7 +152,8 @@ public final class GridCamera {
             // The width will hit the screen.
             h = (f * mHeight) / mWidth;
         }
-        // To fit ITEM_HEIGHT pixels perfectly, the targetZ value must be the 1.0f for the given fov
+        // To fit ITEM_HEIGHT pixels perfectly, the targetZ value must be the
+        // 1.0f for the given fov
         // Thus to fit h pixels,
         h = h / mItemHeight;
         float targetZ = h / mTanFovBy2;
@@ -191,7 +191,7 @@ public final class GridCamera {
         mPosY = mTargetPosY;
         mPosZ = mTargetPosZ;
     }
-    
+
     public void commitMoveInX() {
         mPosX = mTargetPosX;
     }
@@ -203,7 +203,7 @@ public final class GridCamera {
     public void commitMoveInZ() {
         mPosZ = mTargetPosZ;
     }
-    
+
     public boolean computeConstraints(boolean applyConstraints, boolean applyOverflowFeedback, Vector3f firstSlotPosition,
             Vector3f lastSlotPosition) {
         boolean retVal = false;
@@ -240,7 +240,8 @@ public final class GridCamera {
         }
         if (applyConstraints) {
             mEyeEdgeOffsetX = 0.0f;
-            // We look at amount exceeding and calculate target position in the reverse direction.
+            // We look at amount exceeding and calculate target position in the
+            // reverse direction.
             final float maxBounceBack = 0.8f;
             if (mAmountExceeding < -maxBounceBack)
                 mAmountExceeding = -maxBounceBack;
@@ -288,7 +289,7 @@ public final class GridCamera {
     public boolean isAnimating() {
         return (mPosX != mTargetPosX || mPosY != mTargetPosY || mPosZ != mTargetPosZ || mEyeOffsetAnimX != mEyeOffsetX || mEyeEdgeOffsetXAnim != mEyeEdgeOffsetX);
     }
-    
+
     public boolean isZAnimating() {
         return mPosZ != mTargetPosZ;
     }
@@ -309,8 +310,10 @@ public final class GridCamera {
         mTargetEyeX = EYE_X + mPosX;
         if (mEyeZ == EYE_Z) {
             mEyeX = mTargetEyeX;
-            // Enable the line below for achieving tilt while you scroll the wall.
-            // FloatUtils.animate(eyeX_, targetEyeX_, timeElapsedx - (timeElapsedx * 0.35f));
+            // Enable the line below for achieving tilt while you scroll the
+            // wall.
+            // FloatUtils.animate(eyeX_, targetEyeX_, timeElapsedx -
+            // (timeElapsedx * 0.35f));
         } else {
             mEyeX = mTargetEyeX;
         }
@@ -322,4 +325,3 @@ public final class GridCamera {
         mLookAtZ = mPosZ;
     }
 }
-
index b4eb1c2..96be5d5 100644 (file)
@@ -1,6 +1,5 @@
 package com.cooliris.media;
 
-
 public final class GridCameraManager {
     private final GridCamera mCamera;
     private static final Pool<Vector3f> sPool;
@@ -47,10 +46,11 @@ public final class GridCameraManager {
                         width = height;
                         height = temp;
                     }
-                    camera.moveTo(position.x, position.y, zoomin ? camera.getDistanceToFitRect(width * oneByZoom, height * oneByZoom) : 0);
+                    camera.moveTo(position.x, position.y, zoomin ? camera.getDistanceToFitRect(width * oneByZoom, height
+                            * oneByZoom) : 0);
                 } finally {
                     pool.delete(position);
-                    pool.delete(deltaAnchorPosition);        
+                    pool.delete(deltaAnchorPosition);
                 }
             } else {
                 camera.moveYTo(0);
@@ -59,7 +59,8 @@ public final class GridCameraManager {
         }
     }
 
-    // CR: line too long. Documentation--what are the semantics of the return value?
+    // CR: line too long. Documentation--what are the semantics of the return
+    // value?
     /**
      */
     public boolean constrainCameraForSlot(LayoutInterface layout, int slotIndex, Vector3f deltaAnchorPositionIn,
@@ -107,7 +108,7 @@ public final class GridCameraManager {
                     if (bottomExtent > 0) {
                         camera.moveBy(0, -bottomExtent, 0);
                     }
-                } 
+                }
             } finally {
                 pool.delete(position);
                 pool.delete(deltaAnchorPosition);
index 94c6627..fa88a88 100644 (file)
@@ -140,8 +140,7 @@ public final class GridDrawManager {
                     Texture texture = displayItem.getThumbnailImage(context, sThumbnailConfig);
                     if (texture != null && !texture.isLoaded() && numTexturesQueued <= 6) {
                         boolean isCached = texture.isCached();
-                        if (isCached)
-                            view.prime(texture, priority);
+                        view.prime(texture, priority);
                         view.bind(texture);
                         if (priority && isCached && texture.mState != Texture.STATE_ERROR)
                             ++numTexturesQueued;
@@ -386,7 +385,7 @@ public final class GridDrawManager {
     }
 
     public void drawBlendedComponents(RenderView view, GL11 gl, float alpha, int state, int hudMode, float stackMixRatio,
-            float gridMixRatio, MediaBucketList bucketList, boolean isFeedLoading) {
+            float gridMixRatio, MediaBucketList selectedBucketList, MediaBucketList markedBucketList, boolean isFeedLoading) {
         int firstBufferedVisibleSlot = mBufferedVisibleRange.begin;
         int lastBufferedVisibleSlot = mBufferedVisibleRange.end;
         int firstVisibleSlot = mVisibleRange.begin;
@@ -437,10 +436,11 @@ public final class GridDrawManager {
                         if (itemDrawn == null) {
                             continue;
                         }
-                        boolean displayItemPresentInSelectedItems = bucketList.find(itemDrawn.mItemRef);
+                        boolean displayItemPresentInSelectedItems = selectedBucketList.find(itemDrawn.mItemRef);
+                        boolean displayItemPresentInMarkedItems = markedBucketList.find(itemDrawn.mItemRef);
                         Texture previousTexture = (displayItemPresentInSelectedItems) ? texturePressed : texture;
                         Texture textureToUse = (itemDrawn.getHasFocus()) ? (currentFocusIsPressed ? texturePressed : textureFocus)
-                                : ((displayItemPresentInSelectedItems) ? texturePressed : textureGrid);
+                                : ((displayItemPresentInSelectedItems) ? texturePressed : (displayItemPresentInMarkedItems) ? texture : textureGrid);
                         float ratio = timeElapsedSinceGridView;
                         if (itemDrawn.mAlive) {
                             if (state != GridLayer.STATE_GRID_VIEW) {
@@ -509,6 +509,7 @@ public final class GridDrawManager {
                         DisplaySlot displaySlot = displaySlots[i - firstBufferedVisibleSlot];
                         StringTexture textureString = displaySlot.getLocationImage(reverseGeocoder, stringTextureTable);
                         if (textureString != null) {
+                            view.loadTexture(textureString);
                             drawDisplayItem(view, gl, displayItem, textureString, PASS_TEXT_LABEL, null, 0);
                         }
                     }
@@ -550,7 +551,8 @@ public final class GridDrawManager {
                                 Texture locationTexture = view.getResource(drawables
                                         .getIconForSet(displaySlot.getMediaSet(), false), false);
 
-                                // Draw the icon at 0.85 alpha over the top item in the stack.
+                                // Draw the icon at 0.85 alpha over the top item
+                                // in the stack.
                                 gl.glTranslatef(0.24f, 0.5f, 0);
                                 drawDisplayItem(view, gl, displayItem, locationTexture, PASS_MEDIASET_SOURCE_LABEL,
                                         transparentTexture, 0.85f);
@@ -573,7 +575,7 @@ public final class GridDrawManager {
                 for (int i = firstBufferedVisibleSlot; i <= lastBufferedVisibleSlot; ++i) {
                     DisplayItem displayItem = displayItems[(i - firstBufferedVisibleSlot) * GridLayer.MAX_ITEMS_PER_SLOT];
                     if (displayItem != null) {
-                        Texture textureToUse = bucketList.find(displayItem.mItemRef) ? textureSelectedOn : textureSelectedOff;
+                        Texture textureToUse = selectedBucketList.find(displayItem.mItemRef) ? textureSelectedOn : textureSelectedOff;
                         drawDisplayItem(view, gl, displayItem, textureToUse, PASS_SELECTION_LABEL, null, 0);
                     }
                 }
index edc1d08..4eec815 100644 (file)
@@ -78,7 +78,8 @@ public final class GridDrawables {
             sFullscreenGrid[2] = GridQuad.createGridQuad(width, height, 0, 0, 1.0f, oneByAspect, false);
             sFullscreenGrid[2].setDynamic(true);
 
-            // We create supplementary quads for the checkmarks, video overlay and location button
+            // We create supplementary quads for the checkmarks, video overlay
+            // and location button
             float sizeOfSelectedIcon = 32 * Gallery.PIXEL_DENSITY; // In pixels.
             sizeOfSelectedIcon /= itemHeight;
             float sizeOfLocationIcon = 52 * Gallery.PIXEL_DENSITY; // In pixels.
@@ -166,7 +167,8 @@ public final class GridDrawables {
     }
 
     public int getIconForSet(MediaSet set, boolean scaled) {
-        // We return the scaled version for HUD rendering and the unscaled version for 3D rendering.
+        // We return the scaled version for HUD rendering and the unscaled
+        // version for 3D rendering.
         if (scaled) {
             if (set == null) {
                 return R.drawable.icon_folder_small;
index 12b7032..62bd1d3 100644 (file)
@@ -9,667 +9,667 @@ import android.view.KeyEvent;
 import android.view.MotionEvent;
 
 public final class GridInputProcessor implements GestureDetector.OnGestureListener, GestureDetector.OnDoubleTapListener {
-       private int mCurrentFocusSlot;
-       private boolean mCurrentFocusIsPressed;
-       private int mCurrentSelectedSlot;
-
-       private float mPrevTiltValueLowPass;
-       private float mPrevShakeValueHighPass;
-       private float mShakeValue;
-       private int mTouchPosX;
-       private int mTouchPosY;
-       private int mActionCode;
-       private long mPrevTouchTime;
-       private float mFirstTouchPosX;
-       private float mFirstTouchPosY;
-       private float mPrevTouchPosX;
-       private float mPrevTouchPosY;
-       private float mTouchVelX;
-       private float mTouchVelY;
-       private boolean mProcessTouch;
-       private boolean mTouchMoved;
-       private float mDpadIgnoreTime = 0.0f;
-       private GridCamera mCamera;
-       private GridLayer mLayer;
-       private Context mContext;
-       private Pool<Vector3f> mPool;
-       private DisplayItem[] mDisplayItems;
-       private boolean mPrevHitEdge;
-       private boolean mTouchFeedbackDelivered;
-       private GestureDetector mGestureDetector;
-
-       public GridInputProcessor(Context context, GridCamera camera, GridLayer layer, RenderView view, Pool<Vector3f> pool,
-               DisplayItem[] displayItems) {
-               mPool = pool;
-               mCamera = camera;
-               mLayer = layer;
-               mCurrentFocusSlot = Shared.INVALID;
-               mCurrentSelectedSlot = Shared.INVALID;
-               mContext = context;
-               mDisplayItems = displayItems;
-               mGestureDetector = new GestureDetector(context, this);
-               mGestureDetector.setIsLongpressEnabled(true);
-       }
-
-       public int getCurrentFocusSlot() {
-               return mCurrentFocusSlot;
-       }
-
-       public int getCurrentSelectedSlot() {
-               return mCurrentSelectedSlot;
-       }
-
-       public void setCurrentSelectedSlot(int slot) {
-               mCurrentSelectedSlot = slot;
-               GridLayer layer = mLayer;
-               layer.setState(GridLayer.STATE_FULL_SCREEN);
-               mCamera.mConvergenceSpeed = 2.0f;
-               DisplayItem displayItem = layer.getDisplayItemForSlotId(slot);
-               MediaItem item = null;
-               if (displayItem != null)
-                       item = displayItem.mItemRef;
-               layer.getHud().fullscreenSelectionChanged(item, mCurrentSelectedSlot + 1, layer.getCompleteRange().end + 1);
-       }
-
-       public void onSensorChanged(RenderView view, SensorEvent event, int state) {
-               switch (event.sensor.getType()) {
-               case Sensor.TYPE_ACCELEROMETER:
-               case Sensor.TYPE_ORIENTATION:
-                       float[] values = event.values;
-                       float valueToUse = (mCamera.mWidth < mCamera.mHeight) ? values[0] : -values[1];
-                       float tiltValue = 0.8f * mPrevTiltValueLowPass + 0.2f * valueToUse;
-                       if (Math.abs(tiltValue) < 0.5f)
-                               tiltValue = 0.0f;
-                       if (state == GridLayer.STATE_FULL_SCREEN)
-                               tiltValue = 0.0f;
-                       if (tiltValue != 0.0f)
-                               view.requestRender();
-                       mCamera.mEyeOffsetX = -3.0f * tiltValue;
-                       float shakeValue = values[1] * values[1] + values[2] * values[2];
-                       mShakeValue = shakeValue - mPrevShakeValueHighPass;
-                       mPrevShakeValueHighPass = shakeValue;
-                       if (mShakeValue < 16.0f) {
-                               mShakeValue = 0;
-                       } else {
-                               mShakeValue = mShakeValue * 4.0f;
-                               if (mShakeValue > 200) {
-                                       mShakeValue = 200;
-                               }
-                       }
-                       break;
-               }
-       }
-
-       public boolean onTouchEvent(MotionEvent event) {
-               mTouchPosX = (int) (event.getX());
-               mTouchPosY = (int) (event.getY());
-               mActionCode = event.getAction();
-               long timestamp = SystemClock.elapsedRealtime();
-               long delta = timestamp - mPrevTouchTime;
-               mPrevTouchTime = timestamp;
-               float timeElapsed = (float) delta;
-               timeElapsed = timeElapsed * 0.001f; // division by 1000 for seconds
-               switch (mActionCode) {
-               case MotionEvent.ACTION_UP:
-                       if (mProcessTouch == false) {
-                               touchBegan(mTouchPosX, mTouchPosY);
-                       }
-                       touchEnded(mTouchPosX, mTouchPosY, timeElapsed);
-                       break;
-               case MotionEvent.ACTION_DOWN:
-                       mPrevTouchTime = timestamp;
-                       touchBegan(mTouchPosX, mTouchPosY);
-                       break;
-               case MotionEvent.ACTION_MOVE:
-                       touchMoved(mTouchPosX, mTouchPosY, timeElapsed);
-                       break;
-               }
-               mGestureDetector.onTouchEvent(event);
-               return true;
-       }
-
-       public boolean onKeyDown(int keyCode, KeyEvent event, int state) {
-               GridLayer layer = mLayer;
-               if (keyCode == KeyEvent.KEYCODE_BACK) {
-                       if (layer.getViewIntent())
-                               return false;
-                       if (layer.getHud().getMode() == HudLayer.MODE_SELECT) {
-                               layer.deselectAll();
-                               return true;
-                       }
-                       if (layer.inSlideShowMode()) {
-                               layer.endSlideshow();
-                               layer.getHud().setAlpha(1.0f);
-                               return true;
-                       }
-                       float zoomValue = layer.getZoomValue();
-                       if (zoomValue != 1.0f) {
-                               layer.setZoomValue(1.0f);
-                               layer.centerCameraForSlot(mCurrentSelectedSlot, 1.0f);
-                               return true;
-                       }
-                       layer.goBack();
-                       if (state == GridLayer.STATE_MEDIA_SETS)
-                               return false;
-                       return true;
-               }
-               if (mDpadIgnoreTime < 0.1f)
-                       return true;
-               mDpadIgnoreTime = 0.0f;
-               IndexRange bufferedVisibleRange = layer.getBufferedVisibleRange();
-               int firstBufferedVisibleSlot = bufferedVisibleRange.begin;
-               int lastBufferedVisibleSlot = bufferedVisibleRange.end;
-               int anchorSlot = layer.getAnchorSlotIndex(GridLayer.ANCHOR_CENTER);
-               if (state == GridLayer.STATE_FULL_SCREEN) {
-                       if (keyCode != KeyEvent.KEYCODE_VOLUME_UP && keyCode != KeyEvent.KEYCODE_VOLUME_DOWN
-                               && keyCode != KeyEvent.KEYCODE_MUTE && keyCode != KeyEvent.KEYCODE_HEADSETHOOK
-                               && keyCode != KeyEvent.KEYCODE_NOTIFICATION) {
-                               layer.endSlideshow();
-                       }
-                       boolean needsVibrate = false;
-                       if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT) {
-                               needsVibrate = !layer.changeFocusToNextSlot(1.0f);
-                       }
-                       if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT) {
-                               needsVibrate = !layer.changeFocusToPreviousSlot(1.0f);
-                       }
-                       if (needsVibrate) {
-                               vibrateShort();
-                       }
-                       if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER && !mCamera.isAnimating()) {
-                               if (layer.getZoomValue() == 1.0f)
-                                       layer.zoomInToSelectedItem();
-                               else
-                                       layer.setZoomValue(1.0f);
-                       }
-                       if (keyCode == KeyEvent.KEYCODE_MENU) {
-                               if (mLayer.getFeed() != null && mLayer.getFeed().isSingleImageMode()) {
-                                       return true;
-                               }
-                               if (layer.getHud().getMode() == HudLayer.MODE_NORMAL)
-                                       layer.enterSelectionMode();
-                               else
-                                       layer.deselectAll();
-                       }
-               } else {
-                       mCurrentFocusIsPressed = false;
-                       int numRows = ((GridLayoutInterface) layer.getLayoutInterface()).mNumRows;
-                       if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER && mCurrentFocusSlot != Shared.INVALID) {
-                               if (layer.getHud().getMode() != HudLayer.MODE_SELECT) {
-                                       boolean centerCamera = layer.tapGesture(mCurrentFocusSlot, false);
-                                       if (centerCamera) {
-                                               int slotId = mCurrentFocusSlot;
-                                               selectSlot(slotId);
-                                       }
-                                       mCurrentFocusSlot = Shared.INVALID;
-                                       return true;
-                               } else {
-                                       layer.addSlotToSelectedItems(mCurrentFocusSlot, true, true);
-                               }
-                               mCurrentFocusIsPressed = true;
-                       } else if (keyCode == KeyEvent.KEYCODE_MENU && mCurrentFocusSlot != Shared.INVALID) {
-                               if (layer.getHud().getMode() == HudLayer.MODE_NORMAL)
-                                       layer.enterSelectionMode();
-                               else
-                                       layer.deselectAll();
-                       } else if (mCurrentFocusSlot == Shared.INVALID) {
-                               mCurrentFocusSlot = anchorSlot;
-                       } else if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT) {
-                               mCurrentFocusSlot += numRows;
-                       } else if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT) {
-                               mCurrentFocusSlot -= numRows;
-                       } else if (keyCode == KeyEvent.KEYCODE_DPAD_UP) {
-                               --mCurrentFocusSlot;
-                       } else if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN) {
-                               ++mCurrentFocusSlot;
-                       }
-                       if (mCurrentFocusSlot > lastBufferedVisibleSlot) {
-                               mCurrentFocusSlot = lastBufferedVisibleSlot;
-                       }
-                       if (mCurrentFocusSlot < firstBufferedVisibleSlot)
-                               mCurrentFocusSlot = firstBufferedVisibleSlot;
-                       if (mCurrentFocusSlot != Shared.INVALID) {
-                               layer.centerCameraForSlot(mCurrentFocusSlot, 1.0f);
-                       }
-               }
-               return false;
-       }
-
-       private void touchBegan(int posX, int posY) {
-               mPrevTouchPosX = posX;
-               mPrevTouchPosY = posY;
-               mFirstTouchPosX = posX;
-               mFirstTouchPosY = posY;
-               mTouchVelX = 0;
-               mTouchVelY = 0;
-               mProcessTouch = true;
-               mTouchMoved = false;
-               mCamera.stopMovementInX();
-               GridLayer layer = mLayer;
-               mCurrentFocusSlot = layer.getSlotIndexForScreenPosition(posX, posY);
-               mCurrentFocusIsPressed = true;
-               mTouchFeedbackDelivered = false;
-               HudLayer hud = layer.getHud();
-               if (hud.getMode() == HudLayer.MODE_SELECT)
-                       hud.closeSelectionMenu();
-               if (layer.getState() == GridLayer.STATE_FULL_SCREEN && hud.getMode() == HudLayer.MODE_SELECT) {
-                       layer.deselectAll();
-                       hud.setAlpha(1.0f);
-               }
-               int slotId = layer.getSlotIndexForScreenPosition(posX, posY);
-               if (slotId != Shared.INVALID && layer.getState() != GridLayer.STATE_FULL_SCREEN) {
-                       vibrateShort();
-               }
-       }
-
-       private void touchMoved(int posX, int posY, float timeElapsedx) {
-               if (mProcessTouch) {
-                       GridLayer layer = mLayer;
-                       GridCamera camera = mCamera;
-                       float deltaX = -(posX - mPrevTouchPosX); // negation since the wall
-                       // moves in a direction
-                       // opposite to that of
-                       // the touch
-                       float deltaY = -(posY - mPrevTouchPosY);
-                       if (Math.abs(deltaX) >= 10.0f || Math.abs(deltaY) >= 10.0f) {
-                               mTouchMoved = true;
-                       }
-                       Pool<Vector3f> pool = mPool;
-                       Vector3f firstPosition = pool.create();
-                       Vector3f lastPosition = pool.create();
-                       Vector3f deltaAnchorPosition = pool.create();
-                       Vector3f worldPosDelta = pool.create();
-                       try {
-                               deltaAnchorPosition.set(layer.getDeltaAnchorPosition());
-                               LayoutInterface layout = layer.getLayoutInterface();
-                               GridCameraManager.getSlotPositionForSlotIndex(0, camera, layout, deltaAnchorPosition, firstPosition);
-                               int lastSlotIndex = 0;
-                               IndexRange completeRange = layer.getCompleteRange();
-                               synchronized (completeRange) {
-                                       lastSlotIndex = completeRange.end;
-                               }
-                               GridCameraManager.getSlotPositionForSlotIndex(lastSlotIndex, camera, layout, deltaAnchorPosition, lastPosition);
-
-                               camera.convertToRelativeCameraSpace(deltaX, deltaY, 0, worldPosDelta);
-                               deltaX = worldPosDelta.x;
-                               deltaY = worldPosDelta.y;
-                               camera.moveBy(deltaX, (layer.getZoomValue() == 1.0f) ? 0 : deltaY, 0);
-                               deltaX *= camera.mScale;
-                               deltaY *= camera.mScale;
-                       } finally {
-                               pool.delete(firstPosition);
-                               pool.delete(lastPosition);
-                               pool.delete(deltaAnchorPosition);
-                               pool.delete(worldPosDelta);
-                       }
-                       if (layer.getZoomValue() == 1.0f) {
-                               if (camera
-                                       .computeConstraints(false, (layer.getState() != GridLayer.STATE_FULL_SCREEN), firstPosition, lastPosition)) {
-                                       deltaX = 0.0f;
-                                       // vibrate
-                                       if (!mTouchFeedbackDelivered) {
-                                               mTouchFeedbackDelivered = true;
-                                               vibrateLong();
-                                       }
-                               }
-                       }
-                       mTouchVelX = deltaX * timeElapsedx;
-                       mTouchVelY = deltaY * timeElapsedx;
-                       float maxVelXx = (mCamera.mWidth * 0.5f);
-                       float maxVelYx = (mCamera.mHeight);
-                       mTouchVelX = FloatUtils.clamp(mTouchVelX, -maxVelXx, maxVelXx);
-                       mTouchVelY = FloatUtils.clamp(mTouchVelY, -maxVelYx, maxVelYx);
-                       mPrevTouchPosX = posX;
-                       mPrevTouchPosY = posY;
-                       // you want the movement to track the finger immediately
-                       if (mTouchMoved == false)
-                               mCurrentFocusSlot = layer.getSlotIndexForScreenPosition(posX, posY);
-                       else
-                               mCurrentFocusSlot = Shared.INVALID;
-                       if (!mCamera.isZAnimating()) {
-                               mCamera.commitMoveInX();
-                               mCamera.commitMoveInY();
-                       }
-                       int anchorSlotIndex = layer.getAnchorSlotIndex(GridLayer.ANCHOR_LEFT);
-                       DisplayItem[] displayItems = mDisplayItems;
-                       IndexRange bufferedVisibleRange = layer.getBufferedVisibleRange();
-                       int firstBufferedVisibleSlot = bufferedVisibleRange.begin;
-                       int lastBufferedVisibleSlot = bufferedVisibleRange.end;
-                       synchronized (displayItems) {
-                               if (anchorSlotIndex >= firstBufferedVisibleSlot && anchorSlotIndex <= lastBufferedVisibleSlot) {
-                                       DisplayItem item = displayItems[(anchorSlotIndex - firstBufferedVisibleSlot) * GridLayer.MAX_ITEMS_PER_SLOT];
-                                       if (item != null) {
-                                               layer.getHud().setTimeBarTime(item.mItemRef.mDateTakenInMs);
-                                       }
-                               }
-                       }
-               }
-       }
-
-       private void touchEnded(int posX, int posY, float timeElapsedx) {
-               if (mProcessTouch == false)
-                       return;
-               int maxPixelsBeforeSwitch = mCamera.mWidth / 8;
-               mCamera.mConvergenceSpeed = 2.0f;
-               GridLayer layer = mLayer;
-               if (layer.getExpandedSlot() == Shared.INVALID && !layer.feedAboutToChange()) {
-                       if (mCurrentSelectedSlot != Shared.INVALID) {
-                               if (layer.getState() == GridLayer.STATE_FULL_SCREEN) {
-                                       if (!mTouchMoved) {
-                                               // tap gesture for fullscreen
-                                               if (layer.getZoomValue() == 1.0f)
-                                                       layer.changeFocusToSlot(mCurrentSelectedSlot, 1.0f);
-                                       } else if (layer.getZoomValue() == 1.0f) {
-                                               // we want to snap to a new slotIndex based on where the
-                                               // current position is
-                                               if (layer.inSlideShowMode()) {
-                                                       layer.endSlideshow();
-                                               }
-                                               float deltaX = posX - mFirstTouchPosX;
-                                               float deltaY = posY - mFirstTouchPosY;
-                                               if (deltaY != 0) {
-                                                       // it has moved vertically
-                                               }
-                                               layer.changeFocusToSlot(mCurrentSelectedSlot, 1.0f);
-                                               HudLayer hud = layer.getHud();
-                                               if (deltaX > maxPixelsBeforeSwitch && hud.getMode() != HudLayer.MODE_SELECT) {
-                                                       layer.changeFocusToPreviousSlot(1.0f);
-                                               } else if (deltaX < -maxPixelsBeforeSwitch && hud.getMode() != HudLayer.MODE_SELECT) {
-                                                       layer.changeFocusToNextSlot(1.0f);
-                                               }
-                                       } else {
-                                               // in zoomed state
-                                               // we do nothing for now, but we should clamp to the
-                                               // image bounds
-                                               boolean hitEdge = layer.constrainCameraForSlot(mCurrentSelectedSlot);
-                                               // mPrevHitEdge = false;
-                                               if (hitEdge && mPrevHitEdge) {
-                                                       float deltaX = posX - mFirstTouchPosX;
-                                                       float deltaY = posY - mFirstTouchPosY;
-                                                       maxPixelsBeforeSwitch *= 4;
-                                                       if (deltaY != 0) {
-                                                               // it has moved vertically
-                                                       }
-                                                       mPrevHitEdge = false;
-                                                       HudLayer hud = layer.getHud();
-                                                       if (deltaX > maxPixelsBeforeSwitch && hud.getMode() != HudLayer.MODE_SELECT) {
-                                                               layer.changeFocusToPreviousSlot(1.0f);
-                                                       } else if (deltaX < -maxPixelsBeforeSwitch && hud.getMode() != HudLayer.MODE_SELECT) {
-                                                               layer.changeFocusToNextSlot(1.0f);
-                                                       } else {
-                                                               mPrevHitEdge = hitEdge;
-                                                       }
-                                               } else {
-                                                       mPrevHitEdge = hitEdge;
-                                               }
-                                       }
-                               }
-                       } else {
-                               if (!layer.feedAboutToChange() && layer.getZoomValue() == 1.0f) {
-                                       constrainCamera(true);
-                               }
-                       }
-               }
-               mCurrentFocusSlot = Shared.INVALID;
-               mCurrentFocusIsPressed = false;
-               mPrevTouchPosX = posX;
-               mPrevTouchPosY = posY;
-               mProcessTouch = false;
-       }
-
-       private void constrainCamera(boolean b) {
-               Pool<Vector3f> pool = mPool;
-               GridLayer layer = mLayer;
-               Vector3f firstPosition = pool.create();
-               Vector3f lastPosition = pool.create();
-               Vector3f deltaAnchorPosition = pool.create();
-               try {
-                       deltaAnchorPosition.set(layer.getDeltaAnchorPosition());
-                       GridCamera camera = mCamera;
-                       LayoutInterface layout = layer.getLayoutInterface();
-                       GridCameraManager.getSlotPositionForSlotIndex(0, camera, layout, deltaAnchorPosition, firstPosition);
-                       int lastSlotIndex = 0;
-                       IndexRange completeRange = layer.getCompleteRange();
-                       synchronized (completeRange) {
-                               lastSlotIndex = completeRange.end;
-                       }
-                       GridCameraManager.getSlotPositionForSlotIndex(lastSlotIndex, camera, layout, deltaAnchorPosition, lastPosition);
-                       camera.computeConstraints(true, (layer.getState() != GridLayer.STATE_FULL_SCREEN), firstPosition, lastPosition);
-               } finally {
-                       pool.delete(firstPosition);
-                       pool.delete(lastPosition);
-                       pool.delete(deltaAnchorPosition);
-               }
-       }
-
-       public void clearSelection() {
-               mCurrentSelectedSlot = Shared.INVALID;
-       }
-
-       public void clearFocus() {
-               mCurrentFocusSlot = Shared.INVALID;
-       }
-
-       public boolean isFocusItemPressed() {
-               return mCurrentFocusIsPressed;
-       }
-
-       public void update(float timeElapsed) {
-               mDpadIgnoreTime += timeElapsed;
-       }
-
-       public void setCurrentFocusSlot(int slotId) {
-               mCurrentSelectedSlot = slotId;
-       }
-
-       public boolean onDown(MotionEvent e) {
-               // TODO Auto-generated method stub
-               return true;
-       }
-
-       public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
-               if (mCurrentSelectedSlot == Shared.INVALID) {
-                       mCamera.moveYTo(0);
-                       mCamera.moveZTo(0);
-                       mCamera.mConvergenceSpeed = 1.0f;
-                       float normalizedVelocity = velocityX * mCamera.mOneByScale;
-                       // mCamera.moveBy(-velocityX * mCamera.mOneByScale * 0.25f, 0, 0);
-                       // constrainCamera(true);
-                       IndexRange visibleRange = mLayer.getVisibleRange();
-                       int numVisibleSlots = visibleRange.end - visibleRange.begin;
-                       if (numVisibleSlots > 0) {
-                               float fastFlingVelocity = 20.0f;
-                               int slotsToSkip = (int) (numVisibleSlots * (-normalizedVelocity / fastFlingVelocity));
-                               int maxSlots = numVisibleSlots;
-                               if (slotsToSkip > maxSlots)
-                                       slotsToSkip = maxSlots;
-                               if (slotsToSkip < -maxSlots)
-                                       slotsToSkip = -maxSlots;
-                               if (Math.abs(slotsToSkip) <= 1) {
-                                       if (velocityX > 0)
-                                               slotsToSkip = -2;
-                                       else if (velocityX < 0)
-                                               slotsToSkip = 2;
-                               }
-                               int slotToGetTo = mLayer.getAnchorSlotIndex(GridLayer.ANCHOR_CENTER) + slotsToSkip;
-                               if (slotToGetTo < 0)
-                                       slotToGetTo = 0;
-                               int lastSlot = mLayer.getCompleteRange().end;
-                               if (slotToGetTo > lastSlot)
-                                       slotToGetTo = lastSlot;
-                               mLayer.centerCameraForSlot(slotToGetTo, 1.0f);
-                       }
-                       constrainCamera(true);
-                       return true;
-               } else {
-                       return false;
-               }
-       }
-
-       public void onLongPress(MotionEvent e) {
-               if (mLayer.getFeed() != null && mLayer.getFeed().isSingleImageMode()) {
-                       HudLayer hud = mLayer.getHud();
-                       hud.getPathBar().setHidden(true);
-                       hud.getMenuBar().setHidden(true);
-                       if (hud.getMode() != HudLayer.MODE_NORMAL)
-                               hud.setMode(HudLayer.MODE_NORMAL);
-               }
-               if (mCurrentFocusSlot != Shared.INVALID) {
-                       vibrateLong();
-                       GridLayer layer = mLayer;
-                       if (layer.getState() == GridLayer.STATE_FULL_SCREEN) {
-                               layer.deselectAll();
-                       }
-                       HudLayer hud = layer.getHud();
-                       hud.enterSelectionMode();
-                       layer.addSlotToSelectedItems(mCurrentFocusSlot, true, true);
-               }
-       }
-
-       public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
-               // TODO Auto-generated method stub
-               return false;
-       }
-
-       public void onShowPress(MotionEvent e) {
-               // TODO Auto-generated method stub
-
-       }
-
-       public boolean onSingleTapUp(MotionEvent e) {
-               GridLayer layer = mLayer;
-               int posX = (int) e.getX();
-               int posY = (int) e.getY();
-               if (mCurrentSelectedSlot != Shared.INVALID) {
-                       // Fullscreen mode.
-                       mCamera.mConvergenceSpeed = 2.0f;
-                       int slotId = mCurrentSelectedSlot;
-                       if (layer.getZoomValue() == 1.0f) {
-                               layer.centerCameraForSlot(slotId, 1.0f);
-                       } else {
-                               layer.constrainCameraForSlot(slotId);
-                       }
-                       DisplayItem displayItem = layer.getDisplayItemForSlotId(slotId);
-                       if (displayItem != null) {
-                               final MediaItem item = displayItem.mItemRef;
-                               int heightBy2 = mCamera.mHeight / 2;
-                               boolean posYInBounds = (Math.abs(posY - heightBy2) < 64);
-                               if (posX < 32 && posYInBounds) {
-                                       layer.changeFocusToPreviousSlot(1.0f);
-                               } else if (posX > mCamera.mWidth - 32 && posYInBounds) {
-                                       layer.changeFocusToNextSlot(1.0f);
-                               } else if (item.getMediaType() == MediaItem.MEDIA_TYPE_VIDEO) {
-                                       Utils.playVideo(mContext, item);
-                               } else {
-                                       // We stop any slideshow.
-                                       HudLayer hud = layer.getHud();
-                                       if (layer.inSlideShowMode()) {
-                                               layer.endSlideshow();
-                                       } else {
-                                               hud.setAlpha(1.0f - hud.getAlpha());
-                                       }
-                                       if (hud.getMode() == HudLayer.MODE_SELECT) {
-                                               hud.setAlpha(1.0f);
-                                       }
-                               }
-                       }
-               } else {
-                       int slotId = layer.getSlotIndexForScreenPosition(posX, posY);
-                       if (slotId != Shared.INVALID) {
-                               HudLayer hud = layer.getHud();
-                               if (hud.getMode() == HudLayer.MODE_SELECT) {
-                                       layer.addSlotToSelectedItems(slotId, true, true);
-                               } else {
-                                       boolean centerCamera = (mCurrentSelectedSlot == Shared.INVALID) ? layer.tapGesture(slotId, false) : true;
-                                       if (centerCamera) {
-                                               // We check if this item is a video or not.
-                                               selectSlot(slotId);
-                                       }
-                               }
-                       } else {
-                               int state = layer.getState();
-                               if (state != GridLayer.STATE_FULL_SCREEN && state != GridLayer.STATE_GRID_VIEW
-                                       && layer.getHud().getMode() != HudLayer.MODE_SELECT) {
-                                       slotId = layer.getMetadataSlotIndexForScreenPosition(posX, posY);
-                                       if (slotId != Shared.INVALID) {
-                                               layer.tapGesture(slotId, true);
-                                       }
-                               }
-                       }
-               }
-               return true;
-       }
-
-       private void selectSlot(int slotId) {
-               GridLayer layer = mLayer;
-               if (layer.getState() == GridLayer.STATE_GRID_VIEW) {
-                       DisplayItem displayItem = layer.getDisplayItemForSlotId(slotId);
-                       if (displayItem != null) {
-                               final MediaItem item = displayItem.mItemRef;
-                               if (layer.getPickIntent()) {
-                                       // we need to return this item
-                                       ((Gallery) mContext).getHandler().post(new Runnable() {
-                                               public void run() {
-                                                       ((Gallery) mContext).launchCropperOrFinish(item);
-                                               }
-                                       });
-                                       return;
-                               }
-                               if (item.getMediaType() == MediaItem.MEDIA_TYPE_VIDEO) {
-                                       Utils.playVideo(mContext, item);
-                               } else {
-                                       mCurrentSelectedSlot = slotId;
-                                       layer.endSlideshow();
-                                       layer.setState(GridLayer.STATE_FULL_SCREEN);
-                                       mCamera.mConvergenceSpeed = 2.0f;
-                                       layer.getHud().fullscreenSelectionChanged(item, mCurrentSelectedSlot + 1, layer.getCompleteRange().end + 1);
-                               }
-                       }
-               }
-       }
-
-       public boolean onDoubleTap(MotionEvent e) {
-               final GridLayer layer = mLayer;
-               if (layer.getState() == GridLayer.STATE_FULL_SCREEN && !mCamera.isZAnimating()) {
-                       float posX = e.getX();
-                       float posY = e.getY();
-                       final Vector3f retVal = new Vector3f();
-                       posX -= (mCamera.mWidth / 2);
-                       posY -= (mCamera.mHeight / 2);
-                       mCamera.convertToRelativeCameraSpace(posX, posY, 0, retVal);
-                       if (layer.getZoomValue() == 1.0f) {
-                               layer.setZoomValue(3f);
-                               mCamera.update(0.001f);
-                               mCamera.moveBy(retVal.x, retVal.y, 0);
-                               layer.constrainCameraForSlot(mCurrentSelectedSlot);
-                       } else {
-                               layer.setZoomValue(1.0f);
-                       }
-                       mCamera.mConvergenceSpeed = 2.0f;
-               } else {
-                       return onSingleTapConfirmed(e);
-               }
-               return true;
-       }
-
-       public boolean onDoubleTapEvent(MotionEvent e) {
-               return false;
-       }
-
-       public boolean onSingleTapConfirmed(MotionEvent e) {
-               return false;
-       }
-
-       public boolean touchPressed() {
-               return mProcessTouch;
-       }
-
-       private void vibrateShort() {
-               // As per request by Google, this line disables vibration.
-               // mView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
-       }
-
-       private void vibrateLong() {
-               // mView.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY);
-       }
+    private int mCurrentFocusSlot;
+    private boolean mCurrentFocusIsPressed;
+    private int mCurrentSelectedSlot;
+
+    private float mPrevTiltValueLowPass;
+    private float mPrevShakeValueHighPass;
+    private float mShakeValue;
+    private int mTouchPosX;
+    private int mTouchPosY;
+    private int mActionCode;
+    private long mPrevTouchTime;
+    private float mFirstTouchPosX;
+    private float mFirstTouchPosY;
+    private float mPrevTouchPosX;
+    private float mPrevTouchPosY;
+    private float mTouchVelX;
+    private float mTouchVelY;
+    private boolean mProcessTouch;
+    private boolean mTouchMoved;
+    private float mDpadIgnoreTime = 0.0f;
+    private GridCamera mCamera;
+    private GridLayer mLayer;
+    private Context mContext;
+    private Pool<Vector3f> mPool;
+    private DisplayItem[] mDisplayItems;
+    private boolean mPrevHitEdge;
+    private boolean mTouchFeedbackDelivered;
+    private GestureDetector mGestureDetector;
+
+    public GridInputProcessor(Context context, GridCamera camera, GridLayer layer, RenderView view, Pool<Vector3f> pool,
+            DisplayItem[] displayItems) {
+        mPool = pool;
+        mCamera = camera;
+        mLayer = layer;
+        mCurrentFocusSlot = Shared.INVALID;
+        mCurrentSelectedSlot = Shared.INVALID;
+        mContext = context;
+        mDisplayItems = displayItems;
+        mGestureDetector = new GestureDetector(context, this);
+        mGestureDetector.setIsLongpressEnabled(true);
+    }
+
+    public int getCurrentFocusSlot() {
+        return mCurrentFocusSlot;
+    }
+
+    public int getCurrentSelectedSlot() {
+        return mCurrentSelectedSlot;
+    }
+
+    public void setCurrentSelectedSlot(int slot) {
+        mCurrentSelectedSlot = slot;
+        GridLayer layer = mLayer;
+        layer.setState(GridLayer.STATE_FULL_SCREEN);
+        mCamera.mConvergenceSpeed = 2.0f;
+        DisplayItem displayItem = layer.getDisplayItemForSlotId(slot);
+        MediaItem item = null;
+        if (displayItem != null)
+            item = displayItem.mItemRef;
+        layer.getHud().fullscreenSelectionChanged(item, mCurrentSelectedSlot + 1, layer.getCompleteRange().end + 1);
+    }
+
+    public void onSensorChanged(RenderView view, SensorEvent event, int state) {
+        switch (event.sensor.getType()) {
+        case Sensor.TYPE_ACCELEROMETER:
+        case Sensor.TYPE_ORIENTATION:
+            float[] values = event.values;
+            float valueToUse = (mCamera.mWidth < mCamera.mHeight) ? values[0] : -values[1];
+            float tiltValue = 0.8f * mPrevTiltValueLowPass + 0.2f * valueToUse;
+            if (Math.abs(tiltValue) < 0.5f)
+                tiltValue = 0.0f;
+            if (state == GridLayer.STATE_FULL_SCREEN)
+                tiltValue = 0.0f;
+            if (tiltValue != 0.0f)
+                view.requestRender();
+            mCamera.mEyeOffsetX = -3.0f * tiltValue;
+            float shakeValue = values[1] * values[1] + values[2] * values[2];
+            mShakeValue = shakeValue - mPrevShakeValueHighPass;
+            mPrevShakeValueHighPass = shakeValue;
+            if (mShakeValue < 16.0f) {
+                mShakeValue = 0;
+            } else {
+                mShakeValue = mShakeValue * 4.0f;
+                if (mShakeValue > 200) {
+                    mShakeValue = 200;
+                }
+            }
+            break;
+        }
+    }
+
+    public boolean onTouchEvent(MotionEvent event) {
+        mTouchPosX = (int) (event.getX());
+        mTouchPosY = (int) (event.getY());
+        mActionCode = event.getAction();
+        long timestamp = SystemClock.elapsedRealtime();
+        long delta = timestamp - mPrevTouchTime;
+        mPrevTouchTime = timestamp;
+        float timeElapsed = (float) delta;
+        timeElapsed = timeElapsed * 0.001f; // division by 1000 for seconds
+        switch (mActionCode) {
+        case MotionEvent.ACTION_UP:
+            if (mProcessTouch == false) {
+                touchBegan(mTouchPosX, mTouchPosY);
+            }
+            touchEnded(mTouchPosX, mTouchPosY, timeElapsed);
+            break;
+        case MotionEvent.ACTION_DOWN:
+            mPrevTouchTime = timestamp;
+            touchBegan(mTouchPosX, mTouchPosY);
+            break;
+        case MotionEvent.ACTION_MOVE:
+            touchMoved(mTouchPosX, mTouchPosY, timeElapsed);
+            break;
+        }
+        mGestureDetector.onTouchEvent(event);
+        return true;
+    }
+
+    public boolean onKeyDown(int keyCode, KeyEvent event, int state) {
+        GridLayer layer = mLayer;
+        if (keyCode == KeyEvent.KEYCODE_BACK) {
+            if (layer.getViewIntent())
+                return false;
+            if (layer.getHud().getMode() == HudLayer.MODE_SELECT) {
+                layer.deselectAll();
+                return true;
+            }
+            if (layer.inSlideShowMode()) {
+                layer.endSlideshow();
+                layer.getHud().setAlpha(1.0f);
+                return true;
+            }
+            float zoomValue = layer.getZoomValue();
+            if (zoomValue != 1.0f) {
+                layer.setZoomValue(1.0f);
+                layer.centerCameraForSlot(mCurrentSelectedSlot, 1.0f);
+                return true;
+            }
+            layer.goBack();
+            if (state == GridLayer.STATE_MEDIA_SETS)
+                return false;
+            return true;
+        }
+        if (mDpadIgnoreTime < 0.1f)
+            return true;
+        mDpadIgnoreTime = 0.0f;
+        IndexRange bufferedVisibleRange = layer.getBufferedVisibleRange();
+        int firstBufferedVisibleSlot = bufferedVisibleRange.begin;
+        int lastBufferedVisibleSlot = bufferedVisibleRange.end;
+        int anchorSlot = layer.getAnchorSlotIndex(GridLayer.ANCHOR_CENTER);
+        if (state == GridLayer.STATE_FULL_SCREEN) {
+            if (keyCode != KeyEvent.KEYCODE_VOLUME_UP && keyCode != KeyEvent.KEYCODE_VOLUME_DOWN
+                    && keyCode != KeyEvent.KEYCODE_MUTE && keyCode != KeyEvent.KEYCODE_HEADSETHOOK
+                    && keyCode != KeyEvent.KEYCODE_NOTIFICATION) {
+                layer.endSlideshow();
+            }
+            boolean needsVibrate = false;
+            if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT) {
+                needsVibrate = !layer.changeFocusToNextSlot(1.0f);
+            }
+            if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT) {
+                needsVibrate = !layer.changeFocusToPreviousSlot(1.0f);
+            }
+            if (needsVibrate) {
+                vibrateShort();
+            }
+            if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER && !mCamera.isAnimating()) {
+                if (layer.getZoomValue() == 1.0f)
+                    layer.zoomInToSelectedItem();
+                else
+                    layer.setZoomValue(1.0f);
+            }
+            if (keyCode == KeyEvent.KEYCODE_MENU) {
+                if (mLayer.getFeed() != null && mLayer.getFeed().isSingleImageMode()) {
+                    return true;
+                }
+                if (layer.getHud().getMode() == HudLayer.MODE_NORMAL)
+                    layer.enterSelectionMode();
+                else
+                    layer.deselectAll();
+            }
+        } else {
+            mCurrentFocusIsPressed = false;
+            int numRows = ((GridLayoutInterface) layer.getLayoutInterface()).mNumRows;
+            if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER && mCurrentFocusSlot != Shared.INVALID) {
+                if (layer.getHud().getMode() != HudLayer.MODE_SELECT) {
+                    boolean centerCamera = layer.tapGesture(mCurrentFocusSlot, false);
+                    if (centerCamera) {
+                        int slotId = mCurrentFocusSlot;
+                        selectSlot(slotId);
+                    }
+                    mCurrentFocusSlot = Shared.INVALID;
+                    return true;
+                } else {
+                    layer.addSlotToSelectedItems(mCurrentFocusSlot, true, true);
+                }
+                mCurrentFocusIsPressed = true;
+            } else if (keyCode == KeyEvent.KEYCODE_MENU && mCurrentFocusSlot != Shared.INVALID) {
+                if (layer.getHud().getMode() == HudLayer.MODE_NORMAL)
+                    layer.enterSelectionMode();
+                else
+                    layer.deselectAll();
+            } else if (mCurrentFocusSlot == Shared.INVALID) {
+                mCurrentFocusSlot = anchorSlot;
+            } else if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT) {
+                mCurrentFocusSlot += numRows;
+            } else if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT) {
+                mCurrentFocusSlot -= numRows;
+            } else if (keyCode == KeyEvent.KEYCODE_DPAD_UP) {
+                --mCurrentFocusSlot;
+            } else if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN) {
+                ++mCurrentFocusSlot;
+            }
+            if (mCurrentFocusSlot > lastBufferedVisibleSlot) {
+                mCurrentFocusSlot = lastBufferedVisibleSlot;
+            }
+            if (mCurrentFocusSlot < firstBufferedVisibleSlot)
+                mCurrentFocusSlot = firstBufferedVisibleSlot;
+            if (mCurrentFocusSlot != Shared.INVALID) {
+                layer.centerCameraForSlot(mCurrentFocusSlot, 1.0f);
+            }
+        }
+        return false;
+    }
+
+    private void touchBegan(int posX, int posY) {
+        mPrevTouchPosX = posX;
+        mPrevTouchPosY = posY;
+        mFirstTouchPosX = posX;
+        mFirstTouchPosY = posY;
+        mTouchVelX = 0;
+        mTouchVelY = 0;
+        mProcessTouch = true;
+        mTouchMoved = false;
+        mCamera.stopMovementInX();
+        GridLayer layer = mLayer;
+        mCurrentFocusSlot = layer.getSlotIndexForScreenPosition(posX, posY);
+        mCurrentFocusIsPressed = true;
+        mTouchFeedbackDelivered = false;
+        HudLayer hud = layer.getHud();
+        if (hud.getMode() == HudLayer.MODE_SELECT)
+            hud.closeSelectionMenu();
+        if (layer.getState() == GridLayer.STATE_FULL_SCREEN && hud.getMode() == HudLayer.MODE_SELECT) {
+            layer.deselectAll();
+            hud.setAlpha(1.0f);
+        }
+        int slotId = layer.getSlotIndexForScreenPosition(posX, posY);
+        if (slotId != Shared.INVALID && layer.getState() != GridLayer.STATE_FULL_SCREEN) {
+            vibrateShort();
+        }
+    }
+
+    private void touchMoved(int posX, int posY, float timeElapsedx) {
+        if (mProcessTouch) {
+            GridLayer layer = mLayer;
+            GridCamera camera = mCamera;
+            float deltaX = -(posX - mPrevTouchPosX); // negation since the wall
+            // moves in a direction
+            // opposite to that of
+            // the touch
+            float deltaY = -(posY - mPrevTouchPosY);
+            if (Math.abs(deltaX) >= 10.0f || Math.abs(deltaY) >= 10.0f) {
+                mTouchMoved = true;
+            }
+            Pool<Vector3f> pool = mPool;
+            Vector3f firstPosition = pool.create();
+            Vector3f lastPosition = pool.create();
+            Vector3f deltaAnchorPosition = pool.create();
+            Vector3f worldPosDelta = pool.create();
+            try {
+                deltaAnchorPosition.set(layer.getDeltaAnchorPosition());
+                LayoutInterface layout = layer.getLayoutInterface();
+                GridCameraManager.getSlotPositionForSlotIndex(0, camera, layout, deltaAnchorPosition, firstPosition);
+                int lastSlotIndex = 0;
+                IndexRange completeRange = layer.getCompleteRange();
+                synchronized (completeRange) {
+                    lastSlotIndex = completeRange.end;
+                }
+                GridCameraManager.getSlotPositionForSlotIndex(lastSlotIndex, camera, layout, deltaAnchorPosition, lastPosition);
+
+                camera.convertToRelativeCameraSpace(deltaX, deltaY, 0, worldPosDelta);
+                deltaX = worldPosDelta.x;
+                deltaY = worldPosDelta.y;
+                camera.moveBy(deltaX, (layer.getZoomValue() == 1.0f) ? 0 : deltaY, 0);
+                deltaX *= camera.mScale;
+                deltaY *= camera.mScale;
+            } finally {
+                pool.delete(firstPosition);
+                pool.delete(lastPosition);
+                pool.delete(deltaAnchorPosition);
+                pool.delete(worldPosDelta);
+            }
+            if (layer.getZoomValue() == 1.0f) {
+                if (camera
+                        .computeConstraints(false, (layer.getState() != GridLayer.STATE_FULL_SCREEN), firstPosition, lastPosition)) {
+                    deltaX = 0.0f;
+                    // vibrate
+                    if (!mTouchFeedbackDelivered) {
+                        mTouchFeedbackDelivered = true;
+                        vibrateLong();
+                    }
+                }
+            }
+            mTouchVelX = deltaX * timeElapsedx;
+            mTouchVelY = deltaY * timeElapsedx;
+            float maxVelXx = (mCamera.mWidth * 0.5f);
+            float maxVelYx = (mCamera.mHeight);
+            mTouchVelX = FloatUtils.clamp(mTouchVelX, -maxVelXx, maxVelXx);
+            mTouchVelY = FloatUtils.clamp(mTouchVelY, -maxVelYx, maxVelYx);
+            mPrevTouchPosX = posX;
+            mPrevTouchPosY = posY;
+            // you want the movement to track the finger immediately
+            if (mTouchMoved == false)
+                mCurrentFocusSlot = layer.getSlotIndexForScreenPosition(posX, posY);
+            else
+                mCurrentFocusSlot = Shared.INVALID;
+            if (!mCamera.isZAnimating()) {
+                mCamera.commitMoveInX();
+                mCamera.commitMoveInY();
+            }
+            int anchorSlotIndex = layer.getAnchorSlotIndex(GridLayer.ANCHOR_LEFT);
+            DisplayItem[] displayItems = mDisplayItems;
+            IndexRange bufferedVisibleRange = layer.getBufferedVisibleRange();
+            int firstBufferedVisibleSlot = bufferedVisibleRange.begin;
+            int lastBufferedVisibleSlot = bufferedVisibleRange.end;
+            synchronized (displayItems) {
+                if (anchorSlotIndex >= firstBufferedVisibleSlot && anchorSlotIndex <= lastBufferedVisibleSlot) {
+                    DisplayItem item = displayItems[(anchorSlotIndex - firstBufferedVisibleSlot) * GridLayer.MAX_ITEMS_PER_SLOT];
+                    if (item != null) {
+                        layer.getHud().setTimeBarTime(item.mItemRef.mDateTakenInMs);
+                    }
+                }
+            }
+        }
+    }
+
+    private void touchEnded(int posX, int posY, float timeElapsedx) {
+        if (mProcessTouch == false)
+            return;
+        int maxPixelsBeforeSwitch = mCamera.mWidth / 8;
+        mCamera.mConvergenceSpeed = 2.0f;
+        GridLayer layer = mLayer;
+        if (layer.getExpandedSlot() == Shared.INVALID && !layer.feedAboutToChange()) {
+            if (mCurrentSelectedSlot != Shared.INVALID) {
+                if (layer.getState() == GridLayer.STATE_FULL_SCREEN) {
+                    if (!mTouchMoved) {
+                        // tap gesture for fullscreen
+                        if (layer.getZoomValue() == 1.0f)
+                            layer.changeFocusToSlot(mCurrentSelectedSlot, 1.0f);
+                    } else if (layer.getZoomValue() == 1.0f) {
+                        // we want to snap to a new slotIndex based on where the
+                        // current position is
+                        if (layer.inSlideShowMode()) {
+                            layer.endSlideshow();
+                        }
+                        float deltaX = posX - mFirstTouchPosX;
+                        float deltaY = posY - mFirstTouchPosY;
+                        if (deltaY != 0) {
+                            // it has moved vertically
+                        }
+                        layer.changeFocusToSlot(mCurrentSelectedSlot, 1.0f);
+                        HudLayer hud = layer.getHud();
+                        if (deltaX > maxPixelsBeforeSwitch && hud.getMode() != HudLayer.MODE_SELECT) {
+                            layer.changeFocusToPreviousSlot(1.0f);
+                        } else if (deltaX < -maxPixelsBeforeSwitch && hud.getMode() != HudLayer.MODE_SELECT) {
+                            layer.changeFocusToNextSlot(1.0f);
+                        }
+                    } else {
+                        // in zoomed state
+                        // we do nothing for now, but we should clamp to the
+                        // image bounds
+                        boolean hitEdge = layer.constrainCameraForSlot(mCurrentSelectedSlot);
+                        // mPrevHitEdge = false;
+                        if (hitEdge && mPrevHitEdge) {
+                            float deltaX = posX - mFirstTouchPosX;
+                            float deltaY = posY - mFirstTouchPosY;
+                            maxPixelsBeforeSwitch *= 4;
+                            if (deltaY != 0) {
+                                // it has moved vertically
+                            }
+                            mPrevHitEdge = false;
+                            HudLayer hud = layer.getHud();
+                            if (deltaX > maxPixelsBeforeSwitch && hud.getMode() != HudLayer.MODE_SELECT) {
+                                layer.changeFocusToPreviousSlot(1.0f);
+                            } else if (deltaX < -maxPixelsBeforeSwitch && hud.getMode() != HudLayer.MODE_SELECT) {
+                                layer.changeFocusToNextSlot(1.0f);
+                            } else {
+                                mPrevHitEdge = hitEdge;
+                            }
+                        } else {
+                            mPrevHitEdge = hitEdge;
+                        }
+                    }
+                }
+            } else {
+                if (!layer.feedAboutToChange() && layer.getZoomValue() == 1.0f) {
+                    constrainCamera(true);
+                }
+            }
+        }
+        mCurrentFocusSlot = Shared.INVALID;
+        mCurrentFocusIsPressed = false;
+        mPrevTouchPosX = posX;
+        mPrevTouchPosY = posY;
+        mProcessTouch = false;
+    }
+
+    private void constrainCamera(boolean b) {
+        Pool<Vector3f> pool = mPool;
+        GridLayer layer = mLayer;
+        Vector3f firstPosition = pool.create();
+        Vector3f lastPosition = pool.create();
+        Vector3f deltaAnchorPosition = pool.create();
+        try {
+            deltaAnchorPosition.set(layer.getDeltaAnchorPosition());
+            GridCamera camera = mCamera;
+            LayoutInterface layout = layer.getLayoutInterface();
+            GridCameraManager.getSlotPositionForSlotIndex(0, camera, layout, deltaAnchorPosition, firstPosition);
+            int lastSlotIndex = 0;
+            IndexRange completeRange = layer.getCompleteRange();
+            synchronized (completeRange) {
+                lastSlotIndex = completeRange.end;
+            }
+            GridCameraManager.getSlotPositionForSlotIndex(lastSlotIndex, camera, layout, deltaAnchorPosition, lastPosition);
+            camera.computeConstraints(true, (layer.getState() != GridLayer.STATE_FULL_SCREEN), firstPosition, lastPosition);
+        } finally {
+            pool.delete(firstPosition);
+            pool.delete(lastPosition);
+            pool.delete(deltaAnchorPosition);
+        }
+    }
+
+    public void clearSelection() {
+        mCurrentSelectedSlot = Shared.INVALID;
+    }
+
+    public void clearFocus() {
+        mCurrentFocusSlot = Shared.INVALID;
+    }
+
+    public boolean isFocusItemPressed() {
+        return mCurrentFocusIsPressed;
+    }
+
+    public void update(float timeElapsed) {
+        mDpadIgnoreTime += timeElapsed;
+    }
+
+    public void setCurrentFocusSlot(int slotId) {
+        mCurrentSelectedSlot = slotId;
+    }
+
+    public boolean onDown(MotionEvent e) {
+        // TODO Auto-generated method stub
+        return true;
+    }
+
+    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
+        if (mCurrentSelectedSlot == Shared.INVALID) {
+            mCamera.moveYTo(0);
+            mCamera.moveZTo(0);
+            mCamera.mConvergenceSpeed = 1.0f;
+            float normalizedVelocity = velocityX * mCamera.mOneByScale;
+            // mCamera.moveBy(-velocityX * mCamera.mOneByScale * 0.25f, 0, 0);
+            // constrainCamera(true);
+            IndexRange visibleRange = mLayer.getVisibleRange();
+            int numVisibleSlots = visibleRange.end - visibleRange.begin;
+            if (numVisibleSlots > 0) {
+                float fastFlingVelocity = 20.0f;
+                int slotsToSkip = (int) (numVisibleSlots * (-normalizedVelocity / fastFlingVelocity));
+                int maxSlots = numVisibleSlots;
+                if (slotsToSkip > maxSlots)
+                    slotsToSkip = maxSlots;
+                if (slotsToSkip < -maxSlots)
+                    slotsToSkip = -maxSlots;
+                if (Math.abs(slotsToSkip) <= 1) {
+                    if (velocityX > 0)
+                        slotsToSkip = -2;
+                    else if (velocityX < 0)
+                        slotsToSkip = 2;
+                }
+                int slotToGetTo = mLayer.getAnchorSlotIndex(GridLayer.ANCHOR_CENTER) + slotsToSkip;
+                if (slotToGetTo < 0)
+                    slotToGetTo = 0;
+                int lastSlot = mLayer.getCompleteRange().end;
+                if (slotToGetTo > lastSlot)
+                    slotToGetTo = lastSlot;
+                mLayer.centerCameraForSlot(slotToGetTo, 1.0f);
+            }
+            constrainCamera(true);
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    public void onLongPress(MotionEvent e) {
+        if (mLayer.getFeed() != null && mLayer.getFeed().isSingleImageMode()) {
+            HudLayer hud = mLayer.getHud();
+            hud.getPathBar().setHidden(true);
+            hud.getMenuBar().setHidden(true);
+            if (hud.getMode() != HudLayer.MODE_NORMAL)
+                hud.setMode(HudLayer.MODE_NORMAL);
+        }
+        if (mCurrentFocusSlot != Shared.INVALID) {
+            vibrateLong();
+            GridLayer layer = mLayer;
+            if (layer.getState() == GridLayer.STATE_FULL_SCREEN) {
+                layer.deselectAll();
+            }
+            HudLayer hud = layer.getHud();
+            hud.enterSelectionMode();
+            layer.addSlotToSelectedItems(mCurrentFocusSlot, true, true);
+        }
+    }
+
+    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    public void onShowPress(MotionEvent e) {
+        // TODO Auto-generated method stub
+
+    }
+
+    public boolean onSingleTapUp(MotionEvent e) {
+        GridLayer layer = mLayer;
+        int posX = (int) e.getX();
+        int posY = (int) e.getY();
+        if (mCurrentSelectedSlot != Shared.INVALID) {
+            // Fullscreen mode.
+            mCamera.mConvergenceSpeed = 2.0f;
+            int slotId = mCurrentSelectedSlot;
+            if (layer.getZoomValue() == 1.0f) {
+                layer.centerCameraForSlot(slotId, 1.0f);
+            } else {
+                layer.constrainCameraForSlot(slotId);
+            }
+            DisplayItem displayItem = layer.getDisplayItemForSlotId(slotId);
+            if (displayItem != null) {
+                final MediaItem item = displayItem.mItemRef;
+                int heightBy2 = mCamera.mHeight / 2;
+                boolean posYInBounds = (Math.abs(posY - heightBy2) < 64);
+                if (posX < 32 && posYInBounds) {
+                    layer.changeFocusToPreviousSlot(1.0f);
+                } else if (posX > mCamera.mWidth - 32 && posYInBounds) {
+                    layer.changeFocusToNextSlot(1.0f);
+                } else if (item.getMediaType() == MediaItem.MEDIA_TYPE_VIDEO) {
+                    Utils.playVideo(mContext, item);
+                } else {
+                    // We stop any slideshow.
+                    HudLayer hud = layer.getHud();
+                    if (layer.inSlideShowMode()) {
+                        layer.endSlideshow();
+                    } else {
+                        hud.setAlpha(1.0f - hud.getAlpha());
+                    }
+                    if (hud.getMode() == HudLayer.MODE_SELECT) {
+                        hud.setAlpha(1.0f);
+                    }
+                }
+            }
+        } else {
+            int slotId = layer.getSlotIndexForScreenPosition(posX, posY);
+            if (slotId != Shared.INVALID) {
+                HudLayer hud = layer.getHud();
+                if (hud.getMode() == HudLayer.MODE_SELECT) {
+                    layer.addSlotToSelectedItems(slotId, true, true);
+                } else {
+                    boolean centerCamera = (mCurrentSelectedSlot == Shared.INVALID) ? layer.tapGesture(slotId, false) : true;
+                    if (centerCamera) {
+                        // We check if this item is a video or not.
+                        selectSlot(slotId);
+                    }
+                }
+            } else {
+                int state = layer.getState();
+                if (state != GridLayer.STATE_FULL_SCREEN && state != GridLayer.STATE_GRID_VIEW
+                        && layer.getHud().getMode() != HudLayer.MODE_SELECT) {
+                    slotId = layer.getMetadataSlotIndexForScreenPosition(posX, posY);
+                    if (slotId != Shared.INVALID) {
+                        layer.tapGesture(slotId, true);
+                    }
+                }
+            }
+        }
+        return true;
+    }
+
+    private void selectSlot(int slotId) {
+        GridLayer layer = mLayer;
+        if (layer.getState() == GridLayer.STATE_GRID_VIEW) {
+            DisplayItem displayItem = layer.getDisplayItemForSlotId(slotId);
+            if (displayItem != null) {
+                final MediaItem item = displayItem.mItemRef;
+                if (layer.getPickIntent()) {
+                    // we need to return this item
+                    ((Gallery) mContext).getHandler().post(new Runnable() {
+                        public void run() {
+                            ((Gallery) mContext).launchCropperOrFinish(item);
+                        }
+                    });
+                    return;
+                }
+                if (item.getMediaType() == MediaItem.MEDIA_TYPE_VIDEO) {
+                    Utils.playVideo(mContext, item);
+                } else {
+                    mCurrentSelectedSlot = slotId;
+                    layer.endSlideshow();
+                    layer.setState(GridLayer.STATE_FULL_SCREEN);
+                    mCamera.mConvergenceSpeed = 2.0f;
+                    layer.getHud().fullscreenSelectionChanged(item, mCurrentSelectedSlot + 1, layer.getCompleteRange().end + 1);
+                }
+            }
+        }
+    }
+
+    public boolean onDoubleTap(MotionEvent e) {
+        final GridLayer layer = mLayer;
+        if (layer.getState() == GridLayer.STATE_FULL_SCREEN && !mCamera.isZAnimating()) {
+            float posX = e.getX();
+            float posY = e.getY();
+            final Vector3f retVal = new Vector3f();
+            posX -= (mCamera.mWidth / 2);
+            posY -= (mCamera.mHeight / 2);
+            mCamera.convertToRelativeCameraSpace(posX, posY, 0, retVal);
+            if (layer.getZoomValue() == 1.0f) {
+                layer.setZoomValue(3f);
+                mCamera.update(0.001f);
+                mCamera.moveBy(retVal.x, retVal.y, 0);
+                layer.constrainCameraForSlot(mCurrentSelectedSlot);
+            } else {
+                layer.setZoomValue(1.0f);
+            }
+            mCamera.mConvergenceSpeed = 2.0f;
+        } else {
+            return onSingleTapConfirmed(e);
+        }
+        return true;
+    }
+
+    public boolean onDoubleTapEvent(MotionEvent e) {
+        return false;
+    }
+
+    public boolean onSingleTapConfirmed(MotionEvent e) {
+        return false;
+    }
+
+    public boolean touchPressed() {
+        return mProcessTouch;
+    }
+
+    private void vibrateShort() {
+        // As per request by Google, this line disables vibration.
+        // mView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
+    }
+
+    private void vibrateLong() {
+        // mView.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY);
+    }
 }
index 2693752..e17050d 100644 (file)
@@ -12,1427 +12,1430 @@ import android.view.MotionEvent;
 import android.content.Context;
 
 public final class GridLayer extends RootLayer implements MediaFeed.Listener, TimeBar.Listener {
-       public static final int STATE_MEDIA_SETS = 0;
-       public static final int STATE_GRID_VIEW = 1;
-       public static final int STATE_FULL_SCREEN = 2;
-       public static final int STATE_TIMELINE = 3;
-
-       public static final int ANCHOR_LEFT = 0;
-       public static final int ANCHOR_RIGHT = 1;
-       public static final int ANCHOR_CENTER = 2;
-
-       public static final int MAX_ITEMS_PER_SLOT = 12;
-       public static final int MAX_DISPLAYED_ITEMS_PER_SLOT = 4;
-       public static final int MAX_DISPLAY_SLOTS = 96;
-       public static final int MAX_ITEMS_DRAWABLE = MAX_ITEMS_PER_SLOT * MAX_DISPLAY_SLOTS;
-
-       private static final float SLIDESHOW_TRANSITION_TIME = 3.5f;
-
-       private HudLayer mHud;
-       private int mState;
-       private static final IndexRange sBufferedVisibleRange = new IndexRange();
-       private static final IndexRange sVisibleRange = new IndexRange();
-       private static final IndexRange sPreviousDataRange = new IndexRange();
-       private static final IndexRange sCompleteRange = new IndexRange();
-
-       private static final Pool<Vector3f> sTempVec;
-       private static final Pool<Vector3f> sTempVecAlt;
-       static {
-               Vector3f[] vectorPool = new Vector3f[128];
-               int length = vectorPool.length;
-               for (int i = 0; i < length; ++i) {
-                       vectorPool[i] = new Vector3f();
-               }
-               Vector3f[] vectorPoolRenderThread = new Vector3f[128];
-               length = vectorPoolRenderThread.length;
-               for (int i = 0; i < length; ++i) {
-                       vectorPoolRenderThread[i] = new Vector3f();
-               }
-               sTempVec = new Pool<Vector3f>(vectorPool);
-               sTempVecAlt = new Pool<Vector3f>(vectorPoolRenderThread);
-       }
-
-       private static final ArrayList<MediaItem> sTempList = new ArrayList<MediaItem>();
-       private static final MediaItem[] sTempHash = new MediaItem[64];
-
-       private static final Vector3f sDeltaAnchorPositionUncommited = new Vector3f();
-       private static Vector3f sDeltaAnchorPosition = new Vector3f();
-
-       // The display primitives.
-       final private GridDrawables mDrawables;
-       private float mSelectedAlpha = 0.0f;
-       private float mTargetAlpha = 0.0f;
-
-       final private GridCamera mCamera;
-       final private GridCameraManager mCameraManager;
-       final private GridDrawManager mDrawManager;
-       final private GridInputProcessor mInputProcessor;
-
-       private boolean mFeedAboutToChange;
-       private boolean mPerformingLayoutChange;
-       private boolean mFeedChanged;
-
-       private final LayoutInterface mLayoutInterface;
-       private static final LayoutInterface sfullScreenLayoutInterface = new GridLayoutInterface(1);
-
-       private MediaFeed mMediaFeed;
-       private boolean mInAlbum = false;
-       private int mCurrentExpandedSlot;
-
-       private static final DisplayList sDisplayList = new DisplayList();
-       private static final DisplayItem[] sDisplayItems = new DisplayItem[MAX_ITEMS_DRAWABLE];
-       private static final DisplaySlot[] sDisplaySlots = new DisplaySlot[MAX_DISPLAY_SLOTS];
-       private static ArrayList<MediaItem> sVisibleItems;
-
-       private float mTimeElapsedSinceTransition;
-       private final BackgroundLayer mBackground;
-       private boolean mLocationFilter;
-       private float mZoomValue = 1.0f;
-       private float mCurrentFocusItemWidth = 1.0f;
-       private float mCurrentFocusItemHeight = 1.0f;
-       private float mTimeElapsedSinceGridViewReady = 0.0f;
-
-       private boolean mSlideshowMode;
-       private boolean mNoDeleteMode = false;
-       private float mTimeElapsedSinceView;
-       private static final MediaBucketList sBucketList = new MediaBucketList();
-       private float mTimeElapsedSinceStackViewReady;
-
-       private Context mContext;
-       private RenderView mView;
-       private boolean mPickIntent;
-       private boolean mViewIntent;
-       private WakeLock mWakeLock;
-       private int mStartMemoryRange;
-       private int mFramesDirty;
-       private String mRequestFocusContentUri;
-       private int mFrameCount;
-
-       public GridLayer(Context context, int itemWidth, int itemHeight, LayoutInterface layoutInterface, RenderView view) {
-               mBackground = new BackgroundLayer(this);
-               mContext = context;
-               mView = view;
-
-               DisplaySlot[] displaySlots = sDisplaySlots;
-               for (int i = 0; i < MAX_DISPLAY_SLOTS; ++i) {
-                       DisplaySlot slot = new DisplaySlot();
-                       displaySlots[i] = slot;
-               }
-               mLayoutInterface = layoutInterface;
-               mCamera = new GridCamera(0, 0, itemWidth, itemHeight);
-               mDrawables = new GridDrawables(itemWidth, itemHeight);
-               sBufferedVisibleRange.set(Shared.INVALID, Shared.INVALID);
-               sVisibleRange.set(Shared.INVALID, Shared.INVALID);
-               sCompleteRange.set(Shared.INVALID, Shared.INVALID);
-               sPreviousDataRange.set(Shared.INVALID, Shared.INVALID);
-               sDeltaAnchorPosition.set(0, 0, 0);
-               sDeltaAnchorPositionUncommited.set(0, 0, 0);
-               sBucketList.clear();
-
-               sVisibleItems = new ArrayList<MediaItem>();
-               mHud = new HudLayer(context);
-               mHud.setContext(context);
-               mHud.setGridLayer(this);
-               mHud.getPathBar().clear();
-               mHud.setGridLayer(this);
-               mHud.getTimeBar().setListener(this);
-               mHud.getPathBar().pushLabel(R.drawable.icon_home_small, context.getResources().getString(R.string.app_name),
-                       new Runnable() {
-                               public void run() {
-                                       if (mHud.getAlpha() == 1.0f) {
-                                               if (!mFeedAboutToChange) {
-                                                       setState(STATE_MEDIA_SETS);
-                                               }
-                                       } else {
-                                               mHud.setAlpha(1.0f);
-                                       }
-                               }
-                       });
-               mCameraManager = new GridCameraManager(mCamera);
-               mDrawManager = new GridDrawManager(context, mCamera, mDrawables, sDisplayList, sDisplayItems, sDisplaySlots);
-               mInputProcessor = new GridInputProcessor(context, mCamera, this, mView, sTempVec, sDisplayItems);
-               setState(STATE_MEDIA_SETS);
-       }
-
-       public HudLayer getHud() {
-               return mHud;
-       }
-
-       public void shutdown() {
-               if (mMediaFeed != null) {
-                       mMediaFeed.shutdown();
-               }
-               mContext = null;
-               sBucketList.clear();
-               mView = null;
-       }
-
-       public void stop() {
-               endSlideshow();
-               mBackground.clear();
-               handleLowMemory();
-       }
-
-       @Override
-       public void generate(RenderView view, RenderView.Lists lists) {
-               lists.updateList.add(this);
-               lists.opaqueList.add(this);
-               mBackground.generate(view, lists);
-               lists.blendedList.add(this);
-               lists.hitTestList.add(this);
-               mHud.generate(view, lists);
-       }
-
-       @Override
-       protected void onSizeChanged() {
-               mHud.setSize(mWidth, mHeight);
-               mHud.setAlpha(1.0f);
-               mBackground.setSize(mWidth, mHeight);
-               mTimeElapsedSinceTransition = 0.0f;
-               if (mView != null) {
-                       mView.requestRender();
-               }
-       }
-
-       public int getState() {
-               return mState;
-       }
-
-       public void setState(int state) {
-               boolean feedUnchanged = false;
-               if (mState == state) {
-                       feedUnchanged = true;
-               }
-               GridLayoutInterface layoutInterface = (GridLayoutInterface) mLayoutInterface;
-               GridLayoutInterface oldLayout = (GridLayoutInterface) sfullScreenLayoutInterface;
-               oldLayout.mNumRows = layoutInterface.mNumRows;
-               oldLayout.mSpacingX = layoutInterface.mSpacingX;
-               oldLayout.mSpacingY = layoutInterface.mSpacingY;
-               GridCamera camera = mCamera;
-               int numMaxRows = (camera.mHeight >= camera.mWidth) ? 4 : 3;
-               MediaFeed feed = mMediaFeed;
-               boolean performLayout = true;
-               mZoomValue = 1.0f;
-               float yStretch = camera.mDefaultAspectRatio / camera.mAspectRatio;
-               if (yStretch < 1.0f) {
-                       yStretch = 1.0f;
-               }
-               switch (state) {
-               case STATE_GRID_VIEW:
-                       mTimeElapsedSinceGridViewReady = 0.0f;
-                       if (feed != null && feedUnchanged == false) {
-                               boolean updatedData = feed.restorePreviousClusteringState();
-                               if (updatedData) {
-                                       performLayout = false;
-                               }
-                       }
-                       layoutInterface.mNumRows = numMaxRows;
-                       layoutInterface.mSpacingX = (int) (10 * Gallery.PIXEL_DENSITY);
-                       layoutInterface.mSpacingY = (int) (10 * Gallery.PIXEL_DENSITY);
-                       if (mState == STATE_MEDIA_SETS) {
-                               // Entering album.
-                               mInAlbum = true;
-                               MediaSet set = feed.getCurrentSet();
-                               int icon = mDrawables.getIconForSet(set, true);
-                               if (set != null) {
-                                       mHud.getPathBar().pushLabel(icon, set.mNoCountTitleString, new Runnable() {
-                                               public void run() {
-                                                       if (mFeedAboutToChange) {
-                                                               return;
-                                                       }
-                                                       if (mHud.getAlpha() == 1.0f) {
-                                                               disableLocationFiltering();
-                                                               mInputProcessor.clearSelection();
-                                                               setState(STATE_GRID_VIEW);
-                                                       } else {
-                                                               mHud.setAlpha(1.0f);
-                                                       }
-                                               }
-                                       });
-                               }
-                       }
-                       if (mState == STATE_FULL_SCREEN) {
-                               mHud.getPathBar().popLabel();
-                       }
-                       break;
-               case STATE_TIMELINE:
-                       mTimeElapsedSinceStackViewReady = 0.0f;
-                       if (feed != null && feedUnchanged == false) {
-                               feed.performClustering();
-                               performLayout = false;
-                       }
-                       disableLocationFiltering();
-                       layoutInterface.mNumRows = numMaxRows - 1;
-                       layoutInterface.mSpacingX = (int) (100 * Gallery.PIXEL_DENSITY);
-                       layoutInterface.mSpacingY = (int) (70 * Gallery.PIXEL_DENSITY * yStretch);
-                       break;
-               case STATE_FULL_SCREEN:
-                       layoutInterface.mNumRows = 1;
-                       layoutInterface.mSpacingX = (int) (40 * Gallery.PIXEL_DENSITY);
-                       layoutInterface.mSpacingY = (int) (40 * Gallery.PIXEL_DENSITY);
-                       if (mState != STATE_FULL_SCREEN) {
-                               mHud.getPathBar().pushLabel(R.drawable.ic_fs_details, "", new Runnable() {
-                                       public void run() {
-                                               if (mHud.getAlpha() == 1.0f) {
-                                                       mHud.swapFullscreenLabel();
-                                               }
-                                               mHud.setAlpha(1.0f);
-                                       }
-                               });
-                       }
-                       break;
-               case STATE_MEDIA_SETS:
-                       mTimeElapsedSinceStackViewReady = 0.0f;
-                       if (feed != null && feedUnchanged == false) {
-                               feed.restorePreviousClusteringState();
-                               feed.expandMediaSet(Shared.INVALID);
-                               performLayout = false;
-                       }
-                       disableLocationFiltering();
-                       mInputProcessor.clearSelection();
-                       layoutInterface.mNumRows = numMaxRows - 1;
-                       layoutInterface.mSpacingX = (int) (100 * Gallery.PIXEL_DENSITY);
-                       layoutInterface.mSpacingY = (int) (70 * Gallery.PIXEL_DENSITY * yStretch);
-                       if (mInAlbum) {
-                               if (mState == STATE_FULL_SCREEN) {
-                                       mHud.getPathBar().popLabel();
-                               }
-                               mHud.getPathBar().popLabel();
-                               mInAlbum = false;
-                       }
-                       break;
-               }
-               mState = state;
-               mHud.onGridStateChanged();
-               if (performLayout && mFeedAboutToChange == false) {
-                       onLayout(Shared.INVALID, Shared.INVALID, oldLayout);
-               }
-               if (state != STATE_FULL_SCREEN) {
-                       mCamera.moveYTo(0);
-                       mCamera.moveZTo(0);
-               }
-       }
-
-       protected void enableLocationFiltering(String label) {
-               if (mLocationFilter == false) {
-                       mLocationFilter = true;
-                       mHud.getPathBar().pushLabel(R.drawable.icon_location_small, label, new Runnable() {
-                               public void run() {
-                                       if (mHud.getAlpha() == 1.0f) {
-                                               if (mState == STATE_FULL_SCREEN) {
-                                                       mInputProcessor.clearSelection();
-                                                       setState(STATE_GRID_VIEW);
-                                               } else {
-                                                       disableLocationFiltering();
-                                               }
-                                       } else {
-                                               mHud.setAlpha(1.0f);
-                                       }
-                               }
-                       });
-               }
-       }
-
-       protected void disableLocationFiltering() {
-               if (mLocationFilter) {
-                       mLocationFilter = false;
-                       mMediaFeed.removeFilter();
-                       mHud.getPathBar().popLabel();
-               }
-       }
-
-       boolean goBack() {
-               if (mFeedAboutToChange) {
-                       return false;
-               }
-               int state = mState;
-               if (mInputProcessor.getCurrentSelectedSlot() == Shared.INVALID) {
-                       if (mLocationFilter) {
-                               disableLocationFiltering();
-                               setState(STATE_TIMELINE);
-                               return true;
-                       }
-               }
-               switch (state) {
-               case STATE_GRID_VIEW:
-                       setState(STATE_MEDIA_SETS);
-                       break;
-               case STATE_TIMELINE:
-                       setState(STATE_GRID_VIEW);
-                       break;
-               case STATE_FULL_SCREEN:
-                       setState(STATE_GRID_VIEW);
-                       mInputProcessor.clearSelection();
-                       break;
-               default:
-                       return false;
-               }
-               return true;
-       }
-
-       public void endSlideshow() {
-               mSlideshowMode = false;
-               if (mWakeLock != null) {
-                       if (mWakeLock.isHeld()) {
-                               mWakeLock.release();
-                       }
-                       mWakeLock = null;
-               }
-               mHud.setAlpha(1.0f);
-       }
-
-       @Override
-       public void onSensorChanged(RenderView view, SensorEvent event) {
-               mInputProcessor.onSensorChanged(view, event, mState);
-       }
-
-       public DataSource getDataSource() {
-               if (mMediaFeed != null)
-                       return mMediaFeed.getDataSource();
-               return null;
-       }
-
-       public void setDataSource(DataSource dataSource) {
-               MediaFeed feed = mMediaFeed;
-               if (feed != null) {
-                       feed.shutdown();
-                       sDisplayList.clear();
-                       mBackground.clear();
-               }
-               mMediaFeed = new MediaFeed(mContext, dataSource, this);
-               mMediaFeed.start();
-       }
-
-       public IndexRange getVisibleRange() {
-               return sVisibleRange;
-       }
-
-       public IndexRange getBufferedVisibleRange() {
-               return sBufferedVisibleRange;
-       }
-
-       public IndexRange getCompleteRange() {
-               return sCompleteRange;
-       }
-
-       private int hitTest(Vector3f worldPos, int itemWidth, int itemHeight) {
-               int retVal = Shared.INVALID;
-               int firstSlotIndex = 0;
-               int lastSlotIndex = 0;
-               IndexRange rangeToUse = sVisibleRange;
-               synchronized (rangeToUse) {
-                       firstSlotIndex = rangeToUse.begin;
-                       lastSlotIndex = rangeToUse.end;
-               }
-               Pool<Vector3f> pool = sTempVec;
-               float itemWidthBy2 = itemWidth * 0.5f;
-               float itemHeightBy2 = itemHeight * 0.5f;
-               Vector3f position = pool.create();
-               Vector3f deltaAnchorPosition = pool.create();
-               try {
-                       deltaAnchorPosition.set(sDeltaAnchorPosition);
-                       for (int i = firstSlotIndex; i <= lastSlotIndex; ++i) {
-                               GridCameraManager.getSlotPositionForSlotIndex(i, mCamera, mLayoutInterface, deltaAnchorPosition, position);
-                               if (FloatUtils.boundsContainsPoint(position.x - itemWidthBy2, position.x + itemWidthBy2,
-                                       position.y - itemHeightBy2, position.y + itemHeightBy2, worldPos.x, worldPos.y)) {
-                                       retVal = i;
-                                       break;
-                               }
-                       }
-               } finally {
-                       pool.delete(deltaAnchorPosition);
-                       pool.delete(position);
-               }
-               return retVal;
-       }
-
-       void centerCameraForSlot(int slotIndex, float baseConvergence) {
-               float imageTheta = 0.0f;
-               DisplayItem displayItem = getDisplayItemForSlotId(slotIndex);
-               if (displayItem != null) {
-                       imageTheta = displayItem.getImageTheta();
-               }
-               mCameraManager.centerCameraForSlot(mLayoutInterface, slotIndex, baseConvergence, sDeltaAnchorPositionUncommited,
-                       mInputProcessor.getCurrentSelectedSlot(), mZoomValue, imageTheta, mState);
-       }
-
-       boolean constrainCameraForSlot(int slotIndex) {
-               return mCameraManager.constrainCameraForSlot(mLayoutInterface, slotIndex, sDeltaAnchorPosition, mCurrentFocusItemWidth,
-                       mCurrentFocusItemHeight);
-       }
-
-       // Called on render thread before rendering.
-       @Override
-       public boolean update(RenderView view, float timeElapsed) {
-               if (mFeedAboutToChange == false) {
-                       mTimeElapsedSinceTransition += timeElapsed;
-                       mTimeElapsedSinceGridViewReady += timeElapsed;
-                       if (mTimeElapsedSinceGridViewReady >= 1.0f) {
-                               mTimeElapsedSinceGridViewReady = 1.0f;
-                       }
-                       mTimeElapsedSinceStackViewReady += timeElapsed;
-                       if (mTimeElapsedSinceStackViewReady >= 1.0f) {
-                               mTimeElapsedSinceStackViewReady = 1.0f;
-                       }
-               } else {
-                       mTimeElapsedSinceTransition = 0;
-               }
-               if (mMediaFeed != null && mMediaFeed.isSingleImageMode()) {
-                       HudLayer hud = getHud();
-                       hud.getPathBar().setHidden(true);
-                       hud.getMenuBar().setHidden(true);
-                       if (hud.getMode() != HudLayer.MODE_NORMAL)
-                               hud.setMode(HudLayer.MODE_NORMAL);
-               }
-               if (view.elapsedLoadingExpensiveTextures() > 150 || (mMediaFeed != null && mMediaFeed.getWaitingForMediaScanner())) {
-                       mHud.getPathBar().setAnimatedIcons(GridDrawables.TEXTURE_SPINNER);
-               } else {
-                       mHud.getPathBar().setAnimatedIcons(null);
-               }
-
-               // In that case, we need to commit the respective Display Items when the
-               // feed was updated.
-               GridCamera camera = mCamera;
-               camera.update(timeElapsed);
-               DisplayItem anchorDisplayItem = getAnchorDisplayItem(ANCHOR_CENTER);
-               if (anchorDisplayItem != null && !mHud.getTimeBar().isDragged()) {
-                       mHud.getTimeBar().setItem(anchorDisplayItem.mItemRef);
-               }
-               sDisplayList.update(timeElapsed);
-               mInputProcessor.update(timeElapsed);
-               mSelectedAlpha = FloatUtils.animate(mSelectedAlpha, mTargetAlpha, timeElapsed * 0.5f);
-               if (mState == STATE_FULL_SCREEN) {
-                       mHud.autoHide(true);
-               } else {
-                       mHud.autoHide(false);
-                       mHud.setAlpha(1.0f);
-               }
-               GridQuad[] fullscreenQuads = GridDrawables.sFullscreenGrid;
-               int numFullScreenQuads = fullscreenQuads.length;
-               for (int i = 0; i < numFullScreenQuads; ++i) {
-                       fullscreenQuads[i].update(timeElapsed);
-               }
-               if (mSlideshowMode && mState == STATE_FULL_SCREEN) {
-                       mTimeElapsedSinceView += timeElapsed;
-                       if (mTimeElapsedSinceView > SLIDESHOW_TRANSITION_TIME) {
-                               // time to go to the next slide
-                               mTimeElapsedSinceView = 0.0f;
-                               changeFocusToNextSlot(0.5f);
-                               mCamera.commitMoveInX();
-                               mCamera.commitMoveInY();
-                       }
-               }
-               if (mState == STATE_MEDIA_SETS || mState == STATE_TIMELINE) {
-                       mCamera.moveYTo(-0.1f);
-                       mCamera.commitMoveInY();
-               }
-               boolean dirty = mDrawManager.update(timeElapsed);
-               dirty |= mSlideshowMode;
-               dirty |= mFramesDirty > 0;
-               ++mFrameCount;
-               if (mFramesDirty > 0) {
-                       --mFramesDirty;
-               }
-               try {
-                       if (mMediaFeed != null && (mMediaFeed.getWaitingForMediaScanner())) {
-                               // We limit the drawing of the frame so that the MediaScanner
-                               // thread can do its work
-                               Thread.sleep(200);
-                       }
-               } catch (InterruptedException e) {
-
-               }
-               if (sDisplayList.getNumAnimatables() != 0 || mCamera.isAnimating()
-                       || (mTimeElapsedSinceTransition > 0.0f && mTimeElapsedSinceTransition < 1.0f) || mSelectedAlpha != mTargetAlpha
-                       // || (mAnimatedFov != mTargetFov)
-                       || dirty)
-                       return true;
-               else
-                       return false;
-       }
-
-       private void computeVisibleRange() {
-               if (mPerformingLayoutChange)
-                       return;
-               if (sDeltaAnchorPosition.equals(sDeltaAnchorPositionUncommited) == false) {
-                       sDeltaAnchorPosition.set(sDeltaAnchorPositionUncommited);
-               }
-               mCameraManager.computeVisibleRange(mMediaFeed, mLayoutInterface, sDeltaAnchorPosition, sVisibleRange,
-                       sBufferedVisibleRange, sCompleteRange, mState);
-       }
-
-       private void computeVisibleItems() {
-               if (mFeedAboutToChange == true || mPerformingLayoutChange == true) {
-                       return;
-               }
-               computeVisibleRange();
-               int deltaBegin = sBufferedVisibleRange.begin - sPreviousDataRange.begin;
-               int deltaEnd = sBufferedVisibleRange.end - sPreviousDataRange.end;
-               if (deltaBegin != 0 || deltaEnd != 0) {
-                       // The delta has changed, we have to compute the display items
-                       // again.
-                       // We find the intersection range, these slots have not changed at
-                       // all.
-                       int firstVisibleSlotIndex = sBufferedVisibleRange.begin;
-                       int lastVisibleSlotIndex = sBufferedVisibleRange.end;
-                       sPreviousDataRange.begin = firstVisibleSlotIndex;
-                       sPreviousDataRange.end = lastVisibleSlotIndex;
-
-                       Pool<Vector3f> pool = sTempVec;
-                       Vector3f position = pool.create();
-                       Vector3f deltaAnchorPosition = pool.create();
-                       try {
-                               MediaFeed feed = mMediaFeed;
-                               DisplayList displayList = sDisplayList;
-                               DisplayItem[] displayItems = sDisplayItems;
-                               DisplaySlot[] displaySlots = sDisplaySlots;
-                               int numDisplayItems = displayItems.length;
-                               int numDisplaySlots = displaySlots.length;
-                               ArrayList<MediaItem> visibleItems = sVisibleItems;
-                               deltaAnchorPosition.set(sDeltaAnchorPosition);
-                               LayoutInterface layout = mLayoutInterface;
-                               GridCamera camera = mCamera;
-                               for (int i = firstVisibleSlotIndex; i <= lastVisibleSlotIndex; ++i) {
-                                       GridCameraManager.getSlotPositionForSlotIndex(i, camera, layout, deltaAnchorPosition, position);
-                                       MediaSet set = feed.getSetForSlot(i);
-                                       int indexIntoSlots = i - firstVisibleSlotIndex;
-
-                                       if (set != null && indexIntoSlots >= 0 && indexIntoSlots < numDisplaySlots) {
-                                               ArrayList<MediaItem> items = set.getItems();
-                                               displaySlots[indexIntoSlots].setMediaSet(set);
-                                               ArrayList<MediaItem> bestItems = sTempList;
-                                               if (mTimeElapsedSinceTransition < 1.0f) {
-                                                       // We always show the same top thumbnails for a
-                                                       // stack of albums
-                                                       if (mState == STATE_MEDIA_SETS)
-                                                               ArrayUtils.computeSortedIntersection(items, visibleItems, MAX_ITEMS_PER_SLOT, bestItems, sTempHash);
-                                                       else
-                                                               ArrayUtils.computeSortedIntersection(visibleItems, items, MAX_ITEMS_PER_SLOT, bestItems, sTempHash);
-                                               }
-
-                                               int numItemsInSet = set.getNumItems();
-                                               int numBestItems = bestItems.size();
-                                               int originallyFoundItems = numBestItems;
-                                               if (numBestItems < MAX_ITEMS_PER_SLOT) {
-                                                       int itemsRemaining = MAX_ITEMS_PER_SLOT - numBestItems;
-                                                       for (int currItemPos = 0; currItemPos < numItemsInSet; currItemPos++) {
-                                                               MediaItem item = items.get(currItemPos);
-                                                               if (mTimeElapsedSinceTransition >= 1.0f || !bestItems.contains(item)) {
-                                                                       bestItems.add(item);
-                                                                       if (--itemsRemaining == 0) {
-                                                                               break;
-                                                                       }
-                                                               }
-                                                       }
-                                               }
-                                               numBestItems = bestItems.size();
-                                               int baseIndex = (i - firstVisibleSlotIndex) * MAX_ITEMS_PER_SLOT;
-                                               for (int j = 0; j < numBestItems; ++j) {
-                                                       if (baseIndex + j >= numDisplayItems) {
-                                                               break;
-                                                       }
-                                                       if (j >= numItemsInSet) {
-                                                               displayItems[baseIndex + j] = null;
-                                                       } else {
-                                                               MediaItem item = bestItems.get(j);
-                                                               if (item != null) {
-                                                                       DisplayItem displayItem = displayList.get(item);
-                                                                       if ((mState == STATE_FULL_SCREEN && i != mInputProcessor.getCurrentSelectedSlot())
-                                                                               || (mState == STATE_GRID_VIEW && (mTimeElapsedSinceTransition > 1.0f || j >= originallyFoundItems))) {
-                                                                               displayItem.set(position, j, false);
-                                                                               displayItem.commit();
-                                                                       } else {
-                                                                               displayList.setPositionAndStackIndex(displayItem, position, j, true);
-                                                                       }
-                                                                       displayItems[baseIndex + j] = displayItem;
-                                                               }
-                                                       }
-                                               }
-                                               for (int j = numBestItems; j < MAX_ITEMS_PER_SLOT; ++j) {
-                                                       displayItems[baseIndex + j] = null;
-                                               }
-                                               bestItems.clear();
-                                       }
-                               }
-                               if (mFeedChanged) {
-                                       mFeedChanged = false;
-                                       if (mInputProcessor != null && mState == STATE_FULL_SCREEN && mRequestFocusContentUri == null) {
-                                               int currentSelectedSlot = mInputProcessor.getCurrentSelectedSlot();
-                                               if (currentSelectedSlot > sCompleteRange.end)
-                                                       currentSelectedSlot = sCompleteRange.end;
-                                               mInputProcessor.setCurrentSelectedSlot(currentSelectedSlot);
-                                       }
-                                       if (mState == STATE_GRID_VIEW) {
-                                               MediaSet expandedSet = mMediaFeed.getExpandedMediaSet();
-                                               if (expandedSet != null) {
-                                                       if (!mHud.getPathBar().getCurrentLabel().equals(expandedSet.mNoCountTitleString)) {
-                                                               mHud.getPathBar().changeLabel(expandedSet.mNoCountTitleString);
-                                                       }
-                                               }
-                                       }
-                                       if (mRequestFocusContentUri != null) {
-                                               // We have to find the item that has this contentUri
-                                               if (mState == STATE_FULL_SCREEN) {
-                                                       int numSlots = sCompleteRange.end + 1;
-                                                       for (int i = 0; i < numSlots; ++i) {
-                                                               MediaSet set = feed.getSetForSlot(i);
-                                                               ArrayList<MediaItem> items = set.getItems();
-                                                               int numItems = items.size();
-                                                               for (int j = 0; j < numItems; ++j) {
-                                                                       String itemUri = items.get(j).mContentUri;
-                                                                       if (itemUri != null && mRequestFocusContentUri != null) {
-                                                                               if (itemUri.equals(mRequestFocusContentUri)) {
-                                                                                       mInputProcessor.setCurrentSelectedSlot(i);
-                                                                                       break;
-                                                                               }
-                                                                       }
-                                                               }
-                                                       }
-                                               }
-                                               mRequestFocusContentUri = null;
-                                       }
-                               }
-                       } finally {
-                               pool.delete(position);
-                               pool.delete(deltaAnchorPosition);
-                       }
-                       // We keep upto 400 thumbnails in memory.
-                       int numThumbnailsToKeepInMemory = (mState == STATE_MEDIA_SETS || mState == STATE_TIMELINE) ? 100 : 400;
-                       int startMemoryRange = (sBufferedVisibleRange.begin / numThumbnailsToKeepInMemory) * numThumbnailsToKeepInMemory;
-                       if (mStartMemoryRange != startMemoryRange) {
-                               mStartMemoryRange = startMemoryRange;
-                               clearUnusedThumbnails();
-                       }
-               }
-       }
-
-       @Override
-       public void handleLowMemory() {
-               clearUnusedThumbnails();
-               GridDrawables.sStringTextureTable.clear();
-               mBackground.clearCache();
-       }
-
-       // This method can be potentially expensive
-       public void clearUnusedThumbnails() {
-               sDisplayList.clearExcept(sDisplayItems);
-       }
-
-       @Override
-       public void onSurfaceCreated(RenderView view, GL11 gl) {
-               sDisplayList.clear();
-               mHud.clear();
-               mHud.reset();
-               GridDrawables.sStringTextureTable.clear();
-               mDrawables.onSurfaceCreated(view, gl);
-               mBackground.clear();
-       }
-
-       @Override
-       public void onSurfaceChanged(RenderView view, int width, int height) {
-               mCamera.viewportChanged(width, height, mCamera.mItemWidth, mCamera.mItemHeight);
-               view.setFov(mCamera.mFov);
-               setState(mState);
-       }
-
-       // Renders the node in a given pass.
-       public void renderOpaque(RenderView view, GL11 gl) {
-               GridCamera camera = mCamera;
-               int selectedSlotIndex = mInputProcessor.getCurrentSelectedSlot();
-               computeVisibleItems();
-
-               gl.glMatrixMode(GL11.GL_MODELVIEW);
-               gl.glLoadIdentity();
-               GLU.gluLookAt(gl, -camera.mEyeX, -camera.mEyeY, -camera.mEyeZ, -camera.mLookAtX, -camera.mLookAtY, -camera.mLookAtZ,
-                       camera.mUpX, camera.mUpY, camera.mUpZ);
-               view.setAlpha(1.0f);
-               if (mSelectedAlpha != 1.0f) {
-                       gl.glEnable(GL11.GL_BLEND);
-                       gl.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
-                       view.setAlpha(mSelectedAlpha);
-               }
-               if (selectedSlotIndex != Shared.INVALID) {
-                       mTargetAlpha = 0.0f;
-               } else {
-                       mTargetAlpha = 1.0f;
-               }
-               mDrawManager.prepareDraw(sBufferedVisibleRange, sVisibleRange, selectedSlotIndex, mInputProcessor.getCurrentFocusSlot(),
-                       mInputProcessor.isFocusItemPressed());
-               if (mSelectedAlpha != 0.0f) {
-                       mDrawManager.drawThumbnails(view, gl, mState);
-               }
-               if (mSelectedAlpha != 1.0f) {
-                       gl.glDisable(GL11.GL_BLEND);
-               }
-               // We draw the selected slotIndex.
-               if (selectedSlotIndex != Shared.INVALID) {
-                       mDrawManager.drawFocusItems(view, gl, mZoomValue, mSlideshowMode, mTimeElapsedSinceView);
-                       mCurrentFocusItemWidth = mDrawManager.getFocusQuadWidth();
-                       mCurrentFocusItemHeight = mDrawManager.getFocusQuadHeight();
-               }
-               view.setAlpha(mSelectedAlpha);
-       }
-
-       public void renderBlended(RenderView view, GL11 gl) {
-               // We draw the placeholder for all visible slots.
-               if (mHud != null && mDrawManager != null) {
-                       mDrawManager.drawBlendedComponents(view, gl, mSelectedAlpha, mState, mHud.getMode(), mTimeElapsedSinceStackViewReady,
-                               mTimeElapsedSinceGridViewReady, sBucketList, mMediaFeed.getWaitingForMediaScanner() || mFeedAboutToChange
-                                       || mMediaFeed.isLoading());
-               }
-       }
-
-       public synchronized void onLayout(int newAnchorSlotIndex, int currentAnchorSlotIndex, LayoutInterface oldLayout) {
-               if (mPerformingLayoutChange || !sDeltaAnchorPosition.equals(sDeltaAnchorPositionUncommited)) {
-                       return;
-               }
-
-               mTimeElapsedSinceTransition = 0.0f;
-               mPerformingLayoutChange = true;
-               LayoutInterface layout = mLayoutInterface;
-               if (oldLayout == null) {
-                       oldLayout = sfullScreenLayoutInterface;
-               }
-               GridCamera camera = mCamera;
-               if (currentAnchorSlotIndex == Shared.INVALID) {
-                       currentAnchorSlotIndex = getAnchorSlotIndex(ANCHOR_CENTER);
-                       if (mCurrentExpandedSlot != Shared.INVALID) {
-                               currentAnchorSlotIndex = mCurrentExpandedSlot;
-                       }
-                       int selectedSlotIndex = mInputProcessor.getCurrentSelectedSlot();
-                       if (selectedSlotIndex != Shared.INVALID) {
-                               currentAnchorSlotIndex = selectedSlotIndex;
-                       }
-               }
-               if (newAnchorSlotIndex == Shared.INVALID) {
-                       newAnchorSlotIndex = currentAnchorSlotIndex;
-               }
-               int itemHeight = camera.mItemHeight;
-               int itemWidth = camera.mItemWidth;
-               Pool<Vector3f> pool = sTempVec;
-               Vector3f deltaAnchorPosition = pool.create();
-               Vector3f currentSlotPosition = pool.create();
-               try {
-                       deltaAnchorPosition.set(0, 0, 0);
-                       if (currentAnchorSlotIndex != Shared.INVALID && newAnchorSlotIndex != Shared.INVALID) {
-                               layout.getPositionForSlotIndex(newAnchorSlotIndex, itemWidth, itemHeight, deltaAnchorPosition);
-                               oldLayout.getPositionForSlotIndex(currentAnchorSlotIndex, itemWidth, itemHeight, currentSlotPosition);
-                               currentSlotPosition.subtract(sDeltaAnchorPosition);
-                               deltaAnchorPosition.subtract(currentSlotPosition);
-                               deltaAnchorPosition.y = 0;
-                               deltaAnchorPosition.z = 0;
-                       }
-                       sDeltaAnchorPositionUncommited.set(deltaAnchorPosition);
-               } finally {
-                       pool.delete(deltaAnchorPosition);
-                       pool.delete(currentSlotPosition);
-               }
-               centerCameraForSlot(newAnchorSlotIndex, 1.0f);
-               mCurrentExpandedSlot = Shared.INVALID;
-
-               // Force recompute of visible items and their positions.
-               ((GridLayoutInterface) oldLayout).mNumRows = ((GridLayoutInterface) layout).mNumRows;
-               ((GridLayoutInterface) oldLayout).mSpacingX = ((GridLayoutInterface) layout).mSpacingX;
-               ((GridLayoutInterface) oldLayout).mSpacingY = ((GridLayoutInterface) layout).mSpacingY;
-               forceRecomputeVisibleRange();
-               mPerformingLayoutChange = false;
-       }
-
-       private void forceRecomputeVisibleRange() {
-               sPreviousDataRange.begin = Shared.INVALID;
-               sPreviousDataRange.end = Shared.INVALID;
-               if (mView != null) {
-                       mView.requestRender();
-               }
-       }
-
-       // called on background thread
-       public synchronized void onFeedChanged(MediaFeed feed, boolean needsLayout) {
-               if (!needsLayout) {
-                       mFeedChanged = true;
-                       forceRecomputeVisibleRange();
-                       if (mState == STATE_GRID_VIEW || mState == STATE_FULL_SCREEN)
-                               mHud.setFeed(feed, mState, needsLayout);
-                       return;
-               }
-
-               while (mPerformingLayoutChange == true) {
-                       Thread.yield();
-               }
-               if (mState == STATE_GRID_VIEW) {
-                       if (mHud != null) {
-                               MediaSet set = feed.getCurrentSet();
-                               if (set != null && !mLocationFilter)
-                                       mHud.getPathBar().changeLabel(set.mNoCountTitleString);
-                       }
-               }
-               DisplayItem[] displayItems = sDisplayItems;
-               int firstBufferedVisibleSlotIndex = sBufferedVisibleRange.begin;
-               int lastBufferedVisibleSlotIndex = sBufferedVisibleRange.end;
-               int currentlyVisibleSlotIndex = getAnchorSlotIndex(ANCHOR_CENTER);
-               if (mCurrentExpandedSlot != Shared.INVALID) {
-                       currentlyVisibleSlotIndex = mCurrentExpandedSlot;
-               }
-               MediaItem anchorItem = null;
-               ArrayList<MediaItem> visibleItems = sVisibleItems;
-               visibleItems.clear();
-               visibleItems.ensureCapacity(lastBufferedVisibleSlotIndex - firstBufferedVisibleSlotIndex);
-               if (currentlyVisibleSlotIndex != Shared.INVALID && currentlyVisibleSlotIndex >= firstBufferedVisibleSlotIndex
-                       && currentlyVisibleSlotIndex <= lastBufferedVisibleSlotIndex) {
-                       int baseIndex = (currentlyVisibleSlotIndex - firstBufferedVisibleSlotIndex) * MAX_ITEMS_PER_SLOT;
-                       for (int i = 0; i < MAX_ITEMS_PER_SLOT; ++i) {
-                               DisplayItem displayItem = displayItems[baseIndex + i];
-                               if (displayItem != null) {
-                                       if (anchorItem == null) {
-                                               anchorItem = displayItem.mItemRef;
-                                       }
-                                       visibleItems.add(displayItem.mItemRef);
-                               }
-                       }
-               }
-               // We want to add items from the middle.
-               int numItems = lastBufferedVisibleSlotIndex - firstBufferedVisibleSlotIndex + 1;
-               int midPoint = (lastBufferedVisibleSlotIndex - firstBufferedVisibleSlotIndex) / 2;
-               int length = displayItems.length;
-               for (int i = 0; i < numItems; ++i) {
-                       int index = midPoint + Shared.midPointIterator(i);
-                       int indexIntoDisplayItem = (index - firstBufferedVisibleSlotIndex) * MAX_ITEMS_PER_SLOT;
-                       if (indexIntoDisplayItem >= 0 && indexIntoDisplayItem < length) {
-                               for (int j = 0; j < MAX_ITEMS_PER_SLOT; ++j) {
-                                       DisplayItem displayItem = displayItems[indexIntoDisplayItem + j];
-                                       if (displayItem != null) {
-                                               MediaItem item = displayItem.mItemRef;
-                                               if (item != anchorItem) {
-                                                       visibleItems.add(item);
-                                               }
-                                       }
-                               }
-                       }
-               }
-               int newSlotIndex = Shared.INVALID;
-               if (anchorItem != null) {
-                       // We try to find the anchor item in the new feed.
-                       int numSlots = feed.getNumSlots();
-                       for (int i = 0; i < numSlots; ++i) {
-                               MediaSet set = feed.getSetForSlot(i);
-                               if (set != null && set.containsItem(anchorItem)) {
-                                       newSlotIndex = i;
-                                       break;
-                               }
-                       }
-               }
-
-               if (anchorItem != null && newSlotIndex == Shared.INVALID) {
-                       int numSlots = feed.getNumSlots();
-                       MediaSet parentSet = anchorItem.mParentMediaSet;
-                       for (int i = 0; i < numSlots; ++i) {
-                               MediaSet set = feed.getSetForSlot(i);
-                               if (set != null && set.mId == parentSet.mId) {
-                                       newSlotIndex = i;
-                                       break;
-                               }
-                       }
-               }
-
-               // We must create a new display store now since the data has changed.
-               if (newSlotIndex != Shared.INVALID) {
-                       if (mState == STATE_MEDIA_SETS) {
-                               sDisplayList.clearExcept(displayItems);
-                       }
-                       onLayout(newSlotIndex, currentlyVisibleSlotIndex, null);
-               } else {
-                       forceRecomputeVisibleRange();
-               }
-               mCurrentExpandedSlot = Shared.INVALID;
-               mFeedAboutToChange = false;
-               mFeedChanged = true;
-               if (feed != null) {
-                       if (mState == STATE_GRID_VIEW || mState == STATE_FULL_SCREEN)
-                               mHud.setFeed(feed, mState, needsLayout);
-               }
-               if (mView != null) {
-                       mView.requestRender();
-               }
-       }
-
-       public DisplayItem getRepresentativeDisplayItem() {
-               int slotIndex = Shared.INVALID;
-               if (mInputProcessor != null) {
-                       slotIndex = mInputProcessor.getCurrentFocusSlot();
-               }
-               if (slotIndex == Shared.INVALID) {
-                       slotIndex = getAnchorSlotIndex(ANCHOR_CENTER);
-               }
-               int index = (slotIndex - sBufferedVisibleRange.begin) * MAX_ITEMS_PER_SLOT;
-               if (index >= 0 && index < MAX_ITEMS_DRAWABLE) {
-                       return sDisplayItems[index];
-               } else {
-                       return null;
-               }
-       }
-
-       public DisplayItem getAnchorDisplayItem(int type) {
-               int slotIndex = getAnchorSlotIndex(type);
-               return sDisplayItems[(slotIndex - sBufferedVisibleRange.begin) * MAX_ITEMS_PER_SLOT];
-       }
-
-       public float getScrollPosition() {
-               return (mCamera.mLookAtX * mCamera.mScale + sDeltaAnchorPosition.x); // in
-               // pixels
-       }
-
-       public DisplayItem getDisplayItemForScrollPosition(float posX) {
-               Pool<Vector3f> pool = sTempVecAlt;
-               MediaFeed feed = mMediaFeed;
-               int itemWidth = mCamera.mItemWidth;
-               int itemHeight = mCamera.mItemHeight;
-               GridLayoutInterface gridInterface = (GridLayoutInterface) mLayoutInterface;
-               float absolutePosX = posX;
-               int left = (int) ((absolutePosX / itemWidth) * gridInterface.mNumRows);
-               int right = feed == null ? 0 : (int) (feed.getNumSlots());
-               int retSlot = left;
-               Vector3f position = pool.create();
-               try {
-                       for (int i = left; i < right; ++i) {
-                               gridInterface.getPositionForSlotIndex(i, itemWidth, itemHeight, position);
-                               retSlot = i;
-                               if (position.x >= absolutePosX) {
-                                       break;
-                               }
-                       }
-               } finally {
-                       pool.delete(position);
-               }
-               if (mFeedAboutToChange) {
-                       return null;
-               }
-               right = feed == null ? 0 : feed.getNumSlots();
-               if (right == 0) {
-                       return null;
-               }
-
-               if (retSlot >= right)
-                       retSlot = right - 1;
-               MediaSet set = feed.getSetForSlot(retSlot);
-               if (set != null) {
-                       ArrayList<MediaItem> items = set.getItems();
-                       if (items != null && set.getNumItems() > 0) {
-                               return (sDisplayList.get(items.get(0)));
-                       }
-               }
-               return null;
-       }
-
-       // Returns the top left-most item.
-       public int getAnchorSlotIndex(int anchorType) {
-               int retVal = 0;
-               switch (anchorType) {
-               case ANCHOR_LEFT:
-                       retVal = sVisibleRange.begin;
-                       break;
-               case ANCHOR_RIGHT:
-                       retVal = sVisibleRange.end;
-                       break;
-               case ANCHOR_CENTER:
-                       retVal = (sVisibleRange.begin + sVisibleRange.end) / 2;
-                       break;
-               }
-               return retVal;
-       }
-
-       DisplayItem getDisplayItemForSlotId(int slotId) {
-               int index = slotId - sBufferedVisibleRange.begin;
-               if (index >= 0 && slotId <= sBufferedVisibleRange.end) {
-                       return sDisplayItems[index * MAX_ITEMS_PER_SLOT];
-               }
-               return null;
-       }
-
-       boolean changeFocusToNextSlot(float convergence) {
-               int currentSelectedSlot = mInputProcessor.getCurrentSelectedSlot();
-               boolean retVal = changeFocusToSlot(currentSelectedSlot + 1, convergence);
-               if (mInputProcessor.getCurrentSelectedSlot() == currentSelectedSlot) {
-                       endSlideshow();
-                       mHud.setAlpha(1.0f);
-               }
-               return retVal;
-       }
-
-       boolean changeFocusToSlot(int slotId, float convergence) {
-               mZoomValue = 1.0f;
-               int index = slotId - sBufferedVisibleRange.begin;
-               if (index >= 0 && slotId <= sBufferedVisibleRange.end) {
-                       DisplayItem displayItem = sDisplayItems[index * MAX_ITEMS_PER_SLOT];
-                       if (displayItem != null) {
-                               MediaItem item = displayItem.mItemRef;
-                               mHud.fullscreenSelectionChanged(item, slotId + 1, sCompleteRange.end + 1);
-                               if (slotId != Shared.INVALID && slotId <= sCompleteRange.end) {
-                                       mInputProcessor.setCurrentFocusSlot(slotId);
-                                       centerCameraForSlot(slotId, convergence);
-                                       return true;
-                               } else {
-                                       centerCameraForSlot(mInputProcessor.getCurrentSelectedSlot(), convergence);
-                                       return false;
-                               }
-                       }
-               }
-               return false;
-       }
-
-       boolean changeFocusToPreviousSlot(float convergence) {
-               return changeFocusToSlot(mInputProcessor.getCurrentSelectedSlot() - 1, convergence);
-       }
-
-       public ArrayList<MediaBucket> getSelectedBuckets() {
-               return sBucketList.get();
-       }
-
-       public void selectAll() {
-               if (mState != STATE_FULL_SCREEN) {
-                       int numSlots = sCompleteRange.end + 1;
-                       for (int i = 0; i < numSlots; ++i) {
-                               addSlotToSelectedItems(i, false, false);
-                       }
-                       updateCountOfSelectedItems();
-               } else {
-                       addSlotToSelectedItems(mInputProcessor.getCurrentFocusSlot(), false, true);
-               }
-       }
-
-       public void deselectOrCancelSelectMode() {
-               if (sBucketList.size() == 0) {
-                       mHud.cancelSelection();
-               } else {
-                       sBucketList.clear();
-                       updateCountOfSelectedItems();
-               }
-       }
-
-       public void deselectAll() {
-               mHud.cancelSelection();
-               sBucketList.clear();
-               updateCountOfSelectedItems();
-       }
-
-       public void deleteSelection() {
-               // Delete the selection and exit selection mode.
-               mMediaFeed.performOperation(MediaFeed.OPERATION_DELETE, getSelectedBuckets(), null);
-               deselectAll();
-
-               // If the current set is now empty, return to the parent set.
-               if (sCompleteRange.isEmpty()) {
-                       goBack(); // TODO(venkat): This does not work most of the time, can
-                                         // you take a look?
-               }
-       }
-
-       void addSlotToSelectedItems(int slotId, boolean removeIfAlreadyAdded, boolean updateCount) {
-               if (mFeedAboutToChange == false) {
-                       MediaFeed feed = mMediaFeed;
-                       sBucketList.add(slotId, feed, removeIfAlreadyAdded);
-                       if (updateCount) {
-                               updateCountOfSelectedItems();
-                               if (sBucketList.size() == 0)
-                                       deselectAll();
-                       }
-               }
-               mHud.computeBottomMenu();
-       }
-
-       private void updateCountOfSelectedItems() {
-               mHud.updateNumItemsSelected(sBucketList.size());
-       }
-
-       public int getMetadataSlotIndexForScreenPosition(int posX, int posY) {
-               return getSlotForScreenPosition(posX, posY, mCamera.mItemWidth + (int) (100 * Gallery.PIXEL_DENSITY), mCamera.mItemHeight
-                       + (int) (100 * Gallery.PIXEL_DENSITY));
-       }
-
-       public int getSlotIndexForScreenPosition(int posX, int posY) {
-               return getSlotForScreenPosition(posX, posY, mCamera.mItemWidth, mCamera.mItemHeight);
-       }
-
-       private int getSlotForScreenPosition(int posX, int posY, int itemWidth, int itemHeight) {
-               Pool<Vector3f> pool = sTempVec;
-               int retVal = 0;
-               Vector3f worldPos = pool.create();
-               try {
-                       GridCamera camera = mCamera;
-                       camera.convertToCameraSpace(posX, posY, 0, worldPos);
-                       // slots are expressed in pixels as well
-                       worldPos.x *= camera.mScale;
-                       worldPos.y *= camera.mScale;
-                       // we ignore z
-                       retVal = hitTest(worldPos, itemWidth, itemHeight);
-               } finally {
-                       pool.delete(worldPos);
-               }
-               return retVal;
-       }
-
-       public boolean tapGesture(int slotIndex, boolean metadata) {
-               MediaFeed feed = mMediaFeed;
-               if (!feed.isClustered()) {
-                       // It is not clustering.
-                       if (!feed.hasExpandedMediaSet()) {
-                               if (feed.canExpandSet(slotIndex)) {
-                                       mCurrentExpandedSlot = slotIndex;
-                                       feed.expandMediaSet(slotIndex);
-                                       setState(STATE_GRID_VIEW);
-                               }
-                               return false;
-                       } else {
-                               return true;
-                       }
-               } else {
-                       // Select a cluster, and recompute a new cluster within this
-                       // cluster.
-                       mCurrentExpandedSlot = slotIndex;
-                       goBack();
-                       if (metadata) {
-                               DisplaySlot slot = sDisplaySlots[slotIndex - sBufferedVisibleRange.begin];
-                               if (slot.hasValidLocation()) {
-                                       MediaSet set = slot.getMediaSet();
-                                       if (set.mReverseGeocodedLocation != null) {
-                                               enableLocationFiltering(set.mReverseGeocodedLocation);
-                                       }
-                                       feed.setFilter(new LocationMediaFilter(set.mMinLatLatitude, set.mMinLonLongitude, set.mMaxLatLatitude,
-                                               set.mMaxLonLongitude));
-                               }
-                       }
-                       return false;
-               }
-       }
-
-       public void onTimeChanged(TimeBar timebar) {
-               if (mFeedAboutToChange) {
-                       return;
-               }
-               // TODO lot of optimization possible here
-               MediaItem item = timebar.getItem();
-               MediaFeed feed = mMediaFeed;
-               int numSlots = feed.getNumSlots();
-               for (int i = 0; i < numSlots; ++i) {
-                       MediaSet set = feed.getSetForSlot(i);
-                       if (set == null) {
-                               return;
-                       }
-                       ArrayList<MediaItem> items = set.getItems();
-                       if (items == null || set.getNumItems() == 0) {
-                               return;
-                       }
-                       if (items.contains(item)) {
-                               centerCameraForSlot(i, 1.0f);
-                               break;
-                       }
-               }
-       }
-
-       public void onFeedAboutToChange(MediaFeed feed) {
-               mFeedAboutToChange = true;
-               mTimeElapsedSinceTransition = 0;
-       }
-
-       public void startSlideshow() {
-               endSlideshow();
-               mSlideshowMode = true;
-               mZoomValue = 1.0f;
-               centerCameraForSlot(mInputProcessor.getCurrentSelectedSlot(), 1.0f);
-               mTimeElapsedSinceView = SLIDESHOW_TRANSITION_TIME - 1.0f;
-               mHud.setAlpha(0);
-               PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
-               mWakeLock = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "GridView.Slideshow");
-               mWakeLock.acquire();
-       }
-
-       public void enterSelectionMode() {
-               mSlideshowMode = false;
-               mHud.enterSelectionMode();
-               int currentSlot = mInputProcessor.getCurrentSelectedSlot();
-               if (currentSlot == Shared.INVALID) {
-                       currentSlot = mInputProcessor.getCurrentFocusSlot();
-               }
-               addSlotToSelectedItems(currentSlot, false, true);
-       }
-
-       private float getFillScreenZoomValue() {
-               return GridCameraManager.getFillScreenZoomValue(mCamera, sTempVec, mCurrentFocusItemWidth, mCurrentFocusItemHeight);
-       }
-
-       public void zoomInToSelectedItem() {
-               mSlideshowMode = false;
-               float potentialZoomValue = getFillScreenZoomValue();
-               if (mZoomValue < potentialZoomValue) {
-                       mZoomValue = potentialZoomValue;
-               } else {
-                       mZoomValue *= 3.0f;
-               }
-               if (mZoomValue > 6.0f) {
-                       mZoomValue = 6.0f;
-               }
-               mHud.setAlpha(1.0f);
-               centerCameraForSlot(mInputProcessor.getCurrentSelectedSlot(), 1.0f);
-       }
-
-       public void zoomOutFromSelectedItem() {
-               mSlideshowMode = false;
-               if (mZoomValue == getFillScreenZoomValue()) {
-                       mZoomValue = 1.0f;
-               } else {
-                       mZoomValue /= 3.0f;
-               }
-               if (mZoomValue < 1.0f) {
-                       mZoomValue = 1.0f;
-               }
-               mHud.setAlpha(1.0f);
-               centerCameraForSlot(mInputProcessor.getCurrentSelectedSlot(), 1.0f);
-       }
-
-       public void rotateSelectedItems(float f) {
-               MediaBucketList bucketList = sBucketList;
-               ArrayList<MediaBucket> mediaBuckets = bucketList.get();
-               DisplayList displayList = sDisplayList;
-               int numBuckets = mediaBuckets.size();
-               for (int i = 0; i < numBuckets; ++i) {
-                       MediaBucket bucket = mediaBuckets.get(i);
-                       ArrayList<MediaItem> mediaItems = bucket.mediaItems;
-                       if (mediaItems != null) {
-                               int numMediaItems = mediaItems.size();
-                               for (int j = 0; j < numMediaItems; ++j) {
-                                       MediaItem item = mediaItems.get(j);
-                                       DisplayItem displayItem = displayList.get(item);
-                                       displayItem.rotateImageBy(f);
-                                       displayList.addToAnimatables(displayItem);
-                               }
-                       }
-               }
-               if (mState == STATE_FULL_SCREEN) {
-                       centerCameraForSlot(mInputProcessor.getCurrentSelectedSlot(), 1.0f);
-               }
-               mMediaFeed.performOperation(MediaFeed.OPERATION_ROTATE, mediaBuckets, new Float(f));
-               // we recreate these displayitems from the cache
-       }
-
-       public void cropSelectedItem() {
-
-       }
-
-       @Override
-       public boolean onTouchEvent(MotionEvent event) {
-               return mInputProcessor.onTouchEvent(event);
-       }
-
-       @Override
-       public boolean onKeyDown(int keyCode, KeyEvent event) {
-               if (mInputProcessor != null)
-                       return mInputProcessor.onKeyDown(keyCode, event, mState);
-               return false;
-       }
-
-       public boolean inSlideShowMode() {
-               return mSlideshowMode;
-       }
-
-       public boolean noDeleteMode() {
-               return mNoDeleteMode || (mMediaFeed != null && mMediaFeed.isSingleImageMode());
-       }
-
-       public float getZoomValue() {
-               return mZoomValue;
-       }
-
-       public boolean feedAboutToChange() {
-               return mFeedAboutToChange;
-       }
-
-       public boolean isInAlbumMode() {
-               return mInAlbum;
-       }
-
-       public Vector3f getDeltaAnchorPosition() {
-               return sDeltaAnchorPosition;
-       }
-
-       public int getExpandedSlot() {
-               return mCurrentExpandedSlot;
-       }
-
-       public GridLayoutInterface getLayoutInterface() {
-               return (GridLayoutInterface) mLayoutInterface;
-       }
-
-       public void setZoomValue(float f) {
-               mZoomValue = f;
-               centerCameraForSlot(mInputProcessor.getCurrentSelectedSlot(), 1.0f);
-       }
-
-       public void setPickIntent(boolean b) {
-               mPickIntent = b;
-               mHud.getPathBar().popLabel();
-               mHud.getPathBar().pushLabel(R.drawable.icon_location_small, mContext.getResources().getString(R.string.pick),
-                       new Runnable() {
-                               public void run() {
-                                       if (mHud.getAlpha() == 1.0f) {
-                                               if (!mFeedAboutToChange) {
-                                                       setState(STATE_MEDIA_SETS);
-                                               }
-                                       } else {
-                                               mHud.setAlpha(1.0f);
-                                       }
-                               }
-                       });
-       }
-
-       public boolean getPickIntent() {
-               return mPickIntent;
-       }
-
-       public void setViewIntent(boolean b, final String setName) {
-               mViewIntent = b;
-               if (b) {
-                       mMediaFeed.expandMediaSet(0);
-                       setState(STATE_GRID_VIEW);
-                       // We need to make sure we haven't pushed the same label twice
-                       if (mHud.getPathBar().getNumLevels() == 1) {
-                               mHud.getPathBar().pushLabel(R.drawable.icon_folder_small, setName, new Runnable() {
-                                       public void run() {
-                                               if (mFeedAboutToChange) {
-                                                       return;
-                                               }
-                                               if (mHud.getAlpha() == 1.0f) {
-                                                       disableLocationFiltering();
-                                                       if (mInputProcessor != null)
-                                                               mInputProcessor.clearSelection();
-                                                       setState(STATE_GRID_VIEW);
-                                               } else {
-                                                       mHud.setAlpha(1.0f);
-                                               }
-                                       }
-                               });
-                       }
-               }
-       }
-
-       public boolean getViewIntent() {
-               return mViewIntent;
-       }
-
-       public void setSingleImage(boolean noDeleteMode) {
-               mNoDeleteMode = noDeleteMode;
-               mInputProcessor.setCurrentSelectedSlot(0);
-       }
-
-       public MediaFeed getFeed() {
-               return mMediaFeed;
-       }
-
-       public void markDirty(int numFrames) {
-               mFramesDirty = numFrames;
-       }
-
-       public void focusItem(String contentUri) {
-               mRequestFocusContentUri = contentUri;
-               mMediaFeed.updateListener(false);
-       }
+    public static final int STATE_MEDIA_SETS = 0;
+    public static final int STATE_GRID_VIEW = 1;
+    public static final int STATE_FULL_SCREEN = 2;
+    public static final int STATE_TIMELINE = 3;
+
+    public static final int ANCHOR_LEFT = 0;
+    public static final int ANCHOR_RIGHT = 1;
+    public static final int ANCHOR_CENTER = 2;
+
+    public static final int MAX_ITEMS_PER_SLOT = 12;
+    public static final int MAX_DISPLAYED_ITEMS_PER_SLOT = 4;
+    public static final int MAX_DISPLAY_SLOTS = 96;
+    public static final int MAX_ITEMS_DRAWABLE = MAX_ITEMS_PER_SLOT * MAX_DISPLAY_SLOTS;
+
+    private static final float SLIDESHOW_TRANSITION_TIME = 3.5f;
+
+    private HudLayer mHud;
+    private int mState;
+    private static final IndexRange sBufferedVisibleRange = new IndexRange();
+    private static final IndexRange sVisibleRange = new IndexRange();
+    private static final IndexRange sPreviousDataRange = new IndexRange();
+    private static final IndexRange sCompleteRange = new IndexRange();
+
+    private static final Pool<Vector3f> sTempVec;
+    private static final Pool<Vector3f> sTempVecAlt;
+    static {
+        Vector3f[] vectorPool = new Vector3f[128];
+        int length = vectorPool.length;
+        for (int i = 0; i < length; ++i) {
+            vectorPool[i] = new Vector3f();
+        }
+        Vector3f[] vectorPoolRenderThread = new Vector3f[128];
+        length = vectorPoolRenderThread.length;
+        for (int i = 0; i < length; ++i) {
+            vectorPoolRenderThread[i] = new Vector3f();
+        }
+        sTempVec = new Pool<Vector3f>(vectorPool);
+        sTempVecAlt = new Pool<Vector3f>(vectorPoolRenderThread);
+    }
+
+    private static final ArrayList<MediaItem> sTempList = new ArrayList<MediaItem>();
+    private static final MediaItem[] sTempHash = new MediaItem[64];
+
+    private static final Vector3f sDeltaAnchorPositionUncommited = new Vector3f();
+    private static Vector3f sDeltaAnchorPosition = new Vector3f();
+
+    // The display primitives.
+    final private GridDrawables mDrawables;
+    private float mSelectedAlpha = 0.0f;
+    private float mTargetAlpha = 0.0f;
+
+    final private GridCamera mCamera;
+    final private GridCameraManager mCameraManager;
+    final private GridDrawManager mDrawManager;
+    final private GridInputProcessor mInputProcessor;
+
+    private boolean mFeedAboutToChange;
+    private boolean mPerformingLayoutChange;
+    private boolean mFeedChanged;
+
+    private final LayoutInterface mLayoutInterface;
+    private static final LayoutInterface sfullScreenLayoutInterface = new GridLayoutInterface(1);
+
+    private MediaFeed mMediaFeed;
+    private boolean mInAlbum = false;
+    private int mCurrentExpandedSlot;
+
+    private static final DisplayList sDisplayList = new DisplayList();
+    private static final DisplayItem[] sDisplayItems = new DisplayItem[MAX_ITEMS_DRAWABLE];
+    private static final DisplaySlot[] sDisplaySlots = new DisplaySlot[MAX_DISPLAY_SLOTS];
+    private static ArrayList<MediaItem> sVisibleItems;
+
+    private float mTimeElapsedSinceTransition;
+    private final BackgroundLayer mBackground;
+    private boolean mLocationFilter;
+    private float mZoomValue = 1.0f;
+    private float mCurrentFocusItemWidth = 1.0f;
+    private float mCurrentFocusItemHeight = 1.0f;
+    private float mTimeElapsedSinceGridViewReady = 0.0f;
+
+    private boolean mSlideshowMode;
+    private boolean mNoDeleteMode = false;
+    private float mTimeElapsedSinceView;
+    private static final MediaBucketList sSelectedBucketList = new MediaBucketList();
+    private static final MediaBucketList sMarkedBucketList = new MediaBucketList();
+    private float mTimeElapsedSinceStackViewReady;
+
+    private Context mContext;
+    private RenderView mView;
+    private boolean mPickIntent;
+    private boolean mViewIntent;
+    private WakeLock mWakeLock;
+    private int mStartMemoryRange;
+    private int mFramesDirty;
+    private String mRequestFocusContentUri;
+    private int mFrameCount;
+
+    public GridLayer(Context context, int itemWidth, int itemHeight, LayoutInterface layoutInterface, RenderView view) {
+        mBackground = new BackgroundLayer(this);
+        mContext = context;
+        mView = view;
+
+        DisplaySlot[] displaySlots = sDisplaySlots;
+        for (int i = 0; i < MAX_DISPLAY_SLOTS; ++i) {
+            DisplaySlot slot = new DisplaySlot();
+            displaySlots[i] = slot;
+        }
+        mLayoutInterface = layoutInterface;
+        mCamera = new GridCamera(0, 0, itemWidth, itemHeight);
+        mDrawables = new GridDrawables(itemWidth, itemHeight);
+        sBufferedVisibleRange.set(Shared.INVALID, Shared.INVALID);
+        sVisibleRange.set(Shared.INVALID, Shared.INVALID);
+        sCompleteRange.set(Shared.INVALID, Shared.INVALID);
+        sPreviousDataRange.set(Shared.INVALID, Shared.INVALID);
+        sDeltaAnchorPosition.set(0, 0, 0);
+        sDeltaAnchorPositionUncommited.set(0, 0, 0);
+        sSelectedBucketList.clear();
+
+        sVisibleItems = new ArrayList<MediaItem>();
+        mHud = new HudLayer(context);
+        mHud.setContext(context);
+        mHud.setGridLayer(this);
+        mHud.getPathBar().clear();
+        mHud.setGridLayer(this);
+        mHud.getTimeBar().setListener(this);
+        mHud.getPathBar().pushLabel(R.drawable.icon_home_small, context.getResources().getString(R.string.app_name),
+                new Runnable() {
+                    public void run() {
+                        if (mHud.getAlpha() == 1.0f) {
+                            if (!mFeedAboutToChange) {
+                                setState(STATE_MEDIA_SETS);
+                            }
+                        } else {
+                            mHud.setAlpha(1.0f);
+                        }
+                    }
+                });
+        mCameraManager = new GridCameraManager(mCamera);
+        mDrawManager = new GridDrawManager(context, mCamera, mDrawables, sDisplayList, sDisplayItems, sDisplaySlots);
+        mInputProcessor = new GridInputProcessor(context, mCamera, this, mView, sTempVec, sDisplayItems);
+        setState(STATE_MEDIA_SETS);
+    }
+
+    public HudLayer getHud() {
+        return mHud;
+    }
+
+    public void shutdown() {
+        if (mMediaFeed != null) {
+            mMediaFeed.shutdown();
+        }
+        mContext = null;
+        sSelectedBucketList.clear();
+        mView = null;
+    }
+
+    public void stop() {
+        endSlideshow();
+        mBackground.clear();
+        handleLowMemory();
+    }
+
+    @Override
+    public void generate(RenderView view, RenderView.Lists lists) {
+        lists.updateList.add(this);
+        lists.opaqueList.add(this);
+        mBackground.generate(view, lists);
+        lists.blendedList.add(this);
+        lists.hitTestList.add(this);
+        mHud.generate(view, lists);
+    }
+
+    @Override
+    protected void onSizeChanged() {
+        mHud.setSize(mWidth, mHeight);
+        mHud.setAlpha(1.0f);
+        mBackground.setSize(mWidth, mHeight);
+        mTimeElapsedSinceTransition = 0.0f;
+        if (mView != null) {
+            mView.requestRender();
+        }
+    }
+
+    public int getState() {
+        return mState;
+    }
+
+    public void setState(int state) {
+        boolean feedUnchanged = false;
+        if (mState == state) {
+            feedUnchanged = true;
+        }
+        GridLayoutInterface layoutInterface = (GridLayoutInterface) mLayoutInterface;
+        GridLayoutInterface oldLayout = (GridLayoutInterface) sfullScreenLayoutInterface;
+        oldLayout.mNumRows = layoutInterface.mNumRows;
+        oldLayout.mSpacingX = layoutInterface.mSpacingX;
+        oldLayout.mSpacingY = layoutInterface.mSpacingY;
+        GridCamera camera = mCamera;
+        int numMaxRows = (camera.mHeight >= camera.mWidth) ? 4 : 3;
+        MediaFeed feed = mMediaFeed;
+        boolean performLayout = true;
+        mZoomValue = 1.0f;
+        float yStretch = camera.mDefaultAspectRatio / camera.mAspectRatio;
+        if (yStretch < 1.0f) {
+            yStretch = 1.0f;
+        }
+        switch (state) {
+        case STATE_GRID_VIEW:
+            mTimeElapsedSinceGridViewReady = 0.0f;
+            if (feed != null && feedUnchanged == false) {
+                boolean updatedData = feed.restorePreviousClusteringState();
+                if (updatedData) {
+                    performLayout = false;
+                }
+            }
+            layoutInterface.mNumRows = numMaxRows;
+            layoutInterface.mSpacingX = (int) (10 * Gallery.PIXEL_DENSITY);
+            layoutInterface.mSpacingY = (int) (10 * Gallery.PIXEL_DENSITY);
+            if (mState == STATE_MEDIA_SETS) {
+                // Entering album.
+                mInAlbum = true;
+                MediaSet set = feed.getCurrentSet();
+                int icon = mDrawables.getIconForSet(set, true);
+                if (set != null) {
+                    mHud.getPathBar().pushLabel(icon, set.mNoCountTitleString, new Runnable() {
+                        public void run() {
+                            if (mFeedAboutToChange) {
+                                return;
+                            }
+                            if (mHud.getAlpha() == 1.0f) {
+                                disableLocationFiltering();
+                                mInputProcessor.clearSelection();
+                                setState(STATE_GRID_VIEW);
+                            } else {
+                                mHud.setAlpha(1.0f);
+                            }
+                        }
+                    });
+                }
+            }
+            if (mState == STATE_FULL_SCREEN) {
+                mHud.getPathBar().popLabel();
+            }
+            break;
+        case STATE_TIMELINE:
+            mTimeElapsedSinceStackViewReady = 0.0f;
+            if (feed != null && feedUnchanged == false) {
+                feed.performClustering();
+                performLayout = false;
+            }
+            disableLocationFiltering();
+            layoutInterface.mNumRows = numMaxRows - 1;
+            layoutInterface.mSpacingX = (int) (100 * Gallery.PIXEL_DENSITY);
+            layoutInterface.mSpacingY = (int) (70 * Gallery.PIXEL_DENSITY * yStretch);
+            break;
+        case STATE_FULL_SCREEN:
+            layoutInterface.mNumRows = 1;
+            layoutInterface.mSpacingX = (int) (40 * Gallery.PIXEL_DENSITY);
+            layoutInterface.mSpacingY = (int) (40 * Gallery.PIXEL_DENSITY);
+            if (mState != STATE_FULL_SCREEN) {
+                mHud.getPathBar().pushLabel(R.drawable.ic_fs_details, "", new Runnable() {
+                    public void run() {
+                        if (mHud.getAlpha() == 1.0f) {
+                            mHud.swapFullscreenLabel();
+                        }
+                        mHud.setAlpha(1.0f);
+                    }
+                });
+            }
+            break;
+        case STATE_MEDIA_SETS:
+            mTimeElapsedSinceStackViewReady = 0.0f;
+            if (feed != null && feedUnchanged == false) {
+                feed.restorePreviousClusteringState();
+                sMarkedBucketList.clear();
+                feed.expandMediaSet(Shared.INVALID);
+                performLayout = false;
+            }
+            disableLocationFiltering();
+            mInputProcessor.clearSelection();
+            layoutInterface.mNumRows = numMaxRows - 1;
+            layoutInterface.mSpacingX = (int) (100 * Gallery.PIXEL_DENSITY);
+            layoutInterface.mSpacingY = (int) (70 * Gallery.PIXEL_DENSITY * yStretch);
+            if (mInAlbum) {
+                if (mState == STATE_FULL_SCREEN) {
+                    mHud.getPathBar().popLabel();
+                }
+                mHud.getPathBar().popLabel();
+                mInAlbum = false;
+            }
+            break;
+        }
+        mState = state;
+        mHud.onGridStateChanged();
+        if (performLayout && mFeedAboutToChange == false) {
+            onLayout(Shared.INVALID, Shared.INVALID, oldLayout);
+        }
+        if (state != STATE_FULL_SCREEN) {
+            mCamera.moveYTo(0);
+            mCamera.moveZTo(0);
+        }
+    }
+
+    protected void enableLocationFiltering(String label) {
+        if (mLocationFilter == false) {
+            mLocationFilter = true;
+            mHud.getPathBar().pushLabel(R.drawable.icon_location_small, label, new Runnable() {
+                public void run() {
+                    if (mHud.getAlpha() == 1.0f) {
+                        if (mState == STATE_FULL_SCREEN) {
+                            mInputProcessor.clearSelection();
+                            setState(STATE_GRID_VIEW);
+                        } else {
+                            disableLocationFiltering();
+                        }
+                    } else {
+                        mHud.setAlpha(1.0f);
+                    }
+                }
+            });
+        }
+    }
+
+    protected void disableLocationFiltering() {
+        if (mLocationFilter) {
+            mLocationFilter = false;
+            mMediaFeed.removeFilter();
+            mHud.getPathBar().popLabel();
+        }
+    }
+
+    boolean goBack() {
+        if (mFeedAboutToChange) {
+            return false;
+        }
+        int state = mState;
+        if (mInputProcessor.getCurrentSelectedSlot() == Shared.INVALID) {
+            if (mLocationFilter) {
+                disableLocationFiltering();
+                setState(STATE_TIMELINE);
+                return true;
+            }
+        }
+        switch (state) {
+        case STATE_GRID_VIEW:
+            setState(STATE_MEDIA_SETS);
+            break;
+        case STATE_TIMELINE:
+            setState(STATE_GRID_VIEW);
+            break;
+        case STATE_FULL_SCREEN:
+            setState(STATE_GRID_VIEW);
+            mInputProcessor.clearSelection();
+            break;
+        default:
+            return false;
+        }
+        return true;
+    }
+
+    public void endSlideshow() {
+        mSlideshowMode = false;
+        if (mWakeLock != null) {
+            if (mWakeLock.isHeld()) {
+                mWakeLock.release();
+            }
+            mWakeLock = null;
+        }
+        mHud.setAlpha(1.0f);
+    }
+
+    @Override
+    public void onSensorChanged(RenderView view, SensorEvent event) {
+        mInputProcessor.onSensorChanged(view, event, mState);
+    }
+
+    public DataSource getDataSource() {
+        if (mMediaFeed != null)
+            return mMediaFeed.getDataSource();
+        return null;
+    }
+
+    public void setDataSource(DataSource dataSource) {
+        MediaFeed feed = mMediaFeed;
+        if (feed != null) {
+            feed.shutdown();
+            sDisplayList.clear();
+            mBackground.clear();
+        }
+        mMediaFeed = new MediaFeed(mContext, dataSource, this);
+        mMediaFeed.start();
+    }
+
+    public IndexRange getVisibleRange() {
+        return sVisibleRange;
+    }
+
+    public IndexRange getBufferedVisibleRange() {
+        return sBufferedVisibleRange;
+    }
+
+    public IndexRange getCompleteRange() {
+        return sCompleteRange;
+    }
+
+    private int hitTest(Vector3f worldPos, int itemWidth, int itemHeight) {
+        int retVal = Shared.INVALID;
+        int firstSlotIndex = 0;
+        int lastSlotIndex = 0;
+        IndexRange rangeToUse = sVisibleRange;
+        synchronized (rangeToUse) {
+            firstSlotIndex = rangeToUse.begin;
+            lastSlotIndex = rangeToUse.end;
+        }
+        Pool<Vector3f> pool = sTempVec;
+        float itemWidthBy2 = itemWidth * 0.5f;
+        float itemHeightBy2 = itemHeight * 0.5f;
+        Vector3f position = pool.create();
+        Vector3f deltaAnchorPosition = pool.create();
+        try {
+            deltaAnchorPosition.set(sDeltaAnchorPosition);
+            for (int i = firstSlotIndex; i <= lastSlotIndex; ++i) {
+                GridCameraManager.getSlotPositionForSlotIndex(i, mCamera, mLayoutInterface, deltaAnchorPosition, position);
+                if (FloatUtils.boundsContainsPoint(position.x - itemWidthBy2, position.x + itemWidthBy2,
+                        position.y - itemHeightBy2, position.y + itemHeightBy2, worldPos.x, worldPos.y)) {
+                    retVal = i;
+                    break;
+                }
+            }
+        } finally {
+            pool.delete(deltaAnchorPosition);
+            pool.delete(position);
+        }
+        return retVal;
+    }
+
+    void centerCameraForSlot(int slotIndex, float baseConvergence) {
+        float imageTheta = 0.0f;
+        DisplayItem displayItem = getDisplayItemForSlotId(slotIndex);
+        if (displayItem != null) {
+            imageTheta = displayItem.getImageTheta();
+        }
+        mCameraManager.centerCameraForSlot(mLayoutInterface, slotIndex, baseConvergence, sDeltaAnchorPositionUncommited,
+                mInputProcessor.getCurrentSelectedSlot(), mZoomValue, imageTheta, mState);
+    }
+
+    boolean constrainCameraForSlot(int slotIndex) {
+        return mCameraManager.constrainCameraForSlot(mLayoutInterface, slotIndex, sDeltaAnchorPosition, mCurrentFocusItemWidth,
+                mCurrentFocusItemHeight);
+    }
+
+    // Called on render thread before rendering.
+    @Override
+    public boolean update(RenderView view, float timeElapsed) {
+        if (mFeedAboutToChange == false) {
+            mTimeElapsedSinceTransition += timeElapsed;
+            mTimeElapsedSinceGridViewReady += timeElapsed;
+            if (mTimeElapsedSinceGridViewReady >= 1.0f) {
+                mTimeElapsedSinceGridViewReady = 1.0f;
+            }
+            mTimeElapsedSinceStackViewReady += timeElapsed;
+            if (mTimeElapsedSinceStackViewReady >= 1.0f) {
+                mTimeElapsedSinceStackViewReady = 1.0f;
+            }
+        } else {
+            mTimeElapsedSinceTransition = 0;
+        }
+        if (mMediaFeed != null && mMediaFeed.isSingleImageMode()) {
+            HudLayer hud = getHud();
+            hud.getPathBar().setHidden(true);
+            hud.getMenuBar().setHidden(true);
+            if (hud.getMode() != HudLayer.MODE_NORMAL)
+                hud.setMode(HudLayer.MODE_NORMAL);
+        }
+        if (view.elapsedLoadingExpensiveTextures() > 150 || (mMediaFeed != null && mMediaFeed.getWaitingForMediaScanner())) {
+            mHud.getPathBar().setAnimatedIcons(GridDrawables.TEXTURE_SPINNER);
+        } else {
+            mHud.getPathBar().setAnimatedIcons(null);
+        }
+
+        // In that case, we need to commit the respective Display Items when the
+        // feed was updated.
+        GridCamera camera = mCamera;
+        camera.update(timeElapsed);
+        DisplayItem anchorDisplayItem = getAnchorDisplayItem(ANCHOR_CENTER);
+        if (anchorDisplayItem != null && !mHud.getTimeBar().isDragged()) {
+            mHud.getTimeBar().setItem(anchorDisplayItem.mItemRef);
+        }
+        sDisplayList.update(timeElapsed);
+        mInputProcessor.update(timeElapsed);
+        mSelectedAlpha = FloatUtils.animate(mSelectedAlpha, mTargetAlpha, timeElapsed * 0.5f);
+        if (mState == STATE_FULL_SCREEN) {
+            mHud.autoHide(true);
+        } else {
+            mHud.autoHide(false);
+            mHud.setAlpha(1.0f);
+        }
+        GridQuad[] fullscreenQuads = GridDrawables.sFullscreenGrid;
+        int numFullScreenQuads = fullscreenQuads.length;
+        for (int i = 0; i < numFullScreenQuads; ++i) {
+            fullscreenQuads[i].update(timeElapsed);
+        }
+        if (mSlideshowMode && mState == STATE_FULL_SCREEN) {
+            mTimeElapsedSinceView += timeElapsed;
+            if (mTimeElapsedSinceView > SLIDESHOW_TRANSITION_TIME) {
+                // time to go to the next slide
+                mTimeElapsedSinceView = 0.0f;
+                changeFocusToNextSlot(0.5f);
+                mCamera.commitMoveInX();
+                mCamera.commitMoveInY();
+            }
+        }
+        if (mState == STATE_MEDIA_SETS || mState == STATE_TIMELINE) {
+            mCamera.moveYTo(-0.1f);
+            mCamera.commitMoveInY();
+        }
+        boolean dirty = mDrawManager.update(timeElapsed);
+        dirty |= mSlideshowMode;
+        dirty |= mFramesDirty > 0;
+        ++mFrameCount;
+        if (mFramesDirty > 0) {
+            --mFramesDirty;
+        }
+        try {
+            if (mMediaFeed != null && (mMediaFeed.getWaitingForMediaScanner())) {
+                // We limit the drawing of the frame so that the MediaScanner
+                // thread can do its work
+                Thread.sleep(200);
+            }
+        } catch (InterruptedException e) {
+
+        }
+        if (sDisplayList.getNumAnimatables() != 0 || mCamera.isAnimating()
+                || (mTimeElapsedSinceTransition > 0.0f && mTimeElapsedSinceTransition < 1.0f) || mSelectedAlpha != mTargetAlpha
+                // || (mAnimatedFov != mTargetFov)
+                || dirty)
+            return true;
+        else
+            return false;
+    }
+
+    private void computeVisibleRange() {
+        if (mPerformingLayoutChange)
+            return;
+        if (sDeltaAnchorPosition.equals(sDeltaAnchorPositionUncommited) == false) {
+            sDeltaAnchorPosition.set(sDeltaAnchorPositionUncommited);
+        }
+        mCameraManager.computeVisibleRange(mMediaFeed, mLayoutInterface, sDeltaAnchorPosition, sVisibleRange,
+                sBufferedVisibleRange, sCompleteRange, mState);
+    }
+
+    private void computeVisibleItems() {
+        if (mFeedAboutToChange == true || mPerformingLayoutChange == true) {
+            return;
+        }
+        computeVisibleRange();
+        int deltaBegin = sBufferedVisibleRange.begin - sPreviousDataRange.begin;
+        int deltaEnd = sBufferedVisibleRange.end - sPreviousDataRange.end;
+        if (deltaBegin != 0 || deltaEnd != 0) {
+            // The delta has changed, we have to compute the display items
+            // again.
+            // We find the intersection range, these slots have not changed at
+            // all.
+            int firstVisibleSlotIndex = sBufferedVisibleRange.begin;
+            int lastVisibleSlotIndex = sBufferedVisibleRange.end;
+            sPreviousDataRange.begin = firstVisibleSlotIndex;
+            sPreviousDataRange.end = lastVisibleSlotIndex;
+
+            Pool<Vector3f> pool = sTempVec;
+            Vector3f position = pool.create();
+            Vector3f deltaAnchorPosition = pool.create();
+            try {
+                MediaFeed feed = mMediaFeed;
+                DisplayList displayList = sDisplayList;
+                DisplayItem[] displayItems = sDisplayItems;
+                DisplaySlot[] displaySlots = sDisplaySlots;
+                int numDisplayItems = displayItems.length;
+                int numDisplaySlots = displaySlots.length;
+                ArrayList<MediaItem> visibleItems = sVisibleItems;
+                deltaAnchorPosition.set(sDeltaAnchorPosition);
+                LayoutInterface layout = mLayoutInterface;
+                GridCamera camera = mCamera;
+                for (int i = firstVisibleSlotIndex; i <= lastVisibleSlotIndex; ++i) {
+                    GridCameraManager.getSlotPositionForSlotIndex(i, camera, layout, deltaAnchorPosition, position);
+                    MediaSet set = feed.getSetForSlot(i);
+                    int indexIntoSlots = i - firstVisibleSlotIndex;
+
+                    if (set != null && indexIntoSlots >= 0 && indexIntoSlots < numDisplaySlots) {
+                        ArrayList<MediaItem> items = set.getItems();
+                        displaySlots[indexIntoSlots].setMediaSet(set);
+                        ArrayList<MediaItem> bestItems = sTempList;
+                        if (mTimeElapsedSinceTransition < 1.0f) {
+                            // We always show the same top thumbnails for a
+                            // stack of albums
+                            if (mState == STATE_MEDIA_SETS)
+                                ArrayUtils.computeSortedIntersection(items, visibleItems, MAX_ITEMS_PER_SLOT, bestItems, sTempHash);
+                            else
+                                ArrayUtils.computeSortedIntersection(visibleItems, items, MAX_ITEMS_PER_SLOT, bestItems, sTempHash);
+                        }
+
+                        int numItemsInSet = set.getNumItems();
+                        int numBestItems = bestItems.size();
+                        int originallyFoundItems = numBestItems;
+                        if (numBestItems < MAX_ITEMS_PER_SLOT) {
+                            int itemsRemaining = MAX_ITEMS_PER_SLOT - numBestItems;
+                            for (int currItemPos = 0; currItemPos < numItemsInSet; currItemPos++) {
+                                MediaItem item = items.get(currItemPos);
+                                if (mTimeElapsedSinceTransition >= 1.0f || !bestItems.contains(item)) {
+                                    bestItems.add(item);
+                                    if (--itemsRemaining == 0) {
+                                        break;
+                                    }
+                                }
+                            }
+                        }
+                        numBestItems = bestItems.size();
+                        int baseIndex = (i - firstVisibleSlotIndex) * MAX_ITEMS_PER_SLOT;
+                        for (int j = 0; j < numBestItems; ++j) {
+                            if (baseIndex + j >= numDisplayItems) {
+                                break;
+                            }
+                            if (j >= numItemsInSet) {
+                                displayItems[baseIndex + j] = null;
+                            } else {
+                                MediaItem item = bestItems.get(j);
+                                if (item != null) {
+                                    DisplayItem displayItem = displayList.get(item);
+                                    if ((mState == STATE_FULL_SCREEN && i != mInputProcessor.getCurrentSelectedSlot())
+                                            || (mState == STATE_GRID_VIEW && (mTimeElapsedSinceTransition > 1.0f || j >= originallyFoundItems))) {
+                                        displayItem.set(position, j, false);
+                                        displayItem.commit();
+                                    } else {
+                                        displayList.setPositionAndStackIndex(displayItem, position, j, true);
+                                    }
+                                    displayItems[baseIndex + j] = displayItem;
+                                }
+                            }
+                        }
+                        for (int j = numBestItems; j < MAX_ITEMS_PER_SLOT; ++j) {
+                            displayItems[baseIndex + j] = null;
+                        }
+                        bestItems.clear();
+                    }
+                }
+                if (mFeedChanged) {
+                    mFeedChanged = false;
+                    if (mInputProcessor != null && mState == STATE_FULL_SCREEN && mRequestFocusContentUri == null) {
+                        int currentSelectedSlot = mInputProcessor.getCurrentSelectedSlot();
+                        if (currentSelectedSlot > sCompleteRange.end)
+                            currentSelectedSlot = sCompleteRange.end;
+                        mInputProcessor.setCurrentSelectedSlot(currentSelectedSlot);
+                    }
+                    if (mState == STATE_GRID_VIEW) {
+                        MediaSet expandedSet = mMediaFeed.getExpandedMediaSet();
+                        if (expandedSet != null) {
+                            if (!mHud.getPathBar().getCurrentLabel().equals(expandedSet.mNoCountTitleString)) {
+                                mHud.getPathBar().changeLabel(expandedSet.mNoCountTitleString);
+                            }
+                        }
+                    }
+                    if (mRequestFocusContentUri != null) {
+                        // We have to find the item that has this contentUri
+                        if (mState == STATE_FULL_SCREEN) {
+                            int numSlots = sCompleteRange.end + 1;
+                            for (int i = 0; i < numSlots; ++i) {
+                                MediaSet set = feed.getSetForSlot(i);
+                                ArrayList<MediaItem> items = set.getItems();
+                                int numItems = items.size();
+                                for (int j = 0; j < numItems; ++j) {
+                                    String itemUri = items.get(j).mContentUri;
+                                    if (itemUri != null && mRequestFocusContentUri != null) {
+                                        if (itemUri.equals(mRequestFocusContentUri)) {
+                                            mInputProcessor.setCurrentSelectedSlot(i);
+                                            break;
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                        mRequestFocusContentUri = null;
+                    }
+                }
+            } finally {
+                pool.delete(position);
+                pool.delete(deltaAnchorPosition);
+            }
+            // We keep upto 400 thumbnails in memory.
+            int numThumbnailsToKeepInMemory = (mState == STATE_MEDIA_SETS || mState == STATE_TIMELINE) ? 100 : 400;
+            int startMemoryRange = (sBufferedVisibleRange.begin / numThumbnailsToKeepInMemory) * numThumbnailsToKeepInMemory;
+            if (mStartMemoryRange != startMemoryRange) {
+                mStartMemoryRange = startMemoryRange;
+                clearUnusedThumbnails();
+            }
+        }
+    }
+
+    @Override
+    public void handleLowMemory() {
+        clearUnusedThumbnails();
+        GridDrawables.sStringTextureTable.clear();
+        mBackground.clearCache();
+    }
+
+    // This method can be potentially expensive
+    public void clearUnusedThumbnails() {
+        sDisplayList.clearExcept(sDisplayItems);
+    }
+
+    @Override
+    public void onSurfaceCreated(RenderView view, GL11 gl) {
+        sDisplayList.clear();
+        mHud.clear();
+        mHud.reset();
+        GridDrawables.sStringTextureTable.clear();
+        mDrawables.onSurfaceCreated(view, gl);
+        mBackground.clear();
+    }
+
+    @Override
+    public void onSurfaceChanged(RenderView view, int width, int height) {
+        mCamera.viewportChanged(width, height, mCamera.mItemWidth, mCamera.mItemHeight);
+        view.setFov(mCamera.mFov);
+        setState(mState);
+    }
+
+    // Renders the node in a given pass.
+    public void renderOpaque(RenderView view, GL11 gl) {
+        GridCamera camera = mCamera;
+        int selectedSlotIndex = mInputProcessor.getCurrentSelectedSlot();
+        computeVisibleItems();
+
+        gl.glMatrixMode(GL11.GL_MODELVIEW);
+        gl.glLoadIdentity();
+        GLU.gluLookAt(gl, -camera.mEyeX, -camera.mEyeY, -camera.mEyeZ, -camera.mLookAtX, -camera.mLookAtY, -camera.mLookAtZ,
+                camera.mUpX, camera.mUpY, camera.mUpZ);
+        view.setAlpha(1.0f);
+        if (mSelectedAlpha != 1.0f) {
+            gl.glEnable(GL11.GL_BLEND);
+            gl.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
+            view.setAlpha(mSelectedAlpha);
+        }
+        if (selectedSlotIndex != Shared.INVALID) {
+            mTargetAlpha = 0.0f;
+        } else {
+            mTargetAlpha = 1.0f;
+        }
+        mDrawManager.prepareDraw(sBufferedVisibleRange, sVisibleRange, selectedSlotIndex, mInputProcessor.getCurrentFocusSlot(),
+                mInputProcessor.isFocusItemPressed());
+        if (mSelectedAlpha != 0.0f) {
+            mDrawManager.drawThumbnails(view, gl, mState);
+        }
+        if (mSelectedAlpha != 1.0f) {
+            gl.glDisable(GL11.GL_BLEND);
+        }
+        // We draw the selected slotIndex.
+        if (selectedSlotIndex != Shared.INVALID) {
+            mDrawManager.drawFocusItems(view, gl, mZoomValue, mSlideshowMode, mTimeElapsedSinceView);
+            mCurrentFocusItemWidth = mDrawManager.getFocusQuadWidth();
+            mCurrentFocusItemHeight = mDrawManager.getFocusQuadHeight();
+        }
+        view.setAlpha(mSelectedAlpha);
+    }
+
+    public void renderBlended(RenderView view, GL11 gl) {
+        // We draw the placeholder for all visible slots.
+        if (mHud != null && mDrawManager != null) {
+            mDrawManager.drawBlendedComponents(view, gl, mSelectedAlpha, mState, mHud.getMode(), mTimeElapsedSinceStackViewReady,
+                    mTimeElapsedSinceGridViewReady, sSelectedBucketList, sMarkedBucketList, mMediaFeed.getWaitingForMediaScanner()
+                            || mFeedAboutToChange || mMediaFeed.isLoading());
+        }
+    }
+
+    public synchronized void onLayout(int newAnchorSlotIndex, int currentAnchorSlotIndex, LayoutInterface oldLayout) {
+        if (mPerformingLayoutChange || !sDeltaAnchorPosition.equals(sDeltaAnchorPositionUncommited)) {
+            return;
+        }
+
+        mTimeElapsedSinceTransition = 0.0f;
+        mPerformingLayoutChange = true;
+        LayoutInterface layout = mLayoutInterface;
+        if (oldLayout == null) {
+            oldLayout = sfullScreenLayoutInterface;
+        }
+        GridCamera camera = mCamera;
+        if (currentAnchorSlotIndex == Shared.INVALID) {
+            currentAnchorSlotIndex = getAnchorSlotIndex(ANCHOR_CENTER);
+            if (mCurrentExpandedSlot != Shared.INVALID) {
+                currentAnchorSlotIndex = mCurrentExpandedSlot;
+            }
+            int selectedSlotIndex = mInputProcessor.getCurrentSelectedSlot();
+            if (selectedSlotIndex != Shared.INVALID) {
+                currentAnchorSlotIndex = selectedSlotIndex;
+            }
+        }
+        if (newAnchorSlotIndex == Shared.INVALID) {
+            newAnchorSlotIndex = currentAnchorSlotIndex;
+        }
+        int itemHeight = camera.mItemHeight;
+        int itemWidth = camera.mItemWidth;
+        Pool<Vector3f> pool = sTempVec;
+        Vector3f deltaAnchorPosition = pool.create();
+        Vector3f currentSlotPosition = pool.create();
+        try {
+            deltaAnchorPosition.set(0, 0, 0);
+            if (currentAnchorSlotIndex != Shared.INVALID && newAnchorSlotIndex != Shared.INVALID) {
+                layout.getPositionForSlotIndex(newAnchorSlotIndex, itemWidth, itemHeight, deltaAnchorPosition);
+                oldLayout.getPositionForSlotIndex(currentAnchorSlotIndex, itemWidth, itemHeight, currentSlotPosition);
+                currentSlotPosition.subtract(sDeltaAnchorPosition);
+                deltaAnchorPosition.subtract(currentSlotPosition);
+                deltaAnchorPosition.y = 0;
+                deltaAnchorPosition.z = 0;
+            }
+            sDeltaAnchorPositionUncommited.set(deltaAnchorPosition);
+        } finally {
+            pool.delete(deltaAnchorPosition);
+            pool.delete(currentSlotPosition);
+        }
+        centerCameraForSlot(newAnchorSlotIndex, 1.0f);
+        mCurrentExpandedSlot = Shared.INVALID;
+
+        // Force recompute of visible items and their positions.
+        ((GridLayoutInterface) oldLayout).mNumRows = ((GridLayoutInterface) layout).mNumRows;
+        ((GridLayoutInterface) oldLayout).mSpacingX = ((GridLayoutInterface) layout).mSpacingX;
+        ((GridLayoutInterface) oldLayout).mSpacingY = ((GridLayoutInterface) layout).mSpacingY;
+        forceRecomputeVisibleRange();
+        mPerformingLayoutChange = false;
+    }
+
+    private void forceRecomputeVisibleRange() {
+        sPreviousDataRange.begin = Shared.INVALID;
+        sPreviousDataRange.end = Shared.INVALID;
+        if (mView != null) {
+            mView.requestRender();
+        }
+    }
+
+    // called on background thread
+    public synchronized void onFeedChanged(MediaFeed feed, boolean needsLayout) {
+        if (!needsLayout) {
+            mFeedChanged = true;
+            forceRecomputeVisibleRange();
+            if (mState == STATE_GRID_VIEW || mState == STATE_FULL_SCREEN)
+                mHud.setFeed(feed, mState, needsLayout);
+            return;
+        }
+
+        while (mPerformingLayoutChange == true) {
+            Thread.yield();
+        }
+        if (mState == STATE_GRID_VIEW) {
+            if (mHud != null) {
+                MediaSet set = feed.getCurrentSet();
+                if (set != null && !mLocationFilter)
+                    mHud.getPathBar().changeLabel(set.mNoCountTitleString);
+            }
+        }
+        DisplayItem[] displayItems = sDisplayItems;
+        int firstBufferedVisibleSlotIndex = sBufferedVisibleRange.begin;
+        int lastBufferedVisibleSlotIndex = sBufferedVisibleRange.end;
+        int currentlyVisibleSlotIndex = getAnchorSlotIndex(ANCHOR_CENTER);
+        if (mCurrentExpandedSlot != Shared.INVALID) {
+            currentlyVisibleSlotIndex = mCurrentExpandedSlot;
+        }
+        MediaItem anchorItem = null;
+        ArrayList<MediaItem> visibleItems = sVisibleItems;
+        visibleItems.clear();
+        visibleItems.ensureCapacity(lastBufferedVisibleSlotIndex - firstBufferedVisibleSlotIndex);
+        if (currentlyVisibleSlotIndex != Shared.INVALID && currentlyVisibleSlotIndex >= firstBufferedVisibleSlotIndex
+                && currentlyVisibleSlotIndex <= lastBufferedVisibleSlotIndex) {
+            int baseIndex = (currentlyVisibleSlotIndex - firstBufferedVisibleSlotIndex) * MAX_ITEMS_PER_SLOT;
+            for (int i = 0; i < MAX_ITEMS_PER_SLOT; ++i) {
+                DisplayItem displayItem = displayItems[baseIndex + i];
+                if (displayItem != null) {
+                    if (anchorItem == null) {
+                        anchorItem = displayItem.mItemRef;
+                    }
+                    visibleItems.add(displayItem.mItemRef);
+                }
+            }
+        }
+        // We want to add items from the middle.
+        int numItems = lastBufferedVisibleSlotIndex - firstBufferedVisibleSlotIndex + 1;
+        int midPoint = (lastBufferedVisibleSlotIndex - firstBufferedVisibleSlotIndex) / 2;
+        int length = displayItems.length;
+        for (int i = 0; i < numItems; ++i) {
+            int index = midPoint + Shared.midPointIterator(i);
+            int indexIntoDisplayItem = (index - firstBufferedVisibleSlotIndex) * MAX_ITEMS_PER_SLOT;
+            if (indexIntoDisplayItem >= 0 && indexIntoDisplayItem < length) {
+                for (int j = 0; j < MAX_ITEMS_PER_SLOT; ++j) {
+                    DisplayItem displayItem = displayItems[indexIntoDisplayItem + j];
+                    if (displayItem != null) {
+                        MediaItem item = displayItem.mItemRef;
+                        if (item != anchorItem) {
+                            visibleItems.add(item);
+                        }
+                    }
+                }
+            }
+        }
+        int newSlotIndex = Shared.INVALID;
+        if (anchorItem != null) {
+            // We try to find the anchor item in the new feed.
+            int numSlots = feed.getNumSlots();
+            for (int i = 0; i < numSlots; ++i) {
+                MediaSet set = feed.getSetForSlot(i);
+                if (set != null && set.containsItem(anchorItem)) {
+                    newSlotIndex = i;
+                    break;
+                }
+            }
+        }
+
+        if (anchorItem != null && newSlotIndex == Shared.INVALID) {
+            int numSlots = feed.getNumSlots();
+            MediaSet parentSet = anchorItem.mParentMediaSet;
+            for (int i = 0; i < numSlots; ++i) {
+                MediaSet set = feed.getSetForSlot(i);
+                if (set != null && set.mId == parentSet.mId) {
+                    newSlotIndex = i;
+                    break;
+                }
+            }
+        }
+
+        // We must create a new display store now since the data has changed.
+        if (newSlotIndex != Shared.INVALID) {
+            if (mState == STATE_MEDIA_SETS) {
+                sDisplayList.clearExcept(displayItems);
+            }
+            onLayout(newSlotIndex, currentlyVisibleSlotIndex, null);
+        } else {
+            forceRecomputeVisibleRange();
+        }
+        mCurrentExpandedSlot = Shared.INVALID;
+        mFeedAboutToChange = false;
+        mFeedChanged = true;
+        if (feed != null) {
+            if (mState == STATE_GRID_VIEW || mState == STATE_FULL_SCREEN)
+                mHud.setFeed(feed, mState, needsLayout);
+        }
+        if (mView != null) {
+            mView.requestRender();
+        }
+    }
+
+    public DisplayItem getRepresentativeDisplayItem() {
+        int slotIndex = Shared.INVALID;
+        if (mInputProcessor != null) {
+            slotIndex = mInputProcessor.getCurrentFocusSlot();
+        }
+        if (slotIndex == Shared.INVALID) {
+            slotIndex = getAnchorSlotIndex(ANCHOR_CENTER);
+        }
+        int index = (slotIndex - sBufferedVisibleRange.begin) * MAX_ITEMS_PER_SLOT;
+        if (index >= 0 && index < MAX_ITEMS_DRAWABLE) {
+            return sDisplayItems[index];
+        } else {
+            return null;
+        }
+    }
+
+    public DisplayItem getAnchorDisplayItem(int type) {
+        int slotIndex = getAnchorSlotIndex(type);
+        return sDisplayItems[(slotIndex - sBufferedVisibleRange.begin) * MAX_ITEMS_PER_SLOT];
+    }
+
+    public float getScrollPosition() {
+        return (mCamera.mLookAtX * mCamera.mScale + sDeltaAnchorPosition.x); // in
+        // pixels
+    }
+
+    public DisplayItem getDisplayItemForScrollPosition(float posX) {
+        Pool<Vector3f> pool = sTempVecAlt;
+        MediaFeed feed = mMediaFeed;
+        int itemWidth = mCamera.mItemWidth;
+        int itemHeight = mCamera.mItemHeight;
+        GridLayoutInterface gridInterface = (GridLayoutInterface) mLayoutInterface;
+        float absolutePosX = posX;
+        int left = (int) ((absolutePosX / itemWidth) * gridInterface.mNumRows);
+        int right = feed == null ? 0 : (int) (feed.getNumSlots());
+        int retSlot = left;
+        Vector3f position = pool.create();
+        try {
+            for (int i = left; i < right; ++i) {
+                gridInterface.getPositionForSlotIndex(i, itemWidth, itemHeight, position);
+                retSlot = i;
+                if (position.x >= absolutePosX) {
+                    break;
+                }
+            }
+        } finally {
+            pool.delete(position);
+        }
+        if (mFeedAboutToChange) {
+            return null;
+        }
+        right = feed == null ? 0 : feed.getNumSlots();
+        if (right == 0) {
+            return null;
+        }
+
+        if (retSlot >= right)
+            retSlot = right - 1;
+        MediaSet set = feed.getSetForSlot(retSlot);
+        if (set != null) {
+            ArrayList<MediaItem> items = set.getItems();
+            if (items != null && set.getNumItems() > 0) {
+                return (sDisplayList.get(items.get(0)));
+            }
+        }
+        return null;
+    }
+
+    // Returns the top left-most item.
+    public int getAnchorSlotIndex(int anchorType) {
+        int retVal = 0;
+        switch (anchorType) {
+        case ANCHOR_LEFT:
+            retVal = sVisibleRange.begin;
+            break;
+        case ANCHOR_RIGHT:
+            retVal = sVisibleRange.end;
+            break;
+        case ANCHOR_CENTER:
+            retVal = (sVisibleRange.begin + sVisibleRange.end) / 2;
+            break;
+        }
+        return retVal;
+    }
+
+    DisplayItem getDisplayItemForSlotId(int slotId) {
+        int index = slotId - sBufferedVisibleRange.begin;
+        if (index >= 0 && slotId <= sBufferedVisibleRange.end) {
+            return sDisplayItems[index * MAX_ITEMS_PER_SLOT];
+        }
+        return null;
+    }
+
+    boolean changeFocusToNextSlot(float convergence) {
+        int currentSelectedSlot = mInputProcessor.getCurrentSelectedSlot();
+        boolean retVal = changeFocusToSlot(currentSelectedSlot + 1, convergence);
+        if (mInputProcessor.getCurrentSelectedSlot() == currentSelectedSlot) {
+            endSlideshow();
+            mHud.setAlpha(1.0f);
+        }
+        return retVal;
+    }
+
+    boolean changeFocusToSlot(int slotId, float convergence) {
+        mZoomValue = 1.0f;
+        int index = slotId - sBufferedVisibleRange.begin;
+        if (index >= 0 && slotId <= sBufferedVisibleRange.end) {
+            DisplayItem displayItem = sDisplayItems[index * MAX_ITEMS_PER_SLOT];
+            if (displayItem != null) {
+                MediaItem item = displayItem.mItemRef;
+                mHud.fullscreenSelectionChanged(item, slotId + 1, sCompleteRange.end + 1);
+                if (slotId != Shared.INVALID && slotId <= sCompleteRange.end) {
+                    mInputProcessor.setCurrentFocusSlot(slotId);
+                    centerCameraForSlot(slotId, convergence);
+                    return true;
+                } else {
+                    centerCameraForSlot(mInputProcessor.getCurrentSelectedSlot(), convergence);
+                    return false;
+                }
+            }
+        }
+        return false;
+    }
+
+    boolean changeFocusToPreviousSlot(float convergence) {
+        return changeFocusToSlot(mInputProcessor.getCurrentSelectedSlot() - 1, convergence);
+    }
+
+    public ArrayList<MediaBucket> getSelectedBuckets() {
+        return sSelectedBucketList.get();
+    }
+
+    public void selectAll() {
+        if (mState != STATE_FULL_SCREEN) {
+            int numSlots = sCompleteRange.end + 1;
+            for (int i = 0; i < numSlots; ++i) {
+                addSlotToSelectedItems(i, false, false);
+            }
+            updateCountOfSelectedItems();
+        } else {
+            addSlotToSelectedItems(mInputProcessor.getCurrentFocusSlot(), false, true);
+        }
+    }
+
+    public void deselectOrCancelSelectMode() {
+        if (sSelectedBucketList.size() == 0) {
+            mHud.cancelSelection();
+        } else {
+            sSelectedBucketList.clear();
+            updateCountOfSelectedItems();
+        }
+    }
+
+    public void deselectAll() {
+        mHud.cancelSelection();
+        sSelectedBucketList.clear();
+        updateCountOfSelectedItems();
+    }
+
+    public void deleteSelection() {
+        // Delete the selection and exit selection mode.
+        mMediaFeed.performOperation(MediaFeed.OPERATION_DELETE, getSelectedBuckets(), null);
+        deselectAll();
+
+        // If the current set is now empty, return to the parent set.
+        if (sCompleteRange.isEmpty()) {
+            goBack(); // TODO(venkat): This does not work most of the time, can
+            // you take a look?
+        }
+    }
+
+    void addSlotToSelectedItems(int slotId, boolean removeIfAlreadyAdded, boolean updateCount) {
+        if (mFeedAboutToChange == false) {
+            MediaFeed feed = mMediaFeed;
+            sSelectedBucketList.add(slotId, feed, removeIfAlreadyAdded);
+            if (updateCount) {
+                updateCountOfSelectedItems();
+                if (sSelectedBucketList.size() == 0)
+                    deselectAll();
+            }
+        }
+        mHud.computeBottomMenu();
+    }
+
+    private void updateCountOfSelectedItems() {
+        mHud.updateNumItemsSelected(sSelectedBucketList.size());
+    }
+
+    public int getMetadataSlotIndexForScreenPosition(int posX, int posY) {
+        return getSlotForScreenPosition(posX, posY, mCamera.mItemWidth + (int) (100 * Gallery.PIXEL_DENSITY), mCamera.mItemHeight
+                + (int) (100 * Gallery.PIXEL_DENSITY));
+    }
+
+    public int getSlotIndexForScreenPosition(int posX, int posY) {
+        return getSlotForScreenPosition(posX, posY, mCamera.mItemWidth, mCamera.mItemHeight);
+    }
+
+    private int getSlotForScreenPosition(int posX, int posY, int itemWidth, int itemHeight) {
+        Pool<Vector3f> pool = sTempVec;
+        int retVal = 0;
+        Vector3f worldPos = pool.create();
+        try {
+            GridCamera camera = mCamera;
+            camera.convertToCameraSpace(posX, posY, 0, worldPos);
+            // slots are expressed in pixels as well
+            worldPos.x *= camera.mScale;
+            worldPos.y *= camera.mScale;
+            // we ignore z
+            retVal = hitTest(worldPos, itemWidth, itemHeight);
+        } finally {
+            pool.delete(worldPos);
+        }
+        return retVal;
+    }
+
+    public boolean tapGesture(int slotIndex, boolean metadata) {
+        MediaFeed feed = mMediaFeed;
+        if (!feed.isClustered()) {
+            // It is not clustering.
+            if (!feed.hasExpandedMediaSet()) {
+                if (feed.canExpandSet(slotIndex)) {
+                    mCurrentExpandedSlot = slotIndex;
+                    feed.expandMediaSet(slotIndex);
+                    setState(STATE_GRID_VIEW);
+                }
+                return false;
+            } else {
+                return true;
+            }
+        } else {
+            // Select a cluster, and recompute a new cluster within this
+            // cluster.
+            mCurrentExpandedSlot = slotIndex;
+            sMarkedBucketList.add(slotIndex, feed, false);
+            goBack();
+            if (metadata) {
+                DisplaySlot slot = sDisplaySlots[slotIndex - sBufferedVisibleRange.begin];
+                if (slot.hasValidLocation()) {
+                    MediaSet set = slot.getMediaSet();
+                    if (set.mReverseGeocodedLocation != null) {
+                        enableLocationFiltering(set.mReverseGeocodedLocation);
+                    }
+                    feed.setFilter(new LocationMediaFilter(set.mMinLatLatitude, set.mMinLonLongitude, set.mMaxLatLatitude,
+                            set.mMaxLonLongitude));
+                }
+            }
+            return false;
+        }
+    }
+
+    public void onTimeChanged(TimeBar timebar) {
+        if (mFeedAboutToChange) {
+            return;
+        }
+        // TODO lot of optimization possible here
+        MediaItem item = timebar.getItem();
+        MediaFeed feed = mMediaFeed;
+        int numSlots = feed.getNumSlots();
+        for (int i = 0; i < numSlots; ++i) {
+            MediaSet set = feed.getSetForSlot(i);
+            if (set == null) {
+                return;
+            }
+            ArrayList<MediaItem> items = set.getItems();
+            if (items == null || set.getNumItems() == 0) {
+                return;
+            }
+            if (items.contains(item)) {
+                centerCameraForSlot(i, 1.0f);
+                break;
+            }
+        }
+    }
+
+    public void onFeedAboutToChange(MediaFeed feed) {
+        mFeedAboutToChange = true;
+        mTimeElapsedSinceTransition = 0;
+    }
+
+    public void startSlideshow() {
+        endSlideshow();
+        mSlideshowMode = true;
+        mZoomValue = 1.0f;
+        centerCameraForSlot(mInputProcessor.getCurrentSelectedSlot(), 1.0f);
+        mTimeElapsedSinceView = SLIDESHOW_TRANSITION_TIME - 1.0f;
+        mHud.setAlpha(0);
+        PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
+        mWakeLock = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "GridView.Slideshow");
+        mWakeLock.acquire();
+    }
+
+    public void enterSelectionMode() {
+        mSlideshowMode = false;
+        mHud.enterSelectionMode();
+        int currentSlot = mInputProcessor.getCurrentSelectedSlot();
+        if (currentSlot == Shared.INVALID) {
+            currentSlot = mInputProcessor.getCurrentFocusSlot();
+        }
+        addSlotToSelectedItems(currentSlot, false, true);
+    }
+
+    private float getFillScreenZoomValue() {
+        return GridCameraManager.getFillScreenZoomValue(mCamera, sTempVec, mCurrentFocusItemWidth, mCurrentFocusItemHeight);
+    }
+
+    public void zoomInToSelectedItem() {
+        mSlideshowMode = false;
+        float potentialZoomValue = getFillScreenZoomValue();
+        if (mZoomValue < potentialZoomValue) {
+            mZoomValue = potentialZoomValue;
+        } else {
+            mZoomValue *= 3.0f;
+        }
+        if (mZoomValue > 6.0f) {
+            mZoomValue = 6.0f;
+        }
+        mHud.setAlpha(1.0f);
+        centerCameraForSlot(mInputProcessor.getCurrentSelectedSlot(), 1.0f);
+    }
+
+    public void zoomOutFromSelectedItem() {
+        mSlideshowMode = false;
+        if (mZoomValue == getFillScreenZoomValue()) {
+            mZoomValue = 1.0f;
+        } else {
+            mZoomValue /= 3.0f;
+        }
+        if (mZoomValue < 1.0f) {
+            mZoomValue = 1.0f;
+        }
+        mHud.setAlpha(1.0f);
+        centerCameraForSlot(mInputProcessor.getCurrentSelectedSlot(), 1.0f);
+    }
+
+    public void rotateSelectedItems(float f) {
+        MediaBucketList bucketList = sSelectedBucketList;
+        ArrayList<MediaBucket> mediaBuckets = bucketList.get();
+        DisplayList displayList = sDisplayList;
+        int numBuckets = mediaBuckets.size();
+        for (int i = 0; i < numBuckets; ++i) {
+            MediaBucket bucket = mediaBuckets.get(i);
+            ArrayList<MediaItem> mediaItems = bucket.mediaItems;
+            if (mediaItems != null) {
+                int numMediaItems = mediaItems.size();
+                for (int j = 0; j < numMediaItems; ++j) {
+                    MediaItem item = mediaItems.get(j);
+                    DisplayItem displayItem = displayList.get(item);
+                    displayItem.rotateImageBy(f);
+                    displayList.addToAnimatables(displayItem);
+                }
+            }
+        }
+        if (mState == STATE_FULL_SCREEN) {
+            centerCameraForSlot(mInputProcessor.getCurrentSelectedSlot(), 1.0f);
+        }
+        mMediaFeed.performOperation(MediaFeed.OPERATION_ROTATE, mediaBuckets, new Float(f));
+        // we recreate these displayitems from the cache
+    }
+
+    public void cropSelectedItem() {
+
+    }
+
+    @Override
+    public boolean onTouchEvent(MotionEvent event) {
+        return mInputProcessor.onTouchEvent(event);
+    }
+
+    @Override
+    public boolean onKeyDown(int keyCode, KeyEvent event) {
+        if (mInputProcessor != null)
+            return mInputProcessor.onKeyDown(keyCode, event, mState);
+        return false;
+    }
+
+    public boolean inSlideShowMode() {
+        return mSlideshowMode;
+    }
+
+    public boolean noDeleteMode() {
+        return mNoDeleteMode || (mMediaFeed != null && mMediaFeed.isSingleImageMode());
+    }
+
+    public float getZoomValue() {
+        return mZoomValue;
+    }
+
+    public boolean feedAboutToChange() {
+        return mFeedAboutToChange;
+    }
+
+    public boolean isInAlbumMode() {
+        return mInAlbum;
+    }
+
+    public Vector3f getDeltaAnchorPosition() {
+        return sDeltaAnchorPosition;
+    }
+
+    public int getExpandedSlot() {
+        return mCurrentExpandedSlot;
+    }
+
+    public GridLayoutInterface getLayoutInterface() {
+        return (GridLayoutInterface) mLayoutInterface;
+    }
+
+    public void setZoomValue(float f) {
+        mZoomValue = f;
+        centerCameraForSlot(mInputProcessor.getCurrentSelectedSlot(), 1.0f);
+    }
+
+    public void setPickIntent(boolean b) {
+        mPickIntent = b;
+        mHud.getPathBar().popLabel();
+        mHud.getPathBar().pushLabel(R.drawable.icon_location_small, mContext.getResources().getString(R.string.pick),
+                new Runnable() {
+                    public void run() {
+                        if (mHud.getAlpha() == 1.0f) {
+                            if (!mFeedAboutToChange) {
+                                setState(STATE_MEDIA_SETS);
+                            }
+                        } else {
+                            mHud.setAlpha(1.0f);
+                        }
+                    }
+                });
+    }
+
+    public boolean getPickIntent() {
+        return mPickIntent;
+    }
+
+    public void setViewIntent(boolean b, final String setName) {
+        mViewIntent = b;
+        if (b) {
+            mMediaFeed.expandMediaSet(0);
+            setState(STATE_GRID_VIEW);
+            // We need to make sure we haven't pushed the same label twice
+            if (mHud.getPathBar().getNumLevels() == 1) {
+                mHud.getPathBar().pushLabel(R.drawable.icon_folder_small, setName, new Runnable() {
+                    public void run() {
+                        if (mFeedAboutToChange) {
+                            return;
+                        }
+                        if (mHud.getAlpha() == 1.0f) {
+                            disableLocationFiltering();
+                            if (mInputProcessor != null)
+                                mInputProcessor.clearSelection();
+                            setState(STATE_GRID_VIEW);
+                        } else {
+                            mHud.setAlpha(1.0f);
+                        }
+                    }
+                });
+            }
+        }
+    }
+
+    public boolean getViewIntent() {
+        return mViewIntent;
+    }
+
+    public void setSingleImage(boolean noDeleteMode) {
+        mNoDeleteMode = noDeleteMode;
+        mInputProcessor.setCurrentSelectedSlot(0);
+    }
+
+    public MediaFeed getFeed() {
+        return mMediaFeed;
+    }
+
+    public void markDirty(int numFrames) {
+        mFramesDirty = numFrames;
+    }
+
+    public void focusItem(String contentUri) {
+        mRequestFocusContentUri = contentUri;
+        mMediaFeed.updateListener(false);
+    }
 
 }
index 6e8affe..1b8e3ef 100644 (file)
@@ -3,8 +3,8 @@ package com.cooliris.media;
 public final class GridLayoutInterface extends LayoutInterface {
     GridLayoutInterface(int numRows) {
         mNumRows = numRows;
-        mSpacingX = (int)(20 * Gallery.PIXEL_DENSITY);
-        mSpacingY = (int)(40 * Gallery.PIXEL_DENSITY);
+        mSpacingX = (int) (20 * Gallery.PIXEL_DENSITY);
+        mSpacingY = (int) (40 * Gallery.PIXEL_DENSITY);
     }
 
     public void getPositionForSlotIndex(int slotIndex, int itemWidth, int itemHeight, Vector3f outPosition) {
index 326e48e..e33e178 100644 (file)
@@ -25,8 +25,9 @@ import javax.microedition.khronos.opengles.GL10;
 import javax.microedition.khronos.opengles.GL11;
 
 /**
- * A 2D rectangular mesh. Can be drawn textured or untextured. This version is modified from the original Grid.java (found in the
- * SpriteText package in the APIDemos Android sample) to support hardware vertex buffers.
+ * A 2D rectangular mesh. Can be drawn textured or untextured. This version is
+ * modified from the original Grid.java (found in the SpriteText package in the
+ * APIDemos Android sample) to support hardware vertex buffers.
  */
 
 final class GridQuad {
@@ -61,7 +62,7 @@ final class GridQuad {
 
     public static GridQuad createGridQuad(float width, float height, float xOffset, float yOffset, float uExtents, float vExtents,
             boolean generateOrientedQuads) {
-        //generateOrientedQuads = false;
+        // generateOrientedQuads = false;
         GridQuad grid = new GridQuad(generateOrientedQuads);
         grid.mWidth = width;
         grid.mHeight = height;
@@ -175,7 +176,8 @@ final class GridQuad {
 
     public void resizeQuad(float viewAspect, float u, float v, float imageWidth, float imageHeight) {
         // given the u,v; we know the aspect ratio of the image
-        // we have to change one of the co-ords depending upon the image and viewport aspect ratio
+        // we have to change one of the co-ords depending upon the image and
+        // viewport aspect ratio
         mU = u;
         mV = v;
         float imageAspect = imageWidth / imageHeight;
@@ -304,8 +306,9 @@ final class GridQuad {
     }
 
     /**
-     * When the OpenGL ES device is lost, GL handles become invalidated. In that case, we just want to "forget" the old handles
-     * (without explicitly deleting them) and make new ones.
+     * When the OpenGL ES device is lost, GL handles become invalidated. In that
+     * case, we just want to "forget" the old handles (without explicitly
+     * deleting them) and make new ones.
      */
     public void forgetHardwareBuffers() {
         mVertBufferIndex = 0;
@@ -336,9 +339,10 @@ final class GridQuad {
     }
 
     /**
-     * Allocates hardware buffers on the graphics card and fills them with data if a buffer has not already been previously
-     * allocated. Note that this function uses the GL_OES_vertex_buffer_object extension, which is not guaranteed to be supported on
-     * every device.
+     * Allocates hardware buffers on the graphics card and fills them with data
+     * if a buffer has not already been previously allocated. Note that this
+     * function uses the GL_OES_vertex_buffer_object extension, which is not
+     * guaranteed to be supported on every device.
      * 
      * @param gl
      *            A pointer to the OpenGL ES context.
index 1f566bc..3c808f1 100644 (file)
@@ -16,9 +16,10 @@ final class GridQuadFrame {
 
     private int mW;
     private int mH;
-    
+
     // This has 8 quads, 16 vertices, 22 triangles (for tristrip).
-    // We have more triangles because we have to make degenerate triangles to use tri-strips
+    // We have more triangles because we have to make degenerate triangles to
+    // use tri-strips
     public static final int INDEX_COUNT = 25;
     private int mVertBufferIndex;
     private int mIndexBufferIndex;
@@ -85,8 +86,10 @@ final class GridQuadFrame {
         /*
          * Initialize triangle list mesh.
          * 
-         * [0]---[1]---------[2]---[3] ... | / | / | / | [4]---[5]---------[6]---[7] | / | | /| | / | | / | | / | | / |
-         * [8]---[9]---------[10]---[11] | / | \ | \ | [12]--[13]--------[14]---[15]
+         * [0]---[1]---------[2]---[3] ... | / | / | / |
+         * [4]---[5]---------[6]---[7] | / | | /| | / | | / | | / | | / |
+         * [8]---[9]---------[10]---[11] | / | \ | \ |
+         * [12]--[13]--------[14]---[15]
          */
         CharBuffer buffer = mIndexBuffer;
         buffer.put(0, (char) 0);
@@ -135,7 +138,7 @@ final class GridQuadFrame {
         int texIndex = index * 2;
         mTexCoordBuffer.put(texIndex, u);
         mTexCoordBuffer.put(texIndex + 1, v);
-        
+
         int secTexIndex = index * 2;
         mSecTexCoordBuffer.put(secTexIndex, u);
         mSecTexCoordBuffer.put(secTexIndex + 1, v);
@@ -172,8 +175,9 @@ final class GridQuadFrame {
     }
 
     /**
-     * When the OpenGL ES device is lost, GL handles become invalidated. In that case, we just want to "forget" the old handles
-     * (without explicitly deleting them) and make new ones.
+     * When the OpenGL ES device is lost, GL handles become invalidated. In that
+     * case, we just want to "forget" the old handles (without explicitly
+     * deleting them) and make new ones.
      */
     public void forgetHardwareBuffers() {
         mVertBufferIndex = 0;
@@ -195,7 +199,7 @@ final class GridQuadFrame {
 
                 buffer[0] = mTextureCoordBufferIndex;
                 gl11.glDeleteBuffers(1, buffer, 0);
-                
+
                 buffer[0] = mSecTextureCoordBufferIndex;
                 gl11.glDeleteBuffers(1, buffer, 0);
 
@@ -207,9 +211,10 @@ final class GridQuadFrame {
     }
 
     /**
-     * Allocates hardware buffers on the graphics card and fills them with data if a buffer has not already been previously
-     * allocated. Note that this function uses the GL_OES_vertex_buffer_object extension, which is not guaranteed to be supported on
-     * every device.
+     * Allocates hardware buffers on the graphics card and fills them with data
+     * if a buffer has not already been previously allocated. Note that this
+     * function uses the GL_OES_vertex_buffer_object extension, which is not
+     * guaranteed to be supported on every device.
      * 
      * @param gl
      *            A pointer to the OpenGL ES context.
@@ -235,7 +240,7 @@ final class GridQuadFrame {
                 final int texCoordSize = mTexCoordBuffer.capacity() * 4;
                 mTexCoordBuffer.position(0);
                 gl11.glBufferData(GL11.GL_ARRAY_BUFFER, texCoordSize, mTexCoordBuffer, GL11.GL_STATIC_DRAW);
-                
+
                 // Allocate and fill the secondary texture coordinate buffer.
                 gl11.glGenBuffers(1, buffer, 0);
                 mSecTextureCoordBufferIndex = buffer[0];
index c4790a6..7ab5ff7 100644 (file)
@@ -25,8 +25,9 @@ import javax.microedition.khronos.opengles.GL10;
 import javax.microedition.khronos.opengles.GL11;
 
 /**
- * A 2D rectangular mesh. Can be drawn textured or untextured. This version is modified from the original Grid.java (found in the
- * SpriteText package in the APIDemos Android sample) to support hardware vertex buffers.
+ * A 2D rectangular mesh. Can be drawn textured or untextured. This version is
+ * modified from the original Grid.java (found in the SpriteText package in the
+ * APIDemos Android sample) to support hardware vertex buffers.
  */
 final class GridQuadMesh {
     private FloatBuffer mVertexBuffer;
@@ -147,8 +148,9 @@ final class GridQuadMesh {
     }
 
     /**
-     * When the OpenGL ES device is lost, GL handles become invalidated. In that case, we just want to "forget" the old handles
-     * (without explicitly deleting them) and make new ones.
+     * When the OpenGL ES device is lost, GL handles become invalidated. In that
+     * case, we just want to "forget" the old handles (without explicitly
+     * deleting them) and make new ones.
      */
     public void forgetHardwareBuffers() {
         mVertBufferIndex = 0;
@@ -179,9 +181,10 @@ final class GridQuadMesh {
     }
 
     /**
-     * Allocates hardware buffers on the graphics card and fills them with data if a buffer has not already been previously
-     * allocated. Note that this function uses the GL_OES_vertex_buffer_object extension, which is not guaranteed to be supported on
-     * every device.
+     * Allocates hardware buffers on the graphics card and fills them with data
+     * if a buffer has not already been previously allocated. Note that this
+     * function uses the GL_OES_vertex_buffer_object extension, which is not
+     * guaranteed to be supported on every device.
      * 
      * @param gl
      *            A pointer to the OpenGL ES context.
index d65060c..9d585bf 100644 (file)
@@ -16,7 +16,6 @@ package com.cooliris.media;
  * limitations under the License.
  */
 
-
 import android.graphics.Canvas;
 import android.graphics.Matrix;
 import android.graphics.Paint;
@@ -35,14 +34,14 @@ class HighlightView {
 
     @SuppressWarnings("unused")
     private static final String TAG = "HighlightView";
-    View mContext;  // The View displaying the image.
+    View mContext; // The View displaying the image.
 
-    public static final int GROW_NONE        = (1 << 0);
-    public static final int GROW_LEFT_EDGE   = (1 << 1);
-    public static final int GROW_RIGHT_EDGE  = (1 << 2);
-    public static final int GROW_TOP_EDGE    = (1 << 3);
+    public static final int GROW_NONE = (1 << 0);
+    public static final int GROW_LEFT_EDGE = (1 << 1);
+    public static final int GROW_RIGHT_EDGE = (1 << 2);
+    public static final int GROW_TOP_EDGE = (1 << 3);
     public static final int GROW_BOTTOM_EDGE = (1 << 4);
-    public static final int MOVE             = (1 << 5);
+    public static final int MOVE = (1 << 5);
 
     public HighlightView(View ctx) {
         mContext = ctx;
@@ -50,12 +49,9 @@ class HighlightView {
 
     private void init() {
         android.content.res.Resources resources = mContext.getResources();
-        mResizeDrawableWidth =
-                resources.getDrawable(R.drawable.camera_crop_width);
-        mResizeDrawableHeight =
-                resources.getDrawable(R.drawable.camera_crop_height);
-        mResizeDrawableDiagonal =
-                resources.getDrawable(R.drawable.indicator_autocrop);
+        mResizeDrawableWidth = resources.getDrawable(R.drawable.camera_crop_width);
+        mResizeDrawableHeight = resources.getDrawable(R.drawable.camera_crop_height);
+        mResizeDrawableDiagonal = resources.getDrawable(R.drawable.indicator_autocrop);
     }
 
     boolean mIsFocused;
@@ -86,81 +82,59 @@ class HighlightView {
             Rect viewDrawingRect = new Rect();
             mContext.getDrawingRect(viewDrawingRect);
             if (mCircle) {
-                float width  = mDrawRect.width();
+                float width = mDrawRect.width();
                 float height = mDrawRect.height();
-                path.addCircle(mDrawRect.left + (width  / 2),
-                               mDrawRect.top + (height / 2),
-                               width / 2,
-                               Path.Direction.CW);
+                path.addCircle(mDrawRect.left + (width / 2), mDrawRect.top + (height / 2), width / 2, Path.Direction.CW);
                 mOutlinePaint.setColor(0xFFEF04D6);
             } else {
                 path.addRect(new RectF(mDrawRect), Path.Direction.CW);
                 mOutlinePaint.setColor(0xFFFF8A00);
             }
             canvas.clipPath(path, Region.Op.DIFFERENCE);
-            canvas.drawRect(viewDrawingRect,
-                    hasFocus() ? mFocusPaint : mNoFocusPaint);
+            canvas.drawRect(viewDrawingRect, hasFocus() ? mFocusPaint : mNoFocusPaint);
 
             canvas.restore();
             canvas.drawPath(path, mOutlinePaint);
 
             if (mMode == ModifyMode.Grow) {
                 if (mCircle) {
-                    int width  = mResizeDrawableDiagonal.getIntrinsicWidth();
+                    int width = mResizeDrawableDiagonal.getIntrinsicWidth();
                     int height = mResizeDrawableDiagonal.getIntrinsicHeight();
 
-                    int d  = (int) Math.round(Math.cos(/*45deg*/Math.PI / 4D)
-                            * (mDrawRect.width() / 2D));
-                    int x  = mDrawRect.left
-                            + (mDrawRect.width() / 2) + d - width / 2;
-                    int y  = mDrawRect.top
-                            + (mDrawRect.height() / 2) - d - height / 2;
-                    mResizeDrawableDiagonal.setBounds(x, y,
-                            x + mResizeDrawableDiagonal.getIntrinsicWidth(),
-                            y + mResizeDrawableDiagonal.getIntrinsicHeight());
+                    int d = (int) Math.round(Math.cos(/* 45deg */Math.PI / 4D) * (mDrawRect.width() / 2D));
+                    int x = mDrawRect.left + (mDrawRect.width() / 2) + d - width / 2;
+                    int y = mDrawRect.top + (mDrawRect.height() / 2) - d - height / 2;
+                    mResizeDrawableDiagonal.setBounds(x, y, x + mResizeDrawableDiagonal.getIntrinsicWidth(), y
+                            + mResizeDrawableDiagonal.getIntrinsicHeight());
                     mResizeDrawableDiagonal.draw(canvas);
                 } else {
-                    int left    = mDrawRect.left   + 1;
-                    int right   = mDrawRect.right  + 1;
-                    int top     = mDrawRect.top    + 4;
-                    int bottom  = mDrawRect.bottom + 3;
-
-                    int widthWidth   =
-                            mResizeDrawableWidth.getIntrinsicWidth() / 2;
-                    int widthHeight  =
-                            mResizeDrawableWidth.getIntrinsicHeight() / 2;
-                    int heightHeight =
-                            mResizeDrawableHeight.getIntrinsicHeight() / 2;
-                    int heightWidth  =
-                            mResizeDrawableHeight.getIntrinsicWidth() / 2;
-
-                    int xMiddle = mDrawRect.left
-                            + ((mDrawRect.right  - mDrawRect.left) / 2);
-                    int yMiddle = mDrawRect.top
-                            + ((mDrawRect.bottom - mDrawRect.top) / 2);
-
-                    mResizeDrawableWidth.setBounds(left - widthWidth,
-                                                   yMiddle - widthHeight,
-                                                   left + widthWidth,
-                                                   yMiddle + widthHeight);
+                    int left = mDrawRect.left + 1;
+                    int right = mDrawRect.right + 1;
+                    int top = mDrawRect.top + 4;
+                    int bottom = mDrawRect.bottom + 3;
+
+                    int widthWidth = mResizeDrawableWidth.getIntrinsicWidth() / 2;
+                    int widthHeight = mResizeDrawableWidth.getIntrinsicHeight() / 2;
+                    int heightHeight = mResizeDrawableHeight.getIntrinsicHeight() / 2;
+                    int heightWidth = mResizeDrawableHeight.getIntrinsicWidth() / 2;
+
+                    int xMiddle = mDrawRect.left + ((mDrawRect.right - mDrawRect.left) / 2);
+                    int yMiddle = mDrawRect.top + ((mDrawRect.bottom - mDrawRect.top) / 2);
+
+                    mResizeDrawableWidth.setBounds(left - widthWidth, yMiddle - widthHeight, left + widthWidth, yMiddle
+                            + widthHeight);
                     mResizeDrawableWidth.draw(canvas);
 
-                    mResizeDrawableWidth.setBounds(right - widthWidth,
-                                                   yMiddle - widthHeight,
-                                                   right + widthWidth,
-                                                   yMiddle + widthHeight);
+                    mResizeDrawableWidth.setBounds(right - widthWidth, yMiddle - widthHeight, right + widthWidth, yMiddle
+                            + widthHeight);
                     mResizeDrawableWidth.draw(canvas);
 
-                    mResizeDrawableHeight.setBounds(xMiddle - heightWidth,
-                                                    top - heightHeight,
-                                                    xMiddle + heightWidth,
-                                                    top + heightHeight);
+                    mResizeDrawableHeight.setBounds(xMiddle - heightWidth, top - heightHeight, xMiddle + heightWidth, top
+                            + heightHeight);
                     mResizeDrawableHeight.draw(canvas);
 
-                    mResizeDrawableHeight.setBounds(xMiddle - heightWidth,
-                                                    bottom - heightHeight,
-                                                    xMiddle + heightWidth,
-                                                    bottom + heightHeight);
+                    mResizeDrawableHeight.setBounds(xMiddle - heightWidth, bottom - heightHeight, xMiddle + heightWidth, bottom
+                            + heightHeight);
                     mResizeDrawableHeight.draw(canvas);
                 }
             }
@@ -183,9 +157,8 @@ class HighlightView {
         if (mCircle) {
             float distX = x - r.centerX();
             float distY = y - r.centerY();
-            int distanceFromCenter =
-                    (int) Math.sqrt(distX * distX + distY * distY);
-            int radius  = mDrawRect.width() / 2;
+            int distanceFromCenter = (int) Math.sqrt(distX * distX + distY * distY);
+            int radius = mDrawRect.width() / 2;
             int delta = distanceFromCenter - radius;
             if (Math.abs(delta) <= hysteresis) {
                 if (Math.abs(distY) > Math.abs(distX)) {
@@ -209,22 +182,20 @@ class HighlightView {
         } else {
             // verticalCheck makes sure the position is between the top and
             // the bottom edge (with some tolerance). Similar for horizCheck.
-            boolean verticalCheck = (y >= r.top - hysteresis)
-                    && (y < r.bottom + hysteresis);
-            boolean horizCheck = (x >= r.left - hysteresis)
-                    && (x < r.right + hysteresis);
+            boolean verticalCheck = (y >= r.top - hysteresis) && (y < r.bottom + hysteresis);
+            boolean horizCheck = (x >= r.left - hysteresis) && (x < r.right + hysteresis);
 
             // Check whether the position is near some edge(s).
-            if ((Math.abs(r.left - x)     < hysteresis)  &&  verticalCheck) {
+            if ((Math.abs(r.left - x) < hysteresis) && verticalCheck) {
                 retval |= GROW_LEFT_EDGE;
             }
-            if ((Math.abs(r.right - x)    < hysteresis)  &&  verticalCheck) {
+            if ((Math.abs(r.right - x) < hysteresis) && verticalCheck) {
                 retval |= GROW_RIGHT_EDGE;
             }
-            if ((Math.abs(r.top - y)      < hysteresis)  &&  horizCheck) {
+            if ((Math.abs(r.top - y) < hysteresis) && horizCheck) {
                 retval |= GROW_TOP_EDGE;
             }
-            if ((Math.abs(r.bottom - y)   < hysteresis)  &&  horizCheck) {
+            if ((Math.abs(r.bottom - y) < hysteresis) && horizCheck) {
                 retval |= GROW_BOTTOM_EDGE;
             }
 
@@ -244,8 +215,7 @@ class HighlightView {
             return;
         } else if (edge == MOVE) {
             // Convert to image space before sending to moveBy().
-            moveBy(dx * (mCropRect.width() / r.width()),
-                   dy * (mCropRect.height() / r.height()));
+            moveBy(dx * (mCropRect.width() / r.width()), dy * (mCropRect.height() / r.height()));
         } else {
             if (((GROW_LEFT_EDGE | GROW_RIGHT_EDGE) & edge) == 0) {
                 dx = 0;
@@ -258,8 +228,7 @@ class HighlightView {
             // Convert to image space before sending to growBy().
             float xDelta = dx * (mCropRect.width() / r.width());
             float yDelta = dy * (mCropRect.height() / r.height());
-            growBy((((edge & GROW_LEFT_EDGE) != 0) ? -1 : 1) * xDelta,
-                    (((edge & GROW_TOP_EDGE) != 0) ? -1 : 1) * yDelta);
+            growBy((((edge & GROW_LEFT_EDGE) != 0) ? -1 : 1) * xDelta, (((edge & GROW_TOP_EDGE) != 0) ? -1 : 1) * yDelta);
         }
     }
 
@@ -270,13 +239,9 @@ class HighlightView {
         mCropRect.offset(dx, dy);
 
         // Put the cropping rectangle inside image rectangle.
-        mCropRect.offset(
-                Math.max(0, mImageRect.left - mCropRect.left),
-                Math.max(0, mImageRect.top  - mCropRect.top));
+        mCropRect.offset(Math.max(0, mImageRect.left - mCropRect.left), Math.max(0, mImageRect.top - mCropRect.top));
 
-        mCropRect.offset(
-                Math.min(0, mImageRect.right  - mCropRect.right),
-                Math.min(0, mImageRect.bottom - mCropRect.bottom));
+        mCropRect.offset(Math.min(0, mImageRect.right - mCropRect.right), Math.min(0, mImageRect.bottom - mCropRect.bottom));
 
         mDrawRect = computeLayout();
         invalRect.union(mDrawRect);
@@ -320,9 +285,7 @@ class HighlightView {
         if (r.width() < widthCap) {
             r.inset(-(widthCap - r.width()) / 2F, 0F);
         }
-        float heightCap = mMaintainAspectRatio
-                ? (widthCap / mInitialAspectRatio)
-                : widthCap;
+        float heightCap = mMaintainAspectRatio ? (widthCap / mInitialAspectRatio) : widthCap;
         if (r.height() < heightCap) {
             r.inset(0F, -(heightCap - r.height()) / 2F);
         }
@@ -346,25 +309,21 @@ class HighlightView {
 
     // Returns the cropping rectangle in image space.
     public Rect getCropRect() {
-        return new Rect((int) mCropRect.left, (int) mCropRect.top,
-                        (int) mCropRect.right, (int) mCropRect.bottom);
+        return new Rect((int) mCropRect.left, (int) mCropRect.top, (int) mCropRect.right, (int) mCropRect.bottom);
     }
 
     // Maps the cropping rectangle from image space to screen space.
     private Rect computeLayout() {
-        RectF r = new RectF(mCropRect.left, mCropRect.top,
-                            mCropRect.right, mCropRect.bottom);
+        RectF r = new RectF(mCropRect.left, mCropRect.top, mCropRect.right, mCropRect.bottom);
         mMatrix.mapRect(r);
-        return new Rect(Math.round(r.left), Math.round(r.top),
-                        Math.round(r.right), Math.round(r.bottom));
+        return new Rect(Math.round(r.left), Math.round(r.top), Math.round(r.right), Math.round(r.bottom));
     }
 
     public void invalidate() {
         mDrawRect = computeLayout();
     }
 
-    public void setup(Matrix m, Rect imageRect, RectF cropRect, boolean circle,
-                      boolean maintainAspectRatio) {
+    public void setup(Matrix m, Rect imageRect, RectF cropRect, boolean circle, boolean maintainAspectRatio) {
         if (circle) {
             maintainAspectRatio = true;
         }
@@ -388,13 +347,15 @@ class HighlightView {
         init();
     }
 
-    enum ModifyMode { None, Move, Grow }
+    enum ModifyMode {
+        None, Move, Grow
+    }
 
     private ModifyMode mMode = ModifyMode.None;
 
-    Rect mDrawRect;  // in screen space
-    private RectF mImageRect;  // in image space
-    RectF mCropRect;  // in image space
+    Rect mDrawRect; // in screen space
+    private RectF mImageRect; // in image space
+    RectF mCropRect; // in image space
     Matrix mMatrix;
 
     private boolean mMaintainAspectRatio = false;
@@ -409,4 +370,3 @@ class HighlightView {
     private final Paint mNoFocusPaint = new Paint();
     private final Paint mOutlinePaint = new Paint();
 }
-
index 433aaa0..cca6d0f 100644 (file)
@@ -143,12 +143,12 @@ public final class HudLayer extends Layer {
         MenuBar.Menu deleteMenu = new MenuBar.Menu.Builder(context.getResources().getString(R.string.delete)).icon(
                 R.drawable.icon_delete).options(deleteOptions).build();
 
-        MenuBar.Menu moreMenu = new MenuBar.Menu.Builder(context.getResources().getString(R.string.more)).icon(
-                R.drawable.icon_more).onSelect(new Runnable() {
-            public void run() {
-                buildMoreOptions();
-            }
-        }).build();
+        MenuBar.Menu moreMenu = new MenuBar.Menu.Builder(context.getResources().getString(R.string.more))
+                .icon(R.drawable.icon_more).onSelect(new Runnable() {
+                    public void run() {
+                        buildMoreOptions();
+                    }
+                }).build();
 
         mNormalBottomMenu = new MenuBar.Menu[] { shareMenu, deleteMenu, moreMenu };
         mSingleViewIntentBottomMenu = new MenuBar.Menu[] { shareMenu, moreMenu };
@@ -177,8 +177,8 @@ public final class HudLayer extends Layer {
                                     setAlpha(1.0f);
                             }
                         }).build(), /* new MenuBar.Menu.Builder("").build(), */
-                new MenuBar.Menu.Builder(context.getResources().getString(R.string.menu)).icon(R.drawable.icon_more)
-                        .onSingleTapUp(new Runnable() {
+                new MenuBar.Menu.Builder(context.getResources().getString(R.string.menu)).icon(R.drawable.icon_more).onSingleTapUp(
+                        new Runnable() {
                             public void run() {
                                 if (getAlpha() == 1.0f)
                                     mGridLayer.enterSelectionMode();
@@ -187,7 +187,7 @@ public final class HudLayer extends Layer {
                             }
                         }).build() });
     }
-    
+
     public void setContext(Context context) {
         if (mContext != context) {
             mContext = context;
@@ -372,7 +372,8 @@ public final class HudLayer extends Layer {
             }
         }
 
-        // We are assuming that the more menu is the last item in the menu array.
+        // We are assuming that the more menu is the last item in the menu
+        // array.
         int lastIndex = mSelectionMenuBottom.getMenus().length - 1;
         mSelectionMenuBottom.getMenus()[lastIndex].options = options;
     }
@@ -466,7 +467,8 @@ public final class HudLayer extends Layer {
 
         // Show the time bar in stack and grid states, except in selection mode.
         mTimeBar.setHidden(fullscreenMode || selectionMode || stackMode);
-        // mTimeBar.setHidden(selectionMode || (state != GridLayer.STATE_TIMELINE && state != GridLayer.STATE_GRID_VIEW));
+        // mTimeBar.setHidden(selectionMode || (state !=
+        // GridLayer.STATE_TIMELINE && state != GridLayer.STATE_GRID_VIEW));
 
         // Hide the path bar and top-right button in selection mode.
         mPathBar.setHidden(selectionMode);
@@ -604,8 +606,9 @@ public final class HudLayer extends Layer {
     public boolean onTouchEvent(MotionEvent event) {
         if (mMode == MODE_SELECT) {
             /*
-             * setMode(MODE_NORMAL); ArrayList<MediaBucket> displayBuckets = mGridLayer.getSelectedBuckets(); // use this list, and
-             * then clear the items return true;
+             * setMode(MODE_NORMAL); ArrayList<MediaBucket> displayBuckets =
+             * mGridLayer.getSelectedBuckets(); // use this list, and then clear
+             * the items return true;
              */
             return false;
         } else {
@@ -637,7 +640,8 @@ public final class HudLayer extends Layer {
     }
 
     private void updateShareMenu() {
-        // Get the first selected item. Wire this up to multiple-item intents when we move
+        // Get the first selected item. Wire this up to multiple-item intents
+        // when we move
         // to Eclair.
         ArrayList<MediaBucket> selection = mGridLayer.getSelectedBuckets();
         ArrayList<Uri> uris = new ArrayList<Uri>();
@@ -664,8 +668,10 @@ public final class HudLayer extends Layer {
                         mediaType = item.getMediaType();
                         MediaSet parentMediaSet = item.mParentMediaSet;
                         if (parentMediaSet != null && parentMediaSet.mPicasaAlbumId != Shared.INVALID) {
-                            // This will go away once http uri's are supported for all media types.
-                            // This ensures that just the link is shared as a text
+                            // This will go away once http uri's are supported
+                            // for all media types.
+                            // This ensures that just the link is shared as a
+                            // text
                             mimeType = "text/plain";
                         }
                     }
@@ -755,27 +761,28 @@ public final class HudLayer extends Layer {
     public void enterSelectionMode() {
         setAlpha(1.0f);
         setMode(HudLayer.MODE_SELECT);
-        // if we are in single view mode, show the bottom menu without the delete button.
+        // if we are in single view mode, show the bottom menu without the
+        // delete button.
         if (mGridLayer.noDeleteMode()) {
             mSelectionMenuBottom.setMenus(mSingleViewIntentBottomMenu);
         } else {
             mSelectionMenuBottom.setMenus(mNormalBottomMenu);
         }
     }
-    
+
     public void computeBottomMenu() {
-       // we need to the same for picasa albums
+        // we need to the same for picasa albums
         ArrayList<MediaBucket> selection = mGridLayer.getSelectedBuckets();
         Menu[] menus = mSelectionMenuBottom.getMenus();
         if (menus == mSingleViewIntentBottomMenu)
-               return;
+            return;
         int numBuckets = selection.size();
         for (int i = 0; i < numBuckets; ++i) {
-               MediaBucket bucket = selection.get(i);
-               if (bucket.mediaSet.mPicasaAlbumId != Shared.INVALID) {
-                       mSelectionMenuBottom.setMenus(mSingleViewIntentBottomMenu);
-                       break;
-               }
+            MediaBucket bucket = selection.get(i);
+            if (bucket.mediaSet.mPicasaAlbumId != Shared.INVALID) {
+                mSelectionMenuBottom.setMenus(mSingleViewIntentBottomMenu);
+                break;
+            }
         }
     }
 
index 52537d2..40c3421 100644 (file)
@@ -115,7 +115,10 @@ public final class ImageButton extends Layer {
         if (mCurrentImage != image) {
             if (animate) {
                 mFade.setValue(0f);
-                mFade.animateValue(1f, 0.25f, SystemClock.uptimeMillis()); // TODO: use frame clock.
+                mFade.animateValue(1f, 0.25f, SystemClock.uptimeMillis()); // TODO:
+                                                                           // use
+                                                                           // frame
+                                                                           // clock.
                 mPreviousImage = mCurrentImage;
             } else {
                 mFade.setValue(1f);
index 78d8135..2c32a7c 100644 (file)
@@ -33,8 +33,8 @@ import android.provider.MediaStore.Images.ImageColumns;
 import android.util.Log;
 
 /**
- * ImageManager is used to retrieve and store images
- * in the media content provider.
+ * ImageManager is used to retrieve and store images in the media content
+ * provider.
  */
 public class ImageManager {
     private static final String TAG = "ImageManager";
@@ -44,12 +44,12 @@ public class ImageManager {
     /**
      * Enumerate type for the location of the images in gallery.
      */
-    public static enum DataLocation { NONE, INTERNAL, EXTERNAL, ALL }
+    public static enum DataLocation {
+        NONE, INTERNAL, EXTERNAL, ALL
+    }
 
-    public static final Bitmap DEFAULT_THUMBNAIL =
-            Bitmap.createBitmap(32, 32, Bitmap.Config.RGB_565);
-    public static final Bitmap NO_IMAGE_BITMAP =
-            Bitmap.createBitmap(1, 1, Bitmap.Config.RGB_565);
+    public static final Bitmap DEFAULT_THUMBNAIL = Bitmap.createBitmap(32, 32, Bitmap.Config.RGB_565);
+    public static final Bitmap NO_IMAGE_BITMAP = Bitmap.createBitmap(1, 1, Bitmap.Config.RGB_565);
 
     public static final int SORT_ASCENDING = 1;
     public static final int SORT_DESCENDING = 2;
@@ -58,11 +58,8 @@ public class ImageManager {
     public static final int INCLUDE_DRM_IMAGES = (1 << 1);
     public static final int INCLUDE_VIDEOS = (1 << 2);
 
-    public static final String CAMERA_IMAGE_BUCKET_NAME =
-            Environment.getExternalStorageDirectory().toString()
-            + "/DCIM/Camera";
-    public static final String CAMERA_IMAGE_BUCKET_ID =
-            getBucketId(CAMERA_IMAGE_BUCKET_NAME);
+    public static final String CAMERA_IMAGE_BUCKET_NAME = Environment.getExternalStorageDirectory().toString() + "/DCIM/Camera";
+    public static final String CAMERA_IMAGE_BUCKET_ID = getBucketId(CAMERA_IMAGE_BUCKET_NAME);
 
     /**
      * Matches code in MediaProvider.computeBucketValues. Should be a common
@@ -77,12 +74,9 @@ public class ImageManager {
      * imported. This is a temporary fix for bug#1655552.
      */
     public static void ensureOSXCompatibleFolder() {
-        File nnnAAAAA = new File(
-            Environment.getExternalStorageDirectory().toString()
-            + "/DCIM/100ANDRO");
+        File nnnAAAAA = new File(Environment.getExternalStorageDirectory().toString() + "/DCIM/100ANDRO");
         if ((!nnnAAAAA.exists()) && (!nnnAAAAA.mkdir())) {
-            Log.e(TAG, "create NNNAAAAA file: " + nnnAAAAA.getPath()
-                    + " failed");
+            Log.e(TAG, "create NNNAAAAA file: " + nnnAAAAA.getPath() + " failed");
         }
     }
 
@@ -129,8 +123,7 @@ public class ImageManager {
         cr.update(uri, values, null, null);
     }
 
-    public static Uri addImage(ContentResolver cr, String title,
-            long dateTaken, double latitude, double longitude,
+    public static Uri addImage(ContentResolver cr, String title, long dateTaken, double latitude, double longitude,
             int orientation, String directory, String filename) {
 
         ContentValues values = new ContentValues(7);
@@ -146,7 +139,7 @@ public class ImageManager {
 
         values.put(Images.Media.LATITUDE, latitude);
         values.put(Images.Media.LONGITUDE, longitude);
-                
+
         if (directory != null && filename != null) {
             String value = directory + "/" + filename;
             values.put(Images.Media.DATA, value);
@@ -155,14 +148,12 @@ public class ImageManager {
         return cr.insert(STORAGE_URI, values);
     }
 
-
     private static class AddImageCancelable extends BaseCancelable<Void> {
         private final Uri mUri;
         private final ContentResolver mCr;
-        private final byte [] mJpegData;
+        private final byte[] mJpegData;
 
-        public AddImageCancelable(Uri uri, ContentResolver cr,
-                int orientation, Bitmap source, byte[] jpegData) {
+        public AddImageCancelable(Uri uri, ContentResolver cr, int orientation, Bitmap source, byte[] jpegData) {
             if (source == null && jpegData == null || uri == null) {
                 throw new IllegalArgumentException("source cannot be null");
             }
@@ -172,13 +163,10 @@ public class ImageManager {
         }
 
         @Override
-        protected Void execute() throws InterruptedException,
-                ExecutionException {
+        protected Void execute() throws InterruptedException, ExecutionException {
             boolean complete = false;
             try {
-                String[] projection = new String[] {
-                        ImageColumns._ID,
-                        ImageColumns.MINI_THUMB_MAGIC};
+                String[] projection = new String[] { ImageColumns._ID, ImageColumns.MINI_THUMB_MAGIC };
                 Cursor c = mCr.query(mUri, projection, null, null, null);
                 try {
                     c.moveToPosition(0);
@@ -214,26 +202,20 @@ public class ImageManager {
         }
     }
 
-    public static Cancelable<Void> storeImage(
-            Uri uri, ContentResolver cr, int orientation,
-            Bitmap source, byte [] jpegData) {
-        return new AddImageCancelable(
-                uri, cr, orientation, source, jpegData);
+    public static Cancelable<Void> storeImage(Uri uri, ContentResolver cr, int orientation, Bitmap source, byte[] jpegData) {
+        return new AddImageCancelable(uri, cr, orientation, source, jpegData);
     }
 
     static boolean isSingleImageMode(String uriString) {
-        return !uriString.startsWith(
-                MediaStore.Images.Media.EXTERNAL_CONTENT_URI.toString())
-                && !uriString.startsWith(
-                MediaStore.Images.Media.INTERNAL_CONTENT_URI.toString());
+        return !uriString.startsWith(MediaStore.Images.Media.EXTERNAL_CONTENT_URI.toString())
+                && !uriString.startsWith(MediaStore.Images.Media.INTERNAL_CONTENT_URI.toString());
     }
 
     private static boolean checkFsWritable() {
         // Create a temporary file to see whether a volume is really writeable.
         // It's important not to put it in the root directory which may have a
         // limit on the number of files.
-        String directoryName =
-                Environment.getExternalStorageDirectory().toString() + "/DCIM";
+        String directoryName = Environment.getExternalStorageDirectory().toString() + "/DCIM";
         File directory = new File(directoryName);
         if (!directory.isDirectory()) {
             if (!directory.mkdirs()) {
@@ -255,7 +237,7 @@ public class ImageManager {
             return false;
         }
     }
-    
+
     public static boolean quickHasStorage() {
         return Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState());
     }
@@ -273,23 +255,20 @@ public class ImageManager {
             } else {
                 return true;
             }
-        } else if (!requireWriteAccess
-                && Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
+        } else if (!requireWriteAccess && Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
             return true;
         }
         return false;
     }
 
-    private static final Cursor query(final ContentResolver resolver, final Uri uri,
-            final String[] projection, final String selection, final String[] selectionArgs,
-            final String sortOrder) {
+    private static final Cursor query(final ContentResolver resolver, final Uri uri, final String[] projection,
+            final String selection, final String[] selectionArgs, final String sortOrder) {
         try {
             if (resolver == null) {
                 return null;
             }
-            return resolver.query(
-                    uri, projection, selection, selectionArgs, sortOrder);
-         } catch (UnsupportedOperationException ex) {
+            return resolver.query(uri, projection, selection, selectionArgs, sortOrder);
+        } catch (UnsupportedOperationException ex) {
             return null;
         }
 
@@ -297,9 +276,8 @@ public class ImageManager {
 
     public static final boolean isMediaScannerScanning(final ContentResolver cr) {
         boolean result = false;
-        final Cursor cursor = query(cr, MediaStore.getMediaScannerUri(),
-                new String [] {MediaStore.MEDIA_SCANNER_VOLUME},
-                null, null, null);
+        final Cursor cursor = query(cr, MediaStore.getMediaScannerUri(), new String[] { MediaStore.MEDIA_SCANNER_VOLUME }, null,
+                null, null);
         if (cursor != null) {
             if (cursor.getCount() == 1) {
                 cursor.moveToFirst();
@@ -311,13 +289,10 @@ public class ImageManager {
     }
 
     public static String getLastImageThumbPath() {
-        return Environment.getExternalStorageDirectory().toString() +
-               "/DCIM/.thumbnails/image_last_thumb";
+        return Environment.getExternalStorageDirectory().toString() + "/DCIM/.thumbnails/image_last_thumb";
     }
 
     public static String getLastVideoThumbPath() {
-        return Environment.getExternalStorageDirectory().toString() +
-               "/DCIM/.thumbnails/video_last_thumb";
+        return Environment.getExternalStorageDirectory().toString() + "/DCIM/.thumbnails/video_last_thumb";
     }
 }
-
index 19a6ac1..9bfc081 100644 (file)
@@ -32,8 +32,8 @@ abstract class ImageViewTouchBase extends ImageView {
     private static final String TAG = "ImageViewTouchBase";
 
     // This is the base transformation which is used to show the image
-    // initially.  The current computation for this shows the image in
-    // it's entirety, letterboxing as needed.  One could choose to
+    // initially. The current computation for this shows the image in
+    // it's entirety, letterboxing as needed. One could choose to
     // show the image as cropped instead.
     //
     // This matrix is recomputed when we go from the thumbnail image to
@@ -74,8 +74,7 @@ abstract class ImageViewTouchBase extends ImageView {
     private Recycler mRecycler;
 
     @Override
-    protected void onLayout(boolean changed, int left, int top,
-                            int right, int bottom) {
+    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
         super.onLayout(changed, left, top, right, bottom);
         mThisWidth = right - left;
         mThisHeight = bottom - top;
@@ -135,16 +134,14 @@ abstract class ImageViewTouchBase extends ImageView {
 
     // This function changes bitmap, reset base matrix according to the size
     // of the bitmap, and optionally reset the supplementary matrix.
-    public void setImageBitmapResetBase(final Bitmap bitmap,
-            final boolean resetSupp) {
+    public void setImageBitmapResetBase(final Bitmap bitmap, final boolean resetSupp) {
         setImageRotateBitmapResetBase(new RotateBitmap(bitmap), resetSupp);
     }
 
-    public void setImageRotateBitmapResetBase(final RotateBitmap bitmap,
-            final boolean resetSupp) {
+    public void setImageRotateBitmapResetBase(final RotateBitmap bitmap, final boolean resetSupp) {
         final int viewWidth = getWidth();
 
-        if (viewWidth <= 0)  {
+        if (viewWidth <= 0) {
             mOnLayoutRunnable = new Runnable() {
                 public void run() {
                     setImageRotateBitmapResetBase(bitmap, resetSupp);
@@ -168,9 +165,9 @@ abstract class ImageViewTouchBase extends ImageView {
         mMaxZoom = maxZoom();
     }
 
-    // Center as much as possible in one or both axis.  Centering is
-    // defined as follows:  if the image is scaled down below the
-    // view's dimensions then center it (literally).  If the image
+    // Center as much as possible in one or both axis. Centering is
+    // defined as follows: if the image is scaled down below the
+    // view's dimensions then center it (literally). If the image
     // is scaled larger than the view and is translated out of view
     // then translate it back into view (i.e. eliminate black bars).
     protected void center(boolean horizontal, boolean vertical) {
@@ -180,14 +177,12 @@ abstract class ImageViewTouchBase extends ImageView {
 
         Matrix m = getImageViewMatrix();
 
-        RectF rect = new RectF(0, 0,
-                mBitmapDisplayed.getBitmap().getWidth(),
-                mBitmapDisplayed.getBitmap().getHeight());
+        RectF rect = new RectF(0, 0, mBitmapDisplayed.getBitmap().getWidth(), mBitmapDisplayed.getBitmap().getHeight());
 
         m.mapRect(rect);
 
         float height = rect.height();
-        float width  = rect.width();
+        float width = rect.width();
 
         float deltaX = 0, deltaY = 0;
 
@@ -263,9 +258,7 @@ abstract class ImageViewTouchBase extends ImageView {
         matrix.postConcat(bitmap.getRotateMatrix());
         matrix.postScale(scale, scale);
 
-        matrix.postTranslate(
-                (viewWidth  - w * scale) / 2F,
-                (viewHeight - h * scale) / 2F);
+        matrix.postTranslate((viewWidth - w * scale) / 2F, (viewHeight - h * scale) / 2F);
     }
 
     // Combine the base matrix and the supp matrix to make the final matrix.
@@ -288,7 +281,7 @@ abstract class ImageViewTouchBase extends ImageView {
             return 1F;
         }
 
-        float fw = (float) mBitmapDisplayed.getWidth()  / (float) mThisWidth;
+        float fw = (float) mBitmapDisplayed.getWidth() / (float) mThisWidth;
         float fh = (float) mBitmapDisplayed.getHeight() / (float) mThisHeight;
         float max = Math.max(fw, fh) * 4;
         return max;
@@ -307,8 +300,7 @@ abstract class ImageViewTouchBase extends ImageView {
         center(true, true);
     }
 
-    protected void zoomTo(final float scale, final float centerX,
-                          final float centerY, final float durationMs) {
+    protected void zoomTo(final float scale, final float centerX, final float centerY, final float durationMs) {
         final float incrementPerMs = (scale - getScale()) / durationMs;
         final float oldScale = getScale();
         final long startTime = System.currentTimeMillis();
@@ -344,7 +336,7 @@ abstract class ImageViewTouchBase extends ImageView {
 
     protected void zoomIn(float rate) {
         if (getScale() >= mMaxZoom) {
-            return;     // Don't let the user zoom into the molecular level.
+            return; // Don't let the user zoom into the molecular level.
         }
         if (mBitmapDisplayed.getBitmap() == null) {
             return;
index 961f439..22ba4eb 100644 (file)
@@ -68,7 +68,8 @@ public abstract class Layer {
         return false;
     }
 
-    // Allows subclasses to further constrain the hit test defined by layer bounds.
+    // Allows subclasses to further constrain the hit test defined by layer
+    // bounds.
     public boolean containsPoint(float x, float y) {
         return true;
     }
index 81a847a..31dd572 100644 (file)
@@ -2,8 +2,8 @@ package com.cooliris.media;
 
 public abstract class LayoutInterface {
     public abstract void getPositionForSlotIndex(int displayIndex, int itemWidth, int itemHeight, Vector3f outPosition); // the
-                                                                                                                         // positions
-                                                                                                                         // of the
-                                                                                                                         // individual
-                                                                                                                         // slots
+    // positions
+    // of the
+    // individual
+    // slots
 }
index f24cd5c..dab9903 100644 (file)
@@ -12,22 +12,118 @@ import android.os.SystemClock;
 public final class LoadingLayer extends Layer {
     private static final float FADE_INTERVAL = 0.5f;
     private static final float GRAY_VALUE = 0.1f;
-    private static final int[] PRELOAD_RESOURCES_ASYNC_UNSCALED = {R.drawable.stack_frame, R.drawable.grid_frame,
-            R.drawable.stack_frame_focus, R.drawable.stack_frame_gold, R.drawable.btn_location_filter_unscaled, R.drawable.videooverlay,
-            R.drawable.grid_check_on, R.drawable.grid_check_off, R.drawable.icon_camera_small_unscaled, R.drawable.icon_picasa_small_unscaled};
+    private static final int[] PRELOAD_RESOURCES_ASYNC_UNSCALED = { R.drawable.stack_frame, R.drawable.grid_frame,
+            R.drawable.stack_frame_focus, R.drawable.stack_frame_gold, R.drawable.btn_location_filter_unscaled,
+            R.drawable.videooverlay, R.drawable.grid_check_on, R.drawable.grid_check_off, R.drawable.icon_camera_small_unscaled,
+            R.drawable.icon_picasa_small_unscaled };
 
-    private static final int[] PRELOAD_RESOURCES_ASYNC_SCALED = {/*R.drawable.btn_camera_pressed, R.drawable.btn_camera_focus,
-            R.drawable.fullscreen_hud_bg, R.drawable.icon_delete,
-            R.drawable.icon_edit, R.drawable.icon_more, R.drawable.icon_share, R.drawable.selection_bg_upper,
-            R.drawable.selection_menu_bg, R.drawable.selection_menu_bg_pressed, R.drawable.selection_menu_bg_pressed_left,
-            R.drawable.selection_menu_bg_pressed_right, R.drawable.selection_menu_divider, R.drawable.timebar_bg,
-            R.drawable.timebar_knob, R.drawable.timebar_knob_pressed, R.drawable.timebar_prev, R.drawable.timebar_next,
-            R.drawable.mode_grid, R.drawable.mode_stack, R.drawable.icon_camera_small, R.drawable.icon_location_small,
-            R.drawable.icon_picasa_small, R.drawable.icon_folder_small, R.drawable.scroller_new, R.drawable.scroller_pressed_new,
-            R.drawable.btn_camera, R.drawable.btn_play, R.drawable.pathbar_bg, R.drawable.pathbar_cap, R.drawable.pathbar_join,
-            R.drawable.transparent, R.drawable.icon_home_small, R.drawable.ic_fs_details,
-            R.drawable.ic_spinner1, R.drawable.ic_spinner2, R.drawable.ic_spinner3, R.drawable.ic_spinner4, R.drawable.ic_spinner5,
-            R.drawable.ic_spinner6, R.drawable.ic_spinner7, R.drawable.ic_spinner8*/};
+    private static final int[] PRELOAD_RESOURCES_ASYNC_SCALED = {/*
+                                                                  * R.drawable.btn_camera_pressed
+                                                                  * ,
+                                                                  * R.drawable.
+                                                                  * btn_camera_focus
+                                                                  * ,
+                                                                  * R.drawable.
+                                                                  * fullscreen_hud_bg
+                                                                  * ,
+                                                                  * R.drawable.
+                                                                  * icon_delete,
+                                                                  * R.drawable.
+                                                                  * icon_edit,
+                                                                  * R.drawable.
+                                                                  * icon_more,
+                                                                  * R.drawable.
+                                                                  * icon_share,
+                                                                  * R.drawable.
+                                                                  * selection_bg_upper
+                                                                  * ,
+                                                                  * R.drawable.
+                                                                  * selection_menu_bg
+                                                                  * ,
+                                                                  * R.drawable.
+                                                                  * selection_menu_bg_pressed
+                                                                  * ,
+                                                                  * R.drawable.
+                                                                  * selection_menu_bg_pressed_left
+                                                                  * ,
+                                                                  * R.drawable.
+                                                                  * selection_menu_bg_pressed_right
+                                                                  * ,
+                                                                  * R.drawable.
+                                                                  * selection_menu_divider
+                                                                  * ,
+                                                                  * R.drawable.
+                                                                  * timebar_bg,
+                                                                  * R.drawable.
+                                                                  * timebar_knob
+                                                                  * ,
+                                                                  * R.drawable.
+                                                                  * timebar_knob_pressed
+                                                                  * ,
+                                                                  * R.drawable.
+                                                                  * timebar_prev
+                                                                  * ,
+                                                                  * R.drawable.
+                                                                  * timebar_next
+                                                                  * ,
+                                                                  * R.drawable.
+                                                                  * mode_grid,
+                                                                  * R.drawable.
+                                                                  * mode_stack,
+                                                                  * R.drawable.
+                                                                  * icon_camera_small
+                                                                  * ,
+                                                                  * R.drawable.
+                                                                  * icon_location_small
+                                                                  * ,
+                                                                  * R.drawable.
+                                                                  * icon_picasa_small
+                                                                  * ,
+                                                                  * R.drawable.
+                                                                  * icon_folder_small
+                                                                  * ,
+                                                                  * R.drawable.
+                                                                  * scroller_new
+                                                                  * ,
+                                                                  * R.drawable.
+                                                                  * scroller_pressed_new
+                                                                  * ,
+                                                                  * R.drawable.
+                                                                  * btn_camera,
+                                                                  * R.drawable.
+                                                                  * btn_play,
+                                                                  * R.drawable
+                                                                  * .pathbar_bg,
+                                                                  * R.drawable.
+                                                                  * pathbar_cap,
+                                                                  * R.drawable.
+                                                                  * pathbar_join
+                                                                  * ,
+                                                                  * R.drawable.
+                                                                  * transparent,
+                                                                  * R.drawable.
+                                                                  * icon_home_small
+                                                                  * ,
+                                                                  * R.drawable.
+                                                                  * ic_fs_details
+                                                                  * ,
+                                                                  * R.drawable.
+                                                                  * ic_spinner1,
+                                                                  * R.drawable.
+                                                                  * ic_spinner2,
+                                                                  * R.drawable.
+                                                                  * ic_spinner3,
+                                                                  * R.drawable.
+                                                                  * ic_spinner4,
+                                                                  * R.drawable.
+                                                                  * ic_spinner5,
+                                                                  * R.drawable.
+                                                                  * ic_spinner6,
+                                                                  * R.drawable.
+                                                                  * ic_spinner7,
+                                                                  * R.drawable.
+                                                                  * ic_spinner8
+                                                                  */};
 
     private boolean mLoaded = false;
     private final FloatAnim mOpacity = new FloatAnim(1f);
index f93d559..0c8ad6d 100644 (file)
@@ -33,19 +33,20 @@ public final class LocalDataSource implements DataSource {
     public static final int CAMERA_BUCKET_ID = getBucketId(CAMERA_BUCKET_NAME);
     public static final int DOWNLOAD_BUCKET_ID = getBucketId(DOWNLOAD_BUCKET_NAME);
 
-       public static boolean sObserverActive = false;
+    public static boolean sObserverActive = false;
     private boolean mDisableImages;
     private boolean mDisableVideos;
 
     /**
-     * Matches code in MediaProvider.computeBucketValues. Should be a common function.
+     * Matches code in MediaProvider.computeBucketValues. Should be a common
+     * function.
      */
     public static int getBucketId(String path) {
         return (path.toLowerCase().hashCode());
     }
 
     private Context mContext;
-       private ContentObserver mObserver;
+    private ContentObserver mObserver;
 
     public LocalDataSource(Context context) {
         mContext = context;
@@ -65,24 +66,24 @@ public final class LocalDataSource implements DataSource {
         Handler handler = ((Gallery) mContext).getHandler();
         ContentObserver observer = new ContentObserver(handler) {
             public void onChange(boolean selfChange) {
-               MediaSet mediaSet = feed.getCurrentSet();
-               if (mediaSet != null) {
-                       CacheService.markDirtyImmediate(mediaSet.mId);
-                       refreshUI(feed, mediaSet.mId);
-               }
-               CacheService.senseDirty(mContext, new CacheService.Observer() {
-                       public void onChange(long[] ids) {
-                               if (ids != null) {
-                                       int numLongs = ids.length;
-                                       for (int i = 0; i < numLongs; ++i) {
-                                               refreshUI(feed, ids[i]);
-                                       }
-                               }
-                       }
-               });
+                MediaSet mediaSet = feed.getCurrentSet();
+                if (mediaSet != null) {
+                    CacheService.markDirtyImmediate(mediaSet.mId);
+                    refreshUI(feed, mediaSet.mId);
+                }
+                CacheService.senseDirty(mContext, new CacheService.Observer() {
+                    public void onChange(long[] ids) {
+                        if (ids != null) {
+                            int numLongs = ids.length;
+                            for (int i = 0; i < numLongs; ++i) {
+                                refreshUI(feed, ids[i]);
+                            }
+                        }
+                    }
+                });
             }
         };
-        
+
         // Start listening.
         Uri uriImages = Images.Media.EXTERNAL_CONTENT_URI;
         Uri uriVideos = Video.Media.EXTERNAL_CONTENT_URI;
@@ -98,7 +99,7 @@ public final class LocalDataSource implements DataSource {
             stopListeners();
         }
     }
-    
+
     private void stopListeners() {
         ContentResolver cr = mContext.getContentResolver();
         if (mObserver != null) {
@@ -106,7 +107,7 @@ public final class LocalDataSource implements DataSource {
         }
         sObserverActive = false;
     }
-    
+
     protected void refreshUI(MediaFeed feed, long setIdToUse) {
         if (setIdToUse == Shared.INVALID) {
             return;
@@ -171,9 +172,14 @@ public final class LocalDataSource implements DataSource {
                 if (set != null && items != null) {
                     // We need to remove these items from the set.
                     int numItems = items.size();
-                    for (int j = 0; j < numItems; ++j) {
-                        MediaItem item = items.get(j);
-                        cr.delete(Uri.parse(item.mContentUri), null, null);
+                    try {
+                        for (int j = 0; j < numItems; ++j) {
+                            MediaItem item = items.get(j);
+                            cr.delete(Uri.parse(item.mContentUri), null, null);
+                        }
+                    } catch (Exception e) {
+                        // If the database operation failed for any reason.
+                        ;
                     }
                     set.updateNumExpectedItems();
                     set.generateTitle(true);
@@ -213,7 +219,12 @@ public final class LocalDataSource implements DataSource {
             // Update the database entry.
             ContentValues values = new ContentValues();
             values.put(Images.ImageColumns.ORIENTATION, rotationString);
-            cr.update(Uri.parse(item.mContentUri), values, null, null);
+            try {
+                cr.update(Uri.parse(item.mContentUri), values, null, null);
+            } catch (Exception e) {
+                // If the database operation fails for any reason.
+                ;
+            }
 
             // Update the file EXIF information.
             Uri uri = Uri.parse(item.mContentUri);
@@ -243,14 +254,19 @@ public final class LocalDataSource implements DataSource {
         long id = ContentUris.parseId(target);
         ContentResolver cr = context.getContentResolver();
         String whereClause = Images.ImageColumns._ID + "=" + Long.toString(id);
-        Cursor cursor = cr.query(Images.Media.EXTERNAL_CONTENT_URI, CacheService.PROJECTION_IMAGES, whereClause, null, null);
-        if (cursor != null) {
-            if (cursor.moveToFirst()) {
-                item = new MediaItem();
-                CacheService.populateMediaItemFromCursor(item, cr, cursor, Images.Media.EXTERNAL_CONTENT_URI.toString() + "/");
+        try {
+            Cursor cursor = cr.query(Images.Media.EXTERNAL_CONTENT_URI, CacheService.PROJECTION_IMAGES, whereClause, null, null);
+            if (cursor != null) {
+                if (cursor.moveToFirst()) {
+                    item = new MediaItem();
+                    CacheService.populateMediaItemFromCursor(item, cr, cursor, Images.Media.EXTERNAL_CONTENT_URI.toString() + "/");
+                }
+                cursor.close();
+                cursor = null;
             }
-            cursor.close();
-            cursor = null;
+        } catch (Exception e) {
+            // If the database operation failed for any reason.
+            ;
         }
         return item;
     }
@@ -262,14 +278,19 @@ public final class LocalDataSource implements DataSource {
         long bucketId = SingleDataSource.parseBucketIdFromFileUri(fileUri);
         String whereClause = Images.ImageColumns.BUCKET_ID + "=" + bucketId + " AND " + Images.ImageColumns.DATA + "='" + filepath
                 + "'";
-        Cursor cursor = cr.query(Images.Media.EXTERNAL_CONTENT_URI, CacheService.PROJECTION_IMAGES, whereClause, null, null);
-        if (cursor != null) {
-            if (cursor.moveToFirst()) {
-                item = new MediaItem();
-                CacheService.populateMediaItemFromCursor(item, cr, cursor, Images.Media.EXTERNAL_CONTENT_URI.toString() + "/");
+        try {
+            Cursor cursor = cr.query(Images.Media.EXTERNAL_CONTENT_URI, CacheService.PROJECTION_IMAGES, whereClause, null, null);
+            if (cursor != null) {
+                if (cursor.moveToFirst()) {
+                    item = new MediaItem();
+                    CacheService.populateMediaItemFromCursor(item, cr, cursor, Images.Media.EXTERNAL_CONTENT_URI.toString() + "/");
+                }
+                cursor.close();
+                cursor = null;
             }
-            cursor.close();
-            cursor = null;
+        } catch (Exception e) {
+            // If the database operation failed for any reason.
+            ;
         }
         return item;
     }
index 5a5847e..21e8c9c 100644 (file)
@@ -47,7 +47,7 @@ public class LocationMediaFilter extends MediaFilter {
         double dLat = Math.toRadians(lat2 - lat1);
         double dLon = Math.toRadians(lon2 - lon1);
         double a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2))
-                   * Math.sin(dLon / 2) * Math.sin(dLon / 2);
+                * Math.sin(dLon / 2) * Math.sin(dLon / 2);
         double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
         return EARTH_RADIUS_METERS * c;
     }
index 7145487..f55d279 100644 (file)
@@ -23,8 +23,9 @@ import java.lang.reflect.Array;
 import android.util.Log;
 
 /**
- * SparseArrays map longs to Objects. Unlike a normal array of Objects, there can be gaps in the indices. It is intended to be more
- * efficient than using a HashMap to map Longs to Objects.
+ * SparseArrays map longs to Objects. Unlike a normal array of Objects, there
+ * can be gaps in the indices. It is intended to be more efficient than using a
+ * HashMap to map Longs to Objects.
  * 
  * @hide
  */
@@ -40,8 +41,9 @@ public final class LongSparseArray<E> {
     }
 
     /**
-     * Creates a new SparseArray containing no mappings that will not require any additional memory allocation to store the
-     * specified number of mappings.
+     * Creates a new SparseArray containing no mappings that will not require
+     * any additional memory allocation to store the specified number of
+     * mappings.
      */
     public LongSparseArray(int initialCapacity) {
         initialCapacity = ArrayUtils.idealIntArraySize(initialCapacity);
@@ -52,14 +54,16 @@ public final class LongSparseArray<E> {
     }
 
     /**
-     * Gets the Object mapped from the specified key, or <code>null</code> if no such mapping has been made.
+     * Gets the Object mapped from the specified key, or <code>null</code> if no
+     * such mapping has been made.
      */
     public E get(long key) {
         return get(key, null);
     }
 
     /**
-     * Gets the Object mapped from the specified key, or the specified Object if no such mapping has been made.
+     * Gets the Object mapped from the specified key, or the specified Object if
+     * no such mapping has been made.
      */
     @SuppressWarnings("unchecked")
     public E get(long key, E valueIfKeyNotFound) {
@@ -121,8 +125,8 @@ public final class LongSparseArray<E> {
     }
 
     /**
-     * Adds a mapping from the specified key to the specified value, replacing the previous mapping from the specified key if there
-     * was one.
+     * Adds a mapping from the specified key to the specified value, replacing
+     * the previous mapping from the specified key if there was one.
      */
     public void put(long key, E value) {
         int i = binarySearch(mKeys, 0, mSize, key);
@@ -172,7 +176,8 @@ public final class LongSparseArray<E> {
     }
 
     /**
-     * Returns the number of key-value mappings that this SparseArray currently stores.
+     * Returns the number of key-value mappings that this SparseArray currently
+     * stores.
      */
     public int size() {
         if (mGarbage) {
@@ -183,8 +188,9 @@ public final class LongSparseArray<E> {
     }
 
     /**
-     * Given an index in the range <code>0...size()-1</code>, returns the key from the <code>index</code>th key-value mapping that
-     * this SparseArray stores.
+     * Given an index in the range <code>0...size()-1</code>, returns the key
+     * from the <code>index</code>th key-value mapping that this SparseArray
+     * stores.
      */
     public long keyAt(int index) {
         if (mGarbage) {
@@ -195,8 +201,9 @@ public final class LongSparseArray<E> {
     }
 
     /**
-     * Given an index in the range <code>0...size()-1</code>, returns the value from the <code>index</code>th key-value mapping that
-     * this SparseArray stores.
+     * Given an index in the range <code>0...size()-1</code>, returns the value
+     * from the <code>index</code>th key-value mapping that this SparseArray
+     * stores.
      */
     @SuppressWarnings("unchecked")
     public E valueAt(int index) {
@@ -208,8 +215,9 @@ public final class LongSparseArray<E> {
     }
 
     /**
-     * Given an index in the range <code>0...size()-1</code>, sets a new value for the <code>index</code>th key-value mapping that
-     * this SparseArray stores.
+     * Given an index in the range <code>0...size()-1</code>, sets a new value
+     * for the <code>index</code>th key-value mapping that this SparseArray
+     * stores.
      */
     public void setValueAt(int index, E value) {
         if (mGarbage) {
@@ -220,8 +228,8 @@ public final class LongSparseArray<E> {
     }
 
     /**
-     * Returns the index for which {@link #keyAt} would return the specified key, or a negative number if the specified key is not
-     * mapped.
+     * Returns the index for which {@link #keyAt} would return the specified
+     * key, or a negative number if the specified key is not mapped.
      */
     public int indexOfKey(long key) {
         if (mGarbage) {
@@ -232,9 +240,10 @@ public final class LongSparseArray<E> {
     }
 
     /**
-     * Returns an index for which {@link #valueAt} would return the specified key, or a negative number if no keys map to the
-     * specified value. Beware that this is a linear search, unlike lookups by key, and that multiple keys can map to the same value
-     * and this will find only one of them.
+     * Returns an index for which {@link #valueAt} would return the specified
+     * key, or a negative number if no keys map to the specified value. Beware
+     * that this is a linear search, unlike lookups by key, and that multiple
+     * keys can map to the same value and this will find only one of them.
      */
     public int indexOfValue(E value) {
         if (mGarbage) {
@@ -264,7 +273,8 @@ public final class LongSparseArray<E> {
     }
 
     /**
-     * Puts a key/value pair into the array, optimizing for the case where the key is greater than all existing keys in the array.
+     * Puts a key/value pair into the array, optimizing for the case where the
+     * key is greater than all existing keys in the array.
      */
     public void append(long key, E value) {
         if (mSize != 0 && key <= mKeys[mSize - 1]) {
@@ -404,8 +414,9 @@ public final class LongSparseArray<E> {
         }
 
         /**
-         * Returns an empty array of the specified type. The intent is that it will return the same empty array every time to avoid
-         * reallocation, although this is not guaranteed.
+         * Returns an empty array of the specified type. The intent is that it
+         * will return the same empty array every time to avoid reallocation,
+         * although this is not guaranteed.
          */
         @SuppressWarnings("unchecked")
         public static <T> T[] emptyArray(Class<T> kind) {
@@ -420,14 +431,16 @@ public final class LongSparseArray<E> {
                 cache = Array.newInstance(kind, 0);
                 sCache[bucket] = cache;
 
-                // Log.e("cache", "new empty " + kind.getName() + " at " + bucket);
+                // Log.e("cache", "new empty " + kind.getName() + " at " +
+                // bucket);
             }
 
             return (T[]) cache;
         }
 
         /**
-         * Checks that value is present as at least one of the elements of the array.
+         * Checks that value is present as at least one of the elements of the
+         * array.
          * 
          * @param array
          *            the array to check in
index 69d7907..7535bc2 100644 (file)
@@ -38,21 +38,18 @@ public class MatrixStack {
         mTemp = new float[MATRIX_SIZE * 2];
         glLoadIdentity();
     }
-    
+
     public void apply(float[] mCoordsIn, float[] mCoordsOut) {
         Matrix.multiplyMV(mCoordsOut, 0, mMatrix, mTop, mCoordsIn, 0);
     }
 
-    public void glFrustumf(float left, float right, float bottom, float top,
-            float near, float far) {
+    public void glFrustumf(float left, float right, float bottom, float top, float near, float far) {
         Matrix.frustumM(mMatrix, mTop, left, right, bottom, top, near, far);
     }
 
-    public void glFrustumx(int left, int right, int bottom, int top, int near,
-            int far) {
-        glFrustumf(fixedToFloat(left),fixedToFloat(right),
-                fixedToFloat(bottom), fixedToFloat(top),
-                fixedToFloat(near), fixedToFloat(far));
+    public void glFrustumx(int left, int right, int bottom, int top, int near, int far) {
+        glFrustumf(fixedToFloat(left), fixedToFloat(right), fixedToFloat(bottom), fixedToFloat(top), fixedToFloat(near),
+                fixedToFloat(far));
     }
 
     public void glLoadIdentity() {
@@ -68,13 +65,13 @@ public class MatrixStack {
     }
 
     public void glLoadMatrixx(int[] m, int offset) {
-        for(int i = 0; i < MATRIX_SIZE; i++) {
+        for (int i = 0; i < MATRIX_SIZE; i++) {
             mMatrix[mTop + i] = fixedToFloat(m[offset + i]);
         }
     }
 
     public void glLoadMatrixx(IntBuffer m) {
-        for(int i = 0; i < MATRIX_SIZE; i++) {
+        for (int i = 0; i < MATRIX_SIZE; i++) {
             mMatrix[mTop + i] = fixedToFloat(m.get());
         }
     }
@@ -90,29 +87,26 @@ public class MatrixStack {
     }
 
     public void glMultMatrixx(int[] m, int offset) {
-        for(int i = 0; i < MATRIX_SIZE; i++) {
+        for (int i = 0; i < MATRIX_SIZE; i++) {
             mTemp[MATRIX_SIZE + i] = fixedToFloat(m[offset + i]);
         }
         glMultMatrixf(mTemp, MATRIX_SIZE);
     }
 
     public void glMultMatrixx(IntBuffer m) {
-        for(int i = 0; i < MATRIX_SIZE; i++) {
+        for (int i = 0; i < MATRIX_SIZE; i++) {
             mTemp[MATRIX_SIZE + i] = fixedToFloat(m.get());
         }
         glMultMatrixf(mTemp, MATRIX_SIZE);
     }
 
-    public void glOrthof(float left, float right, float bottom, float top,
-            float near, float far) {
+    public void glOrthof(float left, float right, float bottom, float top, float near, float far) {
         Matrix.orthoM(mMatrix, mTop, left, right, bottom, top, near, far);
     }
 
-    public void glOrthox(int left, int right, int bottom, int top, int near,
-            int far) {
-        glOrthof(fixedToFloat(left), fixedToFloat(right),
-                fixedToFloat(bottom), fixedToFloat(top),
-                fixedToFloat(near), fixedToFloat(far));
+    public void glOrthox(int left, int right, int bottom, int top, int near, int far) {
+        glOrthof(fixedToFloat(left), fixedToFloat(right), fixedToFloat(bottom), fixedToFloat(top), fixedToFloat(near),
+                fixedToFloat(far));
     }
 
     public void glPopMatrix() {
@@ -122,8 +116,7 @@ public class MatrixStack {
 
     public void glPushMatrix() {
         preflight_adjust(1);
-        System.arraycopy(mMatrix, mTop, mMatrix, mTop + MATRIX_SIZE,
-                MATRIX_SIZE);
+        System.arraycopy(mMatrix, mTop, mMatrix, mTop + MATRIX_SIZE, MATRIX_SIZE);
         adjust(1);
     }
 
@@ -181,4 +174,3 @@ public class MatrixStack {
     private int mTop;
     private float[] mTemp;
 }
-
index 773fefc..eb715d1 100644 (file)
@@ -3,7 +3,6 @@ package com.cooliris.media;
 import java.util.ArrayList;
 import java.util.HashMap;
 
-
 public final class MediaBucketList {
     private static final Boolean TRUE = new Boolean(true);
     private static final Boolean FALSE = new Boolean(false);
@@ -36,7 +35,8 @@ public final class MediaBucketList {
         return item;
     }
 
-    // Returns the first set selection (ignoring sets corresponding to item selections).
+    // Returns the first set selection (ignoring sets corresponding to item
+    // selections).
     public static MediaSet getFirstSetSelection(ArrayList<MediaBucket> buckets) {
         MediaSet set = null;
         if (buckets != null) {
@@ -65,7 +65,8 @@ public final class MediaBucketList {
                 int numItems = 0;
                 if (bucket.mediaItems == null && bucket.mediaSet != null) {
                     numItems = bucket.mediaSet.getNumItems();
-                    // This selection reflects the bucket itself, and not the items inside the bucket (which is 0).
+                    // This selection reflects the bucket itself, and not the
+                    // items inside the bucket (which is 0).
                     if (numItems == 0) {
                         numItems = 1;
                     }
@@ -116,7 +117,8 @@ public final class MediaBucketList {
             if (bucketCompare.mediaSet == mediaSetToAdd) {
                 // We found the MediaSet.
                 if (!hasExpandedMediaSet) {
-                    // Remove this bucket from the list since this bucket was already selected.
+                    // Remove this bucket from the list since this bucket was
+                    // already selected.
                     if (removeIfAlreadyAdded) {
                         selectedBuckets.remove(bucketCompare);
                     }
@@ -153,7 +155,8 @@ public final class MediaBucketList {
                         boolean foundIndex = false;
                         for (int j = 0; j < numPresentItems; ++j) {
                             if (selectedItems.get(j) == item) {
-                                // This index was already present, we need to remove it.
+                                // This index was already present, we need to
+                                // remove it.
                                 foundIndex = true;
                                 if (removeIfAlreadyAdded) {
                                     selectedItems.remove(j);
@@ -238,7 +241,8 @@ public final class MediaBucketList {
         return (bucket.mediaSet != null && bucket.mediaItems == null) ? true : false;
     }
 
-    // Assumption: If multiple items are selected, they must all be in the first bucket.
+    // Assumption: If multiple items are selected, they must all be in the first
+    // bucket.
     protected static boolean isMultipleItemSelection(ArrayList<MediaBucket> buckets) {
         if (buckets != null) {
             int numBuckets = buckets.size();
index 29b1cd4..12cd96f 100644 (file)
@@ -9,15 +9,19 @@ import android.content.Context;
 import android.content.res.Resources;
 
 /**
- * Implementation of an agglomerative based clustering where all items within a certain time cutoff are grouped into the
- * same cluster. Small adjacent clusters are merged and large individual clusters are considered for splitting.
+ * Implementation of an agglomerative based clustering where all items within a
+ * certain time cutoff are grouped into the same cluster. Small adjacent
+ * clusters are merged and large individual clusters are considered for
+ * splitting.
  * 
- * TODO: Limitation: Can deal with items not being added incrementally to the end of the current date range
- * but effectively assumes this is the case for efficient performance.
+ * TODO: Limitation: Can deal with items not being added incrementally to the
+ * end of the current date range but effectively assumes this is the case for
+ * efficient performance.
  */
 
 public final class MediaClustering {
-    // If 2 items are greater than 25 miles apart, they will be in different clusters.
+    // If 2 items are greater than 25 miles apart, they will be in different
+    // clusters.
     private static final int GEOGRAPHIC_DISTANCE_CUTOFF_IN_MILES = 20;
 
     // Do not want to split based on anything under 1 min.
@@ -43,11 +47,13 @@ public final class MediaClustering {
     // 3 cluster frequencies of each other.
     private static int CLUSTER_SPLIT_MULTIPLIER = 3;
 
-    // The minimum change factor in the time between items to consider a partition.
+    // The minimum change factor in the time between items to consider a
+    // partition.
     // Example: (Item 3 - Item 2) / (Item 2 - Item 1).
     private static final int MIN_PARTITION_CHANGE_FACTOR = 2;
 
-    // Make the cluster split time of a large cluster half that of a regular cluster.
+    // Make the cluster split time of a large cluster half that of a regular
+    // cluster.
     private static final int PARTITION_CLUSTER_SPLIT_TIME_FACTOR = 2;
 
     private ArrayList<Cluster> mClusters;
@@ -78,7 +84,8 @@ public final class MediaClustering {
     public void setTimeRange(long timeRange, int numItems) {
         if (numItems != 0) {
             int meanItemsPerCluster = numItems / NUM_CLUSTERS_TARGETED;
-            // Heuristic to get min and max cluster size - half and double the desired items per cluster.
+            // Heuristic to get min and max cluster size - half and double the
+            // desired items per cluster.
             mMinClusterSize = meanItemsPerCluster / 2;
             mMaxClusterSize = meanItemsPerCluster * 2;
             mClusterSplitTime = timeRange / numItems * CLUSTER_SPLIT_MULTIPLIER;
@@ -117,20 +124,22 @@ public final class MediaClustering {
             boolean geographicallySeparateItem = false;
             boolean itemAddedToCurrentCluster = false;
 
-            // Determine if this item should go in the current cluster or be the start of a new cluster.
+            // Determine if this item should go in the current cluster or be the
+            // start of a new cluster.
             if (numCurrClusterItems == 0) {
                 mCurrCluster.addItem(currentItem);
             } else {
                 MediaItem prevItem = mCurrCluster.getLastItem();
-                if (timeDistance(prevItem, currentItem) < mClusterSplitTime) {
-                    mCurrCluster.addItem(currentItem);
-                    itemAddedToCurrentCluster = true;
-                } else if (isGeographicallySeparated(prevItem, currentItem)) {
+                if (isGeographicallySeparated(prevItem, currentItem)) {
                     mClusters.add(mCurrCluster);
                     geographicallySeparateItem = true;
                 } else if (numCurrClusterItems > mMaxClusterSize) {
                     splitAndAddCurrentCluster();
-                } else if (numClusters > 0 && numCurrClusterItems < mMinClusterSize && !mCurrCluster.mGeographicallySeparatedFromPrevCluster) {
+                } else if (timeDistance(prevItem, currentItem) < mClusterSplitTime) {
+                    mCurrCluster.addItem(currentItem);
+                    itemAddedToCurrentCluster = true;
+                } else if (numClusters > 0 && numCurrClusterItems < mMinClusterSize
+                        && !mCurrCluster.mGeographicallySeparatedFromPrevCluster) {
                     mergeAndAddCurrentCluster();
                 } else {
                     mClusters.add(mCurrCluster);
@@ -154,7 +163,8 @@ public final class MediaClustering {
             // The last cluster may potentially be too big or too small.
             if (numCurrClusterItems > mMaxClusterSize) {
                 splitAndAddCurrentCluster();
-            } else if (numClusters > 0 && numCurrClusterItems < mMinClusterSize && !mCurrCluster.mGeographicallySeparatedFromPrevCluster) {
+            } else if (numClusters > 0 && numCurrClusterItems < mMinClusterSize
+                    && !mCurrCluster.mGeographicallySeparatedFromPrevCluster) {
                 mergeAndAddCurrentCluster();
             } else {
                 mClusters.add(mCurrCluster);
@@ -180,7 +190,7 @@ public final class MediaClustering {
             mClusters.add(partitionedCluster);
         } else {
             mClusters.add(mCurrCluster);
-        }        
+        }
     }
 
     private int getPartitionIndexForCurrentCluster() {
@@ -196,7 +206,7 @@ public final class MediaClustering {
                 MediaItem prevItem = currClusterItems.get(i - 1);
                 MediaItem currItem = currClusterItems.get(i);
                 MediaItem nextItem = currClusterItems.get(i + 1);
-    
+
                 if (prevItem.isDateTakenValid() && currItem.isDateModifiedValid() && nextItem.isDateModifiedValid()) {
                     long diff1 = Math.abs(nextItem.mDateTakenInMs - currItem.mDateTakenInMs);
                     long diff2 = Math.abs(currItem.mDateTakenInMs - prevItem.mDateTakenInMs);
@@ -281,24 +291,33 @@ public final class MediaClustering {
                     String maxDay = DateFormat.format(MMDDYY_FORMAT, maxTimestamp).toString();
 
                     if (minDay.substring(4).equals(maxDay.substring(4))) {
-                        // The items are from the same year - show at least as much granularity as abbrev_all allows.
+                        // The items are from the same year - show at least as
+                        // much granularity as abbrev_all allows.
                         mName = DateUtils.formatDateRange(context, minTimestamp, maxTimestamp, DateUtils.FORMAT_ABBREV_ALL);
 
-                        // Get a more granular date range string if the min and max timestamp are on the same day and from the current year.
+                        // Get a more granular date range string if the min and
+                        // max timestamp are on the same day and from the
+                        // current year.
                         if (minDay.equals(maxDay)) {
                             int flags = DateUtils.FORMAT_ABBREV_MONTH | DateUtils.FORMAT_SHOW_DATE;
-                            // Contains the year only if the date does not correspond to the current year.
+                            // Contains the year only if the date does not
+                            // correspond to the current year.
                             String dateRangeWithOptionalYear = DateUtils.formatDateTime(context, minTimestamp, flags);
-                            String dateRangeWithYear = DateUtils.formatDateTime(context, minTimestamp, flags | DateUtils.FORMAT_SHOW_YEAR);
+                            String dateRangeWithYear = DateUtils.formatDateTime(context, minTimestamp, flags
+                                    | DateUtils.FORMAT_SHOW_YEAR);
                             if (!dateRangeWithOptionalYear.equals(dateRangeWithYear)) {
-                                // This means both dates are from the same year - show the time.
-                                // Not enough room to display the time range. Pick the mid-point.
+                                // This means both dates are from the same year
+                                // - show the time.
+                                // Not enough room to display the time range.
+                                // Pick the mid-point.
                                 long midTimestamp = (minTimestamp + maxTimestamp) / 2;
-                                mName = DateUtils.formatDateRange(context, midTimestamp, midTimestamp, DateUtils.FORMAT_SHOW_TIME | flags);
+                                mName = DateUtils.formatDateRange(context, midTimestamp, midTimestamp, DateUtils.FORMAT_SHOW_TIME
+                                        | flags);
                             }
                         }
                     } else {
-                        // The items are not from the same year - only show month and year.
+                        // The items are not from the same year - only show
+                        // month and year.
                         int flags = DateUtils.FORMAT_NO_MONTH_DAY | DateUtils.FORMAT_ABBREV_MONTH | DateUtils.FORMAT_SHOW_DATE;
                         mName = DateUtils.formatDateRange(context, minTimestamp, maxTimestamp, flags);
                     }
@@ -344,7 +363,8 @@ public final class MediaClustering {
 
     // Returns true if a, b are sufficiently geographically separated.
     private static boolean isGeographicallySeparated(MediaItem a, MediaItem b) {
-        // If a or b are null, a or b have the default latitude, longitude values or are close enough, return false.
+        // If a or b are null, a or b have the default latitude, longitude
+        // values or are close enough, return false.
         if (a != null && b != null && a.isLatLongValid() && b.isLatLongValid()) {
             int distance = (int) (LocationMediaFilter.toMile(LocationMediaFilter.distanceBetween(a.mLatitude, a.mLongitude,
                     b.mLatitude, b.mLongitude)) + 0.5);
index f905ed0..d2e4a28 100644 (file)
@@ -214,7 +214,8 @@ public final class MediaFeed implements Runnable {
                         } else if (set != null && items != null) {
                             // We need to remove these items from the set.
                             int numItems = items.size();
-                            // We also need to delete the items from the cluster.
+                            // We also need to delete the items from the
+                            // cluster.
                             MediaClustering clustering = mClusterSets.get(set);
                             for (int j = 0; j < numItems; ++j) {
                                 MediaItem item = items.get(j);
@@ -243,7 +244,7 @@ public final class MediaFeed implements Runnable {
 
     public void removeMediaSet(MediaSet set) {
         synchronized (mMediaSets) {
-               mMediaSets.remove(set);
+            mMediaSets.remove(set);
         }
         mMediaFeedNeedsToRun = true;
     }
@@ -346,7 +347,8 @@ public final class MediaFeed implements Runnable {
                     return;
                 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
                 DataSource dataSource = mDataSource;
-                // We must wait while the SD card is mounted or the MediaScanner is running.
+                // We must wait while the SD card is mounted or the MediaScanner
+                // is running.
                 if (dataSource != null) {
                     dataSource.loadMediaSets(feed);
                 }
@@ -528,7 +530,8 @@ public final class MediaFeed implements Runnable {
                         }
                         MediaSet set = mediaSets.get(expandedSetIndex);
                         if (numItemsLoaded < set.getNumExpectedItems()) {
-                            // TODO(Venkat) Why are we doing 4th param calculations like this?
+                            // We perform calculations for a window that gets anchored to a multiple of NUM_ITEMS_LOOKAHEAD.
+                            // The start of the window is 0, x, 2x, 3x ... etc where x = NUM_ITEMS_LOOKAHEAD.
                             dataSource.loadItemsForSet(this, set, numItemsLoaded, (requestedItems / NUM_ITEMS_LOOKAHEAD)
                                     * NUM_ITEMS_LOOKAHEAD + NUM_ITEMS_LOOKAHEAD);
                             if (set.getNumExpectedItems() == 0) {
@@ -572,7 +575,7 @@ public final class MediaFeed implements Runnable {
         }
         if (mExpandedMediaSetIndex > 0 && mediaSetIndex == Shared.INVALID) {
             // We are collapsing a previously expanded media set
-            if (mediaSetIndex < mMediaSets.size() && mExpandedMediaSetIndex >= 0) {
+            if (mediaSetIndex < mMediaSets.size() && mExpandedMediaSetIndex >= 0 && mExpandedMediaSetIndex < mMediaSets.size()) {
                 MediaSet set = mMediaSets.get(mExpandedMediaSetIndex);
                 if (set.getNumItems() == 0) {
                     set.clear();
@@ -583,7 +586,8 @@ public final class MediaFeed implements Runnable {
         if (mediaSetIndex < mMediaSets.size() && mediaSetIndex >= 0) {
             // Notify Picasa that the user entered the album.
             // MediaSet set = mMediaSets.get(mediaSetIndex);
-            // PicasaService.requestSync(mContext, PicasaService.TYPE_ALBUM_PHOTOS, set.mPicasaAlbumId);
+            // PicasaService.requestSync(mContext,
+            // PicasaService.TYPE_ALBUM_PHOTOS, set.mPicasaAlbumId);
         }
         updateListener(true);
         mMediaFeedNeedsToRun = true;
@@ -704,7 +708,7 @@ public final class MediaFeed implements Runnable {
         ArrayList<MediaSet> mediaSets = mMediaSets;
         int numSets = mediaSets.size();
         for (int i = 0; i < numSets; ++i) {
-               final MediaSet thisSet = mediaSets.get(i);
+            final MediaSet thisSet = mediaSets.get(i);
             if (thisSet.mId == setId) {
                 mediaSet.mName = thisSet.mName;
                 mediaSet.mHasImages = thisSet.mHasImages;
index a94b536..d9b2734 100644 (file)
@@ -3,14 +3,17 @@ package com.cooliris.media;
 public final class MediaItem {
     public static final int MEDIA_TYPE_IMAGE = 0;
     public static final int MEDIA_TYPE_VIDEO = 1;
-    // Approximately the year 1975 in milliseconds and seconds. Serves as a min cutoff for bad times.
+    // Approximately the year 1975 in milliseconds and seconds. Serves as a min
+    // cutoff for bad times.
     public static final long MIN_VALID_DATE_IN_MS = 157680000000L;
     public static final long MIN_VALID_DATE_IN_SEC = 157680000L;
-    // Approximately the year 2035 in milliseconds ans seconds. Serves as a max cutoff for bad time.
+    // Approximately the year 2035 in milliseconds ans seconds. Serves as a max
+    // cutoff for bad time.
     public static final long MAX_VALID_DATE_IN_MS = 2049840000000L;
     public static final long MAX_VALID_DATE_IN_SEC = 2049840000L;
 
-    // mId is not a unique identifier of the item mId is initialized to -1 in some cases.
+    // mId is not a unique identifier of the item mId is initialized to -1 in
+    // some cases.
     public static final String ID = new String("id");
     public long mId;
 
@@ -91,13 +94,14 @@ public final class MediaItem {
     public boolean isPicassaItem() {
         return (mParentMediaSet != null && mParentMediaSet.isPicassaAlbum());
     }
-    
+
     private static final String VIDEO = "video/";
 
     public int getMediaType() {
         if (mMediaType == -1) {
             // Default to image if mMimetype is null or not video.
-            mMediaType = (mMimeType != null && mMimeType.startsWith(VIDEO)) ? MediaItem.MEDIA_TYPE_VIDEO : MediaItem.MEDIA_TYPE_IMAGE;
+            mMediaType = (mMimeType != null && mMimeType.startsWith(VIDEO)) ? MediaItem.MEDIA_TYPE_VIDEO
+                    : MediaItem.MEDIA_TYPE_IMAGE;
         }
         return mMediaType;
     }
@@ -110,7 +114,7 @@ public final class MediaItem {
         if (mDisplayMimeType == null && mMimeType != null) {
             int slashPos = mMimeType.indexOf('/');
             if (slashPos != -1 && slashPos + 1 < mMimeType.length()) {
-                mDisplayMimeType = mMimeType.substring(slashPos + 1).toUpperCase();                
+                mDisplayMimeType = mMimeType.substring(slashPos + 1).toUpperCase();
             } else {
                 mDisplayMimeType = mMimeType.toUpperCase();
             }
index 9d0b198..553e002 100644 (file)
@@ -37,7 +37,7 @@ public final class MediaItemTexture extends Texture {
         mItem = item;
         mCached = computeCache();
     }
-    
+
     private boolean computeCache() {
         final Config config = mConfig;
         final MediaItem item = mItem;
@@ -83,7 +83,8 @@ public final class MediaItemTexture extends Texture {
         final Config config = mConfig;
         final MediaItem item = mItem;
 
-        // Special case for non-MediaStore content URIs, do not cache the thumbnail.
+        // Special case for non-MediaStore content URIs, do not cache the
+        // thumbnail.
         String uriString = item.mContentUri;
         if (uriString != null) {
             Uri uri = Uri.parse(uriString);
index b929d73..c7cda21 100644 (file)
@@ -13,9 +13,12 @@ public class MediaSet {
     public boolean mHasImages;
     public boolean mHasVideos;
 
-    // The type of the media set. A smart media set is an automatically generated media set. For example, the most recently
-    // viewed items media set is a media set that gets populated by the contents of a folder. A user defined media set
-    // is a set that is made by the user. This would typically correspond to media items belonging to an event.
+    // The type of the media set. A smart media set is an automatically
+    // generated media set. For example, the most recently
+    // viewed items media set is a media set that gets populated by the contents
+    // of a folder. A user defined media set
+    // is a set that is made by the user. This would typically correspond to
+    // media items belonging to an event.
     public int mType;
 
     // The min and max date taken and added at timestamps.
@@ -37,9 +40,11 @@ public class MediaSet {
     public double mMaxLonLatitude;
     public double mMaxLonLongitude = LocationMediaFilter.LON_MIN;
 
-    // Reverse geocoding the latitude, longitude and getting an address or location.
+    // Reverse geocoding the latitude, longitude and getting an address or
+    // location.
     public String mReverseGeocodedLocation;
-    // Set to true if at least one item in the set has a valid latitude and longitude.
+    // Set to true if at least one item in the set has a valid latitude and
+    // longitude.
     public boolean mLatLongDetermined = false;
     public boolean mReverseGeocodedLocationComputed = false;
     public boolean mReverseGeocodedLocationRequestMade = false;
@@ -56,8 +61,10 @@ public class MediaSet {
 
     private ArrayList<MediaItem> mItems;
     public int mNumItemsLoaded = 0;
-    // mNumExpectedItems is preset to how many items are expected to be in the set as it is used to visually
-    // display the number of items in the set and we don't want this display to keep changing as items get loaded.
+    // mNumExpectedItems is preset to how many items are expected to be in the
+    // set as it is used to visually
+    // display the number of items in the set and we don't want this display to
+    // keep changing as items get loaded.
     private int mNumExpectedItems = 0;
     private boolean mNumExpectedItemsCountAccurate = false;
 
@@ -77,7 +84,8 @@ public class MediaSet {
     }
 
     /**
-     * @return underlying ArrayList of MediaItems. Use only for iteration (read operations) on the ArrayList.
+     * @return underlying ArrayList of MediaItems. Use only for iteration (read
+     *         operations) on the ArrayList.
      */
     public ArrayList<MediaItem> getItems() {
         return mItems;
@@ -92,7 +100,7 @@ public class MediaSet {
     public int getNumExpectedItems() {
         return mNumExpectedItems;
     }
-    
+
     public boolean setContainsValidItems() {
         if (mNumExpectedItems == 0)
             return false;
@@ -131,7 +139,8 @@ public class MediaSet {
         mTitleString = mName + size;
         if (truncateTitle) {
             int length = mName.length();
-            mTruncTitleString = (length > 16) ? mName.substring(0, 12) + "..." + mName.substring(length - 4, length) + size : mName + size;
+            mTruncTitleString = (length > 16) ? mName.substring(0, 12) + "..." + mName.substring(length - 4, length) + size : mName
+                    + size;
             mNoCountTitleString = mName;
         } else {
             mTruncTitleString = mTitleString;
@@ -139,11 +148,13 @@ public class MediaSet {
     }
 
     /**
-     * Adds a MediaItem to this set, and increments the load count. Additionally, it also recomputes
-     * the location bounds and time range of the media set.
+     * Adds a MediaItem to this set, and increments the load count.
+     * Additionally, it also recomputes the location bounds and time range of
+     * the media set.
      */
     public void addItem(final MediaItem item) {
-        // Important to not set the parentMediaSet in here as temporary MediaSet's are occasionally
+        // Important to not set the parentMediaSet in here as temporary
+        // MediaSet's are occasionally
         // created and we do not want the MediaItem updated as a result of that.
         if (mItems.size() == 0) {
             mItems.add(item);
@@ -173,10 +184,11 @@ public class MediaSet {
             }
             if (dateAdded > mMaxAddedTimestamp) {
                 mMaxAddedTimestamp = dateAdded;
-            }            
+            }
         }
 
-        // Determining the latitude longitude bounds of the set and setting the location string.
+        // Determining the latitude longitude bounds of the set and setting the
+        // location string.
         if (!item.isLatLongValid()) {
             return;
         }
@@ -207,7 +219,8 @@ public class MediaSet {
     /**
      * Removes a MediaItem if present in the MediaSet.
      * 
-     * @return true if the item was removed, false if removal failed or item was not present in the set.
+     * @return true if the item was removed, false if removal failed or item was
+     *         not present in the set.
      */
     public boolean removeItem(final MediaItem itemToRemove) {
         if (mItems.remove(itemToRemove)) {
@@ -251,11 +264,13 @@ public class MediaSet {
      */
     public boolean isPicassaSet() {
         // 2 cases:-
-        // 1. This set is just a Picassa Album, and all its items are therefore from Picassa.
-        // 2. This set is a random collection of items and each item is a Picassa item.
+        // 1. This set is just a Picassa Album, and all its items are therefore
+        // from Picassa.
+        // 2. This set is a random collection of items and each item is a
+        // Picassa item.
         if (isPicassaAlbum()) {
             return true;
-        } 
+        }
         int numItems = mItems.size();
         for (int i = 0; i < numItems; i++) {
             if (!mItems.get(i).isPicassaItem()) {
index efebce9..280f6de 100644 (file)
@@ -21,7 +21,7 @@ public final class MenuBar extends Layer implements PopupMenu.Listener {
         MENU_TITLE_STYLE.fontSize = 17 * Gallery.PIXEL_DENSITY;
         MENU_TITLE_STYLE.sizeMode = StringTexture.Config.SIZE_EXACT;
         MENU_TITLE_STYLE.overflowMode = StringTexture.Config.OVERFLOW_FADE;
-        
+
         MENU_TITLE_STYLE_TEXT.fontSize = 15 * Gallery.PIXEL_DENSITY;
         MENU_TITLE_STYLE_TEXT.xalignment = StringTexture.Config.ALIGN_HCENTER;
         MENU_TITLE_STYLE_TEXT.sizeMode = StringTexture.Config.SIZE_EXACT;
@@ -70,12 +70,12 @@ public final class MenuBar extends Layer implements PopupMenu.Listener {
             mSubmenu.close(false);
         }
     }
-    
+
     @Override
     protected void onSizeChanged() {
         mNeedsLayout = true;
     }
-    
+
     @Override
     public void generate(RenderView view, RenderView.Lists lists) {
         lists.blendedList.add(this);
@@ -93,14 +93,14 @@ public final class MenuBar extends Layer implements PopupMenu.Listener {
             mNeedsLayout = false;
         }
         if (mGL != gl) {
-               mTextureMap.clear();
-               mGL = gl;
+            mTextureMap.clear();
+            mGL = gl;
         }
-        
+
         // Draw the background.
         Texture background = view.getResource(BACKGROUND);
         int backgroundHeight = background.getHeight();
-        int menuHeight = (int)(HEIGHT * Gallery.PIXEL_DENSITY + 0.5f);
+        int menuHeight = (int) (HEIGHT * Gallery.PIXEL_DENSITY + 0.5f);
         int extra = background.getHeight() - menuHeight;
         view.draw2D(background, mX, mY - extra, mWidth, backgroundHeight);
 
@@ -119,17 +119,17 @@ public final class MenuBar extends Layer implements PopupMenu.Listener {
         if (canDrawHighlight()) {
             drawHighlight(view, gl, touchMenu);
         }
-        
+
         // Draw labels.
         float height = mHeight;
         for (int i = 0; i != numMenus; ++i) {
             // Draw the icon and title.
             Menu menu = menus[i];
             ResourceTexture icon = view.getResource(menu.icon);
-            
+
             StringTexture titleTexture = (StringTexture) mTextureMap.get(menu.title);
             if (titleTexture == null) {
-               titleTexture = new StringTexture(menu.title, menu.config, menu.titleWidth, MENU_TITLE_STYLE.height);
+                titleTexture = new StringTexture(menu.title, menu.config, menu.titleWidth, MENU_TITLE_STYLE.height);
                 view.loadTexture(titleTexture);
                 menu.titleTexture = titleTexture;
                 mTextureMap.put(menu.title, titleTexture);
@@ -145,21 +145,22 @@ public final class MenuBar extends Layer implements PopupMenu.Listener {
             view.draw2D(titleTexture, menu.x + offset + iconWidth, titleY);
         }
     }
-    
+
     private void drawHighlight(RenderView view, GL11 gl, int touchMenu) {
         Texture highlightLeft = view.getResource(MENU_HIGHLIGHT_LEFT);
         Texture highlightMiddle = view.getResource(MENU_HIGHLIGHT_MIDDLE);
         Texture highlightRight = view.getResource(MENU_HIGHLIGHT_RIGHT);
 
         int height = highlightLeft.getHeight();
-        int extra = height - (int)(HEIGHT * Gallery.PIXEL_DENSITY);
+        int extra = height - (int) (HEIGHT * Gallery.PIXEL_DENSITY);
         Menu menu = mMenus[touchMenu];
-        int x = menu.x + (int)(MENU_HIGHLIGHT_EDGE_INSET * Gallery.PIXEL_DENSITY);
-        int width = menu.mWidth - (int)((MENU_HIGHLIGHT_EDGE_INSET * 2) * Gallery.PIXEL_DENSITY);
+        int x = menu.x + (int) (MENU_HIGHLIGHT_EDGE_INSET * Gallery.PIXEL_DENSITY);
+        int width = menu.mWidth - (int) ((MENU_HIGHLIGHT_EDGE_INSET * 2) * Gallery.PIXEL_DENSITY);
         int y = (int) mY - extra;
 
         // Draw left edge.
-        view.draw2D(highlightLeft, x - MENU_HIGHLIGHT_EDGE_WIDTH * Gallery.PIXEL_DENSITY, y, MENU_HIGHLIGHT_EDGE_WIDTH * Gallery.PIXEL_DENSITY, height);
+        view.draw2D(highlightLeft, x - MENU_HIGHLIGHT_EDGE_WIDTH * Gallery.PIXEL_DENSITY, y, MENU_HIGHLIGHT_EDGE_WIDTH
+                * Gallery.PIXEL_DENSITY, height);
 
         // Draw middle.
         view.draw2D(highlightMiddle, x, y, width, height);
@@ -217,7 +218,7 @@ public final class MenuBar extends Layer implements PopupMenu.Listener {
                     int y = (int) mY;
                     didShow = true;
                     submenu.setOptions(options);
-                    submenu.showAtPoint(x, y, (int)mWidth, (int)mHeight);
+                    submenu.showAtPoint(x, y, (int) mWidth, (int) mHeight);
                 }
             }
             if (!didShow) {
@@ -279,7 +280,8 @@ public final class MenuBar extends Layer implements PopupMenu.Listener {
             // Forward event to submenu.
             mSubmenu.onTouchEvent(event);
 
-            // Leave the submenu open if the touch ends on the menu button in less than
+            // Leave the submenu open if the touch ends on the menu button in
+            // less than
             // a time threshold.
             long elapsed = event.getEventTime() - event.getDownTime();
             if (hit != -1) {
@@ -308,85 +310,92 @@ public final class MenuBar extends Layer implements PopupMenu.Listener {
     }
 
     private void layoutMenus() {
-       mTextureMap.clear();
-       
+        mTextureMap.clear();
+
         Menu[] menus = mMenus;
         int numMenus = menus.length;
         // we do the best attempt to fit the menu items and resize them
         // also, it tries to minimize different sized menu items
-        // it finds the maximum width for a set of menu items, and checks whether that width
-        // can be used for all the cells, else, it goes to the next maximum width, so on and
+        // it finds the maximum width for a set of menu items, and checks
+        // whether that width
+        // can be used for all the cells, else, it goes to the next maximum
+        // width, so on and
         // so forth
         if (numMenus != 0) {
             float viewWidth = mWidth;
             int occupiedWidth = 0;
             int previousMaxWidth = Integer.MAX_VALUE;
             int totalDesiredWidth = 0;
-            
+
             for (int i = 0; i < numMenus; i++) {
                 totalDesiredWidth += menus[i].computeRequiredWidth();
             }
-            
+
             if (totalDesiredWidth > viewWidth) {
-               // Just split the menus up by available size / nr of menus.
-               int widthPerMenu = (int) Math.floor(viewWidth / numMenus);
-               int x = 0;
-               
-               for (int i = 0; i < numMenus; i++) {
-                       Menu menu = menus[i];
-                       menu.x = x;
-                       menu.mWidth = widthPerMenu;
-                       menu.titleWidth = widthPerMenu - (20 + (menu.icon != 0 ? 45 : 0)); //TODO factor out padding etc
-
-                       // fix up rounding errors by adding the last pixel to the last menu. 
-                       if (i == numMenus - 1) {
-                               menu.mWidth = (int) viewWidth - x;
-                       }
-                       x += widthPerMenu;
-                       
-               }
+                // Just split the menus up by available size / nr of menus.
+                int widthPerMenu = (int) Math.floor(viewWidth / numMenus);
+                int x = 0;
+
+                for (int i = 0; i < numMenus; i++) {
+                    Menu menu = menus[i];
+                    menu.x = x;
+                    menu.mWidth = widthPerMenu;
+                    menu.titleWidth = widthPerMenu - (20 + (menu.icon != 0 ? 45 : 0)); // TODO
+                                                                                       // factor
+                                                                                       // out
+                                                                                       // padding
+                                                                                       // etc
+
+                    // fix up rounding errors by adding the last pixel to the
+                    // last menu.
+                    if (i == numMenus - 1) {
+                        menu.mWidth = (int) viewWidth - x;
+                    }
+                    x += widthPerMenu;
+
+                }
             } else {
                 boolean foundANewMaxWidth = true;
                 int menusProcessed = 0;
-               
-               while (foundANewMaxWidth && menusProcessed < numMenus) {
-                       foundANewMaxWidth = false;
-                       int maxWidth = 0;
-                       for (int i = 0; i < numMenus; ++i) {
-                           int width = menus[i].computeRequiredWidth();
-                           if (width > maxWidth && width < previousMaxWidth) {
-                               foundANewMaxWidth = true;
-                               maxWidth = width;
-                           }
-                       }
-                       // can all the menus have this width
-                       int cumulativeWidth = maxWidth * (numMenus - menusProcessed) + occupiedWidth;
-                       if (cumulativeWidth < viewWidth || !foundANewMaxWidth || menusProcessed == numMenus - 1) {
-                           float delta = (viewWidth - cumulativeWidth) / numMenus;
-                           if (delta < 0) {
-                               delta = 0;
-                           }
-                           int x = 0;
-                           for (int i = 0; i < numMenus; ++i) {
-                               Menu menu = menus[i];
-                               menu.x = x;
-                               float width = menus[i].computeRequiredWidth();
-                               if (width < maxWidth) {
-                                   width = maxWidth + delta;
-                               } else {
-                                   width += delta;
-                               }
-                               menu.mWidth = (int)width;
-                               menu.titleWidth = StringTexture.computeTextWidthForConfig(menu.title, menu.config);  //(int)menus[i].title.computeTextWidth();
-                               x += width;
-                           }
-                           break;
-                       } else {
-                           ++menusProcessed;
-                           previousMaxWidth = maxWidth;
-                           occupiedWidth += maxWidth;
-                       }
-                   }
+
+                while (foundANewMaxWidth && menusProcessed < numMenus) {
+                    foundANewMaxWidth = false;
+                    int maxWidth = 0;
+                    for (int i = 0; i < numMenus; ++i) {
+                        int width = menus[i].computeRequiredWidth();
+                        if (width > maxWidth && width < previousMaxWidth) {
+                            foundANewMaxWidth = true;
+                            maxWidth = width;
+                        }
+                    }
+                    // can all the menus have this width
+                    int cumulativeWidth = maxWidth * (numMenus - menusProcessed) + occupiedWidth;
+                    if (cumulativeWidth < viewWidth || !foundANewMaxWidth || menusProcessed == numMenus - 1) {
+                        float delta = (viewWidth - cumulativeWidth) / numMenus;
+                        if (delta < 0) {
+                            delta = 0;
+                        }
+                        int x = 0;
+                        for (int i = 0; i < numMenus; ++i) {
+                            Menu menu = menus[i];
+                            menu.x = x;
+                            float width = menus[i].computeRequiredWidth();
+                            if (width < maxWidth) {
+                                width = maxWidth + delta;
+                            } else {
+                                width += delta;
+                            }
+                            menu.mWidth = (int) width;
+                            menu.titleWidth = StringTexture.computeTextWidthForConfig(menu.title, menu.config); // (int)menus[i].title.computeTextWidth();
+                            x += width;
+                        }
+                        break;
+                    } else {
+                        ++menusProcessed;
+                        previousMaxWidth = maxWidth;
+                        occupiedWidth += maxWidth;
+                    }
+                }
             }
         }
     }
@@ -405,7 +414,7 @@ public final class MenuBar extends Layer implements PopupMenu.Listener {
         private int x;
         private int mWidth;
         private static final float ICON_WIDTH = 45.0f;
-        
+
         public static final class Builder {
             private final String title;
             private StringTexture.Config config;
@@ -463,7 +472,7 @@ public final class MenuBar extends Layer implements PopupMenu.Listener {
 
         private Menu(Builder builder) {
             config = builder.config;
-            title = builder.title;  //new StringTexture(builder.title, config);
+            title = builder.title; // new StringTexture(builder.title, config);
             icon = builder.icon;
             onSelect = builder.onSelect;
             onDeselect = builder.onDeselect;
@@ -478,7 +487,7 @@ public final class MenuBar extends Layer implements PopupMenu.Listener {
                 width += (ICON_WIDTH); // * Gallery.PIXEL_DENSITY);
             }
             if (title != null) {
-                width += StringTexture.computeTextWidthForConfig(title, config);//title.computeTextWidth();
+                width += StringTexture.computeTextWidthForConfig(title, config);// title.computeTextWidth();
             }
             // pad it
             width += 20;
@@ -486,7 +495,7 @@ public final class MenuBar extends Layer implements PopupMenu.Listener {
                 width = HEIGHT;
             return width;
         }
-        
+
     }
 
     public void onSelectionChanged(PopupMenu menu, int selectedIndex) {
index 423b211..8829a68 100644 (file)
@@ -23,15 +23,19 @@ import java.util.ArrayList;
 
 public class MonitoredActivity extends Activity {
 
-    private final ArrayList<LifeCycleListener> mListeners =
-            new ArrayList<LifeCycleListener>();
+    private final ArrayList<LifeCycleListener> mListeners = new ArrayList<LifeCycleListener>();
 
     public static interface LifeCycleListener {
         public void onActivityCreated(MonitoredActivity activity);
+
         public void onActivityDestroyed(MonitoredActivity activity);
+
         public void onActivityPaused(MonitoredActivity activity);
+
         public void onActivityResumed(MonitoredActivity activity);
+
         public void onActivityStarted(MonitoredActivity activity);
+
         public void onActivityStopped(MonitoredActivity activity);
     }
 
@@ -56,7 +60,8 @@ public class MonitoredActivity extends Activity {
     }
 
     public void addLifeCycleListener(LifeCycleListener listener) {
-        if (mListeners.contains(listener)) return;
+        if (mListeners.contains(listener))
+            return;
         mListeners.add(listener);
     }
 
@@ -96,4 +101,3 @@ public class MonitoredActivity extends Activity {
         }
     }
 }
-
index b4d4cd9..f794fdd 100644 (file)
@@ -16,7 +16,6 @@ package com.cooliris.media;
  * limitations under the License.
  */
 
-
 import android.app.Activity;
 import android.content.Intent;
 import android.content.pm.ActivityInfo;
@@ -27,7 +26,7 @@ import android.view.View;
 /**
  * This activity plays a video from a specified URI.
  */
-public class MovieView extends Activity  {
+public class MovieView extends Activity {
     @SuppressWarnings("unused")
     private static final String TAG = "MovieView";
 
@@ -49,15 +48,12 @@ public class MovieView extends Activity  {
             }
         };
         if (intent.hasExtra(MediaStore.EXTRA_SCREEN_ORIENTATION)) {
-            int orientation = intent.getIntExtra(
-                    MediaStore.EXTRA_SCREEN_ORIENTATION,
-                    ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
+            int orientation = intent.getIntExtra(MediaStore.EXTRA_SCREEN_ORIENTATION, ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
             if (orientation != getRequestedOrientation()) {
                 setRequestedOrientation(orientation);
             }
         }
-        mFinishOnCompletion = intent.getBooleanExtra(
-                MediaStore.EXTRA_FINISH_ON_COMPLETION, true);
+        mFinishOnCompletion = intent.getBooleanExtra(MediaStore.EXTRA_FINISH_ON_COMPLETION, true);
     }
 
     @Override
@@ -72,4 +68,3 @@ public class MovieView extends Activity  {
         super.onResume();
     }
 }
-
index 3f9161d..e729b4c 100644 (file)
@@ -16,7 +16,6 @@ package com.cooliris.media;
  * limitations under the License.
  */
 
-
 import android.app.AlertDialog;
 import android.content.ContentResolver;
 import android.content.ContentValues;
@@ -36,8 +35,7 @@ import android.view.View;
 import android.widget.MediaController;
 import android.widget.VideoView;
 
-public class MovieViewControl implements MediaPlayer.OnErrorListener,
-        MediaPlayer.OnCompletionListener {
+public class MovieViewControl implements MediaPlayer.OnErrorListener, MediaPlayer.OnCompletionListener {
 
     @SuppressWarnings("unused")
     private static final String TAG = "MovieViewControl";
@@ -48,8 +46,7 @@ public class MovieViewControl implements MediaPlayer.OnErrorListener,
 
     // Copied from MediaPlaybackService in the Music Player app. Should be
     // public, but isn't.
-    private static final String SERVICECMD =
-            "com.android.music.musicservicecommand";
+    private static final String SERVICECMD = "com.android.music.musicservicecommand";
     private static final String CMDNAME = "command";
     private static final String CMDPAUSE = "pause";
 
@@ -73,20 +70,17 @@ public class MovieViewControl implements MediaPlayer.OnErrorListener,
             }
         }
     };
-    
-    public static String formatDuration(final Context context,
-            int durationMs) {
+
+    public static String formatDuration(final Context context, int durationMs) {
         int duration = durationMs / 1000;
         int h = duration / 3600;
         int m = (duration - h * 3600) / 60;
         int s = duration - (h * 3600 + m * 60);
         String durationValue;
         if (h == 0) {
-            durationValue = String.format(
-                    context.getString(R.string.details_ms), m, s);
+            durationValue = String.format(context.getString(R.string.details_ms), m, s);
         } else {
-            durationValue = String.format(
-                    context.getString(R.string.details_hms), h, m, s);
+            durationValue = String.format(context.getString(R.string.details_hms), h, m, s);
         }
         return durationValue;
     }
@@ -101,8 +95,7 @@ public class MovieViewControl implements MediaPlayer.OnErrorListener,
         // For streams that we expect to be slow to start up, show a
         // progress spinner until playback starts.
         String scheme = mUri.getScheme();
-        if ("http".equalsIgnoreCase(scheme)
-                || "rtsp".equalsIgnoreCase(scheme)) {
+        if ("http".equalsIgnoreCase(scheme) || "rtsp".equalsIgnoreCase(scheme)) {
             mHandler.postDelayed(mPlayingChecker, 250);
         } else {
             mProgressView.setVisibility(View.GONE);
@@ -124,24 +117,25 @@ public class MovieViewControl implements MediaPlayer.OnErrorListener,
         if (bookmark != null) {
             AlertDialog.Builder builder = new AlertDialog.Builder(context);
             builder.setTitle(R.string.resume_playing_title);
-            builder.setMessage(String.format(
-                    context.getString(R.string.resume_playing_message),
-                    formatDuration(context, bookmark)));
+            builder
+                    .setMessage(String
+                            .format(context.getString(R.string.resume_playing_message), formatDuration(context, bookmark)));
             builder.setOnCancelListener(new OnCancelListener() {
                 public void onCancel(DialogInterface dialog) {
                     onCompletion();
-                }});
-            builder.setPositiveButton(R.string.resume_playing_resume,
-                    new OnClickListener() {
+                }
+            });
+            builder.setPositiveButton(R.string.resume_playing_resume, new OnClickListener() {
                 public void onClick(DialogInterface dialog, int which) {
                     mVideoView.seekTo(bookmark);
                     mVideoView.start();
-                }});
-            builder.setNegativeButton(R.string.resume_playing_restart,
-                    new OnClickListener() {
+                }
+            });
+            builder.setNegativeButton(R.string.resume_playing_restart, new OnClickListener() {
                 public void onClick(DialogInterface dialog, int which) {
                     mVideoView.start();
-                }});
+                }
+            });
             builder.show();
         } else {
             mVideoView.start();
@@ -151,8 +145,7 @@ public class MovieViewControl implements MediaPlayer.OnErrorListener,
     private static boolean uriSupportsBookmarks(Uri uri) {
         String scheme = uri.getScheme();
         String authority = uri.getAuthority();
-        return ("content".equalsIgnoreCase(scheme)
-                && MediaStore.AUTHORITY.equalsIgnoreCase(authority));
+        return ("content".equalsIgnoreCase(scheme) && MediaStore.AUTHORITY.equalsIgnoreCase(authority));
     }
 
     private Integer getBookmark() {
@@ -160,21 +153,16 @@ public class MovieViewControl implements MediaPlayer.OnErrorListener,
             return null;
         }
 
-        String[] projection = new String[] {
-                Video.VideoColumns.DURATION,
-                Video.VideoColumns.BOOKMARK};
+        String[] projection = new String[] { Video.VideoColumns.DURATION, Video.VideoColumns.BOOKMARK };
 
         try {
-            Cursor cursor = mContentResolver.query(
-                    mUri, projection, null, null, null);
+            Cursor cursor = mContentResolver.query(mUri, projection, null, null, null);
             if (cursor != null) {
                 try {
                     if (cursor.moveToFirst()) {
                         int duration = getCursorInteger(cursor, 0);
                         int bookmark = getCursorInteger(cursor, 1);
-                        if ((bookmark < TWO_MINUTES)
-                                || (duration < FIVE_MINUTES)
-                                || (bookmark > (duration - ONE_MINUTE))) {
+                        if ((bookmark < TWO_MINUTES) || (duration < FIVE_MINUTES) || (bookmark > (duration - ONE_MINUTE))) {
                             return null;
                         }
                         return Integer.valueOf(bookmark);
@@ -253,4 +241,3 @@ public class MovieViewControl implements MediaPlayer.OnErrorListener,
     public void onCompletion() {
     }
 }
-
index 5a1e7c8..6564354 100644 (file)
@@ -26,7 +26,7 @@ public final class PathBarLayer extends Layer {
         mComponents.add(new Component(icon, label, action, 0));
         recomputeComponents();
     }
-    
+
     public void setAnimatedIcons(final int[] icons) {
         final int numComponents = mComponents.size();
         for (int i = 0; i < numComponents; ++i) {
@@ -50,7 +50,7 @@ public final class PathBarLayer extends Layer {
             pushLabel(component.icon, label, component.action);
         }
     }
-    
+
     public String getCurrentLabel() {
         final ArrayList<Component> components = mComponents;
         int lastIndex = components.size() - 1;
@@ -189,10 +189,10 @@ public final class PathBarLayer extends Layer {
             float xOffset = 5 * Gallery.PIXEL_DENSITY;
             // Draw the label.
             final int[] icons = component.animatedIcons;
-            
+
             // Cycles animated icons.
-            final int iconId = (icons != null && icons.length > 0) ? icons[(int) (component.timeElapsed * 20.0f)
-                    % icons.length] : component.icon;
+            final int iconId = (icons != null && icons.length > 0) ? icons[(int) (component.timeElapsed * 20.0f) % icons.length]
+                    : component.icon;
             final Texture icon = view.getResource(iconId);
             if (icon != null) {
                 view.loadTexture(icon);
index 82eb238..321d6cd 100644 (file)
@@ -30,8 +30,7 @@ import java.util.ArrayList;
 
 public class PhotoAppWidgetBind extends Activity {
     private static final String TAG = "PhotoAppWidgetBind";
-    private static final String EXTRA_APPWIDGET_BITMAPS =
-            "com.android.camera.appwidgetbitmaps";
+    private static final String EXTRA_APPWIDGET_BITMAPS = "com.android.camera.appwidgetbitmaps";
 
     @Override
     protected void onCreate(Bundle icicle) {
@@ -47,13 +46,10 @@ public class PhotoAppWidgetBind extends Activity {
         final Intent intent = getIntent();
         final Bundle extras = intent.getExtras();
 
-        final int[] appWidgetIds =
-                extras.getIntArray(AppWidgetManager.EXTRA_APPWIDGET_IDS);
-        final ArrayList<Bitmap> bitmaps =
-                extras.getParcelableArrayList(EXTRA_APPWIDGET_BITMAPS);
+        final int[] appWidgetIds = extras.getIntArray(AppWidgetManager.EXTRA_APPWIDGET_IDS);
+        final ArrayList<Bitmap> bitmaps = extras.getParcelableArrayList(EXTRA_APPWIDGET_BITMAPS);
 
-        if (appWidgetIds == null || bitmaps == null
-                || appWidgetIds.length != bitmaps.size()) {
+        if (appWidgetIds == null || bitmaps == null || appWidgetIds.length != bitmaps.size()) {
             Log.e(TAG, "Problem parsing photo widget bind request");
             return;
         }
@@ -66,12 +62,9 @@ public class PhotoAppWidgetBind extends Activity {
             helper.setPhoto(appWidgetId, bitmaps.get(i));
 
             // Push newly updated widget to surface
-            RemoteViews views =
-                    PhotoAppWidgetProvider.buildUpdate(this, appWidgetId,
-                    helper);
+            RemoteViews views = PhotoAppWidgetProvider.buildUpdate(this, appWidgetId, helper);
             appWidgetManager.updateAppWidget(new int[] { appWidgetId }, views);
         }
         helper.close();
     }
 }
-
index cc0c1c3..7cbdf79 100644 (file)
@@ -40,8 +40,7 @@ public class PhotoAppWidgetConfigure extends Activity {
         // Someone is requesting that we configure the given mAppWidgetId, which
         // means we prompt the user to pick and crop a photo.
 
-        mAppWidgetId = getIntent().getIntExtra(
-                AppWidgetManager.EXTRA_APPWIDGET_ID, -1);
+        mAppWidgetId = getIntent().getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1);
         if (mAppWidgetId == -1) {
             setResult(Activity.RESULT_CANCELED);
             finish();
@@ -63,8 +62,7 @@ public class PhotoAppWidgetConfigure extends Activity {
     }
 
     @Override
-    protected void onActivityResult(int requestCode, int resultCode,
-                                    Intent data) {
+    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
         if (resultCode == RESULT_OK && mAppWidgetId != -1) {
             // Store the cropped photo in our database
             Bitmap bitmap = (Bitmap) data.getParcelableExtra("data");
@@ -74,12 +72,9 @@ public class PhotoAppWidgetConfigure extends Activity {
                 resultCode = Activity.RESULT_OK;
 
                 // Push newly updated widget to surface
-                RemoteViews views = PhotoAppWidgetProvider.buildUpdate(this,
-                        mAppWidgetId, helper);
-                AppWidgetManager appWidgetManager =
-                        AppWidgetManager.getInstance(this);
-                appWidgetManager.updateAppWidget(new int[] {mAppWidgetId},
-                                                 views);
+                RemoteViews views = PhotoAppWidgetProvider.buildUpdate(this, mAppWidgetId, helper);
+                AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(this);
+                appWidgetManager.updateAppWidget(new int[] { mAppWidgetId }, views);
             }
             helper.close();
         } else {
@@ -94,4 +89,3 @@ public class PhotoAppWidgetConfigure extends Activity {
     }
 
 }
-
index 4acd6b8..5bc70f3 100644 (file)
@@ -40,16 +40,14 @@ public class PhotoAppWidgetProvider extends AppWidgetProvider {
     private static final boolean LOGD = true;
 
     @Override
-    public void onUpdate(Context context, AppWidgetManager appWidgetManager,
-                         int[] appWidgetIds) {
+    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
         // Update each requested appWidgetId with its unique photo
         PhotoDatabaseHelper helper = new PhotoDatabaseHelper(context);
         for (int appWidgetId : appWidgetIds) {
             int[] specificAppWidget = new int[] { appWidgetId };
             RemoteViews views = buildUpdate(context, appWidgetId, helper);
             if (LOGD) {
-                Log.d(TAG, "sending out views=" + views
-                        + " for id=" + appWidgetId);
+                Log.d(TAG, "sending out views=" + views + " for id=" + appWidgetId);
             }
             appWidgetManager.updateAppWidget(specificAppWidget, views);
         }
@@ -69,13 +67,11 @@ public class PhotoAppWidgetProvider extends AppWidgetProvider {
     /**
      * Load photo for given widget and build {@link RemoteViews} for it.
      */
-    static RemoteViews buildUpdate(Context context, int appWidgetId,
-                                   PhotoDatabaseHelper helper) {
+    static RemoteViews buildUpdate(Context context, int appWidgetId, PhotoDatabaseHelper helper) {
         RemoteViews views = null;
         Bitmap bitmap = helper.getPhoto(appWidgetId);
         if (bitmap != null) {
-            views = new RemoteViews(context.getPackageName(),
-                                    R.layout.photo_frame);
+            views = new RemoteViews(context.getPackageName(), R.layout.photo_frame);
             views.setImageViewBitmap(R.id.photo, bitmap);
         }
         return views;
@@ -96,15 +92,12 @@ public class PhotoAppWidgetProvider extends AppWidgetProvider {
 
         @Override
         public void onCreate(SQLiteDatabase db) {
-            db.execSQL("CREATE TABLE " + TABLE_PHOTOS + " (" +
-                    FIELD_APPWIDGET_ID + " INTEGER PRIMARY KEY," +
-                    FIELD_PHOTO_BLOB + " BLOB" +
-                    ");");
+            db.execSQL("CREATE TABLE " + TABLE_PHOTOS + " (" + FIELD_APPWIDGET_ID + " INTEGER PRIMARY KEY," + FIELD_PHOTO_BLOB
+                    + " BLOB" + ");");
         }
 
         @Override
-        public void onUpgrade(SQLiteDatabase db, int oldVersion,
-                              int newVersion) {
+        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
             int version = oldVersion;
 
             if (version != DATABASE_VERSION) {
@@ -131,12 +124,10 @@ public class PhotoAppWidgetProvider extends AppWidgetProvider {
 
                 ContentValues values = new ContentValues();
                 values.put(PhotoDatabaseHelper.FIELD_APPWIDGET_ID, appWidgetId);
-                values.put(PhotoDatabaseHelper.FIELD_PHOTO_BLOB,
-                           out.toByteArray());
+                values.put(PhotoDatabaseHelper.FIELD_PHOTO_BLOB, out.toByteArray());
 
                 SQLiteDatabase db = getWritableDatabase();
-                db.insertOrThrow(PhotoDatabaseHelper.TABLE_PHOTOS, null,
-                                 values);
+                db.insertOrThrow(PhotoDatabaseHelper.TABLE_PHOTOS, null, values);
 
                 success = true;
             } catch (SQLiteException e) {
@@ -150,9 +141,7 @@ public class PhotoAppWidgetProvider extends AppWidgetProvider {
             return success;
         }
 
-        static final String[] PHOTOS_PROJECTION = {
-            FIELD_PHOTO_BLOB,
-        };
+        static final String[] PHOTOS_PROJECTION = { FIELD_PHOTO_BLOB, };
 
         static final int INDEX_PHOTO_BLOB = 0;
 
@@ -164,10 +153,8 @@ public class PhotoAppWidgetProvider extends AppWidgetProvider {
             Bitmap bitmap = null;
             try {
                 SQLiteDatabase db = getReadableDatabase();
-                String selection = String.format("%s=%d", FIELD_APPWIDGET_ID,
-                                                 appWidgetId);
-                c = db.query(TABLE_PHOTOS, PHOTOS_PROJECTION, selection, null,
-                        null, null, null, null);
+                String selection = String.format("%s=%d", FIELD_APPWIDGET_ID, appWidgetId);
+                c = db.query(TABLE_PHOTOS, PHOTOS_PROJECTION, selection, null, null, null, null, null);
 
                 if (c != null && LOGD) {
                     Log.d(TAG, "getPhoto query count=" + c.getCount());
@@ -176,8 +163,7 @@ public class PhotoAppWidgetProvider extends AppWidgetProvider {
                 if (c != null && c.moveToFirst()) {
                     byte[] data = c.getBlob(INDEX_PHOTO_BLOB);
                     if (data != null) {
-                        bitmap = BitmapFactory.decodeByteArray(data, 0,
-                                data.length);
+                        bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
                     }
                 }
             } catch (SQLiteException e) {
@@ -196,8 +182,7 @@ public class PhotoAppWidgetProvider extends AppWidgetProvider {
         public void deletePhoto(int appWidgetId) {
             try {
                 SQLiteDatabase db = getWritableDatabase();
-                String whereClause = String.format("%s=%d", FIELD_APPWIDGET_ID,
-                                                   appWidgetId);
+                String whereClause = String.format("%s=%d", FIELD_APPWIDGET_ID, appWidgetId);
                 db.delete(TABLE_PHOTOS, whereClause, null);
             } catch (SQLiteException e) {
                 Log.e(TAG, "Could not delete photo from database", e);
@@ -206,5 +191,3 @@ public class PhotoAppWidgetProvider extends AppWidgetProvider {
     }
 
 }
-
-
index ce61c67..250fd5b 100644 (file)
@@ -58,18 +58,17 @@ public class Photographs extends Activity {
         @Override
         public void handleMessage(Message msg) {
             switch (msg.what) {
-                case SHOW_PROGRESS: {
-                    CharSequence c = getText(R.string.wallpaper);
-                    mProgressDialog = ProgressDialog.show(Photographs.this,
-                            "", c, true, false);
-                    break;
-                }
-                case FINISH: {
-                    closeProgressDialog();
-                    setResult(RESULT_OK);
-                    finish();
-                    break;
-                }
+            case SHOW_PROGRESS: {
+                CharSequence c = getText(R.string.wallpaper);
+                mProgressDialog = ProgressDialog.show(Photographs.this, "", c, true, false);
+                break;
+            }
+            case FINISH: {
+                closeProgressDialog();
+                setResult(RESULT_OK);
+                finish();
+                break;
+            }
             }
         }
     };
@@ -80,8 +79,7 @@ public class Photographs extends Activity {
         private final Context mContext;
         private final File mFile;
 
-        public SetWallpaperThread(Bitmap bitmap, Handler handler,
-                                  Context context, File file) {
+        public SetWallpaperThread(Bitmap bitmap, Handler handler, Context context, File file) {
             mBitmap = bitmap;
             mHandler = handler;
             mContext = context;
@@ -138,8 +136,7 @@ public class Photographs extends Activity {
         Uri imageToUse = getIntent().getData();
         if (imageToUse != null) {
             Intent intent = new Intent();
-            intent.setClassName("com.cooliris.media",
-                                "com.cooliris.media.CropImage");
+            intent.setClassName("com.cooliris.media", "com.cooliris.media.CropImage");
             intent.setData(imageToUse);
             formatIntent(intent);
             startActivityForResult(intent, CROP_DONE);
@@ -162,11 +159,11 @@ public class Photographs extends Activity {
 
         int width = getWallpaperDesiredMinimumWidth();
         int height = getWallpaperDesiredMinimumHeight();
-        intent.putExtra("outputX",         width);
-        intent.putExtra("outputY",         height);
-        intent.putExtra("aspectX",         width);
-        intent.putExtra("aspectY",         height);
-        intent.putExtra("scale",           true);
+        intent.putExtra("outputX", width);
+        intent.putExtra("outputY", height);
+        intent.putExtra("aspectX", width);
+        intent.putExtra("aspectY", height);
+        intent.putExtra("scale", true);
         intent.putExtra("noFaceDetection", true);
         intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(mTempFile));
         intent.putExtra("outputFormat", Bitmap.CompressFormat.PNG.name());
@@ -176,22 +173,17 @@ public class Photographs extends Activity {
     }
 
     @Override
-    protected void onActivityResult(int requestCode, int resultCode,
-                                    Intent data) {
-        if ((requestCode == PHOTO_PICKED || requestCode == CROP_DONE)
-                && (resultCode == RESULT_OK) && (data != null)) {
+    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+        if ((requestCode == PHOTO_PICKED || requestCode == CROP_DONE) && (resultCode == RESULT_OK) && (data != null)) {
             try {
                 InputStream s = new FileInputStream(mTempFile);
                 try {
                     Bitmap bitmap = BitmapFactory.decodeStream(s);
                     if (bitmap == null) {
-                        Log.e(LOG_TAG, "Failed to set wallpaper. "
-                                       + "Couldn't get bitmap for path "
-                                       + mTempFile);
+                        Log.e(LOG_TAG, "Failed to set wallpaper. " + "Couldn't get bitmap for path " + mTempFile);
                     } else {
                         mHandler.sendEmptyMessage(SHOW_PROGRESS);
-                        new SetWallpaperThread(
-                                bitmap, mHandler, this, mTempFile).start();
+                        new SetWallpaperThread(bitmap, mHandler, this, mTempFile).start();
                     }
                     mDoLaunch = false;
                 } finally {
index 868a23e..4f5eed0 100644 (file)
@@ -34,9 +34,9 @@ public final class PicasaDataSource implements DataSource {
     public PicasaDataSource(final Context context) {
         mContext = context;
     }
-    
+
     public static final HashMap<String, Boolean> getAccountStatus(final Context context) {
-       final Account[] accounts = PicasaApi.getAccounts(context);
+        final Account[] accounts = PicasaApi.getAccounts(context);
         int numAccounts = accounts.length;
         HashMap<String, Boolean> accountsEnabled = new HashMap<String, Boolean>(numAccounts);
         for (int i = 0; i < numAccounts; ++i) {
@@ -44,7 +44,8 @@ public final class PicasaDataSource implements DataSource {
             boolean isEnabled = ContentResolver.getSyncAutomatically(account, PicasaContentProvider.AUTHORITY);
             String username = account.name.toLowerCase();
             if (username.contains("@gmail.") || username.contains("@googlemail.")) {
-                // Strip the domain from GMail accounts for canonicalization. TODO: is there an official way?
+                // Strip the domain from GMail accounts for canonicalization.
+                // TODO: is there an official way?
                 username = username.substring(0, username.indexOf('@'));
             }
             accountsEnabled.put(username, new Boolean(isEnabled));
@@ -53,14 +54,17 @@ public final class PicasaDataSource implements DataSource {
     }
 
     public void loadMediaSets(final MediaFeed feed) {
-        // We do this here and not in the constructor to speed application loading time since this method is called in a background thread
-       if (mProviderClient == null) {
+        // We do this here and not in the constructor to speed application
+        // loading time since this method is called in a background thread
+        if (mProviderClient == null) {
             mProviderClient = mContext.getContentResolver().acquireContentProviderClient(PicasaContentProvider.AUTHORITY);
         }
-        // Force permission dialog to be displayed if necessary. TODO: remove this after signed by Google.
+        // Force permission dialog to be displayed if necessary. TODO: remove
+        // this after signed by Google.
         PicasaApi.getAccounts(mContext);
 
-        // Ensure that users are up to date. TODO: also listen for accounts changed broadcast.
+        // Ensure that users are up to date. TODO: also listen for accounts
+        // changed broadcast.
         PicasaService.requestSync(mContext, PicasaService.TYPE_USERS_ALBUMS, 0);
         final Handler handler = ((Gallery) mContext).getHandler();
         final ContentObserver albumObserver = new ContentObserver(handler) {
@@ -109,7 +113,7 @@ public final class PicasaDataSource implements DataSource {
                 final ArrayList<MediaSet> picasaSets = new ArrayList<MediaSet>(numAlbums);
                 do {
                     albumSchema.cursorToObject(cursor, album);
-                    String userLowerCase = album.user.toLowerCase();
+                    String userLowerCase = album.syncAccount.toLowerCase();
                     final Boolean accountEnabledObj = accountsEnabled.get(userLowerCase);
                     final boolean accountEnabled = (accountEnabledObj == null) ? false : accountEnabledObj.booleanValue();
                     if (accountEnabled) {
index f51e7b9..de27492 100644 (file)
@@ -83,7 +83,8 @@ public final class PopupMenu extends Layer {
         mPopupTexture.setNeedsDraw();
         setPosition(clampedX, y);
 
-        // Fade in the menu if it is not already visible, otherwise snap to the new location.
+        // Fade in the menu if it is not already visible, otherwise snap to the
+        // new location.
         // if (!mShow) {
         mShow = true;
         setHidden(false);
@@ -297,7 +298,8 @@ public final class PopupMenu extends Layer {
             backing.eraseColor(0);
             mBackground.draw(canvas, mBackgroundRect, SRC_PAINT);
 
-            // Stamp the popup triangle over the appropriate region ignoring alpha.
+            // Stamp the popup triangle over the appropriate region ignoring
+            // alpha.
             Bitmap triangle = mTriangleBottom;
             canvas.drawBitmap(triangle, mTriangleX, height - triangle.getHeight() - 1, SRC_PAINT);
 
index dada58f..6bb29d5 100644 (file)
@@ -69,7 +69,8 @@ public final class RenderView extends GLSurfaceView implements GLSurfaceView.Ren
     @SuppressWarnings("unchecked")
     private final ReferenceQueue mUnreferencedTextureQueue = new ReferenceQueue();
 
-    // Frame time in milliseconds and delta since last frame in seconds. Uses SystemClock.getUptimeMillis().
+    // Frame time in milliseconds and delta since last frame in seconds. Uses
+    // SystemClock.getUptimeMillis().
     private long mFrameTime = 0;
     private float mFrameInterval = 0.0f;
     private float mAlpha;
@@ -170,8 +171,9 @@ public final class RenderView extends GLSurfaceView implements GLSurfaceView.Ren
 
     private void clearTextureArray(SparseArray<ResourceTexture> array) {
         /*
-         * final int size = array.size(); for (int i = 0; i < size; ++i) { ResourceTexture texture = array.get(array.keyAt(i)); if
-         * (texture != null) { texture.clear(); } }
+         * final int size = array.size(); for (int i = 0; i < size; ++i) {
+         * ResourceTexture texture = array.get(array.keyAt(i)); if (texture !=
+         * null) { texture.clear(); } }
          */
         array.clear();
     }
@@ -215,7 +217,8 @@ public final class RenderView extends GLSurfaceView implements GLSurfaceView.Ren
                 int height = bitmap.getHeight();
                 texture.mWidth = width;
                 texture.mHeight = height;
-                // Create a padded bitmap if the natural size is not a power of 2.
+                // Create a padded bitmap if the natural size is not a power of
+                // 2.
                 if (!Shared.isPowerOf2(width) || !Shared.isPowerOf2(height)) {
                     int paddedWidth = Shared.nextPowerOf2(width);
                     int paddedHeight = Shared.nextPowerOf2(height);
@@ -229,7 +232,8 @@ public final class RenderView extends GLSurfaceView implements GLSurfaceView.Ren
                     canvas.drawBitmap(bitmap, 0, 0, null);
                     bitmap.recycle();
                     bitmap = padded;
-                    // Store normalized width and height for use in texture coordinates.
+                    // Store normalized width and height for use in texture
+                    // coordinates.
                     texture.mNormalizedWidth = (float) width / (float) paddedWidth;
                     texture.mNormalizedHeight = (float) height / (float) paddedHeight;
                 } else {
@@ -318,7 +322,9 @@ public final class RenderView extends GLSurfaceView implements GLSurfaceView.Ren
         texture.mState = Texture.STATE_LOADING;
 
         // Push the texture onto the load input queue.
-        Deque<Texture> inputQueue = (texture.isUncachedVideo()) ? sLoadInputQueueVideo : (texture.isCached()) ? sLoadInputQueueCached : sLoadInputQueue;;
+        Deque<Texture> inputQueue = (texture.isUncachedVideo()) ? sLoadInputQueueVideo
+                : (texture.isCached()) ? sLoadInputQueueCached : sLoadInputQueue;
+        ;
         synchronized (inputQueue) {
             if (highPriority) {
                 inputQueue.addFirst(texture);
@@ -374,7 +380,8 @@ public final class RenderView extends GLSurfaceView implements GLSurfaceView.Ren
         gl.glTexEnvf(GL11.GL_TEXTURE_ENV, GL11.GL_COMBINE_RGB, GL11.GL_INTERPOLATE);
         gl.glTexEnvf(GL11.GL_TEXTURE_ENV, GL11.GL_COMBINE_ALPHA, GL11.GL_INTERPOLATE);
 
-        // Specify the interpolation factor via the alpha component of GL_TEXTURE_ENV_COLOR.
+        // Specify the interpolation factor via the alpha component of
+        // GL_TEXTURE_ENV_COLOR.
         final float[] color = { 1f, 1f, 1f, ratio };
         gl.glTexEnvfv(GL11.GL_TEXTURE_ENV, GL11.GL_TEXTURE_ENV_COLOR, color, 0);
 
@@ -414,7 +421,8 @@ public final class RenderView extends GLSurfaceView implements GLSurfaceView.Ren
                 gl.glTexEnvf(GL11.GL_TEXTURE_ENV, GL11.GL_COMBINE_RGB, GL11.GL_INTERPOLATE);
                 gl.glTexEnvf(GL11.GL_TEXTURE_ENV, GL11.GL_COMBINE_ALPHA, GL11.GL_INTERPOLATE);
 
-                // Specify the interpolation factor via the alpha component of GL_TEXTURE_ENV_COLOR.
+                // Specify the interpolation factor via the alpha component of
+                // GL_TEXTURE_ENV_COLOR.
                 final float[] color = { 1f, 1f, 1f, ratio };
                 gl.glTexEnvfv(GL11.GL_TEXTURE_ENV, GL11.GL_TEXTURE_ENV_COLOR, color, 0);
 
@@ -498,13 +506,14 @@ public final class RenderView extends GLSurfaceView implements GLSurfaceView.Ren
             gl.glTexParameterf(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR);
             GLUtils.texImage2D(GL11.GL_TEXTURE_2D, 0, bitmap, 0);
             glError = gl.glGetError();
-            
+
             bitmap.recycle();
             if (glError == GL11.GL_OUT_OF_MEMORY) {
                 handleLowMemory();
             }
             if (glError != GL11.GL_NO_ERROR) {
-                // There was an error, we need to retry this texture at some later time
+                // There was an error, we need to retry this texture at some
+                // later time
                 Log.i(TAG, "Texture creation fail, glError " + glError);
                 texture.mId = 0;
                 texture.mBitmap = null;
@@ -597,7 +606,7 @@ public final class RenderView extends GLSurfaceView implements GLSurfaceView.Ren
             if (isDirty) {
                 requestRender();
             }
-        
+
             // Clear the depth buffer.
             gl.glClear(GL11.GL_DEPTH_BUFFER_BIT);
             gl.glEnable(GL11.GL_SCISSOR_TEST);
@@ -612,7 +621,7 @@ public final class RenderView extends GLSurfaceView implements GLSurfaceView.Ren
                     layer.renderOpaque(this, gl);
                 }
             }
-            
+
             // Run the blended pass.
             gl.glEnable(GL11.GL_BLEND);
             final ArrayList<Layer> blendedList = lists.blendedList;
@@ -732,7 +741,10 @@ public final class RenderView extends GLSurfaceView implements GLSurfaceView.Ren
         }
     }
 
-    /** Called when the OpenGL surface is recreated without destroying the context. */
+    /**
+     * Called when the OpenGL surface is recreated without destroying the
+     * context.
+     */
     public void onSurfaceChanged(GL10 gl1, int width, int height) {
         GL11 gl = (GL11) gl1;
         mFirstDraw = false;
@@ -765,7 +777,9 @@ public final class RenderView extends GLSurfaceView implements GLSurfaceView.Ren
         gl.glMatrixMode(GL11.GL_MODELVIEW);
     }
 
-    /** Called when the context is created, possibly after automatic destruction. */
+    /**
+     * Called when the context is created, possibly after automatic destruction.
+     */
     public void onSurfaceCreated(GL10 gl1, EGLConfig config) {
         // Clear the resource texture cache.
         clearCache();
@@ -793,9 +807,12 @@ public final class RenderView extends GLSurfaceView implements GLSurfaceView.Ren
         gl.glEnable(GL11.GL_TEXTURE_2D);
         gl.glTexEnvf(GL11.GL_TEXTURE_ENV, GL11.GL_TEXTURE_ENV_MODE, GL11.GL_REPLACE);
 
-        // Set up state for multitexture operations. Since multitexture is currently used
-        // only for layered crossfades the needed state can be factored out into one-time
-        // initialization. This section may need to be folded into drawMixed2D() if multitexture
+        // Set up state for multitexture operations. Since multitexture is
+        // currently used
+        // only for layered crossfades the needed state can be factored out into
+        // one-time
+        // initialization. This section may need to be folded into drawMixed2D()
+        // if multitexture
         // is used for other effects.
 
         // Enable Vertex Arrays
@@ -865,7 +882,7 @@ public final class RenderView extends GLSurfaceView implements GLSurfaceView.Ren
         }
         // Wait for the render thread to process this event.
         if (mTouchEventQueue.size() > 8 && event.getAction() == MotionEvent.ACTION_MOVE)
-               return true;
+            return true;
         synchronized (mTouchEventQueue) {
             MotionEvent eventCopy = MotionEvent.obtain(event);
             mTouchEventQueue.addLast(eventCopy);
@@ -883,9 +900,12 @@ public final class RenderView extends GLSurfaceView implements GLSurfaceView.Ren
         /*
          * if (mGL == null) { return; }
          * 
-         * // Wait for the render thread to process this event. try { synchronized (this) { mCurrentFocusEventGain = gainFocus;
-         * mCurrentFocusEventDirection = direction; mCurrentEventType = EVENT_FOCUS; do { wait(); } while (mCurrentEventType !=
-         * EVENT_NONE); } } catch (InterruptedException e) { // Stop waiting for the render thread if interrupted. }
+         * // Wait for the render thread to process this event. try {
+         * synchronized (this) { mCurrentFocusEventGain = gainFocus;
+         * mCurrentFocusEventDirection = direction; mCurrentEventType =
+         * EVENT_FOCUS; do { wait(); } while (mCurrentEventType != EVENT_NONE);
+         * } } catch (InterruptedException e) { // Stop waiting for the render
+         * thread if interrupted. }
          */
         requestRender();
     }
@@ -948,7 +968,8 @@ public final class RenderView extends GLSurfaceView implements GLSurfaceView.Ren
 
         public void run() {
             Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
-            Deque<Texture> inputQueue = (sVideoTextureLoadThread == this) ? sLoadInputQueueVideo : ((sCachedTextureLoadThread == this) ? sLoadInputQueueCached : sLoadInputQueue);
+            Deque<Texture> inputQueue = (sVideoTextureLoadThread == this) ? sLoadInputQueueVideo
+                    : ((sCachedTextureLoadThread == this) ? sLoadInputQueueCached : sLoadInputQueue);
             Deque<Texture> outputQueue = sLoadOutputQueue;
             try {
                 for (;;) {
index aa80583..719a828 100644 (file)
@@ -12,17 +12,32 @@ import java.util.Locale;
 
 import android.content.Context;
 import android.location.Address;
+import android.location.Criteria;
 import android.location.Geocoder;
+import android.location.Location;
+import android.location.LocationManager;
 import android.os.Process;
 
 public final class ReverseGeocoder extends Thread {
     private static final int MAX_COUNTRY_NAME_LENGTH = 8;
-    // If two points are within 50 miles of each other, use "Around Palo Alto, CA" or "Around Mountain View, CA".
-    // instead of directly jumping to the next level and saying "California, US".
+    // If two points are within 20 miles of each other, use
+    // "Around Palo Alto, CA" or "Around Mountain View, CA".
+    // instead of directly jumping to the next level and saying
+    // "California, US".
     private static final int MAX_LOCALITY_MILE_RANGE = 20;
     private static final Deque<MediaSet> sQueue = new Deque<MediaSet>();
     private static final DiskCache sGeoCache = new DiskCache("geocoder-cache");
     private static final String TAG = "ReverseGeocoder";
+    private static Criteria LOCATION_CRITERIA = new Criteria();
+    private static Address sCurrentAddress; // last known address
+    
+    static {
+        LOCATION_CRITERIA.setAccuracy(Criteria.ACCURACY_COARSE);
+        LOCATION_CRITERIA.setPowerRequirement(Criteria.NO_REQUIREMENT);
+        LOCATION_CRITERIA.setBearingRequired(false);
+        LOCATION_CRITERIA.setSpeedRequired(false);
+        LOCATION_CRITERIA.setAltitudeRequired(false);
+    }
 
     private Geocoder mGeocoder;
     private final Context mContext;
@@ -36,7 +51,7 @@ public final class ReverseGeocoder extends Thread {
     public void enqueue(MediaSet set) {
         Deque<MediaSet> inQueue = sQueue;
         synchronized (inQueue) {
-            inQueue.addLast(set);
+            inQueue.addFirst(set);
             inQueue.notify();
         }
     }
@@ -87,36 +102,88 @@ public final class ReverseGeocoder extends Thread {
     protected String computeMostGranularCommonLocation(final MediaSet set) {
         // The overall min and max latitudes and longitudes of the set.
         double setMinLatitude = set.mMinLatLatitude;
-        double setMinLongitude = set.mMinLonLongitude;
+        double setMinLongitude = set.mMinLatLongitude;
         double setMaxLatitude = set.mMaxLatLatitude;
-        double setMaxLongitude = set.mMaxLonLongitude;
+        double setMaxLongitude = set.mMaxLatLongitude;
+        if (Math.abs(set.mMaxLatLatitude - set.mMinLatLatitude) < Math.abs(set.mMaxLonLongitude - set.mMinLonLongitude)) {
+            setMinLatitude = set.mMinLonLatitude;
+            setMinLongitude = set.mMinLonLongitude;
+            setMaxLatitude = set.mMaxLonLatitude;
+            setMaxLongitude = set.mMaxLonLongitude;
+        }
         Address addr1 = lookupAddress(setMinLatitude, setMinLongitude);
         Address addr2 = lookupAddress(setMaxLatitude, setMaxLongitude);
+        if (addr1 == null)
+            addr1 = addr2;
+        if (addr2 == null)
+            addr2 = addr1;
         if (addr1 == null || addr2 == null) {
             return null;
         }
 
-        // Look at the first line of the address.
-        String closestCommonLocation = valueIfEqual(addr1.getAddressLine(0), addr2.getAddressLine(0));
-        if (closestCommonLocation != null && !("null".equals(closestCommonLocation))) {
-            return closestCommonLocation;
+        // Get current location, we decide the granularity of the string based
+        // on this.
+        LocationManager locationManager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
+        Location location = null;
+        List<String> providers = locationManager.getAllProviders();
+        for (int i = 0; i < providers.size(); ++i) {
+            String provider = providers.get(i);
+            location = (provider != null) ? locationManager.getLastKnownLocation(provider) : null;
+            if (location != null)
+                break;
         }
-
-        // Compare thoroughfare (street address) next.
-        closestCommonLocation = valueIfEqual(addr1.getThoroughfare(), addr2.getThoroughfare());
-        if (closestCommonLocation != null && !("null".equals(closestCommonLocation))) {
-            return closestCommonLocation;
+        String currentCity = "";
+        String currentAdminArea = "";
+        String currentCountry = Locale.getDefault().getCountry();
+        if (location != null) {
+            Address currentAddress = lookupAddress(location.getLatitude(), location.getLongitude());
+            if (currentAddress == null) {
+                currentAddress = sCurrentAddress;
+            } else {
+                sCurrentAddress = currentAddress;
+            }
+            if (currentAddress != null && currentAddress.getCountryCode() != null) {
+                currentCity = currentAddress.getLocality();
+                currentCountry = currentAddress.getCountryCode();
+                currentAdminArea = currentAddress.getAdminArea();
+            }
         }
 
-        // Feature names can sometimes be useful like "Golden Gate Bridge" but can also be
-        // degenerate for street address (like just the house number).
-        closestCommonLocation = valueIfEqual(addr1.getFeatureName(), addr2.getFeatureName());
-        if (closestCommonLocation != null && !("null".equals(closestCommonLocation))) {
-            try {
-                Integer.parseInt(closestCommonLocation);
-                closestCommonLocation = null;
-            } catch (final NumberFormatException nfe) {
-                // The feature name is not an integer, allow and continue.
+        String closestCommonLocation = null;
+
+        if (currentCity.equals(addr1.getLocality()) || currentCity.equals(addr2.getLocality())) {
+            String otherCity = currentCity;
+            if (currentCity.equals(addr1.getLocality())) {
+                otherCity = addr2.getLocality();
+                if ("null".equals(otherCity) || otherCity == null) {
+                    otherCity = addr2.getAdminArea();
+                    if (!currentCountry.equals(addr2.getCountryCode())) {
+                        otherCity += " " + addr2.getCountryCode();
+                    }
+                }
+                addr2 = addr1;
+            } else {
+                otherCity = addr1.getLocality();
+                if ("null".equals(otherCity) || otherCity == null) {
+                    otherCity = addr1.getAdminArea() + " " + addr1.getCountryCode();
+                    ;
+                    if (!currentCountry.equals(addr1.getCountryCode())) {
+                        otherCity += " " + addr1.getCountryCode();
+                    }
+                }
+                addr1 = addr2;
+            }
+            closestCommonLocation = valueIfEqual(addr1.getAddressLine(0), addr2.getAddressLine(0));
+            if (closestCommonLocation != null && !("null".equals(closestCommonLocation))) {
+                if (!currentCity.equals(otherCity)) {
+                    closestCommonLocation += " - " + otherCity;
+                }
+                return closestCommonLocation;
+            }
+
+            // Compare thoroughfare (street address) next.
+            closestCommonLocation = valueIfEqual(addr1.getThoroughfare(), addr2.getThoroughfare());
+            if (closestCommonLocation != null && !("null".equals(closestCommonLocation))) {
                 return closestCommonLocation;
             }
         }
@@ -125,34 +192,46 @@ public final class ReverseGeocoder extends Thread {
         closestCommonLocation = valueIfEqual(addr1.getLocality(), addr2.getLocality());
         if (closestCommonLocation != null && !("null".equals(closestCommonLocation))) {
             String adminArea = addr1.getAdminArea();
-            if (adminArea != null && adminArea.length() > 0) {
-                closestCommonLocation += ", " + adminArea;
+            String countryCode = addr1.getCountryCode();
+            if (adminArea != null && adminArea.length() > 0 && !adminArea.equals(currentAdminArea)) {
+                if (!countryCode.equals(currentCountry)) {
+                    closestCommonLocation += ", " + adminArea + " " + countryCode;
+                } else {
+                    closestCommonLocation += ", " + adminArea;
+                }
             }
             return closestCommonLocation;
         }
 
-        // Just choose one of the localities if within a 50 mile radius.
-        int distance = (int) LocationMediaFilter.toMile(LocationMediaFilter.distanceBetween(setMinLatitude, setMinLongitude,
-                setMaxLatitude, setMaxLongitude));
-        if (distance < MAX_LOCALITY_MILE_RANGE) {
-            // Try each of the points and just return the first one to have a valid address.
-            Address minLatAddress = lookupAddress(setMinLatitude, set.mMinLatLongitude);
-            closestCommonLocation = getLocalityAdminForAddress(minLatAddress, true);
-            if (closestCommonLocation != null) {
-                return closestCommonLocation;
+        // If the admin area is the same as the current location, we hide it and
+        // instead show the city name.
+        if (currentAdminArea.equals(addr1.getAdminArea()) || currentAdminArea.equals(addr2.getAdminArea())) {
+            String addr1Locality = addr2.getLocality();
+            String addr2Locality = addr2.getLocality();
+            if (addr1Locality == null || "null".equals(addr1Locality)) {
+                addr1Locality = addr2Locality;
             }
-            Address minLonAddress = lookupAddress(set.mMinLonLatitude, setMinLongitude);
-            closestCommonLocation = getLocalityAdminForAddress(minLonAddress, true);
-            if (closestCommonLocation != null) {
+            if (addr2Locality == null || "null".equals(addr2Locality)) {
+                addr2Locality = addr1Locality;
+            }
+            if (addr1Locality != null && !"null".equals(addr1Locality)) {
+                closestCommonLocation = addr1.getLocality() + " - " + addr2.getLocality();
                 return closestCommonLocation;
             }
-            Address maxLatAddress = lookupAddress(setMaxLatitude, set.mMaxLatLongitude);
-            closestCommonLocation = getLocalityAdminForAddress(maxLatAddress, true);
+        }
+
+        // Just choose one of the localities if within a MAX_LOCALITY_MILE_RANGE
+        // mile radius.
+        int distance = (int) LocationMediaFilter.toMile(LocationMediaFilter.distanceBetween(setMinLatitude, setMinLongitude,
+                setMaxLatitude, setMaxLongitude));
+        if (distance < MAX_LOCALITY_MILE_RANGE) {
+            // Try each of the points and just return the first one to have a
+            // valid address.
+            closestCommonLocation = getLocalityAdminForAddress(addr1, true);
             if (closestCommonLocation != null) {
                 return closestCommonLocation;
             }
-            Address maxLonAddress = lookupAddress(set.mMaxLonLatitude, setMaxLongitude);
-            closestCommonLocation = getLocalityAdminForAddress(maxLonAddress, true);
+            closestCommonLocation = getLocalityAdminForAddress(addr2, true);
             if (closestCommonLocation != null) {
                 return closestCommonLocation;
             }
@@ -162,8 +241,10 @@ public final class ReverseGeocoder extends Thread {
         closestCommonLocation = valueIfEqual(addr1.getAdminArea(), addr2.getAdminArea());
         if (closestCommonLocation != null && !("null".equals(closestCommonLocation))) {
             String countryCode = addr1.getCountryCode();
-            if (countryCode != null && countryCode.length() > 0) {
-                closestCommonLocation += ", " + countryCode;
+            if (!countryCode.equals(currentCountry)) {
+                if (countryCode != null && countryCode.length() > 0) {
+                    closestCommonLocation += " " + countryCode;
+                }
             }
             return closestCommonLocation;
         }
@@ -176,6 +257,12 @@ public final class ReverseGeocoder extends Thread {
         // There is no intersection, let's choose a nicer name.
         String addr1Country = addr1.getCountryName();
         String addr2Country = addr2.getCountryName();
+        if (addr1Country == null)
+            addr1Country = addr1.getCountryCode();
+        if (addr2Country == null)
+            addr2Country = addr2.getCountryCode();
+        if (addr1Country == null || addr2Country == null)
+            return null;
         if (addr1Country.length() > MAX_COUNTRY_NAME_LENGTH || addr2Country.length() > MAX_COUNTRY_NAME_LENGTH) {
             closestCommonLocation = addr1.getCountryCode() + " - " + addr2.getCountryCode();
         } else {
@@ -190,7 +277,8 @@ public final class ReverseGeocoder extends Thread {
         Address addr = lookupAddress(latitude, longitude);
 
         if (addr != null) {
-            // Look at the first line of the address, thorough fare and feature name in order and pick one.
+            // Look at the first line of the address, thorough fare and feature
+            // name in order and pick one.
             location = addr.getAddressLine(0);
             if (location != null && !("null".equals(location))) {
                 numDetails++;
@@ -257,8 +345,11 @@ public final class ReverseGeocoder extends Thread {
         String localityAdminStr = addr.getLocality();
         if (localityAdminStr != null && !("null".equals(localityAdminStr))) {
             if (approxLocation) {
-                // TODO: Uncomment these lines as soon as we may translations for R.string.around.
-                // localityAdminStr = mContext.getResources().getString(R.string.around) + " " + localityAdminStr;
+                // TODO: Uncomment these lines as soon as we may translations
+                // for R.string.around.
+                // localityAdminStr =
+                // mContext.getResources().getString(R.string.around) + " " +
+                // localityAdminStr;
             }
             String adminArea = addr.getAdminArea();
             if (adminArea != null && adminArea.length() > 0) {
@@ -275,36 +366,40 @@ public final class ReverseGeocoder extends Thread {
             byte[] cachedLocation = sGeoCache.get(locationKey, 0);
             Address address = null;
             if (cachedLocation == null || cachedLocation.length == 0) {
-                List<Address> addresses = mGeocoder.getFromLocation(latitude, longitude, 1);
-                if (!addresses.isEmpty()) {
-                    address = addresses.get(0);
-                    ByteArrayOutputStream bos = new ByteArrayOutputStream();
-                    DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(bos, 256));
-                    Locale locale = address.getLocale();
-                    Utils.writeUTF(dos, locale.getLanguage());
-                    Utils.writeUTF(dos, locale.getCountry());
-                    Utils.writeUTF(dos, locale.getVariant());
-
-                    Utils.writeUTF(dos, address.getThoroughfare());
-                    int numAddressLines = address.getMaxAddressLineIndex();
-                    dos.writeInt(numAddressLines);
-                    for (int i = 0; i < numAddressLines; ++i) {
-                        Utils.writeUTF(dos, address.getAddressLine(i));
+                try {
+                    List<Address> addresses = mGeocoder.getFromLocation(latitude, longitude, 1);
+                    if (!addresses.isEmpty()) {
+                        address = addresses.get(0);
+                        ByteArrayOutputStream bos = new ByteArrayOutputStream();
+                        DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(bos, 256));
+                        Locale locale = address.getLocale();
+                        Utils.writeUTF(dos, locale.getLanguage());
+                        Utils.writeUTF(dos, locale.getCountry());
+                        Utils.writeUTF(dos, locale.getVariant());
+
+                        Utils.writeUTF(dos, address.getThoroughfare());
+                        int numAddressLines = address.getMaxAddressLineIndex();
+                        dos.writeInt(numAddressLines);
+                        for (int i = 0; i < numAddressLines; ++i) {
+                            Utils.writeUTF(dos, address.getAddressLine(i));
+                        }
+                        Utils.writeUTF(dos, address.getFeatureName());
+                        Utils.writeUTF(dos, address.getLocality());
+                        Utils.writeUTF(dos, address.getAdminArea());
+                        Utils.writeUTF(dos, address.getSubAdminArea());
+
+                        Utils.writeUTF(dos, address.getCountryName());
+                        Utils.writeUTF(dos, address.getCountryCode());
+                        Utils.writeUTF(dos, address.getPostalCode());
+                        Utils.writeUTF(dos, address.getPhone());
+                        Utils.writeUTF(dos, address.getUrl());
+
+                        dos.flush();
+                        sGeoCache.put(locationKey, bos.toByteArray());
+                        dos.close();
                     }
-                    Utils.writeUTF(dos, address.getFeatureName());
-                    Utils.writeUTF(dos, address.getLocality());
-                    Utils.writeUTF(dos, address.getAdminArea());
-                    Utils.writeUTF(dos, address.getSubAdminArea());
-
-                    Utils.writeUTF(dos, address.getCountryName());
-                    Utils.writeUTF(dos, address.getCountryCode());
-                    Utils.writeUTF(dos, address.getPostalCode());
-                    Utils.writeUTF(dos, address.getPhone());
-                    Utils.writeUTF(dos, address.getUrl());
-
-                    dos.flush();
-                    sGeoCache.put(locationKey, bos.toByteArray());
-                    dos.close();
+                } finally {
+
                 }
             } else {
                 // Parsing the address from the byte stream.
index 7debd1a..c0abc6d 100644 (file)
@@ -24,8 +24,8 @@ public abstract class RootLayer extends Layer {
     public boolean onKeyUp(int keyCode, KeyEvent event) {
         return false;
     }
-    
+
     public void handleLowMemory() {
-     
+
     }
- }
+}
index 45df573..b3d2c57 100644 (file)
@@ -93,4 +93,3 @@ public class RotateBitmap {
         }
     }
 }
-
index 83527ef..2bf0658 100644 (file)
@@ -15,15 +15,16 @@ public final class Shared {
     public static boolean isPowerOf2(int n) {
         return (n & -n) == n;
     }
-    
+
     /**
-     * @param i : running variable
+     * @param i
+     *            : running variable
      * @return 0, +1, -1, +2, -2, +3, -3 ..
      */
     public static int midPointIterator(int i) {
         if (i != 0) {
-            int tick = ((i-1)/2) + 1;
-            int pass = ((i-1)%2 == 0) ? 1 : -1;
+            int tick = ((i - 1) / 2) + 1;
+            int pass = ((i - 1) % 2 == 0) ? 1 : -1;
             return tick * pass;
         }
         return 0;
@@ -55,15 +56,15 @@ public final class Shared {
         }
         return value;
     }
-    
-       public static long clamp(long value, long min, long max) {
-               if (value < min) {
+
+    public static long clamp(long value, long min, long max) {
+        if (value < min) {
             value = min;
         } else if (value > max) {
             value = max;
         }
         return value;
-       }
+    }
 
     public static float scaleToFit(float srcWidth, float srcHeight, float outerWidth, float outerHeight, boolean clipToFit) {
         float scaleX = outerWidth / srcWidth;
@@ -71,7 +72,8 @@ public final class Shared {
         return (clipToFit ? scaleX > scaleY : scaleX < scaleY) ? scaleX : scaleY;
     }
 
-    // Returns an angle between 0 and 360 degrees independent of the input angle.
+    // Returns an angle between 0 and 360 degrees independent of the input
+    // angle.
     public static float normalizePositive(float angleToRotate) {
         if (angleToRotate == 0.0f) {
             return 0.0f;
@@ -102,15 +104,15 @@ public final class Shared {
         }
         return ExifInterface.ORIENTATION_NORMAL;
     }
-    
+
     public static float exifOrientationToDegrees(int exifOrientation) {
-       if (exifOrientation == ExifInterface.ORIENTATION_ROTATE_90) {
-           return 90;
-       } else if (exifOrientation == ExifInterface.ORIENTATION_ROTATE_180) {
-           return 180;
-       } else if (exifOrientation == ExifInterface.ORIENTATION_ROTATE_270) {
-           return 270;
-       }
-       return 0;
+        if (exifOrientation == ExifInterface.ORIENTATION_ROTATE_90) {
+            return 90;
+        } else if (exifOrientation == ExifInterface.ORIENTATION_ROTATE_180) {
+            return 180;
+        } else if (exifOrientation == ExifInterface.ORIENTATION_ROTATE_270) {
+            return 270;
+        }
+        return 0;
     }
 }
index 98634e8..056cafb 100644 (file)
@@ -21,7 +21,7 @@ public final class SimpleStringTexture extends Texture {
     public float getBaselineHeight() {
         return mBaselineHeight;
     }
-    
+
     @Override
     public boolean isCached() {
         return true;
index 646f3f1..0d9b862 100644 (file)
@@ -60,9 +60,9 @@ public class SingleDataSource implements DataSource {
     public void shutdown() {
 
     }
-    
+
     public boolean isSingleImage() {
-       return mSingleUri;
+        return mSingleUri;
     }
 
     private static boolean isSingleImageMode(String uriString) {
@@ -143,8 +143,9 @@ public class SingleDataSource implements DataSource {
                 for (int i = 1; i < numItems; ++i) {
                     MediaItem thisItem = items.get(i);
                     String filePath = Uri.fromFile(new File(thisItem.mFilePath)).toString();
-                    if (item.mId == thisItem.mId || ((item.mContentUri != null && thisItem.mContentUri != null) && (item.mContentUri.equals(thisItem.mContentUri)
-                            || item.mContentUri.equals(filePath)))) {
+                    if (item.mId == thisItem.mId
+                            || ((item.mContentUri != null && thisItem.mContentUri != null) && (item.mContentUri
+                                    .equals(thisItem.mContentUri) || item.mContentUri.equals(filePath)))) {
                         items.remove(thisItem);
                         --parentSet.mNumItemsLoaded;
                         break;
@@ -157,23 +158,28 @@ public class SingleDataSource implements DataSource {
             final Uri uriImages = Images.Media.EXTERNAL_CONTENT_URI;
             final ContentResolver cr = mContext.getContentResolver();
             String where = null;
-            Cursor cursor = cr.query(uriImages, CacheService.PROJECTION_IMAGES, where, null, null);
-            if (cursor != null && cursor.moveToFirst()) {
-                parentSet.setNumExpectedItems(cursor.getCount());
-                do {
-                    if (Thread.interrupted()) {
-                        return;
+            try {
+                Cursor cursor = cr.query(uriImages, CacheService.PROJECTION_IMAGES, where, null, null);
+                if (cursor != null && cursor.moveToFirst()) {
+                    parentSet.setNumExpectedItems(cursor.getCount());
+                    do {
+                        if (Thread.interrupted()) {
+                            return;
+                        }
+                        final MediaItem item = new MediaItem();
+                        CacheService.populateMediaItemFromCursor(item, cr, cursor, CacheService.BASE_CONTENT_STRING_IMAGES);
+                        feed.addItemToMediaSet(item, parentSet);
+                    } while (cursor.moveToNext());
+                    if (cursor != null) {
+                        cursor.close();
+                        cursor = null;
                     }
-                    final MediaItem item = new MediaItem();
-                    CacheService.populateMediaItemFromCursor(item, cr, cursor, CacheService.BASE_CONTENT_STRING_IMAGES);
-                    feed.addItemToMediaSet(item, parentSet);
-                } while (cursor.moveToNext());
-                if (cursor != null) {
-                    cursor.close();
-                    cursor = null;
+                    parentSet.updateNumExpectedItems();
+                    parentSet.generateTitle(true);
                 }
-                parentSet.updateNumExpectedItems();
-                parentSet.generateTitle(true);
+            } catch (Exception e) {
+                // If the database operation failed for any reason.
+                ;
             }
         } else {
             CacheService.loadMediaItemsIntoMediaFeed(feed, parentSet, rangeStart, rangeEnd, true, true);
index e77a139..f54c39c 100644 (file)
@@ -27,8 +27,8 @@ import android.database.DataSetObserver;
 import android.util.Log;
 
 /**
- * A variant of MergeCursor that sorts the cursors being merged. If decent performance is ever obtained, it can be put back under
- * android.database.
+ * A variant of MergeCursor that sorts the cursors being merged. If decent
+ * performance is ever obtained, it can be put back under android.database.
  */
 public class SortCursor extends AbstractCursor {
     private static final String TAG = "SortCursor";
@@ -129,9 +129,11 @@ public class SortCursor extends AbstractCursor {
             return true;
 
         /*
-         * Find the right cursor Because the client of this cursor (the listadapter/view) tends to jump around in the cursor
-         * somewhat, a simple cache strategy is used to avoid having to search all cursors from the start. TODO: investigate
-         * strategies for optimizing random access and reverse-order access.
+         * Find the right cursor Because the client of this cursor (the
+         * listadapter/view) tends to jump around in the cursor somewhat, a
+         * simple cache strategy is used to avoid having to search all cursors
+         * from the start. TODO: investigate strategies for optimizing random
+         * access and reverse-order access.
          */
 
         int cache_entry = newPosition % ROWCACHESIZE;
index e9bc662..f2dcc35 100644 (file)
@@ -22,9 +22,9 @@ public final class StringTexture extends Texture {
     private static final Paint sPaint = new Paint();
 
     public static int computeTextWidthForConfig(String string, Config config) {
-       return computeTextWidthForConfig(config.fontSize, config.bold ? Typeface.DEFAULT_BOLD : Typeface.DEFAULT, string);
+        return computeTextWidthForConfig(config.fontSize, config.bold ? Typeface.DEFAULT_BOLD : Typeface.DEFAULT, string);
     }
-    
+
     public static int computeTextWidthForConfig(float textSize, Typeface typeface, String string) {
         Paint paint = sPaint;
         synchronized (paint) {
@@ -32,7 +32,7 @@ public final class StringTexture extends Texture {
             paint.setTypeface(typeface);
             paint.setTextSize(textSize);
             // 10 pixel buffer to compensate for the shade at the end.
-            return (int)(10.0f * Gallery.PIXEL_DENSITY) + (int)FloatMath.ceil(paint.measureText(string));
+            return (int) (10.0f * Gallery.PIXEL_DENSITY) + (int) FloatMath.ceil(paint.measureText(string));
         }
     }
 
@@ -64,7 +64,7 @@ public final class StringTexture extends Texture {
     public StringTexture(String string, Config config) {
         this(string, config, config.width, config.height);
     }
-    
+
     public StringTexture(String string, Config config, int width, int height) {
         mString = string;
         mConfig = config;
@@ -83,7 +83,7 @@ public final class StringTexture extends Texture {
             return 0;
         }
     }
-    
+
     @Override
     public boolean isCached() {
         return true;
@@ -156,64 +156,65 @@ public final class StringTexture extends Texture {
         int descent = metrics.descent + padding;
         int backWidth = mWidth;
         int backHeight = mHeight;
-        
+
         String string = mString;
         Rect bounds = new Rect();
         paint.getTextBounds(string, 0, string.length(), bounds);
-        
+
         if (config.sizeMode == Config.SIZE_BOUNDS_TO_TEXT) {
             // do something else
             backWidth = bounds.width() + 2 * padding;
             int height = descent - ascent;
             backHeight = height + padding;
-        } 
+        }
         if (backWidth <= 0 || backHeight <= 0)
             return null;
         Bitmap bitmap = Bitmap.createBitmap(backWidth, backHeight, bmConfig);
         Canvas canvas = new Canvas(bitmap);
         // for top
-        int x = (config.xalignment == Config.ALIGN_LEFT) ? padding
-                : (config.xalignment == Config.ALIGN_RIGHT ? backWidth - padding : backWidth / 2);
+        int x = (config.xalignment == Config.ALIGN_LEFT) ? padding : (config.xalignment == Config.ALIGN_RIGHT ? backWidth - padding
+                : backWidth / 2);
         int y = (config.yalignment == Config.ALIGN_TOP) ? -metrics.top + padding
                 : ((config.yalignment == Config.ALIGN_BOTTOM) ? (backHeight - descent)
                         : ((int) backHeight - (descent + ascent)) / 2);
         // bitmap.eraseColor(0xff00ff00);
         canvas.drawText(stringToDraw, x, y, paint);
-        
+
         if (bounds.width() > backWidth && config.overflowMode == Config.OVERFLOW_FADE) {
-            // Fade the right edge of the string if the text overflows. TODO: BIDI text should fade on the left.
+            // Fade the right edge of the string if the text overflows. TODO:
+            // BIDI text should fade on the left.
             float gradientLeft = backWidth - Config.FADE_WIDTH;
-            LinearGradient gradient = new LinearGradient(gradientLeft, 0, backWidth, 0, 0xffffffff,
-                    0x00ffffff, Shader.TileMode.CLAMP);
+            LinearGradient gradient = new LinearGradient(gradientLeft, 0, backWidth, 0, 0xffffffff, 0x00ffffff,
+                    Shader.TileMode.CLAMP);
             paint = new Paint();
             paint.setShader(gradient);
             paint.setDither(true);
             paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.MULTIPLY));
             canvas.drawRect(gradientLeft, 0, backWidth, backHeight, paint);
         }
-        
+
         mBaselineHeight = padding + metrics.bottom;
         return bitmap;
     }
-    
+
     public static final class Config {
         public static final int SIZE_EXACT = 0;
         public static final int SIZE_TEXT_TO_BOUNDS = 1;
         public static final int SIZE_BOUNDS_TO_TEXT = 2;
-        
+
         public static final int OVERFLOW_CLIP = 0;
         public static final int OVERFLOW_ELLIPSIZE = 1;
         public static final int OVERFLOW_FADE = 2;
-        
+
         public static final int ALIGN_HCENTER = 0;
         public static final int ALIGN_LEFT = 1;
         public static final int ALIGN_RIGHT = 2;
         public static final int ALIGN_TOP = 3;
         public static final int ALIGN_BOTTOM = 4;
         public static final int ALIGN_VCENTER = 5;
-        
+
         private static final int FADE_WIDTH = 30;
-        
+
         public static final Config DEFAULT_CONFIG_SCALED = new Config();
         public static final Config DEFAULT_CONFIG_TRUNCATED = new Config(SIZE_TEXT_TO_BOUNDS);
 
@@ -222,12 +223,13 @@ public final class StringTexture extends Texture {
         public float g = 1f;
         public float b = 1f;
         public float a = 1f;
-        public int shadowRadius = 4 * (int)Gallery.PIXEL_DENSITY;
+        public int shadowRadius = 4 * (int) Gallery.PIXEL_DENSITY;
         public boolean underline = false;
         public boolean bold = false;
         public boolean italic = false;
         public boolean strikeThrough = false;
-        public int width = 256;  // TODO: there is no good default for this, require explicit specification.
+        public int width = 256; // TODO: there is no good default for this,
+                                // require explicit specification.
         public int height = 32;
         public int xalignment = ALIGN_LEFT;
         public int yalignment = ALIGN_VCENTER;
index 422b90d..ed59fcb 100644 (file)
@@ -21,7 +21,7 @@ public abstract class Texture {
     public boolean isCached() {
         return false;
     }
-    
+
     public final void clear() {
         mId = 0;
         mState = STATE_UNLOADED;
@@ -34,7 +34,7 @@ public abstract class Texture {
             mBitmap = null;
         }
     }
-    
+
     public final boolean isLoaded() {
         return mState == STATE_LOADED;
     }
index 1b0184c..d2b47e0 100644 (file)
@@ -75,7 +75,7 @@ public final class TimeBar extends Layer implements MediaFeed.Listener {
         mBackgroundRect = new Rect();
         SRC_PAINT.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));
     }
-    
+
     public void regenerateStringsForContext(Context context) {
         // Create textures for month names.
         String[] months = context.getResources().getStringArray(R.array.months_abbreviated);
@@ -234,14 +234,12 @@ public final class TimeBar extends Layer implements MediaFeed.Listener {
                         if (month != lastMonth) {
                             lastMonth = month;
                             lastDayBlock = -1;
-                            marker = new Marker(dx, time.getTimeInMillis(), year, month, dayBlock,
-                                    Marker.TYPE_MONTH, increment);
+                            marker = new Marker(dx, time.getTimeInMillis(), year, month, dayBlock, Marker.TYPE_MONTH, increment);
                             dx = addMarker(marker);
                         } else if (dayBlock != lastDayBlock) {
                             lastDayBlock = dayBlock;
                             if (dayBlock != 0) {
-                                marker = new Marker(dx, time.getTimeInMillis(), year, month, dayBlock,
-                                        Marker.TYPE_DAY, increment);
+                                marker = new Marker(dx, time.getTimeInMillis(), year, month, dayBlock, Marker.TYPE_DAY, increment);
                                 dx = addMarker(marker);
                             }
                         } else {
@@ -288,13 +286,15 @@ public final class TimeBar extends Layer implements MediaFeed.Listener {
     }
 
     /*
-     * private float getKnobXForPosition(float position) { return position * (mTotalWidth - mKnob.getWidth()); }
+     * private float getKnobXForPosition(float position) { return position *
+     * (mTotalWidth - mKnob.getWidth()); }
      * 
-     * private float getPositionForKnobX(float knobX) { return Math.max(0f, Math.min(1f, knobX / (mTotalWidth - mKnob.getWidth())));
-     * }
+     * private float getPositionForKnobX(float knobX) { return Math.max(0f,
+     * Math.min(1f, knobX / (mTotalWidth - mKnob.getWidth()))); }
      * 
-     * private float getScrollForPosition(float position) { return position * (mTotalWidth - mWidth);// - (1f - 2f * position) *
-     * MARKER_SPACING_PIXELS; }
+     * private float getScrollForPosition(float position) { return position *
+     * (mTotalWidth - mWidth);// - (1f - 2f * position) * MARKER_SPACING_PIXELS;
+     * }
      */
 
     private float getScrollForPosition(float position) {
index 3effa7b..fc38094 100644 (file)
@@ -162,7 +162,8 @@ public class UriTexture extends Texture {
                     }
                     HttpEntity entity = httpResponse.getEntity();
                     if (entity != null) {
-                        // Wrap the entity input stream in a GZIP decoder if necessary.
+                        // Wrap the entity input stream in a GZIP decoder if
+                        // necessary.
                         contentInput = entity.getContent();
                     }
                 }
@@ -237,7 +238,7 @@ public class UriTexture extends Texture {
             return null;
         }
     }
-    
+
     public static String writeHttpDataInDirectory(Context context, String uri, String path) {
         long crc64 = Utils.Crc64Long(uri);
         if (!isCached(crc64, 1024)) {
@@ -286,7 +287,7 @@ public class UriTexture extends Texture {
             }
         }
     }
-    
+
     public static void invalidateCache(long crc64, int maxResolution) {
         String file = createFilePathFromCrc64(crc64, maxResolution);
         if (file != null && crc64 != 0) {
index 8089c30..761430f 100644 (file)
@@ -16,7 +16,6 @@
 
 package com.cooliris.media;
 
-
 import android.app.ProgressDialog;
 import android.content.ActivityNotFoundException;
 import android.content.ComponentName;
@@ -39,11 +38,8 @@ import java.io.Closeable;
  */
 public class Util {
     private static final String TAG = "db.Util";
-    private static final String MAPS_PACKAGE_NAME =
-            "com.google.android.apps.maps";
-    private static final String MAPS_CLASS_NAME =
-            "com.google.android.maps.MapsActivity";
-
+    private static final String MAPS_PACKAGE_NAME = "com.google.android.apps.maps";
+    private static final String MAPS_CLASS_NAME = "com.google.android.maps.MapsActivity";
 
     private Util() {
     }
@@ -53,11 +49,9 @@ public class Util {
     public static Bitmap rotate(Bitmap b, int degrees) {
         if (degrees != 0 && b != null) {
             Matrix m = new Matrix();
-            m.setRotate(degrees,
-                    (float) b.getWidth() / 2, (float) b.getHeight() / 2);
+            m.setRotate(degrees, (float) b.getWidth() / 2, (float) b.getHeight() / 2);
             try {
-                Bitmap b2 = Bitmap.createBitmap(
-                        b, 0, 0, b.getWidth(), b.getHeight(), m, true);
+                Bitmap b2 = Bitmap.createBitmap(b, 0, 0, b.getWidth(), b.getHeight(), m, true);
                 if (b != b2) {
                     b.recycle();
                     b = b2;
@@ -69,38 +63,26 @@ public class Util {
         return b;
     }
 
-    public static Bitmap transform(Matrix scaler,
-                                   Bitmap source,
-                                   int targetWidth,
-                                   int targetHeight,
-                                   boolean scaleUp) {
+    public static Bitmap transform(Matrix scaler, Bitmap source, int targetWidth, int targetHeight, boolean scaleUp) {
         int deltaX = source.getWidth() - targetWidth;
         int deltaY = source.getHeight() - targetHeight;
         if (!scaleUp && (deltaX < 0 || deltaY < 0)) {
             /*
              * In this case the bitmap is smaller, at least in one dimension,
-             * than the target.  Transform it by placing as much of the image
-             * as possible into the target and leaving the top/bottom or
-             * left/right (or both) black.
+             * than the target. Transform it by placing as much of the image as
+             * possible into the target and leaving the top/bottom or left/right
+             * (or both) black.
              */
-            Bitmap b2 = Bitmap.createBitmap(targetWidth, targetHeight,
-                    Bitmap.Config.ARGB_8888);
+            Bitmap b2 = Bitmap.createBitmap(targetWidth, targetHeight, Bitmap.Config.ARGB_8888);
             Canvas c = new Canvas(b2);
 
             int deltaXHalf = Math.max(0, deltaX / 2);
             int deltaYHalf = Math.max(0, deltaY / 2);
-            Rect src = new Rect(
-                    deltaXHalf,
-                    deltaYHalf,
-                    deltaXHalf + Math.min(targetWidth, source.getWidth()),
-                    deltaYHalf + Math.min(targetHeight, source.getHeight()));
-            int dstX = (targetWidth  - src.width())  / 2;
+            Rect src = new Rect(deltaXHalf, deltaYHalf, deltaXHalf + Math.min(targetWidth, source.getWidth()), deltaYHalf
+                    + Math.min(targetHeight, source.getHeight()));
+            int dstX = (targetWidth - src.width()) / 2;
             int dstY = (targetHeight - src.height()) / 2;
-            Rect dst = new Rect(
-                    dstX,
-                    dstY,
-                    targetWidth - dstX,
-                    targetHeight - dstY);
+            Rect dst = new Rect(dstX, dstY, targetWidth - dstX, targetHeight - dstY);
             c.drawBitmap(source, src, dst, null);
             return b2;
         }
@@ -108,7 +90,7 @@ public class Util {
         float bitmapHeightF = source.getHeight();
 
         float bitmapAspect = bitmapWidthF / bitmapHeightF;
-        float viewAspect   = (float) targetWidth / targetHeight;
+        float viewAspect = (float) targetWidth / targetHeight;
 
         if (bitmapAspect > viewAspect) {
             float scale = targetHeight / bitmapHeightF;
@@ -129,8 +111,7 @@ public class Util {
         Bitmap b1;
         if (scaler != null) {
             // this is used for minithumb and crop, so we want to filter here.
-            b1 = Bitmap.createBitmap(source, 0, 0,
-                    source.getWidth(), source.getHeight(), scaler, true);
+            b1 = Bitmap.createBitmap(source, 0, 0, source.getWidth(), source.getHeight(), scaler, true);
         } else {
             b1 = source;
         }
@@ -138,12 +119,7 @@ public class Util {
         int dx1 = Math.max(0, b1.getWidth() - targetWidth);
         int dy1 = Math.max(0, b1.getHeight() - targetHeight);
 
-        Bitmap b2 = Bitmap.createBitmap(
-                b1,
-                dx1 / 2,
-                dy1 / 2,
-                targetWidth,
-                targetHeight);
+        Bitmap b2 = Bitmap.createBitmap(b1, dx1 / 2, dy1 / 2, targetWidth, targetHeight);
 
         if (b1 != source) {
             b1.recycle();
@@ -154,15 +130,14 @@ public class Util {
 
     /**
      * Creates a centered bitmap of the desired size. Recycles the input.
+     * 
      * @param source
      */
-    public static Bitmap extractMiniThumb(
-            Bitmap source, int width, int height) {
+    public static Bitmap extractMiniThumb(Bitmap source, int width, int height) {
         return Util.extractMiniThumb(source, width, height, true);
     }
 
-    public static Bitmap extractMiniThumb(
-            Bitmap source, int width, int height, boolean recycle) {
+    public static Bitmap extractMiniThumb(Bitmap source, int width, int height, boolean recycle) {
         if (source == null) {
             return null;
         }
@@ -183,8 +158,7 @@ public class Util {
         return miniThumbnail;
     }
 
-
-    public static <T>  int indexOf(T [] array, T s) {
+    public static <T> int indexOf(T[] array, T s) {
         for (int i = 0; i < array.length; i++) {
             if (array[i].equals(s)) {
                 return i;
@@ -194,7 +168,8 @@ public class Util {
     }
 
     public static void closeSilently(Closeable c) {
-        if (c == null) return;
+        if (c == null)
+            return;
         try {
             c.close();
         } catch (Throwable t) {
@@ -203,7 +178,8 @@ public class Util {
     }
 
     public static void closeSilently(ParcelFileDescriptor c) {
-        if (c == null) return;
+        if (c == null)
+            return;
         try {
             c.close();
         } catch (Throwable t) {
@@ -222,8 +198,7 @@ public class Util {
         return a == b || a.equals(b);
     }
 
-    private static class BackgroundJob
-            extends MonitoredActivity.LifeCycleAdapter implements Runnable {
+    private static class BackgroundJob extends MonitoredActivity.LifeCycleAdapter implements Runnable {
 
         private final MonitoredActivity mActivity;
         private final ProgressDialog mDialog;
@@ -232,12 +207,12 @@ public class Util {
         private final Runnable mCleanupRunner = new Runnable() {
             public void run() {
                 mActivity.removeLifeCycleListener(BackgroundJob.this);
-                if (mDialog.getWindow() != null) mDialog.dismiss();
+                if (mDialog.getWindow() != null)
+                    mDialog.dismiss();
             }
         };
 
-        public BackgroundJob(MonitoredActivity activity, Runnable job,
-                ProgressDialog dialog, Handler handler) {
+        public BackgroundJob(MonitoredActivity activity, Runnable job, ProgressDialog dialog, Handler handler) {
             mActivity = activity;
             mDialog = dialog;
             mJob = job;
@@ -253,7 +228,6 @@ public class Util {
             }
         }
 
-
         @Override
         public void onActivityDestroyed(MonitoredActivity activity) {
             // We get here only when the onDestroyed being called before
@@ -273,27 +247,25 @@ public class Util {
         }
     }
 
-    public static void startBackgroundJob(MonitoredActivity activity,
-            String title, String message, Runnable job, Handler handler) {
+    public static void startBackgroundJob(MonitoredActivity activity, String title, String message, Runnable job, Handler handler) {
         // Make the progress dialog uncancelable, so that we can gurantee
         // the thread will be done before the activity getting destroyed.
-        ProgressDialog dialog = ProgressDialog.show(
-                activity, title, message, true, false);
+        ProgressDialog dialog = ProgressDialog.show(activity, title, message, true, false);
         new Thread(new BackgroundJob(activity, job, dialog, handler)).start();
     }
 
     // Returns an intent which is used for "set as" menu items.
     public static Intent createSetAsIntent(Uri uri, String mimeType) {
-       // Infer MIME type if missing for file URLs.
-       if (uri.getScheme().equals("file")) {
-               String path = uri.getPath();
-               int lastDotIndex = path.lastIndexOf('.');
-               if (lastDotIndex != -1) {
-                       mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(
-                                       uri.getPath().substring(lastDotIndex + 1).toLowerCase());
-               }
-       }
-       
+        // Infer MIME type if missing for file URLs.
+        if (uri.getScheme().equals("file")) {
+            String path = uri.getPath();
+            int lastDotIndex = path.lastIndexOf('.');
+            if (lastDotIndex != -1) {
+                mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(
+                        uri.getPath().substring(lastDotIndex + 1).toLowerCase());
+            }
+        }
+
         Intent intent = new Intent(Intent.ACTION_ATTACH_DATA);
         intent.setDataAndType(uri, mimeType);
         intent.putExtra("mimeType", mimeType);
@@ -305,7 +277,6 @@ public class Util {
     // it in GMM instead. For those platforms which have no GMM installed,
     // the default Maps application will be chosen.
 
-    
     public static void openMaps(Context context, double latitude, double longitude) {
         try {
             // Try to open the GMM first
@@ -314,12 +285,9 @@ public class Util {
             // the MapView to the specified location, but we need a marker
             // for further operations (routing to/from).
             // The q=(lat, lng) syntax is suggested by geo-team.
-            String url = String.format(
-                    "http://maps.google.com/maps?f=q&q=(%s,%s)", latitude, longitude);
-            ComponentName compName =
-                    new ComponentName(MAPS_PACKAGE_NAME, MAPS_CLASS_NAME);
-            Intent mapsIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url))
-                    .setComponent(compName);
+            String url = String.format("http://maps.google.com/maps?f=q&q=(%s,%s)", latitude, longitude);
+            ComponentName compName = new ComponentName(MAPS_PACKAGE_NAME, MAPS_CLASS_NAME);
+            Intent mapsIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)).setComponent(compName);
             context.startActivity(mapsIntent);
         } catch (ActivityNotFoundException e) {
             // Use the "geo intent" if no GMM is installed
index da115a7..01a2a11 100644 (file)
@@ -126,7 +126,8 @@ public class Utils {
             return null;
         long crc = Crc64Long(in);
         /*
-         * The output is done in two parts to avoid problems with architecture-dependent word order
+         * The output is done in two parts to avoid problems with
+         * architecture-dependent word order
          */
         int low = ((int) crc) & 0xffffffff;
         int high = ((int) (crc >> 32)) & 0xffffffff;
@@ -147,13 +148,13 @@ public class Utils {
         }
         return string;
     }
-    
+
     // Copies src file to dst file.
     // If the dst file does not exist, it is created
     public static void Copy(File src, File dst) throws IOException {
         InputStream in = new FileInputStream(src);
         OutputStream out = new FileOutputStream(dst);
-    
+
         // Transfer bytes from in to out
         byte[] buf = new byte[1024];
         int len;
index 855821c..ec0b990 100644 (file)
@@ -48,9 +48,9 @@ public final class Vector3f {
             return true;
         return false;
     }
-    
+
     @Override
     public String toString() {
-        return (new String("(" + x + ", " + y + ", " + z + ")" ));
+        return (new String("(" + x + ", " + y + ", " + z + ")"));
     }
 }
index 0b631e3..0ab86db 100644 (file)
@@ -58,18 +58,17 @@ public class Wallpaper extends Activity {
         @Override
         public void handleMessage(Message msg) {
             switch (msg.what) {
-                case SHOW_PROGRESS: {
-                    CharSequence c = getText(R.string.wallpaper);
-                    mProgressDialog = ProgressDialog.show(Wallpaper.this,
-                            "", c, true, false);
-                    break;
-                }
-                case FINISH: {
-                    closeProgressDialog();
-                    setResult(RESULT_OK);
-                    finish();
-                    break;
-                }
+            case SHOW_PROGRESS: {
+                CharSequence c = getText(R.string.wallpaper);
+                mProgressDialog = ProgressDialog.show(Wallpaper.this, "", c, true, false);
+                break;
+            }
+            case FINISH: {
+                closeProgressDialog();
+                setResult(RESULT_OK);
+                finish();
+                break;
+            }
             }
         }
     };
@@ -80,8 +79,7 @@ public class Wallpaper extends Activity {
         private final Context mContext;
         private final File mFile;
 
-        public SetWallpaperThread(Bitmap bitmap, Handler handler,
-                                  Context context, File file) {
+        public SetWallpaperThread(Bitmap bitmap, Handler handler, Context context, File file) {
             mBitmap = bitmap;
             mHandler = handler;
             mContext = context;
@@ -138,8 +136,7 @@ public class Wallpaper extends Activity {
         Uri imageToUse = getIntent().getData();
         if (imageToUse != null) {
             Intent intent = new Intent();
-            intent.setClassName("com.cooliris.media",
-                                "com.cooliris.media.CropImage");
+            intent.setClassName("com.cooliris.media", "com.cooliris.media.CropImage");
             intent.setData(imageToUse);
             formatIntent(intent);
             startActivityForResult(intent, CROP_DONE);
@@ -162,11 +159,11 @@ public class Wallpaper extends Activity {
 
         int width = getWallpaperDesiredMinimumWidth();
         int height = getWallpaperDesiredMinimumHeight();
-        intent.putExtra("outputX",         width);
-        intent.putExtra("outputY",         height);
-        intent.putExtra("aspectX",         width);
-        intent.putExtra("aspectY",         height);
-        intent.putExtra("scale",           true);
+        intent.putExtra("outputX", width);
+        intent.putExtra("outputY", height);
+        intent.putExtra("aspectX", width);
+        intent.putExtra("aspectY", height);
+        intent.putExtra("scale", true);
         intent.putExtra("noFaceDetection", true);
         intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(mTempFile));
         intent.putExtra("outputFormat", Bitmap.CompressFormat.PNG.name());
@@ -176,22 +173,17 @@ public class Wallpaper extends Activity {
     }
 
     @Override
-    protected void onActivityResult(int requestCode, int resultCode,
-                                    Intent data) {
-        if ((requestCode == PHOTO_PICKED || requestCode == CROP_DONE)
-                && (resultCode == RESULT_OK) && (data != null)) {
+    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+        if ((requestCode == PHOTO_PICKED || requestCode == CROP_DONE) && (resultCode == RESULT_OK) && (data != null)) {
             try {
                 InputStream s = new FileInputStream(mTempFile);
                 try {
                     Bitmap bitmap = BitmapFactory.decodeStream(s);
                     if (bitmap == null) {
-                        Log.e(LOG_TAG, "Failed to set wallpaper. "
-                                       + "Couldn't get bitmap for path "
-                                       + mTempFile);
+                        Log.e(LOG_TAG, "Failed to set wallpaper. " + "Couldn't get bitmap for path " + mTempFile);
                     } else {
                         mHandler.sendEmptyMessage(SHOW_PROGRESS);
-                        new SetWallpaperThread(
-                                bitmap, mHandler, this, mTempFile).start();
+                        new SetWallpaperThread(bitmap, mHandler, this, mTempFile).start();
                     }
                     mDoLaunch = false;
                 } finally {
index 04091a3..29d2501 100644 (file)
@@ -10,29 +10,31 @@ public final class AlbumEntry extends Entry {
     public static final EntrySchema SCHEMA = new EntrySchema(AlbumEntry.class);
 
     /**
-     * The user account that is the sync source for this entry. Must be set before insert/update.
+     * The user account that is the sync source for this entry. Must be set
+     * before insert/update.
      */
     @Column(Columns.SYNC_ACCOUNT)
     public String syncAccount;
-    
+
     /**
      * The ETag for the album/photos GData feed.
      */
     @Column(Columns.PHOTOS_ETAG)
-       public String photosEtag = null;
-    
+    public String photosEtag = null;
+
     /**
-     * True if the contents of the album need to be synchronized. Must be set before insert/update.
+     * True if the contents of the album need to be synchronized. Must be set
+     * before insert/update.
      */
     @Column(Columns.PHOTOS_DIRTY)
     public boolean photosDirty;
-    
+
     /**
      * The "edit" URI of the album.
      */
     @Column(Columns.EDIT_URI)
     public String editUri;
-    
+
     /**
      * The album owner.
      */
@@ -42,75 +44,76 @@ public final class AlbumEntry extends Entry {
     /**
      * The title of the album.
      */
-    @Column(value=Columns.TITLE)
+    @Column(value = Columns.TITLE)
     public String title;
-    
+
     /**
      * A short summary of the contents of the album.
      */
-    @Column(value=Columns.SUMMARY)
+    @Column(value = Columns.SUMMARY)
     public String summary;
-    
+
     /**
      * The date the album was created.
      */
     @Column(Columns.DATE_PUBLISHED)
     public long datePublished;
-    
+
     /**
      * The date the album was last updated.
      */
     @Column(Columns.DATE_UPDATED)
     public long dateUpdated;
-    
+
     /**
-     * The date the album entry was last edited. May be more recent than dateUpdated.
+     * The date the album entry was last edited. May be more recent than
+     * dateUpdated.
      */
     @Column(Columns.DATE_EDITED)
     public long dateEdited;
-    
+
     /**
      * The number of photos in the album.
      */
     @Column(Columns.NUM_PHOTOS)
     public int numPhotos;
-    
+
     /**
      * The number of bytes of storage that this album uses.
      */
     @Column(Columns.BYTES_USED)
     public long bytesUsed;
-    
+
     /**
      * The user-specified location associated with the album.
      */
     @Column(Columns.LOCATION_STRING)
     public String locationString;
-    
+
     /**
      * The thumbnail URL associated with the album.
      */
     @Column(Columns.THUMBNAIL_URL)
     public String thumbnailUrl;
-    
+
     /**
      * A link to the HTML page associated with the album.
      */
     @Column(Columns.HTML_PAGE_URL)
     public String htmlPageUrl;
-        
+
     /**
      * Column names specific to album entries.
      */
     public static final class Columns extends PicasaApi.Columns {
         public static final String PHOTOS_ETAG = "photos_etag";
-               public static final String USER = "user";
+        public static final String USER = "user";
         public static final String BYTES_USED = "bytes_used";
         public static final String NUM_PHOTOS = "num_photos";
         public static final String LOCATION_STRING = "location_string";
         public static final String PHOTOS_DIRTY = "photos_dirty";
     }
-    
+
     /**
      * Resets values to defaults for object reuse.
      */
@@ -132,69 +135,70 @@ public final class AlbumEntry extends Entry {
         thumbnailUrl = null;
         htmlPageUrl = null;
     }
-    
+
     /**
-     * Sets the property value corresponding to the given XML element, if applicable.
+     * Sets the property value corresponding to the given XML element, if
+     * applicable.
      */
     @Override
     public void setPropertyFromXml(String uri, String localName, Attributes attrs, String content) {
         char localNameChar = localName.charAt(0);
         if (uri.equals(GDataParser.GPHOTO_NAMESPACE)) {
             switch (localNameChar) {
-                case 'i':
-                    if (localName.equals("id")) {
-                        id = Long.parseLong(content);
-                    }
-                    break;
-                case 'u':
-                    if (localName.equals("user")) {
-                        user = content;
-                    }
-                    break;
-                case 'n':
-                    if (localName.equals("numphotos")) {
-                        numPhotos = Integer.parseInt(content);
-                    }
-                    break;
-                case 'b':
-                    if (localName.equals("bytesUsed")) {
-                        bytesUsed = Long.parseLong(content);
-                    }
-                    break;
+            case 'i':
+                if (localName.equals("id")) {
+                    id = Long.parseLong(content);
+                }
+                break;
+            case 'u':
+                if (localName.equals("user")) {
+                    user = content;
+                }
+                break;
+            case 'n':
+                if (localName.equals("numphotos")) {
+                    numPhotos = Integer.parseInt(content);
+                }
+                break;
+            case 'b':
+                if (localName.equals("bytesUsed")) {
+                    bytesUsed = Long.parseLong(content);
+                }
+                break;
             }
         } else if (uri.equals(GDataParser.ATOM_NAMESPACE)) {
             switch (localNameChar) {
-                case 't':
-                    if (localName.equals("title")) {
-                        title = content;
-                    }
-                    break;
-                case 's':
-                    if (localName.equals("summary")) {
-                        summary = content;
-                    }
-                    break;
-                case 'p':
-                    if (localName.equals("published")) {
-                        datePublished = GDataParser.parseAtomTimestamp(content);
-                    }
-                    break;
-                case 'u':
-                    if (localName.equals("updated")) {
-                        dateUpdated = GDataParser.parseAtomTimestamp(content);
-                    }
-                    break;
-                case 'l':
-                    if (localName.equals("link")) {
-                        String rel = attrs.getValue("", "rel");
-                        String href = attrs.getValue("", "href");
-                        if (rel.equals("alternate") && attrs.getValue("", "type").equals("text/html")) {
-                            htmlPageUrl = href;
-                        } else if (rel.equals("edit")) {
-                            editUri = href;
-                        }
+            case 't':
+                if (localName.equals("title")) {
+                    title = content;
+                }
+                break;
+            case 's':
+                if (localName.equals("summary")) {
+                    summary = content;
+                }
+                break;
+            case 'p':
+                if (localName.equals("published")) {
+                    datePublished = GDataParser.parseAtomTimestamp(content);
+                }
+                break;
+            case 'u':
+                if (localName.equals("updated")) {
+                    dateUpdated = GDataParser.parseAtomTimestamp(content);
+                }
+                break;
+            case 'l':
+                if (localName.equals("link")) {
+                    String rel = attrs.getValue("", "rel");
+                    String href = attrs.getValue("", "href");
+                    if (rel.equals("alternate") && attrs.getValue("", "type").equals("text/html")) {
+                        htmlPageUrl = href;
+                    } else if (rel.equals("edit")) {
+                        editUri = href;
                     }
-                    break;
+                }
+                break;
             }
         } else if (uri.equals(GDataParser.APP_NAMESPACE)) {
             if (localName.equals("edited")) {
index 59ce7d7..a48b238 100644 (file)
@@ -8,9 +8,9 @@ import java.lang.annotation.Target;
 import org.xml.sax.Attributes;
 
 public abstract class Entry {
-    public static final String[] ID_PROJECTION = {"_id"};
-    
-    // The primary key of the entry. 
+    public static final String[] ID_PROJECTION = { "_id" };
+
+    // The primary key of the entry.
     @Column("_id")
     public long id = 0;
 
@@ -19,19 +19,21 @@ public abstract class Entry {
     public @interface Table {
         String value();
     }
-    
+
     @Retention(RetentionPolicy.RUNTIME)
     @Target(ElementType.FIELD)
     public @interface Column {
         String value();
+
         boolean indexed() default false;
+
         boolean fullText() default false;
     }
 
     public void clear() {
         id = 0;
     }
-    
+
     public void setPropertyFromXml(String uri, String localName, Attributes attrs, String content) {
         throw new UnsupportedOperationException("Entry class does not support XML parsing");
     }
index 02e5fde..a18fab9 100644 (file)
@@ -18,8 +18,7 @@ public final class EntrySchema {
     public static final int TYPE_FLOAT = 5;
     public static final int TYPE_DOUBLE = 6;
     public static final int TYPE_BLOB = 7;
-    public static final String SQLITE_TYPES[] = { "TEXT", "INTEGER", "INTEGER", "INTEGER",
-                                                 "INTEGER", "REAL", "REAL", "NONE" };
+    public static final String SQLITE_TYPES[] = { "TEXT", "INTEGER", "INTEGER", "INTEGER", "INTEGER", "REAL", "REAL", "NONE" };
 
     private static final String TAG = "SchemaInfo";
     private static final String FULL_TEXT_INDEX_SUFFIX = "_fulltext";
@@ -65,7 +64,7 @@ public final class EntrySchema {
     }
 
     private void logExecSql(SQLiteDatabase db, String sql) {
-        //Log.i(TAG, sql);
+        // Log.i(TAG, sql);
         db.execSQL(sql);
     }
 
@@ -77,30 +76,30 @@ public final class EntrySchema {
                 int columnIndex = column.projectionIndex;
                 Field field = column.field;
                 switch (column.type) {
-                    case TYPE_STRING:
-                        field.set(object, cursor.getString(columnIndex));
-                        break;
-                    case TYPE_BOOLEAN:
-                        field.setBoolean(object, cursor.getShort(columnIndex) == 1);
-                        break;
-                    case TYPE_SHORT:
-                        field.setShort(object, cursor.getShort(columnIndex));
-                        break;
-                    case TYPE_INT:
-                        field.setInt(object, cursor.getInt(columnIndex));
-                        break;
-                    case TYPE_LONG:
-                        field.setLong(object, cursor.getLong(columnIndex));
-                        break;
-                    case TYPE_FLOAT:
-                        field.setFloat(object, cursor.getFloat(columnIndex));
-                        break;
-                    case TYPE_DOUBLE:
-                        field.setDouble(object, cursor.getDouble(columnIndex));
-                        break;
-                    case TYPE_BLOB:
-                        field.set(object, cursor.getBlob(columnIndex));
-                        break;
+                case TYPE_STRING:
+                    field.set(object, cursor.getString(columnIndex));
+                    break;
+                case TYPE_BOOLEAN:
+                    field.setBoolean(object, cursor.getShort(columnIndex) == 1);
+                    break;
+                case TYPE_SHORT:
+                    field.setShort(object, cursor.getShort(columnIndex));
+                    break;
+                case TYPE_INT:
+                    field.setInt(object, cursor.getInt(columnIndex));
+                    break;
+                case TYPE_LONG:
+                    field.setLong(object, cursor.getLong(columnIndex));
+                    break;
+                case TYPE_FLOAT:
+                    field.setFloat(object, cursor.getFloat(columnIndex));
+                    break;
+                case TYPE_DOUBLE:
+                    field.setDouble(object, cursor.getDouble(columnIndex));
+                    break;
+                case TYPE_BLOB:
+                    field.set(object, cursor.getBlob(columnIndex));
+                    break;
                 }
             }
         } catch (IllegalArgumentException e) {
@@ -118,30 +117,30 @@ public final class EntrySchema {
                 String columnName = column.name;
                 Field field = column.field;
                 switch (column.type) {
-                    case TYPE_STRING:
-                        values.put(columnName, (String)field.get(object));
-                        break;
-                    case TYPE_BOOLEAN:
-                        values.put(columnName, field.getBoolean(object));
-                        break;
-                    case TYPE_SHORT:
-                        values.put(columnName, field.getShort(object));
-                        break;
-                    case TYPE_INT:
-                        values.put(columnName, field.getInt(object));
-                        break;
-                    case TYPE_LONG:
-                        values.put(columnName, field.getLong(object));
-                        break;
-                    case TYPE_FLOAT:
-                        values.put(columnName, field.getFloat(object));
-                        break;
-                    case TYPE_DOUBLE:
-                        values.put(columnName, field.getDouble(object));
-                        break;
-                    case TYPE_BLOB:
-                        values.put(columnName, (byte[])field.get(object));
-                        break;
+                case TYPE_STRING:
+                    values.put(columnName, (String) field.get(object));
+                    break;
+                case TYPE_BOOLEAN:
+                    values.put(columnName, field.getBoolean(object));
+                    break;
+                case TYPE_SHORT:
+                    values.put(columnName, field.getShort(object));
+                    break;
+                case TYPE_INT:
+                    values.put(columnName, field.getInt(object));
+                    break;
+                case TYPE_LONG:
+                    values.put(columnName, field.getLong(object));
+                    break;
+                case TYPE_FLOAT:
+                    values.put(columnName, field.getFloat(object));
+                    break;
+                case TYPE_DOUBLE:
+                    values.put(columnName, field.getDouble(object));
+                    break;
+                case TYPE_BLOB:
+                    values.put(columnName, (byte[]) field.get(object));
+                    break;
                 }
             }
         } catch (IllegalArgumentException e) {
@@ -156,8 +155,7 @@ public final class EntrySchema {
     }
 
     public boolean queryWithId(SQLiteDatabase db, long id, Entry entry) {
-        Cursor cursor = db.query(mTableName, mProjection, "_id=?",
-                                 new String[] { Long.toString(id) }, null, null, null);
+        Cursor cursor = db.query(mTableName, mProjection, "_id=?", new String[] { Long.toString(id) }, null, null, null);
         boolean success = false;
         if (cursor.moveToFirst()) {
             cursorToObject(cursor, entry);
@@ -252,7 +250,8 @@ public final class EntrySchema {
             logExecSql(db, sql.toString());
             sql.setLength(0);
 
-            // Build an insert statement that will automatically keep the FTS table in sync.
+            // Build an insert statement that will automatically keep the FTS
+            // table in sync.
             StringBuilder insertSql = new StringBuilder("INSERT OR REPLACE INTO ");
             insertSql.append(ftsTableName);
             insertSql.append(" (_id");
@@ -352,7 +351,7 @@ public final class EntrySchema {
         for (int i = 0; i != fields.length; ++i) {
             // Get column metadata from the annotation.
             Field field = fields[i];
-            Entry.Column info = ((AnnotatedElement)field).getAnnotation(Entry.Column.class);
+            Entry.Column info = ((AnnotatedElement) field).getAnnotation(Entry.Column.class);
             if (info == null) {
                 continue;
             }
@@ -377,14 +376,12 @@ public final class EntrySchema {
             } else if (fieldType == byte[].class) {
                 type = TYPE_BLOB;
             } else {
-                throw new IllegalArgumentException("Unsupported field type for column: " +
-                                                   fieldType.getName());
+                throw new IllegalArgumentException("Unsupported field type for column: " + fieldType.getName());
             }
 
             // Add the column to the array.
             int index = columns.size();
-            columns.add(new ColumnInfo(info.value(), type, info.indexed(), info.fullText(), field,
-                                       index));
+            columns.add(new ColumnInfo(info.value(), type, info.indexed(), info.fullText(), field, index));
         }
 
         // Return a list.
@@ -402,8 +399,7 @@ public final class EntrySchema {
         public final Field field;
         public final int projectionIndex;
 
-        public ColumnInfo(String name, int type, boolean indexed, boolean fullText, Field field,
-                          int projectionIndex) {
+        public ColumnInfo(String name, int type, boolean indexed, boolean fullText, Field field, int projectionIndex) {
             this.name = name.toLowerCase();
             this.type = type;
             this.indexed = indexed;
index d07d12d..5c78fd1 100644 (file)
@@ -38,8 +38,7 @@ public final class GDataClient {
     public static final HttpParams HTTP_PARAMS;
     public static final ThreadSafeClientConnManager HTTP_CONNECTION_MANAGER;
 
-    private final DefaultHttpClient mHttpClient = new DefaultHttpClient(HTTP_CONNECTION_MANAGER,
-                                                                        HTTP_PARAMS);
+    private final DefaultHttpClient mHttpClient = new DefaultHttpClient(HTTP_CONNECTION_MANAGER, HTTP_PARAMS);
     private String mAuthToken;
 
     static {
@@ -69,13 +68,12 @@ public final class GDataClient {
     public void setAuthToken(String authToken) {
         mAuthToken = authToken;
     }
-    
+
     public void get(String feedUrl, Operation operation) throws IOException {
         callMethod(new HttpGet(feedUrl), operation);
     }
 
-    public void post(String feedUrl, byte[] data, String contentType, Operation operation)
-            throws IOException {
+    public void post(String feedUrl, byte[] data, String contentType, Operation operation) throws IOException {
         ByteArrayEntity entity = getCompressedEntity(data);
         entity.setContentType(contentType);
         HttpPost post = new HttpPost(feedUrl);
@@ -83,8 +81,7 @@ public final class GDataClient {
         callMethod(post, operation);
     }
 
-    public void put(String feedUrl, byte[] data, String contentType, Operation operation)
-            throws IOException {
+    public void put(String feedUrl, byte[] data, String contentType, Operation operation) throws IOException {
         ByteArrayEntity entity = getCompressedEntity(data);
         entity.setContentType(contentType);
         HttpPost post = new HttpPost(feedUrl);
@@ -93,8 +90,7 @@ public final class GDataClient {
         callMethod(post, operation);
     }
 
-    public void putStream(String feedUrl, InputStream stream, String contentType,
-                          Operation operation) throws IOException {
+    public void putStream(String feedUrl, InputStream stream, String contentType, Operation operation) throws IOException {
         InputStreamEntity entity = new InputStreamEntity(stream, -1);
         entity.setContentType(contentType);
         HttpPost post = new HttpPost(feedUrl);
@@ -111,8 +107,7 @@ public final class GDataClient {
         callMethod(post, operation);
     }
 
-    private void callMethod(HttpUriRequest request, Operation operation)
-            throws IOException {
+    private void callMethod(HttpUriRequest request, Operation operation) throws IOException {
         // Specify GData protocol version 2.0.
         request.addHeader("GData-Version", "2");
 
@@ -156,7 +151,7 @@ public final class GDataClient {
                 }
             }
         }
-        
+
         // Return the stream if successful.
         Header etagHeader = httpResponse.getFirstHeader("ETag");
         operation.outStatus = status;
index 47132bc..1fb96ad 100644 (file)
@@ -17,13 +17,13 @@ public final class GDataParser implements ContentHandler {
     public static final String GML_NAMESPACE = "http://www.opengis.net/gml";
     private static final String FEED_ELEMENT = "feed";
     private static final String ENTRY_ELEMENT = "entry";
-  
+
     private static final int STATE_DOCUMENT = 0;
     private static final int STATE_FEED = 1;
     private static final int STATE_ENTRY = 2;
-    
+
     private static final int NUM_LEVELS = 5;
-    
+
     private Entry mEntry = null;
     private EntryHandler mHandler = null;
     private int mState = STATE_DOCUMENT;
@@ -32,77 +32,77 @@ public final class GDataParser implements ContentHandler {
     private String[] mName = new String[NUM_LEVELS];
     private AttributesImpl[] mAttributes = new AttributesImpl[NUM_LEVELS];
     private final StringBuilder mValue = new StringBuilder(128);
-    
+
     public interface EntryHandler {
         void handleEntry(Entry entry);
     }
-    
+
     public GDataParser() {
         AttributesImpl[] attributes = mAttributes;
         for (int i = 0; i != NUM_LEVELS; ++i) {
             attributes[i] = new AttributesImpl();
         }
     }
-    
+
     public void setEntry(Entry entry) {
         mEntry = entry;
     }
-    
+
     public void setHandler(EntryHandler handler) {
         mHandler = handler;
     }
-    
+
     public static long parseAtomTimestamp(String timestamp) {
         Time time = new Time();
         time.parse3339(timestamp);
         return time.toMillis(true);
     }
-    
+
     public void startElement(String uri, String localName, String qName, Attributes attrs) throws SAXException {
         switch (mState) {
-            case STATE_DOCUMENT:
-                // Expect an atom:feed element.
-                if (uri.equals(ATOM_NAMESPACE) && localName.equals(FEED_ELEMENT)) {
-                    mState = STATE_FEED;
-                } else {
-                    throw new SAXException();
-                }
-                break;
-            case STATE_FEED:
-                // Expect a feed property element or an atom:entry element.
-                if (uri.equals(ATOM_NAMESPACE) && localName.equals(ENTRY_ELEMENT)) {
-                    mState = STATE_ENTRY;
-                    mEntry.clear();
-                } else {
-                    startProperty(uri, localName, attrs);
-                }
-                break;
-            case STATE_ENTRY:
+        case STATE_DOCUMENT:
+            // Expect an atom:feed element.
+            if (uri.equals(ATOM_NAMESPACE) && localName.equals(FEED_ELEMENT)) {
+                mState = STATE_FEED;
+            } else {
+                throw new SAXException();
+            }
+            break;
+        case STATE_FEED:
+            // Expect a feed property element or an atom:entry element.
+            if (uri.equals(ATOM_NAMESPACE) && localName.equals(ENTRY_ELEMENT)) {
+                mState = STATE_ENTRY;
+                mEntry.clear();
+            } else {
                 startProperty(uri, localName, attrs);
-                break;
+            }
+            break;
+        case STATE_ENTRY:
+            startProperty(uri, localName, attrs);
+            break;
         }
     }
-    
+
     public void endElement(String uri, String localName, String qName) throws SAXException {
         if (mLevel > 0) {
             // Handle property exit.
             endProperty();
-        } else {        
+        } else {
             // Handle state exit.
             switch (mState) {
-                case STATE_DOCUMENT:
-                    throw new SAXException();
-                case STATE_FEED:
-                    mState = STATE_DOCUMENT;
-                    break;
-                case STATE_ENTRY:
-                    mState = STATE_FEED;
-                    mHandler.handleEntry(mEntry);
-                    break;
+            case STATE_DOCUMENT:
+                throw new SAXException();
+            case STATE_FEED:
+                mState = STATE_DOCUMENT;
+                break;
+            case STATE_ENTRY:
+                mState = STATE_FEED;
+                mHandler.handleEntry(mEntry);
+                break;
             }
         }
     }
-    
+
     private void startProperty(String uri, String localName, Attributes attrs) {
         // Push element information onto the property stack.
         int level = mLevel + 1;
@@ -137,7 +137,7 @@ public final class GDataParser implements ContentHandler {
     }
 
     public void skippedEntity(String name) throws SAXException {
-        // Ignored. 
+        // Ignored.
     }
 
     public void startDocument() throws SAXException {
@@ -151,7 +151,7 @@ public final class GDataParser implements ContentHandler {
     public void startPrefixMapping(String prefix, String uri) throws SAXException {
         // Ignored.
     }
-    
+
     public void endPrefixMapping(String prefix) throws SAXException {
         // Ignored.
     }
index 99c53b8..ee4ec24 100644 (file)
@@ -10,7 +10,8 @@ public final class PhotoEntry extends Entry {
     public static final EntrySchema SCHEMA = new EntrySchema(PhotoEntry.class);
 
     /**
-     * The user account that is the sync source for this entry. Must be set before insert/update.
+     * The user account that is the sync source for this entry. Must be set
+     * before insert/update.
      */
     @Column("sync_account")
     public String syncAccount;
@@ -28,7 +29,8 @@ public final class PhotoEntry extends Entry {
     public long albumId;
 
     /**
-     * The display index of the photo within the album. Must be set before insert/update.
+     * The display index of the photo within the album. Must be set before
+     * insert/update.
      */
     @Column(value = "display_index", indexed = true)
     public int displayIndex;
@@ -58,7 +60,8 @@ public final class PhotoEntry extends Entry {
     public long dateUpdated;
 
     /**
-     * The date the photo entry was last edited. May be more recent than dateUpdated.
+     * The date the photo entry was last edited. May be more recent than
+     * dateUpdated.
      */
     @Column("date_edited")
     public long dateEdited;
@@ -88,7 +91,8 @@ public final class PhotoEntry extends Entry {
     public int height;
 
     /**
-     * The rotation of the photo in degrees, if rotation has not already been applied.
+     * The rotation of the photo in degrees, if rotation has not already been
+     * applied.
      */
     @Column("rotation")
     public int rotation;
@@ -124,8 +128,9 @@ public final class PhotoEntry extends Entry {
     public String screennailUrl;
 
     /**
-     * The "content" URL for the photo (currently 1280px, or a video). The original image URL is not fetched since "imgmax" accepts
-     * one size, used to get this resource.
+     * The "content" URL for the photo (currently 1280px, or a video). The
+     * original image URL is not fetched since "imgmax" accepts one size, used
+     * to get this resource.
      */
     @Column("content_url")
     public String contentUrl;
@@ -173,7 +178,8 @@ public final class PhotoEntry extends Entry {
     }
 
     /**
-     * Sets the property value corresponding to the given XML element, if applicable.
+     * Sets the property value corresponding to the given XML element, if
+     * applicable.
      */
     @Override
     public void setPropertyFromXml(String uri, String localName, Attributes attrs, String content) {
index 426685a..15a9f20 100644 (file)
@@ -83,7 +83,8 @@ public final class PicasaApi {
                 // Get the token without user interaction.
                 authToken = accountManager.blockingGetAuthToken(account, PicasaService.SERVICE_NAME, true);
 
-                // TODO: Remove this once the build is signed by Google, since we will always have permission.
+                // TODO: Remove this once the build is signed by Google, since
+                // we will always have permission.
                 // This code requests permission from the user explicitly.
                 if (context instanceof Activity) {
                     Bundle bundle = accountManager.getAuthToken(account, PicasaService.SERVICE_NAME, null, (Activity) context,
@@ -96,7 +97,8 @@ public final class PicasaApi {
                 if (authToken != null) {
                     String username = account.name;
                     if (username.contains("@gmail.") || username.contains("@googlemail.")) {
-                        // Strip the domain from GMail accounts for canonicalization. TODO: is there an official way?
+                        // Strip the domain from GMail accounts for
+                        // canonicalization. TODO: is there an official way?
                         username = username.substring(0, username.indexOf('@'));
                     }
                     authAccounts.add(new AuthAccount(username, authToken, account));
@@ -188,7 +190,8 @@ public final class PicasaApi {
         return RESULT_ERROR;
     }
 
-    public int getAlbumPhotos(AccountManager accountManager, SyncResult syncResult, AlbumEntry album, GDataParser.EntryHandler handler) {
+    public int getAlbumPhotos(AccountManager accountManager, SyncResult syncResult, AlbumEntry album,
+            GDataParser.EntryHandler handler) {
         // Construct the query URL for user albums.
         StringBuilder builder = new StringBuilder(BASE_URL);
         builder.append("user/");
index 7ef74bc..fa61637 100644 (file)
@@ -32,7 +32,7 @@ public final class PicasaContentProvider extends TableContentProvider {
     private final AlbumEntry mAlbumInstance = new AlbumEntry();
     private SyncContext mSyncContext = null;
     private Account mActiveAccount;
-    
+
     @Override
     public void attachInfo(Context context, ProviderInfo info) {
         // Initialize the provider and set the database.
@@ -50,6 +50,7 @@ public final class PicasaContentProvider extends TableContentProvider {
     public static final class Database extends SQLiteOpenHelper {
         public static final String DATABASE_NAME = "picasa.db";
         public static final int DATABASE_VERSION = 83;
+
         public Database(Context context) {
             super(context, DATABASE_NAME, null, DATABASE_VERSION);
         }
@@ -63,7 +64,8 @@ public final class PicasaContentProvider extends TableContentProvider {
 
         @Override
         public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
-            // No new versions yet, if we are asked to upgrade we just reset everything.
+            // No new versions yet, if we are asked to upgrade we just reset
+            // everything.
             PhotoEntry.SCHEMA.dropTables(db);
             AlbumEntry.SCHEMA.dropTables(db);
             UserEntry.SCHEMA.dropTables(db);
@@ -73,7 +75,8 @@ public final class PicasaContentProvider extends TableContentProvider {
 
     @Override
     public int delete(Uri uri, String selection, String[] selectionArgs) {
-        // Ensure that the URI is well-formed. We currently do not allow WHERE clauses.
+        // Ensure that the URI is well-formed. We currently do not allow WHERE
+        // clauses.
         List<String> path = uri.getPathSegments();
         if (path.size() != 2 || !uri.getAuthority().equals(AUTHORITY) || selection != null) {
             return 0;
@@ -116,25 +119,25 @@ public final class PicasaContentProvider extends TableContentProvider {
         context.finish();
         return 0;
     }
-    
+
     public void reloadAccounts() {
-       mSyncContext.reloadAccounts();
+        mSyncContext.reloadAccounts();
     }
+
     public void setActiveSyncAccount(Account account) {
         mActiveAccount = account;
     }
-    
+
     public void syncUsers(SyncResult syncResult) {
-       syncUsers(mSyncContext, syncResult);
+        syncUsers(mSyncContext, syncResult);
     }
 
     public void syncUsersAndAlbums(final boolean syncAlbumPhotos, SyncResult syncResult) {
         SyncContext context = mSyncContext;
-        
+
         // Synchronize users authenticated on the device.
         UserEntry[] users = syncUsers(context, syncResult);
-        
+
         // Synchronize albums for each user.
         String activeUsername = null;
         if (mActiveAccount != null) {
@@ -148,7 +151,8 @@ public final class PicasaContentProvider extends TableContentProvider {
         for (int i = 0, numUsers = users.length; i != numUsers; ++i) {
             if (activeUsername != null && !context.accounts[i].user.equals(activeUsername))
                 continue;
-            if (!ContentResolver.getSyncAutomatically(context.accounts[i].account, AUTHORITY)) continue;
+            if (!ContentResolver.getSyncAutomatically(context.accounts[i].account, AUTHORITY))
+                continue;
             didSyncActiveUserName = true;
             context.api.setAuth(context.accounts[i]);
             syncUserAlbums(context, users[i], syncResult);
@@ -179,7 +183,7 @@ public final class PicasaContentProvider extends TableContentProvider {
         }
         context.finish();
     }
-    
+
     public static boolean isSyncEnabled(String accountName, SyncContext context) {
         PicasaApi.AuthAccount[] accounts = context.accounts;
         int numAccounts = accounts.length;
@@ -212,7 +216,8 @@ public final class PicasaContentProvider extends TableContentProvider {
                 UserEntry entry = new UserEntry();
                 schema.cursorToObject(cursor, entry);
 
-                // Find the corresponding account, or delete the row if it does not exist.
+                // Find the corresponding account, or delete the row if it does
+                // not exist.
                 int i;
                 for (i = 0; i != numUsers; ++i) {
                     Log.i(TAG, "Check " + accounts[i].user + " == " + entry.account);
@@ -258,7 +263,8 @@ public final class PicasaContentProvider extends TableContentProvider {
         // Build a sorted index with existing entry timestamps.
         final EntryMetadata local[] = new EntryMetadata[localCount];
         for (int i = 0; i != localCount; ++i) {
-            cursor.moveToPosition(i); // TODO: throw exception here if returns false?
+            cursor.moveToPosition(i); // TODO: throw exception here if returns
+                                      // false?
             local[i] = new EntryMetadata(cursor.getLong(0), cursor.getLong(1), 0);
         }
         cursor.close();
@@ -333,7 +339,7 @@ public final class PicasaContentProvider extends TableContentProvider {
             if (AlbumEntry.SCHEMA.queryWithId(db, cursor.getLong(0), album)) {
                 syncAlbumPhotos(context, account, album, syncResult);
             }
-            
+
             // Abort if interrupted.
             if (Thread.interrupted()) {
                 ++syncResult.stats.numIoExceptions;
@@ -344,8 +350,8 @@ public final class PicasaContentProvider extends TableContentProvider {
     }
 
     private void syncAlbumPhotos(SyncContext context, final String account, AlbumEntry album, final SyncResult syncResult) {
-       Log.i(TAG, "Syncing Picasa album: " + album.title);
-       
+        Log.i(TAG, "Syncing Picasa album: " + album.title);
+
         // Query existing album entry (id, dateEdited) sorted by ID.
         final SQLiteDatabase db = context.db;
         long albumId = album.id;
@@ -354,11 +360,13 @@ public final class PicasaContentProvider extends TableContentProvider {
                 null, "date_edited");
         int localCount = cursor.getCount();
 
-        // Build a sorted index with existing entry timestamps and display indexes.
+        // Build a sorted index with existing entry timestamps and display
+        // indexes.
         final EntryMetadata local[] = new EntryMetadata[localCount];
         final EntryMetadata key = new EntryMetadata();
         for (int i = 0; i != localCount; ++i) {
-            cursor.moveToPosition(i); // TODO: throw exception here if returns false?
+            cursor.moveToPosition(i); // TODO: throw exception here if returns
+                                      // false?
             local[i] = new EntryMetadata(cursor.getLong(0), cursor.getLong(1), cursor.getInt(2));
         }
         cursor.close();
@@ -448,7 +456,7 @@ public final class PicasaContentProvider extends TableContentProvider {
 
         // Delete all albums.
         db.delete(albumTableName, WHERE_ACCOUNT, whereArgs);
-        
+
         // Delete the user entry.
         db.delete(UserEntry.SCHEMA.getTableName(), "account=?", whereArgs);
     }
@@ -493,7 +501,8 @@ public final class PicasaContentProvider extends TableContentProvider {
         // List of all authenticated user accounts.
         public PicasaApi.AuthAccount[] accounts;
 
-        // A connection to the Picasa API for a specific user account. Initially null.
+        // A connection to the Picasa API for a specific user account. Initially
+        // null.
         public PicasaApi api = new PicasaApi();
 
         // A handle to the Picasa databse.
@@ -512,11 +521,11 @@ public final class PicasaContentProvider extends TableContentProvider {
             db = mDatabase.getWritableDatabase();
             reloadAccounts();
         }
-        
+
         public void reloadAccounts() {
-               accounts = PicasaApi.getAuthenticatedAccounts(getContext());
+            accounts = PicasaApi.getAuthenticatedAccounts(getContext());
         }
-        
+
         public void finish() {
             // Send notifications if needed and reset state.
             ContentResolver cr = getContext().getContentResolver();
index 55905fd..7aae317 100644 (file)
@@ -7,11 +7,11 @@ import android.util.Log;
 
 public class PicasaReceiver extends BroadcastReceiver {
 
-       private static final String TAG = "PicasaRecevier";
+    private static final String TAG = "PicasaRecevier";
 
-       @Override
-       public void onReceive(Context context, Intent intent) {
-           Log.e(TAG, "Accounts changed: " + intent);
-       }
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        Log.e(TAG, "Accounts changed: " + intent);
+    }
 
 }
index 05c3345..a3ac449 100644 (file)
@@ -36,16 +36,17 @@ public final class PicasaService extends Service {
     private static final AtomicBoolean sSyncPending = new AtomicBoolean(false);
 
     public static void requestSync(Context context, int type, long id) {
-       Bundle extras = new Bundle();
-       extras.putInt(KEY_TYPE, type);
-       extras.putLong(KEY_ID, id);
-       
-       Account[] accounts = PicasaApi.getAccounts(context);
-       for (Account account : accounts) {
-           ContentResolver.requestSync(account, PicasaContentProvider.AUTHORITY, extras);
-       }
-       
-       //context.startService(new Intent(context, PicasaService.class).putExtras(extras));
+        Bundle extras = new Bundle();
+        extras.putInt(KEY_TYPE, type);
+        extras.putLong(KEY_ID, id);
+
+        Account[] accounts = PicasaApi.getAccounts(context);
+        for (Account account : accounts) {
+            ContentResolver.requestSync(account, PicasaContentProvider.AUTHORITY, extras);
+        }
+
+        // context.startService(new Intent(context,
+        // PicasaService.class).putExtras(extras));
     }
 
     public PicasaService() {
@@ -53,9 +54,9 @@ public final class PicasaService extends Service {
         mSyncThread.start();
         mSyncHandler = new Handler(mSyncThread.getLooper());
         mSyncHandler.post(new Runnable() {
-               public void run() {
-                       Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
-               }
+            public void run() {
+                Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
+            }
         });
     }
 
@@ -64,45 +65,45 @@ public final class PicasaService extends Service {
         ContentProviderClient client = cr.acquireContentProviderClient(PicasaContentProvider.AUTHORITY);
         return (PicasaContentProvider) client.getLocalContentProvider();
     }
-    
+
     @Override
     public int onStartCommand(final Intent intent, int flags, final int startId) {
-               mSyncHandler.post(new Runnable() {
-                       public void run() {
-                               performSync(PicasaService.this, null, intent.getExtras(), new SyncResult());
-                               stopSelf(startId);
-                       }
-               });
-               return START_NOT_STICKY;
+        mSyncHandler.post(new Runnable() {
+            public void run() {
+                performSync(PicasaService.this, null, intent.getExtras(), new SyncResult());
+                stopSelf(startId);
+            }
+        });
+        return START_NOT_STICKY;
     }
 
     @Override
     public IBinder onBind(Intent intent) {
         return new PicasaSyncAdapter(getApplicationContext()).getSyncAdapterBinder();
     }
-    
+
     @Override
     public void onDestroy() {
-       mSyncThread.quit();
+        mSyncThread.quit();
     }
-    
+
     public static boolean performSync(Context context, Account account, Bundle extras, SyncResult syncResult) {
-       // Skip if another sync is pending.
-       if (!sSyncPending.compareAndSet(false, true)) {
-               return false;
-               }
-       
-       // Perform the sync.
-       performSyncImpl(context, account, extras, syncResult);
-       
-       // Mark sync as complete and notify all waiters.
-       sSyncPending.set(false);
-       synchronized (sSyncPending) {
-           sSyncPending.notifyAll();
-       }
-       return true;
+        // Skip if another sync is pending.
+        if (!sSyncPending.compareAndSet(false, true)) {
+            return false;
+        }
+
+        // Perform the sync.
+        performSyncImpl(context, account, extras, syncResult);
+
+        // Mark sync as complete and notify all waiters.
+        sSyncPending.set(false);
+        synchronized (sSyncPending) {
+            sSyncPending.notifyAll();
+        }
+        return true;
     }
-    
+
     public static void waitForPerformSync() {
         synchronized (sSyncPending) {
             while (sSyncPending.get()) {
@@ -116,54 +117,57 @@ public final class PicasaService extends Service {
             }
         }
     }
-    
+
     private static void performSyncImpl(Context context, Account account, Bundle extras, SyncResult syncResult) {
-       // Initialize newly added accounts to sync by default.
-       String authority = PicasaContentProvider.AUTHORITY;
-       if (extras.getBoolean(ContentResolver.SYNC_EXTRAS_INITIALIZE, false)) {
-               if (account != null && ContentResolver.getIsSyncable(account, authority) < 0) {
-                       try {
-                               ContentResolver.setIsSyncable(account, authority, getIsSyncable(context, account) ? 1 : 0);
-                       } catch (OperationCanceledException e) {
-                       } catch (IOException e) {
-                       }
-               }
-               return;
-       }
-       
-       // Do nothing if sync is disabled for this account. TODO: is this blocked in PicasaContentProvider too?
-       if (account != null && ContentResolver.getIsSyncable(account, authority) < 0) {
-           ++syncResult.stats.numSkippedEntries;
-               return;
-       }
-               
-       // Get the type of sync operation and the entity ID, if applicable. Default to synchronize all.
-       int type = extras.getInt(PicasaService.KEY_TYPE, PicasaService.TYPE_USERS_ALBUMS);
-       long id = extras.getLong(PicasaService.KEY_ID, -1);
-       
-       // Get the content provider instance and reload the list of user accounts.
-       PicasaContentProvider provider = getContentProvider(context);
-       provider.reloadAccounts();
-       
-       // Restrict sync to either a specific account or all accounts.
-       provider.setActiveSyncAccount(account);
-       
-       // Perform the desired sync operation.
-       switch (type) {
-       case PicasaService.TYPE_USERS:
-               provider.syncUsers(syncResult);
-               break;
-       case PicasaService.TYPE_USERS_ALBUMS:
-               provider.syncUsersAndAlbums(true, syncResult);
-               break;
-       case PicasaService.TYPE_ALBUM_PHOTOS:
-               provider.syncAlbumPhotos(id, true, syncResult);
-               break;
-       default:
-               throw new IllegalArgumentException();
-       }
+        // Initialize newly added accounts to sync by default.
+        String authority = PicasaContentProvider.AUTHORITY;
+        if (extras.getBoolean(ContentResolver.SYNC_EXTRAS_INITIALIZE, false)) {
+            if (account != null && ContentResolver.getIsSyncable(account, authority) < 0) {
+                try {
+                    ContentResolver.setIsSyncable(account, authority, getIsSyncable(context, account) ? 1 : 0);
+                } catch (OperationCanceledException e) {
+                } catch (IOException e) {
+                }
+            }
+            return;
+        }
+
+        // Do nothing if sync is disabled for this account. TODO: is this
+        // blocked in PicasaContentProvider too?
+        if (account != null && ContentResolver.getIsSyncable(account, authority) < 0) {
+            ++syncResult.stats.numSkippedEntries;
+            return;
+        }
+
+        // Get the type of sync operation and the entity ID, if applicable.
+        // Default to synchronize all.
+        int type = extras.getInt(PicasaService.KEY_TYPE, PicasaService.TYPE_USERS_ALBUMS);
+        long id = extras.getLong(PicasaService.KEY_ID, -1);
+
+        // Get the content provider instance and reload the list of user
+        // accounts.
+        PicasaContentProvider provider = getContentProvider(context);
+        provider.reloadAccounts();
+
+        // Restrict sync to either a specific account or all accounts.
+        provider.setActiveSyncAccount(account);
+
+        // Perform the desired sync operation.
+        switch (type) {
+        case PicasaService.TYPE_USERS:
+            provider.syncUsers(syncResult);
+            break;
+        case PicasaService.TYPE_USERS_ALBUMS:
+            provider.syncUsersAndAlbums(true, syncResult);
+            break;
+        case PicasaService.TYPE_ALBUM_PHOTOS:
+            provider.syncAlbumPhotos(id, true, syncResult);
+            break;
+        default:
+            throw new IllegalArgumentException();
+        }
     }
-    
+
     private static boolean getIsSyncable(Context context, Account account) throws IOException, OperationCanceledException {
         try {
             Account[] picasaAccounts = AccountManager.get(context).getAccountsByTypeAndFeatures(ACCOUNT_TYPE,
index 8bdfaad..f507e6a 100644 (file)
@@ -27,10 +27,10 @@ public class PicasaSyncAdapter extends AbstractThreadedSyncAdapter {
     }
 
     public static final class AccountChangeReceiver extends BroadcastReceiver {
-               @Override
-               public void onReceive(Context context, Intent intent) {
-                       // TODO: Need to get account list change broadcast.
-               }
-       
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            // TODO: Need to get account list change broadcast.
+        }
+
     }
 }
index 32b4b8c..bacd83a 100644 (file)
@@ -22,26 +22,28 @@ public class TableContentProvider extends ContentProvider {
     public void setDatabase(SQLiteOpenHelper database) {
         mDatabase = database;
     }
-    
+
     public void addMapping(String authority, String path, String mimeSubtype, EntrySchema table) {
         // Add the table URI mapping.
         ArrayList<Mapping> mappings = mMappings;
         UriMatcher matcher = mUriMatcher;
         matcher.addURI(authority, path, mappings.size());
         mappings.add(new Mapping(table, mimeSubtype, false));
-        
+
         // Add the row URI mapping.
         matcher.addURI(authority, path + "/#", mappings.size());
         mappings.add(new Mapping(table, mimeSubtype, true));
     }
-    
+
     @Override
     public boolean onCreate() {
-        // The database may not be loaded yet since attachInfo() has not been called, so we cannot
-        // check that the database opened successfully. Returns true optimistically.
+        // The database may not be loaded yet since attachInfo() has not been
+        // called, so we cannot
+        // check that the database opened successfully. Returns true
+        // optimistically.
         return true;
     }
-    
+
     @Override
     public String getType(Uri uri) {
         // Resolve the URI.
@@ -57,29 +59,29 @@ public class TableContentProvider extends ContentProvider {
     }
 
     @Override
-    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
-                        String sortOrder) {
+    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
         // Resolve the URI.
         int match = mUriMatcher.match(uri);
         if (match == UriMatcher.NO_MATCH) {
             throw new IllegalArgumentException("Invalid URI: " + uri);
         }
-        
+
         // Add the ID predicate if needed.
         Mapping mapping = mMappings.get(match);
         if (mapping.hasId) {
             selection = whereWithId(uri, selection);
         }
-        
-        //System.out.println("QUERY " + uri + " WHERE (" + selection + ")");
+
+        // System.out.println("QUERY " + uri + " WHERE (" + selection + ")");
 
         // Run the query.
         String tableName = mapping.table.getTableName();
-        Cursor cursor = mDatabase.getReadableDatabase().query(tableName, projection, selection, selectionArgs, null, null, sortOrder);
+        Cursor cursor = mDatabase.getReadableDatabase().query(tableName, projection, selection, selectionArgs, null, null,
+                sortOrder);
         cursor.setNotificationUri(getContext().getContentResolver(), uri);
         return cursor;
     }
-    
+
     @Override
     public Uri insert(Uri uri, ContentValues values) {
         // Resolve the URI.
@@ -89,7 +91,8 @@ public class TableContentProvider extends ContentProvider {
             throw new IllegalArgumentException("Invalid URI: " + uri);
         }
 
-        // Insert into the database, notify observers, and return the qualified URI.
+        // Insert into the database, notify observers, and return the qualified
+        // URI.
         String tableName = mapping.table.getTableName();
         long rowId = mDatabase.getWritableDatabase().insert(tableName, NULL_COLUMN_HACK, values);
         if (rowId > 0) {
@@ -99,7 +102,7 @@ public class TableContentProvider extends ContentProvider {
             throw new SQLException("Failed to insert row at: " + uri);
         }
     }
-    
+
     @Override
     public int bulkInsert(Uri uri, ContentValues[] values) {
         // Resolve the URI.
@@ -127,7 +130,7 @@ public class TableContentProvider extends ContentProvider {
         notifyChange(uri);
         return numInserted;
     }
-    
+
     @Override
     public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
         // Resolve the URI.
@@ -135,13 +138,13 @@ public class TableContentProvider extends ContentProvider {
         if (match == UriMatcher.NO_MATCH) {
             throw new IllegalArgumentException("Invalid URI: " + uri);
         }
-        
+
         // Add the ID predicate if needed.
         Mapping mapping = mMappings.get(match);
         if (mapping.hasId) {
             selection = whereWithId(uri, selection);
         }
-        
+
         // Update the item(s) and broadcast a change notification.
         SQLiteDatabase db = mDatabase.getWritableDatabase();
         String tableName = mapping.table.getTableName();
@@ -157,7 +160,7 @@ public class TableContentProvider extends ContentProvider {
         if (match == UriMatcher.NO_MATCH) {
             throw new IllegalArgumentException("Invalid URI: " + uri);
         }
-        
+
         // Add the ID predicate if needed.
         Mapping mapping = mMappings.get(match);
         if (mapping.hasId) {
@@ -171,7 +174,7 @@ public class TableContentProvider extends ContentProvider {
         notifyChange(uri);
         return count;
     }
-    
+
     private final String whereWithId(Uri uri, String selection) {
         String id = uri.getPathSegments().get(1);
         StringBuilder where = new StringBuilder("_id=");
@@ -183,11 +186,11 @@ public class TableContentProvider extends ContentProvider {
         }
         return where.toString();
     }
-    
+
     private final void notifyChange(Uri uri) {
         getContext().getContentResolver().notifyChange(uri, null);
     }
-    
+
     private static final class Mapping {
         public EntrySchema table;
         public String mimeSubtype;
index ac528dc..d25d908 100644 (file)
@@ -6,7 +6,7 @@ public final class UserEntry extends Entry {
 
     @Column("account")
     public String account;
-    
+
     @Column("albums_etag")
     public String albumsEtag;
 }
index e566e68..13b6640 100644 (file)
@@ -12,7 +12,7 @@ import android.content.Context;
 import android.graphics.Bitmap;
 
 public class RandomDataSource implements Slideshow.DataSource {
-    
+
     public Bitmap getBitmapForIndex(Context context, int currentSlideshowCounter) {
         ImageList list = CacheService.getImageList(context);
         // Once we have the id and the thumbid, we can return a bitmap
index 376a739..19dc2d8 100644 (file)
@@ -57,7 +57,7 @@ public class Slideshow extends SurfaceView implements SurfaceHolder.Callback {
     private Rect mQueuedRect;
     private RectF mQueuedFrameRect;
     private static final Vector3f sQueuedGrow = new Vector3f();
-    
+
     private long mPrevTime;
     private long mTimeElapsed;
 
@@ -80,7 +80,8 @@ public class Slideshow extends SurfaceView implements SurfaceHolder.Callback {
     }
 
     public void surfaceCreated(SurfaceHolder holder) {
-        // We may need to make calls to super once this is a subclass of WallpaperService.
+        // We may need to make calls to super once this is a subclass of
+        // WallpaperService.
         mHandler.post(mDrawFrame);
     }
 
@@ -106,33 +107,34 @@ public class Slideshow extends SurfaceView implements SurfaceHolder.Callback {
                 // We draw the source bitmap
                 if (mBitmap != null) {
                     if (mTimeElapsed > SLIDESHOW_DURATION) {
-                        float alpha = ((float)(mTimeElapsed - SLIDESHOW_DURATION)) / 2000.0f;
+                        float alpha = ((float) (mTimeElapsed - SLIDESHOW_DURATION)) / 2000.0f;
                         paint.setColorFilter(null);
                         if (alpha < 1.0f) {
-                            //int val = (int)(255 * (1.0f - alpha));
-                            //int srcColor = Color.argb(val, 0, 0, 0);
-                            //PorterDuffColorFilter colorFilter = new PorterDuffColorFilter(srcColor, Mode.SRC_IN);
-                            //paint.setColorFilter(null);
+                            // int val = (int)(255 * (1.0f - alpha));
+                            // int srcColor = Color.argb(val, 0, 0, 0);
+                            // PorterDuffColorFilter colorFilter = new
+                            // PorterDuffColorFilter(srcColor, Mode.SRC_IN);
+                            // paint.setColorFilter(null);
                         }
                         c.drawBitmap(mBitmap, mRect, mFrameRect, paint);
                         if (alpha < 1.0f) {
-                            int val = (int)(255 * alpha);
+                            int val = (int) (255 * alpha);
                             int srcColor = Color.argb(val, 0, 0, 0);
                             PorterDuffColorFilter colorFilter = new PorterDuffColorFilter(srcColor, Mode.DST_IN);
                             paint.setColorFilter(colorFilter);
                         }
-                        
+
                         c.drawBitmap(mQueuedBitmap, mQueuedRect, mQueuedFrameRect, paint);
                         performUpdate(mQueuedFrameRect, sQueuedGrow, delta);
                         if (alpha >= 1.0f) {
                             // We switch the image.
                             mRect = mQueuedRect;
                             mBitmap = mQueuedBitmap;
-                            mFrameRect =  mQueuedFrameRect;
+                            mFrameRect = mQueuedFrameRect;
                             sGrow.set(sQueuedGrow);
                             mQueuedBitmap = null;
                             mQueuedRect = null;
-                            mQueuedFrameRect =  null;
+                            mQueuedFrameRect = null;
                             mTimeElapsed = 0;
                         }
                     } else {
@@ -154,12 +156,12 @@ public class Slideshow extends SurfaceView implements SurfaceHolder.Callback {
     }
 
     private void performUpdate(RectF rect, Vector3f grow, long delta) {
-        float timeElapsed = ((float)(delta)) / 1000.0f;
+        float timeElapsed = ((float) (delta)) / 1000.0f;
         float amountToGrowX = timeElapsed * (rect.width() / 15.0f);
         float amountToGrowY = amountToGrowX * (rect.height() / rect.width());
         rect.top -= amountToGrowY * grow.x;
         rect.left -= amountToGrowX * grow.y;
-        
+
         rect.bottom += amountToGrowY * (1 - grow.x);
         rect.right += amountToGrowX * (1 - grow.y);
     }
@@ -172,7 +174,7 @@ public class Slideshow extends SurfaceView implements SurfaceHolder.Callback {
                 mFrameRect = new RectF();
                 mFrameRect.right = viewWidth;
                 mFrameRect.bottom = viewHeight;
-                sGrow.set((float)Math.random(), (float)Math.random(), 0);
+                sGrow.set((float) Math.random(), (float) Math.random(), 0);
             }
         }
         if (mQueuedBitmap == null) {
@@ -185,23 +187,23 @@ public class Slideshow extends SurfaceView implements SurfaceHolder.Callback {
                 mQueuedFrameRect = new RectF();
                 mQueuedFrameRect.right = viewWidth;
                 mQueuedFrameRect.bottom = viewHeight;
-                sQueuedGrow.set((float)Math.random(), (float)Math.random(), 0);
+                sQueuedGrow.set((float) Math.random(), (float) Math.random(), 0);
             }
         }
     }
 
     private Rect getRectToFitBitmap(int bitmapWidth, int bitmapHeight, int viewWidth, int viewHeight) {
         Rect rect = new Rect();
-        float viewAspect = (float)viewHeight / viewWidth;
+        float viewAspect = (float) viewHeight / viewWidth;
         float newWidth = bitmapWidth * viewAspect;
         if (bitmapHeight < newWidth) {
             // Vertically constrained.
             newWidth = bitmapHeight / viewAspect;
-            rect.set((int)(bitmapWidth/2 - newWidth/2), 0, (int)(bitmapWidth/2 + newWidth/2), bitmapHeight);
+            rect.set((int) (bitmapWidth / 2 - newWidth / 2), 0, (int) (bitmapWidth / 2 + newWidth / 2), bitmapHeight);
         } else {
             // Horizontally constrained
             float newHeight = bitmapWidth * viewAspect;
-            rect.set(0, (int)(bitmapHeight/2 - newHeight/2), bitmapWidth, (int)(bitmapHeight/2 + newHeight/2));
+            rect.set(0, (int) (bitmapHeight / 2 - newHeight / 2), bitmapWidth, (int) (bitmapHeight / 2 + newHeight / 2));
         }
         return rect;
     }