Issues deteced by Static Code Analysis fixed
[platform/core/uifw/eail.git] / eail / eail / eail_gengrid.c
1 /*
2  * Copyright (c) 2013 Samsung Electronics Co., Ltd.
3  *
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.
8  *
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.
13  *
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.
18  */
19
20 /**
21  * @file eail_gengrid.c
22  * @brief EailGengrid implementation
23  */
24
25 #include <Elementary.h>
26
27 #include "eail_gengrid.h"
28 #include "eail_item_parent.h"
29 #include "eail_factory.h"
30 #include "eail_utils.h"
31 #include "eail_priv.h"
32
33 static void eail_item_parent_interface_init(EailItemParentIface *iface);
34 static void atk_table_interface_init(AtkTableIface *iface);
35 static void atk_selection_interface_init(AtkSelectionIface *iface);
36
37 /** @brief GObject definition for EailGengrid implementation*/
38 G_DEFINE_TYPE_WITH_CODE(EailGengrid,
39                         eail_gengrid,
40                         EAIL_TYPE_WIDGET,
41                         G_IMPLEMENT_INTERFACE(EAIL_TYPE_ITEM_PARENT,
42                                               eail_item_parent_interface_init)
43                         G_IMPLEMENT_INTERFACE(ATK_TYPE_TABLE,
44                                               atk_table_interface_init)
45                         G_IMPLEMENT_INTERFACE(ATK_TYPE_SELECTION,
46                                               atk_selection_interface_init));
47
48 /*
49  * Implementation of the *AtkObject* interface
50  */
51
52 /**
53  * @brief Handler for realized event, used to notify about gengrid content
54  * changes
55  *
56  * @param data passed to callback
57  * @param obj object that raised event
58  * @param event_info additional event info (item is passed here)
59  */
60 void
61 eail_gengrid_item_handle_realized_event(void *data,
62                                         Evas_Object *obj,
63                                         void *event_info)
64 {
65    Elm_Object_Item *item = (Elm_Object_Item *) event_info;
66    AtkObject *atk_item = NULL, *atk_parent = NULL;
67
68    atk_parent = ATK_OBJECT(data);
69    if (!atk_parent) return;
70
71    atk_item = eail_factory_get_item_atk_obj
72                                          (item, ATK_ROLE_LIST_ITEM, atk_parent);
73
74    if (!atk_item) return;
75
76    eail_emit_children_changed_obj(TRUE, atk_parent, atk_item);
77 }
78
79 /**
80  * @brief Handler for unrealized event, used to notify about gengrid content
81  * changes
82  *
83  * @param data passed to callback
84  * @param obj object that raised event
85  * @param event_info additional event info (item is passed here)
86  */
87 void
88 eail_gengrid_item_handle_unrealized_event(void *data,
89                                           Evas_Object *obj,
90                                           void *event_info)
91 {
92    Elm_Object_Item *item = (Elm_Object_Item *) event_info;
93    AtkObject *atk_item = NULL, *atk_parent = NULL;
94
95    atk_parent = ATK_OBJECT(data);
96    if (!atk_parent) return;
97
98    atk_item = eail_factory_get_item_atk_obj
99                                          (item, ATK_ROLE_LIST_ITEM, atk_parent);
100
101    if (!atk_item) return;
102
103    eail_emit_children_changed_obj(FALSE, atk_parent, atk_item);
104    atk_object_notify_state_change(atk_item, ATK_STATE_DEFUNCT, TRUE);
105
106    DBG("Unregistering item from cache...");
107    eail_factory_unregister_item_from_cache(item);
108 }
109
110 /**
111  * @brief Initializes EailGengrid object
112  *
113  * @param obj EailGengrid instance
114  * @param data user data passed for initialization
115  */
116 static void
117 eail_gengrid_initialize(AtkObject *obj, gpointer data)
118 {
119    Evas_Object *nested_widget = NULL;
120    ATK_OBJECT_CLASS(eail_gengrid_parent_class)->initialize(obj, data);
121    obj->role = ATK_ROLE_TABLE;
122
123    nested_widget = eail_widget_get_widget(EAIL_WIDGET(obj));
124    if (!nested_widget)
125      {
126         ERR("No evas object inside EailWidget was found");
127         return;
128      }
129
130    evas_object_smart_callback_add(nested_widget, "selected",
131                                 eail_list_item_handle_selected_event, obj);
132    evas_object_smart_callback_add(nested_widget, "unselected",
133                                 eail_list_item_handle_unselected_event, obj);
134    evas_object_smart_callback_add(nested_widget, "realized",
135                                 eail_gengrid_item_handle_realized_event, obj);
136    evas_object_smart_callback_add(nested_widget, "unrealized",
137                                 eail_gengrid_item_handle_unrealized_event, obj);
138 }
139
140 /**
141  * @brief Gets the list of created widgets
142  *
143  * @param gengrid EailGengrid instance
144  *
145  * @returns Eina_List representing the list of widgets elm_gengrid holds
146  */
147 static Eina_List *
148 eail_gengrid_items_get(EailGengrid *gengrid)
149 {
150    g_return_val_if_fail(EAIL_IS_WIDGET(gengrid), NULL);
151
152    Evas_Object *widget = eail_widget_get_widget(EAIL_WIDGET(gengrid));
153
154    return elm_gengrid_realized_items_get(widget);
155 }
156
157 /**
158  * @brief Gets the number of created widgets
159  *
160  * @param obj AtkObject instance
161  *
162  * @returns integer representing the number of created widgets
163  */
164 static gint
165 eail_gengrid_n_items_get(AtkObject *obj)
166 {
167    gint n_items;
168    Eina_List *items = eail_gengrid_items_get(EAIL_GENGRID(obj));
169    n_items  = eina_list_count(items);
170    eina_list_free(items);
171
172    return n_items;
173 }
174
175 /**
176  * @brief Gets the reference to the specified elm_gengrid's child
177  *
178  * @param obj AtkObject instance
179  * @param i child index
180  *
181  * @returns AtkObject representing the elm_gengrid's child
182  */
183 static AtkObject *
184 eail_gengrid_ref_child(AtkObject *obj, gint i)
185 {
186    g_return_val_if_fail(EAIL_IS_GENGRID(obj), NULL);
187
188    AtkObject *child = NULL;
189
190    Eina_List *list = eail_gengrid_items_get(EAIL_GENGRID(obj));
191    if (eina_list_count(list) > i)
192      {
193         child = eail_factory_get_item_atk_obj
194                              (eina_list_nth(list, i), ATK_ROLE_LIST_ITEM, obj);
195
196         g_object_ref(child);
197      }
198
199    return child;
200 }
201
202 /**
203  * @brief Gets a reference to the state set of the accessible
204  *
205  * The caller must unreference it when it is no longer needed.
206  *
207  * Implementation of ref_state_set from AtkObject.
208  *
209  * @param obj AtkObject instance
210  *
211  * @returns AtkStateSet representing the state set of the accessible
212  */
213 static AtkStateSet *
214 eail_gengrid_ref_state_set(AtkObject *obj)
215 {
216    Evas_Object *widget = eail_widget_get_widget(EAIL_WIDGET(obj));
217    AtkStateSet *state_set =
218       ATK_OBJECT_CLASS(eail_gengrid_parent_class)->ref_state_set(obj);
219
220    if (!widget) return state_set;
221
222    if (elm_gengrid_multi_select_get(widget))
223      atk_state_set_add_state(state_set, ATK_STATE_MULTISELECTABLE);
224
225    return state_set;
226 }
227
228 /**
229  * @brief Initializes EailGengrid object
230  *
231  * @param gengrid EailGengrid instance
232  */
233 static void
234 eail_gengrid_init(EailGengrid *gengrid)
235 {
236 }
237
238 /**
239  * @brief Initializes EailGengrid class
240  *
241  * @param klass EailGengridClass instance
242  */
243 static void
244 eail_gengrid_class_init(EailGengridClass *klass)
245 {
246    AtkObjectClass *atk_class = ATK_OBJECT_CLASS(klass);
247
248    atk_class->initialize = eail_gengrid_initialize;
249    atk_class->get_n_children = eail_gengrid_n_items_get;
250    atk_class->ref_child = eail_gengrid_ref_child;
251    atk_class->ref_state_set = eail_gengrid_ref_state_set;
252 }
253
254 /**
255  * @brief Gets the name of elm_gengrid child
256  *
257  * @param parent EailItemParent instance
258  * @param item EailItem child instance
259  *
260  * @returns string representing the item's name
261  */
262 static const gchar *
263 eail_gengrid_item_name_get(EailItemParent *parent, EailItem *item)
264 {
265    Elm_Object_Item *it = eail_item_get_item(item);
266    /*that will work only for default theme*/
267    if (!it) return NULL;
268
269    return elm_object_item_part_text_get(it, "elm.text");
270 }
271
272 /**
273  * @brief Gets the item's index in parent object
274  *
275  * @param parent EailItemParent instance
276  * @param item EailItem child instance
277  *
278  * @returns integer representing the child's index in parent
279  */
280 static int
281 eail_gengrid_item_index_in_parent_get(EailItemParent *parent, EailItem *item)
282 {
283    Elm_Object_Item *it = eail_item_get_item(item);
284
285    if (!it) return -1;
286
287    return elm_gengrid_item_index_get(it);
288 }
289
290 /**
291  * @brief Gets the state set of EailGengrid item
292  *
293  * @param parent EailItemParent instance
294  * @param item EailItem child instance
295  * @param state_set AtkStateSet to fill
296  *
297  * @returns AtkStateSet representing the state set of the child
298  */
299 static AtkStateSet *
300 eail_gengrid_ref_item_state_set(EailItemParent *parent,
301                                 EailItem *item,
302                                 AtkStateSet *state_set)
303 {
304    Evas_Object *widget = eail_widget_get_widget(EAIL_WIDGET(parent));
305    Elm_Object_Item *it = eail_item_get_item(item);
306
307    if (!widget || !it) return state_set;
308
309    Evas_Object *cell = elm_object_item_widget_get(it);
310
311    if ((elm_gengrid_select_mode_get(widget) != ELM_OBJECT_SELECT_MODE_NONE) &&
312        (elm_gengrid_item_select_mode_get(it) != ELM_OBJECT_SELECT_MODE_NONE))
313      {
314         atk_state_set_add_state(state_set, ATK_STATE_SELECTABLE);
315         if (elm_gengrid_selected_item_get(cell))
316           atk_state_set_add_state(state_set, ATK_STATE_SELECTED);
317      }
318
319    if (evas_object_visible_get(cell))
320      atk_state_set_add_state(state_set, ATK_STATE_VISIBLE);
321
322    atk_state_set_add_state(state_set, ATK_STATE_SHOWING);
323
324    return state_set;
325 }
326
327 /**
328  * @brief Grabs focus of EailGengrid item
329  *
330  * @param parent EailGengrid instance
331  * @param item EailGengrid child instance
332  *
333  * @returns TRUE on success, FALSE otherwise
334  */
335 static gboolean
336 eail_gengrid_grab_item_focus(EailItemParent *parent,
337                              EailItem *item)
338 {
339    Elm_Object_Item *it = eail_item_get_item(item);
340    if (!it) return FALSE;
341
342    Evas_Object *obj = elm_object_item_widget_get(it);
343    if (!elm_object_focus_allow_get(obj)) return FALSE;
344
345    elm_object_focus_set(obj, EINA_TRUE);
346
347    return TRUE;
348 }
349
350 /**
351  * @brief Gets the rectangle which gives the extent of the component
352  *
353  * Implementation of get_extents from AtkComponent for EailGengrid child.
354  *
355  * @param parent EailGengrid instance
356  * @param item EailGengrid child instance
357  * @param [out] x x coordinate
358  * @param [out] y coordinate
359  * @param [out] width width of the rectangle
360  * @param [out] height height of the rectangle
361  * @param coord_type specifies whether the coordinates are relative to the screen or to the components top level window
362  */
363 static void
364 eail_gengrid_item_extents_get(EailItemParent *parent,
365                               EailItem *item,
366                               gint *x,
367                               gint *y,
368                               gint *width,
369                               gint *height,
370                               AtkCoordType coord_type)
371 {
372    Evas_Object *widget = eail_widget_get_widget(EAIL_WIDGET(parent));
373    Elm_Object_Item *it = eail_item_get_item(item);
374
375    if ((!widget) || (!it)) return;
376
377    Evas_Object *it_widget = elm_object_item_widget_get(it);
378    evas_object_geometry_get(it_widget, x, y, width, height);
379
380    if (coord_type == ATK_XY_SCREEN) {
381         int ee_x, ee_y;
382         Ecore_Evas *ee =
383            ecore_evas_ecore_evas_get(evas_object_evas_get(it_widget));
384
385         ecore_evas_geometry_get(ee, &ee_x, &ee_y, NULL, NULL);
386         *x += ee_x;
387         *y += ee_y;
388    }
389 }
390
391 /**
392  * @brief Gets supported actions
393  *
394  * Implementation of EailItemParent->get_actions_supported callback.
395  *
396  * @param parent EailItemParent instance
397  * @param item EailItem instance
398  * @returns implementation representing supported actions
399  */
400 static gint
401 eail_gengrid_get_actions_supported(EailItemParent   *parent,
402                                    EailItem         *item)
403 {
404    return EAIL_ACTION_SUPPORTED_CLICK | EAIL_ACTION_SUPPORTED_PRESS |
405             EAIL_ACTION_SUPPORTED_RELEASE;
406 }
407
408 /**
409  * @brief EailItemParent interface initialization
410  *
411  * @param iface EailItemParentIface instance
412  */
413 static void
414 eail_item_parent_interface_init(EailItemParentIface *iface)
415 {
416    if (!iface) return;
417
418    iface->get_item_name            = eail_gengrid_item_name_get;
419    iface->get_item_index_in_parent = eail_gengrid_item_index_in_parent_get;
420    iface->ref_item_state_set       = eail_gengrid_ref_item_state_set;
421    iface->grab_item_focus          = eail_gengrid_grab_item_focus;
422    iface->get_item_extents         = eail_gengrid_item_extents_get;
423    iface->get_actions_supported    = eail_gengrid_get_actions_supported;
424 }
425
426 /**
427  * @brief Helper function for getting rows and columns count
428  *
429  * @param object elm_gengrid instance
430  * @param [out] rows rows count
431  * @param [out] columns columns count
432  */
433 static void
434 _get_n_rows_columns(const Evas_Object *object,
435                     int *rows, int *columns)
436 {
437    Elm_Object_Item *it;
438    Eina_List *l, *list = elm_gengrid_realized_items_get(object);
439    int row, column;
440
441    if (list == NULL)
442      {
443         *rows = 0;
444         *columns = 0;
445         return;
446      }
447
448    row = column = 0;
449    EINA_LIST_FOREACH(list, l, it)
450      {
451         unsigned int item_row, item_col;
452         elm_gengrid_item_pos_get(it, &item_col, &item_row);
453         if (item_row > row) row++;
454         if (item_col > column) column++;
455      }
456
457    eina_list_free(list);
458    *rows = row + 1;
459    *columns = column + 1;
460 }
461
462
463 /**
464  * @brief Gets the number of rows in the table
465  *
466  * Implementation of get_n_rows from AtkTable.
467  *
468  * @param table AtkTable instance
469  *
470  * @returns integer representing the number of rows
471  */
472 static gint
473 eail_gengrid_n_rows_get(AtkTable *table)
474 {
475    Evas_Object *widget;
476    int rows, columns;
477
478    g_return_val_if_fail(EAIL_IS_GENGRID(table), -1);
479
480    widget = eail_widget_get_widget(EAIL_WIDGET(table));
481    if (!widget) return -1;
482
483    _get_n_rows_columns(widget, &rows, &columns);
484    return rows;
485 }
486
487 /**
488  * @brief Gets the number of columns in the table
489  *
490  * Implementation of get_n_columns from AtkTable.
491  *
492  * @param table AtkTable instance
493  *
494  * @returns integer representing the number of columns
495  */
496 static gint
497 eail_gengrid_n_columns_get(AtkTable *table)
498 {
499    Evas_Object *widget;
500    int rows, columns;
501
502    g_return_val_if_fail(EAIL_IS_GENGRID(table), -1);
503
504    widget = eail_widget_get_widget(EAIL_WIDGET(table));
505
506    _get_n_rows_columns(widget, &rows, &columns);
507
508    return columns;
509 }
510
511 /**
512  * @brief Gets a gint representing the index at the specified row and column
513  *
514  * Implementation of get_index_at from AtkTable.
515  *
516  * @param table AtkTable instance
517  * @param row number of row in table
518  * @param column number of column in table
519  *
520  * @returns integer representing the index of the specified position
521  */
522 static gint
523 eail_gengrid_index_at_get(AtkTable *table, gint row, gint column)
524 {
525    Evas_Object *widget;
526    gint n_rows, n_columns;
527    gint ret_val = -1;
528
529    g_return_val_if_fail(EAIL_IS_GENGRID(table), -1);
530    widget = eail_widget_get_widget(EAIL_WIDGET(table));
531    if (!widget) return -1;
532
533    _get_n_rows_columns(widget, &n_rows, &n_columns);
534
535    if ((row >= n_rows) || (column >= n_columns)) return -1;
536
537    if (elm_gengrid_horizontal_get(widget))
538      ret_val = ((n_columns) * column) + row;
539    else
540      ret_val = ((n_columns) * row) + column;
541
542    /* testing if result is within bounds */
543    if (ret_val >= eail_gengrid_n_items_get(ATK_OBJECT(table)))
544      return -1;
545
546    return ret_val;
547 }
548
549 /**
550  * @brief Get a reference to the table cell at row, column
551  *
552  * Implementation of ref_at from AtkTable.
553  *
554  * @param table AtkTable instance
555  * @param row number of row in table
556  * @param column number of column in table
557  *
558  * @returns AtkObject representing the child object
559  */
560 static AtkObject *
561 eail_gengrid_ref_at(AtkTable *table, gint row, gint column)
562 {
563    gint index;
564
565    g_return_val_if_fail(EAIL_IS_GENGRID(table), NULL);
566
567    index = eail_gengrid_index_at_get(table, row, column);
568    if (index == -1) return NULL;
569
570    return eail_gengrid_ref_child(ATK_OBJECT(table), index);
571 }
572
573 /**
574  * @brief Helper function for getting object's position in table at given index
575  *
576  * @param widget Evas_Object instance
577  * @param [out] row row number
578  * @param [out] column column number
579  * @param index index of child item
580  */
581 static void
582 _get_item_pos(const Evas_Object *widget, gint *row, gint *column, gint index)
583 {
584    Elm_Object_Item *it;
585    Eina_List *list;
586
587    if (!widget)
588      {
589         *row = -1;
590         *column = -1;
591         return;
592      }
593
594    list = elm_gengrid_realized_items_get(widget);
595    it = eina_list_nth(list, index);
596    elm_gengrid_item_pos_get(it, (unsigned int *)column, (unsigned int *)row);
597
598    eina_list_free(list);
599 }
600
601 /**
602  * @brief Gets an integer representing the column at the specified index
603  *
604  * Implementation of get_column_at_index from AtkTable.
605  *
606  * @param table AtkTable instance
607  * @param index child index
608  *
609  * @returns integer representing the column number in table
610  */
611 static gint
612 eail_gengrid_column_at_index_get(AtkTable *table, gint index)
613 {
614    Evas_Object *widget;
615    int row, column;
616
617    g_return_val_if_fail(EAIL_IS_GENGRID(table), -1);
618    if (index >= eail_gengrid_n_items_get(ATK_OBJECT(table)))
619      return -1;
620
621    widget = eail_widget_get_widget(EAIL_WIDGET(table));
622    _get_item_pos(widget, &row, &column, index);
623
624    return column;
625 }
626
627 /**
628  * @brief Gets a gint representing the row at the specified index
629  *
630  * Implementation of get_row_at_index from AtkTable.
631  *
632  * @param table AtkTable instance
633  * @param index child index
634  *
635  * @returns integer representing the row number in table
636  */
637 static gint
638 eail_gengrid_row_at_index_get(AtkTable *table, gint index)
639 {
640    Evas_Object *widget;
641    int row, column;
642
643    g_return_val_if_fail(EAIL_IS_GENGRID(table), -1);
644    if (index >= eail_gengrid_n_items_get(ATK_OBJECT(table)))
645      return -1;
646
647    widget = eail_widget_get_widget(EAIL_WIDGET(table));
648    _get_item_pos(widget, &row, &column, index);
649
650    return row;
651 }
652
653 /**
654  * @brief Gets a boolean value indicating whether the accessible object
655  * at the specified row and column is selected
656  *
657  * Implementation of is_selected from AtkTable.
658  *
659  * @param table AtkTable instance
660  * @param row row's number
661  * @param column column's number
662  *
663  * @returns TRUE if selected, FALSE otherwise
664  */
665 static gboolean
666 eail_gengrid_is_selected(AtkTable *table, gint row, gint column)
667 {
668    Evas_Object *widget;
669    Elm_Object_Item *it;
670    int index;
671    Eina_List *list;
672    gboolean result;
673
674    g_return_val_if_fail(EAIL_IS_GENGRID(table), FALSE);
675    widget = eail_widget_get_widget(EAIL_WIDGET(table));
676    index = eail_gengrid_index_at_get(table, row, column);
677    if (index == -1) return FALSE;
678
679    list = elm_gengrid_realized_items_get(widget);
680    it = eina_list_nth(list, index);
681    result = elm_gengrid_item_selected_get(it);
682
683    eina_list_free(list);
684    return result;
685 }
686
687 /**
688  * @brief Gets a boolean value indicating whether the specified row is selected
689  *
690  * Implementation of is_row_selected from AtkTable interface.
691  *
692  * @param table AtkTable instance
693  * @param row number of row in table
694  *
695  * @returns TRUE if selected, FALSE otherwise
696  */
697 static gboolean
698 eail_gengrid_is_row_selected(AtkTable *table, gint row)
699 {
700    Evas_Object *widget;
701    Eina_List *list;
702    const Eina_List *selected;
703    gboolean result;
704    int list_count, n_rows;
705
706    g_return_val_if_fail(EAIL_IS_GENGRID(table), FALSE);
707    widget = eail_widget_get_widget(EAIL_WIDGET(table));
708    /*it is possible to select row only in multiselct mode*/
709    if (!elm_gengrid_multi_select_get(widget))
710      return FALSE;
711
712    selected = elm_gengrid_selected_items_get(widget);
713    if (!selected) return FALSE;
714
715    n_rows = eail_gengrid_n_rows_get(table);
716    if (row > n_rows) return FALSE;
717
718    list = elm_gengrid_realized_items_get(widget);
719    list_count = eina_list_count(list);
720
721    result = TRUE;
722    for (int i = 0; i < list_count; i++)
723      {
724         Elm_Object_Item *it = eina_list_nth(list, i);
725         unsigned int x, y;
726         elm_gengrid_item_pos_get(it, &x, &y);
727         if((row == x) && (!elm_gengrid_item_selected_get(it)))
728           {
729              /*row is considered selected if all items in row are selected*/
730              result = FALSE;
731              break;
732           }
733      }
734    eina_list_free(list);
735    return result;
736 }
737
738 /**
739  * @brief Gets the selected rows of the table by initializing selected
740  * with the selected row numbers
741  *
742  * This array should be freed by the caller.
743  *
744  * Implementation of get_selected_rows from AtkTable interface.
745  *
746  * @param table AtkTable instance
747  * @param [out] selected selected rows number
748  *
749  * @returns integer representing the selected rows count
750  */
751 static gint
752 eail_gengrid_selected_rows_get(AtkTable *table, gint **selected)
753 {
754    GArray *array;
755    Evas_Object *widget;
756    int n_rows, n_selected;
757
758    g_return_val_if_fail(EAIL_IS_GENGRID(table), 0);
759    widget = eail_widget_get_widget(EAIL_WIDGET(table));
760
761    if (!widget) return 0;
762    if (!elm_gengrid_multi_select_get(widget)) return 0;
763
764    n_rows = eail_gengrid_n_rows_get(table);
765    array = g_array_new(FALSE, FALSE, sizeof(gint));
766    for (int i = 0; i < n_rows; i++)
767      {
768         gboolean success = eail_gengrid_is_row_selected(table, i);
769         if (success) g_array_append_val(array, i);
770      }
771    n_selected = array->len;
772    *selected = (gint *) g_array_free(array, FALSE);
773    return n_selected;
774 }
775
776 /**
777  * @brief Helper function for setting row selection
778  *
779  * @param table AtkTable instance
780  * @param row row number
781  * @param selection EINA_TRUE for selection, EINA_FALSE for removing selection
782  */
783 static void
784 _set_row_selection(AtkTable *table, int row, Eina_Bool selection)
785 {
786    Evas_Object *widget = eail_widget_get_widget(EAIL_WIDGET(table));
787    Eina_List *list = elm_gengrid_realized_items_get(widget);
788    int list_count = eina_list_count(list);
789
790    for (int i = 0; i < list_count; i++)
791      {
792         unsigned int x, y;
793         Elm_Object_Item *it = eina_list_nth(list, i);
794         elm_gengrid_item_pos_get(it, &x, &y);
795         if (x == row)
796           {
797              elm_gengrid_item_selected_set(it, selection);
798           }
799      }
800
801    eina_list_free(list);
802 }
803
804 /**
805  * @brief Adds the specified row to the selection
806  *
807  * Implementation of add_row_selection from AtkTable.
808  *
809  * @param table AtkTable instance
810  * @param row row number in table
811  *
812  * @returns TRUE on success, FALSE otherwise
813  */
814 static gboolean
815 eail_gengrid_add_row_selection(AtkTable *table, gint row)
816 {
817    Evas_Object *widget;
818    int n_rows;
819
820    g_return_val_if_fail(EAIL_IS_GENGRID(table), FALSE);
821    widget = eail_widget_get_widget(EAIL_WIDGET(table));
822
823    if (!widget) return FALSE;
824    if (!elm_gengrid_multi_select_get(widget)) return FALSE;
825    n_rows = eail_gengrid_n_rows_get(table);
826    if (row > n_rows) return FALSE;
827
828    _set_row_selection(table, row, EINA_TRUE);
829    return TRUE;
830 }
831
832 /**
833  * @brief Removes the specified row from the selection
834  *
835  * Implementation of remove_row_selection from AtkTable interface.
836  *
837  * @param table AtkTable instance
838  * @param row number of row in table
839  *
840  * @returns TRUE on success, FALSE otherwise
841  */
842 static gboolean
843 eail_gengrid_remove_row_selection(AtkTable *table, gint row)
844 {
845    Evas_Object *widget;
846    int n_rows;
847
848    g_return_val_if_fail(EAIL_IS_GENGRID(table), FALSE);
849
850    widget = eail_widget_get_widget(EAIL_WIDGET(table));
851    if (!widget) return FALSE;
852    if (!elm_gengrid_multi_select_get(widget)) return FALSE;
853    n_rows = eail_gengrid_n_rows_get(table);
854    if (row > n_rows) return FALSE;
855
856    _set_row_selection(table, row, EINA_FALSE);
857    return TRUE;
858
859 }
860
861 /**
862  * @brief Gets a boolean value indicating whether the specified column is selected
863  *
864  * Implementation of is_column_selected from AtkTable interface.
865  *
866  * @param table AtkTable implementation
867  * @param column number of column in table
868  *
869  * @returns TRUE on selection, FALSE otherwise
870  */
871 static gboolean
872 eail_gengrid_is_column_selected(AtkTable *table, gint column)
873 {
874    Evas_Object *widget;
875    Eina_List *list;
876    const Eina_List *selected;
877    int n_columns, list_count;
878    gboolean result;
879
880    g_return_val_if_fail(EAIL_IS_GENGRID(table), FALSE);
881    widget = eail_widget_get_widget(EAIL_WIDGET(table));
882    if (!elm_gengrid_multi_select_get(widget)) return FALSE;
883    n_columns = eail_gengrid_n_columns_get(table);
884    if (column > n_columns) return FALSE;
885    selected = elm_gengrid_selected_items_get(widget);
886    if (!selected) return FALSE;
887
888    list = elm_gengrid_realized_items_get(widget);
889    list_count = eina_list_count(list);
890    result = TRUE;
891    for (int i = 0; i < list_count; i++)
892      {
893         Elm_Object_Item *it = eina_list_nth(list, i);
894         unsigned int x, y;
895         elm_gengrid_item_pos_get(it, &x, &y);
896         if ((y == column) && (!elm_gengrid_item_selected_get(it)))
897           {
898              result = FALSE;
899              break;
900           }
901      }
902
903    eina_list_free(list);
904    return result;
905 }
906
907 /**
908  * @brief Helper function for setting column selection in elm_gengrid
909  *
910  * @param table AtkTable instance
911  * @param column number of column in table
912  * @param selection EINA_TRUE for selection, EINA_FALSE otherwise
913  */
914 static void
915 _set_column_selection(AtkTable *table, int column, Eina_Bool selection)
916 {
917    Evas_Object *widget = eail_widget_get_widget(EAIL_WIDGET(table));
918    Eina_List *list = elm_gengrid_realized_items_get(widget);
919    int list_count = eina_list_count(list);
920
921    for (int i = 0; i < list_count; i++)
922      {
923         unsigned int x, y;
924         Elm_Object_Item *it = eina_list_nth(list, i);
925         elm_gengrid_item_pos_get(it, &x, &y);
926         if (y == column)
927           {
928              elm_gengrid_item_selected_set(it, selection);
929           }
930      }
931
932    eina_list_free(list);
933 }
934
935 /**
936  * @brief Adds the specified column to the selection
937  *
938  * Implementation of add_column_selection from AtkTable interface.
939  *
940  * @param table AtkTable instance
941  * @param column number of column in table
942  *
943  * @returns TRUE on success, FALSE otherwise
944  */
945 static gboolean
946 eail_gengrid_add_column_selection(AtkTable *table, gint column)
947 {
948    Evas_Object *widget;
949    int n_columns;
950
951    g_return_val_if_fail(EAIL_IS_GENGRID(table), FALSE);
952    widget = eail_widget_get_widget(EAIL_WIDGET(table));
953    if (!widget) return FALSE;
954    if (!elm_gengrid_multi_select_get(widget)) return FALSE;
955    n_columns = eail_gengrid_n_columns_get(table);
956    if (column > n_columns) return FALSE;
957
958    _set_column_selection(table, column, EINA_TRUE);
959    return TRUE;
960 }
961
962 /**
963  * @brief Removes the specified column from the selection
964  *
965  * Implementation of remove_column_selection from AtkTable.
966  *
967  * @param table AtkTable instance
968  * @param column column number in table
969  *
970  * @returns TRUE on success, FALSE otherwise
971  */
972 static gboolean
973 eail_gengrid_remove_column_selection(AtkTable *table, gint column)
974 {
975    Evas_Object *widget;
976    int n_columns;
977
978    g_return_val_if_fail(EAIL_IS_GENGRID(table), FALSE);
979    widget = eail_widget_get_widget(EAIL_WIDGET(table));
980    if (!widget) return FALSE;
981    if (!elm_gengrid_multi_select_get(widget)) return FALSE;
982    n_columns = eail_gengrid_n_columns_get(table);
983    if (column > n_columns) return FALSE;
984
985    _set_column_selection(table, column, EINA_FALSE);
986    return TRUE;
987
988 }
989
990 /**
991  * @brief AtkTable interface initialization
992  *
993  * @param iface AtkTableIface instance
994  */
995 static void
996 atk_table_interface_init(AtkTableIface *iface)
997 {
998    if (!iface) return;
999
1000    iface->ref_at = eail_gengrid_ref_at;
1001    iface->get_n_rows = eail_gengrid_n_rows_get;
1002    iface->get_n_columns = eail_gengrid_n_columns_get;
1003    iface->get_index_at = eail_gengrid_index_at_get;
1004    iface->get_column_at_index = eail_gengrid_column_at_index_get;
1005    iface->get_row_at_index = eail_gengrid_row_at_index_get;
1006    iface->is_row_selected = eail_gengrid_is_row_selected;
1007    iface->is_selected = eail_gengrid_is_selected;
1008    iface->get_selected_rows = eail_gengrid_selected_rows_get;
1009    iface->add_row_selection = eail_gengrid_add_row_selection;
1010    iface->remove_row_selection = eail_gengrid_remove_row_selection;
1011    iface->is_column_selected = eail_gengrid_is_column_selected;
1012    iface->add_column_selection = eail_gengrid_add_column_selection;
1013    iface->remove_column_selection = eail_gengrid_remove_column_selection;
1014
1015    /*unsupported*/
1016    iface->get_column_extent_at = NULL;
1017    iface->get_row_extent_at = NULL;
1018    iface->get_column_header = NULL;
1019    iface->get_column_description = NULL;
1020 }
1021
1022 /**
1023  * @brief Adds the specified accessible child of the object to the object's selection
1024  *
1025  * Implementation of add_selection from AtkSelection interface.
1026  *
1027  * @param selection AtkSelection instance
1028  * @param i index of child to select
1029  *
1030  * @returns TRUE on success, FALSE otherwise
1031  */
1032 static gboolean
1033 eail_gengrid_selection_add(AtkSelection *selection, gint i)
1034 {
1035    Evas_Object *widget;
1036    Elm_Object_Item *it;
1037    Eina_List *list;
1038    gboolean result;
1039
1040    g_return_val_if_fail(EAIL_IS_GENGRID(selection), FALSE);
1041    widget = eail_widget_get_widget(EAIL_WIDGET(selection));
1042    list = elm_gengrid_realized_items_get(widget);
1043
1044    if (i > eina_list_count(list)) return FALSE;
1045    it = eina_list_nth(list, i);
1046
1047    if (elm_gengrid_item_selected_get(it))
1048      result = FALSE;
1049    else
1050      {
1051         elm_gengrid_item_selected_set(it, EINA_TRUE);
1052         result = TRUE;
1053      }
1054
1055    eina_list_free(list);
1056    return result;
1057 }
1058
1059 /**
1060  * @brief Clears the selection in the object so that no children in the object are selected
1061  *
1062  * Implementation of clear_selection from AtkSelection.
1063  *
1064  * @param selection AtkSelection instance
1065  *
1066  * @returns TRUE on success, FALSE otherwise
1067  */
1068 static gboolean
1069 eail_gengrid_selection_clear(AtkSelection *selection)
1070 {
1071    const Eina_List *l, *list;
1072    Evas_Object *widget;
1073    Elm_Object_Item *it;
1074
1075    g_return_val_if_fail(EAIL_IS_GENGRID(selection), FALSE);
1076    widget = eail_widget_get_widget(EAIL_WIDGET(selection));
1077
1078    if (elm_gengrid_multi_select_get(widget))
1079      {
1080         list = elm_gengrid_selected_items_get(widget);
1081         EINA_LIST_FOREACH(list, l, it)
1082           {
1083              elm_gengrid_item_selected_set(it, EINA_FALSE);
1084           }
1085      }
1086    else
1087      {
1088         it = elm_gengrid_selected_item_get(widget);
1089         elm_gengrid_item_selected_set(it, EINA_FALSE);
1090      }
1091
1092    return TRUE;
1093 }
1094
1095
1096 /**
1097  * @brief Gets a reference to the accessible object representing the specified
1098  * selected child of the object
1099  *
1100  * Note: callers should not rely on NULL
1101  * or on a zero value for indication of whether AtkSelectionIface is
1102  * implemented, they should use type checking/interface checking macros
1103  * or the atk_get_accessible_value() convenience method.
1104  *
1105  * Implementation of ref_selection from AtkSelection interface.
1106  *
1107  * @param selection AtkSelection instance
1108  * @param i index of selected child
1109  *
1110  * @returns AtkObject representing the selected object
1111  */
1112 static AtkObject *
1113 eail_gengrid_selection_ref(AtkSelection *selection, gint i)
1114 {
1115    Evas_Object *widget;
1116    Elm_Object_Item *it;
1117    const Eina_List *list;
1118    Eina_Bool multiselect;
1119    AtkObject *child;
1120
1121    g_return_val_if_fail(EAIL_IS_GENGRID(selection), NULL);
1122    widget = eail_widget_get_widget(EAIL_WIDGET(selection));
1123    multiselect = elm_gengrid_multi_select_get(widget);
1124
1125    if ((!multiselect) && (i != 0)) return FALSE;
1126
1127    if (multiselect)
1128      {
1129         list = elm_gengrid_selected_items_get(widget);
1130         if (i > eina_list_count(list)) return NULL;
1131         it = eina_list_nth(list, i);
1132      }
1133    else
1134      {
1135         it = elm_gengrid_selected_item_get(widget);
1136      }
1137
1138    if (!it) return NULL;
1139
1140    child = eail_factory_get_item_atk_obj
1141                               (it, ATK_ROLE_LIST_ITEM, ATK_OBJECT(selection));
1142
1143    g_object_ref(child);
1144
1145    return child;
1146 }
1147
1148 /**
1149  * @brief Gets the number of accessible children currently selected.
1150  *
1151  * Note: callers should not rely on NULL or on a zero value
1152  * for indication of whether AtkSelectionIface is implemented,
1153  * they should use type checking/interface checking macros or
1154  * the atk_get_accessible_value() convenience method.
1155  *
1156  * Implementation of get_selection_count from AtkSelection interface.
1157  *
1158  * @param selection AtkSelection instance
1159  *
1160  * @returns integer representing the number of selected items
1161  */
1162 static gint
1163 eail_gengrid_selection_count_get(AtkSelection *selection)
1164 {
1165    Evas_Object *widget;
1166    Elm_Object_Item *it;
1167    const Eina_List *list;
1168    int n_selections;
1169
1170    g_return_val_if_fail(EAIL_IS_GENGRID(selection), -1);
1171    widget = eail_widget_get_widget(EAIL_WIDGET(selection));
1172    if (!elm_gengrid_multi_select_get(widget))
1173      {
1174         it = elm_gengrid_selected_item_get(widget);
1175         n_selections = (it ? 1 : 0);
1176      }
1177    else
1178      {
1179         list = elm_gengrid_selected_items_get(widget);
1180         n_selections = eina_list_count(list);
1181      }
1182
1183    return n_selections;
1184 }
1185
1186 /**
1187  * @brief Determines if the current child of this object is selected.
1188  *
1189  * Note: callers should not rely on NULL or on a zero value for
1190  * indication of whether AtkSelectionIface is implemented, they
1191  * should use type checking/interface checking macros or
1192  * the atk_get_accessible_value() convenience method.
1193  *
1194  * Implementation of is_child_selected from AtkSelection interface.
1195  *
1196  * @param selection AtkSelection instance
1197  * @param i index of child
1198  *
1199  * @returns TRUE on selection, FALSE otherwise
1200  */
1201 static gboolean
1202 eail_gengrid_selection_is_child_selected(AtkSelection *selection, int i)
1203 {
1204    Evas_Object *widget;
1205    Elm_Object_Item *it;
1206    Eina_List *list;
1207    gboolean selected;
1208
1209    g_return_val_if_fail(EAIL_IS_GENGRID(selection), FALSE);
1210    widget = eail_widget_get_widget(EAIL_WIDGET(selection));
1211    list = elm_gengrid_realized_items_get(widget);
1212
1213    if (i > eina_list_count(list))
1214      {
1215         eina_list_free(list);
1216         return FALSE;
1217      }
1218
1219    it = eina_list_nth(list, i);
1220    selected = (elm_gengrid_item_selected_get(it) ? TRUE : FALSE);
1221    eina_list_free(list);
1222
1223    return selected;
1224 }
1225
1226 /**
1227  * @brief Removes the specified child of the object from the object's selection
1228  *
1229  * Implementation of remove_selection from AtkSelection.
1230  *
1231  * @param selection AtkSelection instance
1232  * @param i index of selected child
1233  *
1234  * @returns TRUE on success, FALSE otherwise
1235  */
1236 static gboolean
1237 eail_gengrid_selection_remove(AtkSelection *selection, gint i)
1238 {
1239    Evas_Object *widget;
1240    Elm_Object_Item *it;
1241    const Eina_List *list;
1242    Eina_Bool multiselect;
1243
1244    g_return_val_if_fail(EAIL_IS_GENGRID(selection), FALSE);
1245    widget = eail_widget_get_widget(EAIL_WIDGET(selection));
1246    multiselect = elm_gengrid_multi_select_get(widget);
1247    if ((!multiselect) && (i != 0)) return FALSE;
1248
1249    if (!multiselect)
1250      {
1251         it = elm_gengrid_selected_item_get(widget);
1252         elm_gengrid_item_selected_set(it, FALSE);
1253      }
1254    else
1255      {
1256         list = elm_gengrid_selected_items_get(widget);
1257         if (i > eina_list_count(list)) return FALSE;
1258
1259         it = eina_list_nth(list, i);
1260         elm_gengrid_item_selected_set(it, EINA_FALSE);
1261     }
1262
1263    return TRUE;
1264 }
1265
1266 /**
1267  * @brief Causes every child of the object to be selected if the object supports multiple selections
1268  *
1269  * Implementation of select_all from AtkSelection interface.
1270  *
1271  * @param selection AtkSelection instance
1272  *
1273  * @return TRUE on success, FALSE otherwise
1274  */
1275 static gboolean
1276 eail_gengrid_selection_select_all(AtkSelection *selection)
1277 {
1278    Evas_Object *widget;
1279    Elm_Object_Item *it;
1280    Eina_List *l, *list;
1281
1282    g_return_val_if_fail(EAIL_IS_GENGRID(selection), FALSE);
1283    widget = eail_widget_get_widget(EAIL_WIDGET(selection));
1284    if (!elm_gengrid_multi_select_get(widget)) return FALSE;
1285
1286    list = elm_gengrid_realized_items_get(widget);
1287    EINA_LIST_FOREACH(list, l, it)
1288      {
1289         elm_gengrid_item_selected_set(it, EINA_TRUE);
1290      }
1291    return TRUE;
1292 }
1293
1294 /**
1295  * @brief AtkSelection interface initialization
1296  *
1297  * @param iface AtkSelectionIface instance
1298  */
1299 static void
1300 atk_selection_interface_init(AtkSelectionIface *iface)
1301 {
1302    g_return_if_fail(iface != NULL);
1303
1304    iface->add_selection = eail_gengrid_selection_add;
1305    iface->clear_selection = eail_gengrid_selection_clear;
1306    iface->ref_selection = eail_gengrid_selection_ref;
1307    iface->get_selection_count = eail_gengrid_selection_count_get;
1308    iface->is_child_selected = eail_gengrid_selection_is_child_selected;
1309    iface->remove_selection = eail_gengrid_selection_remove;
1310    iface->select_all_selection = eail_gengrid_selection_select_all;
1311 }