    rev 48858 : Work in progress for JDK-6303622
    Use generic in Swing components like JComboBox
    1. Added generic return type and parameter type for JComboBox.
    2. Modified JList related classes as well.
    3. Reverted the changes made to "getSelectedValues" as suggested by Joe.
    4. Modified files that were failing on Linux and Mac as well.

       1 /*
       2  * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
       3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       4  *
       5  * This code is free software; you can redistribute it and/or modify it
       6  * under the terms of the GNU General Public License version 2 only, as
       7  * published by the Free Software Foundation.  Oracle designates this
       8  * particular file as subject to the "Classpath" exception as provided
       9  * by Oracle in the LICENSE file that accompanied this code.
      10  *
      11  * This code is distributed in the hope that it will be useful, but WITHOUT
      12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
      13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      14  * version 2 for more details (a copy is included in the LICENSE file that
      15  * accompanied this code).
      16  *
      17  * You should have received a copy of the GNU General Public License version
      18  * 2 along with this work; if not, write to the Free Software Foundation,
      19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
      20  *
      21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
      22  * or visit www.oracle.com if you need additional information or have any
      23  * questions.
      24  */
      25
      26 package javax.swing;
      27
      28 import java.awt.Component;
      29 import java.awt.event.*;
      30 import java.beans.ConstructorProperties;
      31 import java.lang.Boolean;
      32 import javax.swing.table.*;
      33 import javax.swing.event.*;
      34 import java.util.EventObject;
      35 import javax.swing.tree.*;
      36 import java.io.Serializable;
      37
      38 /**
      39  * The default editor for table and tree cells.
      40  * <p>
      41  * <strong>Warning:</strong>
      42  * Serialized objects of this class will not be compatible with
      43  * future Swing releases. The current serialization support is
      44  * appropriate for short term storage or RMI between applications running
      45  * the same version of Swing.  As of 1.4, support for long term storage
      46  * of all JavaBeans&trade;
      47  * has been added to the <code>java.beans</code> package.
      48  * Please see {@link java.beans.XMLEncoder}.
      49  *
      50  * @author Alan Chung
      51  * @author Philip Milne
      52  * @since 1.2
      53  */
      54 @SuppressWarnings("serial") // Same-version serialization only
      55 public class DefaultCellEditor extends AbstractCellEditor
      56     implements TableCellEditor, TreeCellEditor {
      57
      58 //
      59 //  Instance Variables
      60 //
      61
      62     /** The Swing component being edited. */
      63     protected JComponent editorComponent;
      64     /**
      65      * The delegate class which handles all methods sent from the
      66      * <code>CellEditor</code>.
      67      */
      68     protected EditorDelegate delegate;
      69     /**
      70      * An integer specifying the number of clicks needed to start editing.
      71      * Even if <code>clickCountToStart</code> is defined as zero, it
      72      * will not initiate until a click occurs.
      73      */
      74     protected int clickCountToStart = 1;
      75
      76 //
      77 //  Constructors
      78 //
      79
      80     /**
      81      * Constructs a <code>DefaultCellEditor</code> that uses a text field.
      82      *
      83      * @param textField  a <code>JTextField</code> object
      84      */
      85     @ConstructorProperties({"component"})
      86     public DefaultCellEditor(final JTextField textField) {
      87         editorComponent = textField;
      88         this.clickCountToStart = 2;
      89         delegate = new EditorDelegate() {
      90             public void setValue(Object value) {
      91                 textField.setText((value != null) ? value.toString() : "");
      92             }
      93
      94             public Object getCellEditorValue() {
      95                 return textField.getText();
      96             }
      97         };
      98         textField.addActionListener(delegate);
      99     }
     100
     101     /**
     102      * Constructs a <code>DefaultCellEditor</code> object that uses a check box.
     103      *
     104      * @param checkBox  a <code>JCheckBox</code> object
     105      */
     106     public DefaultCellEditor(final JCheckBox checkBox) {
     107         editorComponent = checkBox;
     108         delegate = new EditorDelegate() {
     109             public void setValue(Object value) {
     110                 boolean selected = false;
     111                 if (value instanceof Boolean) {
     112                     selected = ((Boolean)value).booleanValue();
     113                 }
     114                 else if (value instanceof String) {
     115                     selected = value.equals("true");
     116                 }
     117                 checkBox.setSelected(selected);
     118             }
     119
     120             public Object getCellEditorValue() {
     121                 return Boolean.valueOf(checkBox.isSelected());
     122             }
     123         };
     124         checkBox.addActionListener(delegate);
     125         checkBox.setRequestFocusEnabled(false);
     126     }
     127
     128     /**
     129      * Constructs a <code>DefaultCellEditor</code> object that uses a
     130      * combo box.
     131      * @param <E> the type of the elements of comboBox
     132      * @param comboBox  a <code>JComboBox</code> object
     133      */
     134     @SuppressWarnings("unchecked")
     135     public <E> DefaultCellEditor(final JComboBox<E> comboBox) {
     136         editorComponent = comboBox;
     137         comboBox.putClientProperty("JComboBox.isTableCellEditor", Boolean.TRUE);
     138         delegate = new EditorDelegate() {
     139             public void setValue(Object value) {
     140                 comboBox.setSelectedItem((E)value);
     141             }
     142
     143             public Object getCellEditorValue() {
     144                 return comboBox.getSelectedItem();
     145             }
     146
     147             public boolean shouldSelectCell(EventObject anEvent) {
     148                 if (anEvent instanceof MouseEvent) {
     149                     MouseEvent e = (MouseEvent)anEvent;
     150                     return e.getID() != MouseEvent.MOUSE_DRAGGED;
     151                 }
     152                 return true;
     153             }
     154             public boolean stopCellEditing() {
     155                 if (comboBox.isEditable()) {
     156                     // Commit edited value.
     157                     comboBox.actionPerformed(new ActionEvent(
     158                                      DefaultCellEditor.this, 0, ""));
     159                 }
     160                 return super.stopCellEditing();
     161             }
     162         };
     163         comboBox.addActionListener(delegate);
     164     }
     165
     166     /**
     167      * Returns a reference to the editor component.
     168      *
     169      * @return the editor <code>Component</code>
     170      */
     171     public Component getComponent() {
     172         return editorComponent;
     173     }
     174
     175 //
     176 //  Modifying
     177 //
     178
     179     /**
     180      * Specifies the number of clicks needed to start editing.
     181      *
     182      * @param count  an int specifying the number of clicks needed to start editing
     183      * @see #getClickCountToStart
     184      */
     185     public void setClickCountToStart(int count) {
     186         clickCountToStart = count;
     187     }
     188
     189     /**
     190      * Returns the number of clicks needed to start editing.
     191      * @return the number of clicks needed to start editing
     192      */
     193     public int getClickCountToStart() {
     194         return clickCountToStart;
     195     }
     196
     197 //
     198 //  Override the implementations of the superclass, forwarding all methods
     199 //  from the CellEditor interface to our delegate.
     200 //
     201
     202     /**
     203      * Forwards the message from the <code>CellEditor</code> to
     204      * the <code>delegate</code>.
     205      * @see EditorDelegate#getCellEditorValue
     206      */
     207     public Object getCellEditorValue() {
     208         return delegate.getCellEditorValue();
     209     }
     210
     211     /**
     212      * Forwards the message from the <code>CellEditor</code> to
     213      * the <code>delegate</code>.
     214      * @see EditorDelegate#isCellEditable(EventObject)
     215      */
     216     public boolean isCellEditable(EventObject anEvent) {
     217         return delegate.isCellEditable(anEvent);
     218     }
     219
     220     /**
     221      * Forwards the message from the <code>CellEditor</code> to
     222      * the <code>delegate</code>.
     223      * @see EditorDelegate#shouldSelectCell(EventObject)
     224      */
     225     public boolean shouldSelectCell(EventObject anEvent) {
     226         return delegate.shouldSelectCell(anEvent);
     227     }
     228
     229     /**
     230      * Forwards the message from the <code>CellEditor</code> to
     231      * the <code>delegate</code>.
     232      * @see EditorDelegate#stopCellEditing
     233      */
     234     public boolean stopCellEditing() {
     235         return delegate.stopCellEditing();
     236     }
     237
     238     /**
     239      * Forwards the message from the <code>CellEditor</code> to
     240      * the <code>delegate</code>.
     241      * @see EditorDelegate#cancelCellEditing
     242      */
     243     public void cancelCellEditing() {
     244         delegate.cancelCellEditing();
     245     }
     246
     247 //
     248 //  Implementing the TreeCellEditor Interface
     249 //
     250
     251     /** Implements the <code>TreeCellEditor</code> interface. */
     252     public Component getTreeCellEditorComponent(JTree tree, Object value,
     253                                                 boolean isSelected,
     254                                                 boolean expanded,
     255                                                 boolean leaf, int row) {
     256         String         stringValue = tree.convertValueToText(value, isSelected,
     257                                             expanded, leaf, row, false);
     258
     259         delegate.setValue(stringValue);
     260         return editorComponent;
     261     }
     262
     263 //
     264 //  Implementing the CellEditor Interface
     265 //
     266     /** Implements the <code>TableCellEditor</code> interface. */
     267     public Component getTableCellEditorComponent(JTable table, Object value,
     268                                                  boolean isSelected,
     269                                                  int row, int column) {
     270         delegate.setValue(value);
     271         if (editorComponent instanceof JCheckBox) {
     272             //in order to avoid a "flashing" effect when clicking a checkbox
     273             //in a table, it is important for the editor to have as a border
     274             //the same border that the renderer has, and have as the background
     275             //the same color as the renderer has. This is primarily only
     276             //needed for JCheckBox since this editor doesn't fill all the
     277             //visual space of the table cell, unlike a text field.
     278             TableCellRenderer renderer = table.getCellRenderer(row, column);
     279             Component c = renderer.getTableCellRendererComponent(table, value,
     280                     isSelected, true, row, column);
     281             if (c != null) {
     282                 editorComponent.setOpaque(true);
     283                 editorComponent.setBackground(c.getBackground());
     284                 if (c instanceof JComponent) {
     285                     editorComponent.setBorder(((JComponent)c).getBorder());
     286                 }
     287             } else {
     288                 editorComponent.setOpaque(false);
     289             }
     290         }
     291         return editorComponent;
     292     }
     293
     294
     295 //
     296 //  Protected EditorDelegate class
     297 //
     298
     299     /**
     300      * The protected <code>EditorDelegate</code> class.
     301      */
     302     protected class EditorDelegate implements ActionListener, ItemListener, Serializable {
     303
     304         /**  The value of this cell. */
     305         protected Object value;
     306
     307        /**
     308         * Returns the value of this cell.
     309         * @return the value of this cell
     310         */
     311         public Object getCellEditorValue() {
     312             return value;
     313         }
     314
     315        /**
     316         * Sets the value of this cell.
     317         * @param value the new value of this cell
     318         */
     319         public void setValue(Object value) {
     320             this.value = value;
     321         }
     322
     323        /**
     324         * Returns true if <code>anEvent</code> is <b>not</b> a
     325         * <code>MouseEvent</code>.  Otherwise, it returns true
     326         * if the necessary number of clicks have occurred, and
     327         * returns false otherwise.
     328         *
     329         * @param   anEvent         the event
     330         * @return  true  if cell is ready for editing, false otherwise
     331         * @see #setClickCountToStart
     332         * @see #shouldSelectCell
     333         */
     334         public boolean isCellEditable(EventObject anEvent) {
     335             if (anEvent instanceof MouseEvent) {
     336                 return ((MouseEvent)anEvent).getClickCount() >= clickCountToStart;
     337             }
     338             return true;
     339         }
     340
     341        /**
     342         * Returns true to indicate that the editing cell may
     343         * be selected.
     344         *
     345         * @param   anEvent         the event
     346         * @return  true
     347         * @see #isCellEditable
     348         */
     349         public boolean shouldSelectCell(EventObject anEvent) {
     350             return true;
     351         }
     352
     353        /**
     354         * Returns true to indicate that editing has begun.
     355         *
     356         * @param anEvent          the event
     357         * @return true to indicate editing has begun
     358         */
     359         public boolean startCellEditing(EventObject anEvent) {
     360             return true;
     361         }
     362
     363        /**
     364         * Stops editing and
     365         * returns true to indicate that editing has stopped.
     366         * This method calls <code>fireEditingStopped</code>.
     367         *
     368         * @return  true
     369         */
     370         public boolean stopCellEditing() {
     371             fireEditingStopped();
     372             return true;
     373         }
     374
     375        /**
     376         * Cancels editing.  This method calls <code>fireEditingCanceled</code>.
     377         */
     378        public void cancelCellEditing() {
     379            fireEditingCanceled();
     380        }
     381
     382        /**
     383         * When an action is performed, editing is ended.
     384         * @param e the action event
     385         * @see #stopCellEditing
     386         */
     387         public void actionPerformed(ActionEvent e) {
     388             DefaultCellEditor.this.stopCellEditing();
     389         }
     390
     391        /**
     392         * When an item's state changes, editing is ended.
     393         * @param e the action event
     394         * @see #stopCellEditing
     395         */
     396         public void itemStateChanged(ItemEvent e) {
     397             DefaultCellEditor.this.stopCellEditing();
     398         }
     399     }
     400
     401 } // End of class JCellEditor
    --- EOF ---