7031551: Generics: JComboBox
authorrupashka
Wed, 04 May 2011 10:20:14 +0400
changeset 9665 f43db0b310cc
parent 9495 f0b0ad903f6f
child 9666 b373390818b7
7031551: Generics: JComboBox Reviewed-by: alexp, malenkov
jdk/src/share/classes/javax/swing/ComboBoxModel.java
jdk/src/share/classes/javax/swing/DefaultComboBoxModel.java
jdk/src/share/classes/javax/swing/JComboBox.java
jdk/src/share/classes/javax/swing/MutableComboBoxModel.java
jdk/src/share/classes/javax/swing/plaf/basic/BasicDirectoryModel.java
jdk/src/share/classes/javax/swing/plaf/metal/MetalFileChooserUI.java
jdk/test/javax/swing/JComboBox/7031551/bug7031551.java
--- a/jdk/src/share/classes/javax/swing/ComboBoxModel.java	Fri Apr 29 16:03:09 2011 -0700
+++ b/jdk/src/share/classes/javax/swing/ComboBoxModel.java	Wed May 04 10:20:14 2011 +0400
@@ -33,9 +33,11 @@
  * <code>ListModel</code>. This disjoint behavior allows for the temporary
  * storage and retrieval of a selected item in the model.
  *
+ * @param <E> the type of the elements of this model
+ *
  * @author Arnaud Weber
  */
