Whoops, here's the file.

On Sun, 2006-07-30 at 11:06 +0200, Sven de Marothy wrote:
> This fixes several bugs, the most serious being that the selected index
> was not being updated. This also simplifies the code a bit.
> 
> I'd like this to get into the release branch, while it's a rather big
> change, I tested this _very_ rigorously.
> 
> I'll be writing an email to the main list on the event handling.
> 
> /Sven
> 
> 2006-07-30  Sven de Marothy  <[EMAIL PROTECTED]>
> 
>       * java/awt/Choice.java:
>       (accessibleAction): Call select() directly.
>       (add, insert, remove): Reimplement.
>       (dispatchEventImpl): Always call super.
>       (processItemEvent): Does not set the index.
>       * include/gnu_java_awt_peer_gtk_GtkChoicePeer.h
>       * native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkChoicePeer.c
>       (append): removed.
>       (nativeAdd): Name changed to add.
>       (selection_changed_cb): Simplify callback.
>       * gnu/java/awt/peer/gtk/GtkChoicePeer.java
>       (selected): New field.
>       (add): Replaced with native impl.
>       (handleEvent): New method.      
>       
Index: gnu/java/awt/peer/gtk/GtkChoicePeer.java
===================================================================
RCS file: /sources/classpath/classpath/gnu/java/awt/peer/gtk/GtkChoicePeer.java,v
retrieving revision 1.25
diff -U3 -r1.25 GtkChoicePeer.java
--- gnu/java/awt/peer/gtk/GtkChoicePeer.java	7 Oct 2005 23:46:22 -0000	1.25
+++ gnu/java/awt/peer/gtk/GtkChoicePeer.java	30 Jul 2006 08:52:58 -0000
@@ -39,12 +39,15 @@
 package gnu.java.awt.peer.gtk;
 
 import java.awt.Choice;
+import java.awt.AWTEvent;
 import java.awt.event.ItemEvent;
 import java.awt.peer.ChoicePeer;
 
 public class GtkChoicePeer extends GtkComponentPeer
   implements ChoicePeer
 {
+  private int selected;
+  
   public GtkChoicePeer (Choice c)
   {
     super (c);
@@ -52,31 +55,33 @@
     int count = c.getItemCount ();
     if (count > 0)
       {
-	String items[] = new String[count];
 	for (int i = 0; i < count; i++)
-	  items[i] = c.getItem (i);
-	  
-	append (items);
-      }
+	  add( c.getItem(i), i );
 
-    int selected = c.getSelectedIndex();
-    if (selected >= 0)
-      select(selected);
+	selected = c.getSelectedIndex();
+	if( selected >= 0 )
+	  select( selected );
+      }
+    else
+      selected = -1;
   }
 
   native void create ();
 
-  native void append (String items[]);
   native int nativeGetSelected ();
-  native void nativeAdd (String item, int index);
-  native void nativeRemove (int index);
-  native void nativeRemoveAll ();
 
   native void connectSignals ();
 
   native void selectNative (int position);
+
   native void selectNativeUnlocked (int position);
 
+  public native void add (String item, int index);
+
+  native void nativeRemove(int index);
+
+  native void nativeRemoveAll();
+
   public void select (int position)
   {
     if (Thread.currentThread() == GtkToolkit.mainThread)
@@ -85,42 +90,15 @@
       selectNative (position);
   }
 
-  public void add (String item, int index)
-  {
-    int before = nativeGetSelected();
-    
-    nativeAdd (item, index);
-    
-    /* Generate an ItemEvent if we added the first one or
-       if we inserted at or before the currently selected item. */
-    if ((before < 0) || (before >= index))
-      {
-        // Must set our state before notifying listeners
-	((Choice) awtComponent).select (((Choice) awtComponent).getItem (0));
-        postItemEvent (((Choice) awtComponent).getItem (0), ItemEvent.SELECTED);
-      }
-  }
-
-  public void remove (int index)
+  public void remove( int index )
   {
-    int before = nativeGetSelected();
-    int after;
-    
-    nativeRemove (index);
-    after = nativeGetSelected();
-    
-    /* Generate an ItemEvent if we are removing the currently selected item
-       and there are at least one item left. */
-    if ((before == index) && (after >= 0))
-      {
-        // Must set our state before notifying listeners
-	((Choice) awtComponent).select (((Choice) awtComponent).getItem (0));
-        postItemEvent (((Choice) awtComponent).getItem (0), ItemEvent.SELECTED);
-      }
+    selected = -1; // we do not want to trigger a select event here.
+    nativeRemove( index );
   }
 
