Reconcile with ics-factoryrom-release
Change-Id: I445a06a1c4486a76a9278c2ab57415cd902f8927
diff --git a/gallerycommon/src/com/android/gallery3d/common/BitmapUtils.java b/gallerycommon/src/com/android/gallery3d/common/BitmapUtils.java
index aaf4f66..c34e896 100644
--- a/gallerycommon/src/com/android/gallery3d/common/BitmapUtils.java
+++ b/gallerycommon/src/com/android/gallery3d/common/BitmapUtils.java
@@ -85,7 +85,7 @@
// minSideLength long. If that's not possible, return 1.
public static int computeSampleSizeLarger(int w, int h,
int minSideLength) {
- int initialSize = Math.min(w / minSideLength, h / minSideLength);
+ int initialSize = Math.max(w / minSideLength, h / minSideLength);
if (initialSize <= 1) return 1;
return initialSize <= 8
@@ -155,6 +155,17 @@
return resizeBitmapByScale(bitmap, scale, recycle);
}
+ // Resize the bitmap if each side is >= targetSize * 2
+ public static Bitmap resizeDownIfTooBig(
+ Bitmap bitmap, int targetSize, boolean recycle) {
+ int srcWidth = bitmap.getWidth();
+ int srcHeight = bitmap.getHeight();
+ float scale = Math.max(
+ (float) targetSize / srcWidth, (float) targetSize / srcHeight);
+ if (scale > 0.5f) return bitmap;
+ return resizeBitmapByScale(bitmap, scale, recycle);
+ }
+
// Crops a square from the center of the original image.
public static Bitmap cropCenter(Bitmap bitmap, boolean recycle) {
int width = bitmap.getWidth();
diff --git a/gallerycommon/src/com/android/gallery3d/common/EntrySchema.java b/gallerycommon/src/com/android/gallery3d/common/EntrySchema.java
index d652ac9..46de03f 100644
--- a/gallerycommon/src/com/android/gallery3d/common/EntrySchema.java
+++ b/gallerycommon/src/com/android/gallery3d/common/EntrySchema.java
@@ -29,14 +29,14 @@
@SuppressWarnings("unused")
private static final String TAG = "EntrySchema";
- private static final int TYPE_STRING = 0;
- private static final int TYPE_BOOLEAN = 1;
- private static final int TYPE_SHORT = 2;
- private static final int TYPE_INT = 3;
- private static final int TYPE_LONG = 4;
- private static final int TYPE_FLOAT = 5;
- private static final int TYPE_DOUBLE = 6;
- private static final int TYPE_BLOB = 7;
+ public static final int TYPE_STRING = 0;
+ public static final int TYPE_BOOLEAN = 1;
+ public static final int TYPE_SHORT = 2;
+ public static final int TYPE_INT = 3;
+ public static final int TYPE_LONG = 4;
+ public static final int TYPE_FLOAT = 5;
+ public static final int TYPE_DOUBLE = 6;
+ public static final int TYPE_BLOB = 7;
private static final String SQLITE_TYPES[] = {
"TEXT", "INTEGER", "INTEGER", "INTEGER", "INTEGER", "REAL", "REAL", "NONE" };
@@ -91,7 +91,7 @@
return -1;
}
- private ColumnInfo getColumn(String columnName) {
+ public ColumnInfo getColumn(String columnName) {
int index = getColumnIndex(columnName);
return (index < 0) ? null : mColumnInfo[index];
}
diff --git a/src/com/android/gallery3d/app/AlbumPage.java b/src/com/android/gallery3d/app/AlbumPage.java
index 672c0da..55feb38 100644
--- a/src/com/android/gallery3d/app/AlbumPage.java
+++ b/src/com/android/gallery3d/app/AlbumPage.java
@@ -148,6 +148,18 @@
}
}
+ private void onDown(int index) {
+ MediaItem item = mAlbumDataAdapter.get(index);
+ Path path = (item == null) ? null : item.getPath();
+ mSelectionManager.setPressedPath(path);
+ mAlbumView.invalidate();
+ }
+
+ private void onUp() {
+ mSelectionManager.setPressedPath(null);
+ mAlbumView.invalidate();
+ }
+
public void onSingleTapUp(int slotIndex) {
MediaItem item = mAlbumDataAdapter.get(slotIndex);
if (item == null) {
@@ -357,15 +369,26 @@
mSelectionManager.setSelectionListener(this);
mGridDrawer = new GridDrawer((Context) mActivity, mSelectionManager);
Config.AlbumPage config = Config.AlbumPage.get((Context) mActivity);
- mAlbumView = new AlbumView(mActivity,
- config.slotWidth, config.slotHeight, config.displayItemSize);
+ mAlbumView = new AlbumView(mActivity, config.slotViewSpec,
+ 0 /* don't cache thumbnail */);
mAlbumView.setSelectionDrawer(mGridDrawer);
mRootPane.addComponent(mAlbumView);
mAlbumView.setListener(new SlotView.SimpleListener() {
@Override
+ public void onDown(int index) {
+ AlbumPage.this.onDown(index);
+ }
+
+ @Override
+ public void onUp() {
+ AlbumPage.this.onUp();
+ }
+
+ @Override
public void onSingleTapUp(int slotIndex) {
AlbumPage.this.onSingleTapUp(slotIndex);
}
+
@Override
public void onLongTap(int slotIndex) {
AlbumPage.this.onLongTap(slotIndex);
@@ -395,7 +418,8 @@
private void showDetails() {
mShowDetails = true;
if (mDetailsHelper == null) {
- mHighlightDrawer = new HighlightDrawer(mActivity.getAndroidContext());
+ mHighlightDrawer = new HighlightDrawer(mActivity.getAndroidContext(),
+ mSelectionManager);
mDetailsHelper = new DetailsHelper(mActivity, mRootPane, mDetailsSource);
mDetailsHelper.setCloseListener(new CloseListener() {
public void onClose() {
@@ -521,10 +545,6 @@
break;
}
case SelectionManager.SELECT_ALL_MODE: {
- int count = mSelectionManager.getSelectedCount();
- String format = mActivity.getResources().getQuantityString(
- R.plurals.number_of_items_selected, count);
- mActionModeHandler.setTitle(String.format(format, count));
mActionModeHandler.updateSupportedOperation();
mRootPane.invalidate();
break;
diff --git a/src/com/android/gallery3d/app/AlbumSetDataAdapter.java b/src/com/android/gallery3d/app/AlbumSetDataAdapter.java
index 85f3bf5..8322d2b 100644
--- a/src/com/android/gallery3d/app/AlbumSetDataAdapter.java
+++ b/src/com/android/gallery3d/app/AlbumSetDataAdapter.java
@@ -41,7 +41,7 @@
private static final int INDEX_NONE = -1;
private static final int MIN_LOAD_COUNT = 4;
- private static final int MAX_COVER_COUNT = 4;
+ private static final int MAX_COVER_COUNT = 1;
private static final int MSG_LOAD_START = 1;
private static final int MSG_LOAD_FINISH = 2;
diff --git a/src/com/android/gallery3d/app/AlbumSetPage.java b/src/com/android/gallery3d/app/AlbumSetPage.java
index 0970572..0726ba1 100644
--- a/src/com/android/gallery3d/app/AlbumSetPage.java
+++ b/src/com/android/gallery3d/app/AlbumSetPage.java
@@ -63,7 +63,7 @@
public static final String KEY_MEDIA_PATH = "media-path";
public static final String KEY_SET_TITLE = "set-title";
public static final String KEY_SET_SUBTITLE = "set-subtitle";
- public static final String KEY_SELECTED_TAB_TYPE = "selected-tab";
+ public static final String KEY_SELECTED_CLUSTER_TYPE = "selected-cluster";
private static final int DATA_CACHE_SIZE = 256;
private static final int REQUEST_DO_ANIMATION = 1;
@@ -76,7 +76,8 @@
private MediaSet mMediaSet;
private String mTitle;
private String mSubtitle;
- private boolean mShowClusterTabs;
+ private boolean mShowClusterMenu;
+ private int mSelectedAction;
protected SelectionManager mSelectionManager;
private AlbumSetDataAdapter mAlbumSetDataAdapter;
@@ -209,6 +210,18 @@
}
}
+ private void onDown(int index) {
+ MediaSet set = mAlbumSetDataAdapter.getMediaSet(index);
+ Path path = (set == null) ? null : set.getPath();
+ mSelectionManager.setPressedPath(path);
+ mAlbumSetView.invalidate();
+ }
+
+ private void onUp() {
+ mSelectionManager.setPressedPath(null);
+ mAlbumSetView.invalidate();
+ }
+
public void onLongTap(int slotIndex) {
if (mGetContent || mGetAlbum) return;
if (mShowDetails) {
@@ -229,7 +242,7 @@
String newPath = FilterUtils.switchClusterPath(basePath, clusterType);
Bundle data = new Bundle(getData());
data.putString(AlbumSetPage.KEY_MEDIA_PATH, newPath);
- data.putInt(KEY_SELECTED_TAB_TYPE, clusterType);
+ data.putInt(KEY_SELECTED_CLUSTER_TYPE, clusterType);
mAlbumSetView.savePositions(PositionRepository.getInstance(mActivity));
mActivity.getStateManager().switchState(this, AlbumSetPage.class, data);
}
@@ -260,8 +273,8 @@
mDetailsSource = new MyDetailsSource();
GalleryActionBar actionBar = mActivity.getGalleryActionBar();
if (actionBar != null) {
- actionBar.setSelectedTab(data.getInt(
- AlbumSetPage.KEY_SELECTED_TAB_TYPE, FilterUtils.CLUSTER_BY_ALBUM));
+ mSelectedAction = data.getInt(
+ AlbumSetPage.KEY_SELECTED_CLUSTER_TYPE, FilterUtils.CLUSTER_BY_ALBUM);
}
startTransition();
}
@@ -277,7 +290,7 @@
mEyePosition.pause();
DetailsHelper.pause();
GalleryActionBar actionBar = mActivity.getGalleryActionBar();
- if (actionBar != null) actionBar.hideClusterTabs();
+ if (actionBar != null) actionBar.hideClusterMenu();
}
@Override
@@ -291,7 +304,7 @@
mEyePosition.resume();
mActionModeHandler.resume();
GalleryActionBar actionBar = mActivity.getGalleryActionBar();
- if (mShowClusterTabs && actionBar != null) actionBar.showClusterTabs(this);
+ if (mShowClusterMenu && actionBar != null) actionBar.showClusterMenu(mSelectedAction, this);
}
private void initializeData(Bundle data) {
@@ -313,14 +326,23 @@
mGridDrawer = new GridDrawer((Context) mActivity, mSelectionManager);
Config.AlbumSetPage config = Config.AlbumSetPage.get((Context) mActivity);
mAlbumSetView = new AlbumSetView(mActivity, mGridDrawer,
- config.slotWidth, config.slotHeight,
- config.displayItemSize, config.labelFontSize,
- config.labelOffsetY, config.labelMargin);
+ config.slotViewSpec, config.labelSpec);
mAlbumSetView.setListener(new SlotView.SimpleListener() {
@Override
+ public void onDown(int index) {
+ AlbumSetPage.this.onDown(index);
+ }
+
+ @Override
+ public void onUp() {
+ AlbumSetPage.this.onUp();
+ }
+
+ @Override
public void onSingleTapUp(int slotIndex) {
AlbumSetPage.this.onSingleTapUp(slotIndex);
}
+
@Override
public void onLongTap(int slotIndex) {
AlbumSetPage.this.onLongTap(slotIndex);
@@ -363,7 +385,7 @@
inflater.inflate(R.menu.pickup, menu);
actionBar.setTitle(R.string.select_album);
} else {
- mShowClusterTabs = !inAlbum;
+ mShowClusterMenu = !inAlbum;
inflater.inflate(R.menu.albumset, menu);
if (mTitle != null) {
actionBar.setTitle(mTitle);
@@ -485,13 +507,13 @@
switch (mode) {
case SelectionManager.ENTER_SELECTION_MODE: {
- mActivity.getGalleryActionBar().hideClusterTabs();
+ mActivity.getGalleryActionBar().hideClusterMenu();
mActionMode = mActionModeHandler.startActionMode();
break;
}
case SelectionManager.LEAVE_SELECTION_MODE: {
mActionMode.finish();
- mActivity.getGalleryActionBar().showClusterTabs(this);
+ mActivity.getGalleryActionBar().showClusterMenu(mSelectedAction, this);
mRootPane.invalidate();
break;
}
@@ -519,7 +541,8 @@
private void showDetails() {
mShowDetails = true;
if (mDetailsHelper == null) {
- mHighlightDrawer = new HighlightDrawer(mActivity.getAndroidContext());
+ mHighlightDrawer = new HighlightDrawer(mActivity.getAndroidContext(),
+ mSelectionManager);
mDetailsHelper = new DetailsHelper(mActivity, mRootPane, mDetailsSource);
mDetailsHelper.setCloseListener(new CloseListener() {
public void onClose() {
diff --git a/src/com/android/gallery3d/app/Config.java b/src/com/android/gallery3d/app/Config.java
index 4586235..914ea55 100644
--- a/src/com/android/gallery3d/app/Config.java
+++ b/src/com/android/gallery3d/app/Config.java
@@ -17,6 +17,8 @@
package com.android.gallery3d.app;
import com.android.gallery3d.R;
+import com.android.gallery3d.ui.SlotView;
+import com.android.gallery3d.ui.AlbumSetView;
import android.content.Context;
import android.content.res.Resources;
@@ -25,12 +27,8 @@
public static class AlbumSetPage {
private static AlbumSetPage sInstance;
- public final int slotWidth;
- public final int slotHeight;
- public final int displayItemSize;
- public final int labelFontSize;
- public final int labelOffsetY;
- public final int labelMargin;
+ public SlotView.Spec slotViewSpec;
+ public AlbumSetView.LabelSpec labelSpec;
public static synchronized AlbumSetPage get(Context context) {
if (sInstance == null) {
@@ -41,21 +39,34 @@
private AlbumSetPage(Context context) {
Resources r = context.getResources();
- slotWidth = r.getDimensionPixelSize(R.dimen.albumset_slot_width);
- slotHeight = r.getDimensionPixelSize(R.dimen.albumset_slot_height);
- displayItemSize = r.getDimensionPixelSize(R.dimen.albumset_display_item_size);
- labelFontSize = r.getDimensionPixelSize(R.dimen.albumset_label_font_size);
- labelOffsetY = r.getDimensionPixelSize(R.dimen.albumset_label_offset_y);
- labelMargin = r.getDimensionPixelSize(R.dimen.albumset_label_margin);
+
+ slotViewSpec = new SlotView.Spec();
+ slotViewSpec.rowsLand = r.getInteger(R.integer.albumset_rows_land);
+ slotViewSpec.rowsPort = r.getInteger(R.integer.albumset_rows_port);
+ slotViewSpec.slotGap = r.getDimensionPixelSize(R.dimen.albumset_slot_gap);
+
+ labelSpec = new AlbumSetView.LabelSpec();
+ labelSpec.labelBackgroundHeight = r.getDimensionPixelSize(
+ R.dimen.albumset_label_background_height);
+ labelSpec.titleOffset = r.getDimensionPixelSize(
+ R.dimen.albumset_title_offset);
+ labelSpec.countOffset = r.getDimensionPixelSize(
+ R.dimen.albumset_count_offset);
+ labelSpec.titleFontSize = r.getDimensionPixelSize(
+ R.dimen.albumset_title_font_size);
+ labelSpec.countFontSize = r.getDimensionPixelSize(
+ R.dimen.albumset_count_font_size);
+ labelSpec.leftMargin = r.getDimensionPixelSize(
+ R.dimen.albumset_left_margin);
+ labelSpec.iconSize = r.getDimensionPixelSize(
+ R.dimen.albumset_icon_size);
}
}
public static class AlbumPage {
private static AlbumPage sInstance;
- public final int slotWidth;
- public final int slotHeight;
- public final int displayItemSize;
+ public SlotView.Spec slotViewSpec;
public static synchronized AlbumPage get(Context context) {
if (sInstance == null) {
@@ -66,20 +77,19 @@
private AlbumPage(Context context) {
Resources r = context.getResources();
- slotWidth = r.getDimensionPixelSize(R.dimen.album_slot_width);
- slotHeight = r.getDimensionPixelSize(R.dimen.album_slot_height);
- displayItemSize = r.getDimensionPixelSize(R.dimen.album_display_item_size);
+
+ slotViewSpec = new SlotView.Spec();
+ slotViewSpec.rowsLand = r.getInteger(R.integer.album_rows_land);
+ slotViewSpec.rowsPort = r.getInteger(R.integer.album_rows_port);
+ slotViewSpec.slotGap = r.getDimensionPixelSize(R.dimen.album_slot_gap);
}
}
public static class ManageCachePage extends AlbumSetPage {
private static ManageCachePage sInstance;
- public final int cacheBarHeight;
- public final int cacheBarPinLeftMargin;
- public final int cacheBarPinRightMargin;
- public final int cacheBarButtonRightMargin;
- public final int cacheBarFontSize;
+ public final int cachePinSize;
+ public final int cachePinMargin;
public static synchronized ManageCachePage get(Context context) {
if (sInstance == null) {
@@ -91,13 +101,8 @@
public ManageCachePage(Context context) {
super(context);
Resources r = context.getResources();
- cacheBarHeight = r.getDimensionPixelSize(R.dimen.cache_bar_height);
- cacheBarPinLeftMargin = r.getDimensionPixelSize(R.dimen.cache_bar_pin_left_margin);
- cacheBarPinRightMargin = r.getDimensionPixelSize(
- R.dimen.cache_bar_pin_right_margin);
- cacheBarButtonRightMargin = r.getDimensionPixelSize(
- R.dimen.cache_bar_button_right_margin);
- cacheBarFontSize = r.getDimensionPixelSize(R.dimen.cache_bar_font_size);
+ cachePinSize = r.getDimensionPixelSize(R.dimen.cache_pin_size);
+ cachePinMargin = r.getDimensionPixelSize(R.dimen.cache_pin_margin);
}
}
diff --git a/src/com/android/gallery3d/app/GalleryActionBar.java b/src/com/android/gallery3d/app/GalleryActionBar.java
index 3df5e91..98a35a1 100644
--- a/src/com/android/gallery3d/app/GalleryActionBar.java
+++ b/src/com/android/gallery3d/app/GalleryActionBar.java
@@ -19,19 +19,22 @@
import com.android.gallery3d.R;
import android.app.ActionBar;
-import android.app.ActionBar.Tab;
import android.app.Activity;
import android.app.AlertDialog;
-import android.app.FragmentTransaction;
import android.content.Context;
import android.content.DialogInterface;
+import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
import android.widget.ShareActionProvider;
+import android.widget.TextView;
import java.util.ArrayList;
-public class GalleryActionBar implements ActionBar.TabListener {
+public class GalleryActionBar implements ActionBar.OnNavigationListener {
private static final String TAG = "GalleryActionBar";
public interface ClusterRunner {
@@ -42,7 +45,7 @@
public int action;
public boolean enabled;
public boolean visible;
- public int tabTitle;
+ public int spinnerTitle;
public int dialogTitle;
public int clusterBy;
@@ -51,11 +54,11 @@
this(action, applied, enabled, title, title, clusterBy);
}
- public ActionItem(int action, boolean applied, boolean enabled, int tabTitle,
+ public ActionItem(int action, boolean applied, boolean enabled, int spinnerTitle,
int dialogTitle, int clusterBy) {
this.action = action;
this.enabled = enabled;
- this.tabTitle = tabTitle;
+ this.spinnerTitle = spinnerTitle;
this.dialogTitle = dialogTitle;
this.clusterBy = clusterBy;
this.visible = true;
@@ -75,23 +78,47 @@
R.string.group_by_tags)
};
+ private class ClusterAdapter extends BaseAdapter {
+
+ public int getCount() {
+ return sClusterItems.length;
+ }
+
+ public Object getItem(int position) {
+ return sClusterItems[position];
+ }
+
+ public long getItemId(int position) {
+ return sClusterItems[position].action;
+ }
+
+ public View getView(int position, View convertView, ViewGroup parent) {
+ if (convertView == null) {
+ convertView = mInflater.inflate(R.layout.action_bar_text,
+ parent, false);
+ }
+ TextView view = (TextView) convertView;
+ view.setText(sClusterItems[position].spinnerTitle);
+ return convertView;
+ }
+ }
+
private ClusterRunner mClusterRunner;
private CharSequence[] mTitles;
private ArrayList<Integer> mActions;
private Context mContext;
+ private LayoutInflater mInflater;
+ private GalleryActivity mActivity;
private ActionBar mActionBar;
- // We need this because ActionBar.getSelectedTab() doesn't work when
- // ActionBar is hidden.
- private Tab mCurrentTab;
+ private int mCurrentIndex;
+ private ClusterAdapter mAdapter = new ClusterAdapter();
- public GalleryActionBar(Activity activity) {
- mActionBar = activity.getActionBar();
- mContext = activity;
-
- for (ActionItem item : sClusterItems) {
- mActionBar.addTab(mActionBar.newTab().setText(item.tabTitle).
- setTag(item).setTabListener(this));
- }
+ public GalleryActionBar(GalleryActivity activity) {
+ mActionBar = ((Activity) activity).getActionBar();
+ mContext = activity.getAndroidContext();
+ mActivity = activity;
+ mInflater = ((Activity) mActivity).getLayoutInflater();
+ mCurrentIndex = 0;
}
public static int getHeight(Activity activity) {
@@ -131,12 +158,7 @@
}
public int getClusterTypeAction() {
- if (mCurrentTab != null) {
- ActionItem item = (ActionItem) mCurrentTab.getTag();
- return item.action;
- }
- // By default, it's group-by-album
- return FilterUtils.CLUSTER_BY_ALBUM;
+ return sClusterItems[mCurrentIndex].action;
}
public static String getClusterByTypeString(Context context, int type) {
@@ -157,19 +179,19 @@
return shareActionProvider;
}
- public void showClusterTabs(ClusterRunner runner) {
- Log.v(TAG, "showClusterTabs: runner=" + runner);
- // setNavigationMode will trigger onTabSelected, so we should avoid
- // triggering any callback here
+ public void showClusterMenu(int action, ClusterRunner runner) {
+ Log.v(TAG, "showClusterMenu: runner=" + runner);
+ // Don't set cluster runner until action bar is ready.
mClusterRunner = null;
- mActionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
+ mActionBar.setListNavigationCallbacks(mAdapter, this);
+ mActionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);
+ setSelectedAction(action);
mClusterRunner = runner;
}
- public void hideClusterTabs() {
+ public void hideClusterMenu() {
mClusterRunner = null;
mActionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
- Log.v(TAG, "hideClusterTabs: runner=" + mClusterRunner);
}
public void showClusterDialog(final ClusterRunner clusterRunner) {
@@ -203,31 +225,28 @@
return mActionBar == null ? 0 : mActionBar.getHeight();
}
- @Override
- public void onTabSelected(Tab tab, FragmentTransaction ft) {
- if (mCurrentTab == tab) return;
- mCurrentTab = tab;
- ActionItem item = (ActionItem) tab.getTag();
- Log.v(TAG, "onTabSelected: clusterrRunner=" + mClusterRunner);
- if (mClusterRunner != null) mClusterRunner.doCluster(item.action);
- }
-
- @Override
- public void onTabUnselected(Tab tab, FragmentTransaction ft) {
- }
-
- @Override
- public void onTabReselected(Tab tab, FragmentTransaction ft) {
- }
-
- public boolean setSelectedTab(int type) {
- for (int i = 0, n = sClusterItems.length; i < n; ++i) {
+ public boolean setSelectedAction(int type) {
+ for (int i = 0, n = sClusterItems.length; i < n; i++) {
ActionItem item = sClusterItems[i];
if (item.visible && item.action == type) {
- mActionBar.selectTab(mActionBar.getTabAt(i));
+ mActionBar.setSelectedNavigationItem(i);
+ mCurrentIndex = i;
return true;
}
}
return false;
}
+
+ @Override
+ public boolean onNavigationItemSelected(int itemPosition, long itemId) {
+ if (itemPosition != mCurrentIndex && mClusterRunner != null) {
+ mActivity.getGLRoot().lockRenderThread();
+ try {
+ mClusterRunner.doCluster(sClusterItems[itemPosition].action);
+ } finally {
+ mActivity.getGLRoot().unlockRenderThread();
+ }
+ }
+ return false;
+ }
}
diff --git a/src/com/android/gallery3d/app/ManageCachePage.java b/src/com/android/gallery3d/app/ManageCachePage.java
index 940f1be..27f92e4 100644
--- a/src/com/android/gallery3d/app/ManageCachePage.java
+++ b/src/com/android/gallery3d/app/ManageCachePage.java
@@ -113,10 +113,10 @@
int slotViewTop = GalleryActionBar.getHeight(activity);
int slotViewBottom = bottom - top;
- View cacheBar = activity.findViewById(R.id.cache_bar);
- if (cacheBar != null) {
+ View footer = activity.findViewById(R.id.footer);
+ if (footer != null) {
int location[] = {0, 0};
- cacheBar.getLocationOnScreen(location);
+ footer.getLocationOnScreen(location);
slotViewBottom = location[1];
}
@@ -143,6 +143,18 @@
mRootPane.invalidate();
}
+ private void onDown(int index) {
+ MediaSet set = mAlbumSetDataAdapter.getMediaSet(index);
+ Path path = (set == null) ? null : set.getPath();
+ mSelectionManager.setPressedPath(path);
+ mAlbumSetView.invalidate();
+ }
+
+ private void onUp() {
+ mSelectionManager.setPressedPath(null);
+ mAlbumSetView.invalidate();
+ }
+
public void onSingleTapUp(int slotIndex) {
MediaSet targetSet = mAlbumSetDataAdapter.getMediaSet(slotIndex);
if (targetSet == null) return; // Content is dirty, we shall reload soon
@@ -279,15 +291,23 @@
mStaticBackground = new StaticBackground(activity);
mRootPane.addComponent(mStaticBackground);
- mSelectionDrawer = new ManageCacheDrawer(
- (Context) mActivity, mSelectionManager);
Config.ManageCachePage config = Config.ManageCachePage.get(activity);
+ mSelectionDrawer = new ManageCacheDrawer((Context) mActivity,
+ mSelectionManager, config.cachePinSize, config.cachePinMargin);
mAlbumSetView = new AlbumSetView(mActivity, mSelectionDrawer,
- config.slotWidth, config.slotHeight,
- config.displayItemSize, config.labelFontSize,
- config.labelOffsetY, config.labelMargin);
+ config.slotViewSpec, config.labelSpec);
mAlbumSetView.setListener(new SlotView.SimpleListener() {
@Override
+ public void onDown(int index) {
+ ManageCachePage.this.onDown(index);
+ }
+
+ @Override
+ public void onUp() {
+ ManageCachePage.this.onUp();
+ }
+
+ @Override
public void onSingleTapUp(int slotIndex) {
ManageCachePage.this.onSingleTapUp(slotIndex);
}
diff --git a/src/com/android/gallery3d/app/MovieActivity.java b/src/com/android/gallery3d/app/MovieActivity.java
index 4c9be7e..6bc6fdc 100644
--- a/src/com/android/gallery3d/app/MovieActivity.java
+++ b/src/com/android/gallery3d/app/MovieActivity.java
@@ -27,6 +27,7 @@
import android.os.Bundle;
import android.provider.MediaStore;
import android.provider.MediaStore.Video.VideoColumns;
+import android.view.MenuItem;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
@@ -51,8 +52,8 @@
setContentView(R.layout.movie_view);
View rootView = findViewById(R.id.root);
Intent intent = getIntent();
- setVideoTitle(intent);
- mPlayer = new MoviePlayer(rootView, this, intent.getData()) {
+ initializeActionBar(intent);
+ mPlayer = new MoviePlayer(rootView, this, intent.getData(), savedInstanceState) {
@Override
public void onCompletion() {
if (mFinishOnCompletion) {
@@ -73,10 +74,12 @@
WindowManager.LayoutParams winParams = win.getAttributes();
winParams.buttonBrightness = WindowManager.LayoutParams.BRIGHTNESS_OVERRIDE_OFF;
win.setAttributes(winParams);
-
}
- private void setVideoTitle(Intent intent) {
+ private void initializeActionBar(Intent intent) {
+ ActionBar actionBar = getActionBar();
+ actionBar.setDisplayOptions(ActionBar.DISPLAY_HOME_AS_UP,
+ ActionBar.DISPLAY_HOME_AS_UP);
String title = intent.getStringExtra(Intent.EXTRA_TITLE);
if (title == null) {
Cursor cursor = null;
@@ -92,8 +95,16 @@
if (cursor != null) cursor.close();
}
}
- ActionBar actionBar = getActionBar();
- if (title != null && actionBar != null) actionBar.setTitle(title);
+ if (title != null) actionBar.setTitle(title);
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ if (item.getItemId() == android.R.id.home) {
+ finish();
+ return true;
+ }
+ return false;
}
@Override
@@ -124,6 +135,12 @@
}
@Override
+ public void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ mPlayer.onSaveInstanceState(outState);
+ }
+
+ @Override
public void onDestroy() {
mPlayer.onDestroy();
super.onDestroy();
diff --git a/src/com/android/gallery3d/app/MoviePlayer.java b/src/com/android/gallery3d/app/MoviePlayer.java
index 4239944..ee76fa5 100644
--- a/src/com/android/gallery3d/app/MoviePlayer.java
+++ b/src/com/android/gallery3d/app/MoviePlayer.java
@@ -33,6 +33,7 @@
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.net.Uri;
+import android.os.Bundle;
import android.os.Handler;
import android.view.KeyEvent;
import android.view.View;
@@ -49,11 +50,18 @@
@SuppressWarnings("unused")
private static final String TAG = "MoviePlayer";
+ private static final String KEY_VIDEO_POSITION = "video-position";
+ private static final String KEY_RESUMEABLE_TIME = "resumeable-timeout";
+
// Copied from MediaPlaybackService in the Music Player app.
private static final String SERVICECMD = "com.android.music.musicservicecommand";
private static final String CMDNAME = "command";
private static final String CMDPAUSE = "pause";
+ // If we resume the acitivty with in RESUMEABLE_TIMEOUT, we will keep playing.
+ // Otherwise, we pause the player.
+ private static final long RESUMEABLE_TIMEOUT = 3 * 60 * 1000; // 3 mins
+
private Context mContext;
private final VideoView mVideoView;
private final View mProgressView;
@@ -62,10 +70,14 @@
private final Handler mHandler = new Handler();
private final AudioBecomingNoisyReceiver mAudioBecomingNoisyReceiver;
private final ActionBar mActionBar;
+ private final MediaController mMediaController;
- private boolean mHasPaused;
+ private long mResumeableTime = Long.MAX_VALUE;
+ private int mVideoPosition = 0;
+ private boolean mHasPaused = false;
private final Runnable mPlayingChecker = new Runnable() {
+ @Override
public void run() {
if (mVideoView.isPlaying()) {
mProgressView.setVisibility(View.GONE);
@@ -75,7 +87,8 @@
}
};
- public MoviePlayer(View rootView, final MovieActivity movieActivity, Uri videoUri) {
+ public MoviePlayer(View rootView, final MovieActivity movieActivity, Uri videoUri,
+ Bundle savedInstance) {
mContext = movieActivity.getApplicationContext();
mVideoView = (VideoView) rootView.findViewById(R.id.surface_view);
mProgressView = rootView.findViewById(R.id.progress_indicator);
@@ -96,7 +109,7 @@
mVideoView.setOnCompletionListener(this);
mVideoView.setVideoURI(mUri);
- MediaController mediaController = new MediaController(movieActivity) {
+ mMediaController = new MediaController(movieActivity) {
@Override
public void show() {
super.show();
@@ -109,8 +122,8 @@
mActionBar.hide();
}
};
- mVideoView.setMediaController(mediaController);
- mediaController.setOnKeyListener(new View.OnKeyListener() {
+ mMediaController.setOnKeyListener(new View.OnKeyListener() {
+ @Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
if (event.getAction() == KeyEvent.ACTION_UP) {
@@ -121,6 +134,7 @@
return false;
}
});
+ mVideoView.setMediaController(mMediaController);
mAudioBecomingNoisyReceiver = new AudioBecomingNoisyReceiver();
mAudioBecomingNoisyReceiver.register();
@@ -132,14 +146,27 @@
i.putExtra(CMDNAME, CMDPAUSE);
movieActivity.sendBroadcast(i);
- final Integer bookmark = mBookmarker.getBookmark(mUri);
- if (bookmark != null) {
- showResumeDialog(movieActivity, bookmark);
- } else {
+ if (savedInstance != null) { // this is a resumed activity
+ mVideoPosition = savedInstance.getInt(KEY_VIDEO_POSITION, 0);
+ mResumeableTime = savedInstance.getLong(KEY_RESUMEABLE_TIME, Long.MAX_VALUE);
mVideoView.start();
+ mVideoView.suspend();
+ mHasPaused = true;
+ } else {
+ final Integer bookmark = mBookmarker.getBookmark(mUri);
+ if (bookmark != null) {
+ showResumeDialog(movieActivity, bookmark);
+ } else {
+ mVideoView.start();
+ }
}
}
+ public void onSaveInstanceState(Bundle outState) {
+ outState.putInt(KEY_VIDEO_POSITION, mVideoPosition);
+ outState.putLong(KEY_RESUMEABLE_TIME, mResumeableTime);
+ }
+
private void showResumeDialog(Context context, final int bookmark) {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(R.string.resume_playing_title);
@@ -147,12 +174,14 @@
context.getString(R.string.resume_playing_message),
GalleryUtils.formatDuration(context, bookmark / 1000)));
builder.setOnCancelListener(new OnCancelListener() {
+ @Override
public void onCancel(DialogInterface dialog) {
onCompletion();
}
});
builder.setPositiveButton(
R.string.resume_playing_resume, new OnClickListener() {
+ @Override
public void onClick(DialogInterface dialog, int which) {
mVideoView.seekTo(bookmark);
mVideoView.start();
@@ -160,6 +189,7 @@
});
builder.setNegativeButton(
R.string.resume_playing_restart, new OnClickListener() {
+ @Override
public void onClick(DialogInterface dialog, int which) {
mVideoView.start();
}
@@ -168,21 +198,25 @@
}
public void onPause() {
- mHandler.removeCallbacksAndMessages(null);
- mBookmarker.setBookmark(mUri, mVideoView.getCurrentPosition(),
- mVideoView.getDuration());
- mVideoView.suspend();
mHasPaused = true;
+ mHandler.removeCallbacksAndMessages(null);
+ mVideoPosition = mVideoView.getCurrentPosition();
+ mBookmarker.setBookmark(mUri, mVideoPosition, mVideoView.getDuration());
+ mVideoView.suspend();
+ mResumeableTime = System.currentTimeMillis() + RESUMEABLE_TIMEOUT;
}
public void onResume() {
if (mHasPaused) {
- Integer bookmark = mBookmarker.getBookmark(mUri);
- if (bookmark != null) {
- mVideoView.seekTo(bookmark);
+ mVideoView.seekTo(mVideoPosition);
+ mVideoView.resume();
+
+ // If we have slept for too long, pause the play
+ if (System.currentTimeMillis() > mResumeableTime) {
+ mMediaController.show();
+ mVideoView.pause();
}
}
- mVideoView.resume();
}
public void onDestroy() {
diff --git a/src/com/android/gallery3d/app/PhotoPage.java b/src/com/android/gallery3d/app/PhotoPage.java
index a3b385a..44b9299 100644
--- a/src/com/android/gallery3d/app/PhotoPage.java
+++ b/src/com/android/gallery3d/app/PhotoPage.java
@@ -85,6 +85,7 @@
private FilmStripView mFilmStripView;
private DetailsHelper mDetailsHelper;
private boolean mShowDetails;
+ private Path mPendingSharePath;
// mMediaSet could be null if there is no KEY_MEDIA_SET_PATH supplied.
// E.g., viewing a photo in gmail attachment
@@ -240,6 +241,7 @@
mPhotoView.setModel(mModel);
updateCurrentPhoto(mediaItem);
}
+
mHandler = new SynchronizedHandler(mActivity.getGLRoot()) {
@Override
public void handleMessage(Message message) {
@@ -257,6 +259,21 @@
mPhotoView.setOpenedItem(itemPath);
}
+ 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));
+ intent.putExtra(Intent.EXTRA_STREAM, manager.getContentUri(path));
+ mShareActionProvider.setShareIntent(intent);
+ mPendingSharePath = null;
+ } else {
+ // This happens when ActionBar is not created yet.
+ mPendingSharePath = path;
+ }
+ }
+
private void setTitle(String title) {
if (title == null) return;
boolean showTitle = mActivity.getAndroidContext().getResources().getBoolean(
@@ -276,19 +293,10 @@
mDetailsHelper.reloadDetails(mModel.getCurrentIndex());
}
setTitle(photo.getName());
- mPhotoView.showVideoPlayIcon(photo.getMediaType()
- == MediaObject.MEDIA_TYPE_VIDEO);
+ mPhotoView.showVideoPlayIcon(
+ photo.getMediaType() == MediaObject.MEDIA_TYPE_VIDEO);
- // If we have an ActionBar then we update the share intent
- if (mShareActionProvider != null) {
- Path path = photo.getPath();
- DataManager manager = mActivity.getDataManager();
- int type = manager.getMediaType(path);
- Intent intent = new Intent(Intent.ACTION_SEND);
- intent.setType(MenuExecutor.getMimeType(type));
- intent.putExtra(Intent.EXTRA_STREAM, manager.getContentUri(path));
- mShareActionProvider.setShareIntent(intent);
- }
+ updateShareURI(photo.getPath());
}
private void updateMenuOperations() {
@@ -384,6 +392,7 @@
menu.findItem(R.id.action_slideshow).setVisible(
mMediaSet != null && !(mMediaSet instanceof MtpDevice));
mShareActionProvider = GalleryActionBar.initializeShareActionProvider(menu);
+ if (mPendingSharePath != null) updateShareURI(mPendingSharePath);
mMenu = menu;
mShowBars = true;
updateMenuOperations();
diff --git a/src/com/android/gallery3d/data/DecodeUtils.java b/src/com/android/gallery3d/data/DecodeUtils.java
index d2b4ebc..29b2aa7 100644
--- a/src/com/android/gallery3d/data/DecodeUtils.java
+++ b/src/com/android/gallery3d/data/DecodeUtils.java
@@ -102,15 +102,19 @@
options.inSampleSize = BitmapUtils.computeSampleSizeLarger(
options.outWidth, options.outHeight, targetSize);
options.inJustDecodeBounds = false;
- return ensureGLCompatibleBitmap(
- BitmapFactory.decodeFileDescriptor(fd, null, options));
+
+ Bitmap result = BitmapFactory.decodeFileDescriptor(fd, null, options);
+ // We need to resize down if the decoder does not support inSampleSize.
+ // (For example, GIF images.)
+ result = BitmapUtils.resizeDownIfTooBig(result, targetSize, true);
+ return ensureGLCompatibleBitmap(result);
}
/**
* Decodes the bitmap from the given byte array if the image size is larger than the given
* requirement.
*
- * Note: The returned image may be resized down. However, both width and heigh must be
+ * Note: The returned image may be resized down. However, both width and height must be
* larger than the <code>targetSize</code>.
*/
public static Bitmap requestDecodeIfBigEnough(JobContext jc, byte[] data,
diff --git a/src/com/android/gallery3d/data/LocalImage.java b/src/com/android/gallery3d/data/LocalImage.java
index 7ab04c5..e70b2ee 100644
--- a/src/com/android/gallery3d/data/LocalImage.java
+++ b/src/com/android/gallery3d/data/LocalImage.java
@@ -61,6 +61,8 @@
private static final int INDEX_ORIENTATION = 9;
private static final int INDEX_BUCKET_ID = 10;
private static final int INDEX_SIZE_ID = 11;
+ private static final int INDEX_WIDTH = 12;
+ private static final int INDEX_HEIGHT = 13;
static final String[] PROJECTION = {
ImageColumns._ID, // 0
@@ -74,12 +76,17 @@
ImageColumns.DATA, // 8
ImageColumns.ORIENTATION, // 9
ImageColumns.BUCKET_ID, // 10
- ImageColumns.SIZE // 11
+ ImageColumns.SIZE, // 11
+ // These should be changed to proper names after they are made public.
+ "width", // ImageColumns.WIDTH, // 12
+ "height", // ImageColumns.HEIGHT // 13
};
private final GalleryApp mApplication;
public int rotation;
+ public int width;
+ public int height;
public LocalImage(Path path, GalleryApp application, Cursor cursor) {
super(path, nextVersionNumber());
@@ -118,6 +125,8 @@
rotation = cursor.getInt(INDEX_ORIENTATION);
bucketId = cursor.getInt(INDEX_BUCKET_ID);
fileSize = cursor.getLong(INDEX_SIZE_ID);
+ width = cursor.getInt(INDEX_WIDTH);
+ height = cursor.getInt(INDEX_HEIGHT);
}
@Override
@@ -138,6 +147,8 @@
rotation = uh.update(rotation, cursor.getInt(INDEX_ORIENTATION));
bucketId = uh.update(bucketId, cursor.getInt(INDEX_BUCKET_ID));
fileSize = uh.update(fileSize, cursor.getLong(INDEX_SIZE_ID));
+ width = uh.update(width, cursor.getInt(INDEX_WIDTH));
+ height = uh.update(height, cursor.getInt(INDEX_HEIGHT));
return uh.isUpdated();
}
@@ -306,4 +317,14 @@
public int getRotation() {
return rotation;
}
+
+ @Override
+ public int getWidth() {
+ return width;
+ }
+
+ @Override
+ public int getHeight() {
+ return height;
+ }
}
diff --git a/src/com/android/gallery3d/data/LocalVideo.java b/src/com/android/gallery3d/data/LocalVideo.java
index d1498e8..111a5f1 100644
--- a/src/com/android/gallery3d/data/LocalVideo.java
+++ b/src/com/android/gallery3d/data/LocalVideo.java
@@ -210,4 +210,14 @@
}
return details;
}
+
+ @Override
+ public int getWidth() {
+ return 0;
+ }
+
+ @Override
+ public int getHeight() {
+ return 0;
+ }
}
diff --git a/src/com/android/gallery3d/data/MediaItem.java b/src/com/android/gallery3d/data/MediaItem.java
index 0906251..a0c6d8c 100644
--- a/src/com/android/gallery3d/data/MediaItem.java
+++ b/src/com/android/gallery3d/data/MediaItem.java
@@ -78,4 +78,9 @@
}
public abstract String getMimeType();
+
+ // Returns width and height of the media item.
+ // Returns 0, 0 if the information is not available.
+ public abstract int getWidth();
+ public abstract int getHeight();
}
diff --git a/src/com/android/gallery3d/data/MtpImage.java b/src/com/android/gallery3d/data/MtpImage.java
index 218f704..211b2f2 100644
--- a/src/com/android/gallery3d/data/MtpImage.java
+++ b/src/com/android/gallery3d/data/MtpImage.java
@@ -157,4 +157,13 @@
return details;
}
+ @Override
+ public int getWidth() {
+ return mImageWidth;
+ }
+
+ @Override
+ public int getHeight() {
+ return mImageHeight;
+ }
}
diff --git a/src/com/android/gallery3d/data/UriImage.java b/src/com/android/gallery3d/data/UriImage.java
index 3a7ed7c..e97b035 100644
--- a/src/com/android/gallery3d/data/UriImage.java
+++ b/src/com/android/gallery3d/data/UriImage.java
@@ -263,4 +263,14 @@
super.finalize();
}
}
+
+ @Override
+ public int getWidth() {
+ return 0;
+ }
+
+ @Override
+ public int getHeight() {
+ return 0;
+ }
}
diff --git a/src/com/android/gallery3d/gadget/WidgetConfigure.java b/src/com/android/gallery3d/gadget/WidgetConfigure.java
index 747cc3a..a871e24 100644
--- a/src/com/android/gallery3d/gadget/WidgetConfigure.java
+++ b/src/com/android/gallery3d/gadget/WidgetConfigure.java
@@ -48,6 +48,7 @@
// Note: There is also a limit on the size of data that can be
// passed in Binder's transaction.
private static float WIDGET_SCALE_FACTOR = 1.5f;
+ private static int MAX_WIDGET_SIDE = 360;
private int mAppWidgetId = -1;
private int mWidgetType = 0;
@@ -115,10 +116,18 @@
private void setChoosenPhoto(Intent data) {
Resources res = getResources();
- int widgetWidth = Math.round(WIDGET_SCALE_FACTOR
- * res.getDimension(R.dimen.appwidget_width));
- int widgetHeight = Math.round(WIDGET_SCALE_FACTOR
- * res.getDimension(R.dimen.appwidget_height));
+
+ float width = res.getDimension(R.dimen.appwidget_width);
+ float height = res.getDimension(R.dimen.appwidget_height);
+
+ // We try to crop a larger image (by scale factor), but there is still
+ // a bound on the binder limit.
+ float scale = Math.min(WIDGET_SCALE_FACTOR,
+ MAX_WIDGET_SIDE / Math.max(width, height));
+
+ int widgetWidth = Math.round(width * scale);
+ int widgetHeight = Math.round(height * scale);
+
mPickedItem = data.getData();
Intent request = new Intent(CropImage.ACTION_CROP, mPickedItem)
.putExtra(CropImage.KEY_OUTPUT_X, widgetWidth)
diff --git a/src/com/android/gallery3d/photoeditor/filters/DoodleFilter.java b/src/com/android/gallery3d/photoeditor/filters/DoodleFilter.java
index b40f458..4b7b4c9 100644
--- a/src/com/android/gallery3d/photoeditor/filters/DoodleFilter.java
+++ b/src/com/android/gallery3d/photoeditor/filters/DoodleFilter.java
@@ -82,7 +82,7 @@
}
Effect effect = getEffect(context, EffectFactory.EFFECT_BITMAPOVERLAY);
- effect.setParameter("doodle", bitmap);
+ effect.setParameter("bitmap", bitmap);
effect.apply(src.texture(), src.width(), src.height(), dst.texture());
}
}
diff --git a/src/com/android/gallery3d/photoeditor/filters/FillLightFilter.java b/src/com/android/gallery3d/photoeditor/filters/FillLightFilter.java
index a799e6f..29fab3c 100644
--- a/src/com/android/gallery3d/photoeditor/filters/FillLightFilter.java
+++ b/src/com/android/gallery3d/photoeditor/filters/FillLightFilter.java
@@ -42,7 +42,7 @@
@Override
public void process(EffectContext context, Photo src, Photo dst) {
Effect effect = getEffect(context, EffectFactory.EFFECT_FILLLIGHT);
- effect.setParameter("backlight", backlight);
+ effect.setParameter("strength", backlight);
effect.apply(src.texture(), src.width(), src.height(), dst.texture());
}
}
diff --git a/src/com/android/gallery3d/photoeditor/filters/GrainFilter.java b/src/com/android/gallery3d/photoeditor/filters/GrainFilter.java
index 1ee8a9c..191cb44 100644
--- a/src/com/android/gallery3d/photoeditor/filters/GrainFilter.java
+++ b/src/com/android/gallery3d/photoeditor/filters/GrainFilter.java
@@ -42,7 +42,7 @@
@Override
public void process(EffectContext context, Photo src, Photo dst) {
Effect effect = getEffect(context, EffectFactory.EFFECT_GRAIN);
- effect.setParameter("scale", scale);
+ effect.setParameter("strength", scale);
effect.apply(src.texture(), src.width(), src.height(), dst.texture());
}
}
diff --git a/src/com/android/gallery3d/photoeditor/filters/RotateFilter.java b/src/com/android/gallery3d/photoeditor/filters/RotateFilter.java
index 2823466..17f99fd 100644
--- a/src/com/android/gallery3d/photoeditor/filters/RotateFilter.java
+++ b/src/com/android/gallery3d/photoeditor/filters/RotateFilter.java
@@ -40,7 +40,7 @@
dst.changeDimension(src.height(), src.width());
}
Effect effect = getEffect(context, EffectFactory.EFFECT_ROTATE);
- effect.setParameter("degree", degrees);
+ effect.setParameter("angle", (int) degrees);
effect.apply(src.texture(), src.width(), src.height(), dst.texture());
}
}
diff --git a/src/com/android/gallery3d/photoeditor/filters/VignetteFilter.java b/src/com/android/gallery3d/photoeditor/filters/VignetteFilter.java
index d066c8b..2c15972 100644
--- a/src/com/android/gallery3d/photoeditor/filters/VignetteFilter.java
+++ b/src/com/android/gallery3d/photoeditor/filters/VignetteFilter.java
@@ -27,7 +27,7 @@
*/
public class VignetteFilter extends Filter {
- private float range;
+ private float scale;
/**
* Sets the vignette range scale.
@@ -35,17 +35,14 @@
* @param scale ranges from 0 to 1.
*/
public void setScale(float scale) {
- // The 'range' is between 1.3 to 0.6. When scale is zero then range is 1.3
- // which means no vignette at all because the luminousity difference is
- // less than 1/256 and will cause nothing.
- range = 1.30f - (float) Math.sqrt(scale) * 0.7f;
+ this.scale = scale;
validate();
}
@Override
public void process(EffectContext context, Photo src, Photo dst) {
Effect effect = getEffect(context, EffectFactory.EFFECT_VIGNETTE);
- effect.setParameter("range", range);
+ effect.setParameter("scale", scale);
effect.apply(src.texture(), src.width(), src.height(), dst.texture());
}
}
diff --git a/src/com/android/gallery3d/ui/ActionModeHandler.java b/src/com/android/gallery3d/ui/ActionModeHandler.java
index 91a98ce..b8d049b 100644
--- a/src/com/android/gallery3d/ui/ActionModeHandler.java
+++ b/src/com/android/gallery3d/ui/ActionModeHandler.java
@@ -86,7 +86,7 @@
mSelectionMenu = customMenu.addDropDownMenu(
(Button) customView.findViewById(R.id.selection_menu),
R.menu.selection);
- updateSelectAllTitle();
+ updateSelectionMenu();
customMenu.setOnMenuItemClickListener(new OnMenuItemClickListener() {
public boolean onMenuItemClick(MenuItem item) {
return onActionItemClicked(actionMode, item);
@@ -119,12 +119,17 @@
result = mMenuExecutor.onMenuClicked(item, listener);
if (item.getItemId() == R.id.action_select_all) {
updateSupportedOperation();
- updateSelectAllTitle();
+ updateSelectionMenu();
}
return result;
}
- private void updateSelectAllTitle() {
+ private void updateSelectionMenu() {
+ // update title
+ int count = mSelectionManager.getSelectedCount();
+ String format = mActivity.getResources().getQuantityString(
+ R.plurals.number_of_items_selected, count);
+ setTitle(String.format(format, count));
// For clients who call SelectionManager.selectAll() directly, we need to ensure the
// menu status is consistent with selection manager.
MenuItem item = mSelectionMenu.findItem(R.id.action_select_all);
@@ -164,26 +169,25 @@
return true;
}
- private void updateMenuOptionsAndSharingIntent(JobContext jc) {
- ArrayList<Path> paths = mSelectionManager.getSelected(true);
+ // Menu options are determined by selection set itself.
+ // We cannot expand it because MenuExecuter executes it based on
+ // the selection set instead of the expanded result.
+ // e.g. LocalImage can be rotated but collections of them (LocalAlbum) can't.
+ private void updateMenuOptions(JobContext jc) {
+ ArrayList<Path> paths = mSelectionManager.getSelected(false);
if (paths.size() == 0) return;
int operation = MediaObject.SUPPORT_ALL;
DataManager manager = mActivity.getDataManager();
- final ArrayList<Uri> uris = new ArrayList<Uri>();
int type = 0;
for (Path path : paths) {
if (jc.isCancelled()) return;
int support = manager.getSupportedOperations(path);
type |= manager.getMediaType(path);
operation &= support;
- if ((support & MediaObject.SUPPORT_SHARE) != 0) {
- uris.add(manager.getContentUri(path));
- }
}
- final Intent intent = new Intent();
- final String mimeType = MenuExecutor.getMimeType(type);
+ final String mimeType = MenuExecutor.getMimeType(type);
if (paths.size() == 1) {
if (!GalleryUtils.isEditorAvailable((Context) mActivity, mimeType)) {
operation &= ~MediaObject.SUPPORT_EDIT;
@@ -192,19 +196,6 @@
operation &= SUPPORT_MULTIPLE_MASK;
}
- final int size = uris.size();
- Log.v(TAG, "Sharing intent MIME type=" + mimeType + ", uri size = "+ uris.size());
- if (size > 0) {
- if (size > 1) {
- intent.setAction(Intent.ACTION_SEND_MULTIPLE).setType(mimeType);
- intent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, uris);
- } else {
- intent.setAction(Intent.ACTION_SEND).setType(mimeType);
- intent.putExtra(Intent.EXTRA_STREAM, uris.get(0));
- }
- intent.setType(mimeType);
- }
-
final int supportedOperation = operation;
mMainHandler.post(new Runnable() {
@@ -212,13 +203,52 @@
public void run() {
mMenuTask = null;
MenuExecutor.updateMenuOperation(mMenu, supportedOperation);
+ }
+ });
+ }
- if (mShareActionProvider != null && size > 0) {
+ // Share intent needs to expand the selection set so we can get URI of
+ // each media item
+ private void updateSharingIntent(JobContext jc) {
+ if (mShareActionProvider == null) return;
+ ArrayList<Path> paths = mSelectionManager.getSelected(true);
+ if (paths.size() == 0) return;
+
+ final ArrayList<Uri> uris = new ArrayList<Uri>();
+
+ DataManager manager = mActivity.getDataManager();
+ int type = 0;
+
+ final Intent intent = new Intent();
+ for (Path path : paths) {
+ int support = manager.getSupportedOperations(path);
+ type |= manager.getMediaType(path);
+
+ if ((support & MediaObject.SUPPORT_SHARE) != 0) {
+ uris.add(manager.getContentUri(path));
+ }
+ }
+
+ final int size = uris.size();
+ if (size > 0) {
+ final String mimeType = MenuExecutor.getMimeType(type);
+ if (size > 1) {
+ intent.setAction(Intent.ACTION_SEND_MULTIPLE).setType(mimeType);
+ intent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, uris);
+ } else {
+ intent.setAction(Intent.ACTION_SEND).setType(mimeType);
+ intent.putExtra(Intent.EXTRA_STREAM, uris.get(0));
+ }
+ intent.setType(mimeType);
+
+ mMainHandler.post(new Runnable() {
+ @Override
+ public void run() {
Log.v(TAG, "Sharing intent is ready: action = " + intent.getAction());
mShareActionProvider.setShareIntent(intent);
}
- }
- });
+ });
+ }
}
public void updateSupportedOperation(Path path, boolean selected) {
@@ -240,7 +270,8 @@
// Generate sharing intent and update supported operations in the background
mMenuTask = mActivity.getThreadPool().submit(new Job<Void>() {
public Void run(JobContext jc) {
- updateMenuOptionsAndSharingIntent(jc);
+ updateMenuOptions(jc);
+ updateSharingIntent(jc);
return null;
}
});
diff --git a/src/com/android/gallery3d/ui/AlbumSetSlidingWindow.java b/src/com/android/gallery3d/ui/AlbumSetSlidingWindow.java
index 92d8b41..4253685 100644
--- a/src/com/android/gallery3d/ui/AlbumSetSlidingWindow.java
+++ b/src/com/android/gallery3d/ui/AlbumSetSlidingWindow.java
@@ -25,6 +25,7 @@
import com.android.gallery3d.ui.AlbumSetView.AlbumSetItem;
import com.android.gallery3d.util.Future;
import com.android.gallery3d.util.FutureListener;
+import com.android.gallery3d.util.GalleryUtils;
import com.android.gallery3d.util.MediaSetUtils;
import com.android.gallery3d.util.ThreadPool;
@@ -45,9 +46,7 @@
private final AlbumSetView.Model mSource;
private int mSize;
- private int mLabelWidth;
- private int mDisplayItemSize;
- private int mLabelFontSize;
+ private AlbumSetView.LabelSpec mLabelSpec;
private int mContentStart = 0;
private int mContentEnd = 0;
@@ -75,13 +74,11 @@
public int cacheStatus;
}
- public AlbumSetSlidingWindow(GalleryActivity activity, int labelWidth,
- int displayItemSize, int labelFontSize, SelectionDrawer drawer,
+ public AlbumSetSlidingWindow(GalleryActivity activity,
+ AlbumSetView.LabelSpec labelSpec, SelectionDrawer drawer,
AlbumSetView.Model source, int cacheSize) {
source.setModelListener(this);
- mLabelWidth = labelWidth;
- mDisplayItemSize = displayItemSize;
- mLabelFontSize = labelFontSize;
+ mLabelSpec = labelSpec;
mLoadingLabel = activity.getAndroidContext().getString(R.string.loading);
mSource = source;
mSelectionDrawer = drawer;
@@ -341,6 +338,7 @@
private final int mMediaType;
private Texture mContent;
private final long mDataVersion;
+ private boolean mIsPanorama;
public GalleryDisplayItem(int slotIndex, int coverIndex, MediaItem item) {
super(item);
@@ -348,6 +346,7 @@
mCoverIndex = coverIndex;
mMediaType = item.getMediaType();
mDataVersion = item.getDataVersion();
+ mIsPanorama = GalleryUtils.isPanorama(item);
updateContent(mWaitLoadingTexture);
}
@@ -367,20 +366,22 @@
private void updateContent(Texture content) {
mContent = content;
-
- int width = content.getWidth();
- int height = content.getHeight();
-
- float scale = (float) mDisplayItemSize / Math.max(width, height);
-
- width = (int) Math.floor(width * scale);
- height = (int) Math.floor(height * scale);
-
- setSize(width, height);
}
@Override
public boolean render(GLCanvas canvas, int pass) {
+ // Fit the content into the box
+ int width = mContent.getWidth();
+ int height = mContent.getHeight();
+
+ float scalex = mBoxWidth / (float) width;
+ float scaley = mBoxHeight / (float) height;
+ float scale = Math.min(scalex, scaley);
+
+ width = (int) Math.floor(width * scale);
+ height = (int) Math.floor(height * scale);
+
+ // Now draw it
int sourceType = SelectionDrawer.DATASOURCE_TYPE_NOT_CATEGORIZED;
int cacheFlag = MediaSet.CACHE_FLAG_NO;
int cacheStatus = MediaSet.CACHE_STATUS_NOT_CACHED;
@@ -392,8 +393,9 @@
cacheStatus = set.cacheStatus;
}
- mSelectionDrawer.draw(canvas, mContent, mWidth, mHeight,
+ mSelectionDrawer.draw(canvas, mContent, width, height,
getRotation(), path, mCoverIndex, sourceType, mMediaType,
+ mIsPanorama, mLabelSpec.labelBackgroundHeight,
cacheFlag == MediaSet.CACHE_FLAG_FULL,
(cacheFlag == MediaSet.CACHE_FLAG_FULL)
&& (cacheStatus != MediaSet.CACHE_STATUS_CACHED_FULL));
@@ -471,37 +473,65 @@
}
private class LabelDisplayItem extends DisplayItem {
- private static final int FONT_COLOR = Color.WHITE;
+ private static final int FONT_COLOR_TITLE = Color.WHITE;
+ private static final int FONT_COLOR_COUNT = 0x80FFFFFF; // 50% white
- private StringTexture mTexture;
- private String mLabel;
- private String mPostfix;
+ private StringTexture mTextureTitle;
+ private StringTexture mTextureCount;
+ private String mTitle;
+ private String mCount;
+ private int mLastWidth;
private final int mSlotIndex;
+ private boolean mHasIcon;
public LabelDisplayItem(int slotIndex) {
mSlotIndex = slotIndex;
- updateContent();
}
public boolean updateContent() {
- String label = mLoadingLabel;
- String postfix = null;
+ String title = mLoadingLabel;
+ String count = "";
MediaSet set = mSource.getMediaSet(mSlotIndex);
if (set != null) {
- label = Utils.ensureNotNull(set.getName());
- postfix = " (" + set.getTotalMediaItemCount() + ")";
+ title = Utils.ensureNotNull(set.getName());
+ count = "" + set.getTotalMediaItemCount();
}
- if (Utils.equals(label, mLabel)
- && Utils.equals(postfix, mPostfix)) return false;
- mTexture = StringTexture.newInstance(
- label, postfix, mLabelFontSize, FONT_COLOR, mLabelWidth, true);
- setSize(mTexture.getWidth(), mTexture.getHeight());
+ if (Utils.equals(title, mTitle)
+ && Utils.equals(count, mCount)
+ && Utils.equals(mBoxWidth, mLastWidth)) {
+ return false;
+ }
+ mTitle = title;
+ mCount = count;
+ mLastWidth = mBoxWidth;
+ mHasIcon = (identifySourceType(set) !=
+ SelectionDrawer.DATASOURCE_TYPE_NOT_CATEGORIZED);
+
+ AlbumSetView.LabelSpec s = mLabelSpec;
+ mTextureTitle = StringTexture.newInstance(
+ title, s.titleFontSize, FONT_COLOR_TITLE,
+ mBoxWidth - s.leftMargin, false);
+ mTextureCount = StringTexture.newInstance(
+ count, s.countFontSize, FONT_COLOR_COUNT,
+ mBoxWidth - s.leftMargin, true);
+
return true;
}
@Override
public boolean render(GLCanvas canvas, int pass) {
- mTexture.draw(canvas, -mWidth / 2, -mHeight / 2);
+ if (mBoxWidth != mLastWidth) {
+ updateContent();
+ }
+
+ AlbumSetView.LabelSpec s = mLabelSpec;
+ int x = -mBoxWidth / 2;
+ int y = (mBoxHeight + 1) / 2 - s.labelBackgroundHeight;
+ y += s.titleOffset;
+ mTextureTitle.draw(canvas, x + s.leftMargin, y);
+ y += s.titleFontSize + s.countOffset;
+ x += mHasIcon ? s.iconSize : s.leftMargin;
+ mTextureCount.draw(canvas, x, y);
return false;
}
diff --git a/src/com/android/gallery3d/ui/AlbumSetView.java b/src/com/android/gallery3d/ui/AlbumSetView.java
index ef066b3..89dfe4a 100644
--- a/src/com/android/gallery3d/ui/AlbumSetView.java
+++ b/src/com/android/gallery3d/ui/AlbumSetView.java
@@ -40,11 +40,7 @@
private AlbumSetSlidingWindow mDataWindow;
private final GalleryActivity mActivity;
- private final int mSlotWidth;
- private final int mDisplayItemSize;
- private final int mLabelFontSize;
- private final int mLabelOffsetY;
- private final int mLabelMargin;
+ private final LabelSpec mLabelSpec;
private SelectionDrawer mSelectionDrawer;
@@ -67,18 +63,23 @@
public long setDataVersion;
}
+ public static class LabelSpec {
+ public int labelBackgroundHeight;
+ public int titleOffset;
+ public int countOffset;
+ public int titleFontSize;
+ public int countFontSize;
+ public int leftMargin;
+ public int iconSize;
+ }
+
public AlbumSetView(GalleryActivity activity, SelectionDrawer drawer,
- int slotWidth, int slotHeight, int displayItemSize,
- int labelFontSize, int labelOffsetY, int labelMargin) {
+ SlotView.Spec slotViewSpec, LabelSpec labelSpec) {
super(activity.getAndroidContext());
mActivity = activity;
setSelectionDrawer(drawer);
- setSlotSize(slotWidth, slotHeight);
- mSlotWidth = slotWidth;
- mDisplayItemSize = displayItemSize;
- mLabelFontSize = labelFontSize;
- mLabelOffsetY = labelOffsetY;
- mLabelMargin = labelMargin;
+ setSlotSpec(slotViewSpec);
+ mLabelSpec = labelSpec;
}
public void setSelectionDrawer(SelectionDrawer drawer) {
@@ -95,8 +96,7 @@
mDataWindow = null;
}
if (model != null) {
- mDataWindow = new AlbumSetSlidingWindow(mActivity,
- mSlotWidth - mLabelMargin * 2, mDisplayItemSize, mLabelFontSize,
+ mDataWindow = new AlbumSetSlidingWindow(mActivity, mLabelSpec,
mSelectionDrawer, model, CACHE_SIZE);
mDataWindow.setListener(new MyCacheListener());
setSlotCount(mDataWindow.size());
@@ -119,8 +119,7 @@
// Put the cover items in reverse order, so that the first item is on
// top of the rest.
- int labelY = y + mLabelOffsetY - entry.labelItem.getHeight() / 2;
- Position position = new Position(x, labelY, 0f);
+ Position position = new Position(x, y, 0f);
putDisplayItem(position, position, entry.labelItem);
for (int i = 0, n = items.length; i < n; ++i) {
diff --git a/src/com/android/gallery3d/ui/AlbumSlidingWindow.java b/src/com/android/gallery3d/ui/AlbumSlidingWindow.java
index 9b410e9..5184d1c 100644
--- a/src/com/android/gallery3d/ui/AlbumSlidingWindow.java
+++ b/src/com/android/gallery3d/ui/AlbumSlidingWindow.java
@@ -24,6 +24,7 @@
import com.android.gallery3d.data.Path;
import com.android.gallery3d.util.Future;
import com.android.gallery3d.util.FutureListener;
+import com.android.gallery3d.util.GalleryUtils;
import com.android.gallery3d.util.JobLimiter;
import com.android.gallery3d.util.ThreadPool.Job;
import com.android.gallery3d.util.ThreadPool.JobContext;
@@ -38,7 +39,6 @@
private static final int MSG_LOAD_BITMAP_DONE = 0;
private static final int MSG_UPDATE_SLOT = 1;
- private static final int MIN_THUMB_SIZE = 100;
private static final int JOB_LIMIT = 2;
public static interface Listener {
@@ -66,24 +66,20 @@
private SynchronizedHandler mHandler;
private JobLimiter mThreadPool;
- private int mSlotWidth, mSlotHeight;
private int mActiveRequestCount = 0;
private boolean mIsActive = false;
- private int mDisplayItemSize; // 0: disabled
+ private int mCacheThumbSize; // 0: Don't cache the thumbnails
private LruCache<Path, Bitmap> mImageCache = new LruCache<Path, Bitmap>(1000);
public AlbumSlidingWindow(GalleryActivity activity,
AlbumView.Model source, int cacheSize,
- int slotWidth, int slotHeight, int displayItemSize) {
+ int cacheThumbSize) {
source.setModelListener(this);
mSource = source;
mData = new AlbumDisplayItem[cacheSize];
mSize = source.size();
- mSlotWidth = slotWidth;
- mSlotHeight = slotHeight;
- mDisplayItemSize = displayItemSize;
mWaitLoadingTexture = new ColorTexture(Color.TRANSPARENT);
mWaitLoadingTexture.setSize(1, 1);
@@ -288,6 +284,7 @@
private final int mSlotIndex;
private final int mMediaType;
private Texture mContent;
+ private boolean mIsPanorama;
public AlbumDisplayItem(int slotIndex, MediaItem item) {
super(item);
@@ -295,6 +292,7 @@
? MediaItem.MEDIA_TYPE_UNKNOWN
: item.getMediaType();
mSlotIndex = slotIndex;
+ mIsPanorama = GalleryUtils.isPanorama(item);
updateContent(mWaitLoadingTexture);
}
@@ -317,37 +315,37 @@
private void updateContent(Texture content) {
mContent = content;
+ }
+ @Override
+ public boolean render(GLCanvas canvas, int pass) {
+ // Fit the content into the box
int width = mContent.getWidth();
int height = mContent.getHeight();
- float scalex = mDisplayItemSize / (float) width;
- float scaley = mDisplayItemSize / (float) height;
+ float scalex = mBoxWidth / (float) width;
+ float scaley = mBoxHeight / (float) height;
float scale = Math.min(scalex, scaley);
width = (int) Math.floor(width * scale);
height = (int) Math.floor(height * scale);
- setSize(width, height);
- }
-
- @Override
- public boolean render(GLCanvas canvas, int pass) {
+ // Now draw it
if (pass == 0) {
Path path = null;
if (mMediaItem != null) path = mMediaItem.getPath();
- mSelectionDrawer.draw(canvas, mContent, mWidth, mHeight,
- getRotation(), path, mMediaType);
+ mSelectionDrawer.draw(canvas, mContent, width, height,
+ getRotation(), path, mMediaType, mIsPanorama);
return (mFocusIndex == mSlotIndex);
} else if (pass == 1) {
- mSelectionDrawer.drawFocus(canvas, mWidth, mHeight);
+ mSelectionDrawer.drawFocus(canvas, width, height);
}
return false;
}
@Override
public void startLoadBitmap() {
- if (mDisplayItemSize < MIN_THUMB_SIZE) {
+ if (mCacheThumbSize > 0) {
Path path = mMediaItem.getPath();
if (mImageCache.containsKey(path)) {
Bitmap bitmap = mImageCache.get(path);
@@ -368,7 +366,7 @@
Bitmap bitmap = job.run(jc);
if (bitmap != null) {
bitmap = BitmapUtils.resizeDownBySideLength(
- bitmap, mDisplayItemSize, true);
+ bitmap, mCacheThumbSize, true);
}
return bitmap;
}
@@ -390,7 +388,7 @@
mFuture = null;
Bitmap bitmap = future.get();
boolean isCancelled = future.isCancelled();
- if (mDisplayItemSize < MIN_THUMB_SIZE && (bitmap != null || !isCancelled)) {
+ if (mCacheThumbSize > 0 && (bitmap != null || !isCancelled)) {
Path path = mMediaItem.getPath();
mImageCache.put(path, bitmap);
}
diff --git a/src/com/android/gallery3d/ui/AlbumView.java b/src/com/android/gallery3d/ui/AlbumView.java
index 417611a..128259a 100644
--- a/src/com/android/gallery3d/ui/AlbumView.java
+++ b/src/com/android/gallery3d/ui/AlbumView.java
@@ -33,8 +33,7 @@
private AlbumSlidingWindow mDataWindow;
private final GalleryActivity mActivity;
private SelectionDrawer mSelectionDrawer;
- private int mSlotWidth, mSlotHeight;
- private int mDisplayItemSize;
+ private int mCacheThumbSize;
private boolean mIsActive = false;
@@ -50,13 +49,11 @@
public void onSizeChanged(int size);
}
- public AlbumView(GalleryActivity activity,
- int slotWidth, int slotHeight, int displayItemSize) {
+ public AlbumView(GalleryActivity activity, SlotView.Spec spec,
+ int cacheThumbSize) {
super(activity.getAndroidContext());
- mSlotWidth = slotWidth;
- mSlotHeight = slotHeight;
- mDisplayItemSize = displayItemSize;
- setSlotSize(slotWidth, slotHeight);
+ mCacheThumbSize = cacheThumbSize;
+ setSlotSpec(spec);
mActivity = activity;
}
@@ -74,7 +71,7 @@
if (model != null) {
mDataWindow = new AlbumSlidingWindow(
mActivity, model, CACHE_SIZE,
- mSlotWidth, mSlotHeight, mDisplayItemSize);
+ mCacheThumbSize);
mDataWindow.setSelectionDrawer(mSelectionDrawer);
mDataWindow.setListener(new MyDataModelListener());
setSlotCount(model.size());
diff --git a/src/com/android/gallery3d/ui/DialogDetailsView.java b/src/com/android/gallery3d/ui/DialogDetailsView.java
index 07ebc3c..adc9de1 100644
--- a/src/com/android/gallery3d/ui/DialogDetailsView.java
+++ b/src/com/android/gallery3d/ui/DialogDetailsView.java
@@ -146,7 +146,7 @@
case MediaDetails.INDEX_LOCATION: {
double[] latlng = (double[]) detail.getValue();
mLocationIndex = mItems.size();
- value = DetailsHelper.resolveAddress(mContext, latlng, mAdapter);
+ value = DetailsHelper.resolveAddress(mContext, latlng, this);
break;
}
case MediaDetails.INDEX_SIZE: {
diff --git a/src/com/android/gallery3d/ui/DisplayItem.java b/src/com/android/gallery3d/ui/DisplayItem.java
index 3038232..50264c4 100644
--- a/src/com/android/gallery3d/ui/DisplayItem.java
+++ b/src/com/android/gallery3d/ui/DisplayItem.java
@@ -18,12 +18,15 @@
public abstract class DisplayItem {
- protected int mWidth;
- protected int mHeight;
+ protected int mBoxWidth;
+ protected int mBoxHeight;
- protected void setSize(int width, int height) {
- mWidth = width;
- mHeight = height;
+ // setBox() specifies the box that the DisplayItem should render into. It
+ // should be called before first render(). It may be called again between
+ // render() calls to change the size of the box.
+ public void setBox(int width, int height) {
+ mBoxWidth = width;
+ mBoxHeight = height;
}
// returns true if more pass is needed
@@ -31,14 +34,6 @@
public abstract long getIdentity();
- public int getWidth() {
- return mWidth;
- }
-
- public int getHeight() {
- return mHeight;
- }
-
public int getRotation() {
return 0;
}
diff --git a/src/com/android/gallery3d/ui/FilmStripView.java b/src/com/android/gallery3d/ui/FilmStripView.java
index a6be2d1..eaf041e 100644
--- a/src/com/android/gallery3d/ui/FilmStripView.java
+++ b/src/com/android/gallery3d/ui/FilmStripView.java
@@ -20,14 +20,16 @@
import com.android.gallery3d.anim.AlphaAnimation;
import com.android.gallery3d.app.AlbumDataAdapter;
import com.android.gallery3d.app.GalleryActivity;
+import com.android.gallery3d.data.MediaItem;
import com.android.gallery3d.data.MediaSet;
+import com.android.gallery3d.data.Path;
import android.content.Context;
import android.view.MotionEvent;
import android.view.View.MeasureSpec;
-public class FilmStripView extends GLView implements SlotView.Listener,
- ScrollBarView.Listener, UserInteractionListener {
+public class FilmStripView extends GLView implements ScrollBarView.Listener,
+ UserInteractionListener {
@SuppressWarnings("unused")
private static final String TAG = "FilmStripView";
@@ -73,10 +75,34 @@
mGripSize = gripSize;
mStripDrawer = new StripDrawer((Context) activity);
- mAlbumView = new AlbumView(activity, thumbSize, thumbSize, thumbSize);
+ SlotView.Spec spec = new SlotView.Spec();
+ spec.slotWidth = thumbSize;
+ spec.slotHeight = thumbSize;
+ mAlbumView = new AlbumView(activity, spec, thumbSize);
mAlbumView.setOverscrollEffect(SlotView.OVERSCROLL_SYSTEM);
mAlbumView.setSelectionDrawer(mStripDrawer);
- mAlbumView.setListener(this);
+ mAlbumView.setListener(new SlotView.SimpleListener() {
+ @Override
+ public void onDown(int index) {
+ FilmStripView.this.onDown(index);
+ }
+ @Override
+ public void onUp() {
+ FilmStripView.this.onUp();
+ }
+ @Override
+ public void onSingleTapUp(int slotIndex) {
+ FilmStripView.this.onSingleTapUp(slotIndex);
+ }
+ @Override
+ public void onLongTap(int slotIndex) {
+ FilmStripView.this.onLongTap(slotIndex);
+ }
+ @Override
+ public void onScrollPositionChanged(int position, int total) {
+ FilmStripView.this.onScrollPositionChanged(position, total);
+ }
+ });
mAlbumView.setUserInteractionListener(this);
mAlbumDataAdapter = new AlbumDataAdapter(activity, mediaSet);
addComponent(mAlbumView);
@@ -169,20 +195,32 @@
super.render(canvas);
}
- // Called by AlbumView
- @Override
- public void onSingleTapUp(int slotIndex) {
+ private void onDown(int index) {
+ MediaItem item = mAlbumDataAdapter.get(index);
+ Path path = (item == null) ? null : item.getPath();
+ mStripDrawer.setPressedPath(path);
+ mAlbumView.invalidate();
+ }
+
+ private void onUp() {
+ mStripDrawer.setPressedPath(null);
+ mAlbumView.invalidate();
+ }
+
+ private void onSingleTapUp(int slotIndex) {
if (mListener.onSlotSelected(slotIndex)) {
mAlbumView.setFocusIndex(slotIndex);
}
}
- // Called by AlbumView
- @Override
- public void onLongTap(int slotIndex) {
+ private void onLongTap(int slotIndex) {
onSingleTapUp(slotIndex);
}
+ private void onScrollPositionChanged(int position, int total) {
+ mScrollBarView.setContentPosition(position, total);
+ }
+
// Called by AlbumView
@Override
public void onUserInteractionBegin() {
@@ -201,12 +239,6 @@
mUIListener.onUserInteraction();
}
- // Called by AlbumView
- @Override
- public void onScrollPositionChanged(int position, int total) {
- mScrollBarView.setContentPosition(position, total);
- }
-
// Called by ScrollBarView
@Override
public void onScrollBarPositionChanged(int position) {
diff --git a/src/com/android/gallery3d/ui/GLDetailsView.java b/src/com/android/gallery3d/ui/GLDetailsView.java
index cb98d4e..c0542e1 100644
--- a/src/com/android/gallery3d/ui/GLDetailsView.java
+++ b/src/com/android/gallery3d/ui/GLDetailsView.java
@@ -34,6 +34,7 @@
import android.content.Context;
import android.graphics.Color;
import android.graphics.Rect;
+import android.text.Layout;
import android.text.format.Formatter;
import android.view.MotionEvent;
import android.view.View.MeasureSpec;
@@ -259,7 +260,8 @@
context, key), value);
}
Texture label = MultiLineTexture.newInstance(
- value, mMaxDetailLength, FONT_SIZE, FONT_COLOR);
+ value, mMaxDetailLength, FONT_SIZE, FONT_COLOR,
+ Layout.Alignment.ALIGN_NORMAL);
mItems.add(label);
}
}
@@ -274,7 +276,8 @@
public void onAddressAvailable(String address) {
mItems.set(mLocationIndex, MultiLineTexture.newInstance(
- address, mMaxDetailLength, FONT_SIZE, FONT_COLOR));
+ address, mMaxDetailLength, FONT_SIZE, FONT_COLOR,
+ Layout.Alignment.ALIGN_NORMAL));
GLDetailsView.this.invalidate();
}
}
diff --git a/src/com/android/gallery3d/ui/GridDrawer.java b/src/com/android/gallery3d/ui/GridDrawer.java
index 54b175c..394a6c7 100644
--- a/src/com/android/gallery3d/ui/GridDrawer.java
+++ b/src/com/android/gallery3d/ui/GridDrawer.java
@@ -21,28 +21,23 @@
import android.content.Context;
import android.graphics.Color;
+import android.text.Layout;
public class GridDrawer extends IconDrawer {
- private final NinePatchTexture mFrame;
private final NinePatchTexture mFrameSelected;
- private final NinePatchTexture mFrameSelectedTop;
- private final NinePatchTexture mImportBackground;
private Texture mImportLabel;
private int mGridWidth;
private final SelectionManager mSelectionManager;
private final Context mContext;
- private final int FONT_SIZE = 14;
- private final int FONT_COLOR = Color.WHITE;
- private final int IMPORT_LABEL_PADDING = 10;
+ private final int IMPORT_FONT_SIZE = 14;
+ private final int IMPORT_FONT_COLOR = Color.WHITE;
+ private final int IMPORT_LABEL_MARGIN = 10;
private boolean mSelectionMode;
public GridDrawer(Context context, SelectionManager selectionManager) {
super(context);
mContext = context;
- mFrame = new NinePatchTexture(context, R.drawable.album_frame);
mFrameSelected = new NinePatchTexture(context, R.drawable.grid_selected);
- mFrameSelectedTop = new NinePatchTexture(context, R.drawable.grid_selected_top);
- mImportBackground = new NinePatchTexture(context, R.drawable.import_translucent);
mSelectionManager = selectionManager;
}
@@ -52,9 +47,10 @@
}
@Override
- public void draw(GLCanvas canvas, Texture content, int width, int height,
- int rotation, Path path, int topIndex, int dataSourceType,
- int mediaType, boolean wantCache, boolean isCaching) {
+ public void draw(GLCanvas canvas, Texture content, int width,
+ int height, int rotation, Path path, int topIndex,
+ int dataSourceType, int mediaType, boolean isPanorama,
+ int labelBackgroundHeight, boolean wantCache, boolean isCaching) {
int x = -width / 2;
int y = -height / 2;
@@ -70,37 +66,37 @@
y = -height / 2;
}
- drawVideoOverlay(canvas, mediaType, x, y, width, height, topIndex);
-
- NinePatchTexture frame;
- if (mSelectionMode && mSelectionManager.isItemSelected(path)) {
- frame = topIndex == 0 ? mFrameSelectedTop : mFrameSelected;
- } else {
- frame = mFrame;
- }
-
- drawFrame(canvas, frame, x, y, width, height);
+ drawMediaTypeOverlay(canvas, mediaType, isPanorama, x, y, width, height,
+ topIndex);
if (topIndex == 0) {
- ResourceTexture icon = getIcon(dataSourceType);
- if (icon != null) {
- IconDimension id = getIconDimension(icon, width, height);
- if (dataSourceType == DATASOURCE_TYPE_MTP) {
- if (mImportLabel == null || mGridWidth != width) {
- mGridWidth = width;
- mImportLabel = MultiLineTexture.newInstance(
- mContext.getString(R.string.click_import),
- width - id.width - IMPORT_LABEL_PADDING, FONT_SIZE, FONT_COLOR);
- }
- int bgHeight = Math.max(id.height, mImportLabel.getHeight());
- mImportBackground.setSize(width, bgHeight);
- mImportBackground.draw(canvas, x, -y - bgHeight);
- mImportLabel.draw(canvas, x + id.width + IMPORT_LABEL_PADDING,
- -y - bgHeight + Math.abs(bgHeight - mImportLabel.getHeight()) / 2);
- }
- icon.draw(canvas, id.x, id.y, id.width, id.height);
+ drawLabelBackground(canvas, width, height, labelBackgroundHeight);
+ drawIcon(canvas, width, height, dataSourceType);
+ if (dataSourceType == DATASOURCE_TYPE_MTP) {
+ drawImportLabel(canvas, width, height);
}
}
+
+ if (mSelectionManager.isPressedPath(path)) {
+ drawPressedFrame(canvas, x, y, width, height);
+ } else if (mSelectionMode && mSelectionManager.isItemSelected(path)) {
+ drawFrame(canvas, mFrameSelected, x, y, width, height);
+ }
+ }
+
+ // Draws the "click to import" label at the center of the frame
+ private void drawImportLabel(GLCanvas canvas, int width, int height) {
+ if (mImportLabel == null || mGridWidth != width) {
+ mGridWidth = width;
+ mImportLabel = MultiLineTexture.newInstance(
+ mContext.getString(R.string.click_import),
+ width - 2 * IMPORT_LABEL_MARGIN,
+ IMPORT_FONT_SIZE, IMPORT_FONT_COLOR,
+ Layout.Alignment.ALIGN_CENTER);
+ }
+ int w = mImportLabel.getWidth();
+ int h = mImportLabel.getHeight();
+ mImportLabel.draw(canvas, -w / 2, -h / 2);
}
@Override
diff --git a/src/com/android/gallery3d/ui/HighlightDrawer.java b/src/com/android/gallery3d/ui/HighlightDrawer.java
index 9d5868b..ee37d26 100644
--- a/src/com/android/gallery3d/ui/HighlightDrawer.java
+++ b/src/com/android/gallery3d/ui/HighlightDrawer.java
@@ -21,26 +21,25 @@
import android.content.Context;
public class HighlightDrawer extends IconDrawer {
- private final NinePatchTexture mFrame;
private final NinePatchTexture mFrameSelected;
- private final NinePatchTexture mFrameSelectedTop;
private SelectionManager mSelectionManager;
private Path mHighlightItem;
- public HighlightDrawer(Context context) {
+ public HighlightDrawer(Context context, SelectionManager selectionManager) {
super(context);
- mFrame = new NinePatchTexture(context, R.drawable.album_frame);
mFrameSelected = new NinePatchTexture(context, R.drawable.grid_selected);
- mFrameSelectedTop = new NinePatchTexture(context, R.drawable.grid_selected_top);
+ mSelectionManager = selectionManager;
}
public void setHighlightItem(Path item) {
mHighlightItem = item;
}
- public void draw(GLCanvas canvas, Texture content, int width, int height,
- int rotation, Path path, int topIndex, int dataSourceType,
- int mediaType, boolean wantCache, boolean isCaching) {
+ @Override
+ public void draw(GLCanvas canvas, Texture content, int width,
+ int height, int rotation, Path path, int topIndex,
+ int dataSourceType, int mediaType, boolean isPanorama,
+ int labelBackgroundHeight, boolean wantCache, boolean isCaching) {
int x = -width / 2;
int y = -height / 2;
@@ -55,19 +54,18 @@
y = -height / 2;
}
- drawVideoOverlay(canvas, mediaType, x, y, width, height, topIndex);
-
- NinePatchTexture frame;
- if (path == mHighlightItem) {
- frame = topIndex == 0 ? mFrameSelectedTop : mFrameSelected;
- } else {
- frame = mFrame;
- }
-
- drawFrame(canvas, frame, x, y, width, height);
+ drawMediaTypeOverlay(canvas, mediaType, isPanorama, x, y, width, height,
+ topIndex);
if (topIndex == 0) {
+ drawLabelBackground(canvas, width, height, labelBackgroundHeight);
drawIcon(canvas, width, height, dataSourceType);
}
+
+ if (mSelectionManager.isPressedPath(path)) {
+ drawPressedFrame(canvas, x, y, width, height);
+ } else if (path == mHighlightItem) {
+ drawFrame(canvas, mFrameSelected, x, y, width, height);
+ }
}
}
diff --git a/src/com/android/gallery3d/ui/IconDrawer.java b/src/com/android/gallery3d/ui/IconDrawer.java
index 91732d3..781046c 100644
--- a/src/com/android/gallery3d/ui/IconDrawer.java
+++ b/src/com/android/gallery3d/ui/IconDrawer.java
@@ -21,13 +21,18 @@
import android.content.Context;
public abstract class IconDrawer extends SelectionDrawer {
- private final String TAG = "IconDrawer";
+ private static final String TAG = "IconDrawer";
+ private static final int LABEL_BACKGROUND_COLOR = 0x99000000; // 60% black
+
private final ResourceTexture mLocalSetIcon;
private final ResourceTexture mCameraIcon;
private final ResourceTexture mPicasaIcon;
private final ResourceTexture mMtpIcon;
+ private final NinePatchTexture mFramePressed;
+ private final ResourceTexture mPanoramaBorder;
private final Texture mVideoOverlay;
private final Texture mVideoPlayIcon;
+ private final int mIconSize;
public static class IconDimension {
int x;
@@ -37,14 +42,16 @@
}
public IconDrawer(Context context) {
- mLocalSetIcon = new ResourceTexture(context, R.drawable.ic_album_overlay_folder_holo);
- mCameraIcon = new ResourceTexture(context, R.drawable.ic_album_overlay_camera_holo);
- mPicasaIcon = new ResourceTexture(context, R.drawable.ic_album_overlay_picassa_holo);
- mMtpIcon = new ResourceTexture(context, R.drawable.ic_album_overlay_ptp_holo);
- mVideoOverlay = new ResourceTexture(context,
- R.drawable.thumbnail_album_video_overlay_holo);
- mVideoPlayIcon = new ResourceTexture(context,
- R.drawable.videooverlay);
+ mLocalSetIcon = new ResourceTexture(context, R.drawable.frame_overlay_gallery_folder);
+ mCameraIcon = new ResourceTexture(context, R.drawable.frame_overlay_gallery_camera);
+ mPicasaIcon = new ResourceTexture(context, R.drawable.frame_overlay_gallery_picasa);
+ mMtpIcon = new ResourceTexture(context, R.drawable.frame_overlay_gallery_ptp);
+ mVideoOverlay = new ResourceTexture(context, R.drawable.ic_video_thumb);
+ mVideoPlayIcon = new ResourceTexture(context, R.drawable.ic_gallery_play);
+ mPanoramaBorder = new ResourceTexture(context, R.drawable.ic_pan_thumb);
+ mFramePressed = new NinePatchTexture(context, R.drawable.grid_pressed);
+ mIconSize = context.getResources().getDimensionPixelSize(
+ R.dimen.albumset_icon_size);
}
@Override
@@ -88,24 +95,63 @@
protected IconDimension getIconDimension(ResourceTexture icon, int width,
int height) {
IconDimension id = new IconDimension();
- float scale = 0.25f * width / icon.getWidth();
- id.width = (int) (scale * icon.getWidth());
- id.height = (int) (scale * icon.getHeight());
+ float scale = (float) mIconSize / icon.getWidth();
+ id.width = Math.round(scale * icon.getWidth());
+ id.height = Math.round(scale * icon.getHeight());
id.x = -width / 2;
- id.y = height / 2 - id.height;
+ id.y = (height + 1) / 2 - id.height;
return id;
}
- protected void drawVideoOverlay(GLCanvas canvas, int mediaType,
- int x, int y, int width, int height, int topIndex) {
- if (mediaType != MediaObject.MEDIA_TYPE_VIDEO) return;
- mVideoOverlay.draw(canvas, x, y, width, height);
+ protected void drawMediaTypeOverlay(GLCanvas canvas, int mediaType,
+ boolean isPanorama, int x, int y, int width, int height,
+ int topIndex) {
+ if (mediaType == MediaObject.MEDIA_TYPE_VIDEO) {
+ drawVideoOverlay(canvas, x, y, width, height, topIndex);
+ }
+ if (isPanorama) {
+ drawPanoramaBorder(canvas, x, y, width, height);
+ }
+ }
+
+ protected void drawVideoOverlay(GLCanvas canvas, int x, int y,
+ int width, int height, int topIndex) {
+ // Scale the video overlay to the height of the thumbnail and put it
+ // on the left side.
+ float scale = (float) height / mVideoOverlay.getHeight();
+ int w = Math.round(scale * mVideoOverlay.getWidth());
+ int h = Math.round(scale * mVideoOverlay.getHeight());
+ mVideoOverlay.draw(canvas, x, y, w, h);
+
if (topIndex == 0) {
int side = Math.min(width, height) / 6;
mVideoPlayIcon.draw(canvas, -side / 2, -side / 2, side, side);
}
}
+ protected void drawPanoramaBorder(GLCanvas canvas, int x, int y,
+ int width, int height) {
+ float scale = (float) width / mPanoramaBorder.getWidth();
+ int w = Math.round(scale * mPanoramaBorder.getWidth());
+ int h = Math.round(scale * mPanoramaBorder.getHeight());
+ // draw at the top
+ mPanoramaBorder.draw(canvas, x, y, w, h);
+ // draw at the bottom
+ mPanoramaBorder.draw(canvas, x, y + width - h, w, h);
+ }
+
+ protected void drawLabelBackground(GLCanvas canvas, int width, int height,
+ int drawLabelBackground) {
+ int x = -width / 2;
+ int y = (height + 1) / 2 - drawLabelBackground;
+ canvas.fillRect(x, y, width, drawLabelBackground, LABEL_BACKGROUND_COLOR);
+ }
+
+ protected void drawPressedFrame(GLCanvas canvas, int x, int y, int width,
+ int height) {
+ drawFrame(canvas, mFramePressed, x, y, width, height);
+ }
+
@Override
public void drawFocus(GLCanvas canvas, int width, int height) {
}
diff --git a/src/com/android/gallery3d/ui/ManageCacheDrawer.java b/src/com/android/gallery3d/ui/ManageCacheDrawer.java
index cf1e39e..b1ed249 100644
--- a/src/com/android/gallery3d/ui/ManageCacheDrawer.java
+++ b/src/com/android/gallery3d/ui/ManageCacheDrawer.java
@@ -23,25 +23,27 @@
import android.content.Context;
public class ManageCacheDrawer extends IconDrawer {
- private static final int COLOR_CACHING_BACKGROUND = 0x7F000000;
- private static final int ICON_SIZE = 36;
- private final NinePatchTexture mFrame;
private final ResourceTexture mCheckedItem;
private final ResourceTexture mUnCheckedItem;
private final SelectionManager mSelectionManager;
private final ResourceTexture mLocalAlbumIcon;
- private final StringTexture mCaching;
+ private final StringTexture mCachingText;
- public ManageCacheDrawer(Context context, SelectionManager selectionManager) {
+ private final int mCachePinSize;
+ private final int mCachePinMargin;
+
+ public ManageCacheDrawer(Context context, SelectionManager selectionManager,
+ int cachePinSize, int cachePinMargin) {
super(context);
- mFrame = new NinePatchTexture(context, R.drawable.manage_frame);
mCheckedItem = new ResourceTexture(context, R.drawable.btn_make_offline_normal_on_holo_dark);
mUnCheckedItem = new ResourceTexture(context, R.drawable.btn_make_offline_normal_off_holo_dark);
mLocalAlbumIcon = new ResourceTexture(context, R.drawable.btn_make_offline_disabled_on_holo_dark);
String cachingLabel = context.getString(R.string.caching_label);
- mCaching = StringTexture.newInstance(cachingLabel, 12, 0xffffffff);
+ mCachingText = StringTexture.newInstance(cachingLabel, 12, 0xffffffff);
mSelectionManager = selectionManager;
+ mCachePinSize = cachePinSize;
+ mCachePinMargin = cachePinMargin;
}
@Override
@@ -53,12 +55,11 @@
}
@Override
- public void draw(GLCanvas canvas, Texture content, int width, int height,
- int rotation, Path path, int topIndex, int dataSourceType,
- int mediaType, boolean wantCache, boolean isCaching) {
+ public void draw(GLCanvas canvas, Texture content, int width,
+ int height, int rotation, Path path, int topIndex,
+ int dataSourceType, int mediaType, boolean isPanorama,
+ int labelBackgroundHeight, boolean wantCache, boolean isCaching) {
- boolean selected = mSelectionManager.isItemSelected(path);
- boolean chooseToCache = wantCache ^ selected;
int x = -width / 2;
int y = -height / 2;
@@ -74,49 +75,54 @@
y = -height / 2;
}
- drawVideoOverlay(canvas, mediaType, x, y, width, height, topIndex);
-
- drawFrame(canvas, mFrame, x, y, width, height);
+ drawMediaTypeOverlay(canvas, mediaType, isPanorama, x, y, width, height,
+ topIndex);
if (topIndex == 0) {
+ drawLabelBackground(canvas, width, height, labelBackgroundHeight);
drawIcon(canvas, width, height, dataSourceType);
}
if (topIndex == 0) {
- ResourceTexture icon = null;
- if (isLocal(dataSourceType)) {
- icon = mLocalAlbumIcon;
- } else if (chooseToCache) {
- icon = mCheckedItem;
- } else {
- icon = mUnCheckedItem;
- }
+ drawCachingPin(canvas, path, dataSourceType, isCaching, wantCache,
+ width, height);
+ }
- int w = ICON_SIZE;
- int h = ICON_SIZE;
- x = width / 2 - w / 2;
- y = -height / 2 - h / 2;
+ if (mSelectionManager.isPressedPath(path)) {
+ drawPressedFrame(canvas, x, y, width, height);
+ }
+ }
- icon.draw(canvas, x, y, w, h);
+ private void drawCachingPin(GLCanvas canvas, Path path, int dataSourceType,
+ boolean isCaching, boolean wantCache, int width, int height) {
+ boolean selected = mSelectionManager.isItemSelected(path);
+ boolean chooseToCache = wantCache ^ selected;
- if (isCaching) {
- int textWidth = mCaching.getWidth();
- int textHeight = mCaching.getHeight();
- x = -textWidth / 2;
- y = height / 2 - textHeight;
+ ResourceTexture icon = null;
+ if (isLocal(dataSourceType)) {
+ icon = mLocalAlbumIcon;
+ } else if (chooseToCache) {
+ icon = mCheckedItem;
+ } else {
+ icon = mUnCheckedItem;
+ }
- // Leave a few pixels of margin in the background rect.
- float sideMargin = Utils.clamp(textWidth * 0.1f, 2.0f,
- 6.0f);
- float clearance = Utils.clamp(textHeight * 0.1f, 2.0f,
- 6.0f);
+ int w = mCachePinSize;
+ int h = mCachePinSize;
+ int right = (width + 1) / 2;
+ int bottom = (height + 1) / 2;
+ int x = right - w - mCachePinMargin;
+ int y = bottom - h - mCachePinMargin;
- // Overlay the "Caching" wording at the bottom-center of the content.
- canvas.fillRect(x - sideMargin, y - clearance,
- textWidth + sideMargin * 2, textHeight + clearance,
- COLOR_CACHING_BACKGROUND);
- mCaching.draw(canvas, x, y);
- }
+ icon.draw(canvas, x, y, w, h);
+
+ if (isCaching) {
+ int textWidth = mCachingText.getWidth();
+ int textHeight = mCachingText.getHeight();
+ // Align the center of the text to the center of the pin icon
+ x = right - mCachePinMargin - (textWidth + mCachePinSize) / 2;
+ y = bottom - textHeight;
+ mCachingText.draw(canvas, x, y);
}
}
diff --git a/src/com/android/gallery3d/ui/MultiLineTexture.java b/src/com/android/gallery3d/ui/MultiLineTexture.java
index be62d59..b0c3c2b 100644
--- a/src/com/android/gallery3d/ui/MultiLineTexture.java
+++ b/src/com/android/gallery3d/ui/MultiLineTexture.java
@@ -35,10 +35,11 @@
}
public static MultiLineTexture newInstance(
- String text, int maxWidth, float textSize, int color) {
+ String text, int maxWidth, float textSize, int color,
+ Layout.Alignment alignment) {
TextPaint paint = StringTexture.getDefaultPaint(textSize, color);
Layout layout = new StaticLayout(text, 0, text.length(), paint,
- maxWidth, Layout.Alignment.ALIGN_NORMAL, 1, 0, true, null, 0);
+ maxWidth, alignment, 1, 0, true, null, 0);
return new MultiLineTexture(layout);
}
diff --git a/src/com/android/gallery3d/ui/SelectionDrawer.java b/src/com/android/gallery3d/ui/SelectionDrawer.java
index 2655a22..70d8ad5 100644
--- a/src/com/android/gallery3d/ui/SelectionDrawer.java
+++ b/src/com/android/gallery3d/ui/SelectionDrawer.java
@@ -34,15 +34,15 @@
public abstract void prepareDrawing();
public abstract void draw(GLCanvas canvas, Texture content,
int width, int height, int rotation, Path path,
- int topIndex, int dataSourceType, int mediaType,
- boolean wantCache, boolean isCaching);
+ int topIndex, int dataSourceType, int mediaType, boolean isPanorama,
+ int labelBackgroundHeight, boolean wantCache, boolean isCaching);
public abstract void drawFocus(GLCanvas canvas, int width, int height);
public void draw(GLCanvas canvas, Texture content, int width, int height,
- int rotation, Path path, int mediaType) {
+ int rotation, Path path, int mediaType, boolean isPanorama) {
draw(canvas, content, width, height, rotation, path, 0,
- DATASOURCE_TYPE_NOT_CATEGORIZED, mediaType,
- false, false);
+ DATASOURCE_TYPE_NOT_CATEGORIZED, mediaType, isPanorama,
+ 0, false, false);
}
public static void drawWithRotation(GLCanvas canvas, Texture content,
diff --git a/src/com/android/gallery3d/ui/SelectionManager.java b/src/com/android/gallery3d/ui/SelectionManager.java
index 9599f5b..0ab69d2 100644
--- a/src/com/android/gallery3d/ui/SelectionManager.java
+++ b/src/com/android/gallery3d/ui/SelectionManager.java
@@ -47,6 +47,7 @@
private boolean mInSelectionMode;
private boolean mAutoLeave = true;
private int mTotal;
+ private Path mPressedPath;
public interface SelectionListener {
public void onSelectionModeChange(int mode);
@@ -141,6 +142,14 @@
}
}
+ public void setPressedPath(Path path) {
+ mPressedPath = path;
+ }
+
+ public boolean isPressedPath(Path path) {
+ return path != null && path == mPressedPath;
+ }
+
private static void expandMediaSet(ArrayList<Path> items, MediaSet set) {
int subCount = set.getSubMediaSetCount();
for (int i = 0; i < subCount; i++) {
diff --git a/src/com/android/gallery3d/ui/SlotView.java b/src/com/android/gallery3d/ui/SlotView.java
index a8ca5f2..3eb3f17 100644
--- a/src/com/android/gallery3d/ui/SlotView.java
+++ b/src/com/android/gallery3d/ui/SlotView.java
@@ -39,12 +39,16 @@
private static final int INDEX_NONE = -1;
public interface Listener {
+ public void onDown(int index);
+ public void onUp();
public void onSingleTapUp(int index);
public void onLongTap(int index);
public void onScrollPositionChanged(int position, int total);
}
public static class SimpleListener implements Listener {
+ public void onDown(int index) {}
+ public void onUp() {}
public void onSingleTapUp(int index) {}
public void onLongTap(int index) {}
public void onScrollPositionChanged(int position, int total) {}
@@ -126,8 +130,8 @@
updateScrollPosition(position, false);
}
- public void setSlotSize(int slotWidth, int slotHeight) {
- mLayout.setSlotSize(slotWidth, slotHeight);
+ public void setSlotSpec(Spec spec) {
+ mLayout.setSlotSpec(spec);
}
@Override
@@ -191,6 +195,7 @@
}
public void putDisplayItem(Position target, Position base, DisplayItem item) {
+ item.setBox(mLayout.getSlotWidth(), mLayout.getSlotHeight());
ItemEntry entry = new ItemEntry(item, target, base);
mItemList.insertLast(entry);
mItems.put(item, entry);
@@ -350,6 +355,41 @@
}
}
+ // This Spec class is used to specify the size of each slot in the SlotView.
+ // There are two ways to do it:
+ //
+ // (1) Specify slotWidth and slotHeight: they specify the width and height
+ // of each slot. The number of rows and the gap between slots will be
+ // determined automatically.
+ // (2) Specify rowsLand, rowsPort, and slotGap: they specify the number
+ // of rows in landscape/portrait mode and the gap between slots. The
+ // width and height of each slot is determined automatically.
+ //
+ // The initial value of -1 means they are not specified.
+ public static class Spec {
+ public int slotWidth = -1;
+ public int slotHeight = -1;
+
+ public int rowsLand = -1;
+ public int rowsPort = -1;
+ public int slotGap = -1;
+
+ static Spec newWithSize(int width, int height) {
+ Spec s = new Spec();
+ s.slotWidth = width;
+ s.slotHeight = height;
+ return s;
+ }
+
+ static Spec newWithRows(int rowsLand, int rowsPort, int slotGap) {
+ Spec s = new Spec();
+ s.rowsLand = rowsLand;
+ s.rowsPort = rowsPort;
+ s.slotGap = slotGap;
+ return s;
+ }
+ }
+
public static class Layout {
private int mVisibleStart;
@@ -358,6 +398,9 @@
private int mSlotCount;
private int mSlotWidth;
private int mSlotHeight;
+ private int mSlotGap;
+
+ private Spec mSpec;
private int mWidth;
private int mHeight;
@@ -369,9 +412,8 @@
private int mVerticalPadding;
private int mHorizontalPadding;
- public void setSlotSize(int slotWidth, int slotHeight) {
- mSlotWidth = slotWidth;
- mSlotHeight = slotHeight;
+ public void setSlotSpec(Spec spec) {
+ mSpec = spec;
}
public boolean setSlotCount(int slotCount) {
@@ -392,11 +434,19 @@
col = index - row * mUnitCount;
}
- int x = mHorizontalPadding + col * mSlotWidth;
- int y = mVerticalPadding + row * mSlotHeight;
+ int x = mHorizontalPadding + col * (mSlotWidth + mSlotGap);
+ int y = mVerticalPadding + row * (mSlotHeight + mSlotGap);
return new Rect(x, y, x + mSlotWidth, y + mSlotHeight);
}
+ public int getSlotWidth() {
+ return mSlotWidth;
+ }
+
+ public int getSlotHeight() {
+ return mSlotHeight;
+ }
+
public int getContentLength() {
return mContentLength;
}
@@ -417,17 +467,19 @@
int majorLength, int minorLength, /* The view width and height */
int majorUnitSize, int minorUnitSize, /* The slot width and height */
int[] padding) {
- int unitCount = minorLength / minorUnitSize;
+ int unitCount = (minorLength + mSlotGap) / (minorUnitSize + mSlotGap);
if (unitCount == 0) unitCount = 1;
mUnitCount = unitCount;
// We put extra padding above and below the column.
int availableUnits = Math.min(mUnitCount, mSlotCount);
- padding[0] = (minorLength - availableUnits * minorUnitSize) / 2;
+ int usedMinorLength = availableUnits * minorUnitSize +
+ (availableUnits - 1) * mSlotGap;
+ padding[0] = (minorLength - usedMinorLength) / 2;
// Then calculate how many columns we need for all slots.
int count = ((mSlotCount + mUnitCount - 1) / mUnitCount);
- mContentLength = count * majorUnitSize;
+ mContentLength = count * majorUnitSize + (count - 1) * mSlotGap;
// If the content length is less then the screen width, put
// extra padding in left and right.
@@ -435,6 +487,18 @@
}
private void initLayoutParameters() {
+ // Initialize mSlotWidth and mSlotHeight from mSpec
+ if (mSpec.slotWidth != -1) {
+ mSlotGap = 0;
+ mSlotWidth = mSpec.slotWidth;
+ mSlotHeight = mSpec.slotHeight;
+ } else {
+ int rows = (mWidth > mHeight) ? mSpec.rowsLand : mSpec.rowsPort;
+ mSlotGap = mSpec.slotGap;
+ mSlotHeight = Math.max(1, (mHeight - (rows - 1) * mSlotGap) / rows);
+ mSlotWidth = mSlotHeight;
+ }
+
int[] padding = new int[2];
if (WIDE) {
initLayoutParameters(mWidth, mHeight, mSlotWidth, mSlotHeight, padding);
@@ -458,14 +522,18 @@
int position = mScrollPosition;
if (WIDE) {
- int start = Math.max(0, (position / mSlotWidth) * mUnitCount);
- int end = Math.min(mSlotCount, mUnitCount
- * (position + mWidth + mSlotWidth - 1) / mSlotWidth);
+ int startCol = position / (mSlotWidth + mSlotGap);
+ int start = Math.max(0, mUnitCount * startCol);
+ int endCol = (position + mWidth + mSlotWidth + mSlotGap - 1) /
+ (mSlotWidth + mSlotGap);
+ int end = Math.min(mSlotCount, mUnitCount * endCol);
setVisibleRange(start, end);
} else {
- int start = Math.max(0, mUnitCount * (position / mSlotHeight));
- int end = Math.min(mSlotCount, mUnitCount
- * (position + mHeight + mSlotHeight - 1) / mSlotHeight);
+ int startRow = position / (mSlotHeight + mSlotGap);
+ int start = Math.max(0, mUnitCount * startRow);
+ int endRow = (position + mHeight + mSlotHeight + mSlotGap - 1) /
+ (mSlotHeight + mSlotGap);
+ int end = Math.min(mSlotCount, mUnitCount * endRow);
setVisibleRange(start, end);
}
}
@@ -495,21 +563,31 @@
}
public int getSlotIndexByPosition(float x, float y) {
- float absoluteX = x + (WIDE ? mScrollPosition : 0);
+ int absoluteX = Math.round(x) + (WIDE ? mScrollPosition : 0);
+ int absoluteY = Math.round(y) + (WIDE ? 0 : mScrollPosition);
+
absoluteX -= mHorizontalPadding;
- int columnIdx = (int) (absoluteX + 0.5) / mSlotWidth;
- if ((absoluteX - mSlotWidth * columnIdx) < 0
- || (!WIDE && columnIdx >= mUnitCount)) {
+ absoluteY -= mVerticalPadding;
+
+ int columnIdx = absoluteX / (mSlotWidth + mSlotGap);
+ int rowIdx = absoluteY / (mSlotHeight + mSlotGap);
+
+ if (columnIdx < 0 || (!WIDE && columnIdx >= mUnitCount)) {
return INDEX_NONE;
}
- float absoluteY = y + (WIDE ? 0 : mScrollPosition);
- absoluteY -= mVerticalPadding;
- int rowIdx = (int) (absoluteY + 0.5) / mSlotHeight;
- if (((absoluteY - mSlotHeight * rowIdx) < 0)
- || (WIDE && rowIdx >= mUnitCount)) {
+ if (rowIdx < 0 || (WIDE && rowIdx >= mUnitCount)) {
return INDEX_NONE;
}
+
+ if (absoluteX % (mSlotWidth + mSlotGap) >= mSlotWidth) {
+ return INDEX_NONE;
+ }
+
+ if (absoluteY % (mSlotHeight + mSlotGap) >= mSlotHeight) {
+ return INDEX_NONE;
+ }
+
int index = WIDE
? (columnIdx * mUnitCount + rowIdx)
: (rowIdx * mUnitCount + columnIdx);
@@ -523,12 +601,37 @@
}
}
- private class MyGestureListener
- extends GestureDetector.SimpleOnGestureListener {
+ private class MyGestureListener implements
+ GestureDetector.OnGestureListener {
+ private boolean isDown;
+
+ // We call the listener's onDown() when our onShowPress() is called and
+ // call the listener's onUp() when we receive any further event.
+ @Override
+ public void onShowPress(MotionEvent e) {
+ if (isDown) return;
+ int index = mLayout.getSlotIndexByPosition(e.getX(), e.getY());
+ if (index != INDEX_NONE) {
+ isDown = true;
+ mListener.onDown(index);
+ }
+ }
+
+ private void cancelDown() {
+ if (!isDown) return;
+ isDown = false;
+ mListener.onUp();
+ }
+
+ @Override
+ public boolean onDown(MotionEvent e) {
+ return false;
+ }
@Override
public boolean onFling(MotionEvent e1,
MotionEvent e2, float velocityX, float velocityY) {
+ cancelDown();
int scrollLimit = mLayout.getScrollLimit();
if (scrollLimit == 0) return false;
float velocity = WIDE ? velocityX : velocityY;
@@ -541,6 +644,7 @@
@Override
public boolean onScroll(MotionEvent e1,
MotionEvent e2, float distanceX, float distanceY) {
+ cancelDown();
float distance = WIDE ? distanceX : distanceY;
boolean canMove = mScroller.startScroll(
Math.round(distance), 0, mLayout.getScrollLimit());
@@ -553,6 +657,7 @@
@Override
public boolean onSingleTapUp(MotionEvent e) {
+ cancelDown();
if (mDownInScrolling) return true;
int index = mLayout.getSlotIndexByPosition(e.getX(), e.getY());
if (index != INDEX_NONE) mListener.onSingleTapUp(index);
@@ -561,6 +666,7 @@
@Override
public void onLongPress(MotionEvent e) {
+ cancelDown();
if (mDownInScrolling) return;
lockRendering();
try {
diff --git a/src/com/android/gallery3d/ui/StringTexture.java b/src/com/android/gallery3d/ui/StringTexture.java
index 71ab9b3..f576c01 100644
--- a/src/com/android/gallery3d/ui/StringTexture.java
+++ b/src/com/android/gallery3d/ui/StringTexture.java
@@ -56,21 +56,14 @@
}
public static StringTexture newInstance(
- String text, String postfix, float textSize, int color,
+ String text, float textSize, int color,
float lengthLimit, boolean isBold) {
TextPaint paint = getDefaultPaint(textSize, color);
if (isBold) {
paint.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));
}
- if (postfix != null) {
- lengthLimit = Math.max(0,
- lengthLimit - paint.measureText(postfix));
- text = TextUtils.ellipsize(text, paint, lengthLimit,
- TextUtils.TruncateAt.END).toString() + postfix;
- } else {
- text = TextUtils.ellipsize(
- text, paint, lengthLimit, TextUtils.TruncateAt.END).toString();
- }
+ text = TextUtils.ellipsize(
+ text, paint, lengthLimit, TextUtils.TruncateAt.END).toString();
return newInstance(text, paint);
}
diff --git a/src/com/android/gallery3d/ui/StripDrawer.java b/src/com/android/gallery3d/ui/StripDrawer.java
index 0910612..5120a0c 100644
--- a/src/com/android/gallery3d/ui/StripDrawer.java
+++ b/src/com/android/gallery3d/ui/StripDrawer.java
@@ -23,27 +23,43 @@
import android.graphics.Rect;
public class StripDrawer extends SelectionDrawer {
+ private NinePatchTexture mFramePressed;
private NinePatchTexture mFocusBox;
private Rect mFocusBoxPadding;
+ private Path mPressedPath;
public StripDrawer(Context context) {
+ mFramePressed = new NinePatchTexture(context, R.drawable.grid_pressed);
mFocusBox = new NinePatchTexture(context, R.drawable.focus_box);
mFocusBoxPadding = mFocusBox.getPaddings();
}
+ public void setPressedPath(Path path) {
+ mPressedPath = path;
+ }
+
+ private boolean isPressedPath(Path path) {
+ return path != null && path == mPressedPath;
+ }
+
@Override
public void prepareDrawing() {
}
@Override
- public void draw(GLCanvas canvas, Texture content, int width, int height,
- int rotation, Path path, int topIndex, int dataSourceType,
- int mediaType, boolean wantCache, boolean isCaching) {
+ public void draw(GLCanvas canvas, Texture content,
+ int width, int height, int rotation, Path path, int topIndex,
+ int dataSourceType, int mediaType, boolean isPanorama,
+ int labelBackgroundHeight, boolean wantCache, boolean isCaching) {
int x = -width / 2;
int y = -height / 2;
drawWithRotation(canvas, content, x, y, width, height, rotation);
+
+ if (isPressedPath(path)) {
+ drawFrame(canvas, mFramePressed, x, y, width, height);
+ }
}
@Override
diff --git a/src/com/android/gallery3d/util/GalleryUtils.java b/src/com/android/gallery3d/util/GalleryUtils.java
index 9c08dea..6803611 100644
--- a/src/com/android/gallery3d/util/GalleryUtils.java
+++ b/src/com/android/gallery3d/util/GalleryUtils.java
@@ -352,4 +352,11 @@
output[0] = number;
}
}
+
+ public static boolean isPanorama(MediaItem item) {
+ if (item == null) return false;
+ int w = item.getWidth();
+ int h = item.getHeight();
+ return (h > 0 && w / h >= 2);
+ }
}
diff --git a/tests/src/com/android/gallery3d/data/MockItem.java b/tests/src/com/android/gallery3d/data/MockItem.java
index bd6dcd9..2901979 100644
--- a/tests/src/com/android/gallery3d/data/MockItem.java
+++ b/tests/src/com/android/gallery3d/data/MockItem.java
@@ -40,4 +40,14 @@
public String getMimeType() {
return null;
}
+
+ @Override
+ public int getWidth() {
+ return 0;
+ }
+
+ @Override
+ public int getHeight() {
+ return 0;
+ }
}