[els_icon] preload off by default
[framework/uifw/elementary.git] / src / lib / els_icon.c
1 #include <Elementary.h>
2 #include "elm_priv.h"
3
4 typedef struct _Smart_Data Smart_Data;
5
6 struct _Smart_Data
7 {
8    Evas_Coord   x, y, w, h;
9    Evas_Object *obj;
10    int          size;
11    double       scale;
12    unsigned char fill_inside : 1;
13    unsigned char scale_up : 1;
14    unsigned char scale_down : 1;
15    unsigned char preloading : 1;
16    unsigned char show : 1;
17 };
18
19 /* local subsystem functions */
20 static void _smart_reconfigure(Smart_Data *sd);
21 static void _smart_init(void);
22 static void _smart_add(Evas_Object *obj);
23 static void _smart_del(Evas_Object *obj);
24 static void _smart_move(Evas_Object *obj, Evas_Coord x, Evas_Coord y);
25 static void _smart_resize(Evas_Object *obj, Evas_Coord w, Evas_Coord h);
26 static void _smart_show(Evas_Object *obj);
27 static void _smart_hide(Evas_Object *obj);
28 static void _smart_color_set(Evas_Object *obj, int r, int g, int b, int a);
29 static void _smart_clip_set(Evas_Object *obj, Evas_Object * clip);
30 static void _smart_clip_unset(Evas_Object *obj);
31
32 static void _els_smart_icon_flip_horizontal(Smart_Data *sd);
33 static void _els_smart_icon_flip_vertical(Smart_Data *sd);
34 static void _els_smart_icon_rotate_180(Smart_Data *sd);
35
36 /* local subsystem globals */
37 static Evas_Smart *_e_smart = NULL;
38
39 /* externally accessible functions */
40 Evas_Object *
41 _els_smart_icon_add(Evas *evas)
42 {
43    _smart_init();
44    return evas_object_smart_add(evas, _e_smart);
45 }
46
47 Eina_Bool
48 _els_smart_icon_file_key_set(Evas_Object *obj, const char *file, const char *key)
49 {
50    Smart_Data *sd;
51
52    sd = evas_object_smart_data_get(obj);
53    if (!sd) return EINA_FALSE;
54    /* smart code here */
55    if (sd->size != 0)
56      evas_object_image_load_size_set(sd->obj, sd->size, sd->size);
57    evas_object_image_file_set(sd->obj, file, key);
58    /* by default preload off by seok.j.jeong */
59    sd->preloading = 0;
60    sd->show = 1;
61    if (sd->preloading)
62      evas_object_image_preload(sd->obj, EINA_FALSE);
63    if (sd->preloading)
64      evas_object_hide(sd->obj);
65    if (evas_object_image_load_error_get(sd->obj) != EVAS_LOAD_ERROR_NONE)
66      return EINA_FALSE;
67    _smart_reconfigure(sd);
68    return EINA_TRUE;
69 }
70
71 Eina_Bool
72 _els_smart_icon_file_edje_set(Evas_Object *obj, const char *file, const char *part)
73 {
74    Smart_Data *sd;
75
76    sd = evas_object_smart_data_get(obj);
77    if (!sd) return EINA_FALSE;
78    /* smart code here */
79    if (sd->obj) evas_object_del(sd->obj);
80    sd->obj = edje_object_add(evas_object_evas_get(obj));
81    evas_object_smart_member_add(sd->obj, obj);
82    if (!edje_object_file_set(sd->obj, file, part))
83      return EINA_FALSE;
84    _smart_reconfigure(sd);
85    return EINA_TRUE;
86 }
87
88 void
89 _els_smart_icon_smooth_scale_set(Evas_Object *obj, int smooth)
90 {
91    Smart_Data *sd;
92
93    sd = evas_object_smart_data_get(obj);
94    if (!sd) return;
95    if (!strcmp(evas_object_type_get(sd->obj), "edje"))
96      return;
97    evas_object_image_smooth_scale_set(sd->obj, smooth);
98 }
99
100 Evas_Object *
101 _els_smart_icon_object_get(Evas_Object *obj)
102 {
103    Smart_Data *sd;
104    sd = evas_object_smart_data_get(obj);
105    if (!sd) return NULL;
106    return sd->obj;
107 }
108
109 void
110 _els_smart_icon_size_get(Evas_Object *obj, int *w, int *h)
111 {
112    Smart_Data *sd;
113    int tw, th;
114
115    sd = evas_object_smart_data_get(obj);
116    if (!sd) return;
117    if (!strcmp(evas_object_type_get(sd->obj), "edje"))
118      edje_object_size_min_get(sd->obj, &tw, &th);
119    else
120      evas_object_image_size_get(sd->obj, &tw, &th);
121    tw = ((double)tw) * sd->scale;
122    th = ((double)th) * sd->scale;
123    if (w) *w = tw;
124    if (h) *h = th;
125 }
126
127 void
128 _els_smart_icon_fill_inside_set(Evas_Object *obj, int fill_inside)
129 {
130    Smart_Data *sd;
131
132    sd = evas_object_smart_data_get(obj);
133    if (!sd) return;
134    if (((sd->fill_inside) && (fill_inside)) ||
135        ((!sd->fill_inside) && (!fill_inside))) return;
136    sd->fill_inside = fill_inside;
137    _smart_reconfigure(sd);
138 }
139
140 void
141 _els_smart_icon_scale_up_set(Evas_Object *obj, int scale_up)
142 {
143    Smart_Data *sd;
144
145    sd = evas_object_smart_data_get(obj);
146    if (!sd) return;
147    if (((sd->scale_up) && (scale_up)) ||
148        ((!sd->scale_up) && (!scale_up))) return;
149    sd->scale_up = scale_up;
150    _smart_reconfigure(sd);
151 }
152
153 void
154 _els_smart_icon_scale_down_set(Evas_Object *obj, int scale_down)
155 {
156    Smart_Data *sd;
157
158    sd = evas_object_smart_data_get(obj);
159    if (!sd) return;
160    if (((sd->scale_down) && (scale_down)) ||
161        ((!sd->scale_down) && (!scale_down))) return;
162    sd->scale_down = scale_down;
163    _smart_reconfigure(sd);
164 }
165
166 void
167 _els_smart_icon_scale_size_set(Evas_Object *obj, int size)
168 {
169    Smart_Data *sd;
170
171    sd = evas_object_smart_data_get(obj);
172    if (!sd) return;
173    sd->size = size;
174    if (!sd->obj) return;
175    if (!strcmp(evas_object_type_get(sd->obj), "edje"))
176      return;
177    evas_object_image_load_size_set(sd->obj, sd->size, sd->size);
178 }
179
180 void
181 _els_smart_icon_scale_set(Evas_Object *obj, double scale)
182 {
183    Smart_Data *sd;
184
185    sd = evas_object_smart_data_get(obj);
186    if (!sd) return;
187    sd->scale = scale;
188    _smart_reconfigure(sd);
189 }
190
191 void
192 _els_smart_icon_orient_set(Evas_Object *obj, Elm_Image_Orient orient)
193 {
194    Smart_Data *sd;
195    Evas_Object    *tmp;
196    unsigned int   *data, *data2, *to, *from;
197    int             x, y, w, hw, iw, ih;
198    const char     *file, *key;
199
200    sd = evas_object_smart_data_get(obj);
201    if (!sd) return;
202    if (!strcmp(evas_object_type_get(sd->obj), "edje"))
203      return;
204
205    switch (orient)
206      {
207       case ELM_IMAGE_FLIP_HORIZONTAL:
208          _els_smart_icon_flip_horizontal(sd);
209          return;
210       case ELM_IMAGE_FLIP_VERTICAL:
211          _els_smart_icon_flip_vertical(sd);
212          return;
213       case ELM_IMAGE_ROTATE_180_CW:
214          _els_smart_icon_rotate_180(sd);
215          return;
216      default:
217         return;
218      }
219
220    evas_object_image_size_get(sd->obj, &iw, &ih);
221    evas_object_image_file_get(sd->obj, &file, &key);
222    tmp = evas_object_image_add(evas_object_evas_get(sd->obj));
223    evas_object_image_file_set(tmp, file, key);
224    data2 = evas_object_image_data_get(tmp, 0);
225
226    w = ih;
227    ih = iw;
228    iw = w;
229    hw = w * ih;
230
231    evas_object_image_size_set(sd->obj, iw, ih);
232    data = evas_object_image_data_get(sd->obj, 1);
233    switch (orient)
234      {
235       case ELM_IMAGE_FLIP_TRANSPOSE:
236          to = data;
237          hw = -hw + 1;
238          break;
239       case ELM_IMAGE_FLIP_TRANSVERSE:
240          to = data + hw - 1;
241          w = -w;
242          hw = hw - 1;
243          break;
244       case ELM_IMAGE_ROTATE_90_CW:
245          to = data + w - 1;
246          hw = -hw - 1;
247          break;
248       case ELM_IMAGE_ROTATE_90_CCW:
249          to = data + hw - w;
250          w = -w;
251          hw = hw + 1;
252          break;
253       default:
254          ERR("unknown orient %d", orient);
255          evas_object_del(tmp);
256          evas_object_image_data_set(sd->obj, data); // give it back
257          return;
258      }
259    from = data2;
260    for (x = iw; --x >= 0;)
261      {
262         for (y = ih; --y >= 0;)
263           {
264              *to = *from;
265              from++;
266              to += w;
267           }
268         to += hw;
269      }
270    evas_object_del(tmp);
271    evas_object_image_data_set(sd->obj, data);
272    evas_object_image_data_update_add(sd->obj, 0, 0, iw, ih);
273    _smart_reconfigure(sd);
274 }
275
276 /* local subsystem globals */
277 static void
278 _smart_reconfigure(Smart_Data *sd)
279 {
280    int iw, ih;
281    Evas_Coord x, y, w, h;
282
283    if (!sd->obj) return;
284    if (!strcmp(evas_object_type_get(sd->obj), "edje"))
285      {
286         w = sd->w;
287         h = sd->h;
288         x = sd->x;
289         y = sd->y;
290         evas_object_move(sd->obj, x, y);
291         evas_object_resize(sd->obj, w, h);
292      }
293    else
294      {
295         iw = 0;
296         ih = 0;
297         evas_object_image_size_get(sd->obj, &iw, &ih);
298
299         iw = ((double)iw) * sd->scale;
300         ih = ((double)ih) * sd->scale;
301
302         if (iw < 1) iw = 1;
303         if (ih < 1) ih = 1;
304
305         if (sd->fill_inside)
306           {
307              w = sd->w;
308              h = ((double)ih * w) / (double)iw;
309              if (h > sd->h)
310                {
311                   h = sd->h;
312                   w = ((double)iw * h) / (double)ih;
313                }
314           }
315         else
316           {
317              w = sd->w;
318              h = ((double)ih * w) / (double)iw;
319              if (h < sd->h)
320                {
321                   h = sd->h;
322                   w = ((double)iw * h) / (double)ih;
323                }
324           }
325         if (!sd->scale_up)
326           {
327              if ((w > iw) || (h > ih))
328                {
329                   w = iw;
330                   h = ih;
331                }
332           }
333         if (!sd->scale_down)
334           {
335              if ((w < iw) || (h < ih))
336                {
337                   w = iw;
338                   h = ih;
339                }
340           }
341         x = sd->x + ((sd->w - w) / 2);
342         y = sd->y + ((sd->h - h) / 2);
343         evas_object_move(sd->obj, x, y);
344         evas_object_image_fill_set(sd->obj, 0, 0, w, h);
345         evas_object_resize(sd->obj, w, h);
346      }
347 }
348
349 static void
350 _preloaded(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event __UNUSED__)
351 {
352    Smart_Data *sd = data;
353
354    sd->preloading = 0;
355    if(sd->show)
356      evas_object_show(sd->obj);
357 }
358
359 static void
360 _smart_init(void)
361 {
362    if (_e_smart) return;
363      {
364         static const Evas_Smart_Class sc =
365           {
366              "e_icon",
367                EVAS_SMART_CLASS_VERSION,
368                _smart_add,
369                _smart_del,
370                _smart_move,
371                _smart_resize,
372                _smart_show,
373                _smart_hide,
374                _smart_color_set,
375                _smart_clip_set,
376                _smart_clip_unset,
377                NULL,
378                NULL,
379                NULL,
380                NULL,
381                NULL,
382                NULL,
383                NULL
384           };
385         _e_smart = evas_smart_class_new(&sc);
386      }
387 }
388
389 static void
390 _smart_add(Evas_Object *obj)
391 {
392    Smart_Data *sd;
393
394    sd = calloc(1, sizeof(Smart_Data));
395    if (!sd) return;
396    sd->obj = evas_object_image_add(evas_object_evas_get(obj));
397    evas_object_image_scale_hint_set(sd->obj, EVAS_IMAGE_SCALE_HINT_STATIC);
398    sd->x = 0;
399    sd->y = 0;
400    sd->w = 0;
401    sd->h = 0;
402    sd->fill_inside = 1;
403    sd->scale_up = 1;
404    sd->scale_down = 1;
405    sd->size = 64;
406    sd->scale = 1.0;
407    evas_object_smart_member_add(sd->obj, obj);
408    evas_object_smart_data_set(obj, sd);
409    evas_object_event_callback_add(sd->obj, EVAS_CALLBACK_IMAGE_PRELOADED, _preloaded, sd);
410 }
411
412 static void
413 _smart_del(Evas_Object *obj)
414 {
415    Smart_Data *sd;
416
417    sd = evas_object_smart_data_get(obj);
418    if (!sd) return;
419    evas_object_del(sd->obj);
420    free(sd);
421 }
422
423 static void
424 _smart_move(Evas_Object *obj, Evas_Coord x, Evas_Coord y)
425 {
426    Smart_Data *sd;
427
428    sd = evas_object_smart_data_get(obj);
429    if (!sd) return;
430    if ((sd->x == x) && (sd->y == y)) return;
431    sd->x = x;
432    sd->y = y;
433    _smart_reconfigure(sd);
434 }
435
436 static void
437 _smart_resize(Evas_Object *obj, Evas_Coord w, Evas_Coord h)
438 {
439    Smart_Data *sd;
440
441    sd = evas_object_smart_data_get(obj);
442    if (!sd) return;
443    if ((sd->w == w) && (sd->h == h)) return;
444    sd->w = w;
445    sd->h = h;
446    _smart_reconfigure(sd);
447 }
448
449 static void
450 _smart_show(Evas_Object *obj)
451 {
452    Smart_Data *sd;
453
454    sd = evas_object_smart_data_get(obj);
455    if (!sd) return;
456    sd->show = 1;
457    if(!sd->preloading)
458            evas_object_show(sd->obj);
459 }
460
461 static void
462 _smart_hide(Evas_Object *obj)
463 {
464    Smart_Data *sd;
465
466    sd = evas_object_smart_data_get(obj);
467    if (!sd) return;
468    sd->show = 0;
469    evas_object_hide(sd->obj);
470 }
471
472 static void
473 _smart_color_set(Evas_Object *obj, int r, int g, int b, int a)
474 {
475    Smart_Data *sd;
476
477    sd = evas_object_smart_data_get(obj);
478    if (!sd) return;
479    evas_object_color_set(sd->obj, r, g, b, a);
480 }
481
482 static void
483 _smart_clip_set(Evas_Object *obj, Evas_Object * clip)
484 {
485    Smart_Data *sd;
486
487    sd = evas_object_smart_data_get(obj);
488    if (!sd) return;
489    evas_object_clip_set(sd->obj, clip);
490 }
491
492 static void
493 _smart_clip_unset(Evas_Object *obj)
494 {
495    Smart_Data *sd;
496
497    sd = evas_object_smart_data_get(obj);
498    if (!sd) return;
499    evas_object_clip_unset(sd->obj);
500 }
501
502 static void
503 _els_smart_icon_flip_horizontal(Smart_Data *sd)
504 {
505    unsigned int   *data;
506    unsigned int   *p1, *p2, tmp;
507    int             x, y, iw, ih;
508
509    evas_object_image_size_get(sd->obj, &iw, &ih);
510    data = evas_object_image_data_get(sd->obj, 1);
511
512    for (y = 0; y < ih; y++)
513      {
514         p1 = data + (y * iw);
515         p2 = data + ((y + 1) * iw) - 1;
516         for (x = 0; x < (iw >> 1); x++)
517           {
518              tmp = *p1;
519              *p1 = *p2;
520              *p2 = tmp;
521              p1++;
522              p2--;
523           }
524      }
525
526    evas_object_image_data_set(sd->obj, data);
527    evas_object_image_data_update_add(sd->obj, 0, 0, iw, ih);
528    _smart_reconfigure(sd);
529 }
530
531 static void
532 _els_smart_icon_flip_vertical(Smart_Data *sd)
533 {
534    unsigned int   *data;
535    unsigned int   *p1, *p2, tmp;
536    int             x, y, iw, ih;
537
538    evas_object_image_size_get(sd->obj, &iw, &ih);
539    data = evas_object_image_data_get(sd->obj, 1);
540
541    for (y = 0; y < (ih >> 1); y++)
542      {
543         p1 = data + (y * iw);
544         p2 = data + ((ih - 1 - y) * iw);
545         for (x = 0; x < iw; x++)
546           {
547              tmp = *p1;
548              *p1 = *p2;
549              *p2 = tmp;
550              p1++;
551              p2++;
552           }
553      }
554
555    evas_object_image_data_set(sd->obj, data);
556    evas_object_image_data_update_add(sd->obj, 0, 0, iw, ih);
557    _smart_reconfigure(sd);
558 }
559
560 static void
561 _els_smart_icon_rotate_180(Smart_Data *sd)
562 {
563    unsigned int   *data;
564    unsigned int   *p1, *p2, tmp;
565    int             x, hw, iw, ih;
566
567    evas_object_image_size_get(sd->obj, &iw, &ih);
568    data = evas_object_image_data_get(sd->obj, 1);
569
570    hw = iw * ih;
571    x = (hw / 2);
572    p1 = data;
573    p2 = data + hw - 1;
574    for (; --x > 0;)
575      {
576         tmp = *p1;
577         *p1 = *p2;
578         *p2 = tmp;
579         p1++;
580         p2--;
581      }
582    evas_object_image_data_set(sd->obj, data);
583    evas_object_image_data_update_add(sd->obj, 0, 0, iw, ih);
584    _smart_reconfigure(sd);
585 }
586