This patch fixes the long standing problem of not being able to
dynamically switch between a checkbox and a radio button. I.e. moving a
checkbox to a checkbox group changes the checkbox to a radio button.

Tom helped a lot with this patch. He removed the CheckboxGroupPeer and
we fixed it so everything is handled in GtkCheckboxPeer.

There is a mauve test for this. The harmony test
(test.java.awt.CheckboxTest) now passes.


2006-06-30  Lillian Angel  <[EMAIL PROTECTED]>
            Tom Fitzsimmons <[EMAIL PROTECTED]>

        * gnu/java/awt/peer/gtk/GtkCheckboxGroupPeer.java: Removed 
        class.
        * gnu/java/awt/peer/gtk/GtkCheckboxPeer.java:
        Added current_group, groupMap fields. Added definitions for
        new native functions.
        (create): Removed FIXME. Added code to create the check button 
        or radio button when appropriate. Updated groupMap to contain
        pointer to the newly created group.
        (setCheckboxGroup): Added code to handle all cases. Removing
        a button from a group, adding a button to a group, or changing 
        the group of a button.
        (dispose): Changed to call super.
        * include/Makefile.am: Removed reference to
        gnu_java_awt_peer_gtk_GtkCheckboxGroupPeer.h.
        * include/gnu_java_awt_peer_gtk_GtkCheckboxGroupPeer.h: Removed 
        file.
        * include/gnu_java_awt_peer_gtk_GtkCheckboxPeer.h: Added 
        definitions for new functions.
        * native/jni/gtk-peer/Makefile.am: Removed reference to
        gnu_java_awt_peer_gtk_GtkCheckboxGroupPeer.c.
        *
native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkCheckboxGroupPeer.c:
        Removed file.
        * native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkCheckboxPeer.c
       (Java_gnu_java_awt_peer_gtk_GtkCheckboxPeer_combobox_get_widget):
        Renamed to checkbox_get_widget.
        (Java_gnu_java_awt_peer_gtk_GtkCheckboxPeer_connectSignals):
        Changed to use checkbox_get_widget.

(Java_gnu_java_awt_peer_gtk_GtkCheckboxPeer_nativeSetCheckboxGroup):
        Removed.

(Java_gnu_java_awt_peer_gtk_GtkCheckboxPeer_gtkWidgetModifyFont):
        Changed to use checkbox_get_widget.
        (Java_gnu_java_awt_peer_gtk_GtkCheckboxPeer_gtkButtonSetLabel):
        Likewise.
        (Java_gnu_java_awt_peer_gtk_GtkCheckboxPeer_createCheckButton):
        New function. Creates checkbutton without a group.
        (Java_gnu_java_awt_peer_gtk_GtkCheckboxPeer_createRadioButton):
        Creates a radio button in a group, using groupPointer. If 
        groupPointer is 0, then a new group is created.
        (Java_gnu_java_awt_peer_gtk_GtkCheckboxPeer_addToGroup): Adds 
        the check button to a group, using groupPointer. A radio button 
        is created in its place. If groupPointer is 0, then a new group 
        is created.
        (Java_gnu_java_awt_peer_gtk_GtkCheckboxPeer_removeFromGroup): 
        The radio button is removed from the group. A check button is 
        created in its place.
        (Java_gnu_java_awt_peer_gtk_GtkCheckboxPeer_switchToGroup): The
        radio button is moved to a new group.

