introduce efl_ui_focus_composition!
authorMarcel Hollerbach <marcel-hollerbach@t-online.de>
Fri, 29 Sep 2017 20:43:37 +0000 (22:43 +0200)
committerMarcel Hollerbach <marcel-hollerbach@t-online.de>
Tue, 10 Oct 2017 17:28:47 +0000 (19:28 +0200)
It does what the class description tells

src/Makefile_Elementary.am
src/lib/elementary/efl_ui_focus_composition.c [new file with mode: 0644]
src/lib/elementary/efl_ui_focus_composition.eo [new file with mode: 0644]
src/lib/elementary/efl_ui_focus_composition_adapter.eo [new file with mode: 0644]

index 656a7df..f763e60 100644 (file)
@@ -148,6 +148,8 @@ elm_public_eolian_files = \
 elm_private_eolian_files = \
        lib/elementary/efl_ui_internal_text_interactive.eo \
        lib/elementary/efl_ui_focus_layer.eo \
+  lib/elementary/efl_ui_focus_composition.eo \
+       lib/elementary/efl_ui_focus_composition_adapter.eo \
        lib/elementary/efl_ui_win_part.eo \
        tests/elementary/focus_test.eo \
        tests/elementary/focus_test_sub_main.eo \
@@ -704,6 +706,7 @@ lib_elementary_libelementary_la_SOURCES = \
        lib/elementary/efl_ui_focus_manager_root_focus.c \
        lib/elementary/efl_ui_textpath.c \
        lib/elementary/efl_ui_focus_layer.c \
+  lib/elementary/efl_ui_focus_composition.c \
        $(NULL)
 
 
