#include "luncher.h"
static Eina_List *handlers;
static Elm_Gengrid_Item_Class _grid_icon_class;
static void _grid_resize_job(void *data);

static void
_grid_aspect(Instance *inst)
{
   Evas_Coord w, h, square, size;

   if (!eina_list_count(inst->icons))
     return;
   evas_object_geometry_get(inst->o_main, 0, 0, &w, &h);
   size = 0;
   if ((w + h) > 1)
     {
        square = w + h;
        size = floor((square / eina_list_count(inst->icons)));
     }
   inst->size = size;
   elm_gengrid_item_size_set(inst->o_icon_con, size, size);
}

static Eina_Bool
_grid_check_modifiers(Evas_Modifier *modifiers)
{
   if ((evas_key_modifier_is_set(modifiers, "Alt")) ||
       (evas_key_modifier_is_set(modifiers, "Control")) ||
       (evas_key_modifier_is_set(modifiers, "Shift")))
     return EINA_TRUE;
   return EINA_FALSE;
}

static Evas_Object *
_grid_gadget_configure(Evas_Object *g)
{
   if (!luncher_config) return NULL;
   if (luncher_config->config_dialog) return NULL;
   Instance *inst = evas_object_data_get(g, "instance");
   return config_luncher(e_zone_current_get(), inst, EINA_TRUE);
}

static void
_grid_instance_watch(void *data, E_Exec_Instance *ex EINA_UNUSED, E_Exec_Watch_Type type)
{
   Icon *ic = data;

   switch (type)
     {
      case E_EXEC_WATCH_STARTED:
        if (ic->starting) elm_layout_signal_emit(ic->o_layout, "e,state,started", "e");
        ic->starting = EINA_FALSE;
        break;
      default:
        break;
     }
}

static void
_grid_icon_del(Instance *inst, Icon *ic)
{
   inst->icons = eina_list_remove(inst->icons, ic);
   evas_object_del(ic->o_icon);
   evas_object_del(ic->o_layout);
   if (ic->desktop)
     efreet_desktop_unref(ic->desktop);
   eina_stringshare_del(ic->icon);
   eina_stringshare_del(ic->key);
   if (ic->exec)
     e_exec_instance_watcher_del(ic->exec, _grid_instance_watch, ic);
   ic->exec = NULL;
   _grid_aspect(inst);
   E_FREE(ic);
}

static void
_grid_icon_drag_done(E_Drag *drag, int dropped)
{
   Instance *inst = e_object_data_get(E_OBJECT(drag));

   efreet_desktop_unref(drag->data);
   if (!inst) return;
   evas_object_smart_callback_call(e_gadget_site_get(inst->o_main), "gadget_site_unlocked", NULL);
   if (!dropped)
     grid_recalculate(inst);
}

static void
_grid_icon_mouse_move(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_data)
{
   Icon *ic = data;
   Evas_Event_Mouse_Move *ev = event_data;
   int dx, dy;

   if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return;
   if (_grid_check_modifiers(ev->modifiers)) return;

   if (!ic->drag.start) return;

   dx = ev->cur.output.x - ic->drag.x;
   dy = ev->cur.output.y - ic->drag.y;
   if (((dx * dx) + (dy * dy)) >
       (e_config->drag_resist * e_config->drag_resist))
     {
        E_Drag *d;
        Evas_Object *o;
        Evas_Coord x, y, w, h;
        unsigned int size;
        const char *drag_types[] = { "enlightenment/desktop" };

        ic->drag.dnd = 1;
        ic->drag.start = 0;

        evas_object_geometry_get(ic->o_icon, &x, &y, &w, &h);
        d = e_drag_new(x, y, drag_types, 1,
                       ic->desktop, -1, NULL, _grid_icon_drag_done);
        d->button_mask = evas_pointer_button_down_mask_get(e_comp->evas);
        efreet_desktop_ref(ic->desktop);
        size = MAX(w, h);
        o = e_util_desktop_icon_add(ic->desktop, size, e_drag_evas_get(d));
        e_drag_object_set(d, o);

        e_drag_resize(d, w, h);
        e_drag_start(d, ic->drag.x, ic->drag.y);
        e_object_data_set(E_OBJECT(d), ic->inst);
        if (ic->in_order)
          e_order_remove(ic->inst->order, ic->desktop);
     }
}

