bu5hm4n pushed a commit to branch master.

http://git.enlightenment.org/core/efl.git/commit/?id=b364293b0c2238c74a8450c4d27787ebe027b483

commit b364293b0c2238c74a8450c4d27787ebe027b483
Author: Marcel Hollerbach <mar...@osg.samsung.com>
Date:   Sat Nov 11 18:26:53 2017 +0100

    genlist: implement item focus
    
    this implements item-content focus for genlist. feel free to notify me
    if there are any crashes or something simular.
    
    ref T6181
---
 src/lib/elementary/elm_genlist.c        | 105 ++++++++++++++++++++++++++++----
 src/lib/elementary/elm_genlist.eo       |  13 ++--
 src/lib/elementary/elm_genlist_item.eo  |   5 +-
 src/lib/elementary/elm_widget_genlist.h |   3 +
 4 files changed, 108 insertions(+), 18 deletions(-)

diff --git a/src/lib/elementary/elm_genlist.c b/src/lib/elementary/elm_genlist.c
index 6c77edff13..25aa0b1bd5 100644
--- a/src/lib/elementary/elm_genlist.c
+++ b/src/lib/elementary/elm_genlist.c
@@ -8,6 +8,7 @@
 #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>
@@ -15,6 +16,8 @@
 #include "elm_priv.h"
 #include "elm_widget_genlist.h"
 #include "elm_interface_scrollable.h"
+#include "efl_ui_focus_parent_provider_gen.eo.h"
+#include "efl_ui_focus_composition_adapter.eo.h"
 #include "elm_genlist_item.eo.h"
 #include "elm_genlist_pan.eo.h"
 #include "elm_genlist.eo.h"
