1 /* gtkcheckboxpeer.c -- Native implementation of GtkCheckboxPeer
2    Copyright (C) 1998, 1999, 2002, 2003, 2004, 2006
3    Free Software Foundation, Inc.
4 
5 This file is part of GNU Classpath.
6 
7 GNU Classpath is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
11 
12 GNU Classpath is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 General Public License for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with GNU Classpath; see the file COPYING.  If not, write to the
19 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20 02110-1301 USA.
21 
22 Linking this library statically or dynamically with other modules is
23 making a combined work based on this library.  Thus, the terms and
24 conditions of the GNU General Public License cover the whole
25 combination.
26 
27 As a special exception, the copyright holders of this library give you
28 permission to link this library with independent modules to produce an
29 executable, regardless of the license terms of these independent
30 modules, and to copy and distribute the resulting executable under
31 terms of your choice, provided that you also meet, for each linked
32 independent module, the terms and conditions of the license of that
33 module.  An independent module is a module which is not derived from
34 or based on this library.  If you modify this library, you may extend
35 this exception to your version of the library, but you are not
36 obligated to do so.  If you do not wish to do so, delete this
37 exception statement from your version. */
38 
39 
40 #include "gtkpeer.h"
41 #include "gnu_java_awt_peer_gtk_GtkCheckboxPeer.h"
42 #include "gnu_java_awt_peer_gtk_GtkComponentPeer.h"
43 #include "jcl.h"
44 
45 static jmethodID postItemEventID;
46 static jmethodID addToGroupMapID;
47 static GtkWidget *checkbox_get_widget (GtkWidget *widget);
48 static void item_toggled_cb (GtkToggleButton *item, jobject peer);
49 
50 void
cp_gtk_checkbox_init_jni(void)51 cp_gtk_checkbox_init_jni (void)
52 {
53   jclass gtkcheckboxpeer;
54 
55   gtkcheckboxpeer = (*cp_gtk_gdk_env())->FindClass (cp_gtk_gdk_env(),
56                                              "gnu/java/awt/peer/gtk/GtkCheckboxPeer");
57 
58   postItemEventID = (*cp_gtk_gdk_env())->GetMethodID (cp_gtk_gdk_env(), gtkcheckboxpeer,
59                                                "postItemEvent",
60                                                "(Ljava/lang/Object;Z)V");
61 
62   addToGroupMapID = (*cp_gtk_gdk_env())->GetMethodID (cp_gtk_gdk_env(), gtkcheckboxpeer,
63                                                "addToGroupMap",
64                                                "(J)V");
65 }
66 
67 JNIEXPORT void JNICALL
Java_gnu_java_awt_peer_gtk_GtkCheckboxPeer_connectSignals(JNIEnv * env,jobject obj)68 Java_gnu_java_awt_peer_gtk_GtkCheckboxPeer_connectSignals
69   (JNIEnv *env, jobject obj)
70 {
71   void *ptr;
72   jobject gref;
73   GtkWidget *bin;
74 
75   gdk_threads_enter ();
76 
77   ptr = gtkpeer_get_widget (env, obj);
78   gref = gtkpeer_get_global_ref (env, obj);
79   bin = checkbox_get_widget (GTK_WIDGET (ptr));
80 
81   /* Checkbox signals */
82   g_signal_connect (G_OBJECT (bin), "toggled",
83                     G_CALLBACK (item_toggled_cb), gref);
84 
85   /* Component signals */
86   cp_gtk_component_connect_signals (G_OBJECT (bin), gref);
87 
88   gdk_threads_leave ();
89 }
90 
91 JNIEXPORT void JNICALL
Java_gnu_java_awt_peer_gtk_GtkCheckboxPeer_gtkToggleButtonSetActive(JNIEnv * env,jobject obj,jboolean is_active)92 Java_gnu_java_awt_peer_gtk_GtkCheckboxPeer_gtkToggleButtonSetActive
93   (JNIEnv *env, jobject obj, jboolean is_active)
94 {
95   void *ptr;
96   GtkWidget *bin;
97 
98   gdk_threads_enter ();
99 
100   ptr = gtkpeer_get_widget (env, obj);
101   bin = checkbox_get_widget (GTK_WIDGET (ptr));
102 
103   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (bin), is_active);
104 
105   gdk_threads_leave ();
106 }
107 
108 JNIEXPORT void JNICALL
Java_gnu_java_awt_peer_gtk_GtkCheckboxPeer_gtkWidgetModifyFont(JNIEnv * env,jobject obj,jstring name,jint style,jint size)109 Java_gnu_java_awt_peer_gtk_GtkCheckboxPeer_gtkWidgetModifyFont
110   (JNIEnv *env, jobject obj, jstring name, jint style, jint size)
111 {
112   const char *font_name;
113   void *ptr;
114   GtkWidget *button;
115   GtkWidget *label;
116   PangoFontDescription *font_desc;
117 
118   gdk_threads_enter();
119 
120   ptr = gtkpeer_get_widget (env, obj);
121 
122   button = checkbox_get_widget (GTK_WIDGET (ptr));
123   label = gtk_bin_get_child (GTK_BIN(button));
124 
125   if (!label)
126     return;
127 
128   font_name = (*env)->GetStringUTFChars (env, name, NULL);
129 
130   font_desc = pango_font_description_from_string (font_name);
131   pango_font_description_set_size (font_desc,
132                                    size * cp_gtk_dpi_conversion_factor);
133 
134   if (style & AWT_STYLE_BOLD)
135     pango_font_description_set_weight (font_desc, PANGO_WEIGHT_BOLD);
136 
137   if (style & AWT_STYLE_ITALIC)
138     pango_font_description_set_style (font_desc, PANGO_STYLE_OBLIQUE);
139 
140   gtk_widget_modify_font (GTK_WIDGET(label), font_desc);
141 
142   pango_font_description_free (font_desc);
143 
144   (*env)->ReleaseStringUTFChars (env, name, font_name);
145 
146   gdk_threads_leave();
147 }
148 
149 JNIEXPORT void JNICALL
Java_gnu_java_awt_peer_gtk_GtkCheckboxPeer_gtkButtonSetLabel(JNIEnv * env,jobject obj,jstring label)150 Java_gnu_java_awt_peer_gtk_GtkCheckboxPeer_gtkButtonSetLabel
151   (JNIEnv *env, jobject obj, jstring label)
152 {
153   const char *c_label;
154   GtkWidget *label_widget;
155   void *ptr;
156 
157   gdk_threads_enter ();
158 
159   ptr = gtkpeer_get_widget (env, obj);
160 
161   c_label = (*env)->GetStringUTFChars (env, label, NULL);
162 
163   label_widget = gtk_bin_get_child (GTK_BIN (checkbox_get_widget (GTK_WIDGET (ptr))));
164   gtk_label_set_text (GTK_LABEL (label_widget), c_label);
165 
166   (*env)->ReleaseStringUTFChars (env, label, c_label);
167 
168   gdk_threads_leave ();
169 }
170 
171 /* A check button is created if we are not part of
172    a group.
173    This function is called when initially creating the
174    button, so an eventbox is created.
175  */
176 JNIEXPORT void JNICALL
Java_gnu_java_awt_peer_gtk_GtkCheckboxPeer_createCheckButton(JNIEnv * env,jobject obj)177 Java_gnu_java_awt_peer_gtk_GtkCheckboxPeer_createCheckButton
178   (JNIEnv *env, jobject obj)
179 {
180   GtkWidget *button;
181   GtkWidget *eventbox;
182 
183   gdk_threads_enter ();
184 
185   gtkpeer_set_global_ref (env, obj);
186   eventbox = gtk_event_box_new ();
187 
188   button = gtk_check_button_new_with_label ("");
189   gtk_container_add (GTK_CONTAINER (eventbox), button);
190   gtk_widget_show (button);
191 
192   gtkpeer_set_widget (env, obj, eventbox);
193 
194   gdk_threads_leave ();
195 }
196 
197 /* A radio button is created if we are part of a group.
198    groupPointer points to the corresponding group. If 0,
199    a new group is created.
200    This function is called when initially creating the
201    button, so an eventbox is created.
202  */
203 JNIEXPORT void JNICALL
Java_gnu_java_awt_peer_gtk_GtkCheckboxPeer_createRadioButton(JNIEnv * env,jobject obj,jlong groupPointer)204 Java_gnu_java_awt_peer_gtk_GtkCheckboxPeer_createRadioButton
205   (JNIEnv *env, jobject obj, jlong groupPointer)
206 {
207   GtkWidget *button;
208   GtkWidget *eventbox;
209   GSList *native_group = NULL;
210 
211   gdk_threads_enter ();
212 
213   gtkpeer_set_global_ref (env, obj);
214   eventbox = gtk_event_box_new ();
215 
216   if (groupPointer != 0)
217   {
218     native_group = JLONG_TO_PTR (GSList, groupPointer);
219     g_assert (GTK_IS_RADIO_BUTTON (native_group->data));
220   }
221   button = gtk_radio_button_new_with_label (native_group, "");
222 
223   if (native_group == NULL)
224     native_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (button));
225   if (g_slist_index (native_group, GTK_RADIO_BUTTON (button)) == -1)
226   {
227     native_group = g_slist_prepend (native_group, GTK_RADIO_BUTTON (button));
228     GTK_RADIO_BUTTON(button)->group = native_group;
229   }
230 
231   gtk_container_add (GTK_CONTAINER (eventbox), button);
232   gtk_widget_show (button);
233 
234   gtkpeer_set_widget (env, obj, eventbox);
235 
236   (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), obj,
237                                 addToGroupMapID,
238                                 PTR_TO_JLONG (native_group));
239 
240   gdk_threads_leave ();
241 }
242 
243 /* Add the object to the group pointed to by groupPointer.
244    If groupPointer is 0, create a new group and create
245    a radio button. Otherwise, creating a radio button in an
246    existing group.
247  */
248 JNIEXPORT void JNICALL
Java_gnu_java_awt_peer_gtk_GtkCheckboxPeer_addToGroup(JNIEnv * env,jobject obj,jlong groupPointer)249 Java_gnu_java_awt_peer_gtk_GtkCheckboxPeer_addToGroup
250   (JNIEnv *env, jobject obj, jlong groupPointer)
251 {
252   void *ptr;
253   GtkWidget *container;
254   GtkWidget *check_button;
255   GtkWidget *radio_button;
256   const gchar *label;
257   GSList *native_group = NULL;
258 
259   gdk_threads_enter ();
260 
261   ptr = gtkpeer_get_widget (env, obj);
262   container = GTK_WIDGET (ptr);
263   check_button = checkbox_get_widget (container);
264   label = gtk_label_get_text (GTK_LABEL (gtk_bin_get_child
265                                         (GTK_BIN (check_button))));
266 
267   /* Need to remove the check_button, and replace it with
268      a radio button in a group.
269    */
270   if (groupPointer != 0)
271     {
272       native_group = JLONG_TO_PTR (GSList, groupPointer);
273       g_assert (GTK_IS_RADIO_BUTTON (native_group->data));
274     }
275 
276   radio_button = gtk_radio_button_new_with_label (native_group, label);
277   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (radio_button),
278              gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (check_button)));
279 
280   if (native_group == NULL)
281     native_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (radio_button));
282   if (g_slist_index (native_group, GTK_RADIO_BUTTON (radio_button)) == -1)
283   {
284     native_group = g_slist_prepend (native_group, GTK_RADIO_BUTTON (radio_button));
285     GTK_RADIO_BUTTON(radio_button)->group = native_group;
286   }
287 
288   gtk_container_remove (GTK_CONTAINER (container), check_button);
289   gtk_container_add (GTK_CONTAINER (container), radio_button);
290   gtk_widget_show (radio_button);
291 
292   (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), obj,
293                                 addToGroupMapID,
294                                 PTR_TO_JLONG (native_group));
295 
296   gdk_threads_leave ();
297 }
298 
299 /* Remove the object from the group pointed to by groupPointer.
300    We are removing the radio button and creating a check button.
301  */
302 JNIEXPORT void JNICALL
Java_gnu_java_awt_peer_gtk_GtkCheckboxPeer_removeFromGroup(JNIEnv * env,jobject obj)303 Java_gnu_java_awt_peer_gtk_GtkCheckboxPeer_removeFromGroup
304   (JNIEnv *env, jobject obj)
305 {
306   void *ptr;
307   GtkWidget *container;
308   GtkWidget *check_button;
309   GtkWidget *radio_button;
310   GSList *native_group;
311   const gchar *label;
312 
313   gdk_threads_enter ();
314 
315   ptr = gtkpeer_get_widget (env, obj);
316   container = GTK_WIDGET (ptr);
317   radio_button = checkbox_get_widget (container);
318   label = gtk_label_get_text (GTK_LABEL (gtk_bin_get_child
319                                         (GTK_BIN (radio_button))));
320 
321   /* Need to remove the radio_button, and replace it with
322      a check button.
323    */
324   check_button = gtk_check_button_new_with_label (label);
325   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check_button),
326              gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (radio_button)));
327 
328   native_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (radio_button));
329   native_group = g_slist_remove (native_group, GTK_RADIO_BUTTON (radio_button));
330 
331   if (native_group && ! GTK_IS_RADIO_BUTTON (native_group->data))
332     native_group = NULL;
333 
334   GTK_RADIO_BUTTON(radio_button)->group = NULL;
335 
336   gtk_container_remove (GTK_CONTAINER (container), radio_button);
337   gtk_container_add (GTK_CONTAINER (container), check_button);
338   gtk_widget_show (check_button);
339 
340   (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), obj,
341                                 addToGroupMapID,
342                                 PTR_TO_JLONG (native_group));
343 
344   gdk_threads_leave ();
345 }
346 
347 /* Move the radio button to a new group. If groupPointer is
348    0, create a new group.
349  */
350 JNIEXPORT void JNICALL
Java_gnu_java_awt_peer_gtk_GtkCheckboxPeer_switchToGroup(JNIEnv * env,jobject obj,jlong groupPointer)351 Java_gnu_java_awt_peer_gtk_GtkCheckboxPeer_switchToGroup
352   (JNIEnv *env, jobject obj, jlong groupPointer)
353 {
354   void *ptr;
355   GtkWidget *radio_button;
356   GSList *native_group = NULL;
357 
358   gdk_threads_enter ();
359 
360   ptr = gtkpeer_get_widget (env, obj);
361   radio_button = checkbox_get_widget (GTK_WIDGET (ptr));
362 
363   native_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (radio_button));
364   native_group = g_slist_remove (native_group, GTK_RADIO_BUTTON (radio_button));
365   GTK_RADIO_BUTTON(radio_button)->group = NULL;
366 
367   if (groupPointer != 0)
368   {
369     native_group = JLONG_TO_PTR (GSList, groupPointer);
370     g_assert (GTK_IS_RADIO_BUTTON (native_group->data));
371   }
372   gtk_radio_button_set_group (GTK_RADIO_BUTTON (radio_button), native_group);
373 
374   native_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (radio_button));
375   if (g_slist_index (native_group, GTK_RADIO_BUTTON (radio_button)) == -1)
376   {
377     native_group = g_slist_prepend (native_group, GTK_RADIO_BUTTON (radio_button));
378     GTK_RADIO_BUTTON(radio_button)->group = native_group;
379   }
380 
381   (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), obj,
382                                 addToGroupMapID,
383                                 PTR_TO_JLONG (native_group));
384 
385   gdk_threads_leave ();
386 }
387 
388 static void
item_toggled_cb(GtkToggleButton * item,jobject peer)389 item_toggled_cb (GtkToggleButton *item, jobject peer)
390 {
391   (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer,
392                                 postItemEventID,
393                                 peer,
394                                 item->active);
395 }
396 
397 static GtkWidget *
checkbox_get_widget(GtkWidget * widget)398 checkbox_get_widget (GtkWidget *widget)
399 {
400   GtkWidget *wid;
401 
402   g_assert (GTK_IS_EVENT_BOX (widget));
403   wid = gtk_bin_get_child (GTK_BIN(widget));
404 
405   return wid;
406 }
407 
408