static Eina_Bool
_grid_drag_timer(void *data)
{
   Icon *ic = data;

   ic->drag_timer = NULL;
   ic->drag.start = 1;
   evas_object_smart_callback_call(e_gadget_site_get(ic->inst->o_main), "gadget_site_locked", NULL);
   return EINA_FALSE;
}

static void
_grid_icon_mouse_down(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_data)
{
   Icon *ic = data;
   Evas_Event_Mouse_Up *ev = event_data;

   if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
     {
        if (ev->button == 1)
          {
             ic->drag.start = 0;
             ic->drag.dnd = 0;
             E_FREE_FUNC(ic->mouse_in_timer, ecore_timer_del);
             E_FREE_FUNC(ic->mouse_out_timer, ecore_timer_del);
             E_FREE_FUNC(ic->drag_timer, ecore_timer_del);
          }
        return;
     }
   if (_grid_check_modifiers(ev->modifiers)) return;

   if (ev->button == 1)
     {
        ic->drag.x = ev->output.x;
        ic->drag.y = ev->output.y;
        E_FREE_FUNC(ic->drag_timer, ecore_timer_del);
        ic->drag_timer = ecore_timer_loop_add(.35, _grid_drag_timer, ic);
     }
}

static void
_grid_icon_mouse_up(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_data)
{
   Icon *ic = data;
   Evas_Event_Mouse_Up *ev = event_data;

   if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return;
   if (_grid_check_modifiers(ev->modifiers)) return;

   if (ev->button == 1)
     {
        E_FREE_FUNC(ic->drag_timer, ecore_timer_del);
        if (ic->drag.dnd)
          {
             ic->drag.start = 0;
             ic->drag.dnd = 0;
             return;
          }
     }
   if (ev->button == 1 && ic->desktop)
     {
        if (ic->desktop->type == EFREET_DESKTOP_TYPE_APPLICATION)
          {
             E_Exec_Instance *ex;

             ex = e_exec(e_zone_current_get(), ic->desktop, NULL, NULL, "luncher");
             ic->exec = ex;
             e_exec_instance_watcher_add(ex, _grid_instance_watch, ic);
             if (!ic->starting) elm_layout_signal_emit(ic->o_layout, "e,state,starting", "e");
             ic->starting = EINA_TRUE;
          }
        else if (ic->desktop->type == EFREET_DESKTOP_TYPE_LINK)
          {
             if (!strncasecmp(ic->desktop->url, "file:", 5))
               {
                  E_Action *act;

                  act = e_action_find("fileman");
                  if (act)
                    act->func.go(NULL, ic->desktop->url + 5);
               }
          }
     }
}

static void
_grid_icon_mouse_in(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_data)
{
   Icon *ic = data;
   Evas_Event_Mouse_In *ev = event_data;

   if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return;
   if (_grid_check_modifiers(ev->modifiers)) return;

   evas_object_raise(ic->o_layout);
   if (!ic->inst->cfg->hide_tooltips)
     elm_object_tooltip_show(obj);
   ic->active = EINA_TRUE;
   elm_layout_signal_emit(ic->o_layout, "e,state,focused", "e");
}

static void
_grid_icon_mouse_out(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_data EINA_UNUSED)
{
   Icon *ic = data;

   if (!ic->inst->cfg->hide_tooltips)
     elm_object_tooltip_hide(obj);
   elm_layout_signal_emit(ic->o_layout, "e,state,unfocused", "e");
}

static Evas_Object *
_gengrid_icon_get(void *data, Evas_Object *obj EINA_UNUSED, const char *part)
{
   Icon *ic = data;
   if (strcmp(part, "elm.swallow.icon"))
     return NULL;
   return ic->o_layout;
}

