package moduls.frm.Panels;
import java.awt.Color;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.util.LinkedList;
import javax.swing.BorderFactory;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JTextField;
import newickTreeParsing.Tree;
import newickTreeParsing.TreeParser;
import moduls.frm.FrmPrincipalDesk;
public class Jpan_PhyTreeMenu extends JPanel implements ActionListener {
//fields
private FrmPrincipalDesk f;
//GUI components
private Font fontStandard = new Font("Dialog", Font.BOLD, 10);
private JLabel LoadPhyTreeBanner;
private String strLoadPhyTreeBanner = " LOAD A PHYLOGENETIC TREE";
private JButton btnPhyTree;
private String strPhyTree = "Load";
private JTextField CurrentTree, TreeType;
private String strCurrentTree = " Current Tree: ";
private String strTreeType = " Tree Type:";
private JLabel CurrentlyEnabledBanner;
private String strCurrentlyEnabledBanner = " AVAILABLE PHYLOGENETIC TREES";
private JComboBox<String> menuLoadedPhyTrees;
private JButton btnRemoveSelectedPhyTree;
private String strRemoveSelectedPhyTree = "Remove Selected";
private JLabel DisplayOptionsBanner;
private String strDisplayOptions = " PHYLOGENETIC TREE DISPLAY OPTIONS";
private ButtonGroup PhyloDisplayOptions, PhyloTreeType;
private JRadioButton radCladogram, radPhylogram;
private JRadioButton radSpecies, radGene;
private String strSpecies = "Species Tree";
private String strGene = "Gene Tree";
private JCheckBox chkDashed, chkWeights;
private String strCladogram = "Cladogram";
private String strPhylogram = "Phylogram";
private String strchkDashed = "Draw dashed line to label";
private String strchkWeights = "Display support values";
//Data components
private File FilePath = null;
private LinkedList<File> LoadedPhyTrees = new LinkedList<File>();
private LinkedList<Tree> ParsedPhyTrees = new LinkedList<Tree>();
private Tree CurrentParsedTree;
//constructor
public Jpan_PhyTreeMenu(FrmPrincipalDesk fr){
this.f = fr;
this.FilePath = fr.getFileChooserSource();
//build components
this.getPanel();
}
//build components
public void getPanel(){
//initialize panel
this.setLayout(new GridBagLayout());
this.setBorder(BorderFactory.createTitledBorder("Phylogenetic Tree Settings")); // title
final GridBagConstraints c = new GridBagConstraints();
int gridy = 0;
//initial GridBagLayout parameters
c.anchor = GridBagConstraints.FIRST_LINE_START;
c.weightx = 1;
//c.weighty = 1;
c.insets = new Insets(1,1,1,1);
//Load Phylogenetic Tree banner
c.gridx = 0;
c.gridy = gridy;
c.gridheight = 1;
c.fill = GridBagConstraints.HORIZONTAL;
c.gridwidth = 4;
LoadPhyTreeBanner = new JLabel(strLoadPhyTreeBanner);
LoadPhyTreeBanner.setBackground(Color.GRAY);
LoadPhyTreeBanner.setOpaque(true);
LoadPhyTreeBanner.setFont(fontStandard);
add(LoadPhyTreeBanner,c);
gridy++;
//Load Phylogenetic Tree button
c.gridx = 0;
c.gridy = gridy;
c.gridheight = 1;
c.fill = GridBagConstraints.NONE;
c.gridwidth = 4;
btnPhyTree = new JButton(strPhyTree);
btnPhyTree.setFont(fontStandard);
btnPhyTree.addActionListener(this);
add(btnPhyTree,c);
gridy++;
//Currently Loaded banner
c.gridx = 0;
c.gridy = gridy;
c.gridheight = 1;
c.fill = GridBagConstraints.HORIZONTAL;
c.gridwidth = 4;
CurrentlyEnabledBanner = new JLabel(strCurrentlyEnabledBanner);
CurrentlyEnabledBanner.setBackground(Color.GRAY);
CurrentlyEnabledBanner.setOpaque(true);
CurrentlyEnabledBanner.setFont(fontStandard);
add(CurrentlyEnabledBanner,c);
gridy++;
//Currently Loaded tree tag
c.gridx = 0;
c.gridy = gridy;
c.gridheight = 1;
c.fill = GridBagConstraints.NONE;
c.gridwidth = 1;
CurrentTree = new JTextField(strCurrentTree);
CurrentTree.setFont(fontStandard);
CurrentTree.setEditable(false);
add(CurrentTree,c);
gridy++;
// currently loaded motifs drop-down menu
c.ipady = 0;
c.gridx = 0;
c.gridy = gridy;
c.gridwidth = 4;
c.gridheight = 1;
c.fill = GridBagConstraints.HORIZONTAL;
menuLoadedPhyTrees = new JComboBox<String>(getLoadedPhyTrees());
menuLoadedPhyTrees.addActionListener(this);
menuLoadedPhyTrees.setEnabled(true);
menuLoadedPhyTrees.setFont(fontStandard);
add(menuLoadedPhyTrees, c);
gridy++;
//Remove phylogenetic tree button
c.gridx = 0;
c.gridy = gridy;
c.gridheight = 1;
c.fill = GridBagConstraints.NONE;
c.gridwidth = 4;
btnRemoveSelectedPhyTree = new JButton(strRemoveSelectedPhyTree);
btnRemoveSelectedPhyTree.setFont(fontStandard);
btnRemoveSelectedPhyTree.addActionListener(this);
add(btnRemoveSelectedPhyTree,c);
gridy++;
//Currently Loaded tree tag
c.gridx = 0;
c.gridy = gridy;
c.gridheight = 1;
c.fill = GridBagConstraints.NONE;
c.gridwidth = 1;
TreeType = new JTextField(strTreeType);
TreeType.setFont(fontStandard);
TreeType.setEditable(false);
//add(TreeType,c);
gridy++;
//define button group
PhyloTreeType = new ButtonGroup();
radSpecies = new JRadioButton(strSpecies);
radGene = new JRadioButton(strGene);
PhyloTreeType.add(radSpecies);
PhyloTreeType.add(radGene);
//Tree option 1: Species Tree
c.gridx = 0;
c.gridy = gridy;
c.gridheight = 1;
c.fill = GridBagConstraints.HORIZONTAL;
c.gridwidth = 1;
radSpecies.setSelected(true);
radSpecies.addActionListener(this);
//add(radSpecies, c);
//Tree option 2: Gene Tree
c.gridx = 1;
c.gridy = gridy;
c.gridheight = 1;
c.fill = GridBagConstraints.HORIZONTAL;
c.insets = new Insets(1,1,10,1);
c.gridwidth = 1;
radGene.setSelected(false);
radGene.addActionListener(this);
//add(radGene, c);
gridy++;
//Display Options banner
c.gridx = 0;
c.gridy = gridy;
c.gridheight = 1;
c.fill = GridBagConstraints.HORIZONTAL;
c.gridwidth = 4;
c.insets = new Insets(0,0,0,0);
DisplayOptionsBanner = new JLabel(strDisplayOptions);
DisplayOptionsBanner.setBackground(Color.GRAY);
DisplayOptionsBanner.setOpaque(true);
DisplayOptionsBanner.setFont(fontStandard);
add(DisplayOptionsBanner,c);
gridy++;
//define button group
PhyloDisplayOptions = new ButtonGroup();
radCladogram = new JRadioButton(strCladogram);
radPhylogram = new JRadioButton(strPhylogram);
PhyloDisplayOptions.add(radCladogram);
PhyloDisplayOptions.add(radPhylogram);
//Display option 1: cladogram
c.gridx = 0;
c.gridy = gridy;
c.gridheight = 1;
c.fill = GridBagConstraints.HORIZONTAL;
c.gridwidth = 1;
radCladogram.setSelected(false);
radCladogram.addActionListener(this);
add(radCladogram, c);
//Display option 2: phylogram
c.gridx = 1;
c.gridy = gridy;
c.gridheight = 1;
c.fill = GridBagConstraints.HORIZONTAL;
c.gridwidth = 3;
radPhylogram.setSelected(true);
radPhylogram.addActionListener(this);
add(radPhylogram, c);
gridy++;
//option: draw dashed line to label
c.gridx = 1;
c.gridy = gridy;
c.gridheight = 1;
c.fill = GridBagConstraints.HORIZONTAL;
c.gridwidth = 3;
chkDashed = new JCheckBox(strchkDashed);
chkDashed.addActionListener(this);
chkDashed.setSelected(true);
chkDashed.setEnabled(true);
this.add(chkDashed, c);
gridy++;
c.gridx = 0;
c.gridy = gridy;
c.fill = GridBagConstraints.HORIZONTAL;
c.gridwidth = 4;
chkWeights = new JCheckBox(strchkWeights);
chkWeights.setSelected(true);
chkWeights.addActionListener(this);
this.add(chkWeights, c);
gridy++;
}
//convert motifs from linked list to integer array
public String[] getLoadedPhyTrees(){
String PhyTrees[];
if (LoadedPhyTrees.size() > 0){
PhyTrees = new String[LoadedPhyTrees.size()];
for (int i = 0; i < LoadedPhyTrees.size(); i++){
PhyTrees[i] = LoadedPhyTrees.get(i).getName();
}
} else {
PhyTrees = new String[1];
PhyTrees[0] = "<none>";
}
return PhyTrees;
}
//parse a tree
public Tree ParseNewickTree(File NewickTreeFile){
//Initialize output
Tree t;
//attempt to import file
try {
BufferedReader r = new BufferedReader(new FileReader(NewickTreeFile));
TreeParser tp = new TreeParser(r);
t = tp.tokenize(NewickTreeFile.length(), NewickTreeFile.getName(), null);
} catch (FileNotFoundException e) {
JOptionPane.showMessageDialog(null, "The selected file is not appropriately formatted.");
t = null;
}
//return tree file
return t;
}
public Tree ParseNexusTree(File NexusTreeFile){
//Initialize output
Tree t;
//attempt to import file
try {
BufferedReader r = new BufferedReader(new FileReader(NexusTreeFile));
TreeParser tp = new TreeParser(r);
t = tp.tokenize(NexusTreeFile.length(), NexusTreeFile.getName(), null);
} catch (FileNotFoundException e) {
JOptionPane.showMessageDialog(null, "The selected file is not appropriately formatted.");
t = null;
}
return t;
}
@Override
public void actionPerformed(ActionEvent evt) {
if (f.getOS() != null){
//load button
if (evt.getSource().equals(btnPhyTree)){
ImportPhyTree();
}
//switch menu to active tree
if (evt.getSource().equals(menuLoadedPhyTrees)){
//retrieve name of current tree
String CurrentName = (String) menuLoadedPhyTrees.getSelectedItem();
//find this tree in the list, and set it to the active one.
for (Tree t : ParsedPhyTrees){
if (t.getName().equals(CurrentName)){
setCurrentParsedTree(t);
break;
}
}
}
//remove an available phylogenetic tree
if (evt.getSource().equals(btnRemoveSelectedPhyTree)){
//remove from the list of trees
for (Tree t : ParsedPhyTrees){
if (t.getName().equals((String) menuLoadedPhyTrees.getSelectedItem())){
ParsedPhyTrees.remove(t);
f.getOS().getParsedPhyTrees().remove(t);
break;
}
}
//remove from the list of files
for (File f: LoadedPhyTrees){
if (f.getName().equals((String) menuLoadedPhyTrees.getSelectedItem())){
LoadedPhyTrees.remove(f);
break;
}
}
//remake the menu
menuLoadedPhyTrees.removeAllItems();
String[] PhyTrees = getLoadedPhyTrees();
for (String s : PhyTrees){
menuLoadedPhyTrees.addItem(s);
}
}
//display options
if (evt.getSource().equals(radPhylogram)){
this.chkDashed.setEnabled(true);
}
if (evt.getSource().equals(radCladogram)){
this.chkDashed.setEnabled(false);
}
//redraw phylogenetic tree
if (evt.getSource().equals(radPhylogram) ||
evt.getSource().equals(radCladogram) ||
evt.getSource().equals(chkDashed) ||
evt.getSource().equals(chkWeights)){
//update phylogenetic tree, if appropriate.
if (f.getCurrentFrame() != null){ //frame exists
//phylogenetic tree exists
if (f.getCurrentFrame().getInternalFrameData().getQD().getAnalysesList().isOptionRenderPhylogeny()){
//repaint!
f.getCurrentFrame().getInternalFrameData().getPhyloTreePanel().repaint();
}
}
}
} else {
f.NoOS();
}
}
public void ImportPhyTree(){
//create filechooser
JFileChooser getPhyTree = new JFileChooser();
getPhyTree.setFileSelectionMode(JFileChooser.FILES_ONLY);
getPhyTree.setDialogTitle("Select Phylogenetic tree file (Newick format required)");
//open at last open point.
if (f.getFileChooserSource() != null){
getPhyTree.setCurrentDirectory(f.getFileChooserSource());
} else {
getPhyTree.setCurrentDirectory(new File("."));
}
getPhyTree.showOpenDialog(getPhyTree);
//retrieve file
File TreeFile = getPhyTree.getSelectedFile();
//if the file is not null (cancel operation), try to parse
if (TreeFile != null){
//update current directory
f.setFileChooserSource(getPhyTree.getCurrentDirectory());
Tree t = ParseNewickTree(TreeFile);
setCurrentParsedTree(t);
//add + update, if the tree is new.
if (!LoadedPhyTrees.contains(TreeFile) && t != null){
//update catalog
CurrentParsedTree = t; //Tree
ParsedPhyTrees.add(t); //LinkedList<Tree>
LoadedPhyTrees.add(0,TreeFile); //LinkedList<File>
FilePath = TreeFile; //Path
//update GUI
menuLoadedPhyTrees.removeAllItems();
String[] PhyTrees = getLoadedPhyTrees();
for (String s : PhyTrees){
menuLoadedPhyTrees.addItem(s);
}
//update OS
f.getOS().getParsedPhyTrees().add(t);
f.getOS().getLoadedPhyTrees().add(0, TreeFile);
}
}
}
//retrieve the current parsed phylogenetic tree
public Tree getCurrentParsedTree() {
return CurrentParsedTree;
}
public void setCurrentParsedTree(Tree currentParsedTree) {
CurrentParsedTree = currentParsedTree;
}
public JRadioButton getRadCladogram() {
return radCladogram;
}
public JRadioButton getRadPhylogram() {
return radPhylogram;
}
public JCheckBox getChkDashed() {
return chkDashed;
}
public JCheckBox getChkWeights() {
return chkWeights;
}
public LinkedList<Tree> getParsedPhyTrees() {
return ParsedPhyTrees;
}
public void setParsedPhyTrees(LinkedList<Tree> parsedPhyTrees) {
ParsedPhyTrees = parsedPhyTrees;
}
public void setLoadedPhyTrees(LinkedList<File> loadedPhyTrees) {
LoadedPhyTrees = loadedPhyTrees;
}
public File getFilePath() {
return FilePath;
}
public void setFilePath(File filePath) {
FilePath = filePath;
}
public JComboBox<String> getMenuLoadedPhyTrees() {
return menuLoadedPhyTrees;
}
public void setMenuLoadedPhyTrees(JComboBox<String> menuLoadedPhyTrees) {
this.menuLoadedPhyTrees = menuLoadedPhyTrees;
}
public JRadioButton getRadSpecies() {
return radSpecies;
}
public void setRadSpecies(JRadioButton radSpecies) {
this.radSpecies = radSpecies;
}
public JRadioButton getRadGene() {
return radGene;
}
public void setRadGene(JRadioButton radGene) {
this.radGene = radGene;
}
}