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 *