package org.limewire.ui.swing.options;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.swing.Action;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import net.miginfocom.swing.MigLayout;
import org.jdesktop.swingx.JXTable;
import org.limewire.core.api.Category;
import org.limewire.core.api.file.CategoryManager;
import org.limewire.core.api.spam.SpamManager;
import org.limewire.core.settings.FilterSettings;
import org.limewire.core.settings.LibrarySettings;
import org.limewire.setting.Setting;
import org.limewire.ui.swing.action.AbstractAction;
import org.limewire.ui.swing.components.MultiLineLabel;
import org.limewire.ui.swing.components.TextFieldClipboardControl;
import org.limewire.ui.swing.options.actions.OKDialogAction;
import org.limewire.ui.swing.table.MouseableTable;
import org.limewire.ui.swing.util.BackgroundExecutorService;
import org.limewire.ui.swing.util.I18n;
import org.limewire.ui.swing.util.IconManager;
import org.limewire.util.OSUtils;
import ca.odell.glazedlists.BasicEventList;
import ca.odell.glazedlists.CompositeList;
import ca.odell.glazedlists.EventList;
import ca.odell.glazedlists.gui.TableFormat;
import ca.odell.glazedlists.swing.DefaultEventTableModel;
import com.google.inject.Inject;
/**
* Creates a table to manage which file extensions will not show up in search results.
*/
public class FilterFileExtensionsOptionPanel extends AbstractFilterOptionPanel {
private final SpamManager spamManager;
private final CategoryManager categoryManager;
private final UnsafeTypeOptionPanelStateManager settingStateManager;
private JButton defaultButton;
private JButton okButton;
private JTextField keywordTextField;
private JButton addKeywordButton;
private JXTable filterTable;
private final EventList<String> immutableProgramsList;
@Inject
public FilterFileExtensionsOptionPanel(IconManager iconManager, SpamManager spamManager,
CategoryManager categoryManager,
UnsafeTypeOptionPanelStateManager settingStateManager) {
this.spamManager = spamManager;
this.categoryManager = categoryManager;
this.settingStateManager = settingStateManager;
setLayout(new MigLayout("gapy 10, nogrid"));
keywordTextField = new JTextField(30);
addKeywordButton = new JButton(I18n.tr("Add Extension"));
TextFieldClipboardControl.install(keywordTextField);
CompositeList<String> allExtensions = new CompositeList<String>(eventList.getPublisher(),
eventList.getReadWriteLock());
allExtensions.addMemberList(eventList);
immutableProgramsList = new BasicEventList<String>(eventList.getPublisher(),
eventList.getReadWriteLock());
allExtensions.addMemberList(immutableProgramsList);
filterTable = new MouseableTable(new DefaultEventTableModel<String>(
allExtensions, new FileFilterTableFormat(categoryManager, iconManager)));
filterTable.setShowGrid(false, false);
filterTable.setColumnSelectionAllowed(false);
filterTable.setSelectionMode(0);
TableColumn iconColumn = filterTable.getColumn(0);
iconColumn.setCellRenderer(new IconRenderer());
iconColumn.setWidth(16);
iconColumn.setMaxWidth(16);
iconColumn.setMinWidth(16);
TableColumn removeColumn = filterTable.getColumn(FileFilterTableFormat.columnNames.length-1);
removeColumn.setCellRenderer(new RemoveButtonRenderer(filterTable));
removeColumn.setCellEditor(new RemoveButtonRenderer(filterTable));
okButton = new JButton(new OKDialogAction());
addKeywordButton.addActionListener(new ActionListener(){
@Override
public void actionPerformed(ActionEvent e) {
String text = keywordTextField.getText();
if(text == null || text.trim().length() == 0) {
return;
}
text = text.trim();
if(text.charAt(0) != '.') {
text = "." + text;
}
if(!eventList.contains(text) && !immutableProgramsList.contains(text)) {
eventList.add(text);
}
keywordTextField.setText("");
}
});
defaultButton = new JButton(new DefaultAction());
add(new MultiLineLabel(I18n.tr("LimeWire will not show files with the following extensions in your search results"), 300), "span, wrap");
add(keywordTextField, "gapright 10");
add(addKeywordButton,"wrap");
add(new JScrollPane(filterTable), "span 2, grow, wrap");
add(defaultButton, "alignx left");
add(okButton, "tag ok, alignx right");
}
@Override
ApplyOptionResult applyOptions() {
String[] values = eventList.toArray(new String[eventList.size()]);
FilterSettings.BANNED_EXTENSIONS.set(values);
BackgroundExecutorService.execute(new Runnable() {
@Override
public void run() {
spamManager.adjustSpamFilters();
}
});
return new ApplyOptionResult(false,true);
}
@Override
boolean hasChanged() {
List model = Arrays.asList(FilterSettings.BANNED_EXTENSIONS.get());
String[] values = eventList.toArray(new String[eventList.size()]);
return model.equals(new ArrayList<String>(Arrays.asList(values)));
}
private void updateItems() {
eventList.clear();
immutableProgramsList.clear();
// Adds or removes the banned programs to list with non deletable elements to be appended at the end
// based on the allow programs setting.
if (settingStateManager.getValue(LibrarySettings.ALLOW_PROGRAMS) == Boolean.FALSE) {
for ( String extension : categoryManager.getExtensionsForCategory(Category.PROGRAM) ) {
immutableProgramsList.add("." + extension);
}
}
// Add all the banned extensions that are not already accounted for by
// banned programs
for ( String extension : FilterSettings.BANNED_EXTENSIONS.get() ) {
if (!immutableProgramsList.contains(extension)) {
eventList.add(extension);
}
}
}
@Override
public void initOptions() {
updateItems();
settingStateManager.addSettingChangedListener(new OptionPanelStateManager.SettingChangedListener() {
@Override
public void settingChanged(Setting setting) {
if (setting == LibrarySettings.ALLOW_PROGRAMS) {
updateItems();
}
}
});
}
/**
* Reverts the extensions not shown in search results to the default setting.
*/
private class DefaultAction extends AbstractAction {
public DefaultAction() {
putValue(Action.NAME, I18n.tr("Use Default"));
putValue(Action.SHORT_DESCRIPTION, I18n.tr("Revert to default settings"));
}
@Override
public void actionPerformed(ActionEvent e) {
FilterSettings.BANNED_EXTENSIONS.revertToDefault();
updateItems();
}
}
private static class FileFilterTableFormat implements TableFormat<String> {
private final CategoryManager categoryManager;
private final IconManager iconManager;
final int ICON_COLUMN = 0;
final int CATEGORY_COLUMN = 2;
final int TYPE_COLUMN = 3;
static final String[] columnNames = OSUtils.isWindows() ?
new String[] {"", I18n.tr("Extension"), I18n.tr("Category"), I18n.tr("Type"), ""}
: new String[] {"", I18n.tr("Extension"), I18n.tr("Category"), ""};
public FileFilterTableFormat(CategoryManager cagetoryManager, IconManager iconManager) {
this.categoryManager = cagetoryManager;
this.iconManager = iconManager;
}
@Override
public Object getColumnValue(String baseObject, int column) {
switch (column) {
case ICON_COLUMN :
return iconManager.getIconForExtension(baseObject.substring(1));
case CATEGORY_COLUMN :
return categoryManager.getCategoryForExtension(baseObject.substring(1));
case TYPE_COLUMN :
if (OSUtils.isWindows()) {
return iconManager.getIconForExtension(baseObject.substring(1)).toString();
} // ELSE PASS-THROUGH
default:
return baseObject;
}
}
@Override
public int getColumnCount() {
return columnNames.length;
}
@Override
public String getColumnName(int column) {
return columnNames[column];
}
}
private static class IconRenderer implements TableCellRenderer {
private final JLabel component = new JLabel();
@Override
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
if (value == null) {
return null;
}
component.setIcon((Icon) value);
return component;
}
}
}