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