diff options
Diffstat (limited to 'widgets/misc/gal-combo-text.c')
-rw-r--r-- | widgets/misc/gal-combo-text.c | 433 |
1 files changed, 0 insertions, 433 deletions
diff --git a/widgets/misc/gal-combo-text.c b/widgets/misc/gal-combo-text.c deleted file mode 100644 index ba3b4ad7c5..0000000000 --- a/widgets/misc/gal-combo-text.c +++ /dev/null @@ -1,433 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * gtk-combo-text.c - A combo box for selecting from a list. - * Copyright 2000, 2001, Ximian, Inc. - * - * Authors: - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License, version 2, as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#include <config.h> -#include <ctype.h> -#include <gal/util/e-util.h> -#include <gtk/gtksignal.h> -#include <gtk/gtkentry.h> -#include <gtk/gtklist.h> -#include <gtk/gtkscrolledwindow.h> -#include "gal-combo-text.h" - -#define PARENT_TYPE GAL_COMBO_BOX_TYPE -static GtkObjectClass *gal_combo_text_parent_class; - -static gboolean cb_pop_down (GtkWidget *w, GtkWidget *pop_down, - gpointer dummy); - -static void list_unselect_cb (GtkWidget *list, GtkWidget *child, - gpointer data); - -static void update_list_selection (GalComboText *ct, const gchar *text); - -static void -gal_combo_text_destroy (GtkObject *object) -{ - GalComboText *ct = GAL_COMBO_TEXT (object); - - if (ct->elements != NULL) { - g_hash_table_destroy (ct->elements); - ct->elements = NULL; - } - if (ct->list != NULL) { - g_signal_handlers_disconnect_matched (ct, - G_SIGNAL_MATCH_FUNC, - 0, 0, NULL, - cb_pop_down, NULL); - - g_signal_handlers_disconnect_matched (ct->list, - G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA, - 0, 0, NULL, - list_unselect_cb, ct); - ct->list = NULL; - } - - (*gal_combo_text_parent_class->destroy) (object); -} - -static void -gal_combo_text_class_init (GtkObjectClass *object_class) -{ - object_class->destroy = &gal_combo_text_destroy; - gal_combo_text_parent_class = g_type_class_ref (PARENT_TYPE); -} - -static void -gal_combo_text_init (GalComboText *object) -{ -} - -E_MAKE_TYPE (gal_combo_text, - "GalComboText", - GalComboText, - gal_combo_text_class_init, - gal_combo_text_init, - PARENT_TYPE) - -static gint -strcase_equal (gconstpointer v, gconstpointer v2) -{ - return g_strcasecmp ((const gchar*) v, (const gchar*)v2) == 0; -} - - -/* - * a char* hash function from ASU - * - * This is cut/paste from gutils.c - * We've got to do this, because this widget will soon move out of the - * Gnumeric source and into a separate library. - */ -static guint -strcase_hash (gconstpointer v) -{ - const unsigned char *s = (const unsigned char *)v; - const unsigned char *p; - guint h = 0, g; - - for(p = s; *p != '\0'; p += 1) { - h = ( h << 4 ) + tolower (*p); - if ( ( g = h & 0xf0000000 ) ) { - h = h ^ (g >> 24); - h = h ^ g; - } - } - - return h /* % M */; -} - -/** - * gal_combo_text_set_case_sensitive - * @combo_text: ComboText widget - * @val: make case sensitive if TRUE - * - * Specifies whether the text entered into the GtkEntry field and the text - * in the list items is case sensitive. Because the values are stored in a - * hash, it is not legal to change case sensitivity when the list contains - * elements. - * - * Returns: The function returns -1 if request could not be honored. On - * success, it returns 0. - */ -gint -gal_combo_text_set_case_sensitive (GalComboText *combo, gboolean val) -{ - if (combo->elements - && g_hash_table_size (combo->elements) > 0 - && val != combo->case_sensitive) - return -1; - else { - combo->case_sensitive = val; - if (val != combo->case_sensitive) { - GHashFunc hashfunc; - GCompareFunc comparefunc; - - g_hash_table_destroy (combo->elements); - if (combo->case_sensitive) { - hashfunc = g_str_hash; - comparefunc = g_str_equal; - } else { - hashfunc = strcase_hash; - comparefunc = strcase_equal; - } - combo->elements = g_hash_table_new (hashfunc, - comparefunc); - } - return 0; - } -} - -static void -entry_activate_cb (GtkWidget *entry, gpointer data) -{ - GalComboText *combo = GAL_COMBO_TEXT (data); - - update_list_selection (combo, - gtk_entry_get_text (GTK_ENTRY (combo->entry))); -} - - -static void -list_select_cb (GtkWidget *list, GtkWidget *child, gpointer data) -{ - GalComboText *combo = GAL_COMBO_TEXT (data); - GtkEntry *entry = GTK_ENTRY (combo->entry); - gchar *value = (gchar*) g_object_get_data (G_OBJECT (child), "value"); - - g_return_if_fail (entry && value); - - if (combo->cached_entry == child) - combo->cached_entry = NULL; - - gtk_entry_set_text (entry, value); - gtk_signal_handler_block_by_func (GTK_OBJECT (entry), - GTK_SIGNAL_FUNC (entry_activate_cb), - (gpointer) combo); - g_signal_emit_by_name (entry, "activate"); - gtk_signal_handler_unblock_by_func (GTK_OBJECT (entry), - GTK_SIGNAL_FUNC (entry_activate_cb), - (gpointer) combo); - - gal_combo_box_popup_hide (GAL_COMBO_BOX (data)); -} - -static void -list_unselect_cb (GtkWidget *list, GtkWidget *child, gpointer data) -{ - if (GTK_WIDGET_VISIBLE (list)) /* Undo interactive unselect */ - gtk_list_select_child (GTK_LIST (list), child); -} - -static void -cb_toggle (GtkWidget *child, gpointer data) -{ - GalComboText *ct = GAL_COMBO_TEXT (data); - - gtk_list_select_child (GTK_LIST (ct->list), child); -} - -void -gal_combo_text_select_item (GalComboText *ct, int elem) -{ - gtk_list_select_item (GTK_LIST(ct->list), elem); -} - -static void -update_list_selection (GalComboText *ct, const gchar *text) -{ - gpointer candidate; - GtkWidget *child; - - gtk_signal_handler_block_by_func (GTK_OBJECT (ct->list), - GTK_SIGNAL_FUNC (list_select_cb), - (gpointer) ct); - gtk_signal_handler_block_by_func (GTK_OBJECT (ct->list), - GTK_SIGNAL_FUNC (list_unselect_cb), - (gpointer) ct); - - gtk_list_unselect_all (GTK_LIST (ct->list)); - candidate = g_hash_table_lookup (ct->elements, (gconstpointer) text); - if (candidate && GTK_IS_WIDGET (candidate)) { - child = GTK_WIDGET (candidate); - gtk_list_select_child (GTK_LIST (ct->list), child); - gtk_widget_grab_focus (child); - } - gtk_signal_handler_unblock_by_func (GTK_OBJECT (ct->list), - GTK_SIGNAL_FUNC (list_select_cb), - (gpointer) ct); - gtk_signal_handler_unblock_by_func (GTK_OBJECT (ct->list), - GTK_SIGNAL_FUNC (list_unselect_cb), - (gpointer) ct); -} - -void -gal_combo_text_set_text (GalComboText *ct, const gchar *text) -{ - gtk_entry_set_text (GTK_ENTRY (ct->entry), text); - update_list_selection (ct, text); -} - -/* - * We can't just cache the old widget state on entry: If the pointer is - * dragged, we receive two enter-notify-events, and the original cached - * value would be overwritten with the GTK_STATE_ACTIVE we just set. - * - * However, we know that the gtklist only uses GTK_STATE_SELECTED and - * GTK_STATE_NORMAL. We're OK if we only cache those two. - */ -static gboolean -cb_enter (GtkWidget *w, GdkEventCrossing *event, - gpointer user) -{ - GalComboText *ct = user; - GtkStateType state = GTK_WIDGET_STATE (w); - - if (state == GTK_STATE_NORMAL || state == GTK_STATE_SELECTED) { - ct->cached_entry = w; - ct->cache_mouse_state = state; - } - if (state != GTK_STATE_SELECTED) - gtk_widget_set_state (w, GTK_STATE_ACTIVE); - - return TRUE; -} -static gboolean -cb_exit (GtkWidget *w, GdkEventCrossing *event, - gpointer user) -{ - GalComboText *ct = user; - - if (ct->cached_entry == w) - gtk_widget_set_state (w, ct->cache_mouse_state); - - return TRUE; -} - -static gboolean -cb_pop_down (GtkWidget *w, GtkWidget *pop_down, gpointer dummy) -{ - GalComboText *ct = GAL_COMBO_TEXT (w); - - if (ct->cached_entry) - gtk_widget_set_state (ct->cached_entry, ct->cache_mouse_state); - ct->cached_entry = NULL; - - return FALSE; -} - -typedef struct { - GalComboText *ct; - gchar *value; -} WeakRefClosure; - -static void -cb_remove_from_hash (gpointer data, GObject *where_object_was) -{ - WeakRefClosure *closure = data; - - if (closure->ct->elements) - g_hash_table_remove (closure->ct->elements, closure->value); - - g_free (closure->value); - g_free (closure); -} - -void -gal_combo_text_add_item (GalComboText *ct, - const gchar *item, - const gchar *value) -{ - WeakRefClosure *weak_ref_closure; - GtkWidget *listitem; - gchar *value_copy; - - g_return_if_fail (item); - - if (!value) - value = item; - - value_copy = g_strdup (value); - - listitem = gtk_list_item_new_with_label (item); - gtk_widget_show (listitem); - - g_object_set_data_full (G_OBJECT (listitem), "value", - value_copy, g_free); - g_signal_connect (listitem, "enter-notify-event", - G_CALLBACK (cb_enter), - (gpointer) ct); - g_signal_connect (listitem, "leave-notify-event", - G_CALLBACK (cb_exit), - (gpointer) ct); - g_signal_connect (listitem, "toggle", - G_CALLBACK (cb_toggle), - (gpointer) ct); - - gtk_container_add (GTK_CONTAINER (ct->list), - listitem); - - g_hash_table_insert (ct->elements, (gpointer)value_copy, - (gpointer) listitem); - - weak_ref_closure = g_new (WeakRefClosure, 1); - weak_ref_closure->ct = ct; - weak_ref_closure->value = g_strdup (value_copy); - - g_object_weak_ref (G_OBJECT (listitem), - cb_remove_from_hash, - weak_ref_closure); -} - -static void -cb_list_mapped (GtkWidget *widget, gpointer user_data) -{ - GtkList *list = GTK_LIST (widget); - - if (g_list_length (list->selection) > 0) - gtk_widget_grab_focus (GTK_WIDGET ((list->selection->data))); -} - -void -gal_combo_text_construct (GalComboText *ct, gboolean const is_scrolled) -{ - GtkWidget *entry, *list, *scroll, *display_widget; - - ct->case_sensitive = FALSE; - ct->elements = g_hash_table_new (&strcase_hash, - &strcase_equal); - - /* Probably irrelevant, but lets be careful */ - ct->cache_mouse_state = GTK_STATE_NORMAL; - ct->cached_entry = NULL; - - entry = ct->entry = gtk_entry_new (); - list = ct->list = gtk_list_new (); - if (is_scrolled) { - display_widget = scroll = gtk_scrolled_window_new (NULL, NULL); - gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW(scroll), - GTK_POLICY_NEVER, - GTK_POLICY_AUTOMATIC); - - gtk_scrolled_window_add_with_viewport ( - GTK_SCROLLED_WINDOW(scroll), list); - gtk_container_set_focus_hadjustment ( - GTK_CONTAINER (list), - gtk_scrolled_window_get_hadjustment ( - GTK_SCROLLED_WINDOW (scroll))); - gtk_container_set_focus_vadjustment ( - GTK_CONTAINER (list), - gtk_scrolled_window_get_vadjustment ( - GTK_SCROLLED_WINDOW (scroll))); - gtk_widget_set_usize (scroll, 0, 200); /* MAGIC NUMBER */ - } else - display_widget = list; - - g_signal_connect (entry, "activate", - G_CALLBACK (entry_activate_cb), - ct); - g_signal_connect (list, "select-child", - G_CALLBACK (list_select_cb), - ct); - g_signal_connect (list, "unselect-child", - G_CALLBACK (list_unselect_cb), - ct); - g_signal_connect (list, "map", - G_CALLBACK (cb_list_mapped), NULL); - - gtk_widget_show (display_widget); - gtk_widget_show (entry); - gal_combo_box_construct (GAL_COMBO_BOX (ct), entry, display_widget); - g_signal_connect (ct, "pop_down_done", - G_CALLBACK (cb_pop_down), NULL); -} - -GtkWidget* -gal_combo_text_new (gboolean const is_scrolled) -{ - GalComboText *ct; - - ct = g_object_new (GAL_COMBO_TEXT_TYPE, NULL); - gal_combo_text_construct (ct, is_scrolled); - return GTK_WIDGET (ct); -} - |