Hey everyone,
I've attached a patch that implements a new edje part type: EXTERNAL.
The basic idea is as follows:

An application (or library) can implement swallowable widgets that are keyed by a type name. By implementing a few callbacks and registering with edje, the app can allow a themer to include a part of this type by simply doing:

part {
   name: "external_part";
   type: EXTERNAL;
   source: "type_name";
   description {
      ...
      params { int: "foo" 10; string: "bar" "str_val"; ... }
   }
}


The current callbacks are:

Evas_Object *add(void *data, Evas *e, Evas_Object *parent, const Eina_List *params)
   gets called when edje loads and finds an external part of this type
   the parent object is passed in so that it can be sent signals/messages

void signal_emit(void *data, Evas_Object *obj, const char *emission, const char *source) probably should be called 'signal_recv' or so, but gets called when a signal like 'external_part:signal_name' is sent to the parent edj (like GROUP objects, the part name and colon gets stripped off).

void state_set(void *data, Evas_Object *obj, const Eina_List *from_params, const Eina_List *to_params, float pos) called whenever the state changes (including repeatedly while tweening between states)
   use pos to linearly interpolate params between states

I also attached a really basic test program (nothing fancy, left or right click on the bg to trigger state changes or press 's' to switch themes) to illustrate the usage.

It would be interesting to register all of elementary's widgets with edje in this fashion. (We'd still need some way for the theme to specify which app data should be associated with the widget).

Anyway, before committing this, I'd like to get some feedback on the API and ideas for how to extend this concept.

Brian

Attachment: external_test.tar.gz
Description: application/gzip

diff --git a/src/bin/edje_cc_handlers.c b/src/bin/edje_cc_handlers.c
index c68a4e3..2ad00d2 100644
--- a/src/bin/edje_cc_handlers.c
+++ b/src/bin/edje_cc_handlers.c
@@ -129,6 +129,7 @@ static void st_collections_group_parts_part_box_items_item_options(void);
 static void st_collections_group_parts_part_table_items_item_position(void);
 static void st_collections_group_parts_part_table_items_item_span(void);
 
+
 static void ob_collections_group_parts_part_description(void);
 static void st_collections_group_parts_part_description_inherit(void);
 static void st_collections_group_parts_part_description_state(void);
@@ -194,6 +195,11 @@ static void st_collections_group_parts_part_description_table_homogeneous(void);
 static void st_collections_group_parts_part_description_table_align(void);
 static void st_collections_group_parts_part_description_table_padding(void);
 
+/* external part parameters */
+static void st_collections_group_parts_part_description_params_int(void);
+static void st_collections_group_parts_part_description_params_double(void);
+static void st_collections_group_parts_part_description_params_string(void);
+
 static void ob_collections_group_programs_program(void);
 static void st_collections_group_programs_program_name(void);
 static void st_collections_group_programs_program_signal(void);
@@ -391,6 +397,9 @@ New_Statement_Handler statement_handlers[] =
      {"collections.group.parts.part.description.table.homogeneous", st_collections_group_parts_part_description_table_homogeneous},
      {"collections.group.parts.part.description.table.align", st_collections_group_parts_part_description_table_align},
      {"collections.group.parts.part.description.table.padding", st_collections_group_parts_part_description_table_padding},
+     {"collections.group.parts.part.description.params.int", st_collections_group_parts_part_description_params_int},
+     {"collections.group.parts.part.description.params.double", st_collections_group_parts_part_description_params_double},
+     {"collections.group.parts.part.description.params.string", st_collections_group_parts_part_description_params_string},
      {"collections.group.parts.part.description.images.image", st_images_image}, /* dup */
      {"collections.group.parts.part.description.font", st_fonts_font}, /* dup */
      {"collections.group.parts.part.description.fonts.font", st_fonts_font}, /* dup */
@@ -550,6 +559,7 @@ New_Object_Handler object_handlers[] =
      {"collections.group.parts.part.description.gradient.rel2", NULL},
      {"collections.group.parts.part.description.box", NULL},
      {"collections.group.parts.part.description.table", NULL},
