kimcinoo pushed a commit to branch master.
commit e8883dba68391da116237abda30b97c7f3d57388
Author: Shinwoo Kim <[email protected]>
Date: Thu Apr 18 10:52:01 2013 +0900
[access] add elm_access_action(), elm_access_action_cb_set()
---
ChangeLog | 4 +
NEWS | 1 +
src/lib/elm_access.c | 285 +++++++++++++++++++++++++++++++++++++++++++++++++--
src/lib/elm_access.h | 95 +++++++++++++++++
src/lib/elm_widget.h | 3 +-
5 files changed, 380 insertions(+), 8 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index 4e33310..8b36108 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1264,3 +1264,7 @@
2013-04-17 ChunEon Park
* Don't try to pop the naviframe item multiple times.
+
+2013-04-18 Shinwoo Kim
+
+ * Add elm_access_action(), elm_access_action_cb_set()
diff --git a/NEWS b/NEWS
index 9b11d9d..c8c9f56 100644
--- a/NEWS
+++ b/NEWS
@@ -61,6 +61,7 @@ Additions:
* Add elm_mapbuf_auto_set/get.
* Add the API elm_scroller_single_direction_set/get.
* Add the feature for key events.
+ * Add elm_access_action(), elm_access_action_cb_set()
Improvements:
diff --git a/src/lib/elm_access.c b/src/lib/elm_access.c
index 06d9ca1..db4a734 100644
--- a/src/lib/elm_access.c
+++ b/src/lib/elm_access.c
@@ -5,8 +5,25 @@
#define MY_CLASS_NAME "elm_access"
+struct _Func_Data
+{
+ void *user_data; /* Holds user data to CB */
+ Elm_Access_Action_Cb cb;
+};
+
+typedef struct _Func_Data Func_Data;
+
+struct _Action_Info
+{
+ Evas_Object *obj;
+ Func_Data fn[ELM_ACCESS_ACTION_LAST + 1]; /* Callback for specific
action */
+};
+
+typedef struct _Action_Info Action_Info;
+
static Eina_Bool mouse_event_enable = EINA_TRUE;
static Eina_Bool read_mode = EINA_FALSE;
+static Elm_Access_Action_Type action_by = ELM_ACCESS_ACTION_FIRST;
static Evas_Object * _elm_access_add(Evas_Object *parent);
@@ -18,6 +35,38 @@ _elm_access_smart_add(Eo *obj, void *_pd EINA_UNUSED,
va_list *list EINA_UNUSED)
elm_widget_can_focus_set(obj, EINA_TRUE);
}
+static Eina_Bool
+_access_action_callback_call(Evas_Object *obj,
+ Elm_Access_Action_Type type,
+ Elm_Access_Action_Info *action_info)
+{
+ Elm_Access_Action_Info *ai = NULL;
+ Action_Info *a;
+ Eina_Bool ret;
+
+ ret = EINA_FALSE;
+ a = evas_object_data_get(obj, "_elm_access_action_info");
+
+ if (!action_info)
+ {
+ ai = calloc(1, sizeof(Elm_Access_Action_Info));
+ action_info = ai;
+ }
+
+ action_info->action_type = type;
+
+ if ((type == ELM_ACCESS_ACTION_HIGHLIGHT) &&
+ (action_by != ELM_ACCESS_ACTION_FIRST))
+ action_info->action_by = action_by;
+
+ if (a && (a->fn[type].cb))
+ ret = a->fn[type].cb(a->fn[type].user_data, obj, action_info);
+
+ if (ai) free(ai);
+
+ return ret;
+}
+
static void
_elm_access_smart_activate(Eo *obj, void *_pd EINA_UNUSED, va_list *list)
{
@@ -25,6 +74,53 @@ _elm_access_smart_activate(Eo *obj, void *_pd EINA_UNUSED,
va_list *list)
Eina_Bool *ret = va_arg(*list, Eina_Bool *);
if (ret) *ret = EINA_FALSE;
+ int type = ELM_ACCESS_ACTION_FIRST;
+
+ Action_Info *a;
+ a = evas_object_data_get(obj, "_elm_access_action_info");
+
+ switch (act)
+ {
+ case ELM_ACTIVATE_DEFAULT:
+ type = ELM_ACCESS_ACTION_ACTIVATE;
+ break;
+
+ case ELM_ACTIVATE_UP:
+ type = ELM_ACCESS_ACTION_UP;
+ break;
+
+ case ELM_ACTIVATE_DOWN:
+ type = ELM_ACCESS_ACTION_DOWN;
+ break;
+
+ case ELM_ACTIVATE_RIGHT:
+ break;
+
+ case ELM_ACTIVATE_LEFT:
+ break;
+
+ case ELM_ACTIVATE_BACK:
+ type = ELM_ACCESS_ACTION_BACK;
+ break;
+
+ default:
+ break;
+ }
+
+ if (type == ELM_ACCESS_ACTION_FIRST) return;
+
+ /* if an access object has a callback, it would have the intention to do
+ something. so, check here and return EINA_TRUE. */
+ if ((a) && (type > ELM_ACCESS_ACTION_FIRST) &&
+ (type < ELM_ACCESS_ACTION_LAST) &&
+ (a->fn[type].cb))
+ {
+ _access_action_callback_call(obj, type, NULL);
+ if (ret) *ret = EINA_TRUE;
+ return;
+ }
+
+ /* TODO: deprecate below? */
if (act != ELM_ACTIVATE_DEFAULT) return;
Elm_Access_Info *ac = evas_object_data_get(obj, "_elm_access");
@@ -380,6 +476,66 @@ _elm_access_widget_item_access_order_unset(Elm_Widget_Item
*item)
item->access_order = eina_list_remove_list(item->access_order, l);
}
}
+
+static Eina_Bool
+_access_highlight_next_get(Evas_Object *obj, Elm_Focus_Direction dir)
+{
+ int type;
+ Evas_Object *ho, *parent, *target;
+ Elm_Widget_Smart_Data *wd;
+ Eina_Bool ret;
+
+ target = NULL;
+ ret = EINA_FALSE;
+
+ if (!elm_widget_is(obj)) return ret;
+
+ ho = _access_highlight_object_get(obj);
+ if (!ho) ho = obj;
+
+ parent = ho;
+
+ /* find highlight root */
+ do
+ {
+ wd = eo_data_get(parent, ELM_OBJ_WIDGET_CLASS);
+ if (wd->highlight_root)
+ {
+ /* change highlight root */
+ obj = parent;
+ break;
+ }
+ parent = elm_widget_parent_get(parent);
+ }
+ while (parent);
+
+ _elm_access_read_mode_set(EINA_TRUE);
+
+ ret = elm_widget_focus_next_get(obj, dir, &target);
+ if (ret && target)
+ {
+ if (dir == ELM_FOCUS_NEXT)
+ type = ELM_ACCESS_ACTION_HIGHLIGHT_NEXT;
+ else
+ type = ELM_ACCESS_ACTION_HIGHLIGHT_PREV;
+
+ if (!_access_action_callback_call(ho, type, NULL))
+ {
+ /* this value is used in _elm_access_object_highlight();
+ to inform the target object of how to get highlight */
+ action_by = type;
+
+ _elm_access_highlight_set(target);
+
+ action_by = ELM_ACCESS_ACTION_FIRST;
+ }
+ }
+
+ _elm_access_read_mode_set(EINA_FALSE);
+
+ return ret;
+}
+
//-------------------------------------------------------------------------//
EAPI void
_elm_access_highlight_set(Evas_Object* obj)
@@ -476,27 +632,43 @@ _elm_access_highlight_object_activate(Evas_Object *obj,
Elm_Activate act)
EAPI void
_elm_access_highlight_cycle(Evas_Object *obj, Elm_Focus_Direction dir)
{
+ int type;
+ Evas_Object *ho, *parent;
Elm_Widget_Smart_Data *wd;
- Evas_Object *ho;
+
ho = _access_highlight_object_get(obj);
if (!ho) return;
+ parent = ho;
+
/* find highlight root */
do
{
- wd = eo_data_get(ho, ELM_OBJ_WIDGET_CLASS);
+ wd = eo_data_get(parent, ELM_OBJ_WIDGET_CLASS);
if (wd->highlight_root)
{
/* change highlight root */
- obj = ho;
+ obj = parent;
break;
}
- ho = elm_widget_parent_get(ho);
+ parent = elm_widget_parent_get(parent);
}
- while (ho);
+ while (parent);
_elm_access_read_mode_set(EINA_TRUE);
- elm_widget_focus_cycle(obj, dir);
+
+ if (dir == ELM_FOCUS_NEXT)
+ type = ELM_ACCESS_ACTION_HIGHLIGHT_NEXT;
+ else
+ type = ELM_ACCESS_ACTION_HIGHLIGHT_PREV;
+
+ action_by = type;
+
+ if (!_access_action_callback_call(ho, type, NULL))
+ elm_widget_focus_cycle(obj, dir);
+
+ action_by = ELM_ACCESS_ACTION_FIRST;
+
_elm_access_read_mode_set(EINA_FALSE);
}
@@ -623,7 +795,13 @@ _elm_access_object_hilight(Evas_Object *obj)
evas_object_geometry_get(obj, &x, &y, &w, &h);
evas_object_move(o, x, y);
evas_object_resize(o, w, h);
- evas_object_show(o);
+
+ /* use callback, should an access object do below every time when
+ * a window gets a client message ECORE_X_ATOM_E_ILLMUE_ACTION_READ? */
+ if (!_access_action_callback_call(obj, ELM_ACCESS_ACTION_HIGHLIGHT, NULL))
+ evas_object_show(o);
+ else
+ evas_object_hide(o);
}
EAPI void
@@ -840,6 +1018,10 @@ _elm_access_object_unregister(Evas_Object *obj,
Evas_Object *hoverobj)
_elm_access_clear(ac);
free(ac);
}
+
+ Action_Info *a;
+ a = evas_object_data_get(obj, "_elm_access_action_info");
+ if (a) free(a);
}
EAPI void
@@ -1005,6 +1187,95 @@ elm_access_highlight_set(Evas_Object* obj)
_elm_access_highlight_set(obj);
}
+EAPI Eina_Bool
+elm_access_action(Evas_Object *obj, const Elm_Access_Action_Type type,
Elm_Access_Action_Info *action_info)
+{
+ Evas *evas;
+ Evas_Object *ho;
+ Elm_Access_Action_Info *a;
+
+ a = (Elm_Access_Action_Info *) action_info;
+
+ switch (type)
+ {
+ case ELM_ACCESS_ACTION_READ:
+ case ELM_ACCESS_ACTION_HIGHLIGHT:
+ evas = evas_object_evas_get(obj);
+ if (!evas) return EINA_FALSE;
+
+ _elm_access_mouse_event_enabled_set(EINA_TRUE);
+
+ evas_event_feed_mouse_in(evas, 0, NULL);
+ evas_event_feed_mouse_move(evas, a->x, a->y, 0, NULL);
+ _elm_access_mouse_event_enabled_set(EINA_FALSE);
+
+ ho = _access_highlight_object_get(obj);
+ if (ho)
+ _access_action_callback_call(ho, ELM_ACCESS_ACTION_READ, a);
+ break;
+
+ case ELM_ACCESS_ACTION_UNHIGHLIGHT:
+ evas = evas_object_evas_get(obj);
+ if (!evas) return EINA_FALSE;
+ _elm_access_object_hilight_disable(evas);
+ break;
+
+ case ELM_ACCESS_ACTION_HIGHLIGHT_NEXT:
+ if (a->highlight_cycle)
+ _elm_access_highlight_cycle(obj, ELM_FOCUS_NEXT);
+ else
+ return _access_highlight_next_get(obj, ELM_FOCUS_NEXT);
+ break;
+
+ case ELM_ACCESS_ACTION_HIGHLIGHT_PREV:
+ if (a->highlight_cycle)
+ _elm_access_highlight_cycle(obj, ELM_FOCUS_PREVIOUS);
+ else
+ return _access_highlight_next_get(obj, ELM_FOCUS_PREVIOUS);
+ break;
+
+ case ELM_ACCESS_ACTION_ACTIVATE:
+ _elm_access_highlight_object_activate(obj, ELM_ACTIVATE_DEFAULT);
+ break;
+
+ case ELM_ACCESS_ACTION_UP:
+ _elm_access_highlight_object_activate(obj, ELM_ACTIVATE_UP);
+ break;
+
+ case ELM_ACCESS_ACTION_DOWN:
+ _elm_access_highlight_object_activate(obj, ELM_ACTIVATE_DOWN);
+ break;
+
+ case ELM_ACCESS_ACTION_SCROLL:
+ //TODO: SCROLL HIGHLIGHT OBJECT
+ break;
+
+ case ELM_ACCESS_ACTION_BACK:
+ break;
+
+ default:
+ break;
+ }
+
+ return EINA_TRUE;
+}
+
+EAPI void
+elm_access_action_cb_set(Evas_Object *obj, const Elm_Access_Action_Type type,
const Elm_Access_Action_Cb cb, const void *data)
+{
+ Action_Info *a;
+ a = evas_object_data_get(obj, "_elm_access_action_info");
+
+ if (!a)
+ {
+ a = calloc(1, sizeof(Action_Info));
+ evas_object_data_set(obj, "_elm_access_action_info", a);
+ }
+
+ a->obj = obj;
+ a->fn[type].cb = cb;
+ a->fn[type].user_data = (void *)data;
+}
EAPI void
elm_access_external_info_set(Evas_Object *obj, const char *text)
{
diff --git a/src/lib/elm_access.h b/src/lib/elm_access.h
index 20ce6cd..dba781b 100644
--- a/src/lib/elm_access.h
+++ b/src/lib/elm_access.h
@@ -24,13 +24,77 @@ enum _Elm_Access_Info_Type
};
/**
+ * @since 1.8
* @typedef Elm_Access_Info_Type
*/
typedef enum _Elm_Access_Info_Type Elm_Access_Info_Type;
+/**
+ * @enum _Elm_Access_Action_Type
+ * Enum of supported access action types.
+ */
+enum _Elm_Access_Action_Type
+{
+ ELM_ACCESS_ACTION_FIRST = -1,
+
+ ELM_ACCESS_ACTION_HIGHLIGHT, /* highlight an object */
+ ELM_ACCESS_ACTION_UNHIGHLIGHT, /* unhighlight an object */
+ ELM_ACCESS_ACTION_HIGHLIGHT_NEXT, /* set highlight to next object */
+ ELM_ACCESS_ACTION_HIGHLIGHT_PREV, /* set highlight to previous object */
+ ELM_ACCESS_ACTION_ACTIVATE, /* activate a highlight object */
+ ELM_ACCESS_ACTION_SCROLL, /* scroll if one of highlight object parents
+ * is scrollable */
+ ELM_ACCESS_ACTION_UP, /* change value up of highlight object */
+ ELM_ACCESS_ACTION_DOWN, /* change value down of highlight object */
+ ELM_ACCESS_ACTION_BACK, /* go back to a previous view
+ ex: pop naviframe item */
+ ELM_ACCESS_ACTION_READ, /* highlight an object */
+
+ ELM_ACCESS_ACTION_LAST
+};
+
+/**
+ * @since 1.8
+ * @typedef Elm_Access_Action_Type
+ */
+typedef enum _Elm_Access_Action_Type Elm_Access_Action_Type;
+
+struct _Elm_Access_Action_Info
+{
+ Evas_Coord x;
+ Evas_Coord y;
+ unsigned int mouse_type; /* 0: mouse down
+ 1: mouse move
+ 2: mouse up */
+
+ Elm_Access_Action_Type action_type;
+ Elm_Access_Action_Type action_by;
+ Eina_Bool highlight_cycle : 1;
+};
+
+/**
+ * @since 1.8
+ * @typedef Elm_Access_Action_Info
+ */
+typedef struct _Elm_Access_Action_Info Elm_Access_Action_Info;
+
+/**
+ * @since 1.8
+ * @typedef Elm_Access_Action_Cb
+ *
+ * User callback to make access object do specific action
+ *
+ * @param data user data
+ * @param action_info information to classify the action
+ * Returns EINA_TRUE on success, EINA FALSE otherwise
+ *
+ */
+typedef Eina_Bool (*Elm_Access_Action_Cb)(void *data, Evas_Object *obj,
Elm_Access_Action_Info *action_info);
+
typedef char *(*Elm_Access_Info_Cb)(void *data, Evas_Object *obj);
typedef void (*Elm_Access_Activate_Cb)(void *data, Evas_Object *part_obj,
Elm_Object_Item *item);
+
/**
* @brief Register evas object as an accessible object.
* @since 1.8
@@ -146,3 +210,34 @@ EAPI void elm_access_say(const char *text);
* @ingroup Access
*/
EAPI void elm_access_highlight_set(Evas_Object* obj);
+
+/**
+ * @brief Do the accessibility action base on given object.
+ * @since 1.8
+ *
+ * @param obj The object that could be an any object. it would be useful to
use a container widget.
+ * @param type The type of accessibility action.
+ * @param action_info The action information of action @p type to give more
specific information.
+ *
+ * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise
+ *
+ * The return value would be useful, when the @type is
ELM_ACCESS_ACTION_HIGHLIGHT_NEXT
+ * or ELM_ACCESS_ACTION_HIGHLIGHT_PREV. If there is no way to give a highlight,
+ * @c EINA_FALSE will be returned.
+ *
+ * @ingroup Access
+ */
+EAPI Eina_Bool elm_access_action(Evas_Object *obj, const
Elm_Access_Action_Type type, Elm_Access_Action_Info *action_info);
+
+/**
+ * @brief Set a callback function to a given accessibility action type
+ * @since 1.8
+ *
+ * @param obj The object to attach a callback to
+ * @param type The type of accessibility action.
+ * @param cb The callback function to be called when the accessibility action
is triggered.
+ * @param data The data pointer to be passed to @p cb
+ *
+ * @ingroup Access
+ */
+EAPI void elm_access_action_cb_set(Evas_Object *obj, const
Elm_Access_Action_Type type, const Elm_Access_Action_Cb cb, const void *data);
diff --git a/src/lib/elm_widget.h b/src/lib/elm_widget.h
index 5b6c9c9..dc35d2b 100644
--- a/src/lib/elm_widget.h
+++ b/src/lib/elm_widget.h
@@ -310,7 +310,8 @@ typedef enum
ELM_ACTIVATE_UP,
ELM_ACTIVATE_DOWN,
ELM_ACTIVATE_RIGHT,
- ELM_ACTIVATE_LEFT
+ ELM_ACTIVATE_LEFT,
+ ELM_ACTIVATE_BACK
} Elm_Activate;
/* Please, ALWAYS update the ELM_WIDGET_SMART_CLASS_INIT macro
--
------------------------------------------------------------------------------
Precog is a next-generation analytics platform capable of advanced
analytics on semi-structured data. The platform includes APIs for building
apps and a phenomenal toolset for data science. Developers can use
our toolset for easy data analysis & visualization. Get a free account!
http://www2.precog.com/precogplatform/slashdotnewsletter