tizen 2.3.1 release
[framework/uifw/elementary.git] / 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
219 static void
220 _elm_hoversel_smart_del(Evas_Object *obj)
221 {
222    Elm_Hoversel_Item *item;
223
224    ELM_HOVERSEL_DATA_GET(obj, sd);
225
226    EINA_LIST_FREE (sd->items, item)
227      {
228         eina_stringshare_del(item->label);
229         eina_stringshare_del(item->icon_file);
230         eina_stringshare_del(item->icon_group);
231         elm_widget_item_free(item);
232      }
233    elm_hoversel_hover_parent_set(obj, NULL);
234
235    ELM_WIDGET_CLASS(_elm_hoversel_parent_sc)->base.del(obj);
236 }
237
238 static void
239 _elm_hoversel_smart_parent_set(Evas_Object *obj,
240                                Evas_Object *parent)
241 {
242    elm_hoversel_hover_parent_set(obj, parent);
243 }
244
245 static void
246 _elm_hoversel_smart_set_user(Elm_Hoversel_Smart_Class *sc)
247 {
248    ELM_WIDGET_CLASS(sc)->base.add = _elm_hoversel_smart_add;
249    ELM_WIDGET_CLASS(sc)->base.del = _elm_hoversel_smart_del;
250
251    ELM_WIDGET_CLASS(sc)->parent_set = _elm_hoversel_smart_parent_set;
252    ELM_WIDGET_CLASS(sc)->theme = _elm_hoversel_smart_theme;
253    ELM_WIDGET_CLASS(sc)->translate = _elm_hoversel_smart_translate;
254
255    ELM_BUTTON_CLASS(sc)->admits_autorepeat = EINA_FALSE;
256 }
257
258 EAPI const Elm_Hoversel_Smart_Class *
259 elm_hoversel_smart_class_get(void)
260 {
261    static Elm_Hoversel_Smart_Class _sc =
262      ELM_HOVERSEL_SMART_CLASS_INIT_NAME_VERSION(ELM_HOVERSEL_SMART_NAME);
263    static const Elm_Hoversel_Smart_Class *class = NULL;
264    Evas_Smart_Class *esc = (Evas_Smart_Class *)&_sc;
265
266    if (class) return class;
267
268    _elm_hoversel_smart_set(&_sc);
269    esc->callbacks = _smart_callbacks;
270    class = &_sc;
271
272    return class;
273 }
274
275 EAPI Evas_Object *
276 elm_hoversel_add(Evas_Object *parent)
277 {
278    Evas_Object *obj;
279
280    EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
281
282    obj = elm_widget_add(_elm_hoversel_smart_class_new(), parent);
283    if (!obj) return NULL;
284
285    if (!elm_widget_sub_object_add(parent, obj))
286      ERR("could not add %p as sub object of %p", obj, parent);
287
288    ELM_HOVERSEL_DATA_GET(obj, sd);
289
290    elm_widget_mirrored_automatic_set(obj, EINA_FALSE);
291
292    sd->expanded = EINA_FALSE;
293
294    evas_object_smart_callback_add(obj, "clicked", _on_clicked, obj);
295
296    _elm_hoversel_smart_theme(obj);
297
298    //Tizen Only: This should be removed when eo is applied.
299    ELM_WIDGET_DATA_GET(obj, wsd);
300    wsd->on_create = EINA_FALSE;
301
302    return obj;
303 }
304
305 EAPI void
306 elm_hoversel_hover_parent_set(Evas_Object *obj,
307                               Evas_Object *parent)
308 {
309    ELM_HOVERSEL_CHECK(obj);
310    ELM_HOVERSEL_DATA_GET(obj, sd);
311
312    if (sd->hover_parent)
313      evas_object_event_callback_del_full
314        (sd->hover_parent, EVAS_CALLBACK_DEL, _on_parent_del, obj);
315
316    sd->hover_parent = parent;
317    if (sd->hover_parent)
318      evas_object_event_callback_add
319        (sd->hover_parent, EVAS_CALLBACK_DEL, _on_parent_del, obj);
320 }
321
322 EAPI Evas_Object *
323 elm_hoversel_hover_parent_get(const Evas_Object *obj)
324 {
325    ELM_HOVERSEL_CHECK(obj) NULL;
326    ELM_HOVERSEL_DATA_GET(obj, sd);
327
328    return sd->hover_parent;
329 }
330
331 EAPI void
332 elm_hoversel_horizontal_set(Evas_Object *obj,
333                             Eina_Bool horizontal)
334 {
335    ELM_HOVERSEL_CHECK(obj);
336    ELM_HOVERSEL_DATA_GET(obj, sd);
337
338    sd->horizontal = !!horizontal;
339
340    _elm_hoversel_smart_theme(obj);
341 }
342
343 EAPI Eina_Bool
344 elm_hoversel_horizontal_get(const Evas_Object *obj)
345 {
346    ELM_HOVERSEL_CHECK(obj) EINA_FALSE;
347    ELM_HOVERSEL_DATA_GET(obj, sd);
348
349    return sd->horizontal;
350 }
351
352 EAPI void
353 elm_hoversel_hover_begin(Evas_Object *obj)
354 {
355    ELM_HOVERSEL_CHECK(obj);
356    ELM_HOVERSEL_DATA_GET(obj, sd);
357
358    if (sd->hover) return;
359
360    _activate(obj);
361 }
362
363 EAPI void
364 elm_hoversel_hover_end(Evas_Object *obj)
365 {
366    ELM_HOVERSEL_CHECK(obj);
367    ELM_HOVERSEL_DATA_GET(obj, sd);
368
369    if (!sd->hover) return;
370
371    sd->expanded = EINA_FALSE;
372
373    evas_object_del(sd->hover);
374    sd->hover = NULL;
375
376    evas_object_smart_callback_call(obj, SIG_DISMISSED, NULL);
377 }
378
379 EAPI Eina_Bool
380 elm_hoversel_expanded_get(const Evas_Object *obj)
381 {
382    ELM_HOVERSEL_CHECK(obj) EINA_FALSE;
383    ELM_HOVERSEL_DATA_GET(obj, sd);
384
385    return (sd->hover) ? EINA_TRUE : EINA_FALSE;
386 }
387
388 EAPI void
389 elm_hoversel_clear(Evas_Object *obj)
390 {
391    Elm_Object_Item *it;
392    Eina_List *l, *ll;
393
394    ELM_HOVERSEL_CHECK(obj);
395    ELM_HOVERSEL_DATA_GET(obj, sd);
396
397    EINA_LIST_FOREACH_SAFE(sd->items, l, ll, it)
398      {
399         elm_widget_item_del(it);
400      }
401 }
402
403 EAPI const Eina_List *
404 elm_hoversel_items_get(const Evas_Object *obj)
405 {
406    ELM_HOVERSEL_CHECK(obj) NULL;
407    ELM_HOVERSEL_DATA_GET(obj, sd);
408
409    return sd->items;
410 }
411
412 EAPI Elm_Object_Item *
413 elm_hoversel_item_add(Evas_Object *obj,
414                       const char *label,
415                       const char *icon_file,
416                       Elm_Icon_Type icon_type,
417                       Evas_Smart_Cb func,
418                       const void *data)
419 {
420    ELM_HOVERSEL_CHECK(obj) NULL;
421    ELM_HOVERSEL_DATA_GET(obj, sd);
422
423    Elm_Hoversel_Item *item = elm_widget_item_new(obj, Elm_Hoversel_Item);
424    if (!item) return NULL;
425
426    elm_widget_item_del_pre_hook_set(item, _item_del_pre_hook);
427    elm_widget_item_text_get_hook_set(item, _item_text_get_hook);
428
429    item->label = eina_stringshare_add(label);
430    item->icon_file = eina_stringshare_add(icon_file);
431    item->icon_type = icon_type;
432    item->func = func;
433    item->base.data = data;
434
435    sd->items = eina_list_append(sd->items, item);
436
437    return (Elm_Object_Item *)item;
438 }
439
440 EAPI void
441 elm_hoversel_item_icon_set(Elm_Object_Item *it,
442                            const char *icon_file,
443                            const char *icon_group,
444                            Elm_Icon_Type icon_type)
445 {
446    ELM_HOVERSEL_ITEM_CHECK_OR_RETURN(it);
447
448    Elm_Hoversel_Item *item = (Elm_Hoversel_Item *)it;
449
450    eina_stringshare_replace(&item->icon_file, icon_file);
451    eina_stringshare_replace(&item->icon_group, icon_group);
452
453    item->icon_type = icon_type;
454 }
455
456 EAPI void
457 elm_hoversel_item_icon_get(const Elm_Object_Item *it,
458                            const char **icon_file,
459                            const char **icon_group,
460                            Elm_Icon_Type *icon_type)
461 {
462    ELM_HOVERSEL_ITEM_CHECK_OR_RETURN(it);
463
464    Elm_Hoversel_Item *item = (Elm_Hoversel_Item *)it;
465
466    if (icon_file) *icon_file = item->icon_file;
467    if (icon_group) *icon_group = item->icon_group;
468    if (icon_type) *icon_type = item->icon_type;
469 }