introduce a new interface efl_ui_selectable

this is meant to be implemented by entities that *can* be selectabled
(not to be confused with containers that can have selected contents)!

ref T8057

Reviewed-by: Mike Blumenkrantz <michael.blumenkrantz@gmail.com>
Differential Revision: https://phab.enlightenment.org/D9503
This commit is contained in:
Marcel Hollerbach 2019-08-05 19:07:29 +02:00
parent fc12e7721f
commit 1bd9a8f232
8 changed files with 87 additions and 73 deletions

View File

@ -28,7 +28,7 @@ _list_selected(void *data EINA_UNUSED, const Efl_Event *ev)
{
Eo *list = ev->object;
Eo *item = ev->info, *tmp;
printf("list item [%p:%d] is %s\n", item, efl_ui_item_index_get(item), (efl_ui_item_selected_get(item)? "selected" : "unselected"));
printf("list item [%p:%d] is %s\n", item, efl_ui_item_index_get(item), (efl_ui_selectable_selected_get(item)? "selected" : "unselected"));
Eina_Iterator *selects = efl_ui_collection_selected_items_get(list);
@ -42,7 +42,7 @@ static void
_list_unselected(void *data EINA_UNUSED, const Efl_Event *ev)
{
Eo *item = ev->info;
printf("list item [%p : %d] is %s\n", item, efl_ui_item_index_get(item), (efl_ui_item_selected_get(item)? "selected" : "unselected"));
printf("list item [%p : %d] is %s\n", item, efl_ui_item_index_get(item), (efl_ui_selectable_selected_get(item)? "selected" : "unselected"));
}
static void

View File

@ -259,6 +259,7 @@ typedef Eo Efl_Ui_Spotlight_Indicator;
# include <efl_ui_list_default_item.eo.h>
# include <efl_ui_grid_default_item.eo.h>
# include <efl_ui_list_placeholder_item.eo.h>
# include <efl_ui_selectable.eo.h>
/**
* Initialize Elementary

View File

@ -371,7 +371,7 @@ deselect_all(Efl_Ui_Collection_Data *pd)
while(pd->selected)
{
Eo *item = eina_list_data_get(pd->selected);
efl_ui_item_selected_set(item, EINA_FALSE);
efl_ui_selectable_selected_set(item, EINA_FALSE);
EINA_SAFETY_ON_TRUE_RETURN(eina_list_data_get(pd->selected) == item);
}
}
@ -456,41 +456,40 @@ _efl_ui_collection_efl_ui_multi_selectable_select_mode_get(const Eo *obj EINA_UN
}
static void
_selected_cb(void *data, const Efl_Event *ev)
_selection_changed(void *data, const Efl_Event *ev)
{
Eina_Bool selection = *((Eina_Bool*) ev->info);
Eo *obj = data;
MY_DATA_GET(obj, pd);
if (pd->mode == EFL_UI_SELECT_MODE_SINGLE_ALWAYS || pd->mode == EFL_UI_SELECT_MODE_SINGLE)
if (selection)
{
//we might get the situation that the item is already in the list and selected again, so just free the list, it will be rebuild below
if (eina_list_data_get(pd->selected) == ev->object)
if (pd->mode == EFL_UI_SELECT_MODE_SINGLE_ALWAYS || pd->mode == EFL_UI_SELECT_MODE_SINGLE)
{
pd->selected = eina_list_free(pd->selected);
}
else
{
deselect_all(pd);
}
//we might get the situation that the item is already in the list and selected again, so just free the list, it will be rebuild below
if (eina_list_data_get(pd->selected) == ev->object)
{
pd->selected = eina_list_free(pd->selected);
}
else
{
deselect_all(pd);
}
}
else if (pd->mode == EFL_UI_SELECT_MODE_NONE)
{
ERR("Selection while mode is NONE, uncaught state!");
return;
}
pd->selected = eina_list_append(pd->selected, ev->object);
efl_event_callback_call(obj, EFL_UI_EVENT_ITEM_SELECTED, ev->object);
}
else if (pd->mode == EFL_UI_SELECT_MODE_NONE)
else
{
ERR("Selection while mode is NONE, uncaught state!");
return;
pd->selected = eina_list_remove(pd->selected, ev->object);
efl_event_callback_call(obj, EFL_UI_EVENT_ITEM_UNSELECTED, ev->object);
}
pd->selected = eina_list_append(pd->selected, ev->object);
efl_event_callback_call(obj, EFL_UI_EVENT_ITEM_SELECTED, ev->object);
}
static void
_unselected_cb(void *data, const Efl_Event *ev)
{
Eo *obj = data;
MY_DATA_GET(obj, pd);
pd->selected = eina_list_remove(pd->selected, ev->object);
efl_event_callback_call(obj, EFL_UI_EVENT_ITEM_UNSELECTED, ev->object);
}
static void
@ -529,8 +528,7 @@ _redirect_cb(void *data, const Efl_Event *ev)
EFL_CALLBACKS_ARRAY_DEFINE(active_item,
{EFL_GFX_ENTITY_EVENT_HINTS_CHANGED, _hints_changed_cb},
{EFL_UI_EVENT_ITEM_SELECTED, _selected_cb},
{EFL_UI_EVENT_ITEM_UNSELECTED, _unselected_cb},
{EFL_UI_EVENT_SELECTED_CHANGED, _selection_changed},
{EFL_INPUT_EVENT_PRESSED, _redirect_cb},
{EFL_INPUT_EVENT_UNPRESSED, _redirect_cb},
{EFL_INPUT_EVENT_LONGPRESSED, _redirect_cb},

View File

@ -142,6 +142,7 @@ static void
_item_select(Eo *obj, Efl_Ui_Item_Data *pd)
{
Efl_Ui_Select_Mode m;
if (!pd->parent)
return;
m = efl_ui_select_mode_get(pd->parent);
@ -150,9 +151,9 @@ _item_select(Eo *obj, Efl_Ui_Item_Data *pd)
ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
pd->selected = EINA_TRUE;
Eina_Bool tmp = pd->selected = EINA_TRUE;
edje_object_signal_emit(wd->resize_obj, "efl,state,selected", "efl");
efl_event_callback_call(obj, EFL_UI_EVENT_ITEM_SELECTED, NULL);
efl_event_callback_call(obj, EFL_UI_EVENT_SELECTED_CHANGED, &tmp);
}
static void
@ -161,9 +162,9 @@ _item_unselect(Eo *obj, Efl_Ui_Item_Data *pd)
if (!pd->selected) return;
ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
pd->selected = EINA_FALSE;
Eina_Bool tmp = pd->selected =EINA_FALSE;
edje_object_signal_emit(wd->resize_obj, "efl,state,unselected", "efl");
efl_event_callback_call(obj, EFL_UI_EVENT_ITEM_UNSELECTED, NULL);
efl_event_callback_call(obj, EFL_UI_EVENT_SELECTED_CHANGED, &tmp);
}
/* Mouse Controls */
@ -242,7 +243,7 @@ _efl_ui_item_index_get(const Eo *obj, Efl_Ui_Item_Data *pd)
}
EOLIAN static void
_efl_ui_item_selected_set(Eo *obj, Efl_Ui_Item_Data *pd, Eina_Bool select)
_efl_ui_item_efl_ui_selectable_selected_set(Eo *obj, Efl_Ui_Item_Data *pd, Eina_Bool select)
{
Eina_Bool selected = !!select;
ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
@ -253,7 +254,7 @@ _efl_ui_item_selected_set(Eo *obj, Efl_Ui_Item_Data *pd, Eina_Bool select)
}
EOLIAN static Eina_Bool
_efl_ui_item_selected_get(const Eo *obj EINA_UNUSED, Efl_Ui_Item_Data *pd)
_efl_ui_item_efl_ui_selectable_selected_get(const Eo *obj EINA_UNUSED, Efl_Ui_Item_Data *pd)
{
return pd->selected;
}
@ -271,3 +272,4 @@ _efl_ui_item_container_get(const Eo *obj EINA_UNUSED, Efl_Ui_Item_Data *pd)
}
#include "efl_ui_item.eo.c"
#include "efl_ui_selectable.eo.c"