-public interface ComboBoxModel extends ListModel {
+public interface ComboBoxModel<E> extends ListModel<E> {
 
   /**
    * Set the selected item. The implementation of this  method should notify
--- a/jdk/src/share/classes/javax/swing/DefaultComboBoxModel.java	Fri Apr 29 16:03:09 2011 -0700
+++ b/jdk/src/share/classes/javax/swing/DefaultComboBoxModel.java	Wed May 04 10:20:14 2011 +0400
@@ -24,39 +24,28 @@
  */
 package javax.swing;
 
-import java.beans.*;
 import java.util.*;
 
-import java.awt.*;
-import java.awt.event.*;
-
 import java.io.Serializable;
-import java.io.ObjectOutputStream;
-import java.io.ObjectInputStream;
-import java.io.IOException;
-
-import javax.swing.event.*;
-import javax.swing.plaf.*;
-import javax.swing.border.*;
-
-import javax.accessibility.*;
 
 /**
  * The default model for combo boxes.
  *
+ * @param <E> the type of the elements of this model
+ *
  * @author Arnaud Weber
  * @author Tom Santos
  */
 
-public class DefaultComboBoxModel extends AbstractListModel implements MutableComboBoxModel, Serializable {
-    Vector objects;
+public class DefaultComboBoxModel<E> extends AbstractListModel<E> implements MutableComboBoxModel<E>, Serializable {
+    Vector<E> objects;
     Object selectedObject;
 
     /**
      * Constructs an empty DefaultComboBoxModel object.
      */
     public DefaultComboBoxModel() {
-        objects = new Vector();
+        objects = new Vector<E>();
     }
 
     /**
@@ -65,8 +54,8 @@
      *
      * @param items  an array of Object objects
      */
-    public DefaultComboBoxModel(final Object items[]) {
-        objects = new Vector();
+    public DefaultComboBoxModel(final E items[]) {
+        objects = new Vector<E>();
         objects.ensureCapacity( items.length );
 
         int i,c;
@@ -84,7 +73,7 @@
      *
      * @param v  a Vector object ...
      */
-    public DefaultComboBoxModel(Vector<?> v) {
+    public DefaultComboBoxModel(Vector<E> v) {
         objects = v;
 
         if ( getSize() > 0 ) {
@@ -117,7 +106,7 @@
     }
 
     // implements javax.swing.ListModel
-    public Object getElementAt(int index) {
+    public E getElementAt(int index) {
         if ( index >= 0 && index < objects.size() )
             return objects.elementAt(index);
         else
@@ -136,7 +125,7 @@
     }
 
     // implements javax.swing.MutableComboBoxModel
-    public void addElement(Object anObject) {
+    public void addElement(E anObject) {
         objects.addElement(anObject);
         fireIntervalAdded(this,objects.size()-1, objects.size()-1);
         if ( objects.size() == 1 && selectedObject == null && anObject != null ) {
@@ -145,7 +134,7 @@
     }
 
     // implements javax.swing.MutableComboBoxModel
-    public void insertElementAt(Object anObject,int index) {
+    public void insertElementAt(E anObject,int index) {
         objects.insertElementAt(anObject,index);
         fireIntervalAdded(this, index, index);
     }
--- a/jdk/src/share/classes/javax/swing/JComboBox.java	Fri Apr 29 16:03:09 2011 -0700
+++ b/jdk/src/share/classes/javax/swing/JComboBox.java	Wed May 04 10:20:14 2011 +0400
@@ -69,6 +69,8 @@
  * @see ComboBoxModel
  * @see DefaultComboBoxModel
  *
+ * @param <E> the type of the elements of this combo box
+ *
  * @beaninfo
  *   attribute: isContainer false
  * description: A combination of a text field and a drop-down list.
@@ -76,7 +78,7 @@
  * @author Arnaud Weber
  * @author Mark Davidson
  */
-public class JComboBox extends JComponent
+public class JComboBox<E> extends JComponent
 implements ItemSelectable,ListDataListener,ActionListener, Accessible {
     /**
      * @see #getUIClassID
@@ -91,7 +93,7 @@
      * @see #getModel
      * @see #setModel
      */
-    protected ComboBoxModel    dataModel;
+    protected ComboBoxModel<E>    dataModel;
     /**
      * This protected field is implementation specific. Do not access directly
      * or override. Use the accessor methods instead.
@@ -99,7 +101,7 @@
      * @see #getRenderer
      * @see #setRenderer
      */
-    protected ListCellRenderer renderer;
+    protected ListCellRenderer<? super E> renderer;
     /**
      * This protected field is implementation specific. Do not access directly
      * or override. Use the accessor methods instead.
@@ -156,7 +158,7 @@
      */
     protected Object selectedItemReminder = null;
 
-    private Object prototypeDisplayValue;
+    private E prototypeDisplayValue;
 
     // Flag to ensure that infinite loops do not occur with ActionEvents.
     private boolean firingActionEvent = false;
@@ -175,7 +177,7 @@
      *          displayed list of items
      * @see DefaultComboBoxModel
      */
-    public JComboBox(ComboBoxModel aModel) {
+    public JComboBox(ComboBoxModel<E> aModel) {
         super();
         setModel(aModel);
         init();
@@ -189,9 +191,9 @@
      * @param items  an array of objects to insert into the combo box
      * @see DefaultComboBoxModel
      */
-    public JComboBox(final Object items[]) {
+    public JComboBox(E[] items) {
         super();
-        setModel(new DefaultComboBoxModel(items));
+        setModel(new DefaultComboBoxModel<E>(items));
         init();
     }
 
@@ -203,9 +205,9 @@
      * @param items  an array of vectors to insert into the combo box
      * @see DefaultComboBoxModel
      */
-    public JComboBox(Vector<?> items) {
+    public JComboBox(Vector<E> items) {
         super();
-        setModel(new DefaultComboBoxModel(items));
+        setModel(new DefaultComboBoxModel<E>(items));
         init();
     }
 
@@ -219,7 +221,7 @@
      */
     public JComboBox() {
         super();
-        setModel(new DefaultComboBoxModel());
+        setModel(new DefaultComboBoxModel<E>());
         init();
     }
 
@@ -263,7 +265,7 @@
     public void updateUI() {
         setUI((ComboBoxUI)UIManager.getUI(this));
 
-        ListCellRenderer renderer = getRenderer();
+        ListCellRenderer<? super E> renderer = getRenderer();
         if (renderer instanceof Component) {
             SwingUtilities.updateComponentTreeUI((Component)renderer);
         }
@@ -302,8 +304,8 @@
      *        bound: true
      *  description: Model that the combo box uses to get data to display.
      */
-    public void setModel(ComboBoxModel aModel) {
-        ComboBoxModel oldModel = dataModel;
+    public void setModel(ComboBoxModel<E> aModel) {
+        ComboBoxModel<E> oldModel = dataModel;
         if (oldModel != null) {
             oldModel.removeListDataListener(this);
         }
@@ -322,7 +324,7 @@
      * @return the <code>ComboBoxModel</code> that provides the displayed
      *                  list of items
      */
-    public ComboBoxModel getModel() {
+    public ComboBoxModel<E> getModel() {
         return dataModel;
     }
 
@@ -461,8 +463,8 @@
      *     expert: true
      *  description: The renderer that paints the item selected in the list.
      */
-    public void setRenderer(ListCellRenderer aRenderer) {
-        ListCellRenderer oldRenderer = renderer;
+    public void setRenderer(ListCellRenderer<? super E> aRenderer) {
+        ListCellRenderer<? super E> oldRenderer = renderer;
         renderer = aRenderer;
         firePropertyChange( "renderer", oldRenderer, renderer );
         invalidate();
@@ -475,7 +477,7 @@
      * @return  the <code>ListCellRenderer</code> that displays
      *                  the selected item.
      */
-    public ListCellRenderer getRenderer() {
+    public ListCellRenderer<? super E> getRenderer() {
         return renderer;
     }
 
@@ -558,7 +560,7 @@
                 // will be rejected.
                 boolean found = false;
                 for (int i = 0; i < dataModel.getSize(); i++) {
-                    Object element = dataModel.getElementAt(i);
+                    E element = dataModel.getElementAt(i);
                     if (anObject.equals(element)) {
                         found = true;
                         objectToSelect = element;
@@ -640,7 +642,7 @@
     public int getSelectedIndex() {
         Object sObject = dataModel.getSelectedItem();
         int i,c;
-        Object obj;
+        E obj;
 
         for ( i=0,c=dataModel.getSize();i<c;i++ ) {
             obj = dataModel.getElementAt(i);
@@ -658,7 +660,7 @@
      * @see #setPrototypeDisplayValue
      * @since 1.4
      */
-    public Object getPrototypeDisplayValue() {
+    public E getPrototypeDisplayValue() {
         return prototypeDisplayValue;
     }
 
@@ -683,7 +685,7 @@
      *   attribute: visualUpdate true
      * description: The display prototype value, used to compute display width and height.
      */
-    public void setPrototypeDisplayValue(Object prototypeDisplayValue) {
+    public void setPrototypeDisplayValue(E prototypeDisplayValue) {
         Object oldValue = this.prototypeDisplayValue;
         this.prototypeDisplayValue = prototypeDisplayValue;
         firePropertyChange("prototypeDisplayValue", oldValue, prototypeDisplayValue);
@@ -708,12 +710,12 @@
      *   }
      * </pre>
      *
-     * @param anObject the Object to add to the list
+     * @param item the item to add to the list
      * @see MutableComboBoxModel
      */
-    public void addItem(Object anObject) {
+    public void addItem(E item) {
         checkMutableComboBoxModel();
-        ((MutableComboBoxModel)dataModel).addElement(anObject);
+        ((MutableComboBoxModel<E>)dataModel).addElement(item);
     }
 
     /**
@@ -721,14 +723,14 @@
      * This method works only if the <code>JComboBox</code> uses a
      * mutable data model.
      *
-     * @param anObject the <code>Object</code> to add to the list
+     * @param item the item to add to the list
      * @param index    an integer specifying the position at which
      *                  to add the item
      * @see MutableComboBoxModel
      */
-    public void insertItemAt(Object anObject, int index) {
+    public void insertItemAt(E item, int index) {
         checkMutableComboBoxModel();
-        ((MutableComboBoxModel)dataModel).insertElementAt(anObject,index);
+        ((MutableComboBoxModel<E>)dataModel).insertElementAt(item,index);
     }
 
     /**
@@ -756,7 +758,7 @@
      */
     public void removeItemAt(int anIndex) {
         checkMutableComboBoxModel();
-        ((MutableComboBoxModel)dataModel).removeElementAt( anIndex );
+        ((MutableComboBoxModel<E>)dataModel).removeElementAt( anIndex );
     }
 
     /**
@@ -764,7 +766,7 @@
      */
     public void removeAllItems() {
         checkMutableComboBoxModel();
-        MutableComboBoxModel model = (MutableComboBoxModel)dataModel;
+        MutableComboBoxModel<E> model = (MutableComboBoxModel<E>)dataModel;
         int size = model.getSize();
 
         if ( model instanceof DefaultComboBoxModel ) {
@@ -772,7 +774,7 @@
         }
         else {
             for ( int i = 0; i < size; ++i ) {
-                Object element = model.getElementAt( 0 );
+                E element = model.getElementAt( 0 );
                 model.removeElement( element );
             }
         }
@@ -1188,11 +1190,11 @@
 
 
     private static class ComboBoxActionPropertyChangeListener
-                 extends ActionPropertyChangeListener<JComboBox> {
-        ComboBoxActionPropertyChangeListener(JComboBox b, Action a) {
+                 extends ActionPropertyChangeListener<JComboBox<?>> {
+        ComboBoxActionPropertyChangeListener(JComboBox<?> b, Action a) {
             super(b, a);
         }
-        protected void actionPropertyChanged(JComboBox cb,
+        protected void actionPropertyChanged(JComboBox<?> cb,
                                              Action action,
                                              PropertyChangeEvent e) {
             if (AbstractAction.shouldReconfigure(e)) {
@@ -1454,10 +1456,10 @@
      *
      * @param index  an integer indicating the list position, where the first
      *               item starts at zero
-     * @return the <code>Object</code> at that list position; or
+     * @return the item at that list position; or
      *                  <code>null</code> if out of range
      */
-    public Object getItemAt(int index) {
+    public E getItemAt(int index) {
         return dataModel.getElementAt(index);
     }
 
--- a/jdk/src/share/classes/javax/swing/MutableComboBoxModel.java	Fri Apr 29 16:03:09 2011 -0700
+++ b/jdk/src/share/classes/javax/swing/MutableComboBoxModel.java	Wed May 04 10:20:14 2011 +0400
@@ -27,19 +27,21 @@
 /**
  * A mutable version of <code>ComboBoxModel</code>.
  *
+ * @param <E> the type of the elements of this model
+ *
  * @author Tom Santos
  */
 
-public interface MutableComboBoxModel extends ComboBoxModel {
+public interface MutableComboBoxModel<E> extends ComboBoxModel<E> {
 
     /**
      * Adds an item at the end of the model. The implementation of this method
      * should notify all registered <code>ListDataListener</code>s that the
      * item has been added.
      *
-     * @param obj the <code>Object</code> to be added
+     * @param item the item to be added
      */
-    public void addElement( Object obj );
+    public void addElement( E item );
 
     /**
      * Removes an item from the model. The implementation of this method should
@@ -55,17 +57,17 @@
      * should notify all registered <code>ListDataListener</code>s that the
      * item has been added.
      *
-     * @param obj  the <code>Object</code> to be added
+     * @param item  the item to be added
      * @param index  location to add the object
      */
-    public void insertElementAt( Object obj, int index );
+    public void insertElementAt( E item, int index );
 
     /**
      * Removes an item at a specific index. The implementation of this method
      * should notify all registered <code>ListDataListener</code>s that the
      * item has been removed.
      *
-     * @param index  location of object to be removed
+     * @param index  location of the item to be removed
      */
     public void removeElementAt( int index );
 }
--- a/jdk/src/share/classes/javax/swing/plaf/basic/BasicDirectoryModel.java	Fri Apr 29 16:03:09 2011 -0700
+++ b/jdk/src/share/classes/javax/swing/plaf/basic/BasicDirectoryModel.java	Wed May 04 10:20:14 2011 +0400
@@ -40,7 +40,7 @@
  *
  * @author Jeff Dinkins
  */
-public class BasicDirectoryModel extends AbstractListModel implements PropertyChangeListener {
+public class BasicDirectoryModel extends AbstractListModel<Object> implements PropertyChangeListener {
 
     private JFileChooser filechooser = null;
     // PENDING(jeff) pick the size more sensibly
--- a/jdk/src/share/classes/javax/swing/plaf/metal/MetalFileChooserUI.java	Fri Apr 29 16:03:09 2011 -0700
+++ b/jdk/src/share/classes/javax/swing/plaf/metal/MetalFileChooserUI.java	Wed May 04 10:20:14 2011 +0400
@@ -906,7 +906,7 @@
     /**
      * Data model for a type-face selection combo-box.
      */
-    protected class DirectoryComboBoxModel extends AbstractListModel implements ComboBoxModel {
+    protected class DirectoryComboBoxModel extends AbstractListModel<Object> implements ComboBoxModel<Object> {
         Vector<File> directories = new Vector<File>();
         int[] depths = null;
         File selectedDirectory = null;
@@ -1063,7 +1063,7 @@
     /**
      * Data model for a type-face selection combo-box.
      */
-    protected class FilterComboBoxModel extends AbstractListModel implements ComboBoxModel, PropertyChangeListener {
+    protected class FilterComboBoxModel extends AbstractListModel<Object> implements ComboBoxModel<Object>, PropertyChangeListener {
         protected FileFilter[] filters;
         protected FilterComboBoxModel() {
             super();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/JComboBox/7031551/bug7031551.java	Wed May 04 10:20:14 2011 +0400
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ * @bug 7031551
+ * @summary Generics: JComboBox
+ * @author Pavel Porvatov
+ */
+
+import javax.swing.*;
+import java.util.Vector;
+
+public class bug7031551 {
+
+    private static final String TEST_ELEMENT1 = "Test1";
+    private static final String TEST_ELEMENT2 = "Test2";
+    private static final String TEST_ELEMENT3 = "Test3";
+
+    /**
+     * @param args the command line arguments
+     */
+    @SuppressWarnings("unchecked")
+    public static void main(String[] args) {
+        testRawSignatures();
+        testGenericSignatures();
+    }
+
+    @SuppressWarnings("unchecked")
+    private static void testRawSignatures() {
+        // Test JComboBox
+        ComboBoxModel rawTestModel = new DefaultComboBoxModel();
+
+        JComboBox rawTestComboBox = new JComboBox();
+        rawTestComboBox = new JComboBox(rawTestModel);
+        rawTestComboBox = new JComboBox(new Object[]{TEST_ELEMENT1});
+        rawTestComboBox = new JComboBox(new Vector());
+
+        Object unused1 = rawTestComboBox.getPrototypeDisplayValue();
+        rawTestComboBox.setPrototypeDisplayValue(TEST_ELEMENT1);
+
+        ListCellRenderer unused2 = rawTestComboBox.getRenderer();
+        rawTestComboBox.setRenderer(new DefaultListCellRenderer());
+
+        ComboBoxModel unused3 = rawTestComboBox.getModel();
+        rawTestComboBox.setModel(rawTestModel);
+
+        rawTestComboBox.addItem(TEST_ELEMENT2);
+        rawTestComboBox.insertItemAt(TEST_ELEMENT3, 1);
+        rawTestComboBox.removeItem(TEST_ELEMENT2);
+        assertEquals(rawTestComboBox.getItemAt(0), TEST_ELEMENT3);
+        rawTestComboBox.removeAllItems();
+
+        // Test DefaultComboBoxModel
+        DefaultComboBoxModel testModel = new DefaultComboBoxModel();
+        testModel = new DefaultComboBoxModel(new Vector());
+        testModel = new DefaultComboBoxModel(new Object[]{TEST_ELEMENT1});
+
+        testModel.addElement(TEST_ELEMENT2);
+        testModel.insertElementAt(TEST_ELEMENT3, 1);
+        assertEquals(testModel.getElementAt(2), TEST_ELEMENT2);
+    }
+
+    private static void testGenericSignatures() {
+        // Test JComboBox
+        ComboBoxModel<String> stringTestModel = new DefaultComboBoxModel<String>();
+
+        JComboBox<String> stringTestComboBox = new JComboBox<String>();
+        stringTestComboBox = new JComboBox<String>(stringTestModel);
+        stringTestComboBox = new JComboBox<String>(new String[]{TEST_ELEMENT1});
+        stringTestComboBox = new JComboBox<String>(new Vector<String>());
+
+        String unused1 = stringTestComboBox.getPrototypeDisplayValue();
+        stringTestComboBox.setPrototypeDisplayValue(TEST_ELEMENT1);
+
+        ListCellRenderer<? super String> unused2 = stringTestComboBox.getRenderer();
+        stringTestComboBox.setRenderer(new DefaultListCellRenderer());
+
+        ComboBoxModel unused3 = stringTestComboBox.getModel();
+        stringTestComboBox.setModel(stringTestModel);
+
+        stringTestComboBox.addItem(TEST_ELEMENT2);
+        stringTestComboBox.insertItemAt(TEST_ELEMENT3, 1);
+        stringTestComboBox.removeItem(TEST_ELEMENT2);
+        assertEquals(stringTestComboBox.getItemAt(0), TEST_ELEMENT3);
+        stringTestComboBox.removeAllItems();
+
+        // Test DefaultComboBoxModel
+        DefaultComboBoxModel<String> testModel = new DefaultComboBoxModel<String>();
+        testModel = new DefaultComboBoxModel<String>(new Vector<String>());
+        testModel = new DefaultComboBoxModel<String>(new String[]{TEST_ELEMENT1});
+
+        testModel.addElement(TEST_ELEMENT2);
+        testModel.insertElementAt(TEST_ELEMENT3, 1);
+        assertEquals(testModel.getElementAt(2), TEST_ELEMENT2);
+    }
+
+    private static void assertEquals(Object expectedObject, Object actualObject) {
+        if (!expectedObject.equals(actualObject)) {
+            throw new RuntimeException("Expected: " + expectedObject + " but was: " + actualObject);
+        }
+    }
+}
+