+     {"collections.group.parts.part.description.params", NULL},
      {"collections.group.parts.part.description.color_classes", NULL}, /* dup */
      {"collections.group.parts.part.description.color_classes.color_class", ob_color_class}, /* dup */
      {"collections.group.parts.part.description.program", ob_collections_group_programs_program}, /* dup */
@@ -1651,6 +1661,7 @@ st_collections_group_parts_part_type(void)
 			 "GROUP", EDJE_PART_TYPE_GROUP,
 			 "BOX", EDJE_PART_TYPE_BOX,
 			 "TABLE", EDJE_PART_TYPE_TABLE,
+			 "EXTERNAL", EDJE_PART_TYPE_EXTERNAL,
 			 NULL);
 }
 
@@ -2910,6 +2921,7 @@ ob_collections_group_parts_part_description(void)
    ed->table.align.y = 0.5;
    ed->table.padding.x = 0;
    ed->table.padding.y = 0;
+   ed->external_params = NULL;
 }
 
 /**
@@ -3044,6 +3056,20 @@ st_collections_group_parts_part_description_inherit(void)
 
    data_queue_part_slave_lookup(&(parent->text.id_source), &(ed->text.id_source));
    data_queue_part_slave_lookup(&(parent->text.id_text_source), &(ed->text.id_text_source));
+
+   if (parent->external_params)
+     {
+	Eina_List *l;
+	Edje_External_Param *param, *new_param;
+
+	ed->external_params = NULL;
+	EINA_LIST_FOREACH(parent->external_params, l, param)
+	  {
+	     new_param = mem_alloc(SZ(Edje_External_Param));
+	     *new_param = *param;
+	     ed->external_params = eina_list_append(ed->external_params, new_param);
+	  }
+     }
 }
 
 /**
@@ -5415,6 +5441,121 @@ static void st_collections_group_parts_part_description_table_padding(void)
    ed->table.padding.y = parse_int_range(1, 0, 0x7fffffff);
 }
 
+static void
+_st_collections_group_parts_part_description_params(Edje_External_Param_Type type)
+{
+   Edje_Part_Collection *pc;
+   Edje_Part *ep;
+   Edje_Part_Description *ed;
+   Edje_External_Param *param;
+   Eina_List *l;
+   const char *name;
+   int found = 0;
+
+   check_arg_count(2);
+
+   pc = eina_list_data_get(eina_list_last(edje_collections));
+   ep = eina_list_data_get(eina_list_last(pc->parts));
+
+   if (ep->type != EDJE_PART_TYPE_EXTERNAL)
+     {
+	fprintf(stderr, "%s: Error. parse error %s:%i. "
+		"params in non-EXTERNAL part.\n",
+		progname, file_in, line - 1);
+	exit(-1);
+     }
+
+   ed = ep->default_desc;
+   if (ep->other_desc) ed = eina_list_data_get(eina_list_last(ep->other_desc));
+
+   name = parse_str(0);
+
+   /* if a param with this name already exists, overwrite it */
+   EINA_LIST_FOREACH(ed->external_params, l, param)
+     {
+	if (!strcmp(param->name, name))
+	  {
+	     found = 1;
+	     break;
+	  }
+     }
+
+   if (!found)
+     {
+	param = mem_alloc(SZ(Edje_External_Param));
+	param->name = name;
+     }
+
+   param->type = type;
+   param->i = 0;
+   param->d = 0;
+   param->s = NULL;
+
+   switch (type)
+     {
+      case EDJE_EXTERNAL_PARAM_TYPE_INT:
+	 param->i = parse_int(1);
+	 break;
+      case EDJE_EXTERNAL_PARAM_TYPE_DOUBLE:
+	 param->d = parse_float(1);
+	 break;
+      case EDJE_EXTERNAL_PARAM_TYPE_STRING:
+	 param->s = parse_str(1);
+	 break;
+     }
+
+   if (!found)
+     ed->external_params = eina_list_append(ed->external_params, param);
+}
+
+/**
+    @page edcref
+    @property
+        inherit
+    @parameters
+        [param_name] [int_value]
+    @effect
+	Adds an integer parameter for an external object
+    @endproperty
+*/
+static void
+st_collections_group_parts_part_description_params_int(void)
+{
+   _st_collections_group_parts_part_description_params(EDJE_EXTERNAL_PARAM_TYPE_INT);
+}
+
+/**
+    @page edcref
+    @property
+        inherit
+    @parameters
+        [param_name] [double_value]
+    @effect
+	Adds a double parameter for an external object
+    @endproperty
+*/
+static void
+st_collections_group_parts_part_description_params_double(void)
+{
+   _st_collections_group_parts_part_description_params(EDJE_EXTERNAL_PARAM_TYPE_DOUBLE);
+}
+
+/**
+    @page edcref
+    @property
+        inherit
+    @parameters
+        [param_name] [string_value]
+    @effect
+	Adds a string parameter for an external object
+    @endproperty
+*/
+static void
+st_collections_group_parts_part_description_params_string(void)
+{
+   _st_collections_group_parts_part_description_params(EDJE_EXTERNAL_PARAM_TYPE_STRING);
+}
+
 /**
     @page edcref
     @block
diff --git a/src/lib/Edje.h b/src/lib/Edje.h
index e776861..64439ae 100644
--- a/src/lib/Edje.h
+++ b/src/lib/Edje.h
@@ -162,6 +162,37 @@ enum
      EDJE_LOAD_ERROR_RECURSIVE_REFERENCE = 9
 };
 
+enum _Edje_External_Param_Type
+{
+  EDJE_EXTERNAL_PARAM_TYPE_INT,
+  EDJE_EXTERNAL_PARAM_TYPE_DOUBLE,
+  EDJE_EXTERNAL_PARAM_TYPE_STRING,
+  EDJE_EXTERNAL_PARAM_TYPE_MAX
+};
+typedef enum _Edje_External_Param_Type Edje_External_Param_Type;
+
+struct _Edje_External_Param
+{
+  const char *name;
+  Edje_External_Param_Type type;
+  // XXX these could be in a union, but eet doesn't support them (or does it?)
+  int i;
+  double d;
+  const char *s;
+};
+typedef struct _Edje_External_Param Edje_External_Param;
+
+struct _Edje_External_Type
+{
+  Evas_Object *(*add) (void *data, Evas *evas, Evas_Object *parent, const Eina_List *params);
+  void (*state_set) (void *data, Evas_Object *obj, const Eina_List *from_params, const Eina_List *to_params, float pos);
+  void (*signal_emit) (void *data, Evas_Object *obj, const char *emission, const char *source);
+
+  void *data;
+};
+typedef struct _Edje_External_Type Edje_External_Type;
+
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -295,6 +326,12 @@ extern "C" {
 
    EAPI void         edje_message_signal_process        (void);
 
+
+   /* edje_external.c */
+  EAPI Eina_Bool edje_external_type_register(const char *type_name, Edje_External_Type *type_info);
+  EAPI Eina_Bool edje_external_type_unregister(const char *type_name);
+  EAPI Edje_External_Param *edje_external_param_find(const Eina_List *params, const char *key);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am
index 0e6b159..81b61c9 100644
--- a/src/lib/Makefile.am
+++ b/src/lib/Makefile.am
@@ -40,7 +40,8 @@ edje_match.c \
 edje_textblock_styles.c \
 edje_edit.c \
 edje_script_only.c \
