Merge "custom eail widget implementation" into tizen
[platform/core/uifw/eail.git] / eail / eail_diskselector.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_diskselector.c
22  * @brief EailDiskselector implementation
23  */
24
25 #include <Elementary.h>
26
27 #include "eail_diskselector.h"
28 #include "eail_factory.h"
29 #include "eail_item_parent.h"
30 #include "eail_utils.h"
31 #include "eail_priv.h"
32
33 #define EAIL_diskselector_ACTION_NEXT "next" /**< @brief 'next' action name*/
34 #define EAIL_diskselector_ACTION_PREV "previous" /**< @brief 'prev' action name*/
35
36 static void atk_selection_interface_init(AtkSelectionIface *iface);
37 static void eail_item_parent_interface_init(EailItemParentIface *iface);
38 static void eail_diskselector_actions_table_init(EailDiskselector *widget);
39 /**
40  * @brief Definition of EailDiskselector as GObject
41  *
42  * EailDiskselector is extended ScrollableWidget with EAIL_TYPE_ITEM_PARENT and
43  * ATK_TYPE_SELECTION implemented
44  */
45 G_DEFINE_TYPE_WITH_CODE(EailDiskselector,
46                         eail_diskselector,
47                         EAIL_TYPE_SCROLLABLE_WIDGET,
48                         G_IMPLEMENT_INTERFACE(ATK_TYPE_SELECTION,
49                                               atk_selection_interface_init)
50                         G_IMPLEMENT_INTERFACE(EAIL_TYPE_ITEM_PARENT,
51                                               eail_item_parent_interface_init));
52
53 /**
54  * @brief Initializer for AtkObjectClass
55  *
56  * @param obj AtkObject instance
57  * @param data initialization data
58  */
59 static void
60 eail_diskselector_initialize(AtkObject *obj, gpointer data)
61 {
62    Evas_Object *nested_widget = NULL;
63    ATK_OBJECT_CLASS(eail_diskselector_parent_class)->initialize(obj, data);
64    obj->role = ATK_ROLE_LIST;
65
66    EailDiskselector *widget = EAIL_DISKSELECTOR(obj);
67    eail_diskselector_actions_table_init(widget);
68
69    nested_widget = eail_widget_get_widget(EAIL_WIDGET(obj));
70    if (!nested_widget)
71      {
72         ERR("No evas object inside EailWidget was found");
73         return;
74      }
75
76    evas_object_smart_callback_add(nested_widget, "selected",
77                                   eail_list_item_handle_selected_event, obj);
78 }
79
80 /**
81  * @brief Initializer for GObject EailList instance
82  *
83  * @param diskselector EailDiskselector instance
84  */
85 static void
86 eail_diskselector_init(EailDiskselector *diskselector)
87 {
88 }
89
90 /**
91  * @brief Gets the number of accessible children of the accessible.
92  *
93  * Implementation of AtkObject->get_n_children callback.
94  *
95  * @param obj AtkObject instance
96  *
97  * @returns integer representing the number of accessible children of
98  * the accessible
99  */
100 static gint
101 eail_diskselector_get_n_children(AtkObject *obj)
102 {
103    gint n_items;
104
105    Evas_Object *widget = eail_widget_get_widget(EAIL_WIDGET(obj));
106    n_items = eina_list_count(elm_diskselector_items_get(widget));
107
108    return n_items;
109 }
110
111 /**
112  * @brief Gets a reference to the specified accessible child of the object.
113  *
114  * The accessible children are 0-based so the first accessible child is at index 0,
115  * the second at index 1 and so on.
116  *
117  * Implementation of AtkObject->ref_child callback.
118  *
119  * @param obj AtkObject instance
120  * @param i child index
121  *
122  * @returns AtkObject representing the specified accessible child of the
123  * accessible
124  */
125 static AtkObject *
126 eail_diskselector_ref_child(AtkObject *obj, gint i)
127 {
128    const Eina_List *items;
129    AtkObject *child = NULL;
130    Evas_Object *widget = NULL;
131
132    widget = eail_widget_get_widget(EAIL_WIDGET(obj));
133    if (!widget) return NULL;
134
135    items = elm_diskselector_items_get(widget);
136
137    if (eina_list_count(items) > i)
138      {
139         child = eail_factory_get_item_atk_obj
140                              (eina_list_nth(items, i), ATK_ROLE_LIST_ITEM, obj);
141
142         g_object_ref(child);
143      }
144
145    return child;
146 }
147
148 /**
149  * @brief Destructor for EailDiskselector class
150  *
151  * @param object GObject object to be finalized
152  */
153 static void
154 eail_diskselector_finalize(GObject *object)
155 {
156    G_OBJECT_CLASS(eail_diskselector_parent_class)->finalize(object);
157 }
158
159 /**
160  * @brief Initializer for GObject EailDiskselectorClass class
161  *
162  * Defines callbacks for base AtkObject.
163  *
164  * @param klass EailDiskselectorClass instance
165  */
166 static void
167 eail_diskselector_class_init(EailDiskselectorClass *klass)
168 {
169    AtkObjectClass *atk_class = ATK_OBJECT_CLASS(klass);
170    GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
171    atk_class->initialize = eail_diskselector_initialize;
172    atk_class->get_n_children = eail_diskselector_get_n_children;
173    atk_class->ref_child = eail_diskselector_ref_child;
174    gobject_class->finalize = eail_diskselector_finalize;
175 }
176
177 /*
178  * Implementation of the *AtkSelection* interface
179  */
180
181 /**
182  * @brief Adds the specified accessible child of the object to the object's selection.
183  *
184  * Implementation of AtkSelection->add_selection callback.
185  *
186  * @param selection AtkSelection instance
187  * @param i selection index
188  *
189  * @returns TRUE if operation was successful, FALSE otherwise
190  */
191 static gboolean
192 eail_selection_add_selection(AtkSelection *selection,
193                              gint i)
194 {
195    g_return_val_if_fail(EAIL_IS_WIDGET(selection), FALSE);
196    Evas_Object *object = eail_widget_get_widget(EAIL_WIDGET(selection));
197    const Eina_List *items = elm_diskselector_items_get(object);
198    Elm_Object_Item *item = eina_list_nth(items, i);
199    if (!item) return FALSE;
200    elm_diskselector_item_selected_set(item, EINA_TRUE);
201    return TRUE;
202 }
203
204 /**
205  * @brief Clears the selection in the object so that no children in the object are
206  * selected.
207  *
208  * Implementation of AtkSelection->clear_selection callback.
209  *
210  * @param selection AtkSelection instance
211  *
212  * @returns always FALSE - this operation is not supported for Diskselector
213  */
214 static gboolean
215 eail_selection_clear_selection(AtkSelection *selection)
216 {
217    return FALSE;
218 }
219
220 /**
221  * @brief Gets a reference to the accessible object representing the specified selected
222  * child of the object.
223  *
224  * Note: callers should not rely on NULL or on a zero value
225  * for indication of whether AtkSelectionIface is implemented, they should use
226  * type checking/interface checking macros or the atk_get_accessible_value()
227  * convenience method.
228  *
229  * Implementation of AtkSelection->ref_selection callback.
230  *
231  * @param selection AtkSelection instance
232  * @param i selection index
233  *
234  * @returns AtkObject representing the selected accessible or NULL if
235  * selection does not implement this interface
236  */
237 static AtkObject *
238 eail_selection_ref_selection(AtkSelection *selection,
239                              gint i)
240 {
241    g_return_val_if_fail(EAIL_IS_WIDGET(selection), NULL);
242
243    Evas_Object *object = eail_widget_get_widget(EAIL_WIDGET(selection));
244    const Eina_List *items = elm_diskselector_items_get(object);
245    Elm_Object_Item *item = eina_list_nth(items, i);
246    if (!item) return NULL;
247
248    AtkObject *obj;
249    obj = g_object_new(EAIL_TYPE_DISKSELECTOR, NULL);
250    obj->role = ATK_ROLE_LIST_ITEM;
251
252    if (EAIL_IS_ITEM_PARENT(selection))
253      atk_object_set_parent(obj, (AtkObject *)selection);
254
255    atk_object_initialize(obj, item);
256    g_object_ref(obj);
257    return obj;
258 }
259
260 /**
261  * @brief Gets the number of accessible children currently selected.
262  *
263  * Note: callers should not rely on NULL or on a zero value for indication of whether
264  * AtkSelectionIface is implemented, they should use type checking/interface
265  * checking macros or the atk_get_accessible_value() convenience method.
266  *
267  * Implementation of AtkSelection->get_selection_count callback.
268  *
269  * @param selection AtkSelection instance
270  *
271  * @returns always '1' - in Diskselector widget something is always selected
272  */
273 static gint
274 eail_selection_get_selection_count(AtkSelection *selection)
275 {
276    return 1;
277 }
278
279 /**
280  * @brief  Determines if the current child of this object is selected.
281  *
282  * Note: callers should not rely on NULL or on a zero value for indication of whether
283  * AtkSelectionIface is implemented, they should use type checking/interface
284  * checking macros or the atk_get_accessible_value() convenience method.
285  *
286  * Implementation of AtkSelection->is_child_selected callback.
287  *
288  * @param selection AtkSelection instance
289  * @param i child index
290  *
291  * @returns gboolean representing the specified child is selected, or 0 if
292  * selection does not implement this interface
293  */
294 static gboolean
295 eail_selection_is_child_selected(AtkSelection *selection,
296                                  gint i)
297 {
298    g_return_val_if_fail(EAIL_IS_WIDGET(selection), FALSE);
299    Evas_Object *object = eail_widget_get_widget(EAIL_WIDGET(selection));
300    Elm_Object_Item *selected_item = elm_diskselector_selected_item_get(object);
301    Elm_Object_Item *last_item = elm_diskselector_last_item_get(object);
302    Elm_Object_Item *item = elm_diskselector_first_item_get(object);
303    gint n=0;
304    do
305      {
306         if (selected_item==item) break;
307         item = elm_diskselector_item_next_get(item);
308         n++;
309      } while (item!=last_item);
310    return i==n;
311 }
312
313 /**
314  * @brief Removes the specified child of the object from the object's selection.
315  *
316  * Implementation of AtkSelection->remove_selection callback.
317  *
318  * @param selection AtkSelection instance
319  * @param i selection index
320  *
321  * @returns TRUE on success, FALSE otherwise
322  */
323 static gboolean
324 eail_selection_remove_selection(AtkSelection *selection,
325                                 gint i)
326 {
327    g_return_val_if_fail(EAIL_IS_WIDGET(selection), FALSE);
328    Evas_Object *object = eail_widget_get_widget(EAIL_WIDGET(selection));
329    Elm_Object_Item *selected_item = elm_diskselector_first_item_get(object);
330    elm_diskselector_item_selected_set(selected_item, TRUE);
331    return TRUE;
332 }
333
334 /**
335  * @brief Causes every child of the object to be selected if the object supports
336  * multiple selections.
337  *
338  * Implementation of AtkSelection->select_all_selection callback.
339  *
340  * @param selection AtkSelection instance
341  *
342  * @returns FALSE - this operation is not supported for Diskselector widget
343  */
344 static gboolean
345 eail_selection_select_all_selection(AtkSelection *selection)
346 {
347    return FALSE;
348 }
349
350 /**
351  * @brief Initialization of AtkSelectionIface interface
352  *
353  * Function called upon instance creation. It initializes AtkSelection interface
354  * implementation i.e hooks method pointers in the interface structure
355  * to the implementing class's implementation.
356  *
357  * @param iface AtkSelectionIface instance
358  */
359 static void atk_selection_interface_init(AtkSelectionIface *iface)
360 {
361    iface->add_selection        = eail_selection_add_selection;
362    iface->clear_selection      = eail_selection_clear_selection;
363    iface->ref_selection        = eail_selection_ref_selection;
364    iface->get_selection_count  = eail_selection_get_selection_count;
365    iface->is_child_selected    = eail_selection_is_child_selected;
366    iface->remove_selection     = eail_selection_remove_selection;
367    iface->select_all_selection = eail_selection_select_all_selection;
368 }
369
370 /**
371  * @brief Gets the name of a diskselector's child
372  *
373  * @param parent EailItemParent instance
374  * @param item EailItem child instance
375  *
376  * @returns string representing the name of the child
377  */
378 static const gchar *
379 eail_diskselector_item_name_get(EailItemParent *parent, EailItem *item)
380 {
381    Elm_Object_Item *it = eail_item_get_item(item);
382    if (!it) return NULL;
383
384    return elm_object_item_part_text_get(it, NULL);
385 }
386
387 /**
388  * @brief Initialization of EailItemParentIface callbacks
389  *
390  * @param iface EailItemParentIface instance
391  */
392 static void
393 eail_item_parent_interface_init(EailItemParentIface *iface)
394 {
395    iface->get_item_name = eail_diskselector_item_name_get;
396 }
397
398 /**
399  * @brief 'next' action callback
400  *
401  * @param action AtkAction instance
402  * @param data data passed to callback
403  * @return TRUE on success, FALSE otherwise
404  */
405 static gboolean
406 _eail_diskselector_action_next(AtkAction *action, void *data)
407 {
408    Evas_Object *widget;
409    Elm_Object_Item *it_next;
410    Elm_Object_Item *it;
411
412    g_return_val_if_fail(EAIL_IS_DISKSELECTOR(action), FALSE);
413
414    widget = eail_widget_get_widget(EAIL_WIDGET(action));
415    if (!widget) return FALSE;
416
417    it = elm_diskselector_selected_item_get(widget);
418    if (!it) return FALSE;
419
420    it_next = elm_diskselector_item_next_get(it);
421    if (it_next) elm_diskselector_item_selected_set(it_next, EINA_TRUE);
422
423    evas_object_smart_callback_call(widget, "selected", NULL);
424
425    return TRUE;
426 }
427
428 /**
429  * @brief 'prev' action callback
430  *
431  * @param action AtkAction instance
432  * @param data data passed to callback
433  * @return TRUE on success, FALSE otherwise
434  */
435 static gboolean
436 _eail_diskselector_action_prev(AtkAction *action, void *data)
437 {
438    Evas_Object *widget;
439    Elm_Object_Item *it;
440    Elm_Object_Item *it_prev;
441
442    g_return_val_if_fail(EAIL_IS_DISKSELECTOR(action), FALSE);
443
444    widget = eail_widget_get_widget(EAIL_WIDGET(action));
445    if (!widget) return FALSE;
446
447    it = elm_diskselector_selected_item_get(widget);
448    if (!it) return FALSE;
449
450    it_prev = elm_diskselector_item_prev_get(it);
451    if (it_prev) elm_diskselector_item_selected_set(it_prev, EINA_TRUE);
452
453    evas_object_smart_callback_call(widget, "selected", NULL);
454
455    return TRUE;
456 }
457
458 /**
459  * @brief Adds actions for scrolling to actions table
460  * @param widget EailDiskselector instance
461  */
462 static void
463 eail_diskselector_actions_table_init(EailDiskselector *widget)
464 {
465    g_return_if_fail(EAIL_IS_DISKSELECTOR(widget));
466
467    eail_action_widget_action_append(EAIL_ACTION_WIDGET(widget),
468                                     EAIL_diskselector_ACTION_PREV,
469                                     NULL,
470                                     _eail_diskselector_action_prev);
471    eail_action_widget_action_append(EAIL_ACTION_WIDGET(widget),
472                                     EAIL_diskselector_ACTION_NEXT,
473                                     NULL,
474                                     _eail_diskselector_action_next);
475 }