ef62875b75716c6a130b8002de575a4b266b0cc4
[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 EAPI Eina_Bool
658 elm_icon_standard_set(Evas_Object *obj, const char *name)
659 {
660    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
661    Widget_Data *wd = elm_widget_data_get(obj);
662    char *tmp;
663    Eina_Bool ret;
664
665    if ((!wd) || (!name)) return EINA_FALSE;
666
667    /* try locating the icon using the specified lookup order */
668    switch (wd->lookup_order)
669      {
670       case ELM_ICON_LOOKUP_FDO:
671          ret = _icon_freedesktop_set(wd, obj, name, _icon_size_min_get(wd->img));
672          break;
673       case ELM_ICON_LOOKUP_THEME:
674          ret = _icon_standard_set(wd, obj, name);
675          break;
676       case ELM_ICON_LOOKUP_THEME_FDO:
677          ret = _icon_standard_set(wd, obj, name) ||
678             _icon_freedesktop_set(wd, obj, name, _icon_size_min_get(wd->img));
679          break;
680       case ELM_ICON_LOOKUP_FDO_THEME:
681       default:
682          ret = _icon_freedesktop_set(wd, obj, name, _icon_size_min_get(wd->img)) ||
683             _icon_standard_set(wd, obj, name);
684          break;
685      }
686
687    if (ret)
688      {
689         eina_stringshare_replace(&wd->stdicon, name);
690         _sizing_eval(obj);
691         return EINA_TRUE;
692      }
693
694    if (_path_is_absolute(name))
695      return _icon_file_set(wd, obj, name);
696
697    /* if that fails, see if icon name is in the format size/name. if so,
698       try locating a fallback without the size specification */
699    if (!(tmp = strchr(name, '/'))) return EINA_FALSE;
700    ++tmp;
701    if (*tmp) return elm_icon_standard_set(obj, tmp);
702
703    /* give up */
704    return EINA_FALSE;
705 }
706
707 /**
708  * Get the theme, as standard, for an icon
709  *
710  * @param obj The icon object
711  * @return The theme name
712  *
713  * @ingroup Icon
714  */
715 EAPI const char *
716 elm_icon_standard_get(const Evas_Object *obj)
717 {
718    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
719    Widget_Data *wd = elm_widget_data_get(obj);
720    if (!wd) return NULL;
721    return wd->stdicon;
722 }
723
724 /**
725  * Sets icon lookup order, used by elm_icon_standard_set().
726  *
727  * @param obj The icon object
728  * @param order The icon lookup order
729  *
730  * @ingroup Icon
731  */
732 EAPI void
733 elm_icon_order_lookup_set(Evas_Object *obj, Elm_Icon_Lookup_Order order)
734 {
735    ELM_CHECK_WIDTYPE(obj, widtype);
736    Widget_Data *wd = elm_widget_data_get(obj);
737    if (wd) wd->lookup_order = order;
738 }
739
740 /**
741  * Gets the icon lookup order.
742  *
743  * @param obj The icon object
744  * @return The icon lookup order
745  *
746  * @ingroup Icon
747  */
748 EAPI Elm_Icon_Lookup_Order
749 elm_icon_order_lookup_get(const Evas_Object *obj)
750 {
751    ELM_CHECK_WIDTYPE(obj, widtype) ELM_ICON_LOOKUP_THEME_FDO;
752    Widget_Data *wd = elm_widget_data_get(obj);
753    if (!wd) return ELM_ICON_LOOKUP_THEME_FDO;
754    return wd->lookup_order;
755 }
756
757 /**
758  * Set the smooth effect for an icon
759  *
760  * @param obj The icon object
761  * @param smooth A bool to set (or no) smooth effect
762  * (1 = smooth, 0 = not smooth)
763  *
764  * @ingroup Icon
765  */
766 EAPI void
767 elm_icon_smooth_set(Evas_Object *obj, Eina_Bool smooth)
768 {
769    ELM_CHECK_WIDTYPE(obj, widtype);
770    Widget_Data *wd = elm_widget_data_get(obj);
771
772    if (!wd) return;
773    wd->smooth = smooth;
774    _sizing_eval(obj);
775 }
776
777 /**
778  * Get the smooth effect for an icon
779  *
780  * @param obj The icon object
781  * @return If setted smooth effect
782  *
783  * @ingroup Icon
784  */
785 EAPI Eina_Bool
786 elm_icon_smooth_get(const Evas_Object *obj)
787 {
788    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
789    Widget_Data *wd = elm_widget_data_get(obj);
790
791    if (!wd) return EINA_FALSE;
792    return wd->smooth;
793 }
794
795 /**
796  * Set if the object is scalable
797  *
798  * @param obj The icon object
799  * @param no_scale A bool to set scale (or no)
800  * (1 = no_scale, 0 = scale)
801  *
802  * @ingroup Icon
803  */
804 EAPI void
805 elm_icon_no_scale_set(Evas_Object *obj, Eina_Bool no_scale)
806 {
807    ELM_CHECK_WIDTYPE(obj, widtype);
808    Widget_Data *wd = elm_widget_data_get(obj);
809
810    if (!wd) return;
811    wd->no_scale = no_scale;
812    _sizing_eval(obj);
813 }
814
815 /**
816  * Get if the object isn't scalable
817  *
818  * @param obj The icon object
819  * @return If isn't scalable
820  *
821  * @ingroup Icon
822  */
823 EAPI Eina_Bool
824 elm_icon_no_scale_get(const Evas_Object *obj)
825 {
826    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
827    Widget_Data *wd = elm_widget_data_get(obj);
828    if (!wd) return EINA_FALSE;
829    return wd->no_scale;
830 }
831
832 /**
833  * Set if the object is (up/down) scalable
834  *
835  * @param obj The icon object
836  * @param scale_up A bool to set if the object is scalable up
837  * @param scale_down A bool to set if the object is scalable down
838  *
839  * @ingroup Icon
840  */
841 EAPI void
842 elm_icon_scale_set(Evas_Object *obj, Eina_Bool scale_up, Eina_Bool scale_down)
843 {
844    ELM_CHECK_WIDTYPE(obj, widtype);
845    Widget_Data *wd = elm_widget_data_get(obj);
846
847    if (!wd) return;
848    wd->scale_up = scale_up;
849    wd->scale_down = scale_down;
850    _sizing_eval(obj);
851 }
852
853 /**
854  * Get if the object is (up/down) scalable
855  *
856  * @param obj The icon object
857  * @param scale_up A bool to set if the object is scalable up
858  * @param scale_down A bool to set if the object is scalable down
859  *
860  * @ingroup Icon
861  */
862 EAPI void
863 elm_icon_scale_get(const Evas_Object *obj, Eina_Bool *scale_up, Eina_Bool *scale_down)
864 {
865    ELM_CHECK_WIDTYPE(obj, widtype);
866    Widget_Data *wd = elm_widget_data_get(obj);
867    if (!wd) return;
868    if (scale_up) *scale_up = wd->scale_up;
869    if (scale_down) *scale_down = wd->scale_down;
870 }
871
872 /**
873  * Set if the object is filled outside
874  *
875  * @param obj The icon object
876  * @param fill_outside A bool to set if the object is filled outside
877  * (1 = filled, 0 = no filled)
878  *
879  * @ingroup Icon
880  */
881 EAPI void
882 elm_icon_fill_outside_set(Evas_Object *obj, Eina_Bool fill_outside)
883 {
884    ELM_CHECK_WIDTYPE(obj, widtype);
885    Widget_Data *wd = elm_widget_data_get(obj);
886
887    if (!wd) return;
888    wd->fill_outside = fill_outside;
889    _sizing_eval(obj);
890 }
891
892 /**
893  * Get if the object is filled outside
894  *
895  * @param obj The icon object
896  * @return If the object is filled outside
897  *
898  * @ingroup Icon
899  */
900 EAPI Eina_Bool
901 elm_icon_fill_outside_get(const Evas_Object *obj)
902 {
903    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
904    Widget_Data *wd = elm_widget_data_get(obj);
905
906    if (!wd) return EINA_FALSE;
907    return wd->fill_outside;
908 }
909
910 /**
911  * Set the prescale size for the icon
912  *
913  * @param obj The icon object
914  * @param size The prescale size
915  *
916  * @ingroup Icon
917  */
918 EAPI void
919 elm_icon_prescale_set(Evas_Object *obj, int size)
920 {
921    ELM_CHECK_WIDTYPE(obj, widtype);
922    Widget_Data *wd = elm_widget_data_get(obj);
923
924    if (!wd) return;
925    _els_smart_icon_scale_size_set(wd->img, size);
926 }
927
928 /**
929  * Get the prescale size for the icon
930  *
931  * @param obj The icon object
932  * @return The prescale size
933  *
934  * @ingroup Icon
935  */
936 EAPI int
937 elm_icon_prescale_get(const Evas_Object *obj)
938 {
939    ELM_CHECK_WIDTYPE(obj, widtype) 0;
940    Widget_Data *wd = elm_widget_data_get(obj);
941
942    if (!wd) return 0;
943    return _els_smart_icon_scale_size_get(wd->img);
944 }