-/*
- * Copyright (C) 2012 Andrew Neal Licensed under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with the
- * License. You may obtain a copy of the License at
- * http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law
- * or agreed to in writing, software distributed under the License is
- * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the specific language
- * governing permissions and limitations under the License.
- */
-
-package com.cyngn.eleven.ui.fragments.profile;
-
-import android.app.Activity;
+package com.cyngn.eleven.ui.activities;
+
+import android.app.ActionBar;
import android.database.Cursor;
+import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
import android.os.SystemClock;
import android.provider.MediaStore;
-import android.support.v4.app.Fragment;
+import android.support.v4.app.LoaderManager;
import android.support.v4.app.LoaderManager.LoaderCallbacks;
import android.support.v4.content.Loader;
import android.view.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.ImageView;
+import android.widget.TextView;
import com.cyngn.eleven.Config;
import com.cyngn.eleven.R;
import com.cyngn.eleven.adapters.ProfileSongAdapter;
+import com.cyngn.eleven.cache.ImageFetcher;
import com.cyngn.eleven.dragdrop.DragSortListView;
import com.cyngn.eleven.dragdrop.DragSortListView.DragScrollProfile;
import com.cyngn.eleven.dragdrop.DragSortListView.DropListener;
import com.cyngn.eleven.recycler.RecycleHolder;
import com.cyngn.eleven.utils.MusicUtils;
import com.cyngn.eleven.utils.NavUtils;
-import com.cyngn.eleven.widgets.ProfileTabCarousel;
-import com.cyngn.eleven.widgets.VerticalScrollListener;
import java.util.List;
+import java.util.Locale;
-/**
- * This class is used to display all of the songs from a particular playlist.
- *
- * @author Andrew Neal (andrewdneal@gmail.com)
- */
-public class PlaylistSongFragment extends Fragment implements LoaderCallbacks<List<Song>>,
- OnItemClickListener, DropListener, RemoveListener, DragScrollProfile {
+public class PlaylistDetailActivity extends SlidingPanelActivity implements
+ OnScrollListener, LoaderCallbacks<List<Song>>, OnItemClickListener, DropListener,
+ RemoveListener, DragScrollProfile {
/**
* Used to keep context menu items from bleeding into other fragments
*/
private static final int LOADER = 0;
- /**
- * The adapter for the list
- */
- private ProfileSongAdapter mAdapter;
+ private static final int ACTION_BAR_DEFAULT_OPACITY = 65;
+ private Drawable mActionBarBackground;
- /**
- * The list view
- */
private DragSortListView mListView;
+ private ProfileSongAdapter mAdapter;
+
+ private View mHeaderContainer;
+ private ImageView mPlaylistImageView;
+
+ private TextView mNumberOfSongs;
+ private TextView mDurationOfPlaylist;
/**
* Represents a song
private String mSongName, mAlbumName, mArtistName;
/**
- * Profile header
- */
- private ProfileTabCarousel mProfileTabCarousel;
-
- /**
* The Id of the playlist the songs belong to
*/
private long mPlaylistId;
- /**
- * Empty constructor as per the {@link Fragment} documentation
- */
- public PlaylistSongFragment() {
- }
-
- /**
- * {@inheritDoc}
- */
@Override
- public void onAttach(final Activity activity) {
- super.onAttach(activity);
- mProfileTabCarousel = (ProfileTabCarousel)activity
- .findViewById(R.id.acivity_profile_base_tab_carousel);
+ protected int getLayoutToInflate() {
+ return R.layout.playlist_detail;
}
- /**
- * {@inheritDoc}
- */
@Override
- public void onCreate(final Bundle savedInstanceState) {
+ protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- // Create the adpater
+
+ Bundle arguments = getIntent().getExtras();
+ String playlistName = arguments.getString(Config.NAME);
+ mPlaylistId = arguments.getLong(Config.ID);
+
+ setupActionBar(playlistName);
+
+ ViewGroup root = (ViewGroup) findViewById(R.id.activity_base_content);
+ root.setPadding(0, 0, 0, 0); // clear default padding
+
+ setupHero();
+ setupSongList(root);
+
+ LoaderManager lm = getSupportLoaderManager();
+ lm.initLoader(0, arguments, this);
+ }
+
+ private void setupHero() {
+ mPlaylistImageView = (ImageView)findViewById(R.id.image);
+ mHeaderContainer = findViewById(R.id.playlist_header);
+ mNumberOfSongs = (TextView)findViewById(R.id.number_of_songs_text);
+ mDurationOfPlaylist = (TextView)findViewById(R.id.duration_text);
+
+ // TODO: Get the top artist image - do this in the next patch
+ // ImageFetcher.getInstance(this).loadCurrentArtwork(mPlaylistImageView);
+ }
+
+ private void setupSongList(ViewGroup root) {
+ mListView = (DragSortListView) root.findViewById(R.id.list_base);
+ mListView.setOnScrollListener(this);
mAdapter = new ProfileSongAdapter(
- getActivity(),
+ this,
R.layout.edit_track_list_item,
+ R.layout.faux_playlist_header,
ProfileSongAdapter.DISPLAY_PLAYLIST_SETTING
);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public View onCreateView(final LayoutInflater inflater, final ViewGroup container,
- final Bundle savedInstanceState) {
- // The View for the fragment's UI
- final ViewGroup rootView = (ViewGroup)inflater.inflate(R.layout.list_base_nopadding, null);
- // Initialize the list
- mListView = (DragSortListView)rootView.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());
mListView.setRemoveListener(this);
// Quick scroll while dragging
mListView.setDragScrollProfile(this);
- // To help make scrolling smooth
- mListView.setOnScrollListener(new VerticalScrollListener(null, mProfileTabCarousel, 0) {
- @Override
- public void onScrollStateChanged(AbsListView view, int scrollState) {
- super.onScrollStateChanged(view, scrollState);
-
- // 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);
- } else {
- mAdapter.setPauseDiskCache(false);
- mAdapter.notifyDataSetChanged();
- }
- }
- });
// Remove the scrollbars and padding for the fast scroll
mListView.setVerticalScrollBarEnabled(false);
mListView.setFastScrollEnabled(false);
mListView.setPadding(0, 0, 0, 0);
- return rootView;
}
- /**
- * {@inheritDoc}
- */
- @Override
- public void onActivityCreated(final Bundle savedInstanceState) {
- super.onActivityCreated(savedInstanceState);
- // Enable the options menu
- setHasOptionsMenu(true);
- // Start the loader
- final Bundle arguments = getArguments();
- if (arguments != null) {
- mPlaylistId = arguments.getLong(Config.ID);
- getLoaderManager().initLoader(LOADER, arguments, this);
- }
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void onSaveInstanceState(final Bundle outState) {
- super.onSaveInstanceState(outState);
- outState.putAll(getArguments() != null ? getArguments() : new Bundle());
+ private void setupActionBar(String playlistName) {
+ ActionBar actionBar = getActionBar();
+ actionBar.setTitle(playlistName.toUpperCase(Locale.getDefault()));
+ actionBar.setIcon(R.drawable.ic_action_back);
+ actionBar.setHomeButtonEnabled(true);
+ // change action bar background to a drawable we can control
+ mActionBarBackground = new ColorDrawable(getResources().getColor(R.color.header_action_bar_color));
+ mActionBarBackground.setAlpha(ACTION_BAR_DEFAULT_OPACITY);
+ actionBar.setBackgroundDrawable(mActionBarBackground);
}
/**
*/
@Override
public void onCreateContextMenu(final ContextMenu menu, final View v,
- final ContextMenuInfo menuInfo) {
+ final ContextMenu.ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
// Get the position of the selected item
- final AdapterContextMenuInfo info = (AdapterContextMenuInfo)menuInfo;
+ final AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo;
mSelectedPosition = info.position - 1;
// Creat a new song
mSong = mAdapter.getItem(mSelectedPosition);
// 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);
+ MusicUtils.makePlaylistMenu(this, GROUP_ID, subMenu);
// View more content by the song artist
menu.add(GROUP_ID, FragmentMenuItems.MORE_BY_ARTIST, Menu.NONE,
if (item.getGroupId() == GROUP_ID) {
switch (item.getItemId()) {
case FragmentMenuItems.PLAY_SELECTION:
- MusicUtils.playAll(getActivity(), new long[] {
- mSelectedId
+ MusicUtils.playAll(this, new long[]{
+ mSelectedId
}, 0, false);
return true;
case FragmentMenuItems.PLAY_NEXT:
- MusicUtils.playNext(new long[] {
- mSelectedId
+ MusicUtils.playNext(new long[]{
+ mSelectedId
});
return true;
case FragmentMenuItems.ADD_TO_QUEUE:
- MusicUtils.addToQueue(getActivity(), new long[] {
- mSelectedId
+ MusicUtils.addToQueue(this, new long[]{
+ mSelectedId
});
return true;
case FragmentMenuItems.NEW_PLAYLIST:
- CreateNewPlaylist.getInstance(new long[] {
- mSelectedId
- }).show(getFragmentManager(), "CreatePlaylist");
+ CreateNewPlaylist.getInstance(new long[]{
+ mSelectedId
+ }).show(getSupportFragmentManager(), "CreatePlaylist");
return true;
case FragmentMenuItems.PLAYLIST_SELECTED:
final long playlistId = item.getIntent().getLongExtra("playlist", 0);
- MusicUtils.addToPlaylist(getActivity(), new long[] {
- mSelectedId
+ MusicUtils.addToPlaylist(this, new long[]{
+ mSelectedId
}, playlistId);
return true;
case FragmentMenuItems.MORE_BY_ARTIST:
- NavUtils.openArtistProfile(getActivity(), mArtistName);
+ NavUtils.openArtistProfile(this, mArtistName);
return true;
case FragmentMenuItems.USE_AS_RINGTONE:
- MusicUtils.setRingtone(getActivity(), mSelectedId);
+ MusicUtils.setRingtone(this, mSelectedId);
return true;
case FragmentMenuItems.DELETE:
- DeleteDialog.newInstance(mSong.mSongName, new long[] {
- mSelectedId
- }, null).show(getFragmentManager(), "DeleteDialog");
+ DeleteDialog.newInstance(mSong.mSongName, new long[]{
+ mSelectedId
+ }, null).show(getSupportFragmentManager(), "DeleteDialog");
SystemClock.sleep(10);
mAdapter.notifyDataSetChanged();
- getLoaderManager().restartLoader(LOADER, null, this);
+ getSupportLoaderManager().restartLoader(LOADER, null, this);
return true;
case FragmentMenuItems.REMOVE_FROM_PLAYLIST:
mAdapter.remove(mSong);
mAdapter.notifyDataSetChanged();
- MusicUtils.removeFromPlaylist(getActivity(), mSong.mSongId, mPlaylistId);
- getLoaderManager().restartLoader(LOADER, null, this);
+ MusicUtils.removeFromPlaylist(this, mSong.mSongId, mPlaylistId);
+ getSupportLoaderManager().restartLoader(LOADER, null, this);
return true;
default:
break;
* {@inheritDoc}
*/
@Override
- public void onItemClick(final AdapterView<?> parent, final View view, final int position,
- final long id) {
- if (position == 0) {
- return;
- }
- Cursor cursor = PlaylistSongLoader.makePlaylistSongCursor(getActivity(),
- getArguments().getLong(Config.ID));
- final long[] list = MusicUtils.getSongListForCursor(cursor);
- MusicUtils.playAll(getActivity(), list, position - 1, false);
- cursor.close();
- cursor = null;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public Loader<List<Song>> onCreateLoader(final int id, final Bundle args) {
- return new PlaylistSongLoader(getActivity(), mPlaylistId);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void onLoadFinished(final Loader<List<Song>> loader, final List<Song> data) {
- // Check for any errors
- if (data.isEmpty()) {
- return;
- }
-
- // Start fresh
- mAdapter.unload();
- // Return the correct count
- mAdapter.setCount(data);
- // Add the data to the adpater
- for (final Song song : data) {
- mAdapter.add(song);
- }
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void onLoaderReset(final Loader<List<Song>> loader) {
- // Clear the data in the adapter
- mAdapter.unload();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
public float getSpeed(final float w, final long t) {
if (w > 0.8f) {
return mAdapter.getCount() / 0.001f;
mAdapter.remove(mSong);
mAdapter.notifyDataSetChanged();
final Uri uri = MediaStore.Audio.Playlists.Members.getContentUri("external", mPlaylistId);
- getActivity().getContentResolver().delete(uri,
+ getContentResolver().delete(uri,
MediaStore.Audio.Playlists.Members.AUDIO_ID + "=" + mSong.mSongId,
null);
}
mAdapter.remove(mSong);
mAdapter.insert(mSong, realTo);
mAdapter.notifyDataSetChanged();
- MediaStore.Audio.Playlists.Members.moveItem(getActivity().getContentResolver(),
+ MediaStore.Audio.Playlists.Members.moveItem(getContentResolver(),
mPlaylistId, realFrom, realTo);
}
-}
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void onItemClick(final AdapterView<?> parent, final View view, final int position,
+ final long id) {
+ if (position == 0) {
+ return;
+ }
+ Cursor cursor = PlaylistSongLoader.makePlaylistSongCursor(this,
+ mPlaylistId);
+ final long[] list = MusicUtils.getSongListForCursor(cursor);
+ MusicUtils.playAll(this, list, position - 1, false);
+ cursor.close();
+ cursor = null;
+ }
+
+ /**
+ * cause action bar icon tap to act like back -- boo-urns!
+ */
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ finish();
+ return true;
+ default:
+ return super.onOptionsItemSelected(item);
+ }
+ }
+
+ @Override
+ public void onScrollStateChanged(AbsListView view, 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.setPauseDiskCache(true);
+ } else {
+ mAdapter.setPauseDiskCache(false);
+ mAdapter.notifyDataSetChanged();
+ }
+ }
+
+ @Override // OnScrollListener
+ public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
+ View firstChild = view.getChildAt(0);
+ if (firstChild == null) {
+ return;
+ }
+
+ float firstChildY = firstChild.getY();
+
+ // if the first fake header is off the screen,
+ // set opaque and header container to be off screen
+ if (firstVisibleItem != 0) {
+ mHeaderContainer.setY(-mHeaderContainer.getHeight());
+ mActionBarBackground.setAlpha(255);
+ } else {
+ // otherwise set the offset and calculate the alpha
+ mHeaderContainer.setY(firstChildY);
+ int alpha = ACTION_BAR_DEFAULT_OPACITY +
+ (int)((255 - ACTION_BAR_DEFAULT_OPACITY) * -firstChildY /
+ (float)mHeaderContainer.getHeight());
+
+ alpha = Math.min(255, alpha);
+ mActionBarBackground.setAlpha(alpha);
+ }
+ }
+
+ @Override
+ public Loader<List<Song>> onCreateLoader(int i, Bundle bundle) {
+ return new PlaylistSongLoader(this, mPlaylistId);
+ }
+
+ @Override
+ public void onLoadFinished(final Loader<List<Song>> loader, final List<Song> data) {
+ // Check for any errors
+ if (data.isEmpty()) {
+ return;
+ }
+
+ // Start fresh
+ mAdapter.unload();
+ // Return the correct count
+ mAdapter.setCount(data);
+ // set the number of songs
+ String numberOfSongs = MusicUtils.makeLabel(this, R.plurals.Nsongs, data.size());
+ mNumberOfSongs.setText(numberOfSongs);
+
+ long duration = 0;
+
+ // Add the data to the adapter
+ for (final Song song : data) {
+ mAdapter.add(song);
+ duration += song.mDuration;
+ }
+
+ // set the duration
+ String durationString = MusicUtils.makeLongTimeString(this, duration);
+ mDurationOfPlaylist.setText(durationString);
+ }
+
+ @Override
+ public void onLoaderReset(final Loader<List<Song>> loader) {
+ // Clear the data in the adapter
+ mAdapter.unload();
+ }
+}
\ No newline at end of file