-  public void removeAll ()
+  public void removeAll()
   {
+    selected = -1; // we do not want to trigger a select event here.
     nativeRemoveAll();
   }
   
@@ -129,8 +107,35 @@
     add (item, position);
   }
 
-  protected void postChoiceItemEvent (String label, int stateChange)
+  /**
+   * Callback from the native side on an item-select event, 
+   * which posts an event. The event is only posted if it represents an actual
+   * change. Selected is set to the peer's state initially, so that the
+   * first call to select(int) from the constructor will not trigger an event.
+   * (it should not)
+   */
+  protected void postChoiceItemEvent ( int index )
   {
-    postItemEvent (label, stateChange);
+    if( selected != index )
+      {
+	selected = index;
+	postItemEvent (((Choice) awtComponent).getItem( selected ), 
+		       ItemEvent.SELECTED);
+      }
+  }
+
+  /**
+   * Catches the event and calls Choice.select() if the component state
+   * needs updating.
+   */
+  public void handleEvent (AWTEvent event)
+  {
+    super.handleEvent( event );
+    if( event instanceof ItemEvent )
+      if( ((ItemEvent)event).getItemSelectable() == awtComponent &&
+	  ((ItemEvent)event).getStateChange() == ItemEvent.SELECTED )
+	if( ((Choice)awtComponent).getSelectedIndex() != selected )
+	  ((Choice)awtComponent).select( selected );
   }
 }
+
Index: include/gnu_java_awt_peer_gtk_GtkChoicePeer.h
===================================================================
RCS file: /sources/classpath/classpath/include/gnu_java_awt_peer_gtk_GtkChoicePeer.h,v
retrieving revision 1.9
diff -U3 -r1.9 gnu_java_awt_peer_gtk_GtkChoicePeer.h
--- include/gnu_java_awt_peer_gtk_GtkChoicePeer.h	30 Apr 2006 10:37:36 -0000	1.9
+++ include/gnu_java_awt_peer_gtk_GtkChoicePeer.h	30 Jul 2006 08:52:58 -0000
@@ -11,9 +11,8 @@
 #endif
 
 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkChoicePeer_create (JNIEnv *env, jobject);
-JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkChoicePeer_append (JNIEnv *env, jobject, jobjectArray);
 JNIEXPORT jint JNICALL Java_gnu_java_awt_peer_gtk_GtkChoicePeer_nativeGetSelected (JNIEnv *env, jobject);
-JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkChoicePeer_nativeAdd (JNIEnv *env, jobject, jstring, jint);
+JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkChoicePeer_add (JNIEnv *env, jobject, jstring, jint);
 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkChoicePeer_nativeRemove (JNIEnv *env, jobject, jint);
 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkChoicePeer_nativeRemoveAll (JNIEnv *env, jobject);
 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkChoicePeer_connectSignals (JNIEnv *env, jobject);
Index: java/awt/Choice.java
===================================================================
RCS file: /sources/classpath/classpath/java/awt/Choice.java,v
retrieving revision 1.27
diff -U3 -r1.27 Choice.java
--- java/awt/Choice.java	30 Jul 2006 08:52:23 -0000	1.27
+++ java/awt/Choice.java	30 Jul 2006 08:52:59 -0000
@@ -177,9 +177,8 @@
       if (i < 0 || i >= pItems.size())
 	return false;
 	    
-      Choice.this.processItemEvent(new ItemEvent(Choice.this,
-						 ItemEvent.ITEM_STATE_CHANGED,
-						 this, ItemEvent.SELECTED));
+      Choice.this.select( i );
+
       return true;
     }
   }
@@ -246,14 +245,11 @@
 
     pItems.addElement(item);
 
-    int i = pItems.size () - 1;
     if (peer != null)
