com.cyanogenmod.eleven.utils.PopupMenuHelper.java Source code

Java tutorial

Introduction

Here is the source code for com.cyanogenmod.eleven.utils.PopupMenuHelper.java

Source

/*
* Copyright (C) 2014 The CyanogenMod Project
*
* 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.cyanogenmod.eleven.utils;

import android.app.Activity;
import android.support.v4.app.FragmentManager;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.PopupMenu;

import com.android.internal.view.menu.ContextMenuBuilder;
import com.android.internal.view.menu.MenuBuilder;
import com.cyanogenmod.eleven.Config;
import com.cyanogenmod.eleven.R;
import com.cyanogenmod.eleven.menu.CreateNewPlaylist;
import com.cyanogenmod.eleven.menu.FragmentMenuItems;
import com.cyanogenmod.eleven.menu.RenamePlaylist;
import com.cyanogenmod.eleven.provider.RecentStore;

import java.util.TreeSet;

/**
 * Simple helper class that does most of the popup menu inflating and handling
 * It has a few hooks around so that if the class wants customization they can add it on
 * without changing this class too much
 */
public abstract class PopupMenuHelper implements PopupMenu.OnMenuItemClickListener {
    // the different types of pop up menus
    public static enum PopupMenuType {
        Artist, Album, Song, Playlist, SmartPlaylist, SearchResult, Queue,
    }

    protected Activity mActivity;
    protected PopupMenuType mType;
    protected FragmentManager mFragmentManager;

    public PopupMenuHelper(final Activity activity, final FragmentManager fragmentManager) {
        mActivity = activity;
        mFragmentManager = fragmentManager;
    }

    /**
     * Call this to inflate and show the pop up menu
     * @param view the view to anchor the popup menu against
     * @param position the item that was clicked in the popup menu (or -1 if not relevant)
     */
    public void showPopupMenu(final View view, final int position) {
        // create the popup menu
        PopupMenu popupMenu = new PopupMenu(mActivity, view);
        final Menu menu = popupMenu.getMenu();

        // hook up the click listener
        popupMenu.setOnMenuItemClickListener(this);

        // figure what type of pop up menu it is
        mType = onPreparePopupMenu(position);
        if (mType != null) {
            // inflate the menu
            createPopupMenu(menu);
            // show it
            popupMenu.show();
        }
    }

    /**
     * This function allows classes to setup any variables before showing the popup menu
     * @param position the position passed in from showPopupMenu
     * @return the pop up menu type, or null if we shouldn't show a pop up menu
     */
    public abstract PopupMenuType onPreparePopupMenu(final int position);

    /**
     * @return the list of ids needed for some menu actions like playing a list of songs
     */
    protected abstract long[] getIdList();

    protected abstract long getSourceId();

    protected abstract Config.IdType getSourceType();

    /**
     * @return the group id to be used for pop up menu inflating
     */
    protected int getGroupId() {
        return 0;
    }

    /**
     * called when the delete item is pressed.
     */
    protected void onDeleteClicked() {
        throw new UnsupportedOperationException("Method Not Implemented!");
    }

    /**
     * @return the artist name (when needed) for "more by this artist"
     */
    protected String getArtistName() {
        throw new UnsupportedOperationException("Method Not Implemented!");
    }

    /**
     * @return the single id that is needed for the "set as my ringtone"
     */
    protected long getId() {
        long[] idList = getIdList();
        if (idList.length == 1) {
            return idList[0];
        }

        throw new UnsupportedOperationException("Method Not Implemented!");
    }

    /**
     * Called when the user clicks "remove from playlist"
     */
    protected void removeFromPlaylist() {
        throw new UnsupportedOperationException("Method Not Implemented!");
    }

    /**
     * Called when the user clicks "remove from queue"
     */
    protected void removeFromQueue() {
        throw new UnsupportedOperationException("Method Not Implemented!");
    }

    /**
     * Called when the user clicks "play next".  Has a default implementation
     */
    protected void playNext() {
        MusicUtils.playNext(getIdList(), getSourceId(), getSourceType());
    }

    /**
     * Called when the user clicks "play album".
     */
    protected void playAlbum() {
        throw new UnsupportedOperationException("Method Not Implemented!");
    }

