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_genlist.c
22 * @brief EailGenlist implementation
27 #include <Elementary.h>
29 #include "eail_genlist.h"
30 #include "eail_item_parent.h"
31 #include "eail_factory.h"
32 #include "eail_utils.h"
33 #include "eail_priv.h"
35 static void eail_item_parent_interface_init (EailItemParentIface *iface);
36 static void atk_selection_interface_init(AtkSelectionIface *iface);
39 * @brief Definition of EailGenlist as GObject
41 * EailList is extended ScrollableWidget with EAIL_TYPE_ITEM_PARENT and
42 * ATK_TYPE_SELECTION implemented
44 G_DEFINE_TYPE_WITH_CODE(EailGenlist, eail_genlist, EAIL_TYPE_SCROLLABLE_WIDGET,
45 G_IMPLEMENT_INTERFACE(EAIL_TYPE_ITEM_PARENT,
46 eail_item_parent_interface_init)
47 G_IMPLEMENT_INTERFACE(ATK_TYPE_SELECTION,
48 atk_selection_interface_init));
51 * @brief Genlist text part name
53 #define EAIL_GENLIST_TEXT "elm.text"
56 * Implementation of the *AtkObject* interface
60 * @brief Handler for realized event
62 * Notifies about genlist's content changes.
64 * @param data passed to callback
65 * @param obj Evas_Object that raised event
66 * @param event_info additional event info (item is passed here)
69 eail_list_item_handle_realized_event(void *data,
73 Elm_Object_Item *item = (Elm_Object_Item *) event_info;
74 AtkObject *atk_item = NULL, *atk_parent = NULL;
76 atk_parent = ATK_OBJECT(data);
77 if (!atk_parent) return;
79 atk_item = eail_factory_get_item_atk_obj
80 (item, ATK_ROLE_LIST_ITEM, atk_parent);
82 if (!atk_item) return;
84 eail_emit_children_changed_obj(TRUE, atk_parent, atk_item);
88 * @brief Handler for unrealized event, used to notify about genlist content
91 * @param data passed to callback
92 * @param obj object that raised event
93 * @param event_info additional event info (item is passed here)
96 eail_list_item_handle_unrealized_event(void *data,
100 Elm_Object_Item *item = (Elm_Object_Item *) event_info;
101 AtkObject *atk_item = NULL, *atk_parent = NULL;
103 atk_parent = ATK_OBJECT(data);
104 if (!atk_parent) return;
106 atk_item = eail_factory_get_item_atk_obj
107 (item, ATK_ROLE_LIST_ITEM, atk_parent);
109 if (!atk_item) return;
111 eail_emit_children_changed_obj(FALSE, atk_parent, atk_item);
112 atk_object_notify_state_change(atk_item, ATK_STATE_DEFUNCT, TRUE);
114 DBG("Unregistering item from cache...");
115 eail_factory_unregister_item_from_cache(item);
119 * @brief Initializer for AtkObjectClass
120 * @param obj AtkObject instance
121 * @param data initialization data
124 eail_genlist_initialize(AtkObject *obj, gpointer data)
126 Evas_Object *nested_widget = NULL;
127 ATK_OBJECT_CLASS(eail_genlist_parent_class)->initialize(obj, data);
129 obj->role = ATK_ROLE_LIST;
130 g_return_if_fail(EAIL_IS_WIDGET(obj));
132 nested_widget = eail_widget_get_widget(EAIL_WIDGET(obj));
135 ERR("No evas object inside EailWidget was found");
139 evas_object_smart_callback_add(nested_widget, "selected",
140 eail_list_item_handle_selected_event, obj);
141 evas_object_smart_callback_add(nested_widget, "unselected",
142 eail_list_item_handle_unselected_event, obj);
143 evas_object_smart_callback_add(nested_widget, "realized",
144 eail_list_item_handle_realized_event, obj);
145 evas_object_smart_callback_add(nested_widget, "unrealized",
146 eail_list_item_handle_unrealized_event, obj);
150 * @brief Prepares Eina_List filled with Elm_Object_Item* objects
151 * representing items in the list
153 * Call eina_list_free on the returned list when results processing has been finished.
155 * @param genlist EailGenlist instance
157 * @return Eina_List representing the list of list's items
160 eail_genlist_get_items(EailGenlist *genlist)
162 Eina_List *items = NULL;
163 Elm_Object_Item *item;
164 Evas_Object *widget = eail_widget_get_widget(EAIL_WIDGET(genlist));
166 item = elm_genlist_first_item_get(widget);
168 items = eina_list_append(items, item);
169 item = elm_genlist_item_next_get(item);
176 * @brief Gets the number of accessible children of the accessible
178 * Implementation of AtkObject->get_n_children callback.
180 * @param obj AtkObject instance
182 * @returns integer representing the number of accessible children of
186 eail_genlist_get_n_children(AtkObject *obj)
191 items = eail_genlist_get_items(EAIL_GENLIST(obj));
192 n_items = eina_list_count(items);
194 eina_list_free(items);
200 * @brief Gets a reference to the specified accessible child of the object.
202 * The accessible children are 0-based so the first accessible child is
203 * at index 0, the second at index 1 and so on.
205 * Implementation of AtkObject->ref_child callback.
207 * @param obj AtkObject instance
208 * @param i child's index
210 * @returns AtkObject representing the specified accessible child of the
214 eail_genlist_ref_child(AtkObject *obj, gint i)
217 AtkObject *child = NULL;
219 items = eail_genlist_get_items(EAIL_GENLIST(obj));
220 if (eina_list_count(items) > i) {
221 child = eail_factory_get_item_atk_obj
222 (eina_list_nth(items, i), ATK_ROLE_LIST_ITEM, obj);
227 eina_list_free(items);
233 * @brief Gets a reference to the state set of the accessible
235 * The caller must unreference it when it is no longer needed.
237 * Implementation of AtkObject->ref_state_set callback.
239 * @param obj AtkObject instance
241 * @returns AtkStateSet representing the state set of the
245 eail_genlist_ref_state_set(AtkObject *obj)
247 AtkStateSet *state_set;
248 Evas_Object *widget = eail_widget_get_widget(EAIL_WIDGET(obj));
250 state_set = ATK_OBJECT_CLASS(eail_genlist_parent_class)->ref_state_set(obj);
256 if (elm_genlist_multi_select_get(widget)) {
257 atk_state_set_add_state(state_set, ATK_STATE_MULTISELECTABLE);
264 * @brief Initializer for GObject EailList instance
266 * @param genlist EailGenlist instance
269 eail_genlist_init(EailGenlist *genlist)
274 * @brief Initializer for GObject class
276 * Defines callbacks for base AtkObject.
278 * @param klass EailGenlistClass instance
281 eail_genlist_class_init(EailGenlistClass *klass)
283 AtkObjectClass *atk_class = ATK_OBJECT_CLASS(klass);
285 atk_class->initialize = eail_genlist_initialize;
286 atk_class->get_n_children = eail_genlist_get_n_children;
287 atk_class->ref_child = eail_genlist_ref_child;
288 atk_class->ref_state_set = eail_genlist_ref_state_set;
292 * Implementation of the *EailItemParent* interface
296 * @brief Gets the name of EailItem
298 * Implementation of EailItemParent->get_name callback.
300 * @param parent EailItemParent instance
301 * @param item EailItem instance
303 * @returns character string representing the accessible name of
307 eail_genlist_get_item_name(EailItemParent *parent,
310 Evas_Object *widget = eail_widget_get_widget(EAIL_WIDGET(parent));
311 Elm_Object_Item *it = eail_item_get_item(item);
313 if (!widget || !it) return NULL;
315 return elm_object_item_part_text_get(it, EAIL_GENLIST_TEXT);
319 * @brief Gets index of element in parent object
321 * Implementation of EailItemParent->get_item_index_in_parent.
323 * @param parent EailItemParent instance
324 * @param item EailItem instance
326 * @returns integer representing the index of the accessible in its parent
329 eail_genlist_get_item_index_in_parent(EailItemParent *parent,
332 Evas_Object *widget = eail_widget_get_widget(EAIL_WIDGET(parent));
333 Elm_Object_Item *it = eail_item_get_item(item);
335 if (!widget || !it) {
339 return elm_genlist_item_index_get(it)-1;
343 * @brief Gets a reference to the state set of the accessible
345 * The caller must unreference it when it is no longer needed.
347 * Implementation EailItemParent->ref_state_set callback.
349 * @param parent object that holds EailItem in its content
350 * @param item EailItem object
351 * @param state_set current state set
353 * @returns AtkStateSet representing the state set of the accessible
356 eail_genlist_ref_item_state_set(EailItemParent *parent,
358 AtkStateSet *state_set)
360 Evas_Object *widget = eail_widget_get_widget(EAIL_WIDGET(parent));
361 Elm_Object_Item *it = eail_item_get_item(item);
364 if (!widget || !it) {
368 if (elm_genlist_select_mode_get(widget) != ELM_OBJECT_SELECT_MODE_NONE &&
369 elm_genlist_item_select_mode_get(it) != ELM_OBJECT_SELECT_MODE_NONE) {
370 atk_state_set_add_state(state_set, ATK_STATE_SELECTABLE);
372 if (elm_genlist_item_selected_get(it)) {
373 atk_state_set_add_state(state_set, ATK_STATE_SELECTED);
377 if (elm_genlist_item_type_get(it) == ELM_GENLIST_ITEM_TREE) {
378 atk_state_set_add_state(state_set, ATK_STATE_EXPANDABLE);
380 if (elm_genlist_item_expanded_get(it)) {
381 atk_state_set_add_state(state_set, ATK_STATE_EXPANDED);
385 atk_state_set_add_state(state_set, ATK_STATE_VISIBLE);
387 list = elm_genlist_realized_items_get(widget);
388 if (eina_list_data_find(list, it)) {
389 atk_state_set_add_state(state_set, ATK_STATE_SHOWING);
391 eina_list_free(list);
397 * @brief Grabs focus of item
399 * Implementation of EailItemParent->grab_item_focus callback.
401 * @param parent object that holds EailItem in its content
402 * @param item EailItem instance
404 * @returns TRUE if operation was successfull, FALSE otherwise
407 eail_genlist_grab_item_focus(EailItemParent *parent,
410 Evas_Object *widget = eail_widget_get_widget(EAIL_WIDGET(parent));
411 Elm_Object_Item *it = eail_item_get_item(item);
413 if (!widget || !it) {
421 * @brief Gets the rectangle which gives the extent of the component
423 * Implementation of get_extents from AtkComponent.
425 * @param parent object that holds EailItem in its content
426 * @param item EailItem object instance
427 * @param [out] x x coordinate
428 * @param [out] y y coordinate
429 * @param [out] width width of the rectangle
430 * @param [out] height height of the rectangle
431 * @param coord_type specifies whether the coordinates are relative to the
432 * screen or to the components top level window
435 eail_genlist_get_item_extents(EailItemParent *parent,
441 AtkCoordType coord_type)
443 Evas_Object *widget = eail_widget_get_widget(EAIL_WIDGET(parent));
444 Elm_Object_Item *it = eail_item_get_item(item);
446 if (!widget || !it) {
452 * @brief Gets supported actions
454 * Implementation of EailItemParent->get_actions_supported callback.
456 * @param parent EailItemParent instance
457 * @param item EailItem instance
458 * @returns integer representing supported actions
461 eail_genlist_get_actions_supported(EailItemParent *parent,
464 return EAIL_ACTION_SUPPORTED_CLICK | EAIL_ACTION_SUPPORTED_PRESS |
465 EAIL_ACTION_SUPPORTED_RELEASE | EAIL_ACTION_SUPPORTED_EXPAND |
466 EAIL_ACTION_SUPPORTED_SHRINK;
470 * @brief Initialization of EailItemParentIface callbacks
472 * @param iface EailItemParentIface instance
475 eail_item_parent_interface_init(EailItemParentIface *iface)
477 iface->get_item_name = eail_genlist_get_item_name;
478 iface->get_item_index_in_parent = eail_genlist_get_item_index_in_parent;
479 iface->ref_item_state_set = eail_genlist_ref_item_state_set;
480 iface->grab_item_focus = eail_genlist_grab_item_focus;
481 iface->get_item_extents = eail_genlist_get_item_extents;
482 iface->get_actions_supported = eail_genlist_get_actions_supported;
490 * @brief Adds the specified accessible child of the object to the object's selection
492 * Implementation of AtkSelection->add_selection callback.
494 * @param selection AtkSelection instance
495 * @param i selection index
497 * @returns TRUE if operation was successfull, FALSE otherwise
500 eail_genlist_add_selection(AtkSelection *selection,
503 g_return_val_if_fail(EAIL_IS_WIDGET(selection), FALSE);
504 Eina_List *items = eail_genlist_get_items(EAIL_GENLIST(selection));
505 Elm_Object_Item *item = eina_list_nth(items, i);
507 if (!item) return FALSE;
509 elm_genlist_item_selected_set(item, EINA_TRUE);
511 eina_list_free(items);
517 * @brief Gets a reference to the accessible object representing the specified selected
518 * child of the object.
520 * Note: callers should not rely on NULL or on a zero value
521 * for indication of whether AtkSelectionIface is implemented, they should use
522 * type checking/interface checking macros or the atk_get_accessible_value()
523 * convenience method.
525 * Implementation of AtkSelection->ref_selection callback.
527 * @param selection AtkSelection instance
528 * @param i selection index
530 * @returns AtkObject representing the selected accessible or NULL if
531 * selection does not implement this interface
534 eail_genlist_ref_selection(AtkSelection *selection,
537 g_return_val_if_fail(EAIL_IS_WIDGET(selection), NULL);
539 return eail_genlist_ref_child(ATK_OBJECT(selection), i);
543 * @brief Gets the number of accessible children currently selected.
545 * Note: callers should not rely on NULL or on a zero value for indication of whether
546 * AtkSelectionIface is implemented, they should use type checking/interface
547 * checking macros or the atk_get_accessible_value() convenience method.
549 * Implementation of AtkSelection->get_selection_count callback.
551 * @param selection AtkSelection instance
553 * @returns integer representing the number of selected children
556 eail_genlist_get_selection_count(AtkSelection *selection)
558 g_return_val_if_fail(EAIL_IS_WIDGET(selection), FALSE);
559 Evas_Object *object = eail_widget_get_widget(EAIL_WIDGET(selection));
560 const Eina_List *sel_objs = elm_genlist_selected_items_get(object);
562 if (!sel_objs) return 0;
564 return eina_list_count(sel_objs);
568 * @brief Determines if the current child of this object is selected.
570 * Note: callers should not rely on NULL or on a zero value for indication of whether
571 * AtkSelectionIface is implemented, they should use type checking/interface
572 * checking macros or the atk_get_accessible_value() convenience method.
574 * Implementation of AtkSelection->is_child_selected callback.
576 * @param selection AtkSelection instance
577 * @param i index of child
579 * @returns gboolean representing whether the specified child is selected, or 0 if
580 * selection does not implement this interface
583 eail_genlist_is_child_selected(AtkSelection *selection,
586 g_return_val_if_fail(EAIL_IS_WIDGET(selection), FALSE);
587 Evas_Object *object = eail_widget_get_widget(EAIL_WIDGET(selection));
588 Elm_Object_Item *selected_item = elm_genlist_selected_item_get(object);
589 Elm_Object_Item *last_item = elm_genlist_last_item_get(object);
590 Elm_Object_Item *item = elm_genlist_first_item_get(object);
593 /* of course if there is no selected object, that naturally means that none
594 * of children is selected */
595 if (!selected_item) return FALSE;
599 if (selected_item == item) break;
601 item = elm_genlist_item_next_get(item);
603 } while (item != last_item);
609 * @brief Removes the specified child of the object from the object's selection
611 * Implementation of AtkSelection->remove_selection callback.
613 * @param selection AtkSelection instance
614 * @param i index of child
616 * @returns TRUE on success, FALSE otherwise
619 eail_genlist_remove_selection(AtkSelection *selection,
622 Eina_List *items = NULL;
623 Evas_Object *object = NULL;
624 Elm_Object_Item *item = NULL;
626 g_return_val_if_fail(EAIL_IS_WIDGET(selection), FALSE);
627 object = eail_widget_get_widget(EAIL_WIDGET(selection));
628 g_return_val_if_fail(object, FALSE);
630 items = eail_genlist_get_items(EAIL_GENLIST(selection));
631 g_return_val_if_fail((eina_list_count(items) > i), FALSE);
633 item = eina_list_nth(items, i);
634 elm_genlist_item_selected_set(item, EINA_FALSE);
636 eina_list_free(items);
638 /* if change was successful, then selected item now should be different */
639 return (elm_genlist_selected_item_get(object) != item);
643 * @brief Helper function for selecting/unselecting all items in the list depending
644 * on "selected" param value
646 * @param selection AtkSelection instance
647 * @param selected selected state (TRUE means selected)
649 * @returns TRUE on success, FALSE otherwise
652 eail_genlist_mark_all_selected_state(AtkSelection *selection,
655 Eina_List *items = NULL;
658 items = eail_genlist_get_items(EAIL_GENLIST(selection));
659 for (i = 0; i < eina_list_count(items); ++i)
661 Elm_Object_Item *item = eina_list_nth(items, i);
662 if (!item) return FALSE;
664 elm_genlist_item_selected_set(item, selected);
667 eina_list_free(items);
673 * @brief Causes every child of the object to be selected if the object supports
674 * multiple selections
676 * Implementation of AtkSelection->select_all_selection callback.
678 * @param selection AtkSelection instance
680 * @returns TRUE on success, FALSE otherwise
683 eail_genlist_select_all_selection(AtkSelection *selection)
685 g_return_val_if_fail(EAIL_IS_WIDGET(selection), FALSE);
686 Evas_Object *object = eail_widget_get_widget(EAIL_WIDGET(selection));
688 /* can select all only when multiselect is enabled */
689 if (!elm_genlist_multi_select_get(object)) return FALSE;
691 return eail_genlist_mark_all_selected_state(selection, EINA_TRUE);
695 * @brief Clears the selection in the object so that no children in the object are
698 * Implementation of AtkSelection->clear_selection callback.
700 * @param selection AtkSelection instance
702 * @returns TRUE on success, FALSE otherwise
705 eail_genlist_clear_selection(AtkSelection *selection)
707 g_return_val_if_fail(EAIL_IS_WIDGET(selection), FALSE);
709 return eail_genlist_mark_all_selected_state(selection, EINA_FALSE);
713 * @brief Initializer of AtkSelectionIface interface
715 * @param iface AtkSelectionIface instance
717 static void atk_selection_interface_init(AtkSelectionIface *iface)
719 iface->add_selection = eail_genlist_add_selection;
720 iface->clear_selection = eail_genlist_clear_selection;
721 iface->ref_selection = eail_genlist_ref_selection;
722 iface->get_selection_count = eail_genlist_get_selection_count;
723 iface->is_child_selected = eail_genlist_is_child_selected;
724 iface->remove_selection = eail_genlist_remove_selection;
725 iface->select_all_selection = eail_genlist_select_all_selection;