static void
_grid_icon_file_set(Icon *ic, Efreet_Desktop *desktop)
{
   const char *path = NULL, *k = NULL;
   char buf[4096];

   if (desktop)
     {
        if (!desktop->icon)
          path = NULL;
        else if (strncmp(desktop->icon, "/", 1) && !ecore_file_exists(desktop->icon))
          {
             path = efreet_icon_path_find(e_config->icon_theme, desktop->icon, ic->inst->size);
             if (!path)
               {
                  if (e_util_strcmp(e_config->icon_theme, "hicolor"))
                    path = efreet_icon_path_find("hicolor", desktop->icon, ic->inst->size);
               }
          }
        else if (ecore_file_exists(desktop->icon))
          {
             path = desktop->icon;
          }
        if (!path && desktop->icon)
          {
             snprintf(buf, sizeof(buf), "e/icons/%s", desktop->icon);
             if (eina_list_count(e_theme_collection_items_find("base/theme/icons", buf)))
               {
                  path = e_theme_edje_file_get("base/theme/icons", buf);
                  k = buf;
               }
             else
               {
                  path = e_theme_edje_file_get("base/theme/icons", "e/icons/unknown");
                  k =  "e/icons/unknown";
               }
          }
        else if (!path && !desktop->icon)
          {
             path = e_theme_edje_file_get("base/theme/icons", "e/icons/unknown");
             k =  "e/icons/unknown";
          }
     }
   else if (ic->icon)
     {
        if (strncmp(ic->icon, "/", 1) && !ecore_file_exists(ic->icon))
          {
             path = efreet_icon_path_find(e_config->icon_theme, ic->icon, ic->inst->size);
             if (!path)
               {
                  if (e_util_strcmp(e_config->icon_theme, "hicolor"))
                    path = efreet_icon_path_find("hicolor", ic->icon, ic->inst->size);
               }
          }
        else if (ecore_file_exists(ic->icon))
          {
             path = ic->icon;
             k = ic->key;
          }
        if (!path)
          {
             path = e_theme_edje_file_get("base/theme/icons", "e/icons/unknown");
             k =  "e/icons/unknown";
          }
     }
   else
     {
        path = e_theme_edje_file_get("base/theme/icons", "e/icons/unknown");
        k =  "e/icons/unknown";
     }
   elm_image_file_set(ic->o_icon, path, k);
}

static Icon *
_grid_icon_add(Instance *inst, Efreet_Desktop *desktop)
{
   Icon *ic;

   ic = E_NEW(Icon, 1);
   efreet_desktop_ref(desktop);
   ic->desktop = desktop;
   ic->inst = inst;
   ic->preview = NULL;
   ic->preview_box = NULL;
   ic->mouse_in_timer = NULL;
   ic->mouse_out_timer = NULL;
   ic->active = EINA_FALSE;
   ic->starting = EINA_FALSE;
   ic->exec = NULL;

   ic->o_layout = elm_layout_add(inst->o_icon_con);
   e_theme_edje_object_set(ic->o_layout, "e/gadget/luncher/icon",
       "e/gadget/luncher/icon");
   E_FILL(ic->o_layout);
   evas_object_show(ic->o_layout);

   ic->o_icon = elm_icon_add(ic->o_layout);
   E_EXPAND(ic->o_icon);


   _grid_icon_file_set(ic, desktop);

   if (!inst->cfg->hide_tooltips)
     {
        elm_object_tooltip_text_set(ic->o_icon, desktop->name);
        elm_object_tooltip_orient_set(ic->o_icon, ELM_TOOLTIP_ORIENT_CENTER);
        elm_object_tooltip_style_set(ic->o_icon, "luncher");
     }
   evas_object_size_hint_aspect_set(ic->o_icon, EVAS_ASPECT_CONTROL_BOTH, 1, 1);
   elm_layout_content_set(ic->o_layout, "e.swallow.icon", ic->o_icon);
   evas_object_event_callback_add(ic->o_icon, EVAS_CALLBACK_MOUSE_UP,
       _grid_icon_mouse_up, ic);
   evas_object_event_callback_priority_add(ic->o_icon, EVAS_CALLBACK_MOUSE_DOWN, 0,
       _grid_icon_mouse_down, ic);
   evas_object_event_callback_add(ic->o_icon, EVAS_CALLBACK_MOUSE_MOVE,
       _grid_icon_mouse_move, ic);
   evas_object_event_callback_add(ic->o_icon, EVAS_CALLBACK_MOUSE_IN,
       _grid_icon_mouse_in, ic);
   evas_object_event_callback_add(ic->o_icon, EVAS_CALLBACK_MOUSE_OUT,
       _grid_icon_mouse_out, ic);
   evas_object_show(ic->o_icon);

   elm_layout_sizing_eval(ic->o_layout);

   elm_gengrid_item_append(inst->o_icon_con, &_grid_icon_class, ic, NULL, NULL);
   _grid_aspect(inst);

   return ic;
}

