1 #include "e_mod_main.h"
2
3 /* action selector plugin: provides list of actions registered for
4 candidate types provided by current plugin */
5
6 typedef struct _Plugin Plugin;
7
8 struct _Plugin
9 {
10 Evry_Plugin base;
11 Eina_List *actions;
12 Eina_Bool parent;
13 Evry_Action *action;
14 };
15
16 static Evry_Plugin *_plug = NULL;
17
18 static void
_finish(Evry_Plugin * plugin)19 _finish(Evry_Plugin *plugin)
20 {
21 GET_PLUGIN(p, plugin);
22
23 EVRY_PLUGIN_ITEMS_CLEAR(p);
24
25 eina_list_free(p->actions);
26 E_FREE(p);
27 }
28
29 static Evry_Plugin *
_browse(Evry_Plugin * plugin,const Evry_Item * it)30 _browse(Evry_Plugin *plugin, const Evry_Item *it)
31 {
32 Evry_Action *act;
33 Plugin *p;
34
35 if (!(CHECK_TYPE(it, EVRY_TYPE_ACTION)))
36 return NULL;
37
38 act = EVRY_ACTN(it);
39
40 EVRY_PLUGIN_INSTANCE(p, plugin);
41 p->actions = act->fetch(act);
42 p->parent = EINA_TRUE;
43 p->action = act;
44
45 return EVRY_PLUGIN(p);
46 }
47
48 static Evry_Plugin *
_begin(Evry_Plugin * plugin,const Evry_Item * it)49 _begin(Evry_Plugin *plugin, const Evry_Item *it)
50 {
51 Evry_Action *act;
52 Eina_List *l;
53 Plugin *p;
54
55 EVRY_PLUGIN_INSTANCE(p, plugin);
56
57 if (!(CHECK_TYPE(it, EVRY_TYPE_PLUGIN)))
58 {
59 EINA_LIST_FOREACH (evry_conf->actions, l, act)
60 {
61 if (!((!act->it1.type) ||
62 (CHECK_TYPE(it, act->it1.type)) ||
63 (CHECK_SUBTYPE(it, act->it1.type))))
64 continue;
65
66 if (act->check_item && !(act->check_item(act, it)))
67 continue;
68
69 act->base.plugin = EVRY_PLUGIN(p);
70 act->it1.item = it;
71 EVRY_ITEM(act)->hi = NULL;
72
73 p->actions = eina_list_append(p->actions, act);
74 }
75 }
76
77 if (it->plugin)
78 {
79 EINA_LIST_FOREACH (it->plugin->actions, l, act)
80 {
81 act->base.plugin = EVRY_PLUGIN(p);
82
83 act->it1.item = EVRY_ITEM(it->plugin);
84 EVRY_ITEM(act)->hi = NULL;
85 p->actions = eina_list_append(p->actions, act);
86 }
87 }
88
89 return EVRY_PLUGIN(p);
90 }
91
92 static int
_cb_sort(const void * data1,const void * data2)93 _cb_sort(const void *data1, const void *data2)
94 {
95 const Evry_Item *it1 = data1;
96 const Evry_Item *it2 = data2;
97 const Evry_Action *act1 = data1;
98 const Evry_Action *act2 = data2;
99
100 if (act1->remember_context || act2->remember_context)
101 {
102 if (act1->remember_context && !act2->remember_context)
103 return -1;
104 if (!act1->remember_context && act2->remember_context)
105 return 1;
106 }
107
108 /* sort type match before subtype match */
109 if (act1->it1.item && act2->it1.item)
110 {
111 if ((act1->it1.type == act1->it1.item->type) &&
112 (act2->it1.type != act2->it1.item->type))
113 return -1;
114
115 if ((act1->it1.type != act1->it1.item->type) &&
116 (act2->it1.type == act2->it1.item->type))
117 return 1;
118 }
119
120 if (it1->fuzzy_match || it2->fuzzy_match)
121 if (it1->fuzzy_match || it2->fuzzy_match)
122 {
123 if (it1->fuzzy_match && !it2->fuzzy_match)
124 return -1;
125
126 if (!it1->fuzzy_match && it2->fuzzy_match)
127 return 1;
128
129 if (it1->fuzzy_match - it2->fuzzy_match)
130 return it1->fuzzy_match - it2->fuzzy_match;
131 }
132
133 if (it1->priority - it2->priority)
134 return it1->priority - it2->priority;
135
136 return 0;
137 }
138
139 static int
_fetch(Evry_Plugin * plugin,const char * input)140 _fetch(Evry_Plugin *plugin, const char *input)
141 {
142 GET_PLUGIN(p, plugin);
143 Eina_List *l;
144 Evry_Item *it;
145 int match;
146
147 EVRY_PLUGIN_ITEMS_CLEAR(p);
148
149 EINA_LIST_FOREACH (p->actions, l, it)
150 {
151 match = evry_fuzzy_match(it->label, input);
152
153 if (!input || match)
154 {
155 it->fuzzy_match = match;
156 EVRY_PLUGIN_ITEM_APPEND(p, it);
157 }
158 }
159
160 if (!plugin->items) return 0;
161
162 EVRY_PLUGIN_ITEMS_SORT(p, _cb_sort);
163
164 return 1;
165 }
166
167 /***************************************************************************/
168
169 int
evry_plug_actions_init()170 evry_plug_actions_init()
171 {
172 _plug = EVRY_PLUGIN_BASE(N_("Actions"), NULL, EVRY_TYPE_ACTION,
173 _begin, _finish, _fetch);
174
175 _plug->browse = &_browse;
176
177 evry_plugin_register(_plug, EVRY_PLUGIN_ACTION, 2);
178
179 return 1;
180 }
181
182 void
evry_plug_actions_shutdown()183 evry_plug_actions_shutdown()
184 {
185 Evry_Item *it;
186
187 evry_plugin_free(_plug);
188
189 /* bypass unregister, because it modifies the list */
190 EINA_LIST_FREE (evry_conf->actions, it)
191 evry_item_free(it);
192 }
193
194 void
evry_action_register(Evry_Action * act,int priority)195 evry_action_register(Evry_Action *act, int priority)
196 {
197 EVRY_ITEM(act)->priority = priority;
198
199 evry_conf->actions = eina_list_append(evry_conf->actions, act);
200 /* TODO sorting, initialization, etc */
201 }
202
203 void
evry_action_unregister(Evry_Action * act)204 evry_action_unregister(Evry_Action *act)
205 {
206 evry_conf->actions = eina_list_remove(evry_conf->actions, act);
207 /* finish */
208 }
209
210 static void
_action_free_cb(Evry_Item * it)211 _action_free_cb(Evry_Item *it)
212 {
213 GET_ACTION(act, it);
214
215 IF_RELEASE(act->name);
216
217 E_FREE(act);
218 }
219
220 Evry_Action *
evry_action_new(const char * name,const char * label,Evry_Type type_in1,Evry_Type type_in2,const char * icon,int (* action)(Evry_Action * act),int (* check_item)(Evry_Action * act,const Evry_Item * it))221 evry_action_new(const char *name, const char *label,
222 Evry_Type type_in1, Evry_Type type_in2,
223 const char *icon,
224 int (*action)(Evry_Action *act),
225 int (*check_item)(Evry_Action *act, const Evry_Item *it))
226 {
227 Evry_Action *act = EVRY_ITEM_NEW(Evry_Action, _plug, label,
228 NULL, _action_free_cb);
229 if (icon)
230 act->base.icon = eina_stringshare_add(icon);
231
232 act->name = eina_stringshare_add(name);
233
234 act->it1.type = type_in1;
235 act->it2.type = type_in2;
236
237 act->action = action;
238 act->check_item = check_item;
239
240 return act;
241 }
242
243 void
evry_action_free(Evry_Action * act)244 evry_action_free(Evry_Action *act)
245 {
246 evry_action_unregister(act);
247
248 evry_item_free(EVRY_ITEM(act));
249 }
250
251 /* TODO assign actions to plugins othersie there will be too liitle
252 names soon */
253 Evry_Action *
evry_action_find(const char * name)254 evry_action_find(const char *name)
255 {
256 Evry_Action *act = NULL;
257 Eina_List *l;
258
259 const char *n = eina_stringshare_add(name);
260
261 EINA_LIST_FOREACH (evry_conf->actions, l, act)
262 if (act->name == n)
263 break;
264
265 eina_stringshare_del(n);
266
267 return act;
268 }
269
270