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.
21 * @file eail_factory.c
22 * @brief Implementation of factory of EAIL accessible widgets
25 #include <Elementary.h>
27 #include "eail_factory.h"
28 #include "eail_widget.h"
29 #include "eail_window.h"
30 #include "eail_background.h"
32 #include "eail_list.h"
33 #include "eail_genlist.h"
34 #include "eail_label.h"
35 #include "eail_button.h"
36 #include "eail_icon.h"
37 #include "eail_entry.h"
38 #include "eail_frame.h"
39 #include "eail_scroller.h"
40 #include "eail_slider.h"
41 #include "eail_action_slider.h"
42 #include "eail_inwin.h"
43 #include "eail_image.h"
44 #include "eail_check.h"
45 #include "eail_radio_button.h"
46 #include "eail_menu.h"
47 #include "eail_photo.h"
48 #include "eail_photocam.h"
49 #include "eail_separator.h"
50 #include "eail_spinner.h"
51 #include "eail_clock.h"
52 #include "eail_calendar.h"
53 #include "eail_grid.h"
54 #include "eail_route.h"
55 #include "eail_dayselector.h"
56 #include "eail_gengrid.h"
57 #include "eail_progressbar.h"
58 #include "eail_diskselector.h"
59 #include "eail_segment_control.h"
60 #include "eail_conformant.h"
61 #include "eail_colorselector.h"
62 #include "eail_notify.h"
63 #include "eail_naviframe.h"
64 #include "eail_datetime.h"
65 #include "eail_hover.h"
66 #include "eail_popup.h"
67 #include "eail_ctxpopup.h"
68 #include "eail_toolbar.h"
69 #include "eail_multibuttonentry.h"
71 #include "eail_index.h"
72 #include "eail_fileselector.h"
73 #include "eail_fileselector_entry.h"
74 #include "eail_panes.h"
75 #include "eail_panel.h"
76 #include "eail_thumb.h"
77 #include "eail_mapbuf.h"
78 #include "eail_slideshow.h"
79 #include "eail_hoversel.h"
81 #include "eail_glview.h"
82 #include "eail_bubble.h"
83 #include "eail_plug.h"
84 #include "eail_video.h"
85 #include "eail_flip.h"
86 #include "eail_flipselector.h"
87 #include "eail_layout.h"
88 #include "eail_table.h"
89 #include "eail_prefs.h"
90 #include "eail_item.h"
91 #include "eail_item_parent.h"
92 #include "eail_priv.h"
94 /** @brief Cache of created AtkObjects for re-using by multiple ATK clients. It holds
95 * EailFactoryObj* objects inside */
96 static Eina_List *eail_cached_objs = NULL;
99 * @brief Creates an EailFactoryObj instance for the given widget and adds it to cache
101 * @param atk_obj AtkObject instance
102 * @param evas_obj Evas_Object instance
105 _eail_factory_append_wdgt_to_cache(AtkObject *atk_obj, Evas_Object *evas_obj)
107 EailFactoryObj *factory_obj = g_new0(EailFactoryObj, 1);
108 factory_obj->atk_obj = atk_obj;
109 factory_obj->evas_obj = evas_obj;
111 eail_cached_objs = eina_list_append(eail_cached_objs, factory_obj);
115 * @brief Tries to find an AtkObject representing the given Evas_Object* in cache
117 * @param widget Evas_Object instance to find in cache
119 * @returns EailFactoryObj representing the given Evas_Object
120 * or NULL if the widget's representation was not found
122 static EailFactoryObj *
123 _eail_factory_find_obj_for_widget(const Evas_Object *widget)
125 const Eina_List *l = NULL;
126 EailFactoryObj *factory_obj = NULL;
128 EINA_LIST_FOREACH(eail_cached_objs, l, factory_obj)
130 if (widget == factory_obj->evas_obj)
136 /* no widget implementation in cache was found */
141 * @brief Creates an accessible AtkObject for Evas_Object*
143 * Returned AtkObject should be unreferenced when no longer needed to free memory.
145 * @param widget Evas_Object* instance
147 * @returns AtkObject representing the accessible representation of the specified
151 _eail_factory_create_accessible(Evas_Object *widget)
153 const char *type = NULL;
154 AtkObject *accessible = NULL;
156 type = elm_object_widget_type_get(widget);
158 if ((!strcmp(type, "Elm_Win")) || (!strcmp(type, "elm_win")))
160 accessible = g_object_new(EAIL_TYPE_WINDOW, NULL);
162 else if ((!strcmp(type, "Elm_Bg")) || (!strcmp(type, "elm_bg")))
164 accessible = g_object_new(EAIL_TYPE_BACKGROUND, NULL);
166 else if ((!strcmp(type, "Elm_Box")) || (!strcmp(type, "elm_box")))
168 accessible = g_object_new(EAIL_TYPE_BOX, NULL);
170 else if ((!strcmp(type, "Elm_List")) || (!strcmp(type, "elm_list")))
172 accessible = g_object_new(EAIL_TYPE_LIST, NULL);
174 else if ((!strcmp(type, "Elm_Genlist")) || (!strcmp(type, "elm_genlist")))
176 accessible = g_object_new(EAIL_TYPE_GENLIST, NULL);
178 else if ((!strcmp(type, "Elm_Label")) || (!strcmp(type, "elm_label")))
180 accessible = g_object_new(EAIL_TYPE_LABEL, NULL);
182 else if ((!strcmp(type, "Elm_Button")) || (!strcmp(type, "elm_button")))
184 accessible = g_object_new(EAIL_TYPE_BUTTON, NULL);
186 else if ((!strcmp(type, "Elm_Icon")) || (!strcmp(type, "elm_icon")))
188 accessible = g_object_new(EAIL_TYPE_ICON, NULL);
190 else if ((!strcmp(type, "entry")) || (!strcmp(type, "Elm_Entry")) || (!strcmp(type, "elm_entry")))
192 accessible = g_object_new(EAIL_TYPE_ENTRY, NULL);
194 else if ((!strcmp(type, "Elm_Frame")) || (!strcmp(type, "elm_frame")))
196 accessible = g_object_new(EAIL_TYPE_FRAME, NULL);
198 else if ((!strcmp(type, "Elm_Scroller")) || (!strcmp(type, "elm_scroller")))
200 accessible = g_object_new(EAIL_TYPE_SCROLLER, NULL);
202 else if ((!strcmp(type, "Elm_Inwin")) || (!strcmp(type, "elm_inwin")))
204 accessible = g_object_new(EAIL_TYPE_INWIN, NULL);
206 else if ((!strcmp(type, "Elm_Slider")) || (!strcmp(type, "elm_slider")))
208 accessible = g_object_new(EAIL_TYPE_SLIDER, NULL);
210 else if ((!strcmp(type, "Elm_Actionslider")) || (!strcmp(type, "elm_actionslider")))
212 accessible = g_object_new(EAIL_TYPE_ACTION_SLIDER, NULL);
214 else if ((!strcmp(type, "Elm_Imgae")) || (!strcmp(type, "elm_image")))
216 accessible = g_object_new(EAIL_TYPE_IMAGE, NULL);
218 else if ((!strcmp(type, "Elm_Check")) || (!strcmp(type, "elm_check")))
220 accessible = g_object_new(EAIL_TYPE_CHECK, NULL);
222 else if ((!strcmp(type, "Elm_Radio")) || (!strcmp(type, "elm_radio")))
224 accessible = g_object_new(EAIL_TYPE_RADIO_BUTTON, NULL);
226 else if ((!strcmp(type, "Elm_Menu")) || (!strcmp(type, "elm_menu")))
228 accessible = g_object_new(EAIL_TYPE_MENU, NULL);
230 else if ((!strcmp(type, "Elm_Photo")) || (!strcmp(type, "elm_photo")))
232 accessible = g_object_new(EAIL_TYPE_PHOTO, NULL);
234 else if ((!strcmp(type, "Elm_Photocam")) || (!strcmp(type, "elm_photocam")))
236 accessible = g_object_new(EAIL_TYPE_PHOTOCAM, NULL);
238 else if ((!strcmp(type, "Elm_Separator")) || (!strcmp(type, "elm_separator")))
240 accessible = g_object_new(EAIL_TYPE_SEPARATOR, NULL);
242 else if ((!strcmp(type, "Elm_Spinner")) || (!strcmp(type, "elm_spinner")))
244 accessible = g_object_new(EAIL_TYPE_SPINNER, NULL);
246 else if ((!strcmp(type, "Elm_Clock")) || (!strcmp(type, "elm_clock")))
248 accessible = g_object_new(EAIL_TYPE_CLOCK, NULL);
250 else if ((!strcmp(type, "Elm_Calendar")) || (!strcmp(type, "elm_calendar")))
252 accessible = g_object_new(EAIL_TYPE_CALENDAR, NULL);
254 else if ((!strcmp(type, "Elm_Grid")) || (!strcmp(type, "elm_grid")))
256 accessible = g_object_new(EAIL_TYPE_GRID, NULL);
258 else if ((!strcmp(type, "Elm_Route")) || (!strcmp(type, "elm_route")))
260 accessible = g_object_new(EAIL_TYPE_ROUTE, NULL);
262 else if ((!strcmp(type, "Elm_Dayselector")) || (!strcmp(type, "elm_dayselector")))
264 accessible = g_object_new(EAIL_TYPE_DAYSELECTOR, NULL);
266 else if ((!strcmp(type, "Elm_Gengrid")) || (!strcmp(type, "elm_gengrid")))
268 accessible = g_object_new(EAIL_TYPE_GENGRID, NULL);
270 else if ((!strcmp(type, "Elm_Progressbar")) || (!strcmp(type, "elm_progressbar")))
272 accessible = g_object_new(EAIL_TYPE_PROGRESSBAR, NULL);
274 else if ((!strcmp(type, "Elm_Diskselector")) || (!strcmp(type, "elm_diskselector")))
276 accessible = g_object_new(EAIL_TYPE_DISKSELECTOR, NULL);
278 else if ((!strcmp(type, "Elm_Segment_Control")) || (!strcmp(type, "elm_segment_control")))
280 accessible = g_object_new(EAIL_TYPE_SEGMENT_CONTROL, NULL);
282 else if ((!strcmp(type, "Elm_Conformant")) || (!strcmp(type, "elm_conformant")))
284 accessible = g_object_new(EAIL_TYPE_CONFORMANT, NULL);
286 else if ((!strcmp(type, "Elm_Notify")) || (!strcmp(type, "elm_notify")))
288 accessible = g_object_new(EAIL_TYPE_NOTIFY, NULL);
290 else if ((!strcmp(type, "popup")) || (!strcmp(type, "Elm_Popup")) || (!strcmp(type, "elm_popup")))
292 accessible = g_object_new(EAIL_TYPE_POPUP, NULL);
294 else if ((!strcmp(type, "ctxpopup")) || (!strcmp(type, "Elm_Ctxpopup")) || (!strcmp(type, "elm_ctxpopup")))
296 accessible = g_object_new(EAIL_TYPE_CTXPOPUP, NULL);
298 else if ((!strcmp(type, "toolbar")) || (!strcmp(type, "Elm_Toolbar")) || (!strcmp(type, "elm_toolbar")))
300 accessible = g_object_new(EAIL_TYPE_TOOLBAR, NULL);
302 else if ((!strcmp(type, "Elm_Multibuttonentry")) || (!strcmp(type, "elm_multibuttonentry")))
304 accessible = g_object_new(EAIL_TYPE_MULTIBUTTONENTRY, NULL);
306 else if ((!strcmp(type, "Elm_Web")) || (!strcmp(type, "elm_web")))
308 accessible = g_object_new(EAIL_TYPE_WEB, NULL);
310 else if ((!strcmp(type, "Elm_Index")) || (!strcmp(type, "elm_index")))
312 accessible = g_object_new(EAIL_TYPE_INDEX, NULL);
314 else if ((!strcmp(type, "Elm_Fileselector")) || (!strcmp(type, "elm_fileselector")))
316 accessible = g_object_new(EAIL_TYPE_FILESELECTOR, NULL);
318 else if ((!strcmp(type, "Elm_Fileselector_Entry")) || (!strcmp(type, "elm_fileselector_entry")) ||
319 (!strcmp(type, "fileselector_entry")))
321 accessible = g_object_new(EAIL_TYPE_FILESELECTOR_ENTRY, NULL);
323 else if ((!strcmp(type, "Elm_Fileselector_Button")) || (!strcmp(type, "elm_fileselector_button")))
325 /* NOTE: file selector button from accesibility point of view is
326 * no different in handling than regular push button */
327 accessible = g_object_new(EAIL_TYPE_BUTTON, NULL);
329 else if ((!strcmp(type, "Elm_Colorselector")) || (!strcmp(type, "elm_colorselector")))
331 accessible = g_object_new(EAIL_TYPE_COLORSELECTOR, NULL);
333 else if ((!strcmp(type, "Elm_Naviframe")) || (!strcmp(type, "elm_naviframe")))
335 accessible = g_object_new(EAIL_TYPE_NAVIFRAME, NULL);
337 else if ((!strcmp(type, "Elm_Datetime")) || (!strcmp(type, "elm_datetime")))
339 accessible = g_object_new(EAIL_TYPE_DATETIME, NULL);
341 else if ((!strcmp(type, "Elm_Hover")) || (!strcmp(type, "elm_hover")))
343 accessible = g_object_new(EAIL_TYPE_HOVER, NULL);
345 else if ((!strcmp(type, "Elm_Panes")) || (!strcmp(type, "elm_panes")))
347 accessible = g_object_new(EAIL_TYPE_PANES, NULL);
349 else if ((!strcmp(type, "panel")) || (!strcmp(type, "Elm_Panel")) || (!strcmp(type, "elm_panel")))
351 accessible = g_object_new(EAIL_TYPE_PANEL, NULL);
353 else if ((!strcmp(type, "Elm_Thumb")) || (!strcmp(type, "elm_thumb")))
355 accessible = g_object_new(EAIL_TYPE_THUMB, NULL);
357 else if ((!strcmp(type, "Elm_Mapbuf")) || (!strcmp(type, "elm_mapbuf")))
359 accessible = g_object_new(EAIL_TYPE_MAPBUF, NULL);
361 else if ((!strcmp(type, "Elm_Slideshow")) || (!strcmp(type, "elm_slideshow")))
363 accessible = g_object_new(EAIL_TYPE_SLIDESHOW, NULL);
365 else if ((!strcmp(type, "Elm_Hoversel")) || (!strcmp(type, "elm_hoversel")))
367 accessible = g_object_new(EAIL_TYPE_HOVERSEL, NULL);
369 else if ((!strcmp(type, "Elm_Map")) || (!strcmp(type, "elm_map")))
371 accessible = g_object_new(EAIL_TYPE_MAP, NULL);
373 else if ((!strcmp(type, "Elm_Glview")) || (!strcmp(type, "elm_glview")))
375 accessible = g_object_new(EAIL_TYPE_GLVIEW, NULL);
377 else if ((!strcmp(type, "Elm_Bubble")) || (!strcmp(type, "elm_bubble")))
379 accessible = g_object_new(EAIL_TYPE_BUBBLE, NULL);
381 else if ((!strcmp(type, "Elm_Plug")) || (!strcmp(type, "elm_plug")))
383 accessible = g_object_new(EAIL_TYPE_PLUG, NULL);
385 else if ((!strcmp(type, "Elm_Video")) || (!strcmp(type, "elm_video")) || (!strcmp(type, "elm_player")))
387 accessible = g_object_new(EAIL_TYPE_VIDEO, NULL);
389 else if ((!strcmp(type, "Elm_Flip")) || (!strcmp(type, "elm_flip")))
391 accessible = g_object_new(EAIL_TYPE_FLIP, NULL);
393 else if ((!strcmp(type, "Elm_Flipselector")) || (!strcmp(type, "elm_flipselector")))
395 accessible = g_object_new(EAIL_TYPE_FLIPSELECTOR, NULL);
397 else if ((!strcmp(type, "Elm_Layout")) || (!strcmp(type, "elm_layout")))
399 accessible = g_object_new(EAIL_TYPE_LAYOUT, NULL);
401 else if ((!strcmp(type, "Elm_Table")) || (!strcmp(type, "elm_table")))
403 accessible = g_object_new(EAIL_TYPE_TABLE, NULL);
405 else if ((!strcmp(type, "Elm_Prefs")) || (!strcmp(type, "elm_prefs")))
407 accessible = g_object_new(EAIL_TYPE_PREFS, NULL);
411 DBG("Unrecognized specific widget type: %s", type);
412 DBG("Creating basic widget with NULL type.");
413 accessible = g_object_new(EAIL_TYPE_WIDGET, NULL);
418 atk_object_initialize(accessible, widget);
426 * @brief Creates a new EailItem instance with the given ATK role
428 * @param item Elm_Object_Item instance
429 * @param parent AtkObject instance that holds EailItem instance
430 * @param role AtkRole instance that will be used by EailItem
432 * @returns EailItem representing the new EailItem instance
433 * or NULL in case of an error
436 _eail_factory_create_item_atk_obj(Elm_Object_Item *item,
442 obj = g_object_new(EAIL_TYPE_ITEM, NULL);
444 atk_object_set_parent(obj, parent);
445 atk_object_initialize(obj, item);
451 * @param atk_obj AtkObject instance
452 * @param item Elm_Object_Item instance
455 eail_factory_append_item_to_cache(AtkObject *atk_obj, Elm_Object_Item *item)
457 EailFactoryObj *factory_obj = g_new0(EailFactoryObj, 1);
458 factory_obj->atk_obj = atk_obj;
459 factory_obj->obj_item = item;
461 eail_cached_objs = eina_list_append(eail_cached_objs, factory_obj);
465 * @param item Elm_Object_Item* instance to be found
466 * @returns EailFactoryObj instance or NULL if item's representation was not
470 eail_factory_find_obj_for_item(const Elm_Object_Item *item)
472 const Eina_List *l = NULL;
473 EailFactoryObj *factory_obj = NULL;
475 EINA_LIST_FOREACH(eail_cached_objs, l, factory_obj)
477 if (item == factory_obj->obj_item)
483 /* no Atk Elm_Object_Item implementation in cache was found */
489 * If AtkObject was already created for the given item, instance will be returned
490 * from cache instead of creating a new one (it is needed to allow the setting and
491 * storing of name/description changes by multiple clients).
493 * @param item Elm_Object_Item instance that will be used as a source for the AtkObject
495 * @param role role for given item
496 * @param parent AtkObject instance that has the given item inside its content (eg. for
497 * list-item this will be EailList instance)
499 * @returns AtkObject representing the item or NULL in case of a failure
502 eail_factory_get_item_atk_obj(Elm_Object_Item *item,
507 EailFactoryObj *factory_obj = NULL;
509 if (!EAIL_IS_ITEM_PARENT(parent))
511 ERR("Parent does not implement ITEM_PARENT interface");
515 /* first trying to get object from cache*/
516 factory_obj = eail_factory_find_obj_for_item(item);
519 /* already found implementation, no need to create new obj, returning
520 * existing one from cache */
521 if (!factory_obj->atk_obj)
523 ERR("No atk obj found in eail_factory_widget!");
527 return factory_obj->atk_obj;
530 /* if not in cache then creating and then adding to cache for future use*/
531 atk_obj = _eail_factory_create_item_atk_obj(item, role, parent);
532 eail_factory_append_item_to_cache(atk_obj, item);
539 * @param item Elm_Object_Item* instance to be deregistered
542 eail_factory_unregister_item_from_cache(Elm_Object_Item *item)
544 EailFactoryObj *factory_obj = NULL;
546 factory_obj = eail_factory_find_obj_for_item(item);
547 if (!factory_obj) return;
549 eail_cached_objs = eina_list_remove(eail_cached_objs, factory_obj);
556 * @param widget Evas_Object* instance to be deregistered
559 eail_factory_unregister_wdgt_from_cache(Evas_Object *widget)
561 EailFactoryObj *factory_obj = NULL;
563 factory_obj = _eail_factory_find_obj_for_widget(widget);
564 if (!factory_obj) return;
566 eail_cached_objs = eina_list_remove(eail_cached_objs, factory_obj);
572 * @param widget Evas_Object* instance
574 * The returned AtkObject should be unreferenced when no longer needed
577 * @returns AtkObject which is the accessible representation of the specified
581 eail_factory_get_accessible(Evas_Object *widget)
583 EailFactoryObj *factory_widget = NULL;
584 AtkObject *atk_obj = NULL;
588 DBG("Cannot create accessible for NULL-widget");
592 if (!elm_object_widget_check(widget))
594 DBG("%s is NOT elementary object widget!",
595 evas_object_type_get(widget));
599 /* looking for object in cache*/
600 factory_widget = _eail_factory_find_obj_for_widget(widget);
603 /* already found implementation, no need to create new obj, returning
604 * existing one from cache */
605 if (!factory_widget->atk_obj)
607 ERR("No atk obj found in eail_factory_widget!");
611 return factory_widget->atk_obj;
614 /* not found in cache, need to create new instance for atk obj
616 atk_obj = _eail_factory_create_accessible(widget);
619 ERR("No atk obj created in factory");
623 /* appending obj for future re-using*/
624 _eail_factory_append_wdgt_to_cache(atk_obj, widget);
630 * @param role an AtkRole for objects that have to be found
632 * @returns an Eina_List filled with AtkObject * objects
635 eail_factory_find_objects_with_role(AtkRole role)
637 const Eina_List *l = NULL;
638 Eina_List *results_list = NULL;
639 EailFactoryObj *factory_obj = NULL;
641 EINA_LIST_FOREACH(eail_cached_objs, l, factory_obj)
643 AtkObject *atk_obj = factory_obj->atk_obj;
644 if (atk_obj && role == atk_obj->role)
645 results_list = eina_list_append(results_list, atk_obj);