android:layout_alignParentRight="true"
android:layout_marginBottom="40dp"
android:gravity="center"
- android:src="@drawable/menu_item_button" />
+ android:src="@drawable/menu_button" />
<ImageView
android:id="@+id/album_art"
android:layout_height="@dimen/audio_player_controls_top_button_height"
android:layout_weight="0"
android:scaleType="centerInside"
- android:src="@drawable/menu_button" />
+ android:src="@drawable/menu_button_light" />
</LinearLayout>
<RelativeLayout
android:layout_alignParentRight="true"
android:layout_marginBottom="2dp"
android:gravity="center"
- android:src="@drawable/menu_item_button" />
+ android:src="@drawable/menu_button" />
<TextView
android:id="@+id/title"
android:layout_marginBottom="1dp"
android:layout_marginRight="-2dp"
android:gravity="center"
- android:src="@drawable/menu_item_button" />
+ android:src="@drawable/menu_button" />
<TextView
android:id="@+id/title"
android:layout_alignParentRight="true"
android:layout_marginBottom="2dp"
android:gravity="center"
- android:src="@drawable/menu_item_button" />
+ android:src="@drawable/menu_button" />
<TextView
android:id="@+id/title"
style="@style/ListItemMainText.Grid.Single"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_alignParentTop="true" />
+ android:layout_alignParentTop="true"
+ android:layout_toLeftOf="@+id/popup_menu_button"/>
<TextView
android:id="@+id/line_two"
style="@style/ListItemSecondaryText.Grid.Single"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_below="@+id/line_one" />
+ android:layout_below="@+id/line_one"
+ android:layout_toLeftOf="@id/popup_menu_button" />
+
+ <com.cyngn.eleven.widgets.PopupMenuButton
+ android:id="@id/popup_menu_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentRight="true"
+ android:layout_centerVertical="true"
+ android:src="@drawable/menu_button" />
</RelativeLayout>
</RelativeLayout>
\ No newline at end of file
style="@style/ListItemSecondaryText.Single"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_alignParentRight="true"
+ android:layout_toLeftOf="@+id/popup_menu_button"
android:layout_centerVertical="true" />
+
+ <com.cyngn.eleven.widgets.PopupMenuButton
+ android:id="@id/popup_menu_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentRight="true"
+ android:layout_centerVertical="true"
+ android:src="@drawable/menu_button" />
+
</merge>
\ No newline at end of file
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
- android:layout_alignParentRight="true"
+ android:layout_toLeftOf="@+id/popup_menu_button"
android:paddingLeft="@dimen/list_item_progress_padding_left"
android:paddingRight="@dimen/list_item_progress_padding_right">
<include
android:layout_centerVertical="true"
layout="@layout/play_pause_progress_button"/>
</FrameLayout>
+
+ <com.cyngn.eleven.widgets.PopupMenuButton
+ android:id="@id/popup_menu_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentRight="true"
+ android:layout_centerVertical="true"
+ android:src="@drawable/menu_button_light" />
</RelativeLayout>
\ No newline at end of file
style="@style/ListItemSecondaryText.Single"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_alignParentRight="true"
+ android:layout_toLeftOf="@+id/popup_menu_button"
android:layout_centerVertical="true" />
+
+ <com.cyngn.eleven.widgets.PopupMenuButton
+ android:id="@id/popup_menu_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentRight="true"
+ android:layout_centerVertical="true"
+ android:src="@drawable/menu_button" />
</RelativeLayout>
<ImageView
android:layout_width="match_parent"
android:layout_height="@dimen/list_item_image_height"
android:layout_toRightOf="@+id/position_contanier"
- android:layout_toLeftOf="@+id/line_one_right"
+ android:layout_toLeftOf="@+id/popup_menu_button"
android:gravity="center_vertical"
android:minHeight="@dimen/item_normal_height"
android:paddingLeft="@dimen/list_preferred_item_padding" >
android:layout_below="@+id/line_one" />
</RelativeLayout>
- <TextView
- android:id="@+id/line_one_right"
- style="@style/ListItemSecondaryText.Single"
+ <com.cyngn.eleven.widgets.PopupMenuButton
+ android:id="@id/popup_menu_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
- android:layout_centerVertical="true" />
+ android:layout_centerVertical="true"
+ android:src="@drawable/menu_button" />
</RelativeLayout>
<ImageView
import com.cyngn.eleven.ui.MusicHolder.DataHolder;
import com.cyngn.eleven.utils.ApolloUtils;
import com.cyngn.eleven.utils.MusicUtils;
+import com.cyngn.eleven.widgets.IPopupMenuCallback;
/**
* This {@link ArrayAdapter} is used to display all of the albums on a user's
*
* @author Andrew Neal (andrewdneal@gmail.com)
*/
-public class AlbumAdapter extends ArrayAdapter<Album> implements SectionAdapter.BasicAdapter {
+public class AlbumAdapter extends ArrayAdapter<Album>
+ implements SectionAdapter.BasicAdapter, IPopupMenuCallback {
/**
* Number of views (ImageView and TextView)
private DataHolder[] mData;
/**
+ * Used to listen to the pop up menu callbacks
+ */
+ private IPopupMenuCallback.IListener mListener;
+
+ /**
* Constructor of <code>AlbumAdapter</code>
*
* @param context The {@link Context} to use.
convertView = LayoutInflater.from(getContext()).inflate(mLayoutId, parent, false);
holder = new MusicHolder(convertView);
convertView.setTag(holder);
+ // set the pop up menu listener
+ holder.mPopupMenuButton.get().setPopupMenuClickedListener(mListener);
} else {
holder = (MusicHolder)convertView.getTag();
}
// Retrieve the data holder
final DataHolder dataHolder = mData[position];
+ // Sets the position each time because of recycling
+ holder.mPopupMenuButton.get().setPosition(position);
// Set each album name (line one)
holder.mLineOne.get().setText(dataHolder.mLineOne);
// Set the artist name (line two)
public void setTouchPlay(final boolean play) {
mTouchPlay = play;
}
+
+ @Override
+ public void setPopupMenuClickedListener(IPopupMenuCallback.IListener listener) {
+ mListener = listener;
+ }
}
import com.cyngn.eleven.cache.ImageFetcher;
import com.cyngn.eleven.model.Artist;
import com.cyngn.eleven.sectionadapter.SectionAdapter;
+import com.cyngn.eleven.sectionadapter.SectionAdapter.BasicAdapter;
import com.cyngn.eleven.ui.MusicHolder;
import com.cyngn.eleven.ui.MusicHolder.DataHolder;
import com.cyngn.eleven.utils.ApolloUtils;
import com.cyngn.eleven.utils.MusicUtils;
+import com.cyngn.eleven.widgets.IPopupMenuCallback;
/**
* This {@link ArrayAdapter} is used to display all of the artists on a user's
/**
* @author Andrew Neal (andrewdneal@gmail.com)
*/
-public class ArtistAdapter extends ArrayAdapter<Artist> implements SectionAdapter.BasicAdapter {
+public class ArtistAdapter extends ArrayAdapter<Artist> implements BasicAdapter, IPopupMenuCallback {
/**
* Number of views (ImageView and TextView)
private DataHolder[] mData;
/**
+ * Used to listen to the pop up menu callbacks
+ */
+ private IListener mListener;
+
+ /**
* Constructor of <code>ArtistAdapter</code>
*
* @param context The {@link Context} to use.
convertView = LayoutInflater.from(getContext()).inflate(mLayoutId, parent, false);
holder = new MusicHolder(convertView);
convertView.setTag(holder);
+
+ // set the pop up menu listener
+ holder.mPopupMenuButton.get().setPopupMenuClickedListener(mListener);
} else {
holder = (MusicHolder)convertView.getTag();
}
holder.mLineTwo.get().setText(dataHolder.mLineTwo);
// Asynchronously load the artist image into the adapter
mImageFetcher.loadArtistImage(dataHolder.mLineOne, holder.mImage.get());
+ // because of recycling, we need to set the position each time
+ holder.mPopupMenuButton.get().setPosition(position);
return convertView;
}
return -1;
}
+
+ @Override
+ public void setPopupMenuClickedListener(IListener listener) {
+ mListener = listener;
+ }
}
import com.cyngn.eleven.ui.MusicHolder.DataHolder;
import com.cyngn.eleven.ui.fragments.PlaylistFragment;
import com.cyngn.eleven.utils.MusicUtils;
+import com.cyngn.eleven.widgets.IPopupMenuCallback;
/**
* This {@link ArrayAdapter} is used to display all of the playlists on a user's
*
* @author Andrew Neal (andrewdneal@gmail.com)
*/
-public class PlaylistAdapter extends ArrayAdapter<Playlist> {
+public class PlaylistAdapter extends ArrayAdapter<Playlist> implements IPopupMenuCallback {
/**
* Smart playlists and normal playlists
private DataHolder[] mData;
/**
+ * Used to listen to the pop up menu callbacks
+ */
+ protected IListener mListener;
+
+ /**
* Constructor of <code>PlaylistAdapter</code>
*
* @param context The {@link Context} to use.
convertView = LayoutInflater.from(getContext()).inflate(layoutId, parent, false);
holder = new MusicHolder(convertView);
convertView.setTag(holder);
+
+ // set the pop up menu listener
+ holder.mPopupMenuButton.get().setPopupMenuClickedListener(mListener);
} else {
holder = (MusicHolder)convertView.getTag();
}
// Retrieve the data holder
final DataHolder dataHolder = mData[position];
+ // because of recycling, we need to set the position each time
+ holder.mPopupMenuButton.get().setPosition(position);
+
// Set each playlist name (line one)
holder.mLineOne.get().setText(dataHolder.mLineOne);
mData = null;
}
+ @Override
+ public void setPopupMenuClickedListener(IListener listener) {
+ mListener = listener;
+ }
}
import com.cyngn.eleven.utils.ApolloUtils;
import com.cyngn.eleven.utils.Lists;
import com.cyngn.eleven.utils.MusicUtils;
+import com.cyngn.eleven.widgets.IPopupMenuCallback;
import java.util.List;
*
* @author Andrew Neal (andrewdneal@gmail.com)
*/
-public class ProfileSongAdapter extends ArrayAdapter<Song> {
+public class ProfileSongAdapter extends ArrayAdapter<Song> implements IPopupMenuCallback {
/**
* Default display setting: title/album
private List<Song> mCount = Lists.newArrayList();
/**
+ * Used to listen to the pop up menu callbacks
+ */
+ private IListener mListener;
+
+ /**
* Constructor of <code>ProfileSongAdapter</code>
*
* @param activity The {@link Activity} to use
convertView = LayoutInflater.from(getContext()).inflate(mLayoutId, parent, false);
holder = new MusicHolder(convertView);
convertView.setTag(holder);
+
+ // set the pop up menu listener
+ holder.mPopupMenuButton.get().setPopupMenuClickedListener(mListener);
} else {
holder = (MusicHolder)convertView.getTag();
}
// Retrieve the album
final Song song = getItem(position - 1);
+ // because of recycling, we need to set the position each time
+ holder.mPopupMenuButton.get().setPosition(position);
+
// Set each track name (line one)
holder.mLineOne.get().setText(song.mSongName);
// Set the line two
MusicUtils.makeShortTimeString(getContext(), song.mDuration));
}
- ;
-
holder.mLineTwo.get().setText(MusicUtils.makeCombinedString(getContext(),
song.mArtistName, song.mAlbumName));
public boolean isEmpty() {
return (mCount == null || mCount.size() == 0);
}
+
+ @Override
+ public void setPopupMenuClickedListener(IPopupMenuCallback.IListener listener) {
+ mListener = listener;
+ }
}
import com.cyngn.eleven.ui.fragments.SongFragment;
import com.cyngn.eleven.utils.ApolloUtils;
import com.cyngn.eleven.utils.MusicUtils;
+import com.cyngn.eleven.widgets.IPopupMenuCallback;
import com.cyngn.eleven.widgets.PlayPauseProgressButton;
/**
*
* @author Andrew Neal (andrewdneal@gmail.com)
*/
-public class SongAdapter extends ArrayAdapter<Song> implements SectionAdapter.BasicAdapter {
+public class SongAdapter extends ArrayAdapter<Song>
+ implements SectionAdapter.BasicAdapter, IPopupMenuCallback {
/**
* Number of views (TextView)
private DataHolder[] mData;
/**
+ * Used to listen to the pop up menu callbacks
+ */
+ private IPopupMenuCallback.IListener mListener;
+
+ /**
* Constructor of <code>SongAdapter</code>
*
* @param context The {@link Context} to use.
convertView = LayoutInflater.from(getContext()).inflate(mLayoutId, parent, false);
holder = new MusicHolder(convertView);
convertView.setTag(holder);
+
+ holder.mPopupMenuButton.get().setPopupMenuClickedListener(mListener);
} else {
holder = (MusicHolder)convertView.getTag();
}
// Retrieve the data holder
final DataHolder dataHolder = mData[position];
+ // Sets the position each time because of recycling
+ holder.mPopupMenuButton.get().setPosition(position);
// Set each song name (line one)
holder.mLineOne.get().setText(dataHolder.mLineOne);
// Set the album name (line two)
notifyDataSetChanged();
}
}
+
+ @Override
+ public void setPopupMenuClickedListener(IListener listener) {
+ mListener = listener;
+ }
}
import com.cyngn.eleven.ui.MusicHolder;
import com.cyngn.eleven.utils.ApolloUtils;
import com.cyngn.eleven.utils.MusicUtils;
+import com.cyngn.eleven.widgets.IPopupMenuCallback;
import java.util.Locale;
/**
* Used to populate the list view with the search results.
*/
-public final class SummarySearchAdapter extends ArrayAdapter<SearchResult> implements SectionAdapter.BasicAdapter {
+public final class SummarySearchAdapter extends ArrayAdapter<SearchResult>
+ implements SectionAdapter.BasicAdapter, IPopupMenuCallback {
/**
* no-image list item type and with image type
private char[] mPrefix;
/**
+ * Used to listen to the pop up menu callbacks
+ */
+ private IListener mListener;
+
+ /**
* Constructor for <code>SearchAdapter</code>
*
* @param context The {@link Activity} to use.
getViewResourceId(position), parent, false);
holder = new MusicHolder(convertView);
convertView.setTag(holder);
+ // set the pop up menu listener
+ holder.mPopupMenuButton.get().setPopupMenuClickedListener(mListener);
} else {
holder = (MusicHolder)convertView.getTag();
}
+ // Sets the position each time because of recycling
+ holder.mPopupMenuButton.get().setPosition(position);
+
final SearchResult item = getItem(position);
switch (item.mType) {
String albumCount = MusicUtils.makeLabel(getContext(), R.plurals.Nalbums, item.mAlbumCount);
// Album Name | Artist Name (line two)
holder.mLineTwo.get().setText(MusicUtils.makeCombinedString(getContext(), songCount, albumCount));
-
break;
case Album:
// Asynchronously load the album images into the adapter
return -1;
}
+
+ @Override
+ public void setPopupMenuClickedListener(IListener listener) {
+ mListener = listener;
+ }
}
\ No newline at end of file
import android.provider.MediaStore.Audio.AudioColumns;
import com.cyngn.eleven.model.Song;
+import com.cyngn.eleven.sectionadapter.SectionCreator;
import com.cyngn.eleven.utils.Lists;
import java.util.ArrayList;
*
* @author Andrew Neal (andrewdneal@gmail.com)
*/
-public class LastAddedLoader extends WrappedAsyncTaskLoader<List<Song>> {
+public class LastAddedLoader extends SectionCreator.SimpleListLoader<Song> {
/**
* The result
import com.cyngn.eleven.ui.MusicHolder;
import com.cyngn.eleven.utils.SectionCreatorUtils.Section;
import com.cyngn.eleven.utils.SectionCreatorUtils.SectionType;
+import com.cyngn.eleven.widgets.IPopupMenuCallback;
import java.util.TreeMap;
* @param <TArrayAdapter> the arrayadapter that contains TItem and implements BasicAdapter
*/
public class SectionAdapter<TItem,
- TArrayAdapter extends ArrayAdapter<TItem> & SectionAdapter.BasicAdapter>
- extends BaseAdapter {
+ TArrayAdapter extends ArrayAdapter<TItem> & SectionAdapter.BasicAdapter & IPopupMenuCallback>
+ extends BaseAdapter implements IPopupMenuCallback, IPopupMenuCallback.IListener {
/**
* Basic interface that the adapters implement
*/
protected boolean mFooterEnabled;
/**
+ * Popup menu click listener
+ */
+ protected IListener mListener;
+
+ /**
* {@link Context}
*/
protected final Context mContext;
public SectionAdapter(final Activity context, final TArrayAdapter underlyingAdapter) {
mContext = context;
mUnderlyingAdapter = underlyingAdapter;
+ mUnderlyingAdapter.setPopupMenuClickedListener(this);
mSections = new TreeMap<Integer, Section>();
setupHeaderParameters(R.layout.list_header, false);
// since we have no good default footer, just re-use the header layout
return -1;
}
+
+ @Override
+ public void setPopupMenuClickedListener(IListener listener) {
+ mListener = listener;
+ }
+
+ @Override
+ public void onPopupMenuClicked(View v, int position) {
+ if (mListener != null) {
+ mListener.onPopupMenuClicked(v, getExternalPosition(position));
+ }
+ }
}
import com.cyngn.eleven.R;
import com.cyngn.eleven.widgets.PlayPauseProgressButton;
+import com.cyngn.eleven.widgets.PopupMenuButton;
import java.lang.ref.WeakReference;
public WeakReference<View> mDivider;
/**
+ * The divider for the list item
+ */
+ public WeakReference<PopupMenuButton> mPopupMenuButton;
+
+ /**
* Constructor of <code>ViewHolder</code>
*
* @param context The {@link Context} to use.
// Get the divider for the list item
mDivider = new WeakReference<View>(view.findViewById(R.id.divider));
+
+ // Get the pop up menu button
+ mPopupMenuButton = new WeakReference<PopupMenuButton>(
+ (PopupMenuButton)view.findViewById(R.id.popup_menu_button));
}
/**
import android.support.v4.app.LoaderManager;
import android.support.v4.app.LoaderManager.LoaderCallbacks;
import android.support.v4.content.Loader;
-import android.view.ContextMenu;
-import android.view.Menu;
-import android.view.SubMenu;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import com.cyngn.eleven.dragdrop.DragSortListView.DropListener;
import com.cyngn.eleven.dragdrop.DragSortListView.RemoveListener;
import com.cyngn.eleven.loaders.PlaylistSongLoader;
-import com.cyngn.eleven.menu.CreateNewPlaylist;
import com.cyngn.eleven.menu.DeleteDialog;
import com.cyngn.eleven.menu.FragmentMenuItems;
import com.cyngn.eleven.model.Song;
import com.cyngn.eleven.recycler.RecycleHolder;
import com.cyngn.eleven.utils.MusicUtils;
-import com.cyngn.eleven.utils.NavUtils;
+import com.cyngn.eleven.utils.PopupMenuHelper;
+import com.cyngn.eleven.widgets.IPopupMenuCallback;
import com.cyngn.eleven.widgets.NoResultsContainer;
import java.util.ArrayList;
private TextView mDurationOfPlaylist;
/**
- * Represents a song
- */
- private Song mSong;
-
- /**
- * Position of a context menu item
- */
- private int mSelectedPosition;
-
- /**
- * Id of a context menu item
+ * The Id of the playlist the songs belong to
*/
- private long mSelectedId;
+ private long mPlaylistId;
/**
- * The Id of the playlist the songs belong to
+ * Pop up menu helper
*/
- private long mPlaylistId;
+ private PopupMenuHelper mPopupMenuHelper;
@Override
protected int getLayoutToInflate() {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ mPopupMenuHelper = new PopupMenuHelper(this, getSupportFragmentManager()) {
+ /**
+ * Represents a song
+ */
+ private Song mSong;
+
+ @Override
+ protected PopupMenuType onPreparePopupMenu(int position) {
+ // the header has been long-pressed - for now just return, but later if we want
+ // to long-press support for the header, do that logic here
+ if (position == 0) {
+ return null;
+ }
+
+ // Create a new song
+ mSong = mAdapter.getItem(position - 1);
+
+ return PopupMenuType.Song;
+ }
+
+ @Override
+ protected void getAdditionalIds(PopupMenuType type, ArrayList<Integer> list) {
+ super.getAdditionalIds(type, list);
+
+ list.add(FragmentMenuItems.REMOVE_FROM_PLAYLIST);
+ }
+
+ @Override
+ protected long[] getIdList() {
+ return new long[] { mSong.mSongId };
+ }
+
+ @Override
+ protected int getGroupId() {
+ return GROUP_ID;
+ }
+
+ @Override
+ protected long getId() {
+ return mSong.mSongId;
+ }
+
+ @Override
+ protected String getArtistName() {
+ return mSong.mArtistName;
+ }
+
+ @Override
+ protected void onDeleteClicked() {
+ DeleteDialog.newInstance(mSong.mSongName, getIdList(), null)
+ .show(getSupportFragmentManager(), "DeleteDialog");
+ SystemClock.sleep(10);
+ mAdapter.notifyDataSetChanged();
+ getSupportLoaderManager().restartLoader(LOADER, null, PlaylistDetailActivity.this);
+ }
+
+ @Override
+ protected void setShouldRefresh() {
+ // do nothing here since we restart the loader ourselves
+ }
+
+ @Override
+ protected void removeFromPlaylist() {
+ mAdapter.remove(mSong);
+ mAdapter.notifyDataSetChanged();
+ MusicUtils.removeFromPlaylist(PlaylistDetailActivity.this, mSong.mSongId, mPlaylistId);
+ getSupportLoaderManager().restartLoader(LOADER, null, PlaylistDetailActivity.this);
+ }
+ };
+
Bundle arguments = getIntent().getExtras();
String playlistName = arguments.getString(Config.NAME);
mPlaylistId = arguments.getLong(Config.ID);
R.layout.faux_playlist_header,
ProfileSongAdapter.DISPLAY_PLAYLIST_SETTING
);
+ mAdapter.setPopupMenuClickedListener(new IPopupMenuCallback.IListener() {
+ @Override
+ public void onPopupMenuClicked(View v, int position) {
+ mPopupMenuHelper.showPopupMenu(v, position);
+ }
+ });
mListView.setAdapter(mAdapter);
// Release any references to the recycled Views
mListView.setRecyclerListener(new RecycleHolder());
- // Listen for ContextMenus to be created
- mListView.setOnCreateContextMenuListener(this);
// Play the selected song
mListView.setOnItemClickListener(this);
// Set the drop listener
* {@inheritDoc}
*/
@Override
- public void onCreateContextMenu(final ContextMenu menu, final View v,
- final ContextMenu.ContextMenuInfo menuInfo) {
- super.onCreateContextMenu(menu, v, menuInfo);
- // Get the position of the selected item
- final AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo;
- mSelectedPosition = info.position - 1;
-
- // the header has been long-pressed - for now just return, but later if we want
- // to long-press support for the header, do that logic here
- if (mSelectedPosition == -1) {
- return;
- }
-
- // Creat a new song
- mSong = mAdapter.getItem(mSelectedPosition);
- mSelectedId = mSong.mSongId;
-
- // Play the song
- menu.add(GROUP_ID, FragmentMenuItems.PLAY_SELECTION, Menu.NONE,
- getString(R.string.context_menu_play_selection));
-
- // Play next
- menu.add(GROUP_ID, FragmentMenuItems.PLAY_NEXT, Menu.NONE,
- getString(R.string.context_menu_play_next));
-
- // Add the song to the queue
- menu.add(GROUP_ID, FragmentMenuItems.ADD_TO_QUEUE, Menu.NONE,
- getString(R.string.add_to_queue));
-
- // Add the song to a playlist
- final SubMenu subMenu = menu.addSubMenu(GROUP_ID, FragmentMenuItems.ADD_TO_PLAYLIST,
- Menu.NONE, R.string.add_to_playlist);
- MusicUtils.makePlaylistMenu(this, GROUP_ID, subMenu);
-
- // View more content by the song artist
- menu.add(GROUP_ID, FragmentMenuItems.MORE_BY_ARTIST, Menu.NONE,
- getString(R.string.context_menu_more_by_artist));
-
- // Make the song a ringtone
- menu.add(GROUP_ID, FragmentMenuItems.USE_AS_RINGTONE, Menu.NONE,
- getString(R.string.context_menu_use_as_ringtone));
-
- // Remove the song from playlist
- menu.add(GROUP_ID, FragmentMenuItems.REMOVE_FROM_PLAYLIST, Menu.NONE,
- getString(R.string.context_menu_remove_from_playlist));
-
- // Delete the song
- menu.add(GROUP_ID, FragmentMenuItems.DELETE, Menu.NONE,
- getString(R.string.context_menu_delete));
- }
-
- @Override
- public boolean onContextItemSelected(final android.view.MenuItem item) {
- if (item.getGroupId() == GROUP_ID) {
- switch (item.getItemId()) {
- case FragmentMenuItems.PLAY_SELECTION:
- MusicUtils.playAll(this, new long[]{
- mSelectedId
- }, 0, false);
- return true;
- case FragmentMenuItems.PLAY_NEXT:
- MusicUtils.playNext(new long[]{
- mSelectedId
- });
- return true;
- case FragmentMenuItems.ADD_TO_QUEUE:
- MusicUtils.addToQueue(this, new long[]{
- mSelectedId
- });
- return true;
- case FragmentMenuItems.NEW_PLAYLIST:
- CreateNewPlaylist.getInstance(new long[]{
- mSelectedId
- }).show(getSupportFragmentManager(), "CreatePlaylist");
- return true;
- case FragmentMenuItems.PLAYLIST_SELECTED:
- final long playlistId = item.getIntent().getLongExtra("playlist", 0);
- MusicUtils.addToPlaylist(this, new long[]{
- mSelectedId
- }, playlistId);
- return true;
- case FragmentMenuItems.MORE_BY_ARTIST:
- NavUtils.openArtistProfile(this, mSong.mArtistName);
- return true;
- case FragmentMenuItems.USE_AS_RINGTONE:
- MusicUtils.setRingtone(this, mSelectedId);
- return true;
- case FragmentMenuItems.DELETE:
- DeleteDialog.newInstance(mSong.mSongName, new long[]{
- mSelectedId
- }, null).show(getSupportFragmentManager(), "DeleteDialog");
- SystemClock.sleep(10);
- mAdapter.notifyDataSetChanged();
- getSupportLoaderManager().restartLoader(LOADER, null, this);
- return true;
- case FragmentMenuItems.REMOVE_FROM_PLAYLIST:
- mAdapter.remove(mSong);
- mAdapter.notifyDataSetChanged();
- MusicUtils.removeFromPlaylist(this, mSong.mSongId, mPlaylistId);
- getSupportLoaderManager().restartLoader(LOADER, null, this);
- return true;
- default:
- break;
- }
- }
- return super.onContextItemSelected(item);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
public float getSpeed(final float w, final long t) {
if (w > 0.8f) {
return mAdapter.getCount() / 0.001f;
*/
@Override
public void remove(final int which) {
- mSong = mAdapter.getItem(which - 1);
- mAdapter.remove(mSong);
+ Song song = mAdapter.getItem(which - 1);
+ mAdapter.remove(song);
mAdapter.notifyDataSetChanged();
final Uri uri = MediaStore.Audio.Playlists.Members.getContentUri("external", mPlaylistId);
getContentResolver().delete(uri,
- MediaStore.Audio.Playlists.Members.AUDIO_ID + "=" + mSong.mSongId,
+ MediaStore.Audio.Playlists.Members.AUDIO_ID + "=" + song.mSongId,
null);
}
}
final int realFrom = from - 1;
final int realTo = to - 1;
- mSong = mAdapter.getItem(realFrom);
- mAdapter.remove(mSong);
- mAdapter.insert(mSong, realTo);
+ Song song = mAdapter.getItem(realFrom);
+ mAdapter.remove(song);
+ mAdapter.insert(song, realTo);
mAdapter.notifyDataSetChanged();
MediaStore.Audio.Playlists.Members.moveItem(getContentResolver(),
mPlaylistId, realFrom, realTo);
import com.cyngn.eleven.R;
import com.cyngn.eleven.adapters.SummarySearchAdapter;
import com.cyngn.eleven.loaders.WrappedAsyncTaskLoader;
+import com.cyngn.eleven.menu.FragmentMenuItems;
import com.cyngn.eleven.model.AlbumArtistDetails;
import com.cyngn.eleven.model.SearchResult;
import com.cyngn.eleven.model.SearchResult.ResultType;
import com.cyngn.eleven.utils.MusicUtils;
import com.cyngn.eleven.utils.MusicUtils.ServiceToken;
import com.cyngn.eleven.utils.NavUtils;
+import com.cyngn.eleven.utils.PopupMenuHelper;
import com.cyngn.eleven.utils.SectionCreatorUtils;
import com.cyngn.eleven.utils.SectionCreatorUtils.IItemCompare;
+import com.cyngn.eleven.widgets.IPopupMenuCallback;
import com.cyngn.eleven.widgets.NoResultsContainer;
import java.util.ArrayList;
private static int LOADING_DELAY = 500;
/**
+ * Used to keep context menu items from bleeding into other fragments
+ */
+ private static final int GROUP_ID = 5;
+
+ /**
* Identifier for the search loader
*/
private static int SEARCH_LOADER = 0;
private boolean mQuitting = false;
/**
+ * Pop up menu helper
+ */
+ private PopupMenuHelper mPopupMenuHelper;
+
+ /**
* {@inheritDoc}
*/
@Override
public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ mPopupMenuHelper = new PopupMenuHelper(this, getSupportFragmentManager()) {
+ private SearchResult mSelectedItem;
+
+ @Override
+ protected PopupMenuType onPreparePopupMenu(int position) {
+ mSelectedItem = mAdapter.getTItem(position);
+
+ return PopupMenuType.SearchResult;
+ }
+
+ @Override
+ protected long[] getIdList() {
+ switch (mSelectedItem.mType) {
+ case Artist:
+ return MusicUtils.getSongListForArtist(SearchActivity.this,
+ mSelectedItem.mId);
+ case Album:
+ return MusicUtils.getSongListForAlbum(SearchActivity.this,
+ mSelectedItem.mId);
+ case Song:
+ return new long[] { mSelectedItem.mId };
+ case Playlist:
+ return MusicUtils.getSongListForPlaylist(SearchActivity.this,
+ mSelectedItem.mId);
+ default:
+ return null;
+ }
+ }
+
+ @Override
+ protected void getAdditionalIds(PopupMenuType type, ArrayList<Integer> list) {
+ super.getAdditionalIds(type, list);
+
+ if (mSelectedItem.mType == ResultType.Album) {
+ list.add(FragmentMenuItems.MORE_BY_ARTIST);
+ }
+ }
+
+ @Override
+ protected String getArtistName() {
+ return mSelectedItem.mArtist;
+ }
+
+ @Override
+ protected int getGroupId() {
+ return GROUP_ID;
+ }
+
+ @Override
+ protected void onDeleteClicked() {
+ // do nothing
+ }
+
+ @Override
+ protected void setShouldRefresh() {
+ // do nothing
+ }
+ };
+
// Fade it in
overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out);
mAdapter.getUnderlyingAdapter().setPrefix(mFilterString);
mAdapter.setupHeaderParameters(R.layout.list_search_header, false);
mAdapter.setupFooterParameters(R.layout.list_search_footer, true);
+ mAdapter.setPopupMenuClickedListener(new IPopupMenuCallback.IListener() {
+ @Override
+ public void onPopupMenuClicked(View v, int position) {
+ mPopupMenuHelper.showPopupMenu(v, position);
+ }
+ });
// setup the no results container
mNoResultsContainer = (NoResultsContainer)findViewById(R.id.no_results_container);
import android.os.Bundle;
import android.os.SystemClock;
import android.support.v4.app.Fragment;
+import android.support.v4.app.FragmentManager;
import android.support.v4.app.LoaderManager.LoaderCallbacks;
import android.support.v4.content.Loader;
-import android.view.ContextMenu;
-import android.view.ContextMenu.ContextMenuInfo;
import android.view.LayoutInflater;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.view.SubMenu;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.AdapterView;
-import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.GridView;
-import android.widget.ListView;
-import android.widget.TextView;
import com.cyngn.eleven.MusicStateListener;
import com.cyngn.eleven.R;
import com.cyngn.eleven.adapters.AlbumAdapter;
import com.cyngn.eleven.cache.ImageFetcher;
import com.cyngn.eleven.loaders.AlbumLoader;
-import com.cyngn.eleven.menu.CreateNewPlaylist;
import com.cyngn.eleven.menu.DeleteDialog;
-import com.cyngn.eleven.menu.FragmentMenuItems;
import com.cyngn.eleven.model.Album;
import com.cyngn.eleven.recycler.RecycleHolder;
import com.cyngn.eleven.sectionadapter.SectionAdapter;
import com.cyngn.eleven.utils.ApolloUtils;
import com.cyngn.eleven.utils.MusicUtils;
import com.cyngn.eleven.utils.NavUtils;
-import com.cyngn.eleven.utils.PreferenceUtils;
-import com.cyngn.eleven.utils.SectionCreatorUtils;
+import com.cyngn.eleven.utils.PopupMenuHelper;
+import com.cyngn.eleven.widgets.IPopupMenuCallback;
import com.cyngn.eleven.widgets.NoResultsContainer;
import com.viewpagerindicator.TitlePageIndicator;
private GridView mGridView;
/**
- * The list view
- */
- private ListView mListView;
-
- /**
- * Album song list
- */
- private long[] mAlbumList;
-
- /**
- * Represents an album
+ * True if the list should execute {@code #restartLoader()}.
*/
- private Album mAlbum;
+ private boolean mShouldRefresh = false;
/**
- * True if the list should execute {@code #restartLoader()}.
+ * Pop up menu helper
*/
- private boolean mShouldRefresh = false;
+ private PopupMenuHelper mPopupMenuHelper;
/**
* {@inheritDoc}
@Override
public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+
+ mPopupMenuHelper = new PopupMenuHelper(getActivity(), getFragmentManager()) {
+ /**
+ * Represents an album
+ */
+ private Album mAlbum;
+
+ @Override
+ protected PopupMenuType onPreparePopupMenu(int position) {
+ // Create a new album
+ mAlbum = mAdapter.getTItem(position);
+
+ return PopupMenuType.Album;
+ }
+
+ @Override
+ protected long[] getIdList() {
+ return MusicUtils.getSongListForAlbum(getActivity(), mAlbum.mAlbumId);
+ }
+
+ @Override
+ protected int getGroupId() {
+ return GROUP_ID;
+ }
+
+ @Override
+ protected void onDeleteClicked() {
+ mShouldRefresh = true;
+ final String album = mAlbum.mAlbumName;
+ DeleteDialog.newInstance(album, getIdList(),
+ ImageFetcher.generateAlbumCacheKey(album,mAlbum.mArtistName))
+ .show(getFragmentManager(), "DeleteDialog");
+ }
+
+ @Override
+ protected void setShouldRefresh() {
+ mShouldRefresh = true;
+ }
+
+ @Override
+ protected String getArtistName() {
+ return mAlbum.mArtistName;
+ }
+ };
+
int layout = R.layout.grid_items_normal;
AlbumAdapter adapter = new AlbumAdapter(getActivity(), layout);
mAdapter = new SectionAdapter<Album, AlbumAdapter>(getActivity(), adapter);
+ mAdapter.setPopupMenuClickedListener(new IPopupMenuCallback.IListener() {
+ @Override
+ public void onPopupMenuClicked(View v, int position) {
+ mPopupMenuHelper.showPopupMenu(v, position);
+ }
+ });
}
/**
* {@inheritDoc}
*/
@Override
- public void onCreateContextMenu(final ContextMenu menu, final View v,
- final ContextMenuInfo menuInfo) {
- super.onCreateContextMenu(menu, v, menuInfo);
-
- // Get the position of the selected item
- final AdapterContextMenuInfo info = (AdapterContextMenuInfo)menuInfo;
- // Create a new album
- mAlbum = mAdapter.getTItem(info.position);
- // Create a list of the album's songs
- mAlbumList = MusicUtils.getSongListForAlbum(getActivity(), mAlbum.mAlbumId);
-
- // Play the album
- menu.add(GROUP_ID, FragmentMenuItems.PLAY_SELECTION, Menu.NONE,
- getString(R.string.context_menu_play_selection));
-
- // Add the album to the queue
- menu.add(GROUP_ID, FragmentMenuItems.ADD_TO_QUEUE, Menu.NONE,
- getString(R.string.add_to_queue));
-
- // Add the album to a playlist
- final SubMenu subMenu = menu.addSubMenu(GROUP_ID, FragmentMenuItems.ADD_TO_PLAYLIST,
- Menu.NONE, R.string.add_to_playlist);
- MusicUtils.makePlaylistMenu(getActivity(), GROUP_ID, subMenu);
-
- // View more content by the album artist
- menu.add(GROUP_ID, FragmentMenuItems.MORE_BY_ARTIST, Menu.NONE,
- getString(R.string.context_menu_more_by_artist));
-
- // Remove the album from the list
- menu.add(GROUP_ID, FragmentMenuItems.DELETE, Menu.NONE,
- getString(R.string.context_menu_delete));
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public boolean onContextItemSelected(final MenuItem item) {
- // Avoid leaking context menu selections
- if (item.getGroupId() == GROUP_ID) {
- switch (item.getItemId()) {
- case FragmentMenuItems.PLAY_SELECTION:
- MusicUtils.playAll(getActivity(), mAlbumList, 0, false);
- return true;
- case FragmentMenuItems.ADD_TO_QUEUE:
- MusicUtils.addToQueue(getActivity(), mAlbumList);
- return true;
- case FragmentMenuItems.NEW_PLAYLIST:
- CreateNewPlaylist.getInstance(mAlbumList).show(getFragmentManager(),
- "CreatePlaylist");
- return true;
- case FragmentMenuItems.MORE_BY_ARTIST:
- NavUtils.openArtistProfile(getActivity(), mAlbum.mArtistName);
- return true;
- case FragmentMenuItems.PLAYLIST_SELECTED:
- final long id = item.getIntent().getLongExtra("playlist", 0);
- MusicUtils.addToPlaylist(getActivity(), mAlbumList, id);
- return true;
- case FragmentMenuItems.DELETE:
- mShouldRefresh = true;
- final String album = mAlbum.mAlbumName;
- DeleteDialog.newInstance(album, mAlbumList,
- ImageFetcher.generateAlbumCacheKey(album,mAlbum.mArtistName))
- .show(getFragmentManager(), "DeleteDialog");
- return true;
- default:
- break;
- }
- }
- return super.onContextItemSelected(item);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
public void onScrollStateChanged(final AbsListView view, final int scrollState) {
// Pause disk cache access to ensure smoother scrolling
if (scrollState == AbsListView.OnScrollListener.SCROLL_STATE_FLING
@Override
public void onItemClick(final AdapterView<?> parent, final View view, final int position,
final long id) {
- mAlbum = mAdapter.getTItem(position);
- NavUtils.openAlbumProfile(getActivity(), mAlbum.mAlbumName, mAlbum.mArtistName, mAlbum.mAlbumId);
+ Album album = mAdapter.getTItem(position);
+ NavUtils.openAlbumProfile(getActivity(), album.mAlbumName, album.mArtistName, album.mAlbumId);
}
/**
private void initAbsListView(final AbsListView list) {
// Release any references to the recycled Views
list.setRecyclerListener(new RecycleHolder());
- // Listen for ContextMenus to be created
- list.setOnCreateContextMenuListener(this);
// Show the albums and songs from the selected artist
list.setOnItemClickListener(this);
// To help make scrolling smooth
import android.os.Bundle;
import android.os.SystemClock;
import android.support.v4.app.Fragment;
+import android.support.v4.app.FragmentManager;
import android.support.v4.app.LoaderManager.LoaderCallbacks;
import android.support.v4.content.Loader;
-import android.text.TextUtils;
-import android.view.ContextMenu;
-import android.view.ContextMenu.ContextMenuInfo;
import android.view.LayoutInflater;
-import android.view.Menu;
-import android.view.SubMenu;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.AdapterView;
-import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.AdapterView.OnItemClickListener;
-import android.widget.GridView;
import android.widget.ListView;
-import android.widget.TextView;
import com.cyngn.eleven.MusicStateListener;
import com.cyngn.eleven.R;
import com.cyngn.eleven.adapters.ArtistAdapter;
import com.cyngn.eleven.loaders.ArtistLoader;
-import com.cyngn.eleven.menu.CreateNewPlaylist;
import com.cyngn.eleven.menu.DeleteDialog;
-import com.cyngn.eleven.menu.FragmentMenuItems;
import com.cyngn.eleven.model.Artist;
import com.cyngn.eleven.recycler.RecycleHolder;
import com.cyngn.eleven.sectionadapter.SectionAdapter;
import com.cyngn.eleven.sectionadapter.SectionCreator;
import com.cyngn.eleven.sectionadapter.SectionListContainer;
import com.cyngn.eleven.ui.activities.BaseActivity;
-import com.cyngn.eleven.utils.ApolloUtils;
import com.cyngn.eleven.utils.MusicUtils;
import com.cyngn.eleven.utils.NavUtils;
-import com.cyngn.eleven.utils.PreferenceUtils;
+import com.cyngn.eleven.utils.PopupMenuHelper;
import com.cyngn.eleven.utils.SectionCreatorUtils;
import com.cyngn.eleven.utils.SectionCreatorUtils.IItemCompare;
+import com.cyngn.eleven.widgets.IPopupMenuCallback;
import com.cyngn.eleven.widgets.NoResultsContainer;
import com.viewpagerindicator.TitlePageIndicator;
-import java.util.List;
-
/**
* This class is used to display all of the artists on a user's device.
*
private static final int GROUP_ID = 2;
/**
- * Grid view column count. ONE - list, TWO - normal grid, FOUR - landscape
- */
- private static final int ONE = 1, TWO = 2, FOUR = 4;
-
- /**
* LoaderCallbacks identifier
*/
private static final int LOADER = 0;
private SectionAdapter<Artist, ArtistAdapter> mAdapter;
/**
- * The grid view
- */
- private GridView mGridView;
-
- /**
* The list view
*/
private ListView mListView;
/**
- * Artist song list
- */
- private long[] mArtistList;
-
- /**
- * Represents an artist
+ * True if the list should execute {@code #restartLoader()}.
*/
- private Artist mArtist;
+ private boolean mShouldRefresh = false;
/**
- * True if the list should execute {@code #restartLoader()}.
+ * Pop up menu helper
*/
- private boolean mShouldRefresh = false;
+ private PopupMenuHelper mPopupMenuHelper;
/**
* Empty constructor as per the {@link Fragment} documentation
@Override
public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- // Create the adpater
+
+ mPopupMenuHelper = new PopupMenuHelper(getActivity(), getFragmentManager()) {
+ /**
+ * Represents an artist
+ */
+ private Artist mArtist;
+
+ @Override
+ protected PopupMenuType onPreparePopupMenu(int position) {
+ // Create a new model
+ mArtist = mAdapter.getTItem(position);
+
+ return PopupMenuType.Artist;
+ }
+
+ @Override
+ protected long[] getIdList() {
+ return MusicUtils.getSongListForArtist(getActivity(), mArtist.mArtistId);
+ }
+
+ @Override
+ protected int getGroupId() {
+ return GROUP_ID;
+ }
+
+ @Override
+ protected void onDeleteClicked() {
+ mShouldRefresh = true;
+ final String artist = mArtist.mArtistName;
+ DeleteDialog.newInstance(artist, getIdList(), artist).show(
+ getFragmentManager(), "DeleteDialog");
+ }
+
+ @Override
+ protected void setShouldRefresh() {
+ mShouldRefresh = true;
+ }
+ };
+
+ // Create the adapter
final int layout = R.layout.list_item_normal;
ArtistAdapter adapter = new ArtistAdapter(getActivity(), layout);
mAdapter = new SectionAdapter<Artist, ArtistAdapter>(getActivity(), adapter);
+ mAdapter.setPopupMenuClickedListener(new IPopupMenuCallback.IListener() {
+ @Override
+ public void onPopupMenuClicked(View v, int position) {
+ mPopupMenuHelper.showPopupMenu(v, position);
+ }
+ });
}
/**
* {@inheritDoc}
*/
@Override
- public void onCreateContextMenu(final ContextMenu menu, final View v,
- final ContextMenuInfo menuInfo) {
- super.onCreateContextMenu(menu, v, menuInfo);
-
- // Get the position of the selected item
- final AdapterContextMenuInfo info = (AdapterContextMenuInfo)menuInfo;
- // Creat a new model
- mArtist = mAdapter.getTItem(info.position);
- // Create a list of the artist's songs
- mArtistList = MusicUtils.getSongListForArtist(getActivity(), mArtist.mArtistId);
-
- // Play the artist
- menu.add(GROUP_ID, FragmentMenuItems.PLAY_SELECTION, Menu.NONE,
- getString(R.string.context_menu_play_selection));
-
- // Add the artist to the queue
- menu.add(GROUP_ID, FragmentMenuItems.ADD_TO_QUEUE, Menu.NONE,
- getString(R.string.add_to_queue));
-
- // Add the artist to a playlist
- final SubMenu subMenu = menu.addSubMenu(GROUP_ID, FragmentMenuItems.ADD_TO_PLAYLIST,
- Menu.NONE, R.string.add_to_playlist);
- MusicUtils.makePlaylistMenu(getActivity(), GROUP_ID, subMenu);
-
- // Delete the artist
- menu.add(GROUP_ID, FragmentMenuItems.DELETE, Menu.NONE,
- getString(R.string.context_menu_delete));
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public boolean onContextItemSelected(final android.view.MenuItem item) {
- // Avoid leaking context menu selections
- if (item.getGroupId() == GROUP_ID) {
- switch (item.getItemId()) {
- case FragmentMenuItems.PLAY_SELECTION:
- MusicUtils.playAll(getActivity(), mArtistList, 0, true);
- return true;
- case FragmentMenuItems.ADD_TO_QUEUE:
- MusicUtils.addToQueue(getActivity(), mArtistList);
- return true;
- case FragmentMenuItems.NEW_PLAYLIST:
- CreateNewPlaylist.getInstance(mArtistList).show(getFragmentManager(),
- "CreatePlaylist");
- return true;
- case FragmentMenuItems.PLAYLIST_SELECTED:
- final long id = item.getIntent().getLongExtra("playlist", 0);
- MusicUtils.addToPlaylist(getActivity(), mArtistList, id);
- return true;
- case FragmentMenuItems.DELETE:
- mShouldRefresh = true;
- final String artist = mArtist.mArtistName;
- DeleteDialog.newInstance(artist, mArtistList, artist).show(
- getFragmentManager(), "DeleteDialog");
- return true;
- default:
- break;
- }
- }
- return super.onContextItemSelected(item);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
public void onScrollStateChanged(final AbsListView view, final int scrollState) {
// Pause disk cache access to ensure smoother scrolling
if (scrollState == AbsListView.OnScrollListener.SCROLL_STATE_FLING
@Override
public void onItemClick(final AdapterView<?> parent, final View view, final int position,
final long id) {
- mArtist = mAdapter.getTItem(position);
- NavUtils.openArtistProfile(getActivity(), mArtist.mArtistName);
+ Artist artist = mAdapter.getTItem(position);
+ NavUtils.openArtistProfile(getActivity(), artist.mArtistName);
}
/**
private void initAbsListView(final AbsListView list) {
// Release any references to the recycled Views
list.setRecyclerListener(new RecycleHolder());
- // Listen for ContextMenus to be created
- list.setOnCreateContextMenuListener(this);
// Show the albums and songs from the selected artist
list.setOnItemClickListener(this);
// To help make scrolling smooth
@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
MusicUtils.makePlaylistMenu(getActivity(), GROUP_ID, menu);
+ menu.setHeaderTitle(R.string.add_to_playlist);
}
});
import android.app.Activity;
import android.app.AlertDialog;
import android.content.ContentUris;
-import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.support.v4.app.Fragment;
+import android.support.v4.app.FragmentManager;
import android.support.v4.app.LoaderManager.LoaderCallbacks;
import android.support.v4.content.Loader;
-import android.view.ContextMenu;
-import android.view.ContextMenu.ContextMenuInfo;
import android.view.LayoutInflater;
-import android.view.Menu;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
-import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView;
import com.cyngn.eleven.R;
import com.cyngn.eleven.adapters.PlaylistAdapter;
import com.cyngn.eleven.loaders.PlaylistLoader;
-import com.cyngn.eleven.menu.FragmentMenuItems;
-import com.cyngn.eleven.menu.RenamePlaylist;
import com.cyngn.eleven.model.Playlist;
import com.cyngn.eleven.recycler.RecycleHolder;
import com.cyngn.eleven.ui.activities.BaseActivity;
import com.cyngn.eleven.utils.MusicUtils;
import com.cyngn.eleven.utils.NavUtils;
+import com.cyngn.eleven.utils.PopupMenuHelper;
+import com.cyngn.eleven.widgets.IPopupMenuCallback;
import java.util.List;
private ListView mListView;
/**
- * Represents a playlist
+ * True if the list should execute {@code #restartLoader()}.
*/
- private Playlist mPlaylist;
+ private boolean mShouldRefresh = false;
+
+ /**
+ * Pop up menu helper
+ */
+ private PopupMenuHelper mPopupMenuHelper;
/**
* Empty constructor as per the {@link Fragment} documentation
@Override
public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ mPopupMenuHelper = new PopupMenuHelper(getActivity(), getFragmentManager()) {
+ /**
+ * Represents a playlist
+ */
+ private Playlist mPlaylist;
+
+ @Override
+ protected PopupMenuType onPreparePopupMenu(int position) {
+ // Create a new playlist
+ mPlaylist = mAdapter.getItem(position);
+
+ return mPlaylist.isSmartPlaylist() ?
+ PopupMenuType.SmartPlaylist : PopupMenuType.Playlist;
+ }
+
+ @Override
+ protected long[] getIdList() {
+ if (mPlaylist.isSmartPlaylist()) {
+ return MusicUtils.getSongListForSmartPlaylist(getActivity(),
+ SmartPlaylistType.getTypeById(mPlaylist.mPlaylistId));
+ } else {
+ return MusicUtils.getSongListForPlaylist(getActivity(),
+ mPlaylist.mPlaylistId);
+ }
+ }
+
+ @Override
+ protected int getGroupId() {
+ return GROUP_ID;
+ }
+
+ @Override
+ protected void onDeleteClicked() {
+ mShouldRefresh = true;
+ buildDeleteDialog(getId(), mPlaylist.mPlaylistName).show();
+ }
+
+ @Override
+ protected void setShouldRefresh() {
+ mShouldRefresh = true;
+ }
+
+ @Override
+ protected long getId() {
+ return mPlaylist.mPlaylistId;
+ }
+ };
+
// Create the adpater
mAdapter = new PlaylistAdapter(getActivity());
+ mAdapter.setPopupMenuClickedListener(new IPopupMenuCallback.IListener() {
+ @Override
+ public void onPopupMenuClicked(View v, int position) {
+ mPopupMenuHelper.showPopupMenu(v, position);
+ }
+ });
}
/**
mListView.setAdapter(mAdapter);
// Release any references to the recycled Views
mListView.setRecyclerListener(new RecycleHolder());
- // Listen for ContextMenus to be created
- mListView.setOnCreateContextMenuListener(this);
// Play the selected song
mListView.setOnItemClickListener(this);
return rootView;
* {@inheritDoc}
*/
@Override
- public void onCreateContextMenu(final ContextMenu menu, final View v,
- final ContextMenuInfo menuInfo) {
- super.onCreateContextMenu(menu, v, menuInfo);
-
- // Get the position of the selected item
- final AdapterContextMenuInfo info = (AdapterContextMenuInfo)menuInfo;
- final int mPosition = info.position;
- // Create a new playlist
- mPlaylist = mAdapter.getItem(mPosition);
-
- // Play the playlist
- menu.add(GROUP_ID, FragmentMenuItems.PLAY_SELECTION, Menu.NONE,
- R.string.context_menu_play_selection);
-
- // Add the playlist to the queue
- menu.add(GROUP_ID, FragmentMenuItems.ADD_TO_QUEUE, Menu.NONE, R.string.add_to_queue);
-
- // Delete and rename (user made playlists)
- if (info.position > 1) {
- menu.add(GROUP_ID, FragmentMenuItems.RENAME_PLAYLIST, Menu.NONE,
- R.string.context_menu_rename_playlist);
-
- menu.add(GROUP_ID, FragmentMenuItems.DELETE, Menu.NONE, R.string.context_menu_delete);
-
- }
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public boolean onContextItemSelected(final android.view.MenuItem item) {
- if (item.getGroupId() == GROUP_ID) {
- final AdapterContextMenuInfo info = (AdapterContextMenuInfo)item.getMenuInfo();
- switch (item.getItemId()) {
- case FragmentMenuItems.PLAY_SELECTION:
- if (info.position == 0) {
- MusicUtils.playLastAdded(getActivity());
- } else {
- MusicUtils.playPlaylist(getActivity(), mPlaylist.mPlaylistId);
- }
- return true;
- case FragmentMenuItems.ADD_TO_QUEUE:
- long[] list = null;
- if (info.position == 0) {
- list = MusicUtils.getSongListForLastAdded(getActivity());
- } else {
- list = MusicUtils.getSongListForPlaylist(getActivity(),
- mPlaylist.mPlaylistId);
- }
- MusicUtils.addToQueue(getActivity(), list);
- return true;
- case FragmentMenuItems.RENAME_PLAYLIST:
- RenamePlaylist.getInstance(mPlaylist.mPlaylistId).show(
- getFragmentManager(), "RenameDialog");
- return true;
- case FragmentMenuItems.DELETE:
- buildDeleteDialog().show();
- return true;
- default:
- break;
- }
- }
- return super.onContextItemSelected(item);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
public void onItemClick(final AdapterView<?> parent, final View view, final int position,
final long id) {
- mPlaylist = mAdapter.getItem(position);
+ Playlist playlist = mAdapter.getItem(position);
- SmartPlaylistType playlistType = SmartPlaylistType.getTypeById(mPlaylist.mPlaylistId);
+ SmartPlaylistType playlistType = SmartPlaylistType.getTypeById(playlist.mPlaylistId);
if (playlistType != null) {
NavUtils.openSmartPlaylist(getActivity(), playlistType);
} else {
- NavUtils.openPlaylist(getActivity(), mPlaylist.mPlaylistId, mPlaylist.mPlaylistName);
+ NavUtils.openPlaylist(getActivity(), playlist.mPlaylistId, playlist.mPlaylistName);
}
}
*/
@Override
public void restartLoader() {
- // Refresh the list when a playlist is deleted or renamed
- getLoaderManager().restartLoader(LOADER, null, this);
+ if (mShouldRefresh) {
+ getLoaderManager().restartLoader(LOADER, null, this);
+ }
+ mShouldRefresh = false;
}
/**
/**
* Create a new {@link AlertDialog} for easy playlist deletion
*
- * @param context The {@link Context} to use
- * @param title The title of the playlist being deleted
- * @param id The ID of the playlist being deleted
+ * @param playlistName The title of the playlist being deleted
+ * @param playlistId The ID of the playlist being deleted
* @return A new {@link AlertDialog} used to delete playlists
*/
- private final AlertDialog buildDeleteDialog() {
+ private final AlertDialog buildDeleteDialog(final long playlistId, final String playlistName) {
return new AlertDialog.Builder(getActivity())
- .setTitle(getString(R.string.delete_dialog_title, mPlaylist.mPlaylistName))
+ .setTitle(getString(R.string.delete_dialog_title, playlistName))
.setPositiveButton(R.string.context_menu_delete, new OnClickListener() {
@Override
public void onClick(final DialogInterface dialog, final int which) {
final Uri mUri = ContentUris.withAppendedId(
MediaStore.Audio.Playlists.EXTERNAL_CONTENT_URI,
- mPlaylist.mPlaylistId);
+ playlistId);
getActivity().getContentResolver().delete(mUri, null, null);
MusicUtils.refresh();
}
import android.os.Bundle;
import android.os.IBinder;
import android.support.v4.app.Fragment;
+import android.support.v4.app.FragmentManager;
import android.support.v4.app.LoaderManager.LoaderCallbacks;
import android.support.v4.content.Loader;
-import android.view.ContextMenu;
-import android.view.ContextMenu.ContextMenuInfo;
import android.view.LayoutInflater;
-import android.view.Menu;
-import android.view.MenuInflater;
import android.view.MenuItem;
-import android.view.SubMenu;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
-import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.AdapterView.OnItemClickListener;
import com.cyngn.eleven.MusicPlaybackService;
import com.cyngn.eleven.dragdrop.DragSortListView.RemoveListener;
import com.cyngn.eleven.loaders.NowPlayingCursor;
import com.cyngn.eleven.loaders.QueueLoader;
-import com.cyngn.eleven.menu.CreateNewPlaylist;
import com.cyngn.eleven.menu.DeleteDialog;
import com.cyngn.eleven.menu.FragmentMenuItems;
import com.cyngn.eleven.model.Song;
import com.cyngn.eleven.recycler.RecycleHolder;
import com.cyngn.eleven.utils.MusicUtils;
-import com.cyngn.eleven.utils.NavUtils;
+import com.cyngn.eleven.utils.PopupMenuHelper;
+import com.cyngn.eleven.widgets.IPopupMenuCallback;
import com.cyngn.eleven.widgets.PlayPauseProgressButton;
-import com.viewpagerindicator.TitlePageIndicator;
import java.lang.ref.WeakReference;
import java.util.List;
private DragSortListView mListView;
/**
- * Represents a song
+ * Pop up menu helper
*/
- private Song mSong;
-
- /**
- * Position of a context menu item
- */
- private int mSelectedPosition;
-
- /**
- * Id of a context menu item
- */
- private long mSelectedId;
-
- /**
- * Song, album, and artist name used in the context menu
- */
- private String mSongName, mAlbumName, mArtistName;
+ private PopupMenuHelper mPopupMenuHelper;
/**
* Empty constructor as per the {@link Fragment} documentation
@Override
public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ mPopupMenuHelper = new PopupMenuHelper(getActivity(), getFragmentManager()) {
+ private Song mSong;
+ private int mSelectedPosition;
+
+ @Override
+ protected PopupMenuType onPreparePopupMenu(int position) {
+ mSelectedPosition = position;
+ mSong = mAdapter.getItem(mSelectedPosition);
+
+ return PopupMenuType.Queue;
+ }
+
+ @Override
+ protected long[] getIdList() {
+ return new long[] { mSong.mSongId };
+ }
+
+ @Override
+ protected int getGroupId() {
+ return GROUP_ID;
+ }
+
+ @Override
+ protected long getId() {
+ return mSong.mSongId;
+ }
+
+ @Override
+ protected String getArtistName() {
+ return mSong.mArtistName;
+ }
+
+ @Override
+ protected void onDeleteClicked() {
+ DeleteDialog.newInstance(mSong.mSongName,
+ new long[] { getId() }, null).show(getFragmentManager(), "DeleteDialog");
+ }
+
+ @Override
+ protected void setShouldRefresh() {
+ // do nothing
+ }
+
+ @Override
+ protected void playNext() {
+ NowPlayingCursor queue = (NowPlayingCursor)QueueLoader
+ .makeQueueCursor(getActivity());
+ queue.removeItem(mSelectedPosition);
+ queue.close();
+ queue = null;
+ MusicUtils.playNext(getIdList());
+ refreshQueue();
+ }
+
+ @Override
+ protected void removeFromQueue() {
+ MusicUtils.removeTrack(getId());
+ refreshQueue();
+ }
+ };
+
// Create the adpater
mAdapter = new SongAdapter(getActivity(), R.layout.edit_queue_list_item);
+ mAdapter.setPopupMenuClickedListener(new IPopupMenuCallback.IListener() {
+ @Override
+ public void onPopupMenuClicked(View v, int position) {
+ mPopupMenuHelper.showPopupMenu(v, position);
+ }
+ });
}
/**
mListView.setAdapter(mAdapter);
// Release any references to the recycled Views
mListView.setRecyclerListener(new RecycleHolder());
- // Listen for ContextMenus to be created
- mListView.setOnCreateContextMenuListener(this);
// Play the selected song
mListView.setOnItemClickListener(this);
// Set the drop listener
* {@inheritDoc}
*/
@Override
- public void onCreateContextMenu(final ContextMenu menu, final View v,
- final ContextMenuInfo menuInfo) {
- super.onCreateContextMenu(menu, v, menuInfo);
- // Get the position of the selected item
- final AdapterContextMenuInfo info = (AdapterContextMenuInfo)menuInfo;
- mSelectedPosition = info.position;
- // Creat a new song
- mSong = mAdapter.getItem(mSelectedPosition);
- mSelectedId = mSong.mSongId;
- mSongName = mSong.mSongName;
- mAlbumName = mSong.mAlbumName;
- mArtistName = mSong.mArtistName;
-
- // Play the song next
- menu.add(GROUP_ID, FragmentMenuItems.PLAY_NEXT, Menu.NONE,
- getString(R.string.context_menu_play_next));
-
- // Add the song to a playlist
- final SubMenu subMenu = menu.addSubMenu(GROUP_ID, FragmentMenuItems.ADD_TO_PLAYLIST,
- Menu.NONE, R.string.add_to_playlist);
- MusicUtils.makePlaylistMenu(getActivity(), GROUP_ID, subMenu);
-
- // Remove the song from the queue
- menu.add(GROUP_ID, FragmentMenuItems.REMOVE_FROM_QUEUE, Menu.NONE,
- getString(R.string.remove_from_queue));
-
- // View more content by the song artist
- menu.add(GROUP_ID, FragmentMenuItems.MORE_BY_ARTIST, Menu.NONE,
- getString(R.string.context_menu_more_by_artist));
-
- // Make the song a ringtone
- menu.add(GROUP_ID, FragmentMenuItems.USE_AS_RINGTONE, Menu.NONE,
- getString(R.string.context_menu_use_as_ringtone));
-
- // Delete the song
- menu.add(GROUP_ID, FragmentMenuItems.DELETE, Menu.NONE,
- getString(R.string.context_menu_delete));
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public boolean onContextItemSelected(final android.view.MenuItem item) {
- if (item.getGroupId() == GROUP_ID) {
- switch (item.getItemId()) {
- case FragmentMenuItems.PLAY_NEXT:
- NowPlayingCursor queue = (NowPlayingCursor)QueueLoader
- .makeQueueCursor(getActivity());
- queue.removeItem(mSelectedPosition);
- queue.close();
- queue = null;
- MusicUtils.playNext(new long[] {
- mSelectedId
- });
- refreshQueue();
- return true;
- case FragmentMenuItems.REMOVE_FROM_QUEUE:
- MusicUtils.removeTrack(mSelectedId);
- refreshQueue();
- return true;
- case FragmentMenuItems.NEW_PLAYLIST:
- CreateNewPlaylist.getInstance(new long[] {
- mSelectedId
- }).show(getFragmentManager(), "CreatePlaylist");
- return true;
- case FragmentMenuItems.PLAYLIST_SELECTED:
- final long mPlaylistId = item.getIntent().getLongExtra("playlist", 0);
- MusicUtils.addToPlaylist(getActivity(), new long[] {
- mSelectedId
- }, mPlaylistId);
- return true;
- case FragmentMenuItems.MORE_BY_ARTIST:
- NavUtils.openArtistProfile(getActivity(), mArtistName);
- return true;
- case FragmentMenuItems.USE_AS_RINGTONE:
- MusicUtils.setRingtone(getActivity(), mSelectedId);
- return true;
- case FragmentMenuItems.DELETE:
- DeleteDialog.newInstance(mSong.mSongName, new long[] {
- mSelectedId
- }, null).show(getFragmentManager(), "DeleteDialog");
- return true;
- default:
- break;
- }
- }
- return super.onContextItemSelected(item);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
public void onItemClick(final AdapterView<?> parent, final View view, final int position,
final long id) {
// When selecting a track from the queue, just jump there instead of
*/
@Override
public void remove(final int which) {
- mSong = mAdapter.getItem(which);
- mAdapter.remove(mSong);
+ Song song = mAdapter.getItem(which);
+ mAdapter.remove(song);
mAdapter.notifyDataSetChanged();
- MusicUtils.removeTrack(mSong.mSongId);
+ MusicUtils.removeTrack(song.mSongId);
// Build the cache
mAdapter.buildCache();
}
*/
@Override
public void drop(final int from, final int to) {
- mSong = mAdapter.getItem(from);
- mAdapter.remove(mSong);
- mAdapter.insert(mSong, to);
+ Song song = mAdapter.getItem(from);
+ mAdapter.remove(song);
+ mAdapter.insert(song, to);
mAdapter.notifyDataSetChanged();
MusicUtils.moveQueueItem(from, to);
// Build the cache
}
/**
- * Scrolls the list to the currently playing song when the user touches the
- * header in the {@link TitlePageIndicator}.
- */
- public void scrollToCurrentSong() {
- final int currentSongPosition = getItemPositionBySong();
-
- if (currentSongPosition != 0) {
- mListView.setSelection(currentSongPosition);
- }
- }
-
- /**
- * @return The position of an item in the list based on the name of the
- * currently playing song.
- */
- private int getItemPositionBySong() {
- final long trackId = MusicUtils.getCurrentAudioId();
- if (mAdapter == null) {
- return 0;
- }
- for (int i = 0; i < mAdapter.getCount(); i++) {
- if (mAdapter.getItem(i).mSongId == trackId) {
- return i;
- }
- }
- return 0;
- }
-
- /**
* Called to restart the loader callbacks
*/
public void refreshQueue() {
package com.cyngn.eleven.ui.fragments;
-import android.app.Activity;
-import android.database.Cursor;
import android.os.Bundle;
import android.support.v4.content.Loader;
import android.view.Menu;
-import android.view.MenuItem;
-import android.view.View;
-import android.view.ContextMenu;
-import android.view.ContextMenu.ContextMenuInfo;
+import com.cyngn.eleven.Config;
import com.cyngn.eleven.MusicStateListener;
import com.cyngn.eleven.R;
import com.cyngn.eleven.loaders.TopTracksLoader;
import com.cyngn.eleven.menu.FragmentMenuItems;
import com.cyngn.eleven.model.Song;
-import com.cyngn.eleven.provider.RecentStore;
-import com.cyngn.eleven.ui.activities.BaseActivity;
+import com.cyngn.eleven.sectionadapter.SectionCreator;
+import com.cyngn.eleven.sectionadapter.SectionListContainer;
import com.cyngn.eleven.ui.fragments.profile.BasicSongFragment;
import com.cyngn.eleven.utils.MusicUtils;
import com.cyngn.eleven.widgets.NoResultsContainer;
-import java.util.List;
+import java.util.ArrayList;
/**
* This class is used to display all of the recently listened to songs by the
*/
private static final int LOADER = 0;
- /**
- * True if the list should execute {@code #restartLoader()}.
- */
- private boolean mShouldRefresh = false;
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void onAttach(final Activity activity) {
- super.onAttach(activity);
- // Register the music status listener
- ((BaseActivity)activity).setMusicStateListenerListener(this);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void onCreateContextMenu(final ContextMenu menu, final View v,
- final ContextMenuInfo menuInfo) {
- super.onCreateContextMenu(menu, v, menuInfo);
-
- // Remove the album from the list
- menu.add(GROUP_ID, FragmentMenuItems.REMOVE_FROM_RECENT, Menu.NONE,
- getString(R.string.context_menu_remove_from_recent));
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public boolean onContextItemSelected(final MenuItem item) {
- // Avoid leaking context menu selections
- if (item.getGroupId() == GROUP_ID) {
- switch (item.getItemId()) {
- case FragmentMenuItems.REMOVE_FROM_RECENT:
- mShouldRefresh = true;
- RecentStore.getInstance(getActivity()).removeItem(mSelectedId);
- MusicUtils.refresh();
- return true;
- default:
- break;
- }
- }
- return super.onContextItemSelected(item);
- }
-
- /**
- * {@inheritDoc}
- */
@Override
- public Loader<List<Song>> onCreateLoader(final int id, final Bundle args) {
- return new TopTracksLoader(getActivity(), TopTracksLoader.QueryType.RecentSongs);
+ protected void getAdditionaIdsForType(ArrayList<Integer> list) {
+ list.add(FragmentMenuItems.REMOVE_FROM_RECENT);
}
/**
* {@inheritDoc}
*/
@Override
- public void restartLoader() {
- // Update the list when the user deletes any items
- if (mShouldRefresh) {
- getLoaderManager().restartLoader(LOADER, null, this);
- }
- mShouldRefresh = false;
+ public Loader<SectionListContainer<Song>> onCreateLoader(final int id, final Bundle args) {
+ TopTracksLoader loader = new TopTracksLoader(getActivity(),
+ TopTracksLoader.QueryType.RecentSongs);
+ return new SectionCreator<Song>(getActivity(), loader, null);
}
/**
*/
@Override
public void onMetaChanged() {
+ // refresh the list since a track playing means it should be recently played
getLoaderManager().restartLoader(LOADER, null, this);
}
@Override
public void playAll(int position) {
- Cursor cursor = TopTracksLoader.makeRecentTracksCursor(getActivity());
- final long[] list = MusicUtils.getSongListForCursor(cursor);
- MusicUtils.playAll(getActivity(), list, position, false);
- cursor.close();
- cursor = null;
+ MusicUtils.playSmartPlaylist(getActivity(), position,
+ Config.SmartPlaylistType.RecentlyPlayed);
}
@Override
package com.cyngn.eleven.ui.fragments;
-import android.app.Activity;
import android.content.Context;
import android.database.Cursor;
import android.os.Bundle;
-import android.os.SystemClock;
-import android.support.v4.app.Fragment;
-import android.support.v4.app.LoaderManager.LoaderCallbacks;
import android.support.v4.content.Loader;
-import android.text.TextUtils;
-import android.view.ContextMenu;
-import android.view.ContextMenu.ContextMenuInfo;
-import android.view.LayoutInflater;
-import android.view.Menu;
-import android.view.SubMenu;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.AbsListView;
-import android.widget.AbsListView.OnScrollListener;
-import android.widget.AdapterView;
-import android.widget.AdapterView.AdapterContextMenuInfo;
-import android.widget.AdapterView.OnItemClickListener;
-import android.widget.ListView;
-import android.widget.TextView;
-import com.cyngn.eleven.MusicStateListener;
-import com.cyngn.eleven.R;
-import com.cyngn.eleven.adapters.SongAdapter;
import com.cyngn.eleven.loaders.SongLoader;
-import com.cyngn.eleven.menu.CreateNewPlaylist;
-import com.cyngn.eleven.menu.DeleteDialog;
-import com.cyngn.eleven.menu.FragmentMenuItems;
import com.cyngn.eleven.model.Song;
-import com.cyngn.eleven.recycler.RecycleHolder;
-import com.cyngn.eleven.sectionadapter.SectionAdapter;
import com.cyngn.eleven.sectionadapter.SectionCreator;
import com.cyngn.eleven.sectionadapter.SectionListContainer;
-import com.cyngn.eleven.ui.activities.BaseActivity;
+import com.cyngn.eleven.ui.fragments.profile.BasicSongFragment;
import com.cyngn.eleven.utils.MusicUtils;
-import com.cyngn.eleven.utils.NavUtils;
import com.cyngn.eleven.utils.SectionCreatorUtils;
-import com.cyngn.eleven.widgets.NoResultsContainer;
import com.viewpagerindicator.TitlePageIndicator;
-import java.util.List;
-
/**
* This class is used to display all of the songs on a user's device.
- *
+ *
* @author Andrew Neal (andrewdneal@gmail.com)
*/
-public class SongFragment extends Fragment implements LoaderCallbacks<SectionListContainer<Song>>,
- OnScrollListener, OnItemClickListener, MusicStateListener {
+public class SongFragment extends BasicSongFragment {
/**
* Used to keep context menu items from bleeding into other fragments
private static final int LOADER = 0;
/**
- * Fragment UI
- */
- private ViewGroup mRootView;
-
- /**
- * The adapter for the list
- */
- private SectionAdapter<Song, SongAdapter> mAdapter;
-
- /**
- * The list view
- */
- private ListView mListView;
-
- /**
- * Represents a song
- */
- private Song mSong;
-
- /**
- * Position of a context menu item
- */
- private int mSelectedPosition;
-
- /**
- * Id of a context menu item
- */
- private long mSelectedId;
-
- /**
- * Song, album, and artist name used in the context menu
- */
- private String mSongName, mAlbumName, mArtistName;
-
- /**
- * True if the list should execute {@code #restartLoader()}.
- */
- private boolean mShouldRefresh = false;
-
- /**
- * Empty constructor as per the {@link Fragment} documentation
- */
- public SongFragment() {
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void onAttach(final Activity activity) {
- super.onAttach(activity);
- // Register the music status listener
- ((BaseActivity)activity).setMusicStateListenerListener(this);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void onCreate(final Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- // Create the adpater
- mAdapter = new SectionAdapter<Song, SongAdapter>(getActivity(), new SongAdapter(getActivity(), R.layout.list_item_normal));
- }
-
- /**
- * {@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);
- // 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());
- // Listen for ContextMenus to be created
- mListView.setOnCreateContextMenuListener(this);
- // Play the selected song
- mListView.setOnItemClickListener(this);
- // To help make scrolling smooth
- mListView.setOnScrollListener(this);
- return mRootView;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void onActivityCreated(final Bundle savedInstanceState) {
- super.onActivityCreated(savedInstanceState);
- // Enable the options menu
- setHasOptionsMenu(true);
- // Start the loader
- getLoaderManager().initLoader(LOADER, null, this);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void onCreateContextMenu(final ContextMenu menu, final View v,
- final ContextMenuInfo menuInfo) {
- super.onCreateContextMenu(menu, v, menuInfo);
- // Get the position of the selected item
- final AdapterContextMenuInfo info = (AdapterContextMenuInfo)menuInfo;
- mSelectedPosition = info.position;
- // Creat a new song
- mSong = mAdapter.getTItem(mSelectedPosition);
- mSelectedId = mSong.mSongId;
- mSongName = mSong.mSongName;
- mAlbumName = mSong.mAlbumName;
- mArtistName = mSong.mArtistName;
-
- // Play the song
- menu.add(GROUP_ID, FragmentMenuItems.PLAY_SELECTION, Menu.NONE,
- getString(R.string.context_menu_play_selection));
-
- // Play next
- menu.add(GROUP_ID, FragmentMenuItems.PLAY_NEXT, Menu.NONE,
- getString(R.string.context_menu_play_next));
-
- // Add the song to the queue
- menu.add(GROUP_ID, FragmentMenuItems.ADD_TO_QUEUE, Menu.NONE,
- getString(R.string.add_to_queue));
-
- // Add the song to a playlist
- final SubMenu subMenu = menu.addSubMenu(GROUP_ID, FragmentMenuItems.ADD_TO_PLAYLIST,
- Menu.NONE, R.string.add_to_playlist);
- MusicUtils.makePlaylistMenu(getActivity(), GROUP_ID, subMenu);
-
- // View more content by the song artist
- menu.add(GROUP_ID, FragmentMenuItems.MORE_BY_ARTIST, Menu.NONE,
- getString(R.string.context_menu_more_by_artist));
-
- // Make the song a ringtone
- menu.add(GROUP_ID, FragmentMenuItems.USE_AS_RINGTONE, Menu.NONE,
- getString(R.string.context_menu_use_as_ringtone));
-
- // Delete the song
- menu.add(GROUP_ID, FragmentMenuItems.DELETE, Menu.NONE,
- getString(R.string.context_menu_delete));
- }
-
- @Override
- public boolean onContextItemSelected(final android.view.MenuItem item) {
- if (item.getGroupId() == GROUP_ID) {
- switch (item.getItemId()) {
- case FragmentMenuItems.PLAY_SELECTION:
- MusicUtils.playAll(getActivity(), new long[] {
- mSelectedId
- }, 0, false);
- return true;
- case FragmentMenuItems.PLAY_NEXT:
- MusicUtils.playNext(new long[] {
- mSelectedId
- });
- return true;
- case FragmentMenuItems.ADD_TO_QUEUE:
- MusicUtils.addToQueue(getActivity(), new long[] {
- mSelectedId
- });
- return true;
- case FragmentMenuItems.NEW_PLAYLIST:
- CreateNewPlaylist.getInstance(new long[] {
- mSelectedId
- }).show(getFragmentManager(), "CreatePlaylist");
- return true;
- case FragmentMenuItems.PLAYLIST_SELECTED:
- final long mPlaylistId = item.getIntent().getLongExtra("playlist", 0);
- MusicUtils.addToPlaylist(getActivity(), new long[] {
- mSelectedId
- }, mPlaylistId);
- return true;
- case FragmentMenuItems.MORE_BY_ARTIST:
- NavUtils.openArtistProfile(getActivity(), mArtistName);
- return true;
- case FragmentMenuItems.USE_AS_RINGTONE:
- MusicUtils.setRingtone(getActivity(), mSelectedId);
- return true;
- case FragmentMenuItems.DELETE:
- mShouldRefresh = true;
- DeleteDialog.newInstance(mSong.mSongName, new long[] {
- mSelectedId
- }, null).show(getFragmentManager(), "DeleteDialog");
- return true;
- default:
- break;
- }
- }
- return super.onContextItemSelected(item);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void onScrollStateChanged(final AbsListView view, final int scrollState) {
- // Pause disk cache access to ensure smoother scrolling
- if (scrollState == AbsListView.OnScrollListener.SCROLL_STATE_FLING
- || scrollState == AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL) {
- mAdapter.getUnderlyingAdapter().setPauseDiskCache(true);
- } else {
- mAdapter.getUnderlyingAdapter().setPauseDiskCache(false);
- mAdapter.notifyDataSetChanged();
- }
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void onScroll(final AbsListView view, final int firstVisibleItem,
- final int visibleItemCount, final int totalItemCount) {
- // Nothing to do
- }
-
- /**
* {@inheritDoc}
*/
- @Override
- public void onItemClick(final AdapterView<?> parent, final View view, final int position,
- final long id) {
+ public void playAll(int position) {
int internalPosition = mAdapter.getInternalPosition(position);
Cursor cursor = SongLoader.makeSongCursor(getActivity(), null);
final long[] list = MusicUtils.getSongListForCursor(cursor);
return new SectionCreator<Song>(context, songLoader, songComparison);
}
- /**
- * {@inheritDoc}
- */
- @Override
- public void onLoadFinished(final Loader<SectionListContainer<Song>> loader, final SectionListContainer<Song> data) {
- // Check for any errors
- if (data.mListResults.isEmpty()) {
- // Set the empty text
- final NoResultsContainer empty = (NoResultsContainer)mRootView.findViewById(R.id.no_results_container);
- mListView.setEmptyView(empty);
- return;
- }
- // Set the data
- mAdapter.setData(data);
+ @Override
+ public int getGroupId() {
+ return GROUP_ID;
}
- /**
- * {@inheritDoc}
- */
@Override
- public void onLoaderReset(final Loader<SectionListContainer<Song>> loader) {
- // Clear the data in the adapter
- mAdapter.unload();
+ public int getLoaderId() {
+ return LOADER;
}
/**
/**
* @return The position of an item in the list based on the name of the
- * currently playing song.
+ * currently playing song.
*/
private int getItemPositionBySong() {
final long trackId = MusicUtils.getCurrentAudioId();
return position;
}
-
- /**
- * Restarts the loader.
- */
- public void refresh() {
- // Wait a moment for the preference to change.
- SystemClock.sleep(10);
- getLoaderManager().restartLoader(LOADER, null, this);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void restartLoader() {
- // Update the list when the user deletes any items
- if (mShouldRefresh) {
- getLoaderManager().restartLoader(LOADER, null, this);
- }
- mShouldRefresh = false;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void onMetaChanged() {
- // Nothing to do
- }
}
package com.cyngn.eleven.ui.fragments.profile;
+import android.app.Activity;
import android.os.Bundle;
+import android.os.SystemClock;
import android.support.v4.app.Fragment;
import android.support.v4.app.LoaderManager.LoaderCallbacks;
import android.support.v4.content.Loader;
-import android.view.ContextMenu;
-import android.view.ContextMenu.ContextMenuInfo;
import android.view.LayoutInflater;
-import android.view.Menu;
-import android.view.SubMenu;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.AdapterView;
-import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView;
-import android.widget.TextView;
+import com.cyngn.eleven.MusicStateListener;
import com.cyngn.eleven.R;
import com.cyngn.eleven.adapters.SongAdapter;
-import com.cyngn.eleven.menu.CreateNewPlaylist;
import com.cyngn.eleven.menu.DeleteDialog;
-import com.cyngn.eleven.menu.FragmentMenuItems;
import com.cyngn.eleven.model.Song;
import com.cyngn.eleven.recycler.RecycleHolder;
-import com.cyngn.eleven.utils.MusicUtils;
-import com.cyngn.eleven.utils.NavUtils;
+import com.cyngn.eleven.sectionadapter.SectionAdapter;
+import com.cyngn.eleven.sectionadapter.SectionListContainer;
+import com.cyngn.eleven.ui.activities.BaseActivity;
+import com.cyngn.eleven.utils.PopupMenuHelper;
+import com.cyngn.eleven.widgets.IPopupMenuCallback;
import com.cyngn.eleven.widgets.NoResultsContainer;
-import java.util.List;
+import java.util.ArrayList;
/**
* This class is used to display all of the songs
*
* @author Andrew Neal (andrewdneal@gmail.com)
*/
-public abstract class BasicSongFragment extends Fragment implements LoaderCallbacks<List<Song>>,
- OnItemClickListener {
+public abstract class BasicSongFragment extends Fragment implements
+ LoaderCallbacks<SectionListContainer<Song>>, OnItemClickListener, MusicStateListener {
/**
* Fragment UI
/**
* The adapter for the list
*/
- protected SongAdapter mAdapter;
+ protected SectionAdapter<Song, SongAdapter> mAdapter;
/**
* The list view
protected ListView mListView;
/**
- * Represents a song
+ * True if the list should execute {@code #restartLoader()}.
*/
- protected Song mSong;
+ protected boolean mShouldRefresh = false;
/**
- * Position of a context menu item
+ * Pop up menu helper
*/
- protected int mSelectedPosition;
+ private PopupMenuHelper mPopupMenuHelper;
/**
- * Id of a context menu item
- */
- protected long mSelectedId;
-
- /**
- * Song, album, and artist name used in the context menu
+ * Empty constructor as per the {@link Fragment} documentation
*/
- protected String mSongName, mAlbumName, mArtistName;
+ public BasicSongFragment() {
+ }
/**
- * Empty constructor as per the {@link Fragment} documentation
+ * {@inheritDoc}
*/
- public BasicSongFragment() {
+ @Override
+ public void onAttach(final Activity activity) {
+ super.onAttach(activity);
+ // Register the music status listener
+ ((BaseActivity)activity).setMusicStateListenerListener(this);
}
/**
@Override
public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- // Create the adpater
+ mPopupMenuHelper = new PopupMenuHelper(getActivity(), getFragmentManager()) {
+ /**
+ * Represents a song
+ */
+ protected Song mSong;
+
+ @Override
+ protected PopupMenuHelper.PopupMenuType onPreparePopupMenu(int position) {
+ // Create a new song
+ mSong = mAdapter.getTItem(position);
+
+ return PopupMenuType.Song;
+ }
+
+ @Override
+ protected void getAdditionalIds(PopupMenuType type, ArrayList<Integer> list) {
+ super.getAdditionalIds(type, list);
+ BasicSongFragment.this.getAdditionaIdsForType(list);
+ }
+
+ @Override
+ protected long[] getIdList() {
+ return new long[] { mSong.mSongId };
+ }
+
+ @Override
+ protected int getGroupId() {
+ return BasicSongFragment.this.getGroupId();
+ }
+
+ @Override
+ protected void onDeleteClicked() {
+ mShouldRefresh = true;
+ DeleteDialog.newInstance(mSong.mSongName, getIdList(), null).show(
+ getFragmentManager(), "DeleteDialog");
+ }
+
+ @Override
+ protected void setShouldRefresh() {
+ mShouldRefresh = true;
+ }
+
+ @Override
+ protected long getId() {
+ return mSong.mSongId;
+ }
+
+ @Override
+ protected String getArtistName() {
+ return mSong.mArtistName;
+ }
+ };
+
+ // Create the adapter
mAdapter = createAdapter();
+ mAdapter.setPopupMenuClickedListener(new IPopupMenuCallback.IListener() {
+ @Override
+ public void onPopupMenuClicked(View v, int position) {
+ mPopupMenuHelper.showPopupMenu(v, position);
+ }
+ });
+ }
+
+ protected void getAdditionaIdsForType(ArrayList<Integer> list) {
+ // do nothing - let subclasses override
}
/**
mListView.setAdapter(mAdapter);
// Release any references to the recycled Views
mListView.setRecyclerListener(new RecycleHolder());
- // Listen for ContextMenus to be created
- mListView.setOnCreateContextMenuListener(this);
// Play the selected song
mListView.setOnItemClickListener(this);
// To help make scrolling smooth
// Pause disk cache access to ensure smoother scrolling
if (scrollState == AbsListView.OnScrollListener.SCROLL_STATE_FLING
|| scrollState == AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL) {
- mAdapter.setPauseDiskCache(true);
+ mAdapter.getUnderlyingAdapter().setPauseDiskCache(true);
} else {
- mAdapter.setPauseDiskCache(false);
+ mAdapter.getUnderlyingAdapter().setPauseDiskCache(false);
mAdapter.notifyDataSetChanged();
}
}
@Override
public void onActivityCreated(final Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
- // Enable the options menu
- setHasOptionsMenu(true);
// Start the loader
getLoaderManager().initLoader(getLoaderId(), null, this);
}
* {@inheritDoc}
*/
@Override
- public void onCreateContextMenu(final ContextMenu menu, final View v,
- final ContextMenuInfo menuInfo) {
- super.onCreateContextMenu(menu, v, menuInfo);
- // Get the position of the selected item
- final AdapterContextMenuInfo info = (AdapterContextMenuInfo) menuInfo;
- mSelectedPosition = info.position;
- // Creat a new song
- mSong = mAdapter.getItem(mSelectedPosition);
- mSelectedId = mSong.mSongId;
- mSongName = mSong.mSongName;
- mAlbumName = mSong.mAlbumName;
- mArtistName = mSong.mArtistName;
-
- // Play the song
- menu.add(getGroupId(), FragmentMenuItems.PLAY_SELECTION, Menu.NONE,
- getString(R.string.context_menu_play_selection));
-
- // Play next
- menu.add(getGroupId(), FragmentMenuItems.PLAY_NEXT, Menu.NONE,
- getString(R.string.context_menu_play_next));
-
- // Add the song to the queue
- menu.add(getGroupId(), FragmentMenuItems.ADD_TO_QUEUE, Menu.NONE,
- getString(R.string.add_to_queue));
-
- // Add the song to a playlist
- final SubMenu subMenu = menu.addSubMenu(getGroupId(), FragmentMenuItems.ADD_TO_PLAYLIST,
- Menu.NONE, R.string.add_to_playlist);
- MusicUtils.makePlaylistMenu(getActivity(), getGroupId(), subMenu);
-
- // View more content by the song artist
- menu.add(getGroupId(), FragmentMenuItems.MORE_BY_ARTIST, Menu.NONE,
- getString(R.string.context_menu_more_by_artist));
-
- // Make the song a ringtone
- menu.add(getGroupId(), FragmentMenuItems.USE_AS_RINGTONE, Menu.NONE,
- getString(R.string.context_menu_use_as_ringtone));
-
- // Delete the song
- menu.add(getGroupId(), FragmentMenuItems.DELETE, Menu.NONE,
- getString(R.string.context_menu_delete));
- }
-
- @Override
- public boolean onContextItemSelected(final android.view.MenuItem item) {
- if (item.getGroupId() == getGroupId()) {
- switch (item.getItemId()) {
- case FragmentMenuItems.PLAY_SELECTION:
- MusicUtils.playAll(getActivity(), new long[]{
- mSelectedId
- }, 0, false);
- return true;
- case FragmentMenuItems.PLAY_NEXT:
- MusicUtils.playNext(new long[]{
- mSelectedId
- });
- return true;
- case FragmentMenuItems.ADD_TO_QUEUE:
- MusicUtils.addToQueue(getActivity(), new long[]{
- mSelectedId
- });
- return true;
- case FragmentMenuItems.NEW_PLAYLIST:
- CreateNewPlaylist.getInstance(new long[]{
- mSelectedId
- }).show(getFragmentManager(), "CreatePlaylist");
- return true;
- case FragmentMenuItems.PLAYLIST_SELECTED:
- final long mPlaylistId = item.getIntent().getLongExtra("playlist", 0);
- MusicUtils.addToPlaylist(getActivity(), new long[]{
- mSelectedId
- }, mPlaylistId);
- return true;
- case FragmentMenuItems.MORE_BY_ARTIST:
- NavUtils.openArtistProfile(getActivity(), mArtistName);
- return true;
- case FragmentMenuItems.USE_AS_RINGTONE:
- MusicUtils.setRingtone(getActivity(), mSelectedId);
- return true;
- case FragmentMenuItems.DELETE:
- // TODO: Smarter refresh
- DeleteDialog.newInstance(mSong.mSongName, new long[]{
- mSelectedId
- }, null).show(getFragmentManager(), "DeleteDialog");
- return true;
- default:
- break;
- }
- }
- return super.onContextItemSelected(item);
- }
-
- /**
- * {@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<List<Song>> loader, final List<Song> data) {
+ public void onLoadFinished(final Loader<SectionListContainer<Song>> loader,
+ final SectionListContainer<Song> data) {
// Check for any errors
- if (data.isEmpty()) {
+ if (data.mListResults.isEmpty()) {
// Set the empty text
- final NoResultsContainer empty = (NoResultsContainer)mRootView.findViewById(R.id.no_results_container);
+ final NoResultsContainer empty =
+ (NoResultsContainer)mRootView.findViewById(R.id.no_results_container);
// Setup the container strings
setupNoResultsContainer(empty);
// set the empty view into the list view
}
// Start fresh
- mAdapter.unload();
- // Add the data to the adpater
- for (final Song song : data) {
- mAdapter.add(song);
- }
+ mAdapter.setData(data);
+ }
- // Build the cache
- mAdapter.buildCache();
+ /**
+ * Restarts the loader.
+ */
+ public void refresh() {
+ // Wait a moment for the preference to change.
+ SystemClock.sleep(10);
+ getLoaderManager().restartLoader(getLoaderId(), null, this);
}
+ /**
+ * {@inheritDoc}
+ */
+ @Override
public void restartLoader() {
- getLoaderManager().restartLoader(getLoaderId(), null, this);
+ // Update the list when the user deletes any items
+ if (mShouldRefresh) {
+ getLoaderManager().restartLoader(getLoaderId(), null, this);
+ }
+ mShouldRefresh = false;
}
/**
* {@inheritDoc}
*/
@Override
- public void onLoaderReset(final Loader<List<Song>> loader) {
+ 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
+ * 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
+ protected SectionAdapter<Song, SongAdapter> createAdapter() {
+ return new SectionAdapter(getActivity(),
+ new SongAdapter(
+ getActivity(),
+ R.layout.list_item_normal
+ )
);
}
+ @Override
+ public void onMetaChanged() {
+ // do nothing
+ }
/**
* Used to keep context menu items from bleeding into other fragments
package com.cyngn.eleven.ui.fragments.profile;
-import android.database.Cursor;
import android.os.Bundle;
import android.support.v4.content.Loader;
+import com.cyngn.eleven.Config;
import com.cyngn.eleven.R;
import com.cyngn.eleven.loaders.LastAddedLoader;
import com.cyngn.eleven.model.Song;
+import com.cyngn.eleven.sectionadapter.SectionCreator;
+import com.cyngn.eleven.sectionadapter.SectionListContainer;
import com.cyngn.eleven.utils.MusicUtils;
import com.cyngn.eleven.widgets.NoResultsContainer;
-import java.util.List;
-
/**
* This class is used to display all of the songs the user put on their device
* within the last four weeks.
* {@inheritDoc}
*/
@Override
- public Loader<List<Song>> onCreateLoader(final int id, final Bundle args) {
- return new LastAddedLoader(getActivity());
+ public Loader<SectionListContainer<Song>> onCreateLoader(final int id, final Bundle args) {
+ LastAddedLoader loader = new LastAddedLoader(getActivity());
+ return new SectionCreator<Song>(getActivity(), loader, null);
}
@Override
@Override
public void playAll(int position) {
- Cursor cursor = LastAddedLoader.makeLastAddedCursor(getActivity());
- final long[] list = MusicUtils.getSongListForCursor(cursor);
- MusicUtils.playAll(getActivity(), list, position, false);
- cursor.close();
- cursor = null;
+ MusicUtils.playSmartPlaylist(getActivity(), position,
+ Config.SmartPlaylistType.LastAdded);
}
@Override
package com.cyngn.eleven.ui.fragments.profile;
import android.app.Activity;
-import android.database.Cursor;
import android.os.Bundle;
import android.support.v4.content.Loader;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
+import com.cyngn.eleven.Config;
import com.cyngn.eleven.R;
import com.cyngn.eleven.adapters.SongAdapter;
import com.cyngn.eleven.loaders.TopTracksLoader;
import com.cyngn.eleven.model.Song;
+import com.cyngn.eleven.sectionadapter.SectionAdapter;
+import com.cyngn.eleven.sectionadapter.SectionCreator;
+import com.cyngn.eleven.sectionadapter.SectionListContainer;
import com.cyngn.eleven.utils.MusicUtils;
import com.cyngn.eleven.widgets.NoResultsContainer;
-import java.util.List;
-
/**
* This class is used to display all of the songs the user put on their device
* within the last four weeks.
* {@inheritDoc}
*/
@Override
- public Loader<List<Song>> onCreateLoader(final int id, final Bundle args) {
- return new TopTracksLoader(getActivity(), TopTracksLoader.QueryType.TopTracks);
+ public Loader<SectionListContainer<Song>> onCreateLoader(final int id, final Bundle args) {
+ TopTracksLoader loader = new TopTracksLoader(getActivity(),
+ TopTracksLoader.QueryType.TopTracks);
+ return new SectionCreator<Song>(getActivity(), loader, null);
}
@Override
- protected SongAdapter createAdapter() {
- return new TopTracksAdapter(
- getActivity(),
- R.layout.list_item_top_tracks
+ protected SectionAdapter<Song, SongAdapter> createAdapter() {
+ return new SectionAdapter(getActivity(),
+ new TopTracksAdapter(
+ getActivity(),
+ R.layout.list_item_top_tracks
+ )
);
}
@Override
public void playAll(int position) {
- Cursor cursor = TopTracksLoader.makeTopTracksCursor(getActivity());
- final long[] list = MusicUtils.getSongListForCursor(cursor);
- MusicUtils.playAll(getActivity(), list, position, false);
- cursor.close();
- cursor = null;
+ MusicUtils.playSmartPlaylist(getActivity(), position,
+ Config.SmartPlaylistType.TopTracks);
}
public class TopTracksAdapter extends SongAdapter {
import android.util.Log;
import android.view.Menu;
+import com.cyngn.eleven.Config;
+import com.cyngn.eleven.Config.SmartPlaylistType;
import com.cyngn.eleven.IElevenService;
import com.cyngn.eleven.MusicPlaybackService;
import com.cyngn.eleven.R;
import com.cyngn.eleven.loaders.LastAddedLoader;
import com.cyngn.eleven.loaders.PlaylistLoader;
+import com.cyngn.eleven.loaders.PlaylistSongLoader;
import com.cyngn.eleven.loaders.SongLoader;
+import com.cyngn.eleven.loaders.TopTracksLoader;
import com.cyngn.eleven.menu.FragmentMenuItems;
import com.cyngn.eleven.model.AlbumArtistDetails;
import com.cyngn.eleven.provider.RecentStore;
*/
public static void playAll(final Context context, final long[] list, int position,
final boolean forceShuffle) {
- if (list.length == 0 || mService == null) {
+ if (list == null || list.length == 0 || mService == null) {
return;
}
try {
* @return The track list for a playlist
*/
public static final long[] getSongListForPlaylist(final Context context, final long playlistId) {
- final String[] projection = new String[] {
- MediaStore.Audio.Playlists.Members.AUDIO_ID
- };
- Cursor cursor = context.getContentResolver().query(
- MediaStore.Audio.Playlists.Members.getContentUri("external",
- Long.valueOf(playlistId)), projection, null, null,
- MediaStore.Audio.Playlists.Members.DEFAULT_SORT_ORDER);
+ Cursor cursor = PlaylistSongLoader.makePlaylistSongCursor(context, playlistId);
if (cursor != null) {
final long[] list = getSongListForCursor(cursor);
/**
* @param context The {@link Context} to use
+ * @param type The Smart Playlist Type
* @return The song list for the last added playlist
*/
- public static final long[] getSongListForLastAdded(final Context context) {
- final Cursor cursor = LastAddedLoader.makeLastAddedCursor(context);
- if (cursor != null) {
- final int count = cursor.getCount();
- final long[] list = new long[count];
- for (int i = 0; i < count; i++) {
- cursor.moveToNext();
- list[i] = cursor.getLong(0);
+ public static final long[] getSongListForSmartPlaylist(final Context context,
+ final SmartPlaylistType type) {
+ Cursor cursor = null;
+ try {
+ switch (type) {
+ case LastAdded:
+ cursor = LastAddedLoader.makeLastAddedCursor(context);
+ break;
+ case RecentlyPlayed:
+ cursor = TopTracksLoader.makeRecentTracksCursor(context);
+ break;
+ case TopTracks:
+ cursor = TopTracksLoader.makeTopTracksCursor(context);
+ break;
+ }
+ return MusicUtils.getSongListForCursor(cursor);
+ } finally {
+ if (cursor != null) {
+ cursor.close();
+ cursor = null;
}
- return list;
}
- return sEmptyList;
}
/**
- * Plays the last added songs from the past two weeks.
- *
+ * Plays the smart playlist
* @param context The {@link Context} to use
+ * @param position the position to start playing from
+ * @param type The Smart Playlist Type
*/
- public static void playLastAdded(final Context context) {
- playAll(context, getSongListForLastAdded(context), 0, false);
+ public static void playSmartPlaylist(final Context context, final int position,
+ final SmartPlaylistType type) {
+ final long[] list = getSongListForSmartPlaylist(context, type);
+ MusicUtils.playAll(context, list, position, false);
}
/**
--- /dev/null
+/*
+ * Copyright (C) 2014 Cyanogen, Inc.
+ */
+package com.cyngn.eleven.utils;
+
+import android.app.Activity;
+import android.support.v4.app.FragmentManager;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.widget.PopupMenu;
+
+import com.android.internal.view.menu.ContextMenuBuilder;
+import com.android.internal.view.menu.MenuBuilder;
+import com.cyngn.eleven.R;
+import com.cyngn.eleven.menu.CreateNewPlaylist;
+import com.cyngn.eleven.menu.FragmentMenuItems;
+import com.cyngn.eleven.menu.RenamePlaylist;
+import com.cyngn.eleven.provider.RecentStore;
+
+import java.util.ArrayList;
+
+/**
+ * Simple helper class that does most of the popup menu inflating and handling
+ * It has a few hooks around so that if the class wants customization they can add it on
+ * without changing this class too much
+ */
+public abstract class PopupMenuHelper implements PopupMenu.OnMenuItemClickListener {
+ // the different types of pop up menus
+ public static enum PopupMenuType {
+ Artist,
+ Album,
+ Song,
+ Playlist,
+ SmartPlaylist,
+ SearchResult,
+ Queue,
+ }
+
+ protected Activity mActivity;
+ protected PopupMenuType mType;
+ protected FragmentManager mFragmentManager;
+
+ public PopupMenuHelper(final Activity activity, final FragmentManager fragmentManager) {
+ mActivity = activity;
+ mFragmentManager = fragmentManager;
+ }
+
+ /**
+ * Call this to inflate and show the pop up menu
+ * @param view the view to anchor the popup menu against
+ * @param position the item that was clicked in the popup menu (or -1 if not relevant)
+ */
+ public void showPopupMenu(final View view, final int position) {
+ // create the popup menu
+ PopupMenu popupMenu = new PopupMenu(mActivity, view);
+ final Menu menu = popupMenu.getMenu();
+
+ // hook up the click listener
+ popupMenu.setOnMenuItemClickListener(this);
+
+ // figure what type of pop up menu it is
+ mType = onPreparePopupMenu(position);
+ if (mType != null) {
+ // inflate the menu
+ createPopupMenu(menu);
+ // show it
+ popupMenu.show();
+ }
+ }
+
+ /**
+ * This function allows classes to setup any variables before showing the popup menu
+ * @param position the position passed in from showPopupMenu
+ * @return the pop up menu type, or null if we shouldn't show a pop up menu
+ */
+ protected abstract PopupMenuType onPreparePopupMenu(final int position);
+
+ /**
+ * @return the list of ids needed for some menu actions like playing a list of songs
+ */
+ protected abstract long[] getIdList();
+
+ /**
+ * @return the group id to be used for pop up menu inflating
+ */
+ protected abstract int getGroupId();
+
+ /**
+ * called when the delete item is pressed. Since delete is different from class to class
+ * it is not implemented in this class and relies on the contaning classes to implement
+ */
+ protected abstract void onDeleteClicked();
+
+ /**
+ * Tells the containing class that it should probably mark their loaders for refresh
+ */
+ protected abstract void setShouldRefresh();
+
+ /**
+ * @return the artist name (when needed) for "more by this artist"
+ */
+ protected String getArtistName() {
+ throw new UnsupportedOperationException("Method Not Implemented!");
+ }
+
+ /**
+ * @return the single id that is needed for the "set as my ringtone"
+ */
+ protected long getId() {
+ throw new UnsupportedOperationException("Method Not Implemented!");
+ }
+
+ /**
+ * Called when the user clicks "remove from playlist"
+ */
+ protected void removeFromPlaylist() {
+ throw new UnsupportedOperationException("Method Not Implemented!");
+ }
+
+ /**
+ * Called when the user clicks "remove from queue"
+ */
+ protected void removeFromQueue() {
+ throw new UnsupportedOperationException("Method Not Implemented!");
+ }
+
+ /**
+ * Called when the user clicks "play next". Has a default implementation
+ */
+ protected void playNext() {
+ MusicUtils.playNext(getIdList());
+ }
+
+ /**
+ * Creates the pop up menu by inflating the menu items
+ * @param menu Menu to use for adding to
+ */
+ protected void createPopupMenu(final Menu menu) {
+ // get the default items and add them
+ int[] menuItems = getIdsForType(mType);
+ if (menuItems != null) {
+ for (int id : menuItems) {
+ addToMenu(menu, id, getStringResourceForId(id));
+ }
+ }
+
+ // if the containing class wants to add additional items, do it here
+ ArrayList<Integer> additionalItems = new ArrayList<Integer>();
+ getAdditionalIds(mType, additionalItems);
+ for (int id : additionalItems) {
+ addToMenu(menu, id, getAdditionalStringResourceForId(id));
+ }
+ }
+
+ /**
+ * Gets the default menu items for the specified type
+ * @param type of pop up menu to create
+ * @return list of menu items to inflate
+ */
+ private static int[] getIdsForType(PopupMenuType type) {
+ switch (type) {
+ case Artist:
+ return new int[] {
+ FragmentMenuItems.PLAY_SELECTION,
+ FragmentMenuItems.ADD_TO_QUEUE,
+ FragmentMenuItems.ADD_TO_PLAYLIST,
+ FragmentMenuItems.DELETE,
+ };
+ case Album:
+ return new int[] {
+ FragmentMenuItems.PLAY_SELECTION,
+ FragmentMenuItems.ADD_TO_QUEUE,
+ FragmentMenuItems.ADD_TO_PLAYLIST,
+ FragmentMenuItems.MORE_BY_ARTIST,
+ FragmentMenuItems.DELETE,
+ };
+ case Song:
+ return new int[] {
+ FragmentMenuItems.PLAY_SELECTION,
+ FragmentMenuItems.PLAY_NEXT,
+ FragmentMenuItems.ADD_TO_QUEUE,
+ FragmentMenuItems.ADD_TO_PLAYLIST,
+ FragmentMenuItems.MORE_BY_ARTIST,
+ FragmentMenuItems.USE_AS_RINGTONE,
+ FragmentMenuItems.DELETE,
+ };
+ case Playlist:
+ return new int[] {
+ FragmentMenuItems.PLAY_SELECTION,
+ FragmentMenuItems.ADD_TO_QUEUE,
+ FragmentMenuItems.RENAME_PLAYLIST,
+ FragmentMenuItems.DELETE,
+ };
+ case SmartPlaylist:
+ return new int[] {
+ FragmentMenuItems.PLAY_SELECTION,
+ FragmentMenuItems.ADD_TO_QUEUE,
+ };
+ case SearchResult:
+ return new int[] {
+ FragmentMenuItems.PLAY_SELECTION,
+ FragmentMenuItems.ADD_TO_QUEUE,
+ FragmentMenuItems.ADD_TO_PLAYLIST,
+ };
+ case Queue:
+ return new int[] {
+ FragmentMenuItems.PLAY_NEXT,
+ FragmentMenuItems.ADD_TO_PLAYLIST,
+ FragmentMenuItems.REMOVE_FROM_QUEUE,
+ FragmentMenuItems.MORE_BY_ARTIST,
+ FragmentMenuItems.USE_AS_RINGTONE,
+ FragmentMenuItems.DELETE,
+ };
+ }
+
+ return null;
+ }
+
+ /**
+ * Gets the additional menu items to inflate
+ * @param type the pop up menu type
+ * @param list the list to add menu items to
+ */
+ protected void getAdditionalIds(PopupMenuType type, ArrayList<Integer> list) {
+ // do nothing
+ }
+
+ /**
+ * Gets the string resource for an id - if the string resource doesn't exist in this class
+ * the containing class can override this method
+ * @param id the menu id
+ * @return string resource id
+ */
+ protected int getAdditionalStringResourceForId(final int id) {
+ return getStringResourceForId(id);
+ }
+
+ /**
+ * Gets the string resource for an id
+ * @param id the menu id
+ * @return string resource id
+ */
+ public static int getStringResourceForId(final int id) {
+ switch (id) {
+ case FragmentMenuItems.REMOVE_FROM_RECENT:
+ return R.string.context_menu_remove_from_recent;
+ case FragmentMenuItems.PLAY_SELECTION:
+ return R.string.context_menu_play_selection;
+ case FragmentMenuItems.ADD_TO_QUEUE:
+ return R.string.add_to_queue;
+ case FragmentMenuItems.ADD_TO_PLAYLIST:
+ return R.string.add_to_playlist;
+ case FragmentMenuItems.NEW_PLAYLIST:
+ return R.string.new_playlist;
+ case FragmentMenuItems.RENAME_PLAYLIST:
+ return R.string.context_menu_rename_playlist;
+ case FragmentMenuItems.PLAYLIST_SELECTED:
+ return 0; // no string here expected
+ case FragmentMenuItems.MORE_BY_ARTIST:
+ return R.string.context_menu_more_by_artist;
+ case FragmentMenuItems.DELETE:
+ return R.string.context_menu_delete;
+ case FragmentMenuItems.FETCH_ARTIST_IMAGE:
+ return R.string.context_menu_fetch_artist_image;
+ case FragmentMenuItems.FETCH_ALBUM_ART:
+ return R.string.context_menu_fetch_album_art;
+ case FragmentMenuItems.USE_AS_RINGTONE:
+ return R.string.context_menu_use_as_ringtone;
+ case FragmentMenuItems.REMOVE_FROM_PLAYLIST:
+ return R.string.context_menu_remove_from_playlist;
+ case FragmentMenuItems.REMOVE_FROM_QUEUE:
+ return R.string.remove_from_queue;
+ case FragmentMenuItems.PLAY_NEXT:
+ return R.string.context_menu_play_next;
+ }
+
+ return 0;
+ }
+
+ /**
+ * Simple helper function for adding an item to the menu
+ */
+ public void addToMenu(final Menu menu, final int id, final int resourceId) {
+ menu.add(getGroupId(), id, Menu.NONE, mActivity.getString(resourceId));
+ }
+
+ @Override
+ public boolean onMenuItemClick(MenuItem item) {
+ if (item.getGroupId() == getGroupId()) {
+ switch (item.getItemId()) {
+ case FragmentMenuItems.REMOVE_FROM_RECENT:
+ setShouldRefresh();
+ RecentStore.getInstance(mActivity).removeItem(getId());
+ MusicUtils.refresh();
+ return true;
+ case FragmentMenuItems.PLAY_SELECTION:
+ MusicUtils.playAll(mActivity, getIdList(), 0, false);
+ return true;
+ case FragmentMenuItems.ADD_TO_QUEUE:
+ MusicUtils.addToQueue(mActivity, getIdList());
+ return true;
+ case FragmentMenuItems.ADD_TO_PLAYLIST:
+ ContextMenuBuilder builder = new ContextMenuBuilder(mActivity);
+ MusicUtils.makePlaylistMenu(mActivity, getGroupId(), builder);
+ builder.setHeaderTitle(R.string.add_to_playlist);
+ builder.setCallback(new MenuBuilder.Callback() {
+ @Override
+ public boolean onMenuItemSelected(MenuBuilder menu, MenuItem item) {
+ return onMenuItemClick(item);
+ }
+
+ @Override
+ public void onMenuModeChange(MenuBuilder menu) {
+ // do nothing
+ }
+ });
+ builder.show(null, null);
+ return true;
+ case FragmentMenuItems.NEW_PLAYLIST:
+ CreateNewPlaylist.getInstance(getIdList()).show(
+ mFragmentManager, "CreatePlaylist");
+ return true;
+ case FragmentMenuItems.RENAME_PLAYLIST:
+ setShouldRefresh();
+ RenamePlaylist.getInstance(getId()).show(
+ mFragmentManager, "RenameDialog");
+ return true;
+ case FragmentMenuItems.PLAYLIST_SELECTED:
+ final long mPlaylistId = item.getIntent().getLongExtra("playlist", 0);
+ MusicUtils.addToPlaylist(mActivity, getIdList(), mPlaylistId);
+ return true;
+ case FragmentMenuItems.MORE_BY_ARTIST:
+ NavUtils.openArtistProfile(mActivity, getArtistName());
+ return true;
+ case FragmentMenuItems.DELETE:
+ setShouldRefresh();
+ onDeleteClicked();
+ return true;
+ case FragmentMenuItems.USE_AS_RINGTONE:
+ MusicUtils.setRingtone(mActivity, getId());
+ return true;
+ case FragmentMenuItems.REMOVE_FROM_PLAYLIST:
+ setShouldRefresh();
+ removeFromPlaylist();
+ return true;
+ case FragmentMenuItems.REMOVE_FROM_QUEUE:
+ setShouldRefresh();
+ removeFromQueue();
+ return true;
+ case FragmentMenuItems.PLAY_NEXT:
+ playNext();
+ return true;
+ default:
+ break;
+ }
+ }
+
+ return false;
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2014 Cyanogen, Inc.
+ */
+package com.cyngn.eleven.widgets;
+
+import android.view.View;
+
+public interface IPopupMenuCallback {
+ public static interface IListener {
+ void onPopupMenuClicked(final View v, final int position);
+ };
+
+ public void setPopupMenuClickedListener(final IListener listener);
+}
--- /dev/null
+/*
+ * Copyright (C) 2014 Cyanogen, Inc.
+ */
+
+package com.cyngn.eleven.widgets;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.ImageView;
+
+public class PopupMenuButton extends ImageView implements IPopupMenuCallback,
+ View.OnClickListener {
+ protected int mPosition = -1;
+ protected IListener mClickListener = null;
+
+ public PopupMenuButton(Context context, AttributeSet attrs) {
+ super(context, attrs);
+
+ setOnClickListener(this);
+ }
+
+ public void setPosition(final int position) {
+ mPosition = position;
+ }
+
+ @Override
+ public void setPopupMenuClickedListener(final IListener listener) {
+ mClickListener = listener;
+ }
+
+ @Override
+ public void onClick(View v) {
+ if (mClickListener != null) {
+ mClickListener.onPopupMenuClicked(v, mPosition);
+ }
+ }
+}