View File

@ -1,4 +1,4 @@
abstract @beta Efl.Ui.Item extends Efl.Ui.Layout_Base implements Efl.Ui.Container_Selectable, Efl.Input.Clickable
abstract @beta Efl.Ui.Item extends Efl.Ui.Layout_Base implements Efl.Ui.Selectable, Efl.Input.Clickable
{
[[Selectable Item abstraction.
@ -6,7 +6,7 @@ abstract @beta Efl.Ui.Item extends Efl.Ui.Layout_Base implements Efl.Ui.Containe
like @Efl.Ui.List or @Efl.Ui.Grid, for example.
@Efl.Ui.Item provides user interaction through the @Efl.Input.Clickable mixin.
Items can be pressed, long-pressed, etc, and appropriate events are generated.
@Efl.Ui.Item also implements the @Efl.Ui.Container_Selectable interface, meaning that "selected" and
@Efl.Ui.Item also implements the @Efl.Ui.Selectable interface, meaning that "selected" and
"unselected" events are automatically generated.
Classes inheriting from this one only need to deal with the visual representation of the widget.
@ -15,8 +15,8 @@ abstract @beta Efl.Ui.Item extends Efl.Ui.Layout_Base implements Efl.Ui.Containe
Some events are converted to edje signals so the theme can react to them:
@[Efl.Input.Clickable.pressed] -> "efl,state,pressed",
@[Efl.Input.Clickable.unpressed] -> "efl,state,unpressed",
@[Efl.Ui.Container_Selectable.item,selected] -> "efl,state,selected",
@[Efl.Ui.Container_Selectable.item,unselected] -> "efl,state,unselected".
@[Efl.Ui.Selectable.selected,changed] (true) -> "efl,state,selected",
@[Efl.Ui.Selectable.selected,changed] (false) -> "efl,state,unselected".
]]
methods {
@property index {
@ -28,16 +28,6 @@ abstract @beta Efl.Ui.Item extends Efl.Ui.Layout_Base implements Efl.Ui.Containe
index : int; [[The index where to find this item in its $container.]]
}
}
@property selected {
[[Item selected state.
The visual representation of the item will be adjusted accordingly to the new state.
This property is also automatically modified in response to user actions.
]]
values {
select: bool; [[Whether this item is selected or not.]]
}
}
@property container {
[[The container this object is part of.
@ -55,5 +45,6 @@ abstract @beta Efl.Ui.Item extends Efl.Ui.Layout_Base implements Efl.Ui.Containe
Efl.Object.constructor;
Efl.Object.finalize;
Efl.Object.destructor;
Efl.Ui.Selectable.selected {get; set;}
}
}

View File

@ -0,0 +1,21 @@
interface Efl.Ui.Selectable {
[[Selectable interface for ui objects
A object implementing this can be selected. When the selected property of this object changes, the selected,changed event is emitted.
]]
event_prefix: efl_ui;
methods {
@property selected {
[[The selected state of this object
A change to this property emits the changed event.
]]
values {
selected : bool; [[The selected state of this object]]
}
}
}
events {
selected,changed : bool; [[Called when the selected state has changed]]
}
}

View File

@ -182,6 +182,7 @@ pub_eo_files = [
'efl_ui_position_manager_entity.eo',
'efl_ui_position_manager_list.eo',
'efl_ui_position_manager_grid.eo',
'efl_ui_selectable.eo',
]
foreach eo_file : pub_eo_files

View File

@ -55,25 +55,25 @@ EFL_START_TEST(test_multi_select)
efl_event_callback_add(item_container, EFL_UI_EVENT_ITEM_UNSELECTED, _set_pointer_quit, &unselected);
fill_items(EFL_UI_LIST_DEFAULT_ITEM_CLASS);
efl_ui_item_selected_set(efl_pack_content_get(item_container, 0), EINA_TRUE);
efl_ui_selectable_selected_set(efl_pack_content_get(item_container, 0), EINA_TRUE);
ck_assert_ptr_eq(selected, efl_pack_content_get(item_container, 0));
ck_assert_ptr_eq(unselected, NULL);
selected = NULL;
unselected = NULL;
efl_ui_item_selected_set(efl_pack_content_get(item_container, 2), EINA_TRUE);
efl_ui_selectable_selected_set(efl_pack_content_get(item_container, 2), EINA_TRUE);
ck_assert_ptr_eq(selected, efl_pack_content_get(item_container, 2));
ck_assert_ptr_eq(unselected, NULL);
selected = NULL;
unselected = NULL;
ck_assert_int_eq(efl_ui_item_selected_get(efl_pack_content_get(item_container, 0)), EINA_TRUE);
ck_assert_int_eq(efl_ui_item_selected_get(efl_pack_content_get(item_container, 2)), EINA_TRUE);
ck_assert_int_eq(efl_ui_selectable_selected_get(efl_pack_content_get(item_container, 0)), EINA_TRUE);
ck_assert_int_eq(efl_ui_selectable_selected_get(efl_pack_content_get(item_container, 2)), EINA_TRUE);
ck_assert_ptr_eq(efl_ui_collection_last_selected_item_get(item_container), efl_pack_content_get(item_container, 2));
_iterator_to_array(&arr_selected, efl_ui_collection_selected_items_get(item_container));
ck_assert_int_eq(eina_array_count(arr_selected), 2);
ck_assert_ptr_eq(eina_array_data_get(arr_selected, 0), efl_pack_content_get(item_container, 0));
ck_assert_ptr_eq(eina_array_data_get(arr_selected, 1), efl_pack_content_get(item_container, 2));
efl_ui_item_selected_set(efl_pack_content_get(item_container, 2), EINA_TRUE);
efl_ui_selectable_selected_set(efl_pack_content_get(item_container, 2), EINA_TRUE);
ck_assert_ptr_eq(selected, NULL);
ck_assert_ptr_eq(unselected, NULL);
selected = NULL;
@ -93,17 +93,17 @@ EFL_START_TEST(test_multi_select_removal)
efl_event_callback_add(item_container, EFL_UI_EVENT_ITEM_UNSELECTED, _set_pointer_quit, &unselected);
fill_items(EFL_UI_LIST_DEFAULT_ITEM_CLASS);
efl_ui_item_selected_set(efl_pack_content_get(item_container, 0), EINA_TRUE);
efl_ui_selectable_selected_set(efl_pack_content_get(item_container, 0), EINA_TRUE);
selected = NULL;//No need to ckeck the flag, we asserted in the tcase before
efl_ui_item_selected_set(efl_pack_content_get(item_container, 2), EINA_TRUE);
efl_ui_selectable_selected_set(efl_pack_content_get(item_container, 2), EINA_TRUE);
selected = NULL;//No need to ckeck the flag, we asserted in the tcase before
unselected = NULL;
efl_ui_item_selected_set(efl_pack_content_get(item_container, 0), EINA_FALSE);
efl_ui_selectable_selected_set(efl_pack_content_get(item_container, 0), EINA_FALSE);
ck_assert_ptr_eq(selected, NULL);
ck_assert_ptr_eq(unselected, efl_pack_content_get(item_container, 0));
selected = NULL;
unselected = NULL;
efl_ui_item_selected_set(efl_pack_content_get(item_container, 2), EINA_FALSE);
efl_ui_selectable_selected_set(efl_pack_content_get(item_container, 2), EINA_FALSE);
ck_assert_ptr_eq(selected, NULL);
ck_assert_ptr_eq(unselected, efl_pack_content_get(item_container, 2));
selected = NULL;
@ -128,24 +128,24 @@ EFL_START_TEST(test_single_select)
efl_event_callback_add(item_container, EFL_UI_EVENT_ITEM_UNSELECTED, _set_pointer_quit, &unselected);
fill_items(EFL_UI_LIST_DEFAULT_ITEM_CLASS);
efl_ui_item_selected_set(efl_pack_content_get(item_container, 0), EINA_TRUE);
efl_ui_selectable_selected_set(efl_pack_content_get(item_container, 0), EINA_TRUE);
ck_assert_ptr_eq(selected, efl_pack_content_get(item_container, 0));
ck_assert_ptr_eq(unselected, NULL);
selected = NULL;
unselected = NULL;
efl_ui_item_selected_set(efl_pack_content_get(item_container, 2), EINA_TRUE);
efl_ui_selectable_selected_set(efl_pack_content_get(item_container, 2), EINA_TRUE);
ck_assert_ptr_eq(selected, efl_pack_content_get(item_container, 2));
ck_assert_ptr_eq(unselected, efl_pack_content_get(item_container, 0));
selected = NULL;
unselected = NULL;
ck_assert_int_eq(efl_ui_item_selected_get(efl_pack_content_get(item_container, 0)), EINA_FALSE);
ck_assert_int_eq(efl_ui_item_selected_get(efl_pack_content_get(item_container, 2)), EINA_TRUE);
ck_assert_int_eq(efl_ui_selectable_selected_get(efl_pack_content_get(item_container, 0)), EINA_FALSE);
ck_assert_int_eq(efl_ui_selectable_selected_get(efl_pack_content_get(item_container, 2)), EINA_TRUE);
ck_assert_ptr_eq(efl_ui_collection_last_selected_item_get(item_container), efl_pack_content_get(item_container, 2));
_iterator_to_array(&arr_selected, efl_ui_collection_selected_items_get(item_container));
ck_assert_int_eq(eina_array_count(arr_selected), 1);
ck_assert_ptr_eq(eina_array_data_get(arr_selected, 0), efl_pack_content_get(item_container, 2));
efl_ui_item_selected_set(efl_pack_content_get(item_container, 2), EINA_TRUE);
efl_ui_selectable_selected_set(efl_pack_content_get(item_container, 2), EINA_TRUE);
ck_assert_ptr_eq(selected, NULL);
ck_assert_ptr_eq(unselected, NULL);
selected = NULL;
@ -166,23 +166,23 @@ EFL_START_TEST(test_single_select_always)
efl_event_callback_add(item_container, EFL_UI_EVENT_ITEM_UNSELECTED, _set_pointer_quit, &unselected);
fill_items(EFL_UI_LIST_DEFAULT_ITEM_CLASS);
efl_ui_item_selected_set(efl_pack_content_get(item_container, 0), EINA_TRUE);
efl_ui_selectable_selected_set(efl_pack_content_get(item_container, 0), EINA_TRUE);
ck_assert_ptr_eq(selected, efl_pack_content_get(item_container, 0));
ck_assert_ptr_eq(unselected, NULL);
selected = NULL;
unselected = NULL;
efl_ui_item_selected_set(efl_pack_content_get(item_container, 2), EINA_TRUE);
efl_ui_selectable_selected_set(efl_pack_content_get(item_container, 2), EINA_TRUE);
ck_assert_ptr_eq(selected, efl_pack_content_get(item_container, 2));
ck_assert_ptr_eq(unselected, efl_pack_content_get(item_container, 0));
selected = NULL;
unselected = NULL;
efl_ui_item_selected_set(efl_pack_content_get(item_container, 2), EINA_TRUE);
efl_ui_selectable_selected_set(efl_pack_content_get(item_container, 2), EINA_TRUE);
ck_assert_ptr_eq(selected, efl_pack_content_get(item_container, 2));
ck_assert_ptr_eq(unselected, NULL);
selected = NULL;
unselected = NULL;
ck_assert_int_eq(efl_ui_item_selected_get(efl_pack_content_get(item_container, 0)), EINA_FALSE);
ck_assert_int_eq(efl_ui_item_selected_get(efl_pack_content_get(item_container, 2)), EINA_TRUE);
ck_assert_int_eq(efl_ui_selectable_selected_get(efl_pack_content_get(item_container, 0)), EINA_FALSE);
ck_assert_int_eq(efl_ui_selectable_selected_get(efl_pack_content_get(item_container, 2)), EINA_TRUE);
ck_assert_ptr_eq(efl_ui_collection_last_selected_item_get(item_container), efl_pack_content_get(item_container, 2));
_iterator_to_array(&arr_selected, efl_ui_collection_selected_items_get(item_container));
ck_assert_int_eq(eina_array_count(arr_selected), 1);
@ -203,18 +203,18 @@ EFL_START_TEST(test_none_select)
efl_event_callback_add(item_container, EFL_UI_EVENT_ITEM_UNSELECTED, _set_pointer_quit, &unselected);
fill_items(EFL_UI_LIST_DEFAULT_ITEM_CLASS);
efl_ui_item_selected_set(efl_pack_content_get(item_container, 0), EINA_TRUE);
efl_ui_selectable_selected_set(efl_pack_content_get(item_container, 0), EINA_TRUE);
ck_assert_ptr_eq(selected, NULL);
ck_assert_ptr_eq(unselected, NULL);
selected = NULL;
unselected = NULL;
efl_ui_item_selected_set(efl_pack_content_get(item_container, 2), EINA_TRUE);
efl_ui_selectable_selected_set(efl_pack_content_get(item_container, 2), EINA_TRUE);
ck_assert_ptr_eq(selected, NULL);
ck_assert_ptr_eq(unselected, NULL);
selected = NULL;
unselected = NULL;
ck_assert_int_eq(efl_ui_item_selected_get(efl_pack_content_get(item_container, 0)), EINA_FALSE);
ck_assert_int_eq(efl_ui_item_selected_get(efl_pack_content_get(item_container, 2)), EINA_FALSE);
ck_assert_int_eq(efl_ui_selectable_selected_get(efl_pack_content_get(item_container, 0)), EINA_FALSE);
ck_assert_int_eq(efl_ui_selectable_selected_get(efl_pack_content_get(item_container, 2)), EINA_FALSE);
ck_assert_ptr_eq(efl_ui_collection_last_selected_item_get(item_container), NULL);
_iterator_to_array(&arr_selected, efl_ui_collection_selected_items_get(item_container));
ck_assert_int_eq(eina_array_count(arr_selected), 0);