-      {
-	ChoicePeer cp = (ChoicePeer) peer;
-	cp.add (item, i);
-      }
-    else if (selectedIndex == -1) 
-      select(0);
+      ((ChoicePeer) peer).add(item, getItemCount() - 1);
+
+    if (selectedIndex == -1) 
+      select( 0 );
   }
 
   /**
@@ -293,11 +289,9 @@
     pItems.insertElementAt(item, index);
 
     if (peer != null)
-      {
-	ChoicePeer cp = (ChoicePeer) peer;
-	cp.add (item, index);
-      }
-    else if (selectedIndex == -1 || selectedIndex >= index)
+      ((ChoicePeer) peer).add (item, index);
+
+    if (selectedIndex == -1 || selectedIndex >= index)
       select(0);
   }
 
@@ -332,20 +326,21 @@
     pItems.removeElementAt(index);
 
     if (peer != null)
+      ((ChoicePeer) peer).remove( index );
+
+    if( getItemCount() == 0 )
+      selectedIndex = -1;
+    else 
       {
-	ChoicePeer cp = (ChoicePeer) peer;
-	cp.remove (index);
-      }
-    else
-      {
-	if (getItemCount() == 0)
-	  selectedIndex = -1;
-	else if (index == selectedIndex)
-	  select(0);
+	if( index == selectedIndex )
+	  {
+	    if( peer != null ) 
+	      ((ChoicePeer)peer).select( 0 ); // force an event here
+	  }
+	else if( selectedIndex > index )
+	  select( selectedIndex - 1 );
       }
 
-    if (selectedIndex > index)
-      --selectedIndex;
   }
 
   /**
@@ -418,13 +413,12 @@
     if ((index < 0) || (index >= getItemCount()))
       throw new IllegalArgumentException("Bad index: " + index);
 
-    if (pItems.size() > 0) {
-      selectedIndex = index;
-      ChoicePeer cp = (ChoicePeer) peer;
-      if (cp != null) {
-	cp.select(index);
-      }
-    }
+    if( selectedIndex == index ) 
+      return;
+
+    selectedIndex = index;
+    if( peer != null ) 
+      ((ChoicePeer)peer).select( index );
   }
 
   /**
@@ -437,8 +431,8 @@
   public synchronized void select(String item)
   {
     int index = pItems.indexOf(item);
-    if (index >= 0)
-      select(index);
+    if( index >= 0 )
+      select( index );
   }
 
   /**
@@ -490,12 +484,12 @@
 
   void dispatchEventImpl(AWTEvent e)
   {
-    if (e.id <= ItemEvent.ITEM_LAST
-	&& e.id >= ItemEvent.ITEM_FIRST
-	&& (item_listeners != null || (eventMask & AWTEvent.ITEM_EVENT_MASK) != 0))
+    super.dispatchEventImpl(e);
+
+    if( e.id <= ItemEvent.ITEM_LAST && e.id >= ItemEvent.ITEM_FIRST && 
+	( item_listeners != null || 
+	  ( eventMask & AWTEvent.ITEM_EVENT_MASK ) != 0 ) )
       processEvent(e);
-    else
-      super.dispatchEventImpl(e);
   }
 
   /**
@@ -506,9 +500,6 @@
   protected void processItemEvent(ItemEvent event)
   {
     int index = pItems.indexOf((String) event.getItem());
-    // Don't call back into the peers when selecting index here
-    if (event.getStateChange() == ItemEvent.SELECTED)
-      this.selectedIndex = index;
     if (item_listeners != null)
       item_listeners.itemStateChanged(event);
   }
Index: native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkChoicePeer.c
===================================================================
RCS file: /sources/classpath/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkChoicePeer.c,v
retrieving revision 1.21
diff -U3 -r1.21 gnu_java_awt_peer_gtk_GtkChoicePeer.c
--- native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkChoicePeer.c	9 Mar 2006 22:38:57 -0000	1.21
+++ native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkChoicePeer.c	30 Jul 2006 08:52:59 -0000
@@ -1,5 +1,5 @@
 /* gtkchoicepeer.c -- Native implementation of GtkChoicePeer
-   Copyright (C) 1998, 1999 Free Software Foundation, Inc.
+   Copyright (C) 1998, 1999, 2006 Free Software Foundation, Inc.
 
 This file is part of GNU Classpath.
 
@@ -52,7 +52,7 @@
 
   postChoiceItemEventID = (*cp_gtk_gdk_env())->GetMethodID (cp_gtk_gdk_env(), gtkchoicepeer,
                                                "postChoiceItemEvent",
-                                               "(Ljava/lang/String;I)V");
+                                               "(I)V");
 }
 
 static void selection_changed_cb (GtkComboBox *combobox, jobject peer);
@@ -106,39 +106,7 @@
 }
 
 JNIEXPORT void JNICALL 
-Java_gnu_java_awt_peer_gtk_GtkChoicePeer_append 
-  (JNIEnv *env, jobject obj, jobjectArray items)
-{
-  gpointer ptr;
-  jsize count, i;
-  GtkWidget *bin;
-
-  gdk_threads_enter ();
-
-  ptr = NSA_GET_PTR (env, obj);
-  bin = choice_get_widget (GTK_WIDGET (ptr));
-  
-  count = (*env)->GetArrayLength (env, items);
-
-  for (i = 0; i < count; i++) 
-    {
-      jobject item;
-      const char *label;
-
-      item = (*env)->GetObjectArrayElement (env, items, i);
-      label = (*env)->GetStringUTFChars (env, item, NULL);
-
-      gtk_combo_box_append_text (GTK_COMBO_BOX (bin), label);
-
-      (*env)->ReleaseStringUTFChars (env, item, label);
-      (*env)->DeleteLocalRef(env, item);
-    }
-
-  gdk_threads_leave ();
-}
-
-JNIEXPORT void JNICALL 
-Java_gnu_java_awt_peer_gtk_GtkChoicePeer_nativeAdd 
+Java_gnu_java_awt_peer_gtk_GtkChoicePeer_add 
   (JNIEnv *env, jobject obj, jstring item, jint index)
 {
   void *ptr;
@@ -170,14 +138,16 @@
 
   ptr = NSA_GET_PTR (env, obj);
   bin = choice_get_widget (GTK_WIDGET (ptr));
-  
+
+  /* First, unselect everything, to avoid problems when removing items. */
+  gtk_combo_box_set_active (GTK_COMBO_BOX (bin), -1);
   gtk_combo_box_remove_text (GTK_COMBO_BOX (bin), index);
 
   gdk_threads_leave ();
 }
 
