2 * Copyright (C) 2014 The CyanogenMod Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 package com.cyanogenmod.eleven.utils;
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;
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;
34 import java.util.TreeSet;
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
41 public abstract class PopupMenuHelper implements PopupMenu.OnMenuItemClickListener {
42 // the different types of pop up menus
43 public static enum PopupMenuType {
53 protected Activity mActivity;
54 protected PopupMenuType mType;
55 protected FragmentManager mFragmentManager;
57 public PopupMenuHelper(final Activity activity, final FragmentManager fragmentManager) {
59 mFragmentManager = fragmentManager;
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)
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();
72 // hook up the click listener
73 popupMenu.setOnMenuItemClickListener(this);
75 // figure what type of pop up menu it is
76 mType = onPreparePopupMenu(position);
79 createPopupMenu(menu);
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
90 public abstract PopupMenuType onPreparePopupMenu(final int position);
93 * @return the list of ids needed for some menu actions like playing a list of songs
95 protected abstract long[] getIdList();
97 protected abstract long getSourceId();
98 protected abstract Config.IdType getSourceType();
101 * @return the group id to be used for pop up menu inflating
103 protected int getGroupId() {
108 * called when the delete item is pressed.
110 protected void onDeleteClicked() {
111 throw new UnsupportedOperationException("Method Not Implemented!");
115 * @return the artist name (when needed) for "more by this artist"
117 protected String getArtistName() {
118 throw new UnsupportedOperationException("Method Not Implemented!");
122 * @return the single id that is needed for the "set as my ringtone"
124 protected long getId() {
125 long[] idList = getIdList();
126 if (idList.length == 1) {
130 throw new UnsupportedOperationException("Method Not Implemented!");
134 * Called when the user clicks "remove from playlist"
136 protected void removeFromPlaylist() {
137 throw new UnsupportedOperationException("Method Not Implemented!");
141 * Called when the user clicks "remove from queue"
143 protected void removeFromQueue() {
144 throw new UnsupportedOperationException("Method Not Implemented!");
148 * Called when the user clicks "play next". Has a default implementation
150 protected void playNext() {
151 MusicUtils.playNext(getIdList(), getSourceId(), getSourceType());
155 * Called when the user clicks "play album".
157 protected void playAlbum() {
158 throw new UnsupportedOperationException("Method Not Implemented!");
162 * Creates the pop up menu by inflating the menu items
163 * @param menu Menu to use for adding to
165 public void createPopupMenu(final Menu menu) {
166 TreeSet<Integer> menuItems = new TreeSet<Integer>();
168 // get the default items and add them
169 int[] defaultItems = getIdsForType(mType);
170 if (defaultItems != null) {
171 for (int id : defaultItems) {
176 updateMenuIds(mType, menuItems);
178 for (int id : menuItems) {
179 addToMenu(menu, id, getAdditionalStringResourceForId(id));
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
188 private static int[] getIdsForType(PopupMenuType type) {
192 FragmentMenuItems.PLAY_SELECTION,
193 FragmentMenuItems.ADD_TO_QUEUE,
194 FragmentMenuItems.ADD_TO_PLAYLIST,
195 FragmentMenuItems.DELETE,
196 FragmentMenuItems.CHANGE_IMAGE,
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,
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,
220 FragmentMenuItems.PLAY_SELECTION,
221 FragmentMenuItems.ADD_TO_QUEUE,
222 FragmentMenuItems.RENAME_PLAYLIST,
223 FragmentMenuItems.DELETE,
227 FragmentMenuItems.PLAY_SELECTION,
228 FragmentMenuItems.ADD_TO_QUEUE,
232 FragmentMenuItems.PLAY_SELECTION,
233 FragmentMenuItems.ADD_TO_QUEUE,
234 FragmentMenuItems.ADD_TO_PLAYLIST,
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,
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
255 protected void updateMenuIds(PopupMenuType type, TreeSet<Integer> set) {
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
265 protected int getAdditionalStringResourceForId(final int id) {
266 return getStringResourceForId(id);
270 * Gets the string resource for an id
271 * @param id the menu id
272 * @return string resource id
274 public static int getStringResourceForId(final int 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;
316 * Simple helper function for adding an item to the menu
318 public void addToMenu(final Menu menu, final int id, final int resourceId) {
319 menu.add(getGroupId(), id, id /*as order*/, mActivity.getString(resourceId));
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();
330 case FragmentMenuItems.PLAY_SELECTION:
331 MusicUtils.playAll(mActivity, getIdList(), 0, getSourceId(), getSourceType(),
334 case FragmentMenuItems.ADD_TO_QUEUE:
335 MusicUtils.addToQueue(mActivity, getIdList(), getSourceId(), getSourceType());
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() {
343 public boolean onMenuItemSelected(MenuBuilder menu, MenuItem item) {
344 return onMenuItemClick(item);
348 public void onMenuModeChange(MenuBuilder menu) {
352 builder.showDialog(null, null);
354 case FragmentMenuItems.NEW_PLAYLIST:
355 CreateNewPlaylist.getInstance(getIdList()).show(
356 mFragmentManager, "CreatePlaylist");
358 case FragmentMenuItems.RENAME_PLAYLIST:
359 RenamePlaylist.getInstance(getId()).show(
360 mFragmentManager, "RenameDialog");
362 case FragmentMenuItems.PLAYLIST_SELECTED:
363 final long mPlaylistId = item.getIntent().getLongExtra("playlist", 0);
364 MusicUtils.addToPlaylist(mActivity, getIdList(), mPlaylistId);
366 case FragmentMenuItems.MORE_BY_ARTIST:
367 NavUtils.openArtistProfile(mActivity, getArtistName());
369 case FragmentMenuItems.DELETE:
372 case FragmentMenuItems.USE_AS_RINGTONE:
373 MusicUtils.setRingtone(mActivity, getId());
375 case FragmentMenuItems.REMOVE_FROM_PLAYLIST:
376 removeFromPlaylist();
378 case FragmentMenuItems.REMOVE_FROM_QUEUE:
381 case FragmentMenuItems.PLAY_NEXT:
384 case FragmentMenuItems.PLAY_ALBUM: