enlightenment/src/modules/everything/evry_plug_view_list.c

713 lines
14 KiB
C

#include "Evry.h"
typedef struct _List_View List_View;
typedef struct _List_Tab List_Tab;
struct _List_Tab
{
Evry_Plugin *plugin;
Evas_Object *o_tab;
};
struct _List_View
{
Evry_View view;
Evas *evas;
const Evas_Object *swallow;
const Evry_State *state;
Evas_Object *o_list;
Evas_Object *o_tabs;
Eina_List *items;
Eina_List *tabs;
Ecore_Idler *item_idler;
double scroll_align_to;
double scroll_align;
/* int ev_last_is_mouse;
* Evry_Item *item_mouseover; */
/* Ecore_Timer *scroll_timer; */
/* Ecore_Animator *scroll_animator; */
};
static Evry_View *view = NULL;
static void
_list_clear(List_View *v)
{
printf("clear list\n");
Evry_Item *it;
if (v->item_idler)
{
ecore_idler_del(v->item_idler);
v->item_idler = NULL;
}
/* if (v->scroll_timer)
* {
* ecore_timer_del(v->scroll_timer);
* v->scroll_timer = NULL;
* }
*
* if (v->scroll_animator)
* {
* ecore_animator_del(v->scroll_animator);
* v->scroll_animator = NULL;
* } */
/* v->scroll_align = 0; */
if (!v->items) return;
evas_event_freeze(v->evas);
e_box_freeze(v->o_list);
EINA_LIST_FREE(v->items, it)
{
if (it->o_bg)
{
e_box_unpack(it->o_bg);
evas_object_hide(it->o_bg);
}
if (it->o_icon)
evas_object_hide(it->o_icon);
evry_item_free(it);
}
e_box_thaw(v->o_list);
evas_event_thaw(v->evas);
}
static void
_list_scroll_to(List_View *v, const Evry_Item *it)
{
int n, h, mh, i = 0;
Eina_List *l;
if (!it) return;
for(l = v->items; l; l = l->next, i++)
if (l->data == it) break;
n = eina_list_count(v->items);
e_box_min_size_get(v->o_list, NULL, &mh);
evas_object_geometry_get(v->o_list, NULL, NULL, NULL, &h);
if (mh <= h)
{
e_box_align_set(v->o_list, 0.5, 0.0);
return;
}
/* FIXME: how to get size of list before it is completely shown? */
if (n > 6)
{
v->scroll_align_to = (double)i / (double)(n - 1);
{
v->scroll_align = v->scroll_align_to;
e_box_align_set(v->o_list, 0.5, 1.0 - v->scroll_align);
}
}
else
e_box_align_set(v->o_list, 0.5, 0.0);
}
static int
_list_item_idler(void *data)
{
List_View *v = data;
Evry_Plugin *p = v->state->plugin;
Eina_List *l;
Evry_Item *it;
int cnt = 5;
if (!v->item_idler) return 0;
if (!p->icon_get) goto end;
e_box_freeze(v->o_list);
EINA_LIST_FOREACH(v->items, l, it)
{
if (it->o_icon) continue;
it->o_icon = p->icon_get(p, it, v->evas);
if (it->o_icon)
{
edje_object_part_swallow(it->o_bg, "e.swallow.icons", it->o_icon);
evas_object_show(it->o_icon);
cnt--;
}
if (cnt == 0) break;
}
e_box_thaw(v->o_list);
if (cnt == 0) return 1;
end:
v->item_idler = NULL;
return 0;
}
static void
_list_item_set_selected(const Evry_Item *it)
{
if (it->o_bg)
edje_object_signal_emit(it->o_bg, "e,state,selected", "e");
if (it->o_icon)
edje_object_signal_emit(it->o_icon, "e,state,selected", "e");
if (it->browseable)
edje_object_signal_emit(it->o_bg, "e,state,arrow_show", "e");
}
static void
_list_item_set_unselected(const Evry_Item *it)
{
if (it->o_bg)
edje_object_signal_emit(it->o_bg, "e,state,unselected", "e");
if (it->o_icon)
edje_object_signal_emit(it->o_icon, "e,state,unselected", "e");
}
static int
_list_update(List_View *v)
{
Evry_Item *it;
Eina_List *l;
int mw = -1, mh;
Evas_Object *o;
int divider = 1;
_list_clear(v);
if (!v->state->plugin)
return 1;
evas_event_freeze(v->evas);
e_box_freeze(v->o_list);
EINA_LIST_FOREACH(v->state->plugin->items, l, it)
{
o = it->o_bg;
if (!o)
{
o = edje_object_add(v->evas);
it->o_bg = o;
e_theme_edje_object_set(o, "base/theme/everything",
"e/modules/everything/item");
edje_object_part_text_set(o, "e.text.title", it->label);
}
if (mw < 0) edje_object_size_min_get(o, &mw, &mh);
e_box_pack_end(v->o_list, o);
e_box_pack_options_set(o, 1, 1, 1, 0, 0.5, 0.5, mw, mh, 9999, mh);
evas_object_show(o);
if (divider)
{
edje_object_signal_emit(it->o_bg, "e,state,odd", "e");
divider = 0;
}
else
{
edje_object_signal_emit(it->o_bg, "e,state,even", "e");
divider = 1;
}
if (it->o_icon && edje_object_part_exists(o, "e.swallow.icons"))
{
edje_object_part_swallow(o, "e.swallow.icons", it->o_icon);
evas_object_show(it->o_icon);
}
if (it == v->state->sel_item)
_list_item_set_selected(it);
else
_list_item_set_unselected(it);
evry_item_ref(it);
v->items = eina_list_append(v->items, it);
}
e_box_thaw(v->o_list);
evas_event_thaw(v->evas);
_list_scroll_to(v, v->state->sel_item);
v->item_idler = ecore_idler_add(_list_item_idler, v);
return 1;
}
static void
_list_item_sel(List_View *v, const Evry_Item *it)
{
if (v->state->sel_item)
{
Evry_Item *it2 = v->state->sel_item;
if (it == it2) return;
_list_item_set_unselected(it2);
}
_list_item_set_selected(it);
_list_scroll_to(v, it);
}
static void
_list_item_next(List_View *v)
{
Eina_List *l;
Evry_Item *it;
EINA_LIST_FOREACH (v->items, l, it)
{
if (it != v->state->sel_item) continue;
if (l->next)
{
it = l->next->data;
_list_item_sel(v, it);
evry_item_select(v->state, it);
}
break;
}
}
static void
_list_item_prev(List_View *v)
{
Eina_List *l;
Evry_Item *it;
EINA_LIST_FOREACH (v->items, l, it)
{
if (it != v->state->sel_item) continue;
if (l->prev)
{
it = l->prev->data;
_list_item_sel(v, it);
evry_item_select(v->state, it);
return;
}
break;
}
evry_list_win_hide();
}
static void
_list_item_first(List_View *v)
{
Evry_Item *it;
if (!v->items) return;
it = v->items->data;
_list_item_sel(v, it);
evry_item_select(v->state, it);
}
static void
_list_item_last(List_View *v)
{
Evry_Item *it;
if (!v->items) return;
it = eina_list_last(v->items)->data;
_list_item_sel(v, it);
evry_item_select(v->state, it);
}
static void
_list_tab_scroll_to(List_View *v, Evry_Plugin *p)
{
int n, w, mw, i;
double align;
Eina_List *l;
const Evry_State *s = v->state;
for(i = 0, l = s->cur_plugins; l; l = l->next, i++)
if (l->data == p) break;
n = eina_list_count(s->cur_plugins);
e_box_min_size_get(v->o_tabs, &mw, NULL);
evas_object_geometry_get(v->o_tabs, NULL, NULL, &w, NULL);
if (mw <= w + 5)
{
e_box_align_set(v->o_tabs, 0.0, 0.5);
return;
}
if (n > 1)
{
align = (double)i / (double)(n - 1);
/* if (evry_conf->scroll_animate)
* {
* if (!scroll_timer)
* scroll_timer = ecore_timer_add(0.01, _evry_list_scroll_timer, NULL);
* if (!scroll_animator)
* scroll_animator = ecore_animator_add(_evry_list_animator, NULL);
* }
* else */
e_box_align_set(v->o_tabs, 1.0 - align, 0.5);
}
else
e_box_align_set(v->o_tabs, 1.0, 0.5);
}
static void
_list_tabs_update(List_View *v)
{
Eina_List *l, *ll;
Evry_Plugin *p;
const Evry_State *s = v->state;
List_Tab *tab;
Evas_Coord mw, cw, w;
Evas_Object *o;
evas_object_geometry_get(v->o_tabs, NULL, NULL, &w, NULL);
/* remove tabs for not active plugins */
e_box_freeze(v->o_tabs);
EINA_LIST_FOREACH(v->tabs, l, tab)
{
e_box_unpack(tab->o_tab);
evas_object_hide(tab->o_tab);
}
/* show/update tabs of active plugins */
EINA_LIST_FOREACH(s->cur_plugins, l, p)
{
EINA_LIST_FOREACH(v->tabs, ll, tab)
if (tab->plugin == p) break;
if (!tab)
{
tab = E_NEW(List_Tab, 1);
tab->plugin = p;
o = edje_object_add(v->evas);
e_theme_edje_object_set(o, "base/theme/everything",
"e/modules/everything/tab_item");
edje_object_part_text_set(o, "e.text.label", p->name);
tab->o_tab = o;
v->tabs = eina_list_append(v->tabs, tab);
}
o = tab->o_tab;
evas_object_show(o);
e_box_pack_end(v->o_tabs, o);
edje_object_size_min_calc(o, &cw, NULL);
edje_object_size_min_get(o, &mw, NULL);
e_box_pack_options_set(o, 1, 1, 1, 0, 0.0, 0.5,
(mw < cw ? cw : mw), 10,
(w ? w/3 : 150), 9999);
if (s->plugin == p)
edje_object_signal_emit(o, "e,state,selected", "e");
else
edje_object_signal_emit(o, "e,state,unselected", "e");
}
e_box_thaw(v->o_tabs);
if (s->plugin)
_list_tab_scroll_to(v, s->plugin);
}
static void
_list_tabs_clear(List_View *v)
{
Eina_List *l;
List_Tab *tab;
e_box_freeze(v->o_tabs);
EINA_LIST_FOREACH(v->tabs, l, tab)
{
e_box_unpack(tab->o_tab);
evas_object_hide(tab->o_tab);
}
e_box_thaw(v->o_tabs);
}
static void
_list_plugin_select(List_View *v, Evry_Plugin *p)
{
evry_plugin_select(v->state, p);
_list_tabs_update(v);
_list_tab_scroll_to(v, p);
_list_update(v);
}
static void
_list_plugin_next(List_View *v)
{
Eina_List *l;
Evry_Plugin *p = NULL;
const Evry_State *s = v->state;
if (!s->plugin) return;
l = eina_list_data_find_list(s->cur_plugins, s->plugin);
if (l && l->next)
p = l->next->data;
else if (s->plugin != s->cur_plugins->data)
p = s->cur_plugins->data;
if (p) _list_plugin_select(v, p);
}
static void
_list_plugin_next_by_name(List_View *v, const char *key)
{
Eina_List *l;
Evry_Plugin *p, *first = NULL, *next = NULL;
int found = 0;
const Evry_State *s = v->state;
if (!s->plugin) return;
EINA_LIST_FOREACH(s->cur_plugins, l, p)
{
if (p->name && (!strncasecmp(p->name, key, 1)))
{
if (!first) first = p;
if (found && !next)
next = p;
}
if (p == s->plugin) found = 1;
}
if (next)
p = next;
else if (first != s->plugin)
p = first;
else
p = NULL;
if (p) _list_plugin_select(v, p);
}
static void
_list_plugin_prev(List_View *v)
{
Eina_List *l;
Evry_Plugin *p = NULL;
const Evry_State *s = v->state;
if (!s->plugin) return;
l = eina_list_data_find_list(s->cur_plugins, s->plugin);
if (l && l->prev)
p = l->prev->data;
else
{
l = eina_list_last(s->cur_plugins);
if (s->plugin != l->data)
p = l->data;
}
if (p) _list_plugin_select(v, p);
}
static int
_update(const Evry_View *view)
{
List_View *v = (List_View *) view;
_list_update(v);
_list_tabs_update(v);
}
static void
_clear(const Evry_View *view)
{
List_View *v = (List_View *) view;
_list_clear(v);
_list_tabs_clear(v);
}
static int
_cb_key_down(const Evry_View *view, const Ecore_Event_Key *ev)
{
List_View *v = (List_View *) view;
const char *key = ev->key;
if (!strcmp(key, "Up"))
_list_item_prev(v);
else if (!strcmp(key, "Down"))
_list_item_next(v);
else if (!strcmp(key, "End"))
_list_item_last(v);
else if (!strcmp(key, "Home"))
_list_item_first(v);
else if (!strcmp(key, "Next"))
_list_plugin_next(v);
else if (!strcmp(key, "Prior"))
_list_plugin_prev(v);
else if ((!strcmp(key, "Left") && (ev->modifiers & ECORE_EVENT_MODIFIER_CTRL)))
_list_plugin_prev(v);
else if ((!strcmp(key, "Right") && (ev->modifiers & ECORE_EVENT_MODIFIER_CTRL)))
_list_plugin_prev(v);
else if (ev->modifiers & ECORE_EVENT_MODIFIER_CTRL)
_list_plugin_next_by_name(v, key);
else return 0;
return 1;
}
static Evry_View *
_create(const Evry_View *view, const Evry_State *s, const Evas_Object *swallow)
{
List_View *v;
Evas_Object *o;
v = E_NEW(List_View, 1);
v->view = *view;
v->evas = evas_object_evas_get(swallow);
v->swallow = swallow;
v->state = s;
o = e_box_add(v->evas);
e_box_orientation_set(o, 0);
e_box_homogenous_set(o, 1);
v->view.o_list = o;
v->o_list = o;
o = e_box_add(v->evas);
e_box_orientation_set(o, 1);
e_box_homogenous_set(o, 1);
v->view.o_bar = o;
v->o_tabs = o;
return &v->view;
}
static void
_destroy(const Evry_View *view)
{
List_View *v = (List_View *) view;
List_Tab *tab;
_clear(view);
EINA_LIST_FREE(v->tabs, tab)
{
evas_object_del(tab->o_tab);
E_FREE(tab);
}
evas_object_del(v->o_list);
evas_object_del(v->o_tabs);
E_FREE(v);
}
static Eina_Bool
_init(void)
{
view = E_NEW(Evry_View, 1);
view->id = view;
view->name = "List View";
view->create = &_create;
view->destroy = &_destroy;
view->update = &_update;
view->clear = &_clear;
view->cb_key_down = &_cb_key_down;
evry_view_register(view, 1);
return EINA_TRUE;
}
static void
_shutdown(void)
{
evry_view_unregister(view);
E_FREE(view);
}
EINA_MODULE_INIT(_init);
EINA_MODULE_SHUTDOWN(_shutdown);
/* static int
* _list_scroll_timer(void *data __UNUSED__)
* {
* if (v->scroll_animator)
* {
* double spd;
* spd = evry_conf->scroll_speed;
* v->scroll_align = (v->scroll_align * (1.0 - spd)) +
* (v->scroll_align_to * spd);
* return 1;
* }
* v->scroll_timer = NULL;
* return 0;
* }
*
* static int
* _list_animator(void *data __UNUSED__)
* {
* double da;
* Eina_Bool scroll_to = 1;
*
* da = v->scroll_align - v->scroll_align_to;
* if (da < 0.0) da = -da;
* if (da < 0.01)
* {
* v->scroll_align = v->scroll_align_to;
* scroll_to = 0;
* }
* e_box_align_set(v->o_list, 0.5, 1.0 - v->scroll_align);
* if (scroll_to) return 1;
* v->scroll_animator = NULL;
* return 0;
* } */
/* if (evry_conf->scroll_animate)
* {
* if (!v->scroll_timer)
* v->scroll_timer = ecore_timer_add(0.01, _list_scroll_timer, NULL);
* if (!v->scroll_animator)
* v->scroll_animator = ecore_animator_add(_list_animator, NULL);
* }
* else */