OSDN Git Service

dffde739f06c15147d4f1b8b1b7666e2770bf11b
[android-x86/packages-apps-Eleven.git] / src / com / cyanogenmod / eleven / utils / PopupMenuHelper.java
1 /*
2 * Copyright (C) 2014 The CyanogenMod Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 package com.cyanogenmod.eleven.utils;
17
18 import android.app.Activity;
19 import android.support.v4.app.FragmentManager;
20 import android.view.Menu;
21 import android.view.MenuItem;
22 import android.view.View;
23 import android.widget.PopupMenu;
24
25 import com.android.internal.view.menu.ContextMenuBuilder;
26 import com.android.internal.view.menu.MenuBuilder;
27 import com.cyanogenmod.eleven.Config;
28 import com.cyanogenmod.eleven.R;
29 import com.cyanogenmod.eleven.menu.CreateNewPlaylist;
30 import com.cyanogenmod.eleven.menu.FragmentMenuItems;
31 import com.cyanogenmod.eleven.menu.RenamePlaylist;
32 import com.cyanogenmod.eleven.provider.RecentStore;
33
34 import java.util.TreeSet;
35
36 /**
37  * Simple helper class that does most of the popup menu inflating and handling
38  * It has a few hooks around so that if the class wants customization they can add it on
39  * without changing this class too much
40  */
41 public abstract class PopupMenuHelper implements PopupMenu.OnMenuItemClickListener {
42     // the different types of pop up menus
43     public static enum PopupMenuType {
44         Artist,
45         Album,
46         Song,
47         Playlist,
48         SmartPlaylist,
49         SearchResult,
50         Queue,
51     }
52
53     protected Activity mActivity;
54     protected PopupMenuType mType;
55     protected FragmentManager mFragmentManager;
56
57     public PopupMenuHelper(final Activity activity, final FragmentManager fragmentManager) {
58         mActivity = activity;
59         mFragmentManager = fragmentManager;
60     }
61
62     /**
63      * Call this to inflate and show the pop up menu
64      * @param view the view to anchor the popup menu against
65      * @param position the item that was clicked in the popup menu (or -1 if not relevant)
66      */
67     public void showPopupMenu(final View view, final int position) {
68         // create the popup menu
69         PopupMenu popupMenu = new PopupMenu(mActivity, view);
70         final Menu menu = popupMenu.getMenu();
71
72         // hook up the click listener
73         popupMenu.setOnMenuItemClickListener(this);
74
75         // figure what type of pop up menu it is
76         mType = onPreparePopupMenu(position);
77         if (mType != null) {
78             // inflate the menu
79             createPopupMenu(menu);
80             // show it
81             popupMenu.show();
82         }
83     }
84
85     /**
86      * This function allows classes to setup any variables before showing the popup menu
87      * @param position the position passed in from showPopupMenu
88      * @return the pop up menu type, or null if we shouldn't show a pop up menu
89      */
90     public abstract PopupMenuType onPreparePopupMenu(final int position);
91
92     /**
93      * @return the list of ids needed for some menu actions like playing a list of songs
94      */
95     protected abstract long[] getIdList();
96
97     protected abstract long getSourceId();
98     protected abstract Config.IdType getSourceType();
99
100     /**
101      * @return the group id to be used for pop up menu inflating
102      */
103     protected int getGroupId() {
104         return 0;
105     }
106
107     /**
108      * called when the delete item is pressed.
109      */
110     protected void onDeleteClicked() {
111         throw new UnsupportedOperationException("Method Not Implemented!");
112     }
113
114     /**
115      * @return the artist name (when needed) for "more by this artist"
116      */
117     protected String getArtistName() {
118         throw new UnsupportedOperationException("Method Not Implemented!");
119     }
120
121     /**
122      * @return the single id that is needed for the "set as my ringtone"
123      */
124     protected long getId() {
125         long[] idList = getIdList();
126         if (idList.length == 1) {
127             return idList[0];
128         }
129
130         throw new UnsupportedOperationException("Method Not Implemented!");
131     }
132
133     /**
134      * Called when the user clicks "remove from playlist"
135      */
136     protected void removeFromPlaylist() {
137         throw new UnsupportedOperationException("Method Not Implemented!");
138     }
139
140     /**
141      * Called when the user clicks "remove from queue"
142      */
143     protected void removeFromQueue() {
144         throw new UnsupportedOperationException("Method Not Implemented!");
145     }
146
147     /**
148      * Called when the user clicks "play next".  Has a default implementation
149      */
150     protected void playNext() {
151         MusicUtils.playNext(getIdList(), getSourceId(), getSourceType());
152     }
153
154     /**
155      * Called when the user clicks "play album".
156      */
157     protected void playAlbum() {
158         throw new UnsupportedOperationException("Method Not Implemented!");
159     }
160
161     /**
162      * Creates the pop up menu by inflating the menu items
163      * @param menu Menu to use for adding to
164      */
165     public void createPopupMenu(final Menu menu) {
166         TreeSet<Integer> menuItems = new TreeSet<Integer>();
167
168         // get the default items and add them
169         int[] defaultItems = getIdsForType(mType);
170         if (defaultItems != null) {
171             for (int id : defaultItems) {
172                 menuItems.add(id);
173             }
174         }
175
176         updateMenuIds(mType, menuItems);
177
178         for (int id : menuItems) {
179             addToMenu(menu, id, getAdditionalStringResourceForId(id));
180         }
181     }
182
183     /**
184      * Gets the default menu items for the specified type
185      * @param type of pop up menu to create
186      * @return list of menu items to inflate
187      */
188     private static int[] getIdsForType(PopupMenuType type) {
189         switch (type) {
190             case Artist:
191                 return new int[] {
192                     FragmentMenuItems.PLAY_SELECTION,
193                     FragmentMenuItems.ADD_TO_QUEUE,
194                     FragmentMenuItems.ADD_TO_PLAYLIST,
195                     FragmentMenuItems.DELETE,
196                     FragmentMenuItems.CHANGE_IMAGE,
197                 };
198             case Album:
199                 return new int[] {
200                         FragmentMenuItems.PLAY_SELECTION,
201                         FragmentMenuItems.ADD_TO_QUEUE,
202                         FragmentMenuItems.ADD_TO_PLAYLIST,
203                         FragmentMenuItems.MORE_BY_ARTIST,
204                         FragmentMenuItems.DELETE,
205                         FragmentMenuItems.CHANGE_IMAGE,
206                 };
207             case Song:
208                 return new int[] {
209                         FragmentMenuItems.PLAY_SELECTION,
210                         FragmentMenuItems.PLAY_NEXT,
211                         FragmentMenuItems.PLAY_ALBUM,
212                         FragmentMenuItems.ADD_TO_QUEUE,
213                         FragmentMenuItems.ADD_TO_PLAYLIST,
214                         FragmentMenuItems.MORE_BY_ARTIST,
215                         FragmentMenuItems.USE_AS_RINGTONE,
216                         FragmentMenuItems.DELETE,
217                 };
218             case Playlist:
219                 return new int[] {
220                         FragmentMenuItems.PLAY_SELECTION,
221                         FragmentMenuItems.ADD_TO_QUEUE,
222                         FragmentMenuItems.RENAME_PLAYLIST,
223                         FragmentMenuItems.DELETE,
224                 };
225             case SmartPlaylist:
226                 return new int[] {
227                         FragmentMenuItems.PLAY_SELECTION,
228                         FragmentMenuItems.ADD_TO_QUEUE,
229                 };
230             case SearchResult:
231                 return new int[] {
232                         FragmentMenuItems.PLAY_SELECTION,
233                         FragmentMenuItems.ADD_TO_QUEUE,
234                         FragmentMenuItems.ADD_TO_PLAYLIST,
235                 };
236             case Queue:
237                 return new int[] {
238                         FragmentMenuItems.PLAY_NEXT,
239                         FragmentMenuItems.ADD_TO_PLAYLIST,
240                         FragmentMenuItems.REMOVE_FROM_QUEUE,
241                         FragmentMenuItems.MORE_BY_ARTIST,
242                         FragmentMenuItems.USE_AS_RINGTONE,
243                         FragmentMenuItems.DELETE,
244                 };
245         }
246
247         return null;
248     }
249
250     /**
251      * Allows containing classes to add/remove ids to the menu
252      * @param type the pop up menu type
253      * @param set the treeset to add/remove menu items
254      */
255     protected void updateMenuIds(PopupMenuType type, TreeSet<Integer> set) {
256         // do nothing
257     }
258
259     /**
260      * Gets the string resource for an id - if the string resource doesn't exist in this class
261      * the containing class can override this method
262      * @param id the menu id
263      * @return string resource id
264      */
265     protected int getAdditionalStringResourceForId(final int id) {
266         return getStringResourceForId(id);
267     }
268
269     /**
270      * Gets the string resource for an id
271      * @param id the menu id
272      * @return string resource id
273      */
274     public static int getStringResourceForId(final int id) {
275         switch (id) {
276             case FragmentMenuItems.REMOVE_FROM_RECENT:
277                 return R.string.context_menu_remove_from_recent;
278             case FragmentMenuItems.PLAY_SELECTION:
279                 return R.string.context_menu_play_selection;
280             case FragmentMenuItems.ADD_TO_QUEUE:
281                 return R.string.add_to_queue;
282             case FragmentMenuItems.ADD_TO_PLAYLIST:
283                 return R.string.add_to_playlist;
284             case FragmentMenuItems.NEW_PLAYLIST:
285                 return R.string.new_playlist;
286             case FragmentMenuItems.RENAME_PLAYLIST:
287                 return R.string.context_menu_rename_playlist;
288             case FragmentMenuItems.PLAYLIST_SELECTED:
289                 return 0; // no string here expected
290             case FragmentMenuItems.MORE_BY_ARTIST:
291                 return R.string.context_menu_more_by_artist;
292             case FragmentMenuItems.DELETE:
293                 return R.string.context_menu_delete;
294             case FragmentMenuItems.FETCH_ARTIST_IMAGE:
295                 return R.string.context_menu_fetch_artist_image;
296             case FragmentMenuItems.FETCH_ALBUM_ART:
297                 return R.string.context_menu_fetch_album_art;
298             case FragmentMenuItems.USE_AS_RINGTONE:
299                 return R.string.context_menu_use_as_ringtone;
300             case FragmentMenuItems.REMOVE_FROM_PLAYLIST:
301                 return R.string.context_menu_remove_from_playlist;
302             case FragmentMenuItems.REMOVE_FROM_QUEUE:
303                 return R.string.remove_from_queue;
304             case FragmentMenuItems.PLAY_NEXT:
305                 return R.string.context_menu_play_next;
306             case FragmentMenuItems.PLAY_ALBUM:
307                 return R.string.context_menu_play_album;
308             case FragmentMenuItems.CHANGE_IMAGE:
309                 return R.string.context_menu_change_image;
310         }
311
312         return 0;
313     }
314
315     /**
316      * Simple helper function for adding an item to the menu
317      */
318     public void addToMenu(final Menu menu, final int id, final int resourceId) {
319         menu.add(getGroupId(), id, id /*as order*/, mActivity.getString(resourceId));
320     }
321
322     @Override
323     public boolean onMenuItemClick(MenuItem item) {
324         if (item.getGroupId() == getGroupId()) {
325             switch (item.getItemId()) {
326                 case FragmentMenuItems.REMOVE_FROM_RECENT:
327                     RecentStore.getInstance(mActivity).removeItem(getId());
328                     MusicUtils.refresh();
329                     return true;
330                 case FragmentMenuItems.PLAY_SELECTION:
331                     MusicUtils.playAll(mActivity, getIdList(), 0, getSourceId(), getSourceType(),
332                             false);
333                     return true;
334                 case FragmentMenuItems.ADD_TO_QUEUE:
335                     MusicUtils.addToQueue(mActivity, getIdList(), getSourceId(), getSourceType());
336                     return true;
337                 case FragmentMenuItems.ADD_TO_PLAYLIST:
338                     ContextMenuBuilder builder = new ContextMenuBuilder(mActivity);
339                     MusicUtils.makePlaylistMenu(mActivity, getGroupId(), builder);
340                     builder.setHeaderTitle(R.string.add_to_playlist);
341                     builder.setCallback(new MenuBuilder.Callback() {
342                         @Override
343                         public boolean onMenuItemSelected(MenuBuilder menu, MenuItem item) {
344                             return onMenuItemClick(item);
345                         }
346
347                         @Override
348                         public void onMenuModeChange(MenuBuilder menu) {
349                             // do nothing
350                         }
351                     });
352                     builder.showDialog(null, null);
353                     return true;
354                 case FragmentMenuItems.NEW_PLAYLIST:
355                     CreateNewPlaylist.getInstance(getIdList()).show(
356                             mFragmentManager, "CreatePlaylist");
357                     return true;
358                 case FragmentMenuItems.RENAME_PLAYLIST:
359                     RenamePlaylist.getInstance(getId()).show(
360                             mFragmentManager, "RenameDialog");
361                     return true;
362                 case FragmentMenuItems.PLAYLIST_SELECTED:
363                     final long mPlaylistId = item.getIntent().getLongExtra("playlist", 0);
364                     MusicUtils.addToPlaylist(mActivity, getIdList(), mPlaylistId);
365                     return true;
366                 case FragmentMenuItems.MORE_BY_ARTIST:
367                     NavUtils.openArtistProfile(mActivity, getArtistName());
368                     return true;
369                 case FragmentMenuItems.DELETE:
370                     onDeleteClicked();
371                     return true;
372                 case FragmentMenuItems.USE_AS_RINGTONE:
373                     MusicUtils.setRingtone(mActivity, getId());
374                     return true;
375                 case FragmentMenuItems.REMOVE_FROM_PLAYLIST:
376                     removeFromPlaylist();
377                     return true;
378                 case FragmentMenuItems.REMOVE_FROM_QUEUE:
379                     removeFromQueue();
380                     return true;
381                 case FragmentMenuItems.PLAY_NEXT:
382                     playNext();
383                     return true;
384                 case FragmentMenuItems.PLAY_ALBUM:
385                     playAlbum();
386                     return true;
387                 default:
388                     break;
389             }
390         }
391
392         return false;
393     }
394 }