elm_gengrid: implement item-content-focus

#finally

For now we focus the widgets of a item, the item content can be cycled
by tab / Ctrl + tab. up/down/right/left are for now handled by gengrid
and move the focused item (everything else feels super weird with
multiple contents in a item)

ref T6181
This commit is contained in:
Marcel Hollerbach 2017-10-15 15:35:42 +02:00
parent 38d41b4a2b
commit 18194f343e
7 changed files with 150 additions and 5 deletions

View File

@ -157,6 +157,7 @@ elm_private_eolian_files = \
lib/elementary/elm_calendar_item.eo \
lib/elementary/efl_ui_focus_parent_provider.eo \
lib/elementary/efl_ui_focus_parent_provider_standard.eo \
lib/elementary/efl_ui_focus_parent_provider_gen.eo \
$(NULL)
# Legacy classes - not part of public EO API
@ -712,6 +713,7 @@ lib_elementary_libelementary_la_SOURCES = \
lib/elementary/efl_ui_focus_composition.c \
lib/elementary/efl_ui_focus_parent_provider.c \
lib/elementary/efl_ui_focus_parent_provider_standard.c \
lib/elementary/efl_ui_focus_parent_provider_gen.c \
$(NULL)

View File

@ -0,0 +1,70 @@
#ifdef HAVE_CONFIG_H
# include "elementary_config.h"
#endif
#include <Elementary.h>
#include "elm_priv.h"
#include "efl_ui_focus_parent_provider_gen.eo.h"
typedef struct {
Eina_Hash *map;
Elm_Widget *container;
Efl_Ui_Focus_Parent_Provider *provider;
} Efl_Ui_Focus_Parent_Provider_Gen_Data;
EOLIAN static void
_efl_ui_focus_parent_provider_gen_content_item_map_set(Eo *obj, Efl_Ui_Focus_Parent_Provider_Gen_Data *pd, Eina_Hash *map)
{
EINA_SAFETY_ON_TRUE_RETURN(efl_finalized_get(obj));
pd->map = map;
}
EOLIAN static Eina_Hash*
_efl_ui_focus_parent_provider_gen_content_item_map_get(Eo *obj EINA_UNUSED, Efl_Ui_Focus_Parent_Provider_Gen_Data *pd)
{
return pd->map;
}
EOLIAN static void
_efl_ui_focus_parent_provider_gen_container_set(Eo *obj, Efl_Ui_Focus_Parent_Provider_Gen_Data *pd, Elm_Widget *container)
{
EINA_SAFETY_ON_TRUE_RETURN(efl_finalized_get(obj));
pd->container = container;
EINA_SAFETY_ON_NULL_RETURN(efl_parent_get(pd->container));
pd->provider = efl_provider_find(efl_parent_get(pd->container), EFL_UI_FOCUS_PARENT_PROVIDER_INTERFACE);
}
EOLIAN static Elm_Widget*
_efl_ui_focus_parent_provider_gen_container_get(Eo *obj EINA_UNUSED, Efl_Ui_Focus_Parent_Provider_Gen_Data *pd)
{
return pd->container;
}
EOLIAN static Efl_Ui_Focus_Object*
_efl_ui_focus_parent_provider_gen_efl_ui_focus_parent_provider_find_logical_parent(Eo *obj EINA_UNUSED, Efl_Ui_Focus_Parent_Provider_Gen_Data *pd EINA_UNUSED, Efl_Ui_Focus_Object *widget)
{
//first check if this item is in the map
Elm_Widget_Item *item;
item = eina_hash_find(pd->map, &widget);
efl_ui_focus_composition_elements_flush(pd->container);
// We dont have a map entry
if (!item)
{
return efl_ui_focus_parent_provider_find_logical_parent(pd->provider, widget);
}
else
{
return item;
}
}
#include "efl_ui_focus_parent_provider_gen.eo.c"

View File

@ -0,0 +1,17 @@
class Efl.Ui.Focus.Parent_Provider.Gen(Efl.Object, Efl.Ui.Focus.Parent_Provider) {
methods {
@property content_item_map {
values {
map : hash<Elm.Widget, Elm.Widget.Item>;
}
}
@property container {
values {
container : Elm.Widget;
}
}
}
implements {
Efl.Ui.Focus.Parent_Provider.find_logical_parent;
}
}

