summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
authorMarcel Hollerbach <mail@marcel-hollerbach.de>2019-08-06 09:34:42 -0400
committerMike Blumenkrantz <zmike@samsung.com>2019-08-06 09:34:42 -0400
commit63d3af3ce938c1efc8b44075075f2caa55a63a49 (patch)
treec86dbf20f7ae54945b82f261d27eb2ee908694b2 /src/lib
parent49e8334024f81017acc37b3aa42d015b0ec500e3 (diff)
efl_ui_collection: implement initial focus behaviour
Summary: the behaviour here is that the next item according to the direction is getting focused. This sounds easy but is quite complex given the fact that the items might be hidden. This is the first draft for this, to see how good it performes. Reviewers: zmike, stefan_schmidt, cedric Reviewed By: zmike Subscribers: #reviewers, #committers Tags: #efl Differential Revision: https://phab.enlightenment.org/D9496
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/elementary/efl_ui_collection.c125
-rw-r--r--src/lib/elementary/efl_ui_collection_focus_manager.eo7
-rw-r--r--src/lib/elementary/efl_ui_position_manager_common.h5
-rw-r--r--src/lib/elementary/efl_ui_position_manager_entity.eo9
-rw-r--r--src/lib/elementary/efl_ui_position_manager_grid.c31
-rw-r--r--src/lib/elementary/efl_ui_position_manager_grid.eo1
-rw-r--r--src/lib/elementary/efl_ui_position_manager_list.c27
-rw-r--r--src/lib/elementary/efl_ui_position_manager_list.eo1
-rw-r--r--src/lib/elementary/meson.build1
9 files changed, 202 insertions, 5 deletions
diff --git a/src/lib/elementary/efl_ui_collection.c b/src/lib/elementary/efl_ui_collection.c
index 2241c5209d..f1c5b568c3 100644
--- a/src/lib/elementary/efl_ui_collection.c
+++ b/src/lib/elementary/efl_ui_collection.c
@@ -11,6 +11,11 @@
11#include <Elementary.h> 11#include <Elementary.h>
12#include "elm_widget.h" 12#include "elm_widget.h"
13#include "elm_priv.h" 13#include "elm_priv.h"
14#include "efl_ui_collection_focus_manager.eo.h"
15
16typedef struct {
17 Eo *collection;
18} Efl_Ui_Collection_Focus_Manager_Data;
14 19
15typedef struct { 20typedef struct {
16 unsigned int last_index; 21 unsigned int last_index;
@@ -138,6 +143,7 @@ typedef struct {
138 Fast_Accessor obj_accessor; 143 Fast_Accessor obj_accessor;
139 Fast_Accessor size_accessor; 144 Fast_Accessor size_accessor;
140 Efl_Gfx_Entity *sizer; 145 Efl_Gfx_Entity *sizer;
146 unsigned int start_id, end_id;
141} Efl_Ui_Collection_Data; 147} Efl_Ui_Collection_Data;
142 148
143static Eina_Bool register_item(Eo *obj, Efl_Ui_Collection_Data *pd, Efl_Ui_Item *item); 149static Eina_Bool register_item(Eo *obj, Efl_Ui_Collection_Data *pd, Efl_Ui_Item *item);
@@ -745,9 +751,20 @@ _pos_content_min_size_changed_cb(void *data EINA_UNUSED, const Efl_Event *ev)
745 flush_min_size(data, pd); 751 flush_min_size(data, pd);
746} 752}
747 753
754static void
755_visible_range_changed_cb(void *data EINA_UNUSED, const Efl_Event *ev)
756{
757 Efl_Ui_Position_Manager_Range_Update *info = ev->info;
758 MY_DATA_GET(data, pd);
759
760 pd->start_id = info->start_id;
761 pd->end_id = info->end_id;
762}
763
748EFL_CALLBACKS_ARRAY_DEFINE(pos_manager_cbs, 764EFL_CALLBACKS_ARRAY_DEFINE(pos_manager_cbs,
749 {EFL_UI_POSITION_MANAGER_ENTITY_EVENT_CONTENT_SIZE_CHANGED, _pos_content_size_changed_cb}, 765 {EFL_UI_POSITION_MANAGER_ENTITY_EVENT_CONTENT_SIZE_CHANGED, _pos_content_size_changed_cb},
750 {EFL_UI_POSITION_MANAGER_ENTITY_EVENT_CONTENT_MIN_SIZE_CHANGED, _pos_content_min_size_changed_cb}, 766 {EFL_UI_POSITION_MANAGER_ENTITY_EVENT_CONTENT_MIN_SIZE_CHANGED, _pos_content_min_size_changed_cb},
767 {EFL_UI_POSITION_MANAGER_ENTITY_EVENT_VISIBLE_RANGE_CHANGED, _visible_range_changed_cb}
751) 768)
752 769
753EOLIAN static void 770EOLIAN static void
@@ -786,8 +803,11 @@ _efl_ui_collection_position_manager_get(const Eo *obj EINA_UNUSED, Efl_Ui_Collec
786EOLIAN static Efl_Ui_Focus_Manager* 803EOLIAN static Efl_Ui_Focus_Manager*
787_efl_ui_collection_efl_ui_widget_focus_manager_focus_manager_create(Eo *obj, Efl_Ui_Collection_Data *pd EINA_UNUSED, Efl_Ui_Focus_Object *root) 804_efl_ui_collection_efl_ui_widget_focus_manager_focus_manager_create(Eo *obj, Efl_Ui_Collection_Data *pd EINA_UNUSED, Efl_Ui_Focus_Object *root)
788{ 805{
789 return efl_add(EFL_UI_FOCUS_MANAGER_CALC_CLASS, obj, 806 Eo *man = efl_add(EFL_UI_COLLECTION_FOCUS_MANAGER_CLASS, obj,
790 efl_ui_focus_manager_root_set(efl_added, root)); 807 efl_ui_focus_manager_root_set(efl_added, root));
808 Efl_Ui_Collection_Focus_Manager_Data *fm_pd = efl_data_scope_safe_get(man, EFL_UI_COLLECTION_FOCUS_MANAGER_CLASS);
809 fm_pd->collection = obj;
810 return man;
791} 811}
792 812
793EOLIAN static Eina_Bool 813EOLIAN static Eina_Bool
@@ -796,6 +816,19 @@ _efl_ui_collection_efl_ui_widget_focus_state_apply(Eo *obj, Efl_Ui_Collection_Da
796 return efl_ui_widget_focus_state_apply(efl_super(obj, MY_CLASS), current_state, configured_state, obj); 816 return efl_ui_widget_focus_state_apply(efl_super(obj, MY_CLASS), current_state, configured_state, obj);
797} 817}
798 818
819static Efl_Ui_Item *
820_find_item(Eo *obj EINA_UNUSED, Efl_Ui_Collection_Data *pd EINA_UNUSED, Eo *focused_element)
821{
822 if (!focused_element) return NULL;
823
824 while (focused_element && !efl_isa(focused_element, EFL_UI_ITEM_CLASS))
825 {
826 focused_element = efl_ui_widget_parent_get(focused_element);
827 }
828
829 return focused_element;
830}
831
799EOLIAN static Efl_Ui_Focus_Object* 832EOLIAN static Efl_Ui_Focus_Object*
800_efl_ui_collection_efl_ui_focus_manager_move(Eo *obj, Efl_Ui_Collection_Data *pd, Efl_Ui_Focus_Direction direction) 833_efl_ui_collection_efl_ui_focus_manager_move(Eo *obj, Efl_Ui_Collection_Data *pd, Efl_Ui_Focus_Direction direction)
801{ 834{
@@ -803,7 +836,10 @@ _efl_ui_collection_efl_ui_focus_manager_move(Eo *obj, Efl_Ui_Collection_Data *pd
803 Eina_Size2D step; 836 Eina_Size2D step;
804 837
805 focus = efl_ui_focus_manager_focus_get(obj); 838 focus = efl_ui_focus_manager_focus_get(obj);
806 if (focus) 839 new_obj = efl_ui_focus_manager_move(efl_super(obj, MY_CLASS), direction);
840 step = efl_gfx_hint_size_combined_min_get(focus);
841
842 if (new_obj)
807 { 843 {
808 /* if this is outside the viewport, then we must bring that in first */ 844 /* if this is outside the viewport, then we must bring that in first */
809 Eina_Rect viewport; 845 Eina_Rect viewport;
@@ -817,8 +853,7 @@ _efl_ui_collection_efl_ui_focus_manager_move(Eo *obj, Efl_Ui_Collection_Data *pd
817 return focus; 853 return focus;
818 } 854 }
819 } 855 }
820 new_obj = efl_ui_focus_manager_move(efl_super(obj, MY_CLASS), direction); 856
821 step = efl_gfx_hint_size_min_get(focus);
822 if (!new_obj) 857 if (!new_obj)
823 { 858 {
824 Eina_Rect pos = efl_gfx_entity_geometry_get(focus); 859 Eina_Rect pos = efl_gfx_entity_geometry_get(focus);
@@ -875,3 +910,83 @@ _efl_ui_collection_efl_ui_focus_manager_move(Eo *obj, Efl_Ui_Collection_Data *pd
875} 910}
876 911
877#include "efl_ui_collection.eo.c" 912#include "efl_ui_collection.eo.c"
913
914#define ITEM_IS_OUTSIDE_VISIBLE(id) id < collection_pd->start_id || id > collection_pd->end_id
915
916static inline void
917_assert_item_available(Eo *item, int new_id, Efl_Ui_Collection_Data *pd)
918{
919 efl_gfx_entity_visible_set(item, EINA_TRUE);
920 efl_gfx_entity_geometry_set(item, efl_ui_position_manager_entity_position_single_item(pd->pos_man, new_id));
921}
922
923EOLIAN static Efl_Ui_Focus_Object*
924_efl_ui_collection_focus_manager_efl_ui_focus_manager_request_move(Eo *obj, Efl_Ui_Collection_Focus_Manager_Data *pd, Efl_Ui_Focus_Direction direction, Efl_Ui_Focus_Object *child, Eina_Bool logical)
925{
926 MY_DATA_GET(pd->collection, collection_pd);
927 Efl_Ui_Item *new_item, *item;
928 unsigned int item_id;
929
930 if (!child)
931 child = efl_ui_focus_manager_focus_get(obj);
932
933 item = _find_item(obj, collection_pd, child);
934
935 //if this is NULL then we are before finalize, we cannot serve any sane value here
936 if (!collection_pd->pos_man) return NULL;
937 EINA_SAFETY_ON_NULL_RETURN_VAL(item, NULL);
938
939 item_id = efl_ui_item_index_get(item);
940
941 if (ITEM_IS_OUTSIDE_VISIBLE(item_id))
942 {
943 int new_id = efl_ui_position_manager_entity_relative_item(collection_pd->pos_man, efl_ui_item_index_get(item), direction);
944 if (new_id == -1)
945 {
946 new_item = NULL;
947 }
948 else
949 {
950 new_item = eina_list_nth(collection_pd->items, new_id);;
951 _assert_item_available(new_item, new_id, collection_pd);
952 }
953 }
954 else
955 {
956 new_item = efl_ui_focus_manager_request_move(efl_super(obj, EFL_UI_COLLECTION_FOCUS_MANAGER_CLASS), direction, child, logical);
957 }
958
959 return new_item;
960}
961
962
963EOLIAN static void
964_efl_ui_collection_focus_manager_efl_ui_focus_manager_manager_focus_set(Eo *obj, Efl_Ui_Collection_Focus_Manager_Data *pd, Efl_Ui_Focus_Object *focus)
965{
966 MY_DATA_GET(pd->collection, collection_pd);
967 Efl_Ui_Item *item;
968 unsigned int item_id;
969
970 if (focus == efl_ui_focus_manager_root_get(obj))
971 {
972 item = eina_list_data_get(collection_pd->items);
973 }
974 else
975 {
976 item = _find_item(obj, collection_pd, focus);
977 }
978
979 //if this is NULL then we are before finalize, we cannot serve any sane value here
980 if (!collection_pd->pos_man) return;
981 EINA_SAFETY_ON_NULL_RETURN(item);
982
983 item_id = efl_ui_item_index_get(item);
984
985 if (ITEM_IS_OUTSIDE_VISIBLE(item_id))
986 {
987 _assert_item_available(item, item_id, collection_pd);
988 }
989 efl_ui_focus_manager_focus_set(efl_super(obj, EFL_UI_COLLECTION_FOCUS_MANAGER_CLASS), focus);
990}
991
992#include "efl_ui_collection_focus_manager.eo.c"
diff --git a/src/lib/elementary/efl_ui_collection_focus_manager.eo b/src/lib/elementary/efl_ui_collection_focus_manager.eo
new file mode 100644
index 0000000000..6fbf57d89a
--- /dev/null
+++ b/src/lib/elementary/efl_ui_collection_focus_manager.eo
@@ -0,0 +1,7 @@
1class @beta Efl.Ui.Collection.Focus_Manager extends Efl.Ui.Focus.Manager_Calc {
2 [[Internal class which implements collection specific behaviour, cannot be used outside of collection]]
3 implements {
4 Efl.Ui.Focus.Manager.manager_focus { set; }
5 Efl.Ui.Focus.Manager.request_move;
6 }
7}
diff --git a/src/lib/elementary/efl_ui_position_manager_common.h b/src/lib/elementary/efl_ui_position_manager_common.h
index 56c7eeef08..7f84087b00 100644
--- a/src/lib/elementary/efl_ui_position_manager_common.h
+++ b/src/lib/elementary/efl_ui_position_manager_common.h
@@ -39,6 +39,11 @@ vis_change_segment(Api_Callback *cb, int a, int b, Eina_Bool flag)
39 EINA_SAFETY_ON_FALSE_RETURN(_fill_buffer(cb, MIN(a,b), len, data) >= 0); 39 EINA_SAFETY_ON_FALSE_RETURN(_fill_buffer(cb, MIN(a,b), len, data) >= 0);
40 } 40 }
41 ent = data[i - MIN(a,b)]; 41 ent = data[i - MIN(a,b)];
42 if (ent && !flag && (efl_ui_focus_object_focus_get(ent) || efl_ui_focus_object_child_focus_get(ent)))
43 {
44 //we should not make focused object invisible, rather move it to some parking lot
45 efl_gfx_entity_position_set(ent, EINA_POSITION2D(-9999,-9999));
46 }
42 if (ent && !efl_ui_focus_object_focus_get(ent)) 47 if (ent && !efl_ui_focus_object_focus_get(ent))
43 { 48 {
44 efl_gfx_entity_visible_set(ent, flag); 49 efl_gfx_entity_visible_set(ent, flag);
diff --git a/src/lib/elementary/efl_ui_position_manager_entity.eo b/src/lib/elementary/efl_ui_position_manager_entity.eo
index 64c68344d8..fb3bb2d14a 100644
--- a/src/lib/elementary/efl_ui_position_manager_entity.eo
+++ b/src/lib/elementary/efl_ui_position_manager_entity.eo
@@ -1,3 +1,4 @@
1import efl_ui;
1 2
2function Efl.Ui.Position_Manager.Batch_Access_Entity { 3function Efl.Ui.Position_Manager.Batch_Access_Entity {
3 [[ Function callback for getting a batch of items]] 4 [[ Function callback for getting a batch of items]]
@@ -114,6 +115,14 @@ interface @beta Efl.Ui.Position_Manager.Entity extends Efl.Ui.Layout_Orientable
114 end_id : int; [[The last item that has a new size]] 115 end_id : int; [[The last item that has a new size]]
115 } 116 }
116 } 117 }
118 relative_item {
119 [[translate the current_id, into a new id which is oriented in the $direction of $current_id. In case that there is no item, -1 is returned]]
120 params {
121 current_id : uint; [[The id where the direction is oriented at]]
122 direction : Efl.Ui.Focus.Direction; [[The direction where the new id is]]
123 }
124 return : int; [[The id of the item in that direction, or -1 if there is no item in that direction]]
125 }
117 } 126 }
118 events { 127 events {
119 content_size,changed : Eina.Size2D; [[Emitted when the aggregate size of all items has changed. This can be used to resize an enclosing Pan object.]] 128 content_size,changed : Eina.Size2D; [[Emitted when the aggregate size of all items has changed. This can be used to resize an enclosing Pan object.]]
diff --git a/src/lib/elementary/efl_ui_position_manager_grid.c b/src/lib/elementary/efl_ui_position_manager_grid.c
index bf8f793d12..909f986f3e 100644
--- a/src/lib/elementary/efl_ui_position_manager_grid.c
+++ b/src/lib/elementary/efl_ui_position_manager_grid.c
@@ -329,4 +329,35 @@ _efl_ui_position_manager_grid_efl_ui_position_manager_entity_position_single_ite
329 return geom; 329 return geom;
330} 330}
331 331
332EOLIAN static int
333_efl_ui_position_manager_grid_efl_ui_position_manager_entity_relative_item(Eo *obj EINA_UNUSED, Efl_Ui_Position_Manager_Grid_Data *pd, unsigned int current_id, Efl_Ui_Focus_Direction direction)
334{
335 int new_id = current_id;
336 switch(direction)
337 {
338 case EFL_UI_FOCUS_DIRECTION_RIGHT:
339 case EFL_UI_FOCUS_DIRECTION_NEXT:
340 new_id += 1;
341 break;
342 case EFL_UI_FOCUS_DIRECTION_LEFT:
343 case EFL_UI_FOCUS_DIRECTION_PREVIOUS:
344 new_id -= 1;
345 break;
346 case EFL_UI_FOCUS_DIRECTION_UP:
347 new_id -= pd->current_display_table.columns;
348 break;
349 case EFL_UI_FOCUS_DIRECTION_DOWN:
350 new_id += pd->current_display_table.columns;
351 break;
352 default:
353 new_id = -1;
354 ERR("Uncaught case!");
355 break;
356 }
357 if (new_id < 0 || new_id > (int)pd->size)
358 return -1;
359 else
360 return new_id;
361}
362
332#include "efl_ui_position_manager_grid.eo.c" 363#include "efl_ui_position_manager_grid.eo.c"
diff --git a/src/lib/elementary/efl_ui_position_manager_grid.eo b/src/lib/elementary/efl_ui_position_manager_grid.eo
index c7aba19da0..164b48ff52 100644
--- a/src/lib/elementary/efl_ui_position_manager_grid.eo
+++ b/src/lib/elementary/efl_ui_position_manager_grid.eo
@@ -12,6 +12,7 @@ class @beta Efl.Ui.Position_Manager.Grid extends Efl.Object implements Efl.Ui.Po
12 Efl.Ui.Position_Manager.Entity.item_removed; 12 Efl.Ui.Position_Manager.Entity.item_removed;
13 Efl.Ui.Position_Manager.Entity.position_single_item; 13 Efl.Ui.Position_Manager.Entity.position_single_item;
14 Efl.Ui.Position_Manager.Entity.item_size_changed; 14 Efl.Ui.Position_Manager.Entity.item_size_changed;
15 Efl.Ui.Position_Manager.Entity.relative_item;
15 Efl.Ui.Layout_Orientable.orientation {set; get;} 16 Efl.Ui.Layout_Orientable.orientation {set; get;}
16 } 17 }
17} 18}
diff --git a/src/lib/elementary/efl_ui_position_manager_list.c b/src/lib/elementary/efl_ui_position_manager_list.c
index e644a77736..d3cd973a06 100644
--- a/src/lib/elementary/efl_ui_position_manager_list.c
+++ b/src/lib/elementary/efl_ui_position_manager_list.c
@@ -407,5 +407,32 @@ _efl_ui_position_manager_list_efl_object_destructor(Eo *obj, Efl_Ui_Position_Man
407 efl_destructor(efl_super(obj, MY_CLASS)); 407 efl_destructor(efl_super(obj, MY_CLASS));
408} 408}
409 409
410EOLIAN static int
411_efl_ui_position_manager_list_efl_ui_position_manager_entity_relative_item(Eo *obj EINA_UNUSED, Efl_Ui_Position_Manager_List_Data *pd, unsigned int current_id, Efl_Ui_Focus_Direction direction)
412{
413 int new_id = current_id;
414 switch(direction)
415 {
416 case EFL_UI_FOCUS_DIRECTION_RIGHT:
417 case EFL_UI_FOCUS_DIRECTION_NEXT:
418 case EFL_UI_FOCUS_DIRECTION_DOWN:
419 new_id += 1;
420 break;
421 case EFL_UI_FOCUS_DIRECTION_LEFT:
422 case EFL_UI_FOCUS_DIRECTION_PREVIOUS:
423 case EFL_UI_FOCUS_DIRECTION_UP:
424 new_id -= 1;
425 break;
426 default:
427 ERR("Uncaught case!");
428 new_id = -1;
429 break;
430 }
431 if (new_id < 0 || new_id > (int)pd->size)
432 return -1;
433 else
434 return new_id;
435}
436
410 437
411#include "efl_ui_position_manager_list.eo.c" 438#include "efl_ui_position_manager_list.eo.c"
diff --git a/src/lib/elementary/efl_ui_position_manager_list.eo b/src/lib/elementary/efl_ui_position_manager_list.eo
index 5295612724..4764424131 100644
--- a/src/lib/elementary/efl_ui_position_manager_list.eo
+++ b/src/lib/elementary/efl_ui_position_manager_list.eo
@@ -13,6 +13,7 @@ class @beta Efl.Ui.Position_Manager.List extends Efl.Object implements Efl.Ui.Po
13 Efl.Ui.Position_Manager.Entity.item_removed; 13 Efl.Ui.Position_Manager.Entity.item_removed;
14 Efl.Ui.Position_Manager.Entity.position_single_item; 14 Efl.Ui.Position_Manager.Entity.position_single_item;
15 Efl.Ui.Position_Manager.Entity.item_size_changed; 15 Efl.Ui.Position_Manager.Entity.item_size_changed;
16 Efl.Ui.Position_Manager.Entity.relative_item;
16 Efl.Ui.Layout_Orientable.orientation {set; get;} 17 Efl.Ui.Layout_Orientable.orientation {set; get;}
17 } 18 }
18} 19}
diff --git a/src/lib/elementary/meson.build b/src/lib/elementary/meson.build
index 8f0c85a12a..e42223682b 100644
--- a/src/lib/elementary/meson.build
+++ b/src/lib/elementary/meson.build
@@ -237,6 +237,7 @@ priv_eo_files = [
237 'efl_ui_exact_model.eo', 237 'efl_ui_exact_model.eo',
238 'efl_ui_average_model.eo', 238 'efl_ui_average_model.eo',
239 'efl_ui_spotlight_manager_plain.eo', 239 'efl_ui_spotlight_manager_plain.eo',
240 'efl_ui_collection_focus_manager.eo',
240] 241]
241 242
242priv_eo_file_target = [] 243priv_eo_file_target = []