package com.limegroup.gnutella.gui.download;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.io.File;
import java.text.MessageFormat;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.border.EmptyBorder;
import com.limegroup.gnutella.Downloader;
import com.limegroup.gnutella.FileDesc;
import com.limegroup.gnutella.SaveLocationException;
import com.limegroup.gnutella.util.CommonUtils;
import com.limegroup.gnutella.gui.ButtonRow;
import com.limegroup.gnutella.gui.GUIMediator;
import com.limegroup.gnutella.gui.GUIUtils;
import com.limegroup.gnutella.gui.MessageService;
import com.limegroup.gnutella.gui.util.CoreExceptionHandler;
/**
* Handles {@link com.limegroup.gnutella.SaveLocationException SaveLocationExceptions}
* showing the user the exact cause of the exception and giving them a choice
* to choose a different download location or overwrite the existing file.
* <p>
* The dialog stays visible as long as
* {@link com.limegroup.gnutella.gui.download.DownloaderFactory#createDownloader(boolean)}
* throws exceptions and it has not been cancelled.
*/
public class DownloaderDialog extends JDialog {
private DownloaderFactory factory;
private Downloader downloader;
private JLabel titleLabel = new JLabel();
private JLabel descLabel = new JLabel();
private JLabel noteLabel = new JLabel();
private ButtonRow buttons;
/**
* Creates a new dialog for a factory and an already thrown exception.
* @param factory
* @param sle
*/
private DownloaderDialog(DownloaderFactory factory, SaveLocationException sle) {
this.factory = factory;
// dialog
setModal(true);
setResizable(false);
getContentPane().setLayout(new BorderLayout());
GUIUtils.addHideAction((JComponent)getContentPane());
// top panel
JPanel topPanel = new JPanel(new BorderLayout());
topPanel.setBorder(new EmptyBorder(5, 5, 5, 5));
getContentPane().add(topPanel, BorderLayout.CENTER);
// main panel
JPanel mainPanel = new JPanel(new BorderLayout());
topPanel.add(mainPanel, BorderLayout.CENTER);
Color bg = UIManager.getColor("TextField.background");
Color fg = UIManager.getColor("TextField.foreground");
JPanel titlePanel = new JPanel(new BorderLayout());
titlePanel.setBackground(bg);
titlePanel.setBorder(BorderFactory.createEtchedBorder());
JLabel icon = new JLabel(GUIMediator.getThemeImage("warning"));
icon.setBackground(bg);
icon.setBorder(new EmptyBorder(2, 5, 2, 5));
titlePanel.add(icon, BorderLayout.WEST);
titleLabel.setBackground(bg);
titleLabel.setForeground(fg);
titleLabel.setFont(new Font("Dialog", Font.BOLD, 18));
titlePanel.add(titleLabel, BorderLayout.CENTER);
mainPanel.add(titlePanel, BorderLayout.NORTH);
// labels
Box labelBox = Box.createVerticalBox();
mainPanel.add(labelBox, BorderLayout.CENTER);
labelBox.add(descLabel);
labelBox.add(Box.createVerticalStrut(10));
labelBox.add(noteLabel);
labelBox.add(Box.createVerticalStrut(15));
labelBox.add(Box.createVerticalGlue());
mainPanel.add(labelBox, BorderLayout.CENTER);
buttons = new ButtonRow(new Action[] { new OverWriteAction(),
new SaveAsAction(), new CancelAction() },
ButtonRow.X_AXIS, ButtonRow.LEFT_GLUE);
topPanel.add(buttons, BorderLayout.SOUTH);
setContentFromException(sle);
pack();
}
private void setLabel(JLabel label, String text) {
StringBuffer buffer = new StringBuffer("<html><table><tr><td width=\"400\">");
buffer.append(text);
buffer.append("</td></tr></html>");
label.setText(buffer.toString());
}
private void setContentFromException(SaveLocationException sle) {
// special case, close this dialog if visible and show warning dialog
if (sle.getErrorCode() == SaveLocationException.FILE_ALREADY_DOWNLOADING) {
dispose();
DownloaderUtils.showIsAlreadyDownloadingWarning(factory);
return;
}
String error = CoreExceptionHandler.getSaveLocationErrorString(sle);
if (sle.getErrorCode() == SaveLocationException.FILE_ALREADY_EXISTS) {
setTitleLabel(MessageFormat.format(GUIMediator.getStringResource
("DOWNLOADER_DIALOG_WARNING_LABEL"),
new Object[] { CoreExceptionHandler.getShortSaveLocationErrorString(sle) }));
setDescLabel(error);
}
else {
setTitleLabel(MessageFormat.format(GUIMediator.getStringResource
("DOWNLOADER_DIALOG_ERROR_LABEL"),
new Object[] { CoreExceptionHandler.getShortSaveLocationErrorString(sle) }));
setDescLabel(error);
}
FileDesc desc = DownloaderUtils.getFromLibrary(factory.getURN());
if (desc != null) {
setNoteLabel(MessageFormat.format(GUIMediator.getStringResource
("DOWNLOADER_DIALOG_NOTE_LABEL"),
new Object[] { desc.getFile() }));
}
buttons.getButtonAtIndex(0).setVisible
(sle.getErrorCode() == SaveLocationException.FILE_ALREADY_EXISTS);
}
private void setTitleLabel(String text) {
setTitle(text);
titleLabel.setText(text);
}
private void setDescLabel(String text) {
setLabel(descLabel, text);
}
private void setNoteLabel(String text) {
setLabel(noteLabel, text);
}
public static Downloader handle(DownloaderFactory factory,
SaveLocationException sle) {
if (sle.getErrorCode() == SaveLocationException.FILE_ALREADY_DOWNLOADING) {
DownloaderUtils.showIsAlreadyDownloadingWarning(factory);
return null;
}
DownloaderDialog dlg = new DownloaderDialog(factory, sle);
dlg.setLocationRelativeTo(MessageService.getParentComponent());
dlg.setVisible(true);
return dlg.getDownloader();
}
/**
* Returns the successfully created downloader or <code>null</code> if
* the dialog was cancelled.
* @return
*/
public Downloader getDownloader() {
return downloader;
}
private class OverWriteAction extends AbstractAction {
public OverWriteAction() {
putValue(Action.NAME, GUIMediator.getStringResource
("DOWNLOADER_DIALOG_OVERWRITE_ACTION_SHORT_NAME"));
putValue(Action.SHORT_DESCRIPTION, GUIMediator.getStringResource
("DOWNLOADER_DIALOG_OVERWRITE_ACTION_SHORT_DESCRIPTION"));
}
public void actionPerformed(ActionEvent e) {
try {
downloader = factory.createDownloader(true);
dispose();
}
catch (SaveLocationException sle) {
setContentFromException(sle);
}
}
}
private class SaveAsAction extends AbstractAction {
public SaveAsAction() {
putValue(Action.NAME, GUIMediator.getStringResource
("DOWNLOADER_DIALOG_SAVE_AS_ACTION_NAME"));
putValue(Action.SHORT_DESCRIPTION, GUIMediator.getStringResource
("DOWNLOADER_DIALOG_SAVE_AS_ACTION_SHORT_DESCRIPTION"));
}
public void actionPerformed(ActionEvent e) {
File file = DownloaderUtils.showFileChooser(factory,
DownloaderDialog.this);
if (file != null) {
try {
factory.setSaveFile(file);
// OSX's FileDialog box already prompts the user that they're
// going to be overwriting a file, so we don't need to do that
// particular check again.
downloader = factory.createDownloader(CommonUtils.isAnyMac());
dispose();
}
catch (SaveLocationException sle) {
setContentFromException(sle);
}
}
}
}
private class CancelAction extends AbstractAction {
public CancelAction() {
putValue(Action.NAME, GUIMediator.getStringResource
("GENERAL_CANCEL_BUTTON_LABEL"));
putValue(Action.SHORT_DESCRIPTION, GUIMediator.getStringResource
("DOWNLOADER_DIALOG_CANCEL_ACTION_SHORT_DESCRIPTION"));
}
public void actionPerformed(ActionEvent e) {
dispose();
}
}
}