/*
* Copyright (C) Justo Montiel, David Torres, Sergio Gomez, Alberto Fernandez
*
* This library 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.1 of
* the License, or (at your option) any later version.
*
* This library 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 this library; if not, see
* <http://www.gnu.org/licenses/>
*/
package moduls.frm.Panels;
import genomeObjects.CSDisplayData;
import importExport.DadesExternes;
import importExport.FitxerDades;
import inicial.Language;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.FileDialog;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.SwingWorker;
import javax.swing.event.InternalFrameEvent;
import javax.swing.event.InternalFrameListener;
import methods.Reagrupa;
import moduls.frm.FrmInternalFrame;
import moduls.frm.FrmPrincipalDesk;
import moduls.frm.InternalFrameData;
import moduls.frm.children.FrmPiz;
import parser.Fig_Pizarra;
import tipus.Orientation;
import tipus.metodo;
import tipus.tipusDades;
import definicions.Config;
import definicions.MatriuDistancies;
/**
* <p>
* <b>MultiDendrograms</b>
* </p>
*
* Load and Update buttons
*
* @author Justo Montiel, David Torres, Sergio Gómez, Alberto Fernández
*
* @since JDK 6.0
*/
public class Jpan_btn extends JPanel implements ActionListener,
InternalFrameListener, PropertyChangeListener {
// ----- Fields -----------------------------------------------//
private static final long serialVersionUID = 1L;
// Desktop where the dendrogram is to be shown
private final FrmPrincipalDesk fr;
//this button
protected Jpan_btn jb;
// Text to show in the buttons
private String strLoad, strUpdate;
// Load and update buttons
private static JButton btnLoad, btnUpdate;
// Indicates if the buttons Load or Update are being clicked
public static boolean buttonClicked = false;
// Indicate if the text fields have correct values
public static boolean precisionCorrect = false;
public static boolean axisMinCorrect = false;
public static boolean axisMaxCorrect = false;
public static boolean axisSeparationCorrect = false;
public static boolean axisEveryCorrect = false;
public static boolean axisDecimalsCorrect = false;
// Internal frame currently active
private FrmInternalFrame currentInternalFrame = null;
// File with the input data
private static FitxerDades fitx = null; //path to file
private DadesExternes de; //ACTUAL DATA -> must be imported from file
// Text box for the file name
private static JTextField txtFileName;
// MultiDendrogram
private MatriuDistancies multiDendro = null;
// Progress bar for MultiDendrogram computation
private JProgressBar progressBar;
//Search bar + Search submit buttons
private JTextField searchField;
private JButton submitSearch;
// ----- New Fields --------------------------------------------//
//These fields modify the new scrollable tree
private int HorizontalScrollBuffer = 30;
private int VerticalScrollValue = 1500;
// ----- Methods -----------------------------------------------//
// Swing Worker MultiDendrogram computation
class MDComputation extends SwingWorker<Void, Void> {
private final String action;
private final tipusDades typeData;
private final metodo method;
private final int precision;
private final int nbElements;
private double minBase;
public MDComputation(final String action, final tipusDades typeData,
final metodo method, final int precision, final int nbElements,
double minBase) {
this.action = action;
this.typeData = typeData;
this.method = method;
this.precision = precision;
this.nbElements = nbElements;
this.minBase = minBase;
// System.out.println("Step 2");
}
@Override
public Void doInBackground() {
// System.out.println("Step 2.5");
Reagrupa rg;
MatriuDistancies mdNew;
double b;
int progress;
// Initialize progress property
progress = 0;
setProgress(progress);
while (multiDendro.getCardinalitat() > 1) {
try {
//CLUSTERING FROM DISTANCES DATA
rg = new Reagrupa(multiDendro, typeData, method, precision);
mdNew = rg.Recalcula();
//SET THE CURRENT MULTIDENDROGRAM TO THE RESULT FROM RG.RECALCULA()
multiDendro = mdNew;
b = multiDendro.getArrel().getBase();
if ((b < minBase) && (b != 0)) {
minBase = b;
}
progress = 100
* (nbElements - multiDendro.getCardinalitat())
/ (nbElements - 1);
setProgress(progress);
} catch (final Exception e) {
showError(e.getMessage());
}
}
return null;
}
@Override
public void done() {
// System.out.println("Step 3");
multiDendro.getArrel().setBase(minBase);
showCalls(action);
progressBar.setString("");
progressBar.setBorderPainted(false);
progressBar.setValue(0);
fr.setCursor(null); // turn off the wait cursor
}
}
public Jpan_btn(final FrmPrincipalDesk fr) {
super();
this.fr = fr;
this.jb = this;
this.getPanel();
this.setVisible(true);
}
private void getPanel() {
this.setLayout(new GridBagLayout());
this.setBorder(BorderFactory.createTitledBorder(Language.getLabel(20))); // File
final GridBagConstraints c = new GridBagConstraints();
int gridy = 0;
// btn load
c.gridx = 0;
c.gridy = gridy;
c.gridwidth = 1;
c.gridheight = 1;
c.fill = GridBagConstraints.HORIZONTAL;
c.insets = new Insets(1, 1, 1, 1);
strLoad = Language.getLabel(21); // Load
btnLoad = new JButton(strLoad);
btnLoad.addActionListener(this);
add(btnLoad, c);
// btn update
c.gridx = 1;
c.gridy = gridy;
c.gridwidth = GridBagConstraints.REMAINDER;
c.gridheight = 1;
c.fill = GridBagConstraints.HORIZONTAL;
c.insets = new Insets(1, 1, 1, 1);
strUpdate = Language.getLabel(110); // Update
btnUpdate = new JButton(strUpdate);
btnUpdate.addActionListener(this);
btnUpdate.setEnabled(false);
add(btnUpdate, c);
gridy++;
// txt file name
c.gridx = 0;
c.gridy = gridy;
c.gridwidth = GridBagConstraints.REMAINDER;
c.gridheight = 1;
c.fill = GridBagConstraints.HORIZONTAL;
c.insets = new Insets(1, 1, 1, 1);
txtFileName = new JTextField();
txtFileName.setText(Language.getLabel(112)); // No file loaded
txtFileName.addActionListener(this);
txtFileName.setEditable(false);
add(txtFileName, c);
gridy++;
// progress bar
c.gridx = 0;
c.gridy = gridy;
c.gridwidth = GridBagConstraints.REMAINDER;
c.gridheight = 1;
c.fill = GridBagConstraints.HORIZONTAL;
c.insets = new Insets(1, 1, 1, 1);
progressBar = new JProgressBar(0, 100);
progressBar.setStringPainted(true);
progressBar.setString("");
progressBar.setBorderPainted(false);
progressBar.setValue(0);
add(progressBar, c);
gridy++;
// Searchable text
c.gridx = 0;
c.gridy = gridy;
c.gridwidth = GridBagConstraints.HORIZONTAL;
c.gridheight = 1;
c.fill = GridBagConstraints.HORIZONTAL;
c.insets = new Insets(1, 1, 1, 1);
searchField = new JTextField();
searchField.setText(""); // Enter search bar
searchField.addActionListener(this);
searchField.setEditable(true);
add(searchField, c);
gridy++;
//Submit search
c.gridx = 0;
c.gridy = gridy;
c.gridwidth = GridBagConstraints.HORIZONTAL;
c.gridheight = 1;
c.fill = GridBagConstraints.HORIZONTAL;
c.insets = new Insets(1, 1, 1, 1);
submitSearch = new JButton("Submit Search");
submitSearch.addActionListener(this);
add(submitSearch, c);
}
public static void enableUpdate() {
if (precisionCorrect && axisMinCorrect && axisMaxCorrect
&& axisSeparationCorrect && axisEveryCorrect
&& axisDecimalsCorrect) {
btnUpdate.setEnabled(true);
} else {
btnUpdate.setEnabled(false);
}
}
public static String getFileNameNoExt() {
String name = "";
if (fitx != null) {
name = fitx.getNomNoExt();
}
return name;
}
public static void setFileName(String name) {
txtFileName.setText(name);
}
public MatriuDistancies getMatriu() {
return de.getMatriuDistancies();
}
// BUTTONS PUSHED -> LOAD FILE OR UPDATE TREE
@Override
public void actionPerformed(final ActionEvent evt) {
String action = null;
FitxerDades fitxTmp;
boolean ambDades = false;
InternalFrameData ifd;
double minBase;
MDComputation mdComputation;
// System.out.println("Step 1");
//DETERMINE ACTION
if (evt.getActionCommand().equals(strLoad)) {
// LOAD
buttonClicked = true;
action = "Load";
// Load data from file
if (fitx == null) {
/*
* get the data file - the 'getFitxerDades()' method calls the
* built-in GUI file retrieval window 'FileDialog'
*/
fitxTmp = getFitxerDades();
} else {
// Last directory
fitxTmp = getFitxerDades(fitx.getPath());
}
if (fitxTmp == null) {
// Cancel pressed
ambDades = false;
} else {
fitx = fitxTmp;
ambDades = true;
}
} else if (evt.getActionCommand().equals("Submit Search")) {
//SUBMIT BUTTON
buttonClicked = true;
action = "Load";
if (searchField.getText().equals("a")) {
fitx = new FitxerDades();
fitx.setNom("SmallHexokinase.txt");
fitx.setPath("C:/Research/ECRON_lists/");
} else if (searchField.getText().equals("b")){
fitx = new FitxerDades();
fitx.setNom("LargeMatrix.txt");
fitx.setPath("C:/Research/ECRON_lists/");
} else {
fitx = new FitxerDades();
fitx.setNom("TestMatrix2.txt");
fitx.setPath("C:/Research/ECRON_lists/");
}
ambDades = true; //ambDades = "with data"
//System.out.println(fitx.getPath());
} else if (evt.getActionCommand().equals(strUpdate)) {
// UPDATE
buttonClicked = true;
ifd = currentInternalFrame.getInternalFrameData();
if ((Jpan_Menu.getTypeData() == ifd.getTypeData())
&& (Jpan_Menu.getMethod() == ifd.getMethod())
&& (Jpan_Menu.getPrecision() == ifd.getPrecision())) {
action = "Redraw";
} else {
action = "Reload";
}
ambDades = true;
}
//CARRY OUT ACTION
if (ambDades && (action.equals("Load") || action.equals("Reload"))) {
try {
/*
* KEY - DADESEXTERNES converts a data file (bunch of strings) to
* internal mathematical objects used in processing
*/
de = new DadesExternes(fitx);
/*
*
*/
if (action.equals("Load")) {
Jpan_Menu.setPrecision(de.getPrecisio());
//changing this value changes the computation
//places after decimal is a function of the precision.
//Jpan_Menu.setPrecision(2);
}
multiDendro = null;
try {
multiDendro = de.getMatriuDistancies();
minBase = Double.MAX_VALUE;
progressBar.setBorderPainted(true);
progressBar.setString(null);
fr.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
// Instances of javax.swing.SwingWorker are not reusable,
// so we create new instances as needed.
mdComputation = new MDComputation(action,
Jpan_Menu.getTypeData(), Jpan_Menu.getMethod(),
Jpan_Menu.getPrecision(),
multiDendro.getCardinalitat(), minBase);
mdComputation.addPropertyChangeListener(this);
mdComputation.execute();
} catch (final Exception e2) {
buttonClicked = false;
showError(e2.getMessage());
}
} catch (Exception e1) {
buttonClicked = false;
//showError(e1.getMessage());
showError("Who let the dogs out?");
}
} else if (ambDades && action.equals("Redraw")) {
showCalls(action);
} else {
buttonClicked = false;
}
}
private void showCalls(final String action) {
// System.out.println("Step 4");
if (action.equals("Reload") || action.equals("Redraw")) {
currentInternalFrame.doDefaultCloseAction();
}
show(action, Jpan_Menu.getMethod(), Jpan_Menu.getPrecision());
currentInternalFrame.doDefaultCloseAction();
show(action, Jpan_Menu.getMethod(), Jpan_Menu.getPrecision());
txtFileName.setText(fitx.getNom());
btnUpdate.setEnabled(true);
buttonClicked = false;
}
public void show(String action, final metodo method, final int precision) {
// System.out.println("Step 5");
boolean isUpdate;
FrmInternalFrame pizarra;
Config cfg;
InternalFrameData ifd;
FrmPiz fPiz;
Fig_Pizarra figPizarra;
isUpdate = !action.equals("Load");
try {
pizarra = fr.createInternalFrame(isUpdate, method.name());
cfg = fr.getConfig();
cfg.setPizarra(pizarra);
cfg.setFitxerDades(fitx);
cfg.setMatriu(multiDendro);
cfg.setHtNoms(de.getTaulaNoms()); //table names
//determine size of tree rendering based on number of elements
setVerticalScrollValue(de.getTaulaNoms().size());
if (!cfg.isTipusDistancia()) {
if (cfg.getOrientacioDendo().equals(Orientation.NORTH)) {
cfg.setOrientacioDendo(Orientation.SOUTH);
} else if (cfg.getOrientacioDendo().equals(Orientation.SOUTH)) {
cfg.setOrientacioDendo(Orientation.NORTH);
} else if (cfg.getOrientacioDendo().equals(Orientation.EAST)) {
cfg.setOrientacioDendo(Orientation.WEST);
} else if (cfg.getOrientacioDendo().equals(Orientation.WEST)) {
cfg.setOrientacioDendo(Orientation.EAST);
}
}
ifd = new InternalFrameData(fitx, multiDendro);
pizarra.setInternalFrameData(ifd);
// Title for the child window
pizarra.setTitle(fitx.getNom() + " - " + pizarra.getTitle());
//WARNING - modified constructor to avoid problems 8/2/2012
//create a new figure frame
CSDisplayData CSD = new CSDisplayData();
fPiz = new FrmPiz(fr, CSD);
// Set sizes
fPiz.setSize(pizarra.getSize());
fPiz.setPreferredSize(pizarra.getSize());
//determine appropriate rendering dimensions
Dimension d = new Dimension(pizarra.getWidth()-
HorizontalScrollBuffer, VerticalScrollValue);
fPiz.setPreferredSize(d);
// Call Jpan_Menu -> internalFrameActivated()
pizarra.setVisible(true);
if (action.equals("Load") || action.equals("Reload")) {
Jpan_Menu.ajustaValors(cfg);
}
// Current internal frame is the activated frame.
fr.setCurrentFrame(pizarra);
// Convert tree into figures
figPizarra = new Fig_Pizarra(multiDendro.getArrel(), cfg);
// Pass figures to the window
fPiz.setFigures(figPizarra.getFigures());
fPiz.setConfig(cfg);
//scroll panel, with sizes
JScrollPane fPizSP = new JScrollPane(fPiz);
fPizSP.setSize(pizarra.getSize());
fPizSP.setPreferredSize(pizarra.getSize());
//unused options
//fPizSP.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
//fPizSP.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
//pizarra.add(fPiz);
pizarra.add(fPizSP);
} catch (final Exception e) {
e.printStackTrace();
showError(e.getMessage());
}
}
private FitxerDades getFitxerDades() {
return this.getFitxerDades(System.getProperty("user.dir"));
}
//DATA FILE
private FitxerDades getFitxerDades(final String sPath) {
//use pre-existing 'FileDialog' GUI window to retrieve file
final FileDialog fd = new FileDialog(fr, Language.getLabel(9),
FileDialog.LOAD);
FitxerDades fitx; //Data file type is just a bunch of relevant strings
fitx = new FitxerDades();
fd.setDirectory(sPath);
fd.setVisible(true);
if (fd.getFile() == null) {
fitx = null;
} else {
fitx.setNom(fd.getFile());
fitx.setPath(fd.getDirectory());
}
return fitx; //A bunch of strings relating to the file information.
}
private void showError(final String msg) {
JOptionPane.showMessageDialog(null, msg, Language.getLabel(7),
JOptionPane.ERROR_MESSAGE);
}
//Interal Frame - related methods
@Override
public void internalFrameActivated(InternalFrameEvent e) {
InternalFrameData ifd;
currentInternalFrame = (FrmInternalFrame) e.getSource();
btnUpdate.setEnabled(true);
if (!buttonClicked) {
fr.setCurrentFrame(currentInternalFrame);
ifd = currentInternalFrame.getInternalFrameData();
de = ifd.getDadesExternes();
fitx = de.getFitxerDades();
setFileName(fitx.getNom());
multiDendro = ifd.getMultiDendrogram();
Jpan_Menu.setConfigPanel(ifd);
}
}
@Override
public void internalFrameClosing(InternalFrameEvent e) {
FrmInternalFrame.decreaseOpenFrameCount();
btnUpdate.setEnabled(false);
txtFileName.setText(Language.getLabel(112)); // No file loaded
if (!buttonClicked) {
Jpan_Menu.clearConfigPanel();
}
}
@Override
public void internalFrameClosed(InternalFrameEvent e) {
}
@Override
public void internalFrameOpened(InternalFrameEvent e) {
}
@Override
public void internalFrameIconified(InternalFrameEvent e) {
}
@Override
public void internalFrameDeiconified(InternalFrameEvent e) {
}
@Override
public void internalFrameDeactivated(InternalFrameEvent e) {
}
@Override
public void propertyChange(PropertyChangeEvent evt) {
if (evt.getPropertyName() == "progress") {
int progress = (Integer) evt.getNewValue();
progressBar.setValue(progress);
}
}
// generated methods - automatically detect scroll value
public int getVerticalScrollValue() {
return VerticalScrollValue;
}
public void setVerticalScrollValue(int numberOfEntries) {
VerticalScrollValue = 15*numberOfEntries + 250;
}
}