/*
* InputPanel.java
*
* Copyright (c) 2002-2015 Alexei Drummond, Andrew Rambaut and Marc Suchard
*
* This file is part of BEAST.
* See the NOTICE file distributed with this work for additional
* information regarding copyright ownership and licensing.
*
* BEAST is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* BEAST is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with BEAST; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301 USA
*/
package dr.app.treespace.inputpanel;
import dr.app.gui.DeleteActionResponder;
import dr.app.gui.table.MultiLineTableCellRenderer;
import dr.app.gui.table.TableEditorStopper;
import jam.framework.Exportable;
import jam.panels.ActionPanel;
import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.plaf.BorderUIResource;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableColumn;
import java.awt.*;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.event.*;
import java.util.HashSet;
import java.util.Set;
import java.util.Iterator;
import java.io.File;
import java.io.IOException;
import dr.evolution.io.Importer;
import dr.app.treespace.*;
import jebl.evolution.io.ImportException;
/**
* @author Andrew Rambaut
* @version $Id$
*/
public class InputPanel extends JPanel implements DeleteActionResponder, Exportable {
private JScrollPane scrollPane = new JScrollPane();
private JTable dataTable = null;
private DataTableModel dataTableModel = null;
private TreeSpaceFrame frame = null;
private InputFileSettingsDialog inputFileSettingsDialog = null;
private final TreeSpaceDocument document;
public InputPanel(final TreeSpaceFrame parent, final TreeSpaceDocument document, final Action addDataAction) {
this.frame = parent;
this.document = document;
dataTableModel = new DataTableModel();
dataTable = new JTable(dataTableModel);
dataTable.getTableHeader().setReorderingAllowed(false);
// dataTable.getTableHeader().setDefaultRenderer(
// new HeaderRenderer(SwingConstants.LEFT, new Insets(0, 4, 0, 4)));
TableColumn col = dataTable.getColumnModel().getColumn(0);
col.setCellRenderer(new MultiLineTableCellRenderer());
dataTable.setRowHeight(dataTable.getRowHeight() * 2);
dataTable.setDragEnabled(false);
dataTable.setTransferHandler(new FSTransfer());
TableEditorStopper.ensureEditingStopWhenTableLosesFocus(dataTable);
dataTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
public void valueChanged(ListSelectionEvent evt) {
selectionChanged();
}
});
dataTable.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
if (e.getClickCount() == 2) {
editSelection();
}
}
});
scrollPane = new JScrollPane(dataTable,
JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
scrollPane.setOpaque(false);
// JToolBar toolBar1 = new JToolBar();
// toolBar1.setFloatable(false);
// toolBar1.setOpaque(false);
// toolBar1.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0));
// JButton button = new JButton(unlinkModelsAction);
// unlinkModelsAction.setEnabled(false);
// PanelUtils.setupComponent(button);
// toolBar1.add(button);
ActionPanel actionPanel1 = new ActionPanel(true);
actionPanel1.setAddAction(addDataAction);
actionPanel1.setRemoveAction(removeAction);
removeAction.setEnabled(false);
JPanel controlPanel1 = new JPanel(new FlowLayout(FlowLayout.LEFT));
controlPanel1.setOpaque(false);
controlPanel1.add(actionPanel1);
setOpaque(false);
setBorder(new BorderUIResource.EmptyBorderUIResource(new Insets(12, 12, 12, 12)));
setLayout(new BorderLayout(0, 0));
// add(toolBar1, BorderLayout.NORTH);
add(scrollPane, BorderLayout.CENTER);
add(controlPanel1, BorderLayout.SOUTH);
document.addListener(new TreeSpaceDocument.Listener() {
public void dataChanged() {
dataTableModel.fireTableDataChanged();
}
public void settingsChanged() { }
});
}
public void selectionChanged() {
int[] selRows = dataTable.getSelectedRows();
boolean hasSelection = (selRows != null && selRows.length != 0);
removeAction.setEnabled(hasSelection);
frame.setRemoveActionEnabled(this, hasSelection);
}
public JComponent getExportableComponent() {
return dataTable;
}
public void editSelection() {
int selRow = dataTable.getSelectedRow();
if (selRow >= 0) {
InputFile inputFile = document.getInputFiles().get(selRow);
editSettings(inputFile);
}
}
private void editSettings(InputFile inputFile) {
if (inputFileSettingsDialog == null) {
inputFileSettingsDialog = new InputFileSettingsDialog(frame);
}
int result = inputFileSettingsDialog.showDialog(inputFile);
if (result != JOptionPane.CANCEL_OPTION) {
inputFileSettingsDialog.getInputFile(); // force update of builder settings
document.fireDataChanged();
}
}
public void delete() {
int[] selRows = dataTable.getSelectedRows();
Set<InputFile> dataToRemove = new HashSet<InputFile>();
for (int row : selRows) {
dataToRemove.add(document.getInputFiles().get(row));
}
// TODO: would probably be a good idea to check if the user wants to remove the last file
document.getInputFiles().removeAll(dataToRemove);
document.fireDataChanged();
if (document.getInputFiles().size() == 0) {
// all data partitions removed so reset the taxa
frame.setStatusMessage("No data loaded");
}
}
public void selectAll() {
dataTable.selectAll();
}
class DataTableModel extends AbstractTableModel {
private static final long serialVersionUID = -6707994233020715574L;
String[] columnNames = {"Input Files"};
public DataTableModel() {
}
public int getColumnCount() {
return columnNames.length;
}
public int getRowCount() {
return document.getInputFiles().size();
}
public Object getValueAt(int row, int col) {
InputFile inputFile = document.getInputFiles().get(row);
switch (col) {
case 0:
return inputFile;
default:
throw new IllegalArgumentException("unknown column, " + col);
}
}
public boolean isCellEditable(int row, int col) {
return false;
}
public String getColumnName(int column) {
return columnNames[column];
}
public Class getColumnClass(int c) {
if (getRowCount() == 0) {
return Object.class;
}
return getValueAt(0, c).getClass();
}
public String toString() {
StringBuffer buffer = new StringBuffer();
buffer.append(getColumnName(0));
for (int j = 1; j < getColumnCount(); j++) {
buffer.append("\t");
buffer.append(getColumnName(j));
}
buffer.append("\n");
for (int i = 0; i < getRowCount(); i++) {
buffer.append(getValueAt(i, 0));
for (int j = 1; j < getColumnCount(); j++) {
buffer.append("\t");
buffer.append(getValueAt(i, j));
}
buffer.append("\n");
}
return buffer.toString();
}
}
public class FSTransfer extends TransferHandler {
public boolean importData(JComponent comp, Transferable t) {
// Make sure we have the right starting points
if (!(comp instanceof JTable)) {
return false;
}
if (!t.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
return false;
}
try {
java.util.List data = (java.util.List) t.getTransferData(DataFlavor.javaFileListFlavor);
Iterator i = data.iterator();
while (i.hasNext()) {
File f = (File) i.next();
frame.importDataFile(f);
}
return true;
} catch (UnsupportedFlavorException ufe) {
System.err.println("Ack! we should not be here.\nBad Flavor.");
} catch (IOException ioe) {
System.out.println("Something failed during import:\n" + ioe);
} catch (ImportException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
}
return false;
}
// We only support file lists on FSTrees...
public boolean canImport(JComponent comp, DataFlavor[] transferFlavors) {
if (comp instanceof JTable) {
for (int i = 0; i < transferFlavors.length; i++) {
if (!transferFlavors[i].equals(DataFlavor.javaFileListFlavor)) {
return false;
}
}
return true;
}
return false;
}
}
public Action getDeleteAction() {
return removeAction;
}
private Action removeAction = new RemoveDataAction();
private class RemoveDataAction extends AbstractAction {
public RemoveDataAction() {
super("Remove");
setToolTipText("Use this button to remove selected input data from the table");
}
public void actionPerformed(ActionEvent ae) {
delete();
}
}
}