package org.limewire.ui.swing.upload.table; import java.awt.Component; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.File; import java.util.ArrayList; import java.util.Collection; import java.util.List; import javax.swing.JMenu; import javax.swing.JMenuItem; import javax.swing.JPopupMenu; import javax.swing.table.TableCellEditor; import org.limewire.core.api.Category; import org.limewire.core.api.endpoint.RemoteHost; import org.limewire.core.api.library.LibraryManager; import org.limewire.core.api.upload.UploadItem; import org.limewire.core.api.upload.UploadItem.UploadItemType; import org.limewire.ui.swing.library.table.ListMenuFactory; import org.limewire.ui.swing.search.BlockUserMenuFactory; import org.limewire.ui.swing.search.RemoteHostMenuFactory; import org.limewire.ui.swing.upload.UploadMediator; import org.limewire.ui.swing.util.I18n; import com.google.inject.Inject; import com.google.inject.Provider; import com.google.inject.assistedinject.Assisted; /** * Popup menu for the Uploads table. */ public class UploadPopupMenu extends JPopupMenu { private final UploadTable table; private final List<UploadItem> uploadItems; private final Provider<List<File>> selectedFiles; private final UploadActionHandler actionHandler; private final LibraryManager libraryManager; private final RemoteHostMenuFactory browseMenuFactory; private final BlockUserMenuFactory blockUserMenuFactory; private final ListMenuFactory listMenuFactory; private Collection<RemoteHost> remoteHosts; @Inject public UploadPopupMenu( @Assisted UploadTable table, @Assisted List<UploadItem> uploadItems, @FinishedUploadSelected Provider<List<File>> selectedFiles, UploadActionHandler actionHandler, LibraryManager libraryManager, RemoteHostMenuFactory browseMenuFactory, BlockUserMenuFactory blockUserMenuFactory, ListMenuFactory listMenuFactory) { this.table = table; this.uploadItems = uploadItems; this.selectedFiles = selectedFiles; this.actionHandler = actionHandler; this.libraryManager = libraryManager; this.browseMenuFactory = browseMenuFactory; this.blockUserMenuFactory = blockUserMenuFactory; this.listMenuFactory = listMenuFactory; createMenu(); } /** * Builds the menu. */ private void createMenu() { int itemCount = uploadItems.size(); if (itemCount == 0) { throw new IllegalStateException(I18n.tr("No selected items")); } else if (itemCount == 1) { UploadItem item = uploadItems.get(0); switch (item.getUploadItemType()) { case GNUTELLA: createSingleGnutellaMenu(item); break; case BITTORRENT: createSingleTorrentMenu(item); break; default: throw new IllegalStateException(I18n.tr("Unknown upload type: " + item.getUploadItemType())); } } else { // Multiple items selected. createMultipleItemMenu(); } } /** * Builds the menu for a single Gnutella upload item. */ private void createSingleGnutellaMenu(UploadItem uploadItem) { ActionListener listener = new DefaultMenuListener(); boolean done = UploadMediator.isRemovable(uploadItem); boolean browseItem = UploadMediator.isBrowseHost(uploadItem); if (done) { add(createRemoveMenuItem()); } else { add(createCancelMenuItem(listener)); } if (!browseItem) { if (getComponentCount() > 0) { addSeparator(); } JMenuItem launchMenuItem = new JMenuItem(I18n.tr("Play/Open")); launchMenuItem.setActionCommand(isPlayable(uploadItem.getCategory()) ? UploadActionHandler.PLAY_COMMAND : UploadActionHandler.LAUNCH_COMMAND); launchMenuItem.addActionListener(listener); add(launchMenuItem); JMenuItem locateOnDiskMenuItem = new JMenuItem(I18n.tr("Locate on Disk")); locateOnDiskMenuItem.setActionCommand(UploadActionHandler.LOCATE_ON_DISK_COMMAND); locateOnDiskMenuItem.addActionListener(listener); add(locateOnDiskMenuItem); JMenuItem showInLibraryMenuItem = new JMenuItem(I18n.tr("Locate in Library")); showInLibraryMenuItem.setActionCommand(UploadActionHandler.LIBRARY_COMMAND); showInLibraryMenuItem.addActionListener(listener); add(showInLibraryMenuItem).setEnabled(libraryManager.getLibraryManagedList().contains(uploadItem.getUrn())); } if (done && !browseItem) { addSeparator(); JMenu addToListMenu = listMenuFactory.createAddToListMenu(selectedFiles); add(addToListMenu); JMenu showInListMenu = listMenuFactory.createShowInListMenu(selectedFiles, true); add(showInListMenu); } addSeparator(); JMenu browseMenu = browseMenuFactory.createBrowseMenu(getRemoteHosts()); add(browseMenu); JMenu blockMenu = blockUserMenuFactory.createDownloadBlockMenu(getRemoteHosts()); if (blockMenu != null) { add(blockMenu); } if (!browseItem) { addSeparator(); add(createFileInfoMenuItem(listener)); } } /** * Builds the menu for a single BitTorrent upload item. */ private void createSingleTorrentMenu(UploadItem uploadItem) { ActionListener listener = new DefaultMenuListener(); boolean done = UploadMediator.isRemovable(uploadItem); boolean browseItem = UploadMediator.isBrowseHost(uploadItem); boolean pausable = UploadMediator.isPausable(uploadItem); boolean resumable = UploadMediator.isResumable(uploadItem); if (pausable) { add(createPauseMenuItem()); } if (resumable) { add(createResumeMenuItem()); } if (done) { add(createRemoveMenuItem()); } else { add(createCancelMenuItem(listener)); } if (!browseItem) { if (getComponentCount() > 0) { addSeparator(); } JMenuItem locateOnDiskMenuItem = new JMenuItem(I18n.tr("Locate on Disk")); locateOnDiskMenuItem.setActionCommand(UploadActionHandler.LOCATE_ON_DISK_COMMAND); locateOnDiskMenuItem.addActionListener(listener); add(locateOnDiskMenuItem); } if (done) { if (getComponentCount() > 0) { addSeparator(); } JMenu addToListMenu = listMenuFactory.createAddToListMenu(selectedFiles); add(addToListMenu); } if (!browseItem) { if (getComponentCount() > 0) { addSeparator(); } add(createFileInfoMenuItem(listener)); } } /** * Builds the menu for multiple upload items. */ private void createMultipleItemMenu() { boolean allBrowse = isAllBrowse(); boolean allDone = isAllDone(); boolean anyPausable = isAnyPausable(); boolean anyResumable = isAnyResumable(); if (!allDone) { if (anyPausable) { add(createPauseMenuItem()); } if (anyResumable) { add(createResumeMenuItem()); } } if (allDone || isAnyRemovable()) { add(createRemoveMenuItem()); } if (!allDone) { if (getComponentCount() > 0) { addSeparator(); } JMenu browseMenu = browseMenuFactory.createBrowseMenu(getRemoteHosts()); add(browseMenu); JMenu blockMenu = blockUserMenuFactory.createDownloadBlockMenu(getRemoteHosts()); if (blockMenu != null) { add(blockMenu); } addSeparator(); add(createCancelMenuItem(new DefaultMenuListener())); } else if (!allBrowse) { if (getComponentCount() > 0) { addSeparator(); } JMenu addToListMenu = listMenuFactory.createAddToListMenu(selectedFiles); add(addToListMenu); } } /** * Creates a Cancel menu item with the specified action listener. */ private JMenuItem createCancelMenuItem(ActionListener listener) { JMenuItem menuItem = new JMenuItem(I18n.tr("Cancel")); menuItem.setActionCommand(UploadActionHandler.CANCEL_COMMAND); menuItem.addActionListener(listener); return menuItem; } /** * Creates a Remove menu item. */ private JMenuItem createRemoveMenuItem() { JMenuItem menuItem = new JMenuItem(I18n.tr("Clear from Tray")); menuItem.setActionCommand(UploadActionHandler.REMOVE_COMMAND); menuItem.addActionListener(new RemoveMenuListener()); return menuItem; } /** * Creates a Pause menu item. */ private JMenuItem createPauseMenuItem() { JMenuItem menuItem = new JMenuItem(I18n.tr("Pause")); menuItem.setActionCommand(UploadActionHandler.PAUSE_COMMAND); menuItem.addActionListener(new PauseMenuListener()); return menuItem; } /** * Creates a Resume menu item. */ private JMenuItem createResumeMenuItem() { JMenuItem menuItem = new JMenuItem(I18n.tr("Resume")); menuItem.setActionCommand(UploadActionHandler.RESUME_COMMAND); menuItem.addActionListener(new ResumeMenuListener()); return menuItem; } /** * Creates a View Info menu item. */ private JMenuItem createFileInfoMenuItem(ActionListener listener) { JMenuItem menuItem = new JMenuItem(I18n.tr("View File Info...")); menuItem.setActionCommand(UploadActionHandler.PROPERTIES_COMMAND); menuItem.addActionListener(listener); return menuItem; } /** * Returns the remote hosts associated with the upload items. Torrent * items are excluded. */ private Collection<RemoteHost> getRemoteHosts() { if (remoteHosts == null) { remoteHosts = new ArrayList<RemoteHost>(); for (UploadItem item : uploadItems) { if (item.getUploadItemType() != UploadItemType.BITTORRENT) { remoteHosts.add(item.getRemoteHost()); } } } return remoteHosts; } /** * Returns true if all upload items are browse items. */ private boolean isAllBrowse() { for (UploadItem item : uploadItems) { if (!UploadMediator.isBrowseHost(item)) { return false; } } return true; } /** * Returns true if all upload items are done. */ private boolean isAllDone() { for (UploadItem item : uploadItems) { if (!UploadMediator.isRemovable(item)) { return false; } } return true; } /** * Returns true if any upload items are pausable. */ private boolean isAnyPausable() { for (UploadItem item : uploadItems) { if (UploadMediator.isPausable(item)) { return true; } } return false; } /** * Returns true if any upload items are resumable. */ private boolean isAnyResumable() { for (UploadItem item : uploadItems) { if (UploadMediator.isResumable(item)) { return true; } } return false; } /** * Returns true if any upload items are removable. */ private boolean isAnyRemovable() { for (UploadItem item : uploadItems) { if (UploadMediator.isRemovable(item)) { return true; } } return false; } /** * Returns true if the specified Category represents a playable file. */ private boolean isPlayable(Category category) { return (category == Category.AUDIO) || (category == Category.VIDEO); } /** * Cancels cell editing on the table. */ private void cancelEditing() { Component comp = table.getEditorComponent(); if (comp instanceof TableCellEditor) { ((TableCellEditor)comp).cancelCellEditing(); } } /** * Default menu listener that accepts all upload items. */ private class DefaultMenuListener extends MenuListener { @Override protected boolean isValid(UploadItem item) { return true; } } /** * Menu listener to pause upload items. */ private class PauseMenuListener extends MenuListener { @Override protected boolean isValid(UploadItem item) { return UploadMediator.isPausable(item); } } /** * Menu listener to resume upload items. */ private class ResumeMenuListener extends MenuListener { @Override protected boolean isValid(UploadItem item) { return UploadMediator.isResumable(item); } } /** * Menu listener to remove upload items. */ private class RemoveMenuListener extends MenuListener { @Override protected boolean isValid(UploadItem item) { return UploadMediator.isRemovable(item); } } /** * Base class for menu item action listeners. */ private abstract class MenuListener implements ActionListener { @Override public void actionPerformed(ActionEvent e) { for (UploadItem item : uploadItems) { if (isValid(item)) { actionHandler.performAction(e.getActionCommand(), item); } } // must cancel editing cancelEditing(); } /** * Returns true if the specified upload item can be acted on. */ protected abstract boolean isValid(UploadItem item); } }