package com.limegroup.gnutella.gui.options.panes;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.io.File;
import java.io.IOException;
import java.util.Iterator;
import java.util.Set;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.JTextField;
import javax.swing.ListSelectionModel;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import com.limegroup.gnutella.MediaType;
import com.limegroup.gnutella.gui.FileChooserHandler;
import com.limegroup.gnutella.gui.GUIMediator;
import com.limegroup.gnutella.gui.PaddedPanel;
import com.limegroup.gnutella.gui.SaveDirectoryHandler;
import com.limegroup.gnutella.gui.options.OptionsMediator;
import com.limegroup.gnutella.gui.search.NamedMediaType;
import com.limegroup.gnutella.gui.tables.AbstractTableMediator;
import com.limegroup.gnutella.gui.tables.BasicDataLineModel;
import com.limegroup.gnutella.gui.tables.DataLine;
import com.limegroup.gnutella.gui.tables.LimeJTable;
import com.limegroup.gnutella.gui.tables.TableSettings;
/**
* Class which handles the construction of the download directories per
* mediatype table and its associated actions.
*/
class MediaTypeDownloadDirMediator extends AbstractTableMediator {
/**
* The PaneItem on which the media type is displayed.
*/
private final JTextField saveField;
/**
* Handle to the browse action which can be retrieved through
* {@link #getBrowseDirectoryAction()}.
*/
private BrowseDirectoryAction browseAction;
/**
* Handle to the reset action which can be retrieve through the
* {@link #getResetDirectoryAction()}.
*/
private ResetDirectoryAction resetAction;
/**
* Workaround to allow reinstantiation without getting duplicate settings keys.
*/
private static TableSettings cachedSettings = null;
/**
* @param item
* @param id
*/
public MediaTypeDownloadDirMediator(JTextField field) {
super("MEDIA_TYPE_DOWNLOAD_DIR_TABLE");
saveField = field;
saveField.getDocument().addDocumentListener(new DocumentHandler());
}
/**
* Returns true if the settings in the table have changed and they need to
* be saved.
*/
public boolean isDirty() {
for( int i = 0; i < DATA_MODEL.getRowCount(); i++) {
if(((MediaTypeDownloadDirDataLine)DATA_MODEL.get(i)).isDirty())
return true;
}
return false;
}
/**
* Overriden to allow reinstantiation of this class.
*/
protected void buildSettings() {
if (cachedSettings == null) {
super.buildSettings();
cachedSettings = SETTINGS;
}
SETTINGS = cachedSettings;
}
protected void setupConstants() {
MAIN_PANEL = new PaddedPanel(0);
DATA_MODEL = new MediaTypeDownloadDirModel(MediaTypeDownloadDirDataLine.class);
TABLE = new LimeJTable(DATA_MODEL);
TABLE.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
// construct actions here to avoid null pointer exceptions in
// handleNoSelection()
browseAction = new BrowseDirectoryAction();
resetAction = new ResetDirectoryAction();
}
/**
* Save options for each mediatype in the table.
*/
public boolean applyOptions(Set newDirs) throws IOException {
for (int i = 0; i < DATA_MODEL.getRowCount(); i++) {
MediaTypeDownloadDirDataLine dl = (MediaTypeDownloadDirDataLine)DATA_MODEL.get(i);
dl.saveDirectory(newDirs);
}
return false;
}
/**
* Adds save dirs to the given option.
*/
void addSaveDirs(Set set) {
for (int i = 0; i < DATA_MODEL.getRowCount(); i++) {
String dir = ((MediaTypeDownloadDirDataLine)DATA_MODEL.get(i)).getDirectory();
if(dir != null)
set.add(new File(dir));
}
}
/**
* Fill the table with the mediatypes and the directory settings.
*/
public void initOptions() {
DATA_MODEL.clear();
for (Iterator i = NamedMediaType.getAllNamedMediaTypes().iterator(); i.hasNext();) {
NamedMediaType nm = (NamedMediaType) i.next();
if (!nm.getMediaType().getMimeType().equals(MediaType.SCHEMA_ANY_TYPE))
DATA_MODEL.add(nm);
}
// sort alphabetically, so sort twice
DATA_MODEL.sort(0);
DATA_MODEL.sort(0);
updateModel();
}
public Action getBrowseDirectoryAction() {
return browseAction;
}
public Action getResetDirectoryAction() {
return resetAction;
}
/**
* Overriden to disable removal of rows.
*/
public void removeSelection() { }
/*
* @see com.limegroup.gnutella.gui.tables.AbstractTableMediator#updateSplashScreen()
*/
protected void updateSplashScreen() { }
/*
* @see com.limegroup.gnutella.gui.tables.AbstractTableMediator#createPopupMenu()
*/
protected JPopupMenu createPopupMenu() {
JPopupMenu menu = new JPopupMenu();
menu.add(new JMenuItem(browseAction));
menu.add(new JMenuItem(resetAction));
return menu;
}
/**
* Overridden to not popup a menu on the table header.
*/
public void handleHeaderPopupMenu(Point p) { }
/*
* @see com.limegroup.gnutella.gui.tables.ComponentMediator#handleActionKey()
*/
public void handleActionKey() { }
/**
* Enable the browse and reset action.
*/
public void handleSelection(int row) {
browseAction.setEnabled(true);
resetAction.setEnabled(true);
}
/**
* Disable the browse and reset action.
*/
public void handleNoSelection() {
browseAction.setEnabled(false);
resetAction.setEnabled(false);
}
/**
* The table model.
*/
class MediaTypeDownloadDirModel extends BasicDataLineModel {
/**
* @param dataLineClass
*/
public MediaTypeDownloadDirModel(Class dataLineClass) {
super(dataLineClass);
}
public DataLine createDataLine() {
return new MediaTypeDownloadDirDataLine();
}
public boolean isCellEditable(int row, int col) {
return col == 1;
}
public void setValueAt(Object value, int row, int col) {
setDirectory(get(row), new File((String) value));
}
}
/**
* Setting of a download directory for a mediatype should be done with this
* method. It makes sure the directory is a valid download directory.
*
* @param line
* @param dir
*/
private void setDirectory(DataLine line, File dir) {
// Otherwise, make sure they selected a valid directory that
// they can really write to.
if (!SaveDirectoryHandler.isSaveDirectoryValid(dir)) {
GUIMediator.showError("ERROR_INVALID_SAVE_DIRECTORY_SELECTION");
return;
}
try {
String newDir = dir.getCanonicalPath();
MediaTypeDownloadDirDataLine dl = (MediaTypeDownloadDirDataLine) line;
dl.setDirectory(newDir);
} catch (IOException ioe) {
}
}
/**
* Opens a directory chooser dialog and sets the selected directory for the
* selected mediatype row.
*/
private class BrowseDirectoryAction extends AbstractAction {
public BrowseDirectoryAction() {
putValue(Action.NAME, GUIMediator
.getStringResource("GENERAL_BROWSE_BUTTON_LABEL"));
putValue(Action.SHORT_DESCRIPTION, GUIMediator
.getStringResource("OPTIONS_SAVE_MEDIATYPE_BROWSE_TIP"));
}
/*
* @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
*/
public void actionPerformed(ActionEvent e) {
DataLine line = TABLE.getSelectedDataLine();
if (line == null) {
throw new IllegalArgumentException(
"browse action was not correctly disabled");
}
File dir = FileChooserHandler
.getInputDirectory(OptionsMediator.instance().getMainOptionsComponent());
if (dir != null) {
setDirectory(line, dir);
}
}
}
/**
* Resets the selected mediatype row so that its download directory is
* always the default download directory.
*/
private class ResetDirectoryAction extends AbstractAction {
public ResetDirectoryAction() {
putValue(Action.NAME, GUIMediator
.getStringResource("OPTIONS_SAVE_RESET_BUTTON_LABEL"));
putValue(Action.SHORT_DESCRIPTION, GUIMediator
.getStringResource("OPTIONS_SAVE_RESET_BUTTON_TIP"));
}
public void actionPerformed(ActionEvent e) {
DataLine line = TABLE.getSelectedDataLine();
if (line == null) {
throw new IllegalArgumentException(
"reset action was not correctly disabled");
}
MediaTypeDownloadDirDataLine mediaLine = (MediaTypeDownloadDirDataLine) line;
mediaLine.reset();
MediaTypeDownloadDirMediator.this.DATA_MODEL.fireTableDataChanged();
}
}
/**
* Listens for document changes of the {@link SaveDirPaneItem#_saveField}
* and updates the table model accordingly.
*/
private class DocumentHandler implements DocumentListener {
public void insertUpdate(DocumentEvent e) {
MediaTypeDownloadDirMediator.this.updateModel();
}
public void removeUpdate(DocumentEvent e) {
MediaTypeDownloadDirMediator.this.updateModel();
}
public void changedUpdate(DocumentEvent e) {
}
}
/**
* Notify all mediatype rows of a possible change of the default download
* directory.
*/
private void updateModel() {
String text = saveField.getText();
for (int i = 0; i < TABLE.getRowCount(); i++) {
MediaTypeDownloadDirDataLine line = (MediaTypeDownloadDirDataLine) DATA_MODEL
.get(i);
line.setDefaultDir(text);
}
DATA_MODEL.fireTableDataChanged();
}
}