//===================================================================== // File: CutoffDialog.java // Class: CutoffDialog // 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.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.Cutoff; import AFLPcore.CutoffFunction; import AFLPcore.DataList; import AFLPcore.FeatureList; import AFLPcore.Lane; import AFLPcore.Option; import AFLPcore.ProgOptions; /** * This dialog box will display a cutoff. All of the levels of the cutoff * are displayed in a list. Any element of the list can be selected, and * the height of that element can be modified. Additionally, new elements, * cutoff functions, can be added to the list as well as deleted. The * dialog box will save the cutoff to a list of lanes when the "Ok" button * is clicked. * * @see Cutoff * @see CutoffFunction * * @author James J. Benham * @version 1.0.0 * @date August 11, 1998 */ public class CutoffDialog extends Dialog implements ActionListener, ItemListener, KeyListener, WindowListener { private static final String HELP_FILE = "cutoffhelp.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; // 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; private Button okButton; private Button cancelButton; private Button newButton; private Button deleteButton; private Button defaultButton; private Button helpButton; private Button enterButton; private List cutoffList; private TextField heightField; private Cutoff currentCutoff; private DataList lanes; private int index; private double size; private Frame parent; /** * Create a new CutoffDialog 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 CutoffDialog(Frame parent, String title, boolean modal) { super(parent, title, modal); this.parent = parent; index = -1; addWindowListener(this); componentLayout(); loadSelection(index); } /** * Initializes the CutoffDialog with important information. This * should be called before displaying the dialog box. * * @param ct the cutoff to display. The levels of the cutoff will * appear in the list. * @param lanes the lanes to add the cutoff to when the "Ok" button * is clicked. * @param startPos the size in bp where the cutoff should first be * defined. The cutoff will apply to the lane from * the start position to the beginning of the next * cutoff or until the end of the lane. */ public void init(Cutoff ct, DataList lanes, double startPos) { currentCutoff = (Cutoff) ct.clone(); this.lanes = lanes; size = startPos; // refresh the display CutoffFunction ctfn; cutoffList.setVisible(false); cutoffList.removeAll(); for(int i=0; i < currentCutoff.getNumLevels(); i++) { ctfn = currentCutoff.getCutoffFunction(i); cutoffList.add("" + ctfn.getCutoff(size)); } cutoffList.setVisible(true); } /** * Loads the selected function when something in the list is changed. */ public void itemStateChanged(ItemEvent e) { if(e.getSource() == cutoffList) { // get the selected item index = cutoffList.getSelectedIndex(); loadSelection(index); } } /** * Handles the events generated by the buttons. */ public void actionPerformed(ActionEvent e) { try{ if(e.getSource() == okButton) { saveToLanes(); // save the info; dispose(); setVisible(false); } else if(e.getSource() == enterButton) { storeInfo(index); } else if(e.getSource() == cancelButton) { dispose(); setVisible(false); } else if(e.getSource() == newButton) { index = -1; cutoffList.select(index); loadSelection(index); } else if(e.getSource() == deleteButton) { if(index != -1) { cutoffList.remove(index); currentCutoff.deleteFunction(index); index = -1; loadSelection(index); } } else if(e.getSource() == defaultButton) { cutoffList.removeAll(); currentCutoff = new Cutoff(size, 1); CutoffFunction ctfn; ctfn = (CutoffFunction) FeatureList.getCutoffMgr().getDefault(); ctfn = (CutoffFunction) ctfn.clone(); Option opts[] = ctfn.getOptions(); opts[0].setValue(1000); ctfn.setOptions(opts); currentCutoff.setCutoffFunction(ctfn, 0); cutoffList.add("1000.0"); index = -1; loadSelection(index); } else if(e.getSource() == helpButton) { ProgOptions.showHelp(HELP_FILE); } } catch(Throwable error) { ErrorDialog eD = new ErrorDialog((Frame) getParent()); eD.showError(error); } } /** * Used to store the info when enter is pressed in the text field. */ 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. // Only one text field is sending events if (e.getKeyCode() == KeyEvent.VK_ENTER) storeInfo(index); } /** * Closes the dialog box. This has the same affect as pressing the cancel * button. */ public void windowClosing(WindowEvent e) { dispose(); setVisible(false); } /** * Loads the specified cutoff function into the display. In other words, * it loads the value into the height text field. If the index * is -1, then a blank display is loaded. * * @param index the level of the desired cutoff to load. */ private void loadSelection(int index) { if(index != -1) { CutoffFunction ctFn = currentCutoff.getCutoffFunction(index); // update the displays heightField.setText("" + ctFn.getCutoff(size)); } else { heightField.setText(""); } } /** * Reads in the height from the text field and stores it into the * cutoff. If the index is -1, then a new level will * be created and added to the cutoff. * * @param index the level of the current cutoff function, -1 for a * new function * * @exception NumberFormatException occurs if the method cannot read * a number from the text field. */ public void storeInfo(int index) throws NumberFormatException { double height = 0; try{ height = (new Double(heightField.getText())).doubleValue(); } catch(NumberFormatException e) { throw new NumberFormatException("Height must be a number."); } CutoffFunction ctfn; Option opts[]; if(index != -1) { // simply modifiy the current function and update the name in the list ctfn = currentCutoff.getCutoffFunction(index); // get the options and use that to set the height opts = ctfn.getOptions(); // set the first one, which should be the height and store it back opts[0].setValue(height); ctfn.setOptions(opts); cutoffList.replaceItem("" + ctfn.getCutoff(size), index); } else { // We have a new function, so it must be created and then added to the // list. Find the location of the function and insert it there in the // screen list ctfn = (CutoffFunction) FeatureList.getCutoffMgr().getDefault(); ctfn = (CutoffFunction) ctfn.clone(); // get the options and use that to set the height opts = ctfn.getOptions(); // set the first one, which should be the height and store it back opts[0].setValue(height); ctfn.setOptions(opts); // add the function currentCutoff.addFunction(ctfn); // refresh the display cutoffList.setVisible(false); cutoffList.removeAll(); for(int i=0; i < currentCutoff.getNumLevels(); i++) { ctfn = currentCutoff.getCutoffFunction(i); cutoffList.add("" + ctfn.getCutoff(size)); } cutoffList.setVisible(true); } } /** * Shows or hides this dialog box. When it is shown, it will load * a blank selection. * * @param b true to show the component. */ public void setVisible(boolean b) { super.setVisible(b); if(b) { // show blank fields and no selection index = -1; loadSelection(index); } } /** * Takes the cutoff currently defined by this class and adds it to * all of the lanes specified in init. The cutoff is * added at the point specified in init. If a cutoff * already exists at that location, it is replaced. If not, then * the cutoff is simply inserted there. * * @see CutoffDialog#init */ private void saveToLanes() { Lane ln; Cutoff ctff = null; for(int i = 0; i < lanes.size(); i++) { ln = (Lane) lanes.dataAt(i); ctff = ln.cutoffUnder(size); // see if we need to create a new cutoff function for this region. if(ctff.getStartPos() < size) { ln.addCutoff((Cutoff) currentCutoff.clone()); } else { // we have to replace the one there, it's easiest. DataList ctList = ln.getCutoffs(); int location = ctList.find(ctff.getStartPos()).location; ctList.removeElementAt(location); ln.addCutoff((Cutoff) currentCutoff.clone()); } } } /** * Adds all of the components to the dialog box and adds the * appropriate listeners. */ private void componentLayout() { int startY = 0; setLayout(null); setSize(WIDTH, HEIGHT); setResizable(false); //====================Add the list================== cutoffList = new List(); add(cutoffList); cutoffList.setBounds(LIST_H_INSET, LIST_V_INSET, LIST_WIDTH, LIST_HEIGHT); cutoffList.addItemListener(this); startY += LIST_V_INSET; //===================Add height stuff================== Label heightL = new Label("Height:", Label.LEFT); heightField = new TextField(); add(heightL); add(heightField); heightL.setBounds(COMP_H_INSET, startY, LABEL_WIDTH, COMP_HEIGHT); heightField.setBounds(COMP_H_INSET + H_SPACE + LABEL_WIDTH, startY, FIELD_WIDTH, COMP_HEIGHT); heightField.addKeyListener(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); 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; defaultButton = new Button("Default"); add(defaultButton); defaultButton.setBounds(BUTTON_H_INSET, startY, BUTTON_WIDTH, COMP_HEIGHT); defaultButton.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) {} }