Clover coverage report - DrJava Test Coverage (drjava-20120304-r5456)
Coverage timestamp: Sun Mar 4 2012 03:13:23 CST
file stats: LOC: 283   Methods: 20
NCLOC: 160   Classes: 2
 
 Source file Conditionals Statements Methods TOTAL
RecentFileManager.java 50% 66.3% 65% 62.7%
coverage coverage
 1    /*BEGIN_COPYRIGHT_BLOCK
 2    *
 3    * Copyright (c) 2001-2010, JavaPLT group at Rice University (drjava@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 javax.swing.*;
 40    import java.awt.event.*;
 41    import java.io.File;
 42    import java.io.IOException;
 43    import java.util.Vector;
 44    import java.util.HashSet;
 45   
 46    import edu.rice.cs.drjava.DrJava;
 47    import edu.rice.cs.drjava.config.*;
 48    import edu.rice.cs.plt.lambda.Runnable1;
 49   
 50    import edu.rice.cs.util.FileOpenSelector;
 51   
 52    /**
 53    * Manages a list of the most recently used files to be displayed
 54    * in the File menu.
 55    * @version $Id: RecentFileManager.java 5330 2010-07-19 20:49:48Z mgricken $
 56    */
 57    public class RecentFileManager implements OptionConstants {
 58    /** Position in the file menu where the entries start. */
 59    protected int _initPos;
 60   
 61    /** Position in the file menu for the next insert. */
 62    protected int _pos;
 63   
 64    /** All of the recently used files in the list, in order. */
 65    protected Vector<File> _recentFiles;
 66   
 67    /** The maximum number of files to display in the list. */
 68    protected int MAX = DrJava.getConfig().getSetting(RECENT_FILES_MAX_SIZE).intValue();
 69   
 70    /** The File menu containing the entries. */
 71    protected JMenu _fileMenu;
 72   
 73    /** Other File menus to be kept synchronized to the original File menu. */
 74    protected HashSet<JMenu> _mirroredMenus = new HashSet<JMenu>();
 75   
 76    /** The OptionConstant that should be used to retrieve the list of recent files. */
 77    protected VectorOption<File> _settingConfigConstant;
 78   
 79    /** An action that will be invoked when the file is clicked. */
 80    protected RecentFileAction _recentFileAction;
 81   
 82    /** Creates a new RecentFileManager.
 83    * @param pos Position in the file menu
 84    * @param fileMenu File menu to add the entry to
 85    */
 86  81 public RecentFileManager(int pos, JMenu fileMenu, RecentFileAction action, VectorOption<File> settingConfigConstant) {
 87  81 _initPos = _pos = pos;
 88  81 _fileMenu = fileMenu;
 89  81 _recentFileAction = action;
 90  81 _recentFiles = new Vector<File>();
 91  81 _settingConfigConstant = settingConfigConstant;
 92   
 93    // Add each of the files stored in the config
 94  81 Vector<File> files = DrJava.getConfig().getSetting(_settingConfigConstant);
 95   
 96  81 for (int i = files.size() - 1; i >= 0; i--) {
 97  0 File f = files.get(i);
 98  0 if (f.exists()) updateOpenFiles(f);
 99    }
 100    }
 101   
 102    /** Add another menu that should be kept identical to the main File menu.
 103    * @param mirroredMenu menu to keep identical */
 104  0 public void addMirroredMenu(JMenu mirroredMenu) {
 105    // Add the current list of files to the menu
 106  0 if (_recentFiles.size()>0) {
 107  0 mirroredMenu.insertSeparator(_initPos); //one at top
 108    }
 109  0 for(int i=0; i<_recentFiles.size(); ++i) {
 110  0 final File file = _recentFiles.get(i);
 111  0 final FileOpenSelector recentSelector = new FileOpenSelector() {
 112  0 public File[] getFiles() { return new File[] { file }; }
 113    };
 114  0 JMenuItem newItem = new JMenuItem((i+1) + ". " + file.getName());
 115  0 newItem.addActionListener(new AbstractAction("Open " + file.getName()) {
 116  0 public void actionPerformed(ActionEvent ae) {
 117  0 if (_recentFileAction != null) {
 118  0 _recentFileAction.actionPerformed(recentSelector);
 119    }
 120    }
 121    });
 122  0 try { newItem.setToolTipText(file.getCanonicalPath()); }
 123    catch(IOException e) {
 124    // don't worry about it at this point
 125    }
 126  0 mirroredMenu.insert(newItem,_initPos+i+1);
 127    }
 128  0 numberItems();
 129  0 _mirroredMenus.add(mirroredMenu);
 130    }
 131   
 132    /** Remove a menu that was kept identical to the main File menu.
 133    * @param mirroredMenu menu to remove */
 134  0 public void removeMirroredMenu(JMenu mirroredMenu) {
 135  0 _mirroredMenus.remove(mirroredMenu);
 136    }
 137   
 138    /** Returns the list of recently used files, in order. */
 139  7 public Vector<File> getFileVector() { return _recentFiles; }
 140   
 141    /** Changes the maximum number of files to display in the list.
 142    * @param newMax The new maximum number of files to display
 143    */
 144  5 public void updateMax(int newMax) { MAX = newMax; }
 145   
 146    /** Saves the current list of files to the config object. */
 147  0 public void saveRecentFiles() {
 148  0 DrJava.getConfig().setSetting(_settingConfigConstant, _recentFiles);
 149    }
 150   
 151    /** Updates the list after the given file has been opened. */
 152  39 public void updateOpenFiles(final File file) {
 153   
 154  39 if (_recentFiles.size() == 0) {
 155  20 _insertSeparator(_pos); //one at top
 156  20 _pos++;
 157    }
 158   
 159  39 final FileOpenSelector recentSelector = new FileOpenSelector() {
 160  0 public File[] getFiles() { return new File[] { file }; }
 161    };
 162   
 163  39 removeIfInList(file);
 164  39 _recentFiles.add(0,file);
 165   
 166  39 _do(new Runnable1<JMenu>() {
 167  39 public void run(JMenu fileMenu) {
 168  39 JMenuItem newItem = new JMenuItem("");
 169  39 newItem.addActionListener(new AbstractAction("Open " + file.getName()) {
 170  0 public void actionPerformed(ActionEvent ae) {
 171  0 if (_recentFileAction != null) {
 172  0 _recentFileAction.actionPerformed(recentSelector);
 173    }
 174    }
 175    });
 176  39 try { newItem.setToolTipText(file.getCanonicalPath()); }
 177    catch(IOException e) {
 178    // don't worry about it at this point
 179    }
 180  39 fileMenu.insert(newItem,_pos);
 181    }
 182    });
 183  39 numberItems();
 184    }
 185   
 186    /** Removes the given file from the list if it is already there.
 187    * Only removes the first occurrence of the file, since each
 188    * entry should be unique (based on canonical path).
 189    */
 190  42 public void removeIfInList(File file) {
 191    // Use canonical path if possible
 192  42 File canonical = null;
 193  42 try { canonical = file.getCanonicalFile(); }
 194    catch (IOException ioe) {
 195    // Oh well, compare against the file as is
 196    }
 197   
 198  42 for (int i = 0; i < _recentFiles.size(); i++) {
 199  27 File currFile = _recentFiles.get(i);
 200  27 boolean match;
 201  27 if (canonical != null) {
 202  27 try { match = currFile.getCanonicalFile().equals(canonical); }
 203    catch (IOException ioe) {
 204    // Oh well, compare the files themselves
 205  0 match = currFile.equals(file);
 206    }
 207    }
 208    else {
 209    // (couldn't find canonical for file; compare as is)
 210  0 match = currFile.equals(file);
 211    }
 212   
 213  27 if (match) {
 214  6 _recentFiles.remove(i);
 215  6 _remove(_initPos+i+1);
 216  6 break;
 217    }
 218    }
 219    }
 220   
 221    /** Trims the recent file list to the configured size and numbers the
 222    * remaining files according to their position in the list
 223    */
 224  40 public void numberItems() {
 225  40 int delPos = _recentFiles.size();
 226  40 boolean wasEmpty = (delPos == 0);
 227  40 while (delPos > MAX) {
 228  2 _recentFiles.remove(delPos - 1);
 229  2 _remove(_initPos+delPos);
 230   
 231  2 delPos = _recentFiles.size();
 232    }
 233  40 for (int i = 0; i < _recentFiles.size(); i++ ) {
 234  59 final int fi = i;
 235  59 _do(new Runnable1<JMenu>() {
 236  59 public void run(JMenu fileMenu) {
 237  59 JMenuItem currItem = fileMenu.getItem(_initPos+fi+1);
 238  59 currItem.setText((fi+1) + ". " + _recentFiles.get(fi).getName());
 239    }
 240    });
 241    }
 242    // remove the separator
 243  0 if (MAX == 0 && !wasEmpty) { _remove(--_pos); }
 244    }
 245   
 246    /** This interface is to be implemented and passed to the manager
 247    * upon creation. This action specifies what is performed when the
 248    * user selects a file from the list
 249    */
 250    public interface RecentFileAction {
 251    public void actionPerformed(FileOpenSelector selector);
 252    }
 253   
 254    /** Apply the passed runnable to all menus, i.e. _fileMenu and all menus in
 255    * _mirroredMenus. The menu is passed to the runnable in its parameter.
 256    * @param r Runnable to apply to all menus. */
 257  126 public void _do(Runnable1<JMenu> r) {
 258  126 r.run(_fileMenu);
 259  126 for(JMenu fileMenu: _mirroredMenus) {
 260  0 r.run(fileMenu);
 261    }
 262    }
 263   
 264    /** Insert a separator into all menus at the specified position.
 265    * @param pos position for the separator. */
 266  20 public void _insertSeparator(final int pos) {
 267  20 _do(new Runnable1<JMenu>() {
 268  20 public void run(JMenu fileMenu) {
 269  20 fileMenu.insertSeparator(pos); //one at top
 270    }
 271    });
 272    }
 273   
 274    /** Remove a menu item from all menus at the specified position.
 275    * @param pos position from which the menu item should be removed . */
 276  8 public void _remove(final int pos) {
 277  8 _do(new Runnable1<JMenu>() {
 278  8 public void run(JMenu fileMenu) {
 279  8 fileMenu.remove(pos);
 280    }
 281    });
 282    }
 283    }