comparison 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
comparison
equal deleted inserted replaced
15816:317e7613e581 15817:0e3a8505ebbe
1 #include "gntbindable.h"
2 #include "gntstyle.h"
3 #include "gnt.h"
4 #include "gntutils.h"
5
6 static GObjectClass *parent_class = NULL;
7
8 static void
9 gnt_bindable_class_init(GntBindableClass *klass)
10 {
11 parent_class = g_type_class_peek_parent(klass);
12
13 klass->actions = g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
14 (GDestroyNotify)gnt_bindable_action_free);
15 klass->bindings = g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
16 (GDestroyNotify)gnt_bindable_action_param_free);
17
18 gnt_style_read_actions(G_OBJECT_CLASS_TYPE(klass), GNT_BINDABLE_CLASS(klass));
19 GNTDEBUG;
20 }
21
22 static gpointer
23 bindable_clone(GntBindableAction *action)
24 {
25 GntBindableAction *ret = g_new0(GntBindableAction, 1);
26 ret->name = g_strdup(action->name);
27 ret->u = action->u;
28 return ret;
29 }
30
31 static gpointer
32 binding_clone(GntBindableActionParam *param)
33 {
34 GntBindableActionParam *p = g_new0(GntBindableActionParam, 1);
35 p->list = g_list_copy(param->list);
36 p->action = param->action;
37 return p;
38 }
39
40 static void
41 duplicate_hashes(GntBindableClass *klass)
42 {
43 /* Duplicate the bindings from parent class */
44 if (klass->actions) {
45 klass->actions = g_hash_table_duplicate(klass->actions, g_str_hash,
46 g_str_equal, g_free, (GDestroyNotify)gnt_bindable_action_free,
47 (GDupFunc)g_strdup, (GDupFunc)bindable_clone);
48 klass->bindings = g_hash_table_duplicate(klass->bindings, g_str_hash,
49 g_str_equal, g_free, (GDestroyNotify)gnt_bindable_action_param_free,
50 (GDupFunc)g_strdup, (GDupFunc)binding_clone);
51 } else {
52 klass->actions = g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
53 (GDestroyNotify)gnt_bindable_action_free);
54 klass->bindings = g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
55 (GDestroyNotify)gnt_bindable_action_param_free);
56 }
57
58 GNTDEBUG;
59 }
60
61 /******************************************************************************
62 * GntBindable API
63 *****************************************************************************/
64 GType
65 gnt_bindable_get_gtype(void)
66 {
67 static GType type = 0;
68
69 if(type == 0) {
70 static const GTypeInfo info = {
71 sizeof(GntBindableClass),
72 (GBaseInitFunc)duplicate_hashes, /* base_init */
73 NULL, /* base_finalize */
74 (GClassInitFunc)gnt_bindable_class_init,
75 NULL,
76 NULL, /* class_data */
77 sizeof(GntBindable),
78 0, /* n_preallocs */
79 NULL, /* instance_init */
80 NULL /* value_table */
81 };
82
83 type = g_type_register_static(G_TYPE_OBJECT,
84 "GntBindable",
85 &info, G_TYPE_FLAG_ABSTRACT);
86 }
87
88 return type;
89 }
90
91 /**
92 * Key Remaps
93 */
94 const char *
95 gnt_bindable_remap_keys(GntBindable *bindable, const char *text)
96 {
97 const char *remap = NULL;
98 GType type = G_OBJECT_TYPE(bindable);
99 GntBindableClass *klass = GNT_BINDABLE_CLASS(GNT_BINDABLE_GET_CLASS(bindable));
100
101 if (klass->remaps == NULL)
102 {
103 klass->remaps = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
104 gnt_styles_get_keyremaps(type, klass->remaps);
105 }
106
107 remap = g_hash_table_lookup(klass->remaps, text);
108
109 return (remap ? remap : text);
110 }
111
112 /**
113 * Actions and Bindings
114 */
115 gboolean
116 gnt_bindable_perform_action_named(GntBindable *bindable, const char *name, ...)
117 {
118 GntBindableClass *klass = GNT_BINDABLE_CLASS(GNT_BINDABLE_GET_CLASS(bindable));
119 GList *list = NULL;
120 va_list args;
121 GntBindableAction *action;
122 void *p;
123
124 va_start(args, name);
125 while ((p = va_arg(args, void *)) != NULL)
126 list = g_list_append(list, p);
127 va_end(args);
128
129 action = g_hash_table_lookup(klass->actions, name);
130 if (action && action->u.action) {
131 return action->u.action(bindable, list);
132 }
133 return FALSE;
134 }
135
136 gboolean
137 gnt_bindable_perform_action_key(GntBindable *bindable, const char *keys)
138 {
139 GntBindableClass *klass = GNT_BINDABLE_CLASS(GNT_BINDABLE_GET_CLASS(bindable));
140 GntBindableActionParam *param = g_hash_table_lookup(klass->bindings, keys);
141
142 if (param && param->action) {
143 if (param->list)
144 return param->action->u.action(bindable, param->list);
145 else
146 return param->action->u.action_noparam(bindable);
147 }
148 return FALSE;
149 }
150
151 static void
152 register_binding(GntBindableClass *klass, const char *name, const char *trigger, GList *list)
153 {
154 GntBindableActionParam *param;
155 GntBindableAction *action;
156
157 if (name == NULL || *name == '\0') {
158 g_hash_table_remove(klass->bindings, (char*)trigger);
159 gnt_keys_del_combination(trigger);
160 return;
161 }
162
163 action = g_hash_table_lookup(klass->actions, name);
164 if (!action) {
165 g_printerr("GntWidget: Invalid action name %s for %s\n",
166 name, g_type_name(G_OBJECT_CLASS_TYPE(klass)));
167 if (list)
168 g_list_free(list);
169 return;
170 }
171
172 param = g_new0(GntBindableActionParam, 1);
173 param->action = action;
174 param->list = list;
175 g_hash_table_replace(klass->bindings, g_strdup(trigger), param);
176 gnt_keys_add_combination(trigger);
177 }
178
179 void gnt_bindable_register_binding(GntBindableClass *klass, const char *name,
180 const char *trigger, ...)
181 {
182 GList *list = NULL;
183 va_list args;
184 void *data;
185
186 va_start(args, trigger);
187 while ((data = va_arg(args, void *))) {
188 list = g_list_append(list, data);
189 }
190 va_end(args);
191
192 register_binding(klass, name, trigger, list);
193 }
194
195 void gnt_bindable_class_register_action(GntBindableClass *klass, const char *name,
196 GntBindableActionCallback callback, const char *trigger, ...)
197 {
198 void *data;
199 va_list args;
200 GntBindableAction *action = g_new0(GntBindableAction, 1);
201 GList *list;
202
203 action->name = g_strdup(name);
204 action->u.action = callback;
205
206 g_hash_table_replace(klass->actions, g_strdup(name), action);
207
208 if (trigger && *trigger) {
209 list = NULL;
210 va_start(args, trigger);
211 while ((data = va_arg(args, void *))) {
212 list = g_list_append(list, data);
213 }
214 va_end(args);
215
216 register_binding(klass, name, trigger, list);
217 }
218 }
219
220 void gnt_bindable_action_free(GntBindableAction *action)
221 {
222 g_free(action->name);
223 g_free(action);
224 }
225
226 void gnt_bindable_action_param_free(GntBindableActionParam *param)
227 {
228 g_list_free(param->list); /* XXX: There may be a leak here for string parameters */
229 g_free(param);
230 }
231
232