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