Merge "custom eail widget implementation" into tizen
[platform/core/uifw/eail.git] / eail / eail_slideshow.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_slideshow.c
22  * @brief EailSlideshow implementation
23  */
24
25 #include <Elementary.h>
26
27 #include "eail_slideshow.h"
28 #include "eail_factory.h"
29 #include "eail_priv.h"
30
31 /**
32  * @brief Default timeout in seconds
33  */
34 #define SLIDESHOW_DEFAULT_TIMEOUT 3.0
35
36 static void atk_selection_interface_init(AtkSelectionIface *iface);
37 static void atk_action_interface_init(AtkActionIface *iface);
38
39 /**
40  * @brief Define GObject type
41  */
42 G_DEFINE_TYPE_WITH_CODE(EailSlideshow, eail_slideshow, EAIL_TYPE_WIDGET,
43                         G_IMPLEMENT_INTERFACE(ATK_TYPE_SELECTION,
44                                               atk_selection_interface_init)
45                         G_IMPLEMENT_INTERFACE(ATK_TYPE_ACTION,
46                                               atk_action_interface_init));
47
48 /**
49  * @brief Gets a reference to the specified accessible child of the object.
50  *
51  * The accessible children are 0-based so the first accessible child
52  * is at index 0, the second at index 1 and so on.
53  *
54  * Implementation of ref_child from AtkObject interface.
55  *
56  * @param obj AtkObject instance
57  * @param i index of a child object
58  *
59  * @returns AtkObject representing the specified accessible child
60  */
61 static AtkObject*
62 eail_slideshow_ref_child(AtkObject *obj, gint i)
63 {
64    Evas_Object *widget, *child_widget;
65    Elm_Object_Item *it;
66
67    g_return_val_if_fail(EAIL_IS_SLIDESHOW(obj), NULL);
68
69    widget = eail_widget_get_widget(EAIL_WIDGET(obj));
70    if (!widget) return NULL;
71
72    it = elm_slideshow_item_nth_get(widget, i);
73    if (!it) return NULL;
74
75    child_widget = elm_slideshow_item_object_get(it);
76    if (!child_widget)
77      {
78         WRN("Given index %d is beyond realized (cached) views. Returning NULL",
79             i);
80         return NULL;
81      }
82
83    return eail_factory_get_accessible(child_widget);
84 }
85
86 /**
87  * @brief Gets the number of accessible children of the accessible
88  *
89  * Implementation of get_n_children from AtkObject interface.
90  *
91  * @param obj AtkObject instance
92  * @returns integer representing the number of widget's children
93  */
94 static gint
95 eail_slideshow_n_children_get(AtkObject *obj)
96 {
97    Evas_Object *widget;
98    gint items_count;
99
100    g_return_val_if_fail(EAIL_IS_SLIDESHOW(obj), 0);
101
102    widget = eail_widget_get_widget(EAIL_WIDGET(obj));
103    if (!widget) return 0;
104    /*the real number of items stored in slideshow widget is returned by
105      elm_slideshow_count_get. However we will not be able to return all items
106      widget since only those stored in cache are created.*/
107    items_count = elm_slideshow_count_get(widget);
108    return items_count;
109 }
110
111 /**
112  * @brief Initialize EailSlideshow as AtkObject
113  *
114  * @param obj AtkObject instance
115  * @param data user data passed to initialization
116  */
117 static void
118 eail_slideshow_initialize(AtkObject *obj, gpointer data)
119 {
120    ATK_OBJECT_CLASS(eail_slideshow_parent_class)->initialize(obj, data);
121    obj->role = ATK_ROLE_DOCUMENT_PRESENTATION;
122 }
123
124 /**
125  * @brief EailSlideshow object initialization
126  *
127  * @param slideshow EailSlideshow instance
128  */
129 static void
130 eail_slideshow_init(EailSlideshow *slideshow)
131 {
132    slideshow->next_description = NULL;
133    slideshow->previous_description = NULL;
134    slideshow->stop_description = NULL;
135    slideshow->start_description = NULL;
136 }
137
138 /**
139  * @brief Destructor of EailSlideshow object
140  *
141  * @param object GObject instance
142  */
143 static void
144 eail_slideshow_finalize(GObject *object)
145 {
146    EailSlideshow *slideshow = EAIL_SLIDESHOW(object);
147    if (slideshow->next_description) free(slideshow->next_description);
148    if (slideshow->previous_description) free(slideshow->previous_description);
149    if (slideshow->stop_description) free(slideshow->stop_description);
150    if (slideshow->start_description) free(slideshow->start_description);
151
152    G_OBJECT_CLASS(eail_slideshow_parent_class)->finalize(object);
153
154 }
155
156 /**
157  * @brief EailSlideshow class initialization
158  *
159  * @param klass EailSlideshowClass instance
160  */
161 static void
162 eail_slideshow_class_init(EailSlideshowClass *klass)
163 {
164    AtkObjectClass *atk_class = ATK_OBJECT_CLASS(klass);
165    GObjectClass *g_object_class = G_OBJECT_CLASS(klass);
166
167    atk_class->initialize = eail_slideshow_initialize;
168    atk_class->get_n_children = eail_slideshow_n_children_get;
169    atk_class->ref_child = eail_slideshow_ref_child;
170
171    g_object_class->finalize = eail_slideshow_finalize;
172 }
173
174 /**
175  * @brief Gets the number of accessible children currently selected.
176  *
177  * Implementation of get_selection_count from AtkSelection interface.
178  *
179  * @param selection AtkSelection instance
180  *
181  * @returns integer representing the number of currently selected children
182  */
183 static gint
184 eail_slideshow_selection_count(AtkSelection *selection)
185 {
186    g_return_val_if_fail(EAIL_IS_SLIDESHOW(selection), 0);
187
188    return 1;
189 }
190
191 /**
192  * @brief Adds the specified accessible child of the object to the object's selection
193  *
194  * Implementation of add_selection from AtkSelection interface.
195  *
196  * @param selection AtkSelection instance
197  * @param i index of object to select
198  *
199  * @returns TRUE on success, FALSE otherwise
200  */
201 static gboolean
202 eail_slideshow_add_selection(AtkSelection *selection, gint i)
203 {
204    Evas_Object *widget;
205    Elm_Object_Item *it;
206
207    g_return_val_if_fail(EAIL_IS_SLIDESHOW(selection), FALSE);
208
209    widget = eail_widget_get_widget(EAIL_WIDGET(selection));
210    if (!widget) return FALSE;
211
212    it = elm_slideshow_item_nth_get(widget, i);
213    if (!it) return FALSE;
214
215    elm_slideshow_item_show(it);
216
217    return TRUE;
218 }
219
220 /**
221  * @brief Gets a reference to the accessible object representing
222  * the specified selected child of the object.
223  *
224  * Implementation of ref_selecton from AtkSelection.
225  *
226  * @param selection AtkSelection instance
227  * @param i index of selection
228  *
229  * @returns AtkObject representing the specified selected child
230  */
231 static AtkObject*
232 eail_slideshow_ref_selection(AtkSelection *selection, gint i)
233 {
234    Evas_Object *widget, *it_widget;
235    Elm_Object_Item *it;
236
237    g_return_val_if_fail(EAIL_IS_SLIDESHOW(selection), NULL);
238    g_return_val_if_fail(i == 0, NULL);
239
240    widget = eail_widget_get_widget(EAIL_WIDGET(selection));
241    it = elm_slideshow_item_current_get(widget);
242
243    it_widget = elm_slideshow_item_object_get(it);
244
245    return eail_factory_get_accessible(it_widget);
246 }
247
248 /**
249  * @brief Determines if the current child of this object is selected.
250  *
251  * Implementation of is_child_selected from AtkSelection.
252  *
253  * @param selection AtkSelection instance
254  * @param i index of selection
255  *
256  * @return TRUE if object is selected, FALSE otherwise
257  */
258 static gboolean
259 eail_slideshow_is_child_selected(AtkSelection *selection, gint i)
260 {
261    Evas_Object *widget;
262    Elm_Object_Item *it, *current;
263
264    g_return_val_if_fail(EAIL_IS_SLIDESHOW(selection), FALSE);
265
266    widget = eail_widget_get_widget(EAIL_WIDGET(selection));
267    if (!widget) return FALSE;
268
269    current = elm_slideshow_item_current_get(widget);
270    it = elm_slideshow_item_nth_get(widget, i);
271
272    return (it == current);
273 }
274
275 /**
276  * @brief Initialization of AtkSelection interface
277  *
278  * Function called upon instance creation. It initializes AtkValue interface
279  * implementation i.e hooks method pointers in the interface structure
280  * to the implementing class's implementation.
281  *
282  * @param iface AtkObject instance that implements AtkSelectionInterface
283  */
284 static void atk_selection_interface_init(AtkSelectionIface *iface)
285 {
286    g_return_if_fail(iface != NULL);
287
288    iface->add_selection = eail_slideshow_add_selection;
289    iface->ref_selection = eail_slideshow_ref_selection;
290    iface->get_selection_count = eail_slideshow_selection_count;
291    iface->is_child_selected = eail_slideshow_is_child_selected;
292 }
293
294 /**
295  * @brief Gets the number of accessible actions available on the object
296  *
297  * If there are more than one, the first one is considered the "default" action of the object.
298  *
299  * Implementation of get_n_actions from AtkAction interface.
300  *
301  * @param action AtkAction instance
302  * @returns integer representing the number of implemented actions
303  */
304 static gint
305 eail_slideshow_n_actions_get(AtkAction *action)
306 {
307    g_return_val_if_fail(EAIL_IS_SLIDESHOW(action), 0);
308
309    return 4;
310 }
311
312 /**
313  * @brief Gets the name of the specified action of the object
314  *
315  * Implementation of get_name from AtkAction interface.
316  *
317  * @param action AtkAction instance
318  * @param i action index
319  *
320  * @returns string representing the name of the specified action
321  */
322 static const gchar*
323 eail_slideshow_action_name_get(AtkAction *action, int i)
324 {
325    const gchar *action_name;
326    g_return_val_if_fail(EAIL_IS_SLIDESHOW(action), NULL);
327    switch (i)
328      {
329       case 0:
330          /*advance to next image*/
331          action_name = "next";
332          break;
333       case 1:
334          /*advance to previous image*/
335          action_name = "previous";
336          break;
337       case 2:
338          /*stop the slideshow*/
339          action_name = "stop";
340          break;
341       case 3:
342          /*start the slideshow*/
343          action_name = "start";
344          break;
345       default:
346          action_name = NULL;
347          break;
348      }
349
350    return action_name;
351 }
352
353 /**
354  * @brief Compares two doubles
355  *
356  * @param A first number
357  * @param B second number
358  * @param max_ulps number of doubles between A and B
359  * @returns TRUE if A equals B, FALSE otherwise
360  */
361 static gboolean
362 _double_cmp(double A, double B, gint max_ulps)
363 {
364    union {
365         double d;
366         gint64 i;
367    }f1, f2;
368    gint64 diff;
369
370    f1.d = A;
371    f2.d = B;
372
373    g_assert(max_ulps > 0 && max_ulps < 4*1024*1024);
374
375    if (f1.i < 0) f1.i = 0x80000000 - f1.i;
376    if (f2.i < 0) f1.i = 0x80000000 - f2.i;
377
378    diff = abs(f1.i - f2.i);
379    if (diff <= max_ulps)
380      return TRUE;
381
382    return FALSE;
383 }
384
385 /**
386  * @brief Performs the specified action on the object
387  *
388  * Implementation of do_action from AtkAction interface.
389  *
390  * @param action AtkAction instance
391  * @param i action index
392  *
393  * @returns TRUE on success, FALSE otherwise
394  */
395 static gboolean
396 eail_slideshow_do_action(AtkAction *action, gint i)
397 {
398    Evas_Object *widget;
399    gboolean result;
400    double slideshow_timeout;
401
402    g_return_val_if_fail(EAIL_IS_SLIDESHOW(action), FALSE);
403
404    widget = eail_widget_get_widget(EAIL_WIDGET(action));
405    if (!widget) return FALSE;
406
407    if ((elm_object_disabled_get(widget)) || (!evas_object_visible_get(widget)))
408      return FALSE;
409
410    switch (i)
411      {
412        case 0:
413            elm_slideshow_next(widget);
414            result = TRUE;
415            break;
416        case 1:
417            elm_slideshow_previous(widget);
418            result = TRUE;
419            break;
420        case 2:
421            elm_slideshow_timeout_set(widget, 0.0);
422            result = TRUE;
423            break;
424        case 3:
425            slideshow_timeout = elm_slideshow_timeout_get(widget);
426            if (_double_cmp(slideshow_timeout, 0.0, 1))
427              {
428                 result = TRUE;
429                 elm_slideshow_timeout_set(widget, SLIDESHOW_DEFAULT_TIMEOUT);
430                 break;
431              }
432            result = FALSE;
433            break;
434        default:
435            result = FALSE;
436            break;
437      }
438
439    return result;
440 }
441
442 /**
443  * @brief Gets the description of the specified action of the object
444  *
445  * Implementation of get_description from AtkAction interface.
446  *
447  * @param action AtkAction instance
448  * @param i action index
449  *
450  * @returns string representing the description of the specified action
451  */
452 static const gchar *
453 eail_slidshow_description_get(AtkAction *action, gint i)
454 {
455    const gchar *action_description;
456    EailSlideshow *slideshow;
457
458    g_return_val_if_fail(EAIL_IS_SLIDESHOW(action), NULL);
459
460    slideshow = EAIL_SLIDESHOW(action);
461    switch (i)
462      {
463        case 0:
464            action_description = slideshow->next_description;
465            break;
466        case 1:
467            action_description = slideshow->previous_description;
468            break;
469        case 2:
470            action_description = slideshow->stop_description;
471            break;
472        case 3:
473            action_description = slideshow->start_description;
474            break;
475        default:
476            action_description = NULL;
477            break;
478      }
479    return action_description;
480 }
481
482 /**
483  * @brief Sets a description of the specified action of the object
484  *
485  * Implementation of set_description from AtkAction interface.
486  *
487  * @param action AtkAction instance
488  * @param i action index
489  * @param description action's description to set
490  *
491  * @returns TRUE on success, FALSE otherwise
492  */
493 static gboolean
494 eail_slideshow_description_set(AtkAction *action, gint i,
495                                const char *description)
496 {
497    EailSlideshow *slideshow;
498    gchar **value;
499
500    g_return_val_if_fail(EAIL_IS_SLIDESHOW(action), FALSE);
501
502    slideshow = EAIL_SLIDESHOW(action);
503    switch (i)
504      {
505        case 0:
506            value = &slideshow->next_description;
507            break;
508        case 1:
509            value = &slideshow->previous_description;
510            break;
511        case 2:
512            value = &slideshow->stop_description;
513            break;
514        case 3:
515            value = &slideshow->start_description;
516            break;
517        default:
518            value = NULL;
519            break;
520      }
521    if (value)
522      {
523         free(*value);
524         *value = g_strdup(description);
525         return TRUE;
526      }
527    return FALSE;
528 }
529
530 /**
531  * @brief AtkAction interface initialization
532  *
533  * @param iface AtkActionIface instance
534  */
535 static void
536 atk_action_interface_init(AtkActionIface *iface)
537 {
538    g_return_if_fail(iface != NULL);
539    iface->do_action = eail_slideshow_do_action;
540    iface->get_n_actions = eail_slideshow_n_actions_get;
541    iface->get_description = eail_slidshow_description_get;
542    iface->set_description = eail_slideshow_description_set;
543    iface->get_name = eail_slideshow_action_name_get;
544    /*unsupported*/
545    /*iface->get_localized_name;*/
546    /*iface->get_keybinding;*/
547 }