[kaffe] CVS kaffe (robilad): Resynced with GNU Classpath: various Swing bug fixes

Kaffe CVS cvs-commits at kaffe.org
Mon Dec 20 19:23:28 PST 2004


PatchSet 5689 
Date: 2004/12/21 03:18:54
Author: robilad
Branch: HEAD
Tag: (none) 
Log:
Resynced with GNU Classpath: various Swing bug fixes

2004-12-21  Dalibor Topic  <robilad at kaffe.org>

        * libraries/javalib/javax/swing/JComboBox.java,
        libraries/javalib/javax/swing/DefaultComboBoxModel.java,
        libraries/javalib/javax/swing/plaf/basic/BasicComboBoxUI.java:
        Resynced with GNU Classpath.

        2004-12-18  Robert Schuster <thebohemian at gmx.net>

        * javax/swing/JComboBox.java
        added support for no item being selected
        (JComboBox): select first or nothing depending on element
        count
        (setModel): cleaned up unneeded this. usage, added more
        docs, made exception behavior match that of the JDK
        (setLighWeightPopupEnabled): removed unneeded this. usage
        (setEditable): dito
        (setMaximumRowCount): dito
        (setRenderer): dito
        (setPrototypeDisplayValue): dito
        (getSelectedItem): simplified, added more user doc
        (setSelectedIndex): corrected exception behavior, added more user
        doc
        (getSelectedIndex): fixed hardcoded dependency on DefaultComboBoxModel
         (see bug #11255), added performance warning to user doc
        (addItem): fixed exception behavior, added user doc
        (insertItemAt): dito
        (removeItem): dito
        (removeItemAt): dito
        (removeAll): fixed exception behavior, added user doc, added support
        for model not being instance of DefaultComboBoxModel (see bug #11255)
        (getSelectedItemObjects): simplified
        (getItemCount): fixed dependency on DefaultComboBoxModel (see bug #11255)
        (getItemAt): fixed dependency on MutableComboBoxModel (see bug #11255)
        * javax/swing/DefaultComboBoxModel.java:
        (setSelectedItem): updates selected item only if new
        value is null or known (match JDK behavior)
        * javax/swing/plaf/basic/BasicComboBoxUI.java:
        (paintCurrentValue): renders  if no item is selected

Members: 
	ChangeLog:1.3235->1.3236 
	libraries/javalib/javax/swing/DefaultComboBoxModel.java:1.2->1.3 
	libraries/javalib/javax/swing/JComboBox.java:1.3->1.4 
	libraries/javalib/javax/swing/plaf/basic/BasicComboBoxUI.java:1.3->1.4 

Index: kaffe/ChangeLog
diff -u kaffe/ChangeLog:1.3235 kaffe/ChangeLog:1.3236
--- kaffe/ChangeLog:1.3235	Tue Dec 21 02:43:00 2004
+++ kaffe/ChangeLog	Tue Dec 21 03:18:54 2004
@@ -1,3 +1,43 @@
+2004-12-21  Dalibor Topic  <robilad at kaffe.org>
+
+	* libraries/javalib/javax/swing/JComboBox.java,
+	libraries/javalib/javax/swing/DefaultComboBoxModel.java,
+	libraries/javalib/javax/swing/plaf/basic/BasicComboBoxUI.java:
+	Resynced with GNU Classpath.
+
+	2004-12-18  Robert Schuster <thebohemian at gmx.net>
+
+        * javax/swing/JComboBox.java
+        added support for no item being selected
+        (JComboBox): select first or nothing depending on element
+        count
+        (setModel): cleaned up unneeded "this." usage, added more
+        docs, made exception behavior match that of the JDK
+        (setLighWeightPopupEnabled): removed unneeded "this." usage
+        (setEditable): dito
+        (setMaximumRowCount): dito
+        (setRenderer): dito
+        (setPrototypeDisplayValue): dito
+        (getSelectedItem): simplified, added more user doc
+        (setSelectedIndex): corrected exception behavior, added more user
+        doc
+        (getSelectedIndex): fixed hardcoded dependency on DefaultComboBoxModel
+         (see bug #11255), added performance warning to user doc
+        (addItem): fixed exception behavior, added user doc
+        (insertItemAt): dito
+        (removeItem): dito
+        (removeItemAt): dito
+        (removeAll): fixed exception behavior, added user doc, added support
+        for model not being instance of DefaultComboBoxModel (see bug #11255)
+        (getSelectedItemObjects): simplified
+        (getItemCount): fixed dependency on DefaultComboBoxModel (see bug #11255)
+        (getItemAt): fixed dependency on MutableComboBoxModel (see bug #11255)
+        * javax/swing/DefaultComboBoxModel.java:
+        (setSelectedItem): updates selected item only if new
+        value is null or known (match JDK behavior)
+        * javax/swing/plaf/basic/BasicComboBoxUI.java:
+        (paintCurrentValue): renders "" if no item is selected
+
 2004-12-20  Adam Heath  <doogie at brainfood.com>
 
 	* kaffe/kaffevm/systems/unix-jthreads/jthread.c:
Index: kaffe/libraries/javalib/javax/swing/DefaultComboBoxModel.java
diff -u kaffe/libraries/javalib/javax/swing/DefaultComboBoxModel.java:1.2 kaffe/libraries/javalib/javax/swing/DefaultComboBoxModel.java:1.3
--- kaffe/libraries/javalib/javax/swing/DefaultComboBoxModel.java:1.2	Sun Sep 12 15:11:06 2004
+++ kaffe/libraries/javalib/javax/swing/DefaultComboBoxModel.java	Tue Dec 21 03:18:57 2004
@@ -50,6 +50,7 @@
  *
  * @author Andrew Selkirk
  * @author Olga Rodimina
+ * @author Robert Schuster
  * @version 1.0
  */
 public class DefaultComboBoxModel extends AbstractListModel
@@ -182,13 +183,23 @@
    * ListDataEvent to all registered ListDataListeners of the JComboBox. The
    * start and end index of the event is set to -1 to indicate combo box's
    * selection has changed, and not its contents.
+   * 
+   * <p>If the given object is not contained in the combo box list then nothing
+   * happens.</p>
    *
    * @param object item to select in the JComboBox
    */
   public void setSelectedItem(Object object)
   {
-    selectedItem = object;
-    fireContentsChanged(this, -1, -1);
+    
+    /* Updates the selected item only if the given object
+     * is null or in the list (this is how the JDK behaves).
+     */ 
+    if(object == null || list.contains(object)) {
+	selectedItem = object;
+	fireContentsChanged(this, -1, -1);
+    }
+  	
   }
 
   /**
Index: kaffe/libraries/javalib/javax/swing/JComboBox.java
diff -u kaffe/libraries/javalib/javax/swing/JComboBox.java:1.3 kaffe/libraries/javalib/javax/swing/JComboBox.java:1.4
--- kaffe/libraries/javalib/javax/swing/JComboBox.java:1.3	Sun Oct 24 13:39:11 2004
+++ kaffe/libraries/javalib/javax/swing/JComboBox.java	Tue Dec 21 03:18:57 2004
@@ -60,7 +60,6 @@
 import javax.swing.event.PopupMenuListener;
 import javax.swing.plaf.ComboBoxUI;
 
-
 /**
  * JComboBox. JComboBox is a container, that keeps track of elements added to
  * it by the user. JComboBox allows user to select any item in its list and
@@ -69,12 +68,14 @@
  *
  * @author Andrew Selkirk
  * @author Olga Rodimina
+ * @author Robert Schuster
  */
 public class JComboBox extends JComponent implements ItemSelectable,
                                                      ListDataListener,
                                                      ActionListener,
                                                      Accessible
 {
+
   private static final long serialVersionUID = 5654585963292734470L;
 
   /**
@@ -143,7 +144,7 @@
   protected ListCellRenderer renderer;
 
   /**
-   * editor that is responsible for editting an object in a combo box list
+   * Editor that is responsible for editing an object in a combo box list.
    */
   protected ComboBoxEditor editor;
 
@@ -205,9 +206,10 @@
     setModel(model);
     setActionCommand("comboBoxChanged");
 
-    // by default set selected item to the first element in the combo box    
-    if (getItemCount() != 0)
-      setSelectedItem(getItemAt(0));
+    /* By default set selected item to the first element in the combo box
+     * or select nothing if there are no elements.
+     */
+    setSelectedIndex(getItemCount() != 0 ? 0 : -1);    
 
     lightWeightPopupEnabled = true;
     isEditable = false;
@@ -322,21 +324,29 @@
    */
   public void setModel(ComboBoxModel newDataModel)
   {
-    if (this.dataModel == newDataModel)
-      return;
 
-    if (this.dataModel != null)
-      // remove all listeners currently registered with the model.
-      dataModel.removeListDataListener(this);
-
-    ComboBoxModel oldDataModel = this.dataModel;
-    this.dataModel = newDataModel;
-
-    if (this.dataModel != null)
-      // register all listeners with the new data model
-      dataModel.addListDataListener(this);
+    // dataModel is null if it this method is called from inside the constructors.
+    if(dataModel != null) {
+	// Prevents unneccessary updates.
+	if (dataModel == newDataModel)
+		return;
+
+    	// Removes itself (as DataListener) from the to-be-replaced model.
+    	dataModel.removeListDataListener(this);
+    }
+    
+    /* Adds itself as a DataListener to the new model.
+     * It is intentioned that this operation will fail with a NullPointerException if the
+     * caller delivered a null argument.
+     */
+    newDataModel.addListDataListener(this);
+
+    // Stores old data model for event notification.
+    ComboBoxModel oldDataModel = dataModel;
+    dataModel = newDataModel;
 
-    firePropertyChange(MODEL_CHANGED_PROPERTY, oldDataModel, this.dataModel);
+    // Notifies the listeners of the model change.
+    firePropertyChange(MODEL_CHANGED_PROPERTY, oldDataModel, dataModel);
   }
 
   /**
@@ -351,8 +361,8 @@
 
   /**
    * This method sets JComboBox's popup to be either lightweight or
-   * heavyweight. If 'enabled' is true then lightweight popup is  used and
-   * heavyweight otherwise. By default lightweight popup is  used to display
+   * heavyweight. If 'enabled' is true then lightweight popup is used and
+   * heavyweight otherwise. By default lightweight popup is used to display
    * this JComboBox's elements.
    *
    * @param enabled indicates if lightweight popup or heavyweight popup should
@@ -360,7 +370,7 @@
    */
   public void setLightWeightPopupEnabled(boolean enabled)
   {
-    this.lightWeightPopupEnabled = enabled;
+    lightWeightPopupEnabled = enabled;
   }
 
   /**
@@ -388,9 +398,9 @@
    */
   public void setEditable(boolean editable)
   {
-    if (this.isEditable != editable)
+    if (isEditable != editable)
       {
-	this.isEditable = editable;
+	isEditable = editable;
 	firePropertyChange(EDITABLE_CHANGED_PROPERTY, ! isEditable, isEditable);
       }
   }
@@ -407,10 +417,10 @@
   {
     if (maximumRowCount != rowCount)
       {
-	int oldMaximumRowCount = this.maximumRowCount;
-	this.maximumRowCount = rowCount;
+	int oldMaximumRowCount = maximumRowCount;
+	maximumRowCount = rowCount;
 	firePropertyChange(MAXIMUM_ROW_COUNT_CHANGED_PROPERTY,
-	                   oldMaximumRowCount, this.maximumRowCount);
+	                   oldMaximumRowCount, maximumRowCount);
       }
   }
 
@@ -437,12 +447,12 @@
    */
   public void setRenderer(ListCellRenderer aRenderer)
   {
-    if (this.renderer != aRenderer)
+    if (renderer != aRenderer)
       {
-	ListCellRenderer oldRenderer = this.renderer;
-	this.renderer = aRenderer;
+	ListCellRenderer oldRenderer = renderer;
+	renderer = aRenderer;
 	firePropertyChange(RENDERER_CHANGED_PROPERTY, oldRenderer,
-	                   this.renderer);
+	                   renderer);
       }
   }
 
@@ -481,7 +491,7 @@
   }
 
   /**
-   * Returns editor component that is responsible for displaying/editting
+   * Returns editor component that is responsible for displaying/editing
    * selected item in the combo box.
    *
    * @return ComboBoxEditor
@@ -503,45 +513,76 @@
 
   /**
    * Returns currently selected item in the combo box.
+   * The result may be <code>null</code> to indicate that nothing is
+   * currently selected.
    *
    * @return element that is currently selected in this combo box.
    */
   public Object getSelectedItem()
   {
-    Object item = dataModel.getSelectedItem();
-
-    if (item == null && getItemCount() != 0)
-      item = getItemAt(0);
-
-    return item;
+    return dataModel.getSelectedItem();
   }
 
   /**
-   * Forces JComboBox to select component located in the  given index in the
+   * Forces JComboBox to select component located in the given index in the
    * combo box.
+   * <p>If the index is below -1 or exceeds the upper bound an
+   * <code>IllegalArgumentException</code> is thrown.<p/>
+   * <p>If the index is -1 then no item gets selected.</p>
    *
    * @param index index specifying location of the component that  should be
    *        selected.
    */
   public void setSelectedIndex(int index)
   {
-    // FIXME: if index == -1 then nothing should be selected
-    setSelectedItem(dataModel.getElementAt(index));
+  	if(index < -1 || index >= dataModel.getSize()) {
+  		// Fails because index is out of bounds. 
+  		throw new IllegalArgumentException("illegal index: " + index);
+  	} else {
+  		/* Selects the item at the given index or clears the selection if the
+  		 * index value is -1.
+  		 */
+		setSelectedItem((index == -1) ? null : dataModel.getElementAt(index));
+  	}
   }
 
   /**
    * Returns index of the item that is currently selected  in the combo box.
    * If no item is currently selected, then -1 is returned.
+   * 
+   * <p>Note: For performance reasons you should minimize invocation of this
+   * method. If the data model is not an instance of
+   * <code>DefaultComboBoxModel</code> the complexity is O(n) where
+   * n is the number of elements in the combo box.</p>
    *
-   * @return int index specifying location of the currently  selected item in
+   * @return int Index specifying location of the currently selected item in
    *         the combo box or -1 if nothing is selected in the combo box.
    */
   public int getSelectedIndex()
   {
     Object selectedItem = getSelectedItem();
-    if (selectedItem != null && (dataModel instanceof DefaultComboBoxModel))
-      return ((DefaultComboBoxModel) dataModel).getIndexOf(selectedItem);
+    
+    if (selectedItem != null) {
+	
+		if(dataModel instanceof DefaultComboBoxModel) {
+			// Uses special method of DefaultComboBoxModel to retrieve the index.
+        	  	return ((DefaultComboBoxModel) dataModel).getIndexOf(selectedItem);
+		} else {
+			// Iterates over all items to retrieve the index.
+			int size = dataModel.getSize();
+			
+	  		for(int i=0; i < size; i++) {
+	  			Object o = dataModel.getElementAt(i);
+	  			
+				// XXX: Is special handling of ComparableS neccessary?
+	  			if((selectedItem != null) ? selectedItem.equals(o) : o == null) {
+	  				return i;
+	  			}
+	  		}
+		}
+    }
 
+    // returns that no item is currently selected
     return -1;
   }
 
@@ -550,60 +591,104 @@
     return prototypeDisplayValue;
   }
 
-  public void setPrototypeDisplayValue(Object prototypeDisplayValue)
+  public void setPrototypeDisplayValue(Object newPrototypeDisplayValue)
   {
-    this.prototypeDisplayValue = prototypeDisplayValue;
+    prototypeDisplayValue = newPrototypeDisplayValue;
   }
 
   /**
    * This method adds given element to this JComboBox.
+   * <p>A <code>RuntimeException</code> is thrown if the data model is not
+   * an instance of {@link MutableComboBoxModel}.</p>
    *
    * @param element element to add
    */
   public void addItem(Object element)
   {
-    ((MutableComboBoxModel) dataModel).addElement(element);
+  	if(dataModel instanceof MutableComboBoxModel) {
+		((MutableComboBoxModel) dataModel).addElement(element);
+  	} else {
+  		throw new RuntimeException("Unable to add the item because the data model it is not an instance of MutableComboBoxModel.");
+  	}
   }
 
   /**
-   * Inserts given element at the specified index to this JComboBox
+   * Inserts given element at the specified index to this JComboBox.
+   * <p>A <code>RuntimeException</code> is thrown if the data model is not
+   * an instance of {@link MutableComboBoxModel}.</p>
    *
    * @param element element to insert
    * @param index position where to insert the element
    */
   public void insertItemAt(Object element, int index)
   {
-    ((MutableComboBoxModel) dataModel).insertElementAt(element, index);
+	if(dataModel instanceof MutableComboBoxModel) {
+		((MutableComboBoxModel) dataModel).insertElementAt(element, index);
+	} else {
+		throw new RuntimeException("Unable to insert the item because the data model it is not an instance of MutableComboBoxModel.");
+	}
   }
 
   /**
    * This method removes given element from this JComboBox.
+   * <p>A <code>RuntimeException</code> is thrown if the data model is not
+   * an instance of {@link MutableComboBoxModel}.</p>
    *
    * @param element element to remove
    */
   public void removeItem(Object element)
   {
-    ((MutableComboBoxModel) dataModel).removeElement(element);
+	if(dataModel instanceof MutableComboBoxModel) {
+		((MutableComboBoxModel) dataModel).removeElement(element);
+	} else {
+		throw new RuntimeException("Unable to remove the item because the data model it is not an instance of MutableComboBoxModel.");
+	}
   }
 
   /**
    * This method remove element location in the specified index in the
    * JComboBox.
+   * <p>A <code>RuntimeException</code> is thrown if the data model is not
+   * an instance of {@link MutableComboBoxModel}.</p>
    *
    * @param index index specifying position of the element to remove
    */
   public void removeItemAt(int index)
   {
-    ((MutableComboBoxModel) dataModel).removeElementAt(index);
+	if(dataModel instanceof MutableComboBoxModel) {
+		((MutableComboBoxModel) dataModel).removeElementAt(index);
+	} else {
+		throw new RuntimeException("Unable to remove the item because the data model it is not an instance of MutableComboBoxModel.");
+	}
   }
 
   /**
    * This method removes all elements from this JComboBox.
+   * <p>A <code>RuntimeException</code> is thrown if the data model is not
+   * an instance of {@link MutableComboBoxModel}.</p>
+   * 
    */
   public void removeAllItems()
   {
-    if (dataModel instanceof DefaultComboBoxModel)
-      ((DefaultComboBoxModel) dataModel).removeAllElements();
+    if (dataModel instanceof DefaultComboBoxModel) {
+    	// Uses special method if we have a DefaultComboBoxModel.
+	((DefaultComboBoxModel) dataModel).removeAllElements();
+    } else if(dataModel instanceof MutableComboBoxModel){
+    	// Iterates over all items and removes each.
+    	MutableComboBoxModel mcbm = (MutableComboBoxModel) dataModel;
+
+	/* We intentionally remove the items backwards to support
+	 * models which shift their content to the beginning (e.g.
+	 * linked lists) 
+	 */     	
+    	for(int i=mcbm.getSize()-1; i >= 0; i--) {
+    		mcbm.removeElementAt(i);
+    	}
+    	
+    } else {
+	throw new RuntimeException("Unable to remove the items because the data model it is not an instance of MutableComboBoxModel.");
+    }
+      
   }
 
   /**
@@ -801,8 +886,7 @@
    */
   public Object[] getSelectedObjects()
   {
-    Object selectedObject = getSelectedItem();
-    return new Object[] { selectedObject };
+    return new Object[] { getSelectedItem() };
   }
 
   /**
@@ -951,7 +1035,7 @@
    */
   public int getItemCount()
   {
-    return ((DefaultComboBoxModel) dataModel).getSize();
+    return dataModel.getSize();
   }
 
   /**
@@ -963,7 +1047,7 @@
    */
   public Object getItemAt(int index)
   {
-    return ((MutableComboBoxModel) dataModel).getElementAt(index);
+    return dataModel.getElementAt(index);
   }
 
   /**
Index: kaffe/libraries/javalib/javax/swing/plaf/basic/BasicComboBoxUI.java
diff -u kaffe/libraries/javalib/javax/swing/plaf/basic/BasicComboBoxUI.java:1.3 kaffe/libraries/javalib/javax/swing/plaf/basic/BasicComboBoxUI.java:1.4
--- kaffe/libraries/javalib/javax/swing/plaf/basic/BasicComboBoxUI.java:1.3	Sun Oct 24 13:39:19 2004
+++ kaffe/libraries/javalib/javax/swing/plaf/basic/BasicComboBoxUI.java	Tue Dec 21 03:18:57 2004
@@ -80,6 +80,7 @@
  * UI Delegate for JComboBox
  *
  * @author Olga Rodimina
+ * @author Robert Schuster
  */
 public class BasicComboBoxUI extends ComboBoxUI
 {
@@ -783,22 +784,25 @@
       {
 	Object currentValue = comboBox.getSelectedItem();
 	boolean isPressed = arrowButton.getModel().isPressed();
-	if (currentValue != null)
-	  {
-	    Component comp = comboBox.getRenderer()
+
+	/* Gets the component to be drawn for the current value.
+	 * If there is currently no selected item we will take an empty
+	 * String as replacement.
+	 */
+	Component comp = comboBox.getRenderer()
 	                             .getListCellRendererComponent(listBox,
-	                                                           currentValue,
+	                                                           (currentValue != null ? currentValue : ""),
 	                                                           -1,
 	                                                           isPressed,
 	                                                           hasFocus);
-	    if (! comboBox.isEnabled())
+	if (! comboBox.isEnabled())
 	      comp.setEnabled(false);
 
-	    g.translate(borderInsets.left, borderInsets.top);
+	g.translate(borderInsets.left, borderInsets.top);
 	    comp.setBounds(0, 0, bounds.width, bounds.height);
 	    comp.paint(g);
 	    g.translate(-borderInsets.left, -borderInsets.top);
-	  }
+	    
 	comboBox.revalidate();
       }
     else




More information about the kaffe mailing list