Index: gnu/java/awt/peer/gtk/GtkCheckboxGroupPeer.java
===================================================================
RCS file: gnu/java/awt/peer/gtk/GtkCheckboxGroupPeer.java
diff -N gnu/java/awt/peer/gtk/GtkCheckboxGroupPeer.java
--- gnu/java/awt/peer/gtk/GtkCheckboxGroupPeer.java	2 Jul 2005 20:32:12 -0000	1.3
+++ /dev/null	1 Jan 1970 00:00:00 -0000
@@ -1,86 +0,0 @@
-/* GtkCheckboxGroupPeer.java - Wrap a CheckboxGroup
-   Copyright (C) 2002 Free Software Foundation, Inc.
-
-This file is part of GNU Classpath.
-
-GNU Classpath is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Classpath 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 for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Classpath; see the file COPYING.  If not, write to the
-Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301 USA.
-
-Linking this library statically or dynamically with other modules is
-making a combined work based on this library.  Thus, the terms and
-conditions of the GNU General Public License cover the whole
-combination.
-
-As a special exception, the copyright holders of this library give you
-permission to link this library with independent modules to produce an
-executable, regardless of the license terms of these independent
-modules, and to copy and distribute the resulting executable under
-terms of your choice, provided that you also meet, for each linked
-independent module, the terms and conditions of the license of that
-module.  An independent module is a module which is not derived from
-or based on this library.  If you modify this library, you may extend
-this exception to your version of the library, but you are not
-obligated to do so.  If you do not wish to do so, delete this
-exception statement from your version. */
-
-
-package gnu.java.awt.peer.gtk;
-
-import java.awt.CheckboxGroup;
-import java.util.WeakHashMap;
-
-// Note that there is no peer interface for a CheckboxGroup.  We
-// introduce our own in order to make it easier to keep a piece of
-// native state for each one.
-public class GtkCheckboxGroupPeer extends GtkGenericPeer
-{
-  // This maps from a CheckboxGroup to the native peer.
-  private static WeakHashMap map = new WeakHashMap ();
-
-  // Find the native peer corresponding to a CheckboxGroup.
-  public static synchronized GtkCheckboxGroupPeer
-      getCheckboxGroupPeer (CheckboxGroup group)
-  {
-    if (group == null)
-      return null;
-    GtkCheckboxGroupPeer nat = (GtkCheckboxGroupPeer) map.get (group);
-    if (nat == null)
-      {
-	nat = new GtkCheckboxGroupPeer ();
-	map.put (group, nat);
-      }
-    return nat;
-  }
-
-  private GtkCheckboxGroupPeer ()
-  {
-    // We don't need any special state here.  Note that we can't store
-    // a reference to the java-side CheckboxGroup.  That would mean
-    // they could never be collected.
-    super (null);
-  }
-
-  // Dispose of our native resources.
-  public native void dispose ();
-
-  // Remove a given checkbox from this group.
-  public native void remove (GtkCheckboxPeer box);
-
-  // When collected, clean up the native state.
-  protected void finalize ()
-  {
-    dispose ();
-  }
-}
Index: gnu/java/awt/peer/gtk/GtkCheckboxPeer.java
===================================================================
RCS file: /cvsroot/classpath/classpath/gnu/java/awt/peer/gtk/GtkCheckboxPeer.java,v
retrieving revision 1.25
diff -u -r1.25 GtkCheckboxPeer.java
--- gnu/java/awt/peer/gtk/GtkCheckboxPeer.java	20 Jun 2006 20:36:14 -0000	1.25
+++ gnu/java/awt/peer/gtk/GtkCheckboxPeer.java	30 Jun 2006 14:28:14 -0000
@@ -40,20 +40,32 @@
 
 import java.awt.Checkbox;
 import java.awt.CheckboxGroup;
-import java.awt.peer.CheckboxPeer;
-
 import java.awt.event.ItemEvent;
+import java.awt.peer.CheckboxPeer;
+import java.util.WeakHashMap;
 
