summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/com/android/camera/CameraSettings.java4
-rw-r--r--src/com/android/camera/PanoramaModule.java3
-rw-r--r--src/com/android/camera/PhotoModule.java3
-rw-r--r--src/com/android/camera/PhotoUI.java3
-rw-r--r--src/com/android/camera/VideoModule.java3
-rw-r--r--src/com/android/camera/ui/CameraSwitcher.java4
-rw-r--r--src/com/android/gallery3d/app/PhotoPage.java14
-rw-r--r--src/com/android/gallery3d/app/StateManager.java12
-rw-r--r--src/com/android/gallery3d/filtershow/FilterShowActivity.java1
-rw-r--r--src/com/android/gallery3d/filtershow/ImageStateAdapter.java1
-rw-r--r--src/com/android/gallery3d/filtershow/cache/FilteringPipeline.java31
-rw-r--r--src/com/android/gallery3d/filtershow/filters/BaseFiltersManager.java10
-rw-r--r--src/com/android/gallery3d/filtershow/filters/ImageFilterRS.java150
-rw-r--r--src/com/android/gallery3d/filtershow/imageshow/ImageShow.java3
-rw-r--r--src/com/android/gallery3d/filtershow/presets/ImagePreset.java1
-rw-r--r--src/com/android/gallery3d/ui/PhotoView.java9
-rw-r--r--src/com/android/photos/AlbumSetFragment.java126
-rw-r--r--src/com/android/photos/GalleryActivity.java145
-rw-r--r--src/com/android/photos/MultiChoiceManager.java190
-rw-r--r--src/com/android/photos/PhotoSetFragment.java139
-rw-r--r--src/com/android/photos/SelectionManager.java54
-rw-r--r--src/com/android/photos/adapters/AlbumSetCursorAdapter.java89
-rw-r--r--src/com/android/photos/adapters/PhotoThumbnailAdapter.java4
-rw-r--r--src/com/android/photos/data/AlbumSetLoader.java7
-rw-r--r--src/com/android/photos/data/PhotoSetLoader.java17
-rw-r--r--src/com/android/photos/shims/LoaderCompatShim.java5
-rw-r--r--src/com/android/photos/shims/MediaItemsLoader.java37
-rw-r--r--src/com/android/photos/shims/MediaSetLoader.java48
28 files changed, 793 insertions, 320 deletions
diff --git a/src/com/android/camera/CameraSettings.java b/src/com/android/camera/CameraSettings.java
index 31d31e128..64f3681de 100644
--- a/src/com/android/camera/CameraSettings.java
+++ b/src/com/android/camera/CameraSettings.java
@@ -235,8 +235,8 @@ public class CameraSettings {
private void buildExposureCompensation(
PreferenceGroup group, IconListPreference exposure) {
- int max = mParameters.getMaxExposureCompensation();
- int min = mParameters.getMinExposureCompensation();
+ int max = Math.min(3, mParameters.getMaxExposureCompensation());
+ int min = Math.max(-3, mParameters.getMinExposureCompensation());
if (max == 0 && min == 0) {
removePreference(group, exposure.getKey());
return;
diff --git a/src/com/android/camera/PanoramaModule.java b/src/com/android/camera/PanoramaModule.java
index 2703c3596..623d96dc6 100644
--- a/src/com/android/camera/PanoramaModule.java
+++ b/src/com/android/camera/PanoramaModule.java
@@ -66,6 +66,7 @@ import com.android.gallery3d.exif.ExifOutputStream;
import com.android.gallery3d.exif.ExifReader;
import com.android.gallery3d.exif.ExifTag;
import com.android.gallery3d.ui.GLRootView;
+import com.android.gallery3d.util.UsageStatistics;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
@@ -1101,6 +1102,8 @@ public class PanoramaModule implements CameraModule,
// Dismiss open menu if exists.
PopupManager.getInstance(mActivity).notifyShowPopup(null);
mRootView.requestLayout();
+ UsageStatistics.onContentViewChanged(
+ UsageStatistics.COMPONENT_CAMERA, "PanoramaModule");
}
/**
diff --git a/src/com/android/camera/PhotoModule.java b/src/com/android/camera/PhotoModule.java
index 4c627c92c..037e0fdb3 100644
--- a/src/com/android/camera/PhotoModule.java
+++ b/src/com/android/camera/PhotoModule.java
@@ -58,6 +58,7 @@ import com.android.gallery3d.R;
import com.android.gallery3d.common.ApiHelper;
import com.android.gallery3d.filtershow.CropExtras;
import com.android.gallery3d.filtershow.FilterShowActivity;
+import com.android.gallery3d.util.UsageStatistics;
import java.io.File;
import java.io.FileNotFoundException;
@@ -1255,6 +1256,8 @@ public class PhotoModule
// Dismiss open menu if exists.
PopupManager.getInstance(mActivity).notifyShowPopup(null);
+ UsageStatistics.onContentViewChanged(
+ UsageStatistics.COMPONENT_CAMERA, "PhotoModule");
}
void waitCameraStartUpThread() {
diff --git a/src/com/android/camera/PhotoUI.java b/src/com/android/camera/PhotoUI.java
index 995996480..18d0d3e86 100644
--- a/src/com/android/camera/PhotoUI.java
+++ b/src/com/android/camera/PhotoUI.java
@@ -676,7 +676,8 @@ public class PhotoUI implements PieListener,
@Override
public void clearFocus() {
- getFocusIndicator().clear();
+ FocusIndicator indicator = getFocusIndicator();
+ if (indicator != null) indicator.clear();
}
@Override
diff --git a/src/com/android/camera/VideoModule.java b/src/com/android/camera/VideoModule.java
index a168372d1..4ae46a897 100644
--- a/src/com/android/camera/VideoModule.java
+++ b/src/com/android/camera/VideoModule.java
@@ -77,6 +77,7 @@ import com.android.camera.ui.ZoomRenderer;
import com.android.gallery3d.R;
import com.android.gallery3d.common.ApiHelper;
import com.android.gallery3d.util.AccessibilityUtils;
+import com.android.gallery3d.util.UsageStatistics;
import java.io.File;
import java.io.IOException;
@@ -866,6 +867,8 @@ public class VideoModule implements CameraModule,
PopupManager.getInstance(mActivity).notifyShowPopup(null);
mVideoNamer = new VideoNamer();
+ UsageStatistics.onContentViewChanged(
+ UsageStatistics.COMPONENT_CAMERA, "VideoModule");
}
private void setDisplayOrientation() {
diff --git a/src/com/android/camera/ui/CameraSwitcher.java b/src/com/android/camera/ui/CameraSwitcher.java
index ce4f85003..e9551ada2 100644
--- a/src/com/android/camera/ui/CameraSwitcher.java
+++ b/src/com/android/camera/ui/CameraSwitcher.java
@@ -38,6 +38,7 @@ import android.widget.LinearLayout;
import com.android.camera.Util;
import com.android.gallery3d.R;
import com.android.gallery3d.common.ApiHelper;
+import com.android.gallery3d.util.UsageStatistics;
public class CameraSwitcher extends RotateImageView
implements OnClickListener, OnTouchListener {
@@ -106,6 +107,9 @@ public class CameraSwitcher extends RotateImageView
private void onCameraSelected(int ix) {
hidePopup();
if ((ix != mCurrentIndex) && (mListener != null)) {
+ UsageStatistics.onEvent("CameraModeSwitch", null, null);
+ UsageStatistics.setPendingTransitionCause(
+ UsageStatistics.TRANSITION_MENU_TAP);
setCurrentIndex(ix);
mListener.onCameraSelected(mModuleIds[ix]);
}
diff --git a/src/com/android/gallery3d/app/PhotoPage.java b/src/com/android/gallery3d/app/PhotoPage.java
index 44ff62feb..fe6840ecb 100644
--- a/src/com/android/gallery3d/app/PhotoPage.java
+++ b/src/com/android/gallery3d/app/PhotoPage.java
@@ -69,6 +69,7 @@ import com.android.gallery3d.ui.PhotoView;
import com.android.gallery3d.ui.SelectionManager;
import com.android.gallery3d.ui.SynchronizedHandler;
import com.android.gallery3d.util.GalleryUtils;
+import com.android.gallery3d.util.UsageStatistics;
public abstract class PhotoPage extends ActivityState implements
PhotoView.Listener, AppBridge.Server,
@@ -513,6 +514,10 @@ public abstract class PhotoPage extends ActivityState implements
if (oldIndex == 0 && mCurrentIndex > 0
&& !mPhotoView.getFilmMode()) {
mPhotoView.setFilmMode(true);
+ if (mAppBridge != null) {
+ UsageStatistics.onEvent("CameraToFilmstrip",
+ UsageStatistics.TRANSITION_SWIPE, null);
+ }
} else if (oldIndex == 2 && mCurrentIndex == 1) {
mCameraSwitchCutoff = SystemClock.uptimeMillis() +
CAMERA_SWITCH_CUTOFF_THRESHOLD_MS;
@@ -1338,8 +1343,17 @@ public abstract class PhotoPage extends ActivityState implements
}
if (enabled) {
mHandler.removeMessages(MSG_HIDE_BARS);
+ UsageStatistics.onContentViewChanged(
+ UsageStatistics.COMPONENT_GALLERY, "FilmstripPage");
} else {
refreshHidingMessage();
+ if (mAppBridge == null || mCurrentIndex > 0) {
+ UsageStatistics.onContentViewChanged(
+ UsageStatistics.COMPONENT_GALLERY, "SinglePhotoPage");
+ } else {
+ UsageStatistics.onContentViewChanged(
+ UsageStatistics.COMPONENT_CAMERA, "Unknown"); // TODO
+ }
}
}
diff --git a/src/com/android/gallery3d/app/StateManager.java b/src/com/android/gallery3d/app/StateManager.java
index b4b5d4b05..c0c84c950 100644
--- a/src/com/android/gallery3d/app/StateManager.java
+++ b/src/com/android/gallery3d/app/StateManager.java
@@ -24,6 +24,7 @@ import android.os.Parcelable;
import android.view.Menu;
import android.view.MenuItem;
+import com.android.camera.CameraActivity;
import com.android.gallery3d.anim.StateTransitionAnimation;
import com.android.gallery3d.common.Utils;
import com.android.gallery3d.util.UsageStatistics;
@@ -63,9 +64,14 @@ public class StateManager {
StateTransitionAnimation.Transition.Incoming);
if (mIsResumed) top.onPause();
}
- UsageStatistics.onContentViewChanged(
- UsageStatistics.COMPONENT_GALLERY,
- klass.getSimpleName());
+ // Ignore the filmstrip used for the root of the camera app
+ boolean ignoreHit = (mActivity instanceof CameraActivity)
+ && mStack.isEmpty();
+ if (!ignoreHit) {
+ UsageStatistics.onContentViewChanged(
+ UsageStatistics.COMPONENT_GALLERY,
+ klass.getSimpleName());
+ }
state.initialize(mActivity, data);
mStack.push(new StateEntry(data, state));
diff --git a/src/com/android/gallery3d/filtershow/FilterShowActivity.java b/src/com/android/gallery3d/filtershow/FilterShowActivity.java
index 93bb02483..37b2cd9da 100644
--- a/src/com/android/gallery3d/filtershow/FilterShowActivity.java
+++ b/src/com/android/gallery3d/filtershow/FilterShowActivity.java
@@ -574,6 +574,7 @@ public class FilterShowActivity extends Activity implements OnItemClickListener,
// TODO: Using singletons is a bad design choice for many of these
// due static reference leaks and in general. Please refactor.
MasterImage.reset();
+ ImageFilterRS.destroyRenderScriptContext();
FilteringPipeline.reset();
ImageFilter.resetStatics();
FiltersManager.reset();
diff --git a/src/com/android/gallery3d/filtershow/ImageStateAdapter.java b/src/com/android/gallery3d/filtershow/ImageStateAdapter.java
index 62633e26e..1cd5f86c8 100644
--- a/src/com/android/gallery3d/filtershow/ImageStateAdapter.java
+++ b/src/com/android/gallery3d/filtershow/ImageStateAdapter.java
@@ -45,6 +45,7 @@ public class ImageStateAdapter extends ArrayAdapter<FilterRepresentation> {
view = (MovableLinearLayout) inflater.inflate(R.layout.filtershow_imagestate_row, null);
}
FilterRepresentation filter = getItem(position);
+ filter.synchronizeRepresentation();
view.setFilterRepresentation(filter);
ImageView markView = (ImageView) view.findViewById(R.id.selectedMark);
if (filter == MasterImage.getImage().getCurrentFilterRepresentation()) {
diff --git a/src/com/android/gallery3d/filtershow/cache/FilteringPipeline.java b/src/com/android/gallery3d/filtershow/cache/FilteringPipeline.java
index 39b39695c..d7e9a62a7 100644
--- a/src/com/android/gallery3d/filtershow/cache/FilteringPipeline.java
+++ b/src/com/android/gallery3d/filtershow/cache/FilteringPipeline.java
@@ -30,7 +30,7 @@ import com.android.gallery3d.filtershow.presets.ImagePreset;
public class FilteringPipeline implements Handler.Callback {
- private static FilteringPipeline sPipeline;
+ private static volatile FilteringPipeline sPipeline = null;
private static final String LOGTAG = "FilteringPipeline";
private ImagePreset mPreviousGeometryPreset = null;
private ImagePreset mPreviousFiltersPreset = null;
@@ -49,6 +49,8 @@ public class FilteringPipeline implements Handler.Callback {
private final static int COMPUTE_RENDERING_REQUEST = 3;
private final static int COMPUTE_PARTIAL_RENDERING_REQUEST = 4;
+ private boolean mHasUnhandledPreviewRequest = false;
+
private Handler mProcessingHandler = null;
private final Handler mUIHandler = new Handler() {
@Override
@@ -58,6 +60,9 @@ public class FilteringPipeline implements Handler.Callback {
TripleBufferBitmap buffer = MasterImage.getImage().getDoubleBuffer();
buffer.swapConsumer();
MasterImage.getImage().notifyObservers();
+ if (mHasUnhandledPreviewRequest) {
+ updatePreviewBuffer();
+ }
break;
}
case NEW_RENDERING_REQUEST: {
@@ -115,7 +120,7 @@ public class FilteringPipeline implements Handler.Callback {
mProcessingHandler = new Handler(mHandlerThread.getLooper(), this);
}
- public static FilteringPipeline getPipeline() {
+ public synchronized static FilteringPipeline getPipeline() {
if (sPipeline == null) {
sPipeline = new FilteringPipeline();
}
@@ -168,8 +173,6 @@ public class FilteringPipeline implements Handler.Callback {
Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SCRIPT);
mPreviousGeometry = new GeometryMetadata(geometry);
-
- FiltersManager.getManager().resetBitmapsRS();
return true;
}
@@ -194,6 +197,7 @@ public class FilteringPipeline implements Handler.Callback {
if (mOriginalAllocation == null) {
return;
}
+ mHasUnhandledPreviewRequest = true;
if (mProcessingHandler.hasMessages(COMPUTE_PRESET)) {
return;
}
@@ -205,6 +209,7 @@ public class FilteringPipeline implements Handler.Callback {
}
Message msg = mProcessingHandler.obtainMessage(COMPUTE_PRESET);
msg.obj = MasterImage.getImage().getPreset();
+ mHasUnhandledPreviewRequest = false;
mProcessingHandler.sendMessageAtFrontOfQueue(msg);
}
@@ -252,17 +257,19 @@ public class FilteringPipeline implements Handler.Callback {
preset.setupEnvironment();
if (request.getType() == RenderingRequest.PARTIAL_RENDERING) {
- bitmap = MasterImage.getImage().getImageLoader().getScaleOneImageForPreset(null, preset,
+ ImageLoader loader = MasterImage.getImage().getImageLoader();
+ if (loader == null) {
+ Log.w(LOGTAG, "loader not yet setup, cannot handle: " + getType(request));
+ return;
+ }
+ bitmap = loader.getScaleOneImageForPreset(null, preset,
request.getBounds(), request.getDestination(), false);
if (bitmap == null) {
+ Log.w(LOGTAG, "could not get bitmap for: " + getType(request));
return;
}
}
- if (request.getType() == RenderingRequest.FILTERS_RENDERING) {
- FiltersManager.getManager().resetBitmapsRS();
- }
-
if (request.getType() != RenderingRequest.ICON_RENDERING
&& request.getType() != RenderingRequest.PARTIAL_RENDERING) {
updateOriginalAllocation(preset);
@@ -289,9 +296,6 @@ public class FilteringPipeline implements Handler.Callback {
FiltersManager.getManager().freeFilterResources(preset);
}
- if (request.getType() == RenderingRequest.FILTERS_RENDERING) {
- FiltersManager.getManager().resetBitmapsRS();
- }
}
private void compute(TripleBufferBitmap buffer, ImagePreset preset, int type) {
@@ -349,7 +353,8 @@ public class FilteringPipeline implements Handler.Callback {
return mPreviewScaleFactor;
}
- public static void reset() {
+ public static synchronized void reset() {
+ sPipeline.mHandlerThread.quit();
sPipeline = null;
}
}
diff --git a/src/com/android/gallery3d/filtershow/filters/BaseFiltersManager.java b/src/com/android/gallery3d/filtershow/filters/BaseFiltersManager.java
index 215d5d438..f6c3bdd89 100644
--- a/src/com/android/gallery3d/filtershow/filters/BaseFiltersManager.java
+++ b/src/com/android/gallery3d/filtershow/filters/BaseFiltersManager.java
@@ -61,16 +61,6 @@ public abstract class BaseFiltersManager {
return null;
}
- public void resetBitmapsRS() {
- for (Class c : mFilters.keySet()) {
- ImageFilter filter = mFilters.get(c);
- if (filter instanceof ImageFilterRS) {
- ImageFilterRS filterRS = (ImageFilterRS) filter;
- filterRS.resetBitmap();
- }
- }
- }
-
public void freeFilterResources(ImagePreset preset) {
if (preset == null) {
return;
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterRS.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterRS.java
index a06c2e022..595aa9b30 100644
--- a/src/com/android/gallery3d/filtershow/filters/ImageFilterRS.java
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterRS.java
@@ -18,74 +18,79 @@ package com.android.gallery3d.filtershow.filters;
import android.app.Activity;
import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
import android.support.v8.renderscript.*;
import android.util.Log;
+import android.content.res.Resources;
import com.android.gallery3d.R;
public abstract class ImageFilterRS extends ImageFilter {
- private final String LOGTAG = "ImageFilterRS";
+ private static final String LOGTAG = "ImageFilterRS";
- private static RenderScript mRS = null;
- protected static Allocation mInPixelsAllocation;
- protected static Allocation mOutPixelsAllocation;
- private static android.content.res.Resources mResources = null;
- private static Bitmap sOldBitmap = null;
- private Bitmap mOldBitmap = null;
+ protected static volatile Allocation mInPixelsAllocation;
+ protected static volatile Allocation mOutPixelsAllocation;
- private boolean mResourcesLoaded = false;
+ private static volatile RenderScript sRS = null;
+ private static volatile int sWidth = 0;
+ private static volatile int sHeight = 0;
- private final Bitmap.Config mBitmapConfig = Bitmap.Config.ARGB_8888;
+ private static volatile Resources sResources = null;
+ private boolean mResourcesLoaded = false;
- public void resetBitmap() {
- mOldBitmap = null;
- }
+ private static final Bitmap.Config BITMAP_CONFIG = Bitmap.Config.ARGB_8888;
+ // This must be used inside block synchronized on ImageFilterRS class object
public void prepare(Bitmap bitmap, float scaleFactor, int quality) {
- if (sOldBitmap == null
- || (bitmap.getWidth() != sOldBitmap.getWidth())
- || (bitmap.getHeight() != sOldBitmap.getHeight())) {
- if (mInPixelsAllocation != null) {
- mInPixelsAllocation.destroy();
- mInPixelsAllocation = null;
- }
- if (mOutPixelsAllocation != null) {
- mOutPixelsAllocation.destroy();
- mOutPixelsAllocation = null;
+ if (mOutPixelsAllocation == null || mInPixelsAllocation == null ||
+ bitmap.getWidth() != sWidth || bitmap.getHeight() != sHeight) {
+ destroyPixelAllocations();
+ Bitmap bitmapBuffer = bitmap;
+ if (bitmap.getConfig() == null || bitmap.getConfig() != BITMAP_CONFIG) {
+ bitmapBuffer = bitmap.copy(BITMAP_CONFIG, true);
}
- Bitmap bitmapBuffer = bitmap.copy(mBitmapConfig, true);
- mOutPixelsAllocation = Allocation.createFromBitmap(mRS, bitmapBuffer,
+ mOutPixelsAllocation = Allocation.createFromBitmap(sRS, bitmapBuffer,
Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SCRIPT);
- mInPixelsAllocation = Allocation.createTyped(mRS,
+ mInPixelsAllocation = Allocation.createTyped(sRS,
mOutPixelsAllocation.getType());
- sOldBitmap = bitmap;
}
mInPixelsAllocation.copyFrom(bitmap);
- if (mOldBitmap != sOldBitmap || !isResourcesLoaded()) {
+ if (bitmap.getWidth() != sWidth
+ || bitmap.getHeight() != sHeight || !isResourcesLoaded()) {
freeResources();
- createFilter(mResources, scaleFactor, quality);
- mOldBitmap = sOldBitmap;
+ createFilter(sResources, scaleFactor, quality);
+ sWidth = bitmap.getWidth();
+ sHeight = bitmap.getHeight();
setResourcesLoaded(true);
}
}
+ // This must be used inside block synchronized on ImageFilterRS class object
abstract public void createFilter(android.content.res.Resources res,
float scaleFactor, int quality);
+ // This must be used inside block synchronized on ImageFilterRS class object
abstract public void runFilter();
+ // This must be used inside block synchronized on ImageFilterRS class object
public void update(Bitmap bitmap) {
mOutPixelsAllocation.copyTo(bitmap);
}
@Override
public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) {
- if (bitmap == null) {
+ if (bitmap == null || bitmap.getWidth() == 0 || bitmap.getHeight() == 0) {
return bitmap;
}
try {
- prepare(bitmap, scaleFactor, quality);
- runFilter();
- update(bitmap);
+ synchronized(ImageFilterRS.class) {
+ if (sRS == null) {
+ Log.w(LOGTAG, "Cannot apply before calling setRenderScriptContext");
+ return bitmap;
+ }
+ prepare(bitmap, scaleFactor, quality);
+ runFilter();
+ update(bitmap);
+ }
} catch (android.renderscript.RSIllegalArgumentException e) {
Log.e(LOGTAG, "Illegal argument? " + e);
} catch (android.renderscript.RSRuntimeException e) {
@@ -99,15 +104,21 @@ public abstract class ImageFilterRS extends ImageFilter {
return bitmap;
}
- public static RenderScript getRenderScriptContext() {
- return mRS;
+ public static synchronized RenderScript getRenderScriptContext() {
+ return sRS;
}
- public static void setRenderScriptContext(Activity context) {
- if (mRS == null) {
- mRS = RenderScript.create(context);
+ public static synchronized void setRenderScriptContext(Activity context) {
+ if( sRS != null) {
+ Log.w(LOGTAG, "A prior RS context exists when calling setRenderScriptContext");
+ destroyRenderScriptContext();
}
- mResources = context.getResources();
+ sRS = RenderScript.create(context);
+ sResources = context.getResources();
+ destroyPixelAllocations();
+ }
+
+ private static synchronized void destroyPixelAllocations() {
if (mInPixelsAllocation != null) {
mInPixelsAllocation.destroy();
mInPixelsAllocation = null;
@@ -116,32 +127,75 @@ public abstract class ImageFilterRS extends ImageFilter {
mOutPixelsAllocation.destroy();
mOutPixelsAllocation = null;
}
- sOldBitmap = null;
+ sWidth = 0;
+ sHeight = 0;
+ }
+
+ public static synchronized void destroyRenderScriptContext() {
+ destroyPixelAllocations();
+ sRS.destroy();
+ sRS = null;
+ sResources = null;
}
- public Allocation convertRGBAtoA(Bitmap bitmap) {
- Type.Builder tb_a8 = new Type.Builder(mRS, Element.U8(mRS));
- ScriptC_grey greyConvert = new ScriptC_grey(mRS, mResources, R.raw.grey);
+ private static synchronized Allocation convertBitmap(Bitmap bitmap) {
+ return Allocation.createFromBitmap(sRS, bitmap,
+ Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SCRIPT);
+ }
- Allocation bitmapTemp = Allocation.createFromBitmap(mRS, bitmap);
+ private static synchronized Allocation convertRGBAtoA(Bitmap bitmap) {
+ Type.Builder tb_a8 = new Type.Builder(sRS, Element.U8(sRS));
+ ScriptC_grey greyConvert = new ScriptC_grey(sRS,
+ sRS.getApplicationContext().getResources(), R.raw.grey);
- if (bitmapTemp.getType().getElement().isCompatible(Element.U8(mRS))) {
+ Allocation bitmapTemp = convertBitmap(bitmap);
+ if (bitmapTemp.getType().getElement().isCompatible(Element.U8(sRS))) {
return bitmapTemp;
}
tb_a8.setX(bitmapTemp.getType().getX());
tb_a8.setY(bitmapTemp.getType().getY());
- Allocation bitmapAlloc = Allocation.createTyped(mRS, tb_a8.create());
+ Allocation bitmapAlloc = Allocation.createTyped(sRS, tb_a8.create());
greyConvert.forEach_RGBAtoA(bitmapTemp, bitmapAlloc);
return bitmapAlloc;
}
- public boolean isResourcesLoaded() {
+ public Allocation loadResourceAlpha(int resource) {
+ Resources res = null;
+ synchronized(ImageFilterRS.class) {
+ res = sRS.getApplicationContext().getResources();
+ }
+ final BitmapFactory.Options options = new BitmapFactory.Options();
+ options.inPreferredConfig = Bitmap.Config.ALPHA_8;
+ Bitmap bitmap = BitmapFactory.decodeResource(
+ res,
+ resource, options);
+ Allocation ret = convertRGBAtoA(bitmap);
+ bitmap.recycle();
+ return ret;
+ }
+
+ public Allocation loadResource(int resource) {
+ Resources res = null;
+ synchronized(ImageFilterRS.class) {
+ res = sRS.getApplicationContext().getResources();
+ }
+ final BitmapFactory.Options options = new BitmapFactory.Options();
+ options.inPreferredConfig = Bitmap.Config.ARGB_8888;
+ Bitmap bitmap = BitmapFactory.decodeResource(
+ res,
+ resource, options);
+ Allocation ret = convertBitmap(bitmap);
+ bitmap.recycle();
+ return ret;
+ }
+
+ private boolean isResourcesLoaded() {
return mResourcesLoaded;
}
- public void setResourcesLoaded(boolean resourcesLoaded) {
+ private void setResourcesLoaded(boolean resourcesLoaded) {
mResourcesLoaded = resourcesLoaded;
}
diff --git a/src/com/android/gallery3d/filtershow/imageshow/ImageShow.java b/src/com/android/gallery3d/filtershow/imageshow/ImageShow.java
index 38d415633..0b2f96abb 100644
--- a/src/com/android/gallery3d/filtershow/imageshow/ImageShow.java
+++ b/src/com/android/gallery3d/filtershow/imageshow/ImageShow.java
@@ -156,9 +156,6 @@ public class ImageShow extends View implements OnGestureListener,
}
public void onNewValue(int parameter) {
- if (getImagePreset() != null) {
- getImagePreset().fillImageStateAdapter(MasterImage.getImage().getState());
- }
if (getPanelController() != null) {
getPanelController().onNewValue(parameter);
}
diff --git a/src/com/android/gallery3d/filtershow/presets/ImagePreset.java b/src/com/android/gallery3d/filtershow/presets/ImagePreset.java
index e27afe580..b75ac64fb 100644
--- a/src/com/android/gallery3d/filtershow/presets/ImagePreset.java
+++ b/src/com/android/gallery3d/filtershow/presets/ImagePreset.java
@@ -147,6 +147,7 @@ public class ImagePreset {
}
}
MasterImage.getImage().invalidatePreview();
+ fillImageStateAdapter(MasterImage.getImage().getState());
}
public void setDoApplyGeometry(boolean value) {
diff --git a/src/com/android/gallery3d/ui/PhotoView.java b/src/com/android/gallery3d/ui/PhotoView.java
index 40e01ab07..5c8ac1c3e 100644
--- a/src/com/android/gallery3d/ui/PhotoView.java
+++ b/src/com/android/gallery3d/ui/PhotoView.java
@@ -42,6 +42,7 @@ import com.android.gallery3d.glrenderer.StringTexture;
import com.android.gallery3d.glrenderer.Texture;
import com.android.gallery3d.util.GalleryUtils;
import com.android.gallery3d.util.RangeArray;
+import com.android.gallery3d.util.UsageStatistics;
public class PhotoView extends GLView {
@SuppressWarnings("unused")
@@ -1180,8 +1181,16 @@ public class PhotoView extends GLView {
// Removing the touch down flag allows snapback to happen
// for film mode change.
mHolding &= ~HOLD_TOUCH_DOWN;
+ if (mFilmMode) {
+ UsageStatistics.setPendingTransitionCause(
+ UsageStatistics.TRANSITION_PINCH_OUT);
+ } else {
+ UsageStatistics.setPendingTransitionCause(
+ UsageStatistics.TRANSITION_PINCH_IN);
+ }
setFilmMode(!mFilmMode);
+
// We need to call onScaleEnd() before setting mModeChanged
// to true.
onScaleEnd();
diff --git a/src/com/android/photos/AlbumSetFragment.java b/src/com/android/photos/AlbumSetFragment.java
index 0d4fcc023..d0bc81fd6 100644
--- a/src/com/android/photos/AlbumSetFragment.java
+++ b/src/com/android/photos/AlbumSetFragment.java
@@ -21,42 +21,54 @@ import android.app.LoaderManager.LoaderCallbacks;
import android.content.Context;
import android.content.Loader;
import android.database.Cursor;
-import android.graphics.drawable.Drawable;
+import android.net.Uri;
import android.os.Bundle;
-import android.text.format.DateFormat;
+import android.provider.MediaStore.Files.FileColumns;
+import android.util.SparseBooleanArray;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
-import android.widget.CursorAdapter;
import android.widget.GridView;
-import android.widget.ImageView;
-import android.widget.ProgressBar;
-import android.widget.TextView;
import android.widget.Toast;
import com.android.gallery3d.R;
+import com.android.photos.adapters.AlbumSetCursorAdapter;
import com.android.photos.data.AlbumSetLoader;
import com.android.photos.shims.LoaderCompatShim;
import com.android.photos.shims.MediaSetLoader;
-import java.util.Date;
+import java.util.ArrayList;
public class AlbumSetFragment extends Fragment implements OnItemClickListener,
- LoaderCallbacks<Cursor> {
+ LoaderCallbacks<Cursor>, MultiChoiceManager.Delegate, SelectionManager.Client {
private GridView mAlbumSetView;
private View mEmptyView;
private AlbumSetCursorAdapter mAdapter;
+ private LoaderCompatShim<Cursor> mLoaderCompatShim;
+ private MultiChoiceManager mMultiChoiceManager;
+ private SelectionManager mSelectionManager;
private static final int LOADER_ALBUMSET = 1;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- mAdapter = new AlbumSetCursorAdapter(getActivity());
+ Context context = getActivity();
+ mAdapter = new AlbumSetCursorAdapter(context);
+ mMultiChoiceManager = new MultiChoiceManager(context, this);
+ mMultiChoiceManager.setSelectionManager(mSelectionManager);
+ }
+
+ @Override
+ public void setSelectionManager(SelectionManager manager) {
+ mSelectionManager = manager;
+ if (mMultiChoiceManager != null) {
+ mMultiChoiceManager.setSelectionManager(manager);
+ }
}
@Override
@@ -67,6 +79,8 @@ public class AlbumSetFragment extends Fragment implements OnItemClickListener,
mEmptyView = root.findViewById(android.R.id.empty);
mEmptyView.setVisibility(View.GONE);
mAlbumSetView.setAdapter(mAdapter);
+ mAlbumSetView.setChoiceMode(GridView.CHOICE_MODE_MULTIPLE_MODAL);
+ mAlbumSetView.setMultiChoiceModeListener(mMultiChoiceManager);
mAlbumSetView.setOnItemClickListener(this);
getLoaderManager().initLoader(LOADER_ALBUMSET, null, this);
updateEmptyStatus();
@@ -78,6 +92,7 @@ public class AlbumSetFragment extends Fragment implements OnItemClickListener,
// TODO: Switch to AlbumSetLoader
MediaSetLoader loader = new MediaSetLoader(getActivity());
mAdapter.setDrawableFactory(loader);
+ mLoaderCompatShim = loader;
return loader;
}
@@ -100,63 +115,54 @@ public class AlbumSetFragment extends Fragment implements OnItemClickListener,
@Override
public void onItemClick(AdapterView<?> av, View v, int pos, long id) {
- Cursor c = (Cursor) av.getItemAtPosition(pos);
- int albumId = c.getInt(AlbumSetLoader.INDEX_ID);
- // TODO launch an activity showing the photos in the album
- Toast.makeText(v.getContext(), "Clicked " + albumId, Toast.LENGTH_SHORT).show();
+ if (mLoaderCompatShim == null) {
+ // Not fully initialized yet, discard
+ return;
+ }
+ Cursor item = (Cursor) mAdapter.getItem(pos);
+ Toast.makeText(v.getContext(),
+ "Tapped " + item.getInt(AlbumSetLoader.INDEX_ID),
+ Toast.LENGTH_SHORT).show();
}
- private static class AlbumSetCursorAdapter extends CursorAdapter {
+ @Override
+ public int getItemMediaType(Object item) {
+ return FileColumns.MEDIA_TYPE_NONE;
+ }
- private LoaderCompatShim<Cursor> mDrawableFactory;
+ @Override
+ public int getItemSupportedOperations(Object item) {
+ return ((Cursor) item).getInt(AlbumSetLoader.INDEX_SUPPORTED_OPERATIONS);
+ }
- public void setDrawableFactory(LoaderCompatShim<Cursor> factory) {
- mDrawableFactory = factory;
- }
- private Date mDate = new Date(); // Used for converting timestamps for display
+ @Override
+ public Object getItemAtPosition(int position) {
+ return mAdapter.getItem(position);
+ }
- public AlbumSetCursorAdapter(Context context) {
- super(context, null, false);
- }
+ @Override
+ public ArrayList<Uri> getSubItemUrisForItem(Object item) {
+ return mLoaderCompatShim.urisForSubItems((Cursor) item);
+ }
- @Override
- public void bindView(View v, Context context, Cursor cursor) {
- TextView titleTextView = (TextView) v.findViewById(
- R.id.album_set_item_title);
- titleTextView.setText(cursor.getString(AlbumSetLoader.INDEX_TITLE));
-
- TextView dateTextView = (TextView) v.findViewById(
- R.id.album_set_item_date);
- long timestamp = cursor.getLong(AlbumSetLoader.INDEX_TIMESTAMP);
- if (timestamp > 0) {
- mDate.setTime(timestamp);
- dateTextView.setText(DateFormat.getMediumDateFormat(context).format(mDate));
- } else {
- dateTextView.setText(null);
- }
-
- ProgressBar uploadProgressBar = (ProgressBar) v.findViewById(
- R.id.album_set_item_upload_progress);
- if (cursor.getInt(AlbumSetLoader.INDEX_COUNT_PENDING_UPLOAD) > 0) {
- uploadProgressBar.setVisibility(View.VISIBLE);
- uploadProgressBar.setProgress(50);
- } else {
- uploadProgressBar.setVisibility(View.INVISIBLE);
- }
-
- ImageView thumbImageView = (ImageView) v.findViewById(
- R.id.album_set_item_image);
- Drawable recycle = thumbImageView.getDrawable();
- Drawable drawable = mDrawableFactory.drawableForItem(cursor, recycle);
- if (recycle != drawable) {
- thumbImageView.setImageDrawable(drawable);
- }
- }
+ @Override
+ public Object getPathForItemAtPosition(int position) {
+ return mLoaderCompatShim.getPathForItem((Cursor) mAdapter.getItem(position));
+ }
- @Override
- public View newView(Context context, Cursor cursor, ViewGroup parent) {
- return LayoutInflater.from(context).inflate(
- R.layout.album_set_item, parent, false);
- }
+ @Override
+ public void deleteItemWithPath(Object itemPath) {
+ mLoaderCompatShim.deleteItemWithPath(itemPath);
}
+
+ @Override
+ public SparseBooleanArray getSelectedItemPositions() {
+ return mAlbumSetView.getCheckedItemPositions();
+ }
+
+ @Override
+ public int getSelectedItemCount() {
+ return mAlbumSetView.getCheckedItemCount();
+ }
+
}
diff --git a/src/com/android/photos/GalleryActivity.java b/src/com/android/photos/GalleryActivity.java
index 2335658d1..ddf04e365 100644
--- a/src/com/android/photos/GalleryActivity.java
+++ b/src/com/android/photos/GalleryActivity.java
@@ -21,49 +21,53 @@ import android.app.ActionBar.Tab;
import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentTransaction;
+import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
+import android.support.v13.app.FragmentPagerAdapter;
+import android.support.v4.view.ViewPager;
import android.view.Menu;
import android.view.MenuItem;
import com.android.camera.CameraActivity;
import com.android.gallery3d.R;
+import java.util.ArrayList;
+
public class GalleryActivity extends Activity {
- private final String FTAG_PHOTOSET = "PhotoSet";
- private final String FTAG_ALBUMSET = "AlbumSet";
private SelectionManager mSelectionManager;
+ private ViewPager mViewPager;
+ private TabsAdapter mTabsAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ mSelectionManager = new SelectionManager(this);
+ mViewPager = new ViewPager(this);
+ mViewPager.setId(R.id.viewpager);
+ setContentView(mViewPager);
- setupActionBar();
- }
-
- protected SelectionManager getSelectionManager() {
- if (mSelectionManager == null) {
- mSelectionManager = new SelectionManager(this);
- }
- return mSelectionManager;
- }
-
- private void setupActionBar() {
ActionBar ab = getActionBar();
ab.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
ab.setDisplayShowHomeEnabled(false);
ab.setDisplayShowTitleEnabled(false);
- Tab tab = ab.newTab();
- tab.setText(R.string.tab_photos);
- tab.setTabListener(new TabListener<PhotoSetFragment>(this,
- FTAG_PHOTOSET, PhotoSetFragment.class));
- ab.addTab(tab, true);
- tab = ab.newTab();
- tab.setText(R.string.tab_albums);
- tab.setTabListener(new TabListener<AlbumSetFragment>(this,
- FTAG_ALBUMSET, AlbumSetFragment.class));
- ab.addTab(tab);
+
+ mTabsAdapter = new TabsAdapter(this, mViewPager);
+ mTabsAdapter.addTab(ab.newTab().setText(R.string.tab_photos),
+ PhotoSetFragment.class, null);
+ mTabsAdapter.addTab(ab.newTab().setText(R.string.tab_albums),
+ AlbumSetFragment.class, null);
+
+ if (savedInstanceState != null) {
+ ab.setSelectedNavigationItem(savedInstanceState.getInt("tab", 0));
+ }
+ }
+
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ outState.putInt("tab", getActionBar().getSelectedNavigationIndex());
}
@Override
@@ -85,49 +89,88 @@ public class GalleryActivity extends Activity {
}
}
- private static class TabListener<T extends Fragment> implements ActionBar.TabListener {
- private Fragment mFragment;
- private final Activity mActivity;
- private final String mTag;
- private final Class<T> mClass;
-
- /** Constructor used each time a new tab is created.
- * @param activity The host Activity, used to instantiate the fragment
- * @param tag The identifier tag for the fragment
- * @param clz The fragment's Class, used to instantiate the fragment
- */
- public TabListener(Activity activity, String tag, Class<T> clz) {
+ public static class TabsAdapter extends FragmentPagerAdapter implements
+ ActionBar.TabListener, ViewPager.OnPageChangeListener {
+
+ private final GalleryActivity mActivity;
+ private final ActionBar mActionBar;
+ private final ViewPager mViewPager;
+ private final ArrayList<TabInfo> mTabs = new ArrayList<TabInfo>();
+
+ static final class TabInfo {
+
+ private final Class<?> clss;
+ private final Bundle args;
+
+ TabInfo(Class<?> _class, Bundle _args) {
+ clss = _class;
+ args = _args;
+ }
+ }
+
+ public TabsAdapter(GalleryActivity activity, ViewPager pager) {
+ super(activity.getFragmentManager());
mActivity = activity;
- mTag = tag;
- mClass = clz;
+ mActionBar = activity.getActionBar();
+ mViewPager = pager;
+ mViewPager.setAdapter(this);
+ mViewPager.setOnPageChangeListener(this);
+ }
+
+ public void addTab(ActionBar.Tab tab, Class<?> clss, Bundle args) {
+ TabInfo info = new TabInfo(clss, args);
+ tab.setTag(info);
+ tab.setTabListener(this);
+ mTabs.add(info);
+ mActionBar.addTab(tab);
+ notifyDataSetChanged();
+ }
+
+ @Override
+ public int getCount() {
+ return mTabs.size();
+ }
+
+ @Override
+ public Fragment getItem(int position) {
+ TabInfo info = mTabs.get(position);
+ Fragment item = Fragment.instantiate(mActivity, info.clss.getName(),
+ info.args);
+ ((SelectionManager.Client) item).setSelectionManager(
+ mActivity.mSelectionManager);
+ return item;
}
- /* The following are each of the ActionBar.TabListener callbacks */
+ @Override
+ public void onPageScrolled(int position, float positionOffset,
+ int positionOffsetPixels) {
+ }
+
+ @Override
+ public void onPageSelected(int position) {
+ mActionBar.setSelectedNavigationItem(position);
+ }
+
+ @Override
+ public void onPageScrollStateChanged(int state) {
+ }
@Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
- // Check if the fragment is already initialized
- if (mFragment == null) {
- // If not, instantiate and add it to the activity
- mFragment = Fragment.instantiate(mActivity, mClass.getName());
- ft.add(android.R.id.content, mFragment, mTag);
- } else {
- // If it exists, simply attach it in order to show it
- ft.attach(mFragment);
+ Object tag = tab.getTag();
+ for (int i = 0; i < mTabs.size(); i++) {
+ if (mTabs.get(i) == tag) {
+ mViewPager.setCurrentItem(i);
+ }
}
}
@Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
- if (mFragment != null) {
- // Detach the fragment, because another one is being attached
- ft.detach(mFragment);
- }
}
@Override
public void onTabReselected(Tab tab, FragmentTransaction ft) {
- // User selected the already selected tab. Usually do nothing.
}
}
}
diff --git a/src/com/android/photos/MultiChoiceManager.java b/src/com/android/photos/MultiChoiceManager.java
new file mode 100644
index 000000000..e00c842fe
--- /dev/null
+++ b/src/com/android/photos/MultiChoiceManager.java
@@ -0,0 +1,190 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.photos;
+
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.AsyncTask;
+import android.util.SparseBooleanArray;
+import android.view.ActionMode;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.widget.AbsListView.MultiChoiceModeListener;
+import android.widget.ShareActionProvider;
+import android.widget.ShareActionProvider.OnShareTargetSelectedListener;
+
+import com.android.gallery3d.R;
+import com.android.gallery3d.data.MediaObject;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class MultiChoiceManager implements MultiChoiceModeListener,
+ OnShareTargetSelectedListener, SelectionManager.SelectedUriSource {
+
+ public interface Delegate {
+ public SparseBooleanArray getSelectedItemPositions();
+ public int getSelectedItemCount();
+ public int getItemMediaType(Object item);
+ public int getItemSupportedOperations(Object item);
+ public ArrayList<Uri> getSubItemUrisForItem(Object item);
+ public Object getItemAtPosition(int position);
+ public Object getPathForItemAtPosition(int position);
+ public void deleteItemWithPath(Object itemPath);
+ }
+
+ private SelectionManager mSelectionManager;
+ private ShareActionProvider mShareActionProvider;
+ private ActionMode mActionMode;
+ private int numSubItemsCollected = 0;
+ private Context mContext;
+ private Delegate mDelegate;
+
+ private ArrayList<Uri> mSelectedUrisArray = new ArrayList<Uri>();
+
+ public MultiChoiceManager(Context context, Delegate delegate) {
+ mContext = context;
+ mDelegate = delegate;
+ }
+
+ public void setSelectionManager(SelectionManager selectionManager) {
+ mSelectionManager = selectionManager;
+ }
+
+ @Override
+ public ArrayList<Uri> getSelectedShareableUris() {
+ return mSelectedUrisArray;
+ }
+
+ private void updateSelectedTitle(ActionMode mode) {
+ int count = mDelegate.getSelectedItemCount();
+ mode.setTitle(mContext.getResources().getQuantityString(
+ R.plurals.number_of_items_selected, count, count));
+ }
+
+ @Override
+ public void onItemCheckedStateChanged(ActionMode mode, int position, long id,
+ boolean checked) {
+ updateSelectedTitle(mode);
+ Object item = mDelegate.getItemAtPosition(position);
+
+ ArrayList<Uri> subItems = mDelegate.getSubItemUrisForItem(item);
+ if (checked) {
+ mSelectedUrisArray.addAll(subItems);
+ numSubItemsCollected += subItems.size();
+ } else {
+ mSelectedUrisArray.removeAll(subItems);
+ numSubItemsCollected -= subItems.size();
+ }
+
+ mSelectionManager.onItemSelectedStateChanged(mShareActionProvider,
+ mDelegate.getItemMediaType(item),
+ mDelegate.getItemSupportedOperations(item),
+ checked);
+ updateActionItemVisibilities(mode.getMenu(),
+ mSelectionManager.getSupportedOperations());
+ }
+
+ private void updateActionItemVisibilities(Menu menu, int supportedOperations) {
+ MenuItem shareItem = menu.findItem(R.id.menu_share);
+ MenuItem deleteItem = menu.findItem(R.id.menu_delete);
+ shareItem.setVisible((supportedOperations & MediaObject.SUPPORT_SHARE) > 0);
+ deleteItem.setVisible((supportedOperations & MediaObject.SUPPORT_DELETE) > 0);
+ }
+
+ @Override
+ public boolean onCreateActionMode(ActionMode mode, Menu menu) {
+ mSelectionManager.setSelectedUriSource(this);
+ mActionMode = mode;
+ MenuInflater inflater = mode.getMenuInflater();
+ inflater.inflate(R.menu.gallery_multiselect, menu);
+ MenuItem menuItem = menu.findItem(R.id.menu_share);
+ mShareActionProvider = (ShareActionProvider) menuItem.getActionProvider();
+ mShareActionProvider.setOnShareTargetSelectedListener(this);
+ updateSelectedTitle(mode);
+ return true;
+ }
+
+ @Override
+ public void onDestroyActionMode(ActionMode mode) {
+ // onDestroyActionMode gets called when the share target was selected,
+ // but apparently before the ArrayList is serialized in the intent
+ // so we can't clear the old one here.
+ mSelectedUrisArray = new ArrayList<Uri>();
+ mSelectionManager.onClearSelection();
+ mSelectionManager.setSelectedUriSource(null);
+ mShareActionProvider = null;
+ mActionMode = null;
+ }
+
+ @Override
+ public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
+ updateSelectedTitle(mode);
+ return false;
+ }
+
+ @Override
+ public boolean onShareTargetSelected(ShareActionProvider provider, Intent intent) {
+ mActionMode.finish();
+ return false;
+ }
+
+ private static class BulkDeleteTask extends AsyncTask<Void, Void, Void> {
+ private Delegate mDelegate;
+ private List<Object> mPaths;
+
+ public BulkDeleteTask(Delegate delegate, List<Object> paths) {
+ mDelegate = delegate;
+ mPaths = paths;
+ }
+
+ @Override
+ protected Void doInBackground(Void... ignored) {
+ for (Object path : mPaths) {
+ mDelegate.deleteItemWithPath(path);
+ }
+ return null;
+ }
+ }
+
+ @Override
+ public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
+ switch (item.getItemId()) {
+ case R.id.menu_delete:
+ BulkDeleteTask deleteTask = new BulkDeleteTask(mDelegate,
+ getPathsForSelectedItems());
+ deleteTask.execute();
+ mode.finish();
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ private List<Object> getPathsForSelectedItems() {
+ List<Object> paths = new ArrayList<Object>();
+ SparseBooleanArray selected = mDelegate.getSelectedItemPositions();
+ for (int i = 0; i < selected.size(); i++) {
+ if (selected.valueAt(i)) {
+ paths.add(mDelegate.getPathForItemAtPosition(i));
+ }
+ }
+ return paths;
+ }
+}
diff --git a/src/com/android/photos/PhotoSetFragment.java b/src/com/android/photos/PhotoSetFragment.java
index 25d80360d..b485cd051 100644
--- a/src/com/android/photos/PhotoSetFragment.java
+++ b/src/com/android/photos/PhotoSetFragment.java
@@ -18,41 +18,31 @@ package com.android.photos;
import android.app.Fragment;
import android.app.LoaderManager.LoaderCallbacks;
+import android.content.Context;
import android.content.Intent;
import android.content.Loader;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.util.SparseBooleanArray;
-import android.view.ActionMode;
import android.view.LayoutInflater;
-import android.view.Menu;
-import android.view.MenuInflater;
-import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
-import android.widget.AbsListView.MultiChoiceModeListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.GridView;
-import android.widget.ShareActionProvider;
-import android.widget.ShareActionProvider.OnShareTargetSelectedListener;
import com.android.gallery3d.R;
import com.android.gallery3d.app.Gallery;
-import com.android.gallery3d.data.MediaItem;
import com.android.photos.adapters.PhotoThumbnailAdapter;
import com.android.photos.data.PhotoSetLoader;
import com.android.photos.shims.LoaderCompatShim;
import com.android.photos.shims.MediaItemsLoader;
import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.Set;
-public class PhotoSetFragment extends Fragment implements LoaderCallbacks<Cursor>,
- OnItemClickListener, SelectionManager.SelectedUriSource, MultiChoiceModeListener,
- OnShareTargetSelectedListener {
+public class PhotoSetFragment extends Fragment implements OnItemClickListener,
+ LoaderCallbacks<Cursor>, MultiChoiceManager.Delegate, SelectionManager.Client {
private static final int LOADER_PHOTOSET = 1;
@@ -62,14 +52,24 @@ public class PhotoSetFragment extends Fragment implements LoaderCallbacks<Cursor
private boolean mInitialLoadComplete = false;
private LoaderCompatShim<Cursor> mLoaderCompatShim;
private PhotoThumbnailAdapter mAdapter;
+ private MultiChoiceManager mMultiChoiceManager;
private SelectionManager mSelectionManager;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- GalleryActivity activity = (GalleryActivity) getActivity();
- mSelectionManager = activity.getSelectionManager();
- mAdapter = new PhotoThumbnailAdapter(activity);
+ Context context = getActivity();
+ mAdapter = new PhotoThumbnailAdapter(context);
+ mMultiChoiceManager = new MultiChoiceManager(context, this);
+ mMultiChoiceManager.setSelectionManager(mSelectionManager);
+ }
+
+ @Override
+ public void setSelectionManager(SelectionManager manager) {
+ mSelectionManager = manager;
+ if (mMultiChoiceManager != null) {
+ mMultiChoiceManager.setSelectionManager(manager);
+ }
}
@Override
@@ -84,7 +84,7 @@ public class PhotoSetFragment extends Fragment implements LoaderCallbacks<Cursor
mEmptyView.setVisibility(View.GONE);
mPhotoSetView.setAdapter(mAdapter);
mPhotoSetView.setChoiceMode(GridView.CHOICE_MODE_MULTIPLE_MODAL);
- mPhotoSetView.setMultiChoiceModeListener(this);
+ mPhotoSetView.setMultiChoiceModeListener(mMultiChoiceManager);
getLoaderManager().initLoader(LOADER_PHOTOSET, null, this);
updateEmptyStatus();
return root;
@@ -129,112 +129,51 @@ public class PhotoSetFragment extends Fragment implements LoaderCallbacks<Cursor
updateEmptyStatus();
}
- private Set<Uri> mSelectedUris = new HashSet<Uri>();
- private ArrayList<Uri> mSelectedUrisArray = new ArrayList<Uri>();
-
@Override
- public ArrayList<Uri> getSelectedShareableUris() {
- mSelectedUrisArray.clear();
- mSelectedUrisArray.addAll(mSelectedUris);
- return mSelectedUrisArray;
- }
-
- public ArrayList<Uri> getSelectedShareableUrisUncached() {
- mSelectedUrisArray.clear();
- SparseBooleanArray selected = mPhotoSetView.getCheckedItemPositions();
-
- for (int i = 0; i < selected.size(); i++) {
- if (selected.valueAt(i)) {
- Cursor item = mAdapter.getItem(selected.keyAt(i));
- int supported = item.getInt(PhotoSetLoader.INDEX_SUPPORTED_OPERATIONS);
- if ((supported & MediaItem.SUPPORT_SHARE) > 0) {
- mSelectedUrisArray.add(mLoaderCompatShim.uriForItem(item));
- }
- }
- }
-
- return mSelectedUrisArray;
+ public void onLoaderReset(Loader<Cursor> loader) {
}
@Override
- public void onLoaderReset(Loader<Cursor> loader) {
+ public int getItemMediaType(Object item) {
+ return ((Cursor) item).getInt(PhotoSetLoader.INDEX_MEDIA_TYPE);
}
-
- private ShareActionProvider mShareActionProvider;
- private ActionMode mActionMode;
- private boolean mSharePending = false;
-
- private void updateSelectedTitle(ActionMode mode) {
- int count = mPhotoSetView.getCheckedItemCount();
- mode.setTitle(getResources().getQuantityString(
- R.plurals.number_of_items_selected, count, count));
+ @Override
+ public int getItemSupportedOperations(Object item) {
+ return ((Cursor) item).getInt(PhotoSetLoader.INDEX_SUPPORTED_OPERATIONS);
}
@Override
- public void onItemCheckedStateChanged(ActionMode mode, int position, long id,
- boolean checked) {
- updateSelectedTitle(mode);
- Cursor item = mAdapter.getItem(position);
-
- if (checked) {
- mSelectedUris.add(mLoaderCompatShim.uriForItem(item));
- } else {
- mSelectedUris.remove(mLoaderCompatShim.uriForItem(item));
- }
-
- mSelectionManager.onItemSelectedStateChanged(mShareActionProvider,
- item.getInt(PhotoSetLoader.INDEX_MEDIA_TYPE),
- item.getInt(PhotoSetLoader.INDEX_SUPPORTED_OPERATIONS),
- checked);
+ public Object getItemAtPosition(int position) {
+ return mAdapter.getItem(position);
}
+ private ArrayList<Uri> mSubItemUriTemp = new ArrayList<Uri>(1);
@Override
- public boolean onCreateActionMode(ActionMode mode, Menu menu) {
- mSelectionManager.setSelectedUriSource(PhotoSetFragment.this);
- mActionMode = mode;
- MenuInflater inflater = mode.getMenuInflater();
- inflater.inflate(R.menu.gallery_multiselect, menu);
- MenuItem menuItem = menu.findItem(R.id.menu_share);
- mShareActionProvider = (ShareActionProvider) menuItem.getActionProvider();
- mShareActionProvider.setOnShareTargetSelectedListener(this);
- updateSelectedTitle(mode);
- return true;
+ public ArrayList<Uri> getSubItemUrisForItem(Object item) {
+ mSubItemUriTemp.clear();
+ mSubItemUriTemp.add(mLoaderCompatShim.uriForItem((Cursor) item));
+ return mSubItemUriTemp;
}
+
@Override
- public void onDestroyActionMode(ActionMode mode) {
- mSelectedUris.clear();
- if (mSharePending) {
- // onDestroyActionMode gets called when the share target was selected,
- // but apparently before the ArrayList is serialized in the intent
- // so we can't clear the old one here.
- mSelectedUrisArray = new ArrayList<Uri>();
- mSharePending = false;
- } else {
- mSelectedUrisArray.clear();
- }
- mSelectionManager.onClearSelection();
- mSelectionManager.setSelectedUriSource(null);
- mShareActionProvider = null;
- mActionMode = null;
+ public Object getPathForItemAtPosition(int position) {
+ return mLoaderCompatShim.getPathForItem(mAdapter.getItem(position));
}
@Override
- public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
- updateSelectedTitle(mode);
- return false;
+ public void deleteItemWithPath(Object itemPath) {
+ mLoaderCompatShim.deleteItemWithPath(itemPath);
}
@Override
- public boolean onShareTargetSelected(ShareActionProvider provider, Intent intent) {
- mSharePending = true;
- mActionMode.finish();
- return false;
+ public SparseBooleanArray getSelectedItemPositions() {
+ return mPhotoSetView.getCheckedItemPositions();
}
@Override
- public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
- return false;
+ public int getSelectedItemCount() {
+ return mPhotoSetView.getCheckedItemCount();
}
}
diff --git a/src/com/android/photos/SelectionManager.java b/src/com/android/photos/SelectionManager.java
index 979dcc7da..ce340c731 100644
--- a/src/com/android/photos/SelectionManager.java
+++ b/src/com/android/photos/SelectionManager.java
@@ -26,7 +26,7 @@ import android.provider.MediaStore.Files.FileColumns;
import android.widget.ShareActionProvider;
import com.android.gallery3d.common.ApiHelper;
-import com.android.gallery3d.data.MediaItem;
+import com.android.gallery3d.data.MediaObject;
import com.android.gallery3d.util.GalleryUtils;
import java.util.ArrayList;
@@ -41,6 +41,10 @@ public class SelectionManager {
public ArrayList<Uri> getSelectedShareableUris();
}
+ public interface Client {
+ public void setSelectionManager(SelectionManager manager);
+ }
+
public SelectionManager(Activity activity) {
mActivity = activity;
if (ApiHelper.AT_LEAST_16) {
@@ -76,10 +80,10 @@ public class SelectionManager {
mSelectedTotalCount += increment;
mCachedShareableUris = null;
- if ((itemSupportedOperations & MediaItem.SUPPORT_DELETE) > 0) {
+ if ((itemSupportedOperations & MediaObject.SUPPORT_DELETE) > 0) {
mSelectedDeletableCount += increment;
}
- if ((itemSupportedOperations & MediaItem.SUPPORT_SHARE) > 0) {
+ if ((itemSupportedOperations & MediaObject.SUPPORT_SHARE) > 0) {
mSelectedShareableCount += increment;
if (itemType == FileColumns.MEDIA_TYPE_IMAGE) {
mSelectedShareableImageCount += increment;
@@ -93,24 +97,42 @@ public class SelectionManager {
mShareIntent.setAction(null).setType(null);
} else if (mSelectedShareableCount >= 1) {
mCachedShareableUris = mUriSource.getSelectedShareableUris();
- if (mSelectedShareableImageCount == mSelectedShareableCount) {
- mShareIntent.setType(GalleryUtils.MIME_TYPE_IMAGE);
- } else if (mSelectedShareableVideoCount == mSelectedShareableCount) {
- mShareIntent.setType(GalleryUtils.MIME_TYPE_VIDEO);
- } else {
- mShareIntent.setType(GalleryUtils.MIME_TYPE_ALL);
- }
- if (mSelectedShareableCount == 1) {
- mShareIntent.setAction(Intent.ACTION_SEND);
- mShareIntent.putExtra(Intent.EXTRA_STREAM, mCachedShareableUris.get(0));
+ if (mCachedShareableUris.size() == 0) {
+ mShareIntent.setAction(null).setType(null);
} else {
- mShareIntent.setAction(Intent.ACTION_SEND_MULTIPLE);
- mShareIntent.putExtra(Intent.EXTRA_STREAM, mCachedShareableUris);
+ if (mSelectedShareableImageCount == mSelectedShareableCount) {
+ mShareIntent.setType(GalleryUtils.MIME_TYPE_IMAGE);
+ } else if (mSelectedShareableVideoCount == mSelectedShareableCount) {
+ mShareIntent.setType(GalleryUtils.MIME_TYPE_VIDEO);
+ } else {
+ mShareIntent.setType(GalleryUtils.MIME_TYPE_ALL);
+ }
+ if (mCachedShareableUris.size() == 1) {
+ mShareIntent.setAction(Intent.ACTION_SEND);
+ mShareIntent.putExtra(Intent.EXTRA_STREAM, mCachedShareableUris.get(0));
+ } else {
+ mShareIntent.setAction(Intent.ACTION_SEND_MULTIPLE);
+ mShareIntent.putExtra(Intent.EXTRA_STREAM, mCachedShareableUris);
+ }
}
}
share.setShareIntent(mShareIntent);
- // TODO update deletability, editability, etc.
+ // TODO update editability, etc.
+ }
+
+ public int getSupportedOperations() {
+ if (mSelectedTotalCount == 0) {
+ return 0;
+ }
+ int supported = 0;
+ if (mSelectedDeletableCount == mSelectedTotalCount) {
+ supported |= MediaObject.SUPPORT_DELETE;
+ }
+ if (mSelectedShareableCount > 0) {
+ supported |= MediaObject.SUPPORT_SHARE;
+ }
+ return supported;
}
public void onClearSelection() {
diff --git a/src/com/android/photos/adapters/AlbumSetCursorAdapter.java b/src/com/android/photos/adapters/AlbumSetCursorAdapter.java
new file mode 100644
index 000000000..c387f8f47
--- /dev/null
+++ b/src/com/android/photos/adapters/AlbumSetCursorAdapter.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.photos.adapters;
+
+import android.content.Context;
+import android.database.Cursor;
+import android.graphics.drawable.Drawable;
+import android.text.format.DateFormat;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.CursorAdapter;
+import android.widget.ImageView;
+import android.widget.ProgressBar;
+import android.widget.TextView;
+
+import com.android.gallery3d.R;
+import com.android.photos.data.AlbumSetLoader;
+import com.android.photos.shims.LoaderCompatShim;
+
+import java.util.Date;
+
+public class AlbumSetCursorAdapter extends CursorAdapter {
+
+ private LoaderCompatShim<Cursor> mDrawableFactory;
+
+ public void setDrawableFactory(LoaderCompatShim<Cursor> factory) {
+ mDrawableFactory = factory;
+ }
+ private Date mDate = new Date(); // Used for converting timestamps for display
+
+ public AlbumSetCursorAdapter(Context context) {
+ super(context, null, false);
+ }
+
+ @Override
+ public void bindView(View v, Context context, Cursor cursor) {
+ TextView titleTextView = (TextView) v.findViewById(
+ R.id.album_set_item_title);
+ titleTextView.setText(cursor.getString(AlbumSetLoader.INDEX_TITLE));
+
+ TextView dateTextView = (TextView) v.findViewById(
+ R.id.album_set_item_date);
+ long timestamp = cursor.getLong(AlbumSetLoader.INDEX_TIMESTAMP);
+ if (timestamp > 0) {
+ mDate.setTime(timestamp);
+ dateTextView.setText(DateFormat.getMediumDateFormat(context).format(mDate));
+ } else {
+ dateTextView.setText(null);
+ }
+
+ ProgressBar uploadProgressBar = (ProgressBar) v.findViewById(
+ R.id.album_set_item_upload_progress);
+ if (cursor.getInt(AlbumSetLoader.INDEX_COUNT_PENDING_UPLOAD) > 0) {
+ uploadProgressBar.setVisibility(View.VISIBLE);
+ uploadProgressBar.setProgress(50);
+ } else {
+ uploadProgressBar.setVisibility(View.INVISIBLE);
+ }
+
+ ImageView thumbImageView = (ImageView) v.findViewById(
+ R.id.album_set_item_image);
+ Drawable recycle = thumbImageView.getDrawable();
+ Drawable drawable = mDrawableFactory.drawableForItem(cursor, recycle);
+ if (recycle != drawable) {
+ thumbImageView.setImageDrawable(drawable);
+ }
+ }
+
+ @Override
+ public View newView(Context context, Cursor cursor, ViewGroup parent) {
+ return LayoutInflater.from(context).inflate(
+ R.layout.album_set_item, parent, false);
+ }
+}
diff --git a/src/com/android/photos/adapters/PhotoThumbnailAdapter.java b/src/com/android/photos/adapters/PhotoThumbnailAdapter.java
index 3776ca5a2..1190b8c85 100644
--- a/src/com/android/photos/adapters/PhotoThumbnailAdapter.java
+++ b/src/com/android/photos/adapters/PhotoThumbnailAdapter.java
@@ -22,9 +22,7 @@ import android.graphics.drawable.Drawable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
-import android.view.ViewGroup.LayoutParams;
import android.widget.CursorAdapter;
-import android.widget.GridView;
import android.widget.ImageView;
import com.android.gallery3d.R;
@@ -48,7 +46,7 @@ public class PhotoThumbnailAdapter extends CursorAdapter implements GalleryThumb
@Override
public void bindView(View view, Context context, Cursor cursor) {
- ImageView iv = (ImageView) view;
+ ImageView iv = (ImageView) view.findViewById(R.id.thumbnail);
Drawable recycle = iv.getDrawable();
Drawable drawable = mDrawableFactory.drawableForItem(cursor, recycle);
if (recycle != drawable) {
diff --git a/src/com/android/photos/data/AlbumSetLoader.java b/src/com/android/photos/data/AlbumSetLoader.java
index b2b5204e6..940473255 100644
--- a/src/com/android/photos/data/AlbumSetLoader.java
+++ b/src/com/android/photos/data/AlbumSetLoader.java
@@ -12,6 +12,7 @@ public class AlbumSetLoader {
public static final int INDEX_THUMBNAIL_HEIGHT = 5;
public static final int INDEX_COUNT_PENDING_UPLOAD = 6;
public static final int INDEX_COUNT = 7;
+ public static final int INDEX_SUPPORTED_OPERATIONS = 8;
public static final String[] PROJECTION = {
"_id",
@@ -21,7 +22,8 @@ public class AlbumSetLoader {
"thumb_width",
"thumb_height",
"count_pending_upload",
- "_count"
+ "_count",
+ "supported_operations"
};
public static final MatrixCursor MOCK = createRandomCursor(30);
@@ -44,7 +46,8 @@ public class AlbumSetLoader {
0,
0,
(random < .3 ? 1 : 0),
- 1
+ 1,
+ 0
};
return row;
}
diff --git a/src/com/android/photos/data/PhotoSetLoader.java b/src/com/android/photos/data/PhotoSetLoader.java
index 72c8e93cc..56c82c4a9 100644
--- a/src/com/android/photos/data/PhotoSetLoader.java
+++ b/src/com/android/photos/data/PhotoSetLoader.java
@@ -29,6 +29,8 @@ import android.provider.MediaStore.Files.FileColumns;
import com.android.photos.drawables.DataUriThumbnailDrawable;
import com.android.photos.shims.LoaderCompatShim;
+import java.util.ArrayList;
+
public class PhotoSetLoader extends CursorLoader implements LoaderCompatShim<Cursor> {
public static final String SUPPORTED_OPERATIONS = "supported_operations";
@@ -95,4 +97,19 @@ public class PhotoSetLoader extends CursorLoader implements LoaderCompatShim<Cur
public Uri uriForItem(Cursor item) {
return null;
}
+
+ @Override
+ public ArrayList<Uri> urisForSubItems(Cursor item) {
+ return null;
+ }
+
+ @Override
+ public void deleteItemWithPath(Object path) {
+
+ }
+
+ @Override
+ public Object getPathForItem(Cursor item) {
+ return null;
+ }
}
diff --git a/src/com/android/photos/shims/LoaderCompatShim.java b/src/com/android/photos/shims/LoaderCompatShim.java
index 9da4436aa..d5bf710de 100644
--- a/src/com/android/photos/shims/LoaderCompatShim.java
+++ b/src/com/android/photos/shims/LoaderCompatShim.java
@@ -19,8 +19,13 @@ package com.android.photos.shims;
import android.graphics.drawable.Drawable;
import android.net.Uri;
+import java.util.ArrayList;
+
public interface LoaderCompatShim<T> {
Drawable drawableForItem(T item, Drawable recycle);
Uri uriForItem(T item);
+ ArrayList<Uri> urisForSubItems(T item);
+ void deleteItemWithPath(Object path);
+ Object getPathForItem(T item);
}
diff --git a/src/com/android/photos/shims/MediaItemsLoader.java b/src/com/android/photos/shims/MediaItemsLoader.java
index fa41c8ec8..d75823404 100644
--- a/src/com/android/photos/shims/MediaItemsLoader.java
+++ b/src/com/android/photos/shims/MediaItemsLoader.java
@@ -28,12 +28,16 @@ import android.util.SparseArray;
import com.android.gallery3d.data.ContentListener;
import com.android.gallery3d.data.DataManager;
import com.android.gallery3d.data.MediaItem;
+import com.android.gallery3d.data.MediaObject;
import com.android.gallery3d.data.MediaSet;
import com.android.gallery3d.data.MediaSet.ItemConsumer;
import com.android.gallery3d.data.MediaSet.SyncListener;
+import com.android.gallery3d.data.Path;
import com.android.gallery3d.util.Future;
import com.android.photos.data.PhotoSetLoader;
+import java.util.ArrayList;
+
/**
* Returns all MediaItems in a MediaSet, wrapping them in a cursor to appear
* like a PhotoSetLoader
@@ -47,6 +51,7 @@ public class MediaItemsLoader extends AsyncTaskLoader<Cursor> implements LoaderC
};
private final MediaSet mMediaSet;
+ private final DataManager mDataManager;
private Future<Integer> mSyncTask = null;
private ContentListener mObserver = new ContentListener() {
@Override
@@ -58,14 +63,15 @@ public class MediaItemsLoader extends AsyncTaskLoader<Cursor> implements LoaderC
public MediaItemsLoader(Context context) {
super(context);
- DataManager dm = DataManager.from(context);
- String path = dm.getTopSetPath(DataManager.INCLUDE_ALL);
- mMediaSet = dm.getMediaSet(path);
+ mDataManager = DataManager.from(context);
+ String path = mDataManager.getTopSetPath(DataManager.INCLUDE_ALL);
+ mMediaSet = mDataManager.getMediaSet(path);
}
public MediaItemsLoader(Context context, String parentPath) {
super(context);
- mMediaSet = DataManager.from(getContext()).getMediaSet(parentPath);
+ mDataManager = DataManager.from(getContext());
+ mMediaSet = mDataManager.getMediaSet(parentPath);
}
@Override
@@ -157,4 +163,27 @@ public class MediaItemsLoader extends AsyncTaskLoader<Cursor> implements LoaderC
return mi == null ? null : mi.getContentUri();
}
+ @Override
+ public ArrayList<Uri> urisForSubItems(Cursor item) {
+ return null;
+ }
+
+ @Override
+ public void deleteItemWithPath(Object path) {
+ MediaObject o = mDataManager.getMediaObject((Path) path);
+ if (o != null) {
+ o.delete();
+ }
+ }
+
+ @Override
+ public Object getPathForItem(Cursor item) {
+ int index = item.getInt(PhotoSetLoader.INDEX_ID);
+ MediaItem mi = mMediaItems.get(index);
+ if (mi != null) {
+ return mi.getPath();
+ }
+ return null;
+ }
+
}
diff --git a/src/com/android/photos/shims/MediaSetLoader.java b/src/com/android/photos/shims/MediaSetLoader.java
index 96c7485bb..d200807f9 100644
--- a/src/com/android/photos/shims/MediaSetLoader.java
+++ b/src/com/android/photos/shims/MediaSetLoader.java
@@ -26,7 +26,9 @@ import android.net.Uri;
import com.android.gallery3d.data.ContentListener;
import com.android.gallery3d.data.DataManager;
import com.android.gallery3d.data.MediaItem;
+import com.android.gallery3d.data.MediaObject;
import com.android.gallery3d.data.MediaSet;
+import com.android.gallery3d.data.Path;
import com.android.gallery3d.data.MediaSet.SyncListener;
import com.android.gallery3d.util.Future;
import com.android.photos.data.AlbumSetLoader;
@@ -46,6 +48,7 @@ public class MediaSetLoader extends AsyncTaskLoader<Cursor> implements LoaderCom
};
private final MediaSet mMediaSet;
+ private final DataManager mDataManager;
private Future<Integer> mSyncTask = null;
private ContentListener mObserver = new ContentListener() {
@Override
@@ -58,14 +61,15 @@ public class MediaSetLoader extends AsyncTaskLoader<Cursor> implements LoaderCom
public MediaSetLoader(Context context) {
super(context);
- DataManager dm = DataManager.from(context);
- String path = dm.getTopSetPath(DataManager.INCLUDE_ALL);
- mMediaSet = dm.getMediaSet(path);
+ mDataManager = DataManager.from(context);
+ String path = mDataManager.getTopSetPath(DataManager.INCLUDE_ALL);
+ mMediaSet = mDataManager.getMediaSet(path);
}
public MediaSetLoader(Context context, String path) {
super(context);
- mMediaSet = DataManager.from(getContext()).getMediaSet(path);
+ mDataManager = DataManager.from(getContext());
+ mMediaSet = mDataManager.getMediaSet(path);
}
@Override
@@ -111,6 +115,7 @@ public class MediaSetLoader extends AsyncTaskLoader<Cursor> implements LoaderCom
row[AlbumSetLoader.INDEX_ID] = i;
row[AlbumSetLoader.INDEX_TITLE] = m.getName();
row[AlbumSetLoader.INDEX_COUNT] = m.getMediaItemCount();
+ row[AlbumSetLoader.INDEX_SUPPORTED_OPERATIONS] = m.getSupportedOperations();
MediaItem coverItem = m.getCoverMediaItem();
if (coverItem != null) {
row[AlbumSetLoader.INDEX_TIMESTAMP] = coverItem.getDateInMs();
@@ -147,4 +152,39 @@ public class MediaSetLoader extends AsyncTaskLoader<Cursor> implements LoaderCom
MediaSet ms = mMediaSet.getSubMediaSet(index);
return ms == null ? null : ms.getContentUri();
}
+
+ @Override
+ public ArrayList<Uri> urisForSubItems(Cursor item) {
+ int index = item.getInt(AlbumSetLoader.INDEX_ID);
+ MediaSet ms = mMediaSet.getSubMediaSet(index);
+ if (ms == null) return null;
+ final ArrayList<Uri> result = new ArrayList<Uri>();
+ ms.enumerateMediaItems(new MediaSet.ItemConsumer() {
+ @Override
+ public void consume(int index, MediaItem item) {
+ if (item != null) {
+ result.add(item.getContentUri());
+ }
+ }
+ });
+ return result;
+ }
+
+ @Override
+ public void deleteItemWithPath(Object path) {
+ MediaObject o = mDataManager.getMediaObject((Path) path);
+ if (o != null) {
+ o.delete();
+ }
+ }
+
+ @Override
+ public Object getPathForItem(Cursor item) {
+ int index = item.getInt(AlbumSetLoader.INDEX_ID);
+ MediaSet ms = mMediaSet.getSubMediaSet(index);
+ if (ms != null) {
+ return ms.getPath();
+ }
+ return null;
+ }
}