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