+/**
+ * This class wraps either a GtkCheckButton or a GtkOptionButton
+ * depending on if this peer's owner belongs to a CheckboxGroup.
+ */
 public class GtkCheckboxPeer extends GtkComponentPeer
   implements CheckboxPeer
 {
-  // Group from last time it was set.
-  public GtkCheckboxGroupPeer old_group;
+  // The CheckboxGroup to which this GtkCheckboxPeer's owner belongs.
+  public CheckboxGroup current_group;
   // The current state of the GTK checkbox.
-  private boolean currentState;  
+  private boolean currentState;
+
+  // A map from CheckboxGroup to GSList* GTK option group pointer.
+  private static WeakHashMap groupMap = new WeakHashMap();
+
+  public native void createCheckButton ();
+  public native long createRadioButton (long groupPointer);
 
-  public native void create (GtkCheckboxGroupPeer group);
-  public native void nativeSetCheckboxGroup (GtkCheckboxGroupPeer group);
+  public native long addToGroup (long groupPointer);
+  public native long removeFromGroup ();
+  public native long switchToGroup (long groupPointer);
+  
   public native void connectSignals ();
 
   /**
@@ -68,14 +80,37 @@
     super (c);
   }
 
-  // FIXME: we must be able to switch between a checkbutton and a
-  // radiobutton dynamically.
   public void create ()
   {
     Checkbox checkbox = (Checkbox) awtComponent;
-    CheckboxGroup g = checkbox.getCheckboxGroup ();
-    old_group = GtkCheckboxGroupPeer.getCheckboxGroupPeer (g);
-    create (old_group);
+    current_group = checkbox.getCheckboxGroup ();
+    if (current_group == null)
+      {
+        // Initially we're not part of a group so we're backed by a
+        // GtkCheckButton.
+        createCheckButton();
+      }
+    else
+      {
+        // Initially we're part of a group.
+
+        // See if this group is already stored in our map.
+        Long groupPointer = (Long) groupMap.get(current_group);
+        if (groupPointer == null)
+          {
+            // We don't know about this group.  Create a new native
+            // group pointer for this group and store it in our map.
+            groupMap.put(current_group, new Long (createRadioButton(0)));
+          }
+        else
+          {
+            // We already know about this group.  Pass the
+            // corresponding native group pointer value to the native
+            // create method.
+            groupMap.put(current_group,
+                         new Long(createRadioButton(groupPointer.longValue())));
+          }
+      }
     currentState = checkbox.getState();
     gtkToggleButtonSetActive(currentState);
     
@@ -106,14 +141,71 @@
 
   public void setCheckboxGroup (CheckboxGroup group)
   {
-    GtkCheckboxGroupPeer gp
-      = GtkCheckboxGroupPeer.getCheckboxGroupPeer (group);
-    if (gp != old_group)
-      {
-	if (old_group != null)
-	  old_group.remove (this);
-	nativeSetCheckboxGroup (gp);
-	old_group = gp;
+    if (current_group == null && group != null)
+      {
+        // This peer's owner is currently not in a group, and now
+        // we're adding it to a group.  This means that the backing
+        // GtkWidget will change from a GtkCheckButton to a
+        // GtkRadioButton.
+
+        current_group = group;
+
+        // See if the new group is already stored in our map.
+        Long groupPointer = (Long) groupMap.get(current_group);
+        if (groupPointer == null)
+          {
+            // We don't know about this group.  Create a new native
+            // group pointer for this group and store it in our map.
+            groupMap.put(current_group, new Long (addToGroup(0)));
+          }
+        else
+          {
+            // We already know about this group.  Pass the
+            // corresponding native group pointer value to the native
+            // create method.
+            groupMap.put(current_group,
+                         new Long(addToGroup(groupPointer.longValue())));
+          }
+      }
+    else if (current_group != null && group == null)
+      {
+        // This peer's owner is currently in a group, and now we're
+        // removing it from a group.  This means that the backing
+        // GtkWidget will change from a GtkRadioButton to a
+        // GtkCheckButton.
+        groupMap.put(current_group, new Long (removeFromGroup()));
+        current_group = group;
+      }
+    else if (current_group == null && group == null)
+      {
+        // This peer's owner is currently not in a group, and we're
+        // not adding it to a group, so simply return.
+        return;
+      }
+    else if (current_group != group)
+      {
+        // This peer's owner is currently in a group, and now we're
+        // putting it in another group.  This means that we must
+        // remove the backing GtkRadioButton from one group and add it
+        // to the other group.
+
+        // See if the new group is already stored in our map.
+        Long groupPointer = (Long) groupMap.get(group);
+        if (groupPointer == null)
+          {
+            // We don't know about this group.  Create a new native
+            // group pointer for this group and store it in our map.
+            groupMap.put(group, new Long (switchToGroup(0)));
+          }
+        else
+          {
+            // We already know about this group.  Pass the
+            // corresponding native group pointer value to the native
+            // create method.
+            groupMap.put(group,
+                         new Long(switchToGroup(groupPointer.longValue())));
+          }
+        current_group = group;
       }
   }
 
@@ -133,10 +225,6 @@
 
   public void dispose ()
   {
-    // Notify the group so that the native state can be cleaned up
-    // appropriately.
-    if (old_group != null)
-      old_group.remove (this);
     super.dispose ();
   }
 }
Index: include/Makefile.am
===================================================================
RCS file: /cvsroot/classpath/classpath/include/Makefile.am,v
retrieving revision 1.66
diff -u -r1.66 Makefile.am
--- include/Makefile.am	18 Jun 2006 09:16:43 -0000	1.66
+++ include/Makefile.am	30 Jun 2006 14:28:15 -0000
@@ -50,7 +50,6 @@
 $(top_srcdir)/include/gnu_java_awt_peer_gtk_GdkTextLayout.h \
 $(top_srcdir)/include/gnu_java_awt_peer_gtk_GtkButtonPeer.h \
 $(top_srcdir)/include/gnu_java_awt_peer_gtk_GtkCanvasPeer.h \
-$(top_srcdir)/include/gnu_java_awt_peer_gtk_GtkCheckboxGroupPeer.h \
 $(top_srcdir)/include/gnu_java_awt_peer_gtk_GtkCheckboxMenuItemPeer.h \
 $(top_srcdir)/include/gnu_java_awt_peer_gtk_GtkCheckboxPeer.h \
 $(top_srcdir)/include/gnu_java_awt_peer_gtk_GtkChoicePeer.h \
Index: include/gnu_java_awt_peer_gtk_GtkCheckboxGroupPeer.h
===================================================================
RCS file: include/gnu_java_awt_peer_gtk_GtkCheckboxGroupPeer.h
diff -N include/gnu_java_awt_peer_gtk_GtkCheckboxGroupPeer.h
--- include/gnu_java_awt_peer_gtk_GtkCheckboxGroupPeer.h	30 Apr 2006 10:37:36 -0000	1.5
+++ /dev/null	1 Jan 1970 00:00:00 -0000
@@ -1,20 +0,0 @@
-/* DO NOT EDIT THIS FILE - it is machine generated */
-
-#ifndef __gnu_java_awt_peer_gtk_GtkCheckboxGroupPeer__
-#define __gnu_java_awt_peer_gtk_GtkCheckboxGroupPeer__
-
-#include <jni.h>
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkCheckboxGroupPeer_dispose (JNIEnv *env, jobject);
-JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkCheckboxGroupPeer_remove (JNIEnv *env, jobject, jobject);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __gnu_java_awt_peer_gtk_GtkCheckboxGroupPeer__ */
Index: include/gnu_java_awt_peer_gtk_GtkCheckboxPeer.h
===================================================================
RCS file: /cvsroot/classpath/classpath/include/gnu_java_awt_peer_gtk_GtkCheckboxPeer.h,v
retrieving revision 1.10
diff -u -r1.10 gnu_java_awt_peer_gtk_GtkCheckboxPeer.h
--- include/gnu_java_awt_peer_gtk_GtkCheckboxPeer.h	30 Apr 2006 10:37:36 -0000	1.10
+++ include/gnu_java_awt_peer_gtk_GtkCheckboxPeer.h	30 Jun 2006 14:28:15 -0000
@@ -10,8 +10,11 @@
 {
 #endif
 
-JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkCheckboxPeer_create (JNIEnv *env, jobject, jobject);
-JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkCheckboxPeer_nativeSetCheckboxGroup (JNIEnv *env, jobject, jobject);
+JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkCheckboxPeer_createCheckButton (JNIEnv *env, jobject);
+JNIEXPORT jlong JNICALL Java_gnu_java_awt_peer_gtk_GtkCheckboxPeer_createRadioButton (JNIEnv *env, jobject, jlong);
+JNIEXPORT jlong JNICALL Java_gnu_java_awt_peer_gtk_GtkCheckboxPeer_addToGroup (JNIEnv *env, jobject, jlong);
+JNIEXPORT jlong JNICALL Java_gnu_java_awt_peer_gtk_GtkCheckboxPeer_removeFromGroup (JNIEnv *env, jobject);
+JNIEXPORT jlong JNICALL Java_gnu_java_awt_peer_gtk_GtkCheckboxPeer_switchToGroup (JNIEnv *env, jobject, jlong);
 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkCheckboxPeer_connectSignals (JNIEnv *env, jobject);
 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkCheckboxPeer_gtkWidgetModifyFont (JNIEnv *env, jobject, jstring, jint, jint);
 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkCheckboxPeer_gtkButtonSetLabel (JNIEnv *env, jobject, jstring);
Index: native/jni/gtk-peer/Makefile.am
===================================================================
RCS file: /cvsroot/classpath/classpath/native/jni/gtk-peer/Makefile.am,v
retrieving revision 1.45
diff -u -r1.45 Makefile.am
--- native/jni/gtk-peer/Makefile.am	7 Jun 2006 13:54:32 -0000	1.45
+++ native/jni/gtk-peer/Makefile.am	30 Jun 2006 14:28:16 -0000
@@ -15,7 +15,6 @@
 			gnu_java_awt_peer_gtk_GdkTextLayout.c \
 			gnu_java_awt_peer_gtk_GtkButtonPeer.c \
 			gnu_java_awt_peer_gtk_GtkCanvasPeer.c \
-			gnu_java_awt_peer_gtk_GtkCheckboxGroupPeer.c \
 			gnu_java_awt_peer_gtk_GtkCheckboxMenuItemPeer.c \
 			gnu_java_awt_peer_gtk_GtkCheckboxPeer.c \
 			gnu_java_awt_peer_gtk_GtkChoicePeer.c \
Index: native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkCheckboxGroupPeer.c
===================================================================
RCS file: native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkCheckboxGroupPeer.c
diff -N native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkCheckboxGroupPeer.c
--- native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkCheckboxGroupPeer.c	10 Mar 2006 21:06:34 -0000	1.6
+++ /dev/null	1 Jan 1970 00:00:00 -0000
@@ -1,87 +0,0 @@
-/* gtkcheckboxgrouppeer.c -- Native implementation of GtkCheckboxGroupPeer
-   Copyright (C) 2004  Free Software Foundation, Inc.
-
-This file is part of GNU Classpath.
-
-GNU Classpath is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Classpath 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 for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Classpath; see the file COPYING.  If not, write to the
-Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301 USA.
-
-Linking this library statically or dynamically with other modules is
-making a combined work based on this library.  Thus, the terms and
-conditions of the GNU General Public License cover the whole
-combination.
-
-As a special exception, the copyright holders of this library give you
-permission to link this library with independent modules to produce an
-executable, regardless of the license terms of these independent
-modules, and to copy and distribute the resulting executable under
-terms of your choice, provided that you also meet, for each linked
-independent module, the terms and conditions of the license of that
-module.  An independent module is a module which is not derived from
-or based on this library.  If you modify this library, you may extend
-this exception to your version of the library, but you are not
-obligated to do so.  If you do not wish to do so, delete this
-exception statement from your version. */
-
-
-#include "gtkpeer.h"
-#include "gnu_java_awt_peer_gtk_GtkCheckboxGroupPeer.h"
-
-static GtkWidget *comboboxgroup_get_widget (GtkWidget *widget);
-
-JNIEXPORT void JNICALL
-Java_gnu_java_awt_peer_gtk_GtkCheckboxGroupPeer_dispose
-  (JNIEnv *env, jobject obj)
-{
-  /* The actual underlying widget is owned by a different class.  So
-     we just clean up the hash table here.  */
-  NSA_DEL_PTR (env, obj);
-}
-
-JNIEXPORT void JNICALL
-Java_gnu_java_awt_peer_gtk_GtkCheckboxGroupPeer_remove
-  (JNIEnv *env, jobject obj, jobject checkbox)
-{
-  GtkRadioButton *button;
-  void *ptr;
-  GSList *list;
-
-  gdk_threads_enter ();
-
-  ptr = NSA_GET_PTR (env, checkbox);
-  button = GTK_RADIO_BUTTON (comboboxgroup_get_widget (GTK_WIDGET (ptr)));
-
-  /* Update the group to point to some other widget in the group.  We
-     have to do this because Gtk doesn't have a separate object to
-     represent a radio button's group.  */
-  for (list = gtk_radio_button_get_group (button); list != NULL;
-       list = list->next)
-    {
-      if (list->data != button)
-       break;
-    }
-
-  NSA_SET_PTR (env, obj, list ? list->data : NULL);
-
-  gdk_threads_leave ();
-}
-
-static GtkWidget *
-comboboxgroup_get_widget (GtkWidget *widget)
-{
-  if (GTK_IS_EVENT_BOX (widget))
-  	return gtk_bin_get_child (GTK_BIN(widget));
-  return widget;
-}
Index: native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkCheckboxPeer.c
===================================================================
RCS file: /cvsroot/classpath/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkCheckboxPeer.c,v
retrieving revision 1.25
diff -u -r1.25 gnu_java_awt_peer_gtk_GtkCheckboxPeer.c
--- native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkCheckboxPeer.c	10 Mar 2006 21:06:34 -0000	1.25
+++ native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkCheckboxPeer.c	30 Jun 2006 14:28:16 -0000
@@ -40,9 +40,11 @@
 #include "gtkpeer.h"
 #include "gnu_java_awt_peer_gtk_GtkCheckboxPeer.h"
 #include "gnu_java_awt_peer_gtk_GtkComponentPeer.h"
+#include "jcl.h"
 
 static jmethodID postItemEventID;
-static GtkWidget *combobox_get_widget (GtkWidget *widget);
+static GtkWidget *checkbox_get_widget (GtkWidget *widget);
+static void item_toggled_cb (GtkToggleButton *item, jobject peer);
 
 void
 cp_gtk_checkbox_init_jni (void)
@@ -57,59 +59,19 @@
                                                "(Ljava/lang/Object;Z)V");
 }
 
