diff options
Diffstat (limited to 'src/com/android/gallery3d')
-rw-r--r-- | src/com/android/gallery3d/app/GalleryActionBar.java | 14 | ||||
-rw-r--r-- | src/com/android/gallery3d/app/MovieActivity.java | 36 | ||||
-rw-r--r-- | src/com/android/gallery3d/app/PhotoDataAdapter.java | 8 | ||||
-rw-r--r-- | src/com/android/gallery3d/app/PhotoPage.java | 54 | ||||
-rw-r--r-- | src/com/android/gallery3d/provider/GalleryProvider.java | 38 | ||||
-rw-r--r-- | src/com/android/gallery3d/ui/ActionModeHandler.java | 46 | ||||
-rw-r--r-- | src/com/android/gallery3d/ui/GLRootView.java | 95 | ||||
-rw-r--r-- | src/com/android/gallery3d/ui/MenuExecutor.java | 14 | ||||
-rw-r--r-- | src/com/android/gallery3d/ui/TileImageViewAdapter.java | 2 |
9 files changed, 254 insertions, 53 deletions
diff --git a/src/com/android/gallery3d/app/GalleryActionBar.java b/src/com/android/gallery3d/app/GalleryActionBar.java index 23e8f0b16..69f51bccb 100644 --- a/src/com/android/gallery3d/app/GalleryActionBar.java +++ b/src/com/android/gallery3d/app/GalleryActionBar.java @@ -130,12 +130,12 @@ public class GalleryActionBar implements ActionBar.OnNavigationListener { return null; } - public static ShareActionProvider initializeShareActionProvider(Menu menu) { + @TargetApi(ApiHelper.VERSION_CODES.ICE_CREAM_SANDWICH) + public static ShareActionProvider initializeShareActionProvider(Menu menu, + Context context) { MenuItem item = menu.findItem(R.id.action_share); - ShareActionProvider shareActionProvider = null; - if (item != null) { - shareActionProvider = (ShareActionProvider) item.getActionProvider(); - } + ShareActionProvider shareActionProvider = new ShareActionProvider(context); + item.setActionProvider(shareActionProvider); return shareActionProvider; } @@ -230,7 +230,9 @@ public class GalleryActionBar implements ActionBar.OnNavigationListener { @TargetApi(ApiHelper.VERSION_CODES.ICE_CREAM_SANDWICH) private void setHomeButtonEnabled(boolean enabled) { - mActionBar.setHomeButtonEnabled(enabled); + if (ApiHelper.HAS_ACTION_BAR_SET_HOME_BUTTON_ENABLED) { + mActionBar.setHomeButtonEnabled(enabled); + } } public void setDisplayOptions(boolean displayHomeAsUp, boolean showTitle) { diff --git a/src/com/android/gallery3d/app/MovieActivity.java b/src/com/android/gallery3d/app/MovieActivity.java index aa55c9bdf..0a2475acb 100644 --- a/src/com/android/gallery3d/app/MovieActivity.java +++ b/src/com/android/gallery3d/app/MovieActivity.java @@ -167,26 +167,38 @@ public class MovieActivity extends Activity { @Override public boolean onCreateOptionsMenu(Menu menu) { super.onCreateOptionsMenu(menu); - getMenuInflater().inflate(R.menu.movie, menu); - ShareActionProvider provider = GalleryActionBar.initializeShareActionProvider(menu); // Document says EXTRA_STREAM should be a content: Uri // So, we only share the video if it's "content:". - if (provider != null && ContentResolver.SCHEME_CONTENT - .equals(mUri.getScheme())) { - Intent intent = new Intent(Intent.ACTION_SEND); - intent.setType("video/*"); - intent.putExtra(Intent.EXTRA_STREAM, mUri); - provider.setShareIntent(intent); + if (ContentResolver.SCHEME_CONTENT.equals(mUri.getScheme())) { + initializeShareActionProvider(menu); + } else { + menu.findItem(R.id.action_share).setVisible(false); } - return true; } + @TargetApi(ApiHelper.VERSION_CODES.JELLY_BEAN) + private void initializeShareActionProvider(Menu menu) { + if (!ApiHelper.HAS_SHARE_ACTION_PROVIDER) return; + + ShareActionProvider provider = GalleryActionBar.initializeShareActionProvider( + menu, this); + provider.setShareIntent(createShareIntent()); + } + + private Intent createShareIntent() { + Intent intent = new Intent(Intent.ACTION_SEND); + intent.setType("video/*"); + intent.putExtra(Intent.EXTRA_STREAM, mUri); + return intent; + } + @Override public boolean onOptionsItemSelected(MenuItem item) { - if (item.getItemId() == android.R.id.home) { + int id = item.getItemId(); + if (id == android.R.id.home) { if (mTreatUpAsBack) { finish(); } else { @@ -194,6 +206,10 @@ public class MovieActivity extends Activity { finish(); } return true; + } else if (id == R.id.action_share) { + startActivity(Intent.createChooser(createShareIntent(), + getString(R.string.share))); + return true; } return false; } diff --git a/src/com/android/gallery3d/app/PhotoDataAdapter.java b/src/com/android/gallery3d/app/PhotoDataAdapter.java index 5339e7e0a..ae01dd9ec 100644 --- a/src/com/android/gallery3d/app/PhotoDataAdapter.java +++ b/src/com/android/gallery3d/app/PhotoDataAdapter.java @@ -955,6 +955,11 @@ public class PhotoDataAdapter implements PhotoPage.Model { updateImageCache(); updateTileProvider(); updateImageRequests(); + + if (mDataListener != null) { + mDataListener.onPhotoChanged(mCurrentIndex, mItemPath); + } + fireDataChange(); return null; } @@ -1072,7 +1077,8 @@ public class PhotoDataAdapter implements PhotoPage.Model { private int findIndexOfPathInCache(UpdateInfo info, Path path) { ArrayList<MediaItem> items = info.items; for (int i = 0, n = items.size(); i < n; ++i) { - if (items.get(i).getPath() == path) { + MediaItem item = items.get(i); + if (item != null && item.getPath() == path) { return i + info.contentStart; } } diff --git a/src/com/android/gallery3d/app/PhotoPage.java b/src/com/android/gallery3d/app/PhotoPage.java index 678ba6daf..36a3f876f 100644 --- a/src/com/android/gallery3d/app/PhotoPage.java +++ b/src/com/android/gallery3d/app/PhotoPage.java @@ -120,7 +120,7 @@ public class PhotoPage extends ActivityState implements private MediaItem mCurrentPhoto = null; private MenuExecutor mMenuExecutor; private boolean mIsActive; - private ShareActionProvider mShareActionProvider; + private Object mShareActionProvider; // class ShareActionProvider private String mSetPathString; // This is the original mSetPathString before adding the camera preview item. private String mOriginalSetPathString; @@ -325,20 +325,34 @@ public class PhotoPage extends ActivityState implements } } + private Intent createShareIntent(Path path) { + DataManager manager = mActivity.getDataManager(); + Uri uri = manager.getContentUri(path); + int type = manager.getMediaType(path); + Intent intent = new Intent(Intent.ACTION_SEND); + intent.setType(MenuExecutor.getMimeType(type)); + intent.putExtra(Intent.EXTRA_STREAM, uri); + return intent; + } + private void updateShareURI(Path path) { - if (mShareActionProvider != null) { - DataManager manager = mActivity.getDataManager(); - int type = manager.getMediaType(path); - Intent intent = new Intent(Intent.ACTION_SEND); - intent.setType(MenuExecutor.getMimeType(type)); - Uri uri = manager.getContentUri(path); - intent.putExtra(Intent.EXTRA_STREAM, uri); - mShareActionProvider.setShareIntent(intent); - setNfcBeamPushUris(new Uri[]{uri}); - mPendingSharePath = null; - } else { - // This happens when ActionBar is not created yet. - mPendingSharePath = path; + DataManager manager = mActivity.getDataManager(); + Uri uri = manager.getContentUri(path); + setNfcBeamPushUris(new Uri[]{uri}); + setShareActionProviderIntent(path); + } + + @TargetApi(ApiHelper.VERSION_CODES.ICE_CREAM_SANDWICH) + private void setShareActionProviderIntent(Path path) { + if (ApiHelper.HAS_SHARE_ACTION_PROVIDER) { + if (mShareActionProvider != null) { + Intent intent = createShareIntent(path); + ((ShareActionProvider) mShareActionProvider).setShareIntent(intent); + mPendingSharePath = null; + } else { + // This happens when ActionBar is not created yet. + mPendingSharePath = path; + } } } @@ -533,7 +547,11 @@ public class PhotoPage extends ActivityState implements protected boolean onCreateActionBar(Menu menu) { MenuInflater inflater = ((Activity) mActivity).getMenuInflater(); inflater.inflate(R.menu.photo, menu); - mShareActionProvider = GalleryActionBar.initializeShareActionProvider(menu); + + if (ApiHelper.HAS_SHARE_ACTION_PROVIDER) { + mShareActionProvider = GalleryActionBar.initializeShareActionProvider( + menu, mActivity.getAndroidContext()); + } if (mPendingSharePath != null) updateShareURI(mPendingSharePath); mMenu = menu; updateMenuOperations(); @@ -634,6 +652,12 @@ public class PhotoPage extends ActivityState implements mMenuExecutor.onMenuClicked(item, confirmMsg, new ImportCompleteListener(mActivity)); return true; + case R.id.action_share: + Activity activity = (Activity) mActivity; + Intent intent = createShareIntent(mCurrentPhoto.getPath()); + activity.startActivity(Intent.createChooser(intent, + activity.getString(R.string.share))); + return true; default : return false; } diff --git a/src/com/android/gallery3d/provider/GalleryProvider.java b/src/com/android/gallery3d/provider/GalleryProvider.java index 79ec66be8..45f47a42c 100644 --- a/src/com/android/gallery3d/provider/GalleryProvider.java +++ b/src/com/android/gallery3d/provider/GalleryProvider.java @@ -22,13 +22,14 @@ import android.content.Context; import android.database.Cursor; import android.database.MatrixCursor; import android.net.Uri; +import android.os.AsyncTask; import android.os.Binder; -import android.os.Bundle; import android.os.ParcelFileDescriptor; import android.provider.MediaStore.Images.ImageColumns; import android.util.Log; import com.android.gallery3d.app.GalleryApp; +import com.android.gallery3d.common.AsyncTaskUtil; import com.android.gallery3d.common.Utils; import com.android.gallery3d.data.DataManager; import com.android.gallery3d.data.MediaItem; @@ -211,7 +212,7 @@ public class GalleryProvider extends ContentProvider { if (PicasaSource.isPicasaImage(object)) { return PicasaSource.openFile(getContext(), object, mode); } else if (object instanceof MtpImage) { - return openPipeHelper(uri, null, null, null, + return openPipeHelper(null, new MtpPipeDataWriter((MtpImage) object)); } else { throw new FileNotFoundException("unspported type: " + object); @@ -226,6 +227,34 @@ public class GalleryProvider extends ContentProvider { throw new UnsupportedOperationException(); } + private static interface PipeDataWriter<T> { + void writeDataToPipe(ParcelFileDescriptor output, T args); + } + + // Modified from ContentProvider.openPipeHelper. We are target at API LEVEL 10. + // But openPipeHelper is available in API LEVEL 11. + private static <T> ParcelFileDescriptor openPipeHelper( + final T args, final PipeDataWriter<T> func) throws FileNotFoundException { + try { + final ParcelFileDescriptor[] pipe = ParcelFileDescriptor.createPipe(); + AsyncTask<Object, Object, Object> task = new AsyncTask<Object, Object, Object>() { + @Override + protected Object doInBackground(Object... params) { + try { + func.writeDataToPipe(pipe[1], args); + return null; + } finally { + Utils.closeSilently(pipe[1]); + } + } + }; + AsyncTaskUtil.executeInParallel(task, (Object[]) null); + return pipe[0]; + } catch (IOException e) { + throw new FileNotFoundException("failure making pipe"); + } + } + private final class MtpPipeDataWriter implements PipeDataWriter<Object> { private final MtpImage mImage; @@ -234,14 +263,13 @@ public class GalleryProvider extends ContentProvider { } @Override - public void writeDataToPipe(ParcelFileDescriptor output, - Uri uri, String mimeType, Bundle opts, Object args) { + public void writeDataToPipe(ParcelFileDescriptor output, Object args) { OutputStream os = null; try { os = new ParcelFileDescriptor.AutoCloseOutputStream(output); os.write(mImage.getImageData()); } catch (IOException e) { - Log.w(TAG, "fail to download: " + uri, e); + Log.w(TAG, "fail to download: " + mImage.toString(), e); } finally { Utils.closeSilently(os); } diff --git a/src/com/android/gallery3d/ui/ActionModeHandler.java b/src/com/android/gallery3d/ui/ActionModeHandler.java index 0b5cd54cd..12a0e89f4 100644 --- a/src/com/android/gallery3d/ui/ActionModeHandler.java +++ b/src/com/android/gallery3d/ui/ActionModeHandler.java @@ -70,7 +70,7 @@ public class ActionModeHandler implements private ActionModeListener mListener; private Future<?> mMenuTask; private final Handler mMainHandler; - private ShareActionProvider mShareActionProvider; + private Object mShareActionProvider; // class ShareActionProvider public ActionModeHandler( GalleryActivity activity, SelectionManager selectionManager) { @@ -166,21 +166,32 @@ public class ActionModeHandler implements public boolean onCreateActionMode(ActionMode mode, Menu menu) { MenuInflater inflater = mode.getMenuInflater(); inflater.inflate(R.menu.operation, menu); - - mShareActionProvider = GalleryActionBar.initializeShareActionProvider(menu); - OnShareTargetSelectedListener listener = new OnShareTargetSelectedListener() { - @Override - public boolean onShareTargetSelected(ShareActionProvider source, Intent intent) { - mSelectionManager.leaveSelectionMode(); - return false; - } - }; - - mShareActionProvider.setOnShareTargetSelectedListener(listener); + initializeShareActionProvider(menu); mMenu = menu; return true; } + @TargetApi(ApiHelper.VERSION_CODES.ICE_CREAM_SANDWICH) + private void initializeShareActionProvider(Menu menu) { + if (ApiHelper.HAS_SHARE_ACTION_PROVIDER) { + mShareActionProvider = GalleryActionBar.initializeShareActionProvider(menu, + mActivity.getAndroidContext()); + OnShareTargetSelectedListener listener = new OnShareTargetSelectedListener() { + @Override + public boolean onShareTargetSelected(ShareActionProvider source, Intent intent) { + mSelectionManager.leaveSelectionMode(); + return false; + } + }; + ((ShareActionProvider) mShareActionProvider).setOnShareTargetSelectedListener(listener); + } + } + + @TargetApi(ApiHelper.VERSION_CODES.ICE_CREAM_SANDWICH) + private void setShareActionProviderIntent(Intent intent) { + ((ShareActionProvider) mShareActionProvider).setShareIntent(intent); + } + @Override public void onDestroyActionMode(ActionMode mode) { mSelectionManager.leaveSelectionMode(); @@ -288,8 +299,9 @@ public class ActionModeHandler implements updateSelectionMenu(); // Disable share action until share intent is in good shape - final MenuItem item = mShareActionProvider != null ? - mMenu.findItem(R.id.action_share) : null; + final MenuItem item = (!ApiHelper.HAS_SHARE_ACTION_PROVIDER + || (mShareActionProvider != null)) + ? mMenu.findItem(R.id.action_share) : null; final boolean supportShare = item != null; if (supportShare) item.setEnabled(false); @@ -311,7 +323,11 @@ public class ActionModeHandler implements MenuExecutor.updateMenuOperation(mMenu, operation); if (supportShare) { item.setEnabled(true); - mShareActionProvider.setShareIntent(intent); + if (ApiHelper.HAS_SHARE_ACTION_PROVIDER) { + setShareActionProviderIntent(intent); + } else { + mMenuExecutor.setShareIntent(intent); + } } } } diff --git a/src/com/android/gallery3d/ui/GLRootView.java b/src/com/android/gallery3d/ui/GLRootView.java index 9fd9473dc..7f717b7b7 100644 --- a/src/com/android/gallery3d/ui/GLRootView.java +++ b/src/com/android/gallery3d/ui/GLRootView.java @@ -25,7 +25,9 @@ import android.os.Build; import android.os.Process; import android.os.SystemClock; import android.util.AttributeSet; +import android.util.FloatMath; import android.view.MotionEvent; +import android.view.MotionEvent.PointerCoords; import android.view.SurfaceHolder; import android.view.View; @@ -430,7 +432,7 @@ public class GLRootView extends GLSurfaceView } if (mCompensation != 0) { - event.transform(mCompensationMatrix); + event = transformEvent(event, mCompensationMatrix); } mRenderLock.lock(); @@ -447,6 +449,97 @@ public class GLRootView extends GLSurfaceView } } + private static MotionEvent transformEvent(MotionEvent e, Matrix m) { + // We try to use the new transform method if possible because it uses + // less memory. + if (ApiHelper.HAS_MOTION_EVENT_TRANSFORM) { + return transformEventNew(e, m); + } else { + return transformEventOld(e, m); + } + } + + @TargetApi(ApiHelper.VERSION_CODES.HONEYCOMB) + private static MotionEvent transformEventNew(MotionEvent e, Matrix m) { + e.transform(m); + return e; + } + + // This is copied from Input.cpp in the android framework. + private static MotionEvent transformEventOld(MotionEvent e, Matrix m) { + long downTime = e.getDownTime(); + long eventTime = e.getEventTime(); + int action = e.getAction(); + int pointerCount = e.getPointerCount(); + int[] pointerIds = getPointerIds(e); + PointerCoords[] pointerCoords = getPointerCoords(e); + int metaState = e.getMetaState(); + float xPrecision = e.getXPrecision(); + float yPrecision = e.getYPrecision(); + int deviceId = e.getDeviceId(); + int edgeFlags = e.getEdgeFlags(); + int source = e.getSource(); + int flags = e.getFlags(); + + // Copy the x and y coordinates into an array, map them, and copy back. + float[] xy = new float[pointerCoords.length * 2]; + for (int i = 0; i < pointerCount;i++) { + xy[2 * i] = pointerCoords[i].x; + xy[2 * i + 1] = pointerCoords[i].y; + } + m.mapPoints(xy); + for (int i = 0; i < pointerCount;i++) { + pointerCoords[i].x = xy[2 * i]; + pointerCoords[i].y = xy[2 * i + 1]; + pointerCoords[i].orientation = transformAngle( + m, pointerCoords[i].orientation); + } + + MotionEvent n = MotionEvent.obtain(downTime, eventTime, action, + pointerCount, pointerIds, pointerCoords, metaState, xPrecision, + yPrecision, deviceId, edgeFlags, source, flags); + + return n; + } + + private static int[] getPointerIds(MotionEvent e) { + int n = e.getPointerCount(); + int[] r = new int[n]; + for (int i = 0; i < n; i++) { + r[i] = e.getPointerId(i); + } + return r; + } + + private static PointerCoords[] getPointerCoords(MotionEvent e) { + int n = e.getPointerCount(); + PointerCoords[] r = new PointerCoords[n]; + for (int i = 0; i < n; i++) { + r[i] = new PointerCoords(); + e.getPointerCoords(i, r[i]); + } + return r; + } + + private static float transformAngle(Matrix m, float angleRadians) { + // Construct and transform a vector oriented at the specified clockwise + // angle from vertical. Coordinate system: down is increasing Y, right is + // increasing X. + float[] v = new float[2]; + v[0] = FloatMath.sin(angleRadians); + v[1] = -FloatMath.cos(angleRadians); + m.mapVectors(v); + + // Derive the transformed vector's clockwise angle from vertical. + float result = (float) Math.atan2(v[0], -v[1]); + if (result < -Math.PI / 2) { + result += Math.PI; + } else if (result > Math.PI / 2) { + result -= Math.PI; + } + return result; + } + private class IdleRunner implements Runnable { // true if the idle runner is in the queue private boolean mActive = false; diff --git a/src/com/android/gallery3d/ui/MenuExecutor.java b/src/com/android/gallery3d/ui/MenuExecutor.java index aaf5d3974..2ff0327da 100644 --- a/src/com/android/gallery3d/ui/MenuExecutor.java +++ b/src/com/android/gallery3d/ui/MenuExecutor.java @@ -32,6 +32,7 @@ import android.view.MenuItem; import com.android.gallery3d.R; import com.android.gallery3d.app.CropImage; import com.android.gallery3d.app.GalleryActivity; +import com.android.gallery3d.common.ApiHelper; import com.android.gallery3d.common.Utils; import com.android.gallery3d.data.DataManager; import com.android.gallery3d.data.MediaItem; @@ -60,6 +61,7 @@ public class MenuExecutor { private Future<?> mTask; // wait the operation to finish when we want to stop it. private boolean mWaitOnStop; + private Intent mShareIntent; private final GalleryActivity mActivity; private final SelectionManager mSelectionManager; @@ -235,6 +237,14 @@ public class MenuExecutor { case R.id.action_import: title = R.string.Import; break; + case R.id.action_share: { + if (!ApiHelper.HAS_SHARE_ACTION_PROVIDER) { + Activity activity = (Activity) mActivity; + activity.startActivity(Intent.createChooser( + mShareIntent, activity.getString(R.string.share))); + } + return; + } default: return; } @@ -309,6 +319,10 @@ public class MenuExecutor { mWaitOnStop = waitOnStop; } + public void setShareIntent(Intent intent) { + mShareIntent = intent; + } + public static String getMimeType(int type) { switch (type) { case MediaObject.MEDIA_TYPE_IMAGE : diff --git a/src/com/android/gallery3d/ui/TileImageViewAdapter.java b/src/com/android/gallery3d/ui/TileImageViewAdapter.java index 4865e5c67..a14df754a 100644 --- a/src/com/android/gallery3d/ui/TileImageViewAdapter.java +++ b/src/com/android/gallery3d/ui/TileImageViewAdapter.java @@ -16,6 +16,7 @@ package com.android.gallery3d.ui; +import android.annotation.TargetApi; import android.graphics.Bitmap; import android.graphics.Bitmap.Config; import android.graphics.BitmapFactory; @@ -107,6 +108,7 @@ public class TileImageViewAdapter implements TileImageView.Model { // // As a result, we should decode region (50-6, 50-6, 250+6, 250+6) or // (44, 44, 256, 256) from the original photo and down sample it to 106. + @TargetApi(ApiHelper.VERSION_CODES.HONEYCOMB) @Override public Bitmap getTile(int level, int x, int y, int tileSize, int borderSize, BitmapPool pool) { |