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