Clover coverage report - DrJava Test Coverage (drjava-20120304-r5456)
Coverage timestamp: Sun Mar 4 2012 03:13:23 CST
file stats: LOC: 447   Methods: 27
NCLOC: 303   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
AutoCompletePopup.java 0% 0% 0% 0%
coverage
 1    package edu.rice.cs.drjava.ui;
 2   
 3    /*BEGIN_COPYRIGHT_BLOCK
 4    *
 5    * Copyright (c) 2001-2010, JavaPLT group at Rice University (drjava@rice.edu)
 6    * All rights reserved.
 7    *
 8    * Redistribution and use in source and binary forms, with or without
 9    * modification, are permitted provided that the following conditions are met:
 10    * * Redistributions of source code must retain the above copyright
 11    * notice, this list of conditions and the following disclaimer.
 12    * * Redistributions in binary form must reproduce the above copyright
 13    * notice, this list of conditions and the following disclaimer in the
 14    * documentation and/or other materials provided with the distribution.
 15    * * Neither the names of DrJava, the JavaPLT group, Rice University, nor the
 16    * names of its contributors may be used to endorse or promote products
 17    * derived from this software without specific prior written permission.
 18    *
 19    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 20    * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 21    * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 22    * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 23    * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 24    * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 25    * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 26    * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 27    * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 28    * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 29    * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 30    *
 31    * This software is Open Source Initiative approved Open Source Software.
 32    * Open Source Initative Approved is a trademark of the Open Source Initiative.
 33    *
 34    * This file is part of DrJava. Download the current version of this project
 35    * from http://www.drjava.org/ or http://sourceforge.net/projects/drjava/
 36    *
 37    * END_COPYRIGHT_BLOCK*/
 38   
 39    import java.awt.event.*;
 40    import java.awt.Component;
 41    import java.awt.Container;
 42    import java.awt.GridBagLayout;
 43    import java.awt.GridBagConstraints;
 44    import java.awt.Insets;
 45    import java.awt.Color;
 46    import java.awt.EventQueue;
 47    import java.io.IOException;
 48    import java.io.File;
 49    import java.net.URL;
 50    import java.util.*;
 51    import javax.swing.*;
 52    import javax.swing.event.*;
 53    import javax.swing.border.EmptyBorder;
 54    import java.awt.Dimension;
 55    import javax.swing.text.JTextComponent;
 56    import javax.swing.text.BadLocationException;
 57   
 58    import edu.rice.cs.drjava.DrJava;
 59    import edu.rice.cs.drjava.model.SingleDisplayModel;
 60    import edu.rice.cs.drjava.config.OptionConstants;
 61    import edu.rice.cs.drjava.ui.predictive.PredictiveInputFrame;
 62    import edu.rice.cs.drjava.ui.predictive.PredictiveInputModel;
 63    import edu.rice.cs.drjava.model.DummyOpenDefDoc;
 64    import edu.rice.cs.drjava.platform.PlatformFactory;
 65    import edu.rice.cs.drjava.model.OpenDefinitionsDocument;
 66   
 67    import edu.rice.cs.plt.lambda.*;
 68    import edu.rice.cs.plt.iter.*;
 69    import edu.rice.cs.plt.collect.UnionSet;
 70   
 71    import edu.rice.cs.util.swing.SwingFrame;
 72    import edu.rice.cs.util.swing.Utilities;
 73   
 74    import static edu.rice.cs.drjava.ui.MainFrameStatics.*;
 75    import static edu.rice.cs.drjava.ui.predictive.PredictiveInputModel.*;
 76    import static edu.rice.cs.drjava.ui.predictive.PredictiveInputFrame.FrameState;
 77   
 78    /** Autocomplete support.
 79    * @version $Id: AutoCompletePopup.java 5245 2010-05-07 02:59:04Z mgricken $
 80    */
 81    public class AutoCompletePopup {
 82    /** Main frame. */
 83    final protected MainFrame _mainFrame;
 84   
 85    /** Checkbox that controls whether Java API classes are included. */
 86    JCheckBox _completeJavaAPICheckbox = new JCheckBox("Java API");
 87   
 88    /** Frame state. */
 89    protected FrameState _lastState = null;
 90   
 91    /** Complete set of entries. */
 92    final protected Set<AutoCompletePopupEntry> _allEntries;
 93   
 94    /** Set of the document entries. */
 95    final protected Set<AutoCompletePopupEntry> _docEntries;
 96   
 97    /** Set of all the Java API classes. */
 98    final protected Set<AutoCompletePopupEntry> _apiEntries;
 99   
 100    /** Constructor for an auto-complete popup that uses the MainFrame for information.
 101    * @param mf main frame of DrJava */
 102  0 public AutoCompletePopup(MainFrame mf) { this(mf, null); }
 103   
 104    /** Constructor for an auto-complete popup that uses the MainFrame for information.
 105    * @param mf main frame of DrJava
 106    * @param frameState position and size of the dialog
 107    */
 108  0 public AutoCompletePopup(MainFrame mf, String frameState) {
 109  0 _mainFrame = mf;
 110  0 if (frameState!=null) _lastState = new FrameState(frameState);
 111  0 _docEntries = new HashSet<AutoCompletePopupEntry>();
 112  0 _apiEntries = new HashSet<AutoCompletePopupEntry>();
 113  0 _allEntries = new UnionSet<AutoCompletePopupEntry>(_apiEntries,
 114    new UnionSet<AutoCompletePopupEntry>(mf.getCompleteClassSet(),
 115    _docEntries));
 116    }
 117   
 118    /** Display an auto-complete popup with the specified window title centered around
 119    * the parent component. The initial text and caret location are specified, as well
 120    * as the action to be performed if the popup is cancelled or accepted.
 121    * @param parent parent GUI component
 122    * @param title window title
 123    * @param initial initial text
 124    * @param loc caret location in the initial text
 125    * @param canceledAction action to take if canceled
 126    * @param acceptedAction action to take if accepted <simple name, full name, from, to>
 127    */
 128  0 public void show(final Component parent,
 129    final String title,
 130    final String initial,
 131    final int loc,
 132    final Runnable canceledAction,
 133    final Runnable3<AutoCompletePopupEntry,Integer,Integer> acceptedAction) {
 134  0 show(parent, title, initial, loc, IterUtil.make("OK"),
 135    IterUtil.make(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0)), 0, canceledAction, IterUtil.make(acceptedAction));
 136    }
 137   
 138    /** Display an auto-complete popup with the specified window title centered around
 139    * the parent component. The initial text and caret location are specified, as well
 140    * as the action to be performed if the popup is cancelled or accepted.
 141    * @param parent parent GUI component
 142    * @param title window title
 143    * @param initial initial text
 144    * @param loc caret location in the initial text
 145    * @param actionNames names for the actions
 146    * @param canceledAction action to take if canceled
 147    * @param acceptedActions actions to take if accepted <simple name, full name, from, to>
 148    */
 149  0 public void show(final Component parent,
 150    final String title,
 151    final String initial,
 152    final int loc,
 153    final SizedIterable<String> actionNames,
 154    final Runnable canceledAction,
 155    final SizedIterable<Runnable3<AutoCompletePopupEntry,Integer,Integer>> acceptedActions) {
 156  0 SizedIterable<KeyStroke> actionKeyStrokes =
 157    IterUtil.compose(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0),
 158    IterUtil.copy((KeyStroke)null, acceptedActions.size()-1));
 159  0 show(parent, title, initial, loc, actionNames, actionKeyStrokes,
 160    0, canceledAction, acceptedActions);
 161    }
 162   
 163    /** Display an auto-complete popup with the specified window title centered around
 164    * the parent component. The initial text and caret location are specified, as well
 165    * as the action to be performed if the popup is cancelled or accepted.
 166    * @param parent parent GUI component
 167    * @param title window title
 168    * @param initial initial text
 169    * @param loc caret location in the initial text
 170    * @param actionNames names for the actions
 171    * @param actionKeyStrokes keystrokes for the actions
 172    * @param oneMatchActionIndex the action to take when there's just one match, or -1
 173    * @param canceledAction action to take if canceled
 174    * @param acceptedActions actions to take if accepted <simple name, full name, from, to>
 175    */
 176  0 public void show(final Component parent,
 177    final String title,
 178    final String initial,
 179    final int loc,
 180    final SizedIterable<String> actionNames,
 181    final SizedIterable<KeyStroke> actionKeyStrokes,
 182    final int oneMatchActionIndex,
 183    final Runnable canceledAction,
 184    final SizedIterable<Runnable3<AutoCompletePopupEntry,Integer,Integer>> acceptedActions) {
 185  0 assert actionNames.size() == acceptedActions.size();
 186  0 assert actionNames.size() == actionKeyStrokes.size();
 187   
 188  0 _completeJavaAPICheckbox.setSelected(DrJava.getConfig().getSetting(OptionConstants.DIALOG_COMPLETE_JAVAAPI));
 189  0 _completeJavaAPICheckbox.setEnabled(true);
 190   
 191  0 new Thread() {
 192  0 public void run() {
 193  0 List<OpenDefinitionsDocument> docs = _mainFrame.getModel().getOpenDefinitionsDocuments();
 194  0 if ((docs == null) || (docs.size() == 0)) {
 195  0 Utilities.invokeAndWait(canceledAction);
 196  0 return; // do nothing
 197    }
 198   
 199  0 AutoCompletePopupEntry currentEntry = null;
 200  0 _docEntries.clear();
 201  0 for(OpenDefinitionsDocument d: docs) {
 202  0 if (d.isUntitled()) continue;
 203  0 String str = d.toString();
 204  0 if (str.lastIndexOf('.')>=0) {
 205  0 str = str.substring(0, str.lastIndexOf('.'));
 206    }
 207  0 GoToFileListEntry entry = new GoToFileListEntry(d, str);
 208  0 if (d.equals(_mainFrame.getModel().getActiveDocument())) currentEntry = entry;
 209  0 _docEntries.add(entry);
 210    }
 211   
 212  0 if (DrJava.getConfig().getSetting(OptionConstants.DIALOG_COMPLETE_JAVAAPI)) {
 213  0 addJavaAPI();
 214    }
 215   
 216  0 final PredictiveInputModel<AutoCompletePopupEntry> pim =
 217    new PredictiveInputModel<AutoCompletePopupEntry>(true, new PrefixStrategy<AutoCompletePopupEntry>(), _allEntries);
 218  0 String mask = "";
 219  0 String s = initial;
 220   
 221    // check that we're at the end of a word
 222  0 if ((loc<s.length()) && (!Character.isWhitespace(s.charAt(loc))) &&
 223    ("()[]{}<>.,:;/*+-!~&|%".indexOf(s.charAt(loc)) == -1)) {
 224    // TODO: what??
 225  0 Utilities.invokeAndWait(canceledAction);
 226  0 return;
 227    }
 228   
 229    // find start
 230  0 int start = loc;
 231  0 while(start > 0) {
 232  0 if (!Character.isJavaIdentifierPart(s.charAt(start-1))) { break; }
 233  0 --start;
 234    }
 235  0 while((start<s.length()) && (!Character.isJavaIdentifierStart(s.charAt(start))) && (start < loc)) {
 236  0 ++start;
 237    }
 238   
 239  0 int end = loc-1;
 240   
 241  0 if ((start>=0) && (end < s.length())) {
 242  0 mask = s.substring(start, end + 1);
 243  0 pim.setMask(mask);
 244    }
 245   
 246  0 if ((pim.getMatchingItems().size() == 1) && (oneMatchActionIndex >= 0)) {
 247  0 if (pim.getCurrentItem() != null) {
 248    // exactly one match, auto-complete
 249  0 final int finalStart = start;
 250  0 Utilities.invokeAndWait(new Runnable() {
 251  0 public void run() {
 252  0 Iterator<Runnable3<AutoCompletePopupEntry,Integer,Integer>> actionIt =
 253    acceptedActions.iterator();
 254  0 Runnable3<AutoCompletePopupEntry,Integer,Integer> action;
 255  0 int i = oneMatchActionIndex;
 256  0 do {
 257  0 action = actionIt.next();
 258  0 } while(i<0);
 259  0 action.run(pim.getCurrentItem(), finalStart, loc);
 260    }
 261    });
 262  0 return;
 263    }
 264    }
 265   
 266    // not exactly one match
 267  0 pim.setMask(mask);
 268  0 if (pim.getMatchingItems().size() == 0) {
 269    // if there are no matches, shorten the mask until there is at least one
 270  0 mask = pim.getMask();
 271  0 while(mask.length() > 0) {
 272  0 mask = mask.substring(0, mask.length() - 1);
 273  0 pim.setMask(mask);
 274  0 if (pim.getMatchingItems().size() > 0) { break; }
 275    }
 276    }
 277  0 final PredictiveInputFrame<AutoCompletePopupEntry> completeWordDialog =
 278    createCompleteWordDialog(title, start, loc, actionNames, actionKeyStrokes,
 279    canceledAction, acceptedActions);
 280  0 final AutoCompletePopupEntry finalCurrentEntry = currentEntry;
 281  0 Utilities.invokeLater(new Runnable() {
 282  0 public void run() {
 283  0 completeWordDialog.setModel(true, pim); // ignore case
 284  0 completeWordDialog.selectStrategy();
 285  0 if (finalCurrentEntry != null) {
 286  0 completeWordDialog.setCurrentItem(finalCurrentEntry);
 287    }
 288  0 completeWordDialog.setLocationRelativeTo(parent);
 289   
 290  0 if (_lastState != null) {
 291  0 completeWordDialog.setFrameState(_lastState);
 292    }
 293   
 294  0 completeWordDialog.setVisible(true);
 295    }
 296    });
 297    }
 298    }.start();
 299    }
 300   
 301    /** Returns the last state of the frame, i.e. the location and dimension.
 302    * @return frame state
 303    */
 304  0 public FrameState getFrameState() { return _lastState; }
 305   
 306    /** Sets state of the frame, i.e. the location and dimension of the frame for the next use.
 307    * @param ds State to update to, or {@code null} to reset
 308    */
 309  0 public void setFrameState(FrameState ds) {
 310  0 _lastState = ds;
 311    }
 312   
 313    /** Sets state of the frame, i.e. the location and dimension of the frame for the next use.
 314    * @param s State to update to, or {@code null} to reset
 315    */
 316  0 public void setFrameState(String s) {
 317  0 try { _lastState = new FrameState(s); }
 318  0 catch(IllegalArgumentException e) { _lastState = null; }
 319    }
 320   
 321  0 protected PredictiveInputFrame<AutoCompletePopupEntry>
 322    createCompleteWordDialog(final String title,
 323    final int start,
 324    final int loc,
 325    final SizedIterable<String> actionNames,
 326    final SizedIterable<KeyStroke> actionKeyStrokes,
 327    final Runnable canceledAction,
 328    final SizedIterable<Runnable3<AutoCompletePopupEntry,Integer,Integer>> acceptedActions) {
 329  0 final SimpleBox<PredictiveInputFrame<AutoCompletePopupEntry>> dialogThunk =
 330    new SimpleBox<PredictiveInputFrame<AutoCompletePopupEntry>>();
 331    // checkbox whether Java API classes should be completed as well
 332  0 _completeJavaAPICheckbox.addActionListener(new ActionListener() {
 333  0 public void actionPerformed(ActionEvent e) {
 334  0 String curMask = dialogThunk.value().getMask();
 335  0 DrJava.getConfig().setSetting(OptionConstants.DIALOG_COMPLETE_JAVAAPI, _completeJavaAPICheckbox.isSelected());
 336  0 if (_completeJavaAPICheckbox.isSelected()) addJavaAPI(); else removeJavaAPI();
 337  0 dialogThunk.value().setItems(true,_allEntries);
 338  0 dialogThunk.value().setMask(curMask);
 339  0 dialogThunk.value().resetFocus();
 340    }
 341    });
 342  0 PlatformFactory.ONLY.setMnemonic(_completeJavaAPICheckbox,'j');
 343  0 PredictiveInputFrame.InfoSupplier<AutoCompletePopupEntry> info =
 344    new PredictiveInputFrame.InfoSupplier<AutoCompletePopupEntry>() {
 345  0 public String value(AutoCompletePopupEntry entry) {
 346    // show full class name as information
 347  0 StringBuilder sb = new StringBuilder();
 348  0 sb.append(entry.getFullPackage());
 349  0 sb.append(entry.getClassName());
 350  0 return sb.toString();
 351    }
 352    };
 353   
 354  0 List<PredictiveInputFrame.CloseAction<AutoCompletePopupEntry>> actions
 355    = new ArrayList<PredictiveInputFrame.CloseAction<AutoCompletePopupEntry>>();
 356   
 357  0 Iterator<String> nameIt = actionNames.iterator();
 358  0 Iterator<Runnable3<AutoCompletePopupEntry,Integer,Integer>> actionIt =
 359    acceptedActions.iterator();
 360  0 Iterator<KeyStroke> ksIt = actionKeyStrokes.iterator();
 361  0 for(int i=0; i<acceptedActions.size(); ++i) {
 362  0 final int acceptedActionIndex = i;
 363  0 final String name = nameIt.next();
 364  0 final Runnable3<AutoCompletePopupEntry,Integer,Integer> runnable = actionIt.next();
 365  0 final KeyStroke ks = ksIt.next();
 366   
 367  0 PredictiveInputFrame.CloseAction<AutoCompletePopupEntry> okAction =
 368    new PredictiveInputFrame.CloseAction<AutoCompletePopupEntry>() {
 369  0 public String getName() { return name; }
 370  0 public KeyStroke getKeyStroke() { return ks; }
 371  0 public String getToolTipText() { return "Complete the identifier"; }
 372  0 public Object value(final PredictiveInputFrame<AutoCompletePopupEntry> p) {
 373  0 _lastState = p.getFrameState();
 374  0 if (p.getItem() != null) {
 375  0 Utilities.invokeAndWait(new Runnable() {
 376  0 public void run() {
 377  0 runnable.run(p.getItem(), start, loc);
 378    }
 379    });
 380    }
 381    else {
 382  0 Utilities.invokeAndWait(canceledAction);
 383    }
 384  0 return null;
 385    }
 386    };
 387  0 actions.add(okAction);
 388    }
 389   
 390  0 PredictiveInputFrame.CloseAction<AutoCompletePopupEntry> cancelAction =
 391    new PredictiveInputFrame.CloseAction<AutoCompletePopupEntry>() {
 392  0 public String getName() { return "Cancel"; }
 393  0 public KeyStroke getKeyStroke() { return KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0); }
 394  0 public String getToolTipText() { return null; }
 395  0 public Object value(PredictiveInputFrame<AutoCompletePopupEntry> p) {
 396  0 _lastState = p.getFrameState();
 397  0 Utilities.invokeAndWait(canceledAction);
 398  0 return null;
 399    }
 400    };
 401  0 actions.add(cancelAction);
 402   
 403    // Note: PredictiveInputModel.* is statically imported
 404  0 java.util.ArrayList<MatchingStrategy<AutoCompletePopupEntry>> strategies =
 405    new java.util.ArrayList<MatchingStrategy<AutoCompletePopupEntry>>();
 406  0 strategies.add(new FragmentStrategy<AutoCompletePopupEntry>());
 407  0 strategies.add(new PrefixStrategy<AutoCompletePopupEntry>());
 408  0 strategies.add(new RegExStrategy<AutoCompletePopupEntry>());
 409   
 410  0 GoToFileListEntry entry = new GoToFileListEntry(new DummyOpenDefDoc() {
 411  0 public String getPackageNameFromDocument() { return ""; }
 412    }, "dummyComplete");
 413  0 dialogThunk.set(new PredictiveInputFrame<AutoCompletePopupEntry>(null,
 414    title,
 415    true, // force
 416    true, // ignore case
 417    info,
 418    strategies,
 419    actions,
 420    actions.size()-1, // cancel is last
 421    entry) {
 422  0 protected JComponent[] makeOptions() {
 423  0 return new JComponent[] { _completeJavaAPICheckbox };
 424    }
 425    });
 426  0 dialogThunk.value().setSize(dialogThunk.value().getSize().width, 500);
 427  0 dialogThunk.value().setLocationRelativeTo(_mainFrame);
 428  0 return dialogThunk.value();
 429    }
 430   
 431  0 private void addJavaAPI() {
 432  0 Set<JavaAPIListEntry> apiSet = _mainFrame.getJavaAPISet();
 433  0 if (apiSet == null) {
 434  0 DrJava.getConfig().setSetting(OptionConstants.DIALOG_COMPLETE_JAVAAPI, Boolean.FALSE);
 435  0 _completeJavaAPICheckbox.setSelected(false);
 436  0 _completeJavaAPICheckbox.setEnabled(false);
 437    }
 438    else {
 439  0 _apiEntries.clear();
 440  0 _apiEntries.addAll(apiSet);
 441    }
 442    }
 443   
 444  0 private void removeJavaAPI() {
 445  0 _apiEntries.clear();
 446    }
 447    }