-static void item_toggled_cb (GtkToggleButton *item, jobject peer);
-
-JNIEXPORT void JNICALL
-Java_gnu_java_awt_peer_gtk_GtkCheckboxPeer_create
-  (JNIEnv *env, jobject obj, jobject group)
-{
-  GtkWidget *button;
-  GtkWidget *eventbox;
-
-  gdk_threads_enter ();
-
-  NSA_SET_GLOBAL_REF (env, obj);
-  eventbox = gtk_event_box_new ();
-  
-  if (group == NULL)
-  {
-    button = gtk_check_button_new_with_label ("");
-    gtk_container_add (GTK_CONTAINER (eventbox), button);
-    gtk_widget_show (button); 
-  }
-  else
-    {
-      void *native_group = NSA_GET_PTR (env, group);
-      button = gtk_radio_button_new_with_label_from_widget (native_group, "");
-      gtk_container_add (GTK_CONTAINER (eventbox), button);
-      gtk_widget_show (button); 
-      
-      if (native_group == NULL)
-	  {
-	    /* Set the native group so we can use the correct value the
-	       next time around.  FIXME: this doesn't work!  */
-	    NSA_SET_PTR (env, group, button);
-	  }
-    }
-
-  NSA_SET_PTR (env, obj, eventbox);
-
-  gdk_threads_leave ();
-}
-
 JNIEXPORT void JNICALL
 Java_gnu_java_awt_peer_gtk_GtkCheckboxPeer_connectSignals
   (JNIEnv *env, jobject obj)
 {
-  void *ptr = NULL;
-  jobject *gref = NULL;
+  void *ptr;
+  jobject *gref;
   GtkWidget *bin;
 
   gdk_threads_enter ();
 
   ptr = NSA_GET_PTR (env, obj);
   gref = NSA_GET_GLOBAL_REF (env, obj);
-  bin = combobox_get_widget (GTK_WIDGET (ptr));
+  bin = checkbox_get_widget (GTK_WIDGET (ptr));
 
   /* Checkbox signals */
   g_signal_connect (G_OBJECT (bin), "toggled",
@@ -121,46 +83,6 @@
   gdk_threads_leave ();
 }
 
-JNIEXPORT void JNICALL 
-Java_gnu_java_awt_peer_gtk_GtkCheckboxPeer_nativeSetCheckboxGroup
-  (JNIEnv *env, jobject obj, jobject group)
-{
-  GtkRadioButton *button;
-  void *native_group, *ptr;
-  GtkWidget *bin;
-
-  gdk_threads_enter ();
-
-  ptr = NSA_GET_PTR (env, obj);
-  bin = combobox_get_widget (GTK_WIDGET (ptr));
-  
-  /* FIXME: we can't yet switch between a checkbutton and a
-     radiobutton.  However, AWT requires this.  For now we just
-     crash.  */
-
-  button = GTK_RADIO_BUTTON (bin);
-
-  native_group = NSA_GET_PTR (env, group);
-  if (native_group == NULL)
-    gtk_radio_button_set_group (button, NULL);
-  else
-    gtk_radio_button_set_group (button,
-				gtk_radio_button_get_group
-				(GTK_RADIO_BUTTON (native_group)));
-
-  /* If the native group wasn't set on the new CheckboxGroup, then set
-     it now so that the right thing will happen with the next
-     radiobutton.  The native state for a CheckboxGroup is a pointer
-     to one of the widgets in the group.  We are careful to keep this
-     always pointing at a live widget; whenever a widget is destroyed
-     (or otherwise removed from the group), the CheckboxGroup peer is
-     notified.  */
-  if (native_group == NULL)
-    NSA_SET_PTR (env, group, native_group);
-
-  gdk_threads_leave ();
-}
-
 JNIEXPORT void JNICALL
 Java_gnu_java_awt_peer_gtk_GtkCheckboxPeer_gtkToggleButtonSetActive
   (JNIEnv *env, jobject obj, jboolean is_active)
@@ -171,7 +93,7 @@
   gdk_threads_enter ();
 
   ptr = NSA_GET_PTR (env, obj);
-  bin = combobox_get_widget (GTK_WIDGET (ptr));
+  bin = checkbox_get_widget (GTK_WIDGET (ptr));
   
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (bin), is_active);
 
