//===================================================================== // File: OptionDialog.java // Class: OptionDialog // Package: AFLPgui // // Author: James J. Benham (plus a little defiling by Philip DeCamp) // Date: August 12, 1998 // Contact: james_benham@hmc.edu or decamp@portalofevil.com // // Genographer v1.6 - Computer assisted scoring of gels. // Changes Copyright (C) 2001 James J. Benham // 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.Choice; import java.awt.Component; import java.awt.Dialog; import java.awt.Frame; import java.awt.Label; import java.awt.Panel; import java.awt.ScrollPane; import java.awt.TextField; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.WindowEvent; import java.awt.event.WindowListener; import AFLPcore.Option; import AFLPcore.MissingParameterError; /** * This class will display options in a dialog box. The options are * associated with a GUI component by keeping the components in a parrallel * array. The components are displayed on the left side of the dialog, and * if the number of options cause the display space required to exceed the * size of the dialog, a scroll bar becomes available. The dialog will * check to see if all of the required options have been set before * closing. * * @see AFLPcore.Option * * @author James J. Benham * @version 1.0.0 * @date August 12, 1998 */ public class OptionDialog extends Dialog implements ActionListener, WindowListener { // GUI Layout constants private static final int OPTION_WIDTH = 300; private static final int OPTION_HEIGHT = 25; private static final int LABEL_WIDTH = 100; private static final int FIELD_WIDTH = 150; private static final int HEADER_INSET = 5; private static final int HEADER_HEIGHT = 22; private static final int OPTION_INSET = 12; private static final int OPTION_SPACE = 5; private static final int BUTTON_WIDTH = 70; private static final int BUTTON_HEIGHT = 22; private static final int BUTTON_V_SPACE = 5; private static final int BUTTON_H_INSET = 5; private static final int V_INSET = 25; private static final int SCROLL_V_INSET = 20; private static final int SCROLL_WIDTH = 16; private static final int WIDTH = (OPTION_WIDTH + BUTTON_WIDTH + 2*BUTTON_H_INSET); private static final int HEIGHT = 320; private Panel optionPane; private Button okButton; private Button cancelButton; private Component optUIComponent[]; private Option opts[]; private int numRequired; private boolean canceled; private Frame parentWin; /** * Creates a new option dialog with the specified parameters. * * @param opts the options to display * @param parent the owner of this dialog box. */ public OptionDialog(Option opts[], Frame parent) { this(opts, parent, ""); } /** * Creates a new option dialog with the specified parameters * * @param opts the options to display * @param parent the owner of this dialog box. * @param title the title of the dialog box. */ public OptionDialog(Option opts[], Frame parent, String title) { // create a modal dialog box super(parent, title, true); parentWin = parent; this.opts = opts; optUIComponent = new Component[opts.length]; canceled = true; // See how many are required numRequired = 0; for(int i=0; i < opts.length; i++) { if(opts[i].isRequired()) numRequired++; } layoutOptions(); addWindowListener(this); } /** * Reads the options in from the various components. * * @return true if all of the required options have been * set, false otherwise. * * @exception NumberFormatException occurs if one of the options which * is suppossed to be a number is cannot be read as a number. */ private boolean readOptions() { boolean requiredSet; String value; TextField field; Choice choice; for(int i=0; i < opts.length; i++) { switch(opts[i].getType()) { case Option.NUMBER: field = (TextField) optUIComponent[i]; value = field.getText(); if(!value.equals("")) { try { Double db = new Double(value); opts[i].setValue(db.doubleValue()); } catch(NumberFormatException e) { throw new NumberFormatException(opts[i].getLabel() + " must be a number!"); } } break; case Option.STRING: field = (TextField) optUIComponent[i]; value = field.getText(); if(!value.equals("")) opts[i].setValue(value); break; case Option.CHOICE: choice = (Choice) optUIComponent[i]; // just get the selected one. opts[i].setValue(choice.getSelectedItem()); break; } } // see if all of the required parameters have been set requiredSet = true; for(int i=0; i < opts.length; i++) requiredSet = requiredSet && (!opts[i].isRequired() || opts[i].isSet()); return requiredSet; } /** * Gives the options as they were set by the user in the dialog box. * * @return the options for the dialog box. */ public Option[] getOptions() { return opts; } /** * Tells whether the dialog was canceled or not. * * @return true if the dialog was cancelled. */ public boolean isCanceled() { return canceled; } /** * Handles the buttons. If ok is clicked, then the options are read. * if all of the options are set, then it closes the dialog. If not, * then an error is shown. Cancel simply closes the dialog. */ public void actionPerformed(ActionEvent e) { try{ if(e.getSource() == okButton) { boolean allSet = readOptions(); if(allSet) { canceled = false; dispose(); } else { ErrorDialog eD = new ErrorDialog(parentWin); eD.showError(new MissingParameterError("All Required optionst " + " not set.")); } } if(e.getSource() == cancelButton) { canceled = true; dispose(); } } catch(Throwable error) { ErrorDialog eD = new ErrorDialog(parentWin); eD.showError(error); } } /** * Closes the dialog and is equivalent to pressing cancel. */ public void windowClosing(WindowEvent e) { canceled = true; dispose(); } /** * Adds all of the components to the dialog box. */ private void layoutOptions() { int x; int y; setLayout(null); setSize(WIDTH, HEIGHT); setResizable(false); // find out how long this will be int length = ((V_INSET - SCROLL_V_INSET) + opts.length * (OPTION_HEIGHT + OPTION_SPACE)); // add room for the required label if(numRequired > 0) length += OPTION_SPACE + HEADER_HEIGHT; // add room for the optional label if(opts.length > numRequired) length += OPTION_SPACE + HEADER_HEIGHT; // make the scroll pane ScrollPane scrollArea = new ScrollPane(); add(scrollArea); scrollArea.setBounds(0, SCROLL_V_INSET, OPTION_WIDTH, HEIGHT - SCROLL_V_INSET); // create a panel for the options optionPane = new Panel(); // subtract the width of a scroll bar, can be found by // scrollArea.getVScrollbarWidth(), but we must wait around // for the peer to be created, which it wasn't been at this point. // It simply returns 0. So, set it as a constant and just go // with it. It sucks b/c it's system dependent, but it works. optionPane.setBounds(0, 0, OPTION_WIDTH - 4 - SCROLL_WIDTH, length); optionPane.setLayout(null); // Add the options panel to a scroll pane scrollArea.add(optionPane); // ===========add the buttons========== okButton = new Button("Ok"); add(okButton); okButton.addActionListener(this); x = OPTION_WIDTH + BUTTON_H_INSET; y = V_INSET; okButton.setBounds(x, y, BUTTON_WIDTH, BUTTON_HEIGHT); y += BUTTON_HEIGHT + BUTTON_V_SPACE; cancelButton = new Button("Cancel"); add(cancelButton); cancelButton.addActionListener(this); cancelButton.setBounds(x, y, BUTTON_WIDTH, BUTTON_HEIGHT); //===========draw required label============= x = 0; y = V_INSET - SCROLL_V_INSET; // Optional vs Required Distiction in display removed by Philip DeCamp // Re-inserted by jbenham Sept 3, 2001 if(numRequired > 0 && numRequired != opts.length) { Label requiredL = new Label("Required Parameters____________________"); optionPane.add(requiredL); requiredL.setBounds(HEADER_INSET, y, OPTION_WIDTH - HEADER_INSET, HEADER_HEIGHT); y += OPTION_SPACE + HEADER_HEIGHT; } //============ add the required options ============= for(int i=0; i < opts.length; i++) { if(opts[i].isRequired()) { addOption(opts[i], y, i); y += OPTION_HEIGHT + OPTION_SPACE; } } //============add the optional label=========== if(opts.length > numRequired) { Label optionalL; optionalL = new Label("Optional Parameters____________________"); optionPane.add(optionalL); optionalL.setBounds(HEADER_INSET, y, OPTION_WIDTH - HEADER_INSET, HEADER_HEIGHT); y += OPTION_SPACE + HEADER_HEIGHT; } //============ add the optional options ============= for(int i=0; i < opts.length; i++) { if(!opts[i].isRequired()) { addOption(opts[i], y, i); y += OPTION_HEIGHT + OPTION_SPACE; } } // Remove option display code that ignores required vs optional // jbenham Sept 3, 2001 /* *for(int i = 0; i < opts.length; i++){ * addOption(opts[i], y, i); * y+= OPTION_HEIGHT + OPTION_SPACE; *} */ } /** * Creates a GUI component for the specified option and places it * at the specified position. The component is then stored in an * array at the specified index. * * @param option the option to add to the display * @param pos the vertical position to add it at * @param index the index into the array of GUI components. This * is the same as the index of the option in the * option array. */ public void addOption(Option option, int pos, int index) { // Add the label Label label = new Label(option.getLabel() + ":"); optionPane.add(label); if(option.getType() == Option.LABEL) label.setBounds(OPTION_INSET, pos, WIDTH, OPTION_HEIGHT); else label.setBounds(OPTION_INSET, pos, LABEL_WIDTH, OPTION_HEIGHT); // Add the component switch(option.getType()) { case Option.STRING: // just a text box like the number, // difference in reading case Option.NUMBER: TextField tempField = new TextField(); if(option.getType() == Option.NUMBER){ Double tempInt = new Double(option.getNumValue()); tempField.setText(tempInt.toString()); } else tempField.setText(option.getStringValue()); optionPane.add(tempField); tempField.setBounds(OPTION_INSET + LABEL_WIDTH, pos, FIELD_WIDTH, OPTION_HEIGHT); optUIComponent[index] = tempField; break; case Option.CHOICE: Choice tempChoice = new Choice(); // add the choices String choices[] = option.getChoices(); for(int i=0; i < choices.length; i++) tempChoice.add(choices[i]); if(option.getDefaultChoice() != null) tempChoice.select(option.getDefaultChoice()); optionPane.add(tempChoice); tempChoice.setBounds(OPTION_INSET + LABEL_WIDTH, pos, FIELD_WIDTH, OPTION_HEIGHT); optUIComponent[index] = tempChoice; break; } } // ==================Unused methods required by interfaces================= /**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) {} }