OSDN Git Service

Eleven: This adds the empty state for all pages
[android-x86/packages-apps-Eleven.git] / src / com / cyngn / eleven / ui / fragments / profile / BasicSongFragment.java
1 /*
2  * Copyright (C) 2012 Andrew Neal Licensed under the Apache License, Version 2.0
3  * (the "License"); you may not use this file except in compliance with the
4  * License. You may obtain a copy of the License at
5  * http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law
6  * or agreed to in writing, software distributed under the License is
7  * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
8  * KIND, either express or implied. See the License for the specific language
9  * governing permissions and limitations under the License.
10  */
11
12 package com.cyngn.eleven.ui.fragments.profile;
13
14 import android.os.Bundle;
15 import android.support.v4.app.Fragment;
16 import android.support.v4.app.LoaderManager.LoaderCallbacks;
17 import android.support.v4.content.Loader;
18 import android.view.ContextMenu;
19 import android.view.ContextMenu.ContextMenuInfo;
20 import android.view.LayoutInflater;
21 import android.view.Menu;
22 import android.view.SubMenu;
23 import android.view.View;
24 import android.view.ViewGroup;
25 import android.widget.AbsListView;
26 import android.widget.AdapterView;
27 import android.widget.AdapterView.AdapterContextMenuInfo;
28 import android.widget.AdapterView.OnItemClickListener;
29 import android.widget.ListView;
30 import android.widget.TextView;
31
32 import com.cyngn.eleven.R;
33 import com.cyngn.eleven.adapters.SongAdapter;
34 import com.cyngn.eleven.menu.CreateNewPlaylist;
35 import com.cyngn.eleven.menu.DeleteDialog;
36 import com.cyngn.eleven.menu.FragmentMenuItems;
37 import com.cyngn.eleven.model.Song;
38 import com.cyngn.eleven.recycler.RecycleHolder;
39 import com.cyngn.eleven.utils.MusicUtils;
40 import com.cyngn.eleven.utils.NavUtils;
41 import com.cyngn.eleven.widgets.NoResultsContainer;
42
43 import java.util.List;
44
45 /**
46  * This class is used to display all of the songs
47  *
48  * @author Andrew Neal (andrewdneal@gmail.com)
49  */
50 public abstract class BasicSongFragment extends Fragment implements LoaderCallbacks<List<Song>>,
51         OnItemClickListener {
52
53     /**
54      * Fragment UI
55      */
56     protected ViewGroup mRootView;
57
58     /**
59      * The adapter for the list
60      */
61     protected SongAdapter mAdapter;
62
63     /**
64      * The list view
65      */
66     protected ListView mListView;
67
68     /**
69      * Represents a song
70      */
71     protected Song mSong;
72
73     /**
74      * Position of a context menu item
75      */
76     protected int mSelectedPosition;
77
78     /**
79      * Id of a context menu item
80      */
81     protected long mSelectedId;
82
83     /**
84      * Song, album, and artist name used in the context menu
85      */
86     protected String mSongName, mAlbumName, mArtistName;
87
88     /**
89      * Empty constructor as per the {@link Fragment} documentation
90      */
91     public BasicSongFragment() {
92     }
93
94     /**
95      * {@inheritDoc}
96      */
97     @Override
98     public void onCreate(final Bundle savedInstanceState) {
99         super.onCreate(savedInstanceState);
100         // Create the adpater
101         mAdapter = createAdapter();
102     }
103
104     /**
105      * {@inheritDoc}
106      */
107     @Override
108     public View onCreateView(final LayoutInflater inflater, final ViewGroup container,
109                              final Bundle savedInstanceState) {
110         // The View for the fragment's UI
111         mRootView = (ViewGroup) inflater.inflate(R.layout.list_base, null);
112         // Initialize the list
113         mListView = (ListView) mRootView.findViewById(R.id.list_base);
114         // Set the data behind the list
115         mListView.setAdapter(mAdapter);
116         // Release any references to the recycled Views
117         mListView.setRecyclerListener(new RecycleHolder());
118         // Listen for ContextMenus to be created
119         mListView.setOnCreateContextMenuListener(this);
120         // Play the selected song
121         mListView.setOnItemClickListener(this);
122         // To help make scrolling smooth
123         mListView.setOnScrollListener(new AbsListView.OnScrollListener() {
124             @Override
125             public void onScrollStateChanged(AbsListView view, int scrollState) {
126                 // Pause disk cache access to ensure smoother scrolling
127                 if (scrollState == AbsListView.OnScrollListener.SCROLL_STATE_FLING
128                         || scrollState == AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL) {
129                     mAdapter.setPauseDiskCache(true);
130                 } else {
131                     mAdapter.setPauseDiskCache(false);
132                     mAdapter.notifyDataSetChanged();
133                 }
134             }
135
136             @Override
137             public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
138
139             }
140         });
141
142         return mRootView;
143     }
144
145     /**
146      * This allows subclasses to customize the look and feel of the no results container
147      * @param empty NoResultsContainer class
148      */
149     public void setupNoResultsContainer(final NoResultsContainer empty) {
150         // do nothing
151     }
152
153     /**
154      * {@inheritDoc}
155      */
156     @Override
157     public void onActivityCreated(final Bundle savedInstanceState) {
158         super.onActivityCreated(savedInstanceState);
159         // Enable the options menu
160         setHasOptionsMenu(true);
161         // Start the loader
162         getLoaderManager().initLoader(getLoaderId(), null, this);
163     }
164
165     /**
166      * {@inheritDoc}
167      */
168     @Override
169     public void onCreateContextMenu(final ContextMenu menu, final View v,
170                                     final ContextMenuInfo menuInfo) {
171         super.onCreateContextMenu(menu, v, menuInfo);
172         // Get the position of the selected item
173         final AdapterContextMenuInfo info = (AdapterContextMenuInfo) menuInfo;
174         mSelectedPosition = info.position;
175         // Creat a new song
176         mSong = mAdapter.getItem(mSelectedPosition);
177         mSelectedId = mSong.mSongId;
178         mSongName = mSong.mSongName;
179         mAlbumName = mSong.mAlbumName;
180         mArtistName = mSong.mArtistName;
181
182         // Play the song
183         menu.add(getGroupId(), FragmentMenuItems.PLAY_SELECTION, Menu.NONE,
184                 getString(R.string.context_menu_play_selection));
185
186         // Play next
187         menu.add(getGroupId(), FragmentMenuItems.PLAY_NEXT, Menu.NONE,
188                 getString(R.string.context_menu_play_next));
189
190         // Add the song to the queue
191         menu.add(getGroupId(), FragmentMenuItems.ADD_TO_QUEUE, Menu.NONE,
192                 getString(R.string.add_to_queue));
193
194         // Add the song to a playlist
195         final SubMenu subMenu = menu.addSubMenu(getGroupId(), FragmentMenuItems.ADD_TO_PLAYLIST,
196                 Menu.NONE, R.string.add_to_playlist);
197         MusicUtils.makePlaylistMenu(getActivity(), getGroupId(), subMenu);
198
199         // View more content by the song artist
200         menu.add(getGroupId(), FragmentMenuItems.MORE_BY_ARTIST, Menu.NONE,
201                 getString(R.string.context_menu_more_by_artist));
202
203         // Make the song a ringtone
204         menu.add(getGroupId(), FragmentMenuItems.USE_AS_RINGTONE, Menu.NONE,
205                 getString(R.string.context_menu_use_as_ringtone));
206
207         // Delete the song
208         menu.add(getGroupId(), FragmentMenuItems.DELETE, Menu.NONE,
209                 getString(R.string.context_menu_delete));
210     }
211
212     @Override
213     public boolean onContextItemSelected(final android.view.MenuItem item) {
214         if (item.getGroupId() == getGroupId()) {
215             switch (item.getItemId()) {
216                 case FragmentMenuItems.PLAY_SELECTION:
217                     MusicUtils.playAll(getActivity(), new long[]{
218                             mSelectedId
219                     }, 0, false);
220                     return true;
221                 case FragmentMenuItems.PLAY_NEXT:
222                     MusicUtils.playNext(new long[]{
223                             mSelectedId
224                     });
225                     return true;
226                 case FragmentMenuItems.ADD_TO_QUEUE:
227                     MusicUtils.addToQueue(getActivity(), new long[]{
228                             mSelectedId
229                     });
230                     return true;
231                 case FragmentMenuItems.NEW_PLAYLIST:
232                     CreateNewPlaylist.getInstance(new long[]{
233                             mSelectedId
234                     }).show(getFragmentManager(), "CreatePlaylist");
235                     return true;
236                 case FragmentMenuItems.PLAYLIST_SELECTED:
237                     final long mPlaylistId = item.getIntent().getLongExtra("playlist", 0);
238                     MusicUtils.addToPlaylist(getActivity(), new long[]{
239                             mSelectedId
240                     }, mPlaylistId);
241                     return true;
242                 case FragmentMenuItems.MORE_BY_ARTIST:
243                     NavUtils.openArtistProfile(getActivity(), mArtistName);
244                     return true;
245                 case FragmentMenuItems.USE_AS_RINGTONE:
246                     MusicUtils.setRingtone(getActivity(), mSelectedId);
247                     return true;
248                 case FragmentMenuItems.DELETE:
249                     // TODO: Smarter refresh
250                     DeleteDialog.newInstance(mSong.mSongName, new long[]{
251                             mSelectedId
252                     }, null).show(getFragmentManager(), "DeleteDialog");
253                     return true;
254                 default:
255                     break;
256             }
257         }
258         return super.onContextItemSelected(item);
259     }
260
261     /**
262      * {@inheritDoc}
263      */
264     @Override
265     public void onItemClick(final AdapterView<?> parent, final View view, final int position,
266                             final long id) {
267         playAll(position);
268     }
269
270     /**
271      * {@inheritDoc}
272      */
273     @Override
274     public void onLoadFinished(final Loader<List<Song>> loader, final List<Song> data) {
275         // Check for any errors
276         if (data.isEmpty()) {
277             // Set the empty text
278             final NoResultsContainer empty = (NoResultsContainer)mRootView.findViewById(R.id.no_results_container);
279             mListView.setEmptyView(empty);
280             return;
281         }
282
283         // Start fresh
284         mAdapter.unload();
285         // Add the data to the adpater
286         for (final Song song : data) {
287             mAdapter.add(song);
288         }
289
290         // Build the cache
291         mAdapter.buildCache();
292     }
293
294     public void restartLoader() {
295         getLoaderManager().restartLoader(getLoaderId(), null, this);
296     }
297
298     /**
299      * {@inheritDoc}
300      */
301     @Override
302     public void onLoaderReset(final Loader<List<Song>> loader) {
303         // Clear the data in the adapter
304         mAdapter.unload();
305     }
306
307     /**
308      * If the subclasses want to use a customized SongADapter
309      * @return the Song adapter
310      */
311     protected SongAdapter createAdapter() {
312         return new SongAdapter(
313                 getActivity(),
314                 R.layout.list_item_normal
315         );
316     }
317
318
319     /**
320      * Used to keep context menu items from bleeding into other fragments
321      */
322     public abstract int getGroupId();
323
324     /**
325      * LoaderCallbacks identifier
326      */
327     public abstract int getLoaderId();
328
329     /**
330      * If the user clisk play all
331      *
332      * @param position the position of the item clicked or -1 if shuffle all
333      */
334     public abstract void playAll(int position);
335
336 }