From 1503eb16eee660ec28aec47e8ba9f7c85bc25251 Mon Sep 17 00:00:00 2001 From: Daniel Juyung Seo Date: Thu, 18 Apr 2013 01:30:34 +0900 Subject: [PATCH] Revert "I removed it->generation, sd->generation, it->walking, sd->walking" This patch broke at least two stuffs: 1. item movement with key arrow now up/down arrow scrolls genlist now move to upper/lower item. 2. item del routine. item del callbacks are called twice LOL. this also broke apps that use elm_fileselector_button which uses elm_genlist internally. Once these are fixed and tested more, I will re-commit this. This reverts commit cea8e755dbf9b062bb1e6d7a89fbf4c590b8f6b3. --- legacy/elementary/src/lib/elm_genlist.c | 171 +++++++++++++++++-------- legacy/elementary/src/lib/elm_widget_genlist.h | 5 + 2 files changed, 126 insertions(+), 50 deletions(-) diff --git a/legacy/elementary/src/lib/elm_genlist.c b/legacy/elementary/src/lib/elm_genlist.c index 44f1e90..d9317c3 100644 --- a/legacy/elementary/src/lib/elm_genlist.c +++ b/legacy/elementary/src/lib/elm_genlist.c @@ -1075,7 +1075,8 @@ _decorate_all_item_realize(Elm_Gen_Item *it, const char *stacking; const char *stacking_even; - if ((!it) || (it->item->decorate_all_item_realized)) + if ((!it) || (it->item->decorate_all_item_realized) || + (it->generation < GL_IT(it)->wsd->generation)) return; it->deco_all_view = edje_object_add(evas_object_evas_get(WIDGET(it))); @@ -1465,6 +1466,7 @@ _item_realize(Elm_Gen_Item *it, char buf[1024]; int tsize = 20; + if (it->generation < GL_IT(it)->wsd->generation) return; if (it->realized) { if (it->item->order_num_in != in) @@ -1986,7 +1988,8 @@ _item_block_position(Item_Block *itb, EINA_LIST_FOREACH(itb->items, l, it) { - if (GL_IT(it)->wsd->reorder_it == it) + if (it->generation < GL_IT(it)->wsd->generation) continue; + else if (GL_IT(it)->wsd->reorder_it == it) continue; it->x = 0; @@ -2284,7 +2287,7 @@ _item_single_select_up(Elm_Genlist_Smart_Data *sd) if (!sd->selected) { prev = ELM_GEN_ITEM_FROM_INLIST(sd->items->last); - while (prev) + while ((prev) && (prev->generation < sd->generation)) prev = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(prev)->prev); } else @@ -2308,7 +2311,7 @@ _item_single_select_down(Elm_Genlist_Smart_Data *sd) if (!sd->selected) { next = ELM_GEN_ITEM_FROM_INLIST(sd->items); - while (next) + while ((next) && (next->generation < sd->generation)) next = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(next)->next); } else @@ -2692,6 +2695,7 @@ _item_highlight(Elm_Gen_Item *it) if ((GL_IT(it)->wsd->select_mode == ELM_OBJECT_SELECT_MODE_NONE) || (!GL_IT(it)->wsd->highlight) || + (it->generation < GL_IT(it)->wsd->generation) || (it->highlighted) || elm_widget_item_disabled_get(it) || (it->select_mode == ELM_OBJECT_SELECT_MODE_NONE) || (it->item->deco_it_view) || @@ -2717,7 +2721,7 @@ _item_highlight(Elm_Gen_Item *it) static void _item_unhighlight(Elm_Gen_Item *it) { - if (!it->highlighted) + if ((it->generation < GL_IT(it)->wsd->generation) || (!it->highlighted)) return; edje_object_signal_emit(VIEW(it), "elm,state,unselected", "elm"); @@ -2909,6 +2913,11 @@ static void _elm_genlist_item_del_not_serious(Elm_Gen_Item *it) { elm_widget_item_pre_notify_del(it); + it->generation = GL_IT(it)->wsd->generation - 1; /* This means that + * the item is + * deleted */ + + if (it->walking > 0) return; if (it->selected) GL_IT(it)->wsd->selected = @@ -2927,6 +2936,7 @@ _elm_genlist_item_del_serious(Elm_Gen_Item *it) eina_inlist_remove(GL_IT(it)->wsd->items, EINA_INLIST_GET(it)); if (it->tooltip.del_cb) it->tooltip.del_cb((void *)it->tooltip.data, WIDGET(it), it); + GL_IT(it)->wsd->walking -= it->walking; if (it->long_timer) { ecore_timer_del(it->long_timer); @@ -3003,6 +3013,7 @@ _item_del(Elm_Gen_Item *it) static void _item_unselect(Elm_Gen_Item *it) { + if ((it->generation < GL_IT(it)->wsd->generation)) return; _item_unhighlight(it); /* unhighlight the item first */ if (!it->selected) return; /* then check whether the item is selected */ @@ -4226,7 +4237,8 @@ _decorate_item_finished_signal_cb(void *data, te = evas_object_evas_get(obj); - if ((!it->realized) || (!it->item->deco_it_view)) return; + if ((it->generation < GL_IT(it)->wsd->generation) || (!it->realized) + || (!it->item->deco_it_view)) return; evas_event_freeze(te); it->item->nocache_once = EINA_FALSE; @@ -4363,6 +4375,7 @@ _item_block_recalc(Item_Block *itb, itb->num = in; EINA_LIST_FOREACH(itb->items, l, it) { + if (it->generation < GL_IT(it)->wsd->generation) continue; show_me |= it->item->show_me; if (!itb->realized) { @@ -4596,7 +4609,8 @@ _decorate_item_realize(Elm_Gen_Item *it) char buf[1024]; Evas_Object *obj = (GL_IT(it)->wsd)->obj; - if (it->item->deco_it_view) return; + if ((it->item->deco_it_view) || (it->generation < + GL_IT(it)->wsd->generation)) return; evas_event_freeze(evas_object_evas_get(obj)); it->item->deco_it_view = edje_object_add(evas_object_evas_get(WIDGET(it))); @@ -4736,6 +4750,8 @@ _elm_genlist_smart_add(Eo *obj, void *_pd, va_list *list EINA_UNUSED) elm_widget_can_focus_set(obj, EINA_TRUE); elm_widget_on_show_region_hook_set(obj, _show_region_hook, NULL); + priv->generation = 1; + if (!elm_layout_theme_set (obj, "genlist", "base", elm_widget_style_get(obj))) CRITICAL("Failed to set layout!"); @@ -4927,27 +4943,46 @@ _clear(Elm_Genlist_Smart_Data *sd) } static void -_elm_genlist_clear(Evas_Object *obj) +_elm_genlist_clear(Evas_Object *obj, + Eina_Bool standby) { - Elm_Gen_Item *it; + Eina_Inlist *next, *l; ELM_GENLIST_DATA_GET(obj, sd); + if (!standby) sd->generation++; + if (sd->state) { eina_inlist_sorted_state_free(sd->state); sd->state = NULL; } + if (sd->walking > 0) + { + sd->clear_me = EINA_TRUE; + return; + } + evas_event_freeze(evas_object_evas_get(sd->obj)); - // Do not use EINA_INLIST_FOREACH or EINA_INLIST_FOREACH_SAFE - // because sd->items can be modified inside elm_widget_item_del() - while (sd->items) + for (l = sd->items, next = l ? l->next : NULL; + l; + l = next, next = next ? next->next : NULL) { - it = EINA_INLIST_CONTAINER_GET(sd->items->last, Elm_Gen_Item); - it->item->nocache_once = EINA_TRUE; - elm_widget_item_del(it); + Elm_Gen_Item *it = ELM_GEN_ITEM_FROM_INLIST(l); + + if (it->generation < sd->generation) + { + Elm_Gen_Item *itn = NULL; + + if (next) itn = ELM_GEN_ITEM_FROM_INLIST(next); + if (itn) itn->walking++; /* prevent early death of subitem */ + it->del_cb(it); + elm_widget_item_free(it); + if (itn) itn->walking--; + } } + sd->clear_me = EINA_FALSE; sd->pan_changed = EINA_TRUE; if (!sd->queue) { @@ -4982,7 +5017,8 @@ _item_select(Elm_Gen_Item *it) { Evas_Object *obj = WIDGET(it); - if ((it->decorate_it_set) || + if ((it->generation < GL_IT(it)->wsd->generation) || + (it->decorate_it_set) || (it->select_mode == ELM_OBJECT_SELECT_MODE_NONE) || (GL_IT(it)->wsd->select_mode == ELM_OBJECT_SELECT_MODE_NONE)) return; @@ -4997,8 +5033,26 @@ _item_select(Elm_Gen_Item *it) return; evas_object_ref(obj); + it->walking++; + GL_IT(it)->wsd->walking++; if (it->func.func) it->func.func((void *)it->func.data, WIDGET(it), it); - evas_object_smart_callback_call(WIDGET(it), SIG_SELECTED, it); + if (it->generation == GL_IT(it)->wsd->generation) + evas_object_smart_callback_call(WIDGET(it), SIG_SELECTED, it); + + it->walking--; + GL_IT(it)->wsd->walking--; + if ((GL_IT(it)->wsd->clear_me) && (!GL_IT(it)->wsd->walking)) + _elm_genlist_clear(WIDGET(it), EINA_TRUE); + else + { + if ((!it->walking) && (it->generation < GL_IT(it)->wsd->generation)) + { + it->del_cb(it); + elm_widget_item_free(it); + } + else + GL_IT(it)->wsd->last_selected_item = (Elm_Object_Item *)it; + } evas_object_unref(obj); } @@ -5038,6 +5092,8 @@ _item_disable_hook(Elm_Object_Item *item) Evas_Object *obj; Elm_Gen_Item *it = (Elm_Gen_Item *)item; + if (it->generation < GL_IT(it)->wsd->generation) return; + if (it->selected) elm_genlist_item_selected_set(item, EINA_FALSE); @@ -5067,33 +5123,38 @@ _item_del_pre_hook(Elm_Object_Item *item) { Elm_Gen_Item *it = (Elm_Gen_Item *)item; - // FIXME: relative will be better to be fixed. it is too harsh. - if (it->item->rel) - it->item->rel->item->rel_revs = - eina_list_remove(it->item->rel->item->rel_revs, it); - if (it->item->rel_revs) - { - Elm_Gen_Item *tmp; - EINA_LIST_FREE(it->item->rel_revs, tmp) tmp->item->rel = NULL; - } - elm_genlist_item_subitems_clear(item); - if (GL_IT(it)->wsd->show_item == it) - GL_IT(it)->wsd->show_item = NULL; - _elm_genlist_item_del_not_serious(it); - if (it->item->block) + if (it->walking > 0) { - if (it->realized) _elm_genlist_item_unrealize(it, EINA_FALSE); - it->item->block->changed = EINA_TRUE; - if (GL_IT(it)->wsd->calc_job) - ecore_job_del(GL_IT(it)->wsd->calc_job); - GL_IT(it)->wsd->calc_job = - ecore_job_add(_calc_job, GL_IT(it)->wsd); - } - if (it->parent) - { - it->parent->item->items = - eina_list_remove(it->parent->item->items, it); - it->parent = NULL; + // FIXME: relative will be better to be fixed. it is too harsh. + if (it->item->rel) + it->item->rel->item->rel_revs = + eina_list_remove(it->item->rel->item->rel_revs, it); + if (it->item->rel_revs) + { + Elm_Gen_Item *tmp; + EINA_LIST_FREE(it->item->rel_revs, tmp) tmp->item->rel = NULL; + } + elm_genlist_item_subitems_clear(item); + if (GL_IT(it)->wsd->show_item == it) + GL_IT(it)->wsd->show_item = NULL; + + _elm_genlist_item_del_not_serious(it); + if (it->item->block) + { + if (it->realized) _elm_genlist_item_unrealize(it, EINA_FALSE); + it->item->block->changed = EINA_TRUE; + if (GL_IT(it)->wsd->calc_job) + ecore_job_del(GL_IT(it)->wsd->calc_job); + GL_IT(it)->wsd->calc_job = + ecore_job_add(_calc_job, GL_IT(it)->wsd); + } + if (it->parent) + { + it->parent->item->items = + eina_list_remove(it->parent->item->items, it); + it->parent = NULL; + } + return EINA_FALSE; } _item_del(it); @@ -5125,6 +5186,7 @@ _elm_genlist_item_new(Elm_Genlist_Smart_Data *sd, it = elm_widget_item_new(sd->obj, Elm_Gen_Item); if (!it) return NULL; + it->generation = sd->generation; it->itc = itc; elm_genlist_item_class_ref((Elm_Genlist_Item_Class *)itc); @@ -5579,7 +5641,7 @@ elm_genlist_clear(Evas_Object *obj) static void _clear_eo(Eo *obj, void *_pd EINA_UNUSED, va_list *list EINA_UNUSED) { - _elm_genlist_clear(obj); + _elm_genlist_clear(obj, EINA_FALSE); } EAPI void @@ -5784,7 +5846,7 @@ _first_item_get(Eo *obj EINA_UNUSED, void *_pd, va_list *list) if (!sd->items) return; it = ELM_GEN_ITEM_FROM_INLIST(sd->items); - while (it) + while ((it) && (it->generation < sd->generation)) it = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->next); *ret = (Elm_Object_Item *)it; @@ -5812,7 +5874,7 @@ _last_item_get(Eo *obj EINA_UNUSED, void *_pd, va_list *list) if (!sd->items) return; it = ELM_GEN_ITEM_FROM_INLIST(sd->items->last); - while (it) + while ((it) && (it->generation < sd->generation)) it = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->prev); *ret = (Elm_Object_Item *)it; @@ -5829,7 +5891,7 @@ elm_genlist_item_next_get(const Elm_Object_Item *item) while (it) { it = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->next); - if (it) break; + if ((it) && (it->generation == GL_IT(it)->wsd->generation)) break; } return (Elm_Object_Item *)it; @@ -5846,7 +5908,7 @@ elm_genlist_item_prev_get(const Elm_Object_Item *item) while (it) { it = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->prev); - if (it) break; + if ((it) && (it->generation == GL_IT(it)->wsd->generation)) break; } return (Elm_Object_Item *)it; @@ -5897,7 +5959,7 @@ elm_genlist_item_selected_set(Elm_Object_Item *item, ELM_GENLIST_ITEM_CHECK_OR_RETURN(item); sd = GL_IT(it)->wsd; - if (elm_widget_item_disabled_get(it)) + if ((it->generation < sd->generation) || elm_widget_item_disabled_get(it)) return; selected = !!selected; if (it->selected == selected) return; @@ -6073,6 +6135,7 @@ _elm_genlist_item_coordinates_calc(Elm_Object_Item *item, Elm_Gen_Item *it = (Elm_Gen_Item *)item; Evas_Coord gith = 0; + if (it->generation < GL_IT(it)->wsd->generation) return EINA_FALSE; if (!((GL_IT(it)->wsd->homogeneous) && (GL_IT(it)->wsd->mode == ELM_LIST_COMPRESS))) { @@ -6128,6 +6191,7 @@ elm_genlist_item_promote(Elm_Object_Item *item) ELM_GENLIST_ITEM_CHECK_OR_RETURN(item); + if (it->generation < GL_IT(it)->wsd->generation) return; _item_move_before (it, (Elm_Gen_Item *)elm_genlist_first_item_get(WIDGET(it))); } @@ -6138,6 +6202,7 @@ elm_genlist_item_demote(Elm_Object_Item *item) Elm_Gen_Item *it = (Elm_Gen_Item *)item; ELM_GENLIST_ITEM_CHECK_OR_RETURN(item); + if (it->generation < GL_IT(it)->wsd->generation) return; _item_move_after(it, (Elm_Gen_Item *)elm_genlist_last_item_get(WIDGET(it))); } @@ -6193,6 +6258,7 @@ elm_genlist_item_update(Elm_Object_Item *item) ELM_GENLIST_ITEM_CHECK_OR_RETURN(item); if (!it->item->block) return; + if (it->generation < GL_IT(it)->wsd->generation) return; it->item->mincalcd = EINA_FALSE; it->item->updateme = EINA_TRUE; it->item->block->updateme = EINA_TRUE; @@ -6210,6 +6276,7 @@ elm_genlist_item_fields_update(Elm_Object_Item *item, ELM_GENLIST_ITEM_CHECK_OR_RETURN(item); if (!it->item->block) return; + if (it->generation < GL_IT(it)->wsd->generation) return; if ((!itf) || (itf & ELM_GENLIST_ITEM_FIELD_TEXT)) { @@ -6271,6 +6338,7 @@ elm_genlist_item_item_class_update(Elm_Object_Item *item, if (!it->item->block) return; EINA_SAFETY_ON_NULL_RETURN(itc); + if (it->generation < GL_IT(it)->wsd->generation) return; it->itc = itc; it->item->nocache_once = EINA_TRUE; @@ -6310,6 +6378,7 @@ elm_genlist_item_item_class_get(const Elm_Object_Item *item) Elm_Gen_Item *it = (Elm_Gen_Item *)item; ELM_GENLIST_ITEM_CHECK_OR_RETURN(item, NULL); + if (it->generation < GL_IT(it)->wsd->generation) return NULL; return it->itc; } @@ -6779,7 +6848,8 @@ elm_genlist_item_decorate_mode_set(Elm_Object_Item *item, sd = GL_IT(it)->wsd; if (!decorate_it_type) return; - if (elm_widget_item_disabled_get(it)) return; + if ((it->generation < sd->generation) || + elm_widget_item_disabled_get(it)) return; if (sd->decorate_all_mode) return; if ((sd->mode_item == it) && @@ -7168,6 +7238,7 @@ elm_genlist_item_select_mode_set(Elm_Object_Item *item, ELM_GENLIST_ITEM_CHECK_OR_RETURN(item); if (!it) return; + if (it->generation < GL_IT(it)->wsd->generation) return; if (mode >= ELM_OBJECT_SELECT_MODE_MAX) return; if (it->select_mode != mode) diff --git a/legacy/elementary/src/lib/elm_widget_genlist.h b/legacy/elementary/src/lib/elm_widget_genlist.h index fadb71d..e27a74e 100644 --- a/legacy/elementary/src/lib/elm_widget_genlist.h +++ b/legacy/elementary/src/lib/elm_widget_genlist.h @@ -46,6 +46,7 @@ struct _Elm_Genlist_Smart_Data * repositioned */ Elm_Object_Item *last_selected_item; Ecore_Job *calc_job; + int walking; int item_width, item_height; int group_item_width, group_item_height; int minw, minh; @@ -111,6 +112,9 @@ struct _Elm_Genlist_Smart_Data * default. this can be changed by * elm_genlist_longpress_timeout_set() */ double longpress_timeout; + /* a generation of genlist. when genlist is cleared, this value + * will be increased and a new generation will start */ + int generation; Eina_Compare_Cb item_compare_cb; Eina_Compare_Cb item_compare_data_cb; @@ -156,6 +160,7 @@ struct _Elm_Genlist_Smart_Data Eina_Bool highlight : 1; /* a flag whether genlist is marked as to be cleared or not. if * this flag is true, genlist clear was already deferred. */ + Eina_Bool clear_me : 1; Eina_Bool h_bounce : 1; Eina_Bool v_bounce : 1; Eina_Bool bring_in : 1; /* a flag to -- 2.7.4