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;