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