-edje_entry.c
+edje_entry.c \
+edje_external.c
 
 libedje_la_LIBADD = @EDJE_LIBS@ @ECORE_IMF_LIBS@ -lm
 libedje_la_LDFLAGS = -no-undefined @lt_enable_auto_import@ -version-info @version_info@ @release_info@
diff --git a/src/lib/edje_calc.c b/src/lib/edje_calc.c
index 342d51a..bf5b7f1 100644
--- a/src/lib/edje_calc.c
+++ b/src/lib/edje_calc.c
@@ -1570,6 +1570,7 @@ _edje_part_recalc(Edje *ed, Edje_Real_Part *ep, int flags)
 	      /* move and resize are needed for all previous object => no break here. */
 	   case EDJE_PART_TYPE_SWALLOW:
 	   case EDJE_PART_TYPE_GROUP:
+	   case EDJE_PART_TYPE_EXTERNAL:
 	      /* visibility and color have no meaning on SWALLOW and GROUP part. */
 	      evas_object_move(ep->object, ed->x + pf->x, ed->y + pf->y);
 	      evas_object_resize(ep->object, pf->w, pf->h);
@@ -1599,6 +1600,9 @@ _edje_part_recalc(Edje *ed, Edje_Real_Part *ep, int flags)
 	   case EDJE_PART_TYPE_TABLE:
 	      _edje_table_recalc_apply(ed, ep, pf, chosen_desc);
 	      break;