static void
_grid_empty(Instance *inst)
{
   if (inst->icons)
     {
        elm_gengrid_clear(inst->o_icon_con);
        while (inst->icons)
          _grid_icon_del(inst, eina_list_data_get(inst->icons));
	inst->icons = NULL;
     }
}

static void
_grid_fill(Instance *inst)
{
   Icon *ic;

   if (inst->order)
     {
        Efreet_Desktop *desktop;
        Eina_List *list;

        EINA_LIST_FOREACH(inst->order->desktops, list, desktop)
          {
             ic = _grid_icon_add(inst, desktop);
             ic->in_order = EINA_TRUE;
             inst->icons = eina_list_append(inst->icons, ic);
          }
     }
}

static void
_grid_resize_job(void *data)
{
   Instance *inst = data;
   Eina_List *l;
   Icon *ic;

   if (inst)
     {
        elm_layout_sizing_eval(inst->o_main);
        _grid_aspect(inst);
        EINA_LIST_FOREACH(inst->icons, l, ic)
          _grid_icon_file_set(ic, ic->desktop);
        inst->resize_job = NULL;
     }
}

static Eina_Bool
_grid_cb_update_icons(EINA_UNUSED void *data, EINA_UNUSED int ev_type, EINA_UNUSED void *ev)
{
   Instance *inst = NULL;
   Eina_List *l = NULL;

   EINA_LIST_FOREACH(luncher_instances, l, inst)
     {
        if (inst->bar) continue;
        if (inst->resize_job) return ECORE_CALLBACK_RENEW;
        inst->resize_job = ecore_job_add(_grid_resize_job, inst);
     }
   return ECORE_CALLBACK_PASS_ON;
}

static void
_grid_resize(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_data EINA_UNUSED)
{
   Instance *inst = data;

   if (inst->resize_job) return;
   inst->resize_job = ecore_job_add(_grid_resize_job, inst);
}

static void
_grid_removed_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_data)
{
   Instance *inst = data;
   char buf[4096];

   if (inst->o_main != event_data) return;
   if (e_user_dir_snprintf(buf, sizeof(buf), "applications/bar/%s", inst->cfg->dir) >= sizeof(buf))
     return;

   luncher_config->items = eina_list_remove(luncher_config->items, inst->cfg);
   eina_stringshare_del(inst->cfg->dir);
   E_FREE(inst->cfg);
}

static void
_grid_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_data EINA_UNUSED)
{
   Instance *inst = data;

   evas_object_smart_callback_del_full(e_gadget_site_get(obj), "gadget_removed", _grid_removed_cb, inst);
   e_object_del(E_OBJECT(inst->order));
   E_FREE_FUNC(inst->drop_handler, evas_object_del);
   luncher_instances = eina_list_remove(luncher_instances, inst);
   free(inst);
}

static void
_grid_drop_drop(void *data, const char *type, void *event_data)
{
   Instance *inst = data;
   E_Event_Dnd_Drop *ev = event_data;
   Efreet_Desktop *desktop = NULL;
   Eina_List *l = NULL;
   Icon *ic = NULL;

   evas_object_del(inst->place_holder);
   inst->place_holder = NULL;
   if (!strcmp(type, "enlightenment/desktop"))
     desktop = ev->data;
   else if (!strcmp(type, "enlightenment/border"))
     {
        E_Client *ec;

        ec = ev->data;
        desktop = ec->desktop;
        if (!desktop)
          {
             desktop = e_desktop_client_create(ec);
             efreet_desktop_save(desktop);
             e_desktop_edit(desktop);
          }
     }
   else if (!strcmp(type, "text/uri-list"))
     l = ev->data;

   ic = inst->drop_before;
   if (ic)
     {
        if (desktop)
          e_order_prepend_relative(inst->order, desktop, ic->desktop);
        else
          e_order_files_prepend_relative(inst->order, l, ic->desktop);
     }
   else
     {
        if (desktop)
          e_order_append(inst->order, desktop);
        else
          e_order_files_append(inst->order, l);
     }
}

