2 * Copyright (c) 2013 Samsung Electronics Co., Ltd.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public License
15 * along with this library; see the file COPYING.LIB. If not, write to
16 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
22 * @brief Implementation of utility functions used in various places in EAIL
26 /* enabling beta API support for Eo parts*/
27 #define EFL_BETA_API_SUPPORT
30 #include <Elementary.h>
34 /* internal elm_widget api for listening EDJE parts */
36 #define ELM_INTERNAL_API_ARGESFSDFEFC
37 #include <elm_widget.h>
39 #include "eail_utils.h"
40 #include "eail_factory.h"
41 #include "eail_dynamic_content.h"
42 #include "eail_priv.h"
45 * @param string base string to get substring from
46 * @param start_offset beginning offset
47 * @param end_offset end offset
49 * @returns newly allocated substring
52 eail_get_substring(const gchar *string,
56 gchar *substring = NULL;
60 if (!string) return NULL;
62 len = g_utf8_strlen(string, -1);
64 if ((start_offset < 0) ||
65 (start_offset > len - 1) ||
68 else if (end_offset == -1 ||
69 end_offset >= len - 1)
70 sub_len = len - start_offset + 1;
72 sub_len = end_offset - start_offset;
74 substring = g_malloc0(sub_len + 1);
76 return g_utf8_strncpy(substring, &string[start_offset], sub_len);
80 * @param widget Evas_Object for getting state_set
81 * @param state_set current state_set taken from objects parent
83 * @returns filled AtkStateSet for given EvasObject
86 eail_evas_obj_ref_state_set(Evas_Object *widget, AtkStateSet *state_set)
89 atk_state_set_add_state(state_set, ATK_STATE_DEFUNCT);
93 if (!elm_object_disabled_get(widget)) {
94 atk_state_set_add_state(state_set, ATK_STATE_SENSITIVE);
95 atk_state_set_add_state(state_set, ATK_STATE_ENABLED);
98 if (evas_object_visible_get(widget)) {
99 int x, y, width, height;
100 int vp_x, vp_y, vp_width, vp_height;
102 atk_state_set_add_state(state_set, ATK_STATE_VISIBLE);
104 evas_object_geometry_get(widget, &x, &y, &width, &height);
105 evas_output_viewport_get(evas_object_evas_get(widget),
106 &vp_x, &vp_y, &vp_width, &vp_height);
108 if ((x + width) >= vp_x && (y + height) >= vp_y &&
109 (vp_x + vp_width) >= x && (vp_y + vp_height) >= y) {
110 atk_state_set_add_state(state_set, ATK_STATE_SHOWING);
114 if (elm_object_focus_allow_get(widget)) {
115 atk_state_set_add_state(state_set, ATK_STATE_FOCUSABLE);
117 if (elm_object_focus_get(widget)) {
118 atk_state_set_add_state(state_set, ATK_STATE_FOCUSED);
126 * @param widget an Evas_Object
127 * @return TRUE if grabbing focus was successfull, FALSE otherwise
130 eail_evas_obj_grab_focus(Evas_Object *widget)
132 Ecore_Evas *ee = ecore_evas_ecore_evas_get(evas_object_evas_get(widget));
134 if (!widget || !elm_object_focus_allow_get(widget)) {
138 ecore_evas_activate(ee);
139 elm_object_focus_set(widget, EINA_TRUE);
145 * @param widget an Evas_Object to press on
150 eail_mouse_press_on_coords(Evas_Object *widget, int x, int y)
153 evas = evas_object_evas_get(widget);
155 evas_event_feed_mouse_move(evas, x, y, 0, NULL);
156 evas_event_feed_mouse_down(evas, 1, EVAS_BUTTON_NONE, 0, NULL);
160 * @param widget an Evas_Object to press on
165 eail_mouse_release_on_coords(Evas_Object *widget, int x, int y)
168 evas = evas_object_evas_get(widget);
170 evas_event_feed_mouse_move(evas, x, y, 0, NULL);
171 evas_event_feed_mouse_up(evas, 1, EVAS_BUTTON_NONE, 0, NULL);
175 * @param widget an Evas_Object to click on
180 eail_mouse_click_on_coords(Evas_Object *widget, int x, int y)
183 evas = evas_object_evas_get(widget);
185 evas_event_feed_mouse_move(evas, x, y, 0, NULL);
186 evas_event_feed_mouse_down(evas, 1, EVAS_BUTTON_NONE, 0, NULL);
187 evas_event_feed_mouse_up(evas, 1, EVAS_BUTTON_NONE, 0, NULL);
191 * @param widget an Evas_Object to get values for
192 * @param x address of int to put X coord in
193 * @param y address of int to put Y coord in
196 eail_get_coords_widget_center(Evas_Object *widget, int *x, int *y)
199 evas_object_geometry_get(widget, x, y, &w, &h);
206 * @param item an Elm_Object_Item*
208 * @returns Eina_List * filled with raw Evas_Object* (not every returned
209 * Evas_Object is widget - widget-only content is returned by
210 * eail_get_edje_parts_for_item function)
213 eail_get_raw_evas_obj_list_from_item(Elm_Object_Item *item)
215 Evas_Object *edje = NULL;
220 DBG("Edje object for item not found. Returning empty list");\
224 return evas_object_smart_members_get(edje);
228 * @param item Elm_Object_Item * to get strings from
229 * @returns EinaList filled with const gchar* that are representing text
230 * content of item. List have to be freed when no longer needed but DO NOT
231 * FREE CONTENT STRINGS.
234 eail_item_get_content_strings(Elm_Object_Item *item)
236 Eina_List *strings_list = NULL;
237 Eina_List *edje_parts = NULL;
238 Evas_Object *part = NULL;
242 edje_parts = eail_get_raw_evas_obj_list_from_item(item);
243 EINA_LIST_FOREACH(edje_parts, l, part)
245 const gchar *type_name = evas_object_type_get(part);
247 if (0 == strcmp(type_name, "text"))
249 const gchar *text = evas_object_text_text_get(part);
252 strings_list = eina_list_append(strings_list, text);
260 * It does filtering inside and returs only parts that can be used later in
261 * eail factory (only widgets will be returned)
263 * @param item Elm_Object_Item * to get objects from
265 * @returns Eina_List* filled with Evas_Object* objects representing content
269 eail_get_edje_parts_for_item(Elm_Object_Item *item)
271 Eina_List *edje_parts = NULL;
272 Eina_List *usable_parts = NULL;
275 edje_parts = eail_get_raw_evas_obj_list_from_item(item);
276 for (i = 0; i < eina_list_count(edje_parts); ++i)
278 Evas_Object *obj = eina_list_nth(edje_parts, i);
280 /* adding only parts that can be used by eail_factory later */
281 if (elm_object_widget_check(obj))
282 usable_parts = eina_list_append(usable_parts, obj);
285 eina_list_free(edje_parts);
292 * @param widget am Evas_Object
293 * @param type type of scroll action
295 * @returns TRUE if scroll action was successful, FALSE otherwise
298 eail_handle_scroll(Evas_Object *widget,
299 enum EAIL_SCROLL_TYPE type)
303 elm_scroller_region_get(widget, &x, &y, &w, &h);
305 if (EAIL_SCROLL_TYPE_UP == type)
307 else if (EAIL_SCROLL_TYPE_DOWN == type)
309 else if (EAIL_SCROLL_TYPE_RIGHT == type)
311 else if (EAIL_SCROLL_TYPE_LEFT == type)
314 elm_scroller_region_bring_in(widget, x, y, w, h);
321 * @param widget an Evas_Object*
322 * @param data additional action data
323 * @returns TRUE if scroll action was successful, FALSE otherwise
326 eail_action_scroll_up(Evas_Object *widget,
329 return eail_handle_scroll(widget, EAIL_SCROLL_TYPE_UP);
334 * @param widget an Evas_Object*
335 * @param data additional action data
337 * @returns TRUE if scroll action was successful, FALSE otherwise
340 eail_action_scroll_down(Evas_Object *widget,
343 return eail_handle_scroll(widget, EAIL_SCROLL_TYPE_DOWN);
348 * @param widget an Evas_Object*
349 * @param data additional action data
351 * @returns TRUE if scroll action was successful, FALSE otherwise
354 eail_action_scroll_left(Evas_Object *widget,
357 return eail_handle_scroll(widget, EAIL_SCROLL_TYPE_LEFT);
362 * @param widget an Evas_Object*
363 * @param data additional action data
365 * @returns TRUE if scroll action was successful, FALSE otherwise
368 eail_action_scroll_right(Evas_Object *widget,
371 return eail_handle_scroll(widget, EAIL_SCROLL_TYPE_RIGHT);
375 * @param atk_obj an AtkObject that emits the signal
376 * @param signal_name name of signal
377 * @param object_type an GType of object
380 eail_emit_atk_signal(AtkObject *atk_obj, const gchar *signal_name,
383 guint signal = g_signal_lookup (signal_name,object_type);
386 ERR("No signal with name %s was found", signal_name);
390 DBG("Raising %s signal", signal_name);
391 g_signal_emit (atk_obj, signal, 0);
395 * @param added boolean used for marking if child is added. TRUE if child was
396 * added, FALSE when child was removed
397 * @param atk_obj an AtkObject that emits the signal
398 * @param child_number index number of changed child
401 eail_emit_children_changed(gboolean added, AtkObject *atk_obj, gint child_number)
404 DBG("Emitting child-changed for index %d. ADDED: %d", child_number, added);
407 g_signal_emit_by_name
408 (atk_obj, "children_changed::add", child_number, NULL, NULL);
410 g_signal_emit_by_name
411 (atk_obj, "children_changed::remove", child_number, NULL, NULL);
416 * @param added boolean used for marking if child is added. TRUE if child was
417 * added, FALSE when child was removed
418 * @param atk_obj an AtkObject that emits the signal
419 * @param changed_obj pointer to object that has been added/removed
422 eail_emit_children_changed_obj(gboolean added,
424 AtkObject *changed_obj)
427 DBG("Emitting child-changed for obj. ADDED: %d", added);
430 g_signal_emit_by_name
431 (atk_obj, "children_changed::add", NULL, changed_obj, NULL);
433 g_signal_emit_by_name
434 (atk_obj, "children_changed::remove", NULL, changed_obj, NULL);
438 * @brief handles 'selected' state changes for item
440 * @param item an Elm_Object* item
441 * @param selected value of 'selected' state
442 * @param parent an AtkObject* that holds item inside
443 * @param role an AtkRole for item
446 _eail_handle_selected_for_item(Elm_Object_Item *item,
451 AtkObject *atk_item_obj = NULL;
452 if (!item && !parent)
454 ERR("Wrong parameters passed. Ignoring event");
458 atk_item_obj = eail_factory_get_item_atk_obj(item, role, parent);
461 DBG("Couldn't find factory obj for item. Ignoring 'selected' event");
465 atk_object_notify_state_change(atk_item_obj, ATK_STATE_SELECTED, selected);
469 * @brief Function that calls apropriate handling for selected event
471 * @param data passed to callback
472 * @param obj object that raised event
473 * @param event_info additional event info
474 * @param selected selected state
477 _eail_list_item_do_handle_selected_event(void *data,
482 Elm_Object_Item *obj_item = (Elm_Object_Item*)event_info;
485 DBG("obj_item not found in event_info. Ignoring event..");
489 eail_notify_child_focus_changes();
490 _eail_handle_selected_for_item
491 (obj_item, selected, ATK_OBJECT(data), ATK_ROLE_LIST_ITEM);
496 * @param data passed to callback
497 * @param obj object that raised event
498 * @param event_info additional event info
501 eail_list_item_handle_selected_event(void *data,
505 _eail_list_item_do_handle_selected_event(data, obj, event_info, TRUE);
510 * @param data passed to callback
511 * @param obj object that raised event
512 * @param event_info additional event info
515 eail_list_item_handle_unselected_event(void *data,
519 _eail_list_item_do_handle_selected_event(data, obj, event_info, FALSE);
523 * @brief Notifies objects with given role about possible hierarchy changes
525 * @param data an AtkRole
527 * @returns always FALSE
530 _notifiy_content_holders_by_type(gpointer data)
532 Eina_List *objs = NULL, *l = NULL;
533 AtkObject *atk_obj = NULL;
534 AtkRole role = ATK_ROLE_INVALID;
536 role = (AtkRole)data;
538 if (ATK_ROLE_APPLICATION == role)
540 atk_obj = atk_get_root();
541 if (atk_obj && EAIL_IS_DYNAMIC_CONTENT(atk_obj))
542 eail_dynamic_content_update_hierarchy(EAIL_DYNAMIC_CONTENT(atk_obj));
548 objs = eail_factory_find_objects_with_role(role);
549 EINA_LIST_FOREACH(objs, l, atk_obj)
551 if (EAIL_IS_DYNAMIC_CONTENT(atk_obj))
553 eail_dynamic_content_update_hierarchy
554 (EAIL_DYNAMIC_CONTENT(atk_obj));
557 eina_list_free(objs);
564 * @brief Sends notification about possible hierarchy changes to objects
565 * with dynamic content interface
567 * @param delay value in miliseconds, objects will be notified after this
571 _eail_notify_focus_listeners_delayed(guint delay)
574 (delay, _notifiy_content_holders_by_type, (gpointer)ATK_ROLE_APPLICATION);
576 (delay, _notifiy_content_holders_by_type, (gpointer)ATK_ROLE_WINDOW);
578 (delay, _notifiy_content_holders_by_type, (gpointer)ATK_ROLE_FILLER);
582 eail_notify_child_focus_changes(void)
584 _eail_notify_focus_listeners_delayed(0);
585 /* sending delayed notifications to objects after hierarchy has
586 * been fully established*/
587 _eail_notify_focus_listeners_delayed(1600);