From 60a5d20d7f64fb94ecac80b115350ceab324053a Mon Sep 17 00:00:00 2001 From: WooHyun Jung Date: Mon, 25 Mar 2013 09:57:47 +0900 Subject: [PATCH] [Focus] Add APIs. elm_object_focus_next_set/get && elm_object_focused_object_get. These APIs will support flexible focus control. --- src/lib/elm_focus.h | 69 ++++++++++++++++++++ src/lib/elm_general.h | 6 -- src/lib/elm_main.c | 24 +++++++ src/lib/elm_widget.c | 171 +++++++++++++++++++++++++++++++++++++++++++++++++- src/lib/elm_widget.h | 4 ++ 5 files changed, 266 insertions(+), 8 deletions(-) diff --git a/src/lib/elm_focus.h b/src/lib/elm_focus.h index 59fc97c..8ef1b34 100644 --- a/src/lib/elm_focus.h +++ b/src/lib/elm_focus.h @@ -34,6 +34,21 @@ */ /** + * Focus directions. + * + * @ingroup Focus + */ +typedef enum +{ + ELM_FOCUS_PREVIOUS, /**< previous direction */ + ELM_FOCUS_NEXT, /**< next direction */ + ELM_FOCUS_UP, /**< up direction */ + ELM_FOCUS_DOWN, /**< down direction */ + ELM_FOCUS_RIGHT, /**< right direction */ + ELM_FOCUS_LEFT /**< left direction */ +} Elm_Focus_Direction; + +/** * Get the whether an Elementary object has the focus or not. * * @param obj The Elementary object to get the information from @@ -173,11 +188,65 @@ EAPI void elm_object_focus_custom_chain_prepend(Evas_Object *obj * @param obj The object root of sub-tree * @param dir Direction to move the focus * + * @see elm_object_focus_next_object_get(), elm_object_focus_next_object_set() + * * @ingroup Focus */ EAPI void elm_object_focus_next(Evas_Object *obj, Elm_Focus_Direction dir); /** + * Get next object which was set with specific focus direction. + * + * Get next object which was set by elm_object_focus_next_object_set + * with specific focus direction. + * + * @param obj The Elementary object + * @param dir Focus direction + * @return Focus next object or @c NULL, if there is no focus next object. + * + * @see elm_object_focus_next_object_set(), elm_object_focus_next() + * + * @since 1.8 + * + * @ingroup Focus + */ +EAPI Evas_Object * elm_object_focus_next_object_get(const Evas_Object *obj, Elm_Focus_Direction dir); + +/** + * Set next object with specific focus direction. + * + * When focus next object is set with specific focus direction, this object + * will be the first candidate when finding next focusable object. + * Focus next object can be registered with six directions that are previous, + * next, up, down, right, and left. + * + * @param obj The Elementary object + * @param next Focus next object + * @param dir Focus direction + * + * @see elm_object_focus_next_object_get(), elm_object_focus_next() + * + * @since 1.8 + * + * @ingroup Focus + */ +EAPI void elm_object_focus_next_object_set(Evas_Object *obj, Evas_Object *next, Elm_Focus_Direction dir); + +/** + * Get focused object in object tree. + * + * This function returns current focused object in one object sub-tree. + * + * @param obj The object root of sub-tree + * @return Current focused or @c NULL, if there is no focused object. + * + * @since 1.8 + * + * @ingroup Focus + */ +EAPI Evas_Object *elm_object_focused_object_get(const Evas_Object *obj); + +/** * Make the elementary object and its children to be focusable * (or unfocusable). * diff --git a/src/lib/elm_general.h b/src/lib/elm_general.h index b8a7686..d2b5c9b 100644 --- a/src/lib/elm_general.h +++ b/src/lib/elm_general.h @@ -108,12 +108,6 @@ typedef enum typedef enum { - ELM_FOCUS_PREVIOUS, - ELM_FOCUS_NEXT -} Elm_Focus_Direction; - -typedef enum -{ ELM_OBJECT_SELECT_MODE_DEFAULT = 0, /**< default select mode */ ELM_OBJECT_SELECT_MODE_ALWAYS, /**< always select mode */ ELM_OBJECT_SELECT_MODE_NONE, /**< no select mode */ diff --git a/src/lib/elm_main.c b/src/lib/elm_main.c index 36a968d..5b58ce4 100644 --- a/src/lib/elm_main.c +++ b/src/lib/elm_main.c @@ -1162,6 +1162,30 @@ elm_object_focus_next(Evas_Object *obj, elm_widget_focus_cycle(obj, dir); } +EAPI Evas_Object * +elm_object_focus_next_object_get(const Evas_Object *obj, + Elm_Focus_Direction dir) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(obj, NULL); + return elm_widget_focus_next_object_get(obj, dir); +} + +EAPI void +elm_object_focus_next_object_set(Evas_Object *obj, + Evas_Object *next, + Elm_Focus_Direction dir) +{ + EINA_SAFETY_ON_NULL_RETURN(obj); + elm_widget_focus_next_object_set(obj, next, dir); +} + +EAPI Evas_Object * +elm_object_focused_object_get(const Evas_Object *obj) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(obj, NULL); + return elm_widget_focused_object_get(obj); +} + EAPI void elm_object_tree_focus_allow_set(Evas_Object *obj, Eina_Bool tree_focusable) diff --git a/src/lib/elm_widget.c b/src/lib/elm_widget.c index 28009e1..1f0ab14 100644 --- a/src/lib/elm_widget.c +++ b/src/lib/elm_widget.c @@ -2331,7 +2331,34 @@ elm_widget_focus_next_get(const Evas_Object *obj, /* Try use hook */ if (_elm_widget_focus_chain_manager_is(obj)) - return sd->api->focus_next(obj, dir, next); + { + Eina_Bool ret; + ret = sd->api->focus_next(obj, dir, next); + if (!ret && elm_widget_focus_get(obj)) + { + Evas_Object *o = NULL; + if (dir == ELM_FOCUS_PREVIOUS) + o = sd->focus_previous; + else if (dir == ELM_FOCUS_NEXT) + o = sd->focus_next; + else if (dir == ELM_FOCUS_UP) + o = sd->focus_up; + else if (dir == ELM_FOCUS_DOWN) + o = sd->focus_down; + else if (dir == ELM_FOCUS_RIGHT) + o = sd->focus_right; + else if (dir == ELM_FOCUS_LEFT) + o = sd->focus_left; + + if (o) + { + *next = o; + return EINA_TRUE; + } + } + else + return ret; + } if (!elm_widget_can_focus_get(obj)) return EINA_FALSE; @@ -2342,6 +2369,24 @@ elm_widget_focus_next_get(const Evas_Object *obj, if (!_elm_access_object_get(obj)) return EINA_FALSE; } + if (elm_widget_focus_get(obj)) + { + if (dir == ELM_FOCUS_PREVIOUS) + *next = sd->focus_previous; + else if (dir == ELM_FOCUS_NEXT) + *next = sd->focus_next; + else if (dir == ELM_FOCUS_UP) + *next = sd->focus_up; + else if (dir == ELM_FOCUS_DOWN) + *next = sd->focus_down; + else if (dir == ELM_FOCUS_RIGHT) + *next = sd->focus_right; + else if (dir == ELM_FOCUS_LEFT) + *next = sd->focus_left; + + if (*next) + return EINA_TRUE; + } /* Return */ *next = (Evas_Object *)obj; return !ELM_WIDGET_FOCUS_GET(obj); @@ -2374,6 +2419,7 @@ elm_widget_focus_list_next_get(const Evas_Object *obj, Evas_Object **next) { Eina_List *(*list_next)(const Eina_List *list) = NULL; + Evas_Object *focused_object = NULL; if (!next) return EINA_FALSE; @@ -2385,13 +2431,51 @@ elm_widget_focus_list_next_get(const Evas_Object *obj, if (!items) return EINA_FALSE; + /* When Up, Down, Right, or Left, try direction_get first. */ + focused_object = elm_widget_focused_object_get(obj); + if (focused_object) + { + if((dir == ELM_FOCUS_UP) + || (dir == ELM_FOCUS_DOWN) + || (dir == ELM_FOCUS_RIGHT) + || (dir == ELM_FOCUS_LEFT)) + { + *next = elm_widget_focus_next_object_get(focused_object, dir); + if (*next) + return EINA_TRUE; + else + { + Evas_Object *n; + double degree; + double weight; + + if (dir == ELM_FOCUS_UP) degree = 0.0; + else if (dir == ELM_FOCUS_DOWN) degree = 180.0; + else if (dir == ELM_FOCUS_RIGHT) degree = 90.0; + else if (dir == ELM_FOCUS_LEFT) degree = 270.0; + + if (elm_widget_focus_list_direction_get(obj, focused_object, + items, list_data_get, + degree, &n, &weight)) + { + *next = n; + return EINA_TRUE; + } + } + } + } + /* Direction */ if (dir == ELM_FOCUS_PREVIOUS) { items = eina_list_last(items); list_next = eina_list_prev; } - else if (dir == ELM_FOCUS_NEXT) + else if ((dir == ELM_FOCUS_NEXT) + || (dir == ELM_FOCUS_UP) + || (dir == ELM_FOCUS_DOWN) + || (dir == ELM_FOCUS_RIGHT) + || (dir == ELM_FOCUS_LEFT)) list_next = eina_list_next; else return EINA_FALSE; @@ -2430,6 +2514,17 @@ elm_widget_focus_list_next_get(const Evas_Object *obj, *next = tmp; return EINA_TRUE; } + else if ((dir == ELM_FOCUS_UP) + || (dir == ELM_FOCUS_DOWN) + || (dir == ELM_FOCUS_RIGHT) + || (dir == ELM_FOCUS_LEFT)) + { + if (tmp && elm_widget_focus_get(cur)) + { + *next = tmp; + return EINA_FALSE; + } + } else if ((tmp) && (!to_focus)) to_focus = tmp; } @@ -2458,6 +2553,78 @@ elm_widget_focus_list_next_get(const Evas_Object *obj, return EINA_FALSE; } + +/** + * @internal + * + * Get next object which was set with specific focus direction. + * + * Get next object which was set by elm_widget_focus_next_object_set + * with specific focus directioin. + * + * @param obj The widget + * @param dir Direction of focus + * @return Widget which was registered with sepecific focus direction. + * + * @ingroup Widget + */ +EAPI Evas_Object * +elm_widget_focus_next_object_get(const Evas_Object *obj, Elm_Focus_Direction dir) +{ + API_ENTRY return NULL; + + if (dir == ELM_FOCUS_PREVIOUS) + return sd->focus_previous; + else if (dir == ELM_FOCUS_NEXT) + return sd->focus_next; + else if (dir == ELM_FOCUS_UP) + return sd->focus_up; + else if (dir == ELM_FOCUS_DOWN) + return sd->focus_down; + else if (dir == ELM_FOCUS_RIGHT) + return sd->focus_right; + else if (dir == ELM_FOCUS_LEFT) + return sd->focus_left; + + return NULL; +} + +/** + * @internal + * + * Set next object with specific focus direction. + * + * When a widget is set with specific focus direction, this widget will be + * the first candidate when finding the next focus object. + * Focus next object can be registered with six directions that are previous, + * next, up, down, right, and left. + * + * @param obj The widget + * @param next Next focus object + * @param dir Direction of focus + * + * @ingroup Widget + */ +EAPI void +elm_widget_focus_next_object_set(Evas_Object *obj, Evas_Object *next, Elm_Focus_Direction dir) +{ + API_ENTRY return; + + if (dir == ELM_FOCUS_PREVIOUS) + sd->focus_previous = next; + else if (dir == ELM_FOCUS_NEXT) + sd->focus_next = next; + else if (dir == ELM_FOCUS_UP) + sd->focus_up = next; + else if (dir == ELM_FOCUS_DOWN) + sd->focus_down = next; + else if (dir == ELM_FOCUS_RIGHT) + sd->focus_right = next; + else if (dir == ELM_FOCUS_LEFT) + sd->focus_left = next; +} + + EAPI Eina_Bool elm_widget_highlight_get(const Evas_Object *obj) { diff --git a/src/lib/elm_widget.h b/src/lib/elm_widget.h index 4622982..1bc7677 100644 --- a/src/lib/elm_widget.h +++ b/src/lib/elm_widget.h @@ -466,6 +466,8 @@ typedef struct _Elm_Widget_Smart_Data Evas_Object *resize_obj; Evas_Object *hover_obj; Eina_List *tooltips, *cursors; + Evas_Object *focus_previous, *focus_next; + Evas_Object *focus_up, *focus_down, *focus_right, *focus_left; /* "show region" coordinates. all widgets got those because this * info may be set and queried recursively through the widget @@ -708,6 +710,8 @@ EAPI Eina_Bool elm_widget_focus_direction_get(const Evas_Object *obj, con 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 Evas_Object *elm_widget_focus_next_object_get(const Evas_Object *obj, Elm_Focus_Direction dir); +EAPI void elm_widget_focus_next_object_set(Evas_Object *obj, Evas_Object *next, Elm_Focus_Direction dir); EAPI void elm_widget_focus_set(Evas_Object *obj, int first); EAPI void elm_widget_focused_object_clear(Evas_Object *obj); EAPI Evas_Object *elm_widget_parent_get(const Evas_Object *obj); -- 2.7.4