1 #include "e.h"
2 
3 typedef struct _E_Smart_Data E_Smart_Data;
4 typedef struct _Cache_Item   Cache_Item;
5 typedef struct _Cache        Cache;
6 
7 struct _E_Smart_Data
8 {
9    Evas_Coord    x, y, w, h;
10    Evas_Object  *obj;
11    Evas_Object  *eventarea;
12    const char   *fdo;
13    Ecore_Timer  *guessing_animation;
14    Ecore_Timer  *timer, *fdo_reload_timer;
15    double        last_resize;
16    int           size;
17    int           frame, frame_count;
18    unsigned char fill_inside E_BITFIELD;
19    unsigned char scale_up E_BITFIELD;
20    unsigned char preload E_BITFIELD;
21    unsigned char loading E_BITFIELD;
22    unsigned char animated E_BITFIELD;
23    unsigned char invalid E_BITFIELD;
24    Eina_Bool     edje E_BITFIELD;
25 };
26 
27 struct _Cache_Item
28 {
29    unsigned int timestamp;
30 
31    Evas_Object *icon, *obj;
32    const char  *id;
33    Eina_List   *objs;
34 };
35 
36 struct _Cache
37 {
38    Eina_Hash   *hash;
39 
40    char        *file;
41    Eet_File    *ef;
42    Ecore_Timer *timer;
43    Eina_List   *load_queue;
44 };
45 
46 /* local subsystem functions */
47 static void      _e_icon_smart_reconfigure(E_Smart_Data *sd);
48 static void      _e_icon_smart_init(void);
49 static void      _e_icon_smart_add(Evas_Object *obj);
50 static void      _e_icon_smart_del(Evas_Object *obj);
51 static void      _e_icon_smart_move(Evas_Object *obj, Evas_Coord x, Evas_Coord y);
52 static void      _e_icon_smart_resize(Evas_Object *obj, Evas_Coord w, Evas_Coord h);
53 static void      _e_icon_smart_show(Evas_Object *obj);
54 static void      _e_icon_smart_hide(Evas_Object *obj);
55 static void      _e_icon_smart_color_set(Evas_Object *obj, int r, int g, int b, int a);
56 static void      _e_icon_smart_clip_set(Evas_Object *obj, Evas_Object *clip);
57 static void      _e_icon_smart_clip_unset(Evas_Object *obj);
58 static void      _e_icon_obj_prepare(Evas_Object *obj, E_Smart_Data *sd);
59 static void      _e_icon_preloaded(void *data, Evas *e, Evas_Object *obj, void *event_info);
60 
61 /* local subsystem globals */
62 static Evas_Smart *_e_smart = NULL;
63 
64 EINTERN int
e_icon_init(void)65 e_icon_init(void)
66 {
67    return 1;
68 }
69 
70 EINTERN int
e_icon_shutdown(void)71 e_icon_shutdown(void)
72 {
73    return 1;
74 }
75 
76 /* externally accessible functions */
77 E_API Evas_Object *
e_icon_add(Evas * evas)78 e_icon_add(Evas *evas)
79 {
80    _e_icon_smart_init();
81    return evas_object_smart_add(evas, _e_smart);
82 }
83 
84 static void
_e_icon_obj_prepare(Evas_Object * obj,E_Smart_Data * sd)85 _e_icon_obj_prepare(Evas_Object *obj, E_Smart_Data *sd)
86 {
87    if (!sd->obj) return;
88 
89    if (!sd->edje)
90      {
91         Evas_Object *pclip;
92 
93         pclip = evas_object_clip_get(sd->obj);
94         evas_object_del(sd->obj);
95         sd->obj = evas_object_image_add(evas_object_evas_get(obj));
96         if (!sd->animated)
97           evas_object_image_scale_hint_set(sd->obj,
98                                            EVAS_IMAGE_SCALE_HINT_STATIC);
99         evas_object_smart_member_add(sd->obj, obj);
100         evas_object_stack_below(sd->obj, sd->eventarea);
101         evas_object_event_callback_add(sd->obj, EVAS_CALLBACK_IMAGE_PRELOADED,
102                                        _e_icon_preloaded, obj);
103         evas_object_clip_set(sd->obj, pclip);
104      }
105 }
106 
107 static Eina_Bool
_frame_anim(void * data)108 _frame_anim(void *data)
109 {
110    E_Smart_Data *sd = data;
111    double t;
112    int fr;
113 
114    sd->frame++;
115    fr = (sd->frame % (sd->frame_count)) + 1;
116    evas_object_image_animated_frame_set(sd->obj, fr);
117    t = evas_object_image_animated_frame_duration_get(sd->obj, fr, 0);
118    sd->timer = ecore_timer_loop_add(t, _frame_anim, sd);
119    return EINA_FALSE;
120 }
121 
122 static int
_handle_anim(E_Smart_Data * sd)123 _handle_anim(E_Smart_Data *sd)
124 {
125    double t;
126 
127    if (sd->timer) ecore_timer_del(sd->timer);
128    sd->timer = NULL;
129    sd->frame = 0;
130    sd->frame_count = 0;
131    if (!evas_object_image_animated_get(sd->obj)) return 0;
132    sd->frame_count = evas_object_image_animated_frame_count_get(sd->obj);
133    if (sd->frame_count < 2) return 0;
134    if (!sd->invalid) evas_object_show(sd->obj);
135    t = evas_object_image_animated_frame_duration_get(sd->obj, sd->frame, 0);
136    sd->timer = ecore_timer_loop_add(t, _frame_anim, sd);
137    return 1;
138 }
139 
140 E_API void
e_icon_file_set(Evas_Object * obj,const char * file)141 e_icon_file_set(Evas_Object *obj, const char *file)
142 {
143    E_Smart_Data *sd;
144    int len;
145 
146    if (!file) return;
147    if (evas_object_smart_smart_get(obj) != _e_smart) SMARTERR();
148    if (!(sd = evas_object_smart_data_get(obj))) return;
149 
150    len = strlen(file);
151    if ((len > 4) && (!strcasecmp(file + len - 4, ".edj")))
152      {
153         e_icon_file_edje_set(obj, file, "icon");
154         return;
155      }
156 
157    /* smart code here */
158    _e_icon_obj_prepare(obj, sd);
159    /* FIXME: 64x64 - unhappy about this. use icon size */
160    sd->loading = 0;
161    if (sd->fdo)
162      {
163         eina_stringshare_del(sd->fdo);
164         sd->fdo = NULL;
165      }
166 
167    if (sd->timer) ecore_timer_del(sd->timer);
168    sd->timer = NULL;
169    if (sd->guessing_animation) ecore_timer_del(sd->guessing_animation);
170    sd->guessing_animation = NULL;
171    sd->frame = 0;
172    sd->frame_count = 0;
173    sd->invalid = 0;
174    sd->edje = EINA_FALSE;
175 
176    if (sd->size != 0)
177      evas_object_image_load_size_set(sd->obj, sd->size, sd->size);
178    if (sd->preload) evas_object_hide(sd->obj);
179 
180    if (sd->preload)
181      evas_object_image_load_head_skip_set(sd->obj, EINA_TRUE);
182    evas_object_image_file_set(sd->obj, file, NULL);
183 //   if (evas_object_image_load_error_get(sd->obj) != EVAS_LOAD_ERROR_NONE)
184 //     return EINA_FALSE;
185 
186    if (!_handle_anim(sd))
187      {
188         if (sd->preload)
189           {
190              sd->loading = 1;
191              evas_object_image_preload(sd->obj, EINA_FALSE);
192           }
193         else if (evas_object_visible_get(obj))
194           {
195              evas_object_show(sd->obj);
196           }
197      }
198    _e_icon_smart_reconfigure(sd);
199 }
200 
201 E_API void
e_icon_file_key_set(Evas_Object * obj,const char * file,const char * key)202 e_icon_file_key_set(Evas_Object *obj, const char *file, const char *key)
203 {
204    E_Smart_Data *sd;
205 
206    if (evas_object_smart_smart_get(obj) != _e_smart) SMARTERR();
207    if (!(sd = evas_object_smart_data_get(obj))) return;
208 
209    /* smart code here */
210    sd->loading = 0;
211    if (sd->fdo)
212      {
213         eina_stringshare_del(sd->fdo);
214         sd->fdo = NULL;
215      }
216 
217    if (sd->timer) ecore_timer_del(sd->timer);
218    sd->timer = NULL;
219    if (sd->guessing_animation) ecore_timer_del(sd->guessing_animation);
220    sd->guessing_animation = NULL;
221    sd->frame = 0;
222    sd->frame_count = 0;
223    sd->invalid = 0;
224    sd->edje = EINA_FALSE;
225 
226    _e_icon_obj_prepare(obj, sd);
227    if (sd->size != 0)
228      evas_object_image_load_size_set(sd->obj, sd->size, sd->size);
229    if (sd->preload) evas_object_hide(sd->obj);
230    if (sd->preload)
231      evas_object_image_load_head_skip_set(sd->obj, EINA_TRUE);
232    evas_object_image_file_set(sd->obj, file, key);
233 //   if (evas_object_image_load_error_get(sd->obj) != EVAS_LOAD_ERROR_NONE)
234 //     return EINA_FALSE;
235    if (!_handle_anim(sd))
236      {
237         if (sd->preload)
238           {
239              sd->loading = 1;
240              evas_object_image_preload(sd->obj, EINA_FALSE);
241           }
242         else if (evas_object_visible_get(obj))
243           evas_object_show(sd->obj);
244      }
245    _e_icon_smart_reconfigure(sd);
246 }
247 
248 E_API void
e_icon_edje_object_set(Evas_Object * obj,Evas_Object * edje)249 e_icon_edje_object_set(Evas_Object *obj, Evas_Object *edje)
250 {
251    E_Smart_Data *sd;
252 
253    if (evas_object_smart_smart_get(obj) != _e_smart) SMARTERR();
254    if (!(sd = evas_object_smart_data_get(obj))) return;
255 
256    /* smart code here */
257    if (sd->obj) evas_object_del(sd->obj);
258    sd->loading = 0;
259    if (sd->fdo)
260      {
261         eina_stringshare_del(sd->fdo);
262         sd->fdo = NULL;
263      }
264 
265    if (sd->timer) ecore_timer_del(sd->timer);
266    sd->timer = NULL;
267    if (sd->guessing_animation) ecore_timer_del(sd->guessing_animation);
268    sd->guessing_animation = NULL;
269    sd->frame = 0;
270    sd->frame_count = 0;
271    sd->invalid = 0;
272    sd->edje = EINA_TRUE;
273    sd->obj = edje;
274 
275    if (evas_object_visible_get(obj)) evas_object_show(sd->obj);
276    evas_object_smart_member_add(sd->obj, obj);
277    _e_icon_smart_reconfigure(sd);
278 }
279 
280 E_API Evas_Object *
e_icon_edje_get(Evas_Object * obj)281 e_icon_edje_get(Evas_Object *obj)
282 {
283    E_Smart_Data *sd;
284 
285    if (evas_object_smart_smart_get(obj) != _e_smart) SMARTERR(NULL);
286    if (!(sd = evas_object_smart_data_get(obj)))
287      return NULL;
288    return sd->edje ? sd->obj : NULL;
289 }
290 
291 E_API void
e_icon_file_edje_set(Evas_Object * obj,const char * file,const char * part)292 e_icon_file_edje_set(Evas_Object *obj, const char *file, const char *part)
293 {
294    E_Smart_Data *sd;
295 
296    if (evas_object_smart_smart_get(obj) != _e_smart) SMARTERR();
297    if (!(sd = evas_object_smart_data_get(obj))) return;
298 
299    /* smart code here */
300    if (sd->obj) evas_object_del(sd->obj);
301    sd->loading = 0;
302    if (sd->fdo)
303      {
304         eina_stringshare_del(sd->fdo);
305         sd->fdo = NULL;
306      }
307 
308    if (sd->timer) ecore_timer_del(sd->timer);
309    sd->timer = NULL;
310    if (sd->guessing_animation) ecore_timer_del(sd->guessing_animation);
311    sd->guessing_animation = NULL;
312    sd->frame = 0;
313    sd->frame_count = 0;
314    sd->invalid = 0;
315    sd->edje = EINA_TRUE;
316 
317    sd->obj = edje_object_add(evas_object_evas_get(obj));
318    edje_object_file_set(sd->obj, file, part);
319 //   if (edje_object_load_error_get(sd->obj) != EDJE_LOAD_ERROR_NONE)
320 //     return EINA_FALSE;
321    evas_object_smart_member_add(sd->obj, obj);
322    evas_object_stack_below(sd->obj, sd->eventarea);
323    if (evas_object_visible_get(obj)) evas_object_show(sd->obj);
324    _e_icon_smart_reconfigure(sd);
325 }
326 
327 E_API void
e_icon_fdo_icon_set(Evas_Object * obj,const char * icon)328 e_icon_fdo_icon_set(Evas_Object *obj, const char *icon)
329 {
330    E_Smart_Data *sd;
331    const char *path;
332    int len;
333 
334    if (!icon) return;
335    if (evas_object_smart_smart_get(obj) != _e_smart) SMARTERR();
336    if (icon[0] == '/')
337      {
338         e_icon_file_set(obj, icon);
339         return;
340      }
341 
342    if (!(sd = evas_object_smart_data_get(obj))) return;
343 
344    if (sd->timer) ecore_timer_del(sd->timer);
345    sd->timer = NULL;
346    if (sd->guessing_animation) ecore_timer_del(sd->guessing_animation);
347    sd->guessing_animation = NULL;
348    sd->frame = 0;
349    sd->frame_count = 0;
350    sd->invalid = 0;
351    sd->edje = EINA_FALSE;
352 
353    eina_stringshare_replace(&sd->fdo, icon);
354    if (!sd->fdo) return;
355 
356    path = efreet_icon_path_find(e_config->icon_theme, sd->fdo, sd->size);
357    if (!path)
358      {
359         if (e_util_strcmp(e_config->icon_theme, "hicolor"))
360           path = efreet_icon_path_find("hicolor", sd->fdo, sd->size);
361         if (!path) return;
362      }
363 
364    len = strlen(icon);
365    if ((len > 4) && (!strcasecmp(icon + len - 4, ".edj")))
366      {
367         e_icon_file_edje_set(obj, path, "icon");
368         return;
369      }
370 
371    /* smart code here */
372    _e_icon_obj_prepare(obj, sd);
373    sd->loading = 0;
374    if (sd->size != 0)
375      evas_object_image_load_size_set(sd->obj, sd->size, sd->size);
376    if (sd->preload) evas_object_hide(sd->obj);
377    if (sd->preload)
378      evas_object_image_load_head_skip_set(sd->obj, EINA_TRUE);
379    evas_object_image_file_set(sd->obj, path, NULL);
380 //   if (evas_object_image_load_error_get(sd->obj) != EVAS_LOAD_ERROR_NONE)
381 //     return EINA_FALSE;
382    if (sd->preload)
383      {
384         sd->loading = 1;
385         evas_object_image_preload(sd->obj, 0);
386      }
387    else if (evas_object_visible_get(obj))
388      evas_object_show(sd->obj);
389    _e_icon_smart_reconfigure(sd);
390    return;
391 }
392 
393 E_API void
e_icon_image_object_set(Evas_Object * obj,Evas_Object * o)394 e_icon_image_object_set(Evas_Object *obj, Evas_Object *o)
395 {
396    E_Smart_Data *sd;
397    const char *str;
398 
399    if (evas_object_smart_smart_get(obj) != _e_smart) SMARTERR();
400    if (!(sd = evas_object_smart_data_get(obj))) return;
401    str = evas_object_type_get(o);
402    if ((!str) || strcmp(str, "image"))
403      CRI(EINA_COLOR_RED "******************\ntrying to set an image object of type '%s'! this is not what you want!\n******************\n"EINA_COLOR_RESET, str);
404 
405    if (sd->timer) ecore_timer_del(sd->timer);
406    sd->timer = NULL;
407    if (sd->guessing_animation) ecore_timer_del(sd->guessing_animation);
408    sd->guessing_animation = NULL;
409    sd->frame = 0;
410    sd->frame_count = 0;
411    sd->invalid = 0;
412    sd->edje = EINA_FALSE;
413 
414    /* smart code here */
415    if (sd->obj) evas_object_del(sd->obj);
416    sd->loading = 0;
417    sd->obj = o;
418    evas_object_smart_member_add(sd->obj, obj);
419    evas_object_stack_below(sd->obj, sd->eventarea);
420    if (evas_object_visible_get(obj)) evas_object_show(sd->obj);
421    _handle_anim(sd);
422    _e_icon_smart_reconfigure(sd);
423 }
424 
425 E_API Eina_Bool
e_icon_file_get(const Evas_Object * obj,const char ** file,const char ** group)426 e_icon_file_get(const Evas_Object *obj, const char **file, const char **group)
427 {
428    E_Smart_Data *sd;
429 
430    if (evas_object_smart_smart_get(obj) != _e_smart) SMARTERR(EINA_FALSE);
431    if ((!file) && (!group)) return EINA_FALSE;
432    if (file) *file = NULL;
433    if (group) *group = NULL;
434    if (!(sd = evas_object_smart_data_get(obj))) return EINA_FALSE;
435    if (sd->edje)
436      {
437         edje_object_file_get(sd->obj, file, group);
438         return file || group;
439      }
440    evas_object_image_file_get(sd->obj, file, group);
441    return file || group;
442 }
443 
444 E_API void
e_icon_smooth_scale_set(Evas_Object * obj,Eina_Bool smooth)445 e_icon_smooth_scale_set(Evas_Object *obj, Eina_Bool smooth)
446 {
447    E_Smart_Data *sd;
448 
449    if (evas_object_smart_smart_get(obj) != _e_smart) SMARTERRNR();
450    if (!(sd = evas_object_smart_data_get(obj))) return;
451    if (sd->edje) return;
452    evas_object_image_smooth_scale_set(sd->obj, smooth);
453 }
454 
455 E_API Eina_Bool
e_icon_smooth_scale_get(const Evas_Object * obj)456 e_icon_smooth_scale_get(const Evas_Object *obj)
457 {
458    E_Smart_Data *sd;
459 
460    if (evas_object_smart_smart_get(obj) != _e_smart) SMARTERR(0);
461    if (!(sd = evas_object_smart_data_get(obj))) return EINA_FALSE;
462    if (sd->edje)
463      return EINA_FALSE;
464    return evas_object_image_smooth_scale_get(sd->obj);
465 }
466 
467 E_API void
e_icon_alpha_set(Evas_Object * obj,Eina_Bool alpha)468 e_icon_alpha_set(Evas_Object *obj, Eina_Bool alpha)
469 {
470    E_Smart_Data *sd;
471 
472    if (evas_object_smart_smart_get(obj) != _e_smart) SMARTERRNR();
473    if (!(sd = evas_object_smart_data_get(obj))) return;
474    if (sd->edje) return;
475    evas_object_image_alpha_set(sd->obj, alpha);
476 }
477 
478 E_API Eina_Bool
e_icon_alpha_get(const Evas_Object * obj)479 e_icon_alpha_get(const Evas_Object *obj)
480 {
481    E_Smart_Data *sd;
482 
483    if (evas_object_smart_smart_get(obj) != _e_smart) SMARTERR(0);
484    if (!(sd = evas_object_smart_data_get(obj))) return EINA_FALSE;
485    if (sd->edje) return EINA_FALSE;
486    return evas_object_image_alpha_get(sd->obj);
487 }
488 
489 E_API void
e_icon_preload_set(Evas_Object * obj,Eina_Bool preload)490 e_icon_preload_set(Evas_Object *obj, Eina_Bool preload)
491 {
492    E_Smart_Data *sd;
493 
494    if (evas_object_smart_smart_get(obj) != _e_smart) SMARTERRNR();
495    if (!(sd = evas_object_smart_data_get(obj))) return;
496    sd->preload = preload;
497 }
498 
499 E_API Eina_Bool
e_icon_preload_get(const Evas_Object * obj)500 e_icon_preload_get(const Evas_Object *obj)
501 {
502    E_Smart_Data *sd;
503 
504    if (evas_object_smart_smart_get(obj) != _e_smart) SMARTERR(0);
505    if (!(sd = evas_object_smart_data_get(obj))) return EINA_FALSE;
506    return sd->preload;
507 }
508 
509 E_API void
e_icon_size_get(const Evas_Object * obj,int * w,int * h)510 e_icon_size_get(const Evas_Object *obj, int *w, int *h)
511 {
512    E_Smart_Data *sd;
513 
514    if (evas_object_smart_smart_get(obj) != _e_smart) SMARTERRNR();
515    if (!(sd = evas_object_smart_data_get(obj)))
516      {
517         if (w) *w = 0;
518         if (h) *h = 0;
519         return;
520      }
521    if (sd->edje)
522      edje_object_size_min_calc(sd->obj, w, h);
523    else
524      evas_object_image_size_get(sd->obj, w, h);
525 }
526 
527 E_API Eina_Bool
e_icon_fill_inside_get(const Evas_Object * obj)528 e_icon_fill_inside_get(const Evas_Object *obj)
529 {
530    E_Smart_Data *sd;
531 
532    if (evas_object_smart_smart_get(obj) != _e_smart) SMARTERR(0);
533    if (!(sd = evas_object_smart_data_get(obj))) return EINA_FALSE;
534    return sd->fill_inside;
535 }
536 
537 E_API void
e_icon_fill_inside_set(Evas_Object * obj,Eina_Bool fill_inside)538 e_icon_fill_inside_set(Evas_Object *obj, Eina_Bool fill_inside)
539 {
540    E_Smart_Data *sd;
541 
542    if (evas_object_smart_smart_get(obj) != _e_smart) SMARTERRNR();
543    if (!(sd = evas_object_smart_data_get(obj))) return;
544    fill_inside = !!fill_inside;
545    if (sd->fill_inside == fill_inside) return;
546    sd->fill_inside = fill_inside;
547    _e_icon_smart_reconfigure(sd);
548 }
549 
550 E_API Eina_Bool
e_icon_scale_up_get(const Evas_Object * obj)551 e_icon_scale_up_get(const Evas_Object *obj)
552 {
553    E_Smart_Data *sd;
554 
555    if (evas_object_smart_smart_get(obj) != _e_smart) SMARTERR(0);
556    if (!(sd = evas_object_smart_data_get(obj))) return EINA_FALSE;
557    return sd->scale_up;
558 }
559 
560 E_API void
e_icon_scale_up_set(Evas_Object * obj,Eina_Bool scale_up)561 e_icon_scale_up_set(Evas_Object *obj, Eina_Bool scale_up)
562 {
563    E_Smart_Data *sd;
564 
565    if (evas_object_smart_smart_get(obj) != _e_smart) SMARTERRNR();
566    if (!(sd = evas_object_smart_data_get(obj))) return;
567    scale_up = !!scale_up;
568    if (sd->scale_up == scale_up) return;
569    sd->scale_up = scale_up;
570    _e_icon_smart_reconfigure(sd);
571 }
572 
573 E_API void
e_icon_data_set(Evas_Object * obj,void * data,int w,int h)574 e_icon_data_set(Evas_Object *obj, void *data, int w, int h)
575 {
576    E_Smart_Data *sd;
577 
578    if (evas_object_smart_smart_get(obj) != _e_smart) SMARTERRNR();
579    if (!(sd = evas_object_smart_data_get(obj))) return;
580    if (sd->edje) return;
581    evas_object_image_size_set(sd->obj, w, h);
582    evas_object_image_data_copy_set(sd->obj, data);
583 }
584 
585 E_API void *
e_icon_data_get(const Evas_Object * obj,int * w,int * h)586 e_icon_data_get(const Evas_Object *obj, int *w, int *h)
587 {
588    E_Smart_Data *sd;
589 
590    if (evas_object_smart_smart_get(obj) != _e_smart) SMARTERR(NULL);
591    if (!(sd = evas_object_smart_data_get(obj))) return NULL;
592    if (sd->edje) return NULL;
593    evas_object_image_size_get(sd->obj, w, h);
594    return evas_object_image_data_get(sd->obj, 0);
595 }
596 
597 E_API void
e_icon_scale_size_set(Evas_Object * obj,int size)598 e_icon_scale_size_set(Evas_Object *obj, int size)
599 {
600    E_Smart_Data *sd;
601 
602    if (evas_object_smart_smart_get(obj) != _e_smart) SMARTERRNR();
603    if (!(sd = evas_object_smart_data_get(obj))) return;
604    sd->size = size;
605    if (sd->edje) return;
606    evas_object_image_load_size_set(sd->obj, sd->size, sd->size);
607 }
608 
609 E_API int
e_icon_scale_size_get(const Evas_Object * obj)610 e_icon_scale_size_get(const Evas_Object *obj)
611 {
612    E_Smart_Data *sd;
613 
614    if (evas_object_smart_smart_get(obj) != _e_smart) SMARTERR(0);
615    if (!(sd = evas_object_smart_data_get(obj))) return 0;
616    return sd->size;
617 }
618 
619 E_API void
e_icon_selected_set(const Evas_Object * obj,Eina_Bool selected)620 e_icon_selected_set(const Evas_Object *obj, Eina_Bool selected)
621 {
622    E_Smart_Data *sd;
623 
624    if (evas_object_smart_smart_get(obj) != _e_smart) SMARTERRNR();
625    if (!(sd = evas_object_smart_data_get(obj))) return;
626    if (!sd->edje) return;
627    if (selected)
628      edje_object_signal_emit(sd->obj, "e,state,selected", "e");
629    else
630      edje_object_signal_emit(sd->obj, "e,state,unselected", "e");
631 }
632 
633 E_API void
e_icon_edje_emit(const Evas_Object * obj,const char * sig,const char * src)634 e_icon_edje_emit(const Evas_Object *obj, const char *sig, const char *src)
635 {
636    E_Smart_Data *sd;
637 
638    if (evas_object_smart_smart_get(obj) != _e_smart) SMARTERR();
639    if (!(sd = evas_object_smart_data_get(obj))) return;
640    edje_object_signal_emit(sd->obj, sig, src);
641 }
642 
643 /* local subsystem globals */
644 static void
_e_icon_smart_reconfigure(E_Smart_Data * sd)645 _e_icon_smart_reconfigure(E_Smart_Data *sd)
646 {
647    int iw, ih;
648    Evas_Coord x, y, w, h;
649 
650    if (!sd->obj) return;
651    w = sd->w;
652    h = sd->h;
653    x = sd->x;
654    y = sd->y;
655    if (!sd->loading)
656      {
657         if (sd->edje)
658           {
659              evas_object_move(sd->obj, x, y);
660              evas_object_resize(sd->obj, w, h);
661           }
662         else
663           {
664              iw = 0;
665              ih = 0;
666              evas_object_image_size_get(sd->obj, &iw, &ih);
667              if (iw < 1) iw = 1;
668              if (ih < 1) ih = 1;
669 
670              if (sd->fill_inside)
671                {
672                   w = sd->w;
673                   h = ((double)ih * w) / (double)iw;
674                   if (h > sd->h)
675                     {
676                        h = sd->h;
677                        w = ((double)iw * h) / (double)ih;
678                     }
679                }
680              else
681                {
682                   w = sd->w;
683                   h = ((double)ih * w) / (double)iw;
684                   if (h < sd->h)
685                     {
686                        h = sd->h;
687                        w = ((double)iw * h) / (double)ih;
688                     }
689                }
690              if (!sd->scale_up)
691                {
692                   if ((w > iw) || (h > ih))
693                     {
694                        w = iw;
695                        h = ih;
696                     }
697                }
698              x = sd->x + ((sd->w - w) / 2);
699              y = sd->y + ((sd->h - h) / 2);
700              evas_object_move(sd->obj, x, y);
701              evas_object_image_fill_set(sd->obj, 0, 0, w, h);
702              evas_object_resize(sd->obj, w, h);
703           }
704      }
705    evas_object_move(sd->eventarea, x, y);
706    evas_object_resize(sd->eventarea, w, h);
707 }
708 
709 static void
_e_icon_smart_init(void)710 _e_icon_smart_init(void)
711 {
712    if (_e_smart) return;
713    {
714       static Evas_Smart_Class sc = EVAS_SMART_CLASS_INIT_NAME_VERSION("e_icon");
715       if (!sc.add)
716         {
717            sc.add = _e_icon_smart_add;
718            sc.del = _e_icon_smart_del;
719            sc.move = _e_icon_smart_move;
720            sc.resize = _e_icon_smart_resize;
721            sc.show = _e_icon_smart_show;
722            sc.hide = _e_icon_smart_hide;
723            sc.color_set = _e_icon_smart_color_set;
724            sc.clip_set = _e_icon_smart_clip_set;
725            sc.clip_unset = _e_icon_smart_clip_unset;
726         }
727       _e_smart = evas_smart_class_new(&sc);
728    }
729 }
730 
731 static void
_e_icon_preloaded(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)732 _e_icon_preloaded(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
733 {
734    E_Smart_Data *sd;
735    int iw, ih;
736 
737    if (!(sd = evas_object_smart_data_get(data))) return;
738 
739    evas_object_smart_callback_call(data, "preloaded", NULL);
740    evas_object_image_size_get(sd->obj, &iw, &ih);
741    if ((iw > 0) && (ih > 0))
742      {
743         sd->invalid = 0;
744         evas_object_show(sd->obj);
745      }
746    else
747      sd->invalid = 1;
748    sd->loading = 0;
749    _e_icon_smart_reconfigure(sd);
750 }
751 
752 static void
_e_icon_smart_add(Evas_Object * obj)753 _e_icon_smart_add(Evas_Object *obj)
754 {
755    E_Smart_Data *sd;
756 
757    if (!(sd = calloc(1, sizeof(E_Smart_Data)))) return;
758 
759    sd->obj = evas_object_image_add(evas_object_evas_get(obj));
760    evas_object_event_callback_add(sd->obj, EVAS_CALLBACK_IMAGE_PRELOADED,
761                                   _e_icon_preloaded, obj);
762 
763    sd->eventarea = evas_object_rectangle_add(evas_object_evas_get(obj));
764    evas_object_color_set(sd->eventarea, 0, 0, 0, 0);
765    evas_object_smart_member_add(sd->eventarea, obj);
766 
767    sd->x = 0;
768    sd->y = 0;
769    sd->w = 0;
770    sd->h = 0;
771    sd->fill_inside = 1;
772    sd->scale_up = 1;
773    sd->size = 64;
774    sd->preload = 0;
775    evas_object_smart_member_add(sd->obj, obj);
776    evas_object_smart_data_set(obj, sd);
777 }
778 
779 static void
_e_icon_smart_del(Evas_Object * obj)780 _e_icon_smart_del(Evas_Object *obj)
781 {
782    E_Smart_Data *sd;
783 
784    if (!(sd = evas_object_smart_data_get(obj))) return;
785    evas_object_del(sd->obj);
786    evas_object_del(sd->eventarea);
787    if (sd->fdo) eina_stringshare_del(sd->fdo);
788    if (sd->fdo_reload_timer) ecore_timer_del(sd->fdo_reload_timer);
789    if (sd->timer) ecore_timer_del(sd->timer);
790    if (sd->guessing_animation) ecore_timer_del(sd->guessing_animation);
791    evas_object_smart_data_set(obj, NULL);
792    memset(sd, 0, sizeof(*sd));
793    free(sd);
794 }
795 
796 static void
_e_icon_smart_move(Evas_Object * obj,Evas_Coord x,Evas_Coord y)797 _e_icon_smart_move(Evas_Object *obj, Evas_Coord x, Evas_Coord y)
798 {
799    E_Smart_Data *sd;
800 
801    if (!(sd = evas_object_smart_data_get(obj))) return;
802    if ((sd->x == x) && (sd->y == y)) return;
803    sd->x = x;
804    sd->y = y;
805    _e_icon_smart_reconfigure(sd);
806 }
807 
808 static Eina_Bool
_e_icon_guess_anim(void * data)809 _e_icon_guess_anim(void *data)
810 {
811    E_Smart_Data *sd = data;
812    double t = ecore_loop_time_get();
813 
814    if (t - sd->last_resize < 0.2)
815      {
816         evas_object_image_scale_hint_set(sd->obj,
817                                          EVAS_IMAGE_SCALE_HINT_DYNAMIC);
818         sd->animated = EINA_TRUE;
819      }
820    else
821      {
822         evas_object_image_scale_hint_set(sd->obj,
823                                          EVAS_IMAGE_SCALE_HINT_STATIC);
824      }
825 
826    sd->guessing_animation = NULL;
827    return EINA_FALSE;
828 }
829 
830 static Eina_Bool
_e_icon_fdo_reload(void * data)831 _e_icon_fdo_reload(void *data)
832 {
833    E_Smart_Data *sd = data;
834    const char *path;
835 
836    sd->fdo_reload_timer = NULL;
837    sd->size = MAX(sd->w, sd->h);
838    path = efreet_icon_path_find(e_config->icon_theme, sd->fdo, sd->size);
839    if (!path)
840      {
841         if (e_util_strcmp(e_config->icon_theme, "hicolor"))
842           path = efreet_icon_path_find("hicolor", sd->fdo, sd->size);
843         if (!path) return EINA_FALSE;
844      }
845 
846 
847    /* smart code here */
848    evas_object_image_load_size_set(sd->obj, sd->size, sd->size);
849    evas_object_image_file_set(sd->obj, path, NULL);
850    if (sd->preload)
851      {
852         sd->loading = 1;
853         evas_object_image_preload(sd->obj, 0);
854      }
855    return EINA_FALSE;
856 }
857 
858 static void
_e_icon_smart_resize(Evas_Object * obj,Evas_Coord w,Evas_Coord h)859 _e_icon_smart_resize(Evas_Object *obj, Evas_Coord w, Evas_Coord h)
860 {
861    E_Smart_Data *sd;
862 
863    if (!(sd = evas_object_smart_data_get(obj))) return;
864    if ((sd->w == w) && (sd->h == h)) return;
865    sd->w = w;
866    sd->h = h;
867    if (sd->fdo)
868      {
869         if (sd->fdo_reload_timer) ecore_timer_del(sd->fdo_reload_timer);
870         sd->fdo_reload_timer = ecore_timer_loop_add(0.1, _e_icon_fdo_reload, sd);
871      }
872 
873    if ((!sd->edje) && ((sd->loading && sd->preload) ||
874                        (!sd->loading && !sd->preload))
875        && !sd->animated)
876      {
877         evas_object_image_scale_hint_set(sd->obj,
878                                          EVAS_IMAGE_SCALE_HINT_DYNAMIC);
879         if (!sd->guessing_animation)
880           sd->guessing_animation = ecore_timer_loop_add(0.3,
881                                                    _e_icon_guess_anim,
882                                                    sd);
883      }
884 
885    sd->last_resize = ecore_loop_time_get();
886    _e_icon_smart_reconfigure(sd);
887 }
888 
889 static void
_e_icon_smart_show(Evas_Object * obj)890 _e_icon_smart_show(Evas_Object *obj)
891 {
892    E_Smart_Data *sd;
893 
894    if (!(sd = evas_object_smart_data_get(obj))) return;
895    if (!((sd->preload) && (sd->loading)))
896      {
897         if (!sd->invalid) evas_object_show(sd->obj);
898      }
899 
900    evas_object_show(sd->eventarea);
901 }
902 
903 static void
_e_icon_smart_hide(Evas_Object * obj)904 _e_icon_smart_hide(Evas_Object *obj)
905 {
906    E_Smart_Data *sd;
907 
908    if (!(sd = evas_object_smart_data_get(obj))) return;
909    evas_object_hide(sd->obj);
910    evas_object_hide(sd->eventarea);
911 }
912 
913 static void
_e_icon_smart_color_set(Evas_Object * obj,int r,int g,int b,int a)914 _e_icon_smart_color_set(Evas_Object *obj, int r, int g, int b, int a)
915 {
916    E_Smart_Data *sd;
917 
918    if (!(sd = evas_object_smart_data_get(obj))) return;
919    evas_object_color_set(sd->obj, r, g, b, a);
920 }
921 
922 static void
_e_icon_smart_clip_set(Evas_Object * obj,Evas_Object * clip)923 _e_icon_smart_clip_set(Evas_Object *obj, Evas_Object *clip)
924 {
925    E_Smart_Data *sd;
926 
927    if (!(sd = evas_object_smart_data_get(obj))) return;
928    evas_object_clip_set(sd->obj, clip);
929    evas_object_clip_set(sd->eventarea, clip);
930 }
931 
932 static void
_e_icon_smart_clip_unset(Evas_Object * obj)933 _e_icon_smart_clip_unset(Evas_Object *obj)
934 {
935    E_Smart_Data *sd;
936 
937    if (!(sd = evas_object_smart_data_get(obj))) return;
938    evas_object_clip_unset(sd->obj);
939    evas_object_clip_unset(sd->eventarea);
940 }
941