diff options
Diffstat (limited to 'src/org/cyanogenmod/wallpapers/photophase/preferences/ChoosePicturesFragment.java')
-rw-r--r-- | src/org/cyanogenmod/wallpapers/photophase/preferences/ChoosePicturesFragment.java | 496 |
1 files changed, 496 insertions, 0 deletions
diff --git a/src/org/cyanogenmod/wallpapers/photophase/preferences/ChoosePicturesFragment.java b/src/org/cyanogenmod/wallpapers/photophase/preferences/ChoosePicturesFragment.java new file mode 100644 index 0000000..6e41308 --- /dev/null +++ b/src/org/cyanogenmod/wallpapers/photophase/preferences/ChoosePicturesFragment.java @@ -0,0 +1,496 @@ +/* + * 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.preferences; + +import android.content.ContentResolver; +import android.content.Context; +import android.content.Intent; +import android.content.res.Resources; +import android.database.Cursor; +import android.os.AsyncTask; +import android.os.AsyncTask.Status; +import android.os.Bundle; +import android.preference.PreferenceFragment; +import android.provider.MediaStore; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; +import android.view.View; +import android.view.ViewGroup; + +import org.cyanogenmod.wallpapers.photophase.R; +import org.cyanogenmod.wallpapers.photophase.animations.AlbumsFlip3dAnimationController; +import org.cyanogenmod.wallpapers.photophase.model.Album; +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 java.io.File; +import java.text.DateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +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 { + + private static final String TAG = "ChoosePicturesFragment"; + + private static final boolean DEBUG = false; + + private static final int AMOUNT_OF_ADDED_STEPS = 5; + + 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( + MediaStore.Images.Media.EXTERNAL_CONTENT_URI, + new String[]{ MediaStore.MediaColumns.DATA }, + null, + null, + MediaStore.MediaColumns.DATA); + if (c != null) { + try { + long start = System.currentTimeMillis(); + if (DEBUG) Log.v(TAG, "Media library:"); + 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()); + } + } + } + } + + // Add the last album + if (album != null) { + mAlbums.add(album); + mOriginalAlbums.add((Album)album.clone()); + } + long end = System.currentTimeMillis(); + if (DEBUG) Log.v(TAG, "Library loaded in " + (end - start) + " miliseconds"); + + } finally { + c.close(); + } + } + return null; + } + + /** + * {@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)); + } + doEndScroll(steps, true); + + // 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); + } + }; + + /*package*/ ContentResolver mContentResolver; + + /*package*/ List<Album> mAlbums; + /*package*/ List<View> mAlbumViews; + /*package*/ List<Album> mOriginalAlbums; + /*package*/ List<AlbumsFlip3dAnimationController> mAnimationControllers; + + /*package*/ Set<String> mSelectedAlbums; + private Set<String> mOriginalSelectedAlbums; + + /*package*/ VerticalEndlessScroller mScroller; + private CardLayout mAlbumsPanel; + + /*package*/ boolean mSelectionChanged; + + /** + * {@inheritDoc} + */ + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + mContentResolver = getActivity().getContentResolver(); + + // 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(); + mSelectedAlbums = new HashSet<String>(mOriginalSelectedAlbums); + mSelectionChanged = false; + + setHasOptionsMenu(true); + } + + /** + * {@inheritDoc} + */ + @Override + public void onDestroy() { + super.onDestroy(); + if (mAlbumsLoaderTask.getStatus().compareTo(Status.PENDING) == 0) { + mAlbumsLoaderTask.cancel(true); + } + unbindDrawables(mAlbumsPanel); + unregister(); + + // Notify that the settings was changed + Intent intent = new Intent(PreferencesProvider.ACTION_SETTINGS_CHANGED); + if (mSelectionChanged) { + intent.putExtra(PreferencesProvider.EXTRA_FLAG_REDRAW, Boolean.TRUE); + intent.putExtra(PreferencesProvider.EXTRA_FLAG_EMPTY_TEXTURE_QUEUE, Boolean.TRUE); + intent.putExtra(PreferencesProvider.EXTRA_FLAG_MEDIA_RELOAD, Boolean.TRUE); + } + getActivity().sendBroadcast(intent); + } + + /*package*/ void unregister() { + mAlbums.clear(); + mOriginalAlbums.clear(); + mAnimationControllers.clear(); + } + + /** + * Method that unbind all the drawables for a view + * + * @param view The root view + */ + private void unbindDrawables(View view) { + if (view.getBackground() != null) { + view.getBackground().setCallback(null); + } + if (view instanceof ViewGroup) { + for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) { + unbindDrawables(((ViewGroup) view).getChildAt(i)); + } + ((ViewGroup) view).removeAllViews(); + } + } + + /** + * {@inheritDoc} + */ + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + // Inflate the layout for this fragment + mScroller = + (VerticalEndlessScroller)inflater.inflate( + R.layout.choose_picture_fragment, container, false); + mScroller.setCallback(this); + mAlbumsPanel = (CardLayout)mScroller.findViewById(R.id.albums_panel); + + // Force Hardware acceleration + if (!mScroller.isHardwareAccelerated()) { + mScroller.setLayerType(View.LAYER_TYPE_HARDWARE, null); + } + if (!mAlbumsPanel.isHardwareAccelerated()) { + mAlbumsPanel.setLayerType(View.LAYER_TYPE_HARDWARE, null); + } + + // Load the albums + mAlbumsLoaderTask.execute(); + + return mScroller; + } + + /** + * {@inheritDoc} + */ + @Override + public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { + inflater.inflate(R.menu.albums, menu); + } + + /** + * {@inheritDoc} + */ + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case R.id.mnu_ok: + getActivity().finish(); + return true; + case R.id.mnu_restore: + restoreData(); + return true; + case R.id.mnu_invert_all: + invertAll(); + return true; + default: + return super.onOptionsItemSelected(item); + } + } + + /** + * Method that restores the albums to its original state + */ + 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()); + } + + // Update all the views + Preferences.Media.setSelectedMedia(getActivity(), mSelectedAlbums); + updateAll(); + } + + /** + * Method that inverts the selection of all the albums + */ + private void invertAll() { + // Restore and the albums the selection + mSelectedAlbums = new HashSet<String>(); + for (Album album : mAlbums) { + album.setSelected(!album.isSelected()); + album.setSelectedItems(new ArrayList<String>()); + if (album.isSelected()) { + mSelectedAlbums.add(album.getPath()); + } else { + mSelectedAlbums.addAll(album.getSelectedItems()); + } + } + + // Update all the views + Preferences.Media.setSelectedMedia(getActivity(), mSelectedAlbums); + updateAll(); + } + + /** + * Method that updates the current state of all the albums + */ + 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); + } + + // Restore the preference + Preferences.Media.setSelectedMedia(getActivity(), mSelectedAlbums); + mSelectionChanged = true; + + // Restore all the animations states + for (AlbumsFlip3dAnimationController controller : mAnimationControllers) { + controller.reset(); + } + } + + /** + * Method that creates a new album to the card layout + * + * @param album The album to create + * @return View The view create + */ + 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); + } + }); + if (album.isSelected()) { + albumInfo.setSelected(true); + } + albumInfo.addCallBackListener(new AlbumInfo.CallbacksListener() { + @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; + } + + @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; + } + + + }); + + // Load the album picture data + albumPictures.updateView(album, false); + albumPictures.addCallBackListener(new AlbumPictures.CallbacksListener() { + @Override + public void onBackButtonClick(View v) { + // Ignored + } + + @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; + } + }); + + // Register the animation controller + AlbumsFlip3dAnimationController controller = new AlbumsFlip3dAnimationController(albumInfo, albumPictures); + controller.register(); + mAnimationControllers.add(controller); + + return albumView; + } + + /** + * Method that checks if an item is selected + * + * @param item The item + * @return boolean if an item is selected + */ + /*package*/ 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; + } + + /** + * Method that removes the reference to all the items and itself + * + * @param ref The album + */ + /*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(); + } + } + } + + /** + * {@inheritDoc} + */ + @Override + public void onEndScroll() { + doEndScroll(AMOUNT_OF_ADDED_STEPS, false); + } + + /** + * Method that performs a scroll creating new items + * + * @param amount The amount of items to create + * @param animate If the add should be animated + */ + /*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; + } + mAlbumsPanel.addCard(mAlbumViews.remove(0), animate); + } + } +} |