package woSource; import java.awt.*; import java.awt.event.*; import ij.*; import ij.gui.*; import java.util.*; import ij.plugin.frame.Recorder; /** Walter O'Dell PhD, wodell@rochester.edu, 11/6/02 * Overview of GenericDialogPlus and GenericRecallableDialog classes: * these classes enable the specification of scrollbars, buttons, and * the objects available in the GenericDialog class that remain active * until the dialog window is actively closed. * * Attributes: * Scrollbars: enables scrollbars for integer, float and/or double values. * float/double values are facilitated by maintaining a scaling factor * for each scrollbar, and an Ndigits parameter. * Keyboard arrow keys adjust values of most recently mouse-activated scrollbar. * Buttons: enables buttons that perform actions (besides 'exit') * * rowOfItems(): enables placement of multiple objects in a row, * e.g. the scrollbar title, current value and the scrollbar itsself. * addButtons(): enables easy specification of multiple buttons across a row * getBooleanValue(int index_to_list); getNumericValue(); getButtonValue(); getScrollbarValue() * enables access to the value of any individual object without having to go * through the entire list of like-objects with getNext...() functions. * * minor changes to the parent GenericDialog were needed, as described in the header * for the temporary GenericDialog2 class, namely: * 1. Changed 'private' attribute to 'protected' for several variables in parent * class to facilitate use of these variables by GenericDialogPlus class * 2. Added variables (int) x; // GridBagConstraints height variable * and (Container) activePanel; // facilitates row of items option * and code altered to initialize and update these new variables. * It is hoped that these modifications will be made to the parent GenericDialog class * in future versions of ImageJ, negating the need for the GenericDialog2 class * 8/13/2012 added feature: if a button is given focus (can be done in the code) and 'return' hit anywhere * in the GUI, the button's actions will be invoked. **/ class GenericDialogPlus extends GenericDialog2 implements AdjustmentListener, ActionListener, KeyListener, FocusListener { /** Maximum number of each component (numeric field, checkbox, etc). */ public static final int MAX_ITEMS = 20; protected Scrollbar[] scrollbars; protected double[] SBscales; protected double[] SBcurValues; private Label[] SBcurValueLabels; protected int sbIndex, SBtotal; private int[] SBdigits; // Ndigits to right of decimal pt (0==integer) protected int SBlastTouched; // last scrollbar touched; needed for arrow key usage // second panel(s) enables placement of multiple items on same line (row) private Panel twoPanel; private GridBagConstraints tmpc; private GridBagLayout tmpgrid; private int tmpy; public GenericDialogPlus(String title) { super(title); } /** Creates a new GenericDialog using the specified title and parent frame. */ public GenericDialogPlus(String title, Frame parent) { super(title, parent); } /** access the value of the i'th checkbox */ public boolean getBooleanValue(int i) { if (checkbox==null) return false; // else Checkbox cb = (Checkbox)(checkbox.elementAt(i)); return cb.getState(); } /** set the value of the i'th checkbox */ public void setCheckboxValue(int i, boolean newstate) { if (checkbox==null) return; // else Checkbox cb = (Checkbox)(checkbox.elementAt(i)); cb.setState(newstate); } public String getChoiceValue(int i) { if (choice==null) return ""; Choice thisChoice = (Choice)(choice.elementAt(i)); String item = thisChoice.getSelectedItem(); if (macro) { String label = (String)labels.get((Object)thisChoice); item = Macro.getValue(macroOptions, label, item); } return item; } /** access the value of the i'th numeric field */ public double getNumericValue(int i) { if (numberField==null) return 0; // else TextField tf = (TextField)numberField.elementAt(i); String theText = tf.getText(); String originalText = (String)defaultText.elementAt(i); double defaultValue = ((Double)(defaultValues.elementAt(i))).doubleValue(); double value; if (theText.equals(originalText)) value = defaultValue; else { Double d = getValue(theText); if (d!=null) value = d.doubleValue(); else { // invalidNumber = true; value = 0.0; } } return value; } public void beginRowOfItems() { tmpc = c; tmpgrid = grid; tmpy = y; twoPanel = new Panel(); activePanel = twoPanel; grid = new GridBagLayout(); twoPanel.setLayout(grid); c = new GridBagConstraints(); x = y = 0; } public void endRowOfItems() { activePanel = this; c = tmpc; grid = tmpgrid; y = tmpy; c.gridwidth = 1; c.gridx = 0; c.gridy = y; c.anchor = GridBagConstraints.WEST; c.insets = new Insets(0, 0, 0, 0); grid.setConstraints(twoPanel, c); add(twoPanel); x = 0; y++; } /** Adds adjustable scrollbar field. * param label the label * param defaultValue initial state * param digits the number of digits to the right of the decimal place * param minval the range minimum (left side value of slider) * param maxval the range maximum (right side value of slider) * param maxclicks the number of increments in value associated with mouse click * param sliderWidth the scrollbar width (internal padding), in pixels */ public void addScrollBar(String label, double defaultValue, int digits, double minval, double maxval) { // use default 100 clicks and a slider width of 100 addScrollBar(label, defaultValue, digits, minval, maxval, 100, 100); } public void addScrollBar(String label, double defaultValue, int digits, double minval, double maxval, int maxClicks) { addScrollBar(label, defaultValue, digits, minval, maxval, maxClicks, 100); } public void addScrollBar(String label, double defaultValue, int digits, double minval, double maxval, int maxClicks, int sliderWidth) { if (sbIndex >= MAX_ITEMS) { IJ.log(" cannot add another slider, have maxed out at: "+sbIndex); return; } if (scrollbars==null) { scrollbars = new Scrollbar[MAX_ITEMS]; SBscales = new double[MAX_ITEMS]; SBcurValues = new double[MAX_ITEMS]; SBcurValueLabels = new Label[MAX_ITEMS]; SBdigits = new int[MAX_ITEMS]; } // create new panel that is 3 cells wide for SBlabel, SB, SBcurVal Panel sbPanel = new Panel(); GridBagLayout sbGrid = new GridBagLayout(); GridBagConstraints sbc = new GridBagConstraints(); sbPanel.setLayout(sbGrid); // label Label theLabel = new Label(label); sbc.fill = GridBagConstraints.NONE;//HORIZONTAL; sbc.insets = new Insets(5, 0, 0, 0); sbc.gridx = 0; sbc.gridy = 0; sbc.weightx = 1; sbc.anchor = GridBagConstraints.WEST; sbGrid.setConstraints(theLabel, sbc); sbPanel.add(theLabel); // scrollbar: only works with integer values so use scaling SBscales[sbIndex] = Math.pow(10.0, digits); SBcurValues[sbIndex] = defaultValue; int visible = (int)Math.round((maxval-minval)* SBscales[sbIndex]/10.0); scrollbars[sbIndex] = new Scrollbar(Scrollbar.HORIZONTAL, (int)Math.round(defaultValue*SBscales[sbIndex]), visible, /* 'visible' == width of bar inside slider == increment taken when click inside slider window */ (int)Math.round(minval*SBscales[sbIndex]), (int)Math.round(maxval*SBscales[sbIndex] +visible) ); /* Note that the actual maximum value of the scroll bar is the maximum minus the visible. The left side of the bubble indicates the value of the scroll bar. */ scrollbars[sbIndex].addAdjustmentListener(this); scrollbars[sbIndex].addKeyListener(this); // for scrollbar keyboard control int adjIncr = Math.max(1,(int)Math.round((maxval-minval)*SBscales[sbIndex]/maxClicks)); scrollbars[sbIndex].setUnitIncrement(adjIncr); scrollbars[sbIndex].setBlockIncrement(adjIncr*5); sbc.gridx = 1; sbc.ipadx = sliderWidth; // set the scrollbar width (internal padding), in pixels sbc.anchor = GridBagConstraints.WEST; sbGrid.setConstraints(scrollbars[sbIndex], sbc); sbPanel.add(scrollbars[sbIndex]); sbc.ipadx = 0; // reset // current value label SBdigits[sbIndex] = digits; SBcurValueLabels[sbIndex] = new Label(" "+IJ.d2s(SBcurValues[sbIndex], digits)+" "); sbc.gridx = 2; sbc.insets = new Insets(5, 5, 0, 0); sbc.anchor = GridBagConstraints.WEST; sbGrid.setConstraints(SBcurValueLabels[sbIndex], sbc); sbPanel.add(SBcurValueLabels[sbIndex]); c.gridwidth = 2; // this panel will take up one grid in overall GUI c.gridx = x; c.gridy = y; c.insets = new Insets(0, 0, 0, 0); c.anchor = GridBagConstraints.WEST; // CENTER; grid.setConstraints(sbPanel, c); activePanel.add(sbPanel); sbIndex++; if (activePanel == this) { x=0; y++; } else x++; SBtotal = sbIndex; } // end scrollbar field public void setScrollBarUnitIncrement(int inc) { scrollbars[sbIndex-1].setUnitIncrement(inc); } /** Returns the contents of the next scrollbar field. */ public double getNextScrollBar() { if (scrollbars[sbIndex]==null) return -1.0; else return SBcurValues[sbIndex++]; } /** Returns the contents of scrollbar field 'i' */ public double getScrollBarValue(int i) { if (i<0 || i>=SBtotal || scrollbars[i]==null) return -1.0; else return SBcurValues[i]; } /** Sets the contents of scrollbar 'i' field to 'value' */ public void setScrollBarValue(int i, double value) { if (i<0 || i>=SBtotal || scrollbars[i]==null) return; scrollbars[i].setValue((int)Math.round(value*SBscales[i])); SBcurValues[i] = value; SBcurValueLabels[i].setText(IJ.d2s(SBcurValues[i], SBdigits[i])); } // WO 9/25/2012 can reset the limits of the scrollbar public void setScrollBarLimits(int i, int newmin, int newmax) { if (i<0 || i>=SBtotal || scrollbars[i]==null) return; scrollbars[i].setMinimum(newmin); scrollbars[i].setMaximum(newmax); } /** disable/hide a scrollbar */ public void hideScrollBar(int i) { if (i<0 || i>=SBtotal || scrollbars[i]==null) return; scrollbars[i].setVisible(false); } public synchronized void adjustmentValueChanged(AdjustmentEvent e) { for (int i=0; i= MAX_ITEMS) { IJ.log(" cannot add another button, have maxed out at: "+butIndex); return; } buttons[butIndex] = new Button(text); buttons[butIndex].addActionListener(this); buttons[butIndex].addKeyListener(this); // for scrollbar keyboard control buttons[butIndex].addFocusListener(this); // to enable focus control c.gridwidth = 1; c.gridx = x; c.gridy = y; // WO 2/2/11 was c.gridx=0 c.weightx = 1; c.anchor = GridBagConstraints.WEST; if (location == CENTER) c.anchor = GridBagConstraints.CENTER; c.insets = new Insets(5, (x==0)?0:5, 5, 0); // top,left,bot,right c.fill = GridBagConstraints.NONE; grid.setConstraints(buttons[butIndex], c); activePanel.add(buttons[butIndex]); buttons_touched[butIndex] = false; butIndex++; butTot = butIndex; if (activePanel == this) { x=0; y++; } // WO prev: y++; else x++; // WO added } /** adds 2(3,4) buttons in a row to the dialog window. * Easily extendable to add more buttons */ public void addButtons(String text1, String text2) { Panel butPanel = new Panel(); GridBagLayout butGrid = new GridBagLayout(); butPanel.setLayout(butGrid); addButtonToPanel(text1, butPanel, butGrid, 0); addButtonToPanel(text2, butPanel, butGrid, 1); c.gridwidth = 2; c.gridx = 0; c.gridy = y; c.anchor = GridBagConstraints.WEST; c.insets = new Insets(5, 5, 5, 5); // top,left,bot,right grid.setConstraints(butPanel, c); activePanel.add(butPanel); y++; } public void addButtons(String text1, String text2, String text3) { Panel butPanel = new Panel(); GridBagLayout butGrid = new GridBagLayout(); butPanel.setLayout(butGrid); addButtonToPanel(text1, butPanel, butGrid, 0); // label, panel, row in grid addButtonToPanel(text2, butPanel, butGrid, 1); addButtonToPanel(text3, butPanel, butGrid, 2); c.gridwidth = 2; c.gridx = 0; c.gridy = y; c.anchor = GridBagConstraints.WEST; c.insets = new Insets(5, (x==0)?0:5, 5, 0); // top,left,bot,right grid.setConstraints(butPanel, c); activePanel.add(butPanel); y++; } public void addButtons(String text1, String text2, String text3, String text4){ Panel butPanel = new Panel(); GridBagLayout butGrid = new GridBagLayout(); butPanel.setLayout(butGrid); addButtonToPanel(text1, butPanel, butGrid, 0); // label, panel, row in grid addButtonToPanel(text2, butPanel, butGrid, 1); addButtonToPanel(text3, butPanel, butGrid, 2); addButtonToPanel(text4, butPanel, butGrid, 3); c.gridwidth = 2; c.gridx = 0; c.gridy = y; c.anchor = GridBagConstraints.WEST; c.insets = new Insets(5, (x==0)?0:5, 5, 0); // top,left,bot,right grid.setConstraints(butPanel, c); activePanel.add(butPanel); y++; } public void addButtons(String text1, String text2, String text3, String text4, String text5){ Panel butPanel = new Panel(); GridBagLayout butGrid = new GridBagLayout(); butPanel.setLayout(butGrid); addButtonToPanel(text1, butPanel, butGrid, 0); // label, panel, row in grid addButtonToPanel(text2, butPanel, butGrid, 1); addButtonToPanel(text3, butPanel, butGrid, 2); addButtonToPanel(text4, butPanel, butGrid, 3); addButtonToPanel(text5, butPanel, butGrid, 4); c.gridwidth = 3; c.gridx = 0; c.gridy = y; c.anchor = GridBagConstraints.WEST; c.insets = new Insets(5, (x==0)?0:5, 5, 0); // top,left,bot,right grid.setConstraints(butPanel, c); activePanel.add(butPanel); y++; } public void addButtonToPanel(String text, Panel panel, GridBagLayout grid, int row) { if (butIndex >= MAX_ITEMS) { IJ.log(" cannot add another button, have maxed out at: "+butIndex); return; } GridBagConstraints butc = new GridBagConstraints(); buttons[butIndex] = new Button(text); buttons[butIndex].addActionListener(this); buttons[butIndex].addKeyListener(this); butc.gridx = row; butc.gridy = 0; butc.anchor = GridBagConstraints.WEST; c.insets = new Insets(5, (x==0)?0:5, 5, 0); // top,left,bot,right grid.setConstraints(buttons[butIndex], butc); panel.add(buttons[butIndex]); buttons_touched[butIndex] = false; butIndex++; butTot = butIndex; } /** Returns the contents of the next buttons_touched field. */ public boolean getNextButton() { if (butIndex>=butTot) return false; if (buttons_touched[butIndex]) { buttons_touched[butIndex++] = false; return true; } butIndex++; return false; // else } /** Returns the contents of button 'i' field. */ public boolean getButtonValue(int i) { if (i<0 || i>=butTot) return false; else if (!buttons_touched[i]) return false; buttons_touched[i] = false; // reset vale to false return true; // else } public void setButtonLabel(int i, String newlabel) { if (i<0 || i>=butTot) return; buttons[i].setLabel(newlabel); } public void addCanvas(Canvas can) { addCanvas(can, WEST); } public void addCanvas(Canvas can, int location) { c.gridwidth = 2; c.gridx = 0; c.gridy = y; c.weightx = 1; // need weight to anchor something c.anchor = GridBagConstraints.WEST; c.fill = GridBagConstraints.BOTH; if (location == CENTER) c.anchor = GridBagConstraints.CENTER; if (location == EAST) c.anchor = GridBagConstraints.EAST; c.insets = new Insets(10, 10, 0, 10); grid.setConstraints(can, c); activePanel.add(can); y++; } public void addChoice(String label, String[] items, String defaultItem, int location) { c.weightx = 1; // WO default=0; need = 1 to set alignments EAST/WEST, else centers all c.fill = GridBagConstraints.NONE; c.anchor = GridBagConstraints.EAST; if (location == CENTER) c.anchor = GridBagConstraints.CENTER; if (location == WEST) c.anchor = GridBagConstraints.WEST; // WO 2/26/21013: problem that inside teh addChoice below it resets the anchor, so overwrites // the settings above. addChoice(label, items, defaultItem); // in GenericDialog2 class } } /** Walter O'Dell PhD, wodell@rochester.edu, 11/6/02 * alterations from original GenericDialog class in ImageJ v1.28 : * changed global variable attributes from 'private' to 'protected' * for variables: (Buttons) cancel, okay; * (boolean) wasCanceled, macro * (int) y, nfIndex, sfIndex, cbIndex, choiceIndex * (GridBagLayout) grid * (GridBagConstraints) c * added variables: (Container) activePanel * (int) x; // height location of object in panel * * all changes within the code are denoted with "// WO " and are associated * with settings of the 'activePanel' and 'x' variables. These variables are * needed to implement having multiple objects occupying the same height * location within the dialog window -- a string of objects across the panel * ** This class is a customizable modal dialog box. */ class GenericDialog2 extends Dialog implements ActionListener, TextListener, FocusListener, ItemListener, KeyListener { protected Vector defaultValues,defaultText,numberField,stringField,checkbox,choice; protected Component theLabel; protected Label[] Messages; int messageAt, nMessages; static int MaxMSGs = 50; protected TextArea textArea1,textArea2; // WO 4/26/02 changed all from 'private' to 'protected' protected Button cancel, okay; protected boolean wasCanceled; protected int x; // WO added protected int y; protected int nfIndex, sfIndex, cbIndex, choiceIndex; protected GridBagLayout grid; protected GridBagConstraints c; private boolean firstNumericField=true; private boolean invalidNumber; private boolean firstPaint = true; protected Hashtable labels; protected boolean macro; protected String macroOptions; protected Container activePanel; // WO added /** Creates a new GenericDialog with the specified title. Uses the current image image window as the parent frame or the ImageJ frame if no image windows are open. Dialog parameters are recorded by ImageJ's command recorder but this requires that the first word of each label be unique. */ public GenericDialog2(String title) { this(title, WindowManager.getCurrentImage()!=null? (Frame)WindowManager.getCurrentImage().getWindow():IJ.getInstance()); } /** Creates a new GenericDialog using the specified title and parent frame. */ public GenericDialog2(String title, Frame parent) { super(parent, title, true); grid = new GridBagLayout(); c = new GridBagConstraints(); setLayout(grid); macroOptions = Macro.getOptions(); macro = macroOptions!=null; addKeyListener(this); activePanel = this; // WO added } //void showFields(String id) { // String s = id+": "; // for (int i=0; i=labels.length) break; index[i1] = i2; Checkbox cb = new Checkbox(labels[i1]); checkbox.addElement(cb); cb.setState(defaultValues[i1]); if (Recorder.record || macro) saveLabel(cb, labels[i1]); panel.add(cb); i1++; } } c.gridx = x; // WO prev: c.gridx = 0; c.gridy = y; c.gridwidth = 2; c.anchor = GridBagConstraints.WEST; c.insets = new Insets(10, 0, 0, 0); grid.setConstraints(panel, c); activePanel.add(panel); // WO prev: add(panel); if (activePanel == this) { x=0; y++; } // WO added else x++; // WO prev: y++; } public void disableCheckbox(int cbindex) { // turn off checkbox, give focus in window to next item Checkbox cb = (Checkbox)(checkbox.elementAt(cbIndex)); cb.setEnabled(false); } public void enableCheckbox(int cbindex) { Checkbox cb = (Checkbox)(checkbox.elementAt(cbIndex)); cb.setEnabled(true); } /** Adds a popup menu of choices.
WO 2/26/2013 created a choicePalen to hold the label + choice widgets to ensure left alignment * @param label the label * @param items the menu items * @param defaultItem the menu item initially selected */ public void addChoice(String label, String[] items, String defaultItem) { Panel choicePanel = new Panel(); Label theLabel = makeLabel(label); c.gridx = x; // WO prev: c.gridx = 0; c.gridy = y; c.anchor = GridBagConstraints.WEST; // WO 2/26/2013 was EAST. But setting this here nullifies the // version of addChoice above where you can specify the location. c.gridwidth = 1; if (choice==null) { choice = new Vector(4); c.insets = new Insets(5, 0, 5, 0); } else c.insets = new Insets(0, 0, 5, 0); grid.setConstraints(choicePanel, c); // activePanel.add(theLabel); // WO prev: add(theLabel); choicePanel.add(theLabel); // WO prev: add(theLabel); Choice thisChoice = new Choice(); thisChoice.addKeyListener(this); thisChoice.addItemListener(this); for (int i=0; i= MaxMSGs) { Label[] tmpLabels = new Label[MaxMSGs+50+1]; for (int i=0; i=0) // Messages[nMessages-1] = new MultiLineLabel(text); // else Messages[nMessages-1] = new Label(text); //theLabel.addKeyListener(this); c.gridx = x; // WO prev: = 0; c.gridy = y; c.gridwidth = 1; c.anchor = GridBagConstraints.WEST; int leftspacing = 5; if (x==0) leftspacing =0; c.insets = new Insets(5, text.equals("")?leftspacing:10, 5, 0); // top,left,bot,right grid.setConstraints(Messages[nMessages-1], c); activePanel.add(Messages[nMessages-1]); // WO prev: add(theLabel); if (activePanel == this) { x=0; y++; } // WO added else x++; // WO prev: y++; } public void setMessage(int i, String newmsg) { if (i<0) i=0; if (i>=nMessages) i=nMessages-1; Messages[i].setText(newmsg); } /** Adds one or two (side by side) text areas. * @param text1 initial contents of the first text area * @param text2 initial contents of the second text area or null * @param rows the number of rows * @param columns the number of columns */ public void addTextAreas(String text1, String text2, int rows, int columns) { if (textArea1!=null) return; Panel panel = new Panel(); textArea1 = new TextArea(text1,rows,columns,TextArea.SCROLLBARS_NONE); //textArea1.append(text1); panel.add(textArea1); if (text2!=null) { textArea2 = new TextArea(text2,rows,columns,TextArea.SCROLLBARS_NONE); //textArea2.append(text2); panel.add(textArea2); } c.gridx = x; // WO prev: = 0; c.gridy = y; c.gridwidth = 2; c.anchor = GridBagConstraints.WEST; c.insets = new Insets(15, 20, 0, 0); grid.setConstraints(panel, c); activePanel.add(panel); // WO prev: add(panel); if (activePanel == this) { x=0; y++; } // WO added else x++; // WO prev: y++; } /** Returns true if the user clicks on "Cancel". */ public boolean wasCanceled() { if (wasCanceled) Macro.abort(); return wasCanceled; } // WO 9/27/10 invoke/emulate cancel */ public void Cancel() { wasCanceled = true; setVisible(false); dispose(); Macro.abort(); } // WO 5/18/09 set the value in the selected numeric field to 'value' public void setNumericField(int nfIndex, float value) { if (numberField==null) return; TextField tf = (TextField) numberField.elementAt(nfIndex); tf.setText(String.valueOf(value)); } /** Returns the contents of the next numeric field. */ public double getNextNumber() { if (numberField==null) return -1.0; TextField tf = (TextField)numberField.elementAt(nfIndex); String theText = tf.getText(); if (macro) { String label = (String)labels.get((Object)tf); theText = Macro.getValue(macroOptions, label, theText); //IJ.log("getNextNumber: "+label+" "+theText); } String originalText = (String)defaultText.elementAt(nfIndex); double defaultValue = ((Double)(defaultValues.elementAt(nfIndex))).doubleValue(); double value; if (theText.equals(originalText)) value = defaultValue; else { Double d = getValue(theText); if (d!=null) value = d.doubleValue(); else { invalidNumber = true; value = 0.0; } } if (Recorder.record) recordOption(tf, trim(theText)); nfIndex++; return value; } private String trim(String value) { if (value.endsWith(".0")) value = value.substring(0, value.length()-2); if (value.endsWith(".00")) value = value.substring(0, value.length()-3); return value; } private void recordOption(Component component, String value) { String label = (String)labels.get((Object)component); Recorder.recordOption(label, value); } private void recordCheckboxOption(Checkbox cb) { String label = (String)labels.get((Object)cb); if (cb.getState() && label!=null) Recorder.recordOption(label); } protected Double getValue(String theText) { Double d; try {d = new Double(theText);} catch (NumberFormatException e){ d = null; } return d; } /** Returns true if one or more of the numeric fields contained an invalid number. */ public boolean invalidNumber() { boolean wasInvalid = invalidNumber; invalidNumber = false; return wasInvalid; } /** WO 5/18/09 set the value in the selected stringField (sfIndex, ordered 0..N-1) to the 'value' */ public void setStringField(int sfIndex, String value) { if (stringField==null) return; TextField tf = (TextField)(stringField.elementAt(sfIndex)); tf.setText(value); } /** Returns the contents of the next text field. */ public String getNextString() { String theText; if (stringField==null) return ""; TextField tf = (TextField)(stringField.elementAt(sfIndex)); theText = tf.getText(); if (macro) { String label = (String)labels.get((Object)tf); theText = Macro.getValue(macroOptions, label, theText); //IJ.log("getNextString: "+label+" "+theText); } if (Recorder.record) recordOption(tf, theText); sfIndex++; return theText; } /** Returns the state of the next checkbox. */ public boolean getNextBoolean() { if (checkbox==null) return false; Checkbox cb = (Checkbox)(checkbox.elementAt(cbIndex)); if (Recorder.record) recordCheckboxOption(cb); boolean state = cb.getState(); if (macro) { String label = (String)labels.get((Object)cb); String key = Macro.trimKey(label); state = macroOptions.indexOf(key+" ")>=0; //IJ.log("getNextBoolean: "+label+" "+state); } cbIndex++; return state; } /** WO 9/25/07 set the active item in the selected choice to the itemAt. indexed 0..N-1 */ public void setChoice(int choiceIndex, int itemAt) { if (choice==null) return; Choice thisChoice = (Choice)(choice.elementAt(choiceIndex)); thisChoice.select(itemAt); } /** WO 2/3/11 repopulate the choice values */ public void repopulateChoice(int choiceIndex, String[] newitems) { if (choice==null) return; Choice thisChoice = (Choice)(choice.elementAt(choiceIndex)); int prevNitems = thisChoice.getItemCount(); // IJ.log(" in repop choice .. nchoices "+prevNitems); for (int i=0; i