View File

@ -6,12 +6,14 @@
#define EFL_ACCESS_SELECTION_PROTECTED
#define ELM_INTERFACE_ATSPI_WIDGET_ACTION_PROTECTED
#define ELM_WIDGET_ITEM_PROTECTED
#define EFL_UI_FOCUS_COMPOSITION_PROTECTED
#include <Elementary.h>
#include <Elementary_Cursor.h>
#include "elm_priv.h"
#include "elm_widget_gengrid.h"
#include "elm_interface_scrollable.h"
#include "efl_ui_focus_parent_provider_gen.eo.h"
#define MY_PAN_CLASS ELM_GENGRID_PAN_CLASS
@ -1021,6 +1023,7 @@ _item_content_realize(Elm_Gen_Item *it,
Evas_Object *content;
Eina_List *source;
const char *key;
ELM_GENGRID_DATA_GET(it->base->widget, sd);
if (!parts)
{
@ -1050,6 +1053,7 @@ _item_content_realize(Elm_Gen_Item *it,
((void *)WIDGET_ITEM_DATA_GET(EO_OBJ(it)), WIDGET(it), key);
if (!content) goto out;
}
eina_hash_add(sd->content_item_map, &content, it->base->eo_obj);
*contents = eina_list_append(*contents, content);
if (!edje_object_part_swallow(target, key, content))
{
@ -1177,6 +1181,7 @@ _elm_gengrid_item_all_contents_unset(Eo *eo_item EINA_UNUSED, Elm_Gen_Item *it,
Evas_Object *content;
ELM_GENGRID_ITEM_CHECK_OR_RETURN(it);
ELM_GENGRID_DATA_GET(it->base->widget, sd);
EINA_LIST_FREE (it->contents, content)
{
@ -1186,6 +1191,8 @@ _elm_gengrid_item_all_contents_unset(Eo *eo_item EINA_UNUSED, Elm_Gen_Item *it,
edje_object_part_unswallow(VIEW(it), content);
evas_object_hide(content);
if (l) *l = eina_list_append(*l, content);
eina_hash_del_by_key(sd->content_item_map, &content);
}
}
@ -1413,9 +1420,11 @@ static Eina_List *
_content_cache_add(Elm_Gen_Item *it, Eina_List **cache)
{
Evas_Object *content = NULL;
ELM_GENGRID_DATA_GET(it->base->widget, sd);
EINA_LIST_FREE(it->contents, content)
{
*cache = eina_list_append(*cache, content);
eina_hash_del_by_key(sd->content_item_map, &content);
}
return *cache;
@ -3831,18 +3840,18 @@ _elm_gengrid_item_elm_widget_item_focus_set(Eo *eo_it, Elm_Gen_Item *it, Eina_Bo
if (focused)
{
sd->last_focused_item = eo_it;
if (!elm_object_focus_get(obj))
elm_object_focus_set(obj, EINA_TRUE);
if (!elm_widget_focus_get(obj))
return;
if (eo_it != sd->focused_item)
{
if (sd->focused_item)
_elm_gengrid_item_unfocused(sd->focused_item);
_elm_gengrid_item_focused(eo_it);
}
efl_ui_focus_manager_focus_set(obj, eo_it);
}
else
{
@ -4028,6 +4037,8 @@ _elm_gengrid_item_new(Elm_Gengrid_Data *sd,
(!strcmp(it->itc->item_style, "group_index"));
sd->item_count++;
efl_ui_focus_composition_dirty(sd->obj);
return it;
}
@ -4221,6 +4232,14 @@ elm_gengrid_add(Evas_Object *parent)
EOLIAN static Eo *
_elm_gengrid_efl_object_constructor(Eo *obj, Elm_Gengrid_Data *sd)
{
sd->content_item_map = eina_hash_pointer_new(NULL);
sd->provider = efl_add(EFL_UI_FOCUS_PARENT_PROVIDER_GEN_CLASS, obj,
efl_ui_focus_parent_provider_gen_container_set(efl_added, obj),
efl_ui_focus_parent_provider_gen_content_item_map_set(efl_added, sd->content_item_map));
efl_ui_focus_composition_custom_manager_set(obj, obj);
efl_ui_focus_composition_logical_mode_set(obj, EINA_TRUE);
obj = efl_constructor(efl_super(obj, MY_CLASS));
sd->obj = obj;
@ -5661,6 +5680,37 @@ _elm_gengrid_efl_access_selection_child_deselect(Eo *obj EINA_UNUSED, Elm_Gengri
return EINA_FALSE;
}
EOLIAN static Efl_Object*
_elm_gengrid_efl_object_provider_find(Eo *obj, Elm_Gengrid_Data *pd, const Efl_Object *klass)
{
if (klass == EFL_UI_FOCUS_PARENT_PROVIDER_INTERFACE)
return pd->provider;
return efl_provider_find(efl_super(obj, ELM_GENGRID_CLASS), klass);
}
EOLIAN static void
_elm_gengrid_efl_ui_focus_composition_prepare(Eo *obj, Elm_Gengrid_Data *pd)
{
Elm_Gen_Item *item;
Eina_List *order = NULL;
EINA_INLIST_FOREACH(pd->items, item)
{
if (item->base->disabled)
continue;
order = eina_list_append(order, item->base->eo_obj);
}
efl_ui_focus_composition_elements_set(obj, order);
}
EOLIAN static Eina_Bool
_elm_gengrid_elm_widget_focus_state_apply(Eo *obj, Elm_Gengrid_Data *pd EINA_UNUSED, Elm_Widget_Focus_State current_state, Elm_Widget_Focus_State *configured_state, Elm_Widget *redirect EINA_UNUSED)
{
return elm_obj_widget_focus_state_apply(efl_super(obj, MY_CLASS), current_state, configured_state, obj);
}
/* Standard widget overrides */
ELM_WIDGET_KEY_DOWN_DEFAULT_IMPLEMENT(elm_gengrid, Elm_Gengrid_Data)

View File

@ -10,7 +10,7 @@ enum Elm.Gengrid.Reorder_Type
swap [[Swap reorder type]]
}
class Elm.Gengrid (Efl.Ui.Layout, Elm.Interface_Scrollable,
class Elm.Gengrid (Efl.Ui.Layout, Efl.Ui.Focus.Composition, Elm.Interface_Scrollable,
Efl.Ui.Clickable, Elm.Interface.Atspi_Widget_Action,
Efl.Access.Selection)
{
@ -544,6 +544,7 @@ class Elm.Gengrid (Efl.Ui.Layout, Elm.Interface_Scrollable,
implements {
class.constructor;
Efl.Object.constructor;
Efl.Object.provider_find;
Efl.Gfx.position { set; }
Efl.Gfx.size { set; }
Efl.Canvas.Group.group_member_add;
@ -568,6 +569,8 @@ class Elm.Gengrid (Efl.Ui.Layout, Elm.Interface_Scrollable,
Efl.Access.Selection.is_child_selected;
Efl.Access.Selection.all_children_select;
Efl.Access.Selection.clear;
Efl.Ui.Focus.Composition.prepare;
Elm.Widget.focus_state_apply;
}
events {
realized; [[Called when gengrid realized]]

View File

@ -25,7 +25,7 @@ enum Elm.Gengrid.Item.Field_Type
}
class Elm.Gengrid.Item(Elm.Widget.Item)
class Elm.Gengrid.Item(Elm.Widget.Item, Efl.Ui.Focus.Object)
{
[[Elementary gengrid item class]]
legacy_prefix: elm_gengrid_item;

View File

@ -50,6 +50,9 @@ struct _Elm_Gengrid_Data
Elm_Object_Item *bring_in_it;
Elm_Gengrid_Item_Scrollto_Type scroll_to_type;
Eina_Hash *content_item_map;
Eo *provider;
Ecore_Job *calc_job;
int walking;
int item_width, item_height;