Mercurial > pidgin
diff console/libgnt/gntwidget.c @ 14793:8a0cfee11af8
[gaim-migrate @ 17558]
Introduce actions. You can specify the bindings for the actions. Right now, only the tree and the entry widget have them. The manual includes the details. I believe Ethan had suggested something like this a while back. It made sense, so here it is.
committer: Tailor Script <tailor@pidgin.im>
| author | Sadrul Habib Chowdhury <imadil@gmail.com> |
|---|---|
| date | Sat, 21 Oct 2006 21:08:24 +0000 |
| parents | 62bb53609a36 |
| children | 945936eaa74e |
line wrap: on
line diff
--- a/console/libgnt/gntwidget.c Sat Oct 21 20:40:12 2006 +0000 +++ b/console/libgnt/gntwidget.c Sat Oct 21 21:08:24 2006 +0000 @@ -234,6 +234,13 @@ gnt_closure_marshal_BOOLEAN__INT_INT_INT, G_TYPE_BOOLEAN, 3, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT); + klass->actions = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, + (GDestroyNotify)gnt_widget_action_free); + klass->bindings = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, + (GDestroyNotify)gnt_widget_action_param_free); + + gnt_style_read_actions(G_OBJECT_CLASS_TYPE(klass), klass); + GNTDEBUG; } @@ -384,12 +391,56 @@ } gboolean +gnt_widget_perform_action_named(GntWidget *widget, const char *name, ...) +{ + GType type = G_OBJECT_TYPE(widget); + GntWidgetClass *klass = GNT_WIDGET_CLASS(G_OBJECT_GET_CLASS(widget)); + GList *list = NULL; + va_list args; + GntWidgetAction *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) { + if (list) + return action->u.action(widget, list); + else + return action->u.action_noparam(widget); + } + return FALSE; +} + +static gboolean +gnt_widget_perform_action(GntWidget *widget, const char *keys) +{ + GType type = G_OBJECT_TYPE(widget); + GntWidgetClass *klass = GNT_WIDGET_CLASS(G_OBJECT_GET_CLASS(widget)); + GntWidgetActionParam *param = g_hash_table_lookup(klass->bindings, keys); + + if (param && param->action) { + if (param->list) + return param->action->u.action(widget, param->list); + else + return param->action->u.action_noparam(widget); + } + return FALSE; +} + +gboolean gnt_widget_key_pressed(GntWidget *widget, const char *keys) { gboolean ret; if (!GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_CAN_TAKE_FOCUS)) return FALSE; + if (gnt_widget_perform_action(widget, keys)) + return TRUE; + keys = gnt_widget_remap_keys(widget, keys); g_signal_emit(widget, signals[SIG_KEY_PRESSED], 0, keys, &ret); return ret; @@ -632,3 +683,71 @@ gnt_style_get_bool(GNT_STYLE_SHADOW, FALSE)); } +static void +register_binding(GntWidgetClass *klass, const char *name, const char *trigger, GList *list) +{ + GntWidgetActionParam *param; + + if (name == NULL || *name == '\0') { + g_hash_table_remove(klass->bindings, (char*)trigger); + return; + } + + param = g_new0(GntWidgetActionParam, 1); + param->action = g_hash_table_lookup(klass->actions, name); + param->list = list; + g_hash_table_replace(klass->bindings, g_strdup(trigger), param); +} + +void gnt_widget_register_binding(GntWidgetClass *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_widget_class_register_action(GntWidgetClass *klass, const char *name, + GntWidgetActionCallback callback, + const char *trigger, ...) +{ + void *data; + va_list args; + GntWidgetAction *action = g_new0(GntWidgetAction, 1); + GList *list; + + action->name = g_strdup(name); + action->u.action = callback; + + g_hash_table_replace(klass->actions, g_strdup(name), action); + + 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_widget_action_free(GntWidgetAction *action) +{ + g_free(action->name); + g_free(action); +} + +void gnt_widget_action_param_free(GntWidgetActionParam *param) +{ + g_list_free(param->list); /* XXX: There may be a leak here for string parameters */ + g_free(param); +} +
