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