1 #include "luncher.h"
2 static Eina_List *handlers;
3 static Elm_Gengrid_Item_Class _grid_icon_class;
4 static void _grid_resize_job(void *data);
5 
6 static void
_grid_aspect(Instance * inst)7 _grid_aspect(Instance *inst)
8 {
9    Evas_Coord w, h, square, size;
10 
11    if (!eina_list_count(inst->icons))
12      return;
13    evas_object_geometry_get(inst->o_main, 0, 0, &w, &h);
14    size = 0;
15    if ((w + h) > 1)
16      {
17         square = w + h;
18         size = floor((square / eina_list_count(inst->icons)));
19      }
20    inst->size = size;
21    elm_gengrid_item_size_set(inst->o_icon_con, size, size);
22 }
23 
24 static Eina_Bool
_grid_check_modifiers(Evas_Modifier * modifiers)25 _grid_check_modifiers(Evas_Modifier *modifiers)
26 {
27    if ((evas_key_modifier_is_set(modifiers, "Alt")) ||
28        (evas_key_modifier_is_set(modifiers, "Control")) ||
29        (evas_key_modifier_is_set(modifiers, "Shift")))
30      return EINA_TRUE;
31    return EINA_FALSE;
32 }
33 
34 static Evas_Object *
_grid_gadget_configure(Evas_Object * g)35 _grid_gadget_configure(Evas_Object *g)
36 {
37    if (!luncher_config) return NULL;
38    if (luncher_config->config_dialog) return NULL;
39    Instance *inst = evas_object_data_get(g, "instance");
40    return config_luncher(e_zone_current_get(), inst, EINA_TRUE);
41 }
42 
43 static void
_grid_instance_watch(void * data,E_Exec_Instance * ex EINA_UNUSED,E_Exec_Watch_Type type)44 _grid_instance_watch(void *data, E_Exec_Instance *ex EINA_UNUSED, E_Exec_Watch_Type type)
45 {
46    Icon *ic = data;
47 
48    switch (type)
49      {
50       case E_EXEC_WATCH_STARTED:
51         if (ic->starting) elm_layout_signal_emit(ic->o_layout, "e,state,started", "e");
52         ic->starting = EINA_FALSE;
53         break;
54       default:
55         break;
56      }
57 }
58 
59 static void
_grid_icon_del(Instance * inst,Icon * ic)60 _grid_icon_del(Instance *inst, Icon *ic)
61 {
62    inst->icons = eina_list_remove(inst->icons, ic);
63    evas_object_del(ic->o_icon);
64    evas_object_del(ic->o_layout);
65    if (ic->desktop)
66      efreet_desktop_unref(ic->desktop);
67    eina_stringshare_del(ic->icon);
68    eina_stringshare_del(ic->key);
69    if (ic->exec)
70      e_exec_instance_watcher_del(ic->exec, _grid_instance_watch, ic);
71    ic->exec = NULL;
72    _grid_aspect(inst);
73    E_FREE(ic);
74 }
75 
76 static void
_grid_icon_drag_done(E_Drag * drag,int dropped)77 _grid_icon_drag_done(E_Drag *drag, int dropped)
78 {
79    Instance *inst = e_object_data_get(E_OBJECT(drag));
80 
81    efreet_desktop_unref(drag->data);
82    if (!inst) return;
83    evas_object_smart_callback_call(e_gadget_site_get(inst->o_main), "gadget_site_unlocked", NULL);
84    if (!dropped)
85      grid_recalculate(inst);
86 }
87 
88 static void
_grid_icon_mouse_move(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_data)89 _grid_icon_mouse_move(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_data)
90 {
91    Icon *ic = data;
92    Evas_Event_Mouse_Move *ev = event_data;
93    int dx, dy;
94 
95    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return;
96    if (_grid_check_modifiers(ev->modifiers)) return;
97 
98    if (!ic->drag.start) return;
99 
100    dx = ev->cur.output.x - ic->drag.x;
101    dy = ev->cur.output.y - ic->drag.y;
102    if (((dx * dx) + (dy * dy)) >
103        (e_config->drag_resist * e_config->drag_resist))
104      {
105         E_Drag *d;
106         Evas_Object *o;
107         Evas_Coord x, y, w, h;
108         unsigned int size;
109         const char *drag_types[] = { "enlightenment/desktop" };
110 
111         ic->drag.dnd = 1;
112         ic->drag.start = 0;
113 
114         evas_object_geometry_get(ic->o_icon, &x, &y, &w, &h);
115         d = e_drag_new(x, y, drag_types, 1,
116                        ic->desktop, -1, NULL, _grid_icon_drag_done);
117         d->button_mask = evas_pointer_button_down_mask_get(e_comp->evas);
118         efreet_desktop_ref(ic->desktop);
119         size = MAX(w, h);
120         o = e_util_desktop_icon_add(ic->desktop, size, e_drag_evas_get(d));
121         e_drag_object_set(d, o);
122 
123         e_drag_resize(d, w, h);
124         e_drag_start(d, ic->drag.x, ic->drag.y);
125         e_object_data_set(E_OBJECT(d), ic->inst);
126         if (ic->in_order)
127           e_order_remove(ic->inst->order, ic->desktop);
128      }
129 }
130 
131 static Eina_Bool
_grid_drag_timer(void * data)132 _grid_drag_timer(void *data)
133 {
134    Icon *ic = data;
135 
136    ic->drag_timer = NULL;
137    ic->drag.start = 1;
138    evas_object_smart_callback_call(e_gadget_site_get(ic->inst->o_main), "gadget_site_locked", NULL);
139    return EINA_FALSE;
140 }
141 
142 static void
_grid_icon_mouse_down(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_data)143 _grid_icon_mouse_down(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_data)
144 {
145    Icon *ic = data;
146    Evas_Event_Mouse_Up *ev = event_data;
147 
148    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
149      {
150         if (ev->button == 1)
151           {
152              ic->drag.start = 0;
153              ic->drag.dnd = 0;
154              E_FREE_FUNC(ic->mouse_in_timer, ecore_timer_del);
155              E_FREE_FUNC(ic->mouse_out_timer, ecore_timer_del);
156              E_FREE_FUNC(ic->drag_timer, ecore_timer_del);
157           }
158         return;
159      }
160    if (_grid_check_modifiers(ev->modifiers)) return;
161 
162    if (ev->button == 1)
163      {
164         ic->drag.x = ev->output.x;
165         ic->drag.y = ev->output.y;
166         E_FREE_FUNC(ic->drag_timer, ecore_timer_del);
167         ic->drag_timer = ecore_timer_loop_add(.35, _grid_drag_timer, ic);
168      }
169 }
170 
171 static void
_grid_icon_mouse_up(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_data)172 _grid_icon_mouse_up(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_data)
173 {
174    Icon *ic = data;
175    Evas_Event_Mouse_Up *ev = event_data;
176 
177    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return;
178    if (_grid_check_modifiers(ev->modifiers)) return;
179 
180    if (ev->button == 1)
181      {
182         E_FREE_FUNC(ic->drag_timer, ecore_timer_del);
183         if (ic->drag.dnd)
184           {
185              ic->drag.start = 0;
186              ic->drag.dnd = 0;
187              return;
188           }
189      }
190    if (ev->button == 1 && ic->desktop)
191      {
192         if (ic->desktop->type == EFREET_DESKTOP_TYPE_APPLICATION)
193           {
194              E_Exec_Instance *ex;
195 
196              ex = e_exec(e_zone_current_get(), ic->desktop, NULL, NULL, "luncher");
197              ic->exec = ex;
198              e_exec_instance_watcher_add(ex, _grid_instance_watch, ic);
199              if (!ic->starting) elm_layout_signal_emit(ic->o_layout, "e,state,starting", "e");
200              ic->starting = EINA_TRUE;
201           }
202         else if (ic->desktop->type == EFREET_DESKTOP_TYPE_LINK)
203           {
204              if (!strncasecmp(ic->desktop->url, "file:", 5))
205                {
206                   E_Action *act;
207 
208                   act = e_action_find("fileman");
209                   if (act)
210                     act->func.go(NULL, ic->desktop->url + 5);
211                }
212           }
213      }
214 }
215 
216 static void
_grid_icon_mouse_in(void * data,Evas * e EINA_UNUSED,Evas_Object * obj,void * event_data)217 _grid_icon_mouse_in(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_data)
218 {
219    Icon *ic = data;
220    Evas_Event_Mouse_In *ev = event_data;
221 
222    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return;
223    if (_grid_check_modifiers(ev->modifiers)) return;
224 
225    evas_object_raise(ic->o_layout);
226    if (!ic->inst->cfg->hide_tooltips)
227      elm_object_tooltip_show(obj);
228    ic->active = EINA_TRUE;
229    elm_layout_signal_emit(ic->o_layout, "e,state,focused", "e");
230 }
231 
232 static void
_grid_icon_mouse_out(void * data,Evas * e EINA_UNUSED,Evas_Object * obj,void * event_data EINA_UNUSED)233 _grid_icon_mouse_out(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_data EINA_UNUSED)
234 {
235    Icon *ic = data;
236 
237    if (!ic->inst->cfg->hide_tooltips)
238      elm_object_tooltip_hide(obj);
239    elm_layout_signal_emit(ic->o_layout, "e,state,unfocused", "e");
240 }
241 
242 static Evas_Object *
_gengrid_icon_get(void * data,Evas_Object * obj EINA_UNUSED,const char * part)243 _gengrid_icon_get(void *data, Evas_Object *obj EINA_UNUSED, const char *part)
244 {
245    Icon *ic = data;
246    if (strcmp(part, "elm.swallow.icon"))
247      return NULL;
248    return ic->o_layout;
249 }
250 
251 static void
_grid_icon_file_set(Icon * ic,Efreet_Desktop * desktop)252 _grid_icon_file_set(Icon *ic, Efreet_Desktop *desktop)
253 {
254    const char *path = NULL, *k = NULL;
255    char buf[4096];
256 
257    if (desktop)
258      {
259         if (!desktop->icon)
260           path = NULL;
261         else if (strncmp(desktop->icon, "/", 1) && !ecore_file_exists(desktop->icon))
262           {
263              path = efreet_icon_path_find(e_config->icon_theme, desktop->icon, ic->inst->size);
264              if (!path)
265                {
266                   if (e_util_strcmp(e_config->icon_theme, "hicolor"))
267                     path = efreet_icon_path_find("hicolor", desktop->icon, ic->inst->size);
268                }
269           }
270         else if (ecore_file_exists(desktop->icon))
271           {
272              path = desktop->icon;
273           }
274         if (!path && desktop->icon)
275           {
276              snprintf(buf, sizeof(buf), "e/icons/%s", desktop->icon);
277              if (eina_list_count(e_theme_collection_items_find("base/theme/icons", buf)))
278                {
279                   path = e_theme_edje_file_get("base/theme/icons", buf);
280                   k = buf;
281                }
282              else
283                {
284                   path = e_theme_edje_file_get("base/theme/icons", "e/icons/unknown");
285                   k =  "e/icons/unknown";
286                }
287           }
288         else if (!path && !desktop->icon)
289           {
290              path = e_theme_edje_file_get("base/theme/icons", "e/icons/unknown");
291              k =  "e/icons/unknown";
292           }
293      }
294    else if (ic->icon)
295      {
296         if (strncmp(ic->icon, "/", 1) && !ecore_file_exists(ic->icon))
297           {
298              path = efreet_icon_path_find(e_config->icon_theme, ic->icon, ic->inst->size);
299              if (!path)
300                {
301                   if (e_util_strcmp(e_config->icon_theme, "hicolor"))
302                     path = efreet_icon_path_find("hicolor", ic->icon, ic->inst->size);
303                }
304           }
305         else if (ecore_file_exists(ic->icon))
306           {
307              path = ic->icon;
308              k = ic->key;
309           }
310         if (!path)
311           {
312              path = e_theme_edje_file_get("base/theme/icons", "e/icons/unknown");
313              k =  "e/icons/unknown";
314           }
315      }
316    else
317      {
318         path = e_theme_edje_file_get("base/theme/icons", "e/icons/unknown");
319         k =  "e/icons/unknown";
320      }
321    elm_image_file_set(ic->o_icon, path, k);
322 }
323 
324 static Icon *
_grid_icon_add(Instance * inst,Efreet_Desktop * desktop)325 _grid_icon_add(Instance *inst, Efreet_Desktop *desktop)
326 {
327    Icon *ic;
328 
329    ic = E_NEW(Icon, 1);
330    efreet_desktop_ref(desktop);
331    ic->desktop = desktop;
332    ic->inst = inst;
333    ic->preview = NULL;
334    ic->preview_box = NULL;
335    ic->mouse_in_timer = NULL;
336    ic->mouse_out_timer = NULL;
337    ic->active = EINA_FALSE;
338    ic->starting = EINA_FALSE;
339    ic->exec = NULL;
340 
341    ic->o_layout = elm_layout_add(inst->o_icon_con);
342    e_theme_edje_object_set(ic->o_layout, "e/gadget/luncher/icon",
343        "e/gadget/luncher/icon");
344    E_FILL(ic->o_layout);
345    evas_object_show(ic->o_layout);
346 
347    ic->o_icon = elm_icon_add(ic->o_layout);
348    E_EXPAND(ic->o_icon);
349 
350 
351    _grid_icon_file_set(ic, desktop);
352 
353    if (!inst->cfg->hide_tooltips)
354      {
355         elm_object_tooltip_text_set(ic->o_icon, desktop->name);
356         elm_object_tooltip_orient_set(ic->o_icon, ELM_TOOLTIP_ORIENT_CENTER);
357         elm_object_tooltip_style_set(ic->o_icon, "luncher");
358      }
359    evas_object_size_hint_aspect_set(ic->o_icon, EVAS_ASPECT_CONTROL_BOTH, 1, 1);
360    elm_layout_content_set(ic->o_layout, "e.swallow.icon", ic->o_icon);
361    evas_object_event_callback_add(ic->o_icon, EVAS_CALLBACK_MOUSE_UP,
362        _grid_icon_mouse_up, ic);
363    evas_object_event_callback_priority_add(ic->o_icon, EVAS_CALLBACK_MOUSE_DOWN, 0,
364        _grid_icon_mouse_down, ic);
365    evas_object_event_callback_add(ic->o_icon, EVAS_CALLBACK_MOUSE_MOVE,
366        _grid_icon_mouse_move, ic);
367    evas_object_event_callback_add(ic->o_icon, EVAS_CALLBACK_MOUSE_IN,
368        _grid_icon_mouse_in, ic);
369    evas_object_event_callback_add(ic->o_icon, EVAS_CALLBACK_MOUSE_OUT,
370        _grid_icon_mouse_out, ic);
371    evas_object_show(ic->o_icon);
372 
373    elm_layout_sizing_eval(ic->o_layout);
374 
375    elm_gengrid_item_append(inst->o_icon_con, &_grid_icon_class, ic, NULL, NULL);
376    _grid_aspect(inst);
377 
378    return ic;
379 }
380 
381 static void
_grid_empty(Instance * inst)382 _grid_empty(Instance *inst)
383 {
384    if (inst->icons)
385      {
386         elm_gengrid_clear(inst->o_icon_con);
387         while (inst->icons)
388           _grid_icon_del(inst, eina_list_data_get(inst->icons));
389 	inst->icons = NULL;
390      }
391 }
392 
393 static void
_grid_fill(Instance * inst)394 _grid_fill(Instance *inst)
395 {
396    Icon *ic;
397 
398    if (inst->order)
399      {
400         Efreet_Desktop *desktop;
401         Eina_List *list;
402 
403         EINA_LIST_FOREACH(inst->order->desktops, list, desktop)
404           {
405              ic = _grid_icon_add(inst, desktop);
406              ic->in_order = EINA_TRUE;
407              inst->icons = eina_list_append(inst->icons, ic);
408           }
409      }
410 }
411 
412 static void
_grid_resize_job(void * data)413 _grid_resize_job(void *data)
414 {
415    Instance *inst = data;
416    Eina_List *l;
417    Icon *ic;
418 
419    if (inst)
420      {
421         elm_layout_sizing_eval(inst->o_main);
422         _grid_aspect(inst);
423         EINA_LIST_FOREACH(inst->icons, l, ic)
424           _grid_icon_file_set(ic, ic->desktop);
425         inst->resize_job = NULL;
426      }
427 }
428 
429 static Eina_Bool
_grid_cb_update_icons(EINA_UNUSED void * data,EINA_UNUSED int ev_type,EINA_UNUSED void * ev)430 _grid_cb_update_icons(EINA_UNUSED void *data, EINA_UNUSED int ev_type, EINA_UNUSED void *ev)
431 {
432    Instance *inst = NULL;
433    Eina_List *l = NULL;
434 
435    EINA_LIST_FOREACH(luncher_instances, l, inst)
436      {
437         if (inst->bar) continue;
438         if (inst->resize_job) return ECORE_CALLBACK_RENEW;
439         inst->resize_job = ecore_job_add(_grid_resize_job, inst);
440      }
441    return ECORE_CALLBACK_PASS_ON;
442 }
443 
444 static void
_grid_resize(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_data EINA_UNUSED)445 _grid_resize(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_data EINA_UNUSED)
446 {
447    Instance *inst = data;
448 
449    if (inst->resize_job) return;
450    inst->resize_job = ecore_job_add(_grid_resize_job, inst);
451 }
452 
453 static void
_grid_removed_cb(void * data,Evas_Object * obj EINA_UNUSED,void * event_data)454 _grid_removed_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_data)
455 {
456    Instance *inst = data;
457    char buf[4096];
458 
459    if (inst->o_main != event_data) return;
460    if (e_user_dir_snprintf(buf, sizeof(buf), "applications/bar/%s", inst->cfg->dir) >= sizeof(buf))
461      return;
462 
463    luncher_config->items = eina_list_remove(luncher_config->items, inst->cfg);
464    eina_stringshare_del(inst->cfg->dir);
465    E_FREE(inst->cfg);
466 }
467 
468 static void
_grid_del(void * data,Evas * e EINA_UNUSED,Evas_Object * obj,void * event_data EINA_UNUSED)469 _grid_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_data EINA_UNUSED)
470 {
471    Instance *inst = data;
472 
473    evas_object_smart_callback_del_full(e_gadget_site_get(obj), "gadget_removed", _grid_removed_cb, inst);
474    e_object_del(E_OBJECT(inst->order));
475    E_FREE_FUNC(inst->drop_handler, evas_object_del);
476    luncher_instances = eina_list_remove(luncher_instances, inst);
477    free(inst);
478 }
479 
480 static void
_grid_drop_drop(void * data,const char * type,void * event_data)481 _grid_drop_drop(void *data, const char *type, void *event_data)
482 {
483    Instance *inst = data;
484    E_Event_Dnd_Drop *ev = event_data;
485    Efreet_Desktop *desktop = NULL;
486    Eina_List *l = NULL;
487    Icon *ic = NULL;
488 
489    evas_object_del(inst->place_holder);
490    inst->place_holder = NULL;
491    if (!strcmp(type, "enlightenment/desktop"))
492      desktop = ev->data;
493    else if (!strcmp(type, "enlightenment/border"))
494      {
495         E_Client *ec;
496 
497         ec = ev->data;
498         desktop = ec->desktop;
499         if (!desktop)
500           {
501              desktop = e_desktop_client_create(ec);
502              efreet_desktop_save(desktop);
503              e_desktop_edit(desktop);
504           }
505      }
506    else if (!strcmp(type, "text/uri-list"))
507      l = ev->data;
508 
509    ic = inst->drop_before;
510    if (ic)
511      {
512         if (desktop)
513           e_order_prepend_relative(inst->order, desktop, ic->desktop);
514         else
515           e_order_files_prepend_relative(inst->order, l, ic->desktop);
516      }
517    else
518      {
519         if (desktop)
520           e_order_append(inst->order, desktop);
521         else
522           e_order_files_append(inst->order, l);
523      }
524 }
525 
526 static void
_grid_drop_leave(void * data,const char * type EINA_UNUSED,void * event_data EINA_UNUSED)527 _grid_drop_leave(void *data, const char *type EINA_UNUSED, void *event_data EINA_UNUSED)
528 {
529    Instance *inst = data;
530 
531    inst->inside = EINA_FALSE;
532    evas_object_del(inst->place_holder);
533    inst->place_holder = NULL;
534 }
535 
536 static void
_grid_drop_move(void * data,const char * type EINA_UNUSED,void * event_data)537 _grid_drop_move(void *data, const char *type EINA_UNUSED, void *event_data)
538 {
539    Instance *inst = data;
540    E_Event_Dnd_Move *ev = event_data;
541    Evas_Coord x = ev->x, y = ev->y;
542    Eina_List *l;
543    Icon *ic;
544 
545    if (!inst->inside)
546      return;
547 
548    EINA_LIST_FOREACH(inst->icons, l, ic)
549      {
550         Evas_Coord dx, dy, dw, dh;
551 
552         if (!ic->in_order) continue;
553         evas_object_geometry_get(ic->o_layout, &dx, &dy, &dw, &dh);
554         if (E_INSIDE(x, y, dx, dy, dw, dh))
555           inst->drop_before = ic;
556      }
557    if (inst->drop_before)
558      elm_gengrid_item_insert_before(inst->o_icon_con, &_grid_icon_class, inst->place_holder, inst->drop_before->o_layout, NULL, NULL);
559 }
560 
561 static void
_grid_drop_enter(void * data,const char * type EINA_UNUSED,void * event_data EINA_UNUSED)562 _grid_drop_enter(void *data, const char *type EINA_UNUSED, void *event_data EINA_UNUSED)
563 {
564    Instance *inst = data;
565 
566    inst->inside = EINA_TRUE;
567    inst->place_holder = evas_object_rectangle_add(evas_object_evas_get(inst->o_icon_con));
568    evas_object_color_set(inst->place_holder, 0, 0, 0, 0);
569    evas_object_size_hint_min_set(inst->place_holder, inst->size, inst->size);
570    evas_object_size_hint_max_set(inst->place_holder, inst->size, inst->size);
571    evas_object_show(inst->place_holder);
572 }
573 
574 static void
_grid_anchor_changed_cb(void * data,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)575 _grid_anchor_changed_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
576 {
577    Instance *inst = data;
578 
579    if (inst && inst->o_icon_con)
580      {
581         grid_recalculate(inst);
582      }
583 }
584 
585 static void
_grid_order_update(void * data,E_Order * eo EINA_UNUSED)586 _grid_order_update(void *data, E_Order *eo EINA_UNUSED)
587 {
588    Instance *inst = data;
589 
590    if (inst && inst->o_icon_con)
591      {
592         grid_recalculate(inst);
593      }
594 }
595 
596 static void
_grid_created_cb(void * data,Evas_Object * obj,void * event_data EINA_UNUSED)597 _grid_created_cb(void *data, Evas_Object *obj, void *event_data EINA_UNUSED)
598 {
599    Instance *inst = data;
600    char buf[4096];
601    const char *drop[] = { "enlightenment/desktop", "enlightenment/border", "text/uri-list" };
602 
603    inst->o_icon_con = elm_gengrid_add(inst->o_main);
604    elm_object_style_set(inst->o_icon_con, "no_inset_shadow");
605    elm_gengrid_align_set(inst->o_icon_con, 0.5, 0.5);
606    elm_gengrid_select_mode_set(inst->o_icon_con, ELM_OBJECT_SELECT_MODE_NONE);
607    E_FILL(inst->o_icon_con);
608    elm_layout_content_set(inst->o_main, "e.swallow.grid", inst->o_icon_con);
609    evas_object_show(inst->o_icon_con);
610 
611    evas_object_data_set(inst->o_main, "instance", inst);
612    evas_object_data_set(inst->o_icon_con, "instance", inst);
613 
614    e_gadget_configure_cb_set(inst->o_main, _grid_gadget_configure);
615    evas_object_smart_callback_del_full(obj, "gadget_created", _grid_created_cb, data);
616 
617    if (!inst->cfg->dir)
618      inst->cfg->dir = eina_stringshare_add("default");
619    if (inst->cfg->dir[0] != '/')
620      e_user_dir_snprintf(buf, sizeof(buf), "applications/bar/%s/.order",
621                          inst->cfg->dir);
622    else
623      eina_strlcpy(buf, inst->cfg->dir, sizeof(buf));
624 
625    inst->order = e_order_new(buf);
626    e_order_update_callback_set(inst->order, _grid_order_update, inst);
627 
628    _grid_fill(inst);
629 
630    inst->drop_handler =
631      e_gadget_drop_handler_add(inst->o_main, inst,
632                         _grid_drop_enter, _grid_drop_move,
633                         _grid_drop_leave, _grid_drop_drop,
634                         drop, 3);
635    elm_layout_content_set(inst->o_main, "e.swallow.drop", inst->drop_handler);
636    evas_object_show(inst->drop_handler);
637 
638    evas_object_event_callback_add(inst->o_main, EVAS_CALLBACK_RESIZE, _grid_resize, inst);
639    _grid_aspect(inst);
640 }
641 
642 static Config_Item *
_conf_item_get(int * id)643 _conf_item_get(int *id)
644 {
645    Config_Item *ci;
646    Eina_List *l;
647 
648    if (*id > 0)
649      {
650         EINA_LIST_FOREACH(luncher_config->items, l, ci)
651           if (*id == ci->id) return ci;
652      }
653 
654    ci = E_NEW(Config_Item, 1);
655 
656    if (*id != -1)
657      ci->id = eina_list_count(luncher_config->items)+1;
658    else
659      ci->id = -1;
660    ci->dir = eina_stringshare_add("default");
661    luncher_config->items = eina_list_append(luncher_config->items, ci);
662 
663    return ci;
664 }
665 
666 static void
_grid_recalculate_job(void * data)667 _grid_recalculate_job(void *data)
668 {
669    Instance *inst = data;
670 
671    if (inst)
672      {
673         if (inst->o_icon_con)
674           {
675              _grid_empty(inst);
676              _grid_fill(inst);
677           }
678         inst->recalc_job = NULL;
679      }
680 }
681 
682 EINTERN void
grid_recalculate(Instance * inst)683 grid_recalculate(Instance *inst)
684 {
685    E_FREE_FUNC(inst->recalc_job, ecore_job_del);
686    inst->recalc_job = ecore_job_add(_grid_recalculate_job, inst);
687 }
688 
689 EINTERN void
grid_reorder(Instance * inst)690 grid_reorder(Instance *inst)
691 {
692    char buf[4096];
693 
694    if (inst)
695      {
696         E_FREE_FUNC(inst->recalc_job, ecore_job_del);
697         _grid_empty(inst);
698         if (!inst->cfg->dir)
699           inst->cfg->dir = eina_stringshare_add("default");
700         if (inst->cfg->dir[0] != '/')
701           e_user_dir_snprintf(buf, sizeof(buf), "applications/bar/%s/.order",
702                               inst->cfg->dir);
703         else
704           eina_strlcpy(buf, inst->cfg->dir, sizeof(buf));
705         e_object_del(E_OBJECT(inst->order));
706         inst->order = e_order_new(buf);
707         e_order_update_callback_set(inst->order, _grid_order_update, inst);
708         _grid_fill(inst);
709      }
710 }
711 
712 EINTERN Evas_Object *
grid_create(Evas_Object * parent,int * id,E_Gadget_Site_Orient orient)713 grid_create(Evas_Object *parent, int *id, E_Gadget_Site_Orient orient)
714 {
715    Instance *inst;
716 
717    if (orient) return NULL;
718    if (e_gadget_site_is_desklock(parent)) return NULL;
719    inst = E_NEW(Instance, 1);
720    inst->size = 0;
721    inst->resize_job = NULL;
722    inst->cfg = _conf_item_get(id);
723    *id = inst->cfg->id;
724    inst->inside = EINA_FALSE;
725    inst->bar = EINA_FALSE;
726 
727    if (!inst->cfg->preview_size)
728      inst->cfg->preview_size = 64;
729 
730    _grid_icon_class.item_style = "luncher";
731    _grid_icon_class.func.text_get = NULL;
732    _grid_icon_class.func.content_get = _gengrid_icon_get;
733    _grid_icon_class.func.state_get = NULL;
734    _grid_icon_class.func.del = NULL;
735 
736    inst->o_main = elm_layout_add(parent);
737    e_theme_edje_object_set(inst->o_main, "e/gadget/luncher/grid",
738        "e/gadget/luncher/grid");
739    evas_object_event_callback_add(inst->o_main, EVAS_CALLBACK_DEL, _grid_del, inst);
740    evas_object_smart_callback_add(parent, "gadget_created", _grid_created_cb, inst);
741    evas_object_smart_callback_add(parent, "gadget_site_anchor", _grid_anchor_changed_cb, inst);
742    evas_object_smart_callback_add(parent, "gadget_removed", _grid_removed_cb, inst);
743    evas_object_show(inst->o_main);
744 
745    E_LIST_HANDLER_APPEND(handlers, E_EVENT_CONFIG_ICON_THEME,
746                          _grid_cb_update_icons, NULL);
747    E_LIST_HANDLER_APPEND(handlers, EFREET_EVENT_ICON_CACHE_UPDATE,
748                          _grid_cb_update_icons, NULL);
749 
750    if (inst->cfg->id < 0) return inst->o_main;
751    luncher_instances = eina_list_append(luncher_instances, inst);
752 
753    return inst->o_main;
754 }
755