1e5431031f3c61beae23c4462a0161ade4b1127a
[framework/uifw/elementary.git] / src / lib / elm_stackedicon.c
1 #include <Elementary.h>
2 #include "elm_priv.h"
3
4
5 /**
6  * @defgroup Stackedicon Stackedicon
7  * @ingroup Elementary
8  *
9  * This is a Stackedicon.
10  */
11
12
13 #define MAX_ITEM_NUM      (9)
14 #define MAX_MOVE_INTERVAL   (0.2)
15 #define ELM_MAX(v1, v2)       (((v1) > (v2)) ? (v1) : (v2))
16 #define ROT_RIGHT         (5)
17 #define ROT_LEFT         (-5)
18 #define MAX_SHOWN_ITEM      (3)
19
20 struct _Stackedicon_Item
21 {
22    Evas_Object *parent;
23    Evas_Object *ly;
24    Evas_Object *ic;
25    Evas_Object *pad;
26    const char *path;
27    int index;
28    Evas_Coord x, y, w, h;
29    Evas_Coord mw, mh;
30    Eina_Bool exist : 1;
31 };
32
33 typedef struct _Widget_Data Widget_Data;
34 struct _Widget_Data
35 {
36    Evas_Object *base;
37    int interval_x, interval_y;
38    unsigned int time;
39    Ecore_Animator *animator;
40    Eina_List *list;
41    Evas_Coord x, y, w, h;
42    Eina_Bool visible: 1;
43
44    /*  fake img */
45    Evas_Object *fake_img;
46    int r, g, b, a;
47    int mdx, mdy, mmx, mmy;
48    Eina_Bool move_start: 1;
49    Eina_Bool on_update;
50 };
51
52 static const char *widtype = NULL;
53 static void _del_hook(Evas_Object *obj);
54 static void _theme_hook(Evas_Object *obj);
55 static void _sizing_eval(Evas_Object *obj);
56 static void _del_image(void *data);
57 static void _del_all_image(void *data);
58 static unsigned int _current_time_get(void);
59 static void _icon_move_cb(void *data, Evas *e, Evas_Object *obj, void *event_info);
60 static void _icon_move_to_zero(Evas_Object *obj);
61 static Eina_Bool _icon_move_to_zero_cb(void *data);
62 static void _icon_move_map(void *data, int interval_x, int interval_y);
63 static void _icon_map_pos(Evas_Object *obj, int index, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h);
64 static void _calc_item_size(int w, int h, int iw, int ih, int *res_w, int *res_h);
65 static void _add_image(Evas_Object *obj, void *data);
66 static void _fake_img_mouse_down_cb(void *data, Evas *e, Evas_Object *obj, void *event_info);
67 static void _fake_img_mouse_move_cb(void *data, Evas *e, Evas_Object *obj, void *event_info);
68 static void _fake_img_mouse_up_cb(void *data, Evas *e, Evas_Object *obj, void *event_info);
69 static void _add_image_to_buffer(Evas_Object *obj, Evas* e, void *data);
70 static Evas_Object * _create_fake_image(Evas_Object *obj);
71 static void _show_all_image(Evas_Object *obj);
72 static void _hide_all_image(Evas_Object *obj);
73 static void _hide_hidden_image(Evas_Object *obj);
74 static void _update_stackedicon(Evas_Object *obj);
75 static void _resize_cb(void *data, Evas *e, Evas_Object *obj, void *event_info);
76 static void _move_cb(void *data, Evas *e, Evas_Object *obj, void *event_info);
77 static void _show_cb(void *data, Evas * e, Evas_Object * obj, void *event_info);
78 static void _hide_cb(void *data, Evas * e, Evas_Object * obj, void *event_info);
79 static void _event_init(Evas_Object *obj);
80
81 static void
82 _del_hook(Evas_Object *obj)
83 {
84    Widget_Data *wd = elm_widget_data_get(obj);
85    Eina_List *l;
86    Elm_Stackedicon_Item *it;
87    if (!wd) return;
88
89    if (wd->animator)
90      {
91         ecore_animator_del(wd->animator);
92         wd->animator = NULL;
93      }
94
95    _del_all_image(wd);
96
97    if (wd->list)
98      {
99         EINA_LIST_FOREACH(wd->list, l, it)
100            if (it) free(it);
101         eina_list_free(wd->list);
102         wd->list = NULL;
103      }
104 }
105
106 static void
107 _theme_hook(Evas_Object *obj)
108 {
109    Widget_Data *wd = elm_widget_data_get(obj);
110    Eina_List *l;
111    Elm_Stackedicon_Item *it;
112    if (!wd) return;
113
114    _elm_theme_object_set(obj, wd->base, "stackedicon", "base", elm_widget_style_get(obj));
115    if (wd->fake_img) edje_object_part_swallow(wd->base, "elm.bg.swallow", wd->fake_img);
116    edje_object_scale_set(wd->base, elm_widget_scale_get(obj) * _elm_config->scale);
117
118    EINA_LIST_FOREACH(wd->list, l, it)
119      {
120         if (it->ly)   _elm_theme_object_set(obj, it->ly, "stackedicon", "icon", elm_widget_style_get(obj));
121         if (it->ic)   edje_object_part_swallow(it->ly, "contents", it->ic);
122         if (it->pad)   edje_object_part_swallow(it->ly, "shadow", it->pad);
123         edje_object_scale_set(it->ly, elm_widget_scale_get(obj) * _elm_config->scale);
124      }
125    _update_stackedicon(obj);
126    _sizing_eval(obj);
127 }
128
129 static void
130 _sizing_eval(Evas_Object *obj)
131 {
132    Widget_Data *wd = elm_widget_data_get(obj);
133    Evas_Coord minw = -1, minh = -1;
134    Evas_Coord w, h;
135    if (!wd) return;
136
137    edje_object_size_min_restricted_calc(wd->base, &minw, &minh, minw, minh);
138    evas_object_size_hint_min_get(obj, &w, &h);
139    if (w > minw) minw = w;
140    if (h > minh) minh = h;
141    evas_object_size_hint_min_set(obj, minw, minh);
142 }
143
144 static void
145 _del_image(void *data)
146 {
147    Elm_Stackedicon_Item *it = (Elm_Stackedicon_Item *)data;
148
149    if (it->ly)
150      {
151         evas_object_del(it->ly);
152         evas_object_del(it->ic);
153         evas_object_del(it->pad);
154         it->ly = NULL;
155         it->ic = NULL;
156         it->pad = NULL;
157         it->exist = EINA_FALSE;
158      }
159 }
160
161 static void
162 _del_all_image(void *data)
163 {
164    Widget_Data *wd = (Widget_Data *)data;
165    Eina_List *l;
166    Elm_Stackedicon_Item *it = NULL;
167    if (!wd) return;
168
169    EINA_LIST_FOREACH(wd->list, l, it)
170       if (it && it->exist) _del_image(it);
171 }
172
173 static void
174 _icon_move_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
175 {
176    Elm_Stackedicon_Item *it = data;
177    if (!it)   return;
178    Widget_Data *wd = elm_widget_data_get(it->parent);
179    if (!wd) return;
180
181    Evas_Coord x, y;
182
183    if (it->exist && it->ly)
184      {
185         evas_object_geometry_get(obj, &x, &y, NULL, NULL);
186         _icon_map_pos(it->ly, it->index, x, y, it->w, it->h);
187      }
188 }
189
190 static void
191 _fake_img_mouse_down_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
192 {
193    Widget_Data *wd = elm_widget_data_get(data);
194    Evas_Event_Mouse_Down *ev = event_info;
195    Eina_List *l;
196    Elm_Stackedicon_Item *it = NULL;
197    if (!wd) return;
198
199    wd->mdx = ev->output.x;
200    wd->mdy = ev->output.y;
201
202    it = NULL;
203    EINA_LIST_REVERSE_FOREACH(wd->list, l, it)
204      {
205         if (it)
206           {
207              if (!it->exist) _add_image(data, it);
208              evas_object_move(it->ly, wd->x + wd->w/2 - it->mw/2, wd->y + wd->h/2 - it->mh/2);
209              if (wd->visible) evas_object_show(it->ly);
210           }
211      }
212
213    EINA_LIST_REVERSE_FOREACH(wd->list, l, it)
214       if (it && it->exist) evas_object_raise(it->ly);
215
216    evas_object_color_set(wd->fake_img, 0, 0, 0, 0);
217    wd->move_start = TRUE;
218 }
219
220 static void
221 _fake_img_mouse_move_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
222 {
223    Widget_Data *wd = elm_widget_data_get(data);
224    Evas_Event_Mouse_Move *ev = event_info;
225    if (!wd || !ev->buttons) return;
226
227    if (wd->move_start == TRUE)
228      {
229         evas_object_smart_callback_call(data, "drag,start", NULL);
230         _show_all_image(data);
231         wd->move_start = FALSE;
232      }
233
234    wd->mmx = ev->cur.output.x;
235    wd->mmy = ev->cur.output.y;
236
237    wd->interval_x = wd->mmx - wd->mdx;
238    wd->interval_y = wd->mmy - wd->mdy;
239
240    _icon_move_map(wd, wd->x + wd->interval_x, wd->y +  wd->interval_y);
241 }
242
243 static void
244 _fake_img_mouse_up_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
245 {
246    Widget_Data *wd = elm_widget_data_get(data);
247    double interval = 0.0;
248    if (!wd) return;
249
250    interval = sqrt(wd->interval_x*wd->interval_x + wd->interval_y*wd->interval_y);
251
252    if (((double)(interval/wd->h) > MAX_MOVE_INTERVAL))
253      {
254         wd->interval_x = 0;
255         wd->interval_y = 0;
256
257         _icon_move_map(wd, wd->x, wd->y);
258         _hide_hidden_image(data);
259         evas_object_smart_callback_call(data, "expanded", NULL);
260         evas_object_smart_callback_call(data, "drag,stop", NULL);
261      }
262    else
263      {
264         wd->mdx = 0;
265         wd->mdy = 0;
266         wd->mmx = 0;
267         wd->mmx = 0;
268
269         if (wd->animator)
270           {
271              ecore_animator_del(wd->animator);
272              wd->animator = NULL;
273           }
274         wd->time = _current_time_get();
275         wd->animator= ecore_animator_add(_icon_move_to_zero_cb, data);
276      }
277 }
278
279 static unsigned int
280 _current_time_get(void)
281 {
282    struct timeval timev;
283    gettimeofday(&timev, NULL);
284    return ((timev.tv_sec * 1000) + ((timev.tv_usec) / 1000));
285 }
286
287 static void
288 _icon_move_to_zero(Evas_Object *obj)
289 {
290    Widget_Data *wd = elm_widget_data_get(obj);
291    double t;
292    int x, y;
293    if (!wd) return;
294
295    t = ELM_MAX(0.0, _current_time_get() - wd->time) / 100;
296
297    if (t <= 1.0)
298      {
299         x = (1 * sin((t / 2.0) * (M_PI / 2)) * wd->interval_x);
300         y = (1 * sin((t / 2.0) * (M_PI / 2)) * wd->interval_y);
301      }
302    else
303      {
304         x = wd->interval_x;
305         y = wd->interval_y;
306      }
307
308    if ( y == wd->interval_y)
309      {
310         ecore_animator_del(wd->animator);
311         wd->animator = NULL;
312         wd->interval_x = 0;
313         wd->interval_y = 0;
314         _icon_move_map(wd, wd->x, wd->y);
315         _hide_hidden_image(obj);
316         evas_object_smart_callback_call(obj, "clicked", NULL);
317         evas_object_smart_callback_call(obj, "drag,stop", NULL);
318      }
319    else
320      {
321         _icon_move_map(wd, wd->x + wd->interval_x - x, wd->y + wd->interval_y - y);
322      }
323 }
324
325 static Eina_Bool
326 _icon_move_to_zero_cb(void *data)
327 {
328     Evas_Object *obj = (Evas_Object *)data;
329    _icon_move_to_zero(obj);
330
331    return EXIT_FAILURE;
332 }
333
334 static void
335 _icon_move_map(void *data, int interval_x, int interval_y)
336 {
337    Widget_Data *wd = (Widget_Data *)data;
338    int i = 0;
339    int num;
340    int x = 0, y = 0;
341    if (!wd) return;
342    num = eina_list_count(wd->list);
343
344    for (i =0; i  < num; i++)
345      {
346         Elm_Stackedicon_Item *it = NULL;
347         it = (Elm_Stackedicon_Item *)eina_list_nth(wd->list, i);
348
349         if (it != NULL)
350           {
351              x = wd->x  + wd->w/2 - it->mw/2 + ((interval_x - wd->x)/num)*(num -i);
352              y = wd->y + wd->h/2 - it->mh/2 + ((interval_y - wd->y)/num)*(num -i);
353              evas_object_move(it->ly, x, y);
354           }
355      }
356 }
357
358 static void
359 _icon_map_pos(Evas_Object *obj, int index, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h)
360 {
361    Evas_Map *m;
362    int degree = 0;
363
364    if ((index % 3) == 1)
365       degree = ROT_RIGHT;
366    else if ((index % 3) == 2)
367       degree = ROT_LEFT;
368
369    m = evas_map_new(4);
370    evas_map_util_points_populate_from_geometry(m, x, y, w, h, 0);
371    evas_map_util_3d_rotate(m, 0, 0, degree, x + w/2, y + h/2, 0);
372    evas_map_util_3d_perspective(m, x + w/2, y + h/2, 0, 10000);
373    evas_map_smooth_set(m, 1);
374    evas_map_alpha_set(m, 1);
375    evas_object_map_set(obj, m);
376    evas_object_map_enable_set(obj, 1);
377    evas_map_free(m);
378 }
379
380 static void
381 _calc_item_size(int w, int h, int iw, int ih, int *res_w, int *res_h)
382 {
383    if (iw>ih)
384      {
385         if (w*ih/iw > h)
386           {
387              *res_w = h*iw/ih;
388              *res_h = h;
389           }
390         else
391           {
392              *res_w = w;
393              *res_h = w*ih/iw;
394           }
395      }
396    else
397      {
398         if (h*iw/ih > w)
399           {
400              *res_w = w;
401              *res_h = w*h/(h*iw/ih);
402           }
403         else
404           {
405              *res_w = h*iw/ih;
406              *res_h = h;
407           }
408      }
409 }
410
411 static void
412 _add_image(Evas_Object *obj, void *data)
413 {
414    Widget_Data *wd = elm_widget_data_get(obj);
415    Elm_Stackedicon_Item *it = (Elm_Stackedicon_Item *)data;
416    Evas_Object *ly = NULL;
417    Evas_Object *ic = NULL;
418    Evas_Object *pad = NULL;
419    int iw, ih;
420    if (!wd || !it) return;
421
422    ly = edje_object_add(evas_object_evas_get(obj));
423    if (!ly) return;
424    _elm_theme_object_set(obj, ly, "stackedicon", "icon", elm_widget_style_get(obj));
425    evas_object_size_hint_weight_set(ly, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
426    elm_widget_sub_object_add(obj, ly);
427
428    ic = evas_object_image_add(evas_object_evas_get(obj));
429    if (!ic) return;
430    evas_object_image_load_size_set(ic, wd->w/2, wd->h/2);
431    evas_object_image_file_set(ic, it->path, NULL);
432    evas_object_image_size_get(ic, &iw, &ih);
433    if (!iw || !ih) return;
434
435    _calc_item_size(wd->w - 2, wd->h - 2, iw, ih, &it->w, &it->h);
436
437    evas_object_image_fill_set(ic, 0, 0, it->w, it->h);
438    evas_object_size_hint_min_set(ly, it->w, it->h);
439    evas_object_resize(ly, it->w, it->h);
440
441    evas_object_image_filled_set(ic, 1);
442    edje_object_part_swallow(ly, "contents", ic);
443
444    pad = evas_object_rectangle_add(evas_object_evas_get(obj));
445    if (!pad) return;
446    evas_object_size_hint_align_set(pad, EVAS_HINT_FILL, EVAS_HINT_FILL);
447    evas_object_color_set(pad, 0, 0, 0, it->index*25);
448    edje_object_part_swallow(ly, "shadow", pad);
449
450    evas_object_event_callback_add(ly, EVAS_CALLBACK_MOVE, _icon_move_cb, it);
451
452    it->mw = it->w;
453    it->mh = it->h;
454    it->ly = ly;
455    it->ic = ic;
456    it->pad = pad;
457    it->exist = EINA_TRUE;
458 }
459
460 static void
461 _add_image_to_buffer(Evas_Object *obj, Evas* e, void *data)
462 {
463    Widget_Data *wd = elm_widget_data_get(obj);
464    Elm_Stackedicon_Item *it = (Elm_Stackedicon_Item *)data;
465    Evas_Object *ly = NULL;
466    Evas_Object *ic = NULL;
467    int iw, ih, res_w, res_h;
468    if (!wd || !it) return;
469
470    // FIXME: add an opaque rectangle because of alpha bug of evas_map.
471    Evas_Object* rect = evas_object_rectangle_add( e );
472    if (!rect) return;
473    evas_object_resize( rect, 1, 1);
474    evas_object_move(rect, wd->w/2, wd->h/2);
475    evas_object_color_set( rect, 0, 0, 0, 255 );
476    evas_object_show( rect );
477
478    ly = edje_object_add(e);
479    if (!ly) return;
480    _elm_theme_object_set(obj, ly, "stackedicon", "icon", elm_widget_style_get(obj));
481    evas_object_size_hint_weight_set(ly, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
482
483    ic = evas_object_image_add(e);
484    if (!ic) return;
485    evas_object_image_alpha_set(ic, EINA_TRUE);
486    evas_object_image_load_size_set(ic, wd->w/2, wd->h/2);
487    evas_object_image_file_set(ic, it->path, NULL);
488    evas_object_image_size_get(ic, &iw, &ih);
489    if (!iw || !ih) return;
490
491    _calc_item_size(wd->w - 2, wd->h - 2, iw, ih, &res_w, &res_h);
492
493    evas_object_image_fill_set(ic, 0, 0, res_w, res_h);
494    evas_object_image_filled_set(ic, 1);
495    edje_object_part_swallow(ly, "contents", ic);
496
497    evas_object_resize(ly, res_w, res_h);
498    evas_object_move(ly, (wd->w - res_w)/2, (wd->h - res_h)/2);
499    evas_object_show(ly);
500
501    _icon_map_pos(ly, it->index, (wd->w - res_w)/2, (wd->h - res_h)/2, res_w, res_h);
502 }
503
504 static Evas_Object *
505 _create_fake_image(Evas_Object *obj)
506 {
507    Widget_Data *wd = elm_widget_data_get(obj);
508    Evas_Object *eo = NULL;
509    Eina_List *l = NULL;
510    Elm_Stackedicon_Item *it = NULL;
511    if (!wd) return NULL;
512
513    // create fake_img
514    eo = evas_object_image_add(evas_object_evas_get(obj));
515    if (!eo) return NULL;
516    elm_widget_sub_object_add(obj, eo);
517    evas_object_image_alpha_set(eo,EINA_TRUE);
518    evas_object_image_data_set(eo, NULL);
519    evas_object_image_size_set(eo, wd->w, wd->h);
520    evas_object_image_fill_set(eo, 0, 0, wd->w, wd->h);
521    edje_object_part_swallow(wd->base, "elm.bg.swallow", eo);
522
523    // create ecore_evas (buffer)
524    Ecore_Evas* ee = ecore_evas_buffer_new( wd->w, wd->h );
525    Evas* e = ecore_evas_get( ee );
526
527    // add shown icons
528    EINA_LIST_REVERSE_FOREACH(wd->list, l, it)
529      {
530         if (it)
531           {
532              if (it->index >= MAX_SHOWN_ITEM) continue;
533              _add_image_to_buffer(obj, e, it);
534           }
535      }
536    ecore_evas_show( ee );
537
538
539    // copy buffer to data(mem)
540    unsigned char* data = (unsigned char*) calloc( 1, sizeof( unsigned char ) * 4 * wd->w * wd->h );
541    memcpy( data, (unsigned char*) ecore_evas_buffer_pixels_get( ee ), sizeof( unsigned char ) * 4 * wd->w * wd->h );
542    ecore_evas_free( ee );
543
544    // copy data to fake_img
545    evas_object_image_data_copy_set(eo, data);
546    evas_object_image_data_update_add(eo, 0, 0, wd->w, wd->h);
547    evas_object_resize(eo, wd->w, wd->h);
548
549    evas_object_color_get(eo, &wd->r, &wd->g, &wd->b, &wd->a);
550
551    // add mouse events callback
552    evas_object_event_callback_add(eo, EVAS_CALLBACK_MOUSE_DOWN, _fake_img_mouse_down_cb, obj);
553    evas_object_event_callback_add(eo, EVAS_CALLBACK_MOUSE_MOVE, _fake_img_mouse_move_cb, obj);
554    evas_object_event_callback_add(eo, EVAS_CALLBACK_MOUSE_UP, _fake_img_mouse_up_cb, obj);
555
556    return eo;
557 }
558
559 static void
560 _update_stackedicon(Evas_Object *obj)
561 {
562    Widget_Data *wd = elm_widget_data_get(obj);
563    if (!wd || ((wd->w == 1) && (wd->h == 1))) return;
564
565    if (!wd->fake_img)
566      {
567         wd->fake_img = _create_fake_image(obj);
568      }
569    else if (wd->on_update)
570      {
571         wd->on_update = FALSE;
572         elm_widget_sub_object_del(obj, wd->fake_img);
573         edje_object_part_unswallow(wd->base, wd->fake_img);
574         evas_object_del(wd->fake_img);
575         wd->fake_img = NULL;
576         wd->fake_img = _create_fake_image(obj);
577      }
578 }
579
580 static void _show_all_image(Evas_Object *obj)
581 {
582    Widget_Data *wd = elm_widget_data_get(obj);
583    if (!wd) return;
584    int i = 0;
585
586    for (i =0; i < eina_list_count (wd->list); i++)
587      {
588         Elm_Stackedicon_Item *it = NULL;
589         it = (Elm_Stackedicon_Item *)eina_list_nth(wd->list, i);
590
591         if (it != NULL)
592           {
593              if (it->exist == EINA_TRUE)
594                {
595                   evas_object_show(it->ly);
596                }
597           }
598      }
599 }
600
601 static void _hide_all_image(Evas_Object *obj)
602 {
603    Widget_Data *wd = elm_widget_data_get(obj);
604    if (!wd) return;
605    int i = 0;
606
607    for (i =0; i < eina_list_count (wd->list); i++)
608      {
609         Elm_Stackedicon_Item *it = NULL;
610         it = (Elm_Stackedicon_Item *)eina_list_nth(wd->list, i);
611
612         if (it != NULL)
613           {
614              if (it->exist == EINA_TRUE)
615                {
616                   evas_object_hide(it->ly);
617                }
618           }
619      }
620 }
621
622 static void _hide_hidden_image(Evas_Object *obj)
623 {
624    Widget_Data *wd = elm_widget_data_get(obj);
625    Eina_List *l;
626    Elm_Stackedicon_Item *it = NULL;
627    if (!wd) return;
628
629    EINA_LIST_REVERSE_FOREACH(wd->list, l, it)
630      {
631         if (it->ly) evas_object_hide(it->ly);
632      }
633    evas_object_color_set(wd->fake_img, wd->r, wd->g, wd->b, wd->a);
634 }
635
636 static void
637 _resize_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
638 {
639    Widget_Data *wd = elm_widget_data_get(data);
640    Evas_Coord w, h;
641    if (!wd) return;
642
643    evas_object_geometry_get(obj, NULL, NULL, &w, &h);
644    wd->w = w;
645    wd->h = h;
646
647    _update_stackedicon(data);
648 }
649
650 static void
651 _move_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
652 {
653    Widget_Data *wd = elm_widget_data_get(data);
654    Evas_Coord x, y;
655    if (!wd) return;
656
657    evas_object_geometry_get(obj, &x, &y, NULL, NULL);
658    wd->x = x;
659    wd->y = y;
660
661    _update_stackedicon(data);
662 }
663
664 static void
665 _show_cb(void *data, Evas * e, Evas_Object * obj, void *event_info)
666 {
667    Widget_Data *wd = elm_widget_data_get(data);
668    if (!wd) return;
669
670    wd->visible = EINA_TRUE;
671    _update_stackedicon(data);
672 }
673
674 static void
675 _hide_cb(void *data, Evas * e, Evas_Object * obj, void *event_info)
676 {
677    Widget_Data *wd = elm_widget_data_get(data);
678    if (!wd) return;
679
680    wd->visible = EINA_FALSE;
681    _hide_all_image(data);
682 }
683
684 static void
685 _event_init(Evas_Object *obj)
686 {
687    Widget_Data *wd = elm_widget_data_get(obj);
688    if (!wd) return;
689
690    evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE, _resize_cb, obj);
691    evas_object_event_callback_add(obj, EVAS_CALLBACK_MOVE, _move_cb, obj);
692    evas_object_event_callback_add(obj, EVAS_CALLBACK_SHOW, _show_cb, obj);
693    evas_object_event_callback_add(obj, EVAS_CALLBACK_HIDE, _hide_cb, obj);
694 }
695
696 /**
697  * Add a new stackedicon to the parent
698  *
699  * @param parent The parent object
700  * @return The new object or NULL if it cannot be created
701  *
702  * @ingroup Stackedicon
703  */
704 EAPI Evas_Object *
705 elm_stackedicon_add(Evas_Object *parent)
706 {
707    Evas_Object *obj;
708    Evas *e;
709    Widget_Data *wd;
710
711    wd = ELM_NEW(Widget_Data);
712    e = evas_object_evas_get(parent);
713    obj = elm_widget_add(e);
714    ELM_SET_WIDTYPE(widtype, "stackedicon");
715    elm_widget_type_set(obj, "stackedicon");
716    elm_widget_sub_object_add(parent, obj);
717    elm_widget_data_set(obj, wd);
718
719    elm_widget_del_hook_set(obj, _del_hook);
720    elm_widget_theme_hook_set(obj, _theme_hook);
721
722    wd->base = edje_object_add(e);
723    _elm_theme_object_set(obj, wd->base, "stackedicon", "base", "default");
724    elm_widget_resize_object_set(obj, wd->base);
725
726    wd->w = 1;
727    wd->h = 1;
728
729    _event_init(obj);
730    _sizing_eval(obj);
731
732    return obj;
733 }
734
735 /**
736  * This appends a path to the stackedicon
737  *
738  * @param    obj   The stackedicon object
739  * @param    path   The image full path
740  * @return   The new item or NULL if it cannot be created
741  *
742  * @ingroup Stackedicon
743  */
744 EAPI Elm_Stackedicon_Item *elm_stackedicon_item_append(Evas_Object *obj, const char *path)
745 {
746    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
747    Widget_Data *wd = elm_widget_data_get(obj);
748    Elm_Stackedicon_Item *it;
749    if (!wd) return NULL;
750    if (eina_list_count(wd->list) >= MAX_ITEM_NUM) return NULL;
751
752    it = (Elm_Stackedicon_Item *)calloc(1, sizeof(Elm_Stackedicon_Item));
753    it->path = eina_stringshare_add(path);
754    it->parent = obj;
755    it->ly = NULL;
756    it->ic = NULL;
757    it->pad = NULL;
758    it->index = eina_list_count(wd->list);
759    it->exist = EINA_FALSE;
760    wd->list = eina_list_append(wd->list, it);
761
762    if (it->index < MAX_SHOWN_ITEM)
763      {
764         wd->on_update = TRUE;
765         _update_stackedicon(obj);
766      }
767
768    return it;
769 }
770
771 /**
772  * This prepends a path to the stackedicon
773  *
774  * @param    obj   The stackedicon object
775  * @param    path   The image full path
776  * @return   The new item or NULL if it cannot be created
777  *
778  * @ingroup Stackedicon
779  */
780 EAPI Elm_Stackedicon_Item *elm_stackedicon_item_prepend(Evas_Object *obj, const char *path)
781 {
782    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
783    Widget_Data *wd = elm_widget_data_get(obj);
784    Elm_Stackedicon_Item *it;
785    if (!wd) return NULL;
786    if (eina_list_count(wd->list) >= MAX_ITEM_NUM) return NULL;
787
788    it = (Elm_Stackedicon_Item *)calloc(1, sizeof(Elm_Stackedicon_Item));
789    it->path = eina_stringshare_add(path);
790    it->parent = obj;
791    it->ly = NULL;
792    it->ic = NULL;
793    it->pad = NULL;
794    it->index = eina_list_count(wd->list);
795    it->exist = EINA_FALSE;
796    wd->list = eina_list_prepend(wd->list, it);
797
798    if (it->index < MAX_SHOWN_ITEM)
799      {
800         wd->on_update = TRUE;
801         _update_stackedicon(obj);
802      }
803
804    return it;
805 }
806
807 /**
808  * This delete a path at the stackedicon
809  *
810  * @param    Elm_Stackedicon_Item   The delete item
811  *
812  * @ingroup Stackedicon
813  */
814 EAPI void elm_stackedicon_item_del(Elm_Stackedicon_Item *it)
815 {
816    if (!it)return;
817    ELM_CHECK_WIDTYPE(it->parent, widtype);
818    Evas_Object *obj = it->parent;
819    Widget_Data *wd = elm_widget_data_get(obj);
820    Eina_List *l;
821    Elm_Stackedicon_Item *_it = NULL;
822    int i = 0;
823    if (!wd) return;
824
825    if (it->index < MAX_SHOWN_ITEM) wd->on_update = TRUE;
826
827    if (it->exist == EINA_TRUE) _del_image(it);
828    wd->list = eina_list_remove(wd->list, it);
829    free(it);
830
831    EINA_LIST_FOREACH(wd->list, l, _it)
832       if (_it->ly) _it->index = i++;
833
834    _update_stackedicon(obj);
835 }
836
837 /**
838  * Get item list from the stackedicon
839  *
840  * @param    obj   The stackedicon object
841  * @return   The item list or NULL if it cannot be created
842  *
843  * @ingroup Stackedicon
844  */
845 EAPI Eina_List *elm_stackedicon_item_list_get(Evas_Object *obj)
846 {
847    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
848    Widget_Data *wd = elm_widget_data_get(obj);
849    if (!wd) return NULL;
850    return wd->list;
851 }
852