    /**
     * Creates the pop up menu by inflating the menu items
     * @param menu Menu to use for adding to
     */
    public void createPopupMenu(final Menu menu) {
        TreeSet<Integer> menuItems = new TreeSet<Integer>();

        // get the default items and add them
        int[] defaultItems = getIdsForType(mType);
        if (defaultItems != null) {
            for (int id : defaultItems) {
                menuItems.add(id);
            }
        }

        updateMenuIds(mType, menuItems);

        for (int id : menuItems) {
            addToMenu(menu, id, getAdditionalStringResourceForId(id));
        }
    }

    /**
     * Gets the default menu items for the specified type
     * @param type of pop up menu to create
     * @return list of menu items to inflate
     */
    private static int[] getIdsForType(PopupMenuType type) {
        switch (type) {
        case Artist:
            return new int[] { FragmentMenuItems.PLAY_SELECTION, FragmentMenuItems.ADD_TO_QUEUE,
                    FragmentMenuItems.ADD_TO_PLAYLIST, FragmentMenuItems.DELETE, FragmentMenuItems.CHANGE_IMAGE, };
        case Album:
            return new int[] { FragmentMenuItems.PLAY_SELECTION, FragmentMenuItems.ADD_TO_QUEUE,
                    FragmentMenuItems.ADD_TO_PLAYLIST, FragmentMenuItems.MORE_BY_ARTIST, FragmentMenuItems.DELETE,
                    FragmentMenuItems.CHANGE_IMAGE, };
        case Song:
            return new int[] { FragmentMenuItems.PLAY_SELECTION, FragmentMenuItems.PLAY_NEXT,
                    FragmentMenuItems.PLAY_ALBUM, FragmentMenuItems.ADD_TO_QUEUE, FragmentMenuItems.ADD_TO_PLAYLIST,
                    FragmentMenuItems.MORE_BY_ARTIST, FragmentMenuItems.USE_AS_RINGTONE,
                    FragmentMenuItems.DELETE, };
        case Playlist:
            return new int[] { FragmentMenuItems.PLAY_SELECTION, FragmentMenuItems.ADD_TO_QUEUE,
                    FragmentMenuItems.RENAME_PLAYLIST, FragmentMenuItems.DELETE, };
        case SmartPlaylist:
            return new int[] { FragmentMenuItems.PLAY_SELECTION, FragmentMenuItems.ADD_TO_QUEUE, };
        case SearchResult:
            return new int[] { FragmentMenuItems.PLAY_SELECTION, FragmentMenuItems.ADD_TO_QUEUE,
                    FragmentMenuItems.ADD_TO_PLAYLIST, };
        case Queue:
            return new int[] { FragmentMenuItems.PLAY_NEXT, FragmentMenuItems.ADD_TO_PLAYLIST,
                    FragmentMenuItems.REMOVE_FROM_QUEUE, FragmentMenuItems.MORE_BY_ARTIST,
                    FragmentMenuItems.USE_AS_RINGTONE, FragmentMenuItems.DELETE, };
        }

        return null;
    }

    /**
     * Allows containing classes to add/remove ids to the menu
     * @param type the pop up menu type
     * @param set the treeset to add/remove menu items
     */
    protected void updateMenuIds(PopupMenuType type, TreeSet<Integer> set) {
        // do nothing
    }

    /**
     * Gets the string resource for an id - if the string resource doesn't exist in this class
     * the containing class can override this method
     * @param id the menu id
     * @return string resource id
     */
    protected int getAdditionalStringResourceForId(final int id) {
        return getStringResourceForId(id);
    }

