elementar/focus : New feature - focus movement in all direction. By

using elm_widget_focus_direction_go function, focus will be moved from
the current focused object to the near object in one direction.
Direction can be set by degree(for easy usability). Degree changes
clockwise, i.e. 0 means UP, 90 means RIGHT, 180 means DOWN, and 270
means LEFT. You can select any direction by changing this degree.


SVN revision: 70681
This commit is contained in:
WooHyun Jung 2012-05-03 03:02:54 +00:00
parent c0f2f4be91
commit f83917a420
12 changed files with 731 additions and 20 deletions

View File

@ -26,3 +26,8 @@
* Font: actually it doesnt append the font to the hash when font_hash is
created inside. Now it is fixed.
2012-05-03 WooHyun Jung
* Add feature about focus. Focus can be moved in all direction by
by elm_widget_focus_go function.

View File

@ -5,6 +5,8 @@ Changes since Elementary 1.0.0:
Additions:
* Focus can be moved in all directions by elm_widget_focus_go function.
Fixes:
* Genlist : Fixed genlist expandable effect bug when we expand/contract items with many children very quickly.

View File

@ -80,7 +80,7 @@ test_focus(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info
{
Evas_Object *lb = elm_label_add(win);
elm_object_text_set(lb, "<b>Use Tab or Shift+Tab</b>");
elm_object_text_set(lb, "<b>Use Tab or Shift+Tab<br/>or Arrow keys</b>");
evas_object_size_hint_weight_set(lb, 0.0, 0.0);
evas_object_size_hint_align_set(lb, EVAS_HINT_FILL,
EVAS_HINT_FILL);

View File

@ -127,6 +127,31 @@ _elm_box_focus_next_hook(const Evas_Object *obj, Elm_Focus_Direction dir, Evas_O
return elm_widget_focus_list_next_get(obj, items, list_data_get, dir, next);
}
static Eina_Bool
_elm_box_focus_direction_hook(const Evas_Object *obj, const Evas_Object *base, double degree,
Evas_Object **direction, double *weight)
{
Widget_Data *wd = elm_widget_data_get(obj);
const Eina_List *items;
void *(*list_data_get) (const Eina_List *list);
if ((!wd) || (!wd->box))
return EINA_FALSE;
if ((items = elm_widget_focus_custom_chain_get(obj)))
list_data_get = eina_list_data_get;
else
{
Evas_Object_Box_Data *bd = evas_object_smart_data_get(wd->box);
items = bd->children;
list_data_get = _elm_box_list_data_get;
if (!items) return EINA_FALSE;
}
return elm_widget_focus_list_direction_get(obj, base, items, list_data_get, degree,
direction, weight);
}
static void
_theme_hook(Evas_Object *obj)
{
@ -360,6 +385,7 @@ elm_box_add(Evas_Object *parent)
elm_widget_del_hook_set(obj, _del_hook);
elm_widget_del_pre_hook_set(obj, _del_pre_hook);
elm_widget_focus_next_hook_set(obj, _elm_box_focus_next_hook);
elm_widget_focus_direction_hook_set(obj, _elm_box_focus_direction_hook);
elm_widget_can_focus_set(obj, EINA_FALSE);
elm_widget_highlight_ignore_set(obj, EINA_TRUE);
elm_widget_theme_hook_set(obj, _theme_hook);

View File

@ -213,6 +213,19 @@ _elm_bubble_focus_next_hook(const Evas_Object *obj, Elm_Focus_Direction dir, Eva
return elm_widget_focus_next_get(cur, dir, next);
}
static Eina_Bool
_elm_bubble_focus_direction_hook(const Evas_Object *obj, const Evas_Object *base, double degree,
Evas_Object **direction, double *weight)
{
Widget_Data *wd = elm_widget_data_get(obj);
if ((!wd) || (!wd->content))
return EINA_FALSE;
/* Try Focus cycle in subitem */
return elm_widget_focus_direction_get(wd->content, base, degree, direction, weight);
}
static void
_sizing_eval(Evas_Object *obj)
{
@ -322,6 +335,7 @@ elm_bubble_add(Evas_Object *parent)
elm_widget_del_hook_set(obj, _del_hook);
elm_widget_theme_hook_set(obj, _theme_hook);
elm_widget_focus_next_hook_set(obj, _elm_bubble_focus_next_hook);
elm_widget_focus_direction_hook_set(obj, _elm_bubble_focus_direction_hook);
elm_widget_can_focus_set(obj, EINA_FALSE);
elm_widget_text_set_hook_set(obj, _elm_bubble_label_set);
elm_widget_text_get_hook_set(obj, _elm_bubble_label_get);

View File

@ -77,6 +77,19 @@ _elm_frame_focus_next_hook(const Evas_Object *obj, Elm_Focus_Direction dir, Evas
return elm_widget_focus_next_get(wd->content, dir, next);
}
static Eina_Bool
_elm_frame_focus_direction_hook(const Evas_Object *obj, const Evas_Object *base, double degree,
Evas_Object **direction, double *weight)
{
Widget_Data *wd = elm_widget_data_get(obj);
if ((!wd) || (!wd->content))
return EINA_FALSE;
/* Try Focus cycle in subitem */
return elm_widget_focus_direction_get(wd->content, base, degree, direction, weight);
}
static void
_sizing_eval(Evas_Object *obj)
{
@ -240,6 +253,7 @@ elm_frame_add(Evas_Object *parent)
elm_widget_del_hook_set(obj, _del_hook);
elm_widget_theme_hook_set(obj, _theme_hook);
elm_widget_focus_next_hook_set(obj, _elm_frame_focus_next_hook);
elm_widget_focus_direction_hook_set(obj, _elm_frame_focus_direction_hook);
elm_widget_can_focus_set(obj, EINA_FALSE);
elm_widget_text_set_hook_set(obj, _elm_frame_label_set);
elm_widget_text_get_hook_set(obj, _elm_frame_label_get);

View File

@ -180,6 +180,32 @@ _elm_layout_focus_next_hook(const Evas_Object *obj, Elm_Focus_Direction dir, Eva
next);
}
static Eina_Bool
_elm_layout_focus_direction_hook(const Evas_Object *obj, const Evas_Object *base, double degree,
Evas_Object **direction, double *weight)
{
Widget_Data *wd = elm_widget_data_get(obj);
const Eina_List *items;
void *(*list_data_get) (const Eina_List *list);
if ((!wd) || (!wd->subs))
return EINA_FALSE;
/* Focus chain (This block is diferent of elm_win cycle)*/
if ((items = elm_widget_focus_custom_chain_get(obj)))
list_data_get = eina_list_data_get;
else
{
items = wd->subs;
list_data_get = _elm_layout_list_data_get;
if (!items) return EINA_FALSE;
}
return elm_widget_focus_list_direction_get(obj, base, items, list_data_get, degree,
direction, weight);
}
static void
_sizing_eval(Widget_Data *wd)
{
@ -458,6 +484,7 @@ elm_layout_add(Evas_Object *parent)
elm_widget_changed_hook_set(obj, _changed_hook);
elm_widget_can_focus_set(obj, EINA_FALSE);
elm_widget_focus_next_hook_set(obj, _elm_layout_focus_next_hook);
elm_widget_focus_direction_hook_set(obj, _elm_layout_focus_direction_hook);
elm_widget_signal_emit_hook_set(obj, _signal_emit_hook);
elm_widget_signal_callback_add_hook_set(obj, _signal_callback_add_hook);
elm_widget_signal_callback_del_hook_set(obj, _signal_callback_del_hook);

View File

@ -68,31 +68,134 @@ _event_hook(Evas_Object *obj, Evas_Object *src __UNUSED__, Evas_Callback_Type ty
Evas_Coord v_h = 0;
Evas_Coord page_x = 0;
Evas_Coord page_y = 0;
Evas_Coord c_x = 0;
Evas_Coord c_y = 0;
elm_smart_scroller_child_pos_get(wd->scr, &x, &y);
elm_smart_scroller_step_size_get(wd->scr, &step_x, &step_y);
elm_smart_scroller_page_size_get(wd->scr, &page_x, &page_y);
elm_smart_scroller_child_viewport_size_get(wd->scr, &v_w, &v_h);
elm_scroller_child_size_get(obj, &max_x, &max_y);
evas_object_geometry_get(wd->content, &c_x, &c_y, &max_x, &max_y);
if (((!strcmp(ev->keyname, "Left")) ||
(!strcmp(ev->keyname, "KP_Left")) ||
(!strcmp(ev->keyname, "Right")) ||
(!strcmp(ev->keyname, "KP_Right")) ||
(!strcmp(ev->keyname, "Up")) ||
(!strcmp(ev->keyname, "KP_Up")) ||
(!strcmp(ev->keyname, "Down")) ||
(!strcmp(ev->keyname, "KP_Down"))) && (!ev->string))
{
Evas_Object *current_focus = NULL;
Evas_Object *new_focus = NULL;
Eina_List *can_focus_list = NULL;
Evas_Coord f_x = 0;
Evas_Coord f_y = 0;
Evas_Coord f_w = 0;
Evas_Coord f_h = 0;
current_focus = elm_widget_focused_object_get(obj);
evas_object_geometry_get(current_focus, &f_x, &f_y, &f_w, &f_h);
can_focus_list = elm_widget_can_focus_child_list_get(obj);
if ((current_focus == obj) ||
(!ELM_RECTS_INTERSECT(x, y, v_w, v_h,
(f_x - c_x), (f_y - c_y), f_w, f_h)))
{
Evas_Object *cur;
Eina_List *l;
double weight = 0.0;
EINA_LIST_FOREACH(can_focus_list, l, cur)
{
double cur_weight = 0.0;
evas_object_geometry_get(cur, &f_x, &f_y, &f_w, &f_h);
if (ELM_RECTS_INTERSECT(x, y, v_w, v_h,
(f_x - c_x), (f_y - c_y), f_w, f_h))
{
if ((f_x - c_x) > x)
cur_weight += ((f_x - c_x) - x) * ((f_x - c_x) - x);
if ((f_y - c_y) > y)
cur_weight += ((f_y - c_y) - y) * ((f_y - c_y) - y);
if (cur_weight == 0.0)
{
elm_widget_focus_steal(cur);
return EINA_TRUE;
}
cur_weight = 1.0 / cur_weight;
if (cur_weight > weight)
{
new_focus = cur;
weight = cur_weight;
}
}
}
if (new_focus)
{
elm_widget_focus_steal(new_focus);
return EINA_TRUE;
}
}
else
{
Evas_Object *tmp = NULL;
double degree = 0.0, weight = 0.0;
void *(*list_data_get) (const Eina_List *list);
list_data_get = eina_list_data_get;
if ((!strcmp(ev->keyname, "Left")) || (!strcmp(ev->keyname, "KP_Left")))
degree = 270.0;
else if ((!strcmp(ev->keyname, "Right")) || (!strcmp(ev->keyname, "KP_Right")))
degree = 90.0;
else if ((!strcmp(ev->keyname, "Up")) || (!strcmp(ev->keyname, "KP_Up")))
degree = 0.0;
else if ((!strcmp(ev->keyname, "Down")) || (!strcmp(ev->keyname, "KP_Down")))
degree = 180.0;
if (elm_widget_focus_list_direction_get(obj, current_focus, can_focus_list, list_data_get, degree, &tmp, &weight))
new_focus = tmp;
if (new_focus)
{
Evas_Coord l_x = 0;
Evas_Coord l_y = 0;
Evas_Coord l_w = 0;
Evas_Coord l_h = 0;
evas_object_geometry_get(new_focus, &f_x, &f_y, &f_w, &f_h);
l_x = f_x - c_x - step_x;
l_y = f_y - c_y - step_y;
l_w = f_w + (step_x * 2);
l_h = f_h + (step_y * 2);
if (ELM_RECTS_INTERSECT(x, y, v_w, v_h, l_x, l_y, l_w, l_h))
{
elm_widget_focus_steal(new_focus);
return EINA_TRUE;
}
}
}
}
if ((!strcmp(ev->keyname, "Left")) ||
((!strcmp(ev->keyname, "KP_Left")) && (!ev->string)))
{
if (x <= 0) return EINA_FALSE;
x -= step_x;
}
else if ((!strcmp(ev->keyname, "Right")) ||
((!strcmp(ev->keyname, "KP_Right")) && (!ev->string)))
{
if (x >= (max_x - v_w)) return EINA_FALSE;
x += step_x;
}
else if ((!strcmp(ev->keyname, "Up")) ||
((!strcmp(ev->keyname, "KP_Up")) && (!ev->string)))
{
if (y == 0) return EINA_FALSE;
y -= step_y;
}
else if ((!strcmp(ev->keyname, "Down")) ||
((!strcmp(ev->keyname, "KP_Down")) && (!ev->string)))
{
if (y >= (max_y - v_h)) return EINA_FALSE;
y += step_y;
}
else if ((!strcmp(ev->keyname, "Home")) ||

View File

@ -69,6 +69,43 @@ _elm_table_focus_next_hook(const Evas_Object *obj, Elm_Focus_Direction dir, Evas
return ret;
}
static Eina_Bool
_elm_table_focus_direction_hook(const Evas_Object *obj, const Evas_Object *base, double degree,
Evas_Object **direction, double *weight)
{
Widget_Data *wd = elm_widget_data_get(obj);
const Eina_List *items;
void *(*list_data_get) (const Eina_List *list);
Eina_List *(*list_free) (Eina_List *list);
if ((!wd) || (!wd->tbl))
return EINA_FALSE;
/* Focus chain */
/* TODO: Change this to use other chain */
if ((items = elm_widget_focus_custom_chain_get(obj)))
{
list_data_get = eina_list_data_get;
list_free = NULL;
}
else
{
items = evas_object_table_children_get(wd->tbl);
list_data_get = eina_list_data_get;
list_free = eina_list_free;
if (!items) return EINA_FALSE;
}
Eina_Bool ret = elm_widget_focus_list_direction_get(obj, base, items, list_data_get, degree,
direction, weight);
if (list_free)
list_free((Eina_List *)items);
return ret;
}
static void
_mirrored_set(Evas_Object *obj, Eina_Bool rtl)
{
@ -133,6 +170,7 @@ elm_table_add(Evas_Object *parent)
elm_widget_del_hook_set(obj, _del_hook);
elm_widget_del_pre_hook_set(obj, _del_pre_hook);
elm_widget_focus_next_hook_set(obj, _elm_table_focus_next_hook);
elm_widget_focus_direction_hook_set(obj, _elm_table_focus_direction_hook);
elm_widget_can_focus_set(obj, EINA_FALSE);
elm_widget_highlight_ignore_set(obj, EINA_FALSE);
elm_widget_theme_hook_set(obj, _theme_hook);

View File

@ -60,6 +60,11 @@ struct _Smart_Data
Eina_Bool (*focus_next_func)(const Evas_Object *obj,
Elm_Focus_Direction dir,
Evas_Object **next);
Eina_Bool (*focus_direction_func)(const Evas_Object *obj,
const Evas_Object *base,
double degree,
Evas_Object **direction,
double *weight);
void (*on_focus_func)(void *data,
Evas_Object *obj);
void *on_focus_data;
@ -172,6 +177,7 @@ static void _if_focused_revert(Evas_Object *obj,
static Evas_Object *_newest_focus_order_get(Evas_Object *obj,
unsigned int *newest_focus_order,
Eina_Bool can_focus_only);
static double _direction_weight_get(const Evas_Object *obj1, const Evas_Object *obj2, double degree);
/* local subsystem globals */
static Evas_Smart *_e_smart = NULL;
@ -727,6 +733,28 @@ elm_widget_focus_next_hook_set(Evas_Object *obj,
sd->focus_next_func = func;
}
/**
* @internal
*
* Set hook to get near object in one direction.
*
* @param obj The widget object.
* @param func The hook to be used with this widget.
*
* @ingroup Widget
*/
EAPI void
elm_widget_focus_direction_hook_set(Evas_Object *obj,
Eina_Bool (*func)(const Evas_Object *obj,
const Evas_Object *base,
double degree,
Evas_Object **direction,
double *weight))
{
API_ENTRY return;
sd->focus_direction_func = func;
}
/**
* Returns the widget's mirrored mode.
*
@ -1641,26 +1669,156 @@ elm_widget_focus_cycle(Evas_Object *obj,
/**
* @internal
*
* Give focus to near object in one direction.
* Give focus to near object(in object tree) in one direction.
*
* Give focus to near object in direction of one object.
* If none focusable object in given direction, the focus will not change.
* Give focus to near object(in object tree) in direction of current focused object.
* If none focusable object in given direction or none focused object in object tree,
* the focus will not change.
*
* @param obj The reference widget
* @param x Horizontal component of direction to focus
* @param y Vertical component of direction to focus
* @param degree Degree changes clockwise. i.e. 0-degree: Up,
* 90-degree: Right, 180-degree: Down, and 270-degree: Left
* @return EINA_TRUE if focus is moved.
*
* @ingroup Widget
*/
//FIXME: If x, y indicates the elements of the directional vector,
//It would be better if these values are the normalized value(float x, float y)
//or degree.
EINA_DEPRECATED EAPI void
elm_widget_focus_direction_go(Evas_Object *obj __UNUSED__,
int x __UNUSED__,
int y __UNUSED__)
EAPI Eina_Bool
elm_widget_focus_direction_go(Evas_Object *obj, double degree)
{
return; /* TODO */
Evas_Object *target = NULL;
Evas_Object *current_focused = NULL;
double weight = 0.0;
if (!_elm_widget_is(obj)) return EINA_FALSE;
if (!elm_widget_focus_get(obj)) return EINA_FALSE;
current_focused = elm_widget_focused_object_get(obj);
if (elm_widget_focus_direction_get(obj, current_focused, degree, &target, &weight))
{
elm_widget_focus_steal(target);
return EINA_TRUE;
}
return EINA_FALSE;
}
/**
* @internal
*
* Get near object in one direction of base object.
*
* Get near object(in the object sub-tree) in one direction of
* base object. Return the near object by reference.
* By initializing weight, you can filter objects locating far
* from base object. If object is in the specific direction,
* weight is (1/(distance^2)). If object is not exactly in one
* direction, some penalty will be added.
*
* @param obj The widget root of sub-tree
* @param base The base object of the direction
* @param degree Degree changes clockwise. i.e. 0-degree: Up,
* 90-degree: Right, 180-degree: Down, and 270-degree: Left
* @param direction The near object in one direction
* @param weight The weight is bigger when the object is located near
* @return EINA_TRUE if near object is updated.
*
* @ingroup Widget
*/
EAPI Eina_Bool
elm_widget_focus_direction_get(const Evas_Object *obj,
const Evas_Object *base,
double degree,
Evas_Object **direction,
double *weight)
{
API_ENTRY return EINA_FALSE;
/* -1 means the best was already decided. Don't need any more searching. */
if (!direction || !weight || !base || (obj == base))
return EINA_FALSE;
/* Ignore if disabled */
if ((!evas_object_visible_get(obj))
|| (elm_widget_disabled_get(obj))
|| (elm_widget_tree_unfocusable_get(obj)))
return EINA_FALSE;
/* Try use hook */
if (sd->focus_direction_func)
return sd->focus_direction_func(obj, base, degree, direction, weight);
if (!elm_widget_can_focus_get(obj) || elm_widget_focus_get(obj))
return EINA_FALSE;
double c_weight = _direction_weight_get(base, obj, degree);
if ((c_weight == -1.0) || ((c_weight != 0.0) && (*weight != -1.0) &&
((int)(*weight * 1000000) <= (int)(c_weight * 1000000))))
{
if ((int)(*weight * 1000000) == (int)(c_weight * 1000000))
{
Smart_Data *sd1 = evas_object_smart_data_get(*direction);
if (sd1)
{
if (sd->focus_order <= sd1->focus_order)
return EINA_FALSE;
}
}
*direction = (Evas_Object *)obj;
*weight = c_weight;
return EINA_TRUE;
}
return EINA_FALSE;
}
/**
* @internal
*
* Get near object in one direction of base object in list.
*
* Get near object in one direction of base object in the specific
* object list. Return the near object by reference.
* By initializing weight, you can filter objects locating far
* from base object. If object is in the specific direction,
* weight is (1/(distance^2)). If object is not exactly in one
* direction, some penalty will be added.
*
* @param obj The widget root of sub-tree
* @param base The base object of the direction
* @param items list with ordered objects
* @param list_data_get function to get the object from one item of list
* @param degree Degree changes clockwise. i.e. 0-degree: Up,
* 90-degree: Right, 180-degree: Down, and 270-degree: Left
* @param direction The near object in one direction
* @param weight The weight is bigger when the object is located near
* @return EINA_TRUE if near object is updated.
*
* @ingroup Widget
*/
EAPI Eina_Bool
elm_widget_focus_list_direction_get(const Evas_Object *obj,
const Evas_Object *base,
const Eina_List *items,
void *(*list_data_get)(const Eina_List *list),
double degree,
Evas_Object **direction,
double *weight)
{
API_ENTRY return EINA_FALSE;
if (!direction || !weight || !base || !items)
return EINA_FALSE;
const Eina_List *l = items;
Evas_Object *current_best = *direction;
for (; l; l = eina_list_next(l))
{
Evas_Object *cur = list_data_get(l);
elm_widget_focus_direction_get(cur, base, degree, direction, weight);
}
if (current_best != *direction)
return EINA_TRUE;
else
return EINA_FALSE;
}
/**
@ -3609,6 +3767,285 @@ _if_focused_revert(Evas_Object *obj,
}
}
#define _R(x) (int)((x + 0.05) * 10.0)
static double
_direction_weight_get(const Evas_Object *obj1, const Evas_Object *obj2, double degree)
{
Evas_Coord obj_x1, obj_y1, w1, h1, obj_x2, obj_y2, w2, h2;
double x1, yy1, x2, yy2, xx1, yyy1, xx2, yyy2;
double ax, ay, cx, cy;
double weight = -1.0, g = 0.0;
if (obj1 == obj2) return 0.0;
degree -= 90.0;
while (degree >= 360.0)
degree -= 360.0;
while (degree < 0.0)
degree += 360.0;
evas_object_geometry_get(obj1, &obj_x1, &obj_y1, &w1, &h1);
cx = obj_x1 + (w1 / 2.0);
cy = obj_y1 + (h1 / 2.0);
evas_object_geometry_get(obj2, &obj_x2, &obj_y2, &w2, &h2);
if (ELM_RECTS_INTERSECT(obj_x1, obj_y1, w1, h1, obj_x2, obj_y2, w2, h2)) // For overlapping cases.
return 0.0;
/* Change all points to relative one. */
x1 = obj_x1 - cx;
xx1 = x1 + w1;
yy1 = obj_y1 - cy;
yyy1 = yy1 + h1;
x2 = obj_x2 - cx;
xx2 = x2 + w2;
yy2 = obj_y2 - cy;
yyy2 = yy2 + h2;
/* Get crossing points (ax, ay) between obj1 and a line extending to the direction of current degree. */
if (degree == 0.0)
{
ax = xx1;
ay = 0.0;
}
else if (degree == 90.0)
{
ax = 0.0;
ay = yyy1;
}
else if (degree == 180.0)
{
ax = x1;
ay = 0.0;
}
else if (degree == 270.0)
{
ax = 0.0;
ay = yy1;
}
else
{
g = tan(degree * (M_PI / 180.0));
if ((degree > 0.0) && (degree < 90.0))
{
ay = g * xx1;
if (ay <= yyy1) ax = xx1;
else
{
ax = yyy1 / g;
ay = yyy1;
}
}
else if ((degree > 90.0) && (degree < 180.0))
{
ay = g * x1;
if (ay <= yyy1) ax = x1;
else
{
ax = yyy1 / g;
ay = yyy1;
}
}
else if ((degree > 180.0) && (degree < 270.0))
{
ay = g * x1;
if (ay >= yy1) ax = x1;
else
{
ax = yy1 / g;
ay = yy1;
}
}
else
{
ay = g * xx1;
if (ay >= yy1) ax = xx1;
else
{
ax = yy1 / g;
ay = yy1;
}
}
}
/* Filter obj2, if it is not in the specific derection. */
int i = 0;
double rx[4] = {0.0, 0.0, 0.0, 0.0}, ry[4] = {0.0, 0.0, 0.0, 0.0};
double t1, t2, u1, v1, u2, v2;
if ((degree == 45.0) || (degree == 225.0) || (degree == 135.0) || (degree == 315.0))
{
u1 = 1.0;
v1 = 0.0;
u2 = 0.0;
v2 = 1.0;
}
else
{
double g2 = tan((degree + 45.0) * (M_PI / 180.0));
u1 = (-1.0 * g2);
u2 = (1.0 / g2);
v1 = v2 = 1.0;
}
t1 = (u1 * ax) + (v1 * ay);
t2 = (u2 * ax) + (v2 * ay);
if ((_R(t1 * ((u1 * x2) + (v1 * yy2))) > 0) && (_R(t2 * ((u2 * x2) + (v2 * yy2))) > 0))
{
rx[i] = x2;
ry[i++] = yy2;
}
if ((_R(t1 * ((u1 * x2) + (v1 * yyy2))) > 0) && (_R(t2 * ((u2 * x2) + (v2 * yyy2))) > 0))
{
rx[i] = x2;
ry[i++] = yyy2;
}
if ((_R(t1 * ((u1 * xx2) + (v1 * yy2))) > 0) && (_R(t2 * ((u2 * xx2) + (v2 * yy2))) > 0))
{
rx[i] = xx2;
ry[i++] = yy2;
}
if ((_R(t1 * ((u1 * xx2) + (v1 * yyy2))) > 0) && (_R(t2 * ((u2 * xx2) + (v2 * yyy2))) > 0))
{
rx[i] = xx2;
ry[i++] = yyy2;
}
if (i == 0)
{
if (degree == 0.0)
{
if ((_R(xx2) < 0) || (_R(yy2) > 0) || (_R(yyy2) < 0)) return 0.0;
}
else if (degree == 90.0)
{
if ((_R(yyy2) < 0) || (_R(x2) > 0) || (_R(xx2) < 0)) return 0.0;
}
else if (degree == 180.0)
{
if ((_R(x2) > 0) || (_R(yy2) > 0) || (_R(yyy2) < 0)) return 0.0;
}
else if (degree == 270.0)
{
if ((_R(yy2) > 0) || (_R(x2) > 0) || (_R(xx2) < 0)) return 0.0;
}
else
{
if ((_R(g * x2) >= _R(yy2)) && (_R((g * x2)) <= _R(yyy2)))
{
if (!((_R(ax * x2) > 0) && (_R(ay * (g * x2)) > 0))) return 0.0;
}
else if ((_R(g * xx2) >= _R(yy2)) && (_R((g * xx2)) <= _R(yyy2)))
{
if (!((_R(ax * xx2) > 0) && (_R(ay * (g * xx2)) > 0))) return 0.0;
}
else if ((_R((1.0 / g) * yy2) >= _R(xx2)) && (_R((1.0 / g) * yy2) <= _R(xx2)))
{
if (!((_R(ax * ((1.0 / g) * yy2)) > 0) && (_R(ay * yy2) > 0))) return 0.0;
}
else if ((_R((1.0 / g) * yyy2) >= _R(xx2)) && (_R((1.0 / g) * yyy2) <= _R(xx2)))
{
if (!((_R(ax * ((1.0 / g) * yyy2)) > 0) && (_R(ay * yyy2) > 0))) return 0.0;
}
else return 0.0;
}
}
/* Calculate the weight for obj2. */
if (degree == 0.0)
{
if (_R(xx1) > _R(x2)) weight = -1.0;
else if ((_R(yy2) >= _R(yy1)) && (_R(yyy2) <= _R(yyy1))) weight = (x2 - xx1) * (x2 - xx1);
else if (_R(yy2) > 0) weight = ((x2 - xx1) * (x2 - xx1)) + (yy2 * yy2);
else if (_R(yyy2) < 0) weight = ((x2 - xx1) * (x2 - xx1)) + (yyy2 * yyy2);
else weight = (x2 - xx1) * (x2 - xx1);
}
else if (degree == 90.0)
{
if (_R(yyy1) > _R(yy2)) weight = -1.0;
else if ((_R(x2) >= _R(x1)) && (_R(xx2) <= _R(xx1))) weight = (yy2 - yyy1) * (yy2 - yyy1);
else if (_R(x2) > 0) weight = (x2 * x2) + ((yy2 - yyy1) * (yy2 - yyy1));
else if (_R(xx2) < 0) weight = (xx2 * xx2) + ((yy2 - yyy1) * (yy2 - yyy1));
else weight = (yy2 - yyy1) * (yy2 - yyy1);
}
else if (degree == 180.0)
{
if (_R(x1) < _R(xx2)) weight = -1.0;
else if ((_R(yy2) >= _R(yy1)) && (_R(yyy2) <= _R(yyy1))) weight = (x1 - xx2) * (x1 - xx2);
else if (_R(yy2) > 0) weight = ((x1 - xx2) * (x1 - xx2)) + (yy2 * yy2);
else if (_R(yyy2) < 0) weight = ((x1 - xx2) * (x1 - xx2)) + (yyy2 * yyy2);
else weight = (x1 - xx2) * (x1 - xx2);
}
else if (degree == 270.0)
{
if (_R(yy1) < _R(yyy2)) weight = -1.0;
else if ((_R(x2) >= _R(x1)) && (_R(xx2) <= _R(xx1))) weight = (yy1 - yyy2) * (yy1 - yyy2);
else if (_R(x2) > 0) weight = (x2 * x2) + ((yy1 - yyy2) * (yy1 - yyy2));
else if (_R(xx2) < 0) weight = (xx2 * xx2) + ((yy1 - yyy2) * (yy1 - yyy2));
else weight = (yy1 - yyy2) * (yy1 - yyy2);
}
else
{
int j = 0, k = 0;
double sx[4] = {0.0, 0.0, 0.0, 0.0}, sy[4] = {0.0, 0.0, 0.0, 0.0};
double t_weight[4] = {-1.0 , -1.0, -1.0, -1.0};
if ((_R(g * x2) >= _R(yy2)) && (_R(g * x2) <= _R(yyy2)))
{
sx[j] = x2;
sy[j] = g * x2;
t_weight[j++] = ((ax - x2) * (ax - x2)) + ((ay - (g * x2)) * (ay - (g * x2)));
}
if ((_R(g * xx2) >= _R(yy2)) && (_R(g * xx2) <= _R(yyy2)))
{
sx[j] = xx2;
sy[j] = g * xx2;
t_weight[j++] = ((ax - xx2) * (ax - xx2)) + ((ay - (g * xx2)) * (ay - (g * xx2)));
}
if ((_R((1.0 / g) * yy2) >= _R(x2)) && (_R((1.0 / g) * yy2) <= _R(xx2)))
{
sx[j] = (1.0 / g) * yy2;
sy[j] = yy2;
t_weight[j++] = ((ax - ((1.0 / g) * yy2)) * (ax - ((1.0 / g) * yy2))) + ((ay - yy2) * (ay - yy2));
}
if ((_R((1.0 / g) * yyy2) >= _R(x2)) && (_R((1.0 / g) * yyy2) <= _R(xx2)))
{
sx[j] = (1.0 / g) * yyy2;
sy[j] = yyy2;
t_weight[j++] = ((ax - ((1.0 / g) * yyy2)) * (ax - ((1.0 / g) * yyy2))) + ((ay - yyy2) * (ay - yyy2));
}
if((j > 2) || ((j == 2) && ((_R(sx[0]) != _R(sx[1])) || (_R(sy[0]) != _R(sy[1])))))
{
for (; k < j; k++)
{
if (_R(t_weight[k]) == 0) return -1.0;
if ((1 / weight) < (1 / t_weight[k])) weight = t_weight[k];
}
}
else
{
for (; k < i; k++)
{
double ccx, ccy, t1_weight, x_diff, y_diff;
ccx = ((1.0 / g) * rx[k] + ry[k]) / (g + (1.0 / g));
ccy = g * ccx;
x_diff = rx[k] - ccx;
if (x_diff < 0) x_diff *= -1.0;
y_diff = ry[k] - ccy;
if (y_diff < 0) y_diff *= -1.0;
t1_weight = (((ax - ccx) * (ax - ccx)) + ((ay - ccy) * (ay - ccy))) +
((x_diff * x_diff * x_diff) + (y_diff * y_diff * y_diff));
if ((_R(t1_weight) != 0) && ((1 / weight) < (1 / t1_weight)))
weight = t1_weight;
}
}
}
/* Return the current object's weight. */
if (weight == -1.0) return 0.0;
if (_R(weight) == 0) return -1.0;
return (1.0 / weight);
}
static void
_smart_del(Evas_Object *obj)
{

View File

@ -313,6 +313,7 @@ EAPI void elm_widget_on_focus_hook_set(Evas_Object *obj, void (*func
EAPI void elm_widget_on_change_hook_set(Evas_Object *obj, void (*func)(void *data, Evas_Object *obj), void *data);
EAPI void elm_widget_on_show_region_hook_set(Evas_Object *obj, void (*func)(void *data, Evas_Object *obj), void *data);
EAPI void elm_widget_focus_region_hook_set(Evas_Object *obj, void (*func)(Evas_Object *obj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h));
EAPI void elm_widget_focus_direction_hook_set(Evas_Object *obj, Eina_Bool (*func)(const Evas_Object *obj, const Evas_Object *base, double degree, Evas_Object **direction, double *weight));
EAPI void elm_widget_text_set_hook_set(Evas_Object *obj, Elm_Widget_Text_Set_Cb func);
#define elm_widget_text_set_hook_set(obj, func) elm_widget_text_set_hook_set(obj, (Elm_Widget_Text_Set_Cb)(func))
EAPI void elm_widget_text_get_hook_set(Evas_Object *obj, Elm_Widget_Text_Get_Cb func);
@ -358,8 +359,10 @@ EAPI const Eina_List *elm_widget_focus_custom_chain_get(const Evas_Object *obj);
EAPI void elm_widget_focus_custom_chain_append(Evas_Object *obj, Evas_Object *child, Evas_Object *relative_child);
EAPI void elm_widget_focus_custom_chain_prepend(Evas_Object *obj, Evas_Object *child, Evas_Object *relative_child);
EAPI void elm_widget_focus_cycle(Evas_Object *obj, Elm_Focus_Direction dir);
EAPI void elm_widget_focus_direction_go(Evas_Object *obj, int x, int y);
EAPI Eina_Bool elm_widget_focus_direction_go(Evas_Object *obj, double degree);
EAPI Eina_Bool elm_widget_focus_direction_get(const Evas_Object *obj, const Evas_Object *base, double degree, Evas_Object **direction, double *weight);
EAPI Eina_Bool elm_widget_focus_next_get(const Evas_Object *obj, Elm_Focus_Direction dir, Evas_Object **next);
EAPI Eina_Bool elm_widget_focus_list_direction_get(const Evas_Object *obj, const Evas_Object *base, const Eina_List *items, void *(*list_data_get)(const Eina_List *list), double degree, Evas_Object **direction, double *weight);
EAPI Eina_Bool elm_widget_focus_list_next_get(const Evas_Object *obj, const Eina_List *items, void *(*list_data_get)(const Eina_List *list), Elm_Focus_Direction dir, Evas_Object **next);
EAPI void elm_widget_focus_set(Evas_Object *obj, int first);
EAPI void elm_widget_focused_object_clear(Evas_Object *obj);

View File

@ -522,6 +522,32 @@ _elm_win_focus_next_hook(const Evas_Object *obj, Elm_Focus_Direction dir, Evas_O
return EINA_FALSE;
}
static Eina_Bool
_elm_win_focus_direction_hook(const Evas_Object *obj, const Evas_Object *base, double degree,
Evas_Object **direction, double *weight)
{
Elm_Win *wd = elm_widget_data_get(obj);
const Eina_List *items;
const Eina_List *list;
void *(*list_data_get) (const Eina_List *list);
if (!wd)
return EINA_FALSE;
list = elm_widget_sub_object_list_get(obj);
/* Focus chain */
if (list)
{
if (!(items = elm_widget_focus_custom_chain_get(obj)))
items = list;
list_data_get = eina_list_data_get;
return elm_widget_focus_list_direction_get(obj, base, items, list_data_get, degree, direction, weight);
}
return EINA_FALSE;
}
static void
_elm_win_on_focus_hook(void *data __UNUSED__, Evas_Object *obj)
{
@ -540,6 +566,9 @@ _elm_win_event_cb(Evas_Object *obj, Evas_Object *src __UNUSED__, Evas_Callback_T
if (type == EVAS_CALLBACK_KEY_DOWN)
{
Evas_Event_Key_Down *ev = event_info;
Evas_Object *current_focused;
current_focused = elm_widget_focused_object_get(obj);
if (!strcmp(ev->keyname, "Tab"))
{
if (evas_key_modifier_is_set(ev->modifiers, "Shift"))
@ -552,22 +581,34 @@ _elm_win_event_cb(Evas_Object *obj, Evas_Object *src __UNUSED__, Evas_Callback_T
else if ((!strcmp(ev->keyname, "Left")) ||
((!strcmp(ev->keyname, "KP_Left")) && (!ev->string)))
{
//TODO : woohyun jung
if (current_focused == obj)
elm_widget_focus_cycle(obj, ELM_FOCUS_NEXT);
else
elm_widget_focus_direction_go(obj, 270.0);
}
else if ((!strcmp(ev->keyname, "Right")) ||
((!strcmp(ev->keyname, "KP_Right")) && (!ev->string)))
{
//TODO : woohyun jung
if (current_focused == obj)
elm_widget_focus_cycle(obj, ELM_FOCUS_NEXT);
else
elm_widget_focus_direction_go(obj, 90.0);
}
else if ((!strcmp(ev->keyname, "Up")) ||
((!strcmp(ev->keyname, "KP_Up")) && (!ev->string)))
{
//TODO : woohyun jung
if (current_focused == obj)
elm_widget_focus_cycle(obj, ELM_FOCUS_NEXT);
else
elm_widget_focus_direction_go(obj, 0.0);
}
else if ((!strcmp(ev->keyname, "Down")) ||
((!strcmp(ev->keyname, "KP_Down")) && (!ev->string)))
{
//TODO : woohyun jung
if (current_focused == obj)
elm_widget_focus_cycle(obj, ELM_FOCUS_NEXT);
else
elm_widget_focus_direction_go(obj, 180.0);
}
}
@ -1980,6 +2021,7 @@ elm_win_add(Evas_Object *parent, const char *name, Elm_Win_Type type)
elm_widget_can_focus_set(win->win_obj, EINA_TRUE);
elm_widget_highlight_ignore_set(win->win_obj, EINA_TRUE);
elm_widget_focus_next_hook_set(win->win_obj, _elm_win_focus_next_hook);
elm_widget_focus_direction_hook_set(win->win_obj, _elm_win_focus_direction_hook);
evas_object_color_set(win->win_obj, 0, 0, 0, 0);
evas_object_move(win->win_obj, 0, 0);
evas_object_resize(win->win_obj, 1, 1);