#include "e_mod_main.h" typedef struct _View View; typedef struct _Smart_Data Smart_Data; typedef struct _Item Item; #define SIZE_LIST 28 #define SIZE_DETAIL 36 struct _View { Evry_View view; Tab_View *tabs; const Evry_State *state; const Evry_Plugin *plugin; Evas *evas; Evas_Object *bg, *sframe, *span; int iw, ih; int zoom; int mode; int mode_prev; Eina_List *handlers; Eina_Bool hiding; }; /* smart object based on wallpaper module */ struct _Smart_Data { View *view; Eina_List *items; Item *cur_item; Ecore_Idle_Enterer *idle_enter; Evas_Coord x, y, w, h; Evas_Coord cx, cy, cw, ch; Evas_Coord sx, sy; double last_select; double scroll_align; double scroll_align_from; double scroll_align_to; double animator_start; Ecore_Animator *animator; int slide_offset; double slide; double slide_to; int sliding; int mouse_act; int mouse_x; int mouse_y; int mouse_button; Item *it_down; Eina_Bool place; }; struct _Item { Evry_Item *item; Evas_Object *obj; Evas_Coord x, y, w, h; Evas_Object *frame, *image, *thumb; Eina_Bool selected E_BITFIELD; Eina_Bool have_thumb E_BITFIELD; Eina_Bool do_thumb E_BITFIELD; Eina_Bool get_thumb E_BITFIELD; Eina_Bool showing E_BITFIELD; Eina_Bool visible E_BITFIELD; Eina_Bool changed E_BITFIELD; int pos; int max_w, max_h; }; static View *view = NULL; static void _view_clear(Evry_View *view); static void _pan_item_select(Evas_Object *obj, Item *it, int scroll); static void _animator_del(Evas_Object *obj); static Eina_Bool _animator(void *data); static void _cb_thumb_gen(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { Evas_Coord w, h; Item *it = data; if (!it->frame) return; e_icon_size_get(it->thumb, &w, &h); evas_object_size_hint_aspect_set(it->thumb, EVAS_ASPECT_CONTROL_BOTH, w, h); evas_object_size_hint_max_set(it->thumb, w, h); edje_object_part_unswallow(it->frame, it->image); edje_object_part_swallow(it->frame, "e.swallow.thumb", it->thumb); evas_object_show(it->thumb); edje_object_signal_emit(it->frame, "e,action,thumb,show_delayed", "e"); edje_object_message_signal_process(it->frame); it->have_thumb = EINA_TRUE; it->do_thumb = EINA_FALSE; if (it->image) evas_object_del(it->image); it->image = NULL; } static void _cb_preload(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { Item *it = data; if (!it->frame) return; printf("preload callback!!!!\n"); edje_object_part_swallow(it->frame, "e.swallow.icon", it->image); /* evas_object_show(it->image); */ } static int _check_item(const Evry_Item *it) { char *suffix; GET_FILE(file, it); if (!evry_file_path_get(file) || !file->mime) return 0; if (!strncmp(file->mime, "image/", 6)) return 1; if ((suffix = strrchr(it->label, '.'))) if (!strncmp(suffix, ".edj", 4)) return 1; return 0; } static void _item_down(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info) { Evas_Event_Mouse_Down *ev = event_info; Item *it = data; Smart_Data *sd = evas_object_smart_data_get(it->obj); const Evry_State *s; if (!sd) return; sd->mouse_act = 1; sd->it_down = it; sd->mouse_button = ev->button; s = sd->view->state; if ((ev->button == 1) && (ev->flags & EVAS_BUTTON_DOUBLE_CLICK)) { if (it != sd->cur_item) { evry_item_select(s, it->item); _pan_item_select(it->obj, it, 0); } if (it->item->browseable) evry_browse_item(it->item); else evry_plugin_action(s->selector->win, 1); } else { sd->mouse_x = ev->canvas.x; sd->mouse_y = ev->canvas.y; } } static void _item_up(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info) { Evas_Event_Mouse_Up *ev = event_info; Item *it = data; Smart_Data *sd = evas_object_smart_data_get(it->obj); const Evry_State *s; if (!sd) return; sd->mouse_x = 0; sd->mouse_y = 0; if (!sd->it_down) return; edje_object_signal_emit(sd->view->bg, "e,action,hide,into", "e"); edje_object_signal_emit(sd->view->bg, "e,action,hide,back", "e"); sd->it_down = NULL; s = sd->view->state; if (ev->button == 1) { if (!(ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) && (it != sd->cur_item)) { evry_item_select(s, it->item); _pan_item_select(it->obj, it, 0); } } else if (ev->button == 3) { evry_item_select(s, it->item); _pan_item_select(it->obj, it, 0); evry_plugin_action(s->selector->win, 0); } } static void _item_select(Item *it) { it->selected = EINA_TRUE; edje_object_signal_emit(it->frame, "e,state,selected", "e"); if (it->thumb) { if (strcmp(evas_object_type_get(it->thumb), "e_icon")) edje_object_signal_emit(it->thumb, "e,state,selected", "e"); else e_icon_selected_set(it->thumb, EINA_TRUE); } if (it->image) { if (strcmp(evas_object_type_get(it->image), "e_icon")) edje_object_signal_emit(it->image, "e,state,selected", "e"); else e_icon_selected_set(it->image, EINA_TRUE); } } static void _item_unselect(Item *it) { it->selected = EINA_FALSE; edje_object_signal_emit(it->frame, "e,state,unselected", "e"); if (it->thumb) { if (strcmp(evas_object_type_get(it->thumb), "e_icon")) edje_object_signal_emit(it->thumb, "e,state,unselected", "e"); else e_icon_selected_set(it->thumb, EINA_FALSE); } if (it->image) { if (strcmp(evas_object_type_get(it->image), "e_icon")) edje_object_signal_emit(it->image, "e,state,unselected", "e"); else e_icon_selected_set(it->image, EINA_FALSE); } } //static double _icon_time; static void _item_show(View *v, Item *it, Evas_Object *list) { if (it->visible) return; if (!it->frame) { it->frame = edje_object_add(v->evas); if (v->mode == VIEW_MODE_THUMB) { e_theme_edje_object_set(it->frame, "base/theme/modules/everything", "e/modules/everything/thumbview/item/thumb"); } else { e_theme_edje_object_set(it->frame, "base/theme/modules/everything", "e/modules/everything/thumbview/item/list"); if (v->mode == VIEW_MODE_DETAIL) edje_object_signal_emit(it->frame, "e,state,detail,show", "e"); } evas_object_event_callback_add(it->frame, EVAS_CALLBACK_MOUSE_DOWN, _item_down, it); evas_object_event_callback_add(it->frame, EVAS_CALLBACK_MOUSE_UP, _item_up, it); evas_object_smart_member_add(it->frame, list); evas_object_clip_set(it->frame, evas_object_clip_get(list)); if (it->item->selected) _item_select(it); if (it->item->marked) edje_object_signal_emit(it->frame, "e,state,marked", "e"); } edje_object_part_text_set(it->frame, "e.text.label", it->item->label); if (v->mode == VIEW_MODE_DETAIL && it->item->detail) edje_object_part_text_set(it->frame, "e.text.detail", it->item->detail); evas_object_show(it->frame); if (it->item->browseable) edje_object_signal_emit(it->frame, "e,state,browseable", "e"); if (!it->image && !it->have_thumb) { //double t = ecore_time_get(); it->image = evry_util_icon_get(it->item, v->evas); //_icon_time += ecore_time_get() - t; if (it->image) { if (it->max_w == 0) e_icon_size_get(it->image, &it->max_w, &it->max_h); if ((it->max_w > 0) && (it->max_h > 0)) evas_object_size_hint_max_set(it->image, it->max_w * 2, it->max_h * 2); else it->max_w = -1; if (0 && e_icon_preload_get(it->image) && !evas_object_visible_get(it->image)) { evas_object_smart_callback_add(it->image, "preloaded", _cb_preload, it); } else { edje_object_part_swallow(it->frame, "e.swallow.icon", it->image); evas_object_show(it->image); } } else it->have_thumb = EINA_TRUE; } if ((it->get_thumb) || (CHECK_TYPE(it->item, EVRY_TYPE_FILE) && _check_item(it->item))) { char *suffix; it->get_thumb = EINA_TRUE; it->thumb = e_thumb_icon_add(v->evas); GET_FILE(file, it->item); evas_object_smart_callback_add(it->thumb, "e_thumb_gen", _cb_thumb_gen, it); e_thumb_icon_size_set(it->thumb, it->w, it->h); if (it->item->icon && it->item->icon[0]) e_thumb_icon_file_set(it->thumb, it->item->icon, NULL); else if ((suffix = strrchr(file->path, '.')) && (!strncmp(suffix, ".edj", 4))) { e_thumb_icon_file_set(it->thumb, file->path, "e/desktop/background"); e_thumb_icon_size_set(it->thumb, 128, 80); } else e_thumb_icon_file_set(it->thumb, file->path, NULL); e_thumb_icon_begin(it->thumb); it->do_thumb = EINA_TRUE; } edje_object_signal_emit(it->frame, "e,action,thumb,show", "e"); it->visible = EINA_TRUE; } static void _item_hide(Item *it) { if (it->do_thumb) e_thumb_icon_end(it->thumb); if (it->thumb) evas_object_del(it->thumb); if (it->image) evas_object_del(it->image); if (it->frame) evas_object_del(it->frame); it->thumb = NULL; it->image = NULL; it->frame = NULL; it->have_thumb = EINA_FALSE; it->do_thumb = EINA_FALSE; it->visible = EINA_FALSE; } static int _place_items(Smart_Data *sd) { Eina_List *l; Item *it; int divider; Evas_Coord x = 0, y = 0, ww, hh, mw = 0, mh = 0; sd->place = EINA_FALSE; if (sd->view->mode == VIEW_MODE_LIST) { ww = sd->w; hh = SIZE_LIST; } else if (sd->view->mode == VIEW_MODE_DETAIL) { ww = sd->w; hh = SIZE_DETAIL; } else { int w, h; Evas_Object *o = edje_object_add(sd->view->evas); e_theme_edje_object_set(o, "base/theme/modules/everything", "e/modules/everything/thumbview/item/thumb"); edje_object_size_min_get(o, &w, &h); evas_object_del(o); if ((w > 0) && (h > 0)) { divider = sd->w / w; if (divider < 1) divider = 1; ww = w + (sd->w - divider * w) / divider; hh = ((double)h / (double)w * (double)ww); } else { if (sd->view->zoom == 0) ww = 96; else if (sd->view->zoom == 1) ww = 128; else ww = 192; divider = sd->w / ww; if (divider < 1) divider = 1; ww += (sd->w - divider * ww) / divider; divider = sd->h / ww; if (divider < 1) divider = 1; hh = ww + (sd->h - divider * ww) / divider; if (hh > ww) hh = ww + (sd->h - (divider + 1) * ww) / (divider + 1); } } EINA_LIST_FOREACH (sd->items, l, it) { it->x = x; it->y = y; it->w = ww; it->h = hh; if ((x + ww) > mw) mw = x + ww; if ((y + hh) > mh) mh = y + hh; x += ww; if (x <= (sd->w - ww)) continue; x = 0; y += hh; } if ((sd->view->mode == VIEW_MODE_LIST) || (sd->view->mode == VIEW_MODE_DETAIL)) mh += sd->h % hh; if ((mw != sd->cw) || (mh != sd->ch)) { sd->cw = mw; sd->ch = mh; if (sd->cx > (sd->cw - sd->w)) sd->cx = sd->cw - sd->w; if (sd->cy > (sd->ch - sd->h)) sd->cy = sd->ch - sd->h; if (sd->cx < 0) sd->cx = 0; if (sd->cy < 0) sd->cy = 0; return 1; } return 0; } static Eina_Bool _e_smart_reconfigure_do(void *data) { Evas_Object *obj = data; Smart_Data *sd = evas_object_smart_data_get(obj); Eina_List *l; Item *it; Evas_Coord xx, yy; double t; if (!sd) return ECORE_CALLBACK_CANCEL; if (sd->w < 1) { sd->idle_enter = NULL; return ECORE_CALLBACK_CANCEL; } if (sd->view->hiding) { sd->idle_enter = NULL; return ECORE_CALLBACK_CANCEL; } if (sd->cx > (sd->cw - sd->w)) sd->cx = sd->cw - sd->w; if (sd->cy > (sd->ch - sd->h)) sd->cy = sd->ch - sd->h; if (sd->cx < 0) sd->cx = 0; if (sd->cy < 0) sd->cy = 0; if (sd->place && _place_items(sd)) { evas_object_smart_callback_call(obj, "changed", NULL); return ECORE_CALLBACK_RENEW; } t = ecore_time_get(); EINA_LIST_FOREACH (sd->items, l, it) { xx = sd->x - sd->cx + it->x; yy = sd->y - sd->cy + it->y; if (E_INTERSECTS(xx, yy, it->w, it->h, 0, sd->y - it->h * 3, sd->x + sd->w, sd->y + sd->h + it->h * 6)) { if (!it->visible) _item_show(sd->view, it, obj); evas_object_move(it->frame, xx, yy); evas_object_resize(it->frame, it->w, it->h); } else if (it->visible) { _item_hide(it); } it->changed = EINA_FALSE; if (ecore_time_get() - t > 0.01) return ECORE_CALLBACK_RENEW; } sd->idle_enter = NULL; return ECORE_CALLBACK_CANCEL; } static void _e_smart_reconfigure(Evas_Object *obj) { Smart_Data *sd = evas_object_smart_data_get(obj); if (sd->idle_enter) return; sd->idle_enter = ecore_idle_enterer_before_add(_e_smart_reconfigure_do, obj); } static void _e_smart_add(Evas_Object *obj) { Smart_Data *sd = calloc(1, sizeof(Smart_Data)); if (!sd) return; sd->sx = sd->sy = -1; evas_object_smart_data_set(obj, sd); } static void _e_smart_del(Evas_Object *obj) { Smart_Data *sd = evas_object_smart_data_get(obj); if (sd->idle_enter) ecore_idle_enterer_del(sd->idle_enter); free(sd); evas_object_smart_data_set(obj, NULL); } static void _e_smart_move(Evas_Object *obj, Evas_Coord x, Evas_Coord y) { Smart_Data *sd = evas_object_smart_data_get(obj); sd->x = x; sd->y = y; _e_smart_reconfigure(obj); } static void _e_smart_resize(Evas_Object *obj, Evas_Coord w, Evas_Coord h) { Smart_Data *sd = evas_object_smart_data_get(obj); sd->w = w; sd->h = h; sd->place = EINA_TRUE; _e_smart_reconfigure(obj); /* evas_object_smart_callback_call(obj, "changed", NULL); */ } static void _e_smart_show(Evas_Object *obj EINA_UNUSED){} static void _e_smart_hide(Evas_Object *obj EINA_UNUSED){} static void _e_smart_color_set(Evas_Object *obj EINA_UNUSED, int r EINA_UNUSED, int g EINA_UNUSED, int b EINA_UNUSED, int a EINA_UNUSED){} static void _e_smart_clip_set(Evas_Object *obj EINA_UNUSED, Evas_Object *clip EINA_UNUSED){} static void _e_smart_clip_unset(Evas_Object *obj EINA_UNUSED){} static Evas_Object * _pan_add(Evas *evas) { static Evas_Smart *smart = NULL; static const Evas_Smart_Class sc = { "evry_items", EVAS_SMART_CLASS_VERSION, _e_smart_add, _e_smart_del, _e_smart_move, _e_smart_resize, _e_smart_show, _e_smart_hide, _e_smart_color_set, _e_smart_clip_set, _e_smart_clip_unset, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; if (smart == NULL) smart = evas_smart_class_new(&sc); return evas_object_smart_add(evas, smart); } static void _pan_set(Evas_Object *obj, Evas_Coord x, Evas_Coord y) { Smart_Data *sd = evas_object_smart_data_get(obj); if (x > (sd->cw - sd->w)) x = sd->cw - sd->w; if (y > (sd->ch - sd->h)) y = sd->ch - sd->h; if (x < 0) x = 0; if (y < 0) y = 0; if ((sd->cx == x) && (sd->cy == y)) return; sd->cx = x; sd->cy = y; _e_smart_reconfigure(obj); } static void _pan_get(Evas_Object *obj, Evas_Coord *x, Evas_Coord *y) { Smart_Data *sd = evas_object_smart_data_get(obj); if (x) *x = sd->cx; if (y) *y = sd->cy; } static void _pan_max_get(Evas_Object *obj, Evas_Coord *x, Evas_Coord *y) { Smart_Data *sd = evas_object_smart_data_get(obj); if (x) { if (sd->w < sd->cw) *x = sd->cw - sd->w; else *x = 0; } if (y) { if (sd->h < sd->ch) *y = sd->ch - sd->h; else *y = 0; } } static void _pan_child_size_get(Evas_Object *obj, Evas_Coord *w, Evas_Coord *h) { Smart_Data *sd = evas_object_smart_data_get(obj); if (w) *w = sd->cw; if (h) *h = sd->ch; } static void _pan_view_set(Evas_Object *obj, View *v) { Smart_Data *sd = evas_object_smart_data_get(obj); sd->view = v; } static Item * _pan_item_add(Evas_Object *obj, Evry_Item *item) { Smart_Data *sd = evas_object_smart_data_get(obj); Item *it; it = E_NEW(Item, 1); if (!it) return NULL; sd->items = eina_list_append(sd->items, it); it->obj = obj; it->item = item; it->changed = EINA_TRUE; evry_item_ref(item); sd->place = EINA_TRUE; _e_smart_reconfigure(obj); return it; } static void _pan_item_remove(Evas_Object *obj, Item *it) { Smart_Data *sd = evas_object_smart_data_get(obj); sd->items = eina_list_remove(sd->items, it); _item_hide(it); evry_item_free(it->item); sd->place = EINA_TRUE; _e_smart_reconfigure(obj); E_FREE(it); } static void _animator_del(Evas_Object *obj) { Smart_Data *sd = evas_object_smart_data_get(obj); sd->animator = NULL; } static Eina_Bool _animator(void *data) { Smart_Data *sd = evas_object_smart_data_get(data); if (!sd) return ECORE_CALLBACK_CANCEL; double da; double pos = (ecore_loop_time_get() - sd->animator_start) / 0.2; int wait = 0; if (pos < 0.0) pos = 0.0; else if (pos > 1.0) pos = 1.0; if (!EINA_DBL_EQ(sd->scroll_align, sd->scroll_align_to)) { sd->scroll_align = ((sd->scroll_align_from * (1.0 - pos)) + (sd->scroll_align_to * pos)); da = sd->scroll_align - sd->scroll_align_to; if (da < 0.0) da = -da; if (da < 0.02) sd->scroll_align = sd->scroll_align_to; else wait++; e_scrollframe_child_pos_set(sd->view->sframe, 0, sd->scroll_align); } sd->place = EINA_TRUE; if (wait) return ECORE_CALLBACK_RENEW; _animator_del(data); return ECORE_CALLBACK_CANCEL; } static int _child_region_get(Evas_Object *obj, Evas_Coord y, Evas_Coord h) { Smart_Data *sd = evas_object_smart_data_get(obj); Evas_Coord my = 0, ch = 0, py = 0, ny; py = sd->cy; ch = sd->ch; if (sd->h < sd->ch) my = sd->ch - sd->h; else my = 0; ny = py; if (y < py) ny = y; else if ((y + h) > (py + (ch - my))) { ny = y + h - (ch - my); if (ny > y) ny = y; } if (ny < 0) ny = 0; return ny; } static void _pan_item_select(Evas_Object *obj, Item *it, int scroll) { Smart_Data *sd = evas_object_smart_data_get(obj); double align = -1; if (sd->cur_item) { _item_unselect(sd->cur_item); sd->cur_item = NULL; } if (!it) return; _item_select(it); sd->cur_item = it; if (evry_conf->scroll_animate) { double now = ecore_time_get(); if (now - sd->last_select < 0.08) { sd->scroll_align = sd->scroll_align_to; scroll = 0; } sd->last_select = now; } else scroll = 0; if (sd->mouse_act) return; if (sd->view->mode == VIEW_MODE_THUMB) { if (sd->view->zoom < 2) align = _child_region_get(obj, it->y - it->h, it->h * 3); else align = _child_region_get(obj, it->y, it->h); } else { align = _child_region_get(obj, it->y - it->h * 2, it->h * 5); } if (scroll && evry_conf->scroll_animate) { sd->scroll_align_to = align; if ((!EINA_DBL_EQ(align, sd->cy)) && !sd->animator) { sd->animator_start = ecore_loop_time_get(); sd->scroll_align_from = sd->scroll_align; sd->animator = ecore_animator_add(_animator, obj); } } else { sd->scroll_align = sd->scroll_align_to; if (align >= 0) { sd->scroll_align = align; sd->scroll_align_to = align; e_scrollframe_child_pos_set(sd->view->sframe, 0, sd->scroll_align); } _animator_del(obj); } _e_smart_reconfigure(obj); } static void _clear_items(Evas_Object *obj) { Smart_Data *sd = evas_object_smart_data_get(obj); Eina_List *l; Item *it; _animator_del(obj); EINA_LIST_FOREACH (sd->items, l, it) _item_hide(it); } static void _view_clear(Evry_View *ev) { View *v = (View *)ev; Smart_Data *sd = evas_object_smart_data_get(v->span); Item *it; if (!sd) return; sd->mouse_x = 0; sd->mouse_y = 0; sd->mouse_act = 0; sd->it_down = NULL; _clear_items(v->span); if (sd->items) { EINA_LIST_FREE (sd->items, it) { evry_item_free(it->item); E_FREE(it); } } sd->place = EINA_TRUE; _e_smart_reconfigure(v->span); v->tabs->clear(v->tabs); } static int _sort_cb(const void *data1, const void *data2) { const Item *it1 = data1; const Item *it2 = data2; return it1->pos - it2->pos; } static int _update_frame(Evas_Object *obj) { Smart_Data *sd = evas_object_smart_data_get(obj); _animator_del(obj); sd->scroll_align = 0; e_scrollframe_child_pos_set(sd->view->sframe, 0, sd->scroll_align); if (sd->idle_enter) { ecore_idle_enterer_del(sd->idle_enter); sd->idle_enter = NULL; } sd->place = EINA_TRUE; _e_smart_reconfigure_do(obj); _pan_item_select(obj, sd->cur_item, 0); _e_smart_reconfigure(obj); return 0; } static int _view_update(Evry_View *ev) { GET_VIEW(v, ev); Smart_Data *sd = evas_object_smart_data_get(v->span); Item *v_it; Evry_Item *p_it; Eina_List *l, *ll, *v_remove = NULL, *v_items = NULL; int pos, last_pos, last_vis = 0, first_vis = 0; Eina_Bool update = EINA_FALSE; Evry_Plugin *p = v->state->plugin; if (!sd) return 0; sd->cur_item = NULL; sd->it_down = NULL; sd->mouse_act = 0; sd->mouse_x = 0; sd->mouse_y = 0; v->hiding = EINA_FALSE; if (!p) { _view_clear(ev); return 1; } if (p != v->plugin && (v->plugin || (v->mode == VIEW_MODE_NONE))) { if (p->config->view_mode != v->mode) { _clear_items(v->span); if (p->config->view_mode < 0) v->mode = evry_conf->view_mode; else v->mode = p->config->view_mode; } } /* go through current view items */ EINA_LIST_FOREACH (sd->items, l, v_it) { last_pos = v_it->pos; v_it->pos = 0; pos = 1; /* go through plugins current items */ EINA_LIST_FOREACH (p->items, ll, p_it) { if (v_it->item == p_it) { if (pos != last_pos) v_it->changed = EINA_TRUE; v_it->pos = pos; if (p_it->selected) { sd->cur_item = v_it; v_it->selected = EINA_TRUE; } else { if (v_it->selected && v_it->frame) edje_object_signal_emit (v_it->frame, "e,state,unselected", "e"); v_it->selected = EINA_FALSE; } break; } pos++; } if (v_it->visible) { if (!first_vis) first_vis = v_it->pos; last_vis = v_it->pos; } /* view item is in list of current items */ if (v_it->pos) { v_items = eina_list_append(v_items, v_it->item); if (v_it->visible && v_it->changed) update = EINA_TRUE; } else { if (v_it->visible) update = EINA_TRUE; v_remove = eina_list_append(v_remove, v_it); } } EINA_LIST_FREE (v_remove, v_it) _pan_item_remove(v->span, v_it); /* go through plugins current items */ pos = 1; EINA_LIST_FOREACH (p->items, l, p_it) { /* item is not already in view */ if (!eina_list_data_find_list(v_items, p_it)) { v_it = _pan_item_add(v->span, p_it); if (!v_it) continue; v_it->pos = pos; if (p_it == v->state->cur_item) { sd->cur_item = v_it; v_it->selected = EINA_TRUE; } if (pos > first_vis && pos < last_vis) update = EINA_TRUE; } pos++; } if (v_items) eina_list_free(v_items); sd->items = eina_list_sort(sd->items, -1, _sort_cb); if (update || !last_vis || v->plugin != p) { v->plugin = p; _update_frame(v->span); } v->tabs->update(v->tabs); return 0; } static int _cb_key_down(Evry_View *eview, const Ecore_Event_Key *ev) { View *v = (View *)eview; Smart_Data *sd = evas_object_smart_data_get(v->span); Eina_List *l = NULL, *ll; Item *it = NULL; const Evry_State *s; int slide; if (!sd || !(s = v->state) || !(s->plugin)) return 0; const char *key = ev->key; sd->mouse_act = 0; sd->mouse_x = 0; sd->mouse_y = 0; if ((ev->modifiers & ECORE_EVENT_MODIFIER_CTRL) && (!strcmp(key, "2"))) { if (v->mode == VIEW_MODE_LIST) v->mode = VIEW_MODE_DETAIL; else v->mode = VIEW_MODE_LIST; v->zoom = 0; _clear_items(v->span); _update_frame(v->span); goto end; } else if (((ev->modifiers & ECORE_EVENT_MODIFIER_CTRL) && (!strcmp(key, "3"))) || !strcmp(key, "XF86Forward")) { if (v->mode != VIEW_MODE_THUMB) { v->zoom = 0; v->mode = VIEW_MODE_THUMB; _clear_items(v->span); } else { v->zoom++; if (v->zoom > 2) v->zoom = 0; if (v->zoom == 2) _clear_items(v->span); } _update_frame(v->span); goto end; } else if (!strcmp(key, "XF86Back")) { if (v->mode == VIEW_MODE_LIST || v->mode == VIEW_MODE_DETAIL) { v->zoom = 0; v->mode = VIEW_MODE_THUMB; } else { v->mode = VIEW_MODE_DETAIL; } _clear_items(v->span); _update_frame(v->span); goto end; } if (((ev->modifiers & ECORE_EVENT_MODIFIER_SHIFT) || (ev->modifiers & ECORE_EVENT_MODIFIER_CTRL)) && (!strcmp(key, "Up"))) { if (!sd->items) goto end; it = sd->items->data; _pan_item_select(v->span, it, 1); evry_item_select(s, it->item); goto end; } else if (((ev->modifiers & ECORE_EVENT_MODIFIER_SHIFT) || (ev->modifiers & ECORE_EVENT_MODIFIER_CTRL)) && (!strcmp(key, "Down"))) { if (!sd->items) goto end; it = eina_list_last(sd->items)->data; _pan_item_select(v->span, it, 1); evry_item_select(s, it->item); goto end; } if ((ev->modifiers & ECORE_EVENT_MODIFIER_CTRL) && (!strcmp(key, "plus"))) { EINA_LIST_FOREACH (sd->items, ll, it) { if (!it->item->marked) { if (it->frame) edje_object_signal_emit(it->frame, "e,state,marked", "e"); evry_item_mark(s, it->item, 1); } } goto end; } else if ((ev->modifiers & ECORE_EVENT_MODIFIER_CTRL) && (!strcmp(key, "minus"))) { EINA_LIST_FOREACH (sd->items, ll, it) { if (it->item->marked) { if (it->frame) edje_object_signal_emit(it->frame, "e,state,unmarked", "e"); evry_item_mark(s, it->item, 0); } } goto end; } else if (!strcmp(key, "comma")) { if (!sd->cur_item) goto end; if (!sd->cur_item->item->marked) { edje_object_signal_emit(sd->cur_item->frame, "e,state,marked", "e"); evry_item_mark(s, sd->cur_item->item, 1); } else { edje_object_signal_emit(sd->cur_item->frame, "e,state,unmarked", "e"); evry_item_mark(s, sd->cur_item->item, 0); } if (v->mode == VIEW_MODE_THUMB) key = "Right"; else key = "Down"; } if ((slide = v->tabs->key_down(v->tabs, ev))) { /* _view_update(view, -slide); */ _view_update(eview); return 1; } if (sd->items) l = eina_list_data_find_list(sd->items, sd->cur_item); if (!l) l = sd->items; if (v->mode == VIEW_MODE_THUMB && !evry_conf->cycle_mode) { if (!strcmp(key, "Right")) { if (l && l->next) it = l->next->data; if (it) { _pan_item_select(v->span, it, 1); evry_item_select(s, it->item); } goto end; } else if (!strcmp(key, "Left")) { if (l && l->prev) it = l->prev->data; if (it) { _pan_item_select(v->span, it, 1); evry_item_select(s, it->item); } goto end; } } if (!strcmp(key, "Down")) { if (v->mode == VIEW_MODE_THUMB && (!evry_conf->cycle_mode) && (sd->cur_item)) { EINA_LIST_FOREACH (l, ll, it) { if (it->y > sd->cur_item->y && it->x >= sd->cur_item->x) break; } } if (!it && l && l->next) it = l->next->data; if (it) { _pan_item_select(v->span, it, 1); evry_item_select(s, it->item); } goto end; } else if (!strcmp(key, "Up")) { if (v->mode == VIEW_MODE_THUMB && (!evry_conf->cycle_mode) && (sd->cur_item)) { for (ll = l; ll; ll = ll->prev) { it = ll->data; if (it->y < sd->cur_item->y && it->x <= sd->cur_item->x) break; } } if (!it && l && l->prev) it = l->prev->data; if (it) { _pan_item_select(v->span, it, 1); evry_item_select(s, it->item); } goto end; } else if ((!strcmp(key, "Prior") || (!strcmp(key, "Next")))) { int cur = 0; int next = (!strcmp(key, "Next")); if (sd->cur_item) cur = sd->cur_item->y; EINA_LIST_FOREACH (sd->items, l, it) { if (next) { if (it->y >= cur + sd->h) break; } else { if (it->y + it->h >= cur - sd->h) break; } if (!l->next) break; } if (it) { _pan_item_select(v->span, it, 0); evry_item_select(s, it->item); } goto end; } else if (!ev->modifiers && !strcmp(key, "Return")) { if (v->mode == VIEW_MODE_THUMB) { if (!sd->cur_item) goto end; if (evry_browse_item(sd->cur_item->item)) goto end; } } return 0; end: return 1; } static Eina_Bool _cb_item_changed(void *data, int type EINA_UNUSED, void *event) { Evry_Event_Item_Changed *ev = event; View *v = data; Eina_List *l; Item *it; Smart_Data *sd = evas_object_smart_data_get(v->span); if (!sd) return ECORE_CALLBACK_PASS_ON; EINA_LIST_FOREACH (sd->items, l, it) if (it->item == ev->item) break; if (!it) return ECORE_CALLBACK_PASS_ON; if (ev->changed_selection) { _pan_item_select(v->span, it, 1); evry_item_select(v->state, ev->item); } if (!it->visible) return ECORE_CALLBACK_PASS_ON; edje_object_part_text_set(it->frame, "e.text.label", it->item->label); if (ev->changed_icon) { if (it->do_thumb) e_thumb_icon_end(it->thumb); if (it->thumb) evas_object_del(it->thumb); if (it->image) evas_object_del(it->image); it->thumb = NULL; it->image = NULL; it->have_thumb = EINA_FALSE; it->do_thumb = EINA_FALSE; } return ECORE_CALLBACK_PASS_ON; } static Eina_Bool _cb_action_performed(void *data, int type EINA_UNUSED, void *event) { Evry_Event_Action_Performed *ev = event; View *v = data; Eina_List *l; Item *it; Smart_Data *sd; sd = evas_object_smart_data_get(v->span); if (!sd) return ECORE_CALLBACK_PASS_ON; EINA_LIST_FOREACH (sd->items, l, it) { if ((it->item == ev->it1) || (it->item == ev->it2)) break; } if (it && it->visible) { evas_object_raise(it->frame); edje_object_signal_emit(it->frame, "e,action,go", "e"); } return ECORE_CALLBACK_PASS_ON; } static void _view_cb_mouse_wheel(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info) { Evas_Event_Mouse_Wheel *ev = event_info; Smart_Data *sd = evas_object_smart_data_get(obj); if (!sd) return; if (ev->z) { if (sd->cur_item) _item_select(sd->cur_item); sd->mouse_act = 1; } } // FIXME: 'drag into' make mouse input hang after some trials #if 0 static void _view_cb_mouse_down(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info) { Evas_Event_Mouse_Down *ev = event_info; Smart_Data *sd = evas_object_smart_data_get(data); if (!sd) return; sd->mouse_act = 1; sd->mouse_button = ev->button; sd->mouse_x = ev->canvas.x; sd->mouse_y = ev->canvas.y; } static void _view_cb_mouse_up(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { /* Evas_Event_Mouse_Up *ev = event_info; */ Smart_Data *sd = evas_object_smart_data_get(data); if (!sd) return; sd->mouse_x = 0; sd->mouse_y = 0; sd->mouse_button = 0; edje_object_signal_emit(sd->view->bg, "e,action,hide,into", "e"); edje_object_signal_emit(sd->view->bg, "e,action,hide,back", "e"); } #define SLIDE_RESISTANCE 80 static void _view_cb_mouse_move(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info) { Evas_Event_Mouse_Move *ev = event_info; Smart_Data *sd = evas_object_smart_data_get(data); Evry_Selector *sel; int diff_y, diff_x; if (!sd) return; if (!sd->mouse_x) goto end; sel = sd->view->state->selector; if (!sel || !sel->states) return; diff_x = abs(ev->cur.canvas.x - sd->mouse_x); diff_y = abs(ev->cur.canvas.y - sd->mouse_y); if (diff_y > 15 + (diff_x / 2)) { edje_object_signal_emit(sd->view->bg, "e,action,hide,into", "e"); edje_object_signal_emit(sd->view->bg, "e,action,hide,back", "e"); goto end; } if ((sel->states->next) || (sel != sel->win->selectors[0])) edje_object_signal_emit(sd->view->bg, "e,action,show,back", "e"); if (sd->it_down) { if ((sd->it_down->item->browseable) || (sel != sel->win->selectors[2])) edje_object_signal_emit(sd->view->bg, "e,action,show,into", "e"); if ((sd->cur_item != sd->it_down) && (diff_x > 10)) { evry_item_select(sd->view->state, sd->it_down->item); _pan_item_select(data, sd->it_down, 0); } } if (sd->mouse_button == 1) { if (ev->cur.canvas.x - sd->mouse_x > SLIDE_RESISTANCE) { sd->it_down = NULL; sd->mouse_x = 0; sd->mouse_y = 0; if (sel->states->next) evry_browse_back(sel); else evry_selectors_switch(sel->win, -1, EINA_TRUE); } else if ((sd->it_down && (sd->cur_item == sd->it_down)) && (sd->mouse_x - ev->cur.canvas.x > SLIDE_RESISTANCE)) { edje_object_signal_emit(sd->view->bg, "e,action,hide,into", "e"); edje_object_signal_emit(sd->view->bg, "e,action,hide,back", "e"); if (sd->it_down->item->browseable) { evry_browse_item(sd->it_down->item); } else { evry_selectors_switch(sel->win, 1, EINA_TRUE); } sd->it_down = NULL; sd->mouse_x = 0; sd->mouse_y = 0; } } return; end: sd->it_down = NULL; sd->mouse_x = 0; sd->mouse_y = 0; } #endif static void _cb_list_hide(void *data, Evas_Object *obj EINA_UNUSED, const char *emission EINA_UNUSED, const char *source EINA_UNUSED) { View *v = data; v->hiding = EINA_TRUE; } static void _cb_list_show(void *data, Evas_Object *obj EINA_UNUSED, const char *emission EINA_UNUSED, const char *source EINA_UNUSED) { View *v = data; v->hiding = EINA_FALSE; } static Evry_View * _view_create(Evry_View *ev, const Evry_State *s, Evas_Object *swallow) { GET_VIEW(parent, ev); View *v; Ecore_Event_Handler *h; v = E_NEW(View, 1); v->view = *ev; v->state = s; v->evas = evas_object_evas_get(swallow); if (s->plugin) { if ((s->selector->states->next) && ((s->plugin->config->view_mode < 0) || (!strcmp(s->plugin->name, N_("All"))))) v->mode = parent->mode; else if (s->plugin->config->view_mode >= 0) v->mode = s->plugin->config->view_mode; else v->mode = evry_conf->view_mode; } else { if (s->selector->states->next) v->mode = parent->mode; else v->mode = evry_conf->view_mode; } v->plugin = s->plugin; v->mode_prev = v->mode; v->zoom = parent->zoom; v->bg = edje_object_add(v->evas); e_theme_edje_object_set(v->bg, "base/theme/modules/everything", "e/modules/everything/thumbview/main/window"); // scrolled thumbs v->span = _pan_add(v->evas); _pan_view_set(v->span, v); evas_object_event_callback_add(v->span, EVAS_CALLBACK_MOUSE_WHEEL, _view_cb_mouse_wheel, NULL); #if 0 evas_object_event_callback_add(v->bg, EVAS_CALLBACK_MOUSE_MOVE, _view_cb_mouse_move, v->span); evas_object_event_callback_add(v->bg, EVAS_CALLBACK_MOUSE_DOWN, _view_cb_mouse_down, v->span); evas_object_event_callback_add(v->bg, EVAS_CALLBACK_MOUSE_UP, _view_cb_mouse_up, v->span); #endif // the scrollframe holding the scrolled thumbs v->sframe = e_scrollframe_add(v->evas); e_scrollframe_custom_theme_set(v->sframe, "base/theme/modules/everything", "e/modules/everything/thumbview/main/scrollframe"); e_scrollframe_thumbscroll_force(v->sframe, 1); e_scrollframe_extern_pan_set(v->sframe, v->span, _pan_set, _pan_get, _pan_max_get, _pan_child_size_get); edje_object_part_swallow(v->bg, "e.swallow.list", v->sframe); evas_object_show(v->sframe); evas_object_show(v->span); v->tabs = evry_tab_view_new(EVRY_VIEW(v), v->state, v->bg); EVRY_VIEW(v)->o_list = v->bg; EVRY_VIEW(v)->o_bar = v->tabs->o_tabs; h = evry_event_handler_add(EVRY_EVENT_ITEM_CHANGED, _cb_item_changed, v); v->handlers = eina_list_append(v->handlers, h); h = evry_event_handler_add(EVRY_EVENT_ACTION_PERFORMED, _cb_action_performed, v); v->handlers = eina_list_append(v->handlers, h); edje_object_signal_callback_add(v->bg, "e,action,hide,list", "e", _cb_list_hide, v); edje_object_signal_callback_add(v->bg, "e,action,show,list", "e", _cb_list_show, v); return EVRY_VIEW(v); } static void _view_destroy(Evry_View *ev) { Ecore_Event_Handler *h; GET_VIEW(v, ev); _view_clear(ev); evas_object_del(v->span); evas_object_del(v->bg); evas_object_del(v->sframe); evry_tab_view_free(v->tabs); EINA_LIST_FREE (v->handlers, h) ecore_event_handler_del(h); E_FREE(v); } Eina_Bool evry_view_init(void) { if (!evry_api_version_check(EVRY_API_VERSION)) return EINA_FALSE; View *v = E_NEW(View, 1); v->view.id = EVRY_VIEW(v); v->view.name = "Icon View"; v->view.create = &_view_create; v->view.destroy = &_view_destroy; v->view.update = &_view_update; v->view.clear = &_view_clear; v->view.cb_key_down = &_cb_key_down; v->mode = VIEW_MODE_NONE; evry_view_register(EVRY_VIEW(v), 1); view = v; return EINA_TRUE; } void evry_view_shutdown(void) { evry_view_unregister(EVRY_VIEW(view)); E_FREE(view); }