diff finch/libgnt/gntbindable.c @ 15817:0e3a8505ebbe

renamed gaim-text to finch
author Sean Egan <seanegan@gmail.com>
date Sun, 18 Mar 2007 19:38:15 +0000
parents
children 8410511f4dbb
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/libgnt/gntbindable.c	Sun Mar 18 19:38:15 2007 +0000
@@ -0,0 +1,232 @@
+#include "gntbindable.h"
+#include "gntstyle.h"
+#include "gnt.h"
+#include "gntutils.h"
+
+static GObjectClass *parent_class = NULL;
+
+static void
+gnt_bindable_class_init(GntBindableClass *klass)
+{
+	parent_class = g_type_class_peek_parent(klass);
+
+	klass->actions = g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
+				(GDestroyNotify)gnt_bindable_action_free);
+	klass->bindings = g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
+				(GDestroyNotify)gnt_bindable_action_param_free);
+
+	gnt_style_read_actions(G_OBJECT_CLASS_TYPE(klass), GNT_BINDABLE_CLASS(klass));
+	GNTDEBUG;
+}
+
+static gpointer
+bindable_clone(GntBindableAction *action)
+{
+	GntBindableAction *ret = g_new0(GntBindableAction, 1);
+	ret->name = g_strdup(action->name);
+	ret->u = action->u;
+	return ret;
+}
+
+static gpointer
+binding_clone(GntBindableActionParam *param)
+{
+	GntBindableActionParam *p = g_new0(GntBindableActionParam, 1);
+	p->list = g_list_copy(param->list);
+	p->action = param->action;
+	return p;
+}
+
+static void
+duplicate_hashes(GntBindableClass *klass)
+{
+	/* Duplicate the bindings from parent class */
+	if (klass->actions) {
+		klass->actions = g_hash_table_duplicate(klass->actions, g_str_hash,
+					g_str_equal, g_free, (GDestroyNotify)gnt_bindable_action_free,
+					(GDupFunc)g_strdup, (GDupFunc)bindable_clone);
+		klass->bindings = g_hash_table_duplicate(klass->bindings, g_str_hash,
+					g_str_equal, g_free, (GDestroyNotify)gnt_bindable_action_param_free,
+					(GDupFunc)g_strdup, (GDupFunc)binding_clone);
+	} else {
+		klass->actions = g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
+					(GDestroyNotify)gnt_bindable_action_free);
+		klass->bindings = g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
+					(GDestroyNotify)gnt_bindable_action_param_free);
+	}
+
+	GNTDEBUG;
+}
+
+/******************************************************************************
+ * GntBindable API
+ *****************************************************************************/
+GType
+gnt_bindable_get_gtype(void)
+{
+	static GType type = 0;
+
+	if(type == 0) {
+		static const GTypeInfo info = {
+			sizeof(GntBindableClass),
+			(GBaseInitFunc)duplicate_hashes,	/* base_init		*/
+			NULL,					/* base_finalize	*/
+			(GClassInitFunc)gnt_bindable_class_init,
+			NULL,
+			NULL,					/* class_data		*/
+			sizeof(GntBindable),
+			0,						/* n_preallocs		*/
+			NULL,					/* instance_init	*/
+			NULL					/* value_table		*/
+		};
+
+		type = g_type_register_static(G_TYPE_OBJECT,
+									  "GntBindable",
+									  &info, G_TYPE_FLAG_ABSTRACT);
+	}
+
+	return type;
+}
+
+/**
+ * Key Remaps
+ */
+const char *
+gnt_bindable_remap_keys(GntBindable *bindable, const char *text)
+{
+	const char *remap = NULL;
+	GType type = G_OBJECT_TYPE(bindable);
+	GntBindableClass *klass = GNT_BINDABLE_CLASS(GNT_BINDABLE_GET_CLASS(bindable));
+
+	if (klass->remaps == NULL)
+	{
+		klass->remaps = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
+		gnt_styles_get_keyremaps(type, klass->remaps);
+	}
+
+	remap = g_hash_table_lookup(klass->remaps, text);
+
+	return (remap ? remap : text);
+}
+
+/**
+ * Actions and Bindings
+ */
+gboolean
+gnt_bindable_perform_action_named(GntBindable *bindable, const char *name, ...)
+{
+	GntBindableClass *klass = GNT_BINDABLE_CLASS(GNT_BINDABLE_GET_CLASS(bindable));
+	GList *list = NULL;
+	va_list args;
+	GntBindableAction *action;
+	void *p;
+
+	va_start(args, name);
+	while ((p = va_arg(args, void *)) != NULL)
+		list = g_list_append(list, p);
+	va_end(args);
+	
+	action = g_hash_table_lookup(klass->actions, name);
+	if (action && action->u.action) {
+		return action->u.action(bindable, list);
+	}
+	return FALSE;
+}
+
+gboolean
+gnt_bindable_perform_action_key(GntBindable *bindable, const char *keys)
+{
+	GntBindableClass *klass = GNT_BINDABLE_CLASS(GNT_BINDABLE_GET_CLASS(bindable));
+	GntBindableActionParam *param = g_hash_table_lookup(klass->bindings, keys);
+
+	if (param && param->action) {
+		if (param->list)
+			return param->action->u.action(bindable, param->list);
+		else
+			return param->action->u.action_noparam(bindable);
+	}
+	return FALSE;
+}
+
+static void
+register_binding(GntBindableClass *klass, const char *name, const char *trigger, GList *list)
+{
+	GntBindableActionParam *param;
+	GntBindableAction *action;
+
+	if (name == NULL || *name == '\0') {
+		g_hash_table_remove(klass->bindings, (char*)trigger);
+		gnt_keys_del_combination(trigger);
+		return;
+	}
+
+	action = g_hash_table_lookup(klass->actions, name);
+	if (!action) {
+		g_printerr("GntWidget: Invalid action name %s for %s\n",
+				name, g_type_name(G_OBJECT_CLASS_TYPE(klass)));
+		if (list)
+			g_list_free(list);
+		return;
+	}
+
+	param = g_new0(GntBindableActionParam, 1);
+	param->action = action;
+	param->list = list;
+	g_hash_table_replace(klass->bindings, g_strdup(trigger), param);
+	gnt_keys_add_combination(trigger);
+}
+
+void gnt_bindable_register_binding(GntBindableClass *klass, const char *name,
+			const char *trigger, ...)
+{
+	GList *list = NULL;
+	va_list args;
+	void *data;
+
+	va_start(args, trigger);
+	while ((data = va_arg(args, void *))) {
+		list = g_list_append(list, data);
+	}
+	va_end(args);
+
+	register_binding(klass, name, trigger, list);
+}
+
+void gnt_bindable_class_register_action(GntBindableClass *klass, const char *name,
+			GntBindableActionCallback callback, const char *trigger, ...)
+{
+	void *data;
+	va_list args;
+	GntBindableAction *action = g_new0(GntBindableAction, 1);
+	GList *list;
+
+	action->name = g_strdup(name);
+	action->u.action = callback;
+
+	g_hash_table_replace(klass->actions, g_strdup(name), action);
+
+	if (trigger && *trigger) {
+		list = NULL;
+		va_start(args, trigger);
+		while ((data = va_arg(args, void *))) {
+			list = g_list_append(list, data);
+		}
+		va_end(args);
+
+		register_binding(klass, name, trigger, list);
+	}
+}
+
+void gnt_bindable_action_free(GntBindableAction *action)
+{
+	g_free(action->name);
+	g_free(action);
+}
+
+void gnt_bindable_action_param_free(GntBindableActionParam *param)
+{
+	g_list_free(param->list);   /* XXX: There may be a leak here for string parameters */
+	g_free(param);
+}
+
+