Clover coverage report - DrJava Test Coverage (drjava-20110828-r5448)
Coverage timestamp: Sun Aug 28 2011 03:13:33 CDT
file stats: LOC: 416   Methods: 29
NCLOC: 287   Classes: 4
 
 Source file Conditionals Statements Methods TOTAL
ClipboardHistoryFrame.java 0% 0% 0% 0%
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 javax.swing.event.*;
 41    import java.awt.*;
 42    import java.awt.event.*;
 43    import java.util.List;
 44    import java.util.StringTokenizer;
 45    import java.util.NoSuchElementException;
 46   
 47    import edu.rice.cs.drjava.DrJava;
 48    import edu.rice.cs.drjava.config.OptionConstants;
 49    import edu.rice.cs.drjava.model.ClipboardHistoryModel;
 50    import edu.rice.cs.plt.lambda.Lambda;
 51    import edu.rice.cs.util.StringOps;
 52    import edu.rice.cs.util.swing.SwingFrame;
 53    import edu.rice.cs.util.swing.Utilities;
 54   
 55    /** Frame with history of clipboard. */
 56    public class ClipboardHistoryFrame extends SwingFrame {
 57    /** Interface for an action to be performed when the user closes the frame,
 58    * either by using "OK" or "Cancel".
 59    */
 60    public static interface CloseAction extends Lambda<String, Object> { }
 61   
 62    /** Class to save the frame state, i.e. location and dimensions.*/
 63    public static class FrameState {
 64    private Dimension _dim;
 65    private Point _loc;
 66  0 public FrameState(Dimension d, Point l) {
 67  0 _dim = d;
 68  0 _loc = l;
 69    }
 70  0 public FrameState(String s) {
 71  0 StringTokenizer tok = new StringTokenizer(s);
 72  0 try {
 73  0 int x = Integer.valueOf(tok.nextToken());
 74  0 int y = Integer.valueOf(tok.nextToken());
 75  0 _dim = new Dimension(x, y);
 76  0 x = Integer.valueOf(tok.nextToken());
 77  0 y = Integer.valueOf(tok.nextToken());
 78  0 _loc = new Point(x, y);
 79    }
 80    catch(NoSuchElementException nsee) {
 81  0 throw new IllegalArgumentException("Wrong FrameState string: " + nsee);
 82    }
 83    catch(NumberFormatException nfe) {
 84  0 throw new IllegalArgumentException("Wrong FrameState string: " + nfe);
 85    }
 86    }
 87  0 public FrameState(ClipboardHistoryFrame comp) {
 88  0 _dim = comp.getSize();
 89  0 _loc = comp.getLocation();
 90    }
 91  0 public String toString() {
 92  0 final StringBuilder sb = new StringBuilder();
 93  0 sb.append((int)_dim.getWidth());
 94  0 sb.append(' ');
 95  0 sb.append((int)_dim.getHeight());
 96  0 sb.append(' ');
 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 Dimension getDimension() { return _dim; }
 103  0 public Point getLocation() { return _loc; }
 104    }
 105   
 106    /** Clipboard history model */
 107    private ClipboardHistoryModel _chm;
 108   
 109    /** Code for the last button that was pressed.*/
 110    private int _buttonPressed;
 111   
 112    /** Ok button.*/
 113    private JButton _okButton;
 114   
 115    /** Cancel button. */
 116    private JButton _cancelButton;
 117   
 118    /** List with history. */
 119    private JList _historyList;
 120   
 121    /** Text area for that previews the history content. */
 122    private JTextArea _previewArea;
 123   
 124    /** Last frame state. It can be stored and restored. */
 125    private FrameState _lastState = null;
 126   
 127    /** Owner frame. */
 128    private MainFrame _mainFrame;
 129   
 130    /** Close actions for ok and cancel button. */
 131    private CloseAction _okAction, _cancelAction;
 132   
 133    /** Create a new clipboard history frame.
 134    * @param owner owner frame
 135    * @param title dialog title
 136    * @param chm the clipboard history model
 137    * @param okAction the action to perform when OK is clicked
 138    * @param cancelAction the action to perform when Cancel is clicked
 139    */
 140  0 public ClipboardHistoryFrame(MainFrame owner, String title, ClipboardHistoryModel chm,
 141    CloseAction okAction, CloseAction cancelAction) {
 142  0 super(title);
 143  0 _chm = chm;
 144  0 _mainFrame = owner;
 145  0 _okAction = okAction;
 146  0 _cancelAction = cancelAction;
 147  0 init();
 148  0 initDone(); // call mandated by SwingFrame contract
 149    }
 150   
 151    /** Returns the last state of the frame, i.e. the location and dimension.
 152    * @return frame state
 153    */
 154  0 public FrameState getFrameState() { return _lastState; }
 155   
 156    /** Sets state of the frame, i.e. the location and dimension of the frame for the next use.
 157    * @param ds State to update to, or {@code null} to reset
 158    */
 159  0 public void setFrameState(FrameState ds) {
 160  0 _lastState = ds;
 161  0 if (_lastState != null) {
 162  0 setSize(_lastState.getDimension());
 163  0 setLocation(_lastState.getLocation());
 164  0 validate();
 165    }
 166    }
 167   
 168    /** Sets state of the frame, i.e. the location and dimension of the frame for the next use.
 169    * @param s State to update to, or {@code null} to reset
 170    */
 171  0 public void setFrameState(String s) {
 172  0 try { _lastState = new FrameState(s); }
 173  0 catch(IllegalArgumentException e) { _lastState = null; }
 174  0 if (_lastState != null) {
 175  0 setSize(_lastState.getDimension());
 176  0 setLocation(_lastState.getLocation());
 177  0 validate();
 178    }
 179    else {
 180  0 Dimension parentDim = (_mainFrame != null) ? _mainFrame.getSize() : getToolkit().getScreenSize();
 181  0 int xs = (int)parentDim.getWidth()/3;
 182  0 int ys = (int)parentDim.getHeight()/4;
 183  0 setSize(Math.max(xs,400), Math.max(ys, 400));
 184  0 Utilities.setPopupLoc(this, _mainFrame);
 185    }
 186    }
 187   
 188    /** Return the code for the last button that was pressed. This will be either JOptionPane.OK_OPTION or
 189    * JOptionPane.CANCEL_OPTION.
 190    * @return button code
 191    */
 192  0 public int getButtonPressed() {
 193  0 return _buttonPressed;
 194    }
 195   
 196    /** Initialize the frame. */
 197  0 private void init() {
 198  0 addComponentListener(new java.awt.event.ComponentAdapter() {
 199  0 public void componentResized(ComponentEvent e) {
 200  0 validate();
 201  0 _historyList.ensureIndexIsVisible(_historyList.getSelectedIndex());
 202    }
 203    });
 204   
 205  0 JRootPane rootPane = this.getRootPane();
 206  0 InputMap iMap = rootPane.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
 207  0 iMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), "escape");
 208   
 209  0 ActionMap aMap = rootPane.getActionMap();
 210  0 aMap.put("escape", new AbstractAction() {
 211  0 public void actionPerformed(ActionEvent e) {
 212  0 cancelButtonPressed();
 213    }
 214    });
 215   
 216  0 _historyList = new JList();
 217  0 _historyList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
 218  0 _historyList.addListSelectionListener(new ListSelectionListener() {
 219  0 public void valueChanged(ListSelectionEvent e) {
 220  0 updatePreview();
 221    }
 222    });
 223  0 _historyList.setFont(DrJava.getConfig().getSetting(OptionConstants.FONT_MAIN));
 224  0 _historyList.setCellRenderer(new DefaultListCellRenderer() {
 225  0 public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
 226  0 Component c = super.getListCellRendererComponent(list,value,index,isSelected,cellHasFocus);
 227  0 c.setForeground(DrJava.getConfig().getSetting(OptionConstants.DEFINITIONS_NORMAL_COLOR));
 228  0 return c;
 229    }
 230    });
 231  0 _historyList.addFocusListener(new FocusAdapter() {
 232   
 233  0 public void focusLost(FocusEvent e) {
 234  0 if ((e.getOppositeComponent() != _previewArea) &&
 235    (e.getOppositeComponent() != _okButton) &&
 236    (e.getOppositeComponent() != _cancelButton)) {
 237  0 _historyList.requestFocus();
 238    }
 239    }
 240    });
 241   
 242    // buttons
 243  0 _okButton = new JButton("OK");
 244  0 _okButton.addActionListener(new ActionListener() {
 245  0 public void actionPerformed(ActionEvent e) {
 246  0 okButtonPressed();
 247    }
 248    });
 249   
 250  0 _cancelButton = new JButton("Cancel");
 251  0 _cancelButton.addActionListener(new ActionListener() {
 252  0 public void actionPerformed(ActionEvent e) {
 253  0 cancelButtonPressed();
 254    }
 255    });
 256   
 257    // put everything together
 258  0 Container contentPane = getContentPane();
 259   
 260  0 GridBagLayout layout = new GridBagLayout();
 261  0 contentPane.setLayout(layout);
 262   
 263  0 GridBagConstraints c = new GridBagConstraints();
 264  0 c.anchor = GridBagConstraints.NORTHWEST;
 265  0 c.weightx = 1.0;
 266  0 c.weighty = 0.0;
 267  0 c.gridwidth = GridBagConstraints.REMAINDER; // end row
 268  0 c.insets.top = 2;
 269  0 c.insets.left = 2;
 270  0 c.insets.bottom = 2;
 271  0 c.insets.right = 2;
 272   
 273  0 c.fill = GridBagConstraints.BOTH;
 274  0 c.weighty = 1.0;
 275  0 contentPane.add(new JScrollPane(_historyList, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
 276    JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED),
 277    c);
 278   
 279  0 _previewArea = new JTextArea("");
 280  0 _previewArea.setEditable(false);
 281  0 _previewArea.setDragEnabled(false);
 282  0 _previewArea.setEnabled(false);
 283  0 _previewArea.setFont(DrJava.getConfig().getSetting(OptionConstants.FONT_MAIN));
 284  0 _previewArea.setDisabledTextColor(DrJava.getConfig().getSetting(OptionConstants.DEFINITIONS_NORMAL_COLOR));
 285  0 c.weighty = 2.0;
 286  0 contentPane.add(new JScrollPane(_previewArea, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
 287    JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED),
 288    c);
 289   
 290  0 c.anchor = GridBagConstraints.SOUTH;
 291   
 292  0 JPanel buttonPanel = new JPanel(new GridBagLayout());
 293  0 GridBagConstraints bc = new GridBagConstraints();
 294  0 bc.insets.left = 2;
 295  0 bc.insets.right = 2;
 296  0 buttonPanel.add(_okButton, bc);
 297  0 buttonPanel.add(_cancelButton, bc);
 298   
 299  0 c.weighty = 0.0;
 300  0 contentPane.add(buttonPanel, c);
 301   
 302  0 Dimension parentDim = (_mainFrame != null) ? _mainFrame.getSize() : getToolkit().getScreenSize();
 303  0 int xs = (int)parentDim.getWidth()/3;
 304  0 int ys = (int)parentDim.getHeight()/4;
 305  0 setSize(Math.max(xs,400), Math.max(ys, 300));
 306  0 Utilities.setPopupLoc(this, _mainFrame);
 307   
 308  0 updateView();
 309    }
 310   
 311    protected WindowAdapter _windowListener = new WindowAdapter() {
 312  0 public void windowDeactivated(WindowEvent we) {
 313  0 ClipboardHistoryFrame.this.toFront();
 314    }
 315  0 public void windowClosing(WindowEvent we) {
 316  0 cancelButtonPressed();
 317    }
 318    };
 319   
 320    /** Validates before changing visibility. Only runs in the event thread.
 321    * @param vis true if frame should be shown, false if it should be hidden.
 322    */
 323  0 public void setVisible(boolean vis) {
 324  0 assert EventQueue.isDispatchThread();
 325  0 validate();
 326  0 if (vis) {
 327  0 _mainFrame.hourglassOn();
 328  0 updateView();
 329  0 _historyList.requestFocus();
 330  0 toFront();
 331    }
 332    else {
 333  0 removeWindowFocusListener(_windowListener);
 334  0 _mainFrame.hourglassOff();
 335  0 _mainFrame.toFront();
 336    }
 337  0 super.setVisible(vis);
 338    }
 339   
 340    /** Update the displays based on the model. */
 341  0 private void updateView() {
 342  0 List<String> strs = _chm.getStrings();
 343  0 ListItem[] arr = new ListItem[strs.size()];
 344  0 for(int i = 0; i < strs.size(); ++i) arr[strs.size()-i-1] = new ListItem(strs.get(i));
 345  0 _historyList.setListData(arr);
 346  0 if (_historyList.getModel().getSize() > 0) {
 347  0 _historyList.setSelectedIndex(0);
 348  0 getRootPane().setDefaultButton(_okButton);
 349  0 _okButton.setEnabled(true);
 350    }
 351    else {
 352  0 getRootPane().setDefaultButton(_cancelButton);
 353  0 _okButton.setEnabled(false);
 354    }
 355  0 updatePreview();
 356    }
 357   
 358    /** Update the preview area based on the model. */
 359  0 private void updatePreview() {
 360  0 String text = "";
 361  0 if (_historyList.getModel().getSize() > 0) {
 362  0 int index = _historyList.getSelectedIndex();
 363  0 if (index != -1) {
 364  0 text = ((ListItem)_historyList.getModel().getElementAt(_historyList.getSelectedIndex())).getFull();
 365    }
 366    }
 367   
 368  0 _previewArea.setText(text);
 369  0 _previewArea.setCaretPosition(0);
 370    }
 371   
 372    /** Handle OK button. */
 373  0 private void okButtonPressed() {
 374  0 _lastState = new FrameState(ClipboardHistoryFrame.this);
 375  0 setVisible(false);
 376  0 if (_historyList.getModel().getSize() > 0) {
 377  0 _buttonPressed = JOptionPane.OK_OPTION;
 378  0 String s = ((ListItem)_historyList.getModel().getElementAt(_historyList.getSelectedIndex())).getFull();
 379  0 _chm.put(s);
 380  0 _okAction.value(s);
 381    }
 382    else {
 383  0 _buttonPressed = JOptionPane.CANCEL_OPTION;
 384  0 Toolkit.getDefaultToolkit().beep();
 385  0 _cancelAction.value(null);
 386    }
 387    }
 388   
 389    /** Handle cancel button. */
 390  0 private void cancelButtonPressed() {
 391  0 _buttonPressed = JOptionPane.CANCEL_OPTION;
 392  0 _lastState = new FrameState(ClipboardHistoryFrame.this);
 393  0 setVisible(false);
 394  0 _cancelAction.value(null);
 395    }
 396   
 397    /** Keeps a full string, but toString is only the first line. */
 398    private static class ListItem {
 399    private String full, display;
 400  0 public ListItem(String s) {
 401  0 full = s;
 402  0 int index1 = s.indexOf('\n');
 403  0 if (index1 == -1) index1 = s.length();
 404  0 int index2 = s.indexOf(StringOps.EOL);
 405  0 if (index2 == -1) index2 = s.length();
 406  0 display = s.substring(0, Math.min(index1, index2));
 407    }
 408  0 public String getFull() { return full; }
 409  0 public String toString() { return display; }
 410    // public boolean equals(Object o) {
 411    // if (o == null || getClass() != o.getClass()) return false;
 412    // return full.equals(((ListItem)o).full);
 413    // }
 414    // public int hashCode() { return (full != null ? full.hashCode() : 0); }
 415    }
 416    }