package gui;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.FileReader;
import java.io.PrintWriter;
import java.util.HashSet;
import java.util.Set;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JMenuBar;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ScrollPaneConstants;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableColumn;
import jebl.evolution.graphs.Node;
import jebl.evolution.io.NexusImporter;
import jebl.evolution.trees.RootedTree;
import readers.LocationsReader;
import utils.Utils;
import app.SpreadApp;
public class LocationCoordinatesEditor {
private InteractiveTableModel returnValue = null;
private SpreadApp frame;
// Window
private JDialog window;
private Frame owner;
// Menubar
private JMenuBar menu;
// Buttons with options
private JButton load;
private JButton save;
private JButton done;
// Strings for paths
private String locationsFilename;
private File workingDirectory;
// Data, model & stuff for JTable
private JTable table;
private InteractiveTableModel tableModel;
private String[] COLUMN_NAMES = { "Location", "Latitude", "Longitude", "" };
public LocationCoordinatesEditor(SpreadApp frame) {
this.frame = frame;
// Setup Main Menu buttons
load = new JButton("Load", SpreadApp.loadIcon);
save = new JButton("Save", SpreadApp.saveIcon);
done = new JButton("Done", SpreadApp.doneIcon);
// Add Main Menu buttons listeners
load.addActionListener(new ListenOpenLocations());
save.addActionListener(new ListenSaveLocationCoordinates());
done.addActionListener(new ListenOk());
// Setup menu
menu = new JMenuBar();
menu.setLayout(new BorderLayout());
JPanel buttonsHolder = new JPanel();
buttonsHolder.setOpaque(false);
buttonsHolder.add(load);
buttonsHolder.add(save);
buttonsHolder.add(done);
menu.add(buttonsHolder, BorderLayout.WEST);
// Setup table
tableModel = new InteractiveTableModel(COLUMN_NAMES);
tableModel.addTableModelListener(new InteractiveTableModelListener());
table = new JTable(tableModel);
table.setModel(tableModel);
table.setSurrendersFocusOnKeystroke(true);
TableColumn hidden = table.getColumnModel().getColumn(
InteractiveTableModel.HIDDEN_INDEX);
hidden.setMinWidth(2);
hidden.setPreferredWidth(2);
hidden.setMaxWidth(2);
hidden.setCellRenderer(new InteractiveRenderer(
InteractiveTableModel.HIDDEN_INDEX));
JScrollPane scrollPane = new JScrollPane(table,
ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS,
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
RowNumberTable rowNumberTable = new RowNumberTable(table);
scrollPane.setRowHeaderView(rowNumberTable);
scrollPane.setCorner(JScrollPane.UPPER_LEFT_CORNER, rowNumberTable
.getTableHeader());
// Setup window
owner = Utils.getActiveFrame();
window = new JDialog(owner, "Setup location coordinates...");
window.getContentPane().add(menu, BorderLayout.NORTH);
window.getContentPane().add(scrollPane);
window.pack();
window.setLocationRelativeTo(owner);
}// END: LocationCoordinatesEditor()
private class ListenOpenLocations implements ActionListener {
public void actionPerformed(ActionEvent ev) {
try {
final JFileChooser chooser = new JFileChooser();
chooser.setDialogTitle("Loading location file...");
chooser.setMultiSelectionEnabled(false);
chooser.setCurrentDirectory(workingDirectory);
int returnVal = chooser.showOpenDialog(Utils.getActiveFrame());
if (returnVal == JFileChooser.APPROVE_OPTION) {
File file = chooser.getSelectedFile();
locationsFilename = file.getAbsolutePath();
frame.setStatus("Opened " + locationsFilename + "\n");
File tmpDir = chooser.getCurrentDirectory();
if (tmpDir != null) {
workingDirectory = tmpDir;
LocationsReader data = new LocationsReader(
locationsFilename);
if (tableModel.getRowCount() < data.nrow) {
for (int i = 0; i < data.nrow - 1; i++) {
tableModel.addEmptyRow();
}
}
for (int i = 0; i < data.nrow; i++) {
tableModel.setValueAt(data.locations[i], i, 0);
for (int j = 0; j < 2; j++) {
tableModel.setValueAt(
String.valueOf(data.coordinates[i][j]),
i, j + 1);
}// END: col loop
}// END: row loop
}// END: null check
} else {
frame.setStatus("Could not Open! \n");
}
} catch (Exception e) {
Utils.handleException(e, e.getMessage());
}// END: try-catch block
}// END: actionPerformed
}// END: ListenOpenLocations
private class ListenSaveLocationCoordinates implements ActionListener {
public void actionPerformed(ActionEvent ev) {
try {
JFileChooser chooser = new JFileChooser();
chooser.setDialogTitle("Saving as tab delimited file...");
int returnVal = chooser.showSaveDialog(Utils.getActiveFrame());
if (returnVal == JFileChooser.APPROVE_OPTION) {
File file = chooser.getSelectedFile();
String filename = file.getAbsolutePath();
JTableToTDV(filename, tableModel);
frame.setStatus("Saved " + filename + "\n");
} else {
frame.setStatus("Could not Save! \n");
}
} catch (Exception e) {
Utils.handleException(e, e.getMessage());
}// END: try-catch block
}// END: actionPerformed
}// END: ListenSaveLocationCoordinates
private class ListenOk implements ActionListener {
public void actionPerformed(ActionEvent ev) {
window.setVisible(false);
returnValue = tableModel;
frame.setStatus("Loaded " + returnValue.getRowCount()
+ " discrete locations:");
returnValue.printTable();
}// END: actionPerformed
}// END: ListenSaveLocationCoordinates
private class InteractiveTableModelListener implements TableModelListener {
public void tableChanged(TableModelEvent ev) {
if (ev.getType() == TableModelEvent.UPDATE) {
int column = ev.getColumn();
int row = ev.getFirstRow();
table.setColumnSelectionInterval(column + 1, column + 1);
table.setRowSelectionInterval(row, row);
}
}
}// END: InteractiveTableModelListener
@SuppressWarnings("serial")
private class InteractiveRenderer extends DefaultTableCellRenderer {
protected int interactiveColumn;
public InteractiveRenderer(int interactiveColumn) {
this.interactiveColumn = interactiveColumn;
}
public Component getTableCellRendererComponent(JTable table,
Object value, boolean isSelected, boolean hasFocus, int row,
int column) {
Component c = super.getTableCellRendererComponent(table, value,
isSelected, hasFocus, row, column);
if (column == interactiveColumn && hasFocus) {
if ((tableModel.getRowCount() - 1) == row
&& !tableModel.hasEmptyRow()) {
tableModel.addEmptyRow();
}
highlightLastRow(row);
}
return c;
}
}// END: getTableCellRendererComponent
private void highlightLastRow(int row) {
int lastrow = tableModel.getRowCount();
if (row == lastrow - 1) {
table.setRowSelectionInterval(lastrow - 1, lastrow - 1);
} else {
table.setRowSelectionInterval(row + 1, row + 1);
}
table.setColumnSelectionInterval(0, 0);
}// END: highlightLastRow
private void JTableToTDV(String filename, InteractiveTableModel model) {
boolean empty = false;
try {
PrintWriter printWriter = new PrintWriter(filename);
for (int i = 0; i < model.getRowCount(); i++) {
for (int j = 0; j < model.getColumnCount() - 1; j++) {
String s = model.getValueAt(i, j).toString();
empty = s.trim().equals("");
if (!empty) {
printWriter.print(s + "\t");
}// END: check for empty values
}// END: col loop
if (!empty) {
printWriter.println("");
}// END: check for empty values
}// END: row loop
printWriter.close();
} catch (Exception e) {
Utils.handleException(e, e.getMessage());
}// END: try-catch block
}// END: JTableToTDV
private Object[] getUniqueTreeStates(RootedTree tree, String stateAttName) {
Set<String> uniqueTreeStates = new HashSet<String>();
for (Node node : tree.getNodes()) {
if (!tree.isRoot(node)) {
String[] states = Utils.getStringNodeAttribute(node,
stateAttName).split("\\+");
for (int i = 0; i < states.length; i++) {
uniqueTreeStates.add(states[i]);
}
}// END: isRoot
}// END: node loop
Object[] uniqueTreeStatesArray = uniqueTreeStates.toArray();
return uniqueTreeStatesArray;
}// END: getUniqueTreeStates
public void launch(String treeFilename, String stateAttName,
File workingDirectory) {
try {
this.workingDirectory = workingDirectory;
if(treeFilename == null) {
Utils.handleError("Must open a file first.");
return;
}
RootedTree tree = (RootedTree) new NexusImporter(new FileReader(
treeFilename)).importNextTree();
Object[] uniqueTreeStates = getUniqueTreeStates(tree, stateAttName);
for (int i = 0; i < uniqueTreeStates.length; i++) {
tableModel.insertRow(i, new TableRecord(String
.valueOf(uniqueTreeStates[i]), "", ""));
}// END: row loop
// Display Frame
window.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
window.setSize(new Dimension(350, 300));
window.setMinimumSize(new Dimension(100, 100));
window.setResizable(true);
window.setVisible(true);
} catch (Exception e) {
Utils.handleException(e, e.getMessage());
}// END: try-catch block
}// END: launch
public InteractiveTableModel getTable() {
return tableModel;
}
public void launch(File workingDirectory) {
if (!tableModel.hasEmptyRow()) {
tableModel.addEmptyRow();
}
this.workingDirectory = workingDirectory;
// Display Frame
window.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
window.setSize(new Dimension(300, 300));
window.setMinimumSize(new Dimension(100, 100));
window.setResizable(true);
window.setVisible(true);
}// END: launch
public String[] getColumnNames() {
return COLUMN_NAMES;
}// END: getColumnNames
}// END: class