Clover coverage report - DrJava Test Coverage (drjava-20120304-r5456)
Coverage timestamp: Sun Mar 4 2012 03:13:23 CST
file stats: LOC: 590   Methods: 55
NCLOC: 423   Classes: 5
 
 Source file Conditionals Statements Methods TOTAL
VectorOptionComponent.java 27% 48.1% 41.8% 42.9%
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.config;
 38   
 39    import edu.rice.cs.drjava.config.*;
 40    import edu.rice.cs.drjava.*;
 41    import edu.rice.cs.util.swing.SwingFrame;
 42    import edu.rice.cs.drjava.ui.CommonCloseButton;
 43   
 44    import java.awt.*;
 45    import java.awt.event.*;
 46    import javax.swing.table.*;
 47    import javax.swing.event.TableModelListener;
 48    import javax.swing.event.TableModelEvent;
 49    import javax.swing.event.ListSelectionListener;
 50    import javax.swing.event.ListSelectionEvent;
 51    import javax.swing.event.MouseInputListener;
 52    import javax.swing.*;
 53    import javax.swing.border.EmptyBorder;
 54    import javax.swing.plaf.basic.BasicTableUI;
 55    import java.util.Vector;
 56    import java.util.List;
 57    import java.util.ArrayList;
 58   
 59    /** Graphical form of a VectorOption for the Extra Classpath option. Uses a file chooser for each String element.
 60    * @version $Id: VectorOptionComponent.java 5245 2010-05-07 02:59:04Z mgricken $
 61    */
 62    public abstract class VectorOptionComponent<T> extends OptionComponent<Vector<T>,JComponent> implements OptionConstants {
 63    protected JScrollPane _tableScrollPane;
 64    protected JPanel _panel;
 65    protected JTable _table;
 66    protected JPanel _buttonPanel;
 67    protected JButton _moveUpButton;
 68    protected JButton _moveDownButton;
 69    protected boolean _moveButtonEnabled = false;
 70    protected AbstractTableModel _tableModel;
 71    protected JButton _addButton;
 72    protected JButton _removeButton;
 73    protected JTable _buttonTable;
 74    protected AbstractTableModel _buttonTableModel;
 75    protected Vector<T> _data;
 76    protected String[] _columnNames;
 77    protected String _description;
 78    protected int _minRows = 0; // display arbitrarily many
 79    protected int _maxRows = 0; // display arbitrarily many
 80   
 81    /** Builds a new VectorOptionComponent with hidden column name.
 82    * @param opt the option
 83    * @param text the label to display
 84    * @param parent the parent frame
 85    */
 86  0 public VectorOptionComponent(VectorOption<T> opt, String text, SwingFrame parent) {
 87  0 this(opt, text, parent, new String[0]);
 88    }
 89   
 90    /** Builds a new VectorOptionComponent.
 91    * @param opt the option
 92    * @param text the label to display
 93    * @param parent the parent frame
 94    * @param colNames column names or empty array to hide
 95    */
 96  0 public VectorOptionComponent(VectorOption<T> opt, String text, SwingFrame parent, String[] colNames) {
 97  0 this(opt, text, parent, colNames, null, false);
 98    }
 99   
 100    /** Constructor that allows for a tooltip description.
 101    */
 102  0 public VectorOptionComponent(VectorOption<T> opt, String text, SwingFrame parent, String[] colNames,
 103    String description) {
 104  0 this(opt, text, parent, colNames, description, false);
 105    }
 106   
 107    /** Builds a new VectorOptionComponent.
 108    * @param opt the option
 109    * @param text the label to display
 110    * @param parent the parent frame
 111    * @param colNames column names or empty array to hide
 112    * @param moveButtonEnabled true if the move buttons should be enabled
 113    */
 114  23746 public VectorOptionComponent(VectorOption<T> opt, String text, SwingFrame parent, String[] colNames,
 115    String description, boolean moveButtonEnabled) {
 116  23746 super(opt, text, parent);
 117  23746 _columnNames = colNames;
 118  23746 _moveButtonEnabled = moveButtonEnabled;
 119   
 120    //set up table
 121  23746 _data = new Vector<T>();
 122  23746 _tableModel = _makeDecoratedTableModel(_makeTableModel());
 123  23746 _table = new JTable(_tableModel) {
 124    {
 125    // set the column with the "remove" buttons to width 18 (icon is width 16)
 126  23746 getColumnModel().getColumn(getColumnCount()-1).setMinWidth(18);
 127  23746 getColumnModel().getColumn(getColumnCount()-1).setMaxWidth(18);
 128    }
 129   
 130    // auto size the columns
 131  0 public Component prepareRenderer(final TableCellRenderer renderer,
 132    final int row, final int column) {
 133  0 final Component prepareRenderer = super.prepareRenderer(renderer, row, column);
 134  0 final TableColumn tableColumn = getColumnModel().getColumn(column);
 135   
 136  0 tableColumn.setPreferredWidth(Math.max(prepareRenderer.getPreferredSize().width,tableColumn.getPreferredWidth()));
 137   
 138  0 return prepareRenderer;
 139    }
 140    };
 141    // if moving up and down is enabled, allow column drag and drop
 142  23746 if (_moveButtonEnabled) {
 143  76 _table.setUI(new DragDropRowTableUI());
 144    }
 145  23746 _table.setColumnSelectionAllowed(false);
 146  23746 _table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
 147  23746 _table.getTableHeader().setReorderingAllowed(false);
 148   
 149    // create the remove button
 150  23746 _removeButton = new CommonCloseButton();
 151  23746 ButtonEditor buttonEditor = new ButtonEditor(_removeButton);
 152  23746 _removeButton.addActionListener(new ActionListener() {
 153  0 public void actionPerformed(ActionEvent e) {
 154  0 _removeAction();
 155    }
 156    });
 157    // add remove button as default renderer/editor for buttons
 158  23746 _table.setDefaultRenderer(JButton.class, new ComponentCellRenderer());
 159  23746 _table.setDefaultEditor(JButton.class, buttonEditor);
 160   
 161    // create other buttons
 162  23746 _addButton = new JButton(_getAddAction());
 163  23746 _moveUpButton = new JButton(new AbstractAction("Move Up") {
 164  0 public void actionPerformed(ActionEvent ae) {
 165  0 _moveUpAction();
 166    }
 167    });
 168  23746 _moveDownButton = new JButton(new AbstractAction("Move Down") {
 169  0 public void actionPerformed(ActionEvent ae) {
 170  0 _moveDownAction();
 171    }
 172    });
 173   
 174    // list of buttons
 175  23746 final java.util.List<JButton> buttons = getButtons();
 176    // table model of buttons, for the table situated under the values table
 177    // one row, n buttons
 178  23746 _buttonTableModel = new AbstractTableModel() {
 179  23898 public String getColumnName(int col) { return ""; }
 180  152 public int getRowCount() { return 1; }
 181  47644 public int getColumnCount() { return buttons.size(); }
 182  0 public Object getValueAt(int row, int column) { return buttons.get(column); }
 183  0 public Class<?> getColumnClass(int col) { return JButton.class; }
 184  0 public boolean isCellEditable(int row, int col) { return true; }
 185  152 public void setValueAt(Object value, int row, int col) { fireTableCellUpdated(row, col); }
 186    };
 187    // button table
 188  23746 _buttonTable = new JTable(_buttonTableModel);
 189  23746 _buttonTable.setColumnSelectionAllowed(false);
 190  23746 _buttonTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
 191  23746 _buttonTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
 192  23746 _buttonTable.getTableHeader().setReorderingAllowed(false);
 193   
 194    // add button editors/renderers to the button table
 195  23746 for(int i = 0; i < _buttonTable.getColumnCount(); ++i) {
 196  23898 buttonEditor = new ButtonEditor(buttons.get(i));
 197  23898 _buttonTable.getColumnModel().getColumn(i).setCellEditor(buttonEditor);
 198    }
 199  23746 _buttonTable.setDefaultRenderer(JButton.class, new ComponentCellRenderer());
 200  23746 _buttonTable.setTableHeader(null);
 201   
 202    // if moving up and down is enabled, add a selection listener that
 203    // enabled and disables the move up/down buttons if we have enough elements
 204    // in the table and a row is selected
 205  23746 if (_moveButtonEnabled) {
 206  76 ListSelectionListener selListener = new ListSelectionListener() {
 207  0 public void valueChanged(ListSelectionEvent e) {
 208  0 updateButtons();
 209    }
 210    };
 211  76 _table.getSelectionModel().addListSelectionListener(selListener);
 212  76 _table.getColumnModel().getSelectionModel().addListSelectionListener(selListener);
 213    }
 214   
 215    // add components
 216  23746 _tableScrollPane = new JScrollPane(_table, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
 217    JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
 218  23746 JPanel tablesPanel = new JPanel(new BorderLayout());
 219  23746 tablesPanel.add(_tableScrollPane, BorderLayout.CENTER);
 220  23746 tablesPanel.add(_buttonTable, BorderLayout.SOUTH);
 221   
 222  23746 _panel = new JPanel(new BorderLayout());
 223  23746 _panel.add(tablesPanel, BorderLayout.CENTER);
 224  23746 _panel.add(Box.createRigidArea(new Dimension(0,10)), BorderLayout.SOUTH);
 225   
 226  23746 resetToCurrent();
 227   
 228  23746 if (_columnNames.length == 0) {
 229  23746 _table.setTableHeader(null);
 230  23746 _tableScrollPane.setColumnHeaderView(null);
 231    }
 232   
 233  23746 setDescription(description);
 234  23746 updateButtons();
 235  23746 resizeTable();
 236  23746 setComponent(_panel);
 237    }
 238   
 239    /** Returns the decorated table model. This adds another column to it with remove buttons. */
 240  23746 protected AbstractTableModel _makeDecoratedTableModel(final AbstractTableModel other) {
 241  23746 return new AbstractTableModel() {
 242  47492 public String getColumnName(int col) {
 243  47492 if (col==other.getColumnCount()) {
 244  23746 return "";
 245    }
 246    else {
 247  23746 return other.getColumnName(col);
 248    }
 249    }
 250  113732 public int getRowCount() { return other.getRowCount(); }
 251  71238 public int getColumnCount() { return other.getColumnCount()+1; }
 252  0 public Object getValueAt(int row, int column) {
 253  0 if (column==other.getColumnCount()) {
 254  0 return new CommonCloseButton();
 255    }
 256    else {
 257  0 return other.getValueAt(row, column);
 258    }
 259    }
 260  0 public Class<?> getColumnClass(int col) {
 261  0 if (col==other.getColumnCount()) {
 262  0 return JButton.class;
 263    }
 264    else {
 265  0 return other.getColumnClass(col);
 266    }
 267    }
 268  0 public boolean isCellEditable(int row, int col) {
 269  0 if (col==other.getColumnCount()) {
 270  0 return true;
 271    }
 272    else {
 273  0 return other.isCellEditable(row, col);
 274    }
 275    }
 276  0 public void setValueAt(Object value, int row, int col) {
 277  0 if (col==other.getColumnCount()) {
 278  0 fireTableCellUpdated(row, col);
 279    }
 280    else {
 281  0 other.setValueAt(value, row, col);
 282    }
 283    }
 284    };
 285    }
 286   
 287    /** Returns the table model. Can be overridden by subclasses. */
 288  193 protected AbstractTableModel _makeTableModel() {
 289  193 return new AbstractTableModel() {
 290  193 public String getColumnName(int col) { return (_columnNames.length == 0)?super.getColumnName(col):_columnNames[col]; }
 291  411 public int getRowCount() { return _data.size(); }
 292  965 public int getColumnCount() { return 1; }
 293  0 public Object getValueAt(int row, int column) { return _data.get(row); }
 294    };
 295    }
 296   
 297    /** Renderer for GUI components. */
 298    protected static class ComponentCellRenderer implements TableCellRenderer {
 299    DefaultTableCellRenderer _default = new DefaultTableCellRenderer();
 300  0 public Component getTableCellRendererComponent(JTable table, Object value,
 301    boolean isSelected, boolean hasFocus, int row, int column) {
 302  0 if (value instanceof Component) return (Component)value;
 303  0 return _default.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
 304    }
 305    }
 306   
 307    /** Editor for buttons. Clicking causes the button action to be performed. */
 308    protected static class ButtonEditor extends DefaultCellEditor {
 309  47644 public ButtonEditor(JButton b) {
 310  47644 super(new JCheckBox());
 311  47644 editorComponent = b;
 312  47644 setClickCountToStart(1);
 313  47644 b.addActionListener(new ActionListener() {
 314  0 public void actionPerformed(ActionEvent e) {
 315  0 fireEditingStopped();
 316    }
 317    });
 318    }
 319   
 320  0 protected void fireEditingStopped() {
 321  0 super.fireEditingStopped();
 322    }
 323   
 324  0 public Object getCellEditorValue() {
 325  0 return editorComponent;
 326    }
 327   
 328  0 public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
 329  0 return editorComponent;
 330    }
 331    }
 332   
 333    /** Drag and drop UI for tables. */
 334    public class DragDropRowTableUI extends BasicTableUI {
 335    private boolean draggingRow = false;
 336    private int startDragPoint;
 337    private int dyOffset;
 338   
 339  76 protected MouseInputListener createMouseInputListener() {
 340  76 return new DragDropRowMouseInputHandler();
 341    }
 342   
 343  0 public void paint(Graphics g, JComponent c) {
 344  0 super.paint(g, c);
 345   
 346  0 if (draggingRow) {
 347  0 g.setColor(_table.getParent().getBackground());
 348  0 Rectangle cellRect = _table.getCellRect(_table.getSelectedRow(), 0, false);
 349  0 g.copyArea(cellRect.x, cellRect.y, _table.getWidth(), _table.getRowHeight(), cellRect.x, dyOffset);
 350   
 351  0 if (dyOffset < 0) {
 352  0 g.fillRect(cellRect.x, cellRect.y + (_table.getRowHeight() + dyOffset), _table.getWidth(), (dyOffset * -1));
 353    } else {
 354  0 g.fillRect(cellRect.x, cellRect.y, _table.getWidth(), dyOffset);
 355    }
 356    }
 357    }
 358   
 359    class DragDropRowMouseInputHandler extends MouseInputHandler {
 360  0 public void mousePressed(MouseEvent e) {
 361  0 super.mousePressed(e);
 362  0 startDragPoint = (int)e.getPoint().getY();
 363    }
 364   
 365  0 public void mouseDragged(MouseEvent e) {
 366  0 if (_data.size()<2) return;
 367  0 int fromRow = _table.getSelectedRow();
 368   
 369  0 if (fromRow >= 0) {
 370  0 draggingRow = true;
 371   
 372  0 int rowHeight = _table.getRowHeight();
 373  0 int middleOfSelectedRow = (rowHeight * fromRow) + (rowHeight / 2);
 374   
 375  0 int toRow = -1;
 376  0 int yMousePoint = (int)e.getPoint().getY();
 377   
 378  0 if (yMousePoint < (middleOfSelectedRow - rowHeight)) {
 379    // Move row up
 380  0 toRow = fromRow - 1;
 381  0 } else if (yMousePoint > (middleOfSelectedRow + rowHeight)) {
 382    // Move row down
 383  0 toRow = fromRow + 1;
 384    }
 385   
 386  0 if (toRow >= 0 && toRow < _table.getRowCount()) {
 387  0 T fromValue = _data.get(fromRow);
 388  0 T toValue = _data.get(toRow);
 389  0 _data.set(fromRow, toValue);
 390  0 _data.set(toRow, fromValue);
 391  0 _tableModel.fireTableRowsUpdated(Math.min(fromRow,toRow),Math.max(fromRow,toRow));
 392  0 _table.setRowSelectionInterval(toRow, toRow);
 393  0 startDragPoint = yMousePoint;
 394    }
 395   
 396  0 dyOffset = (startDragPoint - yMousePoint) * -1;
 397  0 _table.repaint();
 398    }
 399    }
 400   
 401  0 public void mouseReleased(MouseEvent e){
 402  0 super.mouseReleased(e);
 403   
 404  0 draggingRow = false;
 405  0 table.repaint();
 406    }
 407    }
 408    }
 409   
 410    /** Remove selected rows. */
 411  0 protected void _removeAction() {
 412  0 int[] rows = _table.getSelectedRows();
 413  0 if (rows.length > 0) {
 414    // remove starting from the back so the indices don't have to be adjusted
 415  0 for(int i=rows.length-1; i >= 0; --i) {
 416  0 if (rows[i] >= _data.size()) continue;
 417  0 _removeIndex(rows[i]);
 418    }
 419  0 int last = rows[rows.length-1];
 420  0 if (last == _data.size()) { // we removed the last element
 421  0 if (last > 0) { // and there's more than one element in the list
 422  0 _table.getSelectionModel().setSelectionInterval(last-1,last-1);
 423    }
 424    }
 425    else {
 426  0 _table.getSelectionModel().setSelectionInterval(last,last);
 427    }
 428  0 notifyChangeListeners();
 429    }
 430    }
 431   
 432    /** Move selected rows up by one row. */
 433  0 protected void _moveUpAction() {
 434  0 int[] rows = _table.getSelectedRows();
 435  0 if (rows.length > 0) {
 436  0 _table.getSelectionModel().clearSelection();
 437  0 for(int i = 0; i < rows.length; ++i) {
 438  0 if (rows[i] >= _data.size()) continue;
 439  0 if (rows[i] > 0) {
 440  0 T el = _data.remove(rows[i]);
 441  0 _data.insertElementAt(el, rows[i]-1);
 442  0 _table.getSelectionModel().addSelectionInterval(rows[i]-1,rows[i]-1);
 443  0 _tableModel.fireTableRowsUpdated(rows[i]-1,rows[i]);
 444    }
 445    }
 446  0 notifyChangeListeners();
 447    }
 448    }
 449   
 450    /** Move selected rows down by one row. */
 451  0 protected void _moveDownAction() {
 452  0 int[] rows = _table.getSelectedRows();
 453  0 if (rows.length > 0) {
 454  0 _table.getSelectionModel().clearSelection();
 455  0 for(int i = 0; i < rows.length; ++i) {
 456  0 if (rows[i] >= _data.size()) continue;
 457  0 if (rows[i] < _data.size()-1) {
 458  0 T el = _data.remove(rows[i]);
 459  0 _data.insertElementAt(el, rows[i]+1);
 460  0 _table.getSelectionModel().addSelectionInterval(rows[i]+1,rows[i]+1);
 461  0 _tableModel.fireTableRowsUpdated(rows[i],rows[i]+1);
 462    }
 463    }
 464  0 notifyChangeListeners();
 465    }
 466    }
 467   
 468    /** Add the value to the table, update and resize it. */
 469  0 protected void _addValue(T value) {
 470  0 _data.add(value);
 471  0 _tableModel.fireTableRowsInserted(_data.size()-1, _data.size()-1);
 472  0 _table.getSelectionModel().setSelectionInterval(_data.size()-1,_data.size()-1);
 473  0 notifyChangeListeners();
 474  0 resizeTable();
 475    }
 476   
 477    /** Remove the value at index i, update the table and resize it. */
 478  0 protected void _removeIndex(int i) {
 479  0 _data.remove(i);
 480  0 _tableModel.fireTableRowsDeleted(i,i);
 481  0 resizeTable();
 482    }
 483   
 484    /** Return the buttons that should be added to the table underneath. */
 485  23746 protected java.util.List<JButton> getButtons() {
 486  23746 List<JButton> buttons = new ArrayList<JButton>();
 487  23746 buttons.add(_addButton);
 488  23746 if (_moveButtonEnabled) {
 489  76 buttons.add(_moveUpButton);
 490  76 buttons.add(_moveDownButton);
 491    }
 492  23746 return buttons;
 493    }
 494   
 495    /** Enable and disable buttons. */
 496  23746 protected void updateButtons() {
 497  23746 boolean editable = DrJava.getConfig().isEditable(_option);
 498  23746 if (_moveButtonEnabled) {
 499  76 int[] rows = _table.getSelectedRows();
 500  76 boolean enable = (rows.length > 0) && (_data.size()>1) && editable;
 501  76 _moveUpButton.setEnabled(enable);
 502  76 _moveDownButton.setEnabled(enable);
 503  76 _buttonTableModel.setValueAt(null, 0, 1);
 504  76 _buttonTableModel.setValueAt(null, 0, 2);
 505    }
 506  23746 _addButton.setEnabled(editable);
 507  23746 _removeButton.setEnabled(editable);
 508  23746 _table.setEnabled(editable);
 509    }
 510   
 511    /** Sets the tooltip description text for this option.
 512    * @param description the tooltip text
 513    */
 514  23746 public void setDescription(String description) {
 515  23746 _description = description;
 516  23746 _tableScrollPane.setToolTipText(description);
 517  23746 _table.setToolTipText(description);
 518  23746 _label.setToolTipText(description);
 519    }
 520   
 521    /** Updates the config object with the new setting.
 522    * @return true if the new value is set successfully
 523    */
 524  8 public boolean updateConfig() {
 525  8 Vector<T> oldValue = DrJava.getConfig().getSetting(_option);
 526  8 Vector<T> newValue = getValue();
 527   
 528  8 if ((oldValue.size() != newValue.size()) || // allow cheap short-circuiting
 529    (!oldValue.equals(newValue))) {
 530  6 DrJava.getConfig().setSetting(_option, newValue);
 531  6 resetToCurrent();
 532    }
 533  8 return true;
 534    }
 535   
 536    /** Accessor to the current contents of the table.
 537    * @return The contents of the list in this component in the form of a Vector.
 538    */
 539  8 public Vector<T> getValue() {
 540  8 return new Vector<T>(_data);
 541    }
 542   
 543    /** Displays the given value. */
 544  23768 public void setValue(Vector<T> value) {
 545  23768 _data = new Vector<T>(value);
 546  23768 _tableModel.fireTableDataChanged();
 547  23768 resizeTable();
 548    }
 549   
 550    /** Displays the given value. */
 551  0 public void setValue(ArrayList<T> value) {
 552  0 _data = new Vector<T>(value);
 553  0 _tableModel.fireTableDataChanged();
 554  0 resizeTable();
 555    }
 556   
 557    /** Set the minimum and maximum number of rows to display before using a scrollbar, or 0 for arbitrarily many. */
 558  0 public void setRows(int minRows, int maxRows) { _minRows = minRows; _maxRows = maxRows; resizeTable(); }
 559   
 560    /** Return the required height of the table. */
 561  47514 protected int getTableHeight() {
 562  47514 int pixelsPerRow = 16;
 563  47514 int rows = _tableModel.getRowCount();
 564  47514 if (rows == 0) {
 565  14405 rows = 1;
 566    }
 567    else {
 568  33109 pixelsPerRow = _table.getPreferredSize().height/rows;
 569    }
 570  47514 if (_maxRows > 0) {
 571  0 rows = Math.min(rows, _maxRows);
 572    }
 573  47514 if (_minRows > 0) {
 574  0 rows = Math.max(rows, _minRows);
 575    }
 576    // FontMetrics fm = _table.getFontMetrics(_table.getFont());
 577    // int pixelsPerRow = fm.getHeight() + 1;
 578  47514 int topBound = _tableScrollPane.getViewportBorderBounds().y;
 579  47514 return rows * pixelsPerRow + topBound + 2;
 580    }
 581   
 582    /** Resizes the display table */
 583  47514 public void resizeTable() {
 584  47514 _tableScrollPane.setPreferredSize(new Dimension(0, getTableHeight()));
 585  47514 _parent.validate();
 586    }
 587   
 588    /** Gets an action that adds a component to the set of options. */
 589    protected abstract Action _getAddAction();
 590    }