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