diff options
Diffstat (limited to 'src/com/cyanogenmod/eleven/ui/fragments/profile/BasicSongFragment.java')
-rw-r--r-- | src/com/cyanogenmod/eleven/ui/fragments/profile/BasicSongFragment.java | 324 |
1 files changed, 324 insertions, 0 deletions
diff --git a/src/com/cyanogenmod/eleven/ui/fragments/profile/BasicSongFragment.java b/src/com/cyanogenmod/eleven/ui/fragments/profile/BasicSongFragment.java new file mode 100644 index 0000000..ba9d815 --- /dev/null +++ b/src/com/cyanogenmod/eleven/ui/fragments/profile/BasicSongFragment.java @@ -0,0 +1,324 @@ +/* + * Copyright (C) 2012 Andrew Neal + * Copyright (C) 2014 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 com.cyanogenmod.eleven.ui.fragments.profile; + +import android.os.Bundle; +import android.os.SystemClock; +import android.support.v4.app.Fragment; +import android.support.v4.app.LoaderManager; +import android.support.v4.app.LoaderManager.LoaderCallbacks; +import android.support.v4.content.Loader; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.AbsListView; +import android.widget.AdapterView; +import android.widget.AdapterView.OnItemClickListener; +import android.widget.ListView; + +import com.cyanogenmod.eleven.Config; +import com.cyanogenmod.eleven.MusicStateListener; +import com.cyanogenmod.eleven.R; +import com.cyanogenmod.eleven.adapters.SongAdapter; +import com.cyanogenmod.eleven.model.Song; +import com.cyanogenmod.eleven.recycler.RecycleHolder; +import com.cyanogenmod.eleven.sectionadapter.SectionAdapter; +import com.cyanogenmod.eleven.sectionadapter.SectionListContainer; +import com.cyanogenmod.eleven.service.MusicPlaybackTrack; +import com.cyanogenmod.eleven.ui.activities.BaseActivity; +import com.cyanogenmod.eleven.utils.MusicUtils; +import com.cyanogenmod.eleven.utils.PopupMenuHelper; +import com.cyanogenmod.eleven.utils.SongPopupMenuHelper; +import com.cyanogenmod.eleven.widgets.IPopupMenuCallback; +import com.cyanogenmod.eleven.widgets.LoadingEmptyContainer; +import com.cyanogenmod.eleven.widgets.NoResultsContainer; + +import java.util.TreeSet; + +/** + * This class is used to display all of the songs + * + * @author Andrew Neal (andrewdneal@gmail.com) + */ +public abstract class BasicSongFragment extends Fragment implements + LoaderCallbacks<SectionListContainer<Song>>, OnItemClickListener, MusicStateListener { + + /** + * Fragment UI + */ + protected ViewGroup mRootView; + + /** + * The adapter for the list + */ + protected SectionAdapter<Song, SongAdapter> mAdapter; + + /** + * The list view + */ + protected ListView mListView; + + /** + * Pop up menu helper + */ + protected PopupMenuHelper mPopupMenuHelper; + + /** + * This holds the loading progress bar as well as the no results message + */ + protected LoadingEmptyContainer mLoadingEmptyContainer; + + /** + * Empty constructor as per the {@link Fragment} documentation + */ + public BasicSongFragment() { + } + + /** + * {@inheritDoc} + */ + @Override + public void onCreate(final Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + mPopupMenuHelper = new SongPopupMenuHelper(getActivity(), getFragmentManager()) { + @Override + public Song getSong(int position) { + return mAdapter.getTItem(position); + } + + @Override + protected long getSourceId() { + return getFragmentSourceId(); + } + + @Override + protected Config.IdType getSourceType() { + return getFragmentSourceType(); + } + + @Override + protected void updateMenuIds(PopupMenuType type, TreeSet<Integer> set) { + super.updateMenuIds(type, set); + BasicSongFragment.this.updateMenuIds(set); + } + }; + + // Create the adapter + mAdapter = new SectionAdapter<Song, SongAdapter>(getActivity(), createAdapter()); + mAdapter.setPopupMenuClickedListener(new IPopupMenuCallback.IListener() { + @Override + public void onPopupMenuClicked(View v, int position) { + mPopupMenuHelper.showPopupMenu(v, position); + } + }); + } + + protected long getFragmentSourceId() { + return -1; + } + + protected Config.IdType getFragmentSourceType() { + return Config.IdType.NA; + } + + protected void updateMenuIds(TreeSet<Integer> set) { + // do nothing - let subclasses override + } + + /** + * {@inheritDoc} + */ + @Override + public View onCreateView(final LayoutInflater inflater, final ViewGroup container, + final Bundle savedInstanceState) { + // The View for the fragment's UI + mRootView = (ViewGroup) inflater.inflate(R.layout.list_base, null); + // set the background on the root view + mRootView.setBackgroundColor(getResources().getColor(R.color.background_color)); + // Initialize the list + mListView = (ListView) mRootView.findViewById(R.id.list_base); + // Set the data behind the list + mListView.setAdapter(mAdapter); + // Release any references to the recycled Views + mListView.setRecyclerListener(new RecycleHolder()); + // Play the selected song + mListView.setOnItemClickListener(this); + // To help make scrolling smooth + mListView.setOnScrollListener(new AbsListView.OnScrollListener() { + @Override + public void onScrollStateChanged(AbsListView view, int scrollState) { + // Pause disk cache access to ensure smoother scrolling + if (scrollState == AbsListView.OnScrollListener.SCROLL_STATE_FLING) { + mAdapter.getUnderlyingAdapter().setPauseDiskCache(true); + } else { + mAdapter.getUnderlyingAdapter().setPauseDiskCache(false); + mAdapter.notifyDataSetChanged(); + } + } + + @Override + public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { + + } + }); + + // Show progress bar + mLoadingEmptyContainer = (LoadingEmptyContainer)mRootView.findViewById(R.id.loading_empty_container); + // Setup the container strings + setupNoResultsContainer(mLoadingEmptyContainer.getNoResultsContainer()); + mListView.setEmptyView(mLoadingEmptyContainer); + + // Register the music status listener + ((BaseActivity)getActivity()).setMusicStateListenerListener(this); + + return mRootView; + } + + @Override + public void onDestroyView() { + super.onDestroyView(); + + ((BaseActivity)getActivity()).removeMusicStateListenerListener(this); + } + + /** + * This allows subclasses to customize the look and feel of the no results container + * @param empty NoResultsContainer class + */ + public void setupNoResultsContainer(final NoResultsContainer empty) { + // do nothing + } + + /** + * {@inheritDoc} + */ + @Override + public void onActivityCreated(final Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + // Start the loader + getFragmentLoaderManager().initLoader(getLoaderId(), null, this); + } + + /** + * {@inheritDoc} + */ + @Override + public void onItemClick(final AdapterView<?> parent, final View view, final int position, + final long id) { + playAll(position); + } + + /** + * {@inheritDoc} + */ + @Override + public void onLoadFinished(final Loader<SectionListContainer<Song>> loader, + final SectionListContainer<Song> data) { + if (data.mListResults.isEmpty()) { + mAdapter.unload(); + mLoadingEmptyContainer.showNoResults(); + return; + } + + mAdapter.setData(data); + } + + /** + * @return Gets the list of song ids from the adapter, or null if none + */ + protected long[] getSongIdsFromAdapter() { + if (mAdapter != null) { + final SongAdapter adapter = mAdapter.getUnderlyingAdapter(); + if (adapter != null) { + return adapter.getSongIds(); + } + } + + return null; + } + + /** + * Restarts the loader. + */ + public void refresh() { + // Wait a moment for the preference to change. + SystemClock.sleep(10); + restartLoader(); + } + + /** + * {@inheritDoc} + */ + @Override + public void restartLoader() { + // Update the list when the user deletes any items + getFragmentLoaderManager().restartLoader(getLoaderId(), null, this); + } + + /** + * {@inheritDoc} + */ + @Override + public void onLoaderReset(final Loader<SectionListContainer<Song>> loader) { + // Clear the data in the adapter + mAdapter.unload(); + } + + /** + * If the subclasses want to use a customized SongAdapter they can override this method + * @return the Song adapter + */ + protected SongAdapter createAdapter() { + return new SongAdapter( + getActivity(), + R.layout.list_item_normal, + getFragmentSourceId(), + getFragmentSourceType() + ); + } + + /** + * Allow subclasses to specify a different loader manager + * @return Loader Manager to use + */ + public LoaderManager getFragmentLoaderManager() { + return getLoaderManager(); + } + + @Override + public void onMetaChanged() { + MusicPlaybackTrack currentTrack = MusicUtils.getCurrentTrack(); + if (mAdapter.getUnderlyingAdapter().setCurrentlyPlayingTrack(currentTrack)) { + mAdapter.notifyDataSetChanged(); + } + } + + @Override + public void onPlaylistChanged() { + // Nothing to do + } + + /** + * LoaderCallbacks identifier + */ + public abstract int getLoaderId(); + + /** + * If the user clisk play all + * + * @param position the position of the item clicked or -1 if shuffle all + */ + public abstract void playAll(int position); + +} |