    /**
     * Gets the string resource for an id
     * @param id the menu id
     * @return string resource id
     */
    public static int getStringResourceForId(final int id) {
        switch (id) {
        case FragmentMenuItems.REMOVE_FROM_RECENT:
            return R.string.context_menu_remove_from_recent;
        case FragmentMenuItems.PLAY_SELECTION:
            return R.string.context_menu_play_selection;
        case FragmentMenuItems.ADD_TO_QUEUE:
            return R.string.add_to_queue;
        case FragmentMenuItems.ADD_TO_PLAYLIST:
            return R.string.add_to_playlist;
        case FragmentMenuItems.NEW_PLAYLIST:
            return R.string.new_playlist;
        case FragmentMenuItems.RENAME_PLAYLIST:
            return R.string.context_menu_rename_playlist;
        case FragmentMenuItems.PLAYLIST_SELECTED:
            return 0; // no string here expected
        case FragmentMenuItems.MORE_BY_ARTIST:
            return R.string.context_menu_more_by_artist;
        case FragmentMenuItems.DELETE:
            return R.string.context_menu_delete;
        case FragmentMenuItems.FETCH_ARTIST_IMAGE:
            return R.string.context_menu_fetch_artist_image;
        case FragmentMenuItems.FETCH_ALBUM_ART:
            return R.string.context_menu_fetch_album_art;
        case FragmentMenuItems.USE_AS_RINGTONE:
            return R.string.context_menu_use_as_ringtone;
        case FragmentMenuItems.REMOVE_FROM_PLAYLIST:
            return R.string.context_menu_remove_from_playlist;
        case FragmentMenuItems.REMOVE_FROM_QUEUE:
            return R.string.remove_from_queue;
        case FragmentMenuItems.PLAY_NEXT:
            return R.string.context_menu_play_next;
        case FragmentMenuItems.PLAY_ALBUM:
            return R.string.context_menu_play_album;
        case FragmentMenuItems.CHANGE_IMAGE:
            return R.string.context_menu_change_image;
        }

        return 0;
    }

    /**
     * Simple helper function for adding an item to the menu
     */
    public void addToMenu(final Menu menu, final int id, final int resourceId) {
        menu.add(getGroupId(), id, id /*as order*/, mActivity.getString(resourceId));
    }

    @Override
    public boolean onMenuItemClick(MenuItem item) {
        if (item.getGroupId() == getGroupId()) {
            switch (item.getItemId()) {
            case FragmentMenuItems.REMOVE_FROM_RECENT:
                RecentStore.getInstance(mActivity).removeItem(getId());
                MusicUtils.refresh();
                return true;
            case FragmentMenuItems.PLAY_SELECTION:
                MusicUtils.playAll(mActivity, getIdList(), 0, getSourceId(), getSourceType(), false);
                return true;
            case FragmentMenuItems.ADD_TO_QUEUE:
                MusicUtils.addToQueue(mActivity, getIdList(), getSourceId(), getSourceType());
                return true;
            case FragmentMenuItems.ADD_TO_PLAYLIST:
                ContextMenuBuilder builder = new ContextMenuBuilder(mActivity);
                MusicUtils.makePlaylistMenu(mActivity, getGroupId(), builder);
                builder.setHeaderTitle(R.string.add_to_playlist);
                builder.setCallback(new MenuBuilder.Callback() {
                    @Override
                    public boolean onMenuItemSelected(MenuBuilder menu, MenuItem item) {
                        return onMenuItemClick(item);
                    }

                    @Override
                    public void onMenuModeChange(MenuBuilder menu) {
                        // do nothing
                    }
                });
                builder.show(null, null);
                return true;
            case FragmentMenuItems.NEW_PLAYLIST:
                CreateNewPlaylist.getInstance(getIdList()).show(mFragmentManager, "CreatePlaylist");
                return true;
            case FragmentMenuItems.RENAME_PLAYLIST:
                RenamePlaylist.getInstance(getId()).show(mFragmentManager, "RenameDialog");
                return true;
            case FragmentMenuItems.PLAYLIST_SELECTED:
                final long mPlaylistId = item.getIntent().getLongExtra("playlist", 0);
                MusicUtils.addToPlaylist(mActivity, getIdList(), mPlaylistId);
                return true;
            case FragmentMenuItems.MORE_BY_ARTIST:
                NavUtils.openArtistProfile(mActivity, getArtistName());
                return true;
            case FragmentMenuItems.DELETE:
                onDeleteClicked();
                return true;
            case FragmentMenuItems.USE_AS_RINGTONE:
                MusicUtils.setRingtone(mActivity, getId());
                return true;
            case FragmentMenuItems.REMOVE_FROM_PLAYLIST:
                removeFromPlaylist();
                return true;
            case FragmentMenuItems.REMOVE_FROM_QUEUE:
                removeFromQueue();
                return true;
            case FragmentMenuItems.PLAY_NEXT:
                playNext();
                return true;
            case FragmentMenuItems.PLAY_ALBUM:
                playAlbum();
                return true;
            default:
                break;
            }
        }

        return false;
    }
}