Use the rotation information to loads an image.
[platform/framework/web/livebox-edje.git] / src / script_port.c
1 /*
2  * Copyright 2012  Samsung Electronics Co., Ltd
3  *
4  * Licensed under the Flora License, Version 1.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.tizenopensource.org/license
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <stdio.h>
18 #include <libgen.h>
19 #include <errno.h>
20 #include <unistd.h>
21
22 #include <Evas.h>
23 #include <Edje.h>
24 #include <Eina.h>
25 #include <Ecore.h>
26 #include <Ecore_Evas.h>
27 #include <Eet.h>
28 #include <Ecore_X.h>
29
30 #include <dlog.h>
31 #include <debug.h>
32 #include <vconf.h>
33
34 #include "script_port.h"
35
36 #define TEXT_CLASS      "tizen"
37
38 extern void evas_common_font_flush(void);
39 extern int evas_common_font_cache_get(void);
40 extern void evas_common_font_cache_set(int size);
41
42 struct info {
43         char *file;
44         char *group;
45         char *category;
46         int w;
47         int h;
48
49         Evas *e;
50
51         Eina_List *obj_list;
52 };
53
54 struct child {
55         Evas_Object *obj;
56         char *part;
57 };
58
59 struct obj_info {
60         char *id;
61         Eina_List *children;
62 };
63
64 struct {
65         Ecore_Event_Handler *property_handler;
66         char *font;
67         int size;
68 } s_info = {
69         .property_handler = NULL,
70         .font = NULL,
71         .size = -100,
72 };
73
74 /*!
75  * \NOTE
76  * Reservce this for future use
77 static inline void common_cache_flush(void *evas)
78 {
79         int file_cache;
80         int collection_cache;
81         int image_cache;
82         int font_cache;
83
84         file_cache = edje_file_cache_get();
85         collection_cache = edje_collection_cache_get();
86         image_cache = evas_image_cache_get(evas);
87         font_cache = evas_font_cache_get(evas);
88
89         edje_file_cache_set(file_cache);
90         edje_collection_cache_set(collection_cache);
91         evas_image_cache_set(evas, 0);
92         evas_font_cache_set(evas, 0);
93
94         evas_image_cache_flush(evas);
95         evas_render_idle_flush(evas);
96         evas_font_cache_flush(evas);
97
98         edje_file_cache_flush();
99         edje_collection_cache_flush();
100
101         edje_file_cache_set(file_cache);
102         edje_collection_cache_set(collection_cache);
103         evas_image_cache_set(evas, image_cache);
104         evas_font_cache_set(evas, font_cache);
105
106         eet_clearcache();
107 }
108  */
109
110 static inline Evas_Object *find_edje(struct info *handle, const char *id)
111 {
112         Eina_List *l;
113         Evas_Object *edje;
114         struct obj_info *obj_info;
115
116         EINA_LIST_FOREACH(handle->obj_list, l, edje) {
117                 obj_info = evas_object_data_get(edje, "obj_info");
118                 if (!obj_info) {
119                         ErrPrint("Object info is not valid\n");
120                         continue;
121                 }
122
123                 if (!id) {
124                         if (!obj_info->id)
125                                 return edje;
126
127                         continue;
128                 } else if (!obj_info->id) {
129                         continue;
130                 }
131
132                 if (!strcmp(obj_info->id, id))
133                         return edje;
134         }
135
136         DbgPrint("EDJE[%s] is not found\n", id);
137         return NULL;
138 }
139
140 const char *script_magic_id(void)
141 {
142         return "edje";
143 }
144
145 int script_update_color(void *h, Evas *e, const char *id, const char *part, const char *rgba)
146 {
147         struct info *handle = h;
148         Evas_Object *edje;
149         int r[3], g[3], b[3], a[3];
150         int ret;
151
152         edje = find_edje(handle, id);
153         if (!edje)
154                 return -ENOENT;
155
156         ret = sscanf(rgba, "%d %d %d %d %d %d %d %d %d %d %d %d",
157                                         r, g, b, a,                     /* OBJECT */
158                                         r + 1, g + 1, b + 1, a + 1,     /* OUTLINE */
159                                         r + 2, g + 2, b + 2, a + 2);    /* SHADOW */
160         if (ret != 12) {
161                 DbgPrint("id[%s] part[%s] rgba[%s]\n", id, part, rgba);
162                 return -EINVAL;
163         }
164
165         ret = edje_object_color_class_set(edje, part,
166                                 r[0], g[0], b[0], a[0], /* OBJECT */
167                                 r[1], g[1], b[1], a[1], /* OUTLINE */
168                                 r[2], g[2], b[2], a[2]); /* SHADOW */
169
170         DbgPrint("EDJE[%s] color class is %s changed", id, ret == EINA_TRUE ? "successfully" : "not");
171         return 0;
172 }
173
174 int script_update_text(void *h, Evas *e, const char *id, const char *part, const char *text)
175 {
176         struct info *handle = h;
177         Evas_Object *edje;
178
179         edje = find_edje(handle, id);
180         if (!edje)
181                 return -ENOENT;
182
183         edje_object_part_text_set(edje, part, text);
184         return 0;
185 }
186
187 int script_update_image(void *_h, Evas *e, const char *id, const char *part, const char *path)
188 {
189         struct info *handle = _h;
190         Evas_Load_Error err;
191         Evas_Object *edje;
192         Evas_Object *img;
193         Evas_Coord w, h;
194         struct obj_info *obj_info;
195         struct child *child;
196
197         edje = find_edje(handle, id);
198         if (!edje) {
199                 ErrPrint("No such object: %s\n", id);
200                 return -ENOENT;
201         }
202
203         obj_info = evas_object_data_get(edje, "obj_info");
204         if (!obj_info) {
205                 ErrPrint("Object info is not available\n");
206                 return -EFAULT;
207         }
208
209         img = edje_object_part_swallow_get(edje, part);
210         if (img) {
211                 Eina_List *l;
212                 Eina_List *n;
213
214                 edje_object_part_unswallow(edje, img);
215
216                 EINA_LIST_FOREACH_SAFE(obj_info->children, l, n, child) {
217                         if (child->obj != img)
218                                 continue;
219
220                         obj_info->children = eina_list_remove(obj_info->children, child);
221                         free(child->part);
222                         free(child);
223                         break;
224                 }
225
226                 DbgPrint("delete object %s %p\n", part, img);
227                 evas_object_del(img);
228         }
229
230         if (!path || !strlen(path) || access(path, R_OK) != 0) {
231                 DbgPrint("SKIP - Path: [%s]\n", path);
232                 return 0;
233         }
234
235         child = malloc(sizeof(*child));
236         if (!child) {
237                 ErrPrint("Heap: %s\n", strerror(errno));
238                 return -ENOMEM;
239         }
240
241         child->part = strdup(part);
242         if (!child->part) {
243                 ErrPrint("Heap: %s\n", strerror(errno));
244                 free(child);
245                 return -ENOMEM;
246         }
247
248         img = evas_object_image_filled_add(e);
249         if (!img) {
250                 ErrPrint("Failed to add an image object\n");
251                 free(child->part);
252                 free(child);
253                 return -EFAULT;
254         }
255
256         evas_object_image_load_orientation_set(img, EINA_TRUE);
257
258         child->obj = img;
259
260         evas_object_image_file_set(img, path, NULL);
261         err = evas_object_image_load_error_get(img);
262         if (err != EVAS_LOAD_ERROR_NONE) {
263                 ErrPrint("Load error: %s\n", evas_load_error_str(err));
264                 evas_object_del(img);
265                 free(child->part);
266                 free(child);
267                 return -EIO;
268         }
269
270         evas_object_image_size_get(img, &w, &h);
271         evas_object_image_fill_set(img, 0, 0, w, h);
272         evas_object_size_hint_fill_set(img, EVAS_HINT_FILL, EVAS_HINT_FILL);
273         evas_object_size_hint_weight_set(img, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
274         evas_object_resize(img, w, h);
275
276         /*!
277          * \note
278          * object will be shown by below statement automatically
279          */
280         DbgPrint("%s part swallow image %p\n", part, img);
281         edje_object_part_swallow(edje, part, img);
282         obj_info->children = eina_list_append(obj_info->children, child);
283
284         return 0;
285 }
286
287 static void script_signal_cb(void *data, Evas_Object *obj, const char *emission, const char *source)
288 {
289         struct info *handle = data;
290         Evas_Coord w;
291         Evas_Coord h;
292         Evas_Coord px = 0;
293         Evas_Coord py = 0;
294         Evas_Coord pw = 0;
295         Evas_Coord ph = 0;
296         double sx;
297         double sy;
298         double ex;
299         double ey;
300
301         evas_object_geometry_get(obj, NULL, NULL, &w, &h);
302         edje_object_part_geometry_get(obj, source, &px, &py, &pw, &ph);
303
304         sx = ex = 0.0f;
305         if (w) {
306                 sx = (double)px / (double)w;
307                 ex = (double)(px + pw) / (double)w;
308         }
309
310         sy = ey = 0.0f;
311         if (h) {
312                 sy = (double)py / (double)h;
313                 ey = (double)(py + ph) / (double)h;
314         }
315
316         DbgPrint("Signal emit: source[%s], emission[%s]\n", source, emission);
317         script_signal_emit(handle->e, source, emission, sx, sy, ex, ey);
318 }
319
320 static void edje_del_cb(void *_info, Evas *e, Evas_Object *obj, void *event_info)
321 {
322         struct info *handle = _info;
323         struct obj_info *obj_info;
324         struct child *child;
325
326         handle->obj_list = eina_list_remove(handle->obj_list, obj);
327
328         obj_info = evas_object_data_del(obj, "obj_info");
329         if (!obj_info) {
330                 ErrPrint("Object info is not valid\n");
331                 return;
332         }
333
334         DbgPrint("delete object %s %p\n", obj_info->id, obj);
335
336         edje_object_signal_callback_del_full(obj, "*", "*", script_signal_cb, handle);
337
338         EINA_LIST_FREE(obj_info->children, child) {
339                 DbgPrint("delete object %s %p\n", child->part, child->obj);
340                 if (child->obj)
341                         evas_object_del(child->obj);
342                 free(child->part);
343                 free(child);
344         }
345
346         free(obj_info->id);
347         free(obj_info);
348 }
349
350 int script_update_script(void *h, Evas *e, const char *src_id, const char *target_id, const char *part, const char *path, const char *group)
351 {
352         struct info *handle = h;
353         Evas_Object *edje;
354         Evas_Object *obj;
355         struct obj_info *obj_info;
356         struct child *child;
357
358         DbgPrint("src_id[%s] target_id[%s] part[%s] path[%s] group[%s]\n", src_id, target_id, part, path, group);
359
360         edje = find_edje(handle, src_id);
361         if (!edje) {
362                 ErrPrint("Edje is not exists\n");
363                 return -ENOENT;
364         }
365
366         obj_info = evas_object_data_get(edje, "obj_info");
367         if (!obj_info) {
368                 ErrPrint("Object info is not valid\n");
369                 return -EINVAL;
370         }
371
372         obj = edje_object_part_swallow_get(edje, part);
373         if (obj) {
374                 Eina_List *l;
375                 Eina_List *n;
376
377                 edje_object_part_unswallow(edje, obj);
378
379                 EINA_LIST_FOREACH_SAFE(obj_info->children, l, n, child) {
380                         if (child->obj != obj)
381                                 continue;
382
383                         obj_info->children = eina_list_remove(obj_info->children, child);
384                         free(child->part);
385                         free(child);
386                         break;
387                 }
388
389                 DbgPrint("delete object %s %p\n", part, obj);
390                 evas_object_del(obj);
391         }
392
393         if (!path || !strlen(path) || access(path, R_OK) != 0) {
394                 DbgPrint("SKIP - Path: [%s]\n", path);
395                 return 0;
396         }
397
398         obj = edje_object_add(e);
399         if (!obj) {
400                 ErrPrint("Failed to add a new edje object\n");
401                 return -EFAULT;
402         }
403
404         //edje_object_text_class_set(obj, TEXT_CLASS, s_info.font, s_info.size);
405         if (!edje_object_file_set(obj, path, group)) {
406                 int err;
407                 const char *errmsg;
408
409                 err = edje_object_load_error_get(obj);
410                 errmsg = edje_load_error_str(err);
411                 ErrPrint("Could not load %s from %s: %s\n", group, path, errmsg);
412                 evas_object_del(obj);
413                 return -EIO;
414         }
415
416         evas_object_show(obj);
417
418         obj_info = calloc(1, sizeof(*obj_info));
419         if (!obj_info) {
420                 ErrPrint("Failed to add a obj_info\n");
421                 evas_object_del(obj);
422                 return -ENOMEM;
423         }
424
425         obj_info->id = strdup(target_id);
426         if (!obj_info->id) {
427                 ErrPrint("Failed to add a obj_info\n");
428                 free(obj_info);
429                 evas_object_del(obj);
430                 return -ENOMEM;
431         }
432
433         child = malloc(sizeof(*child));
434         if (!child) {
435                 ErrPrint("Error: %s\n", strerror(errno));
436                 free(obj_info->id);
437                 free(obj_info);
438                 evas_object_del(obj);
439                 return -ENOMEM;
440         }
441
442         child->part = strdup(part);
443         if (!child->part) {
444                 ErrPrint("Error: %s\n", strerror(errno));
445                 free(child);
446                 free(obj_info->id);
447                 free(obj_info);
448                 evas_object_del(obj);
449                 return -ENOMEM;
450         }
451
452         child->obj = obj;
453
454         evas_object_data_set(obj, "obj_info", obj_info);
455         evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL, edje_del_cb, handle);
456         edje_object_signal_callback_add(obj, "*", "*", script_signal_cb, handle);
457         handle->obj_list = eina_list_append(handle->obj_list, obj);
458
459         DbgPrint("%s part swallow edje %p\n", part, obj);
460         edje_object_part_swallow(edje, part, obj);
461         obj_info = evas_object_data_get(edje, "obj_info");
462         obj_info->children = eina_list_append(obj_info->children, child);
463         return 0;
464 }
465
466 int script_update_signal(void *h, Evas *e, const char *id, const char *part, const char *signal)
467 {
468         struct info *handle = h;
469         Evas_Object *edje;
470
471         DbgPrint("id[%s], part[%s], signal[%s]\n", id, part, signal);
472
473         edje = find_edje(handle, id);
474         if (!edje)
475                 return -ENOENT;
476
477         edje_object_signal_emit(edje, signal, part);
478         return 0;
479 }
480
481 int script_update_drag(void *h, Evas *e, const char *id, const char *part, double x, double y)
482 {
483         struct info *handle = h;
484         Evas_Object *edje;
485
486         DbgPrint("id[%s], part[%s], %lfx%lf\n", id, part, x, y);
487
488         edje = find_edje(handle, id);
489         if (!edje)
490                 return -ENOENT;
491
492         edje_object_part_drag_value_set(edje, part, x, y);
493         return 0;
494 }
495
496 int script_update_size(void *han, Evas *e, const char *id, int w, int h)
497 {
498         struct info *handle = han;
499         Evas_Object *edje;
500
501         edje = find_edje(handle, id);
502         if (!edje)
503                 return -ENOENT;
504
505         if (!id) {
506                 handle->w = w;
507                 handle->h = h;
508         }
509
510         DbgPrint("Resize object to %dx%d\n", w, h);
511         evas_object_resize(edje, w, h);
512         return 0;
513 }
514
515 int script_update_category(void *h, Evas *e, const char *id, const char *category)
516 {
517         struct info *handle = h;
518
519         DbgPrint("id[%s], category[%s]\n", id, category);
520
521         if (handle->category) {
522                 free(handle->category);
523                 handle->category = NULL;
524         }
525
526         if (!category)
527                 return 0;
528
529         handle->category = strdup(category);
530         if (!handle->category) {
531                 ErrPrint("Error: %s\n", strerror(errno));
532                 return -ENOMEM;
533         }
534
535         return 0;
536 }
537
538 void *script_create(const char *file, const char *group)
539 {
540         struct info *handle;
541
542         DbgPrint("file[%s], group[%s]\n", file, group);
543
544         handle = calloc(1, sizeof(*handle));
545         if (!handle) {
546                 ErrPrint("Error: %s\n", strerror(errno));
547                 return NULL;
548         }
549
550         handle->file = strdup(file);
551         if (!handle->file) {
552                 ErrPrint("Error: %s\n", strerror(errno));
553                 free(handle);
554                 return NULL;
555         }
556
557         handle->group = strdup(group);
558         if (!handle->group) {
559                 ErrPrint("Error: %s\n", strerror(errno));
560                 free(handle->file);
561                 free(handle);
562                 return NULL;
563         }
564
565         return handle;
566 }
567
568 int script_destroy(void *_handle)
569 {
570         struct info *handle;
571         Evas_Object *edje;
572
573         handle = _handle;
574
575         edje = eina_list_nth(handle->obj_list, 0);
576         if (edje)
577                 evas_object_del(edje);
578
579         free(handle->category);
580         free(handle->file);
581         free(handle->group);
582         free(handle);
583         return 0;
584 }
585
586 int script_load(void *_handle, Evas *e, int w, int h)
587 {
588         struct info *handle;
589         Evas_Object *edje;
590         struct obj_info *obj_info;
591
592         handle = _handle;
593
594         obj_info = calloc(1, sizeof(*obj_info));
595         if (!obj_info) {
596                 ErrPrint("Heap: %s\n", strerror(errno));
597                 return -ENOMEM;
598         }
599
600         edje = edje_object_add(e);
601         if (!edje) {
602                 ErrPrint("Failed to create an edje object\n");
603                 free(obj_info);
604                 return -EFAULT;
605         }
606
607         //edje_object_text_class_set(edje, TEXT_CLASS, s_info.font, s_info.size);
608         DbgPrint("Load edje: %s - %s\n", handle->file, handle->group);
609         if (!edje_object_file_set(edje, handle->file, handle->group)) {
610                 int err;
611                 const char *errmsg;
612
613                 err = edje_object_load_error_get(edje);
614                 errmsg = edje_load_error_str(err);
615                 ErrPrint("Could not load %s from %s: %s\n", handle->group, handle->file, errmsg);
616                 evas_object_del(edje);
617                 free(obj_info);
618                 return -EIO;
619         }
620
621         handle->e = e;
622         handle->w = w;
623         handle->h = h;
624
625         edje_object_signal_callback_add(edje, "*", "*", script_signal_cb, handle);
626         evas_object_event_callback_add(edje, EVAS_CALLBACK_DEL, edje_del_cb, handle);
627         evas_object_size_hint_weight_set(edje, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
628         evas_object_size_hint_fill_set(edje, EVAS_HINT_FILL, EVAS_HINT_FILL);
629         evas_object_resize(edje, handle->w, handle->h);
630         evas_object_show(edje);
631         evas_object_data_set(edje, "obj_info", obj_info);
632
633         handle->obj_list = eina_list_append(handle->obj_list, edje);
634         return 0;
635 }
636
637 int script_unload(void *_handle, Evas *e)
638 {
639         struct info *handle;
640         Evas_Object *edje;
641
642         handle = _handle;
643
644         DbgPrint("Unload edje: %s - %s\n", handle->file, handle->group);
645         edje = eina_list_nth(handle->obj_list, 0);
646         if (edje)
647                 evas_object_del(edje);
648         handle->e = NULL;
649         return 0;
650 }
651
652 static Eina_Bool property_cb(void *data, int type, void *event)
653 {
654         Ecore_X_Event_Window_Property *info = (Ecore_X_Event_Window_Property *)event;
655
656         if (info->atom == ecore_x_atom_get("FONT_TYPE_change") || info->atom == ecore_x_atom_get("BADA_FONT_change")) {
657                 Eina_List *list;
658                 char *text;
659                 char *font;
660                 int cache;
661
662                 font = vconf_get_str("db/setting/accessibility/font_name");
663                 if (!font)
664                         return ECORE_CALLBACK_PASS_ON;
665
666                 if (s_info.font)
667                         free(s_info.font);
668
669                 s_info.font = font;
670
671                 cache = evas_common_font_cache_get();
672                 evas_common_font_cache_set(0);
673                 evas_common_font_flush();
674
675                 list = edje_text_class_list();
676                 EINA_LIST_FREE(list, text) {
677                         if (!strncasecmp(text, TEXT_CLASS, strlen(TEXT_CLASS))) {
678                                 edje_text_class_del(text);
679                                 edje_text_class_set(text, s_info.font, s_info.size);
680                                 DbgPrint("Update text class %s (%s, %d)\n", text, s_info.font, s_info.size);
681                         } else {
682                                 DbgPrint("Skip text class %s\n", text);
683                         }
684                 }
685
686                 evas_common_font_cache_set(cache);
687         }
688
689         return ECORE_CALLBACK_PASS_ON;
690 }
691
692 static void font_name_cb(keynode_t *node, void *user_data)
693 {
694         const char *font;
695
696         if (!node)
697                 return;
698
699         font = vconf_keynode_get_str(node);
700         if (!font)
701                 return;
702
703         DbgPrint("Font changed to %s\n", font);
704 }
705
706 static void font_size_cb(keynode_t *node, void *user_data)
707 {
708         if (!node)
709                 return;
710         /*!
711          * \TODO
712          * Implementing me.
713          */
714         DbgPrint("Size type: %d\n", vconf_keynode_get_int(node));
715 }
716
717 int script_init(void)
718 {
719         int ret;
720         /* ecore is already initialized */
721         edje_init();
722
723         s_info.property_handler = ecore_event_handler_add(ECORE_X_EVENT_WINDOW_PROPERTY, property_cb, NULL);
724         if (!s_info.property_handler)
725                 ErrPrint("Failed to add a property change event handler\n");
726
727         ret = vconf_notify_key_changed(VCONFKEY_SETAPPL_ACCESSIBILITY_FONT_SIZE, font_size_cb, NULL);
728         if (ret < 0)
729                 ErrPrint("Failed to add vconf for font size change\n");
730
731         ret = vconf_notify_key_changed("db/setting/accessibility/font_name", font_name_cb, NULL);
732         if (ret < 0)
733                 ErrPrint("Failed to add vconf for font name change\n");
734
735         return 0;
736 }
737
738 int script_fini(void)
739 {
740
741         vconf_ignore_key_changed("db/setting/accessibility/font_name", font_name_cb);
742         vconf_ignore_key_changed(VCONFKEY_SETAPPL_ACCESSIBILITY_FONT_SIZE, font_size_cb);
743         ecore_event_handler_del(s_info.property_handler);
744         s_info.property_handler = NULL;
745         edje_shutdown();
746         return 0;
747 }
748
749 /* End of a file */