Initialize Tizen 2.3
[framework/uifw/elementary.git] / mobile / src / lib / elc_hoversel.c
1 #include <Elementary.h>
2 #include "elm_priv.h"
3 #include "elm_widget_hoversel.h"
4
5 EAPI const char ELM_HOVERSEL_SMART_NAME[] = "elm_hoversel";
6
7 static const char SIG_SELECTED[] = "selected";
8 static const char SIG_DISMISSED[] = "dismissed";
9 static const Evas_Smart_Cb_Description _smart_callbacks[] = {
10    {SIG_SELECTED, ""},
11    {SIG_DISMISSED, ""},
12    {NULL, NULL}
13 };
14
15 EVAS_SMART_SUBCLASS_NEW
16   (ELM_HOVERSEL_SMART_NAME, _elm_hoversel, Elm_Hoversel_Smart_Class,
17   Elm_Button_Smart_Class, elm_button_smart_class_get, _smart_callbacks);
18
19 static Eina_Bool
20 _elm_hoversel_smart_translate(Evas_Object *obj)
21 {
22    ELM_HOVERSEL_DATA_GET(obj, sd);
23    Elm_Hoversel_Item *it;
24    Eina_List *l;
25
26    EINA_LIST_FOREACH(sd->items, l, it)
27      elm_widget_item_translate(it);
28
29    return EINA_TRUE;
30 }
31
32 static Eina_Bool
33 _elm_hoversel_smart_theme(Evas_Object *obj)
34 {
35    char buf[4096];
36    const char *style;
37
38    ELM_HOVERSEL_DATA_GET(obj, sd);
39
40    style = eina_stringshare_add(elm_widget_style_get(obj));
41
42    if (sd->horizontal)
43      snprintf(buf, sizeof(buf), "hoversel_horizontal/%s", style);
44    else
45      snprintf(buf, sizeof(buf), "hoversel_vertical/%s", style);
46
47    /* hoversel's style has an extra bit: orientation */
48    eina_stringshare_replace(&(ELM_WIDGET_DATA(sd)->style), buf);
49
50    if (!ELM_WIDGET_CLASS(_elm_hoversel_parent_sc)->theme(obj))
51      return EINA_FALSE;
52
53    eina_stringshare_replace(&(ELM_WIDGET_DATA(sd)->style), style);
54
55    eina_stringshare_del(style);
56
57    if (sd->hover)
58      elm_widget_mirrored_set(sd->hover, elm_widget_mirrored_get(obj));
59
60    elm_hoversel_hover_end(obj);
61
62    return EINA_TRUE;
63 }
64
65 static void
66 _on_hover_clicked(void *data,
67                   Evas_Object *obj __UNUSED__,
68                   void *event_info __UNUSED__)
69 {
70    elm_hoversel_hover_end(data);
71 }
72
73 static void
74 _on_item_clicked(void *data,
75                  Evas_Object *obj __UNUSED__,
76                  void *event_info __UNUSED__)
77 {
78    Elm_Hoversel_Item *item = data;
79    Evas_Object *obj2 = WIDGET(item);
80
81    if (item->func) item->func((void *)item->base.data, obj2, item);
82    evas_object_smart_callback_call(obj2, SIG_SELECTED, item);
83    elm_hoversel_hover_end(obj2);
84 }
85
86 static void
87 _activate(Evas_Object *obj)
88 {
89    const Elm_Hoversel_Item *item;
90    Evas_Object *bt, *bx, *ic;
91    const Eina_List *l;
92    char buf[4096];
93
94    ELM_HOVERSEL_DATA_GET(obj, sd);
95
96    if (sd->expanded)
97      {
98         elm_hoversel_hover_end(obj);
99         return;
100      }
101    sd->expanded = EINA_TRUE;
102
103    if (elm_widget_disabled_get(obj)) return;
104
105    sd->hover = elm_hover_add(sd->hover_parent);
106    elm_widget_mirrored_automatic_set(sd->hover, EINA_FALSE);
107
108    if (sd->horizontal)
109      snprintf(buf, sizeof(buf), "hoversel_horizontal/%s",
110               elm_widget_style_get(obj));
111    else
112      snprintf(buf, sizeof(buf), "hoversel_vertical/%s",
113               elm_widget_style_get(obj));
114
115    elm_object_style_set(sd->hover, buf);
116
117    evas_object_smart_callback_add
118      (sd->hover, "clicked", _on_hover_clicked, obj);
119    elm_hover_target_set(sd->hover, obj);
120
121    /* hover's content */
122    bx = elm_box_add(sd->hover);
123    elm_widget_mirrored_automatic_set(bx, EINA_FALSE);
124    elm_box_homogeneous_set(bx, EINA_TRUE);
125    elm_box_horizontal_set(bx, sd->horizontal);
126
127    if (sd->horizontal)
128      snprintf(buf, sizeof(buf), "hoversel_horizontal_entry/%s",
129               elm_widget_style_get(obj));
130    else
131      snprintf(buf, sizeof(buf), "hoversel_vertical_entry/%s",
132               elm_widget_style_get(obj));
133
134    EINA_LIST_FOREACH(sd->items, l, item)
135      {
136         bt = elm_button_add(bx);
137         elm_widget_mirrored_automatic_set(bt, EINA_FALSE);
138         elm_widget_mirrored_set(bt, elm_widget_mirrored_get(obj));
139         elm_object_style_set(bt, buf);
140         elm_object_text_set(bt, item->label);
141
142         if (item->icon_file)
143           {
144              ic = elm_icon_add(obj);
145              elm_image_resizable_set(ic, EINA_FALSE, EINA_TRUE);
146              if (item->icon_type == ELM_ICON_FILE)
147                elm_image_file_set(ic, item->icon_file, item->icon_group);
148              else if (item->icon_type == ELM_ICON_STANDARD)
149                elm_icon_standard_set(ic, item->icon_file);
150              elm_object_part_content_set(bt, "icon", ic);
151           }
152
153         evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
154         evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
155         elm_box_pack_end(bx, bt);
156         evas_object_smart_callback_add(bt, "clicked", _on_item_clicked, item);
157         evas_object_show(bt);
158      }
159
160    if (sd->horizontal)
161      elm_object_part_content_set(sd->hover, elm_hover_best_content_location_get
162                                    (sd->hover, ELM_HOVER_AXIS_HORIZONTAL), bx);
163    else
164      elm_object_part_content_set(sd->hover, elm_hover_best_content_location_get
165                                    (sd->hover, ELM_HOVER_AXIS_VERTICAL), bx);
166
167    evas_object_show(sd->hover);
168 }
169
170 static void
171 _on_clicked(void *data,
172             Evas_Object *obj __UNUSED__,
173             void *event_info __UNUSED__)
174 {
175    _activate(data);
176 }
177
178 static void
179 _on_parent_del(void *data,
180                Evas *e __UNUSED__,
181                Evas_Object *obj __UNUSED__,
182                void *event_info __UNUSED__)
183 {
184    elm_hoversel_hover_parent_set(data, NULL);
185 }
186
187 static const char *
188 _item_text_get_hook(const Elm_Object_Item *it,
189                     const char *part)
190 {
191    if (part && strcmp(part, "default")) return NULL;
192    return ((Elm_Hoversel_Item *)it)->label;
193 }
194
195 static Eina_Bool
196 _item_del_pre_hook(Elm_Object_Item *it)
197 {
198    Elm_Hoversel_Item *item = (Elm_Hoversel_Item *)it;
199
200    ELM_HOVERSEL_DATA_GET_OR_RETURN_VAL(WIDGET(item), sd, EINA_FALSE);
201
202    elm_hoversel_hover_end(WIDGET(item));
203    sd->items = eina_list_remove(sd->items, item);
204    eina_stringshare_del(item->label);
205    eina_stringshare_del(item->icon_file);
206    eina_stringshare_del(item->icon_group);
207
208    return EINA_TRUE;
209 }
210
211 static void
212 _elm_hoversel_smart_add(Evas_Object *obj)
213 {
214    EVAS_SMART_DATA_ALLOC(obj, Elm_Hoversel_Smart_Data);
215
216    ELM_WIDGET_CLASS(_elm_hoversel_parent_sc)->base.add(obj);
217
218    elm_widget_mirrored_automatic_set(obj, EINA_FALSE);
219
220    priv->expanded = EINA_FALSE;
221
222    evas_object_smart_callback_add(obj, "clicked", _on_clicked, obj);
223
224    _elm_hoversel_smart_theme(obj);
225 }
226
227 static void
228 _elm_hoversel_smart_del(Evas_Object *obj)
229 {
230    Elm_Hoversel_Item *item;
231
232    ELM_HOVERSEL_DATA_GET(obj, sd);
233
234    EINA_LIST_FREE (sd->items, item)
235      {
236         eina_stringshare_del(item->label);
237         eina_stringshare_del(item->icon_file);
238         eina_stringshare_del(item->icon_group);
239         elm_widget_item_free(item);
240      }
241    elm_hoversel_hover_parent_set(obj, NULL);
242
243    ELM_WIDGET_CLASS(_elm_hoversel_parent_sc)->base.del(obj);
244 }
245
246 static void
247 _elm_hoversel_smart_parent_set(Evas_Object *obj,
248                                Evas_Object *parent)
249 {
250    elm_hoversel_hover_parent_set(obj, parent);
251 }
252
253 static void
254 _elm_hoversel_smart_set_user(Elm_Hoversel_Smart_Class *sc)
255 {
256    ELM_WIDGET_CLASS(sc)->base.add = _elm_hoversel_smart_add;
257    ELM_WIDGET_CLASS(sc)->base.del = _elm_hoversel_smart_del;
258
259    ELM_WIDGET_CLASS(sc)->parent_set = _elm_hoversel_smart_parent_set;
260    ELM_WIDGET_CLASS(sc)->theme = _elm_hoversel_smart_theme;
261    ELM_WIDGET_CLASS(sc)->translate = _elm_hoversel_smart_translate;
262
263    ELM_BUTTON_CLASS(sc)->admits_autorepeat = EINA_FALSE;
264 }
265
266 EAPI const Elm_Hoversel_Smart_Class *
267 elm_hoversel_smart_class_get(void)
268 {
269    static Elm_Hoversel_Smart_Class _sc =
270      ELM_HOVERSEL_SMART_CLASS_INIT_NAME_VERSION(ELM_HOVERSEL_SMART_NAME);
271    static const Elm_Hoversel_Smart_Class *class = NULL;
272    Evas_Smart_Class *esc = (Evas_Smart_Class *)&_sc;
273
274    if (class) return class;
275
276    _elm_hoversel_smart_set(&_sc);
277    esc->callbacks = _smart_callbacks;
278    class = &_sc;
279
280    return class;
281 }
282
283 EAPI Evas_Object *
284 elm_hoversel_add(Evas_Object *parent)
285 {
286    Evas_Object *obj;
287
288    EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
289
290    obj = elm_widget_add(_elm_hoversel_smart_class_new(), parent);
291    if (!obj) return NULL;
292
293    if (!elm_widget_sub_object_add(parent, obj))
294      ERR("could not add %p as sub object of %p", obj, parent);
295
296    return obj;
297 }
298
299 EAPI void
300 elm_hoversel_hover_parent_set(Evas_Object *obj,
301                               Evas_Object *parent)
302 {
303    ELM_HOVERSEL_CHECK(obj);
304    ELM_HOVERSEL_DATA_GET(obj, sd);
305
306    if (sd->hover_parent)
307      evas_object_event_callback_del_full
308        (sd->hover_parent, EVAS_CALLBACK_DEL, _on_parent_del, obj);
309
310    sd->hover_parent = parent;
311    if (sd->hover_parent)
312      evas_object_event_callback_add
313        (sd->hover_parent, EVAS_CALLBACK_DEL, _on_parent_del, obj);
314 }
315
316 EAPI Evas_Object *
317 elm_hoversel_hover_parent_get(const Evas_Object *obj)
318 {
319    ELM_HOVERSEL_CHECK(obj) NULL;
320    ELM_HOVERSEL_DATA_GET(obj, sd);
321
322    return sd->hover_parent;
323 }
324
325 EAPI void
326 elm_hoversel_horizontal_set(Evas_Object *obj,
327                             Eina_Bool horizontal)
328 {
329    ELM_HOVERSEL_CHECK(obj);
330    ELM_HOVERSEL_DATA_GET(obj, sd);
331
332    sd->horizontal = !!horizontal;
333
334    _elm_hoversel_smart_theme(obj);
335 }
336
337 EAPI Eina_Bool
338 elm_hoversel_horizontal_get(const Evas_Object *obj)
339 {
340    ELM_HOVERSEL_CHECK(obj) EINA_FALSE;
341    ELM_HOVERSEL_DATA_GET(obj, sd);
342
343    return sd->horizontal;
344 }
345
346 EAPI void
347 elm_hoversel_hover_begin(Evas_Object *obj)
348 {
349    ELM_HOVERSEL_CHECK(obj);
350    ELM_HOVERSEL_DATA_GET(obj, sd);
351
352    if (sd->hover) return;
353
354    _activate(obj);
355 }
356
357 EAPI void
358 elm_hoversel_hover_end(Evas_Object *obj)
359 {
360    ELM_HOVERSEL_CHECK(obj);
361    ELM_HOVERSEL_DATA_GET(obj, sd);
362
363    if (!sd->hover) return;
364
365    sd->expanded = EINA_FALSE;
366
367    evas_object_del(sd->hover);
368    sd->hover = NULL;
369
370    evas_object_smart_callback_call(obj, SIG_DISMISSED, NULL);
371 }
372
373 EAPI Eina_Bool
374 elm_hoversel_expanded_get(const Evas_Object *obj)
375 {
376    ELM_HOVERSEL_CHECK(obj) EINA_FALSE;
377    ELM_HOVERSEL_DATA_GET(obj, sd);
378
379    return (sd->hover) ? EINA_TRUE : EINA_FALSE;
380 }
381
382 EAPI void
383 elm_hoversel_clear(Evas_Object *obj)
384 {
385    Elm_Object_Item *it;
386    Eina_List *l, *ll;
387
388    ELM_HOVERSEL_CHECK(obj);
389    ELM_HOVERSEL_DATA_GET(obj, sd);
390
391    EINA_LIST_FOREACH_SAFE(sd->items, l, ll, it)
392      {
393         elm_widget_item_del(it);
394      }
395 }
396
397 EAPI const Eina_List *
398 elm_hoversel_items_get(const Evas_Object *obj)
399 {
400    ELM_HOVERSEL_CHECK(obj) NULL;
401    ELM_HOVERSEL_DATA_GET(obj, sd);
402
403    return sd->items;
404 }
405
406 EAPI Elm_Object_Item *
407 elm_hoversel_item_add(Evas_Object *obj,
408                       const char *label,
409                       const char *icon_file,
410                       Elm_Icon_Type icon_type,
411                       Evas_Smart_Cb func,
412                       const void *data)
413 {
414    ELM_HOVERSEL_CHECK(obj) NULL;
415    ELM_HOVERSEL_DATA_GET(obj, sd);
416
417    Elm_Hoversel_Item *item = elm_widget_item_new(obj, Elm_Hoversel_Item);
418    if (!item) return NULL;
419
420    elm_widget_item_del_pre_hook_set(item, _item_del_pre_hook);
421    elm_widget_item_text_get_hook_set(item, _item_text_get_hook);
422
423    item->label = eina_stringshare_add(label);
424    item->icon_file = eina_stringshare_add(icon_file);
425    item->icon_type = icon_type;
426    item->func = func;
427    item->base.data = data;
428
429    sd->items = eina_list_append(sd->items, item);
430
431    return (Elm_Object_Item *)item;
432 }
433
434 EAPI void
435 elm_hoversel_item_icon_set(Elm_Object_Item *it,
436                            const char *icon_file,
437                            const char *icon_group,
438                            Elm_Icon_Type icon_type)
439 {
440    ELM_HOVERSEL_ITEM_CHECK_OR_RETURN(it);
441
442    Elm_Hoversel_Item *item = (Elm_Hoversel_Item *)it;
443
444    eina_stringshare_replace(&item->icon_file, icon_file);
445    eina_stringshare_replace(&item->icon_group, icon_group);
446
447    item->icon_type = icon_type;
448 }
449
450 EAPI void
451 elm_hoversel_item_icon_get(const Elm_Object_Item *it,
452                            const char **icon_file,
453                            const char **icon_group,
454                            Elm_Icon_Type *icon_type)
455 {
456    ELM_HOVERSEL_ITEM_CHECK_OR_RETURN(it);
457
458    Elm_Hoversel_Item *item = (Elm_Hoversel_Item *)it;
459
460    if (icon_file) *icon_file = item->icon_file;
461    if (icon_group) *icon_group = item->icon_group;
462    if (icon_type) *icon_type = item->icon_type;
463 }