diff --git a/src/lib/elementary/efl_ui_focus_composition.c b/src/lib/elementary/efl_ui_focus_composition.c
new file mode 100644 (file)
index 0000000..2673d33
--- /dev/null
@@ -0,0 +1,170 @@
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+
+#include <Elementary.h>
+#include "elm_priv.h"
+#include "efl_ui_focus_composition.eo.h"
+#include "efl_ui_focus_composition_adapter.eo.h"
+
+#define MY_CLASS EFL_UI_FOCUS_COMPOSITION_MIXIN
+
+typedef struct {
+   Eina_List *order, *targets_ordered;
+   Eina_List *register_target, *registered_targets;
+   Eina_List *adapters;
+   Efl_Ui_Focus_Manager *registered;
+} Efl_Ui_Focus_Composition_Data;
+
+static void
+_state_apply(Eo *obj, Efl_Ui_Focus_Composition_Data *pd)
+{
+   if (!pd->registered && pd->registered_targets)
+     {
+        Efl_Ui_Focus_Object *o;
+        //remove all of them
+        EINA_LIST_FREE(pd->registered_targets, o)
+          {
+             efl_ui_focus_manager_calc_unregister(pd->registered, o);
+          }
+     }
+   else if (pd->registered)
+     {
+        Eina_List *n;
+        Efl_Ui_Focus_Object *o;
+        //remove all of them
+        EINA_LIST_FREE(pd->registered_targets, o)
+          {
+             efl_ui_focus_manager_calc_unregister(pd->registered, o);
+          }
+
+        EINA_LIST_FOREACH(pd->register_target, n, o)
+          {
+             efl_ui_focus_manager_calc_register(pd->registered, o, obj, NULL);
+             pd->registered_targets = eina_list_append(pd->registered_targets, o);
+          }
+
+        efl_ui_focus_manager_calc_update_order(pd->registered, obj, eina_list_clone(pd->targets_ordered));
+     }
+}
+
+EOLIAN static void
+_efl_ui_focus_composition_composition_elements_set(Eo *obj, Efl_Ui_Focus_Composition_Data *pd, Eina_List *logical_order)
+{
+   Efl_Ui_Focus_Composition_Adapter *adapter;
+   Evas_Object *elem;
+   Eina_List *n;
+
+   pd->targets_ordered = eina_list_free(pd->targets_ordered);
+   pd->register_target = eina_list_free(pd->register_target);
+
+   pd->order = eina_list_free(pd->order);
+   pd->order = logical_order;
+
+   //get rid of all adapter objects
+   EINA_LIST_FREE(pd->adapters, adapter)
+     {
+        efl_del(adapter);
+     }
+
+   //now build a composition_elements list
+   EINA_LIST_FOREACH(logical_order, n, elem)
+     {
+        Efl_Ui_Focus_Object *o = elem;
+
+        EINA_SAFETY_ON_NULL_GOTO(elem, cont);
+
+        if (!efl_isa(elem, ELM_WIDGET_CLASS))
+          {
+             if (efl_isa(elem, EFL_UI_FOCUS_OBJECT_MIXIN))
+               {
+                  pd->register_target = eina_list_append(pd->register_target , o);
+               }
+             else if (efl_isa(elem, EFL_GFX_INTERFACE))
+               {
+                  o = efl_add(EFL_UI_FOCUS_COMPOSITION_ADAPTER_CLASS, NULL, efl_ui_focus_composition_adapter_canvas_object_set(efl_added, elem));
+
+                  pd->adapters = eina_list_append(pd->adapters, o);
+                  pd->register_target = eina_list_append(pd->register_target , o);
+               }
+             else
+               {
+                  EINA_SAFETY_ERROR("List contains element that is not EFL_UI_FOCUS_OBJECT_MIXIN or EFL_GFX_INTERFACE or ELM_WIDGET_CLASS");
+                  continue;
+               }
+          }
+
+        pd->targets_ordered = eina_list_append(pd->targets_ordered, o);
+cont:
+        continue;
+     }
+   _state_apply(obj, pd);
+}
+
+EOLIAN static Eina_List*
+_efl_ui_focus_composition_composition_elements_get(Eo *obj EINA_UNUSED, Efl_Ui_Focus_Composition_Data *pd)
+{
+   return eina_list_clone(pd->order);
+}
+
+EOLIAN static Eina_Bool
+_efl_ui_focus_composition_elm_widget_focus_state_apply(Eo *obj, Efl_Ui_Focus_Composition_Data *pd, Elm_Widget_Focus_State current_state, Elm_Widget_Focus_State *configured_state, Elm_Widget *redirect)
+{
+   Eina_Bool registered;
+
+   configured_state->logical = EINA_TRUE;
+
+   //shortcut for having the same configurations
+   if (current_state.manager == configured_state->manager && !current_state.manager)
+     return !!current_state.manager;
+
+   if (configured_state->logical == current_state.logical &&
+       configured_state->manager == current_state.manager &&
+       configured_state->parent == current_state.parent)
+     return !!current_state.manager;
+
+   registered = elm_obj_widget_focus_state_apply(efl_super(obj, MY_CLASS), current_state, configured_state, redirect);
+
+   if (registered)
+     pd->registered = configured_state->manager;
+   else
+     pd->registered = NULL;
+
+   _state_apply(obj, pd);
+
+   return registered;
+}
+
+#include "efl_ui_focus_composition.eo.c"
+
+typedef struct {
+   Evas_Object *object;
+}  Efl_Ui_Focus_Composition_Adapter_Data;
+
+EOLIAN static void
+_efl_ui_focus_composition_adapter_canvas_object_set(Eo *obj EINA_UNUSED, Efl_Ui_Focus_Composition_Adapter_Data *pd, Efl_Canvas_Object *v)
+{
+   pd->object = v;
+}
+
+EOLIAN static Efl_Canvas_Object*
+_efl_ui_focus_composition_adapter_canvas_object_get(Eo *obj EINA_UNUSED, Efl_Ui_Focus_Composition_Adapter_Data *pd)
+{
+   return pd->object;
+}
+
+EOLIAN static Eina_Rect
+_efl_ui_focus_composition_adapter_efl_ui_focus_object_focus_geometry_get(Eo *obj EINA_UNUSED, Efl_Ui_Focus_Composition_Adapter_Data *pd EINA_UNUSED)
+{
+   return efl_gfx_geometry_get(pd->object);
+}
+
+EOLIAN static void
+_efl_ui_focus_composition_adapter_efl_ui_focus_object_focus_set(Eo *obj EINA_UNUSED, Efl_Ui_Focus_Composition_Adapter_Data *pd, Eina_Bool focus)
+{
+   efl_ui_focus_object_focus_set(efl_super(obj, EFL_UI_FOCUS_COMPOSITION_ADAPTER_CLASS), focus);
+
+   evas_object_focus_set(pd->object, efl_ui_focus_object_focus_get(obj));
+}
+
+#include "efl_ui_focus_composition_adapter.eo.c"
diff --git a/src/lib/elementary/efl_ui_focus_composition.eo b/src/lib/elementary/efl_ui_focus_composition.eo
new file mode 100644 (file)
index 0000000..2f7cb8e
--- /dev/null
@@ -0,0 +1,26 @@
+mixin Efl.Ui.Focus.Composition (Efl.Interface, Elm.Widget ) {
+   [[This defines the inheriting widget as Composition widget.
+
+     A composition widget is a widget that is just the logical parent of a other set of widgets thet can be used as interaction.
+   ]]
+   methods {
+      @property composition_elements @protected  {
+         [[Set the order of elements that will be used for composition
+
+           Elements of the list can be either A Elm.Widget, A Efl.Ui.Focus.Object, or a Efl.Gfx.
+
+           If the element is a Efl.Gfx, then the geometry is used as focus geomtry, the focus property is redirected to the evas focus property. The mixin will take care of reistering.
+
+           If the element is a Efl.Ui.Focus.Object, then the mixin will take care of registering the element.
+
+           For the case that the element is a Elm.Widget nothing is done and the widget is just part of the order.
+         ]]
+         values {
+            logical_order : list<Efl.Gfx> @owned; [[The order to use]]
+         }
+      }
+   }
+   implements {
+      Elm.Widget.focus_state_apply;
+   }
+}
diff --git a/src/lib/elementary/efl_ui_focus_composition_adapter.eo b/src/lib/elementary/efl_ui_focus_composition_adapter.eo
new file mode 100644 (file)
index 0000000..016d5d9
--- /dev/null
@@ -0,0 +1,14 @@
+class Efl.Ui.Focus.Composition.Adapter (Efl.Object, Efl.Ui.Focus.Object)
+{
+   methods {
+      @property canvas_object {
+         values {
+            v : Efl.Canvas.Object;
+         }
+      }
+   }
+   implements {
+     Efl.Ui.Focus.Object.focus_geometry {get;}
+     Efl.Ui.Focus.Object.focus {set;}
+   }
+}