2 #include "e_mod_main.h"
4 typedef struct _Instance Instance;
12 Evas_Object *o_base, *o_box, *o_fm, *o_scroll;
16 Eina_List *history, *current;
21 Ecore_Idle_Enterer *idler;
25 /* local function protos */
26 static E_Gadcon_Client *_gc_init(E_Gadcon *gc, const char *name, const char *id, const char *style);
27 static void _gc_shutdown(E_Gadcon_Client *gcc);
28 static void _gc_orient(E_Gadcon_Client *gcc, E_Gadcon_Orient orient);
29 static const char *_gc_label(E_Gadcon_Client_Class *client_class);
30 static Evas_Object *_gc_icon(E_Gadcon_Client_Class *client_class, Evas *evas);
31 static const char *_gc_id_new(E_Gadcon_Client_Class *client_class);
32 static void _cb_mouse_down(void *data, Evas *e, Evas_Object *obj, void *event_info);
33 static void _cb_key_down(void *data, Evas *e, Evas_Object *obj, void *event_info);
34 static void _cb_back_click(void *data, Evas_Object *obj, const char *emission, const char *source);
35 static void _cb_forward_click(void *data, Evas_Object *obj, const char *emission, const char *source);
36 static void _cb_up_click(void *data, Evas_Object *obj, const char *emission, const char *source);
37 static void _cb_refresh_click(void *data, Evas_Object *obj, const char *emission, const char *source);
38 static void _cb_favorites_click(void *data, Evas_Object *obj, const char *emission, const char *source);
39 static void _cb_changed(void *data, Evas_Object *obj, void *event_info);
40 static void _cb_dir_changed(void *data, Evas_Object *obj, void *event_info);
41 static void _cb_button_click(void *data, Evas_Object *obj, const char *emission, const char *source);
42 static void _cb_scroll_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info);
43 static void _box_button_append(Instance *inst, const char *label, void (*func)(void *data, Evas_Object *obj, const char *emission, const char *source));
45 static Eina_List *instances = NULL;
46 static const char *_nav_mod_dir = NULL;
48 /* local gadcon functions */
49 static const E_Gadcon_Client_Class _gc_class =
51 GADCON_CLIENT_CLASS_VERSION, "efm_navigation",
53 _gc_init, _gc_shutdown, _gc_orient, _gc_label, _gc_icon, _gc_id_new, NULL,
54 e_gadcon_site_is_efm_toolbar
55 }, E_GADCON_CLIENT_STYLE_PLAIN
61 e_gadcon_provider_register(&_gc_class);
67 e_fwin_nav_shutdown(void)
69 e_gadcon_provider_unregister(&_gc_class);
74 static void _cb_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
80 evas_object_geometry_get(inst->gcc->gadcon->o_container, 0, 0, &w, &h);
81 e_gadcon_client_min_size_set(inst->gcc, w, h);
82 e_gadcon_client_aspect_set(inst->gcc, w, h);
86 _cb_initial_dir(void *data)
88 Instance *inst = data;
90 _cb_dir_changed(inst, NULL, NULL);
92 return ECORE_CALLBACK_CANCEL;
95 static E_Gadcon_Client *
96 _gc_init(E_Gadcon *gc, const char *name, const char *id, const char *style)
98 Instance *inst = NULL;
105 tbar = e_gadcon_toolbar_get(gc);
106 if (!tbar) return NULL;
108 o_fm = e_toolbar_fm2_get(tbar);
109 if (!o_fm) return NULL;
111 /* make sure only one instance exists in toolbar */
112 EINA_LIST_FOREACH(instances, l, inst)
113 if (inst->tbar == tbar) return NULL;
115 inst = E_NEW(Instance, 1);
116 if (!inst) return NULL;
121 snprintf(buf, sizeof(buf), "%s/e-module-efm_nav.edj", _nav_mod_dir);
122 inst->theme = eina_stringshare_add(buf);
124 inst->o_base = edje_object_add(gc->evas);
125 e_theme_edje_object_set(inst->o_base, "base/theme/modules/efm_navigation",
126 "modules/efm_navigation/main");
128 edje_object_signal_callback_add(inst->o_base, "e,action,back,click", "",
129 _cb_back_click, inst);
130 edje_object_signal_callback_add(inst->o_base, "e,action,forward,click", "",
131 _cb_forward_click, inst);
132 edje_object_signal_callback_add(inst->o_base, "e,action,up,click", "",
134 edje_object_signal_callback_add(inst->o_base, "e,action,refresh,click", "",
135 _cb_refresh_click, inst);
136 edje_object_signal_callback_add(inst->o_base, "e,action,favorites,click", "",
137 _cb_favorites_click, inst);
138 evas_object_show(inst->o_base);
140 inst->o_scroll = e_scrollframe_add(gc->evas);
141 e_scrollframe_custom_theme_set(inst->o_scroll,
142 "base/theme/modules/efm_navigation",
143 "modules/efm_navigation/pathbar_scrollframe");
145 e_scrollframe_single_dir_set(inst->o_scroll, 1);
146 e_scrollframe_policy_set(inst->o_scroll, E_SCROLLFRAME_POLICY_AUTO,
147 E_SCROLLFRAME_POLICY_OFF);
148 e_scrollframe_thumbscroll_force(inst->o_scroll, 1);
149 evas_object_show(inst->o_scroll);
151 inst->o_box = e_box_add(gc->evas);
152 e_box_orientation_set(inst->o_box, 1);
153 e_box_homogenous_set(inst->o_box, 0);
154 e_scrollframe_child_set(inst->o_scroll, inst->o_box);
155 evas_object_show(inst->o_box);
157 evas_object_event_callback_add(inst->o_scroll, EVAS_CALLBACK_RESIZE,
158 _cb_scroll_resize, inst);
160 edje_object_part_swallow(inst->o_base, "e.swallow.pathbar", inst->o_scroll);
162 inst->gcc = e_gadcon_client_new(gc, name, id, style, inst->o_base);
163 inst->gcc->data = inst;
165 /* add the hooks to get signals from efm */
166 evas_object_event_callback_add(inst->o_fm, EVAS_CALLBACK_KEY_DOWN,
168 evas_object_smart_callback_add(inst->o_fm, "changed",
170 evas_object_smart_callback_add(inst->o_fm, "dir_changed",
171 _cb_dir_changed, inst);
173 evas_object_event_callback_add(inst->o_base,
174 EVAS_CALLBACK_MOUSE_DOWN,
175 _cb_mouse_down, inst);
176 if (!inst->gcc->resizable)
178 evas_object_geometry_get(inst->gcc->gadcon->o_container, 0, 0, &w, &h);
179 e_gadcon_client_min_size_set(inst->gcc, w, h);
180 e_gadcon_client_aspect_set(inst->gcc, w, h);
181 evas_object_event_callback_add(inst->gcc->gadcon->o_container,
182 EVAS_CALLBACK_RESIZE,
186 edje_object_signal_emit(inst->o_base, "e,state,back,disabled", "e");
187 edje_object_signal_emit(inst->o_base, "e,state,forward,disabled", "e");
188 edje_object_message_signal_process(inst->o_base);
190 instances = eina_list_append(instances, inst);
192 inst->idler = ecore_idle_enterer_add(_cb_initial_dir, inst);
198 _gc_shutdown(E_Gadcon_Client *gcc)
200 Instance *inst = NULL;
206 instances = eina_list_remove(instances, inst);
208 evas_object_event_callback_del_full(inst->o_fm,
209 EVAS_CALLBACK_KEY_DOWN,
212 evas_object_smart_callback_del(inst->o_fm, "changed", _cb_changed);
213 evas_object_smart_callback_del(inst->o_fm, "dir_changed", _cb_dir_changed);
215 EINA_LIST_FREE(inst->history, s)
216 eina_stringshare_del(s);
218 if (gcc->gadcon->o_container)
219 evas_object_event_callback_del_full(gcc->gadcon->o_container,
220 EVAS_CALLBACK_RESIZE,
223 EINA_LIST_FREE(inst->l_buttons, btn)
226 evas_object_del(btn);
229 if (inst->o_base) evas_object_del(inst->o_base);
230 if (inst->o_box) evas_object_del(inst->o_box);
231 if (inst->o_scroll) evas_object_del(inst->o_scroll);
233 eina_stringshare_del(inst->theme);
239 _gc_orient(E_Gadcon_Client *gcc, E_Gadcon_Orient orient)
246 case E_GADCON_ORIENT_TOP:
247 case E_GADCON_ORIENT_BOTTOM:
248 /* e_gadcon_client_aspect_set(gcc, 16 * 4, 16); */
250 case E_GADCON_ORIENT_LEFT:
251 case E_GADCON_ORIENT_RIGHT:
252 /* e_gadcon_client_aspect_set(gcc, 16, 16 * 4); */
257 /* e_gadcon_client_min_size_set(gcc, 16, 16); */
261 _gc_label(E_Gadcon_Client_Class *client_class __UNUSED__)
263 return _("EFM Navigation");
267 _gc_icon(E_Gadcon_Client_Class *client_class __UNUSED__, Evas *evas)
269 return e_util_icon_theme_icon_add("system-file-manager", 48, evas);
273 _gc_id_new(E_Gadcon_Client_Class *client_class __UNUSED__)
277 snprintf(buf, sizeof(buf), "%s.%d", _gc_class.name,
278 (eina_list_count(instances) + 1));
282 /* local functions */
284 _cb_key_down(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info)
287 Evas_Event_Key_Down *ev;
291 if (evas_key_modifier_is_set(ev->modifiers, "Alt"))
293 if (!strcmp(ev->key, "Left"))
294 _cb_back_click(inst, obj, "e,action,click", "e");
295 else if (!strcmp(ev->key, "Right"))
296 _cb_forward_click(inst, obj, "e,action,click", "e");
297 else if (!strcmp(ev->key, "Up"))
298 _cb_up_click(inst, obj, "e,action,click", "e");
300 else if (evas_key_modifier_is_set(ev->modifiers, "Control"))
302 if (!strcmp(ev->key, "r"))
303 _cb_refresh_click(inst, obj, "e,action,click", "e");
308 _cb_mouse_down(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
311 Evas_Event_Mouse_Down *ev;
318 if ((ev->button != 3) || (inst->gcc->menu)) return;
319 zone = e_util_zone_current_get(e_manager_current_get());
322 m = e_gadcon_client_util_menu_items_append(inst->gcc, m, 0);
323 ecore_x_pointer_xy_get(zone->container->win, &x, &y);
324 e_menu_activate_mouse(m, zone, x, y, 1, 1,
325 E_MENU_POP_DIRECTION_AUTO, ev->timestamp);
329 _cb_back_click(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
335 if ((!inst->current) || (inst->current == eina_list_last(inst->history))) return;
336 inst->current = eina_list_next(inst->current);
338 inst->ignore_dir = 1;
339 e_fm2_path_set(inst->o_fm, eina_list_data_get(inst->current), "/");
343 _cb_forward_click(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
349 if ((!inst->current) || (inst->current == inst->history)) return;
350 inst->current = eina_list_prev(inst->current);
352 inst->ignore_dir = 1;
353 e_fm2_path_set(inst->o_fm, eina_list_data_get(inst->current), "/");
357 _cb_refresh_click(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
363 // Don't destroy forward history when refreshing
364 inst->ignore_dir = 1;
365 e_fm2_path_set(inst->o_fm, NULL, e_fm2_real_path_get(inst->o_fm));
369 _cb_up_click(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
376 t = strdup(e_fm2_real_path_get(inst->o_fm));
382 if (p[0] == 0) p = "/";
383 e_fm2_path_set(inst->o_fm, NULL, p);
387 edje_object_signal_emit(inst->o_base, "e,state,up,disabled", "e");
394 _cb_favorites_click(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
400 e_fm2_path_set(inst->o_fm, "favorites", "/");
404 _cb_changed(void *data, Evas_Object *obj __UNUSED__, void *event_info)
409 inst->tbar = event_info;
413 _cb_button_click(void *data, Evas_Object *obj, const char *emission __UNUSED__, const char *source __UNUSED__)
415 Instance *inst = data;
418 char path[PATH_MAX] = "";
420 EINA_LIST_FOREACH(inst->l_buttons, l, btn)
422 strcat(path, edje_object_part_text_get(btn, "e.text.label"));
423 if (btn == obj) break;
426 e_fm2_path_set(inst->o_fm, "/", path);
430 _cb_scroll_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
432 Instance *inst = data;
433 Evas_Coord mw = 0, mh = 0;
435 evas_object_geometry_get(inst->o_box, NULL, NULL, &mw, NULL);
436 evas_object_geometry_get(inst->o_scroll, NULL, NULL, NULL, &mh);
437 evas_object_resize(inst->o_box, mw, mh);
441 _box_button_append(Instance *inst, const char *label, void (*func)(void *data, Evas_Object *obj, const char *emission, const char *source))
444 Evas_Coord mw = 0, mh = 0;
446 if (!inst || !label || !*label || !func)
449 o = edje_object_add(evas_object_evas_get(inst->o_box));
451 e_theme_edje_object_set(o, "base/theme/modules/efm_navigation",
452 "modules/efm_navigation/pathbar_button");
454 edje_object_signal_callback_add(o, "e,action,click", "", func, inst);
455 edje_object_part_text_set(o, "e.text.label", label);
456 edje_object_size_min_calc(o, &mw, &mh);
457 e_box_pack_end(inst->o_box, o);
459 e_box_pack_options_set(o, 1, 0, 0, 0, 0.5, 0.5, mw, mh, 9999, 9999);
460 e_box_size_min_get(inst->o_box, &mw, NULL);
461 evas_object_geometry_get(inst->o_scroll, NULL, NULL, NULL, &mh);
462 evas_object_resize(inst->o_box, mw, mh);
464 inst->l_buttons = eina_list_append(inst->l_buttons, o);
468 _cb_dir_changed(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
471 const char *realpath;
472 char *path, *dir, *p;
473 Eina_List *l, *ll, *sel = NULL;
475 int mw, sw, changed = 0;
479 if (!(realpath = e_fm2_real_path_get(inst->o_fm))) return;
482 if (!inst->l_buttons)
483 _box_button_append(inst, "/", _cb_button_click);
485 sel = inst->l_buttons;
486 l = eina_list_next(sel);
487 p = path = ecore_file_realpath(realpath);
491 dir = strsep(&p, "/");
493 if (!(*dir)) continue;
495 if (l && (btn = eina_list_data_get(l)))
497 if (strcmp(dir, edje_object_part_text_get(btn, "e.text.label")))
504 evas_object_del(btn);
506 l = eina_list_next(l);
507 btn = eina_list_data_get(l);
510 eina_list_remove_list(inst->l_buttons, ll);
516 l = eina_list_next(l);
521 _box_button_append(inst, dir, _cb_button_click);
522 if (!p) sel = eina_list_last(inst->l_buttons);
530 evas_object_geometry_get(inst->o_box, NULL, NULL, &mw, NULL);
531 edje_object_size_min_calc(e_scrollframe_edje_object_get(inst->o_scroll), &sw, NULL);
533 evas_object_size_hint_max_set(inst->o_scroll, mw + sw, 32);
536 EINA_LIST_FOREACH(inst->l_buttons, l, btn)
538 edje_object_signal_emit(btn, "e,state,selected", "e");
540 edje_object_signal_emit(btn, "e,state,default", "e");
542 /* scroll to selected button */
545 Evas_Coord x, y, w, h, xx, yy, ww = 1;
546 btn = eina_list_data_get(sel);
547 evas_object_geometry_get(btn, &x, &y, &w, &h);
549 /* show buttons around selected */
552 btn = eina_list_data_get(sel->next);
553 evas_object_geometry_get(btn, NULL, NULL, &ww, NULL);
558 btn = eina_list_data_get(sel->prev);
559 evas_object_geometry_get(btn, NULL, NULL, &ww, NULL);
564 evas_object_geometry_get(inst->o_box, &xx, &yy, NULL, NULL);
565 e_scrollframe_child_region_show(inst->o_scroll, x - xx, y - yy, w, h);
569 if ((!inst->ignore_dir) && (eina_list_data_get(inst->current) != realpath))
573 while (inst->history != inst->current)
575 eina_stringshare_del(eina_list_data_get(inst->history));
577 eina_list_remove_list(inst->history, inst->history);
581 eina_list_prepend(inst->history, eina_stringshare_ref(realpath));
582 inst->current = inst->history;
584 inst->ignore_dir = 0;
586 if (!strcmp(realpath, "/"))
587 edje_object_signal_emit(inst->o_base, "e,state,up,disabled", "e");
589 edje_object_signal_emit(inst->o_base, "e,state,up,enabled", "e");
591 if ((!inst->history) || (eina_list_last(inst->history) == inst->current))
592 edje_object_signal_emit(inst->o_base, "e,state,back,disabled", "e");
594 edje_object_signal_emit(inst->o_base, "e,state,back,enabled", "e");
596 if ((!inst->history) || (inst->history == inst->current))
597 edje_object_signal_emit(inst->o_base, "e,state,forward,disabled", "e");
599 edje_object_signal_emit(inst->o_base, "e,state,forward,enabled", "e");