OSDN Git Service

Eleven: Add loading dialogs to all fragments
[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.app.Activity;
15 import android.os.Bundle;
16 import android.os.SystemClock;
17 import android.support.v4.app.Fragment;
18 import android.support.v4.app.LoaderManager;
19 import android.support.v4.app.LoaderManager.LoaderCallbacks;
20 import android.support.v4.content.Loader;
21 import android.view.LayoutInflater;
22 import android.view.View;
23 import android.view.ViewGroup;
24 import android.widget.AbsListView;
25 import android.widget.AdapterView;
26 import android.widget.AdapterView.OnItemClickListener;
27 import android.widget.ListView;
28
29 import com.cyngn.eleven.MusicStateListener;
30 import com.cyngn.eleven.R;
31 import com.cyngn.eleven.adapters.SongAdapter;
32 import com.cyngn.eleven.model.Song;
33 import com.cyngn.eleven.recycler.RecycleHolder;
34 import com.cyngn.eleven.sectionadapter.SectionAdapter;
35 import com.cyngn.eleven.sectionadapter.SectionListContainer;
36 import com.cyngn.eleven.ui.activities.BaseActivity;
37 import com.cyngn.eleven.utils.PopupMenuHelper;
38 import com.cyngn.eleven.utils.SongPopupMenuHelper;
39 import com.cyngn.eleven.widgets.IPopupMenuCallback;
40 import com.cyngn.eleven.widgets.LoadingEmptyContainer;
41 import com.cyngn.eleven.widgets.NoResultsContainer;
42
43 import java.util.TreeSet;
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
51         LoaderCallbacks<SectionListContainer<Song>>, OnItemClickListener, MusicStateListener {
52
53     /**
54      * Fragment UI
55      */
56     protected ViewGroup mRootView;
57
58     /**
59      * The adapter for the list
60      */
61     protected SectionAdapter<Song, SongAdapter> mAdapter;
62
63     /**
64      * The list view
65      */
66     protected ListView mListView;
67
68     /**
69      * Pop up menu helper
70      */
71     protected PopupMenuHelper mPopupMenuHelper;
72
73     /**
74      * This holds the loading progress bar as well as the no results message
75      */
76     protected LoadingEmptyContainer mLoadingEmptyContainer;
77
78     /**
79      * Empty constructor as per the {@link Fragment} documentation
80      */
81     public BasicSongFragment() {
82     }
83
84     /**
85      * {@inheritDoc}
86      */
87     @Override
88     public void onCreate(final Bundle savedInstanceState) {
89         super.onCreate(savedInstanceState);
90         mPopupMenuHelper = new SongPopupMenuHelper(getActivity(), getFragmentManager()) {
91             @Override
92             public Song getSong(int position) {
93                 return mAdapter.getTItem(position);
94             }
95
96             @Override
97             protected void updateMenuIds(PopupMenuType type, TreeSet<Integer> set) {
98                 super.updateMenuIds(type, set);
99                 BasicSongFragment.this.updateMenuIds(set);
100             }
101         };
102
103         // Create the adapter
104         mAdapter = createAdapter();
105         mAdapter.setPopupMenuClickedListener(new IPopupMenuCallback.IListener() {
106             @Override
107             public void onPopupMenuClicked(View v, int position) {
108                 mPopupMenuHelper.showPopupMenu(v, position);
109             }
110         });
111     }
112
113     protected void updateMenuIds(TreeSet<Integer> set) {
114         // do nothing - let subclasses override
115     }
116
117     /**
118      * {@inheritDoc}
119      */
120     @Override
121     public View onCreateView(final LayoutInflater inflater, final ViewGroup container,
122                              final Bundle savedInstanceState) {
123         // The View for the fragment's UI
124         mRootView = (ViewGroup) inflater.inflate(R.layout.list_base, null);
125         // set the background on the root view
126         mRootView.setBackgroundColor(getResources().getColor(R.color.background_color));
127         // Initialize the list
128         mListView = (ListView) mRootView.findViewById(R.id.list_base);
129         // Set the data behind the list
130         mListView.setAdapter(mAdapter);
131         // Release any references to the recycled Views
132         mListView.setRecyclerListener(new RecycleHolder());
133         // Play the selected song
134         mListView.setOnItemClickListener(this);
135         // To help make scrolling smooth
136         mListView.setOnScrollListener(new AbsListView.OnScrollListener() {
137             @Override
138             public void onScrollStateChanged(AbsListView view, int scrollState) {
139                 // Pause disk cache access to ensure smoother scrolling
140                 if (scrollState == AbsListView.OnScrollListener.SCROLL_STATE_FLING
141                         || scrollState == AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL) {
142                     mAdapter.getUnderlyingAdapter().setPauseDiskCache(true);
143                 } else {
144                     mAdapter.getUnderlyingAdapter().setPauseDiskCache(false);
145                     mAdapter.notifyDataSetChanged();
146                 }
147             }
148
149             @Override
150             public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
151
152             }
153         });
154
155         // Show progress bar
156         mLoadingEmptyContainer = (LoadingEmptyContainer)mRootView.findViewById(R.id.loading_empty_container);
157         // Setup the container strings
158         setupNoResultsContainer(mLoadingEmptyContainer.getNoResultsContainer());
159         mListView.setEmptyView(mLoadingEmptyContainer);
160
161         // Register the music status listener
162         ((BaseActivity)getActivity()).setMusicStateListenerListener(this);
163
164         return mRootView;
165     }
166
167     @Override
168     public void onDestroyView() {
169         super.onDestroyView();
170
171         ((BaseActivity)getActivity()).removeMusicStateListenerListener(this);
172     }
173
174     /**
175      * This allows subclasses to customize the look and feel of the no results container
176      * @param empty NoResultsContainer class
177      */
178     public void setupNoResultsContainer(final NoResultsContainer empty) {
179         // do nothing
180     }
181
182     /**
183      * {@inheritDoc}
184      */
185     @Override
186     public void onActivityCreated(final Bundle savedInstanceState) {
187         super.onActivityCreated(savedInstanceState);
188         // Start the loader
189         getFragmentLoaderManager().initLoader(getLoaderId(), null, this);
190     }
191
192     /**
193      * {@inheritDoc}
194      */
195     @Override
196     public void onItemClick(final AdapterView<?> parent, final View view, final int position,
197                             final long id) {
198         playAll(position);
199     }
200
201     /**
202      * {@inheritDoc}
203      */
204     @Override
205     public void onLoadFinished(final Loader<SectionListContainer<Song>> loader,
206                                final SectionListContainer<Song> data) {
207         // Check for any errors
208         if (data.mListResults.isEmpty()) {
209             mLoadingEmptyContainer.showNoResults();
210             return;
211         }
212
213         // Start fresh
214         mAdapter.setData(data);
215     }
216
217     /**
218      * Restarts the loader.
219      */
220     public void refresh() {
221         // Wait a moment for the preference to change.
222         SystemClock.sleep(10);
223         restartLoader();
224     }
225
226     /**
227      * {@inheritDoc}
228      */
229     @Override
230     public void restartLoader() {
231         // Update the list when the user deletes any items
232         getFragmentLoaderManager().restartLoader(getLoaderId(), null, this);
233     }
234
235     /**
236      * {@inheritDoc}
237      */
238     @Override
239     public void onLoaderReset(final Loader<SectionListContainer<Song>> loader) {
240         // Clear the data in the adapter
241         mAdapter.unload();
242     }
243
244     /**
245      * If the subclasses want to use a customized SongAdapter they can override this method
246      * @return the Song adapter
247      */
248     protected SectionAdapter<Song, SongAdapter> createAdapter() {
249         return new SectionAdapter(getActivity(),
250                 new SongAdapter(
251                     getActivity(),
252                     R.layout.list_item_normal
253                 )
254         );
255     }
256
257     /**
258      * Allow subclasses to specify a different loader manager
259      * @return Loader Manager to use
260      */
261     public LoaderManager getFragmentLoaderManager() {
262         return getLoaderManager();
263     }
264
265     @Override
266     public void onMetaChanged() {
267         // do nothing
268     }
269
270     @Override
271     public void onPlaylistChanged() {
272         // Nothing to do
273     }
274
275     /**
276      * LoaderCallbacks identifier
277      */
278     public abstract int getLoaderId();
279
280     /**
281      * If the user clisk play all
282      *
283      * @param position the position of the item clicked or -1 if shuffle all
284      */
285     public abstract void playAll(int position);
286
287 }