console/libgnt/gntbindable.c

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

mercurial