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/elm_calendar_item.eo \
lib/elementary/efl_ui_focus_parent_provider.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_standard.eo \
lib/elementary/efl_ui_focus_parent_provider_gen.eo \
$(NULL) $(NULL)
# Legacy classes - not part of public EO API # 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_composition.c \
lib/elementary/efl_ui_focus_parent_provider.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_standard.c \
lib/elementary/efl_ui_focus_parent_provider_gen.c \
$(NULL) $(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 EFL_ACCESS_SELECTION_PROTECTED
#define ELM_INTERFACE_ATSPI_WIDGET_ACTION_PROTECTED #define ELM_INTERFACE_ATSPI_WIDGET_ACTION_PROTECTED
#define ELM_WIDGET_ITEM_PROTECTED #define ELM_WIDGET_ITEM_PROTECTED
#define EFL_UI_FOCUS_COMPOSITION_PROTECTED
#include <Elementary.h> #include <Elementary.h>
#include <Elementary_Cursor.h> #include <Elementary_Cursor.h>
#include "elm_priv.h" #include "elm_priv.h"
#include "elm_widget_gengrid.h" #include "elm_widget_gengrid.h"
#include "elm_interface_scrollable.h" #include "elm_interface_scrollable.h"
#include "efl_ui_focus_parent_provider_gen.eo.h"
#define MY_PAN_CLASS ELM_GENGRID_PAN_CLASS #define MY_PAN_CLASS ELM_GENGRID_PAN_CLASS
@ -1021,6 +1023,7 @@ _item_content_realize(Elm_Gen_Item *it,
Evas_Object *content; Evas_Object *content;
Eina_List *source; Eina_List *source;
const char *key; const char *key;
ELM_GENGRID_DATA_GET(it->base->widget, sd);
if (!parts) if (!parts)
{ {
@ -1050,6 +1053,7 @@ _item_content_realize(Elm_Gen_Item *it,
((void *)WIDGET_ITEM_DATA_GET(EO_OBJ(it)), WIDGET(it), key); ((void *)WIDGET_ITEM_DATA_GET(EO_OBJ(it)), WIDGET(it), key);
if (!content) goto out; if (!content) goto out;
} }
eina_hash_add(sd->content_item_map, &content, it->base->eo_obj);
*contents = eina_list_append(*contents, content); *contents = eina_list_append(*contents, content);
if (!edje_object_part_swallow(target, key, 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; Evas_Object *content;
ELM_GENGRID_ITEM_CHECK_OR_RETURN(it); ELM_GENGRID_ITEM_CHECK_OR_RETURN(it);
ELM_GENGRID_DATA_GET(it->base->widget, sd);
EINA_LIST_FREE (it->contents, content) 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); edje_object_part_unswallow(VIEW(it), content);
evas_object_hide(content); evas_object_hide(content);
if (l) *l = eina_list_append(*l, 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) _content_cache_add(Elm_Gen_Item *it, Eina_List **cache)
{ {
Evas_Object *content = NULL; Evas_Object *content = NULL;
ELM_GENGRID_DATA_GET(it->base->widget, sd);
EINA_LIST_FREE(it->contents, content) EINA_LIST_FREE(it->contents, content)
{ {
*cache = eina_list_append(*cache, content); *cache = eina_list_append(*cache, content);
eina_hash_del_by_key(sd->content_item_map, &content);
} }
return *cache; 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) if (focused)
{ {
sd->last_focused_item = eo_it; sd->last_focused_item = eo_it;
if (!elm_object_focus_get(obj)) if (!elm_object_focus_get(obj))
elm_object_focus_set(obj, EINA_TRUE); elm_object_focus_set(obj, EINA_TRUE);
if (!elm_widget_focus_get(obj))
return;
if (eo_it != sd->focused_item) if (eo_it != sd->focused_item)
{ {
if (sd->focused_item) if (sd->focused_item)
_elm_gengrid_item_unfocused(sd->focused_item); _elm_gengrid_item_unfocused(sd->focused_item);
_elm_gengrid_item_focused(eo_it); _elm_gengrid_item_focused(eo_it);
} }
efl_ui_focus_manager_focus_set(obj, eo_it);
} }
else else
{ {
@ -4028,6 +4037,8 @@ _elm_gengrid_item_new(Elm_Gengrid_Data *sd,
(!strcmp(it->itc->item_style, "group_index")); (!strcmp(it->itc->item_style, "group_index"));
sd->item_count++; sd->item_count++;
efl_ui_focus_composition_dirty(sd->obj);
return it; return it;
} }
@ -4221,6 +4232,14 @@ elm_gengrid_add(Evas_Object *parent)
EOLIAN static Eo * EOLIAN static Eo *
_elm_gengrid_efl_object_constructor(Eo *obj, Elm_Gengrid_Data *sd) _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)); obj = efl_constructor(efl_super(obj, MY_CLASS));
sd->obj = obj; sd->obj = obj;
@ -5661,6 +5680,37 @@ _elm_gengrid_efl_access_selection_child_deselect(Eo *obj EINA_UNUSED, Elm_Gengri
return EINA_FALSE; 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 */ /* Standard widget overrides */
ELM_WIDGET_KEY_DOWN_DEFAULT_IMPLEMENT(elm_gengrid, Elm_Gengrid_Data) 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]] 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.Ui.Clickable, Elm.Interface.Atspi_Widget_Action,
Efl.Access.Selection) Efl.Access.Selection)
{ {
@ -544,6 +544,7 @@ class Elm.Gengrid (Efl.Ui.Layout, Elm.Interface_Scrollable,
implements { implements {
class.constructor; class.constructor;
Efl.Object.constructor; Efl.Object.constructor;
Efl.Object.provider_find;
Efl.Gfx.position { set; } Efl.Gfx.position { set; }
Efl.Gfx.size { set; } Efl.Gfx.size { set; }
Efl.Canvas.Group.group_member_add; 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.is_child_selected;
Efl.Access.Selection.all_children_select; Efl.Access.Selection.all_children_select;
Efl.Access.Selection.clear; Efl.Access.Selection.clear;
Efl.Ui.Focus.Composition.prepare;
Elm.Widget.focus_state_apply;
} }
events { events {
realized; [[Called when gengrid realized]] 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]] [[Elementary gengrid item class]]
legacy_prefix: elm_gengrid_item; legacy_prefix: elm_gengrid_item;

View File

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