/*
* Copyright (c) 2009 Genome Research Limited.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU Library General Public License as published by the Free
* Software Foundation; either version 2 of the License or (at your option) any
* later version.
*
* This program 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 Library General Public License for more
* details.
*
* You should have received a copy of the GNU Library General Public License
* along with this program; see the file COPYING.LIB. If not, write to the Free
* Software Foundation Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307
* USA
*/
package org.genedb.jogra.plugins;
import org.genedb.db.taxon.TaxonNode;
import org.genedb.db.taxon.TaxonNodeManager;
import org.genedb.jogra.drawing.Jogra;
import org.genedb.jogra.drawing.JograPlugin;
import org.genedb.jogra.services.NamedVector;
import org.apache.log4j.Logger;
import org.bushe.swing.event.EventBus;
import it.cnr.imaa.essi.lablib.gui.checkboxtree.CheckboxTree;
import it.cnr.imaa.essi.lablib.gui.checkboxtree.TreeCheckingEvent;
import it.cnr.imaa.essi.lablib.gui.checkboxtree.TreeCheckingListener;
import it.cnr.imaa.essi.lablib.gui.checkboxtree.TreeCheckingModel;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;
import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.SwingWorker;
import javax.swing.WindowConstants;
import javax.swing.tree.TreePath;
/**
* Organism-Tree/Organism-Chooser plugin for Jogra. Displays the organisms in the database in a hierarchical view and allows
* the user to select as many as necessary. This selection is then published on the EventBus for other plug-ins that need it,
* like the Term Rationaliser. We make use of the TaxonNodeManager class from genedb/db to extract the tree of organisms.
* Started: April 2009
*
* @author nds
*/
public class OrganismTree implements JograPlugin {
private TaxonNodeManager taxonNodeManager;
private List<String> userSelection = new ArrayList<String>(); //Stores the organism names that the user selects
private Jogra jogra;
private static final Logger logger = Logger.getLogger(OrganismTree.class);
public void setTaxonNodeManager(TaxonNodeManager taxonNodeManager) {
this.taxonNodeManager = taxonNodeManager;
}
/**
* Supply a JPanel which will be displayed in the main Jogra application panel,
* used for launching a plug-in, or displaying status
*
* @return a JPanel, ready for displaying
*/
public JPanel getMainWindowPlugin(){
final JPanel panel = new JPanel();
final JLabel label = new JLabel("Select organism(s) to work with");
final JButton button = new JButton("Load organism tree");
//When user clicks button, load a new frame with Jtree
ActionListener actionListener = new ActionListener(){
public void actionPerformed(ActionEvent actionEvent){
try{
new SwingWorker<JFrame, Void>() {
@Override
protected JFrame doInBackground() throws Exception {
return getMainPanel();
}
}.execute();
}catch(Exception e){ //handle exceptions better later
logger.debug(e);
}
}
};
button.addActionListener(actionListener);
Box horizontalBox = Box.createHorizontalBox();
horizontalBox.add(label);
horizontalBox.add(button);
horizontalBox.add(Box.createHorizontalGlue());
panel.add(horizontalBox);
return panel;
}
/**
* Method that creates the JFrame object containing the tree of organisms
* @return
*/
public JFrame getMainPanel() {
final JFrame frame = new JFrame("Organisms currently in the database");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final JButton button = new JButton("Select"); //Create button to confirm user selection. Disabled at first
//TaxonNodeManager created and initialised at start up. Create JTree
TaxonNode taxonNode = taxonNodeManager.getTaxonNodeForLabel("Root");
Vector orgTree = getOrganismTree(taxonNode);
JTree tree = new JTree(orgTree);
final CheckboxTree checkboxTree = new CheckboxTree(tree.getModel()); //checkboxnode constructor takes a tree model
checkboxTree.getCheckingModel().setCheckingMode(TreeCheckingModel.CheckingMode.PROPAGATE_PRESERVING_CHECK); //Check if this can be both SINGLE & PROPOGATE
checkboxTree.addTreeCheckingListener(new TreeCheckingListener() {
public void valueChanged(TreeCheckingEvent e) {
if(e.isCheckedPath()){
button.setText("Select");
button.setEnabled(true);
}
}
});
button.setEnabled(false);
ActionListener actionListener = new ActionListener(){
public void actionPerformed(ActionEvent actionEvent){
try{
userSelection.clear(); //Clear any previous selections
TreePath tp[] = checkboxTree.getCheckingRoots();
for(TreePath p: tp){
userSelection.add(p.getLastPathComponent().toString());
}
frame.setVisible(false); //Make frame disappear
//frame.dispose(); //Or should frame be disposed??
EventBus.publish("selection", userSelection); //EventBus publish mechanism here needs to be tested later
logger.info("ORGANISM TREE: User selected " + userSelection.toString());
}catch(Exception e){ //handle exceptions better
logger.debug(e);
e.printStackTrace();
}
}
};
button.addActionListener(actionListener);
//Place Jtree in scrollable pane to enable scrolling
JScrollPane scrollPane = new JScrollPane(checkboxTree);
frame.add(scrollPane, BorderLayout.CENTER);
frame.add(button, BorderLayout.PAGE_END);
frame.setSize(500,500);
frame.setVisible(true);
frame.setDefaultCloseOperation(WindowConstants.HIDE_ON_CLOSE);
return frame;
}
/**
* A recursive helper method to return the organism hierarchy in vector form
*
* @return Vector containing organism hierarchy
*/
private Vector getOrganismTree(TaxonNode taxonNode){
List<TaxonNode> childrenList = taxonNode.getChildren();
Vector childrenVector = new Vector();
for(TaxonNode child : childrenList){
if(child.isLeaf()){
//if(child.isPopulated()){
childrenVector.add(child.getLabel());
//}
}else{
childrenVector.add(getOrganismTree(child));
}
}
return new NamedVector(taxonNode.getLabel(), childrenVector);
}
/**
* The name of the plug-in, maybe this should be set in the config
*
* @return the name
*/
public String getName(){
return "Organism Tree";
}
/**
* Is there only one instance of the plug-in, by default
*
* @return true if there should only be one copy of the plug-in
*/
public boolean isSingletonByDefault(){
return false; //Shouldn't this be true by default?
}
/**
* Allow the plug-in to indicate whether it has unsaved changes
*
* @return true if there are changes to be saved
*/
public boolean isUnsaved(){
return false;
}
/**
* @param newArgs
*/
public void process(List<String> newArgs){
//What is this meant to do?
}
@Override
public void setJogra(Jogra jogra) {
// TODO Auto-generated method stub
}
}