+	   case EDJE_PART_TYPE_EXTERNAL:
+	      _edje_external_recalc_apply(ed, ep, pf, chosen_desc);
+	      break;
 	   case EDJE_PART_TYPE_RECTANGLE:
 	   case EDJE_PART_TYPE_SWALLOW:
 	   case EDJE_PART_TYPE_GROUP:
diff --git a/src/lib/edje_data.c b/src/lib/edje_data.c
index 63ccb51..084b65e 100644
--- a/src/lib/edje_data.c
+++ b/src/lib/edje_data.c
@@ -26,6 +26,7 @@ EAPI Eet_Data_Descriptor *_edje_edd_edje_part_collection = NULL;
 EAPI Eet_Data_Descriptor *_edje_edd_edje_part = NULL;
 EAPI Eet_Data_Descriptor *_edje_edd_edje_part_description = NULL;
 EAPI Eet_Data_Descriptor *_edje_edd_edje_part_image_id = NULL;
+EAPI Eet_Data_Descriptor *_edje_edd_edje_external_param = NULL;
 
 #define NEWD(str, typ) \
    { eddc.name = str; eddc.size = sizeof(typ); }
@@ -62,6 +63,7 @@ _edje_edd_free(void)
    FREED(_edje_edd_edje_part);
    FREED(_edje_edd_edje_part_description);
    FREED(_edje_edd_edje_part_image_id);
+   FREED(_edje_edd_edje_external_param);
 }
 
 static char *
@@ -270,6 +272,16 @@ _edje_edd_setup(void)
      eet_data_descriptor3_new(&eddc);
    EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_image_id, Edje_Part_Image_Id, "id", id, EET_T_INT);
 
+   NEWD("Edje_External_Param",
+	Edje_External_Param);
+   _edje_edd_edje_external_param =
+     eet_data_descriptor3_new(&eddc);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_external_param, Edje_External_Param, "name", name, EET_T_STRING);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_external_param, Edje_External_Param, "type", type, EET_T_INT);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_external_param, Edje_External_Param, "i", i, EET_T_INT);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_external_param, Edje_External_Param, "d", d, EET_T_DOUBLE);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_external_param, Edje_External_Param, "s", s, EET_T_STRING);
+
    NEWD("Edje_Part_Description",
 	Edje_Part_Description);
    _edje_edd_edje_part_description =
@@ -376,6 +388,7 @@ _edje_edd_setup(void)
    EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description, Edje_Part_Description, "table.align.y", table.align.y, EET_T_DOUBLE);
    EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description, Edje_Part_Description, "table.padding.x", table.padding.x, EET_T_INT);
    EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description, Edje_Part_Description, "table.padding.y", table.padding.y, EET_T_INT);
+   EET_DATA_DESCRIPTOR_ADD_LIST(_edje_edd_edje_part_description, Edje_Part_Description, "external_params", external_params, _edje_edd_edje_external_param);
 
    NEWD("Edje_Pack_Element",
 	 Edje_Pack_Element);
