Merge "custom eail widget implementation" into tizen
[platform/core/uifw/eail.git] / eail / eail_index.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_index.c
22  * @brief EailIndex implementation
23  */
24
25 /* enabling beta API support for Eo parts*/
26 #define EFL_BETA_API_SUPPORT
27
28 #include <Elementary.h>
29
30 #include "eail_index.h"
31 #include "eail_factory.h"
32 #include "eail_item_parent.h"
33 #include "eail_utils.h"
34 /* internal elm_widget api for listening internal index parts */
35 #define ELM_INTERNAL_API_ARGESFSDFEFC
36 #include <elm_widget.h>
37 #include <elm_widget_index.h>
38
39 #ifndef ELM_OBJ_INDEX_CLASS
40 #ifndef ELM_INDEX_CLASS
41 #include <elm_index_eo.h>
42 #endif
43 #endif
44
45 #include "eail_priv.h"
46
47 static void eail_item_parent_interface_init(EailItemParentIface *iface);
48 static void atk_selection_interface_init(AtkSelectionIface *iface);
49
50 /**
51  * @brief EailIndex GObject definition
52  *
53  * It extends EAIL_TYPE_WIDGET class and implements EAIL_TYPE_ITEM_PARENT and
54  * ATK_TYPE_SELECTION interfaces
55  */
56 G_DEFINE_TYPE_WITH_CODE(EailIndex,
57                         eail_index,
58                         EAIL_TYPE_WIDGET,
59                         G_IMPLEMENT_INTERFACE(EAIL_TYPE_ITEM_PARENT,
60                                               eail_item_parent_interface_init)
61                         G_IMPLEMENT_INTERFACE(ATK_TYPE_SELECTION,
62                                               atk_selection_interface_init));
63
64 /*
65  * Implementation of the *AtkObject* interface
66  */
67
68 /**
69  * @brief Initializer for AtkObject
70  *
71  * @param obj AtkObject instance
72  * @param data initialization data
73  */
74 static void
75 eail_index_initialize(AtkObject *obj, gpointer data)
76 {
77    ATK_OBJECT_CLASS(eail_index_parent_class) ->initialize(obj, data);
78    obj->role = ATK_ROLE_LIST;
79 }
80
81 /**
82  * @brief EailIndex GObject instance initializer
83  *
84  * @param button EailIndex instance
85  */
86 static void
87 eail_index_init(EailIndex *button)
88 {
89 }
90
91 /**
92  * @brief Gets the list of Elm_Object_Item* that are contained in an index widget
93  *
94  * @param obj AtkObject instance
95  *
96  * @returns const Eina_List with Elm_Object_Item* for every index
97  */
98 static const Eina_List *
99 eail_index_get_index_items(AtkObject *obj) {
100    Evas_Object *index_widget = NULL;
101
102    index_widget = eail_widget_get_widget(EAIL_WIDGET(obj));
103    g_return_val_if_fail(index_widget, NULL);
104
105    ELM_INDEX_DATA_GET(index_widget, index_sd);
106    g_return_val_if_fail(index_sd, NULL);
107
108    return index_sd->items;
109 }
110 /**
111  * @brief Gets the number of accessible children of the accessible.
112  *
113  * Implementation of AtkObject->get_n_children callback.
114  *
115  * @param obj AtkObject instance
116  *
117  * @returns integer representing the number of accessible children of
118  * the accessible
119  */
120 static gint
121 eail_index_get_n_children(AtkObject *obj)
122 {
123    return eina_list_count(eail_index_get_index_items(obj));
124 }
125
126 /**
127  * @brief Gets a reference to the specified accessible child of the object.
128  *
129  * The accessible children are 0-based so the first accessible child is at index 0,
130  * the second at index 1 and so on.
131  *
132  * Implementation of AtkObject->ref_child callback.
133  *
134  * @param obj AtkObject instance
135  * @param i index of a child
136  *
137  * @returns AtkObject representing the specified accessible child of the
138  * accessible
139  */
140 static AtkObject *
141 eail_index_ref_child(AtkObject *obj, gint i)
142 {
143    const Eina_List *items;
144    AtkObject *child = NULL;
145
146    items = eail_index_get_index_items(obj);
147    if (eina_list_count(items) > i)
148      {
149         child = eail_factory_get_item_atk_obj
150                           (eina_list_nth(items, i), ATK_ROLE_LIST_ITEM, obj);
151
152         g_object_ref(child);
153      }
154
155    return child;
156 }
157
158 /**
159  * @brief Gets the accessible name of the accessible.
160  *
161  * Implementation of AtkObject->get_name callback.
162  *
163  * @param obj AtkObject instance
164  *
165  * @returns string containing the accessible description of
166  * the accessible
167  */
168 static const gchar *
169 eail_index_get_name(AtkObject *obj)
170 {
171    Evas_Object *widget;
172    const char *atk_name;
173
174    g_return_val_if_fail(EAIL_IS_INDEX(obj), NULL);
175
176    atk_name = ATK_OBJECT_CLASS(eail_index_parent_class)->get_name(obj);
177    if (atk_name)
178      return atk_name;
179
180    widget = eail_widget_get_widget(EAIL_WIDGET(obj));
181    if (!widget) return NULL;
182
183    return elm_object_text_get(widget);
184 }
185
186 /**
187  * @brief Destructor of EailIndex object
188  * @param object GObject object to be finalized
189  */
190 static void
191 eail_index_finalize(GObject *object)
192 {
193    G_OBJECT_CLASS(eail_index_parent_class)->finalize(object);
194 }
195
196 /**
197  * @brief Initializer for EailIndex GObject class
198  *
199  * Defines callbacks for base AtkObject.
200  *
201  * @param klass EailIndex instance
202  */
203 static void
204 eail_index_class_init(EailIndexClass *klass)
205 {
206    AtkObjectClass *atk_class = ATK_OBJECT_CLASS(klass);
207    GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
208    atk_class->initialize = eail_index_initialize;
209    atk_class->get_n_children = eail_index_get_n_children;
210    atk_class->ref_child = eail_index_ref_child;
211    atk_class->get_name = eail_index_get_name;
212    gobject_class->finalize = eail_index_finalize;
213 }
214
215 /**
216  * @brief Checks if content get is supported
217  *
218  * Implementation of EailItemParent->is_content_get_supported callback.
219  *
220  * @param parent EailItemParent instance
221  * @param item EailItem instance
222  * @returns always FALSE
223  */
224 gboolean
225 eail_index_content_get_support(EailItemParent   *parent,
226                                EailItem         *item)
227 {
228    return FALSE;
229 }
230
231 /**
232  * @brief Gets item's name
233  *
234  * @param parent EailItemParent instance
235  * @param item EailItem instance
236  * @return string containing item's name
237  */
238 const gchar *
239 eail_index_get_item_name(EailItemParent   *parent,
240                          EailItem         *item)
241 {
242    Elm_Object_Item *it = eail_item_get_item(item);
243
244    return elm_index_item_letter_get(it);
245 }
246
247 /**
248  * @brief Gets index in parent
249  *
250  * @param parent EailItemParent instance
251  * @param item EailItem child instance
252  *
253  * @returns int representing the index in parent
254  */
255 static gint
256 eail_index_get_item_index_in_parent(EailItemParent *parent, EailItem *item)
257 {
258    Elm_Object_Item *it = eail_item_get_item(item);
259    const Eina_List *items;
260    int i = 0;
261
262    if (!it) return -1;
263
264    items = eail_index_get_index_items(ATK_OBJECT(parent));
265    for (i=0; i<eina_list_count(items); ++i)
266    {
267       if (eina_list_nth(items, i) == it)
268       {
269          return i;
270       }
271    }
272
273    return -1;
274 }
275
276 /**
277  * @brief Initialization of EailItemParentIface callbacks
278  *
279  * @param iface EailItemParentIface instance
280  */
281 static void
282 eail_item_parent_interface_init(EailItemParentIface *iface)
283 {
284    iface->get_item_name = eail_index_get_item_name;
285    iface->is_content_get_supported = eail_index_content_get_support;
286    iface->get_item_index_in_parent = eail_index_get_item_index_in_parent;
287 }
288
289 /**
290  * @brief Adds the specified accessible child of the object to the object's selection.
291  *
292  * Implementation of AtkSelection->add_selection callback.
293  *
294  * @param selection AtkSelection instance
295  * @param i index of object
296  *
297  * @returns TRUE if operation was successful, FALSE otherwise
298  */
299 static gboolean
300 eail_index_add_selection(AtkSelection *selection,
301                          gint i)
302 {
303    const Eina_List *items = eail_index_get_index_items(ATK_OBJECT(selection));
304    if (!items) return FALSE;
305    Elm_Object_Item *item = eina_list_nth(items, i);
306
307    if (!item) return FALSE;
308
309    elm_index_item_selected_set(item, EINA_TRUE);
310    return TRUE;
311 }
312
313 /**
314  * @brief Gets a reference to the accessible object representing the specified selected
315  * child of the object.
316  *
317  * Note: callers should not rely on NULL or on a zero value
318  * for indication of whether AtkSelectionIface is implemented, they should use
319  * type checking/interface checking macros or the atk_get_accessible_value()
320  * convenience method.
321  *
322  * Implementation of AtkSelection->ref_selection callback.
323  *
324  * @param selection AtkSelection instance
325  * @param i index of object
326  *
327  * @returns AtkObject representing the selected accessible or NULL if
328  * selection does not implement this interface
329  */
330 static AtkObject *
331 eail_index_ref_selection(AtkSelection *selection,
332                          gint i)
333 {
334    g_return_val_if_fail(EAIL_IS_WIDGET(selection), NULL);
335
336    return eail_index_ref_child(ATK_OBJECT(selection), i);
337 }
338
339 /**
340  * @brief Clears the selection in the object so that no children in the object are
341  * selected.
342  *
343  * Implementation of AtkSelection->clear_selection callback.
344  *
345  * @param selection aAtkSelection instance
346  *
347  * @returns TRUE if success, FALSE otherwise.
348  */
349 static gboolean
350 eail_index_clear_selection(AtkSelection *selection)
351 {
352    g_return_val_if_fail(EAIL_IS_WIDGET(selection), FALSE);
353    Evas_Object *object = eail_widget_get_widget(EAIL_WIDGET(selection));
354    g_return_val_if_fail(object, FALSE);
355
356    Elm_Object_Item *selected_item = elm_index_selected_item_get(object, 0);
357
358    /* no selected item found so selection is already clear, doing nothing and
359     * returning TRUE to mark success*/
360    if (!selected_item) return TRUE;
361
362    elm_index_item_selected_set(selected_item, EINA_FALSE);
363
364    return TRUE;
365 }
366
367 /**
368  * @brief Gets the number of accessible children currently selected.
369  *
370  * Note: callers should not rely on NULL or on a zero value for indication of whether
371  * AtkSelectionIface is implemented, they should use type checking/interface
372  * checking macros or the atk_get_accessible_value() convenience method.
373  *
374  * Implementation of AtkSelection->get_selection_count callback.
375  *
376  * @param selection AtkSelection instance
377  *
378  * @returns integer representing the number of selected elements
379  */
380 static gint
381 eail_index_get_selection_count(AtkSelection *selection)
382 {
383    g_return_val_if_fail(EAIL_IS_WIDGET(selection), FALSE);
384    Evas_Object *object = eail_widget_get_widget(EAIL_WIDGET(selection));
385
386    if (elm_index_selected_item_get(object, 0))
387      return 1;
388    else
389      return 0;
390 }
391
392 /**
393  * @brief Determines if the current child of this object is selected.
394  *
395  * Note: callers should not rely on NULL or on a zero value for indication of whether
396  * AtkSelectionIface is implemented, they should use type checking/interface
397  * checking macros or the atk_get_accessible_value() convenience method.
398  *
399  * Implementation of AtkSelection->is_child_selected callback.
400  *
401  * @param selection AtkSelection instance
402  * @param i index of object
403  *
404  * @returns TRUE if the specified child is selected or
405  * FALSE if selection does not implement this interface
406  */
407 static gboolean
408 eail_index_is_child_selected(AtkSelection *selection,
409                              gint i)
410 {
411    g_return_val_if_fail(EAIL_IS_WIDGET(selection), FALSE);
412    Evas_Object *object = eail_widget_get_widget(EAIL_WIDGET(selection));
413    Elm_Object_Item *selected_item = elm_index_selected_item_get(object, 0);
414    const Eina_List *items = eail_index_get_index_items(ATK_OBJECT(selection));
415    Elm_Object_Item *item_witn_n_index = NULL;
416
417    /* if no item is selected, then we are sure that none of the child is
418     * selected*/
419    if (!selected_item) return FALSE;
420
421    /* no items on list so no child is selected*/
422    if (!items) return FALSE;
423
424    item_witn_n_index =  eina_list_nth(items, i);
425
426    if (item_witn_n_index == selected_item)
427      return TRUE;
428    else
429      return FALSE;
430 }
431
432 /**
433  * @brief Initializer of AtkSelectionIface interface
434  *
435  * @param iface AtkSelectionIface
436  */
437 static void atk_selection_interface_init(AtkSelectionIface *iface)
438 {
439    iface->add_selection        = eail_index_add_selection;
440    iface->clear_selection      = eail_index_clear_selection;
441    iface->ref_selection        = eail_index_ref_selection;
442    iface->get_selection_count  = eail_index_get_selection_count;
443    iface->is_child_selected    = eail_index_is_child_selected;
444 }