static void
_grid_drop_leave(void *data, const char *type EINA_UNUSED, void *event_data EINA_UNUSED)
{
   Instance *inst = data;

   inst->inside = EINA_FALSE;
   evas_object_del(inst->place_holder);
   inst->place_holder = NULL;
}

static void
_grid_drop_move(void *data, const char *type EINA_UNUSED, void *event_data)
{
   Instance *inst = data;
   E_Event_Dnd_Move *ev = event_data;
   Evas_Coord x = ev->x, y = ev->y;
   Eina_List *l;
   Icon *ic;

   if (!inst->inside)
     return;

   EINA_LIST_FOREACH(inst->icons, l, ic)
     {
        Evas_Coord dx, dy, dw, dh;

        if (!ic->in_order) continue;
        evas_object_geometry_get(ic->o_layout, &dx, &dy, &dw, &dh);
        if (E_INSIDE(x, y, dx, dy, dw, dh))
          inst->drop_before = ic;
     }
   if (inst->drop_before)
     elm_gengrid_item_insert_before(inst->o_icon_con, &_grid_icon_class, inst->place_holder, inst->drop_before->o_layout, NULL, NULL);
}

static void
_grid_drop_enter(void *data, const char *type EINA_UNUSED, void *event_data EINA_UNUSED)
{
   Instance *inst = data;

   inst->inside = EINA_TRUE;
   inst->place_holder = evas_object_rectangle_add(evas_object_evas_get(inst->o_icon_con));
   evas_object_color_set(inst->place_holder, 0, 0, 0, 0);
   evas_object_size_hint_min_set(inst->place_holder, inst->size, inst->size);
   evas_object_size_hint_max_set(inst->place_holder, inst->size, inst->size);
   evas_object_show(inst->place_holder);
}

static void
_grid_anchor_changed_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
{
   Instance *inst = data;

   if (inst && inst->o_icon_con)
     {
        grid_recalculate(inst);
     }
}

static void
_grid_order_update(void *data, E_Order *eo EINA_UNUSED)
{
   Instance *inst = data;

   if (inst && inst->o_icon_con)
     {
        grid_recalculate(inst);
     }
}

static void
_grid_created_cb(void *data, Evas_Object *obj, void *event_data EINA_UNUSED)
{
   Instance *inst = data;
   char buf[4096];
   const char *drop[] = { "enlightenment/desktop", "enlightenment/border", "text/uri-list" };

   inst->o_icon_con = elm_gengrid_add(inst->o_main);
   elm_object_style_set(inst->o_icon_con, "no_inset_shadow");
   elm_gengrid_align_set(inst->o_icon_con, 0.5, 0.5);
   elm_gengrid_select_mode_set(inst->o_icon_con, ELM_OBJECT_SELECT_MODE_NONE);
   E_FILL(inst->o_icon_con);
   elm_layout_content_set(inst->o_main, "e.swallow.grid", inst->o_icon_con);
   evas_object_show(inst->o_icon_con);

   evas_object_data_set(inst->o_main, "instance", inst);
   evas_object_data_set(inst->o_icon_con, "instance", inst);

   e_gadget_configure_cb_set(inst->o_main, _grid_gadget_configure);
   evas_object_smart_callback_del_full(obj, "gadget_created", _grid_created_cb, data);

   if (!inst->cfg->dir)
     inst->cfg->dir = eina_stringshare_add("default");
   if (inst->cfg->dir[0] != '/')
     e_user_dir_snprintf(buf, sizeof(buf), "applications/bar/%s/.order",
                         inst->cfg->dir);
   else
     eina_strlcpy(buf, inst->cfg->dir, sizeof(buf));

   inst->order = e_order_new(buf);
   e_order_update_callback_set(inst->order, _grid_order_update, inst);

   _grid_fill(inst);

   inst->drop_handler =
     e_gadget_drop_handler_add(inst->o_main, inst,
                        _grid_drop_enter, _grid_drop_move,
                        _grid_drop_leave, _grid_drop_drop,
                        drop, 3);
   elm_layout_content_set(inst->o_main, "e.swallow.drop", inst->drop_handler);
   evas_object_show(inst->drop_handler);

   evas_object_event_callback_add(inst->o_main, EVAS_CALLBACK_RESIZE, _grid_resize, inst);
   _grid_aspect(inst);
}

