elementary/map - map supports language,changed
[framework/uifw/elementary.git] / src / lib / elm_icon.c
1 #include <Elementary.h>
2 #include "elm_priv.h"
3 #include "elm_widget_icon.h"
4
5 #ifdef ELM_EFREET
6 #define NON_EXISTING (void *)-1
7 static const char *icon_theme = NULL;
8 #endif
9
10 EAPI const char ELM_ICON_SMART_NAME[] = "elm_icon";
11
12 #ifdef HAVE_ELEMENTARY_ETHUMB
13 static Eina_List *_elm_icon_retry = NULL;
14 static int _icon_pending_request = 0;
15 #endif
16
17 static const char SIG_THUMB_DONE[] = "thumb,done";
18 static const char SIG_THUMB_ERROR[] = "thumb,error";
19 static const Evas_Smart_Cb_Description _smart_callbacks[] = {
20    {SIG_THUMB_DONE, ""},
21    {SIG_THUMB_ERROR, ""},
22    {NULL, NULL}
23 };
24
25 EVAS_SMART_SUBCLASS_NEW
26   (ELM_ICON_SMART_NAME, _elm_icon, Elm_Icon_Smart_Class,
27   Elm_Image_Smart_Class, elm_image_smart_class_get, _smart_callbacks);
28
29 /* FIXME: move this code to ecore */
30 #ifdef _WIN32
31 static Eina_Bool
32 _path_is_absolute(const char *path)
33 {
34    //TODO: Check if this works with all absolute paths in windows
35    return (isalpha(*path)) && (*(path + 1) == ':') &&
36           ((*(path + 2) == '\\') || (*(path + 2) == '/'));
37 }
38
39 #else
40 static Eina_Bool
41 _path_is_absolute(const char *path)
42 {
43    return *path == '/';
44 }
45
46 #endif
47
48 static inline int
49 _icon_size_min_get(Evas_Object *icon)
50 {
51    int size;
52
53    elm_image_object_size_get(icon, &size, NULL);
54
55    return (size < 16) ? 16 : size;
56 }
57
58 #ifdef HAVE_ELEMENTARY_ETHUMB
59 static void
60 _icon_thumb_stop(Elm_Icon_Smart_Data *sd,
61                  void *ethumbd)
62 {
63    if (sd->thumb.request)
64      {
65         ethumb_client_thumb_async_cancel(ethumbd, sd->thumb.request);
66         sd->thumb.request = NULL;
67         _icon_pending_request--;
68      }
69
70    if (sd->thumb.retry)
71      {
72         _elm_icon_retry = eina_list_remove(_elm_icon_retry, sd);
73         sd->thumb.retry = EINA_FALSE;
74      }
75 }
76
77 static Eina_Bool
78 _icon_thumb_display(Elm_Icon_Smart_Data *sd)
79 {
80    Eina_Bool ret = EINA_FALSE;
81
82    if (sd->thumb.format == ETHUMB_THUMB_EET)
83      {
84         int prefix_size;
85         const char **ext, *ptr;
86         static const char *extensions[] =
87         {
88            ".avi", ".mp4", ".ogv", ".mov", ".mpg", ".wmv", NULL
89         };
90
91         prefix_size = eina_stringshare_strlen(sd->thumb.file.path) - 4;
92         if (prefix_size >= 0)
93           {
94              ptr = sd->thumb.file.path + prefix_size;
95              for (ext = extensions; *ext; ++ext)
96                if (!strcasecmp(ptr, *ext))
97                  {
98                     sd->is_video = EINA_TRUE;
99                     break;
100                  }
101           }
102
103         ret = elm_image_file_set
104             (ELM_WIDGET_DATA(sd)->obj, sd->thumb.thumb.path,
105             sd->thumb.thumb.key);
106
107         sd->is_video = EINA_FALSE;
108      }
109
110    if (!ret)
111      ret = elm_image_file_set
112          (ELM_WIDGET_DATA(sd)->obj, sd->thumb.thumb.path, sd->thumb.thumb.key);
113
114    if (ret)
115      evas_object_smart_callback_call
116        (ELM_WIDGET_DATA(sd)->obj, SIG_THUMB_DONE, NULL);
117    else
118      evas_object_smart_callback_call
119        (ELM_WIDGET_DATA(sd)->obj, SIG_THUMB_ERROR, NULL);
120
121    return ret;
122 }
123
124 static Eina_Bool
125 _icon_thumb_retry(Elm_Icon_Smart_Data *sd)
126 {
127    return _icon_thumb_display(sd);
128 }
129
130 static void
131 _icon_thumb_cleanup(Ethumb_Client *ethumbd)
132 {
133    Eina_List *l, *ll;
134    Elm_Icon_Smart_Data *sd;
135
136    EINA_LIST_FOREACH_SAFE(_elm_icon_retry, l, ll, sd)
137      if (_icon_thumb_retry(sd))
138        {
139           _elm_icon_retry = eina_list_remove_list(_elm_icon_retry, l);
140           sd->thumb.retry = EINA_FALSE;
141        }
142
143    if (_icon_pending_request == 0)
144      EINA_LIST_FREE (_elm_icon_retry, sd)
145        _icon_thumb_stop(sd, ethumbd);
146 }
147
148 static void
149 _icon_thumb_finish(Elm_Icon_Smart_Data *sd,
150                    Ethumb_Client *ethumbd)
151 {
152    const char *file = NULL, *group = NULL;
153    Eina_Bool ret;
154
155    elm_image_file_get(ELM_WIDGET_DATA(sd)->obj, &file, &group);
156    file = eina_stringshare_ref(file);
157    group = eina_stringshare_ref(group);
158
159    ret = _icon_thumb_display(sd);
160
161    if (!ret && file)
162      {
163         if (!sd->thumb.retry)
164           {
165              _elm_icon_retry = eina_list_append(_elm_icon_retry, sd);
166              sd->thumb.retry = EINA_TRUE;
167           }
168
169         /* Back to previous image */
170         elm_image_file_set(ELM_WIDGET_DATA(sd)->obj, file, group);
171      }
172
173    _icon_thumb_cleanup(ethumbd);
174
175    eina_stringshare_del(file);
176    eina_stringshare_del(group);
177 }
178
179 static void
180 _icon_thumb_done(Ethumb_Client *client,
181                  const char *thumb_path,
182                  const char *thumb_key,
183                  void *data)
184 {
185    Elm_Icon_Smart_Data *sd = data;
186
187    if (EINA_UNLIKELY(!sd->thumb.request))
188      {
189         ERR("Something odd happened with a thumbnail request");
190         return;
191      }
192
193    _icon_pending_request--;
194    sd->thumb.request = NULL;
195
196    eina_stringshare_replace(&sd->thumb.thumb.path, thumb_path);
197    eina_stringshare_replace(&sd->thumb.thumb.key, thumb_key);
198    sd->thumb.format = ethumb_client_format_get(client);
199
200    _icon_thumb_finish(sd, client);
201 }
202
203 static void
204 _icon_thumb_error(Ethumb_Client *client,
205                   void *data)
206 {
207    Elm_Icon_Smart_Data *sd = data;
208
209    if (EINA_UNLIKELY(!sd->thumb.request))
210      {
211         ERR("Something odd happened with a thumbnail request");
212         return;
213      }
214
215    _icon_pending_request--;
216    sd->thumb.request = NULL;
217
218    ERR("could not generate thumbnail for %s (key: %s)",
219        sd->thumb.file.path, sd->thumb.file.key);
220
221    evas_object_smart_callback_call(ELM_WIDGET_DATA(sd)->obj, SIG_THUMB_ERROR, NULL);
222
223    _icon_thumb_cleanup(client);
224 }
225
226 static void
227 _icon_thumb_apply(Elm_Icon_Smart_Data *sd)
228 {
229    Ethumb_Client *ethumbd;
230    int min_size;
231
232    ethumbd = elm_thumb_ethumb_client_get();
233
234    _icon_thumb_stop(sd, ethumbd);
235
236    if (!sd->thumb.file.path) return;
237
238    _icon_pending_request++;
239    if (!ethumb_client_file_set
240          (ethumbd, sd->thumb.file.path, sd->thumb.file.key)) return;
241
242    min_size = _icon_size_min_get(ELM_WIDGET_DATA(sd)->obj);
243    ethumb_client_size_set(ethumbd, min_size, min_size);
244
245    sd->thumb.request = ethumb_client_thumb_async_get
246        (ethumbd, _icon_thumb_done, _icon_thumb_error, sd);
247 }
248
249 static Eina_Bool
250 _icon_thumb_apply_cb(void *data,
251                      int type __UNUSED__,
252                      void *ev __UNUSED__)
253 {
254    Elm_Icon_Smart_Data *sd = data;
255
256    _icon_thumb_apply(sd);
257
258    return ECORE_CALLBACK_RENEW;
259 }
260
261 #endif
262
263 static Eina_Bool
264 #ifdef ELM_EFREET
265 _icon_freedesktop_set(Evas_Object *obj,
266                       const char *name,
267                       int size)
268 #else
269 _icon_freedesktop_set(Evas_Object * obj __UNUSED__,
270                       const char *name __UNUSED__,
271                       int size __UNUSED__)
272 #endif
273 {
274 #ifdef ELM_EFREET
275    const char *path;
276
277    ELM_ICON_DATA_GET(obj, sd);
278
279    elm_need_efreet();
280
281    if (icon_theme == NON_EXISTING) return EINA_FALSE;
282
283    if (!icon_theme)
284      {
285         Efreet_Icon_Theme *theme;
286         /* TODO: Listen for EFREET_EVENT_ICON_CACHE_UPDATE */
287         theme = efreet_icon_theme_find(getenv("E_ICON_THEME"));
288         if (!theme)
289           {
290              const char **itr;
291              static const char *themes[] = {
292                 "gnome", "Human", "oxygen", "hicolor", NULL
293              };
294              for (itr = themes; *itr; itr++)
295                {
296                   theme = efreet_icon_theme_find(*itr);
297                   if (theme) break;
298                }
299           }
300
301         if (!theme)
302           {
303              icon_theme = NON_EXISTING;
304              return EINA_FALSE;
305           }
306         else
307           icon_theme = eina_stringshare_add(theme->name.internal);
308      }
309    path = efreet_icon_path_find(icon_theme, name, size);
310    sd->freedesktop.use = !!path;
311    if (sd->freedesktop.use)
312      {
313         sd->freedesktop.requested_size = size;
314         elm_image_file_set(obj, path, NULL);
315         return EINA_TRUE;
316      }
317 #endif
318    return EINA_FALSE;
319 }
320
321 static void
322 _elm_icon_smart_sizing_eval(Evas_Object *obj)
323 {
324    int w, h;
325
326    ELM_ICON_DATA_GET(obj, sd);
327
328    if (sd->in_eval) return;
329
330    sd->in_eval++;
331    elm_image_object_size_get(obj, &w, &h);
332
333 #ifdef ELM_EFREET
334    if (sd->freedesktop.use && sd->stdicon)
335      {
336         int size;
337         /* This icon has been set to a freedesktop icon, and the requested
338            appears to have a different size than the requested size, so try to
339            request another, higher resolution, icon.
340            FIXME: Find a better heuristic to determine if there should be
341            an icon with a different resolution. */
342         size = ((w / 16) + 1) * 16;
343         _icon_freedesktop_set(obj, sd->stdicon, size);
344      }
345 #endif
346
347    _elm_icon_parent_sc->sizing_eval(obj);
348
349    sd->in_eval--;
350 }
351
352 static void
353 _edje_signals_free(Elm_Icon_Smart_Data *sd)
354 {
355    Edje_Signal_Data *esd;
356
357    EINA_LIST_FREE (sd->edje_signals, esd)
358      {
359         eina_stringshare_del(esd->emission);
360         eina_stringshare_del(esd->source);
361         free(esd);
362      }
363 }
364
365 static Eina_Bool
366 _elm_icon_smart_file_set(Evas_Object *obj,
367                          const char *file,
368                          const char *key)
369 {
370    Evas_Object *pclip;
371
372    ELM_ICON_DATA_GET(obj, sd);
373
374    EINA_SAFETY_ON_NULL_RETURN_VAL(file, EINA_FALSE);
375
376    _edje_signals_free(sd);
377
378 #ifdef ELM_EFREET
379    if (!sd->freedesktop.use)
380      {
381         if (sd->stdicon) eina_stringshare_del(sd->stdicon);
382         sd->stdicon = NULL;
383      }
384 #endif
385
386    if (!sd->is_video) return _elm_icon_parent_sc->file_set(obj, file, key);
387
388    /* parent's edje file setting path replicated here (we got .eet
389     * extension, so bypassing it) */
390    if (ELM_IMAGE_DATA(sd)->prev_img)
391      evas_object_del(ELM_IMAGE_DATA(sd)->prev_img);
392    ELM_IMAGE_DATA(sd)->prev_img = NULL;
393
394    if (!ELM_IMAGE_DATA(sd)->edje)
395      {
396         pclip = evas_object_clip_get(ELM_IMAGE_DATA(sd)->img);
397         if (ELM_IMAGE_DATA(sd)->img) evas_object_del(ELM_IMAGE_DATA(sd)->img);
398
399         /* Edje object instead */
400         ELM_IMAGE_DATA(sd)->img = edje_object_add(evas_object_evas_get(obj));
401         evas_object_smart_member_add(ELM_IMAGE_DATA(sd)->img, obj);
402         if (ELM_IMAGE_DATA(sd)->show)
403           evas_object_show(ELM_IMAGE_DATA(sd)->img);
404         evas_object_clip_set(ELM_IMAGE_DATA(sd)->img, pclip);
405      }
406
407    ELM_IMAGE_DATA(sd)->edje = EINA_TRUE;
408    if (!edje_object_file_set(ELM_IMAGE_DATA(sd)->img, file, key))
409      {
410         ERR("failed to set edje file '%s', group '%s': %s", file, key,
411             edje_load_error_str
412               (edje_object_load_error_get(ELM_IMAGE_DATA(sd)->img)));
413         return EINA_FALSE;
414      }
415
416    evas_object_move(ELM_IMAGE_DATA(sd)->img, ELM_IMAGE_DATA(sd)->img_x,
417                     ELM_IMAGE_DATA(sd)->img_y);
418    evas_object_resize(ELM_IMAGE_DATA(sd)->img, ELM_IMAGE_DATA(sd)->img_w,
419                       ELM_IMAGE_DATA(sd)->img_h);
420
421    return EINA_TRUE;
422 }
423
424 static Eina_Bool
425 _elm_icon_smart_memfile_set(Evas_Object *obj,
426                             const void *img,
427                             size_t size,
428                             const char *format,
429                             const char *key)
430 {
431    ELM_ICON_DATA_GET(obj, sd);
432
433    Eina_Bool ret;
434
435    EINA_SAFETY_ON_NULL_RETURN_VAL(img, EINA_FALSE);
436    EINA_SAFETY_ON_TRUE_RETURN_VAL(!size, EINA_FALSE);
437    eina_stringshare_del(sd->stdicon);
438    sd->stdicon = NULL;
439
440    _edje_signals_free(sd);
441
442    ret = _elm_icon_parent_sc->memfile_set(obj, img, size, format, key);
443
444    return ret;
445 }
446
447 static Eina_Bool
448 _elm_icon_smart_theme(Evas_Object *obj)
449 {
450    ELM_ICON_DATA_GET(obj, sd);
451
452    if (sd->stdicon)
453      _elm_theme_object_icon_set(obj, sd->stdicon, elm_widget_style_get(obj));
454
455    if (!ELM_WIDGET_CLASS(_elm_icon_parent_sc)->theme(obj))
456      return EINA_FALSE;
457
458    return EINA_TRUE;
459 }
460
461 static Eina_Bool
462 _icon_standard_set(Evas_Object *obj,
463                    const char *name)
464 {
465    ELM_ICON_DATA_GET(obj, sd);
466
467    if (_elm_theme_object_icon_set(obj, name, "default"))
468      {
469 #ifdef ELM_EFREET
470         /* TODO: elm_unneed_efreet() */
471         sd->freedesktop.use = EINA_FALSE;
472 #endif
473         return EINA_TRUE;
474      }
475
476    return EINA_FALSE;
477 }
478
479 static Eina_Bool
480 #ifdef ELM_EFREET
481 _icon_file_set(Elm_Icon_Smart_Data *sd,
482                Evas_Object *obj,
483                const char *path)
484 #else
485 _icon_file_set(Elm_Icon_Smart_Data * sd __UNUSED__,
486                Evas_Object * obj,
487                const char *path)
488 #endif
489 {
490    if (elm_image_file_set(obj, path, NULL))
491      {
492 #ifdef ELM_EFREET
493         /* TODO: elm_unneed_efreet() */
494         sd->freedesktop.use = EINA_FALSE;
495 #endif
496         return EINA_TRUE;
497      }
498    return EINA_FALSE;
499 }
500
501 static Eina_Bool
502 _elm_icon_standard_set(Evas_Object *obj,
503                        const char *name,
504                        Eina_Bool *fdo)
505 {
506    char *tmp;
507    Eina_Bool ret;
508
509    ELM_ICON_DATA_GET(obj, sd);
510
511    /* try locating the icon using the specified lookup order */
512    switch (sd->lookup_order)
513      {
514       case ELM_ICON_LOOKUP_FDO:
515         ret = _icon_freedesktop_set(obj, name, _icon_size_min_get(obj));
516         if (ret && fdo) *fdo = EINA_TRUE;
517         break;
518
519       case ELM_ICON_LOOKUP_THEME:
520         ret = _icon_standard_set(obj, name);
521         break;
522
523       case ELM_ICON_LOOKUP_THEME_FDO:
524         ret = _icon_standard_set(obj, name);
525         if (!ret)
526           {
527              ret = _icon_freedesktop_set(obj, name, _icon_size_min_get(obj));
528              if (ret && fdo) *fdo = EINA_TRUE;
529           }
530         break;
531
532       case ELM_ICON_LOOKUP_FDO_THEME:
533       default:
534         ret = _icon_freedesktop_set(obj, name, _icon_size_min_get(obj));
535         if (!ret)
536           ret = _icon_standard_set(obj, name);
537         else if (fdo)
538           *fdo = EINA_TRUE;
539         break;
540      }
541
542    if (ret)
543      {
544         eina_stringshare_replace(&sd->stdicon, name);
545         _elm_icon_smart_sizing_eval(obj);
546         return EINA_TRUE;
547      }
548
549    if (_path_is_absolute(name))
550      return _icon_file_set(sd, 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_cb(void *data,
563                              Evas *e __UNUSED__,
564                              Evas_Object *obj,
565                              void *event_info __UNUSED__)
566 {
567    Elm_Icon_Smart_Data *sd = data;
568    const char *refup = eina_stringshare_ref(sd->stdicon);
569    Eina_Bool fdo = EINA_FALSE;
570
571    if (!_elm_icon_standard_set(obj, sd->stdicon, &fdo) || (!fdo))
572      evas_object_event_callback_del_full
573        (obj, EVAS_CALLBACK_RESIZE, _elm_icon_standard_resize_cb, sd);
574    eina_stringshare_del(refup);
575 }
576
577 #ifdef HAVE_ELEMENTARY_ETHUMB
578 static void
579 _elm_icon_thumb_resize_cb(void *data,
580                           Evas *e __UNUSED__,
581                           Evas_Object *obj,
582                           void *event_info __UNUSED__)
583 {
584    Elm_Icon_Smart_Data *sd = data;
585
586    if (sd->thumb.file.path)
587      elm_icon_thumb_set(obj, sd->thumb.file.path, sd->thumb.file.key);
588 }
589
590 #endif
591
592 static void
593 _elm_icon_smart_add(Evas_Object *obj)
594 {
595    EVAS_SMART_DATA_ALLOC(obj, Elm_Icon_Smart_Data);
596
597    ELM_WIDGET_CLASS(_elm_icon_parent_sc)->base.add(obj);
598
599    priv->lookup_order = ELM_ICON_LOOKUP_THEME_FDO;
600
601 #ifdef HAVE_ELEMENTARY_ETHUMB
602    priv->thumb.request = NULL;
603 #endif
604 }
605
606 static void
607 _elm_icon_smart_del(Evas_Object *obj)
608 {
609 #ifdef HAVE_ELEMENTARY_ETHUMB
610    Ethumb_Client *ethumbd;
611 #endif
612
613    ELM_ICON_DATA_GET(obj, sd);
614
615    if (sd->stdicon) eina_stringshare_del(sd->stdicon);
616
617 #ifdef HAVE_ELEMENTARY_ETHUMB
618    ethumbd = elm_thumb_ethumb_client_get();
619    _icon_thumb_stop(sd, ethumbd);
620
621    eina_stringshare_del(sd->thumb.file.path);
622    eina_stringshare_del(sd->thumb.file.key);
623    eina_stringshare_del(sd->thumb.thumb.path);
624    eina_stringshare_del(sd->thumb.thumb.key);
625
626    if (sd->thumb.eeh)
627      ecore_event_handler_del(sd->thumb.eeh);
628 #endif
629
630    _edje_signals_free(sd);
631
632    ELM_WIDGET_CLASS(_elm_icon_parent_sc)->base.del(obj);
633 }
634
635 /* WARNING: to be deprecated */
636 void
637 _elm_icon_signal_emit(Evas_Object *obj,
638                       const char *emission,
639                       const char *source)
640 {
641    ELM_ICON_DATA_GET(obj, sd);
642
643    if (!ELM_IMAGE_DATA(sd)->edje) return;
644
645    edje_object_signal_emit(ELM_IMAGE_DATA(sd)->img, emission, source);
646 }
647
648 static void
649 _edje_signal_callback(void *data,
650                       Evas_Object *obj __UNUSED__,
651                       const char *emission,
652                       const char *source)
653 {
654    Edje_Signal_Data *esd = data;
655
656    esd->func(esd->data, esd->obj, emission, source);
657 }
658
659 /* WARNING: to be deprecated */
660 void
661 _elm_icon_signal_callback_add(Evas_Object *obj,
662                               const char *emission,
663                               const char *source,
664                               Edje_Signal_Cb func_cb,
665                               void *data)
666 {
667    Edje_Signal_Data *esd;
668
669    ELM_ICON_DATA_GET(obj, sd);
670
671    if (!ELM_IMAGE_DATA(sd)->edje) return;
672
673    esd = ELM_NEW(Edje_Signal_Data);
674    if (!esd) return;
675
676    esd->obj = obj;
677    esd->func = func_cb;
678    esd->emission = eina_stringshare_add(emission);
679    esd->source = eina_stringshare_add(source);
680    esd->data = data;
681    sd->edje_signals =
682      eina_list_append(sd->edje_signals, esd);
683
684    edje_object_signal_callback_add
685      (ELM_IMAGE_DATA(sd)->img, emission, source, _edje_signal_callback, esd);
686 }
687
688 /* WARNING: to be deprecated */
689 void *
690 _elm_icon_signal_callback_del(Evas_Object *obj,
691                               const char *emission,
692                               const char *source,
693                               Edje_Signal_Cb func_cb)
694 {
695    Edje_Signal_Data *esd = NULL;
696    void *data = NULL;
697    Eina_List *l;
698
699    ELM_ICON_DATA_GET(obj, sd);
700
701    if (!ELM_IMAGE_DATA(sd)->edje) return NULL;
702
703    EINA_LIST_FOREACH(sd->edje_signals, l, esd)
704      {
705         if ((esd->func == func_cb) && (!strcmp(esd->emission, emission)) &&
706             (!strcmp(esd->source, source)))
707           {
708              sd->edje_signals = eina_list_remove_list(sd->edje_signals, l);
709              eina_stringshare_del(esd->emission);
710              eina_stringshare_del(esd->source);
711              data = esd->data;
712              free(esd);
713
714              edje_object_signal_callback_del_full
715                (ELM_IMAGE_DATA(sd)->img, emission, source,
716                _edje_signal_callback, esd);
717
718              return data; /* stop at 1st match */
719           }
720      }
721
722    return data;
723 }
724
725 static void
726 _elm_icon_smart_set_user(Elm_Icon_Smart_Class *sc)
727 {
728    ELM_WIDGET_CLASS(sc)->base.add = _elm_icon_smart_add;
729    ELM_WIDGET_CLASS(sc)->base.del = _elm_icon_smart_del;
730
731    ELM_WIDGET_CLASS(sc)->theme = _elm_icon_smart_theme;
732
733    ELM_IMAGE_CLASS(sc)->file_set = _elm_icon_smart_file_set;
734    ELM_IMAGE_CLASS(sc)->memfile_set = _elm_icon_smart_memfile_set;
735    ELM_IMAGE_CLASS(sc)->sizing_eval = _elm_icon_smart_sizing_eval;
736 }
737
738 EAPI const Elm_Icon_Smart_Class *
739 elm_icon_smart_class_get(void)
740 {
741    static Elm_Icon_Smart_Class _sc =
742      ELM_ICON_SMART_CLASS_INIT_NAME_VERSION(ELM_ICON_SMART_NAME);
743    static const Elm_Icon_Smart_Class *class = NULL;
744    Evas_Smart_Class *esc = (Evas_Smart_Class *)&_sc;
745
746    if (class) return class;
747
748    _elm_icon_smart_set(&_sc);
749    esc->callbacks = _smart_callbacks;
750    class = &_sc;
751
752    return class;
753 }
754
755 EAPI Evas_Object *
756 elm_icon_add(Evas_Object *parent)
757 {
758    Evas_Object *obj;
759
760    EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
761
762    obj = elm_widget_add(_elm_icon_smart_class_new(), parent);
763    if (!obj) return NULL;
764
765    if (!elm_widget_sub_object_add(parent, obj))
766      ERR("could not add %p as sub object of %p", obj, parent);
767
768    return obj;
769 }
770
771 EAPI Eina_Bool
772 elm_icon_memfile_set(Evas_Object *obj,
773                      const void *img,
774                      size_t size,
775                      const char *format,
776                      const char *key)
777 {
778    ELM_ICON_CHECK(obj) EINA_FALSE;
779
780    return elm_image_memfile_set(obj, img, size, format, key);
781 }
782
783 EAPI Eina_Bool
784 elm_icon_file_set(Evas_Object *obj,
785                   const char *file,
786                   const char *group)
787 {
788    ELM_ICON_CHECK(obj) EINA_FALSE;
789
790    return elm_image_file_set(obj, file, group);
791 }
792
793 EAPI void
794 elm_icon_file_get(const Evas_Object *obj,
795                   const char **file,
796                   const char **group)
797 {
798    ELM_ICON_CHECK(obj);
799
800    elm_image_file_get(obj, file, group);
801 }
802
803 EAPI void
804 elm_icon_thumb_set(Evas_Object *obj,
805                    const char *file,
806                    const char *group)
807 {
808    ELM_ICON_CHECK(obj);
809
810 #ifdef HAVE_ELEMENTARY_ETHUMB
811    ELM_ICON_DATA_GET(obj, sd);
812
813    evas_object_event_callback_del_full
814      (obj, EVAS_CALLBACK_RESIZE, _elm_icon_standard_resize_cb, sd);
815    evas_object_event_callback_del_full
816      (obj, EVAS_CALLBACK_RESIZE, _elm_icon_thumb_resize_cb, sd);
817
818    evas_object_event_callback_add
819      (obj, EVAS_CALLBACK_RESIZE, _elm_icon_thumb_resize_cb, sd);
820
821    eina_stringshare_replace(&sd->thumb.file.path, file);
822    eina_stringshare_replace(&sd->thumb.file.key, group);
823
824    if (elm_thumb_ethumb_client_connected_get())
825      {
826         _icon_thumb_apply(sd);
827         return;
828      }
829
830    if (!sd->thumb.eeh)
831      {
832         sd->thumb.eeh = ecore_event_handler_add
833             (ELM_ECORE_EVENT_ETHUMB_CONNECT, _icon_thumb_apply_cb, sd);
834      }
835 #else
836    (void)obj;
837    (void)file;
838    (void)group;
839 #endif
840 }
841
842 EAPI Eina_Bool
843 elm_icon_animated_available_get(const Evas_Object *obj)
844 {
845    ELM_ICON_CHECK(obj) EINA_FALSE;
846
847    return elm_image_animated_available_get(obj);
848 }
849
850 EAPI void
851 elm_icon_animated_set(Evas_Object *obj,
852                       Eina_Bool anim)
853 {
854    ELM_ICON_CHECK(obj);
855
856    return elm_image_animated_set(obj, anim);
857 }
858
859 EAPI Eina_Bool
860 elm_icon_animated_get(const Evas_Object *obj)
861 {
862    ELM_ICON_CHECK(obj) EINA_FALSE;
863
864    return elm_image_animated_get(obj);
865 }
866
867 EAPI void
868 elm_icon_animated_play_set(Evas_Object *obj,
869                            Eina_Bool play)
870 {
871    ELM_ICON_CHECK(obj);
872
873    elm_image_animated_play_set(obj, play);
874 }
875
876 EAPI Eina_Bool
877 elm_icon_animated_play_get(const Evas_Object *obj)
878 {
879    ELM_ICON_CHECK(obj) EINA_FALSE;
880
881    return elm_image_animated_play_get(obj);
882 }
883
884 EAPI Eina_Bool
885 elm_icon_standard_set(Evas_Object *obj,
886                       const char *name)
887 {
888    ELM_ICON_CHECK(obj) EINA_FALSE;
889    ELM_ICON_DATA_GET(obj, sd);
890
891    Eina_Bool fdo = EINA_FALSE;
892    Eina_Bool ret;
893
894    if (!name) return EINA_FALSE;
895
896    evas_object_event_callback_del_full
897      (obj, EVAS_CALLBACK_RESIZE, _elm_icon_standard_resize_cb, sd);
898
899    ret = _elm_icon_standard_set(obj, name, &fdo);
900
901    if (fdo)
902      evas_object_event_callback_add
903        (obj, EVAS_CALLBACK_RESIZE, _elm_icon_standard_resize_cb, sd);
904
905    return ret;
906 }
907
908 EAPI const char *
909 elm_icon_standard_get(const Evas_Object *obj)
910 {
911    ELM_ICON_CHECK(obj) NULL;
912    ELM_ICON_DATA_GET(obj, sd);
913
914    return sd->stdicon;
915 }
916
917 EAPI void
918 elm_icon_order_lookup_set(Evas_Object *obj,
919                           Elm_Icon_Lookup_Order order)
920 {
921    ELM_ICON_CHECK(obj);
922    ELM_ICON_DATA_GET(obj, sd);
923
924    sd->lookup_order = order;
925 }
926
927 EAPI Elm_Icon_Lookup_Order
928 elm_icon_order_lookup_get(const Evas_Object *obj)
929 {
930    ELM_ICON_CHECK(obj) ELM_ICON_LOOKUP_THEME_FDO;
931    ELM_ICON_DATA_GET(obj, sd);
932
933    return sd->lookup_order;
934 }
935
936 EAPI void
937 elm_icon_smooth_set(Evas_Object *obj,
938                     Eina_Bool smooth)
939 {
940    ELM_ICON_CHECK(obj);
941
942    elm_image_smooth_set(obj, smooth);
943 }
944
945 EAPI Eina_Bool
946 elm_icon_smooth_get(const Evas_Object *obj)
947 {
948    ELM_ICON_CHECK(obj) EINA_FALSE;
949
950    return elm_image_smooth_get(obj);
951 }
952
953 EAPI void
954 elm_icon_no_scale_set(Evas_Object *obj,
955                       Eina_Bool no_scale)
956 {
957    ELM_ICON_CHECK(obj);
958
959    elm_image_no_scale_set(obj, no_scale);
960 }
961
962 EAPI Eina_Bool
963 elm_icon_no_scale_get(const Evas_Object *obj)
964 {
965    ELM_ICON_CHECK(obj) EINA_FALSE;
966
967    return elm_image_no_scale_get(obj);
968 }
969
970 EAPI void
971 elm_icon_resizable_set(Evas_Object *obj,
972                        Eina_Bool size_up,
973                        Eina_Bool size_down)
974 {
975    ELM_ICON_CHECK(obj);
976
977    elm_image_resizable_set(obj, size_up, size_down);
978 }
979
980 EAPI void
981 elm_icon_resizable_get(const Evas_Object *obj,
982                        Eina_Bool *size_up,
983                        Eina_Bool *size_down)
984 {
985    ELM_ICON_CHECK(obj);
986
987    elm_image_resizable_get(obj, size_up, size_down);
988 }
989
990 EAPI void
991 elm_icon_fill_outside_set(Evas_Object *obj,
992                           Eina_Bool fill_outside)
993 {
994    ELM_ICON_CHECK(obj);
995
996    elm_image_fill_outside_set(obj, fill_outside);
997 }
998
999 EAPI Eina_Bool
1000 elm_icon_fill_outside_get(const Evas_Object *obj)
1001 {
1002    ELM_ICON_CHECK(obj) EINA_FALSE;
1003
1004    return elm_image_fill_outside_get(obj);
1005 }
1006
1007 EAPI void
1008 elm_icon_size_get(const Evas_Object *obj,
1009                   int *w,
1010                   int *h)
1011 {
1012    ELM_ICON_CHECK(obj);
1013
1014    elm_image_object_size_get(obj, w, h);
1015 }
1016
1017 EAPI void
1018 elm_icon_prescale_set(Evas_Object *obj,
1019                       int size)
1020 {
1021    ELM_ICON_CHECK(obj);
1022
1023    elm_image_prescale_set(obj, size);
1024 }
1025
1026 EAPI int
1027 elm_icon_prescale_get(const Evas_Object *obj)
1028 {
1029    ELM_ICON_CHECK(obj) 0;
1030
1031    return elm_image_prescale_get(obj);
1032 }
1033
1034 EAPI Evas_Object *
1035 elm_icon_object_get(Evas_Object *obj)
1036 {
1037    ELM_ICON_CHECK(obj) 0;
1038
1039    return elm_image_object_get(obj);
1040 }
1041
1042 EAPI void
1043 elm_icon_preload_disabled_set(Evas_Object *obj,
1044                               Eina_Bool disabled)
1045 {
1046    ELM_ICON_CHECK(obj);
1047
1048    elm_image_preload_disabled_set(obj, disabled);
1049 }
1050
1051 EAPI void
1052 elm_icon_aspect_fixed_set(Evas_Object *obj,
1053                           Eina_Bool fixed)
1054 {
1055    ELM_ICON_CHECK(obj);
1056
1057    elm_image_aspect_fixed_set(obj, fixed);
1058 }
1059
1060 EAPI Eina_Bool
1061 elm_icon_aspect_fixed_get(const Evas_Object *obj)
1062 {
1063    ELM_ICON_CHECK(obj) EINA_FALSE;
1064
1065    return elm_image_aspect_fixed_get(obj);
1066 }