Java tutorial
/* * PHEX - The pure-java Gnutella-servent. * Copyright (C) 2001 - 2008 Phex Development Group * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * --- SVN Information --- * $Id$ */ package phex.gui.tabs.download; import java.awt.Component; import java.awt.Dimension; import java.awt.Toolkit; import java.awt.datatransfer.StringSelection; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.List; import javax.swing.BorderFactory; import javax.swing.JComponent; import javax.swing.JMenu; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JPopupMenu; import javax.swing.JScrollPane; import javax.swing.JSplitPane; import javax.swing.JTabbedPane; import javax.swing.JTable; import javax.swing.JToolBar; import javax.swing.KeyStroke; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import phex.common.Environment; import phex.common.URN; import phex.common.address.DestAddress; import phex.common.format.NumberFormatUtils; import phex.common.log.LogBuffer; import phex.common.log.LogRecord; import phex.common.log.NLogger; import phex.download.strategy.AvailBeginRandSelectionStrategy; import phex.download.strategy.BeginAvailRandSelectionStrategy; import phex.download.strategy.BeginEndAvailRandSelectionStrategy; import phex.download.strategy.RandomScopeSelectionStrategy; import phex.download.strategy.ScopeSelectionStrategy; import phex.download.strategy.ScopeSelectionStrategyProvider; import phex.download.swarming.SWDownloadCandidate; import phex.download.swarming.SWDownloadFile; import phex.download.swarming.SwarmingManager; import phex.gui.actions.BanHostActionUtils; import phex.gui.actions.FWAction; import phex.gui.actions.FWToggleAction; import phex.gui.actions.GUIActionPerformer; import phex.gui.common.BrowserLauncher; import phex.gui.common.FWElegantPanel; import phex.gui.common.FWMenu; import phex.gui.common.FWToolBar; import phex.gui.common.GUIRegistry; import phex.gui.common.GUIUtils; import phex.gui.common.IconPack; import phex.gui.common.MainFrame; import phex.gui.common.table.FWSortedTableModel; import phex.gui.common.table.FWTable; import phex.gui.dialogs.DownloadConfigDialog; import phex.gui.dialogs.LogBufferDialog; import phex.gui.tabs.FWTab; import phex.prefs.core.BandwidthPrefs; import phex.prefs.core.DownloadPrefs; import phex.query.ResearchSetting; import phex.utils.Localizer; import phex.utils.SystemShellExecute; import phex.utils.URLUtil; import phex.xml.sax.gui.DGuiSettings; import phex.xml.sax.gui.DTable; import com.jgoodies.forms.builder.PanelBuilder; import com.jgoodies.forms.layout.CellConstraints; import com.jgoodies.forms.layout.FormLayout; import com.jgoodies.looks.Options; public class SWDownloadTab extends FWTab { private static final String DOWNLOAD_TABLE_IDENTIFIER = "DownloadTable"; private static final String CANDIDATE_TABLE_IDENTIFIER = "CandidateTable"; private static final SWDownloadFile[] EMPTY_DOWNLOADFILE_ARRAY = new SWDownloadFile[0]; private static final SWDownloadCandidate[] EMPTY_DOWNLOADCANDIDATE_ARRAY = new SWDownloadCandidate[0]; private final SwarmingManager downloadService; private FWTable downloadTable; private JScrollPane downloadTableScrollPane; private SWDownloadTableModel downloadModel; private JTabbedPane downloadDetails; private JPopupMenu downloadPopup; private JMenu downloadPopupSpeedMenu; private FWElegantPanel overviewElegantPanel; private DownloadOverviewPanel downloadOverviewPanel; private FWElegantPanel transfersElegantPanel; private DownloadTransfersPanel transfersPanel; private PanelBuilder candidatePanelBuilder; private FWElegantPanel candidateElegantPanel; private FWTable candidateTable; private JScrollPane candidateTableScrollPane; private SWCandidateTableModel candidateModel; private JPopupMenu candidatePopup; public SWDownloadTab(SwarmingManager downloadService) { super(MainFrame.DOWNLOAD_TAB_ID, Localizer.getString("Download"), GUIRegistry.getInstance().getPlafIconPack().getIcon("Download.Tab"), Localizer.getString("TTTDownloadTab"), Localizer.getChar("DownloadMnemonic"), KeyStroke.getKeyStroke(Localizer.getString("DownloadAccelerator")), MainFrame.DOWNLOAD_TAB_INDEX); if (downloadService == null) { throw new NullPointerException("DownloadService missing"); } this.downloadService = downloadService; } public void initComponent(DGuiSettings guiSettings) { MouseHandler mouseHandler = new MouseHandler(); CellConstraints cc = new CellConstraints(); FormLayout layout = new FormLayout("2dlu, fill:d:grow, 2dlu", // columns "2dlu, fill:d:grow, 2dlu"); //rows PanelBuilder tabBuilder = new PanelBuilder(layout, this); JPanel downloadTablePanel = initDownloadTablePanel(guiSettings, mouseHandler); initDownloadOverviewPanel(); JPanel downloadCandidatePanel = initDownloadCandidatePanel(guiSettings, mouseHandler); initDownloadTransferPanel(guiSettings); downloadDetails = new JTabbedPane(JTabbedPane.BOTTOM); downloadDetails.putClientProperty(Options.EMBEDDED_TABS_KEY, Boolean.TRUE); downloadDetails.setBorder(BorderFactory.createEmptyBorder(2, 0, 0, 0)); downloadDetails.addTab(Localizer.getString("DownloadTab_Overview"), overviewElegantPanel); downloadDetails.addTab(Localizer.getString("DownloadTab_Transfers"), transfersElegantPanel); downloadDetails.addTab(Localizer.getString("Candidates"), downloadCandidatePanel); // Workaround for very strange j2se 1.4 split pane layout behavior Dimension dim = new Dimension(400, 300); downloadTablePanel.setPreferredSize(dim); downloadDetails.setPreferredSize(dim); dim = new Dimension(0, 0); downloadTablePanel.setMinimumSize(dim); downloadDetails.setMinimumSize(dim); JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, downloadTablePanel, downloadDetails); splitPane.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0)); splitPane.setDividerSize(4); splitPane.setOneTouchExpandable(false); splitPane.setDividerLocation(0.5); splitPane.setResizeWeight(0.5); tabBuilder.add(splitPane, cc.xy(2, 2)); // increase table height a bit to display progress bar string better... GUIUtils.adjustTableProgresssBarHeight(downloadTable); GUIUtils.adjustTableProgresssBarHeight(candidateTable); //mDownloadMgr.addDownloadFilesChangeListener( new DownloadFilesChangeHandler() ); ActionListener updateDownloadFileInfoAction = new ActionListener() { public void actionPerformed(ActionEvent e) { updateDownloadFileInfo(); } }; GUIRegistry.getInstance().getGuiUpdateTimer().addActionListener(updateDownloadFileInfoAction); } private void initDownloadOverviewPanel() { downloadOverviewPanel = new DownloadOverviewPanel(); downloadOverviewPanel.initializeComponent(null); overviewElegantPanel = new FWElegantPanel(Localizer.getString("DownloadTab_DownloadOverview"), downloadOverviewPanel); } private void initDownloadTransferPanel(DGuiSettings guiSettings) { transfersPanel = new DownloadTransfersPanel(); transfersPanel.initializeComponent(guiSettings); transfersElegantPanel = new FWElegantPanel(Localizer.getString("DownloadTab_DownloadTransfers"), transfersPanel); } private JPanel initDownloadCandidatePanel(DGuiSettings guiSettings, MouseHandler mouseHandler) { JPanel downloadCandidatePanel = new JPanel(); CellConstraints cc = new CellConstraints(); FormLayout layout = new FormLayout("fill:d:grow", // columns "fill:d:grow, 1dlu, p"); //rows candidatePanelBuilder = new PanelBuilder(layout, downloadCandidatePanel); candidateModel = new SWCandidateTableModel(downloadTable, downloadService); candidateTable = new FWTable(new FWSortedTableModel(candidateModel)); GUIUtils.updateTableFromDGuiSettings(guiSettings, candidateTable, CANDIDATE_TABLE_IDENTIFIER); candidateTable.activateAllHeaderActions(); candidateTable.getSelectionModel().addListSelectionListener(new CandidateSelectionHandler()); candidateTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); candidateTable.addMouseListener(mouseHandler); GUIRegistry.getInstance().getGuiUpdateTimer().addTable(candidateTable); candidateTableScrollPane = FWTable.createFWTableScrollPane(candidateTable); candidateTableScrollPane.addMouseListener(mouseHandler); candidatePanelBuilder.add(candidateTableScrollPane, cc.xy(1, 1)); FWToolBar candidateToolbar = new FWToolBar(JToolBar.HORIZONTAL); candidateToolbar.setBorderPainted(false); candidateToolbar.setFloatable(false); candidatePanelBuilder.add(candidateToolbar, cc.xy(1, 3)); candidatePopup = new JPopupMenu(); // add actions to toolbar and popup FWAction action = new RetryCandidateAction(); addTabAction(action); candidateToolbar.addAction(action); candidatePopup.add(action); action = new RemoveCandidateAction(); addTabAction(action); candidateToolbar.addAction(action); candidatePopup.add(action); candidateTable.getActionMap().put(action, action); candidateTable.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT) .put((KeyStroke) action.getValue(FWAction.ACCELERATOR_KEY), action); candidatePopup.addSeparator(); candidateToolbar.addSeparator(); action = new AddToFavoritesAction(); addTabAction(action); candidatePopup.add(action); action = new BrowseHostAction(); addTabAction(action); candidateToolbar.addAction(action); candidatePopup.add(action); action = new ChatToHostAction(); addTabAction(action); candidateToolbar.addAction(action); candidatePopup.add(action); BanHostActionProvider banHostActionProvider = new BanHostActionProvider(); BanHostActionUtils.BanHostActionMenu bhActionMenu = BanHostActionUtils .createActionMenu(banHostActionProvider); candidatePopup.add(bhActionMenu.menu); addTabActions(bhActionMenu.actions); action = BanHostActionUtils.createToolBarAction(banHostActionProvider); candidateToolbar.addAction(action); addTabAction(action); if (DownloadPrefs.CandidateLogBufferSize.get().intValue() > 0) { action = new CandidateLogAction(); addTabAction(action); candidateToolbar.addAction(action); candidatePopup.add(action); } candidateElegantPanel = new FWElegantPanel(Localizer.getString("DownloadCandidates"), downloadCandidatePanel); return candidateElegantPanel; } private JPanel initDownloadTablePanel(DGuiSettings guiSettings, MouseHandler mouseHandler) { JPanel downloadTablePanel = new JPanel(); CellConstraints cc = new CellConstraints(); FormLayout layout = new FormLayout("fill:d:grow", // columns "fill:d:grow, 1dlu, p"); //rows PanelBuilder tabBuilder = new PanelBuilder(layout, downloadTablePanel); downloadModel = new SWDownloadTableModel(downloadService); downloadTable = new FWTable(new FWSortedTableModel(downloadModel)); GUIUtils.updateTableFromDGuiSettings(guiSettings, downloadTable, DOWNLOAD_TABLE_IDENTIFIER); downloadTable.activateAllHeaderActions(); downloadTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); downloadTable.getSelectionModel().addListSelectionListener(new DownloadSelectionHandler()); downloadTable.addMouseListener(mouseHandler); GUIRegistry.getInstance().getGuiUpdateTimer().addTable(downloadTable); downloadTableScrollPane = FWTable.createFWTableScrollPane(downloadTable); downloadTableScrollPane.addMouseListener(mouseHandler); tabBuilder.add(downloadTableScrollPane, cc.xy(1, 1)); FWToolBar fileToolbar = new FWToolBar(JToolBar.HORIZONTAL); fileToolbar.setBorderPainted(false); fileToolbar.setFloatable(false); tabBuilder.add(fileToolbar, cc.xy(1, 3)); downloadPopup = new JPopupMenu(); FWAction startDownloadAction = new StartDownloadAction(); addTabAction(startDownloadAction); fileToolbar.addAction(startDownloadAction); downloadPopup.add(startDownloadAction); FWAction stopDownloadAction = new StopDownloadAction(); addTabAction(stopDownloadAction); fileToolbar.addAction(stopDownloadAction); downloadPopup.add(stopDownloadAction); FWAction removeDownloadAction = new RemoveDownloadAction(); addTabAction(removeDownloadAction); fileToolbar.addAction(removeDownloadAction); downloadPopup.add(removeDownloadAction); downloadTable.getActionMap().put(removeDownloadAction, removeDownloadAction); downloadTable.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT) .put((KeyStroke) removeDownloadAction.getValue(FWAction.ACCELERATOR_KEY), removeDownloadAction); fileToolbar.addSeparator(); downloadPopup.addSeparator(); FWAction configureDownloadAction = new ConfigureDownloadAction(); addTabAction(configureDownloadAction); fileToolbar.addAction(configureDownloadAction); downloadPopup.add(configureDownloadAction); FWAction searchCandidateAction = new SearchCandidatesAction(); addTabAction(searchCandidateAction); fileToolbar.addAction(searchCandidateAction); downloadPopup.add(searchCandidateAction); downloadPopupSpeedMenu = new JMenu(Localizer.getString("DownloadTab_DownloadSpeed")); downloadPopup.add(downloadPopupSpeedMenu); JMenu priorityMenu = new JMenu(Localizer.getString("Priority")); FWAction priorityTopAction = new MoveDownloadPriorityAction( MoveDownloadPriorityAction.PRIORITY_MOVE_TO_TOP); priorityMenu.add(priorityTopAction); addTabAction(priorityTopAction); FWAction priorityUpAction = new MoveDownloadPriorityAction(MoveDownloadPriorityAction.PRIORITY_MOVE_UP); priorityMenu.add(priorityUpAction); addTabAction(priorityUpAction); FWAction priorityResortAction = new MoveDownloadPriorityAction(MoveDownloadPriorityAction.PRIORITY_RESORT); priorityMenu.add(priorityResortAction); addTabAction(priorityResortAction); FWAction priorityDownAction = new MoveDownloadPriorityAction(MoveDownloadPriorityAction.PRIORITY_MOVE_DOWN); priorityMenu.add(priorityDownAction); addTabAction(priorityDownAction); FWAction priorityBottomAction = new MoveDownloadPriorityAction( MoveDownloadPriorityAction.PRIORITY_MOVE_TO_BOTTOM); priorityMenu.add(priorityBottomAction); addTabAction(priorityBottomAction); downloadPopup.add(priorityMenu); FWMenu orderingMenu = new FWMenu(Localizer.getString("DownloadTab_Strategy")); FWAction action = new SelectStrategyAction(SelectStrategyAction.AVAILABILITY); orderingMenu.addAction(action); addTabAction(action); action = new SelectStrategyAction(SelectStrategyAction.PRIORITIZE_BEGINNING); orderingMenu.addAction(action); addTabAction(action); action = new SelectStrategyAction(SelectStrategyAction.PRIORITIZE_BEGINNING_END); orderingMenu.addAction(action); addTabAction(action); action = new SelectStrategyAction(SelectStrategyAction.RANDOM); orderingMenu.addAction(action); addTabAction(action); downloadPopup.add(orderingMenu); action = new GeneratePreviewAction(); addTabAction(action); fileToolbar.addAction(action); downloadPopup.add(action); action = new ViewBitziTicketAction(); addTabAction(action); downloadPopup.add(action); FWElegantPanel elegantPanel = new FWElegantPanel(Localizer.getString("DownloadFiles"), downloadTablePanel); return elegantPanel; } /** * {@inheritDoc} */ @Override public void updateUI() { super.updateUI(); if (downloadTable != null) { // increase table height a bit to display progress bar string better... GUIUtils.adjustTableProgresssBarHeight(downloadTable); } if (downloadTableScrollPane != null) { FWTable.updateFWTableScrollPane(downloadTableScrollPane); } if (candidateTableScrollPane != null) { FWTable.updateFWTableScrollPane(candidateTableScrollPane); } } /** * Updates dynamic information when changes occur. Called every 2 seconds * to update possible download changes or when the selected download * changes. */ private void updateDownloadFileInfo() { // map view to model int selectedRow = downloadTable.getSelectedRow(); int modelRow = downloadTable.translateRowIndexToModel(selectedRow); refreshTabActions(); SWDownloadFile file = downloadService.getDownloadFile(modelRow); downloadOverviewPanel.updateDownloadFileInfo(file); transfersPanel.updateDownloadFile(file); if (file != null) { ResearchSetting researchSetting = file.getResearchSetting(); if (researchSetting.isSearchRunning()) { Object[] args = { Integer.valueOf(researchSetting.getSearchHitCount()), Integer.valueOf(researchSetting.getSearchProgress()) }; overviewElegantPanel.setTitle(Localizer.getString("DownloadTab_DownloadOverview") + " " + Localizer.getFormatedString("CandidatesSearchingExt", args)); transfersElegantPanel.setTitle(Localizer.getString("DownloadTab_DownloadTransfers") + " " + Localizer.getFormatedString("CandidatesSearchingExt", args)); candidateElegantPanel.setTitle(Localizer.getString("DownloadCandidates") + " " + Localizer.getFormatedString("CandidatesSearchingExt", args)); } else { overviewElegantPanel.setTitle(Localizer.getString("DownloadTab_DownloadOverview")); transfersElegantPanel.setTitle(Localizer.getString("DownloadTab_DownloadTransfers")); candidateElegantPanel.setTitle(Localizer.getString("DownloadCandidates")); } } } private SWDownloadFile[] getSelectedDownloadFiles() { if (downloadTable.getSelectedRowCount() == 0) { return EMPTY_DOWNLOADFILE_ARRAY; } int[] viewIndices = downloadTable.getSelectedRows(); int[] modelIndices = downloadTable.convertRowIndicesToModel(viewIndices); SWDownloadFile[] files = downloadService.getDownloadFilesAt(modelIndices); return files; } private SWDownloadFile getSelectedDownloadFile() { int viewIndex = downloadTable.getSelectedRow(); if (viewIndex < 0) { return null; } int modelIndex = downloadTable.translateRowIndexToModel(viewIndex); SWDownloadFile file = downloadService.getDownloadFile(modelIndex); return file; } private SWDownloadCandidate[] getSelectedDownloadCandidates() { if (candidateTable.getSelectedRowCount() == 0) { return EMPTY_DOWNLOADCANDIDATE_ARRAY; } int[] viewIndices = candidateTable.getSelectedRows(); int[] modelIndices = candidateTable.convertRowIndicesToModel(viewIndices); SWDownloadCandidate[] candidates = new SWDownloadCandidate[modelIndices.length]; SWDownloadFile downloadFile = candidateModel.getDownloadFile(); for (int i = 0; i < candidates.length; i++) { candidates[i] = downloadFile.getCandidate(modelIndices[i]); } return candidates; } private SWDownloadCandidate getSelectedDownloadCandidate() { int viewIndex = candidateTable.getSelectedRow(); int modelIndex = candidateTable.translateRowIndexToModel(viewIndex); if (modelIndex < 0) { return null; } SWDownloadFile downloadFile = candidateModel.getDownloadFile(); SWDownloadCandidate candidate = downloadFile.getCandidate(modelIndex); return candidate; } ////////////////////////////////////////////////////////////////////////// /// XML serializing and deserializing ////////////////////////////////////////////////////////////////////////// /** * {@inheritDoc} */ @Override public void appendDGuiSettings(DGuiSettings dSettings) { super.appendDGuiSettings(dSettings); DTable dTable = GUIUtils.createDTable(downloadTable, DOWNLOAD_TABLE_IDENTIFIER); dSettings.getTableList().getTableList().add(dTable); dTable = GUIUtils.createDTable(candidateTable, CANDIDATE_TABLE_IDENTIFIER); dSettings.getTableList().getTableList().add(dTable); transfersPanel.appendDGuiSettings(dSettings); } ////////////////////////////////////////////////////////////////////////// /// Table Listeners ////////////////////////////////////////////////////////////////////////// /** * Selection listener for download file table. */ class DownloadSelectionHandler implements ListSelectionListener { public void valueChanged(ListSelectionEvent e) { try { updateDownloadFileInfo(); } catch (Exception exp) { NLogger.error(DownloadSelectionHandler.class, exp, exp); } } } /** * Selection listener for download candidate table. */ class CandidateSelectionHandler implements ListSelectionListener { public void valueChanged(ListSelectionEvent e) { if (!e.getValueIsAdjusting()) { refreshTabActions(); } } } private class MouseHandler extends MouseAdapter implements MouseListener { /** * {@inheritDoc} */ @Override public void mouseClicked(MouseEvent e) { } /** * {@inheritDoc} */ @Override public void mouseReleased(MouseEvent e) { if (e.isPopupTrigger()) { popupMenu((Component) e.getSource(), e.getX(), e.getY()); } } /** * {@inheritDoc} */ @Override public void mousePressed(MouseEvent e) { if (e.isPopupTrigger()) { popupMenu((Component) e.getSource(), e.getX(), e.getY()); } } private void popupMenu(Component source, int x, int y) { if (source == downloadTable || source == downloadTableScrollPane) { refreshTabActions(); prepareDownloadPopup(); downloadPopup.show(source, x, y); } else if (source == candidateTable || source == candidateTableScrollPane) { candidatePopup.show(source, x, y); } } public void prepareDownloadPopup() { downloadPopupSpeedMenu.removeAll(); if (downloadTable.getSelectedRowCount() > 0) { downloadPopupSpeedMenu.setEnabled(true); } else { downloadPopupSpeedMenu.setEnabled(false); return; } FWAction action; int downloadBw = BandwidthPrefs.MaxDownloadBandwidth.get().intValue(); if (downloadBw > BandwidthPrefs.MaxTotalBandwidth.get().intValue()) { downloadBw = BandwidthPrefs.MaxTotalBandwidth.get().intValue(); } if (downloadBw >= Integer.MAX_VALUE) { downloadBw = (int) (500 * NumberFormatUtils.ONE_KB); } double downloadBwFraction = downloadBw / 10.0; action = new SetDownloadSpeedAction(Integer.MAX_VALUE); downloadPopupSpeedMenu.add(action); for (int i = 10; i > 0; i--) { action = new SetDownloadSpeedAction((int) (downloadBwFraction * i)); downloadPopupSpeedMenu.add(action); } } } ////////////////////////////////////////////////////////////////////////// /// Actions ////////////////////////////////////////////////////////////////////////// /** * Starts a download. */ class StartDownloadAction extends FWAction { StartDownloadAction() { super(Localizer.getString("StartDownload"), GUIRegistry.getInstance().getPlafIconPack().getIcon("Download.StartDownload"), Localizer.getString("TTTStartDownload")); refreshActionState(); } public void actionPerformed(ActionEvent e) { SWDownloadFile[] files = getSelectedDownloadFiles(); for (int i = 0; i < files.length; i++) { if (files[i] != null && files[i].isDownloadStopped()) { files[i].startDownload(); } } refreshActionState(); } /** * {@inheritDoc} */ @Override public void refreshActionState() { SWDownloadFile[] files = getSelectedDownloadFiles(); boolean state = false; for (int i = 0; i < files.length; i++) { if (files[i] != null && files[i].isDownloadStopped()) { state = true; break; } } setEnabled(state); } } /** * Stops a download. */ class StopDownloadAction extends FWAction { StopDownloadAction() { super(Localizer.getString("StopDownload"), GUIRegistry.getInstance().getPlafIconPack().getIcon("Download.StopDownload"), Localizer.getString("TTTStopDownload")); refreshActionState(); } public void actionPerformed(ActionEvent e) { final SWDownloadFile[] files = getSelectedDownloadFiles(); Runnable runner = new Runnable() { public void run() { try { for (int i = 0; i < files.length; i++) { if (files[i] != null && !files[i].isFileCompletedOrMoved() && !files[i].isDownloadStopped()) { files[i].stopDownload(); } } refreshActionState(); } catch (Throwable th) { NLogger.error(StopDownloadAction.class, th, th); } } }; Environment.getInstance().executeOnThreadPool(runner, "StopDownloadFiles"); } /** * {@inheritDoc} */ @Override public void refreshActionState() { SWDownloadFile[] files = getSelectedDownloadFiles(); boolean state = false; for (int i = 0; i < files.length; i++) { if (files[i] != null && !files[i].isFileCompletedOrMoved() && !files[i].isDownloadStopped()) { state = true; break; } } setEnabled(state); } } class ConfigureDownloadAction extends FWAction { ConfigureDownloadAction() { super(Localizer.getString("ConfigureDownload"), GUIRegistry.getInstance().getPlafIconPack().getIcon("Download.ConfigureDownload"), Localizer.getString("TTTConfigureDownload")); refreshActionState(); } public void actionPerformed(ActionEvent e) { if (downloadTable.getSelectedRowCount() != 1) { setEnabled(false); return; } int viewIdx = downloadTable.getSelectedRow(); int modelIdx = downloadTable.translateRowIndexToModel(viewIdx); SWDownloadFile dfile = downloadService.getDownloadFile(modelIdx); if (dfile != null) { if (dfile.isDownloadInProgress()) { JOptionPane.showMessageDialog(SWDownloadTab.this, Localizer.getString("NoConfigDownloadInProgress"), Localizer.getString("DownloadInProgress"), JOptionPane.WARNING_MESSAGE); return; } int oldStatus = dfile.getStatus(); dfile.stopDownload(); DownloadConfigDialog dialog = new DownloadConfigDialog(dfile); dialog.setVisible(true); dfile.setStatus(oldStatus); } } /** * {@inheritDoc} */ @Override public void refreshActionState() { if (downloadTable.getSelectedRowCount() != 1) { setEnabled(false); return; } SWDownloadFile file = getSelectedDownloadFile(); if (file == null || file.isFileCompletedOrMoved()) { setEnabled(false); } else { setEnabled(true); } } } /** * Removes a download from the list. */ class RemoveDownloadAction extends FWAction { RemoveDownloadAction() { super(Localizer.getString("RemoveDownload"), GUIRegistry.getInstance().getPlafIconPack().getIcon("Download.RemoveDownload"), Localizer.getString("TTTRemoveDownload"), null, KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0)); refreshActionState(); } public void actionPerformed(ActionEvent e) { SWDownloadFile[] files = getSelectedDownloadFiles(); List<SWDownloadFile> warningFiles = new ArrayList<SWDownloadFile>(files.length); List<SWDownloadFile> removeFiles = new ArrayList<SWDownloadFile>(files.length); for (int i = 0; i < files.length; i++) { if (files[i] == null) { continue; } if (files[i].isFileCompletedMoved()) { removeFiles.add(files[i]); } else if (files[i].isFileCompleted()) { // ignore the intermediate state of a file between beeing // completed and beeing completed moved } // if download not started. else if (files[i].getTransferredDataSize() == 0) { removeFiles.add(files[i]); } else {// if not completed... schedule for warning warningFiles.add(files[i]); } } Integer warningSize = Integer.valueOf(warningFiles.size()); for (int i = 0; i < warningSize.intValue(); i++) { SWDownloadFile file = warningFiles.get(i); Object[] warningParams = new Object[] { file.getFileName(), NumberFormatUtils.formatSignificantByteSize(file.getTransferredDataSize()), NumberFormatUtils.formatSignificantByteSize(file.getTransferDataSize()) }; Object[] titleParams = new Object[] { Integer.valueOf(i + 1), warningSize }; Object[] dialogOptions; if (warningSize.intValue() - i > 1) { dialogOptions = new Object[] { Localizer.getString("Yes"), Localizer.getString("No"), Localizer.getString("YesToAll"), Localizer.getString("NoToAll"), }; } else { dialogOptions = new Object[] { Localizer.getString("Yes"), Localizer.getString("No") }; } int choice = JOptionPane.showOptionDialog(GUIRegistry.getInstance().getMainFrame(), Localizer.getFormatedString("RemoveDownloadWarning", warningParams), Localizer.getFormatedString("RemoveDownloadTitle", titleParams), JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE, null, dialogOptions, Localizer.getString("Yes")); if (choice == 0) { removeFiles.add(file); } else if (choice == 2) { removeFiles.addAll(warningFiles.subList(i, warningFiles.size())); break; } else if (choice == 3) { break; } } // do the remove... if (removeFiles.size() > 0) { final SWDownloadFile[] filesToRemove = new SWDownloadFile[removeFiles.size()]; removeFiles.toArray(filesToRemove); Runnable runner = new Runnable() { public void run() { try { downloadService.removeDownloadFiles(filesToRemove); } catch (Throwable th) { NLogger.error(RemoveDownloadAction.class, th, th); } } }; Environment.getInstance().executeOnThreadPool(runner, "RemoveDownloadFiles"); downloadTable.getSelectionModel().clearSelection(); } } /** * {@inheritDoc} */ @Override public void refreshActionState() { int row = downloadTable.getSelectedRow(); if (row < 0) { setEnabled(false); } else { setEnabled(true); } } } /** * */ class SetDownloadSpeedAction extends FWAction { private int speedInBytes; SetDownloadSpeedAction(int speedInBytes) { super(); this.speedInBytes = speedInBytes; String name; if (speedInBytes >= Integer.MAX_VALUE) { name = Localizer.getString("DownloadTab_NoLimit") + " (" + Localizer.getDecimalFormatSymbols().getInfinity() + ")"; } else { name = NumberFormatUtils.formatSignificantByteSize(speedInBytes) + Localizer.getString("PerSec"); } setName(name); } public void actionPerformed(ActionEvent e) { SWDownloadFile[] files = getSelectedDownloadFiles(); for (int i = 0; i < files.length; i++) { if (files[i] != null) { files[i].setDownloadThrottlingRate(speedInBytes); } } } /** * {@inheritDoc} */ @Override public void refreshActionState() { } } /** * Moves a download in the list. */ class MoveDownloadPriorityAction extends FWAction { private static final short PRIORITY_MOVE_TO_TOP = SwarmingManager.PRIORITY_MOVE_TO_TOP; private static final short PRIORITY_MOVE_UP = SwarmingManager.PRIORITY_MOVE_UP; private static final short PRIORITY_MOVE_DOWN = SwarmingManager.PRIORITY_MOVE_DOWN; private static final short PRIORITY_MOVE_TO_BOTTOM = SwarmingManager.PRIORITY_MOVE_TO_BOTTOM; private static final short PRIORITY_RESORT = 100; private short moveDirection; MoveDownloadPriorityAction(short type) { super(); moveDirection = type; switch (type) { case PRIORITY_MOVE_TO_TOP: setName(Localizer.getString("MoveToTop")); setToolTipText(Localizer.getString("TTTMoveToTop")); break; case PRIORITY_MOVE_UP: setName(Localizer.getString("MoveUp")); setToolTipText(Localizer.getString("TTTMoveUp")); break; case PRIORITY_MOVE_DOWN: setName(Localizer.getString("MoveDown")); setToolTipText(Localizer.getString("TTTMoveDown")); break; case PRIORITY_MOVE_TO_BOTTOM: setName(Localizer.getString("MoveToBottom")); setToolTipText(Localizer.getString("TTTMoveToBottom")); break; case PRIORITY_RESORT: setName(Localizer.getString("Resort")); setToolTipText(Localizer.getString("TTTResort")); break; } setupIcons(); refreshActionState(); } private void setupIcons() { IconPack iconPack = GUIRegistry.getInstance().getPlafIconPack(); switch (moveDirection) { case PRIORITY_MOVE_TO_TOP: setSmallIcon(iconPack.getIcon("Download.PriorityTop")); break; case PRIORITY_MOVE_UP: setSmallIcon(iconPack.getIcon("Download.PriorityUp")); break; case PRIORITY_MOVE_DOWN: setSmallIcon(iconPack.getIcon("Download.PriorityDown")); break; case PRIORITY_MOVE_TO_BOTTOM: setSmallIcon(iconPack.getIcon("Download.PriorityBottom")); break; case PRIORITY_RESORT: setSmallIcon(iconPack.getIcon("Download.PriorityResort")); break; } } public void actionPerformed(ActionEvent e) { try { if (moveDirection == PRIORITY_RESORT) { performPriorityResort(); } else { performPriorityUpdate(); } } catch (Throwable th) { NLogger.error(MoveDownloadPriorityAction.class, th, th); } } /** * */ private void performPriorityResort() { int[] viewIndices = new int[downloadTable.getRowCount()]; for (int i = 0; i < viewIndices.length; i++) { viewIndices[i] = i; } final int[] modelIndices = downloadTable.convertRowIndicesToModel(viewIndices); Runnable runner = new Runnable() { public void run() { try { SWDownloadFile[] files = downloadService.getDownloadFilesAt(modelIndices); downloadService.updateDownloadFilePriorities(files); } catch (Throwable th) { NLogger.error(MoveDownloadPriorityAction.class, th, th); } } }; Environment.getInstance().executeOnThreadPool(runner, "ResortPriority"); } /** * */ private void performPriorityUpdate() { final SWDownloadFile[] files = getSelectedDownloadFiles(); Runnable runner = new Runnable() { public void run() { try { for (int i = 0; i < files.length; i++) { if (files[i] != null) { downloadService.moveDownloadFilePriority(files[i], moveDirection); } } } catch (Throwable th) { NLogger.error(MoveDownloadPriorityAction.class, th, th); } } }; Environment.getInstance().executeOnThreadPool(runner, "UpdatePriority"); } /** * {@inheritDoc} */ @Override public void refreshActionState() { if (moveDirection == PRIORITY_RESORT) { setEnabled(true); } else { if (downloadTable.getSelectedRowCount() > 0) { setEnabled(true); } else { setEnabled(false); } } } } class SelectStrategyAction extends FWToggleAction { private static final short AVAILABILITY = 0; private static final short PRIORITIZE_BEGINNING = 1; private static final short PRIORITIZE_BEGINNING_END = 2; private static final short RANDOM = 3; private short strategy; SelectStrategyAction(short strategy) { super(); this.strategy = strategy; switch (strategy) { case AVAILABILITY: setName(Localizer.getString("DownloadTab_StrategyAvailability")); break; case PRIORITIZE_BEGINNING: setName(Localizer.getString("DownloadTab_StrategyBeginning")); break; case PRIORITIZE_BEGINNING_END: setName(Localizer.getString("DownloadTab_StrategyBeginningEnd")); break; case RANDOM: setName(Localizer.getString("DownloadTab_StrategyRandom")); break; } refreshActionState(); } public void actionPerformed(ActionEvent e) { ScopeSelectionStrategy selectionStrategy; switch (strategy) { case AVAILABILITY: selectionStrategy = ScopeSelectionStrategyProvider.getAvailBeginRandSelectionStrategy(); break; case PRIORITIZE_BEGINNING: selectionStrategy = ScopeSelectionStrategyProvider.getBeginAvailRandSelectionStrategy(); break; case PRIORITIZE_BEGINNING_END: selectionStrategy = ScopeSelectionStrategyProvider.getBeginEndAvailRandSelectionStrategy(); break; default: selectionStrategy = ScopeSelectionStrategyProvider.getRandomSelectionStrategy(); break; } SWDownloadFile[] files = getSelectedDownloadFiles(); for (int i = 0; i < files.length; i++) { if (files[i] == null) { continue; } files[i].getMemoryFile().setScopeSelectionStrategy(selectionStrategy); } } /** * {@inheritDoc} */ @Override public void refreshActionState() { if (downloadTable.getSelectedRowCount() == 1) { setEnabled(true); SWDownloadFile file = getSelectedDownloadFile(); if (file == null) { setSelected(false); return; } ScopeSelectionStrategy curStrat = file.getMemoryFile().getScopeSelectionStrategy(); switch (strategy) { case AVAILABILITY: setSelected(curStrat instanceof AvailBeginRandSelectionStrategy); break; case PRIORITIZE_BEGINNING: setSelected(curStrat instanceof BeginAvailRandSelectionStrategy); break; case PRIORITIZE_BEGINNING_END: setSelected(curStrat instanceof BeginEndAvailRandSelectionStrategy); break; default: setSelected(curStrat instanceof RandomScopeSelectionStrategy); break; } } else { setEnabled(false); } } } class GeneratePreviewAction extends FWAction { GeneratePreviewAction() { super(Localizer.getString("DownloadTab_PreviewDownload"), GUIRegistry.getInstance().getPlafIconPack().getIcon("Download.Preview"), Localizer.getString("DownloadTab_TTTPreviewDownload")); refreshActionState(); } public void actionPerformed(ActionEvent e) { try { final SWDownloadFile file = getSelectedDownloadFile(); if (file == null) return; Runnable runner = new Runnable() { public void run() { try { File previewFile = file.getPreviewFile(); SystemShellExecute.launchFile(previewFile); } catch (Throwable th) { NLogger.error(GeneratePreviewAction.class, th, th); } } }; Environment.getInstance().executeOnThreadPool(runner, "GenerateDownloadPreview"); } catch (Throwable th) { NLogger.error(GeneratePreviewAction.class, th, th); } } /** * {@inheritDoc} */ @Override public void refreshActionState() { try { SWDownloadFile file = getSelectedDownloadFile(); if (file == null) { // no file, no do setEnabled(false); } else { setEnabled(file.isPreviewPossible()); } } catch (Throwable th) { NLogger.error(GeneratePreviewAction.class, th, th); } } } private class ViewBitziTicketAction extends FWAction { public ViewBitziTicketAction() { super(Localizer.getString("ViewBitziTicket"), GUIRegistry.getInstance().getPlafIconPack().getIcon("Download.ViewBitzi"), Localizer.getString("TTTViewBitziTicket")); refreshActionState(); } public void actionPerformed(ActionEvent e) { SWDownloadFile file = getSelectedDownloadFile(); if (file == null) { return; } URN urn = file.getFileURN(); if (urn == null) { return; } String url = URLUtil.buildBitziLookupURL(urn); try { BrowserLauncher.openURL(url); } catch (IOException exp) { NLogger.warn(ViewBitziTicketAction.class, exp, exp); Object[] dialogOptions = new Object[] { Localizer.getString("Yes"), Localizer.getString("No") }; int choice = JOptionPane.showOptionDialog(SWDownloadTab.this, Localizer.getString("FailedToLaunchBrowserURLInClipboard"), Localizer.getString("FailedToLaunchBrowser"), JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE, null, dialogOptions, Localizer.getString("Yes")); if (choice == 0) { Toolkit.getDefaultToolkit().getSystemClipboard().setContents(new StringSelection(url), null); } } } /** * {@inheritDoc} */ @Override public void refreshActionState() { if (downloadTable.getSelectedRowCount() == 1) { setEnabled(true); } else { setEnabled(false); } } } /** * Removes a candidate from the list. */ class RemoveCandidateAction extends FWAction { RemoveCandidateAction() { super(Localizer.getString("RemoveCandidate"), GUIRegistry.getInstance().getPlafIconPack().getIcon("Download.RemoveCandidate"), Localizer.getString("TTTRemoveCandidate"), null, KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0)); refreshActionState(); } public void actionPerformed(ActionEvent e) { final SWDownloadCandidate[] candidates = getSelectedDownloadCandidates(); final SWDownloadFile file = candidateModel.getDownloadFile(); Runnable runner = new Runnable() { public void run() { try { for (int i = 0; i < candidates.length; i++) { file.stopDownload(candidates[i]); file.markCandidateIgnored(candidates[i], "CandidateStatusReason_ByUser"); } refreshActionState(); } catch (Throwable th) { NLogger.error(RemoveCandidateAction.class, th, th); } } }; Environment.getInstance().executeOnThreadPool(runner, "RemoveDownloadCandidate"); } /** * {@inheritDoc} */ @Override public void refreshActionState() { int downloadRow = downloadTable.getSelectedRow(); int candidateRow = candidateTable.getSelectedRow(); if (downloadRow < 0 || candidateRow < 0) { setEnabled(false); } else { setEnabled(true); } } } /** * Schedules the candidate to retry a connection for download. */ class RetryCandidateAction extends FWAction { RetryCandidateAction() { super(Localizer.getString("RetryCandidate"), GUIRegistry.getInstance().getPlafIconPack().getIcon("Download.ReconnectHost"), Localizer.getString("TTTRetryCandidate")); refreshActionState(); } public void actionPerformed(ActionEvent e) { SWDownloadCandidate[] candidates = getSelectedDownloadCandidates(); for (int i = 0; i < candidates.length; i++) { if (candidates[i] != null) { candidates[i].manualConnectionRetry(); } } } /** * {@inheritDoc} */ @Override public void refreshActionState() { int downloadRow = downloadTable.getSelectedRow(); int candidateRow = candidateTable.getSelectedRow(); if (downloadRow < 0 || candidateRow < 0) { setEnabled(false); } else { setEnabled(true); } } } private class ChatToHostAction extends FWAction { public ChatToHostAction() { super(Localizer.getString("ChatToHost"), GUIRegistry.getInstance().getPlafIconPack().getIcon("Download.Chat"), Localizer.getString("TTTChatToHost")); refreshActionState(); } public void actionPerformed(ActionEvent e) { SWDownloadCandidate candidate = getSelectedDownloadCandidate(); if (candidate == null) { return; } if (!candidate.isChatSupported()) { return; } GUIActionPerformer.chatToHost(candidate.getHostAddress()); } /** * {@inheritDoc} */ @Override public void refreshActionState() { if (candidateTable.getSelectedRowCount() == 1) { SWDownloadCandidate candidate = getSelectedDownloadCandidate(); if (candidate != null && candidate.isChatSupported()) { setEnabled(true); return; } } setEnabled(false); } } private class BrowseHostAction extends FWAction { public BrowseHostAction() { super(Localizer.getString("BrowseHost"), GUIRegistry.getInstance().getPlafIconPack().getIcon("Download.BrowseHost"), Localizer.getString("TTTBrowseHost")); refreshActionState(); } public void actionPerformed(ActionEvent e) { SWDownloadCandidate candidate = getSelectedDownloadCandidate(); if (candidate == null) { return; } GUIActionPerformer.browseHost(candidate.getHostAddress()); } /** * {@inheritDoc} */ @Override public void refreshActionState() { if (candidateTable.getSelectedRowCount() == 1) { SWDownloadCandidate candidate = getSelectedDownloadCandidate(); if (candidate != null) { setEnabled(true); return; } } setEnabled(false); } } private final class BanHostActionProvider implements BanHostActionUtils.BanHostActionProvider { public DestAddress[] getBanHostAddresses() { SWDownloadCandidate[] candidates = getSelectedDownloadCandidates(); SWDownloadFile file = candidateModel.getDownloadFile(); final DestAddress[] addresses = new DestAddress[candidates.length]; for (int i = 0; i < candidates.length; i++) { file.stopDownload(candidates[i]); file.markCandidateIgnored(candidates[i], "CandidateStatusReason_ByUser"); addresses[i] = candidates[i].getHostAddress(); } return addresses; } public boolean isBanHostActionEnabled(boolean allowMultipleAddresses) { int downloadRow = downloadTable.getSelectedRow(); int candidateRow = candidateTable.getSelectedRow(); if (downloadRow < 0 || candidateRow < 0 || (!allowMultipleAddresses && candidateTable.getSelectedRowCount() > 1)) { return false; } else { return true; } } } private class AddToFavoritesAction extends FWAction { public AddToFavoritesAction() { super(Localizer.getString("AddToFavorites"), GUIRegistry.getInstance().getPlafIconPack().getIcon("Download.FavoriteHost"), Localizer.getString("TTTAddToFavorites")); refreshActionState(); } public void actionPerformed(ActionEvent e) { SWDownloadCandidate[] candidates = getSelectedDownloadCandidates(); DestAddress[] addresses = new DestAddress[candidates.length]; for (int i = 0; i < candidates.length; i++) { addresses[i] = candidates[i].getHostAddress(); } GUIActionPerformer.addHostsToFavorites(addresses); } /** * {@inheritDoc} */ @Override public void refreshActionState() { int downloadRow = downloadTable.getSelectedRow(); int candidateRow = candidateTable.getSelectedRow(); if (downloadRow < 0 || candidateRow < 0) { setEnabled(false); } else { setEnabled(true); } } } /** * Manually search for new candidates. */ private class SearchCandidatesAction extends FWAction { public SearchCandidatesAction() { super(Localizer.getString("Search"), GUIRegistry.getInstance().getPlafIconPack().getIcon("Download.Search"), Localizer.getString("TTTSearchCandidates")); refreshActionState(); } public void actionPerformed(ActionEvent e) { try { int viewIdx = downloadTable.getSelectedRow(); int modelIdx = downloadTable.translateRowIndexToModel(viewIdx); SWDownloadFile file = downloadService.getDownloadFile(modelIdx); file.startSearchForCandidates(); } catch (Throwable th) { NLogger.error(SearchCandidatesAction.class, th, th); } } /** * {@inheritDoc} */ @Override public void refreshActionState() { if (downloadTable.getSelectedRowCount() != 1) { setEnabled(false); return; } int viewIdx = downloadTable.getSelectedRow(); int modelIdx = downloadTable.translateRowIndexToModel(viewIdx); SWDownloadFile file = downloadService.getDownloadFile(modelIdx); if (file == null) { setEnabled(false); } else { if (file.getResearchSetting().isSearchRunning() || file.isFileCompletedOrMoved()) { setEnabled(false); } else { setEnabled(true); } } } } private class CandidateLogAction extends FWAction { public CandidateLogAction() { super(Localizer.getString("DownloadTab_ViewLog"), null, Localizer.getString("DownloadTab_TTTViewLog")); refreshActionState(); } public void actionPerformed(ActionEvent e) { try { SWDownloadCandidate candidate = getSelectedDownloadCandidate(); LogBuffer buffer = downloadService.getCandidateLogBuffer(); Collection<LogRecord> logRecords = buffer.getLogRecords(candidate); if (logRecords != null) { LogBufferDialog dialog = new LogBufferDialog(logRecords); dialog.setVisible(true); } } catch (Throwable th) { NLogger.error(CandidateLogAction.class, th, th); } } /** * {@inheritDoc} */ @Override public void refreshActionState() { if (candidateTable.getSelectedRowCount() == 1) { SWDownloadCandidate candidate = getSelectedDownloadCandidate(); if (candidate != null) { setEnabled(true); return; } } setEnabled(false); } } }