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