diff options
author | jruesga <jorge@ruesga.com> | 2013-07-01 02:42:54 +0200 |
---|---|---|
committer | jruesga <jorge@ruesga.com> | 2013-07-01 02:42:54 +0200 |
commit | f29d68d929061ccbb982019c5020be721bbef862 (patch) | |
tree | 24ce41fb0dd7f942ca9dbe956fe93fe836da66c2 /src/org/cyanogenmod/wallpapers/photophase/widgets | |
download | android_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')
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); + } + } + } +} |