//=====================================================================
// File: BinDialog.java
// Class: BinDialog
// Package: AFLPgui
//
// Author: James J. Benham
// Date: August 11, 1998
// Contact: james_benham@hmc.edu
//
// Genographer v1.0 - Computer assisted scoring of gels.
// Copyright (C) 1998 Montana State University
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; version 2
// of the License.
//
// 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//
// The GNU General Public License is distributed in the file GPL
//=====================================================================
package AFLPgui;
import java.awt.Button;
import java.awt.Checkbox;
import java.awt.Choice;
import java.awt.Dialog;
import java.awt.Frame;
import java.awt.Label;
import java.awt.List;
import java.awt.TextField;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import AFLPcore.Bin;
import AFLPcore.DataList;
import AFLPcore.FeatureList;
import AFLPcore.Option;
import AFLPcore.ProgOptions;
import AFLPcore.ScoreFunction;
import AFLPcore.ScoreManager;
/**
* This is a dialog box that shows a list of bins. It will allow the
* user to add new bins, delete a bin, delete all of the bins, and change
* the parameters of a bin: the location, range, and scoring method.
* The user can change the scoring method for all of the bins at once.
* Changes are stored in a seperate list, and are saved only when the "Ok"
* button is clicked. Most errors are caught and then sent to a dialog
* box to be displayed. The name of the bin displayed in the list depends
* on whether or not the bin has a name defined. If it does, that name will
* be used. Otherwise, the displayed name is simply the location of the bin.
* Methods are provided to both load a bin into the display portion of the
* dialog box and to save the display to a bin.
*
* @author James J. Benham
* @version 1.0.0
* @date August 11, 1998
*/
public class BinDialog extends Dialog implements ActionListener,
ItemListener,
KeyListener,
WindowListener
{
private static final String HELP_FILE = "binhelp.html";
private static int WIDTH = 444;
private static int HEIGHT = 240;
// List box parameters
private static int LIST_H_INSET = 10;
private static int LIST_V_INSET = 30;
private static int LIST_WIDTH = 90;
private static int LIST_HEIGHT = 200;
// Field parameters
private static int V_SPACE = 10;
private static int H_SPACE = 4;
private static int COMP_HEIGHT = 25;
private static int COMP_H_INSET = 110;
private static int LABEL_WIDTH = 80;
private static int FIELD_WIDTH = 80;
private static int CHOICE_WIDTH = 150;
// Button parameters
private static int BUTTON_WIDTH = 80;
private static int ENTER_WIDTH = 120;
private static int SCORE_WIDTH = 110;
private static int BUTTON_H_INSET = 354;
// Check Box parameter
private static int CHECK_INSET = 5;
private static int CHECK_WIDTH = 200;
private Button okButton;
private Button cancelButton;
private Button newButton;
private Button deleteButton;
private Button delAllButton;
private Button helpButton;
private Button enterButton;
private Button scoreOptionButton;
private Checkbox scoreAllCheck;
private List binList;
private Choice scoreChoice;
private TextField nameField;
private TextField locationField;
private TextField rangeField;
private DataList bins;
private DataList savedBins;
private Bin currentBin;
private int index;
private boolean allMode;
private String scoreNames[];
private ScoreFunction scoreFn;
private Frame parent;
/**
* Create a new Bin Dialog with the specified parameters.
*
* @param parent the owner of this dialog box
* @param title the title of the dialog box
* @param modal if true, dialog blocks input to the parent window
* when shown
*/
public BinDialog(Frame parent, String title, boolean modal)
{
super(parent, title, modal);
this.parent = parent;
bins = new DataList();
currentBin = null;
index = -1;
addWindowListener(this);
componentLayout();
loadSelection(index);
}
/**
* The bins to display. Each bin will be given a display name. This
* will be the name of the bin itself if it is defined, or it will
* simply be the bin's location.
*
* @param bins the list of bins to dispaly in the dialog box.
*/
public void setBins(DataList bins)
{
savedBins = bins;
this.bins = bins.completeClone();
// Add the bins to the list
Bin temp;
binList.removeAll();
for(int i=0; i < this.bins.size(); i++)
{
temp = (Bin) this.bins.dataAt(i);
if(temp.getName().equals(""))
binList.add("" + temp.getLocation());
else
binList.add(temp.getName());
}
}
/**
* Handles all of the action event, which come mostly from the
* buttons in the dialog box. To see how each button is handled,
* please see the source.
*/
public void actionPerformed(ActionEvent e)
{
try{
if(e.getSource() == okButton)
{
bins.copyList(savedBins); // store the changes
dispose();
setVisible(false);
}
else if(e.getSource() == enterButton)
{
storeInfo(index);
}
else if(e.getSource() == cancelButton)
{
bins = savedBins; // dispose of changes
dispose();
setVisible(false);
}
else if(e.getSource() == newButton)
{
index = -1;
binList.select(index);
loadSelection(index);
}
else if(e.getSource() == deleteButton)
{
if(index != -1)
{
binList.remove(index);
bins.removeElementAt(index);
index = -1;
loadSelection(index);
}
}
else if(e.getSource() == delAllButton)
{
bins = new DataList();
binList.removeAll();
index = -1;
loadSelection(index);
}
else if(e.getSource() == helpButton)
{
ProgOptions.showHelp(HELP_FILE);
}
else if(e.getSource() == scoreOptionButton)
{
OptionDialog optDialog = new OptionDialog(scoreFn.getOptions(),
(Frame) getParent(),
scoreFn.getName() +
" Parameters");
optDialog.setVisible(true);
if(!optDialog.isCanceled())
{
Option[] opts = optDialog.getOptions();
scoreFn.setOptions(opts);
}
}
}
catch(Throwable error)
{
ErrorDialog eD = new ErrorDialog((Frame) getParent());
eD.showError(error);
}
}
/**
* This handles events generated when the list is manipulated or when
* the check box is changed. It also handles the event when the
* scoring method is changed.
*/
public void itemStateChanged(ItemEvent e)
{
if(e.getSource() == binList)
{
// get the selected item
index = binList.getSelectedIndex();
loadSelection(index);
}
else if(e.getSource() == scoreAllCheck)
{
allMode = scoreAllCheck.getState();
if(allMode)
{
nameField.setText("----------------");
nameField.setEditable(false);
locationField.setText("----------------");
locationField.setEditable(false);
rangeField.setText("----------------");
rangeField.setEditable(false);
binList.setMultipleMode(true);
binList.setVisible(false);
for(int i=0; i < bins.size(); i++)
binList.select(i);
binList.setVisible(true);
binList.setEnabled(false);
}
else
{
nameField.setEditable(true);
locationField.setEditable(true);
rangeField.setEditable(true);
binList.setMultipleMode(false);
binList.setEnabled(true);
binList.select(index);
loadSelection(index);
}
}
else if(e.getSource() == scoreChoice)
{
String value = scoreChoice.getSelectedItem();
scoreFn = (ScoreFunction) FeatureList.getScoreMgr().get(value);
scoreFn = (ScoreFunction) scoreFn.clone();
}
}
/**
* This is used to cause the dialog box to store changes made when
* the Enter key is pushed in one of the fields.
*/
public void keyReleased(KeyEvent e)
{
// Assume that a release of the enter key constitutes the typing
// of the enter key. It is very unlikely that it got pushed down
// somewhere else and released here.
// There are only three listeners, so enter the values if the enter
// key is pushed
if (e.getKeyCode() == KeyEvent.VK_ENTER)
storeInfo(index);
}
/**
* Allows the window to close and has the same affect as pressing the
* cancel button. None of the changes are saved.
*/
public void windowClosing(WindowEvent e)
{
bins = savedBins; // dispose of changes
dispose();
setVisible(false);
}
/**
* Displays the specified bin in the dialog box. If the index
* is -1, then a blank display is created.
*
* @param index the index of the bin in the list of bins.
*
* @see BinDialog#setBins
*/
private void loadSelection(int index)
{
if(index != -1)
{
// retrieve the bin
currentBin = (Bin) bins.dataAt(index);
// update the displays
nameField.setText(currentBin.getName());
locationField.setText("" + currentBin.getLocation());
rangeField.setText("" + currentBin.getRange());
scoreFn = currentBin.getScoreMethod();
scoreChoice.select(scoreFn.getName());
}
else
{
currentBin = null;
nameField.setText("");
locationField.setText("");
rangeField.setText("");
scoreFn = (ScoreFunction) FeatureList.getScoreMgr().getDefault();
scoreChoice.select(FeatureList.getScoreMgr().getDefaultName());
}
}
/**
* This will read in the values from the display and store them
* appropriatly. If the index
is -1, then a new bin will
* be created and added to the list. Otherwise, the values will be read
* in and stored in the currently selected bin. If the check box for
* changing all of the scoring methods is selected, then only the
* score method will be stored, but it will be stored in all of the bins.
*
* @param index the index of the bin in the bin list, -1 for a new bin
*
* @exception NumberFormatException occurs if this method cannot read in
* a number from one of the text boxes.
*/
public void storeInfo(int index) throws NumberFormatException
{
String scoreName;
ScoreManager mgr = FeatureList.getScoreMgr();
if(!allMode)
{
// Read the values from the fields
String name = nameField.getText();
double location = 0;
double range = 0;
try{
location = (new Double(locationField.getText())).doubleValue();
range = (new Double(rangeField.getText())).doubleValue();
}
catch(NumberFormatException e)
{
throw new NumberFormatException("Location and Range must be" +
" numbers.");
}
// Check to see if we should display the name or the size.
String displayName;
if(name.equals(""))
displayName = "" + location;
else
displayName = name;
if(index != -1)
{
// simply modifiy the current bin and update the name in the list
currentBin.setName(name);
currentBin.setLocation(location);
currentBin.setRange(range);
scoreName = scoreChoice.getSelectedItem();
currentBin.setScoreMethod(scoreFn);
binList.replaceItem(displayName, index);
binList.select(index);
}
else
{
// We have a new bin, so it must be created and then added to the
// list. Find the location of the bin and insert it there in the
// screen list
currentBin = new Bin(location, range);
currentBin.setName(name);
currentBin.setScoreMethod((ScoreFunction) mgr.getDefault());
bins.include(currentBin);
index = (bins.find(location)).location;
binList.add(displayName, index);
binList.select(index);
}
}
else
{
// change the scoring method for all of the bins.
for(int i=0; i < bins.size(); i++)
{
scoreFn = (ScoreFunction) scoreFn.clone();
((Bin) bins.dataAt(i)).setScoreMethod(scoreFn);
}
}
}
/**
* Controls wether or not the dialog box is visible. It it is
* true
, then a new blank selection will be loaded.
*
* @param b the visibility state of the dialog box.
*/
public void setVisible(boolean b)
{
super.setVisible(b);
if(b)
{
// show blank fields and no selection
index = -1;
loadSelection(index);
}
}
/**
* Adds all of the components to the dialog box and adds the
* appropriate listeners as well.
*/
private void componentLayout()
{
int startY = 0;
setLayout(null);
setSize(WIDTH, HEIGHT);
setResizable(false);
//====================Add the list==================
binList = new List();
add(binList);
binList.setBounds(LIST_H_INSET, LIST_V_INSET, LIST_WIDTH, LIST_HEIGHT);
binList.addItemListener(this);
//====================Add name stuff=================
Label nameL = new Label("Name:", Label.LEFT);
nameField = new TextField();
add(nameL);
add(nameField);
nameL.setBounds(COMP_H_INSET, LIST_V_INSET, LABEL_WIDTH, COMP_HEIGHT);
nameField.setBounds(COMP_H_INSET + H_SPACE + LABEL_WIDTH, LIST_V_INSET,
FIELD_WIDTH, COMP_HEIGHT);
nameField.addKeyListener(this);
startY += LIST_V_INSET + V_SPACE + COMP_HEIGHT;
//===================Add location stuff==================
Label locationL = new Label("Location:", Label.LEFT);
locationField = new TextField();
add(locationL);
add(locationField);
locationL.setBounds(COMP_H_INSET, startY, LABEL_WIDTH, COMP_HEIGHT);
locationField.setBounds(COMP_H_INSET + H_SPACE + LABEL_WIDTH, startY,
FIELD_WIDTH, COMP_HEIGHT);
locationField.addKeyListener(this);
startY += V_SPACE + COMP_HEIGHT;
//===================Add range stuff==================
Label rangeL = new Label("Range:", Label.LEFT);
rangeField = new TextField();
add(rangeL);
add(rangeField);
rangeL.setBounds(COMP_H_INSET, startY, LABEL_WIDTH, COMP_HEIGHT);
rangeField.setBounds(COMP_H_INSET + H_SPACE + LABEL_WIDTH, startY,
FIELD_WIDTH, COMP_HEIGHT);
rangeField.addKeyListener(this);
startY += V_SPACE + COMP_HEIGHT;
//===================Add score stuff==================
Label scoreL = new Label("Score Using:", Label.LEFT);
scoreChoice = new Choice();
add(scoreL);
add(scoreChoice);
scoreL.setBounds(COMP_H_INSET, startY, LABEL_WIDTH, COMP_HEIGHT);
scoreChoice.setBounds(COMP_H_INSET + H_SPACE + LABEL_WIDTH, startY,
CHOICE_WIDTH, COMP_HEIGHT);
// add the choices
scoreNames = FeatureList.getScoreMgr().getNames();
for(int i=0; i < scoreNames.length; i++)
scoreChoice.add(scoreNames[i]);
scoreChoice.select(FeatureList.getScoreMgr().getDefaultName());
scoreChoice.addItemListener(this);
startY += V_SPACE + COMP_HEIGHT;
//====================Add Score Check Box======================
scoreAllCheck = new Checkbox("Score all using this method", false);
add(scoreAllCheck);
scoreAllCheck.setBounds(COMP_H_INSET + CHECK_INSET, startY,
CHECK_WIDTH, COMP_HEIGHT);
scoreAllCheck.addItemListener(this);
startY += V_SPACE + COMP_HEIGHT;
//====================Add buttons======================
enterButton = new Button("Enter Changes");
add(enterButton);
enterButton.setBounds(COMP_H_INSET, startY, ENTER_WIDTH, COMP_HEIGHT);
enterButton.addActionListener(this);
scoreOptionButton = new Button("Scoring Options");
add(scoreOptionButton);
scoreOptionButton.setBounds(COMP_H_INSET + H_SPACE + ENTER_WIDTH,
startY, SCORE_WIDTH, COMP_HEIGHT);
scoreOptionButton.addActionListener(this);
startY += V_SPACE + COMP_HEIGHT;
startY = LIST_V_INSET;
okButton = new Button("Ok");
add(okButton);
okButton.setBounds(BUTTON_H_INSET, startY, BUTTON_WIDTH, COMP_HEIGHT);
okButton.addActionListener(this);
startY += V_SPACE + COMP_HEIGHT;
cancelButton = new Button("Cancel");
add(cancelButton);
cancelButton.setBounds(BUTTON_H_INSET, startY, BUTTON_WIDTH, COMP_HEIGHT);
cancelButton.addActionListener(this);
startY += V_SPACE + COMP_HEIGHT;
newButton = new Button("New");
add(newButton);
newButton.setBounds(BUTTON_H_INSET, startY, BUTTON_WIDTH, COMP_HEIGHT);
newButton.addActionListener(this);
startY += V_SPACE + COMP_HEIGHT;
deleteButton = new Button("Delete");
add(deleteButton);
deleteButton.setBounds(BUTTON_H_INSET, startY, BUTTON_WIDTH, COMP_HEIGHT);
deleteButton.addActionListener(this);
startY += V_SPACE + COMP_HEIGHT;
delAllButton = new Button("Delete All");
add(delAllButton);
delAllButton.setBounds(BUTTON_H_INSET, startY, BUTTON_WIDTH, COMP_HEIGHT);
delAllButton.addActionListener(this);
startY += V_SPACE + COMP_HEIGHT;
helpButton = new Button("Help");
add(helpButton);
helpButton.setBounds(BUTTON_H_INSET, startY, BUTTON_WIDTH, COMP_HEIGHT);
helpButton.addActionListener(this);
startY += V_SPACE + COMP_HEIGHT;
}
// ==================Unused methods required by interfaces=================
/**Unused*/ public void keyPressed(KeyEvent e) {}
/**Unused*/ public void keyTyped(KeyEvent e) {}
/**Unused*/ public void windowOpened(WindowEvent e) {}
/**Unused*/ public void windowClosed(WindowEvent e) {}
/**Unused*/ public void windowIconified(WindowEvent e) {}
/**Unused*/ public void windowDeiconified(WindowEvent e) {}
/**Unused*/ public void windowActivated(WindowEvent e) {}
/**Unused*/ public void windowDeactivated(WindowEvent e) {}
}