Merge "custom eail widget implementation" into tizen
[platform/core/uifw/eail.git] / eail / eail_hoversel.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_hoversel.c
22  * @brief EailHoversel implementation.
23  */
24
25 #include <Elementary.h>
26
27 #include "eail_hoversel.h"
28 #include "eail_factory.h"
29 #include "eail_item_parent.h"
30 #include "eail_priv.h"
31
32 static void atk_action_interface_init(AtkActionIface *iface);
33 static void eail_item_parent_interface_init(EailItemParentIface *iface);
34
35 /**
36  * @brief EailHoversel type definition
37  */
38 G_DEFINE_TYPE_WITH_CODE(EailHoversel,
39                         eail_hoversel,
40                         EAIL_TYPE_WIDGET,
41                         G_IMPLEMENT_INTERFACE(EAIL_TYPE_ITEM_PARENT,
42                                               eail_item_parent_interface_init)
43                         G_IMPLEMENT_INTERFACE(ATK_TYPE_ACTION,
44                                               atk_action_interface_init));
45
46 /* AtkObject */
47 static AtkStateSet *eail_hoversel_ref_state_set(AtkObject *obj);
48 static gint eail_hoversel_get_n_children(AtkObject *obj);
49 static AtkObject *eail_hoversel_ref_child(AtkObject *obj,
50                                           gint i);
51 static void eail_hoversel_initialize(AtkObject *obj,
52                                      gpointer data);
53 static void eail_hoversel_finalize(GObject *obj);
54
55 /* AtkAction */
56 static const char *eail_hoversel_description_get(AtkAction *action,
57                                                  gint i);
58 static gboolean eail_hoversel_description_set(AtkAction *action,
59                                               gint i,
60                                               const char *description);
61 static const char *eail_hoversel_action_name_get(AtkAction *action,
62                                                  int i);
63 static int eail_hoversel_n_actions_get(AtkAction *action);
64 static gboolean eail_hoversel_do_action(AtkAction *action,
65                                         int i);
66
67 /* EailItemParent */
68
69 /* Helper functions */
70 static const Eina_List *eail_hoversel_items_get(EailHoversel *obj);
71
72 /*
73  * Implementation of the *AtkObject* interface
74  */
75
76 /**
77  * @brief EailHoverser initializer
78  *
79  * @param obj AtkObject instance
80  * @param data initialization data
81  */
82 static void
83 eail_hoversel_initialize(AtkObject *obj, gpointer data)
84 {
85    ATK_OBJECT_CLASS(eail_hoversel_parent_class)->initialize(obj, data);
86    obj->role = ATK_ROLE_GLASS_PANE;
87 }
88
89 /**
90  * @brief EailHoversel finalizer.
91  *
92  * Destroys object and allocated resources.
93  *
94  * @param obj object that needs to be finalized
95  */
96 static void
97 eail_hoversel_finalize(GObject *obj)
98 {
99     EailHoversel *hoversel = EAIL_HOVERSEL(obj);
100
101     if (hoversel->shrink_description) free(hoversel->shrink_description);
102     if (hoversel->expand_description) free(hoversel->expand_description);
103
104     G_OBJECT_CLASS(eail_hoversel_parent_class)->finalize(obj);
105 }
106
107 /**
108  * @brief EailHoversel instance initializer.
109  *
110  * @param hoversel EailHoversel instance
111  */
112 static void
113 eail_hoversel_init(EailHoversel *hoversel)
114 {
115    hoversel->shrink_description = NULL;
116    hoversel->expand_description = NULL;
117 }
118
119 /**
120  * @brief Gets the state set of the accessible.
121  *
122  * The caller must unreference it when it is no longer needed.
123  *
124  * @param accessible EailHoversel instance
125  * @return AtkStateSet containing the state set of the accessible
126  */
127 static AtkStateSet*
128 eail_hoversel_ref_state_set(AtkObject *accessible)
129 {
130    AtkStateSet *state_set = NULL;
131    Evas_Object *widget = NULL;
132
133    state_set =
134        ATK_OBJECT_CLASS(eail_hoversel_parent_class)->ref_state_set(accessible);
135    if (!state_set)
136      {
137         printf("NULL STATE SET");
138      }
139
140    widget = eail_widget_get_widget(EAIL_WIDGET(accessible));
141    if (!widget)
142      {
143         atk_state_set_add_state(state_set, ATK_STATE_DEFUNCT);
144         return state_set;
145      }
146
147    if (elm_hoversel_expanded_get(widget))
148      {
149         atk_state_set_add_state(state_set, ATK_STATE_EXPANDED);
150
151         if (elm_hoversel_horizontal_get(widget))
152           atk_state_set_add_state(state_set, ATK_STATE_HORIZONTAL);
153         else
154           atk_state_set_add_state(state_set, ATK_STATE_VERTICAL);
155      }
156    else
157      {
158         atk_state_set_add_state(state_set, ATK_STATE_DEFAULT);
159      }
160
161    return state_set;
162 }
163
164 /**
165  * @brief Gets the number of accessible children of obj
166  *
167  * @param obj AtkObject instance
168  * @return integer containing the number of obj's children
169  */
170 static gint
171 eail_hoversel_get_n_children(AtkObject *obj)
172 {
173    const Eina_List *list;
174
175    g_return_val_if_fail(EAIL_IS_HOVERSEL(obj), 0);
176
177    list = eail_hoversel_items_get(EAIL_HOVERSEL(obj));
178
179    return eina_list_count(list);
180 }
181
182 /**
183  * @brief Gets a reference to the specified accessible child of the object.
184  *
185  * The accessible children are 0-based so the first accessible child is at index 0, the second at index 1 and so on.
186  *
187  * Implementation of ref_child from AtkObject interface.
188  *
189  * The caller must unreference it when it is no longer needed.
190  *
191  * @param obj AtkObject instance
192  * @param i child index
193  * @return AtkObject containing the reference to the specified accessible child
194  */
195 static AtkObject *
196 eail_hoversel_ref_child(AtkObject *obj,
197                             gint i)
198 {
199    const Eina_List *items;
200    AtkObject *child = NULL;
201
202    g_return_val_if_fail(EAIL_IS_HOVERSEL(obj), NULL);
203
204    items = eail_hoversel_items_get(EAIL_HOVERSEL(obj));
205    if (eina_list_count(items) > i)
206      {
207         child = eail_factory_get_item_atk_obj
208                           (eina_list_nth(items, i), ATK_ROLE_LABEL, obj);
209
210         g_object_ref(child);
211      }
212    else
213      ERR("Tried to ref child with index %d out of bounds!", i);
214
215    return child;
216 }
217
218 /**
219  * @brief EailHoversel class initializer.
220  *
221  * @param klass EailHoverselClass instance
222  */
223 static void
224 eail_hoversel_class_init(EailHoverselClass *klass)
225 {
226    AtkObjectClass *atk_class = ATK_OBJECT_CLASS(klass);
227    GObjectClass *object_class = G_OBJECT_CLASS(klass);
228
229    atk_class->initialize = eail_hoversel_initialize;
230    atk_class->ref_state_set = eail_hoversel_ref_state_set;
231    atk_class->get_n_children = eail_hoversel_get_n_children;
232    atk_class->ref_child = eail_hoversel_ref_child;
233
234    object_class->finalize = eail_hoversel_finalize;
235 }
236
237 /*
238  * Implementation of the *AtkAction* interface
239  */
240
241 /**
242  * @brief AtkAction interface initializer.
243  *
244  * @param iface EailHoversel instance
245  */
246 static void
247 atk_action_interface_init(AtkActionIface *iface)
248 {
249    g_return_if_fail(iface != NULL);
250
251    iface->do_action          = eail_hoversel_do_action;
252    iface->get_n_actions      = eail_hoversel_n_actions_get;
253    iface->get_description    = eail_hoversel_description_get;
254    iface->get_name           = eail_hoversel_action_name_get;
255    iface->set_description    = eail_hoversel_description_set;
256 }
257
258 /**
259  * @brief Gets the description of the specified action of the object.
260  *
261  * Implementation of get_description from AtkAction interface.
262  *
263  * @param action EailHoversel instance
264  * @param i action index
265  * @return string representing the description of the specified action
266  */
267 static const char*
268 eail_hoversel_description_get(AtkAction *action,
269                               gint i)
270 {
271    EailHoversel *hoversel;
272    const char *action_description;
273
274    hoversel = EAIL_HOVERSEL(action);
275    if (!hoversel) return NULL;
276
277    switch (i)
278      {
279        case 0:
280            action_description = hoversel->shrink_description;
281            break;
282        case 1:
283            action_description = hoversel->expand_description;
284            break;
285        default:
286            action_description = NULL;
287            break;
288      }
289
290    return action_description;
291 }
292
293 /**
294  * @brief Sets a description of the specified action of the object.
295  *
296  * Implementation of set_description from AtkAction interface.
297  *
298  * @param action AtkAction instance
299  * @param i index of the action to be performed
300  * @param description action desciption
301  * @return TRUE if description was set successfully, FALSE otherwise
302  */
303 static gboolean
304 eail_hoversel_description_set(AtkAction *action,
305                               gint i,
306                               const char *description)
307 {
308    EailHoversel *hoversel;
309    char **value;
310
311    hoversel = EAIL_HOVERSEL(action);
312    if (!hoversel) return FALSE;
313
314    switch (i)
315      {
316        case 0:
317            value = &hoversel->shrink_description;
318            break;
319        case 1:
320            value = &hoversel->expand_description;
321            break;
322        default:
323            value = NULL;
324            break;
325      }
326
327    if (value)
328      {
329         free(*value);
330         *value = g_strdup(description);
331         return TRUE;
332      }
333
334    return FALSE;
335 }
336
337 /**
338  * @brief Gets the name of the specified action of the object.
339  *
340  * Implementation of get_name from AtkAction interface.
341  *
342  * @param action AtkAction instance
343  * @param i index of the action to be performed
344  * @return string representing the name of the specified action
345  */
346 static const char*
347 eail_hoversel_action_name_get(AtkAction *action,
348                               int i)
349 {
350    const char* action_name;
351
352    switch (i)
353      {
354        case 0:
355            action_name = "shrink";
356            break;
357        case 1:
358            action_name = "expand";
359            break;
360        default:
361            action_name = NULL;
362            break;
363      }
364
365    return action_name;
366 }
367
368 /**
369  * @brief Gets the number of accessible actions available on the object.
370  *
371  * If there are more than one, the first one is considered the "default" action of the object.
372  *
373  * Implementation of get_n_actions from AtkAction interface.
374  *
375  * @param action AtkAction instance
376  * @return integer containing the number of implemented actions
377  */
378 static int
379 eail_hoversel_n_actions_get(AtkAction *action)
380 {
381    return 2;
382 }
383
384 /**
385  * @brief Performs the specified action on the object.
386  *
387  * Implementation of do_action from AtkAction interface.
388  *
389  * @param action AtkAction instance
390  * @param i action index
391  * @return TRUE on success, FALSE otherwise
392  */
393 static gboolean
394 eail_hoversel_do_action(AtkAction *action,
395                         int i)
396 {
397    Evas_Object *widget;
398
399    widget = eail_widget_get_widget(EAIL_WIDGET(action));
400    if (!widget) return FALSE;
401
402    if ((elm_object_disabled_get(widget)) || (!evas_object_visible_get(widget)))
403      return FALSE;
404
405    const char *action_name = atk_action_get_name(action, i);
406    if (!action_name) return FALSE;
407
408    if (!g_strcmp0(action_name, "expand"))
409      {
410         if (elm_hoversel_expanded_get(widget))
411           return FALSE;
412
413         elm_hoversel_hover_begin(widget);
414         atk_object_notify_state_change(ATK_OBJECT(action), ATK_STATE_EXPANDED, TRUE);
415      }
416    else if (!g_strcmp0(action_name, "shrink"))
417      {
418         if (!elm_hoversel_expanded_get(widget))
419           return FALSE;
420
421         elm_hoversel_hover_end(widget);
422         atk_object_notify_state_change(ATK_OBJECT(action), ATK_STATE_EXPANDED, FALSE);
423      }
424
425    return TRUE;
426 }
427
428 /*
429  * Implementation of the *EailItemParent* interface
430  */
431
432 /**
433  * @brief Gets the name of hoversel's child
434  *
435  * @param parent parent instance
436  * @param item child instance
437  *
438  * @returns string representing the name of the child
439  */
440 static const gchar *
441 eail_hoversel_item_name_get(EailItemParent *parent, EailItem *item)
442 {
443    Elm_Object_Item *it = eail_item_get_item(item);
444    if (!it) return NULL;
445
446    return elm_object_item_part_text_get(it, NULL);
447 }
448
449 /**
450  * @brief Checks if content get is supported
451  *
452  * Implementation of EailItemParent->is_content_get_supported callback.
453  *
454  * @param parent EailItemParent instance
455  * @param item EailItem instance
456  * @returns FALSE as there is no content support
457  */
458 gboolean
459 eail_hoversel_content_get_support(EailItemParent   *parent,
460                                   EailItem         *item)
461 {
462    return FALSE;
463 }
464
465 /**
466  * @brief EailItemParent interface initializer
467  *
468  * @param iface EailItemParentIface instance
469  */
470 static void
471 eail_item_parent_interface_init(EailItemParentIface *iface)
472 {
473    iface->get_item_name = eail_hoversel_item_name_get;
474    iface->is_content_get_supported = eail_hoversel_content_get_support;
475 }
476
477 /*
478  * Helper functions
479  */
480
481 /**
482  * @brief Gets obj's items list.
483  *
484  * @param obj EailHoversel instance
485  * @return Eina_List containing obj's items
486  */
487 static const Eina_List *
488 eail_hoversel_items_get(EailHoversel *obj)
489 {
490    Evas_Object *widget;
491    const Eina_List *items = NULL;
492
493    g_return_val_if_fail(EAIL_HOVERSEL(obj), NULL);
494
495    widget = eail_widget_get_widget(EAIL_WIDGET(obj));
496    if (!widget) return NULL;
497
498    items = elm_hoversel_items_get(widget);
499    if (!items) return NULL;
500
501    return items;
502 }