| /* GtkListPeer.c -- implements GtkListPeer's native methods |
| Copyright (C) 1998, 1999, 2003, 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_GtkListPeer.h" |
| |
| static jmethodID postListItemEventID; |
| static GtkWidget *list_get_widget (GtkWidget *widget); |
| |
| void |
| cp_gtk_list_init_jni (void) |
| { |
| jclass gtklistpeer; |
| |
| gtklistpeer = (*cp_gtk_gdk_env())->FindClass (cp_gtk_gdk_env(), |
| "gnu/java/awt/peer/gtk/GtkListPeer"); |
| |
| postListItemEventID = (*cp_gtk_gdk_env())->GetMethodID (cp_gtk_gdk_env(), gtklistpeer, |
| "postItemEvent", |
| "(II)V"); |
| } |
| |
| enum |
| { |
| COLUMN_STRING, |
| N_COLUMNS |
| }; |
| |
| static gboolean item_highlighted_cb (GtkTreeSelection *selection, |
| GtkTreeModel *model, |
| GtkTreePath *path, |
| gboolean path_currently_selected, |
| jobject peer); |
| |
| |
| JNIEXPORT void JNICALL |
| Java_gnu_java_awt_peer_gtk_GtkListPeer_create |
| (JNIEnv *env, jobject obj, jint rows) |
| { |
| GtkWidget *sw; |
| GtkWidget *list; |
| GtkWidget *eventbox; |
| GtkCellRenderer *renderer; |
| GtkTreeViewColumn *column; |
| GtkListStore *list_store; |
| GtkTreeIter iter; |
| GtkRequisition req; |
| gint i; |
| |
| gdk_threads_enter (); |
| |
| /* Create global reference and save it for future use */ |
| NSA_SET_GLOBAL_REF (env, obj); |
| |
| list_store = gtk_list_store_new (N_COLUMNS, G_TYPE_STRING); |
| /* Add the number of rows so that we can calculate the tree view's |
| size request. */ |
| for (i = 0; i < rows; i++) |
| { |
| gtk_list_store_append (list_store, &iter); |
| gtk_list_store_set (list_store, &iter, |
| COLUMN_STRING, "", |
| -1); |
| } |
| list = gtk_tree_view_new_with_model (GTK_TREE_MODEL (list_store)); |
| renderer = gtk_cell_renderer_text_new (); |
| column = gtk_tree_view_column_new_with_attributes (NULL, |
| renderer, |
| "text", |
| COLUMN_STRING, |
| NULL); |
| |
| eventbox = gtk_event_box_new (); |
| sw = gtk_scrolled_window_new (NULL, NULL); |
| gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw), |
| GTK_POLICY_AUTOMATIC, |
| GTK_POLICY_AUTOMATIC); |
| gtk_container_add (GTK_CONTAINER (eventbox), sw); |
| |
| gtk_tree_view_append_column (GTK_TREE_VIEW (list), column); |
| |
| gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (list), FALSE); |
| |
| gtk_widget_size_request (GTK_WIDGET (list), &req); |
| |
| gtk_widget_set_size_request (GTK_WIDGET (list), req.width, req.height); |
| |
| gtk_container_add (GTK_CONTAINER (sw), list); |
| |
| /* Remove the blank rows. */ |
| gtk_list_store_clear (list_store); |
| |
| gtk_widget_show (list); |
| gtk_widget_show (sw); |
| |
| NSA_SET_PTR (env, obj, eventbox); |
| |
| gdk_threads_leave (); |
| } |
| |
| JNIEXPORT void JNICALL |
| Java_gnu_java_awt_peer_gtk_GtkListPeer_connectSignals |
| (JNIEnv *env, jobject obj) |
| { |
| void *ptr; |
| jobject *gref; |
| GtkWidget *list; |
| GtkTreeSelection *selection; |
| |
| gdk_threads_enter (); |
| |
| ptr = NSA_GET_PTR (env, obj); |
| gref = NSA_GET_GLOBAL_REF (env, obj); |
| |
| list = list_get_widget (GTK_WIDGET (ptr)); |
| |
| selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (list)); |
| gtk_tree_selection_set_select_function (selection, item_highlighted_cb, |
| *gref, NULL); |
| |
| cp_gtk_component_connect_signals (G_OBJECT (list), gref); |
| |
| gdk_threads_leave (); |
| } |
| |
| JNIEXPORT void JNICALL |
| Java_gnu_java_awt_peer_gtk_GtkListPeer_gtkWidgetModifyFont |
| (JNIEnv *env, jobject obj, jstring name, jint style, jint size) |
| { |
| const char *font_name; |
| void *ptr; |
| GtkWidget *list; |
| PangoFontDescription *font_desc; |
| |
| gdk_threads_enter(); |
| |
| ptr = NSA_GET_PTR (env, obj); |
| |
| list = list_get_widget (GTK_WIDGET (ptr)); |
| |
| font_name = (*env)->GetStringUTFChars (env, name, NULL); |
| |
| font_desc = pango_font_description_from_string (font_name); |
| pango_font_description_set_size (font_desc, |
| size * cp_gtk_dpi_conversion_factor); |
| |
| if (style & AWT_STYLE_BOLD) |
| pango_font_description_set_weight (font_desc, PANGO_WEIGHT_BOLD); |
| |
| if (style & AWT_STYLE_ITALIC) |
| pango_font_description_set_style (font_desc, PANGO_STYLE_OBLIQUE); |
| |
| gtk_widget_modify_font (GTK_WIDGET (list), font_desc); |
| |
| pango_font_description_free (font_desc); |
| |
| (*env)->ReleaseStringUTFChars (env, name, font_name); |
| |
| gdk_threads_leave(); |
| } |
| |
| JNIEXPORT void JNICALL |
| Java_gnu_java_awt_peer_gtk_GtkListPeer_gtkWidgetRequestFocus |
| (JNIEnv *env, jobject obj) |
| { |
| void *ptr; |
| GtkWidget *list; |
| |
| gdk_threads_enter (); |
| |
| ptr = NSA_GET_PTR (env, obj); |
| |
| list = list_get_widget (GTK_WIDGET (ptr)); |
| gtk_widget_grab_focus (list); |
| |
| gdk_threads_leave (); |
| } |
| |
| JNIEXPORT void JNICALL |
| Java_gnu_java_awt_peer_gtk_GtkListPeer_append |
| (JNIEnv *env, jobject obj, jobjectArray items) |
| { |
| void *ptr; |
| GtkWidget *list; |
| GtkTreeIter iter; |
| GtkTreeModel *list_store; |
| jint count; |
| jint i; |
| |
| gdk_threads_enter (); |
| |
| ptr = NSA_GET_PTR (env, obj); |
| |
| count = (*env)->GetArrayLength (env, items); |
| |
| list = list_get_widget (GTK_WIDGET (ptr)); |
| list_store = gtk_tree_view_get_model (GTK_TREE_VIEW (list)); |
| |
| for (i = 0; i < count; i++) |
| { |
| const char *text; |
| jobject item; |
| |
| item = (*env)->GetObjectArrayElement (env, items, i); |
| |
| text = (*env)->GetStringUTFChars (env, item, NULL); |
| gtk_list_store_append (GTK_LIST_STORE (list_store), &iter); |
| gtk_list_store_set (GTK_LIST_STORE (list_store), &iter, |
| COLUMN_STRING, text, |
| -1); |
| (*env)->ReleaseStringUTFChars (env, item, text); |
| (*env)->DeleteLocalRef(env, item); |
| } |
| |
| gdk_threads_leave (); |
| } |
| |
| JNIEXPORT void JNICALL |
| Java_gnu_java_awt_peer_gtk_GtkListPeer_add |
| (JNIEnv *env, jobject obj, jstring text, jint index) |
| { |
| void *ptr; |
| const char *str; |
| GtkWidget *list; |
| GtkTreeIter iter; |
| GtkTreeModel *list_store; |
| |
| gdk_threads_enter (); |
| |
| ptr = NSA_GET_PTR (env, obj); |
| str = (*env)->GetStringUTFChars (env, text, NULL); |
| |
| list = list_get_widget (GTK_WIDGET (ptr)); |
| list_store = gtk_tree_view_get_model (GTK_TREE_VIEW (list)); |
| |
| if (index == -1) |
| gtk_list_store_append (GTK_LIST_STORE (list_store), &iter); |
| else |
| gtk_list_store_insert (GTK_LIST_STORE (list_store), &iter, index); |
| |
| gtk_list_store_set (GTK_LIST_STORE (list_store), &iter, |
| COLUMN_STRING, str, -1); |
| |
| (*env)->ReleaseStringUTFChars (env, text, str); |
| |
| gdk_threads_leave (); |
| } |
| |
| |
| JNIEXPORT void JNICALL |
| Java_gnu_java_awt_peer_gtk_GtkListPeer_delItems |
| (JNIEnv *env, jobject obj, jint start, jint end) |
| { |
| void *ptr; |
| GtkWidget *list; |
| GtkTreeIter iter; |
| GtkTreeModel *list_store; |
| jint i; |
| jint num_items; |
| |
| gdk_threads_enter (); |
| |
| ptr = NSA_GET_PTR (env, obj); |
| |
| list = list_get_widget (GTK_WIDGET (ptr)); |
| list_store = gtk_tree_view_get_model (GTK_TREE_VIEW (list)); |
| |
| /* Special case: remove all rows. */ |
| if (end == -1) |
| gtk_list_store_clear (GTK_LIST_STORE (list_store)); |
| else |
| { |
| i = 0; |
| num_items = end - start + 1; |
| gtk_tree_model_iter_nth_child (list_store, &iter, NULL, start); |
| while (i < num_items) |
| { |
| gtk_list_store_remove (GTK_LIST_STORE (list_store), &iter); |
| i++; |
| } |
| } |
| |
| gdk_threads_leave (); |
| } |
| |
| JNIEXPORT void JNICALL |
| Java_gnu_java_awt_peer_gtk_GtkListPeer_select |
| (JNIEnv *env, jobject obj, jint index) |
| { |
| void *ptr; |
| GtkWidget *list; |
| GtkTreePath *path; |
| |
| gdk_threads_enter (); |
| |
| ptr = NSA_GET_PTR (env, obj); |
| |
| list = list_get_widget (GTK_WIDGET (ptr)); |
| path = gtk_tree_path_new_from_indices (index, -1); |
| gtk_tree_view_set_cursor (GTK_TREE_VIEW (list), path, NULL, FALSE); |
| |
| gdk_threads_leave (); |
| } |
| |
| JNIEXPORT void JNICALL |
| Java_gnu_java_awt_peer_gtk_GtkListPeer_deselect |
| (JNIEnv *env, jobject obj, jint index) |
| { |
| void *ptr; |
| GtkWidget *list; |
| GtkTreeSelection *selection; |
| GtkTreePath *path; |
| |
| gdk_threads_enter (); |
| |
| ptr = NSA_GET_PTR (env, obj); |
| |
| list = list_get_widget (GTK_WIDGET (ptr)); |
| selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (list)); |
| path = gtk_tree_path_new_from_indices (index, -1); |
| gtk_tree_selection_unselect_path (selection, path); |
| |
| gdk_threads_leave (); |
| } |
| |
| JNIEXPORT void JNICALL |
| Java_gnu_java_awt_peer_gtk_GtkListPeer_getSize |
| (JNIEnv *env, jobject obj, jint rows, jint visible_rows, jintArray jdims) |
| { |
| void *ptr; |
| jint *dims; |
| GtkRequisition current_req; |
| GtkRequisition natural_req; |
| GtkWidget* bin; |
| |
| gdk_threads_enter (); |
| |
| dims = (*env)->GetIntArrayElements (env, jdims, NULL); |
| dims[0] = dims[1] = 0; |
| |
| ptr = NSA_GET_PTR (env, obj); |
| bin = list_get_widget (GTK_WIDGET (ptr)); |
| |
| /* Save the widget's current size request. */ |
| gtk_widget_size_request (bin, ¤t_req); |
| |
| /* Get the widget's "natural" size request. */ |
| gtk_widget_set_size_request (GTK_WIDGET (ptr), -1, -1); |
| gtk_widget_size_request (bin, &natural_req); |
| |
| /* Reset the widget's size request. */ |
| gtk_widget_set_size_request (bin, |
| current_req.width, current_req.height); |
| |
| dims[0] = natural_req.width; |
| |
| /* Calculate the final height, by comparing the number of rows |
| in the list to the number of rows requested by the caller. |
| FIXME: Is there a GTK method that counts the number of rows |
| in the list? If so, we don't need to bring visible_rows from |
| the Java peer. */ |
| if (rows == visible_rows) |
| dims[1] = natural_req.height; |
| else |
| dims[1] = natural_req.height / visible_rows * rows; |
| |
| (*env)->ReleaseIntArrayElements (env, jdims, dims, 0); |
| |
| gdk_threads_leave (); |
| } |
| |
| |
| JNIEXPORT jintArray JNICALL |
| Java_gnu_java_awt_peer_gtk_GtkListPeer_getSelectedIndexes |
| (JNIEnv *env, jobject obj) |
| { |
| void *ptr; |
| GtkWidget *list; |
| GtkTreeSelection *selection; |
| jintArray result_array; |
| jint *result_array_iter; |
| GList *current_row; |
| GList *rows; |
| gint *indices; |
| jint count; |
| jint i; |
| |
| gdk_threads_enter (); |
| |
| ptr = NSA_GET_PTR (env, obj); |
| |
| list = list_get_widget (GTK_WIDGET (ptr)); |
| selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (list)); |
| count = gtk_tree_selection_count_selected_rows (selection); |
| if (count > 0) |
| { |
| current_row = rows = gtk_tree_selection_get_selected_rows (selection, NULL); |
| |
| result_array = (*env)->NewIntArray (env, count); |
| |
| result_array_iter = (*env)->GetIntArrayElements (env, result_array, NULL); |
| |
| for (i = 0; i < count; i++) |
| { |
| indices = gtk_tree_path_get_indices (current_row->data); |
| result_array_iter[i] = indices ? indices[0] : -1; |
| current_row = g_list_next (current_row); |
| } |
| |
| if (rows) |
| { |
| g_list_foreach (rows, (GFunc) gtk_tree_path_free, NULL); |
| g_list_free (rows); |
| } |
| |
| (*env)->ReleaseIntArrayElements (env, result_array, result_array_iter, 0); |
| } |
| else |
| result_array = NULL; |
| |
| gdk_threads_leave (); |
| |
| return result_array; |
| } |
| |
| JNIEXPORT void JNICALL |
| Java_gnu_java_awt_peer_gtk_GtkListPeer_makeVisible |
| (JNIEnv *env, jobject obj, jint index) |
| { |
| void *ptr; |
| GtkWidget *list; |
| GtkTreePath *path; |
| |
| gdk_threads_enter (); |
| |
| ptr = NSA_GET_PTR (env, obj); |
| |
| list = list_get_widget (GTK_WIDGET (ptr)); |
| path = gtk_tree_path_new_from_indices (index, -1); |
| gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (list), path, |
| NULL, FALSE, 0.0, 0.0); |
| |
| gdk_threads_leave (); |
| } |
| |
| JNIEXPORT void JNICALL |
| Java_gnu_java_awt_peer_gtk_GtkListPeer_setMultipleMode |
| (JNIEnv *env, jobject obj, jboolean mode) |
| { |
| void *ptr; |
| GtkWidget *list; |
| GtkTreeSelection *selection; |
| |
| gdk_threads_enter (); |
| |
| ptr = NSA_GET_PTR (env, obj); |
| |
| list = list_get_widget (GTK_WIDGET (ptr)); |
| selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (list)); |
| gtk_tree_selection_set_mode (selection, |
| mode ? GTK_SELECTION_MULTIPLE |
| : GTK_SELECTION_SINGLE); |
| |
| gdk_threads_leave (); |
| } |
| |
| static gboolean |
| item_highlighted_cb (GtkTreeSelection *selection __attribute__((unused)), |
| GtkTreeModel *model, |
| GtkTreePath *path, |
| gboolean path_currently_selected, |
| jobject peer) |
| { |
| GtkTreeIter iter; |
| jint row; |
| gint *indices; |
| |
| if (gtk_tree_model_get_iter (model, &iter, path)) |
| { |
| indices = gtk_tree_path_get_indices (path); |
| row = indices ? indices[0] : -1; |
| |
| if (!path_currently_selected) |
| { |
| (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer, |
| postListItemEventID, |
| row, |
| (jint) AWT_ITEM_SELECTED); |
| } |
| else |
| { |
| (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer, |
| postListItemEventID, |
| row, |
| (jint) AWT_ITEM_DESELECTED); |
| } |
| } |
| |
| return TRUE; |
| } |
| |
| static GtkWidget * |
| list_get_widget (GtkWidget *widget) |
| { |
| GtkWidget *wid; |
| g_assert (GTK_IS_EVENT_BOX (widget)); |
| |
| wid = gtk_bin_get_child (GTK_BIN (widget)); |
| g_assert (GTK_IS_SCROLLED_WINDOW (wid)); |
| |
| wid = gtk_bin_get_child (GTK_BIN (wid)); |
| |
| return wid; |
| } |
| |