From 3c9a46372efe03f6f90488342d999aad02e0036d Mon Sep 17 00:00:00 2001 From: Cedric Bail Date: Sun, 15 Sep 2019 12:50:27 -0700 Subject: [PATCH] elementary: add an interface for asynchronous multi selection. This interface is currently focusing on being use by widget like Efl.Ui.Collection_View or Efl.Ui.Select_Model. I have decided that it should not be available along with Efl.Ui.Multi_Selectable. Differential Revision: https://phab.enlightenment.org/D9957 --- src/lib/elementary/Efl_Ui.h | 1 + src/lib/elementary/efl_ui.eot | 8 + .../elementary/efl_ui_collection_events.eo | 2 +- src/lib/elementary/efl_ui_multi_selectable.eo | 8 +- .../efl_ui_multi_selectable_async.eo | 63 ++++ src/lib/elementary/efl_ui_select_model.c | 348 ++++++++++++++++-- src/lib/elementary/efl_ui_select_model.eo | 36 +- src/lib/elementary/meson.build | 1 + .../elementary/efl_ui_test_select_model.c | 4 +- 9 files changed, 408 insertions(+), 63 deletions(-) create mode 100644 src/lib/elementary/efl_ui_multi_selectable_async.eo diff --git a/src/lib/elementary/Efl_Ui.h b/src/lib/elementary/Efl_Ui.h index 53c10adfcf..2c899fa20c 100644 --- a/src/lib/elementary/Efl_Ui.h +++ b/src/lib/elementary/Efl_Ui.h @@ -326,6 +326,7 @@ typedef Eo Efl_Ui_Spotlight_Indicator; # include # include # include +# include # include # include "efl_ui_list_view_types.eot.h" diff --git a/src/lib/elementary/efl_ui.eot b/src/lib/elementary/efl_ui.eot index 4e665113f6..b397b27094 100644 --- a/src/lib/elementary/efl_ui.eot +++ b/src/lib/elementary/efl_ui.eot @@ -96,5 +96,13 @@ enum @beta Efl.Ui.Widget_Orientation_Mode not change according to the window or screen orientation.]] } +enum @beta Efl.Ui.Select_Mode { + [[Type of multi selectable object.]] + single, [[Only single child is selected. If a child is selected, + previous selected child will be unselected.]] + multi, [[Allow multiple selection of children.]] + none [[No child can be selected at all.]] +} + /* Types for A11Y (internal/beta API) */ type @beta @extern Efl.Access.Action_Data: __undefined_type; [[Internal struct for accesssibility.]] diff --git a/src/lib/elementary/efl_ui_collection_events.eo b/src/lib/elementary/efl_ui_collection_events.eo index 653172564b..9ef6a991df 100644 --- a/src/lib/elementary/efl_ui_collection_events.eo +++ b/src/lib/elementary/efl_ui_collection_events.eo @@ -1,6 +1,6 @@ interface @beta Efl.Ui.Collection_Events { - [[Shared sets of events between @Efl.Ui.Collection and @Efl.Ui.Collection_View.]] + [[Shared sets of events between @Efl.Ui.Collection and Efl.Ui.Collection_View.]] event_prefix: efl_ui; events { item,pressed : Efl.Ui.Item; [[A $press event occurred over an item.]] diff --git a/src/lib/elementary/efl_ui_multi_selectable.eo b/src/lib/elementary/efl_ui_multi_selectable.eo index 9b581357a1..a3806c1608 100644 --- a/src/lib/elementary/efl_ui_multi_selectable.eo +++ b/src/lib/elementary/efl_ui_multi_selectable.eo @@ -1,10 +1,4 @@ -enum @beta Efl.Ui.Select_Mode { - [[Type of multi selectable object.]] - single, [[Only single child is selected. If a child is selected, - previous selected child will be unselected.]] - multi, [[Allow multiple selection of children.]] - none [[No child can be selected at all.]] -} +import efl_ui; interface @beta Efl.Ui.Multi_Selectable extends Efl.Ui.Single_Selectable { diff --git a/src/lib/elementary/efl_ui_multi_selectable_async.eo b/src/lib/elementary/efl_ui_multi_selectable_async.eo new file mode 100644 index 0000000000..6f4ed14abe --- /dev/null +++ b/src/lib/elementary/efl_ui_multi_selectable_async.eo @@ -0,0 +1,63 @@ +import efl_ui; + +interface @beta Efl.Ui.Multi_Selectable_Async extends Efl.Ui.Single_Selectable +{ + [[Interface for getting access to a range of selected items for widgets that provide them asynchronously. + + The implementor of this interface provides the possibility to select multiple @Efl.Ui.Selectable. + If not, only @Efl.Ui.Single_Selectable should be implemented. + A widget can only provide either this interface or @Efl.Ui.Multi_Selectable, but not both.]] + methods + { + @property select_mode { + [[The mode type for children selection.]] + set {} + get {} + values { + mode: Efl.Ui.Select_Mode; [[Type of selection of children]] + } + } + selected_iterator_new { + [[Gets an iterator of all the selected child of this model. + ]] + return: iterator @move @no_unused; [[The iterator gives indices of selected children. + It is valid until any change is made on the model.]] + } + unselected_iterator_new { + [[Gets an iterator of all the child of this model that are not selected. + ]] + return: iterator @move @no_unused; [[The iterator gives indices of unselected children. + It is valid until any change is made on the model.]] + } + select_range { + [[Select a range of @Efl.Ui.Selectable. + + This will select the range of selectables from $a to $b or from $b to $a depending on which one comes first. + If $a or $b are not in the range the widget, an error is returned, and no change is applied. + Both of the passed values will also be selected. + ]] + params { + a : uint64; [[One side of the range.]] + b : uint64; [[The other side of the range.]] + } + } + unselect_range { + [[Unselect a range of @Efl.Ui.Selectable. + + This will unselect the range of selectables from $a to $b or from $b to $a depending on which one comes first. + If $a or $b are not in the range of the widget, an error is returned, and no change is applied. + Both of the passed values will also be unselected. + ]] + params { + a : uint64; [[One side of the range.]] + b : uint64; [[The other side of the range.]] + } + } + select_all { + [[Select all @Efl.Ui.Selectable]] + } + unselect_all { + [[Unselect all @Efl.Ui.Selectable]] + } + } +} diff --git a/src/lib/elementary/efl_ui_select_model.c b/src/lib/elementary/efl_ui_select_model.c index e862b569e0..93db5b3a6f 100644 --- a/src/lib/elementary/efl_ui_select_model.c +++ b/src/lib/elementary/efl_ui_select_model.c @@ -2,6 +2,10 @@ # include #endif +// Note: we do not rely on reflection here to implement select as it require to asynchronously acces +// children. Could be done differently by implementing the children select in the parent instead of +// in the children. For later optimization. + #include #include "elm_priv.h" @@ -13,15 +17,21 @@ typedef struct _Efl_Ui_Select_Model_Data Efl_Ui_Select_Model_Data; struct _Efl_Ui_Select_Model_Data { Efl_Ui_Select_Model_Data *parent; + + Eina_Future *pending_selection_event; + + Efl_Ui_Select_Model *fallback_model; + Efl_Ui_Select_Model *last_model; unsigned long last; - Eina_Bool single_selection : 1; + Efl_Ui_Select_Mode selection; + Eina_Bool none : 1; }; static Eo* _efl_ui_select_model_efl_object_constructor(Eo *obj, - Efl_Ui_Select_Model_Data *pd EINA_UNUSED) + Efl_Ui_Select_Model_Data *pd) { Eo *parent; @@ -29,7 +39,9 @@ _efl_ui_select_model_efl_object_constructor(Eo *obj, efl_boolean_model_boolean_add(obj, "selected", EINA_FALSE); - pd->last = -1; + efl_replace(&pd->last_model, NULL); + pd->last = 0; + pd->none = EINA_TRUE; parent = efl_parent_get(obj); if (efl_isa(parent, EFL_UI_SELECT_MODEL_CLASS)) @@ -38,10 +50,61 @@ _efl_ui_select_model_efl_object_constructor(Eo *obj, return obj; } +static void +_efl_ui_select_model_efl_object_invalidate(Eo *obj, + Efl_Ui_Select_Model_Data *pd) +{ + efl_replace(&pd->fallback_model, NULL); + efl_replace(&pd->last_model, NULL); + pd->none = EINA_TRUE; + + efl_invalidate(efl_super(obj, EFL_UI_SELECT_MODEL_CLASS)); +} + +static void +_efl_ui_select_model_fallback(Efl_Ui_Select_Model_Data *pd) +{ + Eina_Value selected; + + if (!pd->parent) return; + if (!pd->parent->none) return; + if (!pd->parent->fallback_model) return; + // I think it only make sense to trigger the fallback on single mode + if (pd->parent->selection != EFL_UI_SELECT_MODE_SINGLE) return; + + selected = eina_value_bool_init(EINA_TRUE); + efl_model_property_set(pd->parent->fallback_model, "self.selected", &selected); + eina_value_flush(&selected); +} + +static Eina_Value +_select_notification_cb(Eo *o, void *data EINA_UNUSED, const Eina_Value v) +{ + Efl_Ui_Select_Model_Data *pd = efl_data_scope_get(o, EFL_UI_SELECT_MODEL_CLASS); + + efl_event_callback_call(o, EFL_UI_SINGLE_SELECTABLE_EVENT_SELECTION_CHANGED, NULL); + + pd->pending_selection_event = NULL; + + return v; +} + +static void +_efl_ui_select_model_selection_notification(Eo *parent, Efl_Ui_Select_Model_Data *pd) +{ + if (!pd) return; + if (pd->pending_selection_event) return; + + pd->pending_selection_event = efl_future_then(parent, + efl_loop_job(efl_loop_get(parent)), + .success = _select_notification_cb); +} + static Eina_Value _commit_change(Eo *child, void *data EINA_UNUSED, const Eina_Value v) { Efl_Ui_Select_Model_Data *pd; + Eo *parent; Eina_Value *selected = NULL; Eina_Bool selflag = EINA_FALSE; @@ -50,7 +113,8 @@ _commit_change(Eo *child, void *data EINA_UNUSED, const Eina_Value v) selected = efl_model_property_get(child, "selected"); - pd = efl_data_scope_get(efl_parent_get(child), EFL_UI_SELECT_MODEL_CLASS); + parent = efl_parent_get(child); + pd = efl_data_scope_get(parent, EFL_UI_SELECT_MODEL_CLASS); if (!pd) goto on_error; eina_value_bool_get(selected, &selflag); @@ -59,6 +123,7 @@ _commit_change(Eo *child, void *data EINA_UNUSED, const Eina_Value v) // select case pd->none = EINA_FALSE; pd->last = efl_composite_model_index_get(child); + efl_replace(&pd->last_model, child); efl_event_callback_call(child, EFL_UI_SELECT_MODEL_EVENT_SELECTED, child); } else @@ -69,11 +134,17 @@ _commit_change(Eo *child, void *data EINA_UNUSED, const Eina_Value v) last = efl_composite_model_index_get(child); if (pd->last == last) { + efl_replace(&pd->last_model, NULL); pd->last = 0; pd->none = EINA_TRUE; + + // Just in case we need to refill the fallback + _efl_ui_select_model_fallback(pd); } efl_event_callback_call(child, EFL_UI_SELECT_MODEL_EVENT_UNSELECTED, child); } + _efl_ui_select_model_selection_notification(parent, pd); + efl_model_properties_changed(child, "self.selected"); on_error: eina_value_free(selected); @@ -239,7 +310,7 @@ _untangle_free(void *data, static Eina_Iterator * _efl_ui_select_model_efl_model_properties_get(const Eo *obj, - Efl_Ui_Select_Model_Data *pd EINA_UNUSED) + Efl_Ui_Select_Model_Data *pd EINA_UNUSED) { EFL_COMPOSITE_MODEL_PROPERTIES_SUPER(props, obj, EFL_UI_SELECT_MODEL_CLASS, @@ -250,22 +321,23 @@ _efl_ui_select_model_efl_model_properties_get(const Eo *obj, static Eina_Future * _efl_ui_select_model_efl_model_property_set(Eo *obj, - Efl_Ui_Select_Model_Data *pd, - const char *property, Eina_Value *value) + Efl_Ui_Select_Model_Data *pd, + const char *property, Eina_Value *value) { Eina_Value vf = EINA_VALUE_EMPTY; if (eina_streq("single_selection", property)) { - Eina_Bool single_selection = pd->single_selection; + Eina_Bool single_selection = pd->selection == EFL_UI_SELECT_MODE_SINGLE; + Eina_Bool new_selection; Eina_Bool changed; - vf = eina_value_bool_init(single_selection); - eina_value_convert(value, &vf); - eina_value_bool_get(&vf, &single_selection); + if (!eina_value_bool_get(value, &new_selection)) + return efl_loop_future_rejected(obj, EINVAL); - changed = (!pd->single_selection != !single_selection); - pd->single_selection = !!single_selection; + changed = (!!new_selection != !!single_selection); + if (new_selection) pd->selection = EFL_UI_SELECT_MODE_SINGLE; + else pd->selection = EFL_UI_SELECT_MODE_MULTI; if (changed) efl_model_properties_changed(obj, "single_selection"); @@ -276,6 +348,9 @@ _efl_ui_select_model_efl_model_property_set(Eo *obj, { unsigned long l = 0; + if (pd->selection == EFL_UI_SELECT_MODE_NONE) + return efl_loop_future_rejected(obj, EFL_MODEL_ERROR_READ_ONLY); + if (!eina_value_ulong_convert(value, &l)) return efl_loop_future_rejected(obj, EFL_MODEL_ERROR_INCORRECT_VALUE); @@ -293,6 +368,9 @@ _efl_ui_select_model_efl_model_property_set(Eo *obj, Eina_Value *prev; Eina_Future *chain; + if (pd->parent->selection == EFL_UI_SELECT_MODE_NONE) + return efl_loop_future_rejected(obj, EFL_MODEL_ERROR_INCORRECT_VALUE); + prev = efl_model_property_get(efl_super(obj, EFL_UI_SELECT_MODEL_CLASS), "selected"); success = eina_value_bool_get(prev, &prevflag); success &= eina_value_bool_convert(value, &newflag); @@ -303,7 +381,7 @@ _efl_ui_select_model_efl_model_property_set(Eo *obj, if (newflag == prevflag) return efl_loop_future_resolved(obj, eina_value_bool_init(newflag)); - single_selection = pd->parent->single_selection; + single_selection = !!(pd->parent->selection == EFL_UI_SELECT_MODE_SINGLE); // First store the new value in the boolean model we inherit from chain = efl_model_property_set(efl_super(obj, EFL_UI_SELECT_MODEL_CLASS), @@ -321,7 +399,12 @@ _efl_ui_select_model_efl_model_property_set(Eo *obj, i = efl_composite_model_index_get(obj); if (pd->parent->last == i && !newflag) - pd->parent->none = EINA_TRUE; + { + efl_replace(&pd->last_model, NULL); + pd->parent->none = EINA_TRUE; + + _efl_ui_select_model_fallback(pd); + } } else { @@ -362,7 +445,7 @@ static Eina_Value * _efl_ui_select_model_efl_model_property_get(const Eo *obj, Efl_Ui_Select_Model_Data *pd, const char *property) { if (eina_streq("single_selection", property)) - return eina_value_bool_new(pd->single_selection); + return eina_value_bool_new(pd->selection == EFL_UI_SELECT_MODE_SINGLE); // Last selected child if (eina_streq("child.selected", property)) { @@ -374,34 +457,239 @@ _efl_ui_select_model_efl_model_property_get(const Eo *obj, Efl_Ui_Select_Model_D // Redirect to are we ourself selected if (pd->parent && eina_streq("self.selected", property)) { + if (pd->parent->selection == EFL_UI_SELECT_MODE_NONE) + return eina_value_bool_new(EINA_FALSE); return efl_model_property_get(efl_super(obj, EFL_UI_SELECT_MODEL_CLASS), "selected"); } return efl_model_property_get(efl_super(obj, EFL_UI_SELECT_MODEL_CLASS), property); } -static void -_efl_ui_select_model_single_selection_set(Eo *obj EINA_UNUSED, Efl_Ui_Select_Model_Data *pd, Eina_Bool enable) -{ - pd->single_selection = enable; -} - -static Eina_Bool -_efl_ui_select_model_single_selection_get(const Eo *obj EINA_UNUSED, Efl_Ui_Select_Model_Data *pd) -{ - return pd->single_selection; -} - static Eina_Iterator * -_efl_ui_select_model_selected_get(Eo *obj, Efl_Ui_Select_Model_Data *pd EINA_UNUSED) +_efl_ui_select_model_efl_ui_multi_selectable_async_selected_iterator_new(Eo *obj, + Efl_Ui_Select_Model_Data *pd) { + if (pd->parent && pd->parent->selection == EFL_UI_SELECT_MODE_NONE) + return eina_list_iterator_new(NULL); // Quick hack to get a valid empty iterator return efl_boolean_model_boolean_iterator_get(obj, "selected", EINA_TRUE); } static Eina_Iterator * -_efl_ui_select_model_unselected_get(Eo *obj, Efl_Ui_Select_Model_Data *pd EINA_UNUSED) +_efl_ui_select_model_efl_ui_multi_selectable_async_unselected_iterator_new(Eo *obj, + Efl_Ui_Select_Model_Data *pd EINA_UNUSED) { return efl_boolean_model_boolean_iterator_get(obj, "selected", EINA_FALSE); } +static Efl_Ui_Selectable * +_efl_ui_select_model_efl_ui_single_selectable_last_selected_get(const Eo *obj EINA_UNUSED, + Efl_Ui_Select_Model_Data *pd) +{ + return pd->last_model; +} + +static void +_efl_ui_select_model_efl_ui_multi_selectable_async_select_mode_set(Eo *obj, + Efl_Ui_Select_Model_Data *pd, + Efl_Ui_Select_Mode mode) +{ + switch (mode) + { + case EFL_UI_SELECT_MODE_SINGLE: + mode = EFL_UI_SELECT_MODE_SINGLE; + if (pd->selection == EFL_UI_SELECT_MODE_MULTI) + efl_ui_multi_selectable_async_unselect_all(obj); + break; + case EFL_UI_SELECT_MODE_NONE: + if (pd->selection == EFL_UI_SELECT_MODE_MULTI) + efl_ui_multi_selectable_async_unselect_all(obj); + else if (pd->last_model) + { + Eina_Value unselect = eina_value_bool_init(EINA_FALSE); + + efl_model_property_set(pd->last_model, "self.selected", &unselect); + eina_value_flush(&unselect); + } + break; + case EFL_UI_SELECT_MODE_MULTI: + break; + default: + ERR("Unknown select mode passed to %s: %i.", efl_debug_name_get(obj), mode); + return; + } + + pd->selection = mode; + efl_model_properties_changed(obj, "single_selection", "child.selected"); +} + +static Efl_Ui_Select_Mode +_efl_ui_select_model_efl_ui_multi_selectable_async_select_mode_get(const Eo *obj EINA_UNUSED, + Efl_Ui_Select_Model_Data *pd) +{ + return pd->selection; +} + +static void +_efl_ui_select_model_efl_ui_multi_selectable_async_select_all(Eo *obj, + Efl_Ui_Select_Model_Data *pd EINA_UNUSED) +{ + unsigned long count, i; + + // Not the fastest way to implement it, but will reuse more code and be easier as a v1. + // It also make it not very async which could be noticable. + count = efl_model_children_count_get(obj); + + for (i = 0; i < count; i++) + { + Eina_Value p = eina_value_ulong_init(i); + + efl_model_property_set(obj, "child.selected", &p); + + eina_value_flush(&p); + } +} + +static void +_efl_ui_select_model_efl_ui_multi_selectable_async_unselect_all(Eo *obj, + Efl_Ui_Select_Model_Data *pd EINA_UNUSED) +{ + uint64_t count = efl_model_children_count_get(obj); + + efl_ui_multi_selectable_async_unselect_range(obj, 0, count - 1); +} + +static void +_efl_ui_select_model_efl_ui_multi_selectable_async_select_range(Eo *obj, + Efl_Ui_Select_Model_Data *pd EINA_UNUSED, + uint64_t a, uint64_t b) +{ + unsigned long count, i; + + // Not the fastest way to implement it, but will reuse more code and be easier as a v1. + // It also make it not very async which could be noticable. + count = MIN(efl_model_children_count_get(obj), b + 1); + + for (i = a; i < count; i++) + { + Eina_Value p = eina_value_ulong_init(i); + + efl_model_property_set(obj, "child.selected", &p); + + eina_value_flush(&p); + } +} + +static Eina_Value +_children_unselect_then(Eo *o EINA_UNUSED, void *data EINA_UNUSED, const Eina_Value v) +{ + Eo *target; + Eina_Value unselect; + unsigned int i, len; + + unselect = eina_value_bool_init(EINA_FALSE); + + EINA_VALUE_ARRAY_FOREACH(&v, len, i, target) + { + efl_model_property_set(target, "self.selected", &unselect); + } + + eina_value_flush(&unselect); + + return v; +} + +#define BATCH_MAX 100 + +static void +_efl_ui_select_model_efl_ui_multi_selectable_async_unselect_range(Eo *obj, + Efl_Ui_Select_Model_Data *pd EINA_UNUSED, + uint64_t a, uint64_t b) +{ + unsigned int count, batch, i; + + count = MIN(efl_model_children_count_get(obj), b + 1); + + // Fetch group request of children in batches not to big to allow for throttling + // In the callback edit said object property to be unselected + i = a; + batch = 0; + + while (i < count) + { + Eina_Future *f; + + batch = MIN(i + BATCH_MAX, count); + batch -= i; + + f = efl_model_children_slice_get(obj, i, batch); + efl_future_then(obj, f, .success_type = EINA_VALUE_TYPE_ARRAY, + .success = _children_unselect_then); + + i += batch; + } +} + +static void +_efl_ui_select_model_efl_ui_single_selectable_fallback_selection_set(Eo *obj, + Efl_Ui_Select_Model_Data *pd, + Efl_Ui_Selectable *fallback) +{ + Eina_Value *index; + + if (!efl_isa(fallback, EFL_UI_SELECT_MODEL_CLASS)) + { + ERR("Class of object '%s' does not provide the necessary interface for Efl.Ui.Select_Model.fallback.", efl_debug_name_get(fallback)); + return; + } + if (efl_parent_get(fallback) != obj) + { + ERR("Provided object '%s' for fallback isn't a child of '%s'.", + efl_debug_name_get(fallback), efl_debug_name_get(obj)); + return; + } + + efl_replace(&pd->fallback_model, fallback); + + if (!pd->none) return ; + + // When we provide a fallback, we should use it! + index = efl_model_property_get(fallback, EFL_COMPOSITE_MODEL_CHILD_INDEX); + efl_model_property_set(obj, "child.selected", index); + eina_value_free(index); +} + +static Efl_Ui_Selectable * +_efl_ui_select_model_efl_ui_single_selectable_fallback_selection_get(const Eo *obj EINA_UNUSED, + Efl_Ui_Select_Model_Data *pd) +{ + return pd->fallback_model; +} + +static void +_efl_ui_select_model_efl_ui_selectable_selected_set(Eo *obj, + Efl_Ui_Select_Model_Data *pd EINA_UNUSED, + Eina_Bool selected) +{ + Eina_Value set = eina_value_bool_init(selected); + + efl_model_property_set(obj, "self.selected", &set); + + eina_value_flush(&set); +} + +static Eina_Bool +_efl_ui_select_model_efl_ui_selectable_selected_get(const Eo *obj, + Efl_Ui_Select_Model_Data *pd EINA_UNUSED) +{ + Eina_Value *selected; + Eina_Bool r = EINA_FALSE; + + selected = efl_model_property_get(obj, "self.selected"); + eina_value_bool_convert(selected, &r); + eina_value_free(selected); + + return r; +} + #include "efl_ui_select_model.eo.c" +#include "efl_ui_multi_selectable_async.eo.c" diff --git a/src/lib/elementary/efl_ui_select_model.eo b/src/lib/elementary/efl_ui_select_model.eo index 39624da903..4d94d2fa61 100644 --- a/src/lib/elementary/efl_ui_select_model.eo +++ b/src/lib/elementary/efl_ui_select_model.eo @@ -1,33 +1,23 @@ class @beta Efl.Ui.Select_Model extends Efl.Boolean_Model + implements Efl.Ui.Multi_Selectable_Async, + Efl.Ui.Selectable { [[Efl ui select model class]] - methods { - selected_get { - [[Gets an iterator of all the selected child of this model. - ]] - return: iterator; [[The iterator gives indices of selected children. - It is valid until any change is made on the model.]] - } - unselected_get { - [[Gets an iterator of all the child of this model that are not selected. - ]] - return: iterator; [[The iterator gives indices of unselected children. - It is valid until any change is made on the model.]] - } - @property single_selection { - [[Defines if we support only one exclusive selection at a time when set to $true. - - If disable with $false, it will have the behavior of a multi select mode. - ]] - values { - enable: bool; [[$true will enable the exclusive mode.]] - } - } - } implements { Efl.Object.constructor; + Efl.Object.invalidate; Efl.Model.property { get; set; } Efl.Model.properties { get; } + Efl.Ui.Single_Selectable.last_selected { get; } + Efl.Ui.Multi_Selectable_Async.selected_iterator_new; + Efl.Ui.Multi_Selectable_Async.unselected_iterator_new; + Efl.Ui.Multi_Selectable_Async.select_mode {get; set;} + Efl.Ui.Multi_Selectable_Async.select_all; + Efl.Ui.Multi_Selectable_Async.unselect_all; + Efl.Ui.Multi_Selectable_Async.select_range; + Efl.Ui.Multi_Selectable_Async.unselect_range; + Efl.Ui.Single_Selectable.fallback_selection {get; set;} + Efl.Ui.Selectable.selected {get; set;} } events { /* FIXME: The object is emitted in the event_info. This is redundant. */ diff --git a/src/lib/elementary/meson.build b/src/lib/elementary/meson.build index a1c001a7bb..5ef2b05be1 100644 --- a/src/lib/elementary/meson.build +++ b/src/lib/elementary/meson.build @@ -180,6 +180,7 @@ pub_eo_files = [ 'efl_ui_position_manager_grid.eo', 'efl_ui_selectable.eo', 'efl_ui_multi_selectable.eo', + 'efl_ui_multi_selectable_async.eo', 'efl_ui_single_selectable.eo', 'efl_ui_position_manager_data_access_v1.eo', 'efl_ui_tab_bar_default_item.eo', diff --git a/src/tests/elementary/efl_ui_test_select_model.c b/src/tests/elementary/efl_ui_test_select_model.c index e11155c0aa..e2b61c5677 100644 --- a/src/tests/elementary/efl_ui_test_select_model.c +++ b/src/tests/elementary/efl_ui_test_select_model.c @@ -111,12 +111,12 @@ EFL_START_TEST(efl_test_select_model) ecore_main_loop_begin(); - it = efl_ui_select_model_selected_get(model); + it = efl_ui_multi_selectable_async_selected_iterator_new(model); EINA_ITERATOR_FOREACH(it, index) fail_if(*index != 2); eina_iterator_free(it); - it = efl_ui_select_model_unselected_get(model); + it = efl_ui_multi_selectable_async_unselected_iterator_new(model); EINA_ITERATOR_FOREACH(it, index) fail_if(*index == 2); eina_iterator_free(it);