1 #ifdef HAVE_CONFIG_H
2 # include "elementary_config.h"
3 #endif
4 
5 #include "Elementary.h"
6 #include "private.h"
7 
8 int _elm_ext_log_dom = -1;
9 
10 static int init_count = 0;
11 
12 void
external_elm_init(void)13 external_elm_init(void)
14 {
15    int argc = 0;
16    char **argv = NULL;
17 
18    init_count++;
19    DBG("elm_real_init\n");
20    if (init_count > 1) return;
21    ecore_app_args_get(&argc, &argv);
22    elm_init(argc, argv);
23 }
24 
25 static void
external_elm_shutdown(void)26 external_elm_shutdown(void)
27 {
28    init_count--;
29    DBG("elm_real_shutdown\n");
30    if (init_count > 0) return;
31    elm_shutdown();
32 }
33 
34 void
external_signal(void * data EINA_UNUSED,Evas_Object * obj,const char * sig,const char * source)35 external_signal(void *data EINA_UNUSED, Evas_Object *obj, const char *sig,
36                 const char *source)
37 {
38    char *_signal = strdup(sig);
39    char *p = _signal;
40    Evas_Object *content;
41    Edje_External_Type *type;
42 
43    if (!p) goto on_error;
44 
45    while ((*p!='\0') && (*p!=']'))
46      p++;
47 
48 
49    if ((*p=='\0') || (*(p+1)!=':'))
50      {
51         ERR("Invalid External Signal received: '%s' '%s'", sig, source);
52         goto on_error;
53      }
54 
55    *p = '\0';
56    p+=2; //jump ']' and ':'
57 
58    type = evas_object_data_get(obj, "Edje_External_Type");
59    if (!type)
60      {
61         ERR("no external type for object %p", obj);
62         goto on_error;
63      }
64    if (!type->content_get)
65      {
66         ERR("external type '%s' from module '%s' does not provide content_get()",
67             type->module_name, type->module);
68         goto on_error;
69      }
70 
71    content = type->content_get(type->data, obj, _signal);
72    if (content)
73      edje_object_signal_emit(content, sig + (p - _signal), source);
74 
75 on_error:
76    free(_signal);
77    return;
78 }
79 
80 const char *
external_translate(void * data EINA_UNUSED,const char * orig)81 external_translate(void *data EINA_UNUSED, const char *orig)
82 {
83    // in future, mark all params as translatable and use dgettext()
84    // with "elementary" text domain here.
85    return orig;
86 }
87 
88 typedef struct {
89    const char *emission;
90    const char *source;
91    Evas_Object *edje;
92 } Elm_External_Signals_Proxy_Context;
93 
94 static void
_external_signal_proxy_free_cb(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)95 _external_signal_proxy_free_cb(void *data, Evas *e EINA_UNUSED,
96                                Evas_Object *obj EINA_UNUSED,
97                                void *event_info EINA_UNUSED)
98 {
99    Elm_External_Signals_Proxy_Context *ctxt = data;
100    external_elm_shutdown();
101    free(ctxt);
102 }
103 
104 static void
_external_signal_proxy_cb(void * data,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)105 _external_signal_proxy_cb(void *data, Evas_Object *obj EINA_UNUSED,
106                           void *event_info EINA_UNUSED)
107 {
108    Elm_External_Signals_Proxy_Context *ctxt = data;
109    // TODO: Is it worth to check Evas_Smart_Cb_Description and do something
110    // TODO: with event_info given its description?
111    edje_object_signal_emit(ctxt->edje, ctxt->emission, ctxt->source);
112 }
113 
114 Eina_Bool
external_common_param_get(void * data EINA_UNUSED,const Evas_Object * obj,Edje_External_Param * param)115 external_common_param_get(void *data EINA_UNUSED, const Evas_Object *obj,
116                           Edje_External_Param *param)
117 {
118    if (!strcmp(param->name, "style"))
119      {
120         if (param->type == EDJE_EXTERNAL_PARAM_TYPE_STRING)
121           {
122              param->s = elm_object_style_get(obj);
123              return EINA_TRUE;
124           }
125      }
126    else if (!strcmp(param->name, "disabled"))
127      {
128         if (param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL)
129           {
130              param->i = elm_object_disabled_get(obj);
131              return EINA_TRUE;
132           }
133      }
134    return EINA_FALSE;
135 }
136 
137 Eina_Bool
external_common_param_set(void * data EINA_UNUSED,Evas_Object * obj,const Edje_External_Param * param)138 external_common_param_set(void *data EINA_UNUSED, Evas_Object *obj,
139                           const Edje_External_Param *param)
140 {
141    if (!strcmp(param->name, "style"))
142      {
143          if (param->type == EDJE_EXTERNAL_PARAM_TYPE_STRING)
144            {
145               elm_object_style_set(obj, param->s);
146               return EINA_TRUE;
147            }
148      }
149    else if (!strcmp(param->name, "disabled"))
150      {
151          if (param->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL)
152            {
153               elm_object_disabled_set(obj, param->i);
154               return EINA_TRUE;
155            }
156      }
157    return EINA_FALSE;
158 }
159 
160 void
external_signals_proxy(Evas_Object * obj,Evas_Object * edje,const char * part_name)161 external_signals_proxy(Evas_Object *obj, Evas_Object *edje, const char *part_name)
162 {
163    const Evas_Smart_Cb_Description **cls_descs, **inst_descs;
164    unsigned int cls_count, inst_count, total;
165    Elm_External_Signals_Proxy_Context *ctxt;
166 
167    evas_object_smart_callbacks_descriptions_get
168      (obj, &cls_descs, &cls_count, &inst_descs, &inst_count);
169 
170    total = cls_count + inst_count;
171    if (!total) return;
172    ctxt = malloc(sizeof(Elm_External_Signals_Proxy_Context) * total);
173    if (!ctxt) return;
174    evas_object_event_callback_add
175      (obj, EVAS_CALLBACK_FREE, _external_signal_proxy_free_cb, ctxt);
176 
177    for (; cls_count > 0; cls_count--,  cls_descs++, ctxt++)
178      {
179         const Evas_Smart_Cb_Description *d = *cls_descs;
180         ctxt->emission = d->name;
181         ctxt->source = part_name;
182         ctxt->edje = edje;
183         evas_object_smart_callback_add
184            (obj, d->name, _external_signal_proxy_cb, ctxt);
185      }
186 
187    for (; inst_count > 0; inst_count--,  inst_descs++, ctxt++)
188      {
189         const Evas_Smart_Cb_Description *d = *inst_descs;
190         ctxt->emission = d->name;
191         ctxt->source = part_name;
192         ctxt->edje = edje;
193         evas_object_smart_callback_add
194            (obj, d->name, _external_signal_proxy_cb, ctxt);
195      }
196 }
197 
198 void
external_common_params_parse(void * mem,void * data EINA_UNUSED,Evas_Object * obj EINA_UNUSED,const Eina_List * params)199 external_common_params_parse(void *mem, void *data EINA_UNUSED,
200                              Evas_Object *obj EINA_UNUSED,
201                              const Eina_List *params)
202 {
203    Elm_Params *p;
204    const Eina_List *l;
205    Edje_External_Param *param;
206 
207    p = mem;
208    EINA_LIST_FOREACH(params, l, param)
209      {
210         if (!strcmp(param->name, "style"))
211           p->style = eina_stringshare_add(param->s);
212         else if (!strcmp(param->name, "disabled"))
213           {
214              p->disabled = param->i;
215              p->disabled_exists = EINA_TRUE;
216           }
217      }
218 }
219 
220 void
external_common_state_set(void * data EINA_UNUSED,Evas_Object * obj,const void * from_params,const void * to_params,float pos EINA_UNUSED)221 external_common_state_set(void *data EINA_UNUSED, Evas_Object *obj,
222                           const void *from_params, const void *to_params,
223                           float pos EINA_UNUSED)
224 {
225    const Elm_Params *p;
226    if (to_params) p = to_params;
227    else if (from_params) p = from_params;
228    else return;
229 
230    if (p->style)
231       elm_object_style_set(obj, p->style);
232    if (p->disabled_exists)
233      elm_object_disabled_set(obj, p->disabled);
234 }
235 
236 Evas_Object *
external_common_param_icon_get(Evas_Object * obj,const Edje_External_Param * p)237 external_common_param_icon_get(Evas_Object *obj, const Edje_External_Param *p)
238 {
239    Evas_Object *edje, *parent_widget, *icon;
240    const char *file;
241 
242    if ((!p) || (!p->s) || (p->type != EDJE_EXTERNAL_PARAM_TYPE_STRING))
243        return NULL;
244 
245    edje = evas_object_smart_parent_get(obj);
246    edje_object_file_get(edje, &file, NULL);
247 
248    parent_widget = elm_widget_parent_widget_get(obj);
249    if (!parent_widget)
250      parent_widget = edje;
251    icon = elm_icon_add(parent_widget);
252 
253    if ((edje_file_group_exists(file, p->s)) &&
254        (elm_image_file_set(icon, file, p->s)))
255      return icon;
256    if (elm_icon_standard_set(icon, p->s))
257      return icon;
258 
259    ERR("Failed to set icon: '%s'", p->s);
260    evas_object_del(icon);
261    return NULL;
262 }
263 
264 void
external_common_icon_param_parse(Evas_Object ** icon,Evas_Object * obj,const Eina_List * params)265 external_common_icon_param_parse(Evas_Object **icon, Evas_Object *obj,
266                                  const Eina_List *params)
267 {
268    Edje_External_Param *p = edje_external_param_find(params, "icon");
269    *icon = external_common_param_icon_get(obj, p);
270 }
271 
272 Evas_Object *
external_common_param_elm_layout_get(Evas_Object * obj,const Edje_External_Param * p)273 external_common_param_elm_layout_get(Evas_Object *obj,
274                                      const Edje_External_Param *p)
275 {
276    Evas_Object *edje, *parent_widget, *ret;
277    const char *file;
278 
279    if ((!p) || (!p->s) || (p->type != EDJE_EXTERNAL_PARAM_TYPE_STRING))
280        return NULL;
281 
282    edje = evas_object_smart_parent_get(obj);
283    edje_object_file_get(edje, &file, NULL);
284 
285    parent_widget = elm_widget_parent_widget_get(obj);
286    if (parent_widget)
287      {
288         ret = elm_layout_add(parent_widget);
289         if (elm_layout_file_set(ret, file, p->s))
290           return ret;
291      }
292    else
293      {
294         ret = edje_object_add(evas_object_evas_get(edje));
295         if (edje_object_file_set(ret, file, p->s))
296           return ret;
297      }
298    evas_object_del(ret);
299    return NULL;
300 }
301 
302 void
external_common_params_free(void * params)303 external_common_params_free(void *params)
304 {
305    Elm_Params *p = params;
306    if (p->style)
307      eina_stringshare_del(p->style);
308 }
309 
310 #define DEFINE_TYPE(type_name) \
311   extern const Edje_External_Type external_##type_name##_type;
312 #include "modules.inc"
313 #undef DEFINE_TYPE
314 
315 static Edje_External_Type_Info elm_external_types[] =
316 {
317 #define DEFINE_TYPE(type_name)              \
318   { "elm/"#type_name, &external_##type_name##_type },
319 #include "modules.inc"
320 #undef DEFINE_TYPE
321    { NULL, NULL }
322 };
323 
324 static Eina_Bool
elm_mod_init(void)325 elm_mod_init(void)
326 {
327    _elm_ext_log_dom = eina_log_domain_register("elm-externals",
328                                                EINA_COLOR_LIGHTBLUE);
329    edje_external_type_array_register(elm_external_types);
330    return EINA_TRUE;
331 }
332 
333 static void
elm_mod_shutdown(void)334 elm_mod_shutdown(void)
335 {
336    edje_external_type_array_unregister(elm_external_types);
337    if (_elm_ext_log_dom >= 0) eina_log_domain_unregister(_elm_ext_log_dom);
338    _elm_ext_log_dom = -1;
339 }
340 
341 EINA_MODULE_INIT(elm_mod_init);
342 EINA_MODULE_SHUTDOWN(elm_mod_shutdown);
343