package org.seqcode.viz.components;
import java.util.*;
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import javax.swing.event.*;
import javax.swing.table.*;
import org.seqcode.data.core.ExptType;
import org.seqcode.genome.Genome;
import org.seqcode.genome.Species;
import org.seqcode.gseutils.*;
/**
* GenericTablePanel is a single pane panel that holds a table list
*
* @author mahony
*
* @param <X>
*/
public abstract class GenericEditTablePanel<X> extends JPanel implements Closeable, Runnable {
private JButton editButton, filterButton;
protected JComboBox speciesCBox;
protected JTable filteredList;
protected ObjectTableModel<X> filteredModel;
protected JPanel buttonPanel;
private boolean handlingUpdate, dataReady;
private Thread thread;
public GenericEditTablePanel() {
super();
handlingUpdate = false;
dataReady = false;
}
public GenericEditTablePanel(Genome g) {
super();
handlingUpdate = false;
dataReady = false;
}
/**
* UpdateData
* Starts a new thread to update data.
Database work should happen in that thread and the results should
be cached. Swing components should be updated with a call
to SwingUtilities.invokeLater(). Since this also invokes run(),
the run() method must determine the current operation by querying:
handlingNewGenome() and dataReady()
*/
public void updateData() {
if (thread != null && thread.isAlive()) {
thread.interrupt();
thread = null;
}
thread = new Thread(this);
handlingUpdate = true;
dataReady = false;
thread.start();
}
public boolean handlingUpdate() {return handlingUpdate;}
public boolean dataReady() {return dataReady;}
public void run() {
if (handlingUpdate()) {
retrieveData();
handlingUpdate = false;
dataReady = true;
SwingUtilities.invokeLater(this);
} else if (dataReady()) {
updateComponents();
dataReady = false;
}
}
/* retrieve data from the database; must cache somewhere
*/
public abstract void retrieveData();
/* called from swing thread to update the swing components
for the cached data */
public abstract void updateComponents();
/* sub-class constructors must call one of the two init() methods */
public void init(JTable filteredList,
ObjectTableModel<X> filteredModel) {
final JTableHeader header = filteredList.getTableHeader();
final ObjectTableModel filteredmodel = filteredModel;
header.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
filteredmodel.sortByColumn(header.columnAtPoint(e.getPoint()));
}
});
this.filteredList = filteredList;
this.filteredModel = filteredModel;
editButton = new JButton("Edit");
filterButton = new JButton("Filter");
Font tableFont = new Font("SansSerif", Font.PLAIN, 11);
filteredList.setFont(tableFont);
ArrayList<String> orgs = new ArrayList<String>();
orgs.add("");
Collection<String> organisms = Species.getAllSpeciesNames(false);
for (String o : organisms) { orgs.add(o); }
Collections.sort(orgs);
speciesCBox = new JComboBox(orgs.toArray());
speciesCBox.setEditable(true);
final GenericEditTablePanel panel = this;
editButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
panel.edit(getFilteredForEdit());
}
});
filterButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
panel.filter();
}
});
speciesCBox.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
panel.filter();
}
});
filteredList.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
panel.filterToEdit(e);
}
});
JPanel actPanel = new JPanel(); actPanel.setLayout(new BorderLayout());
actPanel.add(new JScrollPane(filteredList), BorderLayout.CENTER);
buttonPanel = new JPanel();
buttonPanel.setLayout(new GridBagLayout());
buttonPanel.add(editButton);
buttonPanel.add(filterButton);
buttonPanel.add(new JLabel("Species:"));
buttonPanel.add(speciesCBox);
JPanel inputsPanel = getInputsPanel();
JPanel allInputsPanel = new JPanel(); allInputsPanel.setLayout(new BorderLayout());
allInputsPanel.add(inputsPanel,BorderLayout.CENTER);
allInputsPanel.add(buttonPanel,BorderLayout.SOUTH);
actPanel.add(allInputsPanel,BorderLayout.SOUTH);
add(actPanel);
}
public void init(ObjectTableModel<X> filteredModel) {
init(new JTable(filteredModel),
filteredModel);
}
public abstract JPanel getInputsPanel();
public abstract void filter();
public abstract void edit(Collection<X> toEdit);
/* returns the elements of the filtered list that should be added
when the "edit" button is pressed */
public Collection<X> getFilteredForEdit() {
ArrayList<X> output = new ArrayList<X>();
int[] inds = filteredList.getSelectedRows();
for (int i = 0; i < inds.length; i++) {
X o = filteredModel.getObject(inds[i]);
output.add(o);
}
return output;
}
//Double click handling
public void filterToEdit(MouseEvent e) {
if(e.getButton() == MouseEvent.BUTTON1 && e.getClickCount() == 2) {
ArrayList<X> output = new ArrayList<X>();
int row = filteredList.rowAtPoint(e.getPoint());
X x = filteredModel.getObject(row);
output.add(x);
edit(output);
}
}
public void close() {}
public boolean isClosed() {return true;}
}