aboutsummaryrefslogtreecommitdiffstats
path: root/src/org/cyanogenmod/wallpapers/photophase/widgets
diff options
context:
space:
mode:
authorjruesga <jorge@ruesga.com>2013-07-01 02:42:54 +0200
committerjruesga <jorge@ruesga.com>2013-07-01 02:42:54 +0200
commitf29d68d929061ccbb982019c5020be721bbef862 (patch)
tree24ce41fb0dd7f942ca9dbe956fe93fe836da66c2 /src/org/cyanogenmod/wallpapers/photophase/widgets
downloadandroid_packages_wallpapers_PhotoPhase-f29d68d929061ccbb982019c5020be721bbef862.tar.gz
android_packages_wallpapers_PhotoPhase-f29d68d929061ccbb982019c5020be721bbef862.tar.bz2
android_packages_wallpapers_PhotoPhase-f29d68d929061ccbb982019c5020be721bbef862.zip
Initial commit
Signed-off-by: jruesga <jorge@ruesga.com>
Diffstat (limited to 'src/org/cyanogenmod/wallpapers/photophase/widgets')
-rw-r--r--src/org/cyanogenmod/wallpapers/photophase/widgets/AlbumInfo.java281
-rw-r--r--src/org/cyanogenmod/wallpapers/photophase/widgets/AlbumPictures.java308
-rw-r--r--src/org/cyanogenmod/wallpapers/photophase/widgets/CardLayout.java92
-rw-r--r--src/org/cyanogenmod/wallpapers/photophase/widgets/ColorPickerPreference.java253
-rw-r--r--src/org/cyanogenmod/wallpapers/photophase/widgets/PicturesView.java139
5 files changed, 1073 insertions, 0 deletions
diff --git a/src/org/cyanogenmod/wallpapers/photophase/widgets/AlbumInfo.java b/src/org/cyanogenmod/wallpapers/photophase/widgets/AlbumInfo.java
new file mode 100644
index 0000000..0711297
--- /dev/null
+++ b/src/org/cyanogenmod/wallpapers/photophase/widgets/AlbumInfo.java
@@ -0,0 +1,281 @@
+/*
+ * 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.content.res.Resources;
+import android.os.AsyncTask.Status;
+import android.util.AttributeSet;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.ImageView;
+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 org.cyanogenmod.wallpapers.photophase.tasks.AsyncPictureLoaderTask;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A view that contains the info about an album
+ */
+public class AlbumInfo extends RelativeLayout
+ implements OnClickListener, OnMenuItemClickListener {
+
+ /**
+ * A convenient listener for receive events of the AlbumPictures class
+ *
+ */
+ public interface CallbacksListener {
+ /**
+ * Invoked when an album was selected
+ *
+ * @param album The album
+ */
+ void onAlbumSelected(Album album);
+
+ /**
+ * Invoked when an album was deselected
+ *
+ * @param album The album
+ */
+ void onAlbumDeselected(Album album);
+ }
+
+ private List<CallbacksListener> mCallbacks;
+
+ /*package*/ Album mAlbum;
+
+ /*package*/ AsyncPictureLoaderTask mTask;
+
+ /*package*/ ImageView mIcon;
+ private TextView mSelectedItems;
+ private TextView mName;
+ private TextView mItems;
+ private View mOverflowButton;
+
+ /**
+ * Constructor of <code>AlbumInfo</code>.
+ *
+ * @param context The current context
+ */
+ public AlbumInfo(Context context) {
+ super(context);
+ init();
+ }
+
+ /**
+ * Constructor of <code>AlbumInfo</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) {
+ super(context, attrs);
+ init();
+ }
+
+ /**
+ * Constructor of <code>AlbumInfo</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 AlbumInfo(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ init();
+ }
+
+ /**
+ * Method that initializes the internal references
+ */
+ private void init() {
+ mCallbacks = new ArrayList<AlbumInfo.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();
+
+ 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);
+
+ 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)));
+ }
+ });
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected void onDetachedFromWindow() {
+ super.onDetachedFromWindow();
+
+ // Cancel pending tasks
+ if (mTask.getStatus().compareTo(Status.PENDING) == 0) {
+ mTask.cancel(true);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void onClick(View v) {
+ if (v.equals(mOverflowButton)) {
+ PopupMenu popup = new PopupMenu(getContext(), v);
+ MenuInflater inflater = popup.getMenuInflater();
+ inflater.inflate(R.menu.album_actions, popup.getMenu());
+ onPreparePopupMenu(popup.getMenu());
+ popup.setOnMenuItemClickListener(this);
+ popup.show();
+ return;
+ }
+ }
+
+ /**
+ * Method called prior to show the popup menu
+ *
+ * @param popup The popup menu
+ */
+ public void onPreparePopupMenu(Menu popup) {
+ if (isSelected()) {
+ popup.findItem(R.id.mnu_select_album).setVisible(false);
+ } else {
+ popup.findItem(R.id.mnu_deselect_album).setVisible(false);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean onMenuItemClick(MenuItem item) {
+ switch (item.getItemId()) {
+ case R.id.mnu_select_album:
+ doSelection(true);
+ break;
+
+ case R.id.mnu_deselect_album:
+ doSelection(false);
+ break;
+
+ default:
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Method that select/deselect the album
+ *
+ * @param selected whether the album is selected
+ */
+ public void doSelection(boolean selected) {
+ setSelected(selected);
+ mAlbum.setSelected(selected);
+ mAlbum.setSelectedItems(new ArrayList<String>());
+ updateView(mAlbum);
+ notifySelectionChanged();
+ }
+
+ /**
+ * Method that notifies to all the registered callbacks that the selection
+ * was changed
+ */
+ private void notifySelectionChanged() {
+ for (CallbacksListener callback : mCallbacks) {
+ if (mAlbum.isSelected()) {
+ callback.onAlbumSelected(mAlbum);
+ } else {
+ callback.onAlbumDeselected(mAlbum);
+ }
+ }
+ }
+
+ /**
+ * Method that updates the view
+ *
+ * @param album The album data
+ */
+ @SuppressWarnings("boxing")
+ public void updateView(Album album) {
+ mAlbum = album;
+
+ if (mIcon != null) {
+ Resources res = getContext().getResources();
+
+ String count = String.valueOf(mAlbum.getSelectedItems().size());
+ if (mAlbum.getItems().size() > 99) {
+ count += "+";
+ }
+ mSelectedItems.setText(count);
+ mSelectedItems.setVisibility(mAlbum.isSelected() ? View.INVISIBLE : View.VISIBLE);
+ mName.setText(mAlbum.getName());
+ int items = mAlbum.getItems().size();
+ mItems.setText(String.format(res.getQuantityText(
+ R.plurals.album_number_of_pictures, items).toString(), items));
+ setSelected(album.isSelected());
+ }
+ }
+}
diff --git a/src/org/cyanogenmod/wallpapers/photophase/widgets/AlbumPictures.java b/src/org/cyanogenmod/wallpapers/photophase/widgets/AlbumPictures.java
new file mode 100644
index 0000000..324fe15
--- /dev/null
+++ b/src/org/cyanogenmod/wallpapers/photophase/widgets/AlbumPictures.java
@@ -0,0 +1,308 @@
+/*
+ * 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.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 PicturesView mScroller;
+ private LinearLayout mHolder;
+ private View mBackButton;
+ private View mOverflowButton;
+
+ private 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>();
+ }
+
+ /**
+ * {@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);
+ }
+
+ /**
+ * 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
+ */
+ public void updateView(Album album) {
+ mAlbum = album;
+
+ if (mHolder != null) {
+ // Create 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);
+ }
+ }
+ }
+
+ /**
+ * {@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() {
+ mScroller.requestLoadOfPendingPictures();
+ }
+
+ /**
+ * 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
+ */
+ private 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
+ */
+ private 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
new file mode 100644
index 0000000..386ffbe
--- /dev/null
+++ b/src/org/cyanogenmod/wallpapers/photophase/widgets/CardLayout.java
@@ -0,0 +1,92 @@
+/*
+ * 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);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected void onAttachedToWindow() {
+ super.onAttachedToWindow();
+ if (isHardwareAccelerated()) {
+ setLayerType(View.LAYER_TYPE_HARDWARE, null);
+ }
+ }
+
+ /**
+ * Add a new card to the layout
+ *
+ * @param card The card view to add
+ */
+ public void addCard(final View card) {
+ post(new Runnable() {
+ @Override
+ public void run() {
+ addView(card);
+ card.startAnimation(AnimationUtils.loadAnimation(getContext(), R.anim.cards_animation));
+ }
+ });
+ }
+}
diff --git a/src/org/cyanogenmod/wallpapers/photophase/widgets/ColorPickerPreference.java b/src/org/cyanogenmod/wallpapers/photophase/widgets/ColorPickerPreference.java
new file mode 100644
index 0000000..42e701d
--- /dev/null
+++ b/src/org/cyanogenmod/wallpapers/photophase/widgets/ColorPickerPreference.java
@@ -0,0 +1,253 @@
+/*
+ * 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 afzkl.development.mColorPicker.views.ColorDialogView;
+import afzkl.development.mColorPicker.views.ColorPanelView;
+
+import android.app.AlertDialog.Builder;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.DialogInterface.OnClickListener;
+import android.content.SharedPreferences;
+import android.content.res.TypedArray;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.preference.DialogPreference;
+import android.preference.Preference;
+import android.util.AttributeSet;
+import android.view.View;
+
+import org.cyanogenmod.wallpapers.photophase.R;
+
+/**
+ * A {@link Preference} that allow to select/pick a color in a new window dialog.
+ */
+public class ColorPickerPreference extends DialogPreference {
+
+ private ColorPanelView mColorPicker;
+ private int mColor;
+
+ private ColorDialogView mColorDlg;
+
+ /**
+ * Constructor of <code>ColorPickerPreference</code>
+ *
+ * @param context The current context
+ */
+ public ColorPickerPreference(Context context) {
+ this(context, null);
+ }
+
+ /**
+ * Constructor of <code>ColorPickerPreference</code>
+ *
+ * @param context The current context
+ * @param attrs The attributes of the XML tag that is inflating the preference.
+ */
+ public ColorPickerPreference(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ setWidgetLayoutResource(R.layout.color_picker_pref_item);
+ }
+
+ /**
+ * Returns the color of the picker.
+ *
+ * @return The color of the picker.
+ */
+ public int getColor() {
+ return this.mColor;
+ }
+
+ /**
+ * Sets the color of the picker and saves it to the {@link SharedPreferences}.
+ *
+ * @param color The new color.
+ */
+ public void setColor(int color) {
+ // Always persist/notify the first time; don't assume the field's default of false.
+ final boolean changed = this.mColor != color;
+ if (changed) {
+ this.mColor = color;
+ // when called from onSetInitialValue the view is still not set
+ if (this.mColorPicker != null) {
+ this.mColorPicker.setColor(color);
+ }
+ persistInt(color);
+ if (changed) {
+ notifyDependencyChange(shouldDisableDependents());
+ notifyChanged();
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected Object onGetDefaultValue(TypedArray a, int index) {
+ return Integer.valueOf(a.getColor(index, 0));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected void onSetInitialValue(boolean restoreValue, Object defaultValue) {
+ setColor(restoreValue ? getPersistedInt(0) : ((Integer)defaultValue).intValue());
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected void onPrepareDialogBuilder(Builder builder) {
+ super.onPrepareDialogBuilder(builder);
+
+ // Configure the dialog
+ this.mColorDlg = new ColorDialogView(getContext());
+ this.mColorDlg.setColor(this.mColor);
+ this.mColorDlg.showAlphaSlider(true);
+ this.mColorDlg.setAlphaSliderText(
+ getContext().getString(R.string.color_picker_alpha_slider_text));
+ this.mColorDlg.setCurrentColorText(
+ getContext().getString(R.string.color_picker_current_text));
+ this.mColorDlg.setNewColorText(
+ getContext().getString(R.string.color_picker_new_text));
+ this.mColorDlg.setColorLabelText(
+ getContext().getString(R.string.color_picker_color));
+ builder.setView(this.mColorDlg);
+
+ // The color is selected by the user and confirmed by clicking ok
+ builder.setPositiveButton(android.R.string.ok, new OnClickListener() {
+ @Override
+ @SuppressWarnings("synthetic-access")
+ public void onClick(DialogInterface dialog, int which) {
+ int color = ColorPickerPreference.this.mColorDlg.getColor();
+ if (callChangeListener(Integer.valueOf(color))) {
+ setColor(color);
+ }
+ dialog.dismiss();
+ }
+ });
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected void onBindView(View view) {
+ super.onBindView(view);
+ View v = view.findViewById(R.id.color_picker);
+ if (v != null && v instanceof ColorPanelView) {
+ this.mColorPicker = (ColorPanelView)v;
+ this.mColorPicker.setColor(this.mColor);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected Parcelable onSaveInstanceState() {
+ final Parcelable superState = super.onSaveInstanceState();
+ if (isPersistent()) {
+ // No need to save instance state since it's persistent
+ return superState;
+ }
+
+ final SavedState myState = new SavedState(superState);
+ myState.color = getColor();
+ return myState;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected void onRestoreInstanceState(Parcelable state) {
+ if (state == null || !state.getClass().equals(SavedState.class)) {
+ // Didn't save state for us in onSaveInstanceState
+ super.onRestoreInstanceState(state);
+ return;
+ }
+
+ SavedState myState = (SavedState) state;
+ super.onRestoreInstanceState(myState.getSuperState());
+ setColor(myState.color);
+ }
+
+ /**
+ * A class for managing the instance state of a {@link ColorPickerPreference}.
+ */
+ static class SavedState extends BaseSavedState {
+ int color;
+
+ /**
+ * Constructor of <code>SavedState</code>
+ *
+ * @param source The source
+ */
+ public SavedState(Parcel source) {
+ super(source);
+ this.color = source.readInt();
+ }
+
+ /**
+ * Constructor of <code>SavedState</code>
+ *
+ * @param superState The parcelable state
+ */
+ public SavedState(Parcelable superState) {
+ super(superState);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ super.writeToParcel(dest, flags);
+ dest.writeInt(this.color);
+ }
+
+ /**
+ * A class that generates instances of the <code>SavedState</code> class from a Parcel.
+ */
+ @SuppressWarnings("hiding")
+ public static final Parcelable.Creator<SavedState> CREATOR =
+ new Parcelable.Creator<SavedState>() {
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public SavedState createFromParcel(Parcel in) {
+ return new SavedState(in);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public SavedState[] newArray(int size) {
+ return new SavedState[size];
+ }
+ };
+ }
+}
diff --git a/src/org/cyanogenmod/wallpapers/photophase/widgets/PicturesView.java b/src/org/cyanogenmod/wallpapers/photophase/widgets/PicturesView.java
new file mode 100644
index 0000000..bb9332c
--- /dev/null
+++ b/src/org/cyanogenmod/wallpapers/photophase/widgets/PicturesView.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.widgets;
+
+import android.content.Context;
+import android.graphics.Rect;
+import android.os.AsyncTask.Status;
+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;
+
+ /**
+ * 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>();
+ }
+
+ /**
+ * {@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);
+ requestLoadOfPendingPictures();
+ }
+
+ /**
+ * Method that load in background all visible and pending pictures
+ */
+ public 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);
+ }
+ }
+ }
+}