efl_ui_collection_view: support focus

with this commit you can more or less use focus. The only uncaught case
for now is that if the object is not available, no focus can be set.
Navigating with focus on the screen however should be possible.

Differential Revision: https://phab.enlightenment.org/D9969
This commit is contained in:
Marcel Hollerbach 2019-09-16 13:50:12 +02:00 committed by Cedric Bail
parent d5a21c7998
commit b057ac1af6
2 changed files with 41 additions and 4 deletions

View File

@ -508,7 +508,6 @@ _entity_fetched_cb(Eo *obj, void *data, const Eina_Value v)
efl_ui_item_container_set(child, obj); efl_ui_item_container_set(child, obj);
efl_ui_widget_sub_object_add(obj, child); efl_ui_widget_sub_object_add(obj, child);
efl_canvas_group_member_add(pd->pan, child); efl_canvas_group_member_add(pd->pan, child);
efl_ui_widget_focus_allow_set(child, EINA_FALSE);
efl_gfx_entity_visible_set(child, EINA_FALSE); efl_gfx_entity_visible_set(child, EINA_FALSE);
#ifdef VIEWPORT_ENABLE #ifdef VIEWPORT_ENABLE
@ -2180,6 +2179,12 @@ _efl_ui_collection_view_efl_ui_focus_manager_move(Eo *obj, Efl_Ui_Collection_Vie
return new_obj; return new_obj;
} }
EOLIAN static Eina_Bool
_efl_ui_collection_view_efl_ui_widget_focus_state_apply(Eo *obj, Efl_Ui_Collection_View_Data *pd EINA_UNUSED, Efl_Ui_Widget_Focus_State current_state, Efl_Ui_Widget_Focus_State *configured_state, Efl_Ui_Widget *redirect EINA_UNUSED)
{
return efl_ui_widget_focus_state_apply(efl_super(obj, MY_CLASS), current_state, configured_state, obj);
}
#include "efl_ui_collection_view.eo.c" #include "efl_ui_collection_view.eo.c"
#define ITEM_IS_OUTSIDE_VISIBLE(id) id < cpd->start_id || id > cpd->end_id #define ITEM_IS_OUTSIDE_VISIBLE(id) id < cpd->start_id || id > cpd->end_id
@ -2240,12 +2245,26 @@ _efl_ui_collection_view_focus_manager_efl_ui_focus_manager_manager_focus_set(Eo
efl_ui_focus_manager_focus_set(efl_super(obj, EFL_UI_COLLECTION_VIEW_FOCUS_MANAGER_CLASS), focus); efl_ui_focus_manager_focus_set(efl_super(obj, EFL_UI_COLLECTION_VIEW_FOCUS_MANAGER_CLASS), focus);
} }
static int
_id_from_item(Efl_Ui_Item *item, uint64_t *index)
{
Eina_Value *vindex;
Efl_Model *model;
model = efl_ui_view_model_get(item);
vindex = efl_model_property_get(model, "child.index");
EINA_SAFETY_ON_FALSE_RETURN_VAL(eina_value_uint64_convert(vindex, index), EINA_FALSE);
eina_value_free(vindex);
return EINA_TRUE;
}
EOLIAN static Efl_Ui_Focus_Object * EOLIAN static Efl_Ui_Focus_Object *
_efl_ui_collection_view_focus_manager_efl_ui_focus_manager_request_move(Eo *obj, Efl_Ui_Collection_View_Focus_Manager_Data *pd, Efl_Ui_Focus_Direction direction, Efl_Ui_Focus_Object *child, Eina_Bool logical) _efl_ui_collection_view_focus_manager_efl_ui_focus_manager_request_move(Eo *obj, Efl_Ui_Collection_View_Focus_Manager_Data *pd, Efl_Ui_Focus_Direction direction, Efl_Ui_Focus_Object *child, Eina_Bool logical)
{ {
MY_DATA_GET(pd->collection, cpd); MY_DATA_GET(pd->collection, cpd);
Efl_Ui_Item *new_item, *item; Efl_Ui_Item *new_item, *item;
unsigned int item_id; uint64_t item_id;
if (!child) if (!child)
child = efl_ui_focus_manager_focus_get(obj); child = efl_ui_focus_manager_focus_get(obj);
@ -2256,14 +2275,15 @@ _efl_ui_collection_view_focus_manager_efl_ui_focus_manager_request_move(Eo *obj,
if (!cpd->manager) return NULL; if (!cpd->manager) return NULL;
if (!item) return NULL; if (!item) return NULL;
item_id = efl_ui_item_index_get(item); if (!_id_from_item(item, &item_id))
return NULL;
if (ITEM_IS_OUTSIDE_VISIBLE(item_id)) if (ITEM_IS_OUTSIDE_VISIBLE(item_id))
{ {
int new_id; int new_id;
new_id = efl_ui_position_manager_entity_relative_item(cpd->manager, new_id = efl_ui_position_manager_entity_relative_item(cpd->manager,
efl_ui_item_index_get(item), item_id,
direction); direction);
if (new_id == -1) if (new_id == -1)
{ {
@ -2271,6 +2291,7 @@ _efl_ui_collection_view_focus_manager_efl_ui_focus_manager_request_move(Eo *obj,
} }
else else
{ {
Efl_Ui_Collection_Item_Lookup *lookup;
#ifdef VIEWPORT_ENABLE #ifdef VIEWPORT_ENABLE
unsigned int i; unsigned int i;
@ -2287,6 +2308,21 @@ _efl_ui_collection_view_focus_manager_efl_ui_focus_manager_request_move(Eo *obj,
if (!new_item) break; // Just in case if (!new_item) break; // Just in case
_assert_item_available(new_item, new_id, cpd); _assert_item_available(new_item, new_id, cpd);
} }
#else
uint64_t search_index = new_id;
lookup = (void*) eina_rbtree_inline_lookup(cpd->cache, &search_index,
sizeof (new_id), _cache_tree_lookup,
NULL);
if (lookup)
{
_assert_item_available(lookup->item.entity, new_id, cpd);
new_item = lookup->item.entity;
}
else
{
ERR("This item cannot get focus right now. It should be visible first.");
new_item = NULL;
}
#endif #endif
} }
} }

View File

@ -53,6 +53,7 @@ class @beta Efl.Ui.Collection_View extends Efl.Ui.Layout_Base implements
Efl.Ui.Scrollable.match_content { set; } Efl.Ui.Scrollable.match_content { set; }
Efl.Ui.Widget_Focus_Manager.focus_manager_create; Efl.Ui.Widget_Focus_Manager.focus_manager_create;
Efl.Ui.Focus.Manager.move; Efl.Ui.Focus.Manager.move;
Efl.Ui.Widget.focus_state_apply;
} }
events { events {
item,realized : Efl.Ui.Item; [[Event triggered when an @Efl.Ui.Item has been provided by the @Efl.Ui.Factory and is about to be used.]] item,realized : Efl.Ui.Item; [[Event triggered when an @Efl.Ui.Item has been provided by the @Efl.Ui.Factory and is about to be used.]]