#include "e_mod_main.h" /* action selector plugin: provides list of actions registered for candidate types provided by current plugin */ typedef struct _Plugin Plugin; struct _Plugin { Evry_Plugin base; Eina_List *actions; Eina_Bool parent; Evry_Action *action; }; static Evry_Plugin *_plug = NULL; static void _finish(Evry_Plugin *plugin) { GET_PLUGIN(p, plugin); EVRY_PLUGIN_ITEMS_CLEAR(p); eina_list_free(p->actions); E_FREE(p); } static Evry_Plugin * _browse(Evry_Plugin *plugin, const Evry_Item *it) { Evry_Action *act; Plugin *p; if (!CHECK_TYPE(it, EVRY_TYPE_ACTION)) return NULL; act = EVRY_ACTN(it); EVRY_PLUGIN_INSTANCE(p, plugin); p->actions = act->fetch(act); p->parent = EINA_TRUE; p->action = act; return EVRY_PLUGIN(p); } static Evry_Plugin * _begin(Evry_Plugin *plugin, const Evry_Item *it) { Evry_Action *act; Eina_List *l; Plugin *p; EVRY_PLUGIN_INSTANCE(p, plugin); if (!(CHECK_TYPE(it, EVRY_TYPE_PLUGIN))) { EINA_LIST_FOREACH (evry_conf->actions, l, act) { if (!((!act->it1.type) || (CHECK_TYPE(it, act->it1.type)) || (CHECK_SUBTYPE(it, act->it1.type)))) continue; if (act->check_item && !(act->check_item(act, it))) continue; act->base.plugin = EVRY_PLUGIN(p); act->it1.item = it; EVRY_ITEM(act)->hi = NULL; p->actions = eina_list_append(p->actions, act); } } if (it->plugin) { EINA_LIST_FOREACH (it->plugin->actions, l, act) { act->base.plugin = EVRY_PLUGIN(p); act->it1.item = EVRY_ITEM(it->plugin); EVRY_ITEM(act)->hi = NULL; p->actions = eina_list_append(p->actions, act); } } return EVRY_PLUGIN(p); } static int _cb_sort(const void *data1, const void *data2) { const Evry_Item *it1 = data1; const Evry_Item *it2 = data2; const Evry_Action *act1 = data1; const Evry_Action *act2 = data2; if (act1->remember_context || act2->remember_context) { if (act1->remember_context && !act2->remember_context) return -1; if (!act1->remember_context && act2->remember_context) return 1; } /* sort type match before subtype match */ if (act1->it1.item && act2->it1.item) { if ((act1->it1.type == act1->it1.item->type) && (act2->it1.type != act2->it1.item->type)) return -1; if ((act1->it1.type != act1->it1.item->type) && (act2->it1.type == act2->it1.item->type)) return 1; } if (it1->fuzzy_match || it2->fuzzy_match) if (it1->fuzzy_match || it2->fuzzy_match) { if (it1->fuzzy_match && !it2->fuzzy_match) return -1; if (!it1->fuzzy_match && it2->fuzzy_match) return 1; if (it1->fuzzy_match - it2->fuzzy_match) return it1->fuzzy_match - it2->fuzzy_match; } if (it1->priority - it2->priority) return it1->priority - it2->priority; return 0; } static int _fetch(Evry_Plugin *plugin, const char *input) { GET_PLUGIN(p, plugin); Eina_List *l; Evry_Item *it; int match; EVRY_PLUGIN_ITEMS_CLEAR(p); EINA_LIST_FOREACH (p->actions, l, it) { match = evry_fuzzy_match(it->label, input); if (!input || match) { it->fuzzy_match = match; EVRY_PLUGIN_ITEM_APPEND(p, it); } } if (!plugin->items) return 0; EVRY_PLUGIN_ITEMS_SORT(p, _cb_sort); return 1; } /***************************************************************************/ int evry_plug_actions_init() { _plug = EVRY_PLUGIN_BASE(N_("Actions"), NULL, EVRY_TYPE_ACTION, _begin, _finish, _fetch); _plug->browse = &_browse; evry_plugin_register(_plug, EVRY_PLUGIN_ACTION, 2); return 1; } void evry_plug_actions_shutdown() { Evry_Item *it; evry_plugin_free(_plug); /* bypass unregister, because it modifies the list */ EINA_LIST_FREE (evry_conf->actions, it) evry_item_free(it); } void evry_action_register(Evry_Action *act, int priority) { EVRY_ITEM(act)->priority = priority; evry_conf->actions = eina_list_append(evry_conf->actions, act); /* TODO sorting, initialization, etc */ } void evry_action_unregister(Evry_Action *act) { evry_conf->actions = eina_list_remove(evry_conf->actions, act); /* finish */ } static void _action_free_cb(Evry_Item *it) { GET_ACTION(act, it); IF_RELEASE(act->name); E_FREE(act); } 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)) { Evry_Action *act = EVRY_ITEM_NEW(Evry_Action, _plug, label, NULL, _action_free_cb); if (icon) act->base.icon = eina_stringshare_add(icon); act->name = eina_stringshare_add(name); act->it1.type = type_in1; act->it2.type = type_in2; act->action = action; act->check_item = check_item; return act; } void evry_action_free(Evry_Action *act) { evry_action_unregister(act); evry_item_free(EVRY_ITEM(act)); } /* TODO assign actions to plugins othersie there will be too liitle names soon */ Evry_Action * evry_action_find(const char *name) { Evry_Action *act = NULL; Eina_List *l; const char *n = eina_stringshare_add(name); EINA_LIST_FOREACH (evry_conf->actions, l, act) if (act->name == n) break; eina_stringshare_del(n); return act; }