@@ -403,6 +406,8 @@ _item_content_realize(Elm_Gen_Item *it,
    Eina_List *source;
    const char *key;
 
+   ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
+
    if (!parts)
      {
         EINA_LIST_FREE(*contents, content)
@@ -437,6 +442,7 @@ _item_content_realize(Elm_Gen_Item *it,
 
         if (content != old)
           {
+             eina_hash_add(sd->content_item_map, &content, it->base->eo_obj);
              // FIXME: Genlist item doesn't update its size when the size of
              // content is changed, so deferred calculation for content should
              // be performed before realization.
@@ -472,6 +478,7 @@ out:
           {
              *contents = eina_list_remove(*contents, old);
              evas_object_del(old);
+             eina_hash_del_by_key(sd->content_item_map, &old);
           }
      }
 }
@@ -1684,6 +1691,7 @@ _item_cache_find(Elm_Gen_Item *it)
 static Eina_List *
 _content_cache_add(Elm_Gen_Item *it, Eina_List **cache)
 {
+   ELM_GENLIST_DATA_GET_FROM_ITEM(it, pd);
    Evas_Object *content = NULL;
    EINA_LIST_FREE(it->contents, content)
      {
@@ -1691,6 +1699,7 @@ _content_cache_add(Elm_Gen_Item *it, Eina_List **cache)
           elm_widget_disabled_set(content, EINA_FALSE);
 
         *cache = eina_list_append(*cache, content);
+        eina_hash_del_by_key(pd->content_item_map, &content);
      }
 
    return *cache;
@@ -5786,16 +5795,50 @@ elm_genlist_add(Evas_Object *parent)
    return elm_legacy_add(MY_CLASS, parent);
 }
 
+static void
+_genlist_element_focused(void *data, const Efl_Event *ev)
+{
+   ELM_GENLIST_DATA_GET(data, pd);
+   Elm_Widget *focused = efl_ui_focus_manager_focus_get(ev->object);
+   Elm_Widget_Item *item;
+
+   if (!focused) return;
+
+   if (efl_isa(focused, EFL_UI_FOCUS_COMPOSITION_ADAPTER_CLASS))
+     item = efl_parent_get(focused);
+   else
+     item = efl_ui_focus_parent_provider_find_logical_parent(pd->provider, 
focused);
+
+   if (efl_isa(item, ELM_GENLIST_ITEM_CLASS))
+     {
+        _elm_genlist_item_focused(item);
+        _all_items_deselect(pd);
+        elm_genlist_item_selected_set(item, EINA_TRUE);
+        elm_genlist_item_bring_in(item, ELM_GENLIST_ITEM_SCROLLTO_MIDDLE);
+     }
+}
+
 EOLIAN static Eo *
 _elm_genlist_efl_object_constructor(Eo *obj, Elm_Genlist_Data *sd)
 {
    obj = efl_constructor(efl_super(obj, MY_CLASS));
+
+   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);
+
    sd->obj = obj;
 
    efl_canvas_object_type_set(obj, MY_CLASS_NAME_LEGACY);
    evas_object_smart_callbacks_descriptions_set(obj, _smart_callbacks);
    efl_access_role_set(obj, EFL_ACCESS_ROLE_LIST);
 
+   efl_event_callback_add(obj, EFL_UI_FOCUS_MANAGER_EVENT_FOCUSED, 
_genlist_element_focused, obj);
+
    return obj;
 }
 
@@ -5924,17 +5967,7 @@ _item_select(Elm_Gen_Item *it)
 
    if (!(sd->focus_on_selection_enabled || 
_elm_config->item_select_on_focus_disable))
      {
-        Evas_Object *swallow_obj;
-        Eina_List *l;
-        EINA_LIST_FOREACH(it->contents, l, swallow_obj)
-          {
-             if (elm_widget_is(swallow_obj) && 
elm_object_focus_get(swallow_obj))
-               {
-                  elm_object_focus_set(obj, EINA_FALSE);
-                  elm_object_focus_set(obj, EINA_TRUE);
-                  break;
-               }
-          }
+        efl_ui_focus_manager_focus_set(obj, it->base->eo_obj);
      }
 
    evas_object_unref(obj);
@@ -6191,6 +6224,8 @@ _elm_genlist_item_new(Elm_Genlist_Data *sd,
    it->item->expanded_depth = depth;
    sd->item_count++;
 
+   efl_ui_focus_composition_dirty(sd->obj);
+
    return it;
 }
 
@@ -8702,6 +8737,54 @@ _elm_genlist_efl_access_selection_child_deselect(Eo *obj 
EINA_UNUSED, Elm_Genlis
    return EINA_FALSE;
 }
 
+EOLIAN static Efl_Object*
+_elm_genlist_efl_object_provider_find(Eo *obj, Elm_Genlist_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_GENLIST_CLASS), klass);
+}
+
+EOLIAN static void 
+_elm_genlist_efl_ui_focus_composition_prepare(Eo *obj, Elm_Genlist_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 void 
+_elm_genlist_item_efl_ui_focus_object_prepare_logical(Eo *obj, Elm_Gen_Item 
*pd)
+{
+   Eina_List *n;
+   Elm_Widget *wid;
+
+   _item_realize(pd, pd->item->order_num_in, EINA_FALSE);
+
+   EINA_LIST_FOREACH(pd->contents, n, wid)
+     {
+        if (efl_isa(wid, ELM_WIDGET_CLASS))
+          _elm_widget_full_eval(wid);
+     }
+
+   efl_ui_focus_object_prepare_logical(efl_super(obj, ELM_GENLIST_ITEM_CLASS));
+}
+
+EOLIAN static Eina_Bool 
+_elm_genlist_elm_widget_focus_state_apply(Eo *obj, Elm_Genlist_Data *pd 
EINA_UNUSED, Elm_Widget_Focus_State current_state, Elm_Widget_Focus_State 
*configured_state, Elm_Widget *redirect EINA_UNUSED)
+{
+   return efl_ui_widget_focus_state_apply(efl_super(obj, MY_CLASS), 
current_state, configured_state, obj);
+}
+
 /* Standard widget overrides */
 
 ELM_WIDGET_KEY_DOWN_DEFAULT_IMPLEMENT(elm_genlist, Elm_Genlist_Data)
diff --git a/src/lib/elementary/elm_genlist.eo 
b/src/lib/elementary/elm_genlist.eo
index 52cb44908c..c0460b12ef 100644
--- a/src/lib/elementary/elm_genlist.eo
+++ b/src/lib/elementary/elm_genlist.eo
@@ -2,7 +2,7 @@ import elm_general;
 import elm_list;
 import elm_genlist_item;
 
-class Elm.Genlist (Efl.Ui.Layout, Elm.Interface_Scrollable, Efl.Ui.Clickable,
+class Elm.Genlist (Efl.Ui.Layout, Efl.Ui.Focus.Composition, 
Elm.Interface_Scrollable, Efl.Ui.Clickable,
                    Elm.Interface.Atspi_Widget_Action, Efl.Access.Selection,
                    Efl.Ui.Selectable)
 {
@@ -301,7 +301,7 @@ class Elm.Genlist (Efl.Ui.Layout, Elm.Interface_Scrollable, 
Efl.Ui.Clickable,
 
               This returns a list of the realized items in the genlist.
               The list contains genlist item pointers. The list must be
-              freed by the caller when done with \@ref eina_list_free. The 
+              freed by the caller when done with \@ref eina_list_free. The
               item pointers in the list are only valid so long as those
               items are not deleted or the genlist is not deleted.
             ]]
@@ -331,7 +331,7 @@ class Elm.Genlist (Efl.Ui.Layout, Elm.Interface_Scrollable, 
Efl.Ui.Clickable,
             [[Get the last item in the genlist
 
               This returns the last item in the list.
-              
+
               If filter is set to genlist, it returns
               last filtered item in the list.
             ]]
@@ -532,6 +532,7 @@ class Elm.Genlist (Efl.Ui.Layout, Elm.Interface_Scrollable, 
Efl.Ui.Clickable,
       Efl.Gfx.position { set; }
       Efl.Gfx.size { set; }
       Efl.Canvas.Group.group_member_add;
+      Efl.Object.provider_find;
       Elm.Widget.theme_apply;
       Elm.Widget.widget_sub_object_add;
       Elm.Widget.on_access_update;
@@ -554,6 +555,8 @@ class Elm.Genlist (Efl.Ui.Layout, Elm.Interface_Scrollable, 
Efl.Ui.Clickable,
       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 {
       item,focused; [[Called when genlist item got focus]]
@@ -568,11 +571,11 @@ class Elm.Genlist (Efl.Ui.Layout, 
Elm.Interface_Scrollable, Efl.Ui.Clickable,
       edge,bottom; [[Called when bottom edge is reached]]
       edge,left; [[Called when left edge is reached]]
       edge,right; [[Called when right edge is reached]]
-      moved; [[Called when genlist item moved]] 
+      moved; [[Called when genlist item moved]]
       moved,before; [[Called when genlist item moved before]]
       moved,after; [[Called when genlist item moved after]]
       swipe; [[Called when swipe is detected]]
-      multi,pinch,in; [[Called when multitouch pinch in detected]] 
+      multi,pinch,in; [[Called when multitouch pinch in detected]]
       multi,pinch,out; [[Called when multitouch pinch out detected]]
       multi,swipe,down; [[Called when multitouch swipe down detected]]
       multi,swipe,up; [[Called when multitouch swipe up detected]]
diff --git a/src/lib/elementary/elm_genlist_item.eo 
b/src/lib/elementary/elm_genlist_item.eo
index 87bc3bcff8..64fb0982a6 100644
--- a/src/lib/elementary/elm_genlist_item.eo
+++ b/src/lib/elementary/elm_genlist_item.eo
@@ -38,7 +38,7 @@ enum Elm.Genlist.Item.Scrollto_Type
    bottom = (1 << 3)   [[To the bottom of viewport.]]
 }
 
-class Elm.Genlist.Item(Elm.Widget.Item)
+class Elm.Genlist.Item(Elm.Widget.Item.Static_Focus)
 {
    [[Elementary genlist item class]]
    legacy_prefix: elm_genlist_item;
@@ -223,7 +223,7 @@ class Elm.Genlist.Item(Elm.Widget.Item)
            @property select_mode {
                 get {
                      [[Get the genlist item's select mode.
- 
+
                        It's ELM_OBJECT_SELECT_MODE_MAX on failure.
                      ]]
                 }
@@ -461,5 +461,6 @@ class Elm.Genlist.Item(Elm.Widget.Item)
            Elm.Widget.Item.cursor_unset;
            Efl.Access.name { get; }
            Efl.Access.state_set { get; }
+           Efl.Ui.Focus.Object.prepare_logical;
       }
 }
diff --git a/src/lib/elementary/elm_widget_genlist.h 
b/src/lib/elementary/elm_widget_genlist.h
index 5e81cbe8ac..69c0cb530a 100644
--- a/src/lib/elementary/elm_widget_genlist.h
+++ b/src/lib/elementary/elm_widget_genlist.h
@@ -149,6 +149,9 @@ struct _Elm_Genlist_Data
    Ecore_Idle_Enterer                   *queue_filter_enterer;
    Eina_Hash                             *size_caches;
 
+   Eina_Hash                            *content_item_map;
+   Eo                                   *provider;
+
    Eina_Bool                             filter;
    Eina_Bool                             focus_on_selection_enabled : 1;
    Eina_Bool                             tree_effect_enabled : 1;

-- 


Reply via email to