package bsearch.app; import java.awt.BorderLayout; import java.awt.FlowLayout; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.File; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JFileChooser; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JSpinner; import javax.swing.JTextField; import javax.swing.SpinnerNumberModel; import org.nlogo.util.MersenneTwisterFast; public class RunOptionsDialog extends javax.swing.JDialog { private static final long serialVersionUID = 1L; private JPanel jPanelNorth; private JPanel jPanelSouth; private JButton jButtonCancel; private JLabel jLabelNumSearches; private JSpinner jSpinnerThreads; private JLabel jLabelThreads; private JSpinner jSpinnerNumSearches; private JPanel jPanelCenter; private JButton jButtonStartSearch; private boolean dialogCanceled = true; private JCheckBox jCheckBoxBriefOutput; private JButton jButtonNewSeed; private JPanel jPanel1; private JSpinner jSpinnerFirstSearchNumber; private JLabel jLabelFirstSearchNumber; private JSpinner jSpinnerRandomSeed; private JLabel jLabelRandomSeed; private JButton jButtonBrowseStem; private JTextField jTextFieldOutputStem; private JLabel jLabelOutputStem; public RunOptionsDialog(JFrame frame, BehaviorSearch.RunOptions runOptions) { super(frame, "Choose experiment running options"); { jPanelNorth = new JPanel(); BorderLayout jPanelNorthLayout = new BorderLayout(); jPanelNorth.setLayout(jPanelNorthLayout); getContentPane().add(jPanelNorth, BorderLayout.NORTH); { jLabelOutputStem = new JLabel(); jPanelNorth.add(jLabelOutputStem, BorderLayout.WEST); jLabelOutputStem.setText("Output file stem: "); jLabelOutputStem.setFont(new java.awt.Font("Dialog",1,12)); } { jTextFieldOutputStem = new JTextField(); jPanelNorth.add(jTextFieldOutputStem, BorderLayout.CENTER); jTextFieldOutputStem.setText("/path/to/some/filename/stem"); jTextFieldOutputStem.setToolTipText("All of the output files will start with the same filename \"stem\" (e.g. MYSTEM.bestHistory.csv, MYSTEM.finalBests.csv)"); } { jButtonBrowseStem = new JButton(); jPanelNorth.add(jButtonBrowseStem, BorderLayout.EAST); jButtonBrowseStem.setText("Browse..."); jButtonBrowseStem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { JFileChooser chooser = new JFileChooser("./experiments/"); chooser.setSelectedFile(new File(jTextFieldOutputStem.getText())); int returnVal = chooser.showSaveDialog(RunOptionsDialog.this); if(returnVal == JFileChooser.APPROVE_OPTION) { jTextFieldOutputStem.setText(chooser.getSelectedFile().getPath()); } } }); } jPanelNorth.setPreferredSize(new java.awt.Dimension(190, 35)); } { jPanelSouth = new JPanel(); FlowLayout jPanelSouthLayout = new FlowLayout(); jPanelSouthLayout.setAlignment(FlowLayout.RIGHT); jPanelSouth.setLayout(jPanelSouthLayout); getContentPane().add(jPanelSouth, BorderLayout.SOUTH); jPanelSouth.setPreferredSize(new java.awt.Dimension(190, 35)); { jButtonStartSearch = new JButton("Start Search"); jPanelSouth.add(jButtonStartSearch); jButtonStartSearch.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent arg0) { dialogCanceled = false; setVisible(false); } }); } { jButtonCancel = new JButton(); jPanelSouth.add(jButtonCancel); jButtonCancel.setText("Cancel"); jButtonCancel.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent arg0) { setVisible(false); } }); } } { jPanelCenter = new JPanel(); getContentPane().add(jPanelCenter, BorderLayout.CENTER); GridBagLayout jPanel2Layout = new GridBagLayout(); jPanel2Layout.columnWidths = new int[] {7, 7}; jPanel2Layout.rowHeights = new int[] {7, 7, 7, 7, 7}; jPanel2Layout.columnWeights = new double[] {0.1, 0.1}; jPanel2Layout.rowWeights = new double[] {0.1, 0.1, 0.1, 0.1, 0.1}; jPanelCenter.setLayout(jPanel2Layout); { jLabelNumSearches = new JLabel(); jPanelCenter.add(jLabelNumSearches, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0)); jLabelNumSearches.setText("Number of searches:"); jLabelNumSearches.setFont(new java.awt.Font("Dialog",1,12)); } { SpinnerNumberModel jSpinnerNumSearchesModel = new SpinnerNumberModel(1,1,10000,1); jSpinnerNumSearches = new JSpinner(); jPanelCenter.add(jSpinnerNumSearches, new GridBagConstraints(1, 0, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 10, 0, 0), 0, 0)); jSpinnerNumSearches.setModel(jSpinnerNumSearchesModel); jSpinnerNumSearches.setToolTipText("How many times should this search be repeated?"); } { jLabelThreads = new JLabel(); jPanelCenter.add(jLabelThreads, new GridBagConstraints(0, 3, 1, 1, 0.0, 0.0, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0)); jLabelThreads.setText("Number of threads:"); jLabelThreads.setToolTipText("(only affects search time performance, not search results)"); jLabelThreads.setFont(new java.awt.Font("SansSerif",1,12)); } { SpinnerNumberModel jSpinnerThreadsModel = new SpinnerNumberModel(1,1,32,1); jSpinnerThreads = new JSpinner(); jPanelCenter.add(jSpinnerThreads, new GridBagConstraints(1, 3, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 10, 0, 0), 0, 0)); jSpinnerThreads.setModel(jSpinnerThreadsModel); jSpinnerThreads.setToolTipText("(only affects search time performance, not search results)"); } { jLabelRandomSeed = new JLabel(); jPanelCenter.add(jLabelRandomSeed, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0)); jLabelRandomSeed.setText("Initial random seed:"); jLabelRandomSeed.setFont(new java.awt.Font("SansSerif",1,12)); } { jPanel1 = new JPanel(); BorderLayout jPanel1Layout = new BorderLayout(); jPanel1.setLayout(jPanel1Layout); jPanelCenter.add(jPanel1, new GridBagConstraints(1, 2, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 10, 0, 0), 0, 0)); { SpinnerNumberModel jSpinnerRandomSeedModel = new SpinnerNumberModel(1,Integer.MIN_VALUE,Integer.MAX_VALUE,1); jSpinnerRandomSeed = new JSpinner(); jPanel1.add(jSpinnerRandomSeed, BorderLayout.CENTER); jSpinnerRandomSeed.setModel(jSpinnerRandomSeedModel); jSpinnerRandomSeed.setToolTipText("random seed to be used for the first search (additional searches will be seeded with following consecutive numbers)"); } { jButtonNewSeed = new JButton(); jPanel1.add(jButtonNewSeed, BorderLayout.EAST); jButtonNewSeed.setText("New"); jButtonNewSeed.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { jSpinnerRandomSeed.setValue(new MersenneTwisterFast().nextInt()); } }); } } { jLabelFirstSearchNumber = new JLabel(); jPanelCenter.add(jLabelFirstSearchNumber, new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0)); jLabelFirstSearchNumber.setText("Starting at search ID:"); jLabelFirstSearchNumber.setFont(new java.awt.Font("Dialog",1,12)); } { SpinnerNumberModel jSpinnerFirstSearchNumberModel = new SpinnerNumberModel(1,0,10000,1); jSpinnerFirstSearchNumber = new JSpinner(); jPanelCenter.add(jSpinnerFirstSearchNumber, new GridBagConstraints(1, 1, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 10, 0, 0), 0, 0)); jSpinnerFirstSearchNumber.setModel(jSpinnerFirstSearchNumberModel); jSpinnerFirstSearchNumber.setToolTipText("What number should the \"search ID\" numbers start at, in the output files?"); } { jCheckBoxBriefOutput = new JCheckBox(); jPanelCenter.add(jCheckBoxBriefOutput, new GridBagConstraints(1, 4, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0)); jCheckBoxBriefOutput.setText("Brief Output?"); jCheckBoxBriefOutput.setToolTipText("Do not create the two largest files, with ALL of the model run and objective function data."); jCheckBoxBriefOutput.setFont(new java.awt.Font("Dialog",1,12)); } } // make sure the OK button always gets focus, so it's easy to close the help dialog. this.addWindowFocusListener(new java.awt.event.WindowAdapter() { @Override public void windowGainedFocus(java.awt.event.WindowEvent e) { jButtonStartSearch.requestFocusInWindow(); } }); init(runOptions); this.setPreferredSize(new java.awt.Dimension(600,280)); this.pack(); // size the window based on the textpane's contents } /////////////////////////////////////////////////////////////////////////////////////////////// //the special comment on the next line marks the remaining code so the Jigloo gui builder won't try to parse it. //$hide>>$ public void init(BehaviorSearch.RunOptions runOptions) { jTextFieldOutputStem.setText(runOptions.outputStem); jSpinnerNumSearches.setValue(runOptions.numSearches); jSpinnerFirstSearchNumber.setValue(runOptions.firstSearchNumber); jSpinnerThreads.setValue(runOptions.numThreads); jSpinnerRandomSeed.setValue(runOptions.randomSeed.intValue()); jCheckBoxBriefOutput.setSelected(runOptions.briefOutput); } public void updateOptions(BehaviorSearch.RunOptions runOptions) { //TODO: input validation for this dialog, and don't let them press OK to close unless it's valid. runOptions.outputStem = jTextFieldOutputStem.getText(); runOptions.numSearches = (Integer) jSpinnerNumSearches.getValue(); runOptions.firstSearchNumber = (Integer) jSpinnerFirstSearchNumber.getValue(); runOptions.numThreads = (Integer) jSpinnerThreads.getValue(); runOptions.randomSeed = (Integer) jSpinnerRandomSeed.getValue(); runOptions.briefOutput = jCheckBoxBriefOutput.isSelected(); } /** * @param parent - parent Frame * @param runOptions - search options object, which will be modified by this dialog * @return true if OK was pressed, false if dialog was canceled. */ public static boolean showDialog(JFrame parent, BehaviorSearch.RunOptions runOptions) { //TODO: make GUI options for shortened output, and suppressing all model results... //TODO: make the GENERATE-random-seed button! RunOptionsDialog dialog = new RunOptionsDialog(parent, runOptions); dialog.setLocationRelativeTo(null); dialog.setModalityType(ModalityType.APPLICATION_MODAL); dialog.setVisible(true); if (dialog.dialogCanceled) { return false; } dialog.updateOptions(runOptions); return true; } //$hide<<$ }