forked from enlightenment/efl
efl_ui_multi_selectable: add APIs for selecting
this can be used to select / unselect a range or all selectables in a container. The range selectable APIs do not have a strong ordering on a and b, b does not have to come after a. ref T8057 Reviewed-by: Mike Blumenkrantz <michael.blumenkrantz@gmail.com> Differential Revision: https://phab.enlightenment.org/D9660
This commit is contained in:
parent
c467dc6e81
commit
35f9fc26e3
|
@ -4,6 +4,18 @@
|
|||
|
||||
#include <Efl_Ui.h>
|
||||
|
||||
static void
|
||||
_select_all(void *data, const Efl_Event *ev EINA_UNUSED)
|
||||
{
|
||||
efl_ui_select_all(data);
|
||||
}
|
||||
|
||||
static void
|
||||
_unselect_all(void *data, const Efl_Event *ev EINA_UNUSED)
|
||||
{
|
||||
efl_ui_unselect_all(data);
|
||||
}
|
||||
|
||||
static void
|
||||
_selection_changed_cb(void *data, const Efl_Event *ev EINA_UNUSED)
|
||||
{
|
||||
|
@ -192,7 +204,7 @@ void create_item_container_ui(const Efl_Class *collection_class, const Efl_Class
|
|||
}
|
||||
}
|
||||
|
||||
efl_pack_table(tbl, o, 1, 0, 1, 12);
|
||||
efl_pack_table(tbl, o, 1, 0, 1, 14);
|
||||
ctx->c = o;
|
||||
|
||||
o = efl_add(EFL_UI_BUTTON_CLASS, tbl,
|
||||
|
@ -269,11 +281,26 @@ void create_item_container_ui(const Efl_Class *collection_class, const Efl_Class
|
|||
efl_event_callback_add(o, EFL_INPUT_EVENT_CLICKED, _add_thousend_items, item_container);
|
||||
efl_pack_table(tbl, o, 0, 10, 1, 1);
|
||||
|
||||
o = efl_add(EFL_UI_BUTTON_CLASS, tbl,
|
||||
efl_gfx_hint_weight_set(efl_added, 0.0, 0.0),
|
||||
efl_gfx_hint_align_set(efl_added, 0, 0.5));
|
||||
efl_text_set(o, "Select All");
|
||||
efl_event_callback_add(o, EFL_INPUT_EVENT_CLICKED, _select_all, item_container);
|
||||
efl_pack_table(tbl, o, 0, 11, 1, 1);
|
||||
|
||||
o = efl_add(EFL_UI_BUTTON_CLASS, tbl,
|
||||
efl_gfx_hint_weight_set(efl_added, 0.0, 0.0),
|
||||
efl_gfx_hint_align_set(efl_added, 0, 0.5));
|
||||
efl_text_set(o, "Unselect All");
|
||||
efl_event_callback_add(o, EFL_INPUT_EVENT_CLICKED, _unselect_all, item_container);
|
||||
efl_pack_table(tbl, o, 0, 12, 1, 1);
|
||||
|
||||
|
||||
bx = efl_add(EFL_UI_RADIO_BOX_CLASS, tbl,
|
||||
efl_gfx_hint_weight_set(efl_added, 0.0, 0.0),
|
||||
efl_gfx_hint_align_set(efl_added, 0, 0.5));
|
||||
efl_event_callback_add(bx, EFL_UI_RADIO_GROUP_EVENT_VALUE_CHANGED, _select_value_cb, item_container);
|
||||
efl_pack_table(tbl, bx, 0, 11, 1, 1);
|
||||
efl_pack_table(tbl, bx, 0, 13, 1, 1);
|
||||
o = efl_add(EFL_UI_RADIO_CLASS, bx,
|
||||
efl_ui_radio_state_value_set(efl_added, EFL_UI_SELECT_MODE_SINGLE));
|
||||
efl_text_set(o, "Singleselect");
|
||||
|
|
|
@ -940,6 +940,76 @@ _efl_ui_collection_efl_ui_focus_manager_move(Eo *obj, Efl_Ui_Collection_Data *pd
|
|||
return new_obj;
|
||||
}
|
||||
|
||||
static void
|
||||
_selectable_range_apply(Eina_List *start, Eina_Bool flag)
|
||||
{
|
||||
Efl_Ui_Selectable *sel;
|
||||
Eina_List *n;
|
||||
|
||||
EINA_LIST_FOREACH(start, n, sel)
|
||||
{
|
||||
efl_ui_selectable_selected_set(sel, flag);
|
||||
}
|
||||
}
|
||||
|
||||
EOLIAN static void
|
||||
_efl_ui_collection_efl_ui_multi_selectable_select_all(Eo *obj EINA_UNUSED, Efl_Ui_Collection_Data *pd)
|
||||
{
|
||||
_selectable_range_apply(pd->items, EINA_TRUE);
|
||||
}
|
||||
|
||||
EOLIAN static void
|
||||
_efl_ui_collection_efl_ui_multi_selectable_unselect_all(Eo *obj EINA_UNUSED, Efl_Ui_Collection_Data *pd)
|
||||
{
|
||||
_selectable_range_apply(pd->items, EINA_FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
_range_selection_find(Eo *obj, Efl_Ui_Collection_Data *pd, Efl_Ui_Selectable *a, Efl_Ui_Selectable *b, Eina_Bool flag)
|
||||
{
|
||||
Eina_List *n;
|
||||
Efl_Ui_Selectable *c;
|
||||
Eina_List *start = NULL, *end = NULL;
|
||||
|
||||
EINA_SAFETY_ON_FALSE_RETURN(efl_ui_widget_parent_get(a) == obj);
|
||||
EINA_SAFETY_ON_FALSE_RETURN(efl_ui_widget_parent_get(b) == obj);
|
||||
|
||||
EINA_LIST_FOREACH(pd->items, n, c)
|
||||
{
|
||||
if (!start)
|
||||
{
|
||||
if (c == a)
|
||||
start = n;
|
||||
else if (c == b)
|
||||
start = n;
|
||||
}
|
||||
else if (!end)
|
||||
{
|
||||
if (c == a)
|
||||
end = n;
|
||||
else if (c == b)
|
||||
end = n;
|
||||
}
|
||||
/* if we have found the first element, start applying the flag */
|
||||
if (start)
|
||||
efl_ui_selectable_selected_set(c, flag);
|
||||
if (end)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
EOLIAN static void
|
||||
_efl_ui_collection_efl_ui_multi_selectable_select_range(Eo *obj, Efl_Ui_Collection_Data *pd, Efl_Ui_Selectable *a, Efl_Ui_Selectable *b)
|
||||
{
|
||||
_range_selection_find(obj, pd, a, b, EINA_TRUE);
|
||||
}
|
||||
|
||||
EOLIAN static void
|
||||
_efl_ui_collection_efl_ui_multi_selectable_unselect_range(Eo *obj, Efl_Ui_Collection_Data *pd, Efl_Ui_Selectable *a, Efl_Ui_Selectable *b)
|
||||
{
|
||||
_range_selection_find(obj, pd, a, b, EINA_FALSE);
|
||||
}
|
||||
|
||||
#include "efl_ui_collection.eo.c"
|
||||
|
||||
#define ITEM_IS_OUTSIDE_VISIBLE(id) id < collection_pd->start_id || id > collection_pd->end_id
|
||||
|
|
|
@ -67,6 +67,10 @@ class @beta Efl.Ui.Collection extends Efl.Ui.Layout_Base implements
|
|||
Efl.Ui.Single_Selectable.last_selected { get; }
|
||||
Efl.Ui.Multi_Selectable.selected_items_get;
|
||||
Efl.Ui.Multi_Selectable.select_mode {get; set;}
|
||||
Efl.Ui.Multi_Selectable.select_all;
|
||||
Efl.Ui.Multi_Selectable.unselect_all;
|
||||
Efl.Ui.Multi_Selectable.select_range;
|
||||
Efl.Ui.Multi_Selectable.unselect_range;
|
||||
}
|
||||
events {
|
||||
item,pressed : Efl.Ui.Item; [[A $press event occurred over an item.]]
|
||||
|
|
|
@ -28,5 +28,38 @@ interface @beta Efl.Ui.Multi_Selectable extends Efl.Ui.Single_Selectable
|
|||
[[Get the selected items in a iterator. The iterator sequence will be decided by selection.]]
|
||||
return: iterator<Efl.Ui.Selectable> @owned @no_unused; [[User has to free the iterator after usage.]]
|
||||
}
|
||||
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 part of the widget, a error is returned, and no change is applied.
|
||||
$null is not allowed as either of the parameters.
|
||||
Both of the passed values will also be selected.
|
||||
]]
|
||||
params {
|
||||
a : Efl.Ui.Selectable; [[One side of the range.]]
|
||||
b : Efl.Ui.Selectable; [[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 part of the widget, a error is returned, and no change is applied.
|
||||
$null is not allowed as either of the parameters.
|
||||
Both of the passed values will also be unselected.
|
||||
]]
|
||||
params {
|
||||
a : Efl.Ui.Selectable; [[One side of the range.]]
|
||||
b : Efl.Ui.Selectable; [[The other side of the range.]]
|
||||
}
|
||||
}
|
||||
select_all {
|
||||
[[Select all @Efl.Ui.Selectable]]
|
||||
}
|
||||
unselect_all {
|
||||
[[Unselect all @Efl.Ui.Selectable]]
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -213,6 +213,91 @@ EFL_START_TEST(test_none_select)
|
|||
}
|
||||
EFL_END_TEST
|
||||
|
||||
EFL_START_TEST(select_all_api)
|
||||
{
|
||||
Eina_Array *arr_selected;
|
||||
|
||||
efl_ui_select_mode_set(widget, EFL_UI_SELECT_MODE_MULTI);
|
||||
efl_ui_select_all(widget);
|
||||
_iterator_to_array(&arr_selected, efl_ui_selected_items_get(widget));
|
||||
|
||||
ck_assert_int_eq(eina_array_count(arr_selected), 3);
|
||||
|
||||
ck_assert_ptr_eq(eina_array_data_get(arr_selected, 0), efl_pack_content_get(widget, 0));
|
||||
ck_assert_ptr_eq(eina_array_data_get(arr_selected, 1), efl_pack_content_get(widget, 1));
|
||||
ck_assert_ptr_eq(eina_array_data_get(arr_selected, 2), efl_pack_content_get(widget, 2));
|
||||
}
|
||||
EFL_END_TEST
|
||||
|
||||
EFL_START_TEST(unselect_all_api)
|
||||
{
|
||||
Eina_Array *arr_selected;
|
||||
|
||||
efl_ui_select_mode_set(widget, EFL_UI_SELECT_MODE_MULTI);
|
||||
efl_ui_selectable_selected_set(efl_pack_content_get(widget, 0), EINA_TRUE);
|
||||
|
||||
efl_ui_unselect_all(widget);
|
||||
_iterator_to_array(&arr_selected, efl_ui_selected_items_get(widget));
|
||||
|
||||
ck_assert_int_eq(eina_array_count(arr_selected), 0);
|
||||
ck_assert_int_eq(efl_ui_selectable_selected_get(efl_pack_content_get(widget, 0)), EINA_FALSE);
|
||||
}
|
||||
EFL_END_TEST
|
||||
|
||||
EFL_START_TEST(unselect_range)
|
||||
{
|
||||
Eina_Array *arr_selected;
|
||||
|
||||
efl_ui_select_mode_set(widget, EFL_UI_SELECT_MODE_MULTI);
|
||||
efl_ui_select_all(widget);
|
||||
|
||||
efl_ui_unselect_range(widget, efl_pack_content_get(widget, 1), efl_pack_content_get(widget, 2));
|
||||
_iterator_to_array(&arr_selected, efl_ui_selected_items_get(widget));
|
||||
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(widget, 0));
|
||||
}
|
||||
EFL_END_TEST
|
||||
|
||||
EFL_START_TEST(unselect_range2)
|
||||
{
|
||||
Eina_Array *arr_selected;
|
||||
|
||||
efl_ui_select_mode_set(widget, EFL_UI_SELECT_MODE_MULTI);
|
||||
efl_ui_select_all(widget);
|
||||
|
||||
efl_ui_unselect_range(widget, efl_pack_content_get(widget, 2), efl_pack_content_get(widget, 1));
|
||||
_iterator_to_array(&arr_selected, efl_ui_selected_items_get(widget));
|
||||
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(widget, 0));
|
||||
}
|
||||
EFL_END_TEST
|
||||
|
||||
EFL_START_TEST(select_range)
|
||||
{
|
||||
Eina_Array *arr_selected;
|
||||
|
||||
efl_ui_select_mode_set(widget, EFL_UI_SELECT_MODE_MULTI);
|
||||
efl_ui_select_range(widget, efl_pack_content_get(widget, 1), efl_pack_content_get(widget, 2));
|
||||
_iterator_to_array(&arr_selected, efl_ui_selected_items_get(widget));
|
||||
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(widget, 1));
|
||||
ck_assert_ptr_eq(eina_array_data_get(arr_selected, 1), efl_pack_content_get(widget, 2));
|
||||
}
|
||||
EFL_END_TEST
|
||||
|
||||
EFL_START_TEST(select_range2)
|
||||
{
|
||||
Eina_Array *arr_selected;
|
||||
|
||||
efl_ui_select_mode_set(widget, EFL_UI_SELECT_MODE_MULTI);
|
||||
efl_ui_select_range(widget, efl_pack_content_get(widget, 2), efl_pack_content_get(widget, 1));
|
||||
_iterator_to_array(&arr_selected, efl_ui_selected_items_get(widget));
|
||||
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(widget, 1));
|
||||
ck_assert_ptr_eq(eina_array_data_get(arr_selected, 1), efl_pack_content_get(widget, 2));
|
||||
}
|
||||
EFL_END_TEST
|
||||
|
||||
void
|
||||
efl_ui_multi_selectable_behavior_test(TCase *tc)
|
||||
{
|
||||
|
@ -222,5 +307,11 @@ efl_ui_multi_selectable_behavior_test(TCase *tc)
|
|||
tcase_add_test(tc, test_single_select);
|
||||
tcase_add_test(tc, test_none_select);
|
||||
tcase_add_test(tc, test_single_select_always);
|
||||
tcase_add_test(tc, select_all_api);
|
||||
tcase_add_test(tc, unselect_all_api);
|
||||
tcase_add_test(tc, unselect_range);
|
||||
tcase_add_test(tc, unselect_range2);
|
||||
tcase_add_test(tc, select_range);
|
||||
tcase_add_test(tc, select_range2);
|
||||
efl_ui_single_selectable_behavior_test(tc);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue