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