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 *