Mercurial > pidgin
diff finch/libgnt/gntbindable.c @ 19174:974f9298814c
propagate from branch 'im.pidgin.pidgin.2.1.0' (head 1b855097a1f8ddde513bda1e81761c8d8455f931)
to branch 'im.pidgin.soc.2007.finchfeat' (head 547aba29502f4db0b429e29c831c88b06270862e)
author | Sadrul Habib Chowdhury <imadil@gmail.com> |
---|---|
date | Sat, 11 Aug 2007 02:38:56 +0000 |
parents | d5a0b09470ee |
children | 33201366bcd4 |
line wrap: on
line diff
--- a/finch/libgnt/gntbindable.c Sat Aug 11 02:38:23 2007 +0000 +++ b/finch/libgnt/gntbindable.c Sat Aug 11 02:38:56 2007 +0000 @@ -20,13 +20,198 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include <string.h> + #include "gntbindable.h" #include "gntstyle.h" #include "gnt.h" #include "gntutils.h" +#include "gnttextview.h" +#include "gnttree.h" +#include "gntbox.h" +#include "gntbutton.h" +#include "gntwindow.h" +#include "gntlabel.h" static GObjectClass *parent_class = NULL; +static struct +{ + char * okeys; /* Old keystrokes */ + char * keys; /* New Keystrokes being bound to the action */ + GntBindableClass * klass; /* Class of the object that's getting keys rebound */ + char * name; /* The name of the action */ + GList * params; /* The list of paramaters */ + +} rebind_info = {NULL,NULL,NULL,NULL,NULL}; + +static void +gnt_bindable_free_rebind_info() +{ + g_free(rebind_info.name); + g_free(rebind_info.keys); + g_free(rebind_info.okeys); +} + +static void +gnt_bindable_rebinding_cancel(GntWidget *button, gpointer data) +{ + gnt_bindable_free_rebind_info(); + gnt_widget_destroy(GNT_WIDGET(data)); +} + +static void +gnt_bindable_rebinding_rebind(GntWidget *button, gpointer data) +{ + + if(rebind_info.keys) { + gnt_bindable_register_binding(rebind_info.klass, + NULL, + rebind_info.okeys, + rebind_info.params); + gnt_bindable_register_binding(rebind_info.klass, + rebind_info.name, + rebind_info.keys, + rebind_info.params); + } + gnt_bindable_free_rebind_info(); + + gnt_widget_destroy(GNT_WIDGET(data)); +} + +static gboolean +gnt_bindable_rebinding_grab_key(GntBindable *bindable, const char *text, gpointer *data) +{ + + GntTextView *textview= GNT_TEXT_VIEW(data); + char *new_text; + const char *tmp; + + if(text && *text){ + + if(!strcmp(text, GNT_KEY_CTRL_I) || !strcmp(text, GNT_KEY_ENTER)){ + return FALSE; + } + + tmp = gnt_key_lookup(text); + new_text = g_strdup_printf("KEY: \"%s\"",tmp); + gnt_text_view_clear(textview); + gnt_text_view_append_text_with_flags(textview,new_text,GNT_TEXT_FLAG_NORMAL); + g_free(new_text); + + g_free(rebind_info.keys); + rebind_info.keys = g_strdup(text); + + + return TRUE; + } + return FALSE; +} +static void +gnt_bindable_rebinding_activate(GntBindable *data, gpointer bindable) +{ + + GntTree * tree = GNT_TREE(data); + + GntWidget *vbox = gnt_box_new(FALSE,TRUE); + + GntWidget *label; + const char * widget_name = g_type_name(G_OBJECT_TYPE(bindable)); + char * keys; + + GntWidget *key_textview; + + GntWidget *bind_button, *cancel_button; + GntWidget *button_box; + + GntWidget *win = gnt_window_new(); + GList * current_row_data,*itr; + char * tmp; + + rebind_info.klass = GNT_BINDABLE_GET_CLASS(bindable); + + current_row_data = gnt_tree_get_selection_text_list(tree); + rebind_info.name = g_strdup(g_list_nth_data(current_row_data,1)); + + keys = gnt_tree_get_selection_data(tree); + rebind_info.okeys = g_strdup(gnt_key_translate(keys)); + + rebind_info.params = NULL; + + itr = current_row_data; + while(itr){ + g_free(itr->data); + itr = itr->next; + } + g_list_free(current_row_data); + + gnt_box_set_alignment(GNT_BOX(vbox), GNT_ALIGN_MID); + + gnt_box_set_title(GNT_BOX(win),"Key Capture"); + + tmp = g_strdup_printf("Type the new bindings for %s in a %s.",rebind_info.name,widget_name); + label = gnt_label_new(tmp); + g_free(tmp); + gnt_box_add_widget(GNT_BOX(vbox),label); + + tmp = g_strdup_printf("KEY: \"%s\"",keys); + key_textview = gnt_text_view_new(); + gnt_widget_set_size(key_textview,key_textview->priv.x,2); + gnt_text_view_append_text_with_flags(GNT_TEXT_VIEW(key_textview),tmp,GNT_TEXT_FLAG_NORMAL); + g_free(tmp); + gnt_widget_set_name(key_textview,"keystroke"); + gnt_box_add_widget(GNT_BOX(vbox),key_textview); + + g_signal_connect(G_OBJECT(win), "key_pressed", G_CALLBACK(gnt_bindable_rebinding_grab_key),key_textview); + + button_box = gnt_box_new(FALSE,FALSE); + + bind_button = gnt_button_new("BIND"); + gnt_widget_set_name(bind_button,"bind"); + gnt_box_add_widget(GNT_BOX(button_box), bind_button); + + cancel_button = gnt_button_new("Cancel"); + gnt_widget_set_name(cancel_button,"cancel"); + gnt_box_add_widget(GNT_BOX(button_box),cancel_button); + + g_signal_connect(G_OBJECT(bind_button), "activate", G_CALLBACK(gnt_bindable_rebinding_rebind),win); + g_signal_connect(G_OBJECT(cancel_button), "activate", G_CALLBACK(gnt_bindable_rebinding_cancel),win); + + + gnt_box_add_widget(GNT_BOX(vbox),button_box); + + gnt_box_add_widget(GNT_BOX(win),vbox); + gnt_widget_show(win); + +} + +typedef struct { + GHashTable *hash; + GntTree *tree; +} BindingView; + +static void +add_binding(gpointer key, gpointer value, gpointer data) +{ + BindingView *bv = data; + GntBindableActionParam *act = value; + const char *name = g_hash_table_lookup(bv->hash, act->action); + if (name && *name) { + const char *k = gnt_key_lookup(key); + if (!k) + k = key; + gnt_tree_add_row_after(bv->tree, (gpointer)k, + gnt_tree_create_row(bv->tree, k, name), NULL, NULL); + } +} + +static void +add_action(gpointer key, gpointer value, gpointer data) +{ + BindingView *bv = data; + g_hash_table_insert(bv->hash, value, key); +} + static void gnt_bindable_class_init(GntBindableClass *klass) { @@ -251,4 +436,56 @@ g_free(param); } +GntBindable * gnt_bindable_bindings_view(GntBindable *bind) +{ + GntBindable *tree = GNT_BINDABLE(gnt_tree_new_with_columns(2)); + GntBindableClass *klass = GNT_BINDABLE_CLASS(GNT_BINDABLE_GET_CLASS(bind)); + GHashTable *hash = g_hash_table_new(g_direct_hash, g_direct_equal); + BindingView bv = {hash, GNT_TREE(tree)}; + gnt_tree_set_compare_func(bv.tree, (GCompareFunc)g_utf8_collate); + g_hash_table_foreach(klass->actions, add_action, &bv); + g_hash_table_foreach(klass->bindings, add_binding, &bv); + if (GNT_TREE(tree)->list == NULL) { + gnt_widget_destroy(GNT_WIDGET(tree)); + tree = NULL; + } else + gnt_tree_adjust_columns(bv.tree); + g_hash_table_destroy(hash); + + return tree; +} + +static void +reset_binding_window(GntBindableClass *window, gpointer k) +{ + GntBindableClass *klass = GNT_BINDABLE_CLASS(k); + klass->help_window = NULL; +} + +gboolean +gnt_bindable_build_help_window(GntBindable *bindable) +{ + + GntWidget *tree; + GntBindableClass *klass = GNT_BINDABLE_GET_CLASS(bindable); + char *title; + + tree = GNT_WIDGET(gnt_bindable_bindings_view(bindable)); + + klass->help_window = GNT_BINDABLE(gnt_window_new()); + title = g_strdup_printf("Bindings for %s", g_type_name(G_OBJECT_TYPE(bindable))); + gnt_box_set_title(GNT_BOX(klass->help_window), title); + if (tree) { + g_signal_connect(G_OBJECT(tree), "activate", G_CALLBACK(gnt_bindable_rebinding_activate), bindable); + gnt_box_add_widget(GNT_BOX(klass->help_window), tree); + } else + gnt_box_add_widget(GNT_BOX(klass->help_window), gnt_label_new("This widget has no customizable bindings.")); + + g_signal_connect(G_OBJECT(klass->help_window), "destroy", G_CALLBACK(reset_binding_window), klass); + gnt_widget_show(GNT_WIDGET(klass->help_window)); + g_free(title); + + return TRUE; +} +