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