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