summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAngus Kong <shkong@google.com>2013-07-30 11:36:00 -0700
committerAngus Kong <shkong@google.com>2013-08-01 16:36:34 -0700
commit8e5e4eedb25a4589342660b928935acca4375fc7 (patch)
tree51e63c6a3bcaeea4e29b98c7e93d50bd9c98873a /src
parentbfed27177046f4b1325bf1bc145ce3bb6b82b1ec (diff)
downloadandroid_packages_apps_Snap-8e5e4eedb25a4589342660b928935acca4375fc7.tar.gz
android_packages_apps_Snap-8e5e4eedb25a4589342660b928935acca4375fc7.tar.bz2
android_packages_apps_Snap-8e5e4eedb25a4589342660b928935acca4375fc7.zip
Add LocalDataAdapter and wrappers.
1. FixedFirstDataAdapter wraps another adapter and add a data at the first position. 2. FixedLastDataAdapter wraps another adapter and add a data at the last position. 3. Make the LocalData interface more complete. - onFullScreen() - canSwipeInFullScreen() - getPath() 3. Add methods to the FilmStripView.DataAdapter to receive UI events. - onDataCentered() - onDataFullScreen() Change-Id: I26d3a3b7facd0c451af43ce5fbbcab2baaaec427
Diffstat (limited to 'src')
-rw-r--r--src/com/android/camera/CameraActivity.java36
-rw-r--r--src/com/android/camera/PhotoUI.java2
-rw-r--r--src/com/android/camera/data/AbstractLocalDataAdapterWrapper.java90
-rw-r--r--src/com/android/camera/data/CameraDataAdapter.java211
-rw-r--r--src/com/android/camera/data/CameraPreviewData.java63
-rw-r--r--src/com/android/camera/data/FixedFirstDataAdapter.java154
-rw-r--r--src/com/android/camera/data/FixedLastDataAdapter.java127
-rw-r--r--src/com/android/camera/data/LocalData.java59
-rw-r--r--src/com/android/camera/data/LocalDataAdapter.java91
-rw-r--r--src/com/android/camera/ui/FilmStripView.java198
10 files changed, 810 insertions, 221 deletions
diff --git a/src/com/android/camera/CameraActivity.java b/src/com/android/camera/CameraActivity.java
index 296c1f9d9..0ed48d721 100644
--- a/src/com/android/camera/CameraActivity.java
+++ b/src/com/android/camera/CameraActivity.java
@@ -42,7 +42,11 @@ import android.view.WindowManager;
import android.widget.ImageView;
import com.android.camera.data.CameraDataAdapter;
+import com.android.camera.data.CameraPreviewData;
+import com.android.camera.data.FixedFirstDataAdapter;
+import com.android.camera.data.FixedLastDataAdapter;
import com.android.camera.data.LocalData;
+import com.android.camera.data.LocalDataAdapter;
import com.android.camera.ui.CameraSwitcher;
import com.android.camera.ui.CameraSwitcher.CameraSwitchListener;
import com.android.camera.ui.FilmStripView;
@@ -68,7 +72,11 @@ public class CameraActivity extends Activity
// panorama. If the extra is not set, it is in the normal camera mode.
public static final String SECURE_CAMERA_EXTRA = "secure_camera";
- private CameraDataAdapter mDataAdapter;
+ /** This data adapter is used by FilmStirpView. */
+ private LocalDataAdapter mDataAdapter;
+ /** This data adapter represents the real local camera data. */
+ private LocalDataAdapter mWrappedDataAdapter;
+
private PanoramaStitchingManager mPanoramaManager;
private int mCurrentModuleIndex;
private CameraModule mCurrentModule;
@@ -87,6 +95,7 @@ public class CameraActivity extends Activity
private MyOrientationEventListener mOrientationListener;
private Handler mMainHandler;
private PanoramaViewHelper mPanoramaViewHelper;
+ private CameraPreviewData mCameraPreviewData;
private class MyOrientationEventListener
extends OrientationEventListener {
@@ -267,8 +276,13 @@ public class CameraActivity extends Activity
LayoutInflater inflater = getLayoutInflater();
View rootLayout = inflater.inflate(R.layout.camera, null, false);
mRootView = rootLayout.findViewById(R.id.camera_app_root);
- mDataAdapter = new CameraDataAdapter(
- new ColorDrawable(getResources().getColor(R.color.photo_placeholder)));
+ mCameraPreviewData = new CameraPreviewData(rootLayout,
+ FilmStripView.ImageData.SIZE_FULL,
+ FilmStripView.ImageData.SIZE_FULL);
+ mWrappedDataAdapter = new FixedFirstDataAdapter(
+ new CameraDataAdapter(new ColorDrawable(
+ getResources().getColor(R.color.photo_placeholder))),
+ mCameraPreviewData);
mFilmStripView = (FilmStripView) findViewById(R.id.filmstrip_view);
mFilmStripView.setViewGap(
getResources().getDimensionPixelSize(R.dimen.camera_film_strip_gap));
@@ -276,9 +290,6 @@ public class CameraActivity extends Activity
mPanoramaViewHelper.onCreate();
mFilmStripView.setPanoramaViewHelper(mPanoramaViewHelper);
// Set up the camera preview first so the preview shows up ASAP.
- mDataAdapter.setCameraPreviewInfo(rootLayout,
- FilmStripView.ImageData.SIZE_FULL, FilmStripView.ImageData.SIZE_FULL);
- mFilmStripView.setDataAdapter(mDataAdapter);
mFilmStripView.setListener(mFilmStripListener);
mCurrentModule = new PhotoModule();
mCurrentModule.init(this, mRootView);
@@ -334,19 +345,22 @@ public class CameraActivity extends Activity
// The loading is done in background and will update the filmstrip later.
if (!mSecureCamera) {
+ mDataAdapter = mWrappedDataAdapter;
mDataAdapter.requestLoad(getContentResolver());
+ mFilmStripView.setDataAdapter(mDataAdapter);
} else {
- // Flush out all the original data first.
- mDataAdapter.flush();
+ // Put a lock placeholder as the last image by setting its date to 0.
ImageView v = (ImageView) getLayoutInflater().inflate(
R.layout.secure_album_placeholder, null);
- // Put a lock placeholder as the last image by setting its date to 0.
- mDataAdapter.addLocalData(
+ mDataAdapter = new FixedLastDataAdapter(
+ mWrappedDataAdapter,
new LocalData.LocalViewData(
v,
v.getDrawable().getIntrinsicWidth(),
v.getDrawable().getIntrinsicHeight(),
0, 0));
+ // Flush out all the original data.
+ mDataAdapter.flush();
}
mPanoramaViewHelper.onStart();
}
@@ -515,7 +529,7 @@ public class CameraActivity extends Activity
}
public void setSwipingEnabled(boolean enable) {
- mDataAdapter.setCameraPreviewLock(!enable);
+ mCameraPreviewData.lockPreview(!enable);
}
// Accessor methods for getting latency times used in performance testing
diff --git a/src/com/android/camera/PhotoUI.java b/src/com/android/camera/PhotoUI.java
index 1e341a686..d58ed7f13 100644
--- a/src/com/android/camera/PhotoUI.java
+++ b/src/com/android/camera/PhotoUI.java
@@ -342,7 +342,7 @@ public class PhotoUI implements PieListener,
public void initializeControlByIntent() {
mBlocker = mRootView.findViewById(R.id.blocker);
- mPreviewThumb = mActivity.findViewById(R.id.preview_thumb);
+ mPreviewThumb = mRootView.findViewById(R.id.preview_thumb);
mPreviewThumb.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
diff --git a/src/com/android/camera/data/AbstractLocalDataAdapterWrapper.java b/src/com/android/camera/data/AbstractLocalDataAdapterWrapper.java
new file mode 100644
index 000000000..66c55850a
--- /dev/null
+++ b/src/com/android/camera/data/AbstractLocalDataAdapterWrapper.java
@@ -0,0 +1,90 @@
+/*
+ * 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.camera.data;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.net.Uri;
+
+/**
+ * An abstract {@link LocalDataAdapter} implementation to wrap another
+ * {@link LocalDataAdapter}. All implementations related to data id is not
+ * addressed in this abstract class since wrapping another data adapter
+ * surely makes things different for data id.
+ *
+ * @see FixedFirstDataAdapter
+ * @see FixedLastDataAdapter
+ */
+public abstract class AbstractLocalDataAdapterWrapper implements LocalDataAdapter {
+
+ protected final LocalDataAdapter mAdapter;
+ protected int mSuggestedWidth;
+ protected int mSuggestedHeight;
+
+ /**
+ * Constructor.
+ *
+ * @param wrappedAdapter The {@link LocalDataAdapter} to be wrapped.
+ */
+ AbstractLocalDataAdapterWrapper(LocalDataAdapter wrappedAdapter) {
+ if (wrappedAdapter == null) {
+ throw new AssertionError("data adapter is null");
+ }
+ mAdapter = wrappedAdapter;
+ }
+
+ @Override
+ public void suggestViewSizeBound(int w, int h) {
+ mSuggestedWidth = w;
+ mSuggestedHeight = h;
+ }
+
+ @Override
+ public void setListener(Listener listener) {
+ mAdapter.setListener(listener);
+ }
+
+ @Override
+ public void requestLoad(ContentResolver resolver) {
+ mAdapter.requestLoad(resolver);
+ }
+
+ @Override
+ public void addNewVideo(ContentResolver resolver, Uri uri) {
+ mAdapter.addNewVideo(resolver, uri);
+ }
+
+ @Override
+ public void addNewPhoto(ContentResolver resolver, Uri uri) {
+ mAdapter.addNewPhoto(resolver, uri);
+ }
+
+ @Override
+ public void flush() {
+ mAdapter.flush();
+ }
+
+ @Override
+ public boolean executeDeletion(Context context) {
+ return mAdapter.executeDeletion(context);
+ }
+
+ @Override
+ public boolean undoDataRemoval() {
+ return mAdapter.undoDataRemoval();
+ }
+}
diff --git a/src/com/android/camera/data/CameraDataAdapter.java b/src/com/android/camera/data/CameraDataAdapter.java
index 443aaa05d..3605f7190 100644
--- a/src/com/android/camera/data/CameraDataAdapter.java
+++ b/src/com/android/camera/data/CameraDataAdapter.java
@@ -27,7 +27,6 @@ import android.util.Log;
import android.view.View;
import com.android.camera.Storage;
-import com.android.camera.ui.FilmStripView;
import com.android.camera.ui.FilmStripView.ImageData;
import com.android.gallery3d.util.LightCycleHelper.PanoramaViewHelper;
@@ -37,12 +36,9 @@ import java.util.Comparator;
import java.util.List;
/**
- * A FilmStrip.DataProvider that provide data in the camera folder.
- *
- * The given view for camera preview won't be added until the preview info
- * has been set by setCameraPreviewInfo(int, int).
+ * A {@link LocalDataAdapter} that provides data in the camera folder.
*/
-public class CameraDataAdapter implements FilmStripView.DataAdapter {
+public class CameraDataAdapter implements LocalDataAdapter {
private static final String TAG = CameraDataAdapter.class.getSimpleName();
private static final int DEFAULT_DECODE_SIZE = 3000;
@@ -51,33 +47,23 @@ public class CameraDataAdapter implements FilmStripView.DataAdapter {
private List<LocalData> mImages;
private Listener mListener;
- private View mCameraPreviewView;
private Drawable mPlaceHolder;
private int mSuggestedWidth = DEFAULT_DECODE_SIZE;
private int mSuggestedHeight = DEFAULT_DECODE_SIZE;
- private boolean mCameraPreviewLocked;
private LocalData mLocalDataToDelete;
public CameraDataAdapter(Drawable placeHolder) {
mPlaceHolder = placeHolder;
}
- public void setCameraPreviewInfo(View cameraPreview, int width, int height) {
- mCameraPreviewView = cameraPreview;
- addOrReplaceCameraData(buildCameraImageData(width, height));
- }
-
+ @Override
public void requestLoad(ContentResolver resolver) {
QueryTask qtask = new QueryTask();
qtask.execute(resolver);
}
- public void setCameraPreviewLock(boolean locked) {
- mCameraPreviewLocked = locked;
- }
-
@Override
public int getTotalNumber() {
if (mImages == null) {
@@ -91,15 +77,8 @@ public class CameraDataAdapter implements FilmStripView.DataAdapter {
return getData(id);
}
- public LocalData getData(int id) {
- if (mImages == null || id >= mImages.size() || id < 0) {
- return null;
- }
- return mImages.get(id);
- }
-
@Override
- public void suggestDecodeSize(int w, int h) {
+ public void suggestViewSizeBound(int w, int h) {
if (w <= 0 || h <= 0) {
mSuggestedWidth = mSuggestedHeight = DEFAULT_DECODE_SIZE;
} else {
@@ -131,14 +110,26 @@ public class CameraDataAdapter implements FilmStripView.DataAdapter {
}
@Override
- public boolean canSwipeInFullScreen(int id) {
- if (mImages.get(id).getType()
- == ImageData.TYPE_CAMERA_PREVIEW) {
- return !mCameraPreviewLocked;
+ public void onDataFullScreen(int dataID, boolean fullScreen) {
+ if (dataID < mImages.size() && dataID >= 0) {
+ mImages.get(dataID).onFullScreen(fullScreen);
}
- return false;
}
+ @Override
+ public void onDataCentered(int dataID, boolean centered) {
+ // do nothing.
+ }
+
+ @Override
+ public boolean canSwipeInFullScreen(int dataID) {
+ if (dataID < mImages.size() && dataID > 0) {
+ return mImages.get(dataID).canSwipeInFullScreen();
+ }
+ return true;
+ }
+
+ @Override
public void removeData(Context c, int dataID) {
if (dataID >= mImages.size()) return;
LocalData d = mImages.remove(dataID);
@@ -166,6 +157,7 @@ public class CameraDataAdapter implements FilmStripView.DataAdapter {
}
}
+ @Override
public void addNewVideo(ContentResolver cr, Uri uri) {
Cursor c = cr.query(uri,
LocalData.Video.QUERY_PROJECTION,
@@ -176,6 +168,7 @@ public class CameraDataAdapter implements FilmStripView.DataAdapter {
}
}
+ @Override
public void addNewPhoto(ContentResolver cr, Uri uri) {
Cursor c = cr.query(uri,
LocalData.Photo.QUERY_PROJECTION,
@@ -186,6 +179,13 @@ public class CameraDataAdapter implements FilmStripView.DataAdapter {
}
}
+ @Override
+ public int findDataByContentUri(Uri uri) {
+ // TODO: find the data.
+ return -1;
+ }
+
+ @Override
public boolean undoDataRemoval() {
if (mLocalDataToDelete == null) return false;
LocalData d = mLocalDataToDelete;
@@ -194,6 +194,7 @@ public class CameraDataAdapter implements FilmStripView.DataAdapter {
return true;
}
+ @Override
public boolean executeDeletion(Context c) {
if (mLocalDataToDelete == null) return false;
@@ -203,6 +204,18 @@ public class CameraDataAdapter implements FilmStripView.DataAdapter {
return true;
}
+ @Override
+ public void flush() {
+ replaceData(null);
+ }
+
+ private LocalData getData(int id) {
+ if (mImages == null || id >= mImages.size() || id < 0) {
+ return null;
+ }
+ return mImages.get(id);
+ }
+
// Update all the data but keep the camera data if already set.
private void replaceData(List<LocalData> list) {
boolean changed = (list != mImages);
@@ -244,61 +257,6 @@ public class CameraDataAdapter implements FilmStripView.DataAdapter {
}
}
- public void flush() {
- replaceData(null);
- }
-
- public void addLocalData(LocalData data) {
- insertData(data);
- }
-
- private LocalData buildCameraImageData(int width, int height) {
- LocalData d = new CameraPreviewData(width, height);
- return d;
- }
-
- private void addOrReplaceCameraData(LocalData data) {
- if (mImages == null) {
- mImages = new ArrayList<LocalData>();
- }
- if (mImages.size() == 0) {
- // No data at all.
- mImages.add(0, data);
- if (mListener != null) {
- mListener.onDataLoaded();
- }
- return;
- }
-
- LocalData first = mImages.get(0);
- if (first.getType() == ImageData.TYPE_CAMERA_PREVIEW) {
- // Replace the old camera data.
- mImages.set(0, data);
- if (mListener != null) {
- mListener.onDataUpdated(new UpdateReporter() {
- @Override
- public boolean isDataRemoved(int id) {
- return false;
- }
-
- @Override
- public boolean isDataUpdated(int id) {
- if (id == 0) {
- return true;
- }
- return false;
- }
- });
- }
- } else {
- // Add a new camera data.
- mImages.add(0, data);
- if (mListener != null) {
- mListener.onDataLoaded();
- }
- }
- }
-
private class QueryTask extends AsyncTask<ContentResolver, Void, List<LocalData>> {
@Override
protected List<LocalData> doInBackground(ContentResolver... resolver) {
@@ -387,87 +345,4 @@ public class CameraDataAdapter implements FilmStripView.DataAdapter {
return null;
}
}
-
- private class CameraPreviewData implements LocalData {
- private int width;
- private int height;
-
- CameraPreviewData(int w, int h) {
- width = w;
- height = h;
- }
-
- @Override
- public long getDateTaken() {
- // This value is used for sorting.
- return -1;
- }
-
- @Override
- public long getDateModified() {
- // This value might be used for sorting.
- return -1;
- }
-
- @Override
- public String getTitle() {
- return "";
- }
-
- @Override
- public int getWidth() {
- return width;
- }
-
- @Override
- public int getHeight() {
- return height;
- }
-
- @Override
- public int getType() {
- return ImageData.TYPE_CAMERA_PREVIEW;
- }
-
- @Override
- public boolean isUIActionSupported(int action) {
- return false;
- }
-
- @Override
- public boolean isDataActionSupported(int action) {
- return false;
- }
-
- @Override
- public boolean delete(Context c) {
- return false;
- }
-
- @Override
- public View getView(Context c, int width, int height, Drawable placeHolder) {
- return mCameraPreviewView;
- }
-
- @Override
- public void prepare() {
- // do nothing.
- }
-
- @Override
- public void recycle() {
- // do nothing.
- }
-
- @Override
- public void isPhotoSphere(Context context, PanoramaSupportCallback callback) {
- // Not a photo sphere panorama.
- callback.panoramaInfoAvailable(false, false);
- }
-
- @Override
- public void viewPhotoSphere(PanoramaViewHelper helper) {
- // do nothing.
- }
- }
}
diff --git a/src/com/android/camera/data/CameraPreviewData.java b/src/com/android/camera/data/CameraPreviewData.java
new file mode 100644
index 000000000..8f8e2138d
--- /dev/null
+++ b/src/com/android/camera/data/CameraPreviewData.java
@@ -0,0 +1,63 @@
+/*
+ * 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.camera.data;
+
+import android.view.View;
+
+import com.android.camera.ui.FilmStripView.ImageData;
+
+/**
+ * A class implementing {@link LocalData} to represent a camera preview.
+ */
+public class CameraPreviewData extends LocalData.LocalViewData {
+
+ private boolean mPreviewLocked;
+
+ /**
+ * Constructor.
+ *
+ * @param v The {@link android.view.View} for camera preview.
+ * @param width The width of the camera preview.
+ * @param height The height of the camera preview.
+ */
+ public CameraPreviewData(View v, int width, int height) {
+ super(v, width, height, -1, -1);
+ mPreviewLocked = true;
+ }
+
+ @Override
+ public int getType() {
+ return ImageData.TYPE_CAMERA_PREVIEW;
+ }
+
+ @Override
+ public boolean canSwipeInFullScreen() {
+ return !mPreviewLocked;
+ }
+
+ /**
+ * Locks the camera preview. When the camera preview is locked, swipe
+ * to film strip is not allowed. One case is when the video recording
+ * is in progress.
+ *
+ * @param lock {@code true} if the preview should be locked. {@code false}
+ * otherwise.
+ */
+ public void lockPreview(boolean lock) {
+ mPreviewLocked = lock;
+ }
+}
diff --git a/src/com/android/camera/data/FixedFirstDataAdapter.java b/src/com/android/camera/data/FixedFirstDataAdapter.java
new file mode 100644
index 000000000..34ba0a1a0
--- /dev/null
+++ b/src/com/android/camera/data/FixedFirstDataAdapter.java
@@ -0,0 +1,154 @@
+/*
+ * 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.camera.data;
+
+import android.content.Context;
+import android.net.Uri;
+import android.view.View;
+
+import com.android.camera.ui.FilmStripView;
+import com.android.camera.ui.FilmStripView.DataAdapter;
+import com.android.camera.ui.FilmStripView.ImageData;
+
+/**
+ * A {@link LocalDataAdapter} which puts a {@link LocalData} fixed at the first
+ * position. It's done by combining a {@link LocalData} and another
+ * {@link LocalDataAdapter}.
+ */
+public class FixedFirstDataAdapter extends AbstractLocalDataAdapterWrapper
+ implements DataAdapter.Listener {
+
+ private final LocalData mFirstData;
+ private Listener mListener;
+
+ /**
+ * Constructor.
+ *
+ * @param wrappedAdapter The {@link LocalDataAdapter} to be wrapped.
+ * @param firstData The {@link LocalData} to be placed at the first
+ * position.
+ */
+ public FixedFirstDataAdapter(
+ LocalDataAdapter wrappedAdapter,
+ LocalData firstData) {
+ super(wrappedAdapter);
+ if (firstData == null) {
+ throw new AssertionError("data is null");
+ }
+ mFirstData = firstData;
+ }
+
+ @Override
+ public void removeData(Context context, int dataID) {
+ if (dataID > 0) {
+ mAdapter.removeData(context, dataID - 1);
+ }
+ }
+
+ @Override
+ public int findDataByContentUri(Uri uri) {
+ int pos = mAdapter.findDataByContentUri(uri);
+ if (pos != -1) {
+ return pos + 1;
+ }
+ return -1;
+ }
+
+ @Override
+ public int getTotalNumber() {
+ return (mAdapter.getTotalNumber() + 1);
+ }
+
+ @Override
+ public View getView(Context context, int dataID) {
+ if (dataID == 0) {
+ return mFirstData.getView(
+ context, mSuggestedWidth, mSuggestedHeight, null);
+ }
+ return mAdapter.getView(context, dataID - 1);
+ }
+
+ @Override
+ public ImageData getImageData(int dataID) {
+ if (dataID == 0) {
+ return mFirstData;
+ }
+ return mAdapter.getImageData(dataID - 1);
+ }
+
+ @Override
+ public void onDataFullScreen(int dataID, boolean fullScreen) {
+ if (dataID == 0) {
+ mFirstData.onFullScreen(fullScreen);
+ } else {
+ mAdapter.onDataFullScreen(dataID - 1, fullScreen);
+ }
+ }
+
+ @Override
+ public void onDataCentered(int dataID, boolean centered) {
+ if (dataID != 0) {
+ mAdapter.onDataCentered(dataID, centered);
+ } else {
+ // TODO: notify the data
+ }
+ }
+
+ @Override
+ public void setListener(Listener listener) {
+ mListener = listener;
+ mAdapter.setListener((listener == null) ? null : this);
+ }
+
+ @Override
+ public boolean canSwipeInFullScreen(int dataID) {
+ if (dataID == 0) {
+ return mFirstData.canSwipeInFullScreen();
+ }
+ return mAdapter.canSwipeInFullScreen(dataID - 1);
+ }
+
+ @Override
+ public void onDataLoaded() {
+ mListener.onDataLoaded();
+ }
+
+ @Override
+ public void onDataUpdated(final UpdateReporter reporter) {
+ mListener.onDataUpdated(new UpdateReporter() {
+ @Override
+ public boolean isDataRemoved(int dataID) {
+ return reporter.isDataRemoved(dataID + 1);
+ }
+
+ @Override
+ public boolean isDataUpdated(int dataID) {
+ return reporter.isDataUpdated(dataID + 1);
+ }
+ });
+ }
+
+ @Override
+ public void onDataInserted(int dataID, ImageData data) {
+ mListener.onDataInserted(dataID + 1, data);
+ }
+
+ @Override
+ public void onDataRemoved(int dataID, ImageData data) {
+ mListener.onDataRemoved(dataID + 1, data);
+ }
+}
diff --git a/src/com/android/camera/data/FixedLastDataAdapter.java b/src/com/android/camera/data/FixedLastDataAdapter.java
new file mode 100644
index 000000000..16c047d1a
--- /dev/null
+++ b/src/com/android/camera/data/FixedLastDataAdapter.java
@@ -0,0 +1,127 @@
+/*
+ * 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.camera.data;
+
+import android.content.Context;
+import android.net.Uri;
+import android.view.View;
+
+import com.android.camera.ui.FilmStripView;
+
+/**
+ * A {@link LocalDataAdapter} which puts a {@link LocalData} fixed at the last
+ * position. It's done by combining a {@link LocalData} and another
+ * {@link LocalDataAdapter}.
+ */
+public class FixedLastDataAdapter extends AbstractLocalDataAdapterWrapper {
+
+ private final LocalData mLastData;
+
+ /**
+ * Constructor.
+ *
+ * @param wrappedAdapter The {@link LocalDataAdapter} to be wrapped.
+ * @param lastData The {@link LocalData} to be placed at the last position.
+ */
+ public FixedLastDataAdapter(
+ LocalDataAdapter wrappedAdapter,
+ LocalData lastData) {
+ super(wrappedAdapter);
+ if (lastData == null) {
+ throw new AssertionError("data is null");
+ }
+ mLastData = lastData;
+ }
+
+ @Override
+ public void removeData(Context context, int dataID) {
+ if (dataID < mAdapter.getTotalNumber()) {
+ mAdapter.removeData(context, dataID);
+ }
+ }
+
+ @Override
+ public int findDataByContentUri(Uri uri) {
+ return mAdapter.findDataByContentUri(uri);
+ }
+
+ @Override
+ public int getTotalNumber() {
+ return mAdapter.getTotalNumber() + 1;
+ }
+
+ @Override
+ public View getView(Context context, int dataID) {
+ int totalNumber = mAdapter.getTotalNumber();
+
+ if (dataID < totalNumber) {
+ return mAdapter.getView(context, dataID);
+ } else if (dataID == totalNumber) {
+ return mLastData.getView(context,
+ mSuggestedWidth, mSuggestedHeight, null);
+ }
+
+ return null;
+ }
+
+ @Override
+ public FilmStripView.ImageData getImageData(int dataID) {
+ int totalNumber = mAdapter.getTotalNumber();
+
+ if (dataID < totalNumber) {
+ return mAdapter.getImageData(dataID);
+ } else if (dataID == totalNumber) {
+ return mLastData;
+ }
+ return null;
+ }
+
+ @Override
+ public void onDataFullScreen(int dataID, boolean fullScreen) {
+ int totalNumber = mAdapter.getTotalNumber();
+
+ if (dataID < totalNumber) {
+ mAdapter.onDataFullScreen(dataID, fullScreen);
+ } else if (dataID == totalNumber) {
+ mLastData.onFullScreen(fullScreen);
+ }
+ }
+
+ @Override
+ public void onDataCentered(int dataID, boolean centered) {
+ int totalNumber = mAdapter.getTotalNumber();
+
+ if (dataID < totalNumber) {
+ mAdapter.onDataCentered(dataID, centered);
+ } else if (dataID == totalNumber) {
+ // TODO: notify the data
+ }
+ }
+
+ @Override
+ public boolean canSwipeInFullScreen(int dataID) {
+ int totalNumber = mAdapter.getTotalNumber();
+
+ if (dataID < totalNumber) {
+ return mAdapter.canSwipeInFullScreen(dataID);
+ } else if (dataID == totalNumber) {
+ return mLastData.canSwipeInFullScreen();
+ }
+ return false;
+ }
+}
+
diff --git a/src/com/android/camera/data/LocalData.java b/src/com/android/camera/data/LocalData.java
index 0a51be956..efccfe332 100644
--- a/src/com/android/camera/data/LocalData.java
+++ b/src/com/android/camera/data/LocalData.java
@@ -67,14 +67,17 @@ public interface LocalData extends FilmStripView.ImageData {
String getTitle();
boolean isDataActionSupported(int action);
boolean delete(Context c);
+ void onFullScreen(boolean fullScreen);
+ boolean canSwipeInFullScreen();
+ String getPath();
static class NewestFirstComparator implements Comparator<LocalData> {
- // Compare taken/modified date of LocalData in descent order to make
- // newer data in the front.
- // The negative numbers here are always considered "bigger" than
- // positive ones. Thus, if any one of the numbers is negative, the logic
- // is reversed.
+ /** Compare taken/modified date of LocalData in descent order to make
+ newer data in the front.
+ The negative numbers here are always considered "bigger" than
+ positive ones. Thus, if any one of the numbers is negative, the logic
+ is reversed. */
private static int compareDate(long v1, long v2) {
if (v1 >= 0 && v2 >= 0) {
return ((v1 < v2) ? 1 : ((v1 > v2) ? -1 : 0));
@@ -98,10 +101,16 @@ public interface LocalData extends FilmStripView.ImageData {
// Implementations below.
/**
+<<<<<<< HEAD
* A base class for all the local media files. The bitmap is loaded in
* background thread. Subclasses should implement their own background
* loading thread by subclassing BitmapLoadTask and overriding
* doInBackground() to return a bitmap.
+=======
+ * A base class for all the local media files. The bitmap is loaded in background
+ * thread. Subclasses should implement their own background loading thread by
+ * sub-classing BitmapLoadTask and overriding doInBackground() to return a bitmap.
+>>>>>>> Add LocalDataAdapter and wrappers.
*/
abstract static class LocalMediaData implements LocalData {
protected long id;
@@ -149,6 +158,11 @@ public interface LocalData extends FilmStripView.ImageData {
}
@Override
+ public String getPath() {
+ return path;
+ }
+
+ @Override
public boolean isUIActionSupported(int action) {
return false;
}
@@ -164,7 +178,6 @@ public interface LocalData extends FilmStripView.ImageData {
return f.delete();
}
-
@Override
public void viewPhotoSphere(PanoramaViewHelper helper) {
helper.showPanorama(getContentUri());
@@ -196,6 +209,16 @@ public interface LocalData extends FilmStripView.ImageData {
});
}
+ @Override
+ public void onFullScreen(boolean fullScreen) {
+ // do nothing.
+ }
+
+ @Override
+ public boolean canSwipeInFullScreen() {
+ return true;
+ }
+
protected ImageView fillImageView(Context ctx, ImageView v,
int decodeWidth, int decodeHeight, Drawable placeHolder) {
v.setScaleType(ImageView.ScaleType.FIT_XY);
@@ -287,6 +310,9 @@ public interface LocalData extends FilmStripView.ImageData {
static final String QUERY_ORDER = ImageColumns.DATE_TAKEN + " DESC, "
+ ImageColumns._ID + " DESC";
+ /**
+ * These values should be kept in sync with column IDs (COL_*) above.
+ */
static final String[] QUERY_PROJECTION = {
ImageColumns._ID, // 0, int
ImageColumns.TITLE, // 1, string
@@ -432,6 +458,7 @@ public interface LocalData extends FilmStripView.ImageData {
public static final int COL_DATA = 5;
public static final int COL_WIDTH = 6;
public static final int COL_HEIGHT = 7;
+ public static final int COL_RESOLUTION = 8;
static final Uri CONTENT_URI = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
@@ -444,6 +471,9 @@ public interface LocalData extends FilmStripView.ImageData {
static final String QUERY_ORDER = VideoColumns.DATE_TAKEN + " DESC, "
+ VideoColumns._ID + " DESC";
+ /**
+ * These values should be kept in sync with column IDs (COL_*) above.
+ */
static final String[] QUERY_PROJECTION = {
VideoColumns._ID, // 0, int
VideoColumns.TITLE, // 1, string
@@ -453,7 +483,7 @@ public interface LocalData extends FilmStripView.ImageData {
VideoColumns.DATA, // 5, string
VideoColumns.WIDTH, // 6, int
VideoColumns.HEIGHT, // 7, int
- VideoColumns.RESOLUTION
+ VideoColumns.RESOLUTION // 8, string
};
private Uri mPlayUri;
@@ -637,6 +667,11 @@ public interface LocalData extends FilmStripView.ImageData {
}
@Override
+ public String getPath() {
+ return "";
+ }
+
+ @Override
public boolean isUIActionSupported(int action) {
return false;
}
@@ -676,6 +711,16 @@ public interface LocalData extends FilmStripView.ImageData {
public void viewPhotoSphere(PanoramaViewHelper helper) {
// do nothing.
}
+
+ @Override
+ public void onFullScreen(boolean fullScreen) {
+ // do nothing.
+ }
+
+ @Override
+ public boolean canSwipeInFullScreen() {
+ return true;
+ }
}
}
diff --git a/src/com/android/camera/data/LocalDataAdapter.java b/src/com/android/camera/data/LocalDataAdapter.java
new file mode 100644
index 000000000..3b4f07dea
--- /dev/null
+++ b/src/com/android/camera/data/LocalDataAdapter.java
@@ -0,0 +1,91 @@
+/*
+ * 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.camera.data;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.net.Uri;
+
+import static com.android.camera.ui.FilmStripView.DataAdapter;
+
+/**
+ * An interface which extends {@link DataAdapter} and defines operations on
+ * the data in the local camera folder.
+ */
+public interface LocalDataAdapter extends DataAdapter {
+
+ /**
+ * Request for loading the local data.
+ *
+ * @param resolver {@link ContentResolver} used for data loading.
+ */
+ public void requestLoad(ContentResolver resolver);
+
+ /**
+ * Remove the data in the local camera folder.
+ *
+ * @param context {@link Context} used to remove the data.
+ * @param dataID ID of data to be deleted.
+ */
+ public void removeData(Context context, int dataID);
+
+ /**
+ * Add new local video data.
+ *
+ * @param resolver {@link ContentResolver} used to add the data.
+ * @param uri {@link Uri} of the video.
+ */
+ public void addNewVideo(ContentResolver resolver, Uri uri);
+
+ /**
+ * Adds new local photo data.
+ *
+ * @param resolver {@link ContentResolver} used to add the data.
+ * @param uri {@link Uri} of the photo.
+ */
+ public void addNewPhoto(ContentResolver resolver, Uri uri);
+
+ /**
+ * Finds the {@link LocalData} of the specified content Uri.
+ *
+ * @param Uri The content Uri of the {@link LocalData}.
+ * @return The index of the data. {@code -1} if not found.
+ */
+ public int findDataByContentUri(Uri uri);
+
+ /**
+ * Clears all the data currently loaded.
+ */
+ public void flush();
+
+ /**
+ * Executes the deletion task. Delete the data waiting in the deletion queue.
+ *
+ * @param context The {@link Context} from the caller.
+ * @return {@code true} if task has been executed, {@code false}
+ * otherwise.
+ */
+ public boolean executeDeletion(Context context);
+
+ /**
+ * Undo a deletion. If there is any data waiting to be deleted in the queue,
+ * move it out of the deletion queue.
+ *
+ * @return {@code true} if there are items in the queue, {@code false} otherwise.
+ */
+ public boolean undoDataRemoval();
+}
diff --git a/src/com/android/camera/ui/FilmStripView.java b/src/com/android/camera/ui/FilmStripView.java
index 347357eb9..8a1a85a55 100644
--- a/src/com/android/camera/ui/FilmStripView.java
+++ b/src/com/android/camera/ui/FilmStripView.java
@@ -90,8 +90,6 @@ public class FilmStripView extends ViewGroup {
/**
* Called then photo sphere info has been loaded.
*
- * @param imageId the ID of the image the information is returned
- * for
* @param isPanorama whether the image is a valid photo sphere
* @param isPanorama360 whether the photo sphere is a full 360
* degree horizontal panorama
@@ -100,11 +98,13 @@ public class FilmStripView extends ViewGroup {
boolean isPanorama360);
}
+ // Image data types.
public static final int TYPE_NONE = 0;
public static final int TYPE_CAMERA_PREVIEW = 1;
public static final int TYPE_PHOTO = 2;
public static final int TYPE_VIDEO = 3;
+ // Actions allowed to be performed on the image data.
// The actions are defined bit-wise so we can use bit operations like
// | and &.
public static final int ACTION_NONE = 0;
@@ -112,25 +112,58 @@ public class FilmStripView extends ViewGroup {
public static final int ACTION_DEMOTE = (1 << 1);
/**
- * SIZE_FULL means disgard the width or height when deciding the view
- * size of this ImageData, just use full screen size.
+ * SIZE_FULL can be returned by {@link ImageData#getWidth()} and
+ * {@link ImageData#getHeight()}.
+ * When SIZE_FULL is returned for width/height, it means the the
+ * width or height will be disregarded when deciding the view size
+ * of this ImageData, just use full screen size.
*/
public static final int SIZE_FULL = -2;
- // The values returned by getWidth() and getHeight() will be used for
- // layout.
+ /**
+ * Returns the width of the image. The final layout of the view returned
+ * by {@link DataAdapter#getView(android.content.Context, int)} will
+ * preserve the aspect ratio of
+ * {@link com.android.camera.ui.FilmStripView.ImageData#getWidth()} and
+ * {@link com.android.camera.ui.FilmStripView.ImageData#getHeight()}.
+ */
public int getWidth();
+
+ /**
+ * Returns the width of the image. The final layout of the view returned
+ * by {@link DataAdapter#getView(android.content.Context, int)} will
+ * preserve the aspect ratio of
+ * {@link com.android.camera.ui.FilmStripView.ImageData#getWidth()} and
+ * {@link com.android.camera.ui.FilmStripView.ImageData#getHeight()}.
+ */
public int getHeight();
+ /** Returns the image data type */
public int getType();
+ /**
+ * Checks if the UI action is supported.
+ *
+ * @param action The UI actions to check.
+ * @return {@code false} if at least one of the actions is not
+ * supported. {@code true} otherwise.
+ */
public boolean isUIActionSupported(int action);
- /** This should be called first time before using it. */
+ /**
+ * Gives the data a hint when its view is going to be displayed.
+ * {@code FilmStripView} should always call this function before
+ * showing its corresponding view every time.
+ */
public void prepare();
- /** This should be called before we nullify the reference to this data. */
+ /**
+ * Gives the data a hint when its view is going to be removed from the
+ * view hierarchy. {@code FilmStripView} should always call this
+ * function after its corresponding view is removed from the view
+ * hierarchy.
+ */
public void recycle();
/**
@@ -146,13 +179,27 @@ public class FilmStripView extends ViewGroup {
public void viewPhotoSphere(PanoramaViewHelper helper);
}
+ /**
+ * An interfaces which defines the interactions between the
+ * {@link ImageData} and the {@link FilmStripView}.
+ */
public interface DataAdapter {
+ /**
+ * An interface which defines the update report used to return to
+ * the {@link com.android.camera.ui.FilmStripView.Listener}.
+ */
public interface UpdateReporter {
- public boolean isDataRemoved(int id);
+ /** Checks if the data of dataID is removed. */
+ public boolean isDataRemoved(int dataID);
- public boolean isDataUpdated(int id);
+ /** Checks if the data of dataID is updated. */
+ public boolean isDataUpdated(int dataID);
}
+ /**
+ * An interface which defines the listener for UI actions over
+ * {@link ImageData}.
+ */
public interface Listener {
// Called when the whole data loading is done. No any assumption
// on previous data.
@@ -167,30 +214,107 @@ public class FilmStripView extends ViewGroup {
public void onDataRemoved(int dataID, ImageData data);
}
+ /** Returns the total number of image data */
public int getTotalNumber();
- public View getView(Context context, int id);
+ /**
+ * Returns the view to visually present the image data.
+ *
+ * @param context The {@link Context} to create the view.
+ * @param dataID The ID of the image data to be presented.
+ * @return The view representing the image data. Null if
+ * unavailable or the {@code dataID} is out of range.
+ */
+ public View getView(Context context, int dataID);
- public ImageData getImageData(int id);
+ /**
+ * Returns the {@link ImageData} specified by the ID.
+ *
+ * @param dataID The ID of the {@link ImageData}.
+ * @return The specified {@link ImageData}. Null if not available.
+ */
+ public ImageData getImageData(int dataID);
- public void suggestDecodeSize(int w, int h);
+ /**
+ * Suggests the data adapter the maximum possible size of the layout
+ * so the {@link DataAdapter} can optimize the view returned for the
+ * {@link ImageData}.
+ *
+ * @param w Maximum width.
+ * @param h Maximum height.
+ */
+ public void suggestViewSizeBound(int w, int h);
+ /**
+ * Sets the listener for FilmStripView UI actions over the ImageData.
+ *
+ * @param listener The listener to use.
+ */
public void setListener(Listener listener);
- /** true if the view of the data can be moved when in fullscreen. */
- public boolean canSwipeInFullScreen(int id);
+ /**
+ * The callback when the item enters/leaves full-screen.
+ * TODO: Call this function actually.
+ *
+ * @param dataID The ID of the image data.
+ * @param fullScreen {@code true} if the data is entering full-screen.
+ * {@code false} otherwise.
+ */
+ public void onDataFullScreen(int dataID, boolean fullScreen);
+
+ /**
+ * The callback when the item is centered/off-centered.
+ * TODO: Calls this function actually.
+ *
+ * @param dataID The ID of the image data.
+ * @param centered {@code true} if the data is centered.
+ * {@code false} otherwise.
+ */
+ public void onDataCentered(int dataID, boolean centered);
+
+ /**
+ * Returns {@code true} if the view of the data can be moved by swipe
+ * gesture when in full-screen.
+ *
+ * @param dataID The ID of the data.
+ * @return {@code true} if the view can be moved,
+ * {@code false} otherwise.
+ */
+ public boolean canSwipeInFullScreen(int dataID);
}
+ /**
+ * An interface which defines the FilmStripView UI action listener.
+ */
public interface Listener {
+ /**
+ * Callback when the data is promoted.
+ *
+ * @param dataID The ID of the promoted data.
+ */
public void onDataPromoted(int dataID);
+ /**
+ * Callback when the data is demoted.
+ *
+ * @param dataID The ID of the demoted data.
+ */
public void onDataDemoted(int dataID);
public void onDataFullScreenChange(int dataID, boolean full);
+ /**
+ * Callback when entering/leaving camera mode.
+ *
+ * @param toCamera {@code true} if entering camera mode. Otherwise,
+ * {@code false}
+ */
public void onSwitchMode(boolean toCamera);
}
+ /**
+ * An interface which defines the controller of {@link FilmStripView}.
+ */
public interface Controller {
public boolean isScalling();
@@ -306,16 +430,19 @@ public class FilmStripView extends ViewGroup {
}
}
+ /** Constructor. */
public FilmStripView(Context context) {
super(context);
init(context);
}
+ /** Constructor. */
public FilmStripView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
+ /** Constructor. */
public FilmStripView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context);
@@ -337,6 +464,11 @@ public class FilmStripView extends ViewGroup {
mSlop = (int) getContext().getResources().getDimension(R.dimen.pie_touch_slop);
}
+ /**
+ * Returns the controller.
+ *
+ * @return The {@code Controller}.
+ */
public Controller getController() {
return mController;
}
@@ -422,14 +554,11 @@ public class FilmStripView extends ViewGroup {
}
if (mDataAdapter != null) {
- mDataAdapter.suggestDecodeSize(boundWidth / 2, boundHeight / 2);
+ mDataAdapter.suggestViewSizeBound(boundWidth / 2, boundHeight / 2);
}
- for (int i = 0; i < mViewInfo.length; i++) {
- ViewInfo info = mViewInfo[i];
- if (mViewInfo[i] == null) {
- continue;
- }
+ for (ViewInfo info : mViewInfo) {
+ if (info == null) continue;
int id = info.getID();
int[] dim = calculateChildDimension(
@@ -437,21 +566,23 @@ public class FilmStripView extends ViewGroup {
mDataAdapter.getImageData(id).getHeight(),
boundWidth, boundHeight);
- mViewInfo[i].getView().measure(
- View.MeasureSpec.makeMeasureSpec(
- dim[0], View.MeasureSpec.EXACTLY),
- View.MeasureSpec.makeMeasureSpec(
- dim[1], View.MeasureSpec.EXACTLY));
+ info.getView().measure(
+ MeasureSpec.makeMeasureSpec(
+ dim[0], MeasureSpec.EXACTLY),
+ MeasureSpec.makeMeasureSpec(
+ dim[1], MeasureSpec.EXACTLY));
}
}
@Override
protected boolean fitSystemWindows(Rect insets) {
- // Set the position of the "View Photo Sphere" button.
- FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) mViewPhotoSphereButton
- .getLayoutParams();
- params.bottomMargin = insets.bottom;
- mViewPhotoSphereButton.setLayoutParams(params);
+ if (mViewPhotoSphereButton != null) {
+ // Set the position of the "View Photo Sphere" button.
+ FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) mViewPhotoSphereButton
+ .getLayoutParams();
+ params.bottomMargin = insets.bottom;
+ mViewPhotoSphereButton.setLayoutParams(params);
+ }
return super.fitSystemWindows(insets);
}
@@ -762,8 +893,7 @@ public class FilmStripView extends ViewGroup {
}
private void slideViewBack(View v) {
- v.animate()
- .translationX(0)
+ v.animate().translationX(0)
.alpha(1f)
.setDuration(DURATION_GEOMETRY_ADJUST)
.setInterpolator(mViewAnimInterpolator)
@@ -968,7 +1098,7 @@ public class FilmStripView extends ViewGroup {
public void setDataAdapter(DataAdapter adapter) {
mDataAdapter = adapter;
- mDataAdapter.suggestDecodeSize(getMeasuredWidth(), getMeasuredHeight());
+ mDataAdapter.suggestViewSizeBound(getMeasuredWidth(), getMeasuredHeight());
mDataAdapter.setListener(new DataAdapter.Listener() {
@Override
public void onDataLoaded() {