[Focus] Add APIs. elm_object_focus_next_set/get && elm_object_focused_object_get...
authorWooHyun Jung <wh0705.jung@samsung.com>
Mon, 25 Mar 2013 00:57:47 +0000 (09:57 +0900)
committerSungho Kwak <sungho1.kwak@samsung.com>
Thu, 28 Mar 2013 02:48:09 +0000 (11:48 +0900)
src/lib/elm_focus.h
src/lib/elm_general.h
src/lib/elm_main.c
src/lib/elm_widget.c
src/lib/elm_widget.h

index 59fc97c..8ef1b34 100644 (file)
  */
 
 /**
+ * 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).
  *
index b8a7686..d2b5c9b 100644 (file)
@@ -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 */
index 36a968d..5b58ce4 100644 (file)
@@ -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)
index 28009e1..1f0ab14 100644 (file)
@@ -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)
 {
index 4622982..1bc7677 100644 (file)
@@ -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);