Merge "custom eail widget implementation" into tizen
[platform/core/uifw/eail.git] / eail / eail_flipselector.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_flipselector.c
22  * @brief EailFlipselector implementation.
23  */
24
25 #include <Elementary.h>
26
27 #include "eail_flipselector.h"
28 #include "eail_factory.h"
29 #include "eail_item_parent.h"
30 #include "eail_priv.h"
31
32 /**
33  * @brief Maximum number of selections
34  */
35 #define FLIPSELECTOR_MAX_SELECTIONS 1
36
37 static void atk_selection_interface_init(AtkSelectionIface *iface);
38 static void atk_action_interface_init(AtkActionIface *iface);
39 static void eail_item_parent_interface_init(EailItemParentIface *iface);
40
41 /**
42  * @brief EailFlipselector type definition
43  */
44 G_DEFINE_TYPE_WITH_CODE(EailFlipselector,
45                         eail_flipselector,
46                         EAIL_TYPE_WIDGET,
47                         G_IMPLEMENT_INTERFACE(EAIL_TYPE_ITEM_PARENT,
48                                               eail_item_parent_interface_init)
49                         G_IMPLEMENT_INTERFACE(ATK_TYPE_SELECTION,
50                                               atk_selection_interface_init)
51                         G_IMPLEMENT_INTERFACE(ATK_TYPE_ACTION,
52                                               atk_action_interface_init));
53
54 /**
55  * @brief Function executed on selected event
56  *
57  * @param data user data passed to callback
58  * @param obj source object
59  * @param event_info event info
60  */
61 static void
62 _on_selected(void *data,
63              Evas_Object *obj,
64              void *event_info)
65 {
66     EailFlipselector *flip = EAIL_FLIPSELECTOR(data);
67     atk_object_notify_state_change(ATK_OBJECT(flip), ATK_STATE_SELECTED, TRUE);
68 }
69
70 /**
71  * @brief EailFlipselector initializer
72  *
73  * @param obj AtkObject instance
74  * @param data initialization data
75  */
76 static void
77 eail_flipselector_initialize(AtkObject *obj, gpointer data)
78 {
79    Evas_Object *widget;
80
81    ATK_OBJECT_CLASS(eail_flipselector_parent_class)->initialize(obj, data);
82    obj->role = ATK_ROLE_LIST;
83
84    widget = eail_widget_get_widget(EAIL_WIDGET(obj));
85
86    evas_object_smart_callback_add(widget, "selected", _on_selected, obj);
87    evas_object_smart_callback_add(widget, "selected", _on_selected, obj);
88 }
89
90 /**
91  * @brief EailFlipselector finalizer
92  *
93  * Frees memory assigned to object.
94  *
95  * @param object GObject instance
96  */
97 static void
98 eail_flipselector_finalize(GObject *object)
99 {
100    EailFlipselector *flipselector = EAIL_FLIPSELECTOR(object);
101
102    if (flipselector->next_description) free(flipselector->next_description);
103    if (flipselector->prev_description) free(flipselector->prev_description);
104
105    G_OBJECT_CLASS(eail_flipselector_parent_class)->finalize(object);
106 }
107
108 /**
109  * @brief Gets obj's items list
110  *
111  * @param obj EailFlipselector instance
112  * @return Eina_List representing the list of obj's items
113  */
114 static const Eina_List *
115 eail_flipselector_items_get(EailFlipselector *obj)
116 {
117    Evas_Object *widget;
118    const Eina_List *items = NULL;
119
120    g_return_val_if_fail(EAIL_FLIPSELECTOR(obj), NULL);
121
122    widget = eail_widget_get_widget(EAIL_WIDGET(obj));
123    if (!widget) return NULL;
124
125    items = elm_flipselector_items_get(widget);
126    if (!items) return NULL;
127
128    return items;
129 }
130
131 /**
132  * @brief Gets a reference to the i-th child of the accessible
133  *
134  * The caller must unreference it when it is no longer needed.
135  *
136  * @param obj AtkObject instance
137  * @param i child index
138  * @return AtkObject representing the i-th child of the accessible
139  */
140 static AtkObject *
141 eail_flipselector_ref_child(AtkObject *obj,
142                             gint i)
143 {
144    const Eina_List *items;
145    AtkObject *child = NULL;
146
147    g_return_val_if_fail(EAIL_IS_FLIPSELECTOR(obj), NULL);
148
149    items = eail_flipselector_items_get(EAIL_FLIPSELECTOR(obj));
150    if (eina_list_count(items) > i)
151      {
152         child = eail_factory_get_item_atk_obj
153                            (eina_list_nth(items, i), ATK_ROLE_LABEL, obj);
154
155         g_object_ref(child);
156      }
157    else
158      ERR("Tried to ref child with index %d out of bounds!", i);
159
160    return child;
161 }
162
163 /**
164  * @brief Gets the number of children of the accessible
165  *
166  * @param obj AtkObject instance
167  * @return integer representing the number children of the accessible
168  */
169 static gint
170 eail_flipselector_get_n_children(AtkObject *obj)
171 {
172    const Eina_List *list;
173
174    g_return_val_if_fail(EAIL_IS_FLIPSELECTOR(obj), 0);
175
176    list = eail_flipselector_items_get(EAIL_FLIPSELECTOR(obj));
177
178    return eina_list_count(list);
179 }
180
181 /**
182  * @brief EailFlipselector interface initializer
183  *
184  * @param flipselector EailFlipselector instance
185  */
186 static void
187 eail_flipselector_init(EailFlipselector *flipselector)
188 {
189    flipselector->next_description = NULL;
190    flipselector->prev_description = NULL;
191 }
192
193
194
195 /**
196  * @brief Gets the name of a flipselector's child
197  *
198  * @param parent EailItemParent instance
199  * @param item EailItem instance
200  *
201  * @returns string representing the name of the child
202  */
203 static const gchar *
204 eail_flipselector_item_name_get(EailItemParent *parent, EailItem *item)
205 {
206    Elm_Object_Item *it = eail_item_get_item(item);
207    if (!it) return NULL;
208
209    return elm_object_item_part_text_get(it, NULL);
210 }
211
212 /**
213  * @brief Checks if content get is supported
214  *
215  * Implementation of EailItemParent->is_content_get_supported callback.
216  *
217  * @param parent EailItemParent instance
218  * @param item EailItem instance
219  * @returns FALSE as there is no content support
220  */
221 gboolean
222 eail_flipselector_content_get_support(EailItemParent   *parent,
223                                           EailItem         *item)
224 {
225    return FALSE;
226 }
227
228 /**
229  * @brief EailItemParent interface initializer
230  *
231  * @param iface EailItemParentIface instance
232  */
233 static void
234 eail_item_parent_interface_init(EailItemParentIface *iface)
235 {
236    iface->get_item_name = eail_flipselector_item_name_get;
237    iface->is_content_get_supported = eail_flipselector_content_get_support;
238 }
239
240 /**
241  * @brief EailFlipselector class initializer
242  *
243  * @param klass EailFlipselectorClass instance
244  */
245 static void
246 eail_flipselector_class_init(EailFlipselectorClass *klass)
247 {
248    AtkObjectClass *atk_class = ATK_OBJECT_CLASS(klass);
249    GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
250
251    atk_class->initialize = eail_flipselector_initialize;
252    atk_class->get_n_children = eail_flipselector_get_n_children;
253    atk_class->ref_child = eail_flipselector_ref_child;
254    gobject_class->finalize = eail_flipselector_finalize;
255 }
256
257 /**
258  * @brief Selects the i-th item of the accessible
259  *
260  * @param selection AtkSelection instance
261  * @param i item index
262  * @return TRUE if item was successfully selected, FALSE otherwise
263  */
264 static gboolean
265 eail_flipselector_add_selection(AtkSelection *selection,
266                                 gint i)
267 {
268    Elm_Object_Item *it;
269    const Eina_List *list;
270
271    g_return_val_if_fail(EAIL_IS_FLIPSELECTOR(selection), FALSE);
272
273    list = eail_flipselector_items_get(EAIL_FLIPSELECTOR(selection));
274
275    if (eina_list_count(list) > i)
276      {
277         it = eina_list_nth(list, i);
278         if (!it) return FALSE;
279
280         elm_flipselector_item_selected_set(it, EINA_TRUE);
281      }
282
283    return TRUE;
284 }
285
286 /**
287  * @brief Clears selections
288  *
289  * @param selection AtkSelection instance
290  * @return always FALSE
291  */
292 static gboolean
293 eail_flipselector_clear_selection(AtkSelection *selection)
294 {
295    return FALSE;
296 }
297
298 /**
299  * @brief Gets the number of currently selected children
300  *
301  * @param selection AtkSelection instance
302  * @return integer representing the number of selected children
303  */
304 static gint
305 eail_flipselector_get_selection_count(AtkSelection *selection)
306 {
307    return FLIPSELECTOR_MAX_SELECTIONS;
308 }
309
310 /**
311  * @brief Determines if the i-th child of the accessible is selected
312  *
313  * @param selection AtkSelection instance
314  * @param i child index
315  * @return TRUE if the i-th child is selected, FALSE otherwise
316  */
317 static gboolean
318 eail_flipselector_is_child_selected(AtkSelection *selection,
319                                     gint i)
320 {
321    Evas_Object *widget;
322    Elm_Object_Item *sel_it = NULL;
323    Elm_Object_Item *it = NULL;
324    const Eina_List *list;
325
326    g_return_val_if_fail(EAIL_IS_FLIPSELECTOR(selection), FALSE);
327
328    list = eail_flipselector_items_get(EAIL_FLIPSELECTOR(selection));
329
330    if (eina_list_count(list) > i)
331      {
332         widget = eail_widget_get_widget(EAIL_WIDGET(selection));
333         if (!widget) return FALSE;
334
335         sel_it = elm_flipselector_selected_item_get(widget);
336         if (!sel_it) return FALSE;
337
338         it = eina_list_nth(list, i);
339      }
340
341    return sel_it == it;
342 }
343
344 /**
345  * @brief Removes the i-th selection of the accessible
346  *
347  * @param selection AtkSelection instance
348  * @param i selection index
349  * @return TRUE if selection was successfully removed, FALSE otherwise
350  */
351 static gboolean
352 eail_flipselector_remove_selection(AtkSelection *selection,
353                                    gint i)
354 {
355    Evas_Object *widget;
356    Elm_Object_Item *sel_it;
357    Elm_Object_Item *it;
358    const Eina_List *list;
359
360    g_return_val_if_fail(EAIL_IS_FLIPSELECTOR(selection), FALSE);
361
362    list = eail_flipselector_items_get(EAIL_FLIPSELECTOR(selection));
363
364    if (eina_list_count(list) > i)
365      {
366         widget = eail_widget_get_widget(EAIL_WIDGET(selection));
367         if (!widget) return FALSE;
368
369         sel_it = elm_flipselector_selected_item_get(widget);
370         if (!sel_it) return FALSE;
371
372         it = eina_list_nth(list, i);
373         if (it == sel_it)
374           {
375              elm_flipselector_item_selected_set(sel_it, EINA_FALSE);
376
377              return TRUE;
378           }
379      }
380
381    return FALSE;
382 }
383
384 /**
385  * @brief Selects all children of the accessible
386  *
387  * @param selection AtkSelection instance
388  * @returns always FALSE
389  */
390 static gboolean
391 eail_flipselector_select_all_selection(AtkSelection *selection)
392 {
393    return FALSE;
394 }
395
396 /**
397  * @brief AtkSelection interface initializer
398  *
399  * @param iface AtkSelectionIface instance
400  */
401 static void atk_selection_interface_init(AtkSelectionIface *iface)
402 {
403    iface->add_selection        = eail_flipselector_add_selection;
404    iface->clear_selection      = eail_flipselector_clear_selection;
405    iface->get_selection_count  = eail_flipselector_get_selection_count;
406    iface->is_child_selected    = eail_flipselector_is_child_selected;
407    iface->remove_selection     = eail_flipselector_remove_selection;
408    iface->select_all_selection = eail_flipselector_select_all_selection;
409 }
410
411 /*
412  * Implementation of the *AtkAction* interface
413  */
414
415 /**
416  * @brief Performs the i-th action
417  *
418  * @param action AtkAction instance
419  * @param i action index
420  * @return TRUE on success, FALSE otherwise
421  */
422 static gboolean
423 eail_flipselector_action_do_action(AtkAction *action,
424                                    gint i)
425 {
426    Evas_Object *widget;
427    const char *action_name;
428
429    widget = eail_widget_get_widget(EAIL_WIDGET(action));
430    if (!widget) return FALSE;
431
432    if ((elm_object_disabled_get(widget)) || (!evas_object_visible_get(widget)))
433      return FALSE;
434
435    action_name = atk_action_get_name(action, i);
436    if (!action_name) return FALSE;
437
438    if (!g_strcmp0("next", action_name))
439      elm_flipselector_flip_next(widget);
440    else if (!g_strcmp0("previous", action_name))
441      elm_flipselector_flip_prev(widget);
442    else
443      return FALSE;
444
445    return TRUE;
446 }
447
448 /**
449  * @brief Gets the number of actions available on the object
450  *
451  * @param action AtkAction instance
452  * @return integer representing the number of implemented actions
453  */
454 static gint
455 eail_flipselector_action_get_n_actions(AtkAction *action)
456 {
457    return 2;
458 }
459
460 /**
461  * @brief Gets the description string of an action with the given index
462  *
463  * @param action AtkAction instance
464  * @param i index of action
465  *
466  * @returns string representing the specified action's description
467  * or NULL if one was not found
468  */
469 static const gchar *
470 eail_flipselector_action_get_description(AtkAction *action,
471                                          gint i)
472 {
473    const char *action_description = NULL;
474    EailFlipselector *flipselector;
475
476    flipselector = EAIL_FLIPSELECTOR(action);
477    if (!flipselector) return NULL;
478
479    switch (i)
480      {
481        case 0:
482            action_description = flipselector->next_description;
483            break;
484
485        case 1:
486            action_description = flipselector->prev_description;
487            break;
488
489        default:
490            action_description = NULL;
491            break;
492      }
493
494    return action_description;
495 }
496
497 /**
498  * @brief Gets the name string of an action with the given index
499  *
500  * @param action AtkAction instance
501  * @param i action index
502  * @return string representing the specified action's name
503  * or NULL if one was not found
504  */
505 static const gchar *
506 eail_flipselector_action_get_name(AtkAction *action,
507                                   gint i)
508 {
509    const char* action_name = NULL;
510
511    switch (i)
512      {
513        case 0:
514            /* user selects next item */
515            action_name = "next";
516            break;
517
518        case 1:
519            /* user selects previous item */
520            action_name = "previous";
521            break;
522
523        default:
524            action_name = NULL;
525            break;
526      }
527
528    return action_name;
529 }
530
531 /**
532  * @brief Sets the description of the specified action
533  *
534  * @param action AtkAction instance
535  * @param i action's number
536  * @param desc action's description
537  * @return TRUE if description was set successfully, FALSE otherwise
538  */
539 static gboolean
540 eail_flipselector_action_set_description(AtkAction *action,
541                                          gint i,
542                                          const gchar *desc)
543 {
544    EailFlipselector *flipselector;
545    char **value;
546
547    flipselector = EAIL_FLIPSELECTOR(action);
548    if (!flipselector) return FALSE;
549
550    switch (i)
551      {
552        case 0:
553            value = &flipselector->next_description;
554            break;
555
556        case 1:
557            value = &flipselector->prev_description;
558            break;
559
560        default:
561            value = NULL;
562            break;
563      }
564
565    if (value)
566      {
567         free(*value);
568         *value = g_strdup(desc);
569
570         return TRUE;
571      }
572
573    return FALSE;
574 }
575
576 /**
577  * @brief AtkAction interface initializer
578  *
579  * @param iface AtkActionIface instance
580  */
581 static void
582 atk_action_interface_init(AtkActionIface *iface)
583 {
584    g_return_if_fail(iface != NULL);
585
586    iface->do_action          = eail_flipselector_action_do_action;
587    iface->get_n_actions      = eail_flipselector_action_get_n_actions;
588    iface->get_description    = eail_flipselector_action_get_description;
589    iface->get_name           = eail_flipselector_action_get_name;
590    iface->set_description    = eail_flipselector_action_set_description;
591 }
592