summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--res/layout/filtershow_actionbar_effects.xml140
-rwxr-xr-x[-rw-r--r--]src/com/android/gallery3d/app/TimeLineDataLoader.java72
-rwxr-xr-x[-rw-r--r--]src/com/android/gallery3d/app/TimeLinePage.java414
-rwxr-xr-x[-rw-r--r--]src/com/android/gallery3d/data/TimeLineTitleMediaItem.java360
-rw-r--r--src/com/android/gallery3d/ui/TimeLineSlidingWindow.java143
-rw-r--r--src/com/android/gallery3d/ui/TimeLineSlotRenderer.java160
-rw-r--r--src/com/android/gallery3d/ui/TimeLineSlotView.java760
-rwxr-xr-x[-rw-r--r--]src/com/android/gallery3d/ui/TimeLineTitleMaker.java229
8 files changed, 958 insertions, 1320 deletions
diff --git a/res/layout/filtershow_actionbar_effects.xml b/res/layout/filtershow_actionbar_effects.xml
index 995399618..90554bbf2 100644
--- a/res/layout/filtershow_actionbar_effects.xml
+++ b/res/layout/filtershow_actionbar_effects.xml
@@ -2,6 +2,7 @@
<!--
Copyright (C) 2013 The Android Open Source Project
+
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
@@ -16,107 +17,54 @@
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/top"
android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical"
+ android:layout_height="48dip"
+ android:baselineAligned="false"
+ android:orientation="horizontal"
android:visibility="visible" >
- <View
- android:background="@color/toolbar_separation_line"
- android:layout_height="1dip"
- android:layout_width="match_parent"/>
+ <ImageButton
+ android:id="@+id/cancelFilter"
+ android:layout_width="wrap_content"
+ android:layout_height="fill_parent"
+ android:layout_gravity="left|center_vertical"
+ android:layout_weight=".1"
+ android:background="@android:color/transparent"
+ android:gravity="center"
+ android:src="@drawable/ic_menu_cancel_holo_light"
+ android:textSize="18dip" />
<LinearLayout
+ android:id="@+id/panelAccessoryViewList"
android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical">
-
- <LinearLayout
- android:id="@+id/controlArea"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:layout_alignParentBottom="true"
- android:visibility="visible">
-
- <SeekBar
- android:id="@+id/primarySeekBar"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_gravity="center_vertical"
- style="@style/FilterShowSlider"/>
-
- </LinearLayout>
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="48dip"
- android:background="@color/background_main_toolbar"
- android:orientation="horizontal"
- android:baselineAligned="false"
- android:visibility="visible">
-
- <ImageButton
- android:id="@+id/cancelFilter"
- android:layout_width="wrap_content"
- android:layout_height="fill_parent"
- android:layout_gravity="left|center_vertical"
- android:background="@android:color/transparent"
- android:layout_weight=".1"
- android:gravity="center"
- android:src="@drawable/ic_menu_cancel_holo_light"
- android:textSize="18dip"/>
-
- <ImageView
- android:layout_width="2dp"
- android:layout_height="fill_parent"
- android:src="@drawable/filtershow_vertical_bar"/>
-
- <LinearLayout
- android:id="@+id/panelAccessoryViewList"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:layout_weight="1"
- android:orientation="horizontal"
- android:visibility="visible">
-
- <com.android.gallery3d.filtershow.editors.SwapButton
- android:id="@+id/applyEffect"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:layout_gravity="center"
- android:background="@android:color/transparent"
- android:text="@string/apply_effect"
- android:textSize="18dip"
- android:drawableEnd="@drawable/filtershow_menu_marker_rtl"
- android:textAllCaps="true"
- />
-
- </LinearLayout>
-
- <ImageView
- android:layout_width="2dp"
- android:layout_height="fill_parent"
- android:src="@drawable/filtershow_vertical_bar"/>
-
- <ImageButton
- android:id="@+id/applyFilter"
- android:layout_width="wrap_content"
- android:layout_height="fill_parent"
- android:layout_gravity="right|center_vertical"
- android:layout_weight=".1"
- android:background="@android:color/transparent"
- android:gravity="center"
- android:src="@drawable/ic_menu_done_holo_light"
- android:textSize="18dip"/>
- </LinearLayout>
-
- <FrameLayout android:id="@+id/state_panel_container"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:visibility="visible" />
-
+ android:layout_height="match_parent"
+ android:layout_weight="1"
+ android:gravity="center"
+ android:orientation="horizontal"
+ android:visibility="visible" >
+
+ <com.android.gallery3d.filtershow.editors.SwapButton
+ android:id="@+id/applyEffect"
+ android:layout_width="@dimen/swap_button_width"
+ android:layout_height="@dimen/swap_button_height"
+ android:layout_gravity="center_vertical|center_horizontal"
+ android:background="@android:color/transparent"
+ android:drawableEnd="@drawable/spinner_triangle"
+ android:gravity="center"
+ android:text="@string/apply_effect"
+ android:textColor="#ffffff"
+ android:textSize="16sp" />
</LinearLayout>
-</LinearLayout>
+ <ImageButton
+ android:id="@+id/applyFilter"
+ android:layout_width="wrap_content"
+ android:layout_height="fill_parent"
+ android:layout_gravity="right|center_vertical"
+ android:layout_weight=".1"
+ android:background="@android:color/transparent"
+ android:gravity="center"
+ android:src="@drawable/ic_menu_done_holo_light"
+ android:textSize="18dip" />
+
+</LinearLayout> \ No newline at end of file
diff --git a/src/com/android/gallery3d/app/TimeLineDataLoader.java b/src/com/android/gallery3d/app/TimeLineDataLoader.java
index b56304e39..6817b8871 100644..100755
--- a/src/com/android/gallery3d/app/TimeLineDataLoader.java
+++ b/src/com/android/gallery3d/app/TimeLineDataLoader.java
@@ -19,8 +19,6 @@ package com.android.gallery3d.app;
import android.os.Handler;
import android.os.Message;
import android.os.Process;
-import android.text.TextUtils;
-import android.view.View;
import com.android.gallery3d.common.Utils;
import com.android.gallery3d.data.ContentListener;
@@ -28,6 +26,7 @@ import com.android.gallery3d.data.MediaItem;
import com.android.gallery3d.data.MediaObject;
import com.android.gallery3d.data.MediaSet;
import com.android.gallery3d.data.Path;
+import com.android.gallery3d.data.ClusterAlbumSet;
import com.android.gallery3d.ui.SynchronizedHandler;
import java.util.ArrayList;
@@ -35,12 +34,12 @@ import java.util.Arrays;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
-import java.util.Locale;
-public class AlbumDataLoader {
+public class TimeLineDataLoader {
@SuppressWarnings("unused")
- private static final String TAG = "AlbumDataAdapter";
+ private static final String TAG = "TimeLineDataLoader";
private static final int DATA_CACHE_SIZE = 1000;
+ private boolean mNewVersion = false;
private static final int MSG_LOAD_START = 1;
private static final int MSG_LOAD_FINISH = 2;
@@ -56,14 +55,17 @@ public class AlbumDataLoader {
public static interface DataListener {
public void onContentChanged(int index);
public void onSizeChanged(int size);
+ public void onVersionChanged();
}
+
private int mActiveStart = 0;
private int mActiveEnd = 0;
private int mContentStart = 0;
private int mContentEnd = 0;
+ private ArrayList<MediaItem> mTotalMediaItems;
private final MediaSet mSource;
private long mSourceVersion = MediaObject.INVALID_DATA_VERSION;
@@ -78,9 +80,8 @@ public class AlbumDataLoader {
// the data version on which last loading failed
private long mFailedVersion = MediaObject.INVALID_DATA_VERSION;
- public AlbumDataLoader(AbstractGalleryActivity context, MediaSet mediaSet) {
+ public TimeLineDataLoader(AbstractGalleryActivity context, MediaSet mediaSet) {
mSource = mediaSet;
-
mData = new MediaItem[DATA_CACHE_SIZE];
mItemVersion = new long[DATA_CACHE_SIZE];
mSetVersion = new long[DATA_CACHE_SIZE];
@@ -121,15 +122,31 @@ public class AlbumDataLoader {
mSource.removeContentListener(mSourceListener);
}
+
+ public MediaSet getMediaSet(int index) {
+ MediaSet mediaSet = ((ClusterAlbumSet)mSource).getAlbumFromindex(index);
+ return mediaSet;
+ }
+
public MediaItem get(int index) {
- if (!isActive(index)
- && View.LAYOUT_DIRECTION_LTR == TextUtils
- .getLayoutDirectionFromLocale(Locale.getDefault())) {
+ if (!isActive(index)) {
return mSource.getMediaItem(index, 1).get(0);
}
return mData[index % mData.length];
}
+ public MediaItem getTimeLineTitleItem(int index) {
+ return ((ClusterAlbumSet)mSource).getTimelineTitleMediaItem(index);
+ }
+
+ public int getTimeLineTitlesCount() {
+ return ((ClusterAlbumSet) mSource).getSubMediaSetCount();
+ }
+
+ public ArrayList<MediaItem> getAllMediaItems() {
+ return mTotalMediaItems;
+ }
+
public int getActiveStart() {
return mActiveStart;
}
@@ -170,8 +187,6 @@ public class AlbumDataLoader {
mContentStart = contentStart;
mContentEnd = contentEnd;
}
- long[] itemVersion = mItemVersion;
- long[] setVersion = mSetVersion;
if (contentStart >= end || start >= contentEnd) {
for (int i = start, n = end; i < n; ++i) {
clearSlot(i % DATA_CACHE_SIZE);
@@ -287,6 +302,9 @@ public class AlbumDataLoader {
@Override
public Void call() throws Exception {
UpdateInfo info = mUpdateInfo;
+ if ( info.version != mSourceVersion) {
+ mNewVersion = true;
+ }
mSourceVersion = info.version;
if (mSize != info.size) {
mSize = info.size;
@@ -312,14 +330,16 @@ public class AlbumDataLoader {
int index = i % DATA_CACHE_SIZE;
mSetVersion[index] = info.version;
MediaItem updateItem = items.get(i - info.reloadStart);
- long itemVersion = updateItem.getDataVersion();
- if (mItemVersion[index] != itemVersion) {
- mItemVersion[index] = itemVersion;
- mData[index] = updateItem;
- if (mDataListener != null && i >= mActiveStart && i < mActiveEnd) {
- mDataListener.onContentChanged(i);
+ if (updateItem != null) {
+ long itemVersion = updateItem.getDataVersion();
+ if (mItemVersion[index] != itemVersion) {
+ mItemVersion[index] = itemVersion;
+ mData[index] = updateItem;
+ if (mDataListener != null && i >= mActiveStart && i < mActiveEnd) {
+ mDataListener.onContentChanged(i);
+ }
}
- }
+ }
}
return null;
}
@@ -354,19 +374,17 @@ public class AlbumDataLoader {
@Override
public void run() {
- Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
+ Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
boolean updateComplete = false;
while (mActive) {
synchronized (this) {
if (mActive && !mDirty && updateComplete) {
updateLoading(false);
if (mFailedVersion != MediaObject.INVALID_DATA_VERSION) {
- Log.d(TAG, "reload pause");
}
Utils.waitWithoutInterrupt(this);
if (mActive && (mFailedVersion != MediaObject.INVALID_DATA_VERSION)) {
- Log.d(TAG, "reload resume");
}
continue;
}
@@ -376,7 +394,9 @@ public class AlbumDataLoader {
long version = mSource.reload();
UpdateInfo info = executeAndWait(new GetUpdateInfo(version));
updateComplete = info == null;
- if (updateComplete) continue;
+ if (updateComplete) {
+ continue;
+ }
if (info.version != version) {
info.size = mSource.getMediaItemCount();
info.version = version;
@@ -384,7 +404,13 @@ public class AlbumDataLoader {
if (info.reloadCount > 0) {
info.items = mSource.getMediaItem(info.reloadStart, info.reloadCount);
}
+
executeAndWait(new UpdateContent(info));
+ if (mNewVersion) {
+ mNewVersion = false;
+ mTotalMediaItems = mSource.getMediaItem(0, mSource.getMediaItemCount());
+ mDataListener.onVersionChanged();
+ }
}
updateLoading(false);
}
diff --git a/src/com/android/gallery3d/app/TimeLinePage.java b/src/com/android/gallery3d/app/TimeLinePage.java
index 932865a06..b3134ddcb 100644..100755
--- a/src/com/android/gallery3d/app/TimeLinePage.java
+++ b/src/com/android/gallery3d/app/TimeLinePage.java
@@ -1,4 +1,7 @@
/*
+ * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ *
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -19,36 +22,44 @@ package com.android.gallery3d.app;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
-import android.drm.DrmHelper;
+import android.content.res.Configuration;
+import android.graphics.Color;
import android.graphics.Rect;
import android.net.Uri;
+import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.provider.MediaStore;
import android.text.TextUtils;
+import android.util.TypedValue;
+import android.view.Gravity;
import android.view.HapticFeedbackConstants;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+import android.widget.RelativeLayout;
+import android.widget.TextView;
import android.widget.Toast;
-import com.android.gallery3d.R;
import com.android.gallery3d.common.Utils;
+import com.android.gallery3d.data.ClusterAlbum;
import com.android.gallery3d.data.DataManager;
import com.android.gallery3d.data.MediaDetails;
import com.android.gallery3d.data.MediaItem;
import com.android.gallery3d.data.MediaObject;
import com.android.gallery3d.data.MediaSet;
import com.android.gallery3d.data.Path;
+import com.android.gallery3d.data.ClusterAlbumSet;
import com.android.gallery3d.filtershow.crop.CropActivity;
import com.android.gallery3d.filtershow.crop.CropExtras;
import com.android.gallery3d.glrenderer.FadeTexture;
import com.android.gallery3d.glrenderer.GLCanvas;
import com.android.gallery3d.ui.ActionModeHandler;
import com.android.gallery3d.ui.ActionModeHandler.ActionModeListener;
-import com.android.gallery3d.ui.AlbumSlotRenderer;
import com.android.gallery3d.ui.DetailsHelper;
import com.android.gallery3d.ui.DetailsHelper.CloseListener;
import com.android.gallery3d.ui.GLRoot;
@@ -56,25 +67,26 @@ import com.android.gallery3d.ui.GLView;
import com.android.gallery3d.ui.PhotoFallbackEffect;
import com.android.gallery3d.ui.RelativePosition;
import com.android.gallery3d.ui.SelectionManager;
-import com.android.gallery3d.ui.SlotView;
import com.android.gallery3d.ui.SynchronizedHandler;
+import com.android.gallery3d.ui.TimeLineSlotRenderer;
+import com.android.gallery3d.ui.TimeLineSlotView;
import com.android.gallery3d.util.Future;
import com.android.gallery3d.util.GalleryUtils;
-import com.android.gallery3d.util.MediaSetUtils;
+import com.android.gallery3d.R;
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
import java.util.Locale;
-public class AlbumPage extends ActivityState implements GalleryActionBar.ClusterRunner,
- SelectionManager.SelectionListener, MediaSet.SyncListener, GalleryActionBar.OnAlbumModeSelectedListener {
- @SuppressWarnings("unused")
- private static final String TAG = "AlbumPage";
+public class TimeLinePage extends ActivityState implements
+ GalleryActionBar.ClusterRunner, SelectionManager.SelectionListener,
+ MediaSet.SyncListener, GalleryActionBar.OnAlbumModeSelectedListener {
+
+ private static final String TAG = "TimeLinePage";
public static final String KEY_MEDIA_PATH = "media-path";
- public static final String KEY_PARENT_MEDIA_PATH = "parent-media-path";
- public static final String KEY_SET_CENTER = "set-center";
public static final String KEY_AUTO_SELECT_ALL = "auto-select-all";
public static final String KEY_SHOW_CLUSTER_MENU = "cluster-menu";
- public static final String KEY_EMPTY_ALBUM = "empty-album";
public static final String KEY_RESUME_ANIMATION = "resume_animation";
private static final int REQUEST_SLIDESHOW = 1;
@@ -86,23 +98,16 @@ public class AlbumPage extends ActivityState implements GalleryActionBar.Cluster
private static final float USER_DISTANCE_METER = 0.3f;
- // Data cache size, equal to AlbumDataLoader.DATA_CACHE_SIZE
- private static final int DATA_CACHE_SIZE = 256;
-
private boolean mIsActive = false;
- private AlbumSlotRenderer mAlbumView;
+ private TimeLineSlotRenderer mAlbumView;
private Path mMediaSetPath;
- private String mParentMediaSetString;
- private SlotView mSlotView;
-
- private AlbumDataLoader mAlbumDataAdapter;
-
+ private TimeLineSlotView mSlotView;
+ private TimeLineDataLoader mAlbumDataAdapter;
protected SelectionManager mSelectionManager;
-
private boolean mGetContent;
private boolean mShowClusterMenu;
- private ActionModeHandler mActionModeHandler;
+ protected ActionModeHandler mActionModeHandler;
private int mFocusIndex = 0;
private DetailsHelper mDetailsHelper;
private MyDetailsSource mDetailsSource;
@@ -112,7 +117,7 @@ public class AlbumPage extends ActivityState implements GalleryActionBar.Cluster
private Future<Integer> mSyncTask = null;
private boolean mLaunchedFromPhotoPage;
private boolean mInCameraApp;
- private boolean mInCameraAndWantQuitOnPause;
+ private TextView tvEmptyAlbum;
private int mLoadingBits = 0;
private boolean mInitialSynced = false;
@@ -126,26 +131,30 @@ public class AlbumPage extends ActivityState implements GalleryActionBar.Cluster
private PhotoFallbackEffect mResumeEffect;
private PhotoFallbackEffect.PositionProvider mPositionProvider =
new PhotoFallbackEffect.PositionProvider() {
- @Override
- public Rect getPosition(int index) {
- Rect rect = mSlotView.getSlotRect(index);
- Rect bounds = mSlotView.bounds();
- rect.offset(bounds.left - mSlotView.getScrollX(),
- bounds.top - mSlotView.getScrollY());
- return rect;
- }
+ @Override
+ public Rect getPosition(int index) {
+ Rect rect = mSlotView.getSlotRect(index);
+ Rect bounds = mSlotView.bounds();
+ rect.offset(bounds.left - mSlotView.getScrollX(),
+ bounds.top - mSlotView.getScrollY());
+ return rect;
+ }
+
+ @Override
+ public int getItemIndex(Path path) {
+ int start = mSlotView.getVisibleStart();
+ int end = mSlotView.getVisibleEnd();
+ for (int i = start; i < end; ++i) {
+ MediaItem item = mAlbumDataAdapter.get(i);
+ if (item != null && item.getPath() == path) return i;
+ }
+ return -1;
+ }
+ };
+
+ private Button mCameraButton;
+ private boolean mShowedEmptyToastForSelf = false;
- @Override
- public int getItemIndex(Path path) {
- int start = mSlotView.getVisibleStart();
- int end = mSlotView.getVisibleEnd();
- for (int i = start; i < end; ++i) {
- MediaItem item = mAlbumDataAdapter.get(i);
- if (item != null && item.getPath() == path) return i;
- }
- return -1;
- }
- };
@Override
protected int getBackgroundColorId() {
@@ -160,8 +169,14 @@ public class AlbumPage extends ActivityState implements GalleryActionBar.Cluster
boolean changed, int left, int top, int right, int bottom) {
int slotViewTop = mActivity.getGalleryActionBar().getHeight();
+ int padding =0 ;
+ if((right - left) > (bottom - top)) {
+ padding = (int) mActivity.getResources().getDimension(R.dimen.timeline_land_margin);
+ } else {
+ padding = (int) mActivity.getResources().getDimension(R.dimen.timeline_port_margin);
+ }
int slotViewBottom = bottom - top;
- int slotViewRight = right - left;
+ int slotViewRight = right - left - padding;
if (mShowDetails) {
mDetailsHelper.layout(left, slotViewTop, right, bottom);
@@ -171,7 +186,7 @@ public class AlbumPage extends ActivityState implements GalleryActionBar.Cluster
// Set the mSlotView as a reference point to the open animation
mOpenCenter.setReferencePosition(0, slotViewTop);
- mSlotView.layout(0, slotViewTop, slotViewRight, slotViewBottom);
+ mSlotView.layout(padding, slotViewTop, slotViewRight, slotViewBottom);
GalleryUtils.setViewPointMatrix(mMatrix,
(right - left) / 2, (bottom - top) / 2, -mUserDistance);
}
@@ -215,12 +230,10 @@ public class AlbumPage extends ActivityState implements GalleryActionBar.Cluster
mSelectionManager.leaveSelectionMode();
} else {
if(mLaunchedFromPhotoPage) {
- mActivity.getTransitionStore().putIfNotPresent(
- PhotoPage.KEY_ALBUMPAGE_TRANSITION,
- PhotoPage.MSG_ALBUMPAGE_RESUMED);
+ mActivity.getTransitionStore().putIfNotPresent(
+ PhotoPage.KEY_ALBUMPAGE_TRANSITION,
+ PhotoPage.MSG_ALBUMPAGE_RESUMED);
}
- // TODO: fix this regression
- // mAlbumView.savePositions(PositionRepository.getInstance(mActivity));
if (mInCameraApp) {
super.onBackPressed();
} else {
@@ -232,14 +245,8 @@ public class AlbumPage extends ActivityState implements GalleryActionBar.Cluster
private void onUpPressed() {
if (mInCameraApp) {
GalleryUtils.startGalleryActivity(mActivity);
- } else if (mActivity.getStateManager().getStateCount() > 1) {
+ } else
super.onBackPressed();
- } else if (mParentMediaSetString != null) {
- Bundle data = new Bundle(getData());
- data.putString(AlbumSetPage.KEY_MEDIA_PATH, mParentMediaSetString);
- mActivity.getStateManager().switchState(
- this, AlbumSetPage.class, data);
- }
}
private void onDown(int index) {
@@ -255,35 +262,32 @@ public class AlbumPage extends ActivityState implements GalleryActionBar.Cluster
}
}
- private void onSingleTapUp(int slotIndex) {
+ private void onSingleTapUp(int slotIndex , boolean isTitle) {
if (!mIsActive) return;
-
- if (mSelectionManager.inSelectionMode()) {
- MediaItem item = mAlbumDataAdapter.get(slotIndex);
- if (item == null) return; // Item not ready yet, ignore the click
- mSelectionManager.toggle(item.getPath());
- mSlotView.invalidate();
- } else {
- // Render transition in pressed state
- mAlbumView.setPressedIndex(slotIndex);
- mAlbumView.setPressedUp();
- mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_PICK_PHOTO, slotIndex, 0),
- FadeTexture.DURATION);
- }
+ if (mSelectionManager.inSelectionMode()) {
+ if(isTitle){
+ MediaSet targetSet = mAlbumDataAdapter.getMediaSet(slotIndex);
+ if (targetSet == null) return;
+ ArrayList<Path> paths = ((ClusterAlbum)targetSet).getMediaItems();
+ if (paths == null || paths.size() <= 0) return;
+ mSelectionManager.toggleTimeLineSet(paths);
+ mSlotView.invalidate();
+ } else {
+ MediaItem item = mAlbumDataAdapter.get(slotIndex);
+ if (item == null) return; // Item not ready yet, ignore the click
+ mSelectionManager.toggle(item.getPath());
+ mSlotView.invalidate();
+ }
+ } else if(!isTitle){
+ // Render transition in pressed state
+ mAlbumView.setPressedIndex(slotIndex);
+ mAlbumView.setPressedUp();
+ mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_PICK_PHOTO, slotIndex, 0),
+ FadeTexture.DURATION);
+ }
}
private void pickPhoto(int slotIndex) {
- if ((View.LAYOUT_DIRECTION_RTL == TextUtils
- .getLayoutDirectionFromLocale(Locale.getDefault()))
- && !mGetContent) {
- // Fetch corresponding slotIndex from another side, (RTL)
- if (slotIndex > DATA_CACHE_SIZE / 2
- && slotIndex < mAlbumDataAdapter.size() - DATA_CACHE_SIZE / 2) {
- slotIndex = mAlbumDataAdapter.size() - slotIndex - 2;
- } else {
- slotIndex = mAlbumDataAdapter.size() - slotIndex - 1;
- }
- }
pickPhoto(slotIndex, false);
}
@@ -297,30 +301,11 @@ public class AlbumPage extends ActivityState implements GalleryActionBar.Cluster
MediaItem item = mAlbumDataAdapter.get(slotIndex);
- // Checking it is RTL or not
- boolean isLayoutRtl = (View.LAYOUT_DIRECTION_RTL == TextUtils
- .getLayoutDirectionFromLocale(Locale.getDefault())) ? true : false;
-
- // When not RTL, return directly to ignore the click
- if (!isLayoutRtl && item == null) {
- return;
- }
-
if (mGetContent) {
- if (isLayoutRtl && item == null) {
+ if (item == null)
return; // Item not ready yet, ignore the click
- }
- if (DrmHelper.isDrmFile(DrmHelper.getFilePath(
- mActivity.getAndroidContext(), item.getContentUri()))) {
- Toast.makeText(mActivity, R.string.no_permission_for_drm,
- Toast.LENGTH_SHORT).show();
- return;
- }
onGetContent(item);
} else if (mLaunchedFromPhotoPage) {
- if (isLayoutRtl && item == null) {
- return; // Item not ready yet, ignore the click
- }
TransitionStore transitions = mActivity.getTransitionStore();
transitions.put(
PhotoPage.KEY_ALBUMPAGE_TRANSITION,
@@ -328,31 +313,25 @@ public class AlbumPage extends ActivityState implements GalleryActionBar.Cluster
transitions.put(PhotoPage.KEY_INDEX_HINT, slotIndex);
onBackPressed();
} else {
- // Get into the PhotoPage.
- // mAlbumView.savePositions(PositionRepository.getInstance(mActivity));
+ MediaSet targetset = mAlbumDataAdapter.getMediaSet(slotIndex);
+ if (targetset == null || item == null) return;
+
Bundle data = new Bundle();
- data.putInt(PhotoPage.KEY_INDEX_HINT, slotIndex);
+ data.putInt(PhotoPage.KEY_INDEX_HINT, slotIndex-1);
+ data.putString(PhotoPage.KEY_MEDIA_SET_PATH,
+ targetset.getPath().toString());
data.putParcelable(PhotoPage.KEY_OPEN_ANIMATION_RECT,
mSlotView.getSlotRect(slotIndex, mRootPane));
- data.putString(PhotoPage.KEY_MEDIA_SET_PATH,
- mMediaSetPath.toString());
-
- // Item not ready yet, don't pass the photo path to bundle
- if (!isLayoutRtl && item != null) {
- data.putString(PhotoPage.KEY_MEDIA_ITEM_PATH,
- item.getPath().toString());
- }
+ data.putString(PhotoPage.KEY_MEDIA_ITEM_PATH,
+ item.getPath().toString());
+ data.putBoolean(PhotoPage.KEY_FROM_TIMELINE_SCREEN, true);
data.putInt(PhotoPage.KEY_ALBUMPAGE_TRANSITION,
PhotoPage.MSG_ALBUMPAGE_STARTED);
data.putBoolean(PhotoPage.KEY_START_IN_FILMSTRIP,
startInFilmstrip);
- data.putBoolean(PhotoPage.KEY_IN_CAMERA_ROLL, mMediaSet.isCameraRoll());
- if (startInFilmstrip) {
- mActivity.getStateManager().switchState(this, FilmstripPage.class, data);
- } else {
- mActivity.getStateManager().startStateForResult(
- SinglePhotoPage.class, REQUEST_PHOTO, data);
- }
+ data.putBoolean(PhotoPage.KEY_IN_CAMERA_ROLL, targetset.isCameraRoll());
+ mActivity.getStateManager().startStateForResult(
+ SinglePhotoPage.class, REQUEST_PHOTO, data);
}
}
@@ -371,19 +350,29 @@ public class AlbumPage extends ActivityState implements GalleryActionBar.Cluster
activity.finish();
} else {
Intent intent = new Intent(null, item.getContentUri())
- .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+ .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
activity.setResult(Activity.RESULT_OK, intent);
activity.finish();
}
}
- public void onLongTap(int slotIndex) {
+ public void onLongTap(int slotIndex, boolean isTitle) {
if (mGetContent) return;
- MediaItem item = mAlbumDataAdapter.get(slotIndex);
- if (item == null) return;
- mSelectionManager.setAutoLeaveSelectionMode(true);
- mSelectionManager.toggle(item.getPath());
- mSlotView.invalidate();
+ if(isTitle){
+ MediaSet targetSet = mAlbumDataAdapter.getMediaSet(slotIndex);
+ if (targetSet == null) return;
+ ArrayList<Path> paths = ((ClusterAlbum)targetSet).getMediaItems();
+ if (paths == null || paths.size() <= 0) return;
+ mSelectionManager.setAutoLeaveSelectionMode(true);
+ mSelectionManager.toggleTimeLineSet(paths);
+ mSlotView.invalidate();
+ } else {
+ MediaItem item = mAlbumDataAdapter.get(slotIndex);
+ if (item == null) return;
+ mSelectionManager.setAutoLeaveSelectionMode(true);
+ mSelectionManager.toggle(item.getPath());
+ mSlotView.invalidate();
+ }
}
@Override
@@ -399,7 +388,6 @@ public class AlbumPage extends ActivityState implements GalleryActionBar.Cluster
GalleryActionBar.getClusterByTypeString(context, clusterType));
}
- // mAlbumView.savePositions(PositionRepository.getInstance(mActivity));
mActivity.getStateManager().startStateForResult(
AlbumSetPage.class, REQUEST_DO_ANIMATION, data);
}
@@ -413,7 +401,6 @@ public class AlbumPage extends ActivityState implements GalleryActionBar.Cluster
mGetContent = data.getBoolean(GalleryActivity.KEY_GET_CONTENT, false);
mShowClusterMenu = data.getBoolean(KEY_SHOW_CLUSTER_MENU, false);
mDetailsSource = new MyDetailsSource();
- Context context = mActivity.getAndroidContext();
if (data.getBoolean(KEY_AUTO_SELECT_ALL)) {
mSelectionManager.selectAll();
@@ -441,6 +428,7 @@ public class AlbumPage extends ActivityState implements GalleryActionBar.Cluster
@Override
protected void onResume() {
super.onResume();
+
mIsActive = true;
mResumeEffect = mActivity.getTransitionStore().get(KEY_RESUME_ANIMATION);
@@ -452,14 +440,6 @@ public class AlbumPage extends ActivityState implements GalleryActionBar.Cluster
setContentPane(mRootPane);
- boolean enableHomeButton = (mActivity.getStateManager().getStateCount() > 1) |
- mParentMediaSetString != null;
- GalleryActionBar actionBar = mActivity.getGalleryActionBar();
- actionBar.setDisplayOptions(enableHomeButton, false);
- if (!mGetContent) {
- actionBar.enableAlbumModeMenu(GalleryActionBar.ALBUM_GRID_MODE_SELECTED, this);
- }
-
// Set the reload bit here to prevent it exit this page in clearLoadingBit().
setLoadingBit(BIT_LOADING_RELOAD);
mLoadingFailed = false;
@@ -472,7 +452,6 @@ public class AlbumPage extends ActivityState implements GalleryActionBar.Cluster
setLoadingBit(BIT_LOADING_SYNC);
mSyncTask = mMediaSet.requestSync(this);
}
- mInCameraAndWantQuitOnPause = mInCameraApp;
}
@Override
@@ -488,15 +467,18 @@ public class AlbumPage extends ActivityState implements GalleryActionBar.Cluster
mAlbumDataAdapter.pause();
mAlbumView.pause();
DetailsHelper.pause();
- if (!mGetContent) {
+ /*if (!mGetContent) {
mActivity.getGalleryActionBar().disableAlbumModeMenu(true);
- }
+ }*/
if (mSyncTask != null) {
mSyncTask.cancel();
mSyncTask = null;
clearLoadingBit(BIT_LOADING_SYNC);
}
+
+ hideEmptyAlbumToast();
+ hideCameraButton();
}
@Override
@@ -511,31 +493,31 @@ public class AlbumPage extends ActivityState implements GalleryActionBar.Cluster
private void initializeViews() {
mSelectionManager = new SelectionManager(mActivity, false);
mSelectionManager.setSelectionListener(this);
- Config.AlbumPage config = Config.AlbumPage.get(mActivity);
- mSlotView = new SlotView(mActivity, config.slotViewSpec);
- mAlbumView = new AlbumSlotRenderer(mActivity, mSlotView,
- mSelectionManager, config.placeholderColor);
+ Config.TimeLinePage config = Config.TimeLinePage.get(mActivity);
+ mSlotView = new TimeLineSlotView(mActivity, config.slotViewSpec);
+ mAlbumView = new TimeLineSlotRenderer(mActivity, mSlotView,
+ mSelectionManager, config.labelSpec, config.placeholderColor);
mSlotView.setSlotRenderer(mAlbumView);
mRootPane.addComponent(mSlotView);
- mSlotView.setListener(new SlotView.SimpleListener() {
+ mSlotView.setListener(new TimeLineSlotView.SimpleListener() {
@Override
public void onDown(int index) {
- AlbumPage.this.onDown(index);
+ TimeLinePage.this.onDown(index);
}
@Override
public void onUp(boolean followedByLongPress) {
- AlbumPage.this.onUp(followedByLongPress);
+ TimeLinePage.this.onUp(followedByLongPress);
}
@Override
- public void onSingleTapUp(int slotIndex) {
- AlbumPage.this.onSingleTapUp(slotIndex);
+ public void onSingleTapUp(int slotIndex, boolean isTitle) {
+ TimeLinePage.this.onSingleTapUp(slotIndex, isTitle);
}
@Override
- public void onLongTap(int slotIndex) {
- AlbumPage.this.onLongTap(slotIndex);
+ public void onLongTap(int slotIndex, boolean isTitle) {
+ TimeLinePage.this.onLongTap(slotIndex, isTitle);
}
});
mActionModeHandler = new ActionModeHandler(mActivity, mSelectionManager);
@@ -549,13 +531,13 @@ public class AlbumPage extends ActivityState implements GalleryActionBar.Cluster
private void initializeData(Bundle data) {
mMediaSetPath = Path.fromString(data.getString(KEY_MEDIA_PATH));
- mParentMediaSetString = data.getString(KEY_PARENT_MEDIA_PATH);
mMediaSet = mActivity.getDataManager().getMediaSet(mMediaSetPath);
if (mMediaSet == null) {
Utils.fail("MediaSet is null. Path = %s", mMediaSetPath);
}
+ mAlbumDataAdapter = new TimeLineDataLoader(mActivity, mMediaSet);
mSelectionManager.setSourceMediaSet(mMediaSet);
- mAlbumDataAdapter = new AlbumDataLoader(mActivity, mMediaSet);
+ //mSelectionManager.setAlbumDataAdapter(mAlbumDataAdapter);
mAlbumDataAdapter.setLoadingListener(new MyLoadingListener());
mAlbumView.setModel(mAlbumDataAdapter);
}
@@ -592,17 +574,15 @@ public class AlbumPage extends ActivityState implements GalleryActionBar.Cluster
actionBar.setTitle(GalleryUtils.getSelectionModePrompt(typeBits));
} else {
inflator.inflate(R.menu.album, menu);
- actionBar.setTitle(mMediaSet.getName());
+ actionBar.setTitle(R.string.timeline_title);
FilterUtils.setupMenuItems(actionBar, mMediaSetPath, true);
-
- menu.findItem(R.id.action_group_by).setVisible(mShowClusterMenu);
- menu.findItem(R.id.action_camera).setVisible(
- MediaSetUtils.isCameraSource(mMediaSetPath)
- && GalleryUtils.isCameraAvailable(mActivity));
-
+ //menu.findItem(R.id.action_group_by).setVisible(mShowClusterMenu);
+ menu.findItem(R.id.action_camera).setVisible(GalleryUtils.isAnyCameraAvailable(mActivity));
+ menu.findItem(R.id.action_sync_picasa_albums).setVisible(true);
+ menu.findItem(R.id.action_view_type).setVisible(false);
}
- actionBar.setSubtitle(null);
+
return true;
}
@@ -647,15 +627,10 @@ public class AlbumPage extends ActivityState implements GalleryActionBar.Cluster
mActivity.getStateManager().finishState(this);
return true;
case R.id.action_select:
- mSelectionManager.setAutoLeaveSelectionMode(false);
+ mSelectionManager.setAutoLeaveSelectionMode(true);
mSelectionManager.enterSelectionMode();
return true;
- case R.id.action_group_by: {
- mActivity.getGalleryActionBar().showClusterDialog(this);
- return true;
- }
case R.id.action_slideshow: {
- mInCameraAndWantQuitOnPause = false;
Bundle data = new Bundle();
data.putString(SlideshowPage.KEY_SET_PATH,
mMediaSetPath.toString());
@@ -684,7 +659,8 @@ public class AlbumPage extends ActivityState implements GalleryActionBar.Cluster
@Override
protected void onStateResult(int request, int result, Intent data) {
switch (request) {
- case REQUEST_SLIDESHOW: {
+ case REQUEST_SLIDESHOW:
+ {
// data could be null, if there is no images in the album
if (data == null) return;
mFocusIndex = data.getIntExtra(SlideshowPage.KEY_PHOTO_INDEX, 0);
@@ -694,22 +670,7 @@ public class AlbumPage extends ActivityState implements GalleryActionBar.Cluster
case REQUEST_PHOTO: {
if (data == null) return;
mFocusIndex = data.getIntExtra(PhotoPage.KEY_RETURN_INDEX_HINT, 0);
- if (View.LAYOUT_DIRECTION_RTL == TextUtils
- .getLayoutDirectionFromLocale(Locale.getDefault())) {
- // Fetch corresponding index from another side, only in RTL
- mFocusIndex = mAlbumDataAdapter.size() - mFocusIndex - 1;
- // Prepare to jump to mFocusIndex position, only enabled in RTL
- mSlotView.setIsFromPhotoPage(true);
- }
-
- // Let picture of mFocusIndex visible
mSlotView.makeSlotVisible(mFocusIndex);
-
- if (View.LAYOUT_DIRECTION_RTL == TextUtils
- .getLayoutDirectionFromLocale(Locale.getDefault())) {
- // Reset variable
- mSlotView.setIsFromPhotoPage(false);
- }
break;
}
case REQUEST_DO_ANIMATION: {
@@ -725,14 +686,17 @@ public class AlbumPage extends ActivityState implements GalleryActionBar.Cluster
case SelectionManager.ENTER_SELECTION_MODE: {
mActionModeHandler.startActionMode();
performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
+ ((GalleryActivity)mActivity).toggleNavDrawer(false);
break;
}
case SelectionManager.LEAVE_SELECTION_MODE: {
mActionModeHandler.finishActionMode();
+ ((GalleryActivity)mActivity).toggleNavDrawer(true);
mRootPane.invalidate();
break;
}
- case SelectionManager.SELECT_ALL_MODE: {
+ case SelectionManager.SELECT_ALL_MODE:
+ case SelectionManager.SELECT_NONE_MODE: {
mActionModeHandler.updateSupportedOperation();
mRootPane.invalidate();
break;
@@ -753,7 +717,7 @@ public class AlbumPage extends ActivityState implements GalleryActionBar.Cluster
public void onSyncDone(final MediaSet mediaSet, final int resultCode) {
Log.d(TAG, "onSyncDone: " + Utils.maskDebugInfo(mediaSet.getName()) + " result="
+ resultCode);
- ((Activity) mActivity).runOnUiThread(new Runnable() {
+ mActivity.runOnUiThread(new Runnable() {
@Override
public void run() {
GLRoot root = mActivity.getGLRoot();
@@ -793,11 +757,19 @@ public class AlbumPage extends ActivityState implements GalleryActionBar.Cluster
mLoadingBits &= ~loadTaskBit;
if (mLoadingBits == 0 && mIsActive) {
if (mAlbumDataAdapter.size() == 0) {
- Intent result = new Intent();
- result.putExtra(KEY_EMPTY_ALBUM, true);
- setStateResult(Activity.RESULT_OK, result);
- mActivity.getStateManager().finishState(this);
+ mShowedEmptyToastForSelf = true;
+ showEmptyAlbumToast(Toast.LENGTH_LONG);
+ mSlotView.invalidate();
}
+ return;
+ }
+ // Hide the empty album toast if we are in the root instance of
+ // AlbumSetPage and the album is no longer empty (for instance,
+ // after a sync is completed and web albums have been synced)
+ if (mShowedEmptyToastForSelf) {
+ mShowedEmptyToastForSelf = false;
+ hideEmptyAlbumToast();
+ //hideCameraButton();
}
}
@@ -821,19 +793,22 @@ public class AlbumPage extends ActivityState implements GalleryActionBar.Cluster
@Override
public int size() {
- return mAlbumDataAdapter.size();
+ return mAlbumDataAdapter.size() - mAlbumDataAdapter.getTimeLineTitlesCount();
}
@Override
public int setIndex() {
+ if (mSelectionManager.getSelected(false) == null) return -1;
Path id = mSelectionManager.getSelected(false).get(0);
mIndex = mAlbumDataAdapter.findItem(id);
- return mIndex;
+ int albumIndex = ((ClusterAlbumSet) mMediaSet).findTimelineAlbumIndex(mIndex);
+ return mIndex - albumIndex - 1;
}
@Override
public MediaDetails getDetails() {
// this relies on setIndex() being called beforehand
+ if (mIndex < 0) return null;
MediaObject item = mAlbumDataAdapter.get(mIndex);
if (item != null) {
mAlbumView.setHighlightItemPath(item.getPath());
@@ -850,4 +825,61 @@ public class AlbumPage extends ActivityState implements GalleryActionBar.Cluster
switchToFilmstrip();
}
}
+
+ private WeakReference<Toast> mEmptyAlbumToast = null;
+
+ private void showCameraButton() {
+ if (mCameraButton == null && !setupCameraButton()) return;
+ mCameraButton.setVisibility(View.VISIBLE);
+ }
+
+ private void hideCameraButton() {
+ if (mCameraButton == null) return;
+ mCameraButton.setVisibility(View.GONE);
+ }
+
+ private boolean setupCameraButton() {
+ if (!GalleryUtils.isAnyCameraAvailable(mActivity)) return false;
+ RelativeLayout galleryRoot = (RelativeLayout)mActivity.findViewById(R.id.gallery_root);
+ if (galleryRoot == null) return false;
+
+ mCameraButton = new Button(mActivity);
+ mCameraButton.setText(R.string.camera_label);
+ mCameraButton.setCompoundDrawablesWithIntrinsicBounds(0, R.drawable.frame_overlay_gallery_camera, 0, 0);
+ mCameraButton.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View arg0) {
+ GalleryUtils.startCameraActivity(mActivity);
+ }
+ });
+ RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(
+ RelativeLayout.LayoutParams.WRAP_CONTENT,
+ RelativeLayout.LayoutParams.WRAP_CONTENT);
+ lp.addRule(RelativeLayout.CENTER_IN_PARENT);
+ galleryRoot.addView(mCameraButton, lp);
+ return true;
+ }
+
+ private void showEmptyAlbumToast(int toastLength) {
+ tvEmptyAlbum = new TextView(mActivity);
+ tvEmptyAlbum.setText(R.string.tvEmptyAlbum);
+ tvEmptyAlbum.setTextColor(Color.parseColor("#8A000000"));
+ tvEmptyAlbum.setGravity(Gravity.CENTER);
+ tvEmptyAlbum.setTextSize(TypedValue.COMPLEX_UNIT_SP,20);
+ RelativeLayout galleryRoot = (RelativeLayout) ((Activity) mActivity)
+ .findViewById(R.id.gallery_root);
+ RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(
+ RelativeLayout.LayoutParams.WRAP_CONTENT,
+ RelativeLayout.LayoutParams.WRAP_CONTENT);
+ lp.addRule(RelativeLayout.CENTER_IN_PARENT);
+ galleryRoot.addView(tvEmptyAlbum, lp);
+ }
+
+ private void hideEmptyAlbumToast() {
+
+ if (tvEmptyAlbum != null)
+ {
+ tvEmptyAlbum.setVisibility(View.GONE);
+ }
+ }
}
diff --git a/src/com/android/gallery3d/data/TimeLineTitleMediaItem.java b/src/com/android/gallery3d/data/TimeLineTitleMediaItem.java
index 1b0384548..cb24c669b 100644..100755
--- a/src/com/android/gallery3d/data/TimeLineTitleMediaItem.java
+++ b/src/com/android/gallery3d/data/TimeLineTitleMediaItem.java
@@ -1,4 +1,7 @@
/*
+ * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ *
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -16,370 +19,67 @@
package com.android.gallery3d.data;
-import android.annotation.TargetApi;
-import android.content.ContentResolver;
-import android.content.ContentValues;
-import android.database.Cursor;
-import android.drm.DrmHelper;
import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
import android.graphics.BitmapRegionDecoder;
-import android.net.Uri;
-import android.os.Build;
-import android.provider.MediaStore.Images;
-import android.provider.MediaStore.Images.ImageColumns;
-import android.provider.MediaStore.MediaColumns;
-import android.util.Log;
-import com.android.gallery3d.app.GalleryApp;
-import com.android.gallery3d.app.PanoramaMetadataSupport;
-import com.android.gallery3d.common.ApiHelper;
-import com.android.gallery3d.common.BitmapUtils;
-import com.android.gallery3d.exif.ExifInterface;
-import com.android.gallery3d.exif.ExifTag;
-import com.android.gallery3d.filtershow.tools.SaveImage;
+import com.android.gallery3d.common.Utils;
+import com.android.gallery3d.ui.TimeLineTitleMaker;
import com.android.gallery3d.util.GalleryUtils;
import com.android.gallery3d.util.ThreadPool.Job;
-import com.android.gallery3d.util.ThreadPool.JobContext;
-import com.android.gallery3d.util.UpdateHelper;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-
-// LocalImage represents an image in the local storage.
-public class LocalImage extends LocalMediaItem {
- private static final String TAG = "LocalImage";
-
- static final Path ITEM_PATH = Path.fromString("/local/image/item");
-
- // Must preserve order between these indices and the order of the terms in
- // the following PROJECTION array.
- private static final int INDEX_ID = 0;
- private static final int INDEX_CAPTION = 1;
- private static final int INDEX_MIME_TYPE = 2;
- private static final int INDEX_LATITUDE = 3;
- private static final int INDEX_LONGITUDE = 4;
- private static final int INDEX_DATE_TAKEN = 5;
- private static final int INDEX_DATE_ADDED = 6;
- private static final int INDEX_DATE_MODIFIED = 7;
- private static final int INDEX_DATA = 8;
- private static final int INDEX_ORIENTATION = 9;
- private static final int INDEX_BUCKET_ID = 10;
- private static final int INDEX_SIZE = 11;
- private static final int INDEX_WIDTH = 12;
- private static final int INDEX_HEIGHT = 13;
- static final String[] PROJECTION = {
- ImageColumns._ID, // 0
- ImageColumns.TITLE, // 1
- ImageColumns.MIME_TYPE, // 2
- ImageColumns.LATITUDE, // 3
- ImageColumns.LONGITUDE, // 4
- ImageColumns.DATE_TAKEN, // 5
- ImageColumns.DATE_ADDED, // 6
- ImageColumns.DATE_MODIFIED, // 7
- ImageColumns.DATA, // 8
- ImageColumns.ORIENTATION, // 9
- ImageColumns.BUCKET_ID, // 10
- ImageColumns.SIZE, // 11
- "0", // 12
- "0" // 13
- };
+public class TimeLineTitleMediaItem extends MediaItem {
+ private static final String TAG = "TimeLineTitleMediaItem";
+ private String mTitle;
+ private int mPhotoCount;
+ private int mVideoCount;
- static {
- updateWidthAndHeightProjection();
+ public TimeLineTitleMediaItem(Path path) {
+ super(path);
}
- @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
- private static void updateWidthAndHeightProjection() {
- if (ApiHelper.HAS_MEDIA_COLUMNS_WIDTH_AND_HEIGHT) {
- PROJECTION[INDEX_WIDTH] = MediaColumns.WIDTH;
- PROJECTION[INDEX_HEIGHT] = MediaColumns.HEIGHT;
- }
- }
-
- private final GalleryApp mApplication;
-
- public int rotation;
- private PanoramaMetadataSupport mPanoramaMetadata = new PanoramaMetadataSupport(this);
-
- public LocalImage(Path path, GalleryApp application, Cursor cursor) {
- super(path, nextVersionNumber());
- mApplication = application;
- loadFromCursor(cursor);
- }
-
- public LocalImage(Path path, GalleryApp application, int id) {
- super(path, nextVersionNumber());
- mApplication = application;
- ContentResolver resolver = mApplication.getContentResolver();
- Uri uri = Images.Media.EXTERNAL_CONTENT_URI;
- Cursor cursor = LocalAlbum.getItemCursor(resolver, uri, PROJECTION, id);
- if (cursor == null) {
- throw new RuntimeException("cannot get cursor for: " + path);
- }
- try {
- if (cursor.moveToNext()) {
- loadFromCursor(cursor);
- } else {
- throw new RuntimeException("cannot find data for: " + path);
- }
- } finally {
- cursor.close();
+ public Job<Bitmap> requestTitle(int type, TimeLineTitleMaker maker) {
+ if (maker != null) {
+ return maker.requestTimeLineTitle(mTitle, mPhotoCount, mVideoCount);
}
+ return null;
}
- private void loadFromCursor(Cursor cursor) {
- id = cursor.getInt(INDEX_ID);
- caption = cursor.getString(INDEX_CAPTION);
- mimeType = cursor.getString(INDEX_MIME_TYPE);
- latitude = cursor.getDouble(INDEX_LATITUDE);
- longitude = cursor.getDouble(INDEX_LONGITUDE);
- dateTakenInMs = cursor.getLong(INDEX_DATE_TAKEN);
- dateAddedInSec = cursor.getLong(INDEX_DATE_ADDED);
- dateModifiedInSec = cursor.getLong(INDEX_DATE_MODIFIED);
- filePath = cursor.getString(INDEX_DATA);
- rotation = cursor.getInt(INDEX_ORIENTATION);
- bucketId = cursor.getInt(INDEX_BUCKET_ID);
- fileSize = cursor.getLong(INDEX_SIZE);
- width = cursor.getInt(INDEX_WIDTH);
- height = cursor.getInt(INDEX_HEIGHT);
+ public void setTitle(String title) {
+ mTitle = title;
}
-
- @Override
- protected boolean updateFromCursor(Cursor cursor) {
- UpdateHelper uh = new UpdateHelper();
- id = uh.update(id, cursor.getInt(INDEX_ID));
- caption = uh.update(caption, cursor.getString(INDEX_CAPTION));
- mimeType = uh.update(mimeType, cursor.getString(INDEX_MIME_TYPE));
- latitude = uh.update(latitude, cursor.getDouble(INDEX_LATITUDE));
- longitude = uh.update(longitude, cursor.getDouble(INDEX_LONGITUDE));
- dateTakenInMs = uh.update(
- dateTakenInMs, cursor.getLong(INDEX_DATE_TAKEN));
- dateAddedInSec = uh.update(
- dateAddedInSec, cursor.getLong(INDEX_DATE_ADDED));
- dateModifiedInSec = uh.update(
- dateModifiedInSec, cursor.getLong(INDEX_DATE_MODIFIED));
- filePath = uh.update(filePath, cursor.getString(INDEX_DATA));
- 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));
- width = uh.update(width, cursor.getInt(INDEX_WIDTH));
- height = uh.update(height, cursor.getInt(INDEX_HEIGHT));
- return uh.isUpdated();
- }
-
- @Override
public Job<Bitmap> requestImage(int type) {
- return new LocalImageRequest(mApplication, mPath, dateModifiedInSec,
- type, filePath, mimeType);
+ return null;
}
- public static class LocalImageRequest extends ImageCacheRequest {
- private String mLocalFilePath;
-
- LocalImageRequest(GalleryApp application, Path path, long timeModified,
- int type, String localFilePath) {
- super(application, path, timeModified, type,
- MediaItem.getTargetSize(type));
- mLocalFilePath = localFilePath;
- }
-
- LocalImageRequest(GalleryApp application, Path path, long timeModified,
- int type, String localFilePath, String mimeType) {
- super(application, path, timeModified, type,
- MediaItem.getTargetSize(type),localFilePath, mimeType);
- mLocalFilePath = localFilePath;
- }
-
- @Override
- public Bitmap onDecodeOriginal(JobContext jc, final int type) {
- BitmapFactory.Options options = new BitmapFactory.Options();
- options.inPreferredConfig = Bitmap.Config.ARGB_8888;
-
- if (DrmHelper.isDrmFile(mLocalFilePath)) {
- return DecodeUtils.ensureGLCompatibleBitmap(DrmHelper
- .getBitmap(mLocalFilePath, options));
- }
-
- int targetSize = MediaItem.getTargetSize(type);
-
- // try to decode from JPEG EXIF
- if (type == MediaItem.TYPE_MICROTHUMBNAIL) {
- ExifInterface exif = new ExifInterface();
- byte[] thumbData = null;
- try {
- exif.readExif(mLocalFilePath);
- thumbData = exif.getThumbnail();
- } catch (FileNotFoundException e) {
- Log.w(TAG, "failed to find file to read thumbnail: " + mLocalFilePath);
- } catch (IOException e) {
- Log.w(TAG, "failed to get thumbnail from: " + mLocalFilePath);
- }
- if (thumbData != null) {
- Bitmap bitmap = DecodeUtils.decodeIfBigEnough(
- jc, thumbData, options, targetSize);
- if (bitmap != null) return bitmap;
- }
- }
-
- return DecodeUtils.decodeThumbnail(jc, mLocalFilePath, options, targetSize, type);
- }
- }
-
- @Override
public Job<BitmapRegionDecoder> requestLargeImage() {
- return new LocalLargeImageRequest(filePath);
+ Log.e(TAG, "Operation not supported");
+ return null;
}
- public static class LocalLargeImageRequest
- implements Job<BitmapRegionDecoder> {
- String mLocalFilePath;
-
- public LocalLargeImageRequest(String localFilePath) {
- mLocalFilePath = localFilePath;
- }
-
- @Override
- public BitmapRegionDecoder run(JobContext jc) {
- if (DrmHelper.isDrmFile(mLocalFilePath)) {
- return DrmHelper.createBitmapRegionDecoder(mLocalFilePath,
- false);
- }
-
- return DecodeUtils.createBitmapRegionDecoder(jc, mLocalFilePath, false);
- }
- }
-
- @Override
- public int getSupportedOperations() {
- int operation = SUPPORT_DELETE | SUPPORT_INFO;
- if (DrmHelper.isDrmFile(getFilePath())) {
- if (DrmHelper.isDrmFLBlocking(mApplication.getAndroidContext(),
- getFilePath())) {
- operation |= SUPPORT_SETAS;
- }
- operation |= SUPPORT_DRM_INFO | SUPPORT_FULL_IMAGE;
- if (DrmHelper.isShareableDrmFile(getFilePath())) {
- operation |= SUPPORT_SHARE;
- }
- } else {
- operation = SUPPORT_DELETE | SUPPORT_SHARE | SUPPORT_CROP
- | SUPPORT_SETAS | SUPPORT_PRINT | SUPPORT_INFO;
- if (BitmapUtils.isSupportedByRegionDecoder(mimeType)) {
- operation |= SUPPORT_FULL_IMAGE | SUPPORT_EDIT;
- }
-
- if (BitmapUtils.isRotationSupported(mimeType)) {
- operation |= SUPPORT_ROTATE;
- }
-
- if (GalleryUtils.isValidLocation(latitude, longitude)) {
- operation |= SUPPORT_SHOW_ON_MAP;
- }
- }
- return operation;
- }
-
- @Override
- public void getPanoramaSupport(PanoramaSupportCallback callback) {
- mPanoramaMetadata.getPanoramaSupport(mApplication, callback);
- }
-
- @Override
- public void clearCachedPanoramaSupport() {
- mPanoramaMetadata.clearCachedValues();
- }
-
- @Override
- public void delete() {
- GalleryUtils.assertNotInRenderThread();
- Uri baseUri = Images.Media.EXTERNAL_CONTENT_URI;
- ContentResolver contentResolver = mApplication.getContentResolver();
- SaveImage.deleteAuxFiles(contentResolver, getContentUri());
- contentResolver.delete(baseUri, "_id=?",
- new String[]{String.valueOf(id)});
- }
-
- @Override
- public void rotate(int degrees) {
- GalleryUtils.assertNotInRenderThread();
- Uri baseUri = Images.Media.EXTERNAL_CONTENT_URI;
- ContentValues values = new ContentValues();
- int rotation = (this.rotation + degrees) % 360;
- if (rotation < 0) rotation += 360;
-
- if (mimeType.equalsIgnoreCase("image/jpeg")) {
- ExifInterface exifInterface = new ExifInterface();
- ExifTag tag = exifInterface.buildTag(ExifInterface.TAG_ORIENTATION,
- ExifInterface.getOrientationValueForRotation(rotation));
- if(tag != null) {
- exifInterface.setTag(tag);
- try {
- exifInterface.forceRewriteExif(filePath);
- fileSize = new File(filePath).length();
- values.put(Images.Media.SIZE, fileSize);
- } catch (FileNotFoundException e) {
- Log.w(TAG, "cannot find file to set exif: " + filePath);
- } catch (IOException e) {
- Log.w(TAG, "cannot set exif data: " + filePath);
- }
- } else {
- Log.w(TAG, "Could not build tag: " + ExifInterface.TAG_ORIENTATION);
- }
- }
-
- values.put(Images.Media.ORIENTATION, rotation);
- mApplication.getContentResolver().update(baseUri, values, "_id=?",
- new String[]{String.valueOf(id)});
- }
-
- @Override
- public Uri getContentUri() {
- Uri baseUri = Images.Media.EXTERNAL_CONTENT_URI;
- return baseUri.buildUpon().appendPath(String.valueOf(id)).build();
+ public String getMimeType() {
+ return MediaObject.MEDIA_TYPE_IMAGE_STRING;
}
@Override
public int getMediaType() {
- if (DrmHelper.isDrmFile(getFilePath())) {
- return MEDIA_TYPE_DRM_IMAGE;
- }
-
- return MEDIA_TYPE_IMAGE;
+ return MediaObject.MEDIA_TYPE_TIMELINE_TITLE;
}
- @Override
- public MediaDetails getDetails() {
- MediaDetails details = super.getDetails();
- details.addDetail(MediaDetails.INDEX_ORIENTATION, Integer.valueOf(rotation));
- if (MIME_TYPE_JPEG.equals(mimeType)) {
- // ExifInterface returns incorrect values for photos in other format.
- // For example, the width and height of an webp images is always '0'.
- MediaDetails.extractExifInfo(details, filePath);
- }
- return details;
+ public void setImageCount(int images) {
+ mPhotoCount = images;
}
- @Override
- public int getRotation() {
- return rotation;
+ public void setVideoCount(int video) {
+ mVideoCount = video;
}
- @Override
public int getWidth() {
- return width;
+ return 0;
}
- @Override
public int getHeight() {
- return height;
+ return 0;
}
- @Override
- public String getFilePath() {
- return filePath;
- }
}
diff --git a/src/com/android/gallery3d/ui/TimeLineSlidingWindow.java b/src/com/android/gallery3d/ui/TimeLineSlidingWindow.java
index fec7d1e92..0c44d46f3 100644
--- a/src/com/android/gallery3d/ui/TimeLineSlidingWindow.java
+++ b/src/com/android/gallery3d/ui/TimeLineSlidingWindow.java
@@ -20,21 +20,23 @@ import android.graphics.Bitmap;
import android.os.Message;
import com.android.gallery3d.app.AbstractGalleryActivity;
-import com.android.gallery3d.app.AlbumDataLoader;
+import com.android.gallery3d.app.TimeLineDataLoader;
import com.android.gallery3d.common.Utils;
import com.android.gallery3d.data.MediaItem;
import com.android.gallery3d.data.MediaObject;
-import com.android.gallery3d.data.MediaObject.PanoramaSupportCallback;
import com.android.gallery3d.data.Path;
+import com.android.gallery3d.data.TimeLineTitleMediaItem;
import com.android.gallery3d.glrenderer.Texture;
import com.android.gallery3d.glrenderer.TiledTexture;
import com.android.gallery3d.util.Future;
import com.android.gallery3d.util.FutureListener;
import com.android.gallery3d.util.JobLimiter;
-public class AlbumSlidingWindow implements AlbumDataLoader.DataListener {
+import java.util.ArrayList;
+
+public class TimeLineSlidingWindow implements TimeLineDataLoader.DataListener {
@SuppressWarnings("unused")
- private static final String TAG = "AlbumSlidingWindow";
+ private static final String TAG = "TimeLineSlidingWindow";
private static final int MSG_UPDATE_ENTRY = 0;
private static final int JOB_LIMIT = 2;
@@ -42,6 +44,8 @@ public class AlbumSlidingWindow implements AlbumDataLoader.DataListener {
public static interface Listener {
public void onSizeChanged(int size);
public void onContentChanged();
+ public void onVersionChanged();
+ public int getTitleWidth();
}
public static class AlbumEntry {
@@ -54,47 +58,39 @@ public class AlbumSlidingWindow implements AlbumDataLoader.DataListener {
public TiledTexture bitmapTexture;
public Texture content;
private BitmapLoader contentLoader;
- private PanoSupportListener mPanoSupportListener;
+
}
- private final AlbumDataLoader mSource;
+ private final TimeLineDataLoader mSource;
private final AlbumEntry mData[];
private final SynchronizedHandler mHandler;
private final JobLimiter mThreadPool;
private final TiledTexture.Uploader mTileUploader;
private int mSize;
-
+ private int mSlotWidth;
private int mContentStart = 0;
private int mContentEnd = 0;
-
private int mActiveStart = 0;
private int mActiveEnd = 0;
-
private Listener mListener;
-
private int mActiveRequestCount = 0;
private boolean mIsActive = false;
- private class PanoSupportListener implements PanoramaSupportCallback {
- public final AlbumEntry mEntry;
- public PanoSupportListener (AlbumEntry entry) {
- mEntry = entry;
- }
- @Override
- public void panoramaInfoAvailable(MediaObject mediaObject, boolean isPanorama,
- boolean isPanorama360) {
- if (mEntry != null) mEntry.isPanorama = isPanorama;
- }
- }
+ private TimeLineTitleMaker mTitleMaker;
+ private int mTitleSize;
+ private int mTitleContentStart = 0;
+ private int mTitleContentEnd = 0;
+ private final int TITLE_CACHE_SIZE = 15;
- public AlbumSlidingWindow(AbstractGalleryActivity activity,
- AlbumDataLoader source, int cacheSize) {
+ public TimeLineSlidingWindow(AbstractGalleryActivity activity,
+ TimeLineDataLoader source,
+ int cacheSize, TimeLineSlotRenderer.LabelSpec labelSpec,
+ SelectionManager selection, TimeLineSlotView slotView) {
source.setDataListener(this);
mSource = source;
mData = new AlbumEntry[cacheSize];
mSize = source.size();
-
mHandler = new SynchronizedHandler(activity.getGLRoot()) {
@Override
public void handleMessage(Message message) {
@@ -105,6 +101,7 @@ public class AlbumSlidingWindow implements AlbumDataLoader.DataListener {
mThreadPool = new JobLimiter(activity.getThreadPool(), JOB_LIMIT);
mTileUploader = new TiledTexture.Uploader(activity.getGLRoot());
+ mTitleMaker = new TimeLineTitleMaker(activity.getAndroidContext(), labelSpec, slotView);
}
public void setListener(Listener listener) {
@@ -113,10 +110,10 @@ public class AlbumSlidingWindow implements AlbumDataLoader.DataListener {
public AlbumEntry get(int slotIndex) {
if (!isActiveSlot(slotIndex)) {
- Utils.fail("invalid slot: %s outsides (%s, %s)",
- slotIndex, mActiveStart, mActiveEnd);
+ return null;
}
- return mData[slotIndex % mData.length];
+ AlbumEntry item = mData[slotIndex % mData.length];
+ return item;
}
public boolean isActiveSlot(int slotIndex) {
@@ -162,7 +159,7 @@ public class AlbumSlidingWindow implements AlbumDataLoader.DataListener {
}
public void setActiveWindow(int start, int end) {
- if (!(start <= end && end - start <= mData.length && end <= mSize)) {
+ if (!(start <= end && end - start <= mData.length)) {
Utils.fail("%s, %s, %s, %s", start, end, mData.length, mSize);
}
AlbumEntry data[] = mData;
@@ -181,12 +178,17 @@ public class AlbumSlidingWindow implements AlbumDataLoader.DataListener {
private void uploadBgTextureInSlot(int index) {
if (index < mContentEnd && index >= mContentStart) {
AlbumEntry entry = mData[index % mData.length];
+ if (entry == null) return;
if (entry.bitmapTexture != null) {
mTileUploader.addTexture(entry.bitmapTexture);
}
}
}
+ public ArrayList<MediaItem> getAllMediaItems() {
+ return mSource.getAllMediaItems();
+ }
+
private void updateTextureUploadQueue() {
if (!mIsActive) return;
mTileUploader.clear();
@@ -194,6 +196,9 @@ public class AlbumSlidingWindow implements AlbumDataLoader.DataListener {
// add foreground textures
for (int i = mActiveStart, n = mActiveEnd; i < n; ++i) {
AlbumEntry entry = mData[i % mData.length];
+ if (entry == null) {
+ continue;
+ }
if (entry.bitmapTexture != null) {
mTileUploader.addTexture(entry.bitmapTexture);
}
@@ -216,7 +221,7 @@ public class AlbumSlidingWindow implements AlbumDataLoader.DataListener {
private void requestNonactiveImages() {
int range = Math.max(
(mContentEnd - mActiveEnd), (mActiveStart - mContentStart));
- for (int i = 0 ;i < range; ++i) {
+ for (int i = 0; i < range; ++i) {
requestSlotImage(mActiveEnd + i);
requestSlotImage(mActiveStart - 1 - i);
}
@@ -226,11 +231,7 @@ public class AlbumSlidingWindow implements AlbumDataLoader.DataListener {
private boolean requestSlotImage(int slotIndex) {
if (slotIndex < mContentStart || slotIndex >= mContentEnd) return false;
AlbumEntry entry = mData[slotIndex % mData.length];
- if (entry.content != null || entry.item == null) return false;
-
- // Set up the panorama callback
- entry.mPanoSupportListener = new PanoSupportListener(entry);
- entry.item.getPanoramaSupport(entry.mPanoSupportListener);
+ if (entry == null || entry.item == null) return false;
entry.contentLoader.startLoad();
return entry.contentLoader.isRequestInProgress();
@@ -239,7 +240,7 @@ public class AlbumSlidingWindow implements AlbumDataLoader.DataListener {
private void cancelNonactiveImages() {
int range = Math.max(
(mContentEnd - mActiveEnd), (mActiveStart - mContentStart));
- for (int i = 0 ;i < range; ++i) {
+ for (int i = 0; i < range; ++i) {
cancelSlotImage(mActiveEnd + i);
cancelSlotImage(mActiveStart - 1 - i);
}
@@ -248,6 +249,7 @@ public class AlbumSlidingWindow implements AlbumDataLoader.DataListener {
private void cancelSlotImage(int slotIndex) {
if (slotIndex < mContentStart || slotIndex >= mContentEnd) return;
AlbumEntry item = mData[slotIndex % mData.length];
+ if (item == null) return;
if (item.contentLoader != null) item.contentLoader.cancelLoad();
}
@@ -255,11 +257,14 @@ public class AlbumSlidingWindow implements AlbumDataLoader.DataListener {
AlbumEntry data[] = mData;
int index = slotIndex % data.length;
AlbumEntry entry = data[index];
- if (entry.contentLoader != null) entry.contentLoader.recycle();
- if (entry.bitmapTexture != null) entry.bitmapTexture.recycle();
+ if (entry != null) {
+ if (entry.contentLoader != null) entry.contentLoader.recycle();
+ if (entry.bitmapTexture != null) entry.bitmapTexture.recycle();
+ }
data[index] = null;
}
+
private void prepareSlotContent(int slotIndex) {
AlbumEntry entry = new AlbumEntry();
MediaItem item = mSource.get(slotIndex); // item could be null;
@@ -285,7 +290,7 @@ public class AlbumSlidingWindow implements AlbumDataLoader.DataListener {
}
}
- private class ThumbnailLoader extends BitmapLoader {
+ private class ThumbnailLoader extends BitmapLoader {
private final int mSlotIndex;
private final MediaItem mItem;
@@ -296,8 +301,15 @@ public class AlbumSlidingWindow implements AlbumDataLoader.DataListener {
@Override
protected Future<Bitmap> submitBitmapTask(FutureListener<Bitmap> l) {
- return mThreadPool.submit(
- mItem.requestImage(MediaItem.TYPE_MICROTHUMBNAIL), this);
+ if (mItem.getMediaType() != MediaObject.MEDIA_TYPE_TIMELINE_TITLE) {
+ return mThreadPool.submit(
+ mItem.requestImage(MediaItem.TYPE_MICROTHUMBNAIL), this);
+ } else if( mItem.getMediaType() == MediaObject.MEDIA_TYPE_TIMELINE_TITLE ){
+ return mThreadPool.submit(
+ ((TimeLineTitleMediaItem) mItem).requestTitle(
+ MediaItem.TYPE_MICROTHUMBNAIL, mTitleMaker), this);
+ }
+ return null;
}
@Override
@@ -308,18 +320,21 @@ public class AlbumSlidingWindow implements AlbumDataLoader.DataListener {
public void updateEntry() {
Bitmap bitmap = getBitmap();
if (bitmap == null) return; // error or recycled
- AlbumEntry entry = mData[mSlotIndex % mData.length];
- entry.bitmapTexture = new TiledTexture(bitmap);
- entry.content = entry.bitmapTexture;
- if (isActiveSlot(mSlotIndex)) {
- mTileUploader.addTexture(entry.bitmapTexture);
- --mActiveRequestCount;
- if (mActiveRequestCount == 0) requestNonactiveImages();
- if (mListener != null) mListener.onContentChanged();
- } else {
- mTileUploader.addTexture(entry.bitmapTexture);
- }
+ AlbumEntry entry = mData[mSlotIndex % mData.length];
+ if (entry == null) return;
+ entry.bitmapTexture = new TiledTexture(bitmap);
+ entry.content = entry.bitmapTexture;
+
+ if (isActiveSlot(mSlotIndex)) {
+ mTileUploader.addTexture(entry.bitmapTexture);
+ --mActiveRequestCount;
+ if (mActiveRequestCount == 0) requestNonactiveImages();
+ if (mListener != null) mListener.onContentChanged();
+ } else {
+ mTileUploader.addTexture(entry.bitmapTexture);
+ }
+
}
}
@@ -339,12 +354,18 @@ public class AlbumSlidingWindow implements AlbumDataLoader.DataListener {
freeSlotContent(index);
prepareSlotContent(index);
updateAllImageRequests();
+ updateTextureUploadQueue();
if (mListener != null && isActiveSlot(index)) {
mListener.onContentChanged();
}
}
}
+ @Override
+ public void onVersionChanged() {
+ mListener.onVersionChanged();
+ }
+
public void resume() {
mIsActive = true;
TiledTexture.prepareResources();
@@ -362,4 +383,24 @@ public class AlbumSlidingWindow implements AlbumDataLoader.DataListener {
freeSlotContent(i);
}
}
+
+ public void onSlotSizeChanged(int width, int height) {
+ if (mSlotWidth == width) return;
+
+ mSlotWidth = width;
+
+ if (!mIsActive) return;
+ for (int slotIndex = mContentStart, n = mContentEnd; slotIndex < n; ++slotIndex) {
+ AlbumEntry entry = mData[slotIndex % mData.length];
+ if (entry == null) {
+ continue;
+ }
+ if (entry.mediaType == MediaItem.MEDIA_TYPE_TIMELINE_TITLE) {
+ freeSlotContent(slotIndex);
+ prepareSlotContent(slotIndex);
+ }
+ }
+ updateAllImageRequests();
+ updateTextureUploadQueue();
+ }
}
diff --git a/src/com/android/gallery3d/ui/TimeLineSlotRenderer.java b/src/com/android/gallery3d/ui/TimeLineSlotRenderer.java
index 5c1441ee9..5483647e7 100644
--- a/src/com/android/gallery3d/ui/TimeLineSlotRenderer.java
+++ b/src/com/android/gallery3d/ui/TimeLineSlotRenderer.java
@@ -16,8 +16,10 @@
package com.android.gallery3d.ui;
+
import com.android.gallery3d.app.AbstractGalleryActivity;
-import com.android.gallery3d.app.AlbumDataLoader;
+import com.android.gallery3d.app.TimeLineDataLoader;
+import com.android.gallery3d.data.MediaItem;
import com.android.gallery3d.data.MediaObject;
import com.android.gallery3d.data.Path;
import com.android.gallery3d.glrenderer.ColorTexture;
@@ -26,21 +28,20 @@ import com.android.gallery3d.glrenderer.GLCanvas;
import com.android.gallery3d.glrenderer.Texture;
import com.android.gallery3d.glrenderer.TiledTexture;
-public class AlbumSlotRenderer extends AbstractSlotRenderer {
+import java.util.ArrayList;
+
+public class TimeLineSlotRenderer extends AbstractSlotRenderer {
+
@SuppressWarnings("unused")
private static final String TAG = "AlbumView";
- public interface SlotFilter {
- public boolean acceptSlot(int index);
- }
-
private final int mPlaceholderColor;
private static final int CACHE_SIZE = 96;
- private AlbumSlidingWindow mDataWindow;
+ private TimeLineSlidingWindow mDataWindow;
private final AbstractGalleryActivity mActivity;
private final ColorTexture mWaitLoadingTexture;
- private final SlotView mSlotView;
+ private final TimeLineSlotView mSlotView;
private final SelectionManager mSelectionManager;
private int mPressedIndex = -1;
@@ -48,18 +49,29 @@ public class AlbumSlotRenderer extends AbstractSlotRenderer {
private Path mHighlightItemPath = null;
private boolean mInSelectionMode;
- private SlotFilter mSlotFilter;
+ private AlbumSlotRenderer.SlotFilter mSlotFilter;
+ private final LabelSpec mLabelSpec;
- public AlbumSlotRenderer(AbstractGalleryActivity activity, SlotView slotView,
- SelectionManager selectionManager, int placeholderColor) {
+ public static class LabelSpec {
+
+ public int timeLineTitleHeight;
+ public int timeLineTitleFontSize;
+ public int timeLineTitleTextColor;
+ public int timeLineNumberTextColor;
+ public int timeLineTitleBackgroundColor;
+}
+ public TimeLineSlotRenderer(AbstractGalleryActivity activity, TimeLineSlotView slotView,
+ SelectionManager selectionManager, LabelSpec labelSpec,
+ int placeholderColor) {
super(activity);
mActivity = activity;
mSlotView = slotView;
+ mLabelSpec = labelSpec;
mSelectionManager = selectionManager;
mPlaceholderColor = placeholderColor;
-
mWaitLoadingTexture = new ColorTexture(mPlaceholderColor);
mWaitLoadingTexture.setSize(1, 1);
+
}
public void setPressedIndex(int index) {
@@ -80,67 +92,19 @@ public class AlbumSlotRenderer extends AbstractSlotRenderer {
mSlotView.invalidate();
}
- public void setModel(AlbumDataLoader model) {
- if (mDataWindow != null) {
- mDataWindow.setListener(null);
- mSlotView.setSlotCount(0);
- mDataWindow = null;
- }
- if (model != null) {
- mDataWindow = new AlbumSlidingWindow(mActivity, model, CACHE_SIZE);
- mDataWindow.setListener(new MyDataModelListener());
- mSlotView.setSlotCount(model.size());
- }
- }
-
- private static Texture checkTexture(Texture texture) {
+ protected static Texture checkContentTexture(Texture texture) {
return (texture instanceof TiledTexture)
&& !((TiledTexture) texture).isReady()
? null
: texture;
}
- @Override
- public int renderSlot(GLCanvas canvas, int index, int pass, int width, int height) {
- if (mSlotFilter != null && !mSlotFilter.acceptSlot(index)) return 0;
-
- AlbumSlidingWindow.AlbumEntry entry = mDataWindow.get(index);
-
- int renderRequestFlags = 0;
-
- Texture content = checkTexture(entry.content);
- if (content == null) {
- content = mWaitLoadingTexture;
- entry.isWaitDisplayed = true;
- } else if (entry.isWaitDisplayed) {
- entry.isWaitDisplayed = false;
- content = new FadeInTexture(mPlaceholderColor, entry.bitmapTexture);
- entry.content = content;
- }
- drawContent(canvas, content, width, height, entry.rotation);
- if ((content instanceof FadeInTexture) &&
- ((FadeInTexture) content).isAnimating()) {
- renderRequestFlags |= SlotView.RENDER_MORE_FRAME;
- }
-
- if (entry.mediaType == MediaObject.MEDIA_TYPE_VIDEO) {
- drawVideoOverlay(canvas, width, height);
- } else if ((entry.mediaType == MediaObject.MEDIA_TYPE_DRM_VIDEO)
- || (entry.mediaType == MediaObject.MEDIA_TYPE_DRM_IMAGE)) {
- drawDrmOverlay(canvas, width, height, entry.mediaType);
- }
-
- if (entry.isPanorama) {
- drawPanoramaIcon(canvas, width, height);
- }
-
- renderRequestFlags |= renderOverlay(canvas, index, entry, width, height);
-
- return renderRequestFlags;
+ public ArrayList<MediaItem> getAllMediaItems() {
+ return mDataWindow.getAllMediaItems();
}
- private int renderOverlay(GLCanvas canvas, int index,
- AlbumSlidingWindow.AlbumEntry entry, int width, int height) {
+ protected int renderOverlay(GLCanvas canvas, int index,
+ TimeLineSlidingWindow.AlbumEntry entry, int width, int height) {
int renderRequestFlags = 0;
if (mPressedIndex == index) {
if (mAnimatePressedUp) {
@@ -155,13 +119,14 @@ public class AlbumSlotRenderer extends AbstractSlotRenderer {
}
} else if ((entry.path != null) && (mHighlightItemPath == entry.path)) {
drawSelectedFrame(canvas, width, height);
- } else if (mInSelectionMode && mSelectionManager.isItemSelected(entry.path)) {
+ } else if (mInSelectionMode && entry.mediaType != MediaItem.MEDIA_TYPE_TIMELINE_TITLE
+ && mSelectionManager.isItemSelected(entry.path)) {
drawSelectedFrame(canvas, width, height);
}
return renderRequestFlags;
}
- private class MyDataModelListener implements AlbumSlidingWindow.Listener {
+ protected class MyDataModelListener implements TimeLineSlidingWindow.Listener {
@Override
public void onContentChanged() {
mSlotView.invalidate();
@@ -172,6 +137,17 @@ public class AlbumSlotRenderer extends AbstractSlotRenderer {
mSlotView.setSlotCount(size);
mSlotView.invalidate();
}
+
+ @Override
+ public void onVersionChanged() {
+ mSlotView.onVersionChanged();
+ }
+
+ @Override
+ public int getTitleWidth() {
+ return mSlotView.getTitleWidth();
+ }
+
}
public void resume() {
@@ -196,10 +172,56 @@ public class AlbumSlotRenderer extends AbstractSlotRenderer {
@Override
public void onSlotSizeChanged(int width, int height) {
- // Do nothing
+ if (mDataWindow != null) {
+ mDataWindow.onSlotSizeChanged(width, height);
+ }
}
- public void setSlotFilter(SlotFilter slotFilter) {
+ public void setSlotFilter(AlbumSlotRenderer.SlotFilter slotFilter) {
mSlotFilter = slotFilter;
}
+
+ public void setModel(TimeLineDataLoader model) {
+ if (mDataWindow != null) {
+ mDataWindow.setListener(null);
+ mSlotView.setSlotCount(0);
+ mDataWindow = null;
+ }
+ if (model != null) {
+ mDataWindow = new TimeLineSlidingWindow(mActivity, model, CACHE_SIZE, mLabelSpec,
+ mSelectionManager, mSlotView);
+ mDataWindow.setListener(new MyDataModelListener());
+ mSlotView.setSlotCount(model.size());
+ }
+ }
+
+ @Override
+ public int renderSlot(GLCanvas canvas, int index, int pass, int width, int height) {
+ if (mSlotFilter != null && !mSlotFilter.acceptSlot(index)) return 0;
+
+ TimeLineSlidingWindow.AlbumEntry entry = mDataWindow.get(index);
+ int renderRequestFlags = 0;
+ Texture content = checkContentTexture(entry.content);
+ if (content == null) {
+ content = mWaitLoadingTexture;
+ entry.isWaitDisplayed = true;
+ } else if (entry.isWaitDisplayed) {
+ entry.isWaitDisplayed = false;
+ content = new FadeInTexture(mPlaceholderColor, entry.bitmapTexture);
+ entry.content = content;
+ }
+ drawContent(canvas, content, width, height, entry.rotation);
+ if ((content instanceof FadeInTexture) &&
+ ((FadeInTexture) content).isAnimating()) {
+ renderRequestFlags |= SlotView.RENDER_MORE_FRAME;
+ }
+
+ if (entry.mediaType == MediaObject.MEDIA_TYPE_VIDEO) {
+ drawVideoOverlay(canvas, width, height, true, 0);
+ }
+
+ renderRequestFlags |= renderOverlay(canvas, index, entry, width, height);
+
+ return renderRequestFlags;
+ }
}
diff --git a/src/com/android/gallery3d/ui/TimeLineSlotView.java b/src/com/android/gallery3d/ui/TimeLineSlotView.java
index eaf23f553..fc764570a 100644
--- a/src/com/android/gallery3d/ui/TimeLineSlotView.java
+++ b/src/com/android/gallery3d/ui/TimeLineSlotView.java
@@ -1,4 +1,7 @@
/*
+ * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ *
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -13,12 +16,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
package com.android.gallery3d.ui;
import android.graphics.Rect;
-import android.os.Handler;
import android.text.TextUtils;
+import android.util.Log;
+import android.os.SystemProperties;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
@@ -27,51 +30,47 @@ import android.view.animation.DecelerateInterpolator;
import com.android.gallery3d.anim.Animation;
import com.android.gallery3d.app.AbstractGalleryActivity;
import com.android.gallery3d.common.Utils;
+import com.android.gallery3d.data.MediaItem;
+import com.android.gallery3d.data.MediaObject;
import com.android.gallery3d.glrenderer.GLCanvas;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
import java.util.Locale;
-public class SlotView extends GLView {
+public class TimeLineSlotView extends GLView {
@SuppressWarnings("unused")
- private static final String TAG = "SlotView";
+ private static final String TAG = "TimeLineSlotView";
- private static final boolean WIDE = true;
- private static final int INDEX_NONE = -1;
+ public static final int INDEX_NONE = -1;
+ private static final int mainKey = SystemProperties.getInt("qemu.hw.mainkeys", 1);
public static final int RENDER_MORE_PASS = 1;
public static final int RENDER_MORE_FRAME = 2;
+ private int mWidth = 0;
+
public interface Listener {
public void onDown(int index);
public void onUp(boolean followedByLongPress);
- public void onSingleTapUp(int index);
- public void onLongTap(int index);
+ public void onSingleTapUp(int index, boolean isTitle);
+ public void onLongTap(int index, boolean isTitle);
public void onScrollPositionChanged(int position, int total);
}
public static class SimpleListener implements Listener {
@Override public void onDown(int index) {}
@Override public void onUp(boolean followedByLongPress) {}
- @Override public void onSingleTapUp(int index) {}
- @Override public void onLongTap(int index) {}
+ @Override public void onSingleTapUp(int index, boolean isTitle) {}
+ @Override public void onLongTap(int index, boolean isTitle) {}
@Override public void onScrollPositionChanged(int position, int total) {}
}
- public static interface SlotRenderer {
- public void prepareDrawing();
- public void onVisibleRangeChanged(int visibleStart, int visibleEnd);
- public void onSlotSizeChanged(int width, int height);
- public int renderSlot(GLCanvas canvas, int index, int pass, int width, int height);
- }
-
private final GestureDetector mGestureDetector;
private final ScrollerHelper mScroller;
- private final Paper mPaper = new Paper();
private Listener mListener;
- private UserInteractionListener mUIListener;
-
- private boolean mMoreAnimation = false;
private SlotAnimation mAnimation = null;
private final Layout mLayout = new Layout();
private int mStartIndex = INDEX_NONE;
@@ -79,15 +78,12 @@ public class SlotView extends GLView {
// whether the down action happened while the view is scrolling.
private boolean mDownInScrolling;
private int mOverscrollEffect = OVERSCROLL_3D;
- private final Handler mHandler;
- private SlotRenderer mRenderer;
+ private TimeLineSlotRenderer mRenderer;
private int[] mRequestRenderSlots = new int[16];
public static final int OVERSCROLL_3D = 0;
- public static final int OVERSCROLL_SYSTEM = 1;
- public static final int OVERSCROLL_NONE = 2;
// to prevent allocating memory
private final Rect mTempRect = new Rect();
@@ -95,17 +91,15 @@ public class SlotView extends GLView {
// Flag to check whether it is come from Photo Page.
private boolean isFromPhotoPage = false;
- public SlotView(AbstractGalleryActivity activity, Spec spec) {
+ public TimeLineSlotView(AbstractGalleryActivity activity, Spec spec) {
mGestureDetector = new GestureDetector(activity, new MyGestureListener());
mScroller = new ScrollerHelper(activity);
- mHandler = new SynchronizedHandler(activity.getGLRoot());
setSlotSpec(spec);
}
- public void setSlotRenderer(SlotRenderer slotDrawer) {
+ public void setSlotRenderer(TimeLineSlotRenderer slotDrawer) {
mRenderer = slotDrawer;
if (mRenderer != null) {
- mRenderer.onSlotSizeChanged(mLayout.mSlotWidth, mLayout.mSlotHeight);
mRenderer.onVisibleRangeChanged(getVisibleStart(), getVisibleEnd());
}
}
@@ -116,27 +110,28 @@ public class SlotView extends GLView {
return;
}
Rect rect = mLayout.getSlotRect(index, mTempRect);
- int position = WIDE
- ? (rect.left + rect.right - getWidth()) / 2
- : (rect.top + rect.bottom - getHeight()) / 2;
+ int position = (rect.top + rect.bottom - getHeight()) / 2;
+
setScrollPosition(position);
}
public void makeSlotVisible(int index) {
Rect rect = mLayout.getSlotRect(index, mTempRect);
- int visibleBegin = WIDE ? mScrollX : mScrollY;
- int visibleLength = WIDE ? getWidth() : getHeight();
+ int visibleBegin = mScrollY;
+ int visibleLength = getHeight();
int visibleEnd = visibleBegin + visibleLength;
- int slotBegin = WIDE ? rect.left : rect.top;
- int slotEnd = WIDE ? rect.right : rect.bottom;
+ int slotBegin = rect.top;
+ int slotEnd = rect.bottom;
int position = visibleBegin;
if (visibleLength < slotEnd - slotBegin) {
position = visibleBegin;
} else if (slotBegin < visibleBegin) {
position = slotBegin;
- } else if (slotEnd > visibleEnd) {
+ } else if (slotEnd > visibleEnd && mainKey == 1) {
position = slotEnd - visibleLength;
+ } else if (slotBegin > visibleEnd && mainKey == 0) {
+ position = slotBegin - visibleLength;
}
setScrollPosition(position);
@@ -149,13 +144,15 @@ public class SlotView extends GLView {
isFromPhotoPage = flag;
}
+
public void setScrollPosition(int position) {
- if (View.LAYOUT_DIRECTION_RTL == TextUtils
- .getLayoutDirectionFromLocale(Locale.getDefault())
- && position == 0 && !isFromPhotoPage) {
- // If RTL and not from Photo Page, set position to max.
- position = mLayout.getScrollLimit();
- }
+ /*if (View.LAYOUT_DIRECTION_RTL == TextUtils
+ .getLayoutDirectionFromLocale(Locale.getDefault())
+ && position == 0 && !isFromPhotoPage) {
+ // If RTL and not from Photo Page, set position to max.
+ position = mLayout.getScrollLimit();
+ }*/
+
position = Utils.clamp(position, 0, mLayout.getScrollLimit());
mScroller.setPosition(position);
updateScrollPosition(position, false);
@@ -166,13 +163,9 @@ public class SlotView extends GLView {
}
@Override
- public void addComponent(GLView view) {
- throw new UnsupportedOperationException();
- }
-
- @Override
protected void onLayout(boolean changeSize, int l, int t, int r, int b) {
if (!changeSize) return;
+ mWidth = r - l;
// Make sure we are still at a resonable scroll position after the size
// is changed (like orientation change). We choose to keep the center
@@ -182,7 +175,6 @@ public class SlotView extends GLView {
mLayout.setSize(r - l, b - t);
makeSlotVisible(visibleIndex);
if (mOverscrollEffect == OVERSCROLL_3D) {
- mPaper.setSize(r - l, b - t);
}
}
@@ -199,12 +191,8 @@ public class SlotView extends GLView {
}
private void updateScrollPosition(int position, boolean force) {
- if (!force && (WIDE ? position == mScrollX : position == mScrollY)) return;
- if (WIDE) {
- mScrollX = position;
- } else {
- mScrollY = position;
- }
+ if (!force && (position == mScrollY)) return;
+ mScrollY = position;
mLayout.setScrollPosition(position);
onScrollPositionChanged(position);
}
@@ -220,7 +208,6 @@ public class SlotView extends GLView {
@Override
protected boolean onTouch(MotionEvent event) {
- if (mUIListener != null) mUIListener.onUserInteraction();
mGestureDetector.onTouchEvent(event);
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
@@ -228,7 +215,6 @@ public class SlotView extends GLView {
mScroller.forceFinished();
break;
case MotionEvent.ACTION_UP:
- mPaper.onRelease();
invalidate();
break;
}
@@ -239,15 +225,6 @@ public class SlotView extends GLView {
mListener = listener;
}
- public void setUserInteractionListener(UserInteractionListener listener) {
- mUIListener = listener;
- }
-
- public void setOverscrollEffect(int kind) {
- mOverscrollEffect = kind;
- mScroller.setOverfling(kind == OVERSCROLL_SYSTEM);
- }
-
private static int[] expandIntArray(int array[], int capacity) {
while (array.length < capacity) {
array = new int[array.length * 2];
@@ -264,13 +241,11 @@ public class SlotView extends GLView {
long animTime = AnimationTime.get();
boolean more = mScroller.advanceAnimation(animTime);
- more |= mLayout.advanceAnimation(animTime);
int oldX = mScrollX;
updateScrollPosition(mScroller.getPosition(), false);
- boolean paperActive = false;
if (mOverscrollEffect == OVERSCROLL_3D) {
- // Check if an edge is reached and notify mPaper if so.
+ // Check if an edge is reached and notify mPaper if so
int newX = mScrollX;
int limit = mLayout.getScrollLimit();
if (oldX > 0 && newX == 0 || oldX < limit && newX == limit) {
@@ -279,13 +254,13 @@ public class SlotView extends GLView {
// I don't know why, but getCurrVelocity() can return NaN.
if (!Float.isNaN(v)) {
- mPaper.edgeReached(v);
+ //mPaper.edgeReached(v);
}
+ //paperActive = mPaper.advanceAnimation();
}
- paperActive = mPaper.advanceAnimation();
}
- more |= paperActive;
+ //more |= paperActive;
if (mAnimation != null) {
more |= mAnimation.calculate(animTime);
@@ -295,10 +270,10 @@ public class SlotView extends GLView {
int requestCount = 0;
int requestedSlot[] = expandIntArray(mRequestRenderSlots,
- mLayout.mVisibleEnd - mLayout.mVisibleStart);
+ mLayout.getVisibleEnd() - mLayout.getVisibleStart());
- for (int i = mLayout.mVisibleEnd - 1; i >= mLayout.mVisibleStart; --i) {
- int r = renderItem(canvas, i, 0, paperActive);
+ for (int i = mLayout.getVisibleEnd() - 1; i >= mLayout.getVisibleStart(); --i) {
+ int r = renderItem(canvas, i, 0, false);
if ((r & RENDER_MORE_FRAME) != 0) more = true;
if ((r & RENDER_MORE_PASS) != 0) requestedSlot[requestCount++] = i;
}
@@ -307,8 +282,8 @@ public class SlotView extends GLView {
int newCount = 0;
for (int i = 0; i < requestCount; ++i) {
int r = renderItem(canvas,
- requestedSlot[i], pass, paperActive);
- if ((r & RENDER_MORE_FRAME) != 0) more = true;
+ requestedSlot[i], pass, false);
+ if ((r & RENDER_MORE_FRAME) != 0) more = false;
if ((r & RENDER_MORE_PASS) != 0) requestedSlot[newCount++] = i;
}
requestCount = newCount;
@@ -318,27 +293,15 @@ public class SlotView extends GLView {
if (more) invalidate();
- final UserInteractionListener listener = mUIListener;
- if (mMoreAnimation && !more && listener != null) {
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- listener.onUserInteractionEnd();
- }
- });
- }
- mMoreAnimation = more;
}
private int renderItem(
GLCanvas canvas, int index, int pass, boolean paperActive) {
+
canvas.save(GLCanvas.SAVE_FLAG_ALPHA | GLCanvas.SAVE_FLAG_MATRIX);
Rect rect = mLayout.getSlotRect(index, mTempRect);
- if (paperActive) {
- canvas.multiplyMatrix(mPaper.getTransform(rect, mScrollX), 0);
- } else {
- canvas.translate(rect.left, rect.top, 0);
- }
+ if (rect == null) return 0;
+ canvas.translate(rect.left, rect.top, 0);
if (mAnimation != null && mAnimation.isActive()) {
mAnimation.apply(canvas, index, rect);
}
@@ -391,277 +354,6 @@ public class SlotView extends GLView {
}
}
- // 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 slotHeightAdditional = 0;
-
- public int rowsLand = -1;
- public int rowsPort = -1;
- public int slotGap = -1;
- }
-
- public class Layout {
-
- private int mVisibleStart;
- private int mVisibleEnd;
-
- private int mSlotCount;
- private int mSlotWidth;
- private int mSlotHeight;
- private int mSlotGap;
-
- private Spec mSpec;
-
- private int mWidth;
- private int mHeight;
-
- private int mUnitCount;
- private int mContentLength;
- private int mScrollPosition;
-
- private IntegerAnimation mVerticalPadding = new IntegerAnimation();
- private IntegerAnimation mHorizontalPadding = new IntegerAnimation();
-
- public void setSlotSpec(Spec spec) {
- mSpec = spec;
- }
-
- public boolean setSlotCount(int slotCount) {
- if (slotCount == mSlotCount) return false;
- if (mSlotCount != 0) {
- mHorizontalPadding.setEnabled(true);
- mVerticalPadding.setEnabled(true);
- }
- mSlotCount = slotCount;
- int hPadding = mHorizontalPadding.getTarget();
- int vPadding = mVerticalPadding.getTarget();
- initLayoutParameters();
- return vPadding != mVerticalPadding.getTarget()
- || hPadding != mHorizontalPadding.getTarget();
- }
-
- public Rect getSlotRect(int index, Rect rect) {
- int col, row;
- if (WIDE) {
- if (View.LAYOUT_DIRECTION_RTL == TextUtils
- .getLayoutDirectionFromLocale(Locale.getDefault())) {
- // If RTL, recalculate the columns and rows.
- int count = ((mSlotCount + mUnitCount - 1) / mUnitCount);
- col = count - index / mUnitCount - 1;
- row = index % mUnitCount;
- } else {
- col = index / mUnitCount;
- row = index - col * mUnitCount;
- }
- } else {
- row = index / mUnitCount;
- col = index - row * mUnitCount;
- }
-
- int x = mHorizontalPadding.get() + col * (mSlotWidth + mSlotGap);
- int y = mVerticalPadding.get() + row * (mSlotHeight + mSlotGap);
- rect.set(x, y, x + mSlotWidth, y + mSlotHeight);
- return rect;
- }
-
- public int getSlotWidth() {
- return mSlotWidth;
- }
-
- public int getSlotHeight() {
- return mSlotHeight;
- }
-
- // Calculate
- // (1) mUnitCount: the number of slots we can fit into one column (or row).
- // (2) mContentLength: the width (or height) we need to display all the
- // columns (rows).
- // (3) padding[]: the vertical and horizontal padding we need in order
- // to put the slots towards to the center of the display.
- //
- // The "major" direction is the direction the user can scroll. The other
- // direction is the "minor" direction.
- //
- // The comments inside this method are the description when the major
- // directon is horizontal (X), and the minor directon is vertical (Y).
- private void initLayoutParameters(
- int majorLength, int minorLength, /* The view width and height */
- int majorUnitSize, int minorUnitSize, /* The slot width and height */
- int[] padding) {
- 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);
- 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 + (count - 1) * mSlotGap;
-
- // If the content length is less then the screen width, put
- // extra padding in left and right.
- padding[1] = Math.max(0, (majorLength - mContentLength) / 2);
- }
-
- 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 - mSpec.slotHeightAdditional;
- }
-
- if (mRenderer != null) {
- mRenderer.onSlotSizeChanged(mSlotWidth, mSlotHeight);
- }
-
- int[] padding = new int[2];
- if (WIDE) {
- initLayoutParameters(mWidth, mHeight, mSlotWidth, mSlotHeight, padding);
- mVerticalPadding.startAnimateTo(padding[0]);
- mHorizontalPadding.startAnimateTo(padding[1]);
- } else {
- initLayoutParameters(mHeight, mWidth, mSlotHeight, mSlotWidth, padding);
- mVerticalPadding.startAnimateTo(padding[1]);
- mHorizontalPadding.startAnimateTo(padding[0]);
- }
- updateVisibleSlotRange();
- }
-
- public void setSize(int width, int height) {
- mWidth = width;
- mHeight = height;
- initLayoutParameters();
- }
-
- private void updateVisibleSlotRange() {
- int position = mScrollPosition;
-
- if (WIDE) {
- if (View.LAYOUT_DIRECTION_RTL == TextUtils
- .getLayoutDirectionFromLocale(Locale.getDefault())) {
- // If RTL, recalculate the position.
- position = mContentLength > mWidth ? (mContentLength - position - mWidth)
- : position;
- position = Math.max(0, position);
- }
- 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 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);
- }
- }
-
- public void setScrollPosition(int position) {
- if (mScrollPosition == position) return;
- mScrollPosition = position;
- updateVisibleSlotRange();
- }
-
- private void setVisibleRange(int start, int end) {
- if (start == mVisibleStart && end == mVisibleEnd) return;
- if (start < end) {
- mVisibleStart = start;
- mVisibleEnd = end;
- } else {
- mVisibleStart = mVisibleEnd = 0;
- }
- if (mRenderer != null) {
- mRenderer.onVisibleRangeChanged(mVisibleStart, mVisibleEnd);
- }
- }
-
- public int getVisibleStart() {
- return mVisibleStart;
- }
-
- public int getVisibleEnd() {
- return mVisibleEnd;
- }
-
- public int getSlotIndexByPosition(float x, float y) {
- int absoluteX = Math.round(x) + (WIDE ? mScrollPosition : 0);
- int absoluteY = Math.round(y) + (WIDE ? 0 : mScrollPosition);
- if (View.LAYOUT_DIRECTION_RTL == TextUtils
- .getLayoutDirectionFromLocale(Locale.getDefault())) {
- // If RTL, recalculate the absoluteX.
- absoluteX = mContentLength > mWidth ? (mContentLength - absoluteX) : mWidth
- - absoluteX;
- }
- absoluteX -= mHorizontalPadding.get();
- absoluteY -= mVerticalPadding.get();
-
- if (absoluteX < 0 || absoluteY < 0) {
- return INDEX_NONE;
- }
-
- int columnIdx = absoluteX / (mSlotWidth + mSlotGap);
- int rowIdx = absoluteY / (mSlotHeight + mSlotGap);
-
- if (!WIDE && columnIdx >= mUnitCount) {
- return INDEX_NONE;
- }
-
- if (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);
-
- return index >= mSlotCount ? INDEX_NONE : index;
- }
-
- public int getScrollLimit() {
- int limit = WIDE ? mContentLength - mWidth : mContentLength - mHeight;
- return limit <= 0 ? 0 : limit;
- }
-
- public boolean advanceAnimation(long animTime) {
- // use '|' to make sure both sides will be executed
- return mVerticalPadding.calculate(animTime) | mHorizontalPadding.calculate(animTime);
- }
- }
-
private class MyGestureListener implements GestureDetector.OnGestureListener {
private boolean isDown;
@@ -700,9 +392,7 @@ public class SlotView extends GLView {
cancelDown(false);
int scrollLimit = mLayout.getScrollLimit();
if (scrollLimit == 0) return false;
- float velocity = WIDE ? velocityX : velocityY;
- mScroller.fling((int) -velocity, 0, scrollLimit);
- if (mUIListener != null) mUIListener.onUserInteractionBegin();
+ mScroller.fling((int) -velocityY, 0, scrollLimit);
invalidate();
return true;
}
@@ -711,11 +401,10 @@ public class SlotView extends GLView {
public boolean onScroll(MotionEvent e1,
MotionEvent e2, float distanceX, float distanceY) {
cancelDown(false);
- float distance = WIDE ? distanceX : distanceY;
int overDistance = mScroller.startScroll(
- Math.round(distance), 0, mLayout.getScrollLimit());
+ Math.round(distanceY), 0, mLayout.getScrollLimit());
if (mOverscrollEffect == OVERSCROLL_3D && overDistance != 0) {
- mPaper.overScroll(overDistance);
+ //mPaper.overScroll(overDistance);
}
invalidate();
return true;
@@ -725,9 +414,19 @@ public class SlotView extends GLView {
public boolean onSingleTapUp(MotionEvent e) {
cancelDown(false);
if (mDownInScrolling) return true;
- int index = mLayout.getSlotIndexByPosition(e.getX(), e.getY());
- if (index != INDEX_NONE) mListener.onSingleTapUp(index);
- return true;
+ RectSlot slot = mLayout.getRectSlotByPosition(e.getX(), e.getY());
+ if (slot == null) {
+ return true;
+ }
+ int index = slot.slotIndex;
+ if (index != INDEX_NONE) {
+ if (slot.mediaType == MediaObject.MEDIA_TYPE_TIMELINE_TITLE) {
+ mListener.onSingleTapUp(index, true);
+ return true;
+ }
+ mListener.onSingleTapUp(index, false);
+ }
+ return true;
}
@Override
@@ -736,8 +435,18 @@ public class SlotView extends GLView {
if (mDownInScrolling) return;
lockRendering();
try {
- int index = mLayout.getSlotIndexByPosition(e.getX(), e.getY());
- if (index != INDEX_NONE) mListener.onLongTap(index);
+ RectSlot slot = mLayout.getRectSlotByPosition(e.getX(), e.getY());
+ if (slot == null) return;
+
+ int index = slot.slotIndex;
+ if (index != INDEX_NONE) {
+ if (slot.mediaType == MediaObject.MEDIA_TYPE_TIMELINE_TITLE) {
+ mListener.onLongTap(index, true);
+
+ } else {
+ mListener.onLongTap(index, false);
+ }
+ }
} finally {
unlockRendering();
}
@@ -758,10 +467,15 @@ public class SlotView extends GLView {
mStartIndex = INDEX_NONE;
}
// Reset the scroll position to avoid scrolling over the updated limit.
- setScrollPosition(WIDE ? mScrollX : mScrollY);
+ setScrollPosition(mScrollY);
return changed;
}
+ public void onVersionChanged() {
+ mLayout.createSlots();
+ invalidate();
+ }
+
public int getVisibleStart() {
return mLayout.getVisibleStart();
}
@@ -788,48 +502,286 @@ public class SlotView extends GLView {
return r;
}
- private static class IntegerAnimation extends Animation {
- private int mTarget;
- private int mCurrent = 0;
- private int mFrom = 0;
- private boolean mEnabled = false;
+ public int getTitleWidth() {
+ return mWidth;
+ }
+
+ // This Spec class is used to specify the size of each slot in the SlotView.
+ // There are two ways to do it:
+ //
+ // Specify colsLand, colsPort, 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 colsLand = -1;
+ public int colsPort = -1;
+ public int titleHeight = -1;
+ public int slotGapPort = -1;
+ public int slotGapLand = -1;
+ }
+
+ public class Layout {
+
+ private int mVisibleStart;
+ private int mVisibleEnd;
+
+ public int mSlotCount;
+ private int mSlotWidth;
+ private int mSlotHeight;
+ private int mSlotGap;
+
+ private Spec mSpec;
+
+ private int mWidth;
+ private int mHeight;
+
+ private int mUnitCount;
+ private int mContentLength;
+ private int mScrollPosition;
+
+ private ArrayList<Integer> mHeightList;
+ private HashMap<Integer, RectSlot> mMediaSlotMap;
- public void setEnabled(boolean enabled) {
- mEnabled = enabled;
+ public void setSlotSpec(TimeLineSlotView.Spec spec) {
+ mSpec = spec;
}
- public void startAnimateTo(int target) {
- if (!mEnabled) {
- mTarget = mCurrent = target;
- return;
+ public boolean setSlotCount(int slotCount) {
+ if (slotCount == mSlotCount) return false;
+ mSlotCount = slotCount;
+ initLayoutParameters();
+ updateVisibleSlotRange();
+ return true;
+ }
+
+ public Rect getSlotRect(int index, Rect rect) {
+ if (index >= mVisibleStart && index < mVisibleEnd && mVisibleEnd != 0) {
+ RectSlot slot = getRectSlot(index);
+ if (slot == null) {
+ return null;
+ }
+ return getSlotRect(slot, rect);
}
- if (target == mTarget) return;
+ return rect;
+ }
- mFrom = mCurrent;
- mTarget = target;
- setDuration(180);
- start();
+ private void initLayoutParameters() {
+ mUnitCount = (mWidth > mHeight) ? mSpec.colsLand : mSpec.colsPort;
+ mSlotGap = (mWidth > mHeight) ? mSpec.slotGapLand: mSpec.slotGapPort;
+ mSlotWidth = Math.round((mWidth - (mUnitCount - 1) * mSlotGap) / mUnitCount);
+ mSlotHeight = mSlotWidth;
+ if (mRenderer != null) {
+ mRenderer.onSlotSizeChanged(mSlotWidth, mSlotHeight);
+ }
}
- public int get() {
- return mCurrent;
+ private void setSize(int width, int height) {
+ mWidth = width;
+ mHeight = height;
+ initLayoutParameters();
+ createSlots();
+ updateVisibleSlotRange();
}
- public int getTarget() {
- return mTarget;
+ public void setScrollPosition(int position) {
+ if (mScrollPosition == position) return;
+ mScrollPosition = position;
+ updateVisibleSlotRange();
}
- @Override
- protected void onCalculate(float progress) {
- mCurrent = Math.round(mFrom + progress * (mTarget - mFrom));
- if (progress == 1f) mEnabled = false;
+ private Rect getSlotRect(RectSlot slot, Rect rect) {
+ if (rect == null) {
+ Log.e(TAG, "LAYOUT: null rect passed");
+ Utils.assertTrue(false);
+ }
+ int x = 0;
+ int y = 0;
+ int w = mSlotWidth;
+ int h = 0;
+ if (slot.mediaType == MediaObject.MEDIA_TYPE_TIMELINE_TITLE) {
+ x = 0;
+ y = slot.totalHeight - (mSpec.titleHeight);
+ w = mWidth;
+ h = mSpec.titleHeight;
+ } else {
+ x = slot.slotCol * (mSlotWidth + mSlotGap);
+ y = slot.totalHeight -(mSlotHeight);
+ w = mSlotWidth;
+ h = mSlotHeight;
+ }
+ rect.set(x, y, x + w, y + h);
+ return rect;
+ }
+
+ private synchronized void updateVisibleSlotRange() {
+ int position = mScrollPosition;
+ if(mHeightList!= null && mHeightList.size()>0 ) {
+ int indexStart = Arrays.binarySearch(mHeightList.toArray(new Integer[0]), position);
+ int indexEnd = Arrays.binarySearch(mHeightList.toArray(new Integer[0]), position+mHeight);
+ if(indexStart<0) {
+ indexStart = (indexStart * (- 1)) - 1;
+ } if (indexEnd<0) {
+ indexEnd = (indexEnd * (- 1)) - 1;
+ }
+ int startSlotIndex = mHeightList.indexOf(mHeightList.get(indexStart));
+ if(indexEnd> mHeightList.size()-1) {
+ indexEnd = mHeightList.size()-1;
+ }
+ int endSlotIndex = mHeightList.lastIndexOf(mHeightList.get(indexEnd));
+
+
+ int endSlotIndexStr = mHeightList.indexOf(mHeightList.get(indexEnd));
+ if(((endSlotIndex-endSlotIndexStr) % mUnitCount) == (mUnitCount-1) && (startSlotIndex>mUnitCount)) {
+ startSlotIndex= startSlotIndex-mUnitCount;
+ }
+
+ setVisibleRange(startSlotIndex, Math.min(mSlotCount, endSlotIndex + 1));
+ }
+ }
+
+ private void setVisibleRange(int start, int end) {
+ if (start == mVisibleStart && end == mVisibleEnd) return;
+ if (start < end) {
+ mVisibleStart = start;
+ mVisibleEnd = end;
+ } else {
+ mVisibleStart = mVisibleEnd = 0;
+ }
+ if (mRenderer != null) {
+ mRenderer.onVisibleRangeChanged(mVisibleStart, mVisibleEnd);
+ }
+ }
+
+ public int getVisibleStart() {
+ return mVisibleStart;
+ }
+
+ public int getVisibleEnd() {
+ return mVisibleEnd;
+ }
+
+ public int getSlotIndexByPosition(float x, float y) {
+ RectSlot slot = getRectSlotByPosition(x, y);
+ if (slot == null) return INDEX_NONE;
+
+ return slot.slotIndex;
+
+ }
+
+ public RectSlot getRectSlotByPosition(float x, float y) {
+ int absoluteX = Math.round(x);
+ int absoluteY = Math.round(y) + mScrollPosition;
+
+ if (absoluteX < 0 || absoluteY < 0) {
+ return null;
+ }
+ if (absoluteY > mContentLength)
+ return null;
+
+ int columnIdx = absoluteX / (mSlotWidth + mSlotGap);
+
+ RectSlot rectSlot;
+
+ int index = Arrays.binarySearch(mHeightList.toArray(new Integer[0]), absoluteY);
+ if(index<0){
+ index = (index*-1) -1;
+ }
+ if(index >= mHeightList.size()) {
+ index = mHeightList.size()-1;
+ }
+ int startIndex = mHeightList.indexOf(mHeightList.get(index));
+ int maxIndex = mHeightList.lastIndexOf(mHeightList.get(index));
+ if(mMediaSlotMap.get(startIndex).mediaType == MediaObject.MEDIA_TYPE_TIMELINE_TITLE) {
+ return mMediaSlotMap.get(startIndex);
+ }
+ for(int i= startIndex;(i< startIndex+mUnitCount) && (i<=maxIndex); i++) {
+ rectSlot = mMediaSlotMap.get(i);
+ if(rectSlot.slotCol== columnIdx) {
+ return rectSlot;
+ }
+ }
+ return null;
+ }
+
+ public int getScrollLimit() {
+ if (mHeightList != null && mHeightList.size() > 0) {
+ return Math.max(0, mContentLength -mHeight);
+ }
+ return 0;
+ }
+
+
+
+ public void createSlots() {
+ ArrayList<MediaItem> mediaItemlist = new ArrayList<MediaItem>();
+ if (mRenderer != null) {
+ mediaItemlist = mRenderer.getAllMediaItems();
+ }
+ if (mediaItemlist != null && mediaItemlist.size() > 0) {
+ if (mHeightList == null) {
+ mHeightList = new ArrayList<Integer>();
+ }
+ if (mMediaSlotMap == null) {
+ mMediaSlotMap = new HashMap<Integer, RectSlot>();
+ }
+ mHeightList.clear();
+ mMediaSlotMap.clear();
+ boolean isPrevTitle = false;
+ int j = 0;
+ int col = 0;
+ int totalHieght = 0;
+ for (int i = 0; i < mediaItemlist.size(); ++i) {
+ MediaItem info = mediaItemlist.get(i);
+
+ if (info.getMediaType() == MediaObject.MEDIA_TYPE_TIMELINE_TITLE) {
+ totalHieght += (mSpec.titleHeight+mSlotGap);
+ isPrevTitle = true;
+ col =0;
+ } else {
+ if (isPrevTitle) {
+ j =0;
+ isPrevTitle = false;
+ } else {
+ ++j;
+ }
+ if(j%mUnitCount == 0) {
+ totalHieght += (mSlotHeight+mSlotGap);
+ col =0;
+ } else {
+ col = j%mUnitCount;
+ }
+
+ }
+ mHeightList.add(totalHieght);
+ RectSlot rectslot = new RectSlot(info.getMediaType(), i, col, totalHieght);
+ mMediaSlotMap.put(rectslot.slotIndex, rectslot);
+ }
+ mContentLength = mHeightList.get(mHeightList.size() -1);
+ mSlotCount = mediaItemlist.size();
+ }
+ updateVisibleSlotRange();
+ }
+
+ public RectSlot getRectSlot(int slotIndex) {
+ return mMediaSlotMap.get(slotIndex);
}
}
- /**
- * Get the SlotView's max scroll value.
- */
- public int getScrollLimit() {
- return mLayout.getScrollLimit();
+
+
+ public static class RectSlot {
+ public int mediaType;
+ public int slotIndex;
+ public int slotCol;
+ public int totalHeight;
+
+ public RectSlot(int type, int index, int col, int height) {
+ mediaType = type;
+ slotIndex = index;
+ slotCol = col;
+ totalHeight = height;
+ }
}
}
diff --git a/src/com/android/gallery3d/ui/TimeLineTitleMaker.java b/src/com/android/gallery3d/ui/TimeLineTitleMaker.java
index 3ac3bb7fe..45acdef87 100644..100755
--- a/src/com/android/gallery3d/ui/TimeLineTitleMaker.java
+++ b/src/com/android/gallery3d/ui/TimeLineTitleMaker.java
@@ -1,4 +1,7 @@
/*
+ * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ *
* Copyright (C) 2012 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -19,221 +22,135 @@ package com.android.gallery3d.ui;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
-import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.PorterDuff;
import android.graphics.Typeface;
import android.text.TextPaint;
import android.text.TextUtils;
-import android.view.View;
-import com.android.gallery3d.R;
-import com.android.gallery3d.data.DataSourceType;
-import com.android.photos.data.GalleryBitmapPool;
import com.android.gallery3d.util.ThreadPool;
import com.android.gallery3d.util.ThreadPool.JobContext;
+import com.android.photos.data.GalleryBitmapPool;
+import com.android.gallery3d.R;
-import java.util.Locale;
+public class TimeLineTitleMaker {
-public class AlbumLabelMaker {
+ private final String TAG = "TimelineTitleMaker";
private static final int BORDER_SIZE = 0;
- private final AlbumSetSlotRenderer.LabelSpec mSpec;
+ private final TimeLineSlotRenderer.LabelSpec mSpec;
private final TextPaint mTitlePaint;
private final TextPaint mCountPaint;
private final Context mContext;
+ private final TimeLineSlotView mTimeLineSlotView;
- private int mLabelWidth;
- private int mBitmapWidth;
- private int mBitmapHeight;
-
- private final LazyLoadedBitmap mLocalSetIcon;
- private final LazyLoadedBitmap mPicasaIcon;
- private final LazyLoadedBitmap mCameraIcon;
-
- public AlbumLabelMaker(Context context, AlbumSetSlotRenderer.LabelSpec spec) {
+ public TimeLineTitleMaker(Context context, TimeLineSlotRenderer.LabelSpec spec, TimeLineSlotView slotView) {
mContext = context;
mSpec = spec;
- mTitlePaint = getTextPaint(spec.titleFontSize, spec.titleColor, false);
- mCountPaint = getTextPaint(spec.countFontSize, spec.countColor, false);
-
- mLocalSetIcon = new LazyLoadedBitmap(R.drawable.frame_overlay_gallery_folder);
- mPicasaIcon = new LazyLoadedBitmap(R.drawable.frame_overlay_gallery_picasa);
- mCameraIcon = new LazyLoadedBitmap(R.drawable.frame_overlay_gallery_camera);
- }
-
- public static int getBorderSize() {
- return BORDER_SIZE;
+ mTimeLineSlotView = slotView;
+ mTitlePaint = getTextPaint(spec.timeLineTitleFontSize, spec.timeLineTitleTextColor , true);
+ mCountPaint = getTextPaint(spec.timeLineTitleFontSize, spec.timeLineNumberTextColor, true);
}
- private Bitmap getOverlayAlbumIcon(int sourceType) {
- switch (sourceType) {
- case DataSourceType.TYPE_CAMERA:
- return mCameraIcon.get();
- case DataSourceType.TYPE_LOCAL:
- return mLocalSetIcon.get();
- case DataSourceType.TYPE_PICASA:
- return mPicasaIcon.get();
- }
- return null;
- }
-
- private static TextPaint getTextPaint(int textSize, int color, boolean isBold) {
+ private static TextPaint getTextPaint(
+ int textSize, int color, boolean isBold) {
TextPaint paint = new TextPaint();
paint.setTextSize(textSize);
paint.setAntiAlias(true);
paint.setColor(color);
- //paint.setShadowLayer(2f, 0f, 0f, Color.LTGRAY);
+ paint.setTypeface(Typeface.SANS_SERIF);
if (isBold) {
paint.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));
}
return paint;
}
- private class LazyLoadedBitmap {
- private Bitmap mBitmap;
- private int mResId;
-
- public LazyLoadedBitmap(int resId) {
- mResId = resId;
- }
-
- public synchronized Bitmap get() {
- if (mBitmap == null) {
- BitmapFactory.Options options = new BitmapFactory.Options();
- options.inPreferredConfig = Bitmap.Config.ARGB_8888;
- mBitmap = BitmapFactory.decodeResource(
- mContext.getResources(), mResId, options);
- }
- return mBitmap;
- }
- }
-
- public synchronized void setLabelWidth(int width) {
- if (mLabelWidth == width) return;
- mLabelWidth = width;
- int borders = 2 * BORDER_SIZE;
- mBitmapWidth = width + borders;
- mBitmapHeight = mSpec.labelBackgroundHeight + borders;
- }
-
- public ThreadPool.Job<Bitmap> requestLabel(
- String title, String count, int sourceType) {
- return new AlbumLabelJob(title, count, sourceType);
+ public ThreadPool.Job<Bitmap> requestTimeLineTitle( String title,
+ int photoCount, int videoCount) {
+ return new TimeLineTitle(title,photoCount, videoCount, mContext );
}
static void drawText(Canvas canvas,
- int x, int y, String text, int lengthLimit, TextPaint p) {
- // The TextPaint cannot be used concurrently
- synchronized (p) {
- text = TextUtils.ellipsize(
- text, p, lengthLimit, TextUtils.TruncateAt.END).toString();
- canvas.drawText(text, x, y - p.getFontMetricsInt().ascent, p);
- }
+ int x, int y, String text, int lengthLimit, TextPaint p) {
+ text = TextUtils.ellipsize(
+ text, p, lengthLimit, TextUtils.TruncateAt.END).toString();
+ canvas.drawText(text, x, y - p.getFontMetricsInt().ascent, p);
}
- private class AlbumLabelJob implements ThreadPool.Job<Bitmap> {
- private final String mTitle;
- private final String mCount;
- private final int mSourceType;
-
- public AlbumLabelJob(String title, String count, int sourceType) {
+ private class TimeLineTitle implements ThreadPool.Job<Bitmap> {
+ private String mTitle;
+ private int mVideoCount;
+ private int mImageCount;
+ private Context mContext;
+ public TimeLineTitle(String title, int imageCount, int videoCount, Context context) {
mTitle = title;
- mCount = count;
- mSourceType = sourceType;
+ mImageCount = imageCount;
+ mVideoCount = videoCount;
+ mContext = context;
+
}
@Override
public Bitmap run(JobContext jc) {
- AlbumSetSlotRenderer.LabelSpec s = mSpec;
-
- String title = mTitle;
- String count = mCount;
- Bitmap icon = getOverlayAlbumIcon(mSourceType);
+ TimeLineSlotRenderer.LabelSpec spec = mSpec;
Bitmap bitmap;
- int labelWidth;
-
+ int width = mTimeLineSlotView.getTitleWidth();
+ int height= spec.timeLineTitleHeight;
synchronized (this) {
- labelWidth = mLabelWidth;
- bitmap = GalleryBitmapPool.getInstance().get(mBitmapWidth, mBitmapHeight);
+ bitmap = GalleryBitmapPool.getInstance().get(width, height);
}
-
if (bitmap == null) {
int borders = 2 * BORDER_SIZE;
- bitmap = Bitmap.createBitmap(labelWidth + borders,
- s.labelBackgroundHeight + borders, Config.ARGB_8888);
+ bitmap = Bitmap.createBitmap(width + borders,
+ height + borders, Config.ARGB_8888);
+ }
+ if (bitmap == null) {
+ return null;
}
-
Canvas canvas = new Canvas(bitmap);
canvas.clipRect(BORDER_SIZE, BORDER_SIZE,
bitmap.getWidth() - BORDER_SIZE,
bitmap.getHeight() - BORDER_SIZE);
- canvas.drawColor(mSpec.backgroundColor, PorterDuff.Mode.SRC);
+ canvas.drawColor(mSpec.timeLineTitleBackgroundColor, PorterDuff.Mode.SRC);
canvas.translate(BORDER_SIZE, BORDER_SIZE);
- if (View.LAYOUT_DIRECTION_RTL == TextUtils
- .getLayoutDirectionFromLocale(Locale.getDefault())) {// RTL
- // draw title
- if (jc.isCancelled()) return null;
- int strLength = (int) mTitlePaint.measureText(title);
- int x = labelWidth - (s.leftMargin + s.iconSize) - strLength;
- // TODO: is the offset relevant in new reskin?
- // int y = s.titleOffset;
- int y = (s.labelBackgroundHeight - s.titleFontSize) / 2;
- drawText(canvas, x, y, title, labelWidth - s.leftMargin - x -
- s.titleRightMargin, mTitlePaint);
-
- // draw count
- if (jc.isCancelled()) return null;
- x = s.leftMargin + 10;// plus 10 to get a much bigger margin
- y = (s.labelBackgroundHeight - s.countFontSize) / 2;
- drawText(canvas, x, y, count,
- labelWidth - x, mCountPaint);
- // draw the icon
- if (icon != null) {
- if (jc.isCancelled()) return null;
- float scale = (float) s.iconSize / icon.getWidth();
- canvas.translate(labelWidth - s.leftMargin - s.iconSize,
- (s.labelBackgroundHeight -
- Math.round(scale * icon.getHeight())) / 2f);
- canvas.scale(scale, scale);
- canvas.drawBitmap(icon, 0, 0, null);
+
+ StringBuilder sb = new StringBuilder();
+ if(mImageCount != 0) {
+ sb.append(mContext.getResources().getQuantityString(R.plurals.number_of_photos, mImageCount, mImageCount));
+ if(mVideoCount!=0) {
+ sb.append(mContext.getResources().getQuantityString(
+ R.plurals.number_of_videos, mVideoCount, mVideoCount));
}
- } else { // LTR
- // draw title
- if (jc.isCancelled()) return null;
- int x = s.leftMargin + s.iconSize;
- // TODO: is the offset relevant in new reskin?
- // int y = s.titleOffset;
- int y = (s.labelBackgroundHeight - s.titleFontSize) / 2;
- drawText(canvas, x, y, title, labelWidth - s.leftMargin - x -
- s.titleRightMargin, mTitlePaint);
-
- // draw count
- if (jc.isCancelled()) return null;
- x = labelWidth - s.titleRightMargin;
- y = (s.labelBackgroundHeight - s.countFontSize) / 2;
- drawText(canvas, x, y, count,
- labelWidth - x, mCountPaint);
-
- // draw the icon
- if (icon != null) {
- if (jc.isCancelled()) return null;
- float scale = (float) s.iconSize / icon.getWidth();
- canvas.translate(s.leftMargin, (s.labelBackgroundHeight -
- Math.round(scale * icon.getHeight())) / 2f);
- canvas.scale(scale, scale);
- canvas.drawBitmap(icon, 0, 0, null);
+ } else {
+ if(mVideoCount != 0) {
+ sb.append(mContext.getResources().getQuantityString(
+ R.plurals.number_of_videos, mVideoCount, mVideoCount));
}
}
+ String countString = sb.toString();
+
+ if (jc.isCancelled()) return null;
+
+ int x;
+ int y = 0;
+ if (mTitle != null) {
+ mTitle = mTitle.toUpperCase();
+ x = 16;
+ y = (height/2)-14;
+ drawText(canvas, x, y, mTitle, width-x, mTitlePaint);
+ }
+
+ if (countString != null) {
+ y = (height/2)-14;
+ x = width - countString.length()- 100;
+ drawText(canvas, x, y, countString,
+ width - x, mCountPaint);
+ }
return bitmap;
}
}
-
- public void recycleLabel(Bitmap label) {
- GalleryBitmapPool.getInstance().put(label);
- }
}