Clover coverage report - DrJava Test Coverage (drjava-20120304-r5456)
Coverage timestamp: Sun Mar 4 2012 03:13:23 CST
file stats: LOC: 1,089   Methods: 67
NCLOC: 825   Classes: 2
 
 Source file Conditionals Statements Methods TOTAL
ExecuteExternalDialog.java 14.9% 49.8% 23.9% 42.1%
coverage coverage
 1    /*BEGIN_COPYRIGHT_BLOCK
 2    *
 3    * Copyright (c) 2001-2010, JavaPLT group at Rice University (javaplt@rice.edu)
 4    * All rights reserved.
 5    *
 6    * Redistribution and use in source and binary forms, with or without
 7    * modification, are permitted provided that the following conditions are met:
 8    * * Redistributions of source code must retain the above copyright
 9    * notice, this list of conditions and the following disclaimer.
 10    * * Redistributions in binary form must reproduce the above copyright
 11    * notice, this list of conditions and the following disclaimer in the
 12    * documentation and/or other materials provided with the distribution.
 13    * * Neither the names of DrJava, the JavaPLT group, Rice University, nor the
 14    * names of its contributors may be used to endorse or promote products
 15    * derived from this software without specific prior written permission.
 16    *
 17    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 18    * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 19    * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 20    * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 21    * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 22    * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 23    * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 24    * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 25    * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 26    * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 27    * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 28    *
 29    * This software is Open Source Initiative approved Open Source Software.
 30    * Open Source Initative Approved is a trademark of the Open Source Initiative.
 31    *
 32    * This file is part of DrJava. Download the current version of this project
 33    * from http://www.drjava.org/ or http://sourceforge.net/projects/drjava/
 34    *
 35    * END_COPYRIGHT_BLOCK*/
 36   
 37    package edu.rice.cs.drjava.ui;
 38   
 39    import edu.rice.cs.drjava.DrJava;
 40    import edu.rice.cs.drjava.config.OptionConstants;
 41    import edu.rice.cs.drjava.config.PropertyMaps;
 42    import edu.rice.cs.drjava.config.*;
 43   
 44    import edu.rice.cs.plt.lambda.Runnable1;
 45    import edu.rice.cs.plt.lambda.LambdaUtil;
 46    import edu.rice.cs.plt.concurrent.CompletionMonitor;
 47    import edu.rice.cs.util.BalancingStreamTokenizer;
 48    import edu.rice.cs.util.ProcessCreator;
 49    import edu.rice.cs.util.GeneralProcessCreator;
 50    import edu.rice.cs.util.StringOps;
 51    import edu.rice.cs.util.XMLConfig;
 52    import edu.rice.cs.util.swing.DirectoryChooser;
 53    import edu.rice.cs.util.swing.FileChooser;
 54    import edu.rice.cs.util.swing.SwingFrame;
 55    import edu.rice.cs.util.swing.Utilities;
 56   
 57    import java.awt.*;
 58    import java.awt.event.*;
 59    import java.io.File;
 60    import java.io.IOException;
 61    import java.io.StringReader;
 62    import java.util.*;
 63    import javax.swing.*;
 64    import javax.swing.border.EmptyBorder;
 65    import javax.swing.event.*;
 66    import javax.swing.text.*;
 67   
 68    public class ExecuteExternalDialog extends SwingFrame implements OptionConstants {
 69    private static final int FRAME_WIDTH = 750;
 70    private static final int FRAME_HEIGHT = 500;
 71   
 72    /** Class to save the frame state, i.e. location. */
 73    public static class FrameState {
 74    private Point _loc;
 75  0 public FrameState(Point l) {
 76  0 _loc = l;
 77    }
 78  38 public FrameState(String s) {
 79  38 StringTokenizer tok = new StringTokenizer(s);
 80  38 try {
 81  38 int x = Integer.valueOf(tok.nextToken());
 82  0 int y = Integer.valueOf(tok.nextToken());
 83  0 _loc = new Point(x, y);
 84    }
 85    catch(NoSuchElementException nsee) {
 86  0 throw new IllegalArgumentException("Wrong FrameState string: " + nsee);
 87    }
 88    catch(NumberFormatException nfe) {
 89  38 throw new IllegalArgumentException("Wrong FrameState string: " + nfe);
 90    }
 91    }
 92  0 public FrameState(ExecuteExternalDialog comp) {
 93  0 _loc = comp.getLocation();
 94    }
 95  0 public String toString() {
 96  0 final StringBuilder sb = new StringBuilder();
 97  0 sb.append(_loc.x);
 98  0 sb.append(' ');
 99  0 sb.append(_loc.y);
 100  0 return sb.toString();
 101    }
 102  0 public Point getLocation() { return _loc; }
 103    }
 104   
 105    /** Run Command button. */
 106    private JButton _runCommandButton;
 107    /** Save Command button. */
 108    private JButton _saveCommandButton;
 109    /** Insert Command button. */
 110    private JButton _insertCommandButton;
 111    /** Cancel Command button. */
 112    private JButton _cancelCommandButton;
 113    /** Entered command line. */
 114    private JTextPane _commandLine;
 115    /** Command line preview label. */
 116    private JLabel _commandLinePreviewLabel;
 117    /** Command line preview. */
 118    private JTextPane _commandLinePreview;
 119    /** Command line preview document. */
 120    private StyledDocument _commandLineDoc;
 121    /** Entered command line working directory. */
 122    private JTextPane _commandWorkDirLine;
 123    /** Command line working directory preview. */
 124    private JTextPane _commandWorkDirLinePreview;
 125    /** Command line working directory preview document. */
 126    private StyledDocument _commandWorkDirLineDoc;
 127    /** Command working directory button. */
 128    private JButton _commandWorkDirBtn;
 129    /** Entered command line enclosing file. */
 130    private JTextPane _commandEnclosingFileLine;
 131    /** Command line enclosing file preview. */
 132    private JTextPane _commandEnclosingFileLinePreview;
 133    /** Command line enclosing file preview document. */
 134    private StyledDocument _commandEnclosingFileLineDoc;
 135    /** Command enclosing file button. */
 136    private JButton _commandEnclosingFileBtn;
 137    /** Last of the two text panes to have focus. */
 138    private JTextPane _lastCommandFocus;
 139   
 140    /** Style for variable the executable part. */
 141    SimpleAttributeSet _varCommandLineCmdStyle;
 142    /** Style for erroneous variable the command args part. */
 143    SimpleAttributeSet _varErrorCommandLineCmdStyle;
 144    /** Style for normal text */
 145    SimpleAttributeSet _commandLineCmdAS;
 146   
 147    /** Command line panel. */
 148    JPanel _commandPanel;
 149    /** Command line document listener. */
 150    DocumentListener _documentListener;
 151    /** Command line work directory document listener. */
 152    DocumentListener _workDirDocumentListener;
 153    /** Command line enclosing file document listener. */
 154    DocumentListener _enclosingFileDocumentListener;
 155   
 156    /** Directory chooser to open when clicking the "..." button. */
 157    protected DirectoryChooser _dirChooser;
 158    /** File chooser to open when clicking the "..." button. */
 159    protected FileChooser _fileChooser;
 160   
 161    /** Dialog to insert variables. */
 162    protected InsertVariableDialog _insertVarDialog;
 163   
 164    /** Completion monitor to simulate modal behavior. */
 165    protected CompletionMonitor _insertVarDialogMonitor = new CompletionMonitor();
 166   
 167    /** Completion monitor to tell the calling dialog that we're done. Only used if _editMode is true. */
 168    private CompletionMonitor _cm;
 169   
 170    /** Main frame. */
 171    protected MainFrame _mainFrame;
 172    /** Last frame state. It can be stored and restored. */
 173    protected FrameState _lastState = null;
 174   
 175    /** Edit mode if true. */
 176    protected boolean _editMode = false;
 177   
 178    /** Index of the saved external process being edited if _editMode is true. */
 179    protected int _editIndex = -1;
 180   
 181    /** PropertyMaps used for substitution when replacing variables. */
 182    protected PropertyMaps _props;
 183   
 184    public static final String STALE_TOOLTIP = "<html>Note: Values of variables might not be current for<br>" +
 185    "performance reasons. They will be current when executed.</html>";
 186   
 187    /** Returns the last state of the frame, i.e. the location and dimension.
 188    * @return frame state
 189    */
 190  0 public FrameState getFrameState() { return _lastState; }
 191   
 192    /** Sets state of the frame, i.e. the location and dimension of the frame for the next use.
 193    * @param ds State to update to, or {@code null} to reset
 194    */
 195  0 public void setFrameState(FrameState ds) {
 196  0 _lastState = ds;
 197  0 if (_lastState != null) {
 198  0 setLocation(_lastState.getLocation());
 199  0 validate();
 200    }
 201    }
 202   
 203    /** Sets state of the frame, i.e. the location and dimension of the frame for the next use.
 204    * @param s State to update to, or {@code null} to reset
 205    */
 206  38 public void setFrameState(String s) {
 207  38 try { _lastState = new FrameState(s); }
 208  38 catch(IllegalArgumentException e) { _lastState = null; }
 209  0 if (_lastState != null) setLocation(_lastState.getLocation());
 210  38 else Utilities.setPopupLoc(this, _mainFrame);
 211  38 validate();
 212    }
 213   
 214    /** Create a dialog.
 215    * @param mf the instance of mainframe to query into the project
 216    * @param editMode true if a saved external process is edited
 217    * @param editIndex index of the saved external processes to edit
 218    * @param cm completion monitor telling the calling dialog that we are done
 219    */
 220  38 public ExecuteExternalDialog(MainFrame mf, boolean editMode, int editIndex, CompletionMonitor cm) {
 221  38 super("Execute External Process");
 222  38 try { _props = PropertyMaps.TEMPLATE.clone(); } catch(CloneNotSupportedException e) {
 223  0 throw new edu.rice.cs.util.UnexpectedException(e);
 224    }
 225  38 _mainFrame = mf;
 226  38 _editMode = editMode;
 227  38 _editIndex = editIndex;
 228  38 _cm = cm;
 229  38 initComponents();
 230  38 if (editMode) {
 231  0 if (editIndex>=DrJava.getConfig().getSetting(OptionConstants.EXTERNAL_SAVED_COUNT)) {
 232  0 throw new IllegalArgumentException("Trying to edit saved external process that does not exist");
 233    }
 234  0 final String cmdline = DrJava.getConfig().getSetting(OptionConstants.EXTERNAL_SAVED_CMDLINES).get(editIndex);
 235  0 final String workdir = DrJava.getConfig().getSetting(OptionConstants.EXTERNAL_SAVED_WORKDIRS).get(editIndex);
 236  0 final String enclosingFile =
 237    DrJava.getConfig().getSetting(OptionConstants.EXTERNAL_SAVED_ENCLOSING_DJAPP_FILES).get(editIndex);
 238  0 _commandLine.setText(cmdline);
 239  0 _commandWorkDirLine.setText(workdir);
 240  0 _commandEnclosingFileLine.setText(enclosingFile);
 241    }
 242  38 initDone(); // call mandated by SwingFrame contract
 243    }
 244   
 245    /** Create a dialog with the "Run" button.
 246    * @param mf the instance of mainframe to query into the project
 247    */
 248  38 public ExecuteExternalDialog(MainFrame mf) {
 249  38 this(mf, false, -1, null);
 250    }
 251   
 252    /** Build the dialog. */
 253  38 private void initComponents() {
 254  38 _dirChooser = new DirectoryChooser(this);
 255  38 _dirChooser.setDialogTitle("Select Work Directory");
 256  38 _dirChooser.setApproveButtonText("Select");
 257  38 _fileChooser = new FileChooser(null);
 258  38 _fileChooser.setDialogTitle("Select Enclosing .djapp File");
 259  38 _fileChooser.setApproveButtonText("Select");
 260   
 261  38 super.getContentPane().setLayout(new GridLayout(1,1));
 262   
 263  38 if (_editMode) {
 264  0 Action saveCommandAction = new AbstractAction("Save") {
 265  0 public void actionPerformed(ActionEvent e) {
 266  0 _saveCommand();
 267    }
 268    };
 269  0 _saveCommandButton = new JButton(saveCommandAction);
 270    }
 271    else {
 272  38 Action runCommandAction = new AbstractAction("Run Command Line") {
 273  0 public void actionPerformed(ActionEvent e) {
 274  0 _runCommand();
 275    }
 276    };
 277  38 _runCommandButton = new JButton(runCommandAction);
 278  38 _runCommandButton.addFocusListener(new FocusAdapter() {
 279  0 public void focusGained(FocusEvent e) {
 280  0 _insertCommandButton.setEnabled(false);
 281    }
 282  0 public void focusLost(FocusEvent e) {
 283  0 if ((e.getOppositeComponent() == _commandLinePreview) ||
 284    (e.getOppositeComponent() == _commandWorkDirLinePreview) ||
 285    (e.getOppositeComponent() == _commandEnclosingFileLinePreview)) {
 286  0 _runCommandButton.requestFocus();
 287    }
 288    }
 289    });
 290   
 291  38 Action saveCommandAction = new AbstractAction("Save to Menu...") {
 292  0 public void actionPerformed(ActionEvent e) {
 293  0 _saveCommand();
 294    }
 295    };
 296  38 _saveCommandButton = new JButton(saveCommandAction);
 297    }
 298   
 299  38 _insertVarDialog = new InsertVariableDialog(_mainFrame, _insertVarDialogMonitor);
 300  38 Action insertCommandAction = new AbstractAction("Insert Variable...") {
 301  0 public void actionPerformed(ActionEvent e) {
 302  0 _insertVariableCommand();
 303    }
 304    };
 305  38 _insertCommandButton = new JButton(insertCommandAction);
 306  38 _insertCommandButton.setEnabled(false);
 307   
 308  38 Action cancelAction = new AbstractAction("Cancel") {
 309  0 public void actionPerformed(ActionEvent e) {
 310  0 _cancel();
 311    }
 312    };
 313  38 _cancelCommandButton = new JButton(cancelAction);
 314   
 315    // set up "Command Line" panel
 316   
 317  38 Utilities.invokeAndWait(new Runnable() {
 318  38 public void run() {
 319  38 _commandPanel = makeCommandPane();
 320   
 321  38 getContentPane().add(_commandPanel);
 322  38 setResizable(false);
 323   
 324  38 setSize(FRAME_WIDTH, FRAME_HEIGHT);
 325  38 Utilities.setPopupLoc(ExecuteExternalDialog.this, _mainFrame);
 326  38 _commandLine.requestFocus();
 327    }
 328    });
 329    }
 330   
 331  38 private JPanel makeCommandPane() {
 332  38 JPanel panel = new JPanel(new BorderLayout());
 333  38 GridBagLayout gridbag = new GridBagLayout();
 334  38 JPanel main = new JPanel(gridbag);
 335  38 GridBagConstraints c = new GridBagConstraints();
 336  38 main.setLayout(gridbag);
 337  38 c.fill = GridBagConstraints.BOTH;
 338  38 Insets labelInsets = new Insets(5, 10, 0, 0);
 339  38 Insets compInsets = new Insets(5, 5, 0, 10);
 340   
 341  38 c.weightx = 0.0;
 342  38 c.weighty = 0.0;
 343  38 c.insets = labelInsets;
 344  38 JLabel commandLineLabel = new JLabel("Command line:");
 345  38 gridbag.setConstraints(commandLineLabel, c);
 346  38 main.add(commandLineLabel);
 347   
 348  38 c.weightx = 1.0;
 349  38 c.weighty = 32.0;
 350  38 c.gridwidth = GridBagConstraints.REMAINDER;
 351  38 c.insets = compInsets;
 352   
 353  38 _commandLine = new JTextPane();
 354    // do not allow a newline
 355  38 _commandLine.addKeyListener(new KeyListener() {
 356  0 public void keyPressed(KeyEvent e) {
 357  0 if (e.getKeyCode() == KeyEvent.VK_ENTER) e.consume();
 358  0 else if (e.getKeyCode() == KeyEvent.VK_TAB) {
 359  0 e.consume();
 360  0 if (e.isShiftDown()) {
 361  0 _insertCommandButton.setEnabled(false);
 362  0 _cancelCommandButton.requestFocus();
 363    }
 364  0 else _commandWorkDirLine.requestFocus();
 365    }
 366    }
 367  0 public void keyReleased(KeyEvent e) { }
 368  0 public void keyTyped(KeyEvent e) { }
 369    });
 370  38 JScrollPane commandLineSP = new JScrollPane(_commandLine);
 371  38 commandLineSP.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED);
 372  38 gridbag.setConstraints(commandLineSP, c);
 373  38 main.add(commandLineSP);
 374   
 375  38 c.weightx = 0.0;
 376  38 c.weighty = 0.0;
 377  38 c.gridwidth = 1;
 378  38 c.insets = labelInsets;
 379  38 _commandLinePreviewLabel = new JLabel("<html>Command line preview:<br>(0 characters)</html>");
 380  38 _commandLinePreviewLabel.setToolTipText(STALE_TOOLTIP);
 381  38 gridbag.setConstraints(_commandLinePreviewLabel, c);
 382  38 main.add(_commandLinePreviewLabel);
 383   
 384  38 c.weightx = 1.0;
 385  38 c.weighty = 32.0;
 386  38 c.gridwidth = GridBagConstraints.REMAINDER;
 387  38 c.insets = compInsets;
 388   
 389  38 _commandLinePreview = new JTextPane();
 390  38 _commandLinePreview.setToolTipText(STALE_TOOLTIP);
 391  38 _commandLineDoc = (StyledDocument)_commandLinePreview.getDocument();
 392   
 393    // Create a style object and then set the style attributes
 394  38 _varCommandLineCmdStyle = new SimpleAttributeSet();
 395  38 StyleConstants.setBackground(_varCommandLineCmdStyle, DrJava.getConfig().getSetting(DEFINITIONS_MATCH_COLOR));
 396   
 397  38 _commandLineCmdAS = new SimpleAttributeSet();
 398  38 StyleConstants.setForeground(_commandLineCmdAS, DrJava.getConfig().getSetting(DEFINITIONS_NORMAL_COLOR));
 399  38 _varCommandLineCmdStyle = new SimpleAttributeSet();
 400  38 StyleConstants.setBackground(_varCommandLineCmdStyle, DrJava.getConfig().getSetting(DEFINITIONS_MATCH_COLOR));
 401  38 _varErrorCommandLineCmdStyle = new SimpleAttributeSet();
 402  38 StyleConstants.setBackground(_varErrorCommandLineCmdStyle, DrJava.getConfig().getSetting(DEBUG_BREAKPOINT_COLOR));
 403  38 _varCommandLineCmdStyle = new SimpleAttributeSet();
 404  38 StyleConstants.setBackground(_varCommandLineCmdStyle, DrJava.getConfig().getSetting(DEFINITIONS_MATCH_COLOR));
 405   
 406  38 _commandLinePreview.setEditable(false);
 407  38 _commandLinePreview.setBackground(Color.LIGHT_GRAY);
 408  38 _commandLinePreview.setSelectedTextColor(Color.LIGHT_GRAY);
 409  38 JScrollPane commandLinePreviewSP = new JScrollPane(_commandLinePreview);
 410  38 commandLinePreviewSP.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED);
 411  38 gridbag.setConstraints(commandLinePreviewSP, c);
 412  38 main.add(commandLinePreviewSP);
 413   
 414    // work directory
 415  38 c.weightx = 0.0;
 416  38 c.weighty = 0.0;
 417  38 c.gridwidth = 1;
 418  38 c.insets = labelInsets;
 419  38 JLabel workDirLabel = new JLabel("Work directory:");
 420  38 gridbag.setConstraints(workDirLabel, c);
 421  38 main.add(workDirLabel);
 422   
 423  38 c.weightx = 1.0;
 424  38 c.weighty = 8.0;
 425  38 c.gridwidth = GridBagConstraints.RELATIVE;
 426  38 c.insets = compInsets;
 427   
 428  38 _commandWorkDirLine = new JTextPane();
 429    // do not allow a newline
 430  38 _commandWorkDirLine.addKeyListener(new KeyListener() {
 431  0 public void keyPressed(KeyEvent e) {
 432  0 if (e.getKeyCode() == KeyEvent.VK_ENTER) e.consume();
 433  0 else if (e.getKeyCode() == KeyEvent.VK_TAB) {
 434  0 e.consume();
 435  0 if (e.isShiftDown()) {
 436  0 _commandLine.requestFocus();
 437    }
 438  0 else _commandEnclosingFileLine.requestFocus();
 439    }
 440    }
 441  0 public void keyReleased(KeyEvent e) { }
 442  0 public void keyTyped(KeyEvent e) { }
 443    });
 444  38 JScrollPane commandWorkDirLineSP = new JScrollPane(_commandWorkDirLine);
 445  38 commandWorkDirLineSP.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED);
 446  38 gridbag.setConstraints(commandWorkDirLineSP, c);
 447  38 main.add(commandWorkDirLineSP);
 448   
 449  38 c.weightx = 0.0;
 450  38 c.weighty = 0.0;
 451  38 c.gridwidth = GridBagConstraints.REMAINDER;
 452  38 c.insets = compInsets;
 453   
 454  38 _commandWorkDirBtn = new JButton("...");
 455  38 _commandWorkDirBtn.addActionListener(new ActionListener() {
 456  0 public void actionPerformed(ActionEvent e) { chooseFile(_commandWorkDirLine); }
 457    });
 458  38 gridbag.setConstraints(_commandWorkDirBtn, c);
 459  38 main.add(_commandWorkDirBtn);
 460   
 461  38 c.weightx = 0.0;
 462  38 c.weighty = 0.0;
 463  38 c.gridwidth = 1;
 464  38 c.insets = labelInsets;
 465  38 JLabel commandWorkDirLinePreviewLabel = new JLabel("Work directory preview:");
 466  38 commandWorkDirLinePreviewLabel.setToolTipText(STALE_TOOLTIP);
 467  38 gridbag.setConstraints(commandWorkDirLinePreviewLabel, c);
 468  38 main.add(commandWorkDirLinePreviewLabel);
 469   
 470  38 c.weightx = 1.0;
 471  38 c.weighty = 8.0;
 472  38 c.gridwidth = GridBagConstraints.REMAINDER;
 473  38 c.insets = compInsets;
 474   
 475  38 _commandWorkDirLinePreview = new JTextPane();
 476  38 _commandWorkDirLinePreview.setToolTipText(STALE_TOOLTIP);
 477  38 _commandWorkDirLineDoc = (StyledDocument)_commandWorkDirLinePreview.getDocument();
 478   
 479  38 _commandWorkDirLinePreview.setEditable(false);
 480  38 _commandWorkDirLinePreview.setBackground(Color.LIGHT_GRAY);
 481  38 _commandWorkDirLinePreview.setSelectedTextColor(Color.LIGHT_GRAY);
 482  38 JScrollPane commandWorkDirLinePreviewSP = new JScrollPane(_commandWorkDirLinePreview);
 483  38 commandWorkDirLinePreviewSP.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED);
 484  38 gridbag.setConstraints(commandWorkDirLinePreviewSP, c);
 485  38 main.add(commandWorkDirLinePreviewSP);
 486   
 487    // enclosing .djapp file
 488  38 c.weightx = 0.0;
 489  38 c.weighty = 0.0;
 490  38 c.gridwidth = 1;
 491  38 c.insets = labelInsets;
 492  38 JLabel enclosingFileLabel = new JLabel("Enclosing .djapp file:");
 493  38 gridbag.setConstraints(enclosingFileLabel, c);
 494  38 main.add(enclosingFileLabel);
 495   
 496  38 c.weightx = 1.0;
 497  38 c.weighty = 8.0;
 498  38 c.gridwidth = GridBagConstraints.RELATIVE;
 499  38 c.insets = compInsets;
 500   
 501  38 _commandEnclosingFileLine = new JTextPane();
 502    // do not allow a newline
 503  38 _commandEnclosingFileLine.addKeyListener(new KeyListener() {
 504  0 public void keyPressed(KeyEvent e) {
 505  0 if (e.getKeyCode() == KeyEvent.VK_ENTER) e.consume();
 506  0 else if (e.getKeyCode() == KeyEvent.VK_TAB) {
 507  0 e.consume();
 508  0 if (e.isShiftDown()) _commandWorkDirLine.requestFocus();
 509    else {
 510  0 _insertCommandButton.setEnabled(false);
 511  0 if (_editMode) {
 512  0 _saveCommandButton.requestFocus();
 513    }
 514  0 else _runCommandButton.requestFocus();
 515    }
 516    }
 517    }
 518  0 public void keyReleased(KeyEvent e) { }
 519  0 public void keyTyped(KeyEvent e) { }
 520    });
 521  38 JScrollPane commandEnclosingFileLineSP = new JScrollPane(_commandEnclosingFileLine);
 522  38 commandEnclosingFileLineSP.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED);
 523  38 gridbag.setConstraints(commandEnclosingFileLineSP, c);
 524  38 main.add(commandEnclosingFileLineSP);
 525   
 526  38 c.weightx = 0.0;
 527  38 c.weighty = 0.0;
 528  38 c.gridwidth = GridBagConstraints.REMAINDER;
 529  38 c.insets = compInsets;
 530   
 531  38 _commandEnclosingFileBtn = new JButton("...");
 532  38 _commandEnclosingFileBtn.addActionListener(new ActionListener() {
 533  0 public void actionPerformed(ActionEvent e) { chooseFile(_commandEnclosingFileLine); }
 534    });
 535  38 gridbag.setConstraints(_commandEnclosingFileBtn, c);
 536  38 main.add(_commandEnclosingFileBtn);
 537   
 538  38 c.weightx = 0.0;
 539  38 c.weighty = 0.0;
 540  38 c.gridwidth = 1;
 541  38 c.insets = labelInsets;
 542  38 JLabel commandEnclosingFileLinePreviewLabel = new JLabel("Enclosing .djapp file preview:");
 543  38 commandEnclosingFileLinePreviewLabel.setToolTipText(STALE_TOOLTIP);
 544  38 gridbag.setConstraints(commandEnclosingFileLinePreviewLabel, c);
 545  38 main.add(commandEnclosingFileLinePreviewLabel);
 546   
 547  38 c.weightx = 1.0;
 548  38 c.weighty = 8.0;
 549  38 c.gridwidth = GridBagConstraints.REMAINDER;
 550  38 c.insets = compInsets;
 551   
 552  38 _commandEnclosingFileLinePreview = new JTextPane();
 553  38 _commandEnclosingFileLinePreview.setToolTipText(STALE_TOOLTIP);
 554  38 _commandEnclosingFileLineDoc = (StyledDocument)_commandEnclosingFileLinePreview.getDocument();
 555   
 556  38 _commandEnclosingFileLinePreview.setEditable(false);
 557  38 _commandEnclosingFileLinePreview.setBackground(Color.LIGHT_GRAY);
 558  38 _commandEnclosingFileLinePreview.setSelectedTextColor(Color.LIGHT_GRAY);
 559  38 JScrollPane commandEnclosingFileLinePreviewSP = new JScrollPane(_commandEnclosingFileLinePreview);
 560  38 commandEnclosingFileLinePreviewSP.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED);
 561  38 gridbag.setConstraints(commandEnclosingFileLinePreviewSP, c);
 562  38 main.add(commandEnclosingFileLinePreviewSP);
 563   
 564    // bottom panel
 565  38 panel.add(main, BorderLayout.CENTER);
 566  38 JPanel bottom = new JPanel();
 567  38 bottom.setBorder(new EmptyBorder(5, 5, 5, 5));
 568  38 bottom.setLayout(new BoxLayout(bottom, BoxLayout.X_AXIS));
 569  38 bottom.add(Box.createHorizontalGlue());
 570  38 if (!_editMode) {
 571  38 bottom.add(_runCommandButton);
 572    }
 573  38 bottom.add(_saveCommandButton);
 574  38 bottom.add(_insertCommandButton);
 575  38 bottom.add(_cancelCommandButton);
 576  38 bottom.add(Box.createHorizontalGlue());
 577  38 panel.add(bottom, BorderLayout.SOUTH);
 578   
 579    // update the preview of the actual command line post substitution
 580  38 _documentListener = new DocumentListener() {
 581  38 public void update(DocumentEvent e) {
 582  38 assert EventQueue.isDispatchThread();
 583  38 try {
 584    // preview
 585  38 _commandLineDoc.remove(0,_commandLineDoc.getLength());
 586  38 String text = StringOps.replaceVariables(_commandLine.getText(), _props, PropertyMaps.GET_LAZY);
 587  38 _commandLineDoc.insertString(_commandLineDoc.getLength(), StringOps.unescapeFileName(text), null);
 588   
 589    // command line
 590  38 colorVariables(_commandLine,
 591    _props,
 592    this,
 593    _commandLineCmdAS,
 594    _varCommandLineCmdStyle,
 595    _varErrorCommandLineCmdStyle);
 596  38 _commandLinePreviewLabel.setText("<html>Command line preview:<br>(" + _commandLinePreview.getText().length()+
 597    " characters)</html>");
 598    }
 599  0 catch(BadLocationException ble) { _commandLinePreview.setText("Error."); }
 600    }
 601  38 public void changedUpdate(DocumentEvent e) { update(e); }
 602  0 public void insertUpdate(DocumentEvent e) { update(e); }
 603  0 public void removeUpdate(DocumentEvent e) { update(e); }
 604    };
 605  38 _commandLine.getDocument().addDocumentListener(_documentListener);
 606  38 _documentListener.changedUpdate(null);
 607   
 608    // update the preview of the actual work directory post substitution
 609  38 _workDirDocumentListener = new DocumentListener() {
 610  76 public void update(DocumentEvent e) {
 611  76 assert EventQueue.isDispatchThread();
 612  76 try {
 613    // preview
 614  76 _commandWorkDirLineDoc.remove(0,_commandWorkDirLineDoc.getLength());
 615  76 String text = StringOps.replaceVariables(_commandWorkDirLine.getText(), _props, PropertyMaps.GET_LAZY);
 616  76 _commandWorkDirLineDoc.insertString(0, StringOps.unescapeFileName(text), null);
 617   
 618    // command line
 619  76 colorVariables(_commandWorkDirLine,
 620    _props,
 621    this,
 622    _commandLineCmdAS,
 623    _varCommandLineCmdStyle,
 624    _varErrorCommandLineCmdStyle);
 625    }
 626  0 catch(BadLocationException ble) { _commandLinePreview.setText("Error: " + ble); }
 627    }
 628  38 public void changedUpdate(DocumentEvent e) { update(e); }
 629  38 public void insertUpdate(DocumentEvent e) { update(e); }
 630  0 public void removeUpdate(DocumentEvent e) { update(e); }
 631    };
 632  38 _commandWorkDirLine.getDocument().addDocumentListener(_workDirDocumentListener);
 633  38 _commandWorkDirLine.setText("${drjava.working.dir}");
 634  38 _workDirDocumentListener.changedUpdate(null);
 635   
 636    // update the preview of the actual enclosing .djapp file post substitution
 637  38 _enclosingFileDocumentListener = new DocumentListener() {
 638  38 public void update(DocumentEvent e) {
 639  38 assert EventQueue.isDispatchThread();
 640  38 try {
 641    // preview
 642  38 _commandEnclosingFileLineDoc.remove(0,_commandEnclosingFileLineDoc.getLength());
 643  38 String text = StringOps.replaceVariables(_commandEnclosingFileLine.getText(), _props, PropertyMaps.GET_LAZY);
 644  38 _commandEnclosingFileLineDoc.insertString(0, StringOps.unescapeFileName(text), null);
 645   
 646    // command line
 647  38 colorVariables(_commandEnclosingFileLine,
 648    _props,
 649    this,
 650    _commandLineCmdAS,
 651    _varCommandLineCmdStyle,
 652    _varErrorCommandLineCmdStyle);
 653    }
 654    catch(BadLocationException ble) {
 655  0 _commandLinePreview.setText("Error: " + ble);
 656    }
 657    }
 658  38 public void changedUpdate(DocumentEvent e) { update(e); }
 659  0 public void insertUpdate(DocumentEvent e) { update(e); }
 660  0 public void removeUpdate(DocumentEvent e) { update(e); }
 661    };
 662  38 _commandEnclosingFileLine.getDocument().addDocumentListener(_enclosingFileDocumentListener);
 663  38 _commandEnclosingFileLine.setText("");
 664  38 _enclosingFileDocumentListener.changedUpdate(null);
 665   
 666  38 _lastCommandFocus = _commandLine;
 667    // do not allow preview to have focus
 668  38 _commandLine.addFocusListener(new FocusAdapter() {
 669  0 public void focusGained(FocusEvent e) {
 670  0 _lastCommandFocus = (JTextPane)e.getComponent();
 671  0 _insertCommandButton.setEnabled(true);
 672    }
 673  0 public void focusLost(FocusEvent e) {
 674  0 if ((e.getOppositeComponent() == _commandLinePreview) ||
 675    (e.getOppositeComponent() == _commandWorkDirLinePreview)) {
 676  0 _commandLine.requestFocus();
 677    }
 678    }
 679    });
 680  38 _commandWorkDirLine.addFocusListener(new FocusAdapter() {
 681  0 public void focusGained(FocusEvent e) {
 682  0 _lastCommandFocus = (JTextPane)e.getComponent();
 683  0 _insertCommandButton.setEnabled(true);
 684    }
 685  0 public void focusLost(FocusEvent e) {
 686  0 if ((e.getOppositeComponent() == _commandLinePreview) ||
 687    (e.getOppositeComponent() == _commandWorkDirLinePreview)) {
 688  0 _commandWorkDirLine.requestFocus();
 689    }
 690    }
 691    });
 692   
 693  38 return panel;
 694    }
 695   
 696    /** Color properties as variables.
 697    * @param pane the pane that contains the text
 698    * @param props the properties to color */
 699  152 protected void colorVariables(final JTextPane pane,
 700    final PropertyMaps props,
 701    final DocumentListener dl,
 702    final SimpleAttributeSet normal,
 703    final SimpleAttributeSet variable,
 704    final SimpleAttributeSet error) {
 705  152 EventQueue.invokeLater(new Runnable() {
 706  152 public void run() {
 707  152 StyledDocument doc = (StyledDocument)pane.getDocument();
 708  152 doc.removeDocumentListener(dl);
 709  152 String str = pane.getText();
 710  152 BalancingStreamTokenizer tok = new BalancingStreamTokenizer(new StringReader(str), '$');
 711  152 tok.wordRange(0,255);
 712  152 tok.addQuotes("${", "}");
 713   
 714  152 int pos = 0;
 715  152 doc.setCharacterAttributes(0,str.length(),normal,true);
 716  152 String next = null;
 717  152 try {
 718  ? while((next=tok.getNextToken()) != null) {
 719  76 if ((tok.token() == BalancingStreamTokenizer.Token.QUOTED) && (next.startsWith("${"))) {
 720  76 if (next.endsWith("}")) {
 721  76 String key;
 722  76 String attrList = "";
 723  76 int firstCurly = next.indexOf('}');
 724  76 int firstSemi = next.indexOf(';');
 725  76 if (firstSemi < 0) {
 726  76 key = next.substring(2,firstCurly);
 727    }
 728    else {
 729  0 key = next.substring(2,firstSemi);
 730  0 attrList = next.substring(firstSemi+1,next.length()-1).trim();
 731    }
 732  76 boolean found = false;
 733  76 for(String category: props.getCategories()) {
 734  216 DrJavaProperty p = props.getProperty(category, key);
 735  216 if (p != null) {
 736  64 found = true;
 737  64 doc.setCharacterAttributes(pos,pos+next.length(),variable,true);
 738   
 739    // found property name
 740    // if we have a list of attributes
 741  64 if (attrList.length() > 0) {
 742    // +2 for "${", +1 for ";"
 743  0 int subpos = pos + 2 + key.length() + 1;
 744  0 int added = 0;
 745  0 BalancingStreamTokenizer atok = new BalancingStreamTokenizer(new StringReader(attrList), '$');
 746  0 atok.wordRange(0,255);
 747  0 atok.addQuotes("${", "}");
 748  0 atok.addQuotes("\"", "\"");
 749  0 atok.addKeyword(";");
 750  0 atok.addKeyword("=");
 751    // LOG.log("\tProcessing AttrList");
 752  0 String n = null;
 753  0 while((n=atok.getNextToken()) != null) {
 754  0 if ((n == null) || (atok.token() != BalancingStreamTokenizer.Token.NORMAL) ||
 755    n.trim().equals(";") || n.trim().equals("=") || n.trim().startsWith("\"")) {
 756  0 doc.setCharacterAttributes(subpos,pos+next.length(),error,true);
 757  0 break;
 758    }
 759  0 added += n.length();
 760  0 String name = n.trim();
 761  0 n = atok.getNextToken();
 762  0 if ((n == null) || (atok.token() != BalancingStreamTokenizer.Token.KEYWORD) ||
 763    (!n.trim().equals("="))) {
 764  0 doc.setCharacterAttributes(subpos,pos+next.length(),error,true);
 765  0 break;
 766    }
 767  0 added += n.length();
 768  0 n = atok.getNextToken();
 769  0 if ((n == null) || (atok.token() != BalancingStreamTokenizer.Token.QUOTED) ||
 770    (!n.trim().startsWith("\""))) {
 771  0 doc.setCharacterAttributes(subpos,pos+next.length(),error,true);
 772  0 break;
 773    }
 774  0 added += n.length();
 775  0 n = atok.getNextToken();
 776  0 if ((n != null && (atok.token() != BalancingStreamTokenizer.Token.KEYWORD || ! n.equals(";"))) ||
 777    (n == null && atok.token() != BalancingStreamTokenizer.Token.END)) {
 778  0 doc.setCharacterAttributes(subpos,pos+next.length(),error,true);
 779  0 break;
 780    }
 781  0 if (n != null) { added += n.length(); }
 782  0 try { p.getAttribute(name); }
 783    catch(IllegalArgumentException e) {
 784  0 doc.setCharacterAttributes(subpos, subpos + added, error, true);
 785    }
 786  0 subpos += added;
 787    }
 788    }
 789    }
 790  64 if (found) break;
 791    }
 792  12 if (!found) doc.setCharacterAttributes(pos,pos+next.length(),error,true);
 793    }
 794  0 else doc.setCharacterAttributes(pos,pos+next.length(),error,true);
 795    }
 796  0 else doc.setCharacterAttributes(pos,pos+next.length(),normal,true);
 797  76 pos += next.length();
 798    }
 799    }
 800    catch(IOException e) { /* ignore */ }
 801  152 finally { doc.addDocumentListener(dl); }
 802    }
 803    });
 804    }
 805   
 806    /** Method that handels the Cancel button */
 807  0 private void _cancel() {
 808  0 _lastState = new FrameState(this);
 809  0 this.setVisible(false);
 810  0 if (_cm != null) { _cm.signal(); }
 811    }
 812   
 813    // public static edu.rice.cs.util.Log LOG = new edu.rice.cs.util.Log("process.txt", false);
 814   
 815    /** Run a command and return an external process panel.
 816    * @param name name of the process
 817    * @param cmdline the command line to execute, before evaluation
 818    * @param workdir the work directory, before evaluation
 819    * @param enclosingFile the enclosing .djapp JAR file, or "" if not enclosed
 820    * @param pm PropertyMaps used for substitution when replacing variables
 821    * @return ExternalProcessPanel that displays the output of the process
 822    */
 823  0 public ExternalProcessPanel runCommand(String name, String cmdline, String workdir,
 824    String enclosingFile, PropertyMaps pm) {
 825  0 ((MutableFileProperty)pm.getProperty("enclosing.djapp.file")).setFile(enclosingFile.length() > 0?
 826    new File(enclosingFile):null);
 827  0 ProcessCreator pc = new GeneralProcessCreator(cmdline, workdir.trim(), pm);
 828  0 String label = "External";
 829  0 if (!name.equals("")) { label += ": " + name; }
 830  0 final ExternalProcessPanel panel = new ExternalProcessPanel(_mainFrame, label, pc);
 831  0 _mainFrame._tabs.addLast(panel);
 832  0 panel.getMainPanel().addFocusListener(new FocusAdapter() {
 833  0 public void focusGained(FocusEvent e) { _mainFrame._lastFocusOwner = panel; }
 834    });
 835  0 panel.setVisible(true);
 836  0 _mainFrame.showTab(panel, true);
 837  0 _mainFrame._tabbedPane.setSelectedComponent(panel);
 838    // Use EventQueue.invokeLater to ensure that focus is set AFTER the panel has been selected
 839  0 EventQueue.invokeLater(new Runnable() { public void run() { panel.requestFocusInWindow(); } });
 840  0 return panel;
 841    }
 842   
 843    /** Execute the command line. */
 844  0 private void _runCommand() {
 845  0 _mainFrame.updateStatusField("Executing external process...");
 846  0 GeneralProcessCreator.LOG.log("_runCommand(): ${enclosing.djapp.file} = " + _commandEnclosingFileLine.getText());
 847   
 848  0 _mainFrame.removeModalWindowAdapter(this);
 849  0 if (_commandLinePreview.getText().length() > 0) {
 850  0 try {
 851  0 _props = PropertyMaps.TEMPLATE.clone();
 852  0 PropertyMaps pm = _props.clone();
 853  0 runCommand("", _commandLine.getText(), _commandWorkDirLine.getText(),
 854    _commandEnclosingFileLine.getText().trim(), pm);
 855    }
 856  0 catch(CloneNotSupportedException e) { throw new edu.rice.cs.util.UnexpectedException(e); }
 857    }
 858   
 859    // Always apply and save settings
 860  0 _saveSettings();
 861  0 this.setVisible(false);
 862  0 if (_cm != null) { _cm.signal(); }
 863    }
 864   
 865    /** Save the command line to the menu. */
 866  0 private void _saveCommand() {
 867  0 if (_editMode) {
 868  0 final Vector<String> names = DrJava.getConfig().getSetting(OptionConstants.EXTERNAL_SAVED_NAMES);
 869  0 _mainFrame.removeModalWindowAdapter(this);
 870  0 String name = JOptionPane.showInputDialog(this, "Name for saved process:", names.get(_editIndex));
 871  0 _mainFrame.installModalWindowAdapter(this, LambdaUtil.NO_OP, CANCEL);
 872  0 if (name == null) {
 873    // Always apply and save settings
 874  0 _saveSettings();
 875  0 this.setVisible(false);
 876  0 if (_cm != null) { _cm.signal(); }
 877  0 return;
 878    }
 879  0 editInMenu(_editIndex, name, _commandLine.getText(), _commandWorkDirLine.getText(),
 880    _commandEnclosingFileLine.getText());
 881    }
 882    else {
 883  0 int count = DrJava.getConfig().getSetting(OptionConstants.EXTERNAL_SAVED_COUNT);
 884  0 _mainFrame.removeModalWindowAdapter(this);
 885  0 String name = JOptionPane.showInputDialog(this, "Name for saved process:", "External Java " + (count+1));
 886  0 _mainFrame.installModalWindowAdapter(this, LambdaUtil.NO_OP, CANCEL);
 887  0 if (name == null) {
 888    // Always apply and save settings
 889  0 _saveSettings();
 890  0 this.setVisible(false);
 891  0 if (_cm != null) { _cm.signal(); }
 892  0 return;
 893    }
 894  0 addToMenu(name, _commandLine.getText(), _commandWorkDirLine.getText(), _commandEnclosingFileLine.getText());
 895    }
 896   
 897    // Always apply and save settings
 898  0 _saveSettings();
 899  0 this.setVisible(false);
 900  0 if (_cm != null) { _cm.signal(); }
 901    }
 902   
 903    /** Add new process to menu.
 904    * @param name process name
 905    * @param cmdline command line
 906    * @param workdir work directory
 907    * @param enclosingFile the enclosing .djapp JAR file, or "" if not enclosed
 908    * @return number of processes in the menu */
 909  0 public static int addToMenu(String name, String cmdline, String workdir, String enclosingFile) {
 910  0 GeneralProcessCreator.LOG.log("addToMenu(): enclosingFile = " + enclosingFile);
 911  0 int count = DrJava.getConfig().getSetting(OptionConstants.EXTERNAL_SAVED_COUNT);
 912  0 ++count;
 913  0 final Vector<String> names = DrJava.getConfig().getSetting(OptionConstants.EXTERNAL_SAVED_NAMES);
 914  0 final Vector<String> cmdlines = DrJava.getConfig().getSetting(OptionConstants.EXTERNAL_SAVED_CMDLINES);
 915  0 final Vector<String> workdirs = DrJava.getConfig().getSetting(OptionConstants.EXTERNAL_SAVED_WORKDIRS);
 916  0 final Vector<String> enclosingFiles =
 917    DrJava.getConfig().getSetting(OptionConstants.EXTERNAL_SAVED_ENCLOSING_DJAPP_FILES);
 918   
 919  0 names.add(name);
 920  0 DrJava.getConfig().setSetting(OptionConstants.EXTERNAL_SAVED_NAMES,names);
 921   
 922  0 cmdlines.add(cmdline);
 923  0 DrJava.getConfig().setSetting(OptionConstants.EXTERNAL_SAVED_CMDLINES,cmdlines);
 924   
 925  0 workdirs.add(workdir);
 926  0 DrJava.getConfig().setSetting(OptionConstants.EXTERNAL_SAVED_WORKDIRS,workdirs);
 927   
 928  0 enclosingFiles.add(enclosingFile);
 929  0 DrJava.getConfig().setSetting(OptionConstants.EXTERNAL_SAVED_ENCLOSING_DJAPP_FILES,enclosingFiles);
 930   
 931  0 DrJava.getConfig().setSetting(OptionConstants.EXTERNAL_SAVED_COUNT,count);
 932   
 933  0 return count;
 934    }
 935   
 936    /** Edit existing process in menu.
 937    * @param editIndex the index of the process to edit
 938    * @param name process name
 939    * @param cmdline command line
 940    * @param workdir work directory
 941    * @param enclosingFile the enclosing .djapp JAR file, or "" if not enclosed
 942    */
 943  0 public static void editInMenu(int editIndex, String name, String cmdline, String workdir, String enclosingFile) {
 944  0 GeneralProcessCreator.LOG.log("editInMenu(): enclosingFile = " + enclosingFile);
 945  0 final Vector<String> names = DrJava.getConfig().getSetting(OptionConstants.EXTERNAL_SAVED_NAMES);
 946  0 final Vector<String> cmdlines = DrJava.getConfig().getSetting(OptionConstants.EXTERNAL_SAVED_CMDLINES);
 947  0 final Vector<String> workdirs = DrJava.getConfig().getSetting(OptionConstants.EXTERNAL_SAVED_WORKDIRS);
 948  0 final Vector<String> enclosingFiles = DrJava.getConfig().getSetting(OptionConstants.EXTERNAL_SAVED_ENCLOSING_DJAPP_FILES);
 949   
 950  0 names.set(editIndex,name);
 951  0 DrJava.getConfig().setSetting(OptionConstants.EXTERNAL_SAVED_NAMES,names);
 952   
 953  0 cmdlines.set(editIndex,cmdline);
 954  0 DrJava.getConfig().setSetting(OptionConstants.EXTERNAL_SAVED_CMDLINES,cmdlines);
 955   
 956  0 workdirs.set(editIndex,workdir);
 957  0 DrJava.getConfig().setSetting(OptionConstants.EXTERNAL_SAVED_WORKDIRS,workdirs);
 958   
 959  0 enclosingFiles.set(editIndex,enclosingFile);
 960  0 DrJava.getConfig().setSetting(OptionConstants.EXTERNAL_SAVED_ENCLOSING_DJAPP_FILES,enclosingFiles);
 961    }
 962   
 963    /** Save process to file.
 964    * @param index index of the process to save
 965    * @param f file */
 966  0 public static void saveToFile(int index, File f) {
 967  0 final Vector<String> names = DrJava.getConfig().getSetting(OptionConstants.EXTERNAL_SAVED_NAMES);
 968  0 final Vector<String> cmdlines = DrJava.getConfig().getSetting(OptionConstants.EXTERNAL_SAVED_CMDLINES);
 969  0 final Vector<String> workdirs = DrJava.getConfig().getSetting(OptionConstants.EXTERNAL_SAVED_WORKDIRS);
 970  0 final Vector<String> enclosingFiles = DrJava.getConfig().getSetting(OptionConstants.EXTERNAL_SAVED_ENCLOSING_DJAPP_FILES);
 971   
 972  0 XMLConfig xc = new XMLConfig();
 973    // System.out.println("saveToFile(" + index + ", " + f + ")");
 974    // System.out.println("\t" + names.get(index));
 975  0 xc.set("drjava/extprocess/name", names.get(index));
 976  0 xc.set("drjava/extprocess/cmdline", cmdlines.get(index));
 977  0 xc.set("drjava/extprocess/workdir", workdirs.get(index));
 978  0 xc.set("drjava/extprocess/enlcosingfile", enclosingFiles.get(index));
 979  0 xc.save(f);
 980    }
 981   
 982    /** Save the settings for this dialog. */
 983  0 private boolean _saveSettings() {
 984  0 _lastState = new FrameState(this);
 985  0 return true;
 986    }
 987   
 988    /** Insert a variable into the command line. */
 989  0 private void _insertVariableCommand() {
 990  0 _props.clearVariables();
 991  0 _mainFrame.removeModalWindowAdapter(this);
 992  0 _insertVarDialogMonitor.reset();
 993  0 _insertVarDialog.setVisible(true);
 994    // start a new thread to wait for the dialog to finish
 995    // this waiting cannot happen in the event thread, as that would block the other dialog
 996  0 new Thread(new Runnable() {
 997  0 public void run() {
 998  0 _insertVarDialogMonitor.attemptEnsureSignaled();
 999    // dialog has finished, figure out the results in the event thread
 1000  0 EventQueue.invokeLater(new Runnable() {
 1001  0 public void run() {
 1002  0 EventQueue.invokeLater(new Runnable() { public void run() { ExecuteExternalDialog.this.toFront(); } });
 1003  0 _mainFrame.installModalWindowAdapter(ExecuteExternalDialog.this, LambdaUtil.NO_OP, CANCEL);
 1004   
 1005  0 edu.rice.cs.plt.tuple.Pair<String,DrJavaProperty> selected = _insertVarDialog.getSelected();
 1006  0 if (selected != null) {
 1007  0 String text = _lastCommandFocus.getText();
 1008  0 Caret caret = _lastCommandFocus.getCaret();
 1009  0 int min = Math.min(caret.getDot(), caret.getMark());
 1010  0 int max = Math.max(caret.getDot(), caret.getMark());
 1011  0 if (min != max) { text = text.substring(0, min) + text.substring(max); }
 1012  0 text = text.substring(0,min) + "${" + selected.first() + "}" + text.substring(min);
 1013  0 _lastCommandFocus.setText(text);
 1014  0 caret.setDot(min+selected.first().length()+2);
 1015  0 _lastCommandFocus.setCaret(caret);
 1016    }
 1017    }
 1018    });
 1019    }
 1020    }).start();
 1021    }
 1022   
 1023    /** Runnable that calls _cancel. */
 1024    protected final Runnable1<WindowEvent> CANCEL = new Runnable1<WindowEvent>() {
 1025  0 public void run(WindowEvent e) { _cancel(); }
 1026    };
 1027   
 1028    /** Toggle visibility of this frame. Warning, it behaves like a modal dialog. */
 1029  0 public void setVisible(boolean vis) {
 1030  0 assert EventQueue.isDispatchThread();
 1031  0 validate();
 1032  0 if (vis) {
 1033  0 try { _props = PropertyMaps.TEMPLATE.clone(); } catch(CloneNotSupportedException e) {
 1034  0 throw new edu.rice.cs.util.UnexpectedException(e);
 1035    }
 1036  0 _mainFrame.hourglassOn();
 1037  0 _mainFrame.installModalWindowAdapter(this, LambdaUtil.NO_OP, CANCEL);
 1038  0 _documentListener.changedUpdate(null);
 1039  0 _workDirDocumentListener.changedUpdate(null);
 1040  0 toFront();
 1041    }
 1042    else {
 1043  0 _mainFrame.removeModalWindowAdapter(this);
 1044  0 _mainFrame.hourglassOff();
 1045  0 _mainFrame.toFront();
 1046    }
 1047  0 super.setVisible(vis);
 1048    }
 1049   
 1050    /** Opens the file chooser to select a directory, putting the result in the file field. */
 1051  0 protected void chooseDir(JTextPane pane) {
 1052    // Get the file from the chooser
 1053  0 File wd = new File(StringOps.replaceVariables(pane.getText().trim(), _props, PropertyMaps.GET_CURRENT));
 1054  0 if ((pane.getText().equals("")) ||
 1055    (!wd.exists()) &&
 1056    (!wd.isDirectory())) {
 1057  0 wd = new File(System.getProperty("user.dir"));
 1058    }
 1059   
 1060  0 _dirChooser.setSelectedFile(wd);
 1061  0 _mainFrame.removeModalWindowAdapter(this);
 1062  0 int returnValue = _dirChooser.showDialog(wd);
 1063  0 _mainFrame.installModalWindowAdapter(this, LambdaUtil.NO_OP, CANCEL);
 1064  0 if (returnValue == DirectoryChooser.APPROVE_OPTION) {
 1065  0 File chosen = _dirChooser.getSelectedDirectory();
 1066  0 if (chosen != null) { pane.setText(chosen.toString()); };
 1067    }
 1068    }
 1069   
 1070    /** Opens the file chooser to select a file, putting the result in the file field. */
 1071  0 protected void chooseFile(JTextPane pane) {
 1072    // Get the file from the chooser
 1073  0 File wd = new File(StringOps.replaceVariables(pane.getText().trim(), _props, PropertyMaps.GET_CURRENT));
 1074  0 if ((pane.getText().equals("")) ||
 1075    (!wd.exists()) &&
 1076    (!wd.isFile())) {
 1077  0 wd = null;
 1078    }
 1079   
 1080  0 _fileChooser.setSelectedFile(wd);
 1081  0 _mainFrame.removeModalWindowAdapter(this);
 1082  0 int returnValue = _fileChooser.showOpenDialog(this);
 1083  0 _mainFrame.installModalWindowAdapter(this, LambdaUtil.NO_OP, CANCEL);
 1084  0 if (returnValue == DirectoryChooser.APPROVE_OPTION) {
 1085  0 File chosen = _fileChooser.getSelectedFile();
 1086  0 if (chosen != null) { pane.setText(chosen.toString()); } else { pane.setText(""); }
 1087    }
 1088    }
 1089    }