diff --git a/src/lib/edje_external.c b/src/lib/edje_external.c
new file mode 100644
index 0000000..70d15bc
--- /dev/null
+++ b/src/lib/edje_external.c
@@ -0,0 +1,187 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#include "edje_private.h"
+
+static Eina_Hash *type_registry = NULL;
+static int init_count = 0;
+
+EAPI Eina_Bool
+edje_external_type_register(const char *type_name, Edje_External_Type *type_info)
+{
+   if (eina_hash_find(type_registry, type_name))
+     {
+	printf("EDJE ERROR: external type '%s' already registered\n", type_name);
+	return EINA_FALSE;
+     }
+   return eina_hash_add(type_registry, type_name, type_info);
+}
+
+EAPI Eina_Bool
+edje_external_type_unregister(const char *type_name)
+{
+   return eina_hash_del_by_key(type_registry, type_name);
+}
+
+EAPI Edje_External_Param *
+edje_external_param_find(const Eina_List *params, const char *key)
+{
+   const Eina_List *l;
+   Edje_External_Param *param;
+
+   EINA_LIST_FOREACH(params, l, param)
+      if (!strcmp(param->name, key)) return param;
+
+   return NULL;
+}
+
+EAPI Eina_Bool
+edje_external_param_int_get(const Eina_List *params, const char *key, int *ret)
+{
+   Edje_External_Param *param;
+
+   if (!params) return EINA_FALSE;
+   param = edje_external_param_find(params, key);
+
+   if (param && param->type == EDJE_EXTERNAL_PARAM_TYPE_INT && ret)
+     {
+	*ret = param->i;
+	return EINA_TRUE;
+     }
+
+   return EINA_FALSE;
+}
+
+EAPI Eina_Bool
+edje_external_param_double_get(const Eina_List *params, const char *key, double *ret)
+{
+   Edje_External_Param *param;
+
+   if (!params) return EINA_FALSE;
+   param = edje_external_param_find(params, key);
+
+   if (param && param->type == EDJE_EXTERNAL_PARAM_TYPE_DOUBLE && ret)
+     {
+	*ret = param->d;
+	return EINA_TRUE;
+     }
+
+   return EINA_FALSE;
+}
+
+EAPI Eina_Bool
+edje_external_param_string_get(const Eina_List *params, const char *key, const char **ret)
+{
+   Edje_External_Param *param;
+
+   if (!params) return EINA_FALSE;
+   param = edje_external_param_find(params, key);
+
+   if (param && param->type == EDJE_EXTERNAL_PARAM_TYPE_STRING && ret)
+     {
+	*ret = param->s;
+	return EINA_TRUE;
+     }
+
+   return EINA_FALSE;
+}
+
+
+void
+_edje_external_init()
+{
+   if (!type_registry)
+     type_registry = eina_hash_string_superfast_new(NULL);
+
+   init_count++;
+}
+
+void
+_edje_external_shutdown()
+{
+   if (--init_count == 0)
+     {
+	eina_hash_free(type_registry);
+	type_registry = NULL;
+     }
+}
+
+Evas_Object *
+_edje_external_type_add(const char *type_name, Evas *evas, Evas_Object *parent, const Eina_List *params)
+{
+   Edje_External_Type *type;
+   Evas_Object *obj;
+
+   type = eina_hash_find(type_registry, type_name);
+   if (!type)
+     {
+	printf("EDJE ERROR: external type '%s' not registered\n", type_name);
+	return NULL;
+     }
+
+   obj = type->add(type->data, evas, parent, params);
+   if (!obj)
+     {
+	printf("EDJE ERROR: external type '%s' returned NULL from constructor\n", type_name);
+	return NULL;
+     }
+
+   evas_object_data_set(obj, "Edje_External_Type", type);
+
+   printf("evas object: %p, external type: %p, data_get: %p\n", obj, type, evas_object_data_get(obj, "Edje_External_Type"));
+   return obj;
+}
+
+void
+_edje_external_signal_emit(Evas_Object *obj, const char *emission, const char *source)
+{
+   Edje_External_Type *type;
+
+   type = evas_object_data_get(obj, "Edje_External_Type");
+   if (!type)
+     {
+	printf("EDJE ERROR: external type data not found.\n");
+	return;
+     }
+
+   type->signal_emit(type->data, obj, emission, source);
+}
+
+void
+_edje_external_params_free(Eina_List *external_params, unsigned int free_strings)
+{
+   Eina_List *l;
+   Edje_External_Param *param;
+   Edje_Part_Description *desc;
+
+   EINA_LIST_FREE(external_params, param)
+     {
+	if (free_strings)
+	  {
+	     if (param->name) eina_stringshare_del(param->name);
+	     if (param->s) eina_stringshare_del(param->s);
+	  }
+	free(param);
+     }
+}
+
+void
+_edje_external_recalc_apply(Edje *ed, Edje_Real_Part *ep,
+      Edje_Calc_Params *params,
+      Edje_Part_Description *chosen_desc)
+{
+   Edje_External_Type *type;
+   if (!ep->swallowed_object) return;
+
+   type = evas_object_data_get(ep->swallowed_object, "Edje_External_Type");
+
+   if (!type) return;
+
+   if (!type->state_set) return;
+
+   type->state_set(type->data, ep->swallowed_object,
+	 ep->param1.description->external_params,
+	 (ep->param2.description ? ep->param2.description->external_params : NULL),
+	 ep->description_pos);
+}
diff --git a/src/lib/edje_load.c b/src/lib/edje_load.c
index 75f8a47..9c8b7d0 100644
--- a/src/lib/edje_load.c
+++ b/src/lib/edje_load.c
@@ -370,7 +370,7 @@ _edje_object_file_set_internal(Evas_Object *obj, const char *file, const char *g
 		       rp->object = evas_object_text_add(ed->evas);
 		       evas_object_text_font_source_set(rp->object, ed->path);
 		    }