static Config_Item *
_conf_item_get(int *id)
{
   Config_Item *ci;
   Eina_List *l;

   if (*id > 0)
     {
        EINA_LIST_FOREACH(luncher_config->items, l, ci)
          if (*id == ci->id) return ci;
     }

   ci = E_NEW(Config_Item, 1);

   if (*id != -1)
     ci->id = eina_list_count(luncher_config->items)+1;
   else
     ci->id = -1;
   ci->dir = eina_stringshare_add("default");
   luncher_config->items = eina_list_append(luncher_config->items, ci);

   return ci;
}

static void
_grid_recalculate_job(void *data)
{
   Instance *inst = data;

   if (inst)
     {
        if (inst->o_icon_con)
          {
             _grid_empty(inst);
             _grid_fill(inst);
          }
        inst->recalc_job = NULL;
     }
}

EINTERN void
grid_recalculate(Instance *inst)
{
   E_FREE_FUNC(inst->recalc_job, ecore_job_del);
   inst->recalc_job = ecore_job_add(_grid_recalculate_job, inst);
}

EINTERN void
grid_reorder(Instance *inst)
{
   char buf[4096];

   if (inst)
     {
        E_FREE_FUNC(inst->recalc_job, ecore_job_del);
        _grid_empty(inst);
        if (!inst->cfg->dir)
          inst->cfg->dir = eina_stringshare_add("default");
        if (inst->cfg->dir[0] != '/')
          e_user_dir_snprintf(buf, sizeof(buf), "applications/bar/%s/.order",
                              inst->cfg->dir);
        else
          eina_strlcpy(buf, inst->cfg->dir, sizeof(buf));
        e_object_del(E_OBJECT(inst->order));
        inst->order = e_order_new(buf);
        e_order_update_callback_set(inst->order, _grid_order_update, inst);
        _grid_fill(inst);
     }
}

EINTERN Evas_Object *
grid_create(Evas_Object *parent, int *id, E_Gadget_Site_Orient orient)
{
   Instance *inst;

   if (orient) return NULL;
   if (e_gadget_site_is_desklock(parent)) return NULL;
   inst = E_NEW(Instance, 1);
   inst->size = 0;
   inst->resize_job = NULL;
   inst->cfg = _conf_item_get(id);
   *id = inst->cfg->id;
   inst->inside = EINA_FALSE;
   inst->bar = EINA_FALSE;

   if (!inst->cfg->preview_size)
     inst->cfg->preview_size = 64;

   _grid_icon_class.item_style = "luncher";
   _grid_icon_class.func.text_get = NULL;
   _grid_icon_class.func.content_get = _gengrid_icon_get;
   _grid_icon_class.func.state_get = NULL;
   _grid_icon_class.func.del = NULL;

   inst->o_main = elm_layout_add(parent);
   e_theme_edje_object_set(inst->o_main, "e/gadget/luncher/grid",
       "e/gadget/luncher/grid");
   evas_object_event_callback_add(inst->o_main, EVAS_CALLBACK_DEL, _grid_del, inst);
   evas_object_smart_callback_add(parent, "gadget_created", _grid_created_cb, inst);
   evas_object_smart_callback_add(parent, "gadget_site_anchor", _grid_anchor_changed_cb, inst);
   evas_object_smart_callback_add(parent, "gadget_removed", _grid_removed_cb, inst);
   evas_object_show(inst->o_main);

   E_LIST_HANDLER_APPEND(handlers, E_EVENT_CONFIG_ICON_THEME,
                         _grid_cb_update_icons, NULL);
   E_LIST_HANDLER_APPEND(handlers, EFREET_EVENT_ICON_CACHE_UPDATE,
                         _grid_cb_update_icons, NULL);

   if (inst->cfg->id < 0) return inst->o_main;
   luncher_instances = eina_list_append(luncher_instances, inst);

   return inst->o_main;
}
