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