woohyun pushed a commit to branch master.
commit 8a76263959981dcc8620820e567e3e0b7ace0774
Author: WooHyun Jung <[email protected]>
Date: Sat Mar 23 09:36:21 2013 +0900
elementary/focus : Add four more focus direftions. ELM_FOCUS_UP,
ELM_FOCUS_DOWN, ELM_FOCUS_RIGHT, and ELM_FOCUS_LEFT. These are for supporting
elm_object_focus_next with four directions. And I added
elm_object_focus_next_object_set(get). By setting focus next object manually,
developer can set its own first candidate of focus next. Lastly I added
elm_object_focused_object_get, for easy finding of current focused object in
one object sub-tree.
---
ChangeLog | 6 ++
NEWS | 3 +
src/lib/elm_focus.h | 60 +++++++++++++++-
src/lib/elm_main.c | 24 +++++++
src/lib/elm_widget.c | 200 ++++++++++++++++++++++++++++++++++++++++++++++++++-
src/lib/elm_widget.h | 30 ++++++++
6 files changed, 319 insertions(+), 4 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index deefb8d..583036d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1172,3 +1172,9 @@
* Fix elm box layout when an item has a max size, and that squashes all
content even when the minimum size is greater.
+
+2013-03-23 WooHyun Jung
+
+ * Add four more focus directions. ELM_FOCUS_UP/DOWN/RIGHT/LEFT.
+ * Add elm_object_focus_next_object_get/set.
+ * Add elm_object_focused_object_get.
diff --git a/NEWS b/NEWS
index ba19160..2a2fc15 100644
--- a/NEWS
+++ b/NEWS
@@ -50,6 +50,9 @@ Additions:
* Add elm_naviframe_item_pop_cb_set().
* Add elm_widget_newest_focus_order_get for knowing the last object(and its
focus order) which got focus.
* Add the smart signals in scroller. "scroll,left", "scroll,right",
"scroll,up", "scroll,down".
+ * Add four more focus diretions. ELM_FOCUS_UP, ELM_FOCUS_DOWN,
ELM_FOCUS_RIGHT, ELM_FOCUS_LEFT.
+ * Add APIs - elm_object_focus_next_object_get,
elm_object_focus_next_object_set.
+ * Add API - elm_object_focused_object_get.
Improvements:
diff --git a/src/lib/elm_focus.h b/src/lib/elm_focus.h
index 300ecae..282526a 100644
--- a/src/lib/elm_focus.h
+++ b/src/lib/elm_focus.h
@@ -41,7 +41,11 @@
typedef enum
{
ELM_FOCUS_PREVIOUS, /**< previous direction */
- ELM_FOCUS_NEXT /**< next 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;
/**
@@ -187,11 +191,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_main.c b/src/lib/elm_main.c
index a77849d..a83a72a 100644
--- a/src/lib/elm_main.c
+++ b/src/lib/elm_main.c
@@ -1295,6 +1295,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 193cfcf..4d4cc64 100644
--- a/src/lib/elm_widget.c
+++ b/src/lib/elm_widget.c
@@ -2550,7 +2550,7 @@ _elm_widget_focus_list_direction_get(Eo *obj EINA_UNUSED,
void *_pd EINA_UNUSED,
* focus before chain end, the first candidate will be returned.
*
* @param obj The widget root of sub-tree
- * @param dir Direction os focus chain
+ * @param dir Direction of focus chain
* @param next The next object in focus chain
* @return EINA_TRUE if don't need focus chain restart/loop back
* to use 'next' obj.
@@ -2578,6 +2578,7 @@ _elm_widget_focus_next_get(Eo *obj, void *_pd
EINA_UNUSED, va_list *list)
Elm_Focus_Direction dir = va_arg(*list, Elm_Focus_Direction);
Evas_Object **next = va_arg(*list, Evas_Object **);
Eina_Bool *ret = va_arg(*list, Eina_Bool *);
+ Elm_Widget_Smart_Data *sd = _pd;
*ret = EINA_FALSE;
if (!next)
@@ -2595,6 +2596,29 @@ _elm_widget_focus_next_get(Eo *obj, void *_pd
EINA_UNUSED, va_list *list)
{
Eina_Bool int_ret = EINA_FALSE;
eo_do((Eo *)obj, elm_wdg_focus_next(dir, next, &int_ret));
+ if (!int_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;
+ *ret = EINA_TRUE;
+ return;
+ }
+ }
*ret = int_ret;
return;
}
@@ -2610,6 +2634,28 @@ _elm_widget_focus_next_get(Eo *obj, void *_pd
EINA_UNUSED, va_list *list)
if (!ac) return;
}
+ 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)
+ {
+ *ret = EINA_TRUE;
+ return;
+ }
+ }
+
/* Return */
*next = (Evas_Object *)obj;
*ret = !ELM_WIDGET_FOCUS_GET(obj);
@@ -2625,7 +2671,7 @@ _elm_widget_focus_next_get(Eo *obj, void *_pd
EINA_UNUSED, va_list *list)
* focus before list end, the first candidate will be returned.
*
* @param obj The widget root of sub-tree
- * @param dir Direction os focus chain
+ * @param dir Direction of focus chain
* @param items list with ordered objects
* @param list_data_get function to get the object from one item of list
* @param next The next object in focus chain
@@ -2658,6 +2704,7 @@ _elm_widget_focus_list_next_get(Eo *obj, void *_pd
EINA_UNUSED, va_list *list)
if (ret) *ret = EINA_FALSE;
Eina_List *(*list_next)(const Eina_List *list) = NULL;
+ Evas_Object *focused_object = NULL;
if (!next)
return;
@@ -2669,13 +2716,55 @@ _elm_widget_focus_list_next_get(Eo *obj, void *_pd
EINA_UNUSED, va_list *list)
if (!items)
return;
+ /* 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)
+ {
+ if (ret) *ret = EINA_TRUE;
+ return;
+ }
+ 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;
+ if (ret) *ret = EINA_TRUE;
+ return;
+ }
+ }
+ }
+ }
+
/* 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;
@@ -2715,6 +2804,17 @@ _elm_widget_focus_list_next_get(Eo *obj, void *_pd
EINA_UNUSED, va_list *list)
if (ret) *ret = EINA_TRUE;
return;
}
+ 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;
+ }
+ }
else if ((tmp) && (!to_focus))
to_focus = tmp;
}
@@ -2743,6 +2843,96 @@ _elm_widget_focus_list_next_get(Eo *obj, void *_pd
EINA_UNUSED, va_list *list)
return;
}
+/**
+ * @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)
+{
+ ELM_WIDGET_CHECK(obj) NULL;
+
+ Evas_Object *ret = NULL;
+ eo_do((Eo *) obj, elm_wdg_focus_next_object_get(dir, &ret));
+ return ret;
+}
+
+static void
+_elm_widget_focus_next_object_get(Eo *obj EINA_UNUSED, void *_pd, va_list
*list)
+{
+ Elm_Focus_Direction dir = va_arg(*list, Elm_Focus_Direction);
+ Evas_Object **ret = va_arg(*list, Evas_Object **);
+ Elm_Widget_Smart_Data *sd = _pd;
+
+ if (dir == ELM_FOCUS_PREVIOUS)
+ *ret = sd->focus_previous;
+ else if (dir == ELM_FOCUS_NEXT)
+ *ret = sd->focus_next;
+ else if (dir == ELM_FOCUS_UP)
+ *ret = sd->focus_up;
+ else if (dir == ELM_FOCUS_DOWN)
+ *ret = sd->focus_down;
+ else if (dir == ELM_FOCUS_RIGHT)
+ *ret = sd->focus_right;
+ else if (dir == ELM_FOCUS_LEFT)
+ *ret = sd->focus_left;
+}
+
+/**
+ * @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)
+{
+ ELM_WIDGET_CHECK(obj);
+ if (!next) return;
+ eo_do((Eo *) obj, elm_wdg_focus_next_object_set(next, dir));
+}
+
+static void
+_elm_widget_focus_next_object_set(Eo *obj EINA_UNUSED, void *_pd, va_list
*list)
+{
+ Evas_Object *next = va_arg(*list, Evas_Object *);
+ Elm_Focus_Direction dir = va_arg(*list, Elm_Focus_Direction);
+ Elm_Widget_Smart_Data *sd = _pd;
+
+ 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 void
elm_widget_parent_highlight_set(Evas_Object *obj,
Eina_Bool highlighted)
@@ -5717,6 +5907,8 @@ _class_constructor(Eo_Class *klass)
EO_OP_FUNC(ELM_WIDGET_ID(ELM_WIDGET_SUB_ID_FOCUS_LIST_DIRECTION_GET),
_elm_widget_focus_list_direction_get),
EO_OP_FUNC(ELM_WIDGET_ID(ELM_WIDGET_SUB_ID_FOCUS_NEXT_GET),
_elm_widget_focus_next_get),
EO_OP_FUNC(ELM_WIDGET_ID(ELM_WIDGET_SUB_ID_FOCUS_LIST_NEXT_GET),
_elm_widget_focus_list_next_get),
+ EO_OP_FUNC(ELM_WIDGET_ID(ELM_WIDGET_SUB_ID_FOCUS_NEXT_OBJECT_GET),
_elm_widget_focus_next_object_get),
+ EO_OP_FUNC(ELM_WIDGET_ID(ELM_WIDGET_SUB_ID_FOCUS_NEXT_OBJECT_SET),
_elm_widget_focus_next_object_set),
EO_OP_FUNC(ELM_WIDGET_ID(ELM_WIDGET_SUB_ID_PARENT_HIGHLIGHT_SET),
_elm_widget_parent_highlight_set),
EO_OP_FUNC(ELM_WIDGET_ID(ELM_WIDGET_SUB_ID_DISPLAY_MODE_SET),
_elm_widget_display_mode_set),
EO_OP_FUNC(ELM_WIDGET_ID(ELM_WIDGET_SUB_ID_DISPLAY_MODE_GET),
_elm_widget_display_mode_get),
@@ -5858,6 +6050,8 @@ static const Eo_Op_Description op_desc[] = {
EO_OP_DESCRIPTION(ELM_WIDGET_SUB_ID_FOCUS_LIST_DIRECTION_GET, "Get near
object in one direction of base object in list."),
EO_OP_DESCRIPTION(ELM_WIDGET_SUB_ID_FOCUS_NEXT_GET, "Get next object in
focus chain of object tree."),
EO_OP_DESCRIPTION(ELM_WIDGET_SUB_ID_FOCUS_LIST_NEXT_GET, "Get next object
in focus chain of object tree in list."),
+ EO_OP_DESCRIPTION(ELM_WIDGET_SUB_ID_FOCUS_NEXT_OBJECT_GET, "Get next
object specified by focus direction."),
+ EO_OP_DESCRIPTION(ELM_WIDGET_SUB_ID_FOCUS_NEXT_OBJECT_SET, "Set next
object with specific focus direction."),
EO_OP_DESCRIPTION(ELM_WIDGET_SUB_ID_PARENT_HIGHLIGHT_SET, "Set
highlighted value from itself to top parent object."),
EO_OP_DESCRIPTION(ELM_WIDGET_SUB_ID_DISPLAY_MODE_SET, "Sets the widget
and child widget's Evas_Display_Mode."),
diff --git a/src/lib/elm_widget.h b/src/lib/elm_widget.h
index 50d4cfc..5b6c9c9 100644
--- a/src/lib/elm_widget.h
+++ b/src/lib/elm_widget.h
@@ -377,6 +377,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
@@ -626,6 +628,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_parent_highlight_set(Evas_Object *obj,
Eina_Bool highlighted);
EAPI void elm_widget_focus_set(Evas_Object *obj, int first);
EAPI void elm_widget_focused_object_clear(Evas_Object *obj);
@@ -1145,6 +1149,8 @@ enum
ELM_WIDGET_SUB_ID_FOCUS_LIST_DIRECTION_GET,
ELM_WIDGET_SUB_ID_FOCUS_NEXT_GET,
ELM_WIDGET_SUB_ID_FOCUS_LIST_NEXT_GET,
+ ELM_WIDGET_SUB_ID_FOCUS_NEXT_OBJECT_GET,
+ ELM_WIDGET_SUB_ID_FOCUS_NEXT_OBJECT_SET,
ELM_WIDGET_SUB_ID_PARENT_HIGHLIGHT_SET,
ELM_WIDGET_SUB_ID_DISPLAY_MODE_SET,
@@ -2333,6 +2339,30 @@ typedef void * (*list_data_get_func_type)(const
Eina_List * l);
#define elm_wdg_focus_list_next_get(items, list_data_get, dir, next, ret)
ELM_WIDGET_ID(ELM_WIDGET_SUB_ID_FOCUS_LIST_NEXT_GET), EO_TYPECHECK(const
Eina_List *, items), EO_TYPECHECK(list_data_get_func_type, list_data_get),
EO_TYPECHECK(Elm_Focus_Direction, dir), EO_TYPECHECK(Evas_Object **, next),
EO_TYPECHECK(Eina_Bool *, ret)
/**
+ * @def elm_wdg_focus_next_object_get
+ * @since 1.8
+ *
+ * No description supplied by the EAPI.
+ *
+ * @param[in] dir
+ * @param[out] ret
+ *
+ */
+#define elm_wdg_focus_next_object_get(dir, ret)
ELM_WIDGET_ID(ELM_WIDGET_SUB_ID_FOCUS_NEXT_OBJECT_GET),
EO_TYPECHECK(Elm_Focus_Direction, dir), EO_TYPECHECK(Evas_Object **, ret)
+
+/**
+ * @def elm_wdg_focus_next_object_set
+ * @since 1.8
+ *
+ * No description supplied by the EAPI.
+ *
+ * @param[in] next
+ * @param[in] dir
+ *
+ */
+#define elm_wdg_focus_next_object_set(next, dir)
ELM_WIDGET_ID(ELM_WIDGET_SUB_ID_FOCUS_NEXT_OBJECT_SET),
EO_TYPECHECK(Evas_Object *, next), EO_TYPECHECK(Elm_Focus_Direction, dir)
+
+/**
* @def elm_wdg_parent_highlight_set
* @since 1.8
*
--
------------------------------------------------------------------------------
Everyone hates slow websites. So do we.
Make your web apps faster with AppDynamics
Download AppDynamics Lite for free today:
http://p.sf.net/sfu/appdyn_d2d_mar