-JNIEXPORT void JNICALL 
-Java_gnu_java_awt_peer_gtk_GtkChoicePeer_nativeRemoveAll 
+JNIEXPORT void JNICALL
+Java_gnu_java_awt_peer_gtk_GtkChoicePeer_nativeRemoveAll
   (JNIEnv *env, jobject obj)
 {
   void *ptr;
@@ -224,8 +194,7 @@
   
   ptr = NSA_GET_PTR (env, obj);
   bin = choice_get_widget (GTK_WIDGET (ptr));
-  
-  gtk_combo_box_set_active (GTK_COMBO_BOX (bin), index);
+  gtk_combo_box_set_active (GTK_COMBO_BOX (bin), (gint)index);
 }
 
 JNIEXPORT jint JNICALL 
@@ -251,26 +220,11 @@
 static void
 selection_changed_cb (GtkComboBox *combobox, jobject peer)
 {
-  jstring label;
-  GtkTreeModel *model;
-  GtkTreeIter iter;
-  gchar *selected;
-  gint index;
-
-  index = gtk_combo_box_get_active(combobox);
+  gint index = gtk_combo_box_get_active(combobox);
 
   if (index >= 0)
-    {
-      model = gtk_combo_box_get_model (combobox);
-      gtk_combo_box_get_active_iter (combobox, &iter);
-      gtk_tree_model_get (model, &iter, 0, &selected, -1);
-      label = (*cp_gtk_gdk_env())->NewStringUTF (cp_gtk_gdk_env(), selected);
-
-      (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer,
-                                    postChoiceItemEventID,
-                                    label,
-                                    (jint) AWT_ITEM_SELECTED);
-    }
+    (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer,
+					 postChoiceItemEventID, (jint)index );
 }
 
 static GtkWidget *

Reply via email to