elementary: use new Ethumb facility.
[framework/uifw/elementary.git] / src / lib / elm_icon.c
1 #include <Elementary.h>
2 #include "elm_priv.h"
3 #include "els_icon.h"
4
5 #ifdef ELM_EFREET
6 #define NON_EXISTING (void *)-1
7 static const char *icon_theme = NULL;
8 #endif
9
10 typedef struct _Widget_Data Widget_Data;
11
12 struct _Widget_Data
13 {
14    Evas_Object *img;
15    const char *stdicon;
16    Elm_Icon_Lookup_Order lookup_order;
17
18 #ifdef HAVE_ELEMENTARY_ETHUMB
19    struct {
20       struct {
21          const char *path;
22          const char *key;
23       } file, thumb;
24
25       Ecore_Event_Handler *eeh;
26
27       Ethumb_Thumb_Format format;
28
29       Ethumb_Client_Async *request;
30
31       Eina_Bool retry : 1;
32    } thumb;
33 #endif
34
35 #ifdef ELM_EFREET
36    struct {
37         int requested_size;
38         Eina_Bool use : 1;
39    } freedesktop;
40 #endif
41    int in_eval;
42    Eina_Bool scale_up : 1;
43    Eina_Bool scale_down : 1;
44    Eina_Bool smooth : 1;
45    Eina_Bool fill_outside : 1;
46    Eina_Bool no_scale : 1;
47
48    /* for animation feature */
49    Ecore_Timer *timer;
50    int frame_count;
51    int cur_frame;
52    double duration;
53    Eina_Bool anim : 1;
54    Eina_Bool play : 1;
55 };
56
57 #ifdef HAVE_ELEMENTARY_ETHUMB
58 static Eina_List *_elm_icon_retry = NULL;
59 static int _icon_pending_request = 0;
60 #endif
61
62 static const char *widtype = NULL;
63 static void _del_hook(Evas_Object *obj);
64 static void _theme_hook(Evas_Object *obj);
65 static void _sizing_eval(Evas_Object *obj);
66 static void _mouse_up(void *data, Evas *e, Evas_Object *obj, void *event_info);
67
68 static Eina_Bool _icon_standard_set(Widget_Data *wd, Evas_Object *obj, const char *name);
69 static Eina_Bool _icon_freedesktop_set(Widget_Data *wd, Evas_Object *obj, const char *name, int size);
70
71 static const char SIG_CLICKED[] = "clicked";
72
73 static const Evas_Smart_Cb_Description _signals[] = {
74    {SIG_CLICKED, ""},
75    {NULL, NULL}
76 };
77
78
79 //FIXME: move this code to ecore
80 #ifdef _WIN32
81 static Eina_Bool
82 _path_is_absolute(const char *path)
83 {
84    //TODO: Check if this works with all absolute paths in windows
85    return ((isalpha (*path)) && (*(path + 1) == ':') && ((*(path + 2) == '\\') || (*(path + 2) == '/')));
86 }
87 #else
88 static Eina_Bool
89 _path_is_absolute(const char *path)
90 {
91    return  (*path == '/');
92 }
93 #endif
94
95 static inline int
96 _icon_size_min_get(Evas_Object *icon)
97 {
98    int size;
99    _els_smart_icon_size_get(icon, &size, NULL);
100    return (size < 16) ? 16 : size;
101 }
102
103 #ifdef HAVE_ELEMENTARY_ETHUMB
104 static void
105 _icon_thumb_stop(Widget_Data *wd, void *ethumbd)
106 {
107    if (wd->thumb.request)
108      {
109         ethumb_client_thumb_async_cancel(ethumbd, wd->thumb.request);
110         wd->thumb.request = NULL;
111         _icon_pending_request--;
112      }
113
114    if (wd->thumb.retry)
115      {
116         _elm_icon_retry = eina_list_remove(_elm_icon_retry, wd);
117         wd->thumb.retry = EINA_FALSE;
118      }
119 }
120
121 static Eina_Bool
122 _icon_thumb_display(Widget_Data *wd)
123 {
124    Eina_Bool ret = EINA_FALSE;
125
126    if (wd->thumb.format == ETHUMB_THUMB_EET)
127      {
128         static const char *extensions[] = {
129           ".avi", ".mp4", ".ogv", ".mov", ".mpg", ".wmv", NULL
130         };
131         const char **ext, *ptr;
132         int prefix_size;
133         Eina_Bool video = EINA_FALSE;
134
135         prefix_size = eina_stringshare_strlen(wd->thumb.file.path) - 4;
136         if (prefix_size >= 0)
137           {
138              ptr = wd->thumb.file.path + prefix_size;
139              for (ext = extensions; *ext; ++ext)
140                if (!strcasecmp(ptr, *ext))
141                  {
142                     video = EINA_TRUE;
143                     break;
144                  }
145           }
146
147         if (video)
148           ret = _els_smart_icon_file_edje_set(wd->img, wd->thumb.thumb.path, wd->thumb.thumb.key);
149      }
150
151    if (!ret)
152      ret = _els_smart_icon_file_key_set(wd->img, wd->thumb.thumb.path, wd->thumb.thumb.key);
153
154    return ret;
155 }
156
157 static Eina_Bool
158 _icon_thumb_retry(Widget_Data *wd)
159 {
160    return _icon_thumb_display(wd);
161 }
162
163 static void
164 _icon_thumb_cleanup(Ethumb_Client *ethumbd)
165 {
166    Eina_List *l, *ll;
167    Widget_Data *wd;
168
169    EINA_LIST_FOREACH_SAFE(_elm_icon_retry, l, ll, wd)
170      if (_icon_thumb_retry(wd))
171        {
172           _elm_icon_retry = eina_list_remove_list(_elm_icon_retry, l);
173           wd->thumb.retry = EINA_FALSE;
174        }
175
176    if (_icon_pending_request == 0)
177      EINA_LIST_FREE(_elm_icon_retry, wd)
178        _icon_thumb_stop(wd, ethumbd);
179 }
180
181 static void
182 _icon_thumb_finish(Widget_Data *wd, Ethumb_Client *ethumbd)
183 {
184    const char *file = NULL, *group = NULL;
185    Eina_Bool ret;
186
187    _els_smart_icon_file_get(wd->img, &file, &group);
188    file = eina_stringshare_ref(file);
189    group = eina_stringshare_ref(group);
190
191    ret = _icon_thumb_display(wd);
192
193    if (!ret && file)
194      {
195         const char *p;
196
197         if (!wd->thumb.retry)
198           {
199              _elm_icon_retry = eina_list_append(_elm_icon_retry, wd);
200              wd->thumb.retry = EINA_TRUE;
201           }
202
203         /* Back to previous image */
204         if (((p = strrchr(file, '.'))) && (!strcasecmp(p, ".edj")))
205           _els_smart_icon_file_edje_set(wd->img, file, group);
206         else
207           _els_smart_icon_file_key_set(wd->img, file, group);
208      }
209
210    _icon_thumb_cleanup(ethumbd);
211
212    eina_stringshare_del(file);
213    eina_stringshare_del(group);
214 }
215
216 static void
217 _icon_thumb_done(Ethumb_Client *client, const char *thumb_path, const char *thumb_key, void *data)
218 {
219    Widget_Data *wd = data;
220
221    assert(wd->thumb.request);
222
223    _icon_pending_request--;
224    wd->thumb.request = NULL;
225
226    eina_stringshare_replace(&wd->thumb.thumb.path, thumb_path);
227    eina_stringshare_replace(&wd->thumb.thumb.key, thumb_key);
228    wd->thumb.format = ethumb_client_format_get(client);
229
230    _icon_thumb_finish(wd, client);
231 }
232
233 static void
234 _icon_thumb_error(Ethumb_Client *client, void *data)
235 {
236    Widget_Data *wd = data;
237
238    assert(wd->thumb.request);
239
240    _icon_pending_request--;
241    wd->thumb.request = NULL;
242
243    ERR("could not generate thumbnail for %s (key: %s)", wd->thumb.file.path, wd->thumb.file.key);
244    _icon_thumb_cleanup(client);
245 }
246
247 static void
248 _icon_thumb_apply(Widget_Data *wd)
249 {
250    Ethumb_Client *ethumbd;
251
252    ethumbd = elm_thumb_ethumb_client_get();
253
254    _icon_thumb_stop(wd, ethumbd);
255
256    if (!wd->thumb.file.path) return ;
257
258    _icon_pending_request++;
259    if (!ethumb_client_file_set(ethumbd, wd->thumb.file.path, wd->thumb.file.key)) return ;
260    ethumb_client_size_set(ethumbd, _icon_size_min_get(wd->img), _icon_size_min_get(wd->img));
261    wd->thumb.request = ethumb_client_thumb_async_get(ethumbd, _icon_thumb_done, _icon_thumb_error, wd);
262 }
263
264 static Eina_Bool
265 _icon_thumb_apply_cb(void *data, int type __UNUSED__, void *ev __UNUSED__)
266 {
267    Widget_Data *wd = data;
268
269    _icon_thumb_apply(wd);
270    return ECORE_CALLBACK_RENEW;
271 }
272 #endif
273
274 static void
275 _del_hook(Evas_Object *obj)
276 {
277    Widget_Data *wd = elm_widget_data_get(obj);
278 #ifdef HAVE_ELEMENTARY_ETHUMB
279    Ethumb_Client *ethumbd;
280 #endif
281
282    if (!wd) return;
283    if (wd->stdicon) eina_stringshare_del(wd->stdicon);
284
285 #ifdef HAVE_ELEMENTARY_ETHUMB
286    ethumbd = elm_thumb_ethumb_client_get();
287    _icon_thumb_stop(wd, ethumbd);
288
289    eina_stringshare_del(wd->thumb.file.path);
290    eina_stringshare_del(wd->thumb.file.key);
291    eina_stringshare_del(wd->thumb.thumb.path);
292    eina_stringshare_del(wd->thumb.thumb.key);
293
294    if (wd->thumb.eeh)
295      ecore_event_handler_del(wd->thumb.eeh);
296 #endif
297
298    if (wd->timer)
299      ecore_timer_del(wd->timer);
300    free(wd);
301 }
302
303 static void
304 _theme_hook(Evas_Object *obj)
305 {
306    Widget_Data *wd = elm_widget_data_get(obj);
307    if (!wd) return;
308    if (wd->stdicon)
309      _elm_theme_object_icon_set(obj, wd->img, wd->stdicon, elm_widget_style_get(obj));
310    _sizing_eval(obj);
311 }
312
313 static void
314 _signal_emit_hook(Evas_Object *obj, const char *emission, const char *source)
315 {
316    Widget_Data *wd = elm_widget_data_get(obj);
317    if (!wd) return;
318    Evas_Object *icon_edje;
319    icon_edje = _els_smart_icon_edje_get(wd->img);
320    if (!icon_edje) return;
321    edje_object_signal_emit(icon_edje, emission, source);
322 }
323
324 static void
325 _signal_callback_add_hook(Evas_Object *obj, const char *emission, const char *source, Edje_Signal_Cb func_cb, void *data)
326 {
327    Widget_Data *wd = elm_widget_data_get(obj);
328    if (!wd) return;
329    Evas_Object *icon_edje;
330    icon_edje = _els_smart_icon_edje_get(wd->img);
331    if (!icon_edje) return;
332    edje_object_signal_callback_add(icon_edje, emission, source, func_cb, data);
333 }
334
335 static void
336 _signal_callback_del_hook(Evas_Object *obj, const char *emission, const char *source, Edje_Signal_Cb func_cb, void *data)
337 {
338    Widget_Data *wd = elm_widget_data_get(obj);
339    if (!wd) return;
340    Evas_Object *icon_edje;
341    icon_edje = _els_smart_icon_edje_get(wd->img);
342    if (!icon_edje) return;
343    edje_object_signal_callback_del_full(icon_edje, emission, source, func_cb,
344                                         data);
345 }
346
347 static void
348 _sizing_eval(Evas_Object *obj)
349 {
350    Widget_Data *wd = elm_widget_data_get(obj);
351    if (!wd) return;
352    Evas_Coord minw = -1, minh = -1, maxw = -1, maxh = -1;
353    int w, h;
354
355    wd->in_eval++;
356    _els_smart_icon_size_get(wd->img, &w, &h);
357 #ifdef ELM_EFREET
358    if (wd->freedesktop.use && wd->stdicon)
359      {
360         int size;
361         /* This icon has been set to a freedesktop icon, and the requested
362            appears to have a different size than the requested size, so try to
363            request another, higher resolution, icon.
364 FIXME: Find a better heuristic to determine if there should be
365 an icon with a different resolution. */
366         size = ((w / 16) + 1) * 16;
367         _icon_freedesktop_set(wd, obj, wd->stdicon, size);
368      }
369 #endif
370    _els_smart_icon_scale_up_set(wd->img, wd->scale_up);
371    _els_smart_icon_scale_down_set(wd->img, wd->scale_down);
372    _els_smart_icon_smooth_scale_set(wd->img, wd->smooth);
373    _els_smart_icon_fill_inside_set(wd->img, !(wd->fill_outside));
374    if (wd->no_scale) _els_smart_icon_scale_set(wd->img, 1.0);
375    else
376      {
377         _els_smart_icon_scale_set(wd->img, elm_widget_scale_get(obj) *
378                                   _elm_config->scale);
379         _els_smart_icon_size_get(wd->img, &w, &h);
380      }
381    if (!wd->scale_down)
382      {
383         minw = w;
384         minh = h;
385      }
386    if (!wd->scale_up)
387      {
388         maxw = w;
389         maxh = h;
390      }
391    evas_object_size_hint_min_set(obj, minw, minh);
392    evas_object_size_hint_max_set(obj, maxw, maxh);
393    wd->in_eval--;
394 }
395
396 static void
397 _mouse_up(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
398 {
399    Evas_Event_Mouse_Up *ev = event_info;
400    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return;
401    evas_object_smart_callback_call(data, SIG_CLICKED, event_info);
402 }
403
404 static Eina_Bool
405 _elm_icon_animate_cb(void *data)
406 {
407    Widget_Data  *wd = data;
408    Evas_Object  *img_obj;
409
410    if (!wd) return ECORE_CALLBACK_CANCEL;
411    if (!wd->anim) return ECORE_CALLBACK_CANCEL;
412
413    img_obj = _els_smart_icon_object_get(wd->img);
414    wd->cur_frame++;
415    if (wd->cur_frame > wd->frame_count)
416      wd->cur_frame = wd->cur_frame % wd->frame_count;
417    evas_object_image_animated_frame_set(img_obj, wd->cur_frame);
418
419    wd->duration = evas_object_image_animated_frame_duration_get(img_obj, wd->cur_frame, 0);
420
421    if (wd->duration > 0)
422      ecore_timer_interval_set(wd->timer, wd->duration);
423    return ECORE_CALLBACK_RENEW;
424 }
425
426 static Eina_Bool
427 _icon_standard_set(Widget_Data *wd, Evas_Object *obj, const char *name)
428 {
429    if (_elm_theme_object_icon_set(obj, wd->img, name, "default"))
430      {
431 #ifdef ELM_EFREET
432         /* TODO: elm_unneed_efreet() */
433         wd->freedesktop.use = EINA_FALSE;
434 #endif
435         return EINA_TRUE;
436      }
437    return EINA_FALSE;
438 }
439
440 static Eina_Bool
441 #ifdef ELM_EFREET
442 _icon_file_set(Widget_Data *wd, Evas_Object *obj, const char *path)
443 #else
444 _icon_file_set(Widget_Data *wd __UNUSED__, Evas_Object *obj, const char *path)
445 #endif
446 {
447    if (elm_icon_file_set(obj, path, NULL))
448      {
449 #ifdef ELM_EFREET
450         /* TODO: elm_unneed_efreet() */
451         wd->freedesktop.use = EINA_FALSE;
452 #endif
453         return EINA_TRUE;
454      }
455    return EINA_FALSE;
456 }
457
458 static Eina_Bool
459 #ifdef ELM_EFREET
460 _icon_freedesktop_set(Widget_Data *wd, Evas_Object *obj, const char *name, int size)
461 #else
462 _icon_freedesktop_set(Widget_Data *wd __UNUSED__, Evas_Object *obj __UNUSED__, const char *name __UNUSED__, int size __UNUSED__)
463 #endif
464 {
465 #ifdef ELM_EFREET
466    const char *path;
467
468    elm_need_efreet();
469    if (icon_theme == NON_EXISTING) return EINA_FALSE;
470    if (!icon_theme)
471      {
472         Efreet_Icon_Theme *theme;
473         /* TODO: Listen for EFREET_EVENT_ICON_CACHE_UPDATE */
474         theme = efreet_icon_theme_find(getenv("E_ICON_THEME"));
475         if (!theme)
476           {
477              const char **itr;
478              static const char *themes[] = {
479                   "gnome", "Human", "oxygen", "hicolor", NULL
480              };
481              for (itr = themes; *itr; itr++)
482                {
483                   theme = efreet_icon_theme_find(*itr);
484                   if (theme) break;
485                }
486           }
487
488         if (!theme)
489           {
490              icon_theme = NON_EXISTING;
491              return EINA_FALSE;
492           }
493         else
494           icon_theme = eina_stringshare_add(theme->name.internal);
495      }
496    path = efreet_icon_path_find(icon_theme, name, size);
497    wd->freedesktop.use = !!path;
498    if (wd->freedesktop.use)
499      {
500         wd->freedesktop.requested_size = size;
501         elm_icon_file_set(obj, path, NULL);
502         return EINA_TRUE;
503      }
504 #endif
505    return EINA_FALSE;
506 }
507
508 static Eina_Bool
509 _elm_icon_standard_set(Widget_Data *wd, Evas_Object *obj, const char *name, Eina_Bool *fdo)
510 {
511    char *tmp;
512    Eina_Bool ret;
513
514    /* try locating the icon using the specified lookup order */
515    switch (wd->lookup_order)
516      {
517       case ELM_ICON_LOOKUP_FDO:
518          ret = _icon_freedesktop_set(wd, obj, name, _icon_size_min_get(wd->img));
519          if (ret && fdo) *fdo = EINA_TRUE;
520          break;
521       case ELM_ICON_LOOKUP_THEME:
522          ret = _icon_standard_set(wd, obj, name);
523          break;
524       case ELM_ICON_LOOKUP_THEME_FDO:
525          ret = _icon_standard_set(wd, obj, name);
526          if (!ret)
527            {
528               ret = _icon_freedesktop_set(wd, obj, name, _icon_size_min_get(wd->img));
529               if (ret && fdo) *fdo = EINA_TRUE;
530            }
531          break;
532       case ELM_ICON_LOOKUP_FDO_THEME:
533       default:
534          ret = _icon_freedesktop_set(wd, obj, name, _icon_size_min_get(wd->img));
535          if (!ret)
536            ret = _icon_standard_set(wd, obj, name);
537          else if (fdo)
538            *fdo = EINA_TRUE;
539          break;
540      }
541
542    if (ret)
543      {
544         eina_stringshare_replace(&wd->stdicon, name);
545         if (!wd->in_eval) _sizing_eval(obj);
546         return EINA_TRUE;
547      }
548
549    if (_path_is_absolute(name))
550      return _icon_file_set(wd, obj, name);
551
552    /* if that fails, see if icon name is in the format size/name. if so,
553       try locating a fallback without the size specification */
554    if (!(tmp = strchr(name, '/'))) return EINA_FALSE;
555    ++tmp;
556    if (*tmp) return elm_icon_standard_set(obj, tmp);
557    /* give up */
558    return EINA_FALSE;
559 }
560
561 static void
562 _elm_icon_standard_resize(void *data,
563                           Evas *e __UNUSED__,
564                           Evas_Object *obj,
565                           void *event_info __UNUSED__)
566 {
567    Widget_Data *wd = data;
568    const char *refup = eina_stringshare_ref(wd->stdicon);
569    Eina_Bool fdo = EINA_FALSE;
570
571    if (!_elm_icon_standard_set(wd, obj, wd->stdicon, &fdo) || (!fdo))
572      evas_object_event_callback_del_full(obj, EVAS_CALLBACK_RESIZE,
573                                          _elm_icon_standard_resize, wd);
574    eina_stringshare_del(refup);
575 }
576
577 #ifdef HAVE_ELEMENTARY_ETHUMB
578 static void
579 _elm_icon_thumb_resize(void *data,
580                        Evas *e __UNUSED__,
581                        Evas_Object *obj,
582                        void *event_info __UNUSED__)
583 {
584    Widget_Data *wd = data;
585
586    if (wd->thumb.file.path)
587      elm_icon_thumb_set(obj, wd->thumb.file.path, wd->thumb.file.key);
588 }
589 #endif
590
591 EAPI Evas_Object *
592 elm_icon_add(Evas_Object *parent)
593 {
594    Evas_Object *obj;
595    Evas *e;
596    Widget_Data *wd;
597
598    ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
599
600    ELM_SET_WIDTYPE(widtype, "icon");
601    elm_widget_type_set(obj, "icon");
602    elm_widget_can_focus_set(obj, EINA_FALSE);
603    elm_widget_sub_object_add(parent, obj);
604    elm_widget_data_set(obj, wd);
605    elm_widget_del_hook_set(obj, _del_hook);
606    elm_widget_theme_hook_set(obj, _theme_hook);
607    elm_widget_signal_emit_hook_set(obj, _signal_emit_hook);
608    elm_widget_signal_callback_add_hook_set(obj, _signal_callback_add_hook);
609    elm_widget_signal_callback_del_hook_set(obj, _signal_callback_del_hook);
610
611    wd->lookup_order = ELM_ICON_LOOKUP_THEME_FDO;
612    wd->img = _els_smart_icon_add(e);
613    evas_object_event_callback_add(wd->img, EVAS_CALLBACK_MOUSE_UP,
614                                   _mouse_up, obj);
615    evas_object_repeat_events_set(wd->img, EINA_TRUE);
616    elm_widget_resize_object_set(obj, wd->img);
617
618    evas_object_smart_callbacks_descriptions_set(obj, _signals);
619
620 #ifdef HAVE_ELEMENTARY_ETHUMB
621    wd->thumb.request = NULL;
622 #endif
623
624    wd->smooth = EINA_TRUE;
625    wd->scale_up = EINA_TRUE;
626    wd->scale_down = EINA_TRUE;
627
628    _sizing_eval(obj);
629    return obj;
630 }
631
632 EAPI Eina_Bool
633 elm_icon_memfile_set(Evas_Object *obj, const void *img, size_t size, const char *format, const char *key)
634 {
635    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
636    Widget_Data *wd = elm_widget_data_get(obj);
637    Eina_Bool ret;
638
639    if (!wd) return EINA_FALSE;
640    EINA_SAFETY_ON_NULL_RETURN_VAL(img, EINA_FALSE);
641    EINA_SAFETY_ON_TRUE_RETURN_VAL(!size, EINA_FALSE);
642    eina_stringshare_del(wd->stdicon);
643    wd->stdicon = NULL;
644    ret = _els_smart_icon_memfile_set(wd->img, img, size, format, key);
645    if (!wd->in_eval) _sizing_eval(obj);
646    return ret;
647 }
648
649 EAPI Eina_Bool
650 elm_icon_file_set(Evas_Object *obj, const char *file, const char *group)
651 {
652    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
653    Widget_Data *wd = elm_widget_data_get(obj);
654    Eina_Bool ret;
655    const char *tmp_file;
656    const char *tmp_group;
657
658    if (!wd) return EINA_FALSE;
659    EINA_SAFETY_ON_NULL_RETURN_VAL(file, EINA_FALSE);
660
661    _els_smart_icon_file_get(wd->img, &tmp_file, &tmp_group);
662    if ((tmp_file == file || (file && tmp_file && !strcmp(tmp_file, file)))
663        && (group == tmp_group || (group && tmp_group && !strcmp(group, tmp_group))))
664      return EINA_TRUE;
665
666 #ifdef ELM_EFREET
667    if (!wd->freedesktop.use)
668      {
669         if (wd->stdicon) eina_stringshare_del(wd->stdicon);
670         wd->stdicon = NULL;
671      }
672 #endif
673    if (eina_str_has_extension(file, ".edj"))
674      ret = _els_smart_icon_file_edje_set(wd->img, file, group);
675    else
676      ret = _els_smart_icon_file_key_set(wd->img, file, group);
677    if (!wd->in_eval) _sizing_eval(obj);
678    return ret;
679 }
680
681 EAPI void
682 elm_icon_file_get(const Evas_Object *obj, const char **file, const char **group)
683 {
684    ELM_CHECK_WIDTYPE(obj, widtype);
685    Widget_Data *wd = elm_widget_data_get(obj);
686    if (!wd) return;
687    _els_smart_icon_file_get(wd->img, file, group);
688 }
689
690 EAPI void
691 elm_icon_thumb_set(Evas_Object *obj, const char *file, const char *group)
692 {
693    ELM_CHECK_WIDTYPE(obj, widtype);
694    Widget_Data *wd = elm_widget_data_get(obj);
695    if (!wd) return;
696
697 #ifdef HAVE_ELEMENTARY_ETHUMB
698    evas_object_event_callback_del_full(obj, EVAS_CALLBACK_RESIZE,
699                                        _elm_icon_standard_resize, wd);
700    evas_object_event_callback_del_full(obj, EVAS_CALLBACK_RESIZE,
701                                        _elm_icon_thumb_resize, wd);
702
703    evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE,
704                                   _elm_icon_thumb_resize, wd);
705
706    eina_stringshare_replace(&wd->thumb.file.path, file);
707    eina_stringshare_replace(&wd->thumb.file.key, group);
708
709    if (elm_thumb_ethumb_client_connected())
710      {
711         _icon_thumb_apply(wd);
712         return ;
713      }
714
715    if (!wd->thumb.eeh)
716      {
717         wd->thumb.eeh = ecore_event_handler_add(ELM_ECORE_EVENT_ETHUMB_CONNECT, _icon_thumb_apply_cb, wd);
718      }
719 #else
720    (void) obj;
721    (void) file;
722    (void) group;
723 #endif
724 }
725
726
727 EAPI Eina_Bool
728 elm_icon_animated_available_get(const Evas_Object *obj)
729 {
730    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
731    Evas_Object *img_obj ;
732    Widget_Data *wd = elm_widget_data_get(obj);
733    if (!wd) return EINA_FALSE;
734
735    img_obj = _els_smart_icon_object_get(wd->img);
736
737    return evas_object_image_animated_get(img_obj);
738 }
739
740 EAPI void
741 elm_icon_animated_set(Evas_Object *obj, Eina_Bool anim)
742 {
743    ELM_CHECK_WIDTYPE(obj, widtype);
744    Evas_Object *img_obj ;
745    Widget_Data *wd = elm_widget_data_get(obj);
746    if (!wd) return;
747    if (wd->anim == anim) return;
748
749    img_obj = _els_smart_icon_object_get(wd->img);
750    if (!evas_object_image_animated_get(img_obj)) return;
751    if (anim)
752      {
753         wd->frame_count = evas_object_image_animated_frame_count_get(img_obj);
754         wd->cur_frame = 1;
755         wd->duration = evas_object_image_animated_frame_duration_get(img_obj, wd->cur_frame, 0);
756         evas_object_image_animated_frame_set(img_obj, wd->cur_frame);
757      }
758    else
759      {
760         wd->frame_count = -1;
761         wd->cur_frame = -1;
762         wd->duration = -1;
763      }
764    wd->anim = anim;
765    return;
766 }
767
768 EAPI Eina_Bool
769 elm_icon_animated_get(const Evas_Object *obj)
770 {
771    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
772    Widget_Data *wd = elm_widget_data_get(obj);
773    if (!wd) return EINA_FALSE;
774    return wd->anim;
775 }
776
777 EAPI void
778 elm_icon_animated_play_set(Evas_Object *obj, Eina_Bool play)
779 {
780    ELM_CHECK_WIDTYPE(obj, widtype);
781    Widget_Data *wd = elm_widget_data_get(obj);
782    if (!wd) return;
783    if (!wd->anim) return;
784    if (wd->play == play) return;
785
786    if (play)
787      {
788         wd->timer = ecore_timer_add(wd->duration, _elm_icon_animate_cb, wd);
789      }
790    else
791      {
792         if (wd->timer)
793           {
794              ecore_timer_del(wd->timer);
795              wd->timer = NULL;
796           }
797      }
798    wd->play = play;
799
800 }
801
802 EAPI Eina_Bool
803 elm_icon_animated_play_get(const Evas_Object *obj)
804 {
805    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
806    Widget_Data *wd = elm_widget_data_get(obj);
807    if (!wd) return EINA_FALSE;
808    return wd->play;
809 }
810
811 EAPI Eina_Bool
812 elm_icon_standard_set(Evas_Object *obj, const char *name)
813 {
814    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
815    Widget_Data *wd = elm_widget_data_get(obj);
816    Eina_Bool fdo = EINA_FALSE;
817    Eina_Bool ret;
818
819    if ((!wd) || (!name)) return EINA_FALSE;
820
821    evas_object_event_callback_del_full(obj, EVAS_CALLBACK_RESIZE,
822                                        _elm_icon_standard_resize, wd);
823
824    ret = _elm_icon_standard_set(wd, obj, name, &fdo);
825
826    if (fdo)
827      evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE,
828                                     _elm_icon_standard_resize, wd);
829
830    return ret;
831 }
832
833 EAPI const char *
834 elm_icon_standard_get(const Evas_Object *obj)
835 {
836    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
837    Widget_Data *wd = elm_widget_data_get(obj);
838    if (!wd) return NULL;
839    return wd->stdicon;
840 }
841
842 EAPI void
843 elm_icon_order_lookup_set(Evas_Object *obj, Elm_Icon_Lookup_Order order)
844 {
845    ELM_CHECK_WIDTYPE(obj, widtype);
846    Widget_Data *wd = elm_widget_data_get(obj);
847    if (wd) wd->lookup_order = order;
848 }
849
850 EAPI Elm_Icon_Lookup_Order
851 elm_icon_order_lookup_get(const Evas_Object *obj)
852 {
853    ELM_CHECK_WIDTYPE(obj, widtype) ELM_ICON_LOOKUP_THEME_FDO;
854    Widget_Data *wd = elm_widget_data_get(obj);
855    if (!wd) return ELM_ICON_LOOKUP_THEME_FDO;
856    return wd->lookup_order;
857 }
858
859 EAPI void
860 elm_icon_smooth_set(Evas_Object *obj, Eina_Bool smooth)
861 {
862    ELM_CHECK_WIDTYPE(obj, widtype);
863    Widget_Data *wd = elm_widget_data_get(obj);
864
865    if (!wd) return;
866    wd->smooth = smooth;
867    if (!wd->in_eval) _sizing_eval(obj);
868 }
869
870 EAPI Eina_Bool
871 elm_icon_smooth_get(const Evas_Object *obj)
872 {
873    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
874    Widget_Data *wd = elm_widget_data_get(obj);
875
876    if (!wd) return EINA_FALSE;
877    return wd->smooth;
878 }
879
880 EAPI void
881 elm_icon_no_scale_set(Evas_Object *obj, Eina_Bool no_scale)
882 {
883    ELM_CHECK_WIDTYPE(obj, widtype);
884    Widget_Data *wd = elm_widget_data_get(obj);
885
886    if (!wd) return;
887    wd->no_scale = no_scale;
888    if (!wd->in_eval) _sizing_eval(obj);
889 }
890
891 EAPI Eina_Bool
892 elm_icon_no_scale_get(const Evas_Object *obj)
893 {
894    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
895    Widget_Data *wd = elm_widget_data_get(obj);
896    if (!wd) return EINA_FALSE;
897    return wd->no_scale;
898 }
899
900 EAPI void
901 elm_icon_scale_set(Evas_Object *obj, Eina_Bool scale_up, Eina_Bool scale_down)
902 {
903    ELM_CHECK_WIDTYPE(obj, widtype);
904    Widget_Data *wd = elm_widget_data_get(obj);
905
906    if (!wd) return;
907    wd->scale_up = scale_up;
908    wd->scale_down = scale_down;
909    if (!wd->in_eval) _sizing_eval(obj);
910 }
911
912 EAPI void
913 elm_icon_scale_get(const Evas_Object *obj, Eina_Bool *scale_up, Eina_Bool *scale_down)
914 {
915    ELM_CHECK_WIDTYPE(obj, widtype);
916    Widget_Data *wd = elm_widget_data_get(obj);
917    if (!wd) return;
918    if (scale_up) *scale_up = wd->scale_up;
919    if (scale_down) *scale_down = wd->scale_down;
920 }
921
922 EAPI void
923 elm_icon_fill_outside_set(Evas_Object *obj, Eina_Bool fill_outside)
924 {
925    ELM_CHECK_WIDTYPE(obj, widtype);
926    Widget_Data *wd = elm_widget_data_get(obj);
927
928    if (!wd) return;
929    wd->fill_outside = fill_outside;
930    if (!wd->in_eval) _sizing_eval(obj);
931 }
932
933 EAPI void
934 elm_icon_size_get(const Evas_Object *obj, int *w, int *h)
935 {
936    ELM_CHECK_WIDTYPE(obj, widtype);
937    Widget_Data *wd = elm_widget_data_get(obj);
938
939    if (!wd) return;
940    _els_smart_icon_size_get(wd->img, w, h);
941 }
942
943 EAPI Eina_Bool
944 elm_icon_fill_outside_get(const Evas_Object *obj)
945 {
946    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
947    Widget_Data *wd = elm_widget_data_get(obj);
948
949    if (!wd) return EINA_FALSE;
950    return wd->fill_outside;
951 }
952
953 EAPI void
954 elm_icon_prescale_set(Evas_Object *obj, int size)
955 {
956    ELM_CHECK_WIDTYPE(obj, widtype);
957    Widget_Data *wd = elm_widget_data_get(obj);
958
959    if (!wd) return;
960    _els_smart_icon_scale_size_set(wd->img, size);
961 }
962
963 EAPI int
964 elm_icon_prescale_get(const Evas_Object *obj)
965 {
966    ELM_CHECK_WIDTYPE(obj, widtype) 0;
967    Widget_Data *wd = elm_widget_data_get(obj);
968
969    if (!wd) return 0;
970    return _els_smart_icon_scale_size_get(wd->img);
971 }
972
973 EAPI Evas_Object *
974 elm_icon_object_get(Evas_Object *obj)
975 {
976    ELM_CHECK_WIDTYPE(obj, widtype) 0;
977    Widget_Data *wd = elm_widget_data_get(obj);
978
979    if (!wd) return NULL;
980    return _els_smart_icon_object_get(wd->img);
981 }
982
983 EAPI void
984 elm_icon_preload_set(Evas_Object *obj, Eina_Bool disable)
985 {
986    ELM_CHECK_WIDTYPE(obj, widtype);
987    Widget_Data *wd = elm_widget_data_get(obj);
988
989    if (!wd) return;
990    _els_smart_icon_preload_set(wd->img, disable);
991 }