-		  else if (ep->type == EDJE_PART_TYPE_SWALLOW || ep->type == EDJE_PART_TYPE_GROUP)
+		  else if (ep->type == EDJE_PART_TYPE_SWALLOW || ep->type == EDJE_PART_TYPE_GROUP || ep->type == EDJE_PART_TYPE_EXTERNAL)
 		    {
 		       rp->object = evas_object_rectangle_add(ed->evas);
 		       evas_object_color_set(rp->object, 0, 0, 0, 0);
@@ -542,9 +542,17 @@ _edje_object_file_set_internal(Evas_Object *obj, const char *file, const char *g
 		  const char *source = NULL;
 		  
 		  rp = ed->table_parts[i];
-		  if (rp->part->type != EDJE_PART_TYPE_GROUP &&
+		  if (rp->part->type == EDJE_PART_TYPE_EXTERNAL)
+		    {
+		       Evas_Object *child_obj;
+		       child_obj = _edje_external_type_add(rp->part->source, evas_object_evas_get(ed->obj), ed->obj, rp->part->default_desc->external_params);
+		       if (child_obj) _edje_real_part_swallow(rp, child_obj);
+		       continue;
+		    }
+		  else if (rp->part->type != EDJE_PART_TYPE_GROUP &&
 		      rp->part->type != EDJE_PART_TYPE_BOX &&
 		      rp->part->type != EDJE_PART_TYPE_TABLE) continue;
+
 		  if (rp->part->type == EDJE_PART_TYPE_GROUP)
 		    source = rp->part->source;
 		  else if (rp->part->type == EDJE_PART_TYPE_BOX ||
@@ -799,7 +807,7 @@ _edje_file_del(Edje *ed)
 
                   /* Objects swallowed by the app do not get deleted,
                    but those internally swallowed (GROUP type) do. */
-		  if (rp->part->type == EDJE_PART_TYPE_GROUP)
+		  if (rp->part->type == EDJE_PART_TYPE_GROUP || rp->part->type == EDJE_PART_TYPE_EXTERNAL)
 		    evas_object_del(rp->swallowed_object);
 
 		  rp->swallowed_object = NULL;
@@ -1120,6 +1128,8 @@ _edje_collection_free_part_description_free(Edje_Part_Description *desc, unsigne
 	desc->image.tween_list = eina_list_remove(desc->image.tween_list, pi);
 	free(pi);
      }
+   if (desc->external_params)
+     _edje_external_params_free(desc->external_params, free_strings);
    if (free_strings)
      {
 	if (desc->color_class)     eina_stringshare_del(desc->color_class);
diff --git a/src/lib/edje_main.c b/src/lib/edje_main.c
index 976b532..7a7ce79 100644
--- a/src/lib/edje_main.c
+++ b/src/lib/edje_main.c
@@ -26,6 +26,7 @@ edje_init(void)
 	_edje_edd_setup();
 	_edje_text_init();
 	_edje_box_init();
+	_edje_external_init();
 	embryo_init();
 	eet_init();
      }
@@ -55,6 +56,7 @@ edje_shutdown(void)
    _edje_text_class_members_free();
    _edje_text_class_hash_free();
    _edje_box_shutdown();
+   _edje_external_shutdown();
    embryo_shutdown();
    ecore_job_shutdown();
    eet_shutdown();
diff --git a/src/lib/edje_private.h b/src/lib/edje_private.h
index 59d8372..310a4e5 100644
--- a/src/lib/edje_private.h
+++ b/src/lib/edje_private.h
@@ -155,7 +155,8 @@ typedef struct _Edje_Patterns                        Edje_Patterns;
 #define EDJE_PART_TYPE_GROUP     7
 #define EDJE_PART_TYPE_BOX       8
 #define EDJE_PART_TYPE_TABLE     9
-#define EDJE_PART_TYPE_LAST     10
+#define EDJE_PART_TYPE_EXTERNAL 10
+#define EDJE_PART_TYPE_LAST     11
 
 #define EDJE_TEXT_EFFECT_NONE                0
 #define EDJE_TEXT_EFFECT_PLAIN               1
@@ -605,11 +606,11 @@ struct _Edje_Part_Description
    } table;
 
    Edje_Color color, color2, color3;  /* color for rect or text, shadow etc. */
+   Eina_List *external_params; /* parameters for external objects */
 
    unsigned char     visible; /* is it shown */
 };
 
-
 /*----------*/
 
 
@@ -1312,4 +1313,14 @@ void _edje_entry_cursor_geometry_get(Edje_Real_Part *rp, Evas_Coord *cx, Evas_Co
 void _edje_entry_select_allow_set(Edje_Real_Part *rp, Eina_Bool allow);
 void _edje_entry_select_abort(Edje_Real_Part *rp);
 
+
+void _edje_external_init();
+void _edje_external_shutdown();
+Evas_Object *_edje_external_type_add(const char *type_name, Evas *evas, Evas_Object *parent, const Eina_List *params);
+void _edje_external_signal_emit(Evas_Object *obj, const char *emission, const char *source);
+void _edje_external_params_free(Eina_List *params, unsigned int free_strings);
+void _edje_external_recalc_apply(Edje *ed, Edje_Real_Part *ep, Edje_Calc_Params *params, Edje_Part_Description *chosen_desc);
+
+
+
 #endif
diff --git a/src/lib/edje_program.c b/src/lib/edje_program.c
index a04c4b0..cd80439 100644
--- a/src/lib/edje_program.c
+++ b/src/lib/edje_program.c
@@ -824,8 +824,8 @@ _edje_emit(Edje *ed, const char *sig, const char *src)
      {
         size_t length;
         char *part;
-       /* the signal contains a colon, split the signal into "group:signal",
-	* and deliver it to "group"
+       /* the signal contains a colon, split the signal into "part:signal",
+	* and deliver it to "part" (if there is a GROUP or EXTERNAL part named "part")
 	*/
        length = strlen(sig) + 1;
        part = alloca(length);
@@ -842,17 +842,25 @@ _edje_emit(Edje *ed, const char *sig, const char *src)
             for (i = 0; i < ed->table_parts_size; i++)
               {
                  Edje_Real_Part *rp = ed->table_parts[i];
-                 if ((rp->part->type == EDJE_PART_TYPE_GROUP) &&
+                 if ((rp->part->type == EDJE_PART_TYPE_GROUP || rp->part->type == EDJE_PART_TYPE_EXTERNAL) &&
                      (rp->swallowed_object) &&
                      (rp->part) && (rp->part->name) &&
                      (strcmp(rp->part->name, part) == 0))
                    {
-                      Edje *ed2 = _edje_fetch(rp->swallowed_object);
-                      if (ed2) _edje_emit(ed2, newsig, src);
-                      return; /* stop processing.
-			       * XXX maybe let signal be processed anyway?
-			       * XXX in this case, just comment this line
-			       */
+		      if (rp->part->type == EDJE_PART_TYPE_GROUP)
+			{
+			   Edje *ed2 = _edje_fetch(rp->swallowed_object);
+			   if (ed2) _edje_emit(ed2, newsig, src);
+			   return; /* stop processing.
+				    * XXX maybe let signal be processed anyway?
+				    * XXX in this case, just comment this line
+				    */
+			}
+		      else if (rp->part->type == EDJE_PART_TYPE_EXTERNAL)
+			{
+			   _edje_external_signal_emit(rp->swallowed_object, newsig, src);
+			   return;
+			}
                    }
               }
          }
------------------------------------------------------------------------------
_______________________________________________
enlightenment-devel mailing list
enlightenment-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/enlightenment-devel

Reply via email to