elementary/focus : Add four more focus direftions. ELM_FOCUS_UP, ELM_FOCUS_DOWN,...
authorWooHyun Jung <wh0705.jung@samsung.com>
Sat, 23 Mar 2013 00:36:21 +0000 (09:36 +0900)
committerWooHyun Jung <wh0705.jung@samsung.com>
Sat, 23 Mar 2013 00:36:21 +0000 (09:36 +0900)
ChangeLog
NEWS
src/lib/elm_focus.h
src/lib/elm_main.c
src/lib/elm_widget.c
src/lib/elm_widget.h

index deefb8d..583036d 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
 
         * 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 (file)
--- 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:
 
index 300ecae..282526a 100644 (file)
 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).
  *
index a77849d..a83a72a 100644 (file)
@@ -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)
index 193cfcf..4d4cc64 100644 (file)
@@ -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."),
index 50d4cfc..5b6c9c9 100644 (file)
@@ -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
  *