Add "size" option for image container.
[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 #include <ctype.h>
22
23 #include <Evas.h>
24 #include <Edje.h>
25 #include <Eina.h>
26 #include <Ecore.h>
27 #include <Ecore_Evas.h>
28 #include <Eet.h>
29 #include <Ecore_X.h>
30
31 #include <dlog.h>
32 #include <debug.h>
33 #include <vconf.h>
34
35 #include "script_port.h"
36
37 #define TEXT_CLASS      "tizen"
38
39 #define PUBLIC __attribute__((visibility("default")))
40
41 extern void evas_common_font_flush(void);
42 extern int evas_common_font_cache_get(void);
43 extern void evas_common_font_cache_set(int size);
44
45 struct image_option {
46         int orient;
47         int aspect;
48         enum {
49                 FILL_DISABLE,
50                 FILL_IN_SIZE,
51                 FILL_OVER_SIZE,
52         } fill;
53
54         int width;
55         int height;
56 };
57
58 struct info {
59         char *file;
60         char *group;
61         char *category;
62         int w;
63         int h;
64
65         Evas *e;
66
67         Eina_List *obj_list;
68 };
69
70 struct child {
71         Evas_Object *obj;
72         char *part;
73 };
74
75 struct obj_info {
76         char *id;
77         Eina_List *children;
78 };
79
80 static struct {
81         Ecore_Event_Handler *property_handler;
82         char *font;
83         int size;
84 } s_info = {
85         .property_handler = NULL,
86         .font = NULL,
87         .size = -100,
88 };
89
90 /*!
91  * \NOTE
92  * Reservce this for future use
93 static inline void common_cache_flush(void *evas)
94 {
95         int file_cache;
96         int collection_cache;
97         int image_cache;
98         int font_cache;
99
100         file_cache = edje_file_cache_get();
101         collection_cache = edje_collection_cache_get();
102         image_cache = evas_image_cache_get(evas);
103         font_cache = evas_font_cache_get(evas);
104
105         edje_file_cache_set(file_cache);
106         edje_collection_cache_set(collection_cache);
107         evas_image_cache_set(evas, 0);
108         evas_font_cache_set(evas, 0);
109
110         evas_image_cache_flush(evas);
111         evas_render_idle_flush(evas);
112         evas_font_cache_flush(evas);
113
114         edje_file_cache_flush();
115         edje_collection_cache_flush();
116
117         edje_file_cache_set(file_cache);
118         edje_collection_cache_set(collection_cache);
119         evas_image_cache_set(evas, image_cache);
120         evas_font_cache_set(evas, font_cache);
121
122         eet_clearcache();
123 }
124  */
125
126 static inline Evas_Object *find_edje(struct info *handle, const char *id)
127 {
128         Eina_List *l;
129         Evas_Object *edje;
130         struct obj_info *obj_info;
131
132         EINA_LIST_FOREACH(handle->obj_list, l, edje) {
133                 obj_info = evas_object_data_get(edje, "obj_info");
134                 if (!obj_info) {
135                         ErrPrint("Object info is not valid\n");
136                         continue;
137                 }
138
139                 if (!id) {
140                         if (!obj_info->id)
141                                 return edje;
142
143                         continue;
144                 } else if (!obj_info->id) {
145                         continue;
146                 }
147
148                 if (!strcmp(obj_info->id, id))
149                         return edje;
150         }
151
152         DbgPrint("EDJE[%s] is not found\n", id);
153         return NULL;
154 }
155
156 PUBLIC const char *script_magic_id(void)
157 {
158         return "edje";
159 }
160
161 PUBLIC int script_update_color(void *h, Evas *e, const char *id, const char *part, const char *rgba)
162 {
163         struct info *handle = h;
164         Evas_Object *edje;
165         int r[3], g[3], b[3], a[3];
166         int ret;
167
168         edje = find_edje(handle, id);
169         if (!edje)
170                 return -ENOENT;
171
172         ret = sscanf(rgba, "%d %d %d %d %d %d %d %d %d %d %d %d",
173                                         r, g, b, a,                     /* OBJECT */
174                                         r + 1, g + 1, b + 1, a + 1,     /* OUTLINE */
175                                         r + 2, g + 2, b + 2, a + 2);    /* SHADOW */
176         if (ret != 12) {
177                 DbgPrint("id[%s] part[%s] rgba[%s]\n", id, part, rgba);
178                 return -EINVAL;
179         }
180
181         ret = edje_object_color_class_set(edje, part,
182                                 r[0], g[0], b[0], a[0], /* OBJECT */
183                                 r[1], g[1], b[1], a[1], /* OUTLINE */
184                                 r[2], g[2], b[2], a[2]); /* SHADOW */
185
186         DbgPrint("EDJE[%s] color class is %s changed", id, ret == EINA_TRUE ? "successfully" : "not");
187         return 0;
188 }
189
190 PUBLIC int script_update_text(void *h, Evas *e, const char *id, const char *part, const char *text)
191 {
192         struct info *handle = h;
193         Evas_Object *edje;
194
195         edje = find_edje(handle, id);
196         if (!edje)
197                 return -ENOENT;
198
199         edje_object_part_text_set(edje, part, text);
200         return 0;
201 }
202
203 static void parse_aspect(struct image_option *img_opt, const char *value, int len)
204 {
205         while (len > 0 && *value == ' ') {
206                 value++;
207                 len--;
208         }
209
210         if (len < 4)
211                 return;
212
213         img_opt->aspect = !strncasecmp(value, "true", 4);
214         DbgPrint("Parsed ASPECT: %d (%s)\n", img_opt->aspect, value);
215 }
216
217 static void parse_orient(struct image_option *img_opt, const char *value, int len)
218 {
219         while (len > 0 && *value == ' ') {
220                 value++;
221                 len--;
222         }
223
224         if (len < 4)
225                 return;
226
227         img_opt->orient = !strncasecmp(value, "true", 4);
228         DbgPrint("Parsed ORIENT: %d (%s)\n", img_opt->aspect, value);
229 }
230
231 static void parse_size(struct image_option *img_opt, const char *value, int len)
232 {
233         int width;
234         int height;
235         char *buf;
236
237         while (len > 0 && *value == ' ') {
238                 value++;
239                 len--;
240         }
241
242         buf = strndup(value, len);
243         if (!buf) {
244                 ErrPrint("Heap: %s\n", strerror(errno));
245                 return;
246         }
247
248         if (sscanf(buf, "%dx%d", &width, &height) == 2) {
249                 img_opt->width = width;
250                 img_opt->height = height;
251                 DbgPrint("Parsed size : %dx%d (%s)\n", width, height, buf);
252         } else {
253                 DbgPrint("Invalid size tag[%s]\n", buf);
254         }
255
256         free(buf);
257 }
258
259 static void parse_fill(struct image_option *img_opt, const char *value, int len)
260 {
261         while (len > 0 && *value == ' ') {
262                 value++;
263                 len--;
264         }
265
266         if (!strncasecmp(value, "in-size", len))
267                 img_opt->fill = FILL_IN_SIZE;
268         else if (!strncasecmp(value, "over-size", len))
269                 img_opt->fill = FILL_OVER_SIZE;
270         else
271                 img_opt->fill = FILL_DISABLE;
272
273         DbgPrint("Parsed FILL: %d (%s)\n", img_opt->fill, value);
274 }
275
276 static inline void parse_image_option(const char *option, struct image_option *img_opt)
277 {
278         const char *ptr;
279         const char *cmd;
280         const char *value;
281         struct {
282                 const char *cmd;
283                 void (*handler)(struct image_option *img_opt, const char *value, int len);
284         } cmd_list[] = {
285                 {
286                         .cmd = "aspect", /* Keep the aspect ratio */
287                         .handler = parse_aspect,
288                 },
289                 {
290                         .cmd = "orient", /* Keep the orientation value: for the rotated images */
291                         .handler = parse_orient,
292                 },
293                 {
294                         .cmd = "fill", /* Fill the image to its container */
295                         .handler = parse_fill, /* Value: in-size, over-size, disable(default) */
296                 },
297                 {
298                         .cmd = "size",
299                         .handler = parse_size,
300                 },
301         };
302         enum {
303                 STATE_START,
304                 STATE_TOKEN,
305                 STATE_DATA,
306                 STATE_IGNORE,
307                 STATE_ERROR,
308                 STATE_END,
309         } state;
310         int idx;
311         int tag;
312
313         if (!option || !*option)
314                 return;
315
316         state = STATE_START;
317
318         for (ptr = option; state != STATE_END; ptr++) {
319                 switch (state) {
320                 case STATE_START:
321                         if (*ptr == '\0') {
322                                 state = STATE_END;
323                                 continue;
324                         }
325
326                         if (isalpha(*ptr)) {
327                                 state = STATE_TOKEN;
328                                 ptr--;
329                         }
330                         tag = 0;
331                         idx = 0;
332
333                         cmd = cmd_list[tag].cmd;
334                         break;
335                 case STATE_IGNORE:
336                         if (*ptr == '=') {
337                                 state = STATE_DATA;
338                                 value = ptr;
339                         } else if (*ptr == '\0') {
340                                 state = STATE_END;
341                         }
342                         break;
343                 case STATE_TOKEN:
344                         if (cmd[idx] == '\0' && (*ptr == ' ' || *ptr == '\t' || *ptr == '=')) {
345                                 if (*ptr == '=') {
346                                         value = ptr;
347                                         state = STATE_DATA;
348                                 } else {
349                                         state = STATE_IGNORE;
350                                 }
351                                 idx = 0;
352                         } else if (*ptr == '\0') {
353                                 state = STATE_END;
354                         } else if (cmd[idx] == *ptr) {
355                                 idx++;
356                         } else {
357                                 ptr -= (idx + 1);
358
359                                 tag++;
360                                 if (tag == sizeof(cmd_list) / sizeof(cmd_list[0])) {
361                                         tag = 0;
362                                         state = STATE_ERROR;
363                                 } else {
364                                         cmd = cmd_list[tag].cmd;
365                                 }
366                                 idx = 0;
367                         }
368                         break;
369                 case STATE_DATA:
370                         if (*ptr == ';' || *ptr == '\0') {
371                                 cmd_list[tag].handler(img_opt, value + 1, idx);
372                                 state = *ptr ? STATE_START : STATE_END;
373                         } else {
374                                 idx++;
375                         }
376                         break;
377                 case STATE_ERROR:
378                         if (*ptr == ';')
379                                 state = STATE_START;
380                         else if (*ptr == '\0')
381                                 state = STATE_END;
382                         break;
383                 default:
384                         break;
385                 }
386         }
387 }
388
389 static void cropped_resize_cb(void *data, Evas *e, Evas_Object *obj, void *ei)
390 {
391         Evas_Coord w;
392         Evas_Coord h;
393         int part_w;
394         int part_h;
395
396         /* grab image size */
397         part_w = (int)evas_object_data_get(obj, "part_w");
398         part_h = (int)evas_object_data_get(obj, "part_h");
399         w = (int)evas_object_data_get(obj, "w");
400         h = (int)evas_object_data_get(obj, "h");
401
402         /* grab base object dimensions */
403         evas_object_resize(obj, part_w, part_h);
404         evas_object_image_fill_set(obj, 0, 0, w, h);
405
406         DbgPrint("Cropped: %dx%d - %dx%d, ImageSize(%dx%d)\n", (w - part_w) / 2, (h - part_h) / 2, part_w, part_h, w, h);
407 }
408
409 PUBLIC int script_update_image(void *_h, Evas *e, const char *id, const char *part, const char *path, const char *option)
410 {
411         struct info *handle = _h;
412         Evas_Load_Error err;
413         Evas_Object *edje;
414         Evas_Object *img;
415         Evas_Coord w, h;
416         struct obj_info *obj_info;
417         struct child *child;
418         struct image_option img_opt = {
419                 .aspect = 0,
420                 .orient = 0,
421                 .fill = FILL_DISABLE,
422                 .width = -1,
423                 .height = -1,
424         };
425
426         edje = find_edje(handle, id);
427         if (!edje) {
428                 ErrPrint("No such object: %s\n", id);
429                 return -ENOENT;
430         }
431
432         obj_info = evas_object_data_get(edje, "obj_info");
433         if (!obj_info) {
434                 ErrPrint("Object info is not available\n");
435                 return -EFAULT;
436         }
437
438         img = edje_object_part_swallow_get(edje, part);
439         if (img) {
440                 Eina_List *l;
441                 Eina_List *n;
442
443                 edje_object_part_unswallow(edje, img);
444
445                 EINA_LIST_FOREACH_SAFE(obj_info->children, l, n, child) {
446                         if (child->obj != img)
447                                 continue;
448
449                         obj_info->children = eina_list_remove(obj_info->children, child);
450                         free(child->part);
451                         free(child);
452                         break;
453                 }
454
455                 DbgPrint("delete object %s %p\n", part, img);
456                 evas_object_del(img);
457         }
458
459         if (!path || !strlen(path) || access(path, R_OK) != 0) {
460                 DbgPrint("SKIP - Path: [%s]\n", path);
461                 return 0;
462         }
463
464         child = malloc(sizeof(*child));
465         if (!child) {
466                 ErrPrint("Heap: %s\n", strerror(errno));
467                 return -ENOMEM;
468         }
469
470         child->part = strdup(part);
471         if (!child->part) {
472                 ErrPrint("Heap: %s\n", strerror(errno));
473                 free(child);
474                 return -ENOMEM;
475         }
476
477         img = evas_object_image_add(e);
478         if (!img) {
479                 ErrPrint("Failed to add an image object\n");
480                 free(child->part);
481                 free(child);
482                 return -EFAULT;
483         }
484
485         parse_image_option(option, &img_opt);
486         evas_object_image_load_orientation_set(img, img_opt.orient);
487
488         evas_object_image_file_set(img, path, NULL);
489
490         err = evas_object_image_load_error_get(img);
491         if (err != EVAS_LOAD_ERROR_NONE) {
492                 ErrPrint("Load error: %s\n", evas_load_error_str(err));
493                 evas_object_del(img);
494                 free(child->part);
495                 free(child);
496                 return -EIO;
497         }
498
499         evas_object_image_size_get(img, &w, &h);
500         if (img_opt.aspect) {
501                 if (img_opt.fill == FILL_OVER_SIZE) {
502                         Evas_Coord part_w;
503                         Evas_Coord part_h;
504                         Evas_Coord tmp_w;
505                         Evas_Coord tmp_h;
506
507                         if (img_opt.width >= 0 && img_opt.height >= 0) {
508                                 part_w = img_opt.width;
509                                 part_h = img_opt.height;
510                         } else {
511                                 edje_object_part_geometry_get(edje, part, NULL, NULL, &part_w, &part_h);
512                         }
513                         evas_object_data_set(img, "part_w", (void *)part_w);
514                         evas_object_data_set(img, "part_h", (void *)part_h);
515                         DbgPrint("Original %dx%d (part: %dx%d)\n", w, h, part_w, part_h);
516
517                         tmp_w = part_w - w;
518                         tmp_h = part_h - h;
519
520                         if (abs(tmp_w) > abs(tmp_h)) {
521                                 if (tmp_w > 0) {
522                                         DbgPrint("Before: (h = %d * %d / %d)\n", part_w, h, w);
523                                         h = (int)((double)part_w * (double)h / (double)w);
524                                         w = part_w;
525                                         DbgPrint("Size: %dx%d\n", w, h);
526                                 }
527                         } else {
528                                 if (tmp_h > 0) {
529                                         DbgPrint("Before: (w = %d * %d / %d)\n", part_h, w, h);
530                                         w = (int)((double)part_h * (double)w / (double)h);
531                                         h = part_h;
532                                         DbgPrint("Size: %dx%d\n", w, h);
533                                 }
534                         }
535
536                         evas_object_data_set(img, "w", (void *)w);
537                         evas_object_data_set(img, "h", (void *)h);
538                         evas_object_image_load_size_set(img, w, h);
539                         evas_object_image_load_region_set(img, (w - part_w) / 2, (h - part_h) / 2, part_w, part_h);
540                         evas_object_image_reload(img);
541                         evas_object_event_callback_add(img, EVAS_CALLBACK_RESIZE, cropped_resize_cb, NULL);
542                 } else {
543                         evas_object_image_fill_set(img, 0, 0, w, h);
544                         evas_object_size_hint_fill_set(img, EVAS_HINT_FILL, EVAS_HINT_FILL);
545                         evas_object_size_hint_aspect_set(img, EVAS_ASPECT_CONTROL_BOTH, w, h);
546                 }
547         } else {
548                 if (img_opt.width >= 0 && img_opt.height >= 0) {
549                         w = img_opt.width;
550                         h = img_opt.height;
551                         DbgPrint("Using given image size: %dx%d\n", w, h);
552                 }
553
554                 evas_object_image_fill_set(img, 0, 0, w, h);
555                 evas_object_size_hint_fill_set(img, EVAS_HINT_FILL, EVAS_HINT_FILL);
556                 evas_object_size_hint_weight_set(img, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
557         }
558
559         /*!
560          * \note
561          * object will be shown by below statement automatically
562          */
563         DbgPrint("%s part swallow image %p (%dx%d)\n", part, img, w, h);
564         child->obj = img;
565         edje_object_part_swallow(edje, part, img);
566         obj_info->children = eina_list_append(obj_info->children, child);
567
568         return 0;
569 }
570
571 static void script_signal_cb(void *data, Evas_Object *obj, const char *emission, const char *source)
572 {
573         struct info *handle = data;
574         Evas_Coord w;
575         Evas_Coord h;
576         Evas_Coord px = 0;
577         Evas_Coord py = 0;
578         Evas_Coord pw = 0;
579         Evas_Coord ph = 0;
580         double sx;
581         double sy;
582         double ex;
583         double ey;
584
585         evas_object_geometry_get(obj, NULL, NULL, &w, &h);
586         edje_object_part_geometry_get(obj, source, &px, &py, &pw, &ph);
587
588         sx = ex = 0.0f;
589         if (w) {
590                 sx = (double)px / (double)w;
591                 ex = (double)(px + pw) / (double)w;
592         }
593
594         sy = ey = 0.0f;
595         if (h) {
596                 sy = (double)py / (double)h;
597                 ey = (double)(py + ph) / (double)h;
598         }
599
600         DbgPrint("Signal emit: source[%s], emission[%s]\n", source, emission);
601         script_signal_emit(handle->e, source, emission, sx, sy, ex, ey);
602 }
603
604 static void edje_del_cb(void *_info, Evas *e, Evas_Object *obj, void *event_info)
605 {
606         struct info *handle = _info;
607         struct obj_info *obj_info;
608         struct child *child;
609
610         handle->obj_list = eina_list_remove(handle->obj_list, obj);
611
612         obj_info = evas_object_data_del(obj, "obj_info");
613         if (!obj_info) {
614                 ErrPrint("Object info is not valid\n");
615                 return;
616         }
617
618         DbgPrint("delete object %s %p\n", obj_info->id, obj);
619
620         edje_object_signal_callback_del_full(obj, "*", "*", script_signal_cb, handle);
621
622         EINA_LIST_FREE(obj_info->children, child) {
623                 DbgPrint("delete object %s %p\n", child->part, child->obj);
624                 if (child->obj)
625                         evas_object_del(child->obj);
626                 free(child->part);
627                 free(child);
628         }
629
630         free(obj_info->id);
631         free(obj_info);
632 }
633
634 PUBLIC 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)
635 {
636         struct info *handle = h;
637         Evas_Object *edje;
638         Evas_Object *obj;
639         struct obj_info *obj_info;
640         struct child *child;
641
642         DbgPrint("src_id[%s] target_id[%s] part[%s] path[%s] group[%s]\n", src_id, target_id, part, path, group);
643
644         edje = find_edje(handle, src_id);
645         if (!edje) {
646                 ErrPrint("Edje is not exists\n");
647                 return -ENOENT;
648         }
649
650         obj_info = evas_object_data_get(edje, "obj_info");
651         if (!obj_info) {
652                 ErrPrint("Object info is not valid\n");
653                 return -EINVAL;
654         }
655
656         obj = edje_object_part_swallow_get(edje, part);
657         if (obj) {
658                 Eina_List *l;
659                 Eina_List *n;
660
661                 edje_object_part_unswallow(edje, obj);
662
663                 EINA_LIST_FOREACH_SAFE(obj_info->children, l, n, child) {
664                         if (child->obj != obj)
665                                 continue;
666
667                         obj_info->children = eina_list_remove(obj_info->children, child);
668                         free(child->part);
669                         free(child);
670                         break;
671                 }
672
673                 DbgPrint("delete object %s %p\n", part, obj);
674                 evas_object_del(obj);
675         }
676
677         if (!path || !strlen(path) || access(path, R_OK) != 0) {
678                 DbgPrint("SKIP - Path: [%s]\n", path);
679                 return 0;
680         }
681
682         obj = edje_object_add(e);
683         if (!obj) {
684                 ErrPrint("Failed to add a new edje object\n");
685                 return -EFAULT;
686         }
687
688         //edje_object_text_class_set(obj, TEXT_CLASS, s_info.font, s_info.size);
689         if (!edje_object_file_set(obj, path, group)) {
690                 int err;
691                 const char *errmsg;
692
693                 err = edje_object_load_error_get(obj);
694                 errmsg = edje_load_error_str(err);
695                 ErrPrint("Could not load %s from %s: %s\n", group, path, errmsg);
696                 evas_object_del(obj);
697                 return -EIO;
698         }
699
700         evas_object_show(obj);
701
702         obj_info = calloc(1, sizeof(*obj_info));
703         if (!obj_info) {
704                 ErrPrint("Failed to add a obj_info\n");
705                 evas_object_del(obj);
706                 return -ENOMEM;
707         }
708
709         obj_info->id = strdup(target_id);
710         if (!obj_info->id) {
711                 ErrPrint("Failed to add a obj_info\n");
712                 free(obj_info);
713                 evas_object_del(obj);
714                 return -ENOMEM;
715         }
716
717         child = malloc(sizeof(*child));
718         if (!child) {
719                 ErrPrint("Error: %s\n", strerror(errno));
720                 free(obj_info->id);
721                 free(obj_info);
722                 evas_object_del(obj);
723                 return -ENOMEM;
724         }
725
726         child->part = strdup(part);
727         if (!child->part) {
728                 ErrPrint("Error: %s\n", strerror(errno));
729                 free(child);
730                 free(obj_info->id);
731                 free(obj_info);
732                 evas_object_del(obj);
733                 return -ENOMEM;
734         }
735
736         child->obj = obj;
737
738         evas_object_data_set(obj, "obj_info", obj_info);
739         evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL, edje_del_cb, handle);
740         edje_object_signal_callback_add(obj, "*", "*", script_signal_cb, handle);
741         handle->obj_list = eina_list_append(handle->obj_list, obj);
742
743         DbgPrint("%s part swallow edje %p\n", part, obj);
744         edje_object_part_swallow(edje, part, obj);
745         obj_info = evas_object_data_get(edje, "obj_info");
746         obj_info->children = eina_list_append(obj_info->children, child);
747         return 0;
748 }
749
750 PUBLIC int script_update_signal(void *h, Evas *e, const char *id, const char *part, const char *signal)
751 {
752         struct info *handle = h;
753         Evas_Object *edje;
754
755         DbgPrint("id[%s], part[%s], signal[%s]\n", id, part, signal);
756
757         edje = find_edje(handle, id);
758         if (!edje)
759                 return -ENOENT;
760
761         edje_object_signal_emit(edje, signal, part);
762         return 0;
763 }
764
765 PUBLIC int script_update_drag(void *h, Evas *e, const char *id, const char *part, double x, double y)
766 {
767         struct info *handle = h;
768         Evas_Object *edje;
769
770         DbgPrint("id[%s], part[%s], %lfx%lf\n", id, part, x, y);
771
772         edje = find_edje(handle, id);
773         if (!edje)
774                 return -ENOENT;
775
776         edje_object_part_drag_value_set(edje, part, x, y);
777         return 0;
778 }
779
780 PUBLIC int script_update_size(void *han, Evas *e, const char *id, int w, int h)
781 {
782         struct info *handle = han;
783         Evas_Object *edje;
784
785         edje = find_edje(handle, id);
786         if (!edje)
787                 return -ENOENT;
788
789         if (!id) {
790                 handle->w = w;
791                 handle->h = h;
792         }
793
794         DbgPrint("Resize object to %dx%d\n", w, h);
795         evas_object_resize(edje, w, h);
796         return 0;
797 }
798
799 PUBLIC int script_update_category(void *h, Evas *e, const char *id, const char *category)
800 {
801         struct info *handle = h;
802
803         DbgPrint("id[%s], category[%s]\n", id, category);
804
805         if (handle->category) {
806                 free(handle->category);
807                 handle->category = NULL;
808         }
809
810         if (!category)
811                 return 0;
812
813         handle->category = strdup(category);
814         if (!handle->category) {
815                 ErrPrint("Error: %s\n", strerror(errno));
816                 return -ENOMEM;
817         }
818
819         return 0;
820 }
821
822 PUBLIC void *script_create(const char *file, const char *group)
823 {
824         struct info *handle;
825
826         DbgPrint("file[%s], group[%s]\n", file, group);
827
828         handle = calloc(1, sizeof(*handle));
829         if (!handle) {
830                 ErrPrint("Error: %s\n", strerror(errno));
831                 return NULL;
832         }
833
834         handle->file = strdup(file);
835         if (!handle->file) {
836                 ErrPrint("Error: %s\n", strerror(errno));
837                 free(handle);
838                 return NULL;
839         }
840
841         handle->group = strdup(group);
842         if (!handle->group) {
843                 ErrPrint("Error: %s\n", strerror(errno));
844                 free(handle->file);
845                 free(handle);
846                 return NULL;
847         }
848
849         return handle;
850 }
851
852 PUBLIC int script_destroy(void *_handle)
853 {
854         struct info *handle;
855         Evas_Object *edje;
856
857         handle = _handle;
858
859         edje = eina_list_nth(handle->obj_list, 0);
860         if (edje)
861                 evas_object_del(edje);
862
863         free(handle->category);
864         free(handle->file);
865         free(handle->group);
866         free(handle);
867         return 0;
868 }
869
870 PUBLIC int script_load(void *_handle, Evas *e, int w, int h)
871 {
872         struct info *handle;
873         Evas_Object *edje;
874         struct obj_info *obj_info;
875
876         handle = _handle;
877
878         obj_info = calloc(1, sizeof(*obj_info));
879         if (!obj_info) {
880                 ErrPrint("Heap: %s\n", strerror(errno));
881                 return -ENOMEM;
882         }
883
884         edje = edje_object_add(e);
885         if (!edje) {
886                 ErrPrint("Failed to create an edje object\n");
887                 free(obj_info);
888                 return -EFAULT;
889         }
890
891         //edje_object_text_class_set(edje, TEXT_CLASS, s_info.font, s_info.size);
892         DbgPrint("Load edje: %s - %s\n", handle->file, handle->group);
893         if (!edje_object_file_set(edje, handle->file, handle->group)) {
894                 int err;
895                 const char *errmsg;
896
897                 err = edje_object_load_error_get(edje);
898                 errmsg = edje_load_error_str(err);
899                 ErrPrint("Could not load %s from %s: %s\n", handle->group, handle->file, errmsg);
900                 evas_object_del(edje);
901                 free(obj_info);
902                 return -EIO;
903         }
904
905         handle->e = e;
906         handle->w = w;
907         handle->h = h;
908
909         edje_object_signal_callback_add(edje, "*", "*", script_signal_cb, handle);
910         evas_object_event_callback_add(edje, EVAS_CALLBACK_DEL, edje_del_cb, handle);
911         evas_object_size_hint_weight_set(edje, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
912         evas_object_size_hint_fill_set(edje, EVAS_HINT_FILL, EVAS_HINT_FILL);
913         evas_object_resize(edje, handle->w, handle->h);
914         evas_object_show(edje);
915         evas_object_data_set(edje, "obj_info", obj_info);
916
917         handle->obj_list = eina_list_append(handle->obj_list, edje);
918         return 0;
919 }
920
921 PUBLIC int script_unload(void *_handle, Evas *e)
922 {
923         struct info *handle;
924         Evas_Object *edje;
925
926         handle = _handle;
927
928         DbgPrint("Unload edje: %s - %s\n", handle->file, handle->group);
929         edje = eina_list_nth(handle->obj_list, 0);
930         if (edje)
931                 evas_object_del(edje);
932         handle->e = NULL;
933         return 0;
934 }
935
936 static Eina_Bool property_cb(void *data, int type, void *event)
937 {
938         Ecore_X_Event_Window_Property *info = (Ecore_X_Event_Window_Property *)event;
939
940         if (info->atom == ecore_x_atom_get("FONT_TYPE_change") || info->atom == ecore_x_atom_get("BADA_FONT_change")) {
941                 Eina_List *list;
942                 char *text;
943                 char *font;
944                 int cache;
945
946                 font = vconf_get_str("db/setting/accessibility/font_name");
947                 if (!font)
948                         return ECORE_CALLBACK_PASS_ON;
949
950                 if (s_info.font)
951                         free(s_info.font);
952
953                 s_info.font = font;
954
955                 cache = evas_common_font_cache_get();
956                 evas_common_font_cache_set(0);
957                 evas_common_font_flush();
958
959                 list = edje_text_class_list();
960                 EINA_LIST_FREE(list, text) {
961                         if (!strncasecmp(text, TEXT_CLASS, strlen(TEXT_CLASS))) {
962                                 edje_text_class_del(text);
963                                 edje_text_class_set(text, s_info.font, s_info.size);
964                                 DbgPrint("Update text class %s (%s, %d)\n", text, s_info.font, s_info.size);
965                         } else {
966                                 DbgPrint("Skip text class %s\n", text);
967                         }
968                 }
969
970                 evas_common_font_cache_set(cache);
971         }
972
973         return ECORE_CALLBACK_PASS_ON;
974 }
975
976 static void font_name_cb(keynode_t *node, void *user_data)
977 {
978         const char *font;
979
980         if (!node)
981                 return;
982
983         font = vconf_keynode_get_str(node);
984         if (!font)
985                 return;
986
987         DbgPrint("Font changed to %s\n", font);
988 }
989
990 static void font_size_cb(keynode_t *node, void *user_data)
991 {
992         if (!node)
993                 return;
994         /*!
995          * \TODO
996          * Implementing me.
997          */
998         DbgPrint("Size type: %d\n", vconf_keynode_get_int(node));
999 }
1000
1001 PUBLIC int script_init(void)
1002 {
1003         int ret;
1004         /* ecore is already initialized */
1005         edje_init();
1006
1007         s_info.property_handler = ecore_event_handler_add(ECORE_X_EVENT_WINDOW_PROPERTY, property_cb, NULL);
1008         if (!s_info.property_handler)
1009                 ErrPrint("Failed to add a property change event handler\n");
1010
1011         ret = vconf_notify_key_changed(VCONFKEY_SETAPPL_ACCESSIBILITY_FONT_SIZE, font_size_cb, NULL);
1012         if (ret < 0)
1013                 ErrPrint("Failed to add vconf for font size change\n");
1014
1015         ret = vconf_notify_key_changed("db/setting/accessibility/font_name", font_name_cb, NULL);
1016         if (ret < 0)
1017                 ErrPrint("Failed to add vconf for font name change\n");
1018
1019         return 0;
1020 }
1021
1022 PUBLIC int script_fini(void)
1023 {
1024
1025         vconf_ignore_key_changed("db/setting/accessibility/font_name", font_name_cb);
1026         vconf_ignore_key_changed(VCONFKEY_SETAPPL_ACCESSIBILITY_FONT_SIZE, font_size_cb);
1027         ecore_event_handler_del(s_info.property_handler);
1028         s_info.property_handler = NULL;
1029         edje_shutdown();
1030         return 0;
1031 }
1032
1033 /* End of a file */