package org.phenoscape.view;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import javax.swing.AbstractAction;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JToolBar;
import org.apache.log4j.Logger;
import org.bbop.framework.AbstractGUIComponent;
import org.obo.annotation.base.OntologySource;
import org.obo.annotation.base.UserOntologyConfiguration;
import org.obo.app.swing.BugWorkaroundTable;
import org.obo.app.swing.PlaceholderRenderer;
import org.obo.app.swing.TableColumnPrefsSaver;
import ca.odell.glazedlists.BasicEventList;
import ca.odell.glazedlists.EventList;
import ca.odell.glazedlists.gui.AdvancedTableFormat;
import ca.odell.glazedlists.gui.WritableTableFormat;
import ca.odell.glazedlists.swing.EventSelectionModel;
import ca.odell.glazedlists.swing.EventTableModel;
import com.eekboom.utils.Strings;
public class OntologyPreferencesComponent extends AbstractGUIComponent {
private JButton addURLButton;
private JButton deleteURLButton;
private JButton applyButton;
private JButton revertChangesButton;
private JButton revertToDefaultsButton;
private final EventList<OntologySource> sources = new BasicEventList<OntologySource>();
private final EventSelectionModel<OntologySource> sourcesSelectionModel = new EventSelectionModel<OntologySource>(sources);
private final List<OntologySource> oldSources = new ArrayList<OntologySource>();
private final UserOntologyConfiguration config;
//TODO enable/disable apply & revert buttons
public OntologyPreferencesComponent(String id, UserOntologyConfiguration configuration) {
super(id);
this.config = configuration;
}
@Override
public void init() {
super.init();
final List<OntologySource> storedSources = this.config.getStoredSources();
if (storedSources != null) {
this.sources.addAll(storedSources);
}
this.cloneContents(this.sources, this.oldSources);
this.initializeInterface();
}
private void addSource() {
this.sources.add(new OntologySource());
}
private void deleteSelectedSource() {
final OntologySource source = this.getSelectedSource();
if (source != null) { this.sources.remove(source); }
}
private void applyChanges() {
this.config.storeSources(this.sources);
this.cloneContents(this.sources, this.oldSources);
//TODO tell user they will need to relaunch to see changes
}
private void revertChanges() {
this.cloneContents(this.oldSources, this.sources);
}
private void revertToDefaults() {
this.config.clearStoredSources();
this.sources.clear();
//TODO tell user they will need to relaunch to see changes
}
private OntologySource getSelectedSource() {
final EventList<OntologySource> selected = this.sourcesSelectionModel.getSelected();
if (selected.size() == 1) {
return selected.get(0);
} else {
return null;
}
}
private void cloneContents(List<OntologySource> original, List<OntologySource> destination) {
destination.clear();
for (OntologySource item : original) {
destination.add(item.copy());
}
}
private void initializeInterface() {
this.setLayout(new BorderLayout());
final EventTableModel<OntologySource> sourcesTableModel = new EventTableModel<OntologySource>(this.sources, new OntologySourcesTableFormat());
final JTable sourcesTable = new BugWorkaroundTable(sourcesTableModel);
sourcesTable.setSelectionModel(this.sourcesSelectionModel);
sourcesTable.setDefaultRenderer(Object.class, new PlaceholderRenderer("None"));
sourcesTable.putClientProperty("Quaqua.Table.style", "striped");
new TableColumnPrefsSaver(sourcesTable, this.getClass().getName());
//final TableComparatorChooser<Character> sortChooser = new TableComparatorChooser<Character>(charactersTable, this.getController().getSortedCharacters(), false);
//sortChooser.addSortActionListener(new SortDisabler());
this.add(new JScrollPane(sourcesTable), BorderLayout.CENTER);
this.add(this.createToolBar(), BorderLayout.NORTH);
this.add(this.createSavePanel(), BorderLayout.SOUTH);
}
private JToolBar createToolBar() {
final JToolBar toolBar = new JToolBar();
this.addURLButton = new JButton(new AbstractAction(null, new ImageIcon(this.getClass().getResource("/org/phenoscape/view/images/list-add.png"))) {
@Override
public void actionPerformed(ActionEvent e) {
addSource();
}
});
this.addURLButton.setToolTipText("Add Source URL");
toolBar.add(this.addURLButton);
this.deleteURLButton = new JButton(new AbstractAction(null, new ImageIcon(this.getClass().getResource("/org/phenoscape/view/images/list-remove.png"))) {
@Override
public void actionPerformed(ActionEvent e) {
deleteSelectedSource();
}
});
this.deleteURLButton.setToolTipText("Delete Source URL");
toolBar.add(this.deleteURLButton);
toolBar.setFloatable(false);
return toolBar;
}
private JPanel createSavePanel() {
final JPanel panel = new JPanel(new BorderLayout());
this.revertToDefaultsButton = new JButton(new AbstractAction("Revert to defaults") {
@Override
public void actionPerformed(ActionEvent e) {
revertToDefaults();
}
});
this.revertToDefaultsButton.setToolTipText("Clear custom ontology sources and revert to Phenex defaults.");
panel.add(this.revertToDefaultsButton, BorderLayout.WEST);
this.revertChangesButton = new JButton(new AbstractAction("Revert") {
@Override
public void actionPerformed(ActionEvent e) {
revertChanges();
}
});
this.revertChangesButton.setToolTipText("Revert Changes");
panel.add(this.revertChangesButton, BorderLayout.CENTER);
this.applyButton = new JButton(new AbstractAction("Apply") {
@Override
public void actionPerformed(ActionEvent e) {
applyChanges();
}
});
this.applyButton.setToolTipText("Apply Changes");
panel.add(this.applyButton, BorderLayout.EAST);
return panel;
}
private class OntologySourcesTableFormat implements WritableTableFormat<OntologySource>, AdvancedTableFormat<OntologySource> {
@Override
public boolean isEditable(OntologySource source, int column) {
return true;
}
@Override
public OntologySource setColumnValue(OntologySource source, Object editedValue, int column) {
switch(column) {
case 0: source.setLabel(editedValue.toString()); break;
case 1:
try {
source.setURL(new URL(editedValue.toString()));
} catch (MalformedURLException e) {
log().error("User entered bad URL");
} break;
}
return source;
}
@Override
public int getColumnCount() {
return 2;
}
@Override
public String getColumnName(int column) {
switch(column) {
case 0: return "Label";
case 1: return "URL";
}
return null;
}
@Override
public Object getColumnValue(OntologySource source, int column) {
switch(column) {
case 0: return source.getLabel();
case 1: return source.getURL();
}
return null;
}
@Override
public Class<?> getColumnClass(int column) {
switch(column) {
case 0: return String.class;
case 1: return URL.class;
}
return null;
}
@Override
public Comparator<?> getColumnComparator(int column) {
switch(column) {
case 0: return Strings.getNaturalComparator();
case 1: return new Comparator<URL>() {
@Override
public int compare(URL o1, URL o2) {
return Strings.compareNatural(o1.toString(), o2.toString());
}
};
}
return null;
}
}
private Logger log() {
return Logger.getLogger(this.getClass());
}
}