@@ -192,7 +114,7 @@
 
   ptr = NSA_GET_PTR (env, obj);
 
-  button = combobox_get_widget (GTK_WIDGET (ptr));
+  button = checkbox_get_widget (GTK_WIDGET (ptr));
   label = gtk_bin_get_child (GTK_BIN(button));
 
   if (!label)
@@ -233,7 +155,7 @@
 
   c_label = (*env)->GetStringUTFChars (env, label, NULL);
 
-  label_widget = gtk_bin_get_child (GTK_BIN (combobox_get_widget (GTK_WIDGET (ptr))));
+  label_widget = gtk_bin_get_child (GTK_BIN (checkbox_get_widget (GTK_WIDGET (ptr))));
   gtk_label_set_text (GTK_LABEL (label_widget), c_label);
 
   (*env)->ReleaseStringUTFChars (env, label, c_label);
@@ -241,6 +163,222 @@
   gdk_threads_leave ();
 }
 
+/* A check button is created if we are not part of 
+   a group. 
+   This function is called when initially creating the
+   button, so an eventbox is created.
+ */
+JNIEXPORT void JNICALL 
+Java_gnu_java_awt_peer_gtk_GtkCheckboxPeer_createCheckButton 
+  (JNIEnv *env, jobject obj)
+{
+  GtkWidget *button;
+  GtkWidget *eventbox;
+
+  gdk_threads_enter ();
+
+  NSA_SET_GLOBAL_REF (env, obj);
+  eventbox = gtk_event_box_new ();
+
+  button = gtk_check_button_new_with_label ("");
+  gtk_container_add (GTK_CONTAINER (eventbox), button);
+  gtk_widget_show (button); 
+
+  NSA_SET_PTR (env, obj, eventbox);
+
+  gdk_threads_leave ();
+}
+
+/* A radio button is created if we are part of a group. 
+   groupPointer points to the corresponding group. If 0,
+   a new group is created.
+   This function is called when initially creating the
+   button, so an eventbox is created.
+ */
+JNIEXPORT jlong JNICALL 
+Java_gnu_java_awt_peer_gtk_GtkCheckboxPeer_createRadioButton 
+  (JNIEnv *env, jobject obj, jlong groupPointer)
+{
+  GtkWidget *button;
+  GtkWidget *eventbox;
+  GSList *native_group = NULL;
+  
+  gdk_threads_enter ();
+
+  NSA_SET_GLOBAL_REF (env, obj);
+  eventbox = gtk_event_box_new ();
+
+  if (groupPointer != 0)
+  {
+    native_group = JLONG_TO_PTR (GSList, groupPointer);
+    if(! GTK_IS_RADIO_BUTTON (native_group->data))
+      native_group = NULL;
+  }
+  button = gtk_radio_button_new_with_label (native_group, "");
+  
+  if (native_group == NULL)
+    native_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (button));
+  if (g_slist_index (native_group, GTK_RADIO_BUTTON (button)) == -1)
+  {
+    native_group = g_slist_prepend (native_group, GTK_RADIO_BUTTON (button));
+    GTK_RADIO_BUTTON(button)->group = native_group;  
+  }
+  
+  gtk_container_add (GTK_CONTAINER (eventbox), button);
+  gtk_widget_show (button);
+  
+  NSA_SET_PTR (env, obj, eventbox);
+  
+  gdk_threads_leave ();
+  
+  return PTR_TO_JLONG (native_group);
+}
+
+/* Add the object to the group pointed to by groupPointer.
+   If groupPointer is 0, create a new group and create
+   a radio button. Otherwise, creating a radio button in an
+   existing group.
+ */
+JNIEXPORT jlong JNICALL 
+Java_gnu_java_awt_peer_gtk_GtkCheckboxPeer_addToGroup 
+  (JNIEnv *env, jobject obj, jlong groupPointer)
+{
+  void *ptr;
+  GtkWidget *container;
+  GtkWidget *check_button;
+  GtkWidget *radio_button;
+  const gchar *label;
+  GSList *native_group = NULL;
+
+  gdk_threads_enter ();
+
+  ptr = NSA_GET_PTR (env, obj);
+  container = GTK_WIDGET (ptr);
+  check_button = checkbox_get_widget (container);
+  label = gtk_label_get_text (GTK_LABEL (gtk_bin_get_child 
+                                        (GTK_BIN (check_button))));
+                                        
+  /* Need to remove the check_button, and replace it with 
+     a radio button in a group.
+   */
+  if (groupPointer != 0)
+    {
+      native_group = JLONG_TO_PTR (GSList, groupPointer);
+      if(! GTK_IS_RADIO_BUTTON (native_group->data))
+        native_group = NULL;
+    }
+      
+  radio_button = gtk_radio_button_new_with_label (native_group, label);
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (radio_button), 
+             gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (check_button)));
+  
+  if (native_group == NULL)
+    native_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (radio_button));
+  if (g_slist_index (native_group, GTK_RADIO_BUTTON (radio_button)) == -1)
+  {
+    native_group = g_slist_prepend (native_group, GTK_RADIO_BUTTON (radio_button));
+    GTK_RADIO_BUTTON(radio_button)->group = native_group;
+  }
+             
+  gtk_container_remove (GTK_CONTAINER (container), check_button);
+
+  NSA_DEL_PTR (env, obj);
+  NSA_SET_PTR (env, obj, container);
+  
+  gtk_container_add (GTK_CONTAINER (container), radio_button);
+  gtk_widget_show (radio_button);
+  
+  gdk_threads_leave ();
+  
+  return PTR_TO_JLONG (native_group);
+}
+
+/* Remove the object from the group pointed to by groupPointer.
+   We are removing the radio button and creating a check button. 
+ */
+JNIEXPORT jlong JNICALL 
+Java_gnu_java_awt_peer_gtk_GtkCheckboxPeer_removeFromGroup 
+  (JNIEnv *env, jobject obj)
+{
+  void *ptr;
+  GtkWidget *container;
+  GtkWidget *check_button;
+  GtkWidget *radio_button;
+  GSList *native_group;
+  const gchar *label;
+    
+  gdk_threads_enter ();
+
+  ptr = NSA_GET_PTR (env, obj);
+  container = GTK_WIDGET (ptr);
+  radio_button = checkbox_get_widget (container);
+  label = gtk_label_get_text (GTK_LABEL (gtk_bin_get_child 
+                                        (GTK_BIN (radio_button))));
+                                        
+  /* Need to remove the radio_button, and replace it with 
+     a check button.
+   */   
+  check_button = gtk_check_button_new_with_label (label);
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check_button), 
+             gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (radio_button))); 
+             
+  native_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (radio_button));
+  native_group = g_slist_remove (native_group, GTK_RADIO_BUTTON (radio_button));
+  GTK_RADIO_BUTTON(radio_button)->group = NULL;
+  
+  gtk_container_remove (GTK_CONTAINER (container), radio_button);
+    
+  NSA_DEL_PTR (env, obj);
+  NSA_SET_PTR (env, obj, container);
+  
+  gtk_container_add (GTK_CONTAINER (container), check_button);
+  gtk_widget_show (check_button);
+  
+  gdk_threads_leave ();
+  
+  return PTR_TO_JLONG (native_group);
+}
+
+/* Move the radio button to a new group. If groupPointer is
+   0, create a new group.
+ */
+JNIEXPORT jlong JNICALL 
+Java_gnu_java_awt_peer_gtk_GtkCheckboxPeer_switchToGroup 
+  (JNIEnv *env, jobject obj, jlong groupPointer)
+{
+  void *ptr;
+  GtkWidget *radio_button;
+  GSList *native_group = NULL;
+  
+  gdk_threads_enter ();
+
+  ptr = NSA_GET_PTR (env, obj);
+  radio_button = checkbox_get_widget (GTK_WIDGET (ptr));
+  
+  native_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (radio_button));
+  native_group = g_slist_remove (native_group, GTK_RADIO_BUTTON (radio_button));
+  GTK_RADIO_BUTTON(radio_button)->group = NULL;
+  
+  if (groupPointer != 0)
+  {
+    native_group = JLONG_TO_PTR (GSList, groupPointer);
+    if(! GTK_IS_RADIO_BUTTON (native_group->data))
+      native_group = NULL;
+  }
+  gtk_radio_button_set_group (GTK_RADIO_BUTTON (radio_button), native_group);
+  
+  native_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (radio_button));
+  if (g_slist_index (native_group, GTK_RADIO_BUTTON (radio_button)) == -1)
+  {
+    native_group = g_slist_prepend (native_group, GTK_RADIO_BUTTON (radio_button));
+    GTK_RADIO_BUTTON(radio_button)->group = native_group;
+  }
+   
+  gdk_threads_leave ();
+  
+  return PTR_TO_JLONG (native_group);
+}
+
 static void
 item_toggled_cb (GtkToggleButton *item, jobject peer)
 {
@@ -251,7 +389,7 @@
 }
 
 static GtkWidget *
-combobox_get_widget (GtkWidget *widget)
+checkbox_get_widget (GtkWidget *widget)
 {
   GtkWidget *wid;
 

Reply via email to