Imported Upstream version 1.7.1
[platform/upstream/edje.git] / src / lib / edje_external.c
1 #include "edje_private.h"
2
3 static Eina_Hash *type_registry = NULL;
4 static int init_count = 0;
5
6 EAPI const char *
7 edje_external_param_type_str(Edje_External_Param_Type type)
8 {
9    switch (type)
10      {
11       case EDJE_EXTERNAL_PARAM_TYPE_INT:
12          return "INT";
13       case EDJE_EXTERNAL_PARAM_TYPE_DOUBLE:
14          return "DOUBLE";
15       case EDJE_EXTERNAL_PARAM_TYPE_STRING:
16          return "STRING";
17       case EDJE_EXTERNAL_PARAM_TYPE_BOOL:
18          return "BOOL";
19       case EDJE_EXTERNAL_PARAM_TYPE_CHOICE:
20          return "CHOICE";
21       default:
22          return "(unknown)";
23      }
24 }
25
26 EAPI Evas_Object *
27 edje_object_part_external_object_get(const Evas_Object *obj, const char *part)
28 {
29    Edje *ed;
30    Edje_Real_Part *rp;
31
32    ed = _edje_fetch(obj);
33    if ((!ed) || (!part)) return NULL;
34
35    /* Need to recalc before providing the object. */
36    _edje_recalc_do(ed);
37
38    rp = _edje_real_part_recursive_get(ed, (char *)part);
39    if (!rp)
40      {
41         ERR("no part '%s'", part);
42         return NULL;
43      }
44    if (rp->part->type != EDJE_PART_TYPE_EXTERNAL)
45      {
46         ERR("cannot get external object of a part '%s' that is not EXTERNAL",
47             rp->part->name);
48         return NULL;
49      }
50    return rp->swallowed_object;
51 }
52
53 EAPI Eina_Bool
54 edje_object_part_external_param_set(Evas_Object *obj, const char *part, const Edje_External_Param *param)
55 {
56    Edje *ed;
57    Edje_Real_Part *rp;
58
59    if ((!param) || (!param->name)) return EINA_FALSE;
60
61    ed = _edje_fetch(obj);
62    if ((!ed) || (!part)) return EINA_FALSE;
63
64    rp = _edje_real_part_recursive_get(ed, (char *)part);
65    if (!rp)
66      {
67         ERR("no part '%s'", part);
68         return EINA_FALSE;
69      }
70
71    return _edje_external_param_set(obj, rp, param);
72 }
73
74 EAPI Eina_Bool
75 edje_object_part_external_param_get(const Evas_Object *obj, const char *part, Edje_External_Param *param)
76 {
77    Edje *ed;
78    Edje_Real_Part *rp;
79
80    if ((!param) || (!param->name)) return EINA_FALSE;
81
82    ed = _edje_fetch(obj);
83    if ((!ed) || (!part)) return EINA_FALSE;
84
85    rp = _edje_real_part_recursive_get(ed, (char *)part);
86    if (!rp)
87      {
88         ERR("no part '%s'", part);
89         return EINA_FALSE;
90      }
91
92    return _edje_external_param_get(obj, rp, param);
93 }
94
95
96
97 EAPI Evas_Object *
98 edje_object_part_external_content_get(const Evas_Object *obj, const char *part, const char *content)
99 {
100    Edje *ed;
101    Edje_Real_Part *rp;
102
103    if (!content) return EINA_FALSE;
104
105    ed = _edje_fetch(obj);
106    if ((!ed) || (!part)) return EINA_FALSE;
107
108    rp = _edje_real_part_recursive_get(ed, (char *)part);
109    if (!rp)
110      {
111         ERR("no part '%s'", part);
112         return EINA_FALSE;
113      }
114
115    return _edje_external_content_get(rp->swallowed_object, content);
116 }
117
118 EAPI Edje_External_Param_Type
119 edje_object_part_external_param_type_get(const Evas_Object *obj, const char *part, const char *param)
120 {
121    Edje *ed;
122    Edje_Real_Part *rp;
123    Edje_External_Type *type;
124    Edje_External_Param_Info *info;
125
126    ed = _edje_fetch(obj);
127    if ((!ed) || (!part)) return EDJE_EXTERNAL_PARAM_TYPE_MAX;
128
129    rp = _edje_real_part_recursive_get(ed, (char *)part);
130    if (!rp)
131      {
132         ERR("no part '%s'", part);
133         return EDJE_EXTERNAL_PARAM_TYPE_MAX;
134      }
135    type = evas_object_data_get(rp->swallowed_object, "Edje_External_Type");
136    if (!type)
137      {
138         ERR("no external type for object %p", obj);
139         return EDJE_EXTERNAL_PARAM_TYPE_MAX;
140      }
141    if (!type->parameters_info)
142      {
143         ERR("no parameters information for external type '%s'",
144             type->module_name);
145         return EDJE_EXTERNAL_PARAM_TYPE_MAX;
146      }
147    for (info = type->parameters_info; info->name; info++)
148      if (strcmp(info->name, param) == 0)
149        return info->type;
150
151    ERR("no parameter '%s' external type '%s'", param, type->module_name);
152    return EDJE_EXTERNAL_PARAM_TYPE_MAX;
153 }
154
155
156 EAPI Eina_Bool
157 edje_external_type_register(const char *type_name, const Edje_External_Type *type_info)
158 {
159    if (!type_name)
160      return EINA_FALSE;
161    if (!type_info)
162      return EINA_FALSE;
163
164    if (type_info->abi_version != EDJE_EXTERNAL_TYPE_ABI_VERSION)
165      {
166         ERR("external type '%s' (%p) has incorrect abi version. "
167                "got %#x where %#x was expected.",
168                type_name, type_info,
169                type_info->abi_version, EDJE_EXTERNAL_TYPE_ABI_VERSION);
170         return EINA_FALSE;
171      }
172
173    if (eina_hash_find(type_registry, type_name))
174      {
175         ERR("External type '%s' already registered", type_name);
176         return EINA_FALSE;
177      }
178    return eina_hash_add(type_registry, type_name, type_info);
179 }
180
181 EAPI Eina_Bool
182 edje_external_type_unregister(const char *type_name)
183 {
184    if (!type_name)
185      return EINA_FALSE;
186    return eina_hash_del_by_key(type_registry, type_name);
187 }
188
189 EAPI void
190 edje_external_type_array_register(const Edje_External_Type_Info *array)
191 {
192    const Edje_External_Type_Info *itr;
193
194    if (!array)
195      return;
196
197    for (itr = array; itr->name; itr++)
198      {
199         if (itr->info->abi_version != EDJE_EXTERNAL_TYPE_ABI_VERSION)
200           {
201              ERR("external type '%s' (%p) has incorrect abi "
202                     "version. got %#x where %#x was expected.",
203                     itr->name, itr->info,
204                     itr->info->abi_version, EDJE_EXTERNAL_TYPE_ABI_VERSION);
205              continue;
206           }
207
208         eina_hash_direct_add(type_registry, itr->name, itr->info);
209      }
210 }
211
212 EAPI void
213 edje_external_type_array_unregister(const Edje_External_Type_Info *array)
214 {
215    const Edje_External_Type_Info *itr;
216
217    if (!array)
218      return;
219
220    for (itr = array; itr->name; itr++)
221      eina_hash_del(type_registry, itr->name, itr->info);
222 }
223
224 EAPI unsigned int
225 edje_external_type_abi_version_get(void)
226 {
227    return EDJE_EXTERNAL_TYPE_ABI_VERSION;
228 }
229
230 EAPI Eina_Iterator *
231 edje_external_iterator_get(void)
232 {
233    return eina_hash_iterator_tuple_new(type_registry);
234 }
235
236 EAPI Edje_External_Param *
237 edje_external_param_find(const Eina_List *params, const char *key)
238 {
239    const Eina_List *l;
240    Edje_External_Param *param;
241
242    EINA_LIST_FOREACH(params, l, param)
243       if (!strcmp(param->name, key)) return param;
244
245    return NULL;
246 }
247
248 EAPI Eina_Bool
249 edje_external_param_int_get(const Eina_List *params, const char *key, int *ret)
250 {
251    Edje_External_Param *param;
252
253    if (!params) return EINA_FALSE;
254    param = edje_external_param_find(params, key);
255
256    if (param && param->type == EDJE_EXTERNAL_PARAM_TYPE_INT && ret)
257      {
258         *ret = param->i;
259         return EINA_TRUE;
260      }
261
262    return EINA_FALSE;
263 }
264
265 EAPI Eina_Bool
266 edje_external_param_double_get(const Eina_List *params, const char *key, double *ret)
267 {
268    Edje_External_Param *param;
269
270    if (!params) return EINA_FALSE;
271    param = edje_external_param_find(params, key);
272
273    if (param && param->type == EDJE_EXTERNAL_PARAM_TYPE_DOUBLE && ret)
274      {
275         *ret = param->d;
276         return EINA_TRUE;
277      }
278
279    return EINA_FALSE;
280 }
281
282 EAPI Eina_Bool
283 edje_external_param_string_get(const Eina_List *params, const char *key, const char **ret)
284 {
285    Edje_External_Param *param;
286
287    if (!params) return EINA_FALSE;
288    param = edje_external_param_find(params, key);
289
290    if (param && param->type == EDJE_EXTERNAL_PARAM_TYPE_STRING && ret)
291      {
292         *ret = param->s;
293         return EINA_TRUE;
294      }
295
296    return EINA_FALSE;
297 }
298
299 EAPI Eina_Bool
300 edje_external_param_bool_get(const Eina_List *params, const char *key, Eina_Bool *ret)
301 {
302    Edje_External_Param *param;
303
304    if (!params) return EINA_FALSE;
305    param = edje_external_param_find(params, key);
306
307    if (param && param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL && ret)
308      {
309         *ret = param->i;
310         return EINA_TRUE;
311      }
312
313    return EINA_FALSE;
314 }
315
316 EAPI Eina_Bool
317 edje_external_param_choice_get(const Eina_List *params, const char *key, const char **ret)
318 {
319    Edje_External_Param *param;
320
321    if (!params) return EINA_FALSE;
322    param = edje_external_param_find(params, key);
323
324    if (param && param->type == EDJE_EXTERNAL_PARAM_TYPE_CHOICE && ret)
325      {
326         *ret = param->s;
327         return EINA_TRUE;
328      }
329
330    return EINA_FALSE;
331 }
332
333 EAPI const Edje_External_Param_Info *
334 edje_external_param_info_get(const char *type_name)
335 {
336    Edje_External_Type *type;
337
338    type = eina_hash_find(type_registry, type_name);
339    if (!type)
340      return NULL;
341    return type->parameters_info;
342 }
343
344 EAPI const Edje_External_Type *
345 edje_external_type_get(const char *type_name)
346 {
347    return eina_hash_find(type_registry, type_name);
348 }
349
350 void
351 _edje_external_init()
352 {
353    if (!type_registry)
354      type_registry = eina_hash_string_superfast_new(NULL);
355
356    init_count++;
357 }
358
359 void
360 _edje_external_shutdown()
361 {
362    if (--init_count == 0)
363      {
364         eina_hash_free(type_registry);
365         type_registry = NULL;
366      }
367 }
368
369 Evas_Object *
370 _edje_external_type_add(const char *type_name, Evas *evas, Evas_Object *parent, const Eina_List *params, const char *part_name)
371 {
372    Edje_External_Type *type;
373    Evas_Object *obj;
374
375    type = eina_hash_find(type_registry, type_name);
376    if (!type)
377      {
378         ERR("external type '%s' not registered", type_name);
379         return NULL;
380      }
381
382    obj = type->add(type->data, evas, parent, params, part_name);
383    if (!obj)
384      {
385         ERR("External type '%s' returned NULL from constructor", type_name);
386         return NULL;
387      }
388
389    evas_object_data_set(obj, "Edje_External_Type", type);
390
391    return obj;
392 }
393
394 void
395 _edje_external_signal_emit(Evas_Object *obj, const char *emission, const char *source)
396 {
397    Edje_External_Type *type;
398
399    type = evas_object_data_get(obj, "Edje_External_Type");
400    if (!type)
401      {
402         ERR("External type data not found.");
403         return;
404      }
405
406    type->signal_emit(type->data, obj, emission, source);
407 }
408
409 Eina_Bool
410 _edje_external_param_set(Evas_Object *obj, Edje_Real_Part *rp, const Edje_External_Param *param)
411 {
412    Evas_Object *swallowed_object = rp->swallowed_object;
413    Edje_External_Type *type = evas_object_data_get(swallowed_object, "Edje_External_Type");
414    if (!type)
415      {
416         if ((rp->part->type == EDJE_PART_TYPE_TEXT) ||
417             (rp->part->type == EDJE_PART_TYPE_TEXTBLOCK))
418           {
419              if ((param->type == EDJE_EXTERNAL_PARAM_TYPE_STRING) &&
420                  (!strcmp (param->name, "text")) && (obj))
421                 {
422                    return edje_object_part_text_set(obj, rp->part->name, param->s);
423                 }
424           }
425
426         ERR("no external type for object %p", swallowed_object);
427         return EINA_FALSE;
428      }
429    if (!type->param_set)
430      {
431         ERR("external type '%s' from module '%s' does not provide param_set()",
432             type->module_name, type->module);
433         return EINA_FALSE;
434      }
435    return type->param_set(type->data, swallowed_object, param);
436 }
437
438 Eina_Bool
439 _edje_external_param_get(const Evas_Object *obj, Edje_Real_Part *rp, Edje_External_Param *param)
440 {
441    Evas_Object *swallowed_object = rp->swallowed_object;
442    Edje_External_Type *type = evas_object_data_get(swallowed_object, "Edje_External_Type");
443    if (!type)
444      {
445         if ((rp->part->type == EDJE_PART_TYPE_TEXT) ||
446             (rp->part->type == EDJE_PART_TYPE_TEXTBLOCK))
447           {
448              const char *text;
449              param->type = EDJE_EXTERNAL_PARAM_TYPE_STRING;
450              param->name = "text";
451              text = edje_object_part_text_get(obj, rp->part->name);
452              param->s = text;
453              return EINA_TRUE;
454           }
455        
456         ERR("no external type for object %p", swallowed_object);
457         return EINA_FALSE;
458      }
459    if (!type->param_get)
460      {
461         ERR("external type '%s' from module '%s' does not provide param_get()",
462             type->module_name, type->module);
463         return EINA_FALSE;
464      }
465    return type->param_get(type->data, swallowed_object, param);
466 }
467
468 Evas_Object*
469 _edje_external_content_get(const Evas_Object *obj, const char *content)
470 {
471    Edje_External_Type *type = evas_object_data_get(obj, "Edje_External_Type");
472    if (!type)
473      {
474         ERR("no external type for object %p", obj);
475         return EINA_FALSE;
476      }
477    if (!type->content_get)
478      {
479         ERR("external type '%s' from module '%s' does not provide content_get()",
480             type->module_name, type->module);
481         return EINA_FALSE;
482      }
483    return type->content_get(type->data, obj, content);
484 }
485
486 void
487 _edje_external_params_free(Eina_List *external_params, Eina_Bool free_strings)
488 {
489    Edje_External_Param *param;
490
491    EINA_LIST_FREE(external_params, param)
492      {
493         if (free_strings)
494           {
495              if (param->name) eina_stringshare_del(param->name);
496              if (param->s) eina_stringshare_del(param->s);
497           }
498         free(param);
499      }
500 }
501
502 void
503 _edje_external_recalc_apply(Edje *ed __UNUSED__, Edje_Real_Part *ep,
504                             Edje_Calc_Params *params __UNUSED__,
505                             Edje_Part_Description_Common *chosen_desc __UNUSED__)
506 {
507    Edje_External_Type *type;
508    Edje_Part_Description_External *ext;
509    void *params1, *params2 = NULL;
510
511    if (!ep->swallowed_object) return;
512    type = evas_object_data_get(ep->swallowed_object, "Edje_External_Type");
513
514    if ((!type) || (!type->state_set)) return;
515
516    ext = (Edje_Part_Description_External*) ep->param1.description;
517
518    params1 = ep->param1.external_params ?
519      ep->param1.external_params : ext->external_params;
520
521    if (ep->param2 && ep->param2->description)
522      {
523         ext = (Edje_Part_Description_External*) ep->param2->description;
524
525         params2 = ep->param2->external_params ?
526           ep->param2->external_params : ext->external_params;
527      }
528
529    type->state_set(type->data, ep->swallowed_object,
530                    params1, params2, ep->description_pos);
531 }
532
533 void *
534 _edje_external_params_parse(Evas_Object *obj, const Eina_List *params)
535 {
536    Edje_External_Type *type;
537
538    type = evas_object_data_get(obj, "Edje_External_Type");
539    if (!type) return NULL;
540
541    if (!type->params_parse) return NULL;
542
543    return type->params_parse(type->data, obj, params);
544 }
545
546 void
547 _edje_external_parsed_params_free(Evas_Object *obj, void *params)
548 {
549    Edje_External_Type *type;
550
551    if (!params) return;
552
553    type = evas_object_data_get(obj, "Edje_External_Type");
554    if (!type) return;
555
556    if (!type->params_free) return;
557
558    type->params_free(params);
559 }