aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJorge Ruesga <jorge@ruesga.com>2013-11-02 02:20:56 +0100
committerJorge Ruesga <jorge@ruesga.com>2013-11-02 02:20:56 +0100
commit4effddfe30fd045834232f6bb66070edf079578d (patch)
tree2e57f74d55685891a49b02ec069c118cf5b15110 /src
parentca2f0060cc367ac8174a27a3124cd0124e49c627 (diff)
downloadandroid_packages_wallpapers_PhotoPhase-4effddfe30fd045834232f6bb66070edf079578d.tar.gz
android_packages_wallpapers_PhotoPhase-4effddfe30fd045834232f6bb66070edf079578d.tar.bz2
android_packages_wallpapers_PhotoPhase-4effddfe30fd045834232f6bb66070edf079578d.zip
Multiples fixes
- Fully rewrite the album selection preference - Fix multiple style - Fix lints - Resources cleanup Signed-off-by: Jorge Ruesga <jorge@ruesga.com>
Diffstat (limited to 'src')
-rw-r--r--src/org/cyanogenmod/wallpapers/photophase/MediaPictureDiscoverer.java2
-rw-r--r--src/org/cyanogenmod/wallpapers/photophase/PhotoPhaseRenderer.java28
-rw-r--r--src/org/cyanogenmod/wallpapers/photophase/PhotoPhaseWallpaper.java2
-rw-r--r--src/org/cyanogenmod/wallpapers/photophase/TextureManager.java10
-rw-r--r--src/org/cyanogenmod/wallpapers/photophase/adapters/AlbumCardUiAdapter.java139
-rw-r--r--src/org/cyanogenmod/wallpapers/photophase/adapters/AlbumPictureAdapter.java127
-rw-r--r--src/org/cyanogenmod/wallpapers/photophase/animations/Flip3dAnimationController.java (renamed from src/org/cyanogenmod/wallpapers/photophase/animations/AlbumsFlip3dAnimationController.java)113
-rw-r--r--src/org/cyanogenmod/wallpapers/photophase/animations/Rotate3dAnimation.java93
-rw-r--r--src/org/cyanogenmod/wallpapers/photophase/model/Album.java23
-rw-r--r--src/org/cyanogenmod/wallpapers/photophase/model/Picture.java64
-rw-r--r--src/org/cyanogenmod/wallpapers/photophase/preferences/ChoosePicturesFragment.java805
-rw-r--r--src/org/cyanogenmod/wallpapers/photophase/preferences/DispositionFragment.java2
-rw-r--r--src/org/cyanogenmod/wallpapers/photophase/preferences/PhotoPhasePreferences.java3
-rw-r--r--src/org/cyanogenmod/wallpapers/photophase/preferences/PreferencesProvider.java13
-rw-r--r--src/org/cyanogenmod/wallpapers/photophase/tasks/AsyncPictureLoaderTask.java52
-rw-r--r--src/org/cyanogenmod/wallpapers/photophase/widgets/AlbumInfoView.java (renamed from src/org/cyanogenmod/wallpapers/photophase/widgets/AlbumInfo.java)159
-rw-r--r--src/org/cyanogenmod/wallpapers/photophase/widgets/AlbumPictures.java345
-rw-r--r--src/org/cyanogenmod/wallpapers/photophase/widgets/CardLayout.java91
-rw-r--r--src/org/cyanogenmod/wallpapers/photophase/widgets/DispositionView.java8
-rw-r--r--src/org/cyanogenmod/wallpapers/photophase/widgets/PictureItemView.java204
-rw-r--r--src/org/cyanogenmod/wallpapers/photophase/widgets/PicturesView.java164
-rw-r--r--src/org/cyanogenmod/wallpapers/photophase/widgets/VerticalEndlessScroller.java114
22 files changed, 1510 insertions, 1051 deletions
diff --git a/src/org/cyanogenmod/wallpapers/photophase/MediaPictureDiscoverer.java b/src/org/cyanogenmod/wallpapers/photophase/MediaPictureDiscoverer.java
index 4228abf..f45dcd6 100644
--- a/src/org/cyanogenmod/wallpapers/photophase/MediaPictureDiscoverer.java
+++ b/src/org/cyanogenmod/wallpapers/photophase/MediaPictureDiscoverer.java
@@ -264,7 +264,7 @@ public class MediaPictureDiscoverer {
}
}
- /*package*/ final Context mContext;
+ final Context mContext;
private final OnMediaPictureDiscoveredListener mCallback;
private AsyncDiscoverTask mTask;
diff --git a/src/org/cyanogenmod/wallpapers/photophase/PhotoPhaseRenderer.java b/src/org/cyanogenmod/wallpapers/photophase/PhotoPhaseRenderer.java
index f57d53b..c307023 100644
--- a/src/org/cyanogenmod/wallpapers/photophase/PhotoPhaseRenderer.java
+++ b/src/org/cyanogenmod/wallpapers/photophase/PhotoPhaseRenderer.java
@@ -62,25 +62,25 @@ public class PhotoPhaseRenderer implements GLSurfaceView.Renderer {
private final long mInstance;
private static long sInstances;
- /*package*/ final Context mContext;
- /*package*/ EffectContext mEffectContext;
+ final Context mContext;
+ EffectContext mEffectContext;
private final Handler mHandler;
- /*package*/ final GLESSurfaceDispatcher mDispatcher;
- /*package*/ TextureManager mTextureManager;
+ final GLESSurfaceDispatcher mDispatcher;
+ TextureManager mTextureManager;
- /*package*/ PhotoPhaseWallpaperWorld mWorld;
- /*package*/ ColorShape mOverlay;
- /*package*/ OopsShape mOopsShape;
+ PhotoPhaseWallpaperWorld mWorld;
+ ColorShape mOverlay;
+ OopsShape mOopsShape;
- /*package*/ long mLastRunningTransition;
+ long mLastRunningTransition;
private long mLastTouchTime;
private static final long TOUCH_BARRIER_TIME = 1000L;
- /*package*/ int mWidth = -1;
- /*package*/ int mHeight = -1;
+ int mWidth = -1;
+ int mHeight = -1;
private int mStatusBarHeight = 0;
- /*package*/ int mMeasuredHeight = -1;
+ int mMeasuredHeight = -1;
private final float[] mMVPMatrix = new float[16];
private final float[] mProjMatrix = new float[16];
@@ -88,7 +88,7 @@ public class PhotoPhaseRenderer implements GLSurfaceView.Renderer {
private final Object mDrawing = new Object();
- /*package*/ final Object mMediaSync = new Object();
+ final Object mMediaSync = new Object();
private PendingIntent mMediaScanIntent;
private final BroadcastReceiver mSettingsChangedReceiver = new BroadcastReceiver() {
@@ -383,13 +383,13 @@ public class PhotoPhaseRenderer implements GLSurfaceView.Renderer {
/**
* Method that deselect the current transition
*/
- /*package*/ synchronized void deselectCurrentTransition() {
+ synchronized void deselectCurrentTransition() {
mHandler.removeCallbacks(mTransitionThread);
mWorld.deselectTransition(mMVPMatrix);
mLastRunningTransition = 0;
}
- /*package*/ void scheduleOrCancelMediaScan() {
+ void scheduleOrCancelMediaScan() {
int interval = Preferences.Media.getRefreshFrecuency();
if (interval != Preferences.Media.MEDIA_RELOAD_DISABLED) {
scheduleMediaScan(interval);
diff --git a/src/org/cyanogenmod/wallpapers/photophase/PhotoPhaseWallpaper.java b/src/org/cyanogenmod/wallpapers/photophase/PhotoPhaseWallpaper.java
index 625212c..5152bc8 100644
--- a/src/org/cyanogenmod/wallpapers/photophase/PhotoPhaseWallpaper.java
+++ b/src/org/cyanogenmod/wallpapers/photophase/PhotoPhaseWallpaper.java
@@ -96,7 +96,7 @@ public class PhotoPhaseWallpaper
class PhotoPhaseWallpaperEngine extends GLES20WallpaperService.GLES20Engine {
private final Handler mHandler;
- /*package*/ final ActivityManager mActivityManager;
+ final ActivityManager mActivityManager;
/**
* Constructor of <code>PhotoPhaseWallpaperEngine<code>
diff --git a/src/org/cyanogenmod/wallpapers/photophase/TextureManager.java b/src/org/cyanogenmod/wallpapers/photophase/TextureManager.java
index 6c8de05..3731a1b 100644
--- a/src/org/cyanogenmod/wallpapers/photophase/TextureManager.java
+++ b/src/org/cyanogenmod/wallpapers/photophase/TextureManager.java
@@ -59,8 +59,8 @@ public class TextureManager implements OnMediaPictureDiscoveredListener {
BackgroundPictureLoaderThread mBackgroundTask;
/*protected*/ final MediaPictureDiscoverer mPictureDiscoverer;
- /*package*/ Rect mScreenDimensions;
- /*package*/ Rect mDimensions;
+ Rect mScreenDimensions;
+ Rect mDimensions;
final GLESSurfaceDispatcher mDispatcher;
@@ -73,7 +73,7 @@ public class TextureManager implements OnMediaPictureDiscoveredListener {
/**
* A private runnable that will run in the GLThread
*/
- /*package*/ class PictureDispatcher implements Runnable {
+ class PictureDispatcher implements Runnable {
File mImage;
GLESTextureInfo ti = null;
final Object mWait = new Object();
@@ -428,7 +428,7 @@ public class TextureManager implements OnMediaPictureDiscoveredListener {
* @param ti The original texture information
* @param effect The effect to apply to the destination picture
*/
- /*package*/ void fixAspectRatio(TextureRequestor requestor, GLESTextureInfo ti) {
+ void fixAspectRatio(TextureRequestor requestor, GLESTextureInfo ti) {
// Check if we have to apply any correction to the image
if (Preferences.General.isFixAspectRatio()) {
// Transform requestor dimensions to screen dimensions
@@ -472,7 +472,7 @@ public class TextureManager implements OnMediaPictureDiscoveredListener {
boolean mRun;
boolean mTaskPaused;
- /*package*/ boolean mEmpty;
+ boolean mEmpty;
private final List<File> mNewImages;
private final List<File> mUsedImages;
diff --git a/src/org/cyanogenmod/wallpapers/photophase/adapters/AlbumCardUiAdapter.java b/src/org/cyanogenmod/wallpapers/photophase/adapters/AlbumCardUiAdapter.java
new file mode 100644
index 0000000..b321b73
--- /dev/null
+++ b/src/org/cyanogenmod/wallpapers/photophase/adapters/AlbumCardUiAdapter.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2013 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.cyanogenmod.wallpapers.photophase.adapters;
+
+import android.animation.Animator;
+import android.animation.AnimatorInflater;
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.animation.Animation;
+import android.view.animation.AnimationUtils;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+
+import org.cyanogenmod.wallpapers.photophase.R;
+import org.cyanogenmod.wallpapers.photophase.model.Album;
+import org.cyanogenmod.wallpapers.photophase.widgets.AlbumInfoView;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * An implementation of {@link ArrayAdapter} supporting "Google Now Card Layout" like layout
+ */
+public class AlbumCardUiAdapter extends ArrayAdapter<Album> {
+
+ /**
+ * A class that conforms with the ViewHolder pattern to performance
+ * the list view rendering.
+ */
+ private static class ViewHolder {
+ public ViewHolder() {
+ super();
+ }
+ AlbumInfoView mAlbumInfoView;
+ Animation mCardAnimation;
+ Animator mCardAnimator;
+ }
+
+ private List<Album> mData = new ArrayList<Album>();
+
+ private AlbumInfoView.CallbacksListener mAlbumInfoCallback;
+
+ /**
+ * Constructor of <code>AlbumCardUiAdapter</code>.
+ *
+ * @param context The current context
+ * @param parent The adapter view
+ * @param data The array with all the album data
+ * @param callback The album info view callback
+ */
+ public AlbumCardUiAdapter(Context context, AdapterView<?> parent, List<Album> data,
+ AlbumInfoView.CallbacksListener callback) {
+ super(context, R.id.album_name, data);
+ mData = data;
+ mAlbumInfoCallback = callback;
+ }
+
+ /**
+ * Method that dispose the elements of the adapter.
+ */
+ public void dispose() {
+ clear();
+ this.mData = null;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+
+ // Retrieve album
+ final Album album = this.mData.get(position);
+
+ // Check to reuse view
+ View v = convertView;
+ if (v == null) {
+ //Create the view holder
+ LayoutInflater li =
+ (LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ v = li.inflate(R.layout.album_info, parent, false);
+
+ // Create the controller for the view
+ ViewHolder viewHolder = new ViewHolder();
+ viewHolder.mAlbumInfoView = (AlbumInfoView)v.findViewById(R.id.album_info);
+ viewHolder.mAlbumInfoView.setAlbum(album);
+ viewHolder.mAlbumInfoView.addCallBackListener(mAlbumInfoCallback);
+ v.setTag(viewHolder);
+ }
+
+ // Retrieve the view holder
+ ViewHolder viewHolder = (ViewHolder)v.getTag();
+
+ // Retrieve the view holder and update the view
+ viewHolder.mAlbumInfoView.updateView(album);
+
+ // Animate the view?
+ if (!album.isDisplayed()) {
+ album.setDisplayed(true);
+
+ // Reset the animation
+ if (viewHolder.mCardAnimation != null) {
+ viewHolder.mCardAnimation.cancel();
+ }
+ if (viewHolder.mCardAnimator != null) {
+ viewHolder.mCardAnimator.cancel();
+ }
+
+ // Card Animation
+ viewHolder.mCardAnimation = AnimationUtils.loadAnimation(
+ getContext(), R.anim.cards_slide_up);
+ v.startAnimation(viewHolder.mCardAnimation);
+ viewHolder.mCardAnimator = AnimatorInflater.loadAnimator(getContext(),
+ R.animator.cards_rotate_animator);
+ viewHolder.mCardAnimator.setTarget(v);
+ viewHolder.mCardAnimator.start();
+ }
+
+ // Return the view
+ return v;
+ }
+
+}
diff --git a/src/org/cyanogenmod/wallpapers/photophase/adapters/AlbumPictureAdapter.java b/src/org/cyanogenmod/wallpapers/photophase/adapters/AlbumPictureAdapter.java
new file mode 100644
index 0000000..addc298
--- /dev/null
+++ b/src/org/cyanogenmod/wallpapers/photophase/adapters/AlbumPictureAdapter.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2013 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.cyanogenmod.wallpapers.photophase.adapters;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+
+import org.cyanogenmod.wallpapers.photophase.R;
+import org.cyanogenmod.wallpapers.photophase.model.Picture;
+import org.cyanogenmod.wallpapers.photophase.widgets.PictureItemView;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * An implementation of {@link ArrayAdapter} an album picture
+ */
+public class AlbumPictureAdapter extends ArrayAdapter<Picture> {
+
+ /**
+ * A class that conforms with the ViewHolder pattern to performance
+ * the list view rendering.
+ */
+ private static class ViewHolder {
+ public ViewHolder() {
+ super();
+ }
+ PictureItemView mPictureItemView;
+ }
+
+ private List<Picture> mData = new ArrayList<Picture>();
+ private AdapterView<?> mParent;
+
+ /**
+ * Constructor of <code>AlbumPictureAdapter</code>.
+ *
+ * @param context The current context
+ * @param data The pictures data
+ */
+ public AlbumPictureAdapter(Context context, List<Picture> data, AdapterView<?> parent) {
+ super(context, R.id.picture_thumbnail, data);
+ mData = data;
+ mParent = parent;
+ }
+
+ /**
+ * Method that dispose the elements of the adapter.
+ */
+ public void dispose() {
+ clear();
+ this.mData = null;
+ }
+
+ @Override
+ public void notifyDataSetChanged() {
+ int start = mParent.getFirstVisiblePosition();
+ int last = mParent.getLastVisiblePosition();
+ for (int i = start; i <= last; i++) {
+ View v = mParent.getChildAt(i);
+ getView(i, v, mParent, false);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ return getView(position, convertView, parent, true);
+ }
+
+ /**
+ * Method that returns a view for a position
+ *
+ * @param position The position
+ * @param convertView A reusable view or null
+ * @param parent The parent of the view
+ * @param refreshIcon If the view should refresh its icon
+ * @return View The view
+ */
+ private View getView(int position, View convertView, ViewGroup parent, boolean refreshIcon) {
+ final Picture picture = this.mData.get(position);
+
+ // Check to reuse view
+ View v = convertView;
+ if (v == null) {
+ //Create the view holder
+ LayoutInflater li =
+ (LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ v = li.inflate(R.layout.picture_item, parent, false);
+
+ // Create the controller for the view
+ ViewHolder viewHolder = new ViewHolder();
+ viewHolder.mPictureItemView = (PictureItemView)v.findViewById(R.id.picture);
+ viewHolder.mPictureItemView.setPicture(picture);
+ v.setTag(viewHolder);
+ }
+
+ // Retrieve the view holder
+ ViewHolder viewHolder = (ViewHolder)v.getTag();
+
+ // Retrieve the view holder and update the view
+ viewHolder.mPictureItemView.updateView(picture, refreshIcon);
+
+ // Return the view
+ return v;
+ }
+
+}
diff --git a/src/org/cyanogenmod/wallpapers/photophase/animations/AlbumsFlip3dAnimationController.java b/src/org/cyanogenmod/wallpapers/photophase/animations/Flip3dAnimationController.java
index 228f827..69f023d 100644
--- a/src/org/cyanogenmod/wallpapers/photophase/animations/AlbumsFlip3dAnimationController.java
+++ b/src/org/cyanogenmod/wallpapers/photophase/animations/Flip3dAnimationController.java
@@ -16,20 +16,14 @@
package org.cyanogenmod.wallpapers.photophase.animations;
import android.view.View;
-import android.view.View.OnClickListener;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.Animation;
import android.view.animation.Animation.AnimationListener;
-import org.cyanogenmod.wallpapers.photophase.model.Album;
-import org.cyanogenmod.wallpapers.photophase.widgets.AlbumInfo;
-import org.cyanogenmod.wallpapers.photophase.widgets.AlbumPictures;
-import org.cyanogenmod.wallpapers.photophase.widgets.AlbumPictures.CallbacksListener;
-
/**
- * A class that manages a flip 3d effect of an album
+ * A class that manages a flip 3d effect of two views
*/
-public class AlbumsFlip3dAnimationController {
+public class Flip3dAnimationController {
private static final int DURATION = 200;
@@ -37,13 +31,15 @@ public class AlbumsFlip3dAnimationController {
View mBack;
boolean mFrontFace;
+ final Object mLock = new Object();
+
/**
- * Constructor of <code>AlbumsFlip3dAnimationController</code>
+ * Constructor of <code>Flip3dAnimationController</code>
*
* @param front The front view
* @param back The back view
*/
- public AlbumsFlip3dAnimationController(AlbumInfo front, AlbumPictures back) {
+ public Flip3dAnimationController(View front, View back) {
super();
mFront = front;
mBack = back;
@@ -51,45 +47,48 @@ public class AlbumsFlip3dAnimationController {
mFrontFace = true;
}
+ public boolean isFrontFace() {
+ return mFrontFace;
+ }
+
/**
- * Method that register the controller
+ * Method that reset the controller
*/
- public void register() {
- getFrontView().setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- getBackView().setVisibility(View.INVISIBLE);
- applyAnimation(false);
- }
- });
- ((AlbumPictures)getBackView()).addCallBackListener(new CallbacksListener() {
- @Override
- public void onBackButtonClick(View v) {
- getBackView().setVisibility(View.INVISIBLE);
- applyAnimation(true);
- }
-
- @Override
- public void onSelectionChanged(Album album) {
- // Ignore
- }
- });
+ public void reset() {
+ changeToFrontFace(true);
}
/**
- * Method that unregister the controller
+ * Method that change the view to the front face
+ *
+ * @param animate Do with animation
*/
- public void unregister() {
- getFrontView().setOnClickListener(null);
- getBackView().setOnClickListener(null);
+ public void changeToFrontFace(boolean animate) {
+ if (!mFrontFace) {
+ if (animate) {
+ applyAnimation(true);
+ } else {
+ mBack.setVisibility(View.GONE);
+ mFront.setVisibility(View.VISIBLE);
+ mFrontFace = true;
+ }
+ }
}
/**
- * Method that reset the controller
+ * Method that change the view to the back face
+ *
+ * @param animate Do with animation
*/
- public void reset() {
- if (!mFrontFace) {
- applyAnimation(true);
+ public void changeToBackFace(boolean animate) {
+ if (mFrontFace) {
+ if (animate) {
+ applyAnimation(true);
+ } else {
+ mFront.setVisibility(View.GONE);
+ mBack.setVisibility(View.VISIBLE);
+ mFrontFace = false;
+ }
}
}
@@ -98,11 +97,11 @@ public class AlbumsFlip3dAnimationController {
*
* @param inverse Applies the inverse animation
*/
- /*package*/ void applyAnimation(boolean inverse) {
+ void applyAnimation(boolean inverse) {
applyTransformation(getFrontView(), 0, 90 * (inverse ? -1 : 1), true);
}
- /*package*/ void applyTransformation(final View v, float start, float end, final boolean step1) {
+ void applyTransformation(final View v, float start, float end, final boolean step1) {
final float centerX = v.getWidth() / 2.0f;
final float centerY = v.getHeight() / 2.0f;
@@ -117,8 +116,6 @@ public class AlbumsFlip3dAnimationController {
if (!step1) {
getBackView().setVisibility(View.VISIBLE);
}
- getFrontView().setOnClickListener(null);
- getBackView().setOnClickListener(null);
}
@Override
@@ -128,24 +125,16 @@ public class AlbumsFlip3dAnimationController {
@Override
public void onAnimationEnd(Animation animation) {
- getFrontView().setAnimation(null);
- getBackView().setAnimation(null);
- if (step1) {
- getFrontView().setVisibility(View.INVISIBLE);
- applyTransformation(getBackView(), -90 * (!mFrontFace ? -1 : 1), 0, false);
- } else {
- mFrontFace = !mFrontFace;
- getBackView().setVisibility(View.GONE);
- if (mFrontFace) {
- getFrontView().setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View view) {
- getBackView().setVisibility(View.INVISIBLE);
- applyAnimation(false);
- }
- });
+ synchronized (mLock) {
+ getFrontView().setAnimation(null);
+ getBackView().setAnimation(null);
+ if (step1) {
+ getFrontView().setVisibility(View.INVISIBLE);
+ applyTransformation(getBackView(),
+ -90 * (!mFrontFace ? -1 : 1), 0, false);
} else {
- ((AlbumPictures)getFrontView()).onShow();
+ mFrontFace = !mFrontFace;
+ getBackView().setVisibility(View.GONE);
}
}
}
@@ -153,11 +142,11 @@ public class AlbumsFlip3dAnimationController {
v.startAnimation(anim);
}
- /*package*/ View getFrontView() {
+ View getFrontView() {
return mFrontFace ? mFront : mBack;
}
- /*package*/ View getBackView() {
+ View getBackView() {
return !mFrontFace ? mFront : mBack;
}
}
diff --git a/src/org/cyanogenmod/wallpapers/photophase/animations/Rotate3dAnimation.java b/src/org/cyanogenmod/wallpapers/photophase/animations/Rotate3dAnimation.java
new file mode 100644
index 0000000..814ef0f
--- /dev/null
+++ b/src/org/cyanogenmod/wallpapers/photophase/animations/Rotate3dAnimation.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.cyanogenmod.wallpapers.photophase.animations;
+
+import android.view.animation.Animation;
+import android.view.animation.Transformation;
+import android.graphics.Camera;
+import android.graphics.Matrix;
+
+/**
+ * An animation that rotates the view on the Y axis between two specified angles.
+ * This animation also adds a translation on the Z axis (depth) to improve the effect.
+ */
+public class Rotate3dAnimation extends Animation {
+ private final float mFromDegrees;
+ private final float mToDegrees;
+ private final float mCenterX;
+ private final float mCenterY;
+ private final float mDepthZ;
+ private final boolean mReverse;
+ private Camera mCamera;
+
+ /**
+ * Creates a new 3D rotation on the Y axis. The rotation is defined by its
+ * start angle and its end angle. Both angles are in degrees. The rotation
+ * is performed around a center point on the 2D space, definied by a pair
+ * of X and Y coordinates, called centerX and centerY. When the animation
+ * starts, a translation on the Z axis (depth) is performed. The length
+ * of the translation can be specified, as well as whether the translation
+ * should be reversed in time.
+ *
+ * @param fromDegrees the start angle of the 3D rotation
+ * @param toDegrees the end angle of the 3D rotation
+ * @param centerX the X center of the 3D rotation
+ * @param centerY the Y center of the 3D rotation
+ * @param reverse true if the translation should be reversed, false otherwise
+ */
+ public Rotate3dAnimation(float fromDegrees, float toDegrees,
+ float centerX, float centerY, float depthZ, boolean reverse) {
+ mFromDegrees = fromDegrees;
+ mToDegrees = toDegrees;
+ mCenterX = centerX;
+ mCenterY = centerY;
+ mDepthZ = depthZ;
+ mReverse = reverse;
+ }
+
+ @Override
+ public void initialize(int width, int height, int parentWidth, int parentHeight) {
+ super.initialize(width, height, parentWidth, parentHeight);
+ mCamera = new Camera();
+ }
+
+ @Override
+ protected void applyTransformation(float interpolatedTime, Transformation t) {
+ final float fromDegrees = mFromDegrees;
+ float degrees = fromDegrees + ((mToDegrees - fromDegrees) * interpolatedTime);
+
+ final float centerX = mCenterX;
+ final float centerY = mCenterY;
+ final Camera camera = mCamera;
+
+ final Matrix matrix = t.getMatrix();
+
+ camera.save();
+ if (mReverse) {
+ camera.translate(0.0f, 0.0f, mDepthZ * interpolatedTime);
+ } else {
+ camera.translate(0.0f, 0.0f, mDepthZ * (1.0f - interpolatedTime));
+ }
+ camera.rotateY(degrees);
+ camera.getMatrix(matrix);
+ camera.restore();
+
+ matrix.preTranslate(-centerX, -centerY);
+ matrix.postTranslate(centerX, centerY);
+ }
+}
+
diff --git a/src/org/cyanogenmod/wallpapers/photophase/model/Album.java b/src/org/cyanogenmod/wallpapers/photophase/model/Album.java
index 83f067d..0c1c2a2 100644
--- a/src/org/cyanogenmod/wallpapers/photophase/model/Album.java
+++ b/src/org/cyanogenmod/wallpapers/photophase/model/Album.java
@@ -24,16 +24,20 @@ import java.util.List;
/**
* A class that represents an album
*/
-public class Album implements Comparable<Album>, Cloneable {
+public class Album implements Comparable<Album>, Cloneable {
private Drawable mIcon;
private String mPath;
private String mName;
private String mDate;
private boolean mSelected;
- private List<String> mItems;
+ private List<Picture> mItems;
+ // We have this array for performance access. Do not forget to sync with Picture#selected
private List<String> mSelectedItems;
+ // Ui properties
+ private boolean mDisplayed = false;
+
public Drawable getIcon() {
return mIcon;
}
@@ -74,11 +78,11 @@ public class Album implements Comparable<Album>, Cloneable {
this.mSelected = selected;
}
- public List<String> getItems() {
+ public List<Picture> getItems() {
return mItems;
}
- public void setItems(List<String> items) {
+ public void setItems(List<Picture> items) {
this.mItems = items;
}
@@ -90,6 +94,14 @@ public class Album implements Comparable<Album>, Cloneable {
this.mSelectedItems = selectedItems;
}
+ public boolean isDisplayed() {
+ return mDisplayed;
+ }
+
+ public void setDisplayed(boolean mDisplayed) {
+ this.mDisplayed = mDisplayed;
+ }
+
@Override
public int compareTo(Album another) {
return mPath.compareTo(another.mPath);
@@ -102,9 +114,10 @@ public class Album implements Comparable<Album>, Cloneable {
album.mPath = mPath;
album.mName = mName;
album.mDate = mDate;
- album.mItems = new ArrayList<String>(mItems);
+ album.mItems = new ArrayList<Picture>(mItems);
album.mSelectedItems = new ArrayList<String>(mSelectedItems);
album.mSelected = mSelected;
+ album.mDisplayed = mDisplayed;
return album;
}
}
diff --git a/src/org/cyanogenmod/wallpapers/photophase/model/Picture.java b/src/org/cyanogenmod/wallpapers/photophase/model/Picture.java
new file mode 100644
index 0000000..76b1bb6
--- /dev/null
+++ b/src/org/cyanogenmod/wallpapers/photophase/model/Picture.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2013 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.cyanogenmod.wallpapers.photophase.model;
+
+import java.io.File;
+
+/**
+ * A class that represents a picture
+ */
+public class Picture implements Comparable<Picture>, Cloneable {
+
+ private String mPath;
+ private boolean mSelected;
+
+ public Picture(String path, boolean selected) {
+ super();
+ this.mPath = path;
+ this.mSelected = selected;
+ }
+
+ public String getPath() {
+ return mPath;
+ }
+
+ public void setPath(String path) {
+ this.mPath = path;
+ }
+
+ public boolean isSelected() {
+ return mSelected;
+ }
+
+ public void setSelected(boolean selected) {
+ this.mSelected = selected;
+ }
+
+ public String getName() {
+ return new File(mPath).getName();
+ }
+
+ @Override
+ public int compareTo(Picture another) {
+ return mPath.compareTo(another.mPath);
+ }
+
+ @Override
+ public Object clone() {
+ return new Picture(mPath, mSelected);
+ }
+}
diff --git a/src/org/cyanogenmod/wallpapers/photophase/preferences/ChoosePicturesFragment.java b/src/org/cyanogenmod/wallpapers/photophase/preferences/ChoosePicturesFragment.java
index 6e41308..00d75a6 100644
--- a/src/org/cyanogenmod/wallpapers/photophase/preferences/ChoosePicturesFragment.java
+++ b/src/org/cyanogenmod/wallpapers/photophase/preferences/ChoosePicturesFragment.java
@@ -16,7 +16,9 @@
package org.cyanogenmod.wallpapers.photophase.preferences;
-import android.content.ContentResolver;
+import android.animation.Animator;
+import android.animation.Animator.AnimatorListener;
+import android.animation.ObjectAnimator;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
@@ -24,6 +26,8 @@ import android.database.Cursor;
import android.os.AsyncTask;
import android.os.AsyncTask.Status;
import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
import android.preference.PreferenceFragment;
import android.provider.MediaStore;
import android.util.Log;
@@ -32,19 +36,30 @@ import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
+import android.view.View.OnClickListener;
import android.view.ViewGroup;
+import android.view.animation.AccelerateDecelerateInterpolator;
+import android.view.animation.AlphaAnimation;
+import android.view.animation.Animation;
+import android.widget.AdapterView;
+import android.widget.AdapterView.OnItemClickListener;
+import android.widget.FrameLayout;
+import android.widget.GridView;
+import android.widget.ImageView;
+import android.widget.ListView;
+import android.widget.TextView;
import org.cyanogenmod.wallpapers.photophase.R;
-import org.cyanogenmod.wallpapers.photophase.animations.AlbumsFlip3dAnimationController;
+import org.cyanogenmod.wallpapers.photophase.adapters.AlbumCardUiAdapter;
+import org.cyanogenmod.wallpapers.photophase.adapters.AlbumPictureAdapter;
import org.cyanogenmod.wallpapers.photophase.model.Album;
+import org.cyanogenmod.wallpapers.photophase.model.Picture;
import org.cyanogenmod.wallpapers.photophase.preferences.PreferencesProvider.Preferences;
-import org.cyanogenmod.wallpapers.photophase.widgets.AlbumInfo;
-import org.cyanogenmod.wallpapers.photophase.widgets.AlbumPictures;
-import org.cyanogenmod.wallpapers.photophase.widgets.CardLayout;
-import org.cyanogenmod.wallpapers.photophase.widgets.VerticalEndlessScroller;
-import org.cyanogenmod.wallpapers.photophase.widgets.VerticalEndlessScroller.OnEndScrollListener;
+import org.cyanogenmod.wallpapers.photophase.widgets.AlbumInfoView;
+import org.cyanogenmod.wallpapers.photophase.widgets.PictureItemView;
import java.io.File;
+import java.io.IOException;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Date;
@@ -56,25 +71,28 @@ import java.util.Set;
/**
* A fragment class for select the picture that will be displayed on the wallpaper
*/
-public class ChoosePicturesFragment extends PreferenceFragment implements OnEndScrollListener {
+public class ChoosePicturesFragment extends PreferenceFragment
+ implements AlbumInfoView.CallbacksListener, OnClickListener {
private static final String TAG = "ChoosePicturesFragment";
private static final boolean DEBUG = false;
- private static final int AMOUNT_OF_ADDED_STEPS = 5;
+ private static final int PROGRESS_STEPS = 5;
+
+ // The album loader task
+ private final AsyncTask<Void, Album, Void> mTask = new AsyncTask<Void, Album, Void>() {
+
+ private DateFormat mDateFormat;
- private final AsyncTask<Void, Album, Void> mAlbumsLoaderTask = new AsyncTask<Void, Album, Void>() {
/**
* {@inheritDoc}
*/
@Override
protected Void doInBackground(Void... params) {
// Query all the external content and classify the pictures in albums and load the cards
- DateFormat df = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT);
- Album album = null;
- unregister();
- Cursor c = mContentResolver.query(
+ mDateFormat = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT);
+ Cursor c = getActivity().getContentResolver().query(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
new String[]{ MediaStore.MediaColumns.DATA },
null,
@@ -84,40 +102,31 @@ public class ChoosePicturesFragment extends PreferenceFragment implements OnEndS
try {
long start = System.currentTimeMillis();
if (DEBUG) Log.v(TAG, "Media library:");
+ int count = 0;
+ List<Album> pending = new ArrayList<Album>();
+ List<Album> all = new ArrayList<Album>();
+ Album album = null;
while (c.moveToNext()) {
- // Only valid files (those i can read)
- String p = c.getString(0);
- if (DEBUG) Log.v(TAG, "\t" + p);
- if (p != null) {
- File f = new File(p);
- if (f.isFile() && f.canRead()) {
- File path = f.getParentFile();
- String name = path.getName();
- if (album == null || album.getPath().compareTo(path.getAbsolutePath()) != 0) {
- if (album != null) {
- mAlbums.add(album);
- mOriginalAlbums.add((Album)album.clone());
- }
- album = new Album();
- album.setPath(path.getAbsolutePath());
- album.setName(name);
- album.setDate(df.format(new Date(path.lastModified())));
- album.setSelected(isSelectedItem(album.getPath()));
- album.setItems(new ArrayList<String>());
- album.setSelectedItems(new ArrayList<String>());
- }
- album.getItems().add(f.getAbsolutePath());
- if (isSelectedItem(f.getAbsolutePath())) {
- album.getSelectedItems().add(f.getAbsolutePath());
- }
- }
+ album = processPath(all, pending, album, c.getString(0));
+ count++;
+ if (count % PROGRESS_STEPS == 0) {
+ // Notify and clean
+ publishProgress(pending.toArray(new Album[pending.size()]));
+ pending.clear();
}
}
- // Add the last album
+ // Add the last albums
if (album != null) {
- mAlbums.add(album);
+ // Add to global structures
+ all.add(album);
mOriginalAlbums.add((Album)album.clone());
+
+ // Add to local structures and notify
+ pending.add(album);
+
+ // Notify
+ publishProgress(pending.toArray(new Album[pending.size()]));
}
long end = System.currentTimeMillis();
if (DEBUG) Log.v(TAG, "Library loaded in " + (end - start) + " miliseconds");
@@ -133,43 +142,139 @@ public class ChoosePicturesFragment extends PreferenceFragment implements OnEndS
* {@inheritDoc}
*/
@Override
+ protected void onProgressUpdate(Album... albums) {
+ for(Album album : albums) {
+ mAlbums.add(album);
+ }
+ mAlbumAdapter.notifyDataSetChanged();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
protected void onPostExecute(Void result) {
- Resources res = getActivity().getResources();
- int size = (int)(res.getDimension(R.dimen.album_size) +
- res.getDimension(R.dimen.small_margin));
- mScroller.setEndPadding(size * AMOUNT_OF_ADDED_STEPS);
- int height = mScroller.getMeasuredHeight();
- int steps = (height / size) + AMOUNT_OF_ADDED_STEPS;
-
- // Create the views an force a redraw the items
- mAlbumViews = new ArrayList<View>(mAlbums.size());
- for (Album item : mAlbums) {
- mAlbumViews.add(createAlbumView(item));
+ mAlbumAdapter.notifyDataSetChanged();
+ }
+
+ /**
+ * Method that process a album path
+ *
+ * @param all All the albums
+ * @param pending Pending albums to notify
+ * @param data The current album data
+ * @param path The path to analyze
+ * @return Album The new current album
+ */
+ private Album processPath(List<Album> all, List<Album> pending, Album data, String path) {
+ // Only valid files (those i can read)
+ if (DEBUG) Log.v(TAG, "\t" + path);
+ Album album = data;
+ if (path != null) {
+ File f = new File(path);
+ if (f.isFile() && f.canRead()) {
+ File p = f.getParentFile();
+ String name = p.getName();
+ if (album == null || album.getPath().compareTo(p.getAbsolutePath()) != 0) {
+ if (album != null) {
+ // Add to global structures
+ all.add(album);
+ mOriginalAlbums.add((Album)album.clone());
+
+ // Add to local structures and notify
+ pending.add(album);
+ }
+ album = new Album();
+ album.setPath(p.getAbsolutePath());
+ album.setName(name);
+ album.setDate(mDateFormat.format(new Date(p.lastModified())));
+ album.setSelected(isSelectedItem(album.getPath()));
+ album.setItems(new ArrayList<Picture>());
+ album.setSelectedItems(new ArrayList<String>());
+ }
+ boolean selected = isSelectedItem(f.getAbsolutePath());
+ album.getItems().add(new Picture(f.getAbsolutePath(), selected));
+ if (selected) {
+ album.getSelectedItems().add(f.getAbsolutePath());
+ }
+ }
}
- doEndScroll(steps, true);
+ return album;
+ }
- // We not need Hardware acceleration anymore (no more animations)
- // Disable drawing cache
- mScroller.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
- mScroller.setDrawingCacheEnabled(false);
- mScroller.setSmoothScrollingEnabled(true);
+ /**
+ * Method that checks if an item is selected
+ *
+ * @param item The item
+ * @return boolean if an item is selected
+ */
+ private boolean isSelectedItem(String item) {
+ Iterator<String> it = mSelectedAlbums.iterator();
+ while (it.hasNext()) {
+ String albumPath = it.next();
+ if (item.compareTo(albumPath) == 0) {
+ return true;
+ }
+ }
+ return false;
}
};
- /*package*/ ContentResolver mContentResolver;
+ private final Handler.Callback mCallback = new Handler.Callback() {
+ @Override
+ public boolean handleMessage(Message msg) {
+ if (msg.what == MSG_LOAD_PICTURES) {
+ loadPictures((Album)msg.obj);
+ return true;
+ }
+ return false;
+ }
+ };
- /*package*/ List<Album> mAlbums;
- /*package*/ List<View> mAlbumViews;
- /*package*/ List<Album> mOriginalAlbums;
- /*package*/ List<AlbumsFlip3dAnimationController> mAnimationControllers;
+ OnItemClickListener mOnItemClickListener = new OnItemClickListener() {
+ @Override
+ public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+ if (mShowingAlbums) {
+ onHeaderPressed(parent, view, position);
+ } else {
+ onPicturePressed(view);
+ }
+ }
+ };
+
+ private static final int MSG_LOAD_PICTURES = 1;
- /*package*/ Set<String> mSelectedAlbums;
+ List<Album> mAlbums;
+ List<Album> mOriginalAlbums;
+
+ Set<String> mSelectedAlbums;
private Set<String> mOriginalSelectedAlbums;
- /*package*/ VerticalEndlessScroller mScroller;
- private CardLayout mAlbumsPanel;
+ ViewGroup mContainer;
+
+ ListView mAlbumsPanel;
+ AlbumCardUiAdapter mAlbumAdapter;
- /*package*/ boolean mSelectionChanged;
+ GridView mPicturesPanel;
+ AlbumPictureAdapter mPictureAdapter;
+
+ private boolean mSelectionChanged;
+
+ // Animation references
+ ViewGroup mSrcParent;
+ View mSrcView;
+ ViewGroup mDstParent;
+ View mDstView;
+
+ Album mAlbum;
+
+ private int mPicturesAnimDurationIn;
+ private int mPicturesAnimDurationOut;
+
+ Handler mHandler;
+ LayoutInflater mInflater;
+
+ boolean mShowingAlbums;
/**
* {@inheritDoc}
@@ -177,22 +282,26 @@ public class ChoosePicturesFragment extends PreferenceFragment implements OnEndS
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- mContentResolver = getActivity().getContentResolver();
+ mHandler = new Handler(mCallback);
+ mShowingAlbums = true;
// Create an empty album
mAlbums = new ArrayList<Album>();
mOriginalAlbums = new ArrayList<Album>();
- mAnimationControllers = new ArrayList<AlbumsFlip3dAnimationController>();
// Change the preference manager
getPreferenceManager().setSharedPreferencesName(PreferencesProvider.PREFERENCES_FILE);
getPreferenceManager().setSharedPreferencesMode(Context.MODE_PRIVATE);
// Load the albums user selection
- mOriginalSelectedAlbums = Preferences.Media.getSelectedMedia();
+ mOriginalSelectedAlbums = removeObsoleteAlbumsData(Preferences.Media.getSelectedMedia());
mSelectedAlbums = new HashSet<String>(mOriginalSelectedAlbums);
mSelectionChanged = false;
+ Resources res = getActivity().getResources();
+ mPicturesAnimDurationIn = res.getInteger(R.integer.pictures_anim_in);
+ mPicturesAnimDurationOut = res.getInteger(R.integer.pictures_anim_out);
+
setHasOptionsMenu(true);
}
@@ -202,12 +311,19 @@ public class ChoosePicturesFragment extends PreferenceFragment implements OnEndS
@Override
public void onDestroy() {
super.onDestroy();
- if (mAlbumsLoaderTask.getStatus().compareTo(Status.PENDING) == 0) {
- mAlbumsLoaderTask.cancel(true);
+ if (mTask.getStatus().compareTo(Status.PENDING) == 0) {
+ mTask.cancel(true);
}
unbindDrawables(mAlbumsPanel);
unregister();
+ if (!mShowingAlbums) {
+ mPicturesPanel.setVisibility(View.GONE);
+ mDstView.setVisibility(View.GONE);
+ mDstParent.removeView(mPicturesPanel);
+ mDstParent.removeView(mDstView);
+ }
+
// Notify that the settings was changed
Intent intent = new Intent(PreferencesProvider.ACTION_SETTINGS_CHANGED);
if (mSelectionChanged) {
@@ -218,10 +334,9 @@ public class ChoosePicturesFragment extends PreferenceFragment implements OnEndS
getActivity().sendBroadcast(intent);
}
- /*package*/ void unregister() {
+ private void unregister() {
mAlbums.clear();
mOriginalAlbums.clear();
- mAnimationControllers.clear();
}
/**
@@ -229,7 +344,7 @@ public class ChoosePicturesFragment extends PreferenceFragment implements OnEndS
*
* @param view The root view
*/
- private void unbindDrawables(View view) {
+ void unbindDrawables(View view) {
if (view.getBackground() != null) {
view.getBackground().setCallback(null);
}
@@ -237,7 +352,6 @@ public class ChoosePicturesFragment extends PreferenceFragment implements OnEndS
for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) {
unbindDrawables(((ViewGroup) view).getChildAt(i));
}
- ((ViewGroup) view).removeAllViews();
}
}
@@ -245,26 +359,43 @@ public class ChoosePicturesFragment extends PreferenceFragment implements OnEndS
* {@inheritDoc}
*/
@Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ public View onCreateView(final LayoutInflater inflater, final ViewGroup container,
+ Bundle savedInstanceState) {
+
+ mContainer = container;
+ mInflater = inflater;
+
// Inflate the layout for this fragment
- mScroller =
- (VerticalEndlessScroller)inflater.inflate(
+ FrameLayout root =
+ (FrameLayout)mInflater.inflate(
R.layout.choose_picture_fragment, container, false);
- mScroller.setCallback(this);
- mAlbumsPanel = (CardLayout)mScroller.findViewById(R.id.albums_panel);
+ mAlbumsPanel = (ListView)root.findViewById(R.id.albums_panel);
+ mAlbumsPanel.setSmoothScrollbarEnabled(true);
+ mAlbumAdapter = new AlbumCardUiAdapter(getActivity(), mAlbumsPanel, mAlbums, this);
+ mAlbumsPanel.setAdapter(mAlbumAdapter);
+ mAlbumsPanel.setOnItemClickListener(mOnItemClickListener);
// Force Hardware acceleration
- if (!mScroller.isHardwareAccelerated()) {
- mScroller.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+ if (!root.isHardwareAccelerated()) {
+ root.setLayerType(View.LAYER_TYPE_HARDWARE, null);
}
if (!mAlbumsPanel.isHardwareAccelerated()) {
mAlbumsPanel.setLayerType(View.LAYER_TYPE_HARDWARE, null);
}
// Load the albums
- mAlbumsLoaderTask.execute();
+ unregister();
+ mTask.execute();
+
+ return root;
+ }
- return mScroller;
+ @Override
+ public void onClick(View v) {
+ // Hide the albums picture with animation
+ if (v.equals(mDstView)) {
+ hideAlbumPictures(mDstParent, mDstView, mSrcParent, mSrcView);
+ }
}
/**
@@ -287,8 +418,12 @@ public class ChoosePicturesFragment extends PreferenceFragment implements OnEndS
case R.id.mnu_restore:
restoreData();
return true;
- case R.id.mnu_invert_all:
- invertAll();
+ case R.id.mnu_invert:
+ if (mShowingAlbums) {
+ invertAll();
+ } else {
+ invertAlbum(mAlbum);
+ }
return true;
default:
return super.onOptionsItemSelected(item);
@@ -301,14 +436,25 @@ public class ChoosePicturesFragment extends PreferenceFragment implements OnEndS
private void restoreData() {
// Restore and the albums the selection
mSelectedAlbums = new HashSet<String>(mOriginalSelectedAlbums);
- mAlbums.clear();
- for (Album album : mOriginalAlbums) {
- mAlbums.add((Album)album.clone());
+ int count = mAlbums.size();
+ for (int i = 0; i < count ; i++) {
+ Album album = mAlbums.get(i);
+ Album originalAlbum = mOriginalAlbums.get(i);
+
+ // Update selected status
+ album.setSelected(originalAlbum.isSelected());
+ album.setItems(new ArrayList<Picture>(originalAlbum.getItems()));
+ album.setSelectedItems(new ArrayList<String>(originalAlbum.getSelectedItems()));
}
+ mAlbumAdapter.notifyDataSetChanged();
- // Update all the views
+ // Update settings
Preferences.Media.setSelectedMedia(getActivity(), mSelectedAlbums);
- updateAll();
+ mSelectionChanged = true;
+
+ if (!mShowingAlbums) {
+ hideAlbumPictures(mDstParent, mDstView, mSrcParent, mSrcView);
+ }
}
/**
@@ -325,172 +471,431 @@ public class ChoosePicturesFragment extends PreferenceFragment implements OnEndS
} else {
mSelectedAlbums.addAll(album.getSelectedItems());
}
+ for (Picture picture : album.getItems()) {
+ picture.setSelected(false);
+ }
}
+ mAlbumAdapter.notifyDataSetChanged();
- // Update all the views
+ // Update settings
Preferences.Media.setSelectedMedia(getActivity(), mSelectedAlbums);
- updateAll();
+ mSelectionChanged = true;
}
/**
- * Method that updates the current state of all the albums
+ * Method that inverts the selection of an album
+ *
+ * @param album The album which to invert its selection
*/
- private void updateAll() {
- // Update every view (albums and views should have the same size)
- int count = mAlbumsPanel.getChildCount();
- for (int i = 0; i < count; i++) {
- Album album = mAlbums.get(i);
- View v = mAlbumsPanel.getChildAt(i);
- AlbumInfo albumInfo = (AlbumInfo)v.findViewById(R.id.album_info);
- AlbumPictures albumPictures = (AlbumPictures)v.findViewById(R.id.album_pictures);
- albumInfo.updateView(album);
- albumPictures.updateView(album, true);
+ private void invertAlbum(Album album) {
+ // Remove all pictures of the album
+ removeAlbumItems(album);
+ List<String> origSelectedItems = new ArrayList<String>(album.getSelectedItems());
+ List<String> selectedItems = album.getSelectedItems();
+ album.getSelectedItems().clear();
+ for (Picture picture : album.getItems()) {
+ boolean selected = !origSelectedItems.contains(picture.getPath());
+ if (selected) {
+ selectedItems.add(picture.getPath());
+ }
+ picture.setSelected(selected);
}
- // Restore the preference
+ // Notify pictures dataset changed
+ mPictureAdapter.notifyDataSetChanged();
+ updateAlbumInfo(mDstView, album);
+
+ mSelectedAlbums.addAll(album.getSelectedItems());
Preferences.Media.setSelectedMedia(getActivity(), mSelectedAlbums);
mSelectionChanged = true;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void onAlbumSelected(Album album) {
+ updateAlbumSelection(album, true);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void onAlbumDeselected(Album album) {
+ updateAlbumSelection(album, false);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void onAllPicturesSelected(Album album) {
+ updateAllPicturesSelection(album, true);
+ }
- // Restore all the animations states
- for (AlbumsFlip3dAnimationController controller : mAnimationControllers) {
- controller.reset();
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void onAllPicturesDeselected(Album album) {
+ updateAllPicturesSelection(album, false);
+ }
+
+ /**
+ * Method that update the album selection
+ *
+ * @param album The album to update
+ * @param selected If the album is selected
+ */
+ private void updateAlbumSelection(Album album, boolean selected) {
+ // Remove all pictures of the album
+ removeAlbumItems(album);
+ album.setSelected(selected);
+ album.getSelectedItems().clear();
+ for (Picture picture : album.getItems()) {
+ picture.setSelected(false);
+ }
+ if (selected) {
+ mSelectedAlbums.add(album.getPath());
}
+
+ if (!mShowingAlbums) {
+ // Notify pictures dataset changed
+ updateAlbumInfo(mDstView, album);
+ mPictureAdapter.notifyDataSetChanged();
+ }
+ updateAlbumInfo(mSrcView, album);
+
+ Preferences.Media.setSelectedMedia(getActivity(), mSelectedAlbums);
+ mSelectionChanged = true;
}
/**
- * Method that creates a new album to the card layout
+ * Method that update the whole picture selection
*
- * @param album The album to create
- * @return View The view create
+ * @param album The album to update
+ * @param selected If all the picture were selected
*/
- View createAlbumView(final Album album) {
- LayoutInflater li = (LayoutInflater)getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- final View albumView = li.inflate(R.layout.album, mAlbumsPanel, false);
- final AlbumInfo albumInfo = (AlbumInfo)albumView.findViewById(R.id.album_info);
- final AlbumPictures albumPictures = (AlbumPictures)albumView.findViewById(R.id.album_pictures);
-
- // Load the album info
- albumInfo.post(new Runnable() {
- @Override
- public void run() {
- albumInfo.updateView(album);
+ private void updateAllPicturesSelection(Album album, boolean selected) {
+ // Remove all pictures of the album
+ removeAlbumItems(album);
+ List<String> selectedItems = album.getSelectedItems();
+ selectedItems.clear();
+ for (Picture picture : album.getItems()) {
+ if (selected) {
+ selectedItems.add(picture.getPath());
+ }
+ picture.setSelected(selected);
+ }
+ album.setSelected(false);
+
+ // Notify pictures dataset changed
+ mPictureAdapter.notifyDataSetChanged();
+ updateAlbumInfo(mDstView, album);
+
+ mSelectedAlbums.addAll(album.getSelectedItems());
+ Preferences.Media.setSelectedMedia(getActivity(), mSelectedAlbums);
+ mSelectionChanged = true;
+ }
+
+ /**
+ * Method that removes the reference to all the items and itself
+ *
+ * @param ref The album
+ */
+ private void removeAlbumItems(Album ref) {
+ Iterator<String> it = mSelectedAlbums.iterator();
+ while (it.hasNext()) {
+ String item = it.next();
+ String parent = new File(item).getParent();
+ if (parent.compareTo(ref.getPath()) == 0) {
+ it.remove();
+ } else if (item.compareTo(ref.getPath()) == 0) {
+ it.remove();
}
- });
- if (album.isSelected()) {
- albumInfo.setSelected(true);
}
- albumInfo.addCallBackListener(new AlbumInfo.CallbacksListener() {
+ }
+
+ /**
+ * Method that shows the album pictures while animating the view
+ *
+ * @param srcParent The source parent view
+ * @param srcView The source view
+ * @param dstParent The destination parent view
+ * @param dstView The destination view
+ */
+ void showAlbumPictures(final ViewGroup srcParent, final View srcView,
+ final ViewGroup dstParent, final View dstView) {
+
+ // Hide the source view
+ srcView.setAlpha(0.0f);
+
+ // Animation from bottom to top
+ ObjectAnimator anim1 = ObjectAnimator.ofFloat(dstView, "translationY",
+ srcView.getY(), srcParent.getPaddingTop());
+ anim1.setDuration(mPicturesAnimDurationIn);
+ anim1.setInterpolator(new AccelerateDecelerateInterpolator());
+ anim1.addListener(new AnimatorListener() {
@Override
- public void onAlbumSelected(Album ref) {
- // Remove all pictures of the album and add the album reference
- removeAlbumItems(ref);
- mSelectedAlbums.add(ref.getPath());
- ref.setSelected(true);
- albumPictures.updateView(ref, true);
-
- Preferences.Media.setSelectedMedia(getActivity(), mSelectedAlbums);
- mSelectionChanged = true;
+ public void onAnimationStart(Animator animation) {
+ // Ignore
}
@Override
- public void onAlbumDeselected(Album ref) {
- // Remove all pictures of the album
- removeAlbumItems(ref);
- ref.setSelected(false);
- albumPictures.updateView(ref, true);
-
- Preferences.Media.setSelectedMedia(getActivity(), mSelectedAlbums);
- mSelectionChanged = true;
+ public void onAnimationRepeat(Animator animation) {
+ // Ignore
}
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ // Re-layout the view in its new position
+ dstView.setOnClickListener(ChoosePicturesFragment.this);
+
+ // And now finally show the new album pictures layout
+ // and fill it
+ mPicturesPanel.setVisibility(View.VISIBLE);
+ mHandler.sendMessage(mHandler.obtainMessage(MSG_LOAD_PICTURES, mAlbum));
+ mShowingAlbums = false;
+ }
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ // Ignore
+ }
});
+ anim1.start();
+
+ // Hide the parent view
+ AlphaAnimation anim2 = new AlphaAnimation(1.0f, 0.0f);
+ anim2.setDuration(mPicturesAnimDurationIn);
+ anim2.setFillAfter(true);
+ anim2.setZAdjustment(Animation.ZORDER_BOTTOM);
+ anim2.setInterpolator(new AccelerateDecelerateInterpolator());
+ srcParent.setEnabled(false);
+ srcParent.startAnimation(anim2);
+
+ // Save the references
+ mSrcParent = srcParent;
+ mSrcView = srcView;
+ mDstParent = dstParent;
+ mDstView = dstView;
+ }
+
+ /**
+ * Method that hides the album pictures while animating the view
+ *
+ * @param srcParent The source parent view
+ * @param srcView The source view
+ * @param dstParent The destination parent view
+ * @param dstView The destination view
+ */
+ void hideAlbumPictures(final ViewGroup srcParent, final View srcView,
+ final ViewGroup dstParent, final View dstView) {
+
+ mPicturesPanel.setVisibility(View.INVISIBLE);
+
+ // Animation from top to bottom
+ ObjectAnimator anim1 = ObjectAnimator.ofFloat(srcView, "translationY",
+ dstParent.getPaddingTop(), dstView.getY());
+ anim1.setDuration(mPicturesAnimDurationOut);
+ anim1.setInterpolator(new AccelerateDecelerateInterpolator());
+ anim1.addListener(new AnimatorListener() {
+ @Override
+ public void onAnimationStart(Animator animation) {
+ // Ignore
+ }
- // Load the album picture data
- albumPictures.updateView(album, false);
- albumPictures.addCallBackListener(new AlbumPictures.CallbacksListener() {
@Override
- public void onBackButtonClick(View v) {
- // Ignored
+ public void onAnimationRepeat(Animator animation) {
+ // Ignore
}
@Override
- public void onSelectionChanged(Album ref) {
- // Remove, add, and persist the selection
- removeAlbumItems(ref);
- mSelectedAlbums.addAll(ref.getSelectedItems());
- ref.setSelected(false);
- albumInfo.updateView(ref);
-
- Preferences.Media.setSelectedMedia(getActivity(), mSelectedAlbums);
- mSelectionChanged = true;
+ public void onAnimationEnd(Animator animation) {
+ // Remove the source view and show the destination view
+ srcParent.removeView(srcView);
+ dstView.setAlpha(1.0f);
+ dstParent.setEnabled(true);
+ unbindDrawables(mPicturesPanel);
+ srcParent.removeView(mPicturesPanel);
+
+ mShowingAlbums = true;
+ }
+
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ // Ignore
}
});
+ anim1.start();
+
+ // Hide the parent view
+ AlphaAnimation anim2 = new AlphaAnimation(0.0f, 1.0f);
+ anim2.setDuration(mPicturesAnimDurationOut);
+ anim2.setFillAfter(true);
+ anim2.setZAdjustment(Animation.ZORDER_BOTTOM);
+ anim2.setInterpolator(new AccelerateDecelerateInterpolator());
+ dstParent.startAnimation(anim2);
+ }
+
+ /**
+ * Method that updates an album info
+ *
+ * @param v The header view
+ * @param album The album data
+ */
+ void updateAlbumInfo(View v, Album album) {
+ Resources res = getActivity().getResources();
+
+ AlbumInfoView info = (AlbumInfoView)v.findViewById(R.id.album_info);
+ info.setAlbum(album);
- // Register the animation controller
- AlbumsFlip3dAnimationController controller = new AlbumsFlip3dAnimationController(albumInfo, albumPictures);
- controller.register();
- mAnimationControllers.add(controller);
+ ImageView icon = (ImageView)info.findViewById(R.id.album_thumbnail);
+ TextView name = (TextView)info.findViewById(R.id.album_name);
+ TextView items = (TextView)info.findViewById(R.id.album_items);
+ TextView selectedItems = (TextView)info.findViewById(R.id.album_selected_items);
- return albumView;
+ icon.setImageDrawable(album.getIcon());
+ name.setText(album.getName());
+
+ int size = album.getItems().size();
+ items.setText(String.format(res.getQuantityText(
+ R.plurals.album_number_of_pictures, size).toString(), Integer.valueOf(size)));
+
+ int selected = album.getSelectedItems().size();
+ String count = String.valueOf(selected);
+ if (selected > 99) {
+ count = "99+";
+ }
+ selectedItems.setText(count);
+ selectedItems.setVisibility(!album.isSelected() ? View.VISIBLE : View.INVISIBLE);
+ info.setSelected(album.isSelected());
}
/**
- * Method that checks if an item is selected
+ * Method that load all the pictures of the album
*
- * @param item The item
- * @return boolean if an item is selected
+ * @param album
*/
- /*package*/ boolean isSelectedItem(String item) {
- Iterator<String> it = mSelectedAlbums.iterator();
- while (it.hasNext()) {
- String albumPath = it.next();
- if (item.compareTo(albumPath) == 0) {
- return true;
- }
+ void loadPictures(Album album) {
+ List<Picture> items = album.getItems();
+
+ // Calculate the grid dimensions
+ Resources res = getActivity().getResources();
+ int pictureWidth = (int)res.getDimension(R.dimen.picture_size);
+ int gridWidth = mPicturesPanel.getWidth();
+ int columns = gridWidth / pictureWidth;
+ int space = (gridWidth / pictureWidth) / (columns - 1);
+ if (columns < items.size()) {
+ space = (int)res.getDimension(R.dimen.small_padding);
}
- return false;
+ mPicturesPanel.setHorizontalSpacing(space);
+ mPicturesPanel.setVerticalSpacing(space);
+ mPicturesPanel.setStretchMode(GridView.STRETCH_SPACING);
+ mPicturesPanel.setColumnWidth(pictureWidth);
+ mPicturesPanel.setNumColumns(columns);
+
+ mPictureAdapter = new AlbumPictureAdapter(getActivity(), items, mPicturesPanel);
+ mPicturesPanel.setAdapter(mPictureAdapter);
}
/**
- * Method that removes the reference to all the items and itself
+ * Method invoked when an album header was pressed
*
- * @param ref The album
+ * @param parent The parent view
+ * @param view The header view
+ * @param position The position
*/
- /*package*/ void removeAlbumItems(Album ref) {
- Iterator<String> it = mSelectedAlbums.iterator();
- while (it.hasNext()) {
- String item = it.next();
- String parent = new File(item).getParent();
- if (parent.compareTo(ref.getPath()) == 0) {
- it.remove();
- } else if (item.compareTo(ref.getPath()) == 0) {
- it.remove();
- }
+ void onHeaderPressed(AdapterView<?> parent, View view, int position) {
+ mAlbum = mAlbumAdapter.getItem(position);
+
+ // Header view
+ View header = mInflater.inflate(R.layout.album_info, null);
+ header.setTranslationY(view.getY() + parent.getPaddingTop());
+ header.setLayoutParams(new ViewGroup.LayoutParams(view.getWidth(), view.getHeight()));
+
+ // Pictures view
+ mPicturesPanel = (GridView) mInflater.inflate(R.layout.pictures_view, null);
+ if (!mPicturesPanel.isHardwareAccelerated()) {
+ mPicturesPanel.setLayerType(View.LAYER_TYPE_HARDWARE, null);
}
+ mPicturesPanel.setY(view.getHeight());
+ mPicturesPanel.setLayoutParams(new ViewGroup.LayoutParams(view.getWidth(),
+ parent.getHeight() - view.getHeight() -
+ parent.getPaddingTop() - parent.getPaddingBottom()));
+ mPicturesPanel.setVisibility(View.INVISIBLE);
+ mPicturesPanel.setOnItemClickListener(mOnItemClickListener);
+
+ // Add to the container
+ mContainer.addView(mPicturesPanel);
+ mContainer.addView(header);
+
+ // Update and display the album pictures view
+ AlbumInfoView info = (AlbumInfoView)header.findViewById(R.id.album_info);
+ info.addCallBackListener(ChoosePicturesFragment.this);
+ info.setAlbumMode(false);
+ updateAlbumInfo(header, mAlbum);
+ showAlbumPictures(parent, view, mContainer, header);
}
/**
- * {@inheritDoc}
+ * Method invoked when a picture view was pressed
+ *
+ * @param view The picture view
*/
- @Override
- public void onEndScroll() {
- doEndScroll(AMOUNT_OF_ADDED_STEPS, false);
+ void onPicturePressed(View view) {
+ PictureItemView pictureView = (PictureItemView)view.findViewById(R.id.picture);
+ if (pictureView != null) {
+ Picture picture = pictureView.getPicture();
+ removeAlbumItems(mAlbum);
+ List<String> selectedItems = mAlbum.getSelectedItems();
+ if (selectedItems.contains(picture.getPath())) {
+ selectedItems.remove(picture.getPath());
+ picture.setSelected(false);
+ } else {
+ selectedItems.add(picture.getPath());
+ picture.setSelected(true);
+ mAlbum.setSelected(false);
+ }
+
+ // Notify all the views
+ pictureView.updateView(picture, false);
+ updateAlbumInfo(mDstView, mAlbum);
+ mAlbumAdapter.notifyDataSetChanged();
+
+ // Update settings
+ mSelectedAlbums.addAll(mAlbum.getSelectedItems());
+ Preferences.Media.setSelectedMedia(getActivity(), mSelectedAlbums);
+ mSelectionChanged = true;
+ }
}
/**
- * Method that performs a scroll creating new items
+ * Method that removes all the inexistent albums and pictures
*
- * @param amount The amount of items to create
- * @param animate If the add should be animated
+ * @param data The data to filter
+ * @return Set<String> The data filtered
*/
- /*package*/ synchronized void doEndScroll(int amount, boolean animate) {
- for (int i = 0; i < amount; i++) {
- //Add to the panel of cards
- if (mAlbumViews == null || mAlbumViews.isEmpty()) {
- break;
+ private Set<String> removeObsoleteAlbumsData(Set<String> data) {
+ Set<String> validDataList = new HashSet<String>();
+ Iterator<String> it = data.iterator();
+ while (it.hasNext()) {
+ File f = new File(it.next());
+ if (f.exists()) {
+ try {
+ validDataList.add(f.getCanonicalPath());
+ } catch (IOException ioex) {
+ // Ignore
+ }
}
- mAlbumsPanel.addCard(mAlbumViews.remove(0), animate);
}
+ if (data.size() != validDataList.size()) {
+ // Obsolete entries were removed
+ data.clear();
+ data.addAll(validDataList);
+ Preferences.Media.setSelectedMedia(getActivity(), mOriginalSelectedAlbums);
+ }
+ return data;
}
}
diff --git a/src/org/cyanogenmod/wallpapers/photophase/preferences/DispositionFragment.java b/src/org/cyanogenmod/wallpapers/photophase/preferences/DispositionFragment.java
index b0204c3..7071e76 100644
--- a/src/org/cyanogenmod/wallpapers/photophase/preferences/DispositionFragment.java
+++ b/src/org/cyanogenmod/wallpapers/photophase/preferences/DispositionFragment.java
@@ -53,7 +53,7 @@ public abstract class DispositionFragment
}
};
- /*package*/ DispositionView mDispositionView;
+ DispositionView mDispositionView;
private MenuItem mDeleteMenu;
diff --git a/src/org/cyanogenmod/wallpapers/photophase/preferences/PhotoPhasePreferences.java b/src/org/cyanogenmod/wallpapers/photophase/preferences/PhotoPhasePreferences.java
index 4e8c46e..b5c0d83 100644
--- a/src/org/cyanogenmod/wallpapers/photophase/preferences/PhotoPhasePreferences.java
+++ b/src/org/cyanogenmod/wallpapers/photophase/preferences/PhotoPhasePreferences.java
@@ -47,7 +47,8 @@ public class PhotoPhasePreferences extends PreferenceActivity {
private void initTitleActionBar() {
//Configure the action bar options
getActionBar().setDisplayOptions(
- ActionBar.DISPLAY_SHOW_CUSTOM | ActionBar.DISPLAY_SHOW_HOME | ActionBar.DISPLAY_SHOW_TITLE);
+ ActionBar.DISPLAY_SHOW_CUSTOM | ActionBar.DISPLAY_SHOW_HOME |
+ ActionBar.DISPLAY_SHOW_TITLE);
getActionBar().setDisplayHomeAsUpEnabled(true);
}
diff --git a/src/org/cyanogenmod/wallpapers/photophase/preferences/PreferencesProvider.java b/src/org/cyanogenmod/wallpapers/photophase/preferences/PreferencesProvider.java
index 1bf8359..0edc8b7 100644
--- a/src/org/cyanogenmod/wallpapers/photophase/preferences/PreferencesProvider.java
+++ b/src/org/cyanogenmod/wallpapers/photophase/preferences/PreferencesProvider.java
@@ -96,7 +96,7 @@ public final class PreferencesProvider {
/**
* @hide
*/
- /*package*/ static int[] TRANSITIONS_INTERVALS;
+ static int[] TRANSITIONS_INTERVALS;
/**
* Method that loads the all the preferences of the application
@@ -350,7 +350,12 @@ public final class PreferencesProvider {
* @return Set<String> The list of albums and pictures to be displayed
*/
public static Set<String> getLastDiscorevedAlbums() {
- return getStringSet("media_last_disvored_albums", new HashSet<String>());
+ // FIXME Typo. Remove when version 1005 is obsolete and unused
+ Set<String> oldKey = getStringSet("media_last_disvored_albums", new HashSet<String>());
+ if (oldKey.size() > 0) {
+ return oldKey;
+ }
+ return getStringSet("media_last_discovered_albums", new HashSet<String>());
}
/**
@@ -364,7 +369,9 @@ public final class PreferencesProvider {
SharedPreferences preferences =
context.getSharedPreferences(PREFERENCES_FILE, Context.MODE_PRIVATE);
Editor editor = preferences.edit();
- editor.putStringSet("media_last_disvored_albums", albums);
+ // FIXME Typo. Remove when version 1005 is obsolete and unused
+ editor.remove("media_last_disvored_albums");
+ editor.putStringSet("media_last_discovered_albums", albums);
editor.commit();
reload(context);
}
diff --git a/src/org/cyanogenmod/wallpapers/photophase/tasks/AsyncPictureLoaderTask.java b/src/org/cyanogenmod/wallpapers/photophase/tasks/AsyncPictureLoaderTask.java
index bc07b17..3ea1885 100644
--- a/src/org/cyanogenmod/wallpapers/photophase/tasks/AsyncPictureLoaderTask.java
+++ b/src/org/cyanogenmod/wallpapers/photophase/tasks/AsyncPictureLoaderTask.java
@@ -32,8 +32,34 @@ import java.io.File;
*/
public class AsyncPictureLoaderTask extends AsyncTask<File, Void, Drawable> {
+ /**
+ * Notify whether the picture was loaded
+ */
+ public static abstract class OnPictureLoaded {
+ Object[] mRefs;
+
+ /**
+ * Constructor of <code>OnPictureLoaded</code>
+ *
+ * @param refs References to notify
+ */
+ public OnPictureLoaded(Object...refs) {
+ super();
+ mRefs = refs;
+ }
+
+ /**
+ * Invoked when a picture is loaded
+ *
+ * @param o The original object reference
+ * @param drawable The drawable
+ */
+ public abstract void onPictureLoaded(Object o, Drawable drawable);
+ }
+
private final Context mContext;
private final ImageView mView;
+ private final OnPictureLoaded mCallback;
/**
* Constructor of <code>AsyncPictureLoaderTask</code>
@@ -42,9 +68,21 @@ public class AsyncPictureLoaderTask extends AsyncTask<File, Void, Drawable> {
* @param v The associated view
*/
public AsyncPictureLoaderTask(Context context, ImageView v) {
+ this(context, v, null);
+ }
+
+ /**
+ * Constructor of <code>AsyncPictureLoaderTask</code>
+ *
+ * @param context The current context
+ * @param v The associated view
+ * @param callback A callback to notify when the picture was loaded
+ */
+ public AsyncPictureLoaderTask(Context context, ImageView v, OnPictureLoaded callback) {
super();
mContext = context;
mView = v;
+ mCallback = callback;
}
/**
@@ -56,7 +94,15 @@ public class AsyncPictureLoaderTask extends AsyncTask<File, Void, Drawable> {
int height = mView.getMeasuredHeight();
Bitmap bitmap = BitmapUtils.decodeBitmap(params[0], width, height);
if (bitmap != null) {
- return new BitmapDrawable(mContext.getResources(), bitmap);
+ Drawable dw = new BitmapDrawable(mContext.getResources(), bitmap);
+ if (mCallback != null) {
+ for (Object o : mCallback.mRefs) {
+ if (!isCancelled()) {
+ mCallback.onPictureLoaded(o, dw);
+ }
+ }
+ }
+ return dw;
}
return null;
}
@@ -66,6 +112,8 @@ public class AsyncPictureLoaderTask extends AsyncTask<File, Void, Drawable> {
*/
@Override
protected void onPostExecute(Drawable result) {
- mView.setImageDrawable(result);
+ if (!isCancelled()) {
+ mView.setImageDrawable(result);
+ }
}
}
diff --git a/src/org/cyanogenmod/wallpapers/photophase/widgets/AlbumInfo.java b/src/org/cyanogenmod/wallpapers/photophase/widgets/AlbumInfoView.java
index 8e335c3..3cfe4d3 100644
--- a/src/org/cyanogenmod/wallpapers/photophase/widgets/AlbumInfo.java
+++ b/src/org/cyanogenmod/wallpapers/photophase/widgets/AlbumInfoView.java
@@ -18,6 +18,8 @@ package org.cyanogenmod.wallpapers.photophase.widgets;
import android.content.Context;
import android.content.res.Resources;
+import android.graphics.drawable.Drawable;
+import android.os.AsyncTask;
import android.os.AsyncTask.Status;
import android.util.AttributeSet;
import android.view.Menu;
@@ -40,10 +42,10 @@ import java.util.ArrayList;
import java.util.List;
/**
- * A view that contains the info about an album
+ * A view that contains the view of the info of an album
*/
-public class AlbumInfo extends RelativeLayout
- implements OnClickListener, OnMenuItemClickListener {
+public class AlbumInfoView extends RelativeLayout
+ implements OnClickListener, OnMenuItemClickListener {
/**
* A convenient listener for receive events of the AlbumPictures class
@@ -63,43 +65,70 @@ public class AlbumInfo extends RelativeLayout
* @param album The album
*/
void onAlbumDeselected(Album album);
+
+ /**
+ * Invoked when an all of the picture of the album were selected
+ *
+ * @param album The album
+ */
+ void onAllPicturesSelected(Album album);
+
+ /**
+ * Invoked when an all of the picture of the album were deselected
+ *
+ * @param album The album
+ */
+ void onAllPicturesDeselected(Album album);
+ }
+
+ private class OnPictureLoaded extends AsyncPictureLoaderTask.OnPictureLoaded {
+ public OnPictureLoaded(Album album) {
+ super(new Object[]{album});
+ }
+
+ @Override
+ public void onPictureLoaded(Object o, Drawable drawable) {
+ ((Album)o).setIcon(drawable);
+ }
}
private List<CallbacksListener> mCallbacks;
- /*package*/ Album mAlbum;
+ private Album mAlbum;
- /*package*/ AsyncPictureLoaderTask mTask;
+ private AsyncPictureLoaderTask mTask;
- /*package*/ ImageView mIcon;
+ private ImageView mIcon;
private TextView mSelectedItems;
private TextView mName;
private TextView mItems;
private View mOverflowButton;
+ private boolean mAlbumMode;
+
/**
- * Constructor of <code>AlbumInfo</code>.
+ * Constructor of <code>AlbumInfoView</code>.
*
* @param context The current context
*/
- public AlbumInfo(Context context) {
+ public AlbumInfoView(Context context) {
super(context);
init();
}
/**
- * Constructor of <code>AlbumInfo</code>.
+ * Constructor of <code>AlbumInfoView</code>.
*
* @param context The current context
* @param attrs The attributes of the XML tag that is inflating the view.
*/
- public AlbumInfo(Context context, AttributeSet attrs) {
+ public AlbumInfoView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
/**
- * Constructor of <code>AlbumInfo</code>.
+ * Constructor of <code>AlbumInfoView</code>.
*
* @param context The current context
* @param attrs The attributes of the XML tag that is inflating the view.
@@ -108,7 +137,7 @@ public class AlbumInfo extends RelativeLayout
* either be an attribute resource, whose value will be retrieved
* from the current theme, or an explicit style resource.
*/
- public AlbumInfo(Context context, AttributeSet attrs, int defStyle) {
+ public AlbumInfoView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
@@ -117,7 +146,17 @@ public class AlbumInfo extends RelativeLayout
* Method that initializes the internal references
*/
private void init() {
- mCallbacks = new ArrayList<AlbumInfo.CallbacksListener>();
+ mCallbacks = new ArrayList<AlbumInfoView.CallbacksListener>();
+ mAlbumMode = true;
+ }
+
+ /**
+ * Method that set the album mode
+ *
+ * @param albumMode The album mode
+ */
+ public void setAlbumMode(boolean albumMode) {
+ this.mAlbumMode = albumMode;
}
/**
@@ -145,13 +184,6 @@ public class AlbumInfo extends RelativeLayout
protected void onAttachedToWindow() {
super.onAttachedToWindow();
- mIcon = (ImageView)findViewById(R.id.album_thumbnail);
- mSelectedItems = (TextView)findViewById(R.id.album_selected_items);
- mName = (TextView)findViewById(R.id.album_name);
- mItems = (TextView)findViewById(R.id.album_items);
- mOverflowButton = findViewById(R.id.overflow);
- mOverflowButton.setOnClickListener(this);
-
updateView(mAlbum);
}
@@ -180,7 +212,6 @@ public class AlbumInfo extends RelativeLayout
onPreparePopupMenu(popup.getMenu());
popup.setOnMenuItemClickListener(this);
popup.show();
- return;
}
}
@@ -195,6 +226,10 @@ public class AlbumInfo extends RelativeLayout
} else {
popup.findItem(R.id.mnu_deselect_album).setVisible(false);
}
+ if (mAlbumMode) {
+ popup.findItem(R.id.mnu_select_all).setVisible(false);
+ popup.findItem(R.id.mnu_deselect_all).setVisible(false);
+ }
}
/**
@@ -211,6 +246,14 @@ public class AlbumInfo extends RelativeLayout
doSelection(false);
break;
+ case R.id.mnu_select_all:
+ notifyPictureSelectionChanged(true);
+ break;
+
+ case R.id.mnu_deselect_all:
+ notifyPictureSelectionChanged(false);
+ break;
+
default:
return false;
}
@@ -226,8 +269,8 @@ public class AlbumInfo extends RelativeLayout
setSelected(selected);
mAlbum.setSelected(selected);
mAlbum.setSelectedItems(new ArrayList<String>());
- updateView(mAlbum);
notifySelectionChanged();
+ updateView(mAlbum);
}
/**
@@ -245,40 +288,80 @@ public class AlbumInfo extends RelativeLayout
}
/**
+ * Method that notifies to all the registered callbacks that the selection
+ * was changed
+ */
+ private void notifyPictureSelectionChanged(boolean selected) {
+ for (CallbacksListener callback : mCallbacks) {
+ if (selected) {
+ callback.onAllPicturesSelected(mAlbum);
+ } else {
+ callback.onAllPicturesDeselected(mAlbum);
+ }
+ }
+ }
+
+ /**
+ * Method that sets the album
+ *
+ * @param album The album
+ */
+ public void setAlbum(Album album) {
+ mAlbum = album;
+ }
+
+ /**
* Method that updates the view
*
* @param album The album data
*/
@SuppressWarnings("boxing")
public void updateView(Album album) {
- mAlbum = album;
+ // Destroy the update drawable task
+ if (mTask != null && (mTask.getStatus() == AsyncTask.Status.RUNNING ||
+ mTask.getStatus() == AsyncTask.Status.PENDING)) {
+ mTask.cancel(true);
+ }
+
+ // Retrieve the views references
+ if (mIcon == null) {
+ mIcon = (ImageView)findViewById(R.id.album_thumbnail);
+ mSelectedItems = (TextView)findViewById(R.id.album_selected_items);
+ mName = (TextView)findViewById(R.id.album_name);
+ mItems = (TextView)findViewById(R.id.album_items);
+ mOverflowButton = findViewById(R.id.overflow_button);
+ mOverflowButton.setOnClickListener(this);
+ }
- if (mAlbum != null && mIcon != null) {
+ // Update the views
+ if (album != null) {
Resources res = getContext().getResources();
- int selectedItems = mAlbum.getSelectedItems().size();
+ setAlbum(album);
+
+ int selectedItems = album.getSelectedItems().size();
String count = String.valueOf(selectedItems);
if (selectedItems > 99) {
- count += "+";
+ count = "99+";
}
mSelectedItems.setText(count);
- mSelectedItems.setVisibility(mAlbum.isSelected() ? View.INVISIBLE : View.VISIBLE);
- mName.setText(mAlbum.getName());
- int items = mAlbum.getItems().size();
+ mSelectedItems.setVisibility(album.isSelected() ? View.INVISIBLE : View.VISIBLE);
+ mName.setText(album.getName());
+ int items = album.getItems().size();
mItems.setText(String.format(res.getQuantityText(
R.plurals.album_number_of_pictures, items).toString(), items));
setSelected(album.isSelected());
- if (mTask == null) {
- post(new Runnable() {
- @Override
- public void run() {
- // Show as icon, the first picture
- mTask = new AsyncPictureLoaderTask(getContext(), mIcon);
- mTask.execute(new File(mAlbum.getItems().get(0)));
- }
- });
+ Drawable dw = album.getIcon();
+ mIcon.setImageDrawable(dw);
+ if (dw == null) {
+ mIcon.setImageDrawable(null);
+
+ // Show as icon, the first picture
+ mTask = new AsyncPictureLoaderTask(getContext(), mIcon, new OnPictureLoaded(album));
+ mTask.execute(new File(album.getItems().get(0).getPath()));
}
}
}
+
}
diff --git a/src/org/cyanogenmod/wallpapers/photophase/widgets/AlbumPictures.java b/src/org/cyanogenmod/wallpapers/photophase/widgets/AlbumPictures.java
deleted file mode 100644
index 5d0c60f..0000000
--- a/src/org/cyanogenmod/wallpapers/photophase/widgets/AlbumPictures.java
+++ /dev/null
@@ -1,345 +0,0 @@
-/*
- * Copyright (C) 2013 The CyanogenMod Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.cyanogenmod.wallpapers.photophase.widgets;
-
-import android.content.Context;
-import android.os.Handler;
-import android.util.AttributeSet;
-import android.view.LayoutInflater;
-import android.view.MenuInflater;
-import android.view.MenuItem;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.widget.LinearLayout;
-import android.widget.PopupMenu;
-import android.widget.PopupMenu.OnMenuItemClickListener;
-import android.widget.RelativeLayout;
-import android.widget.TextView;
-
-import org.cyanogenmod.wallpapers.photophase.R;
-import org.cyanogenmod.wallpapers.photophase.model.Album;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * A view that contains the pictures of an album
- */
-public class AlbumPictures extends RelativeLayout
- implements OnClickListener, OnMenuItemClickListener {
-
- private static final int SELECTION_SELECT_ALL = 1;
- private static final int SELECTION_DESELECT_ALL = 2;
- private static final int SELECTION_INVERT = 3;
-
- /**
- * A convenient listener for receive events of the AlbumPictures class
- *
- */
- public interface CallbacksListener {
- /**
- * Invoked when the user pressed the back button
- */
- void onBackButtonClick(View v);
-
- /**
- * Invoked when the selection was changed
- *
- * @param album The album
- */
- void onSelectionChanged(Album album);
- }
-
- private List<CallbacksListener> mCallbacks;
-
- private Handler mHandler;
-
- /*package*/ PicturesView mScroller;
- /*package*/ LinearLayout mHolder;
- private View mBackButton;
- private View mOverflowButton;
-
- private boolean mInitialized;
-
- /*package*/ Album mAlbum;
-
- /**
- * Constructor of <code>AlbumPictures</code>.
- *
- * @param context The current context
- */
- public AlbumPictures(Context context) {
- super(context);
- init();
- }
-
- /**
- * Constructor of <code>AlbumPictures</code>.
- *
- * @param context The current context
- * @param attrs The attributes of the XML tag that is inflating the view.
- */
- public AlbumPictures(Context context, AttributeSet attrs) {
- super(context, attrs);
- init();
- }
-
- /**
- * Constructor of <code>AlbumPictures</code>.
- *
- * @param context The current context
- * @param attrs The attributes of the XML tag that is inflating the view.
- * @param defStyle The default style to apply to this view. If 0, no style
- * will be applied (beyond what is included in the theme). This may
- * either be an attribute resource, whose value will be retrieved
- * from the current theme, or an explicit style resource.
- */
- public AlbumPictures(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- init();
- }
-
- /**
- * Method that initializes the internal references
- */
- private void init() {
- mCallbacks = new ArrayList<AlbumPictures.CallbacksListener>();
- mHandler = new Handler();
- mInitialized = false;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- protected void onAttachedToWindow() {
- super.onAttachedToWindow();
- mScroller = (PicturesView)findViewById(R.id.album_pictures_scroller);
- mHolder = (LinearLayout)findViewById(R.id.album_pictures_holder);
- mBackButton = findViewById(R.id.back);
- mBackButton.setOnClickListener(this);
- mOverflowButton = findViewById(R.id.overflow);
- mOverflowButton.setOnClickListener(this);
- TextView title = (TextView)findViewById(R.id.album_pictures_title);
- title.setText(mAlbum.getName());
-
- updateView(mAlbum, false);
- }
-
- /**
- * Method that adds the class that will be listen for events of this class
- *
- * @param callback The callback class
- */
- public void addCallBackListener(CallbacksListener callback) {
- this.mCallbacks.add(callback);
- }
-
- /**
- * Method that removes the class from the current callbacks
- *
- * @param callback The callback class
- */
- public void removeCallBackListener(CallbacksListener callback) {
- this.mCallbacks.remove(callback);
- }
-
- /**
- * Method that set the data of the view
- *
- * @param album The album data
- * @param recreate If the view should be recreated
- */
- public void updateView(Album album, boolean recreate) {
- mAlbum = album;
- recreateView(false);
- }
-
- /**
- * Method that recreates the the view
- *
- * @param propagateShow If should propagate the show event
- */
- private void recreateView(final boolean propagateShow) {
- if (mHolder != null) {
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- int pictures = mHolder.getChildCount();
- if (pictures != mAlbum.getItems().size()) {
- // Recreate the pictures
- final LayoutInflater inflater = (LayoutInflater) getContext().
- getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- mScroller.cancelTasks();
- mHolder.removeAllViews();
- for (final String picture : mAlbum.getItems()) {
- View v = createPicture(inflater, picture, isPictureSelected(picture));
- mHolder.addView(v);
- }
- } else {
- int i = 0;
- for (final String picture : mAlbum.getItems()) {
- View v = mHolder.getChildAt(i);
- v.setSelected(isPictureSelected(picture));
- i++;
- }
- }
- if (propagateShow) {
- mScroller.onShow();
- }
- }
- });
- }
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void onClick(View v) {
- // Check which is the view pressed
- if (v.equals(mBackButton)) {
- for (CallbacksListener callback : mCallbacks) {
- callback.onBackButtonClick(v);
- }
- return;
- }
- if (v.equals(mOverflowButton)) {
- PopupMenu popup = new PopupMenu(getContext(), v);
- MenuInflater inflater = popup.getMenuInflater();
- inflater.inflate(R.menu.pictures_actions, popup.getMenu());
- popup.setOnMenuItemClickListener(this);
- popup.show();
- return;
- }
-
- // A picture view
- v.setSelected(!v.isSelected());
- notifySelectionChanged();
- }
-
- /**
- * Method that notifies to all the registered callbacks that the selection
- * was changed
- */
- private void notifySelectionChanged() {
- List<String> selection = new ArrayList<String>();
- int count = mHolder.getChildCount();
- for (int i = 0; i < count; i++) {
- View v = mHolder.getChildAt(i);
- if (v.isSelected()) {
- selection.add((String)v.getTag());
- }
- }
- mAlbum.setSelectedItems(selection);
- mAlbum.setSelected(false);
-
- for (CallbacksListener callback : mCallbacks) {
- callback.onSelectionChanged(mAlbum);
- }
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public boolean onMenuItemClick(MenuItem item) {
- switch (item.getItemId()) {
- case R.id.mnu_select_all:
- doSelection(SELECTION_SELECT_ALL);
- break;
-
- case R.id.mnu_deselect_all:
- doSelection(SELECTION_DESELECT_ALL);
- break;
-
- case R.id.mnu_invert_selection:
- doSelection(SELECTION_INVERT);
- break;
-
- default:
- return false;
- }
- return true;
- }
-
- /**
- * Operate over the selection of the pictures of this album.
- *
- * @param action Takes the next values:
- * <ul>
- * <li>SELECTION_SELECT_ALL: select all</li>
- * <li>SELECTION_DESELECT_ALL: deselect all</li>
- * <li>SELECTION_INVERT: invert selection</li>
- * </ul>
- */
- private void doSelection(int action) {
- int count = mHolder.getChildCount();
- for (int i = 0; i < count; i++) {
- View v = mHolder.getChildAt(i);
-
- boolean selected = true;
- if (action == SELECTION_DESELECT_ALL) {
- selected = false;
- } else if (action == SELECTION_INVERT) {
- selected = !v.isSelected();
- }
- v.setSelected(selected);
- }
- notifySelectionChanged();
- }
-
- /**
- * Method invoked when the view is displayed
- */
- public void onShow() {
- if (!mInitialized) {
- mInitialized = true;
- recreateView(true);
- }
- }
-
- /**
- * Method that creates a new picture view
- *
- * @param inflater The inflater of the parent view
- * @param picture The path of the picture
- * @param selected If the picture is selected
- */
- /*package*/ View createPicture(LayoutInflater inflater, String picture, boolean selected) {
- final View v = inflater.inflate(R.layout.picture_item, mHolder, false);
- v.setTag(picture);
- v.setSelected(selected);
- v.setOnClickListener(this);
- return v;
- }
-
- /**
- * Method that check if a picture is selected
- *
- * @param picture The picture to check
- * @return boolean whether the picture is selected
- */
- /*package*/ boolean isPictureSelected(String picture) {
- for (String item : mAlbum.getSelectedItems()) {
- if (item.compareTo(picture) == 0) {
- return true;
- }
- }
- return false;
- }
-}
diff --git a/src/org/cyanogenmod/wallpapers/photophase/widgets/CardLayout.java b/src/org/cyanogenmod/wallpapers/photophase/widgets/CardLayout.java
deleted file mode 100644
index e1953cd..0000000
--- a/src/org/cyanogenmod/wallpapers/photophase/widgets/CardLayout.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright (C) 2013 The CyanogenMod Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.cyanogenmod.wallpapers.photophase.widgets;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.view.View;
-import android.view.animation.AnimationUtils;
-import android.widget.LinearLayout;
-
-import org.cyanogenmod.wallpapers.photophase.R;
-
-/**
- * A "Google Now Card Layout" like layout
- */
-public class CardLayout extends LinearLayout {
-
- boolean inverted = false;
-
- /**
- * Constructor of <code>CardLayout</code>.
- *
- * @param context The current context
- */
- public CardLayout(Context context) {
- super(context);
- }
-
- /**
- * Constructor of <code>CardLayout</code>.
- *
- * @param context The current context
- * @param attrs The attributes of the XML tag that is inflating the view.
- */
- public CardLayout(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- /**
- * Constructor of <code>CardLayout</code>.
- *
- * @param context The current context
- * @param attrs The attributes of the XML tag that is inflating the view.
- * @param defStyle The default style to apply to this view. If 0, no style
- * will be applied (beyond what is included in the theme). This may
- * either be an attribute resource, whose value will be retrieved
- * from the current theme, or an explicit style resource.
- */
- public CardLayout(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- }
-
- /**
- * Add a new card to the layout
- *
- * @param card The card view to add
- * @param animate If the add should be animated
- */
- public void addCard(final View card, final boolean animate) {
- post(new Runnable() {
- @Override
- public void run() {
- addView(card);
- if (animate) {
- if (inverted) {
- card.startAnimation(AnimationUtils.loadAnimation(
- getContext(), R.anim.cards_animation_up_right));
- } else {
- card.startAnimation(AnimationUtils.loadAnimation(
- getContext(), R.anim.cards_animation_up_left));
- }
- inverted = !inverted;
- }
- }
- });
- }
-}
diff --git a/src/org/cyanogenmod/wallpapers/photophase/widgets/DispositionView.java b/src/org/cyanogenmod/wallpapers/photophase/widgets/DispositionView.java
index 22d00a6..0bc462f 100644
--- a/src/org/cyanogenmod/wallpapers/photophase/widgets/DispositionView.java
+++ b/src/org/cyanogenmod/wallpapers/photophase/widgets/DispositionView.java
@@ -74,7 +74,7 @@ public class DispositionView extends RelativeLayout implements OnLongClickListen
private int mCols;
private int mRows;
- /*package*/ View mTarget;
+ View mTarget;
private ResizeFrame mResizeFrame;
private int mInternalPadding;
private Rect mOldResizeFrameLocation;
@@ -323,7 +323,7 @@ public class DispositionView extends RelativeLayout implements OnLongClickListen
*
* @param target The disposition target
*/
- /*package*/ void finishDeleteAnimation(Disposition target) {
+ void finishDeleteAnimation(Disposition target) {
removeView(mTarget);
mDispositions.remove(target);
Collections.sort(mDispositions);
@@ -514,7 +514,7 @@ public class DispositionView extends RelativeLayout implements OnLongClickListen
*
* @return The target view
*/
- /*package*/ View findTargetFromResizeFrame() {
+ View findTargetFromResizeFrame() {
int count = getChildCount();
for (int i = 0; i < count; i++) {
View v = getChildAt(i);
@@ -552,7 +552,7 @@ public class DispositionView extends RelativeLayout implements OnLongClickListen
*
* @param v The target view
*/
- /*package*/ boolean selectTarget(View v) {
+ boolean selectTarget(View v) {
//Do not do long click if we do not have a target
if (mTarget != null && v.equals(mTarget)) return false;
diff --git a/src/org/cyanogenmod/wallpapers/photophase/widgets/PictureItemView.java b/src/org/cyanogenmod/wallpapers/photophase/widgets/PictureItemView.java
new file mode 100644
index 0000000..aac7e24
--- /dev/null
+++ b/src/org/cyanogenmod/wallpapers/photophase/widgets/PictureItemView.java
@@ -0,0 +1,204 @@
+/*
+ * Copyright (C) 2013 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.cyanogenmod.wallpapers.photophase.widgets;
+
+import android.content.Context;
+import android.os.AsyncTask;
+import android.os.AsyncTask.Status;
+import android.util.AttributeSet;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+
+import org.cyanogenmod.wallpapers.photophase.R;
+import org.cyanogenmod.wallpapers.photophase.model.Picture;
+import org.cyanogenmod.wallpapers.photophase.tasks.AsyncPictureLoaderTask;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A view that contains the view of the picture of an abbum
+ */
+public class PictureItemView extends FrameLayout {
+
+ /**
+ * A convenient listener for receive events of the PictureItemView class
+ *
+ */
+ public interface CallbacksListener {
+ /**
+ * Invoked when an Picture was selected
+ *
+ * @param Picture The Picture
+ */
+ void onPictureSelected(Picture Picture);
+
+ /**
+ * Invoked when an Picture was deselected
+ *
+ * @param Picture The Picture
+ */
+ void onPictureDeselected(Picture Picture);
+ }
+
+ private List<CallbacksListener> mCallbacks;
+
+ private Picture mPicture;
+
+ private AsyncPictureLoaderTask mTask;
+
+ private ImageView mIcon;
+
+ /**
+ * Constructor of <code>PictureItemView</code>.
+ *
+ * @param context The current context
+ */
+ public PictureItemView(Context context) {
+ super(context);
+ init();
+ }
+
+ /**
+ * Constructor of <code>PictureItemView</code>.
+ *
+ * @param context The current context
+ * @param attrs The attributes of the XML tag that is inflating the view.
+ */
+ public PictureItemView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ init();
+ }
+
+ /**
+ * Constructor of <code>PictureItemView</code>.
+ *
+ * @param context The current context
+ * @param attrs The attributes of the XML tag that is inflating the view.
+ * @param defStyle The default style to apply to this view. If 0, no style
+ * will be applied (beyond what is included in the theme). This may
+ * either be an attribute resource, whose value will be retrieved
+ * from the current theme, or an explicit style resource.
+ */
+ public PictureItemView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ init();
+ }
+
+ /**
+ * Method that initializes the internal references
+ */
+ private void init() {
+ mCallbacks = new ArrayList<PictureItemView.CallbacksListener>();
+ }
+
+ /**
+ * Method that adds the class that will be listen for events of this class
+ *
+ * @param callback The callback class
+ */
+ public void addCallBackListener(CallbacksListener callback) {
+ this.mCallbacks.add(callback);
+ }
+
+ /**
+ * Method that removes the class from the current callbacks
+ *
+ * @param callback The callback class
+ */
+ public void removeCallBackListener(CallbacksListener callback) {
+ this.mCallbacks.remove(callback);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected void onAttachedToWindow() {
+ super.onAttachedToWindow();
+
+ updateView(mPicture, true);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected void onDetachedFromWindow() {
+ super.onDetachedFromWindow();
+
+ // Cancel pending tasks
+ if (mTask != null && mTask.getStatus().compareTo(Status.PENDING) == 0) {
+ mTask.cancel(true);
+ }
+ }
+
+ /**
+ * Method that returns the picture
+ *
+ * @return Picture The picture
+ */
+ public Picture getPicture() {
+ return mPicture;
+ }
+
+ /**
+ * Method that sets the picture
+ *
+ * @param picture The picture
+ */
+ public void setPicture(Picture picture) {
+ mPicture = picture;
+ }
+
+ /**
+ * Method that updates the view
+ *
+ * @param picture The picture data
+ */
+ public void updateView(Picture picture, boolean refreshIcon) {
+ // Destroy the update drawable task
+ if (mTask != null && (mTask.getStatus() == AsyncTask.Status.RUNNING ||
+ mTask.getStatus() == AsyncTask.Status.PENDING)) {
+ mTask.cancel(true);
+ }
+
+ // Retrieve the views references
+ if (mIcon == null) {
+ mIcon = (ImageView)findViewById(R.id.picture_thumbnail);
+ }
+
+ // Update the views
+ if (picture != null) {
+ setPicture(picture);
+
+ setSelected(picture.isSelected());
+
+ // Do no try to cache the images (this generates a lot of memory an we want
+ // to have a low memory footprint)
+ if (refreshIcon) {
+ mIcon.setImageDrawable(null);
+
+ // Show as icon, the first picture
+ mTask = new AsyncPictureLoaderTask(getContext(), mIcon);
+ mTask.execute(new File(picture.getPath()));
+ }
+ }
+ }
+
+}
diff --git a/src/org/cyanogenmod/wallpapers/photophase/widgets/PicturesView.java b/src/org/cyanogenmod/wallpapers/photophase/widgets/PicturesView.java
deleted file mode 100644
index 0744751..0000000
--- a/src/org/cyanogenmod/wallpapers/photophase/widgets/PicturesView.java
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * Copyright (C) 2013 The CyanogenMod Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.cyanogenmod.wallpapers.photophase.widgets;
-
-import android.content.Context;
-import android.graphics.Rect;
-import android.os.AsyncTask.Status;
-import android.os.Handler;
-import android.util.AttributeSet;
-import android.view.ViewGroup;
-import android.widget.HorizontalScrollView;
-import android.widget.ImageView;
-
-import org.cyanogenmod.wallpapers.photophase.R;
-import org.cyanogenmod.wallpapers.photophase.tasks.AsyncPictureLoaderTask;
-
-import java.io.File;
-import java.util.HashMap;
-import java.util.Iterator;
-
-/**
- * A view that contains all the pictures of an album
- */
-public class PicturesView extends HorizontalScrollView {
-
- private HashMap<File, AsyncPictureLoaderTask> mTasks;
- private Handler mHandler;
-
- /**
- * Constructor of <code>PicturesView</code>.
- *
- * @param context The current context
- */
- public PicturesView(Context context) {
- super(context);
- init();
- }
-
- /**
- * Constructor of <code>PicturesView</code>.
- *
- * @param context The current context
- * @param attrs The attributes of the XML tag that is inflating the view.
- */
- public PicturesView(Context context, AttributeSet attrs) {
- super(context, attrs);
- init();
- }
-
- /**
- * Constructor of <code>PicturesView</code>.
- *
- * @param context The current context
- * @param attrs The attributes of the XML tag that is inflating the view.
- * @param defStyle The default style to apply to this view. If 0, no style
- * will be applied (beyond what is included in the theme). This may
- * either be an attribute resource, whose value will be retrieved
- * from the current theme, or an explicit style resource.
- */
- public PicturesView(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- init();
- }
-
- /**
- * Method that initializes the structures of this class
- */
- private void init() {
- mTasks = new HashMap<File, AsyncPictureLoaderTask>();
- mHandler = new Handler();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- protected void onDetachedFromWindow() {
- super.onDetachedFromWindow();
- cancelTasks();
- }
-
- /**
- * Method that removes all tasks
- */
- public void cancelTasks() {
- // Cancel all the pending task
- Iterator<AsyncPictureLoaderTask> it = mTasks.values().iterator();
- while (it.hasNext()) {
- AsyncPictureLoaderTask task = it.next();
- if (task.getStatus().compareTo(Status.PENDING) == 0) {
- task.cancel(true);
- }
- }
- mTasks.clear();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- protected void onScrollChanged(int l, int t, int oldl, int oldt) {
- super.onScrollChanged(l, t, oldl, oldt);
- // Estimated velocity (in some moment we must obtain some scrolling with an estimated
- // velocity below of 3)
- int velocity = Math.abs(l - oldl);
- if (velocity <= 3) {
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- requestLoadOfPendingPictures();
- }
- });
- }
- }
-
- /**
- * Method invoked when the view is displayed
- */
- public void onShow() {
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- requestLoadOfPendingPictures();
- }
- });
- }
-
- /**
- * Method that load in background all visible and pending pictures
- */
- /*package*/ void requestLoadOfPendingPictures() {
- // Get the visible rect
- Rect r = new Rect();
- getHitRect(r);
-
- // Get all the image views
- ViewGroup vg = (ViewGroup)getChildAt(0);
- int count = vg.getChildCount();
- for (int i = 0; i < count; i++) {
- ViewGroup picView = (ViewGroup)vg.getChildAt(i);
- File image = new File((String)picView.getTag());
- if (picView.getLocalVisibleRect(r) && !mTasks.containsKey(image)) {
- ImageView iv = (ImageView)picView.findViewById(R.id.picture_thumbnail);
- AsyncPictureLoaderTask task = new AsyncPictureLoaderTask(getContext(), iv);
- task.execute(image);
- mTasks.put(image, task);
- }
- }
- }
-}
diff --git a/src/org/cyanogenmod/wallpapers/photophase/widgets/VerticalEndlessScroller.java b/src/org/cyanogenmod/wallpapers/photophase/widgets/VerticalEndlessScroller.java
deleted file mode 100644
index 67a1f17..0000000
--- a/src/org/cyanogenmod/wallpapers/photophase/widgets/VerticalEndlessScroller.java
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright (C) 2013 The CyanogenMod Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.cyanogenmod.wallpapers.photophase.widgets;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.view.View;
-import android.widget.ScrollView;
-
-/**
- * A scroll view that notifies the end of the scroll to create new views
- * dynamically.
- */
-public class VerticalEndlessScroller extends ScrollView {
-
- /**
- * Interface to communicate end-scroll events
- */
- public interface OnEndScrollListener {
- /**
- * Called when the scroll reachs the end of the scroll
- */
- void onEndScroll();
- }
-
- private OnEndScrollListener mCallback;
- private int mEndPadding = 0;
- private boolean mSwitch = false;
-
- /**
- * Constructor of <code>VerticalEndlessScroller</code>.
- *
- * @param context The current context
- */
- public VerticalEndlessScroller(Context context) {
- super(context);
- }
-
- /**
- * Constructor of <code>VerticalEndlessScroller</code>.
- *
- * @param context The current context
- * @param attrs The attributes of the XML tag that is inflating the view.
- */
- public VerticalEndlessScroller(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- /**
- * Constructor of <code>VerticalEndlessScroller</code>.
- *
- * @param context The current context
- * @param attrs The attributes of the XML tag that is inflating the view.
- * @param defStyle The default style to apply to this view. If 0, no style
- * will be applied (beyond what is included in the theme). This may
- * either be an attribute resource, whose value will be retrieved
- * from the current theme, or an explicit style resource.
- */
- public VerticalEndlessScroller(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- }
-
- /**
- * Method that set the callback for notify end-scroll events
- *
- * @param callback The callback
- */
- public void setCallback(OnEndScrollListener callback) {
- mCallback = callback;
- }
-
- /**
- * Method that set the end padding for fired the event
- *
- * @param endPadding The end padding
- */
- public void setEndPadding(int endPadding) {
- this.mEndPadding = endPadding;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- protected void onScrollChanged(int l, int t, int oldl, int oldt) {
- // We take the last child in the scrollview
- View view = getChildAt(getChildCount() - 1);
- int diff = (view.getBottom() - (getHeight() + getScrollY()));
- if ((!mSwitch && diff <= mEndPadding)) {
- if (mCallback != null) {
- mCallback.onEndScroll();
- mSwitch = true;
- return;
- }
- } else if (diff > mEndPadding) {
- mSwitch = false;
- }
- }
-
-}