efl_ui_focus_graph: add a new way for calculating relations

this fixes the testsuite, and brings better relations back.
This commit is contained in:
Marcel Hollerbach 2018-05-02 18:24:14 +02:00
parent cd0bd865eb
commit b2437c0339
2 changed files with 113 additions and 27 deletions

View File

@ -8,6 +8,12 @@
#include "elm_priv.h" #include "elm_priv.h"
#include "efl_ui_focus_graph.h" #include "efl_ui_focus_graph.h"
typedef enum {
Q_TOP = 1, Q_RIGHT = 2, Q_LEFT = 4, Q_BOTTOM = 8, Q_LAST = 16
} Quadrant;
Quadrant q_helper[] = {Q_TOP, Q_RIGHT, Q_LEFT, Q_BOTTOM};
static inline Efl_Ui_Focus_Object* static inline Efl_Ui_Focus_Object*
_convert(Efl_Ui_Focus_Graph_Context *ctx, Opaque_Graph_Member *member) _convert(Efl_Ui_Focus_Graph_Context *ctx, Opaque_Graph_Member *member)
{ {
@ -28,64 +34,143 @@ _minus(Eina_Position2D r1, Eina_Position2D r2)
} }
static inline unsigned int static inline unsigned int
_order(Eina_Position2D pos) _distance(Eina_Rect o, Eina_Rect r2, Quadrant q)
{ {
return pow(pos.x, 2) + pow(pos.y, 2); int res = INT_MAX;
if (q == Q_TOP)
res = o.y - eina_rectangle_max_y(&r2.rect);
else if (q == Q_LEFT)
res = o.x - eina_rectangle_max_x(&r2.rect);
else if (q == Q_BOTTOM)
res = r2.y - eina_rectangle_max_y(&o.rect);
else if (q == Q_RIGHT)
res = r2.x - eina_rectangle_max_x(&o.rect);
return res;
} }
static inline Efl_Ui_Focus_Graph_Calc_Direction_Result* static inline Efl_Ui_Focus_Graph_Calc_Direction_Result*
_quadrant_get(Eina_Position2D pos, Efl_Ui_Focus_Graph_Calc_Result *result) _result_get(Quadrant q, Efl_Ui_Focus_Graph_Calc_Result *result)
{ {
if (pos.y > abs(pos.x)) return &result->top; if (q == Q_TOP) return &result->top;
else if (pos.x >= abs(pos.y)) return &result->left; else if (q == Q_LEFT) return &result->left;
else if (pos.y < -abs(pos.x)) return &result->bottom; else if (q == Q_BOTTOM) return &result->bottom;
else if (pos.y >= -abs(pos.x)) return &result->right; else if (q == Q_RIGHT) return &result->right;
else return NULL; else return NULL;
} }
typedef struct { static inline void
unsigned int distance; _quadrant_get(Eina_Rect origin, Eina_Rect elem, Quadrant *all, Quadrant *clean)
} Direction_Calc_Result; {
int dis = 0;
*clean = 0;
*all = 0;
if (eina_rectangle_max_y(&elem.rect) <= origin.y)
{
dis = origin.y - elem.y;
if (eina_spans_intersect(origin.x - dis, 2*dis + origin.w, elem.x, elem.w))
*all |= Q_TOP;
if (eina_spans_intersect(origin.x, origin.w, elem.x, elem.w))
*clean |= Q_TOP;
}
if (elem.y >= eina_rectangle_max_y(&origin.rect))
{
dis = eina_rectangle_max_y(&elem.rect) - origin.y;
if (eina_spans_intersect(origin.x - dis, 2*dis + origin.w, elem.x, elem.w))
*all |= Q_BOTTOM;
if (eina_spans_intersect(origin.x, origin.w, elem.x, elem.w))
*clean |= Q_BOTTOM;
}
if (elem.x >= eina_rectangle_max_x(&origin.rect))
{
dis = eina_rectangle_max_x(&elem.rect) - origin.x;
if (eina_spans_intersect(origin.y - dis, 2*dis + origin.h, elem.y, elem.h))
*all |= Q_RIGHT;
if (eina_spans_intersect(origin.y, origin.h, elem.y, elem.h))
*clean |= Q_RIGHT;
}
if (eina_rectangle_max_x(&elem.rect) <= origin.x)
{
dis = origin.x - elem.x;
if (eina_spans_intersect(origin.y - dis, 2*dis + origin.h, elem.y, elem.h))
*all |= Q_LEFT;
if (eina_spans_intersect(origin.y, origin.h, elem.y, elem.h))
*clean |= Q_LEFT;
}
}
void void
efl_ui_focus_graph_calc(Efl_Ui_Focus_Graph_Context *ctx, Eina_Iterator *nodes, Opaque_Graph_Member *origin_obj, Efl_Ui_Focus_Graph_Calc_Result *result) efl_ui_focus_graph_calc(Efl_Ui_Focus_Graph_Context *ctx, Eina_Iterator *nodes, Opaque_Graph_Member *origin_obj, Efl_Ui_Focus_Graph_Calc_Result *result)
{ {
Opaque_Graph_Member *elem_obj; Opaque_Graph_Member *elem_obj;
Eina_Position2D origin_pos, elem_pos, relative_pos;
Eina_Rect origin, elem; Eina_Rect origin, elem;
memset(result, 0, sizeof(Efl_Ui_Focus_Graph_Calc_Result)); for (int i = 0; i < 4; ++i)
{
Efl_Ui_Focus_Graph_Calc_Direction_Result *res;
res = _result_get(q_helper[i], result);
res->clean = EINA_FALSE;
res->distance = INT_MAX;
res->relation = NULL;
}
origin = efl_ui_focus_object_focus_geometry_get(_convert(ctx, origin_obj)); origin = efl_ui_focus_object_focus_geometry_get(_convert(ctx, origin_obj));
origin_pos = _middle(origin);
//printf("=========> CALCING %p %s\n", _convert(ctx, origin_obj), elm_object_text_get(_convert(ctx, origin_obj)));
EINA_ITERATOR_FOREACH(nodes, elem_obj) EINA_ITERATOR_FOREACH(nodes, elem_obj)
{ {
Efl_Ui_Focus_Graph_Calc_Direction_Result *res; Efl_Ui_Focus_Graph_Calc_Direction_Result *res;
unsigned int distance; unsigned int distance;
Quadrant all;
Quadrant clean;
if (elem_obj == origin_obj) continue; if (elem_obj == origin_obj) continue;
elem = efl_ui_focus_object_focus_geometry_get(_convert(ctx, elem_obj)); elem = efl_ui_focus_object_focus_geometry_get(_convert(ctx, elem_obj));
elem_pos = _middle(elem);
relative_pos = _minus(elem_pos, origin_pos);
distance = _order(relative_pos);
res = _quadrant_get(relative_pos, result);
EINA_SAFETY_ON_NULL_GOTO(res, cont);
if (res->distance > distance || res->distance == 0) if (eina_rectangle_intersection(&origin.rect, &elem.rect)) continue;
_quadrant_get(origin, elem, &all, &clean);
for (int i = 0; i < 4; ++i)
{ {
res->relation = eina_list_free(res->relation); if (q_helper[i] & all)
res->relation = eina_list_append(res->relation, elem_obj); {
res->distance = distance; res = _result_get(q_helper[i], result);
} EINA_SAFETY_ON_NULL_GOTO(res, cont);
else if (res->distance == distance)
{ distance = _distance(origin, elem, q_helper[i]);
res->relation = eina_list_append(res->relation, elem_obj);
if ((res->distance > distance && res->clean == (q_helper[i] & clean)) ||
(!res->clean && q_helper[i] & clean))
{
res->relation = eina_list_free(res->relation);
res->relation = eina_list_append(res->relation, elem_obj);
res->distance = distance;
res->clean = q_helper[i] & clean;
//printf("=========> %p BETTER_NOW %d \t %p %s\n", res, distance, origin_obj, elm_object_text_get(_convert(ctx, elem_obj)));
}
else if (res->distance == distance)
{
res->relation = eina_list_append(res->relation, elem_obj);
//printf("=========> %p BETTER_NOW_ADD %d \t %p %s\n", res, distance, origin_obj, elm_object_text_get(_convert(ctx, elem_obj)));
}
}
} }
continue; continue;
cont: cont:
printf("%d - %d\n", relative_pos.x, relative_pos.y);
continue; continue;
} }
} }

View File

@ -10,6 +10,7 @@ typedef struct _Opaque_Graph_Memeber Opaque_Graph_Member;
typedef struct { typedef struct {
Eina_List *relation; Eina_List *relation;
Eina_Bool clean;
unsigned int distance; unsigned int distance;
} Efl_Ui_Focus_Graph_Calc_Direction_Result; } Efl_Ui_Focus_Graph_Calc_Direction_Result;