Add CHOICES to EXTERNAL support.
authorbarbieri <barbieri@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Mon, 29 Mar 2010 21:51:40 +0000 (21:51 +0000)
committerbarbieri <barbieri@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Mon, 29 Mar 2010 21:51:40 +0000 (21:51 +0000)
Choices are useful to represent enumerations and restricted set of
elements to user. Usually this is displayed in hoversel/comboboxes.

git-svn-id: svn+ssh://svn.enlightenment.org/var/svn/e/trunk/edje@47570 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33

data/include/edje.inc
src/bin/edje_cc_handlers.c
src/lib/Edje.h
src/lib/edje_edit.c
src/lib/edje_embryo.c
src/lib/edje_external.c
src/lib/edje_program.c

index 49097d9..8faceec 100644 (file)
@@ -158,6 +158,9 @@ native       external_param_set_float(id, param_name[], Float:value);
 native       external_param_get_strlen(id, param_name[]);
 native       external_param_get_str(id, param_name[], value[], value_maxlen);
 native       external_param_set_str(id, param_name[], value[]);
+native       external_param_get_choice_strlen(id, param_name[]);
+native       external_param_get_choice(id, param_name[], value[], value_maxlen);
+native       external_param_set_choice(id, param_name[], value[]);
 native       external_param_get_bool(id, param_name[]);
 native       external_param_set_bool(id, param_name[], value);
 
index ca808a1..8318bd4 100644 (file)
@@ -240,6 +240,8 @@ static void st_collections_group_parts_part_description_params_double(void);
 
 static void st_collections_group_programs_program_name(void);
 static void st_collections_group_parts_part_description_params_string(void);
+static void st_collections_group_parts_part_description_params_bool(void);
+static void st_collections_group_parts_part_description_params_choice(void);
 static void st_collections_group_programs_program_signal(void);
 static void st_collections_group_programs_program_source(void);
 static void st_collections_group_programs_program_filter(void);
@@ -460,6 +462,8 @@ New_Statement_Handler statement_handlers[] =
      {"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.params.bool", st_collections_group_parts_part_description_params_bool},
+     {"collections.group.parts.part.description.params.choice", st_collections_group_parts_part_description_params_choice},
      {"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 */
@@ -6204,6 +6208,8 @@ st_collections_group_parts_part_description_perspective_focal(void)
             int: "name" 0;
             double: "other_name" 0.0;
             string: "another_name" "some text";
+           bool: "name" 1;
+           choice: "some_name" "value";
         }
         ..
     }
@@ -6264,12 +6270,14 @@ _st_collections_group_parts_part_description_params(Edje_External_Param_Type typ
 
    switch (type)
      {
+      case EDJE_EXTERNAL_PARAM_TYPE_BOOL:
       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_CHOICE:
       case EDJE_EXTERNAL_PARAM_TYPE_STRING:
         param->s = parse_str(1);
         break;
@@ -6327,6 +6335,40 @@ st_collections_group_parts_part_description_params_string(void)
    _st_collections_group_parts_part_description_params(EDJE_EXTERNAL_PARAM_TYPE_STRING);
 }
 
+/**
+    @page edcref
+    @property
+        bool
+    @parameters
+        [param_name] [bool_value]
+    @effect
+        Adds an boolean parameter for an external object. Value must be 0 or 1.
+    @endproperty
+*/
+static void
+st_collections_group_parts_part_description_params_bool(void)
+{
+   _st_collections_group_parts_part_description_params(EDJE_EXTERNAL_PARAM_TYPE_BOOL);
+}
+
+/**
+    @page edcref
+    @property
+        choice
+    @parameters
+        [param_name] [choice_string]
+    @effect
+        Adds a choice parameter for an external object. The possible
+        choice values are defined by external type at their register time
+        and will be validated at runtime.
+    @endproperty
+*/
+static void
+st_collections_group_parts_part_description_params_choice(void)
+{
+   _st_collections_group_parts_part_description_params(EDJE_EXTERNAL_PARAM_TYPE_CHOICE);
+}
+
 
 /**
    @edcsection{program, Program block}
index 9f8a1cd..3d1b8b1 100644 (file)
@@ -247,6 +247,7 @@ enum _Edje_External_Param_Type
   EDJE_EXTERNAL_PARAM_TYPE_DOUBLE,
   EDJE_EXTERNAL_PARAM_TYPE_STRING,
   EDJE_EXTERNAL_PARAM_TYPE_BOOL,
+  EDJE_EXTERNAL_PARAM_TYPE_CHOICE,
   EDJE_EXTERNAL_PARAM_TYPE_MAX
 };
 typedef enum _Edje_External_Param_Type Edje_External_Param_Type;
@@ -258,9 +259,9 @@ 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;
+   int i; /**< used by both integer and boolean */
    double d;
-   const char *s;
+   const char *s; /**< used by both string and choice */
 };
 typedef struct _Edje_External_Param Edje_External_Param;
 
@@ -293,6 +294,11 @@ struct _Edje_External_Param_Info
              const char *false_str;
              const char *true_str;
           } b;
+       struct
+         {
+            const char *def;
+            const char **choices; /* NULL terminated array */
+         } c;
      } info;
 };
 typedef struct _Edje_External_Param_Info Edje_External_Param_Info;
@@ -305,6 +311,8 @@ typedef struct _Edje_External_Param_Info Edje_External_Param_Info;
   {name, EDJE_EXTERNAL_PARAM_TYPE_STRING, {.s = {def, accept, deny}}}
 #define EDJE_EXTERNAL_PARAM_INFO_BOOL_FULL(name, def, false_str, true_str) \
   {name, EDJE_EXTERNAL_PARAM_TYPE_BOOL, {.b = {def, false_str, true_str}}}
+#define EDJE_EXTERNAL_PARAM_INFO_CHOICE_FULL(name, def, choices) \
+  {name, EDJE_EXTERNAL_PARAM_TYPE_CHOICE, {.c = {def, choices}}}
 
 #define EDJE_EXTERNAL_PARAM_INFO_INT_DEFAULT(name, def) \
    EDJE_EXTERNAL_PARAM_INFO_INT_FULL(name, def, EDJE_EXTERNAL_INT_UNSET, EDJE_EXTERNAL_INT_UNSET, EDJE_EXTERNAL_INT_UNSET)
@@ -326,6 +334,22 @@ typedef struct _Edje_External_Param_Info Edje_External_Param_Info;
 
 #define EDJE_EXTERNAL_PARAM_INFO_SENTINEL {NULL, 0, {.s = {NULL, NULL, NULL}}}
 
+/**
+ * @struct _Edje_External_Type information about an external type to be used.
+ *
+ * This structure provides information on how to display and modify a
+ * third party Evas_Object in Edje.
+ *
+ * Some function pointers are not really used by Edje, but provide
+ * means for Edje users to better interact with such objects. For
+ * instance, an editor may use label_get() and icon_get() to list all
+ * registered external types.
+ *
+ * @note The function pointers provided in this structure must check
+ *       for errors and invalid or out-of-range values as for
+ *       performance reasons Edje will not enforce hints provided as
+ *       #Edje_External_Param_Info in the member parameters_info.
+ */
 struct _Edje_External_Type
 {
 #define EDJE_EXTERNAL_TYPE_ABI_VERSION (2)
@@ -547,6 +571,7 @@ extern "C" {
    EAPI Eina_Bool edje_external_param_double_get(const Eina_List *params, const char *key, double *ret);
    EAPI Eina_Bool edje_external_param_string_get(const Eina_List *params, const char *key, const char **ret);
    EAPI Eina_Bool edje_external_param_bool_get(const Eina_List *params, const char *key, Eina_Bool *ret);
+   EAPI Eina_Bool edje_external_param_choice_get(const Eina_List *params, const char *key, const char **ret);
    EAPI const Edje_External_Param_Info *edje_external_param_info_get(const char *type_name);
    EAPI const Edje_External_Type *edje_external_type_get(const char *type_name);
 
index fb5c87c..9771ed9 100644 (file)
@@ -2660,6 +2660,10 @@ edje_edit_state_add(Evas_Object *obj, const char *part, const char *name)
                case EDJE_EXTERNAL_PARAM_TYPE_DOUBLE:
                   p->d = pi->info.d.def;
                   break;
+               case EDJE_EXTERNAL_PARAM_TYPE_CHOICE:
+                  if (pi->info.c.def)
+                    p->s = eina_stringshare_add(pi->info.c.def);
+                  break;
                case EDJE_EXTERNAL_PARAM_TYPE_STRING:
                   if (pi->info.s.def)
                     p->s = eina_stringshare_add(pi->info.s.def);
@@ -2838,6 +2842,7 @@ edje_edit_state_copy(Evas_Object *obj, const char *part, const char *from, const
           case EDJE_EXTERNAL_PARAM_TYPE_DOUBLE:
              new_p->d = p->d;
              break;
+          case EDJE_EXTERNAL_PARAM_TYPE_CHOICE:
           case EDJE_EXTERNAL_PARAM_TYPE_STRING:
              new_p->s = eina_stringshare_add(p->s);
              break;
@@ -3621,6 +3626,7 @@ edje_edit_state_external_param_get(Evas_Object *obj, const char *part, const cha
                 case EDJE_EXTERNAL_PARAM_TYPE_DOUBLE:
                    *value = &p->d;
                    break;
+                case EDJE_EXTERNAL_PARAM_TYPE_CHOICE:
                 case EDJE_EXTERNAL_PARAM_TYPE_STRING:
                    *value = (void *)p->s;
                    break;
@@ -3693,12 +3699,33 @@ edje_edit_state_external_param_string_get(Evas_Object *obj, const char *part, co
    return EINA_FALSE;
 }
 
+EAPI Eina_Bool
+edje_edit_state_external_param_choice_get(Evas_Object *obj, const char *part, const char *state, const char *param, const char **value)
+{
+   Eina_List *l;
+   Edje_External_Param *p;
+   GET_PD_OR_RETURN(EINA_FALSE);
+
+   EINA_LIST_FOREACH(pd->external_params, l, p)
+      if (!strcmp(p->name, param))
+       {
+          if (p->type != EDJE_EXTERNAL_PARAM_TYPE_CHOICE)
+            return EINA_FALSE;
+          if (value)
+            *value = p->s;
+          return EINA_TRUE;
+       }
+
+   return EINA_FALSE;
+}
+
 /**
  * Arguments should have proper sized values matching their types:
  *   - EDJE_EXTERNAL_PARAM_TYPE_INT: int
  *   - EDJE_EXTERNAL_PARAM_TYPE_BOOL: int
  *   - EDJE_EXTERNAL_PARAM_TYPE_DOUBLE: double
  *   - EDJE_EXTERNAL_PARAM_TYPE_STRING: char*
+ *   - EDJE_EXTERNAL_PARAM_TYPE_CHOICE: char*
  */
 EAPI Eina_Bool
 edje_edit_state_external_param_set(Evas_Object *obj, const char *part, const char *state, const char *param, Edje_External_Param_Type type, ...)
@@ -3748,6 +3775,7 @@ edje_edit_state_external_param_set(Evas_Object *obj, const char *part, const cha
       case EDJE_EXTERNAL_PARAM_TYPE_DOUBLE:
         p->d = (double)va_arg(ap, double);
         break;
+      case EDJE_EXTERNAL_PARAM_TYPE_CHOICE:
       case EDJE_EXTERNAL_PARAM_TYPE_STRING:
         p->s = eina_stringshare_add((const char *)va_arg(ap, char *));
         break;
@@ -3786,6 +3814,12 @@ edje_edit_state_external_param_string_set(Evas_Object *obj, const char *part, co
    return edje_edit_state_external_param_set(obj, part, state, param, EDJE_EXTERNAL_PARAM_TYPE_STRING, value);
 }
 
+EAPI Eina_Bool
+edje_edit_state_external_param_choice_set(Evas_Object *obj, const char *part, const char *state, const char *param, const char *value)
+{
+   return edje_edit_state_external_param_set(obj, part, state, param, EDJE_EXTERNAL_PARAM_TYPE_CHOICE, value);
+}
+
 /**************/
 /*  TEXT API */
 /**************/
@@ -6057,7 +6091,16 @@ _edje_generate_source_of_state(Evas_Object *obj, const char *part, const char *s
                        break;
                     case EDJE_EXTERNAL_PARAM_TYPE_STRING:
                        if (p->s)
-                         fprintf(f, I6"string: \"%s\" \"%s\";\n", p->name, p->s);
+                         fprintf(f, I6"string: \"%s\" \"%s\";\n",
+                                 p->name, p->s);
+                       break;
+                    case EDJE_EXTERNAL_PARAM_TYPE_BOOL:
+                       fprintf(f, I6"bool: \"%s\" \"%d\";\n", p->name, p->i);
+                       break;
+                    case EDJE_EXTERNAL_PARAM_TYPE_CHOICE:
+                       if (p->s)
+                         fprintf(f, I6"choice: \"%s\" \"%s\";\n",
+                                 p->name, p->s);
                        break;
                     default:
                        break;
index ada4b21..492118a 100644 (file)
@@ -218,6 +218,9 @@ void *alloca (size_t);
  * external_param_get_strlen(id, param_name[])
  * external_param_get_str(id, param_name[], value[], value_maxlen)
  * external_param_set_str(id, param_name[], value[])
+ * external_param_get_choice_strlen(id, param_name[])
+ * external_param_get_choice(id, param_name[], value[], value_maxlen)
+ * external_param_set_choice(id, param_name[], value[])
  * external_param_get_bool(id, param_name[])
  * external_param_set_bool(id, param_name[], value)
  *
@@ -2502,6 +2505,107 @@ _edje_embryo_fn_external_param_set_str(Embryo_Program *ep, Embryo_Cell *params)
    return _edje_external_param_set(rp->swallowed_object, &eep);
 }
 
+/* external_param_get_choice_strlen(id, param_name[]) */
+static Embryo_Cell
+_edje_embryo_fn_external_param_get_choice_strlen(Embryo_Program *ep, Embryo_Cell *params)
+{
+   Edje *ed;
+   int part_id;
+   Edje_Real_Part *rp;
+   Edje_External_Param eep;
+   char *param_name;
+
+   CHKPARAM(2);
+   ed = embryo_program_data_get(ep);
+
+   part_id = params[1];
+   if (part_id < 0) return 0;
+   rp = ed->table_parts[part_id % ed->table_parts_size];
+
+   GETSTR(param_name, params[2]);
+   if (!param_name) return 0;
+   eep.name = param_name;
+   eep.type = EDJE_EXTERNAL_PARAM_TYPE_CHOICE;
+   eep.s = NULL;
+   _edje_external_param_get(rp->swallowed_object, &eep);
+   if (!eep.s) return 0;
+   return strlen(eep.s);
+}
+
+/* external_param_get_choice(id, param_name[], val[], val_maxlen) */
+static Embryo_Cell
+_edje_embryo_fn_external_param_get_choice(Embryo_Program *ep, Embryo_Cell *params)
+{
+   Edje *ed;
+   int part_id;
+   Edje_Real_Part *rp;
+   Edje_External_Param eep;
+   char *param_name;
+   size_t src_len, dst_len;
+
+   CHKPARAM(4);
+   dst_len = params[4];
+   if (dst_len < 1) goto error;
+
+   ed = embryo_program_data_get(ep);
+
+   part_id = params[1];
+   if (part_id < 0) goto error;
+   rp = ed->table_parts[part_id % ed->table_parts_size];
+
+   GETSTR(param_name, params[2]);
+   if (!param_name) return 0;
+   eep.name = param_name;
+   eep.type = EDJE_EXTERNAL_PARAM_TYPE_CHOICE;
+   eep.s = NULL;
+   _edje_external_param_get(rp->swallowed_object, &eep);
+   if (!eep.s) goto error;
+   src_len = strlen(eep.s);
+   if (src_len < dst_len)
+     {
+       SETSTR(eep.s, params[3]);
+     }
+   else
+     {
+       char *tmp = alloca(dst_len);
+       memcpy(tmp, eep.s, dst_len - 1);
+       tmp[dst_len] = '\0';
+       SETSTR(tmp, params[3]);
+     }
+   return 1;
+
+ error:
+   SETSTR("", params[3]);
+   return 0;
+}
+
+/* external_param_set_choice(id, param_name[], val[]) */
+static Embryo_Cell
+_edje_embryo_fn_external_param_set_choice(Embryo_Program *ep, Embryo_Cell *params)
+{
+   Edje *ed;
+   int part_id;
+   Edje_Real_Part *rp;
+   Edje_External_Param eep;
+   char *param_name, *val;
+
+   CHKPARAM(3);
+   ed = embryo_program_data_get(ep);
+
+   part_id = params[1];
+   if (part_id < 0) return 0;
+   rp = ed->table_parts[part_id % ed->table_parts_size];
+
+   GETSTR(param_name, params[2]);
+   if (!param_name) return 0;
+   eep.name = param_name;
+   eep.type = EDJE_EXTERNAL_PARAM_TYPE_CHOICE;
+   GETSTR(val, params[3]);
+   if (!val) return 0;
+   eep.s = val;
+   return _edje_external_param_set(rp->swallowed_object, &eep);
+}
+
 /* external_param_get_bool(id, param_name[]) */
 static Embryo_Cell
 _edje_embryo_fn_external_param_get_bool(Embryo_Program *ep, Embryo_Cell *params)
index 1512942..1356a8b 100644 (file)
@@ -28,6 +28,8 @@ edje_external_param_type_str(Edje_External_Param_Type type)
         return "STRING";
       case EDJE_EXTERNAL_PARAM_TYPE_BOOL:
         return "BOOL";
+      case EDJE_EXTERNAL_PARAM_TYPE_CHOICE:
+        return "CHOICE";
       default:
         return "(unknown)";
      }
@@ -92,6 +94,12 @@ edje_object_part_external_object_get(const Evas_Object *obj, const char *part)
  *       function. The interpretation of how state_set parameters and
  *       param_set will interact is up to the external plugin.
  *
+ * @note this function will not check if parameter value is valid
+ *       using #Edje_External_Param_Info minimum, maximum, valid
+ *       choices and others. However these should be checked by the
+ *       underlying implementation provided by the external
+ *       plugin. This is done for performance reasons.
+ *
  * @param obj A valid Evas_Object handle
  * @param part The part name
  * @param param the parameter details, including its name, type and
@@ -452,6 +460,23 @@ edje_external_param_bool_get(const Eina_List *params, const char *key, Eina_Bool
    return EINA_FALSE;
 }
 
+EAPI Eina_Bool
+edje_external_param_choice_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_CHOICE && ret)
+     {
+       *ret = param->s;
+       return EINA_TRUE;
+     }
+
+   return EINA_FALSE;
+}
+
 /**
  * Get the array of parameters information about a type given its name.
  *
index 67fdcaa..5002fb7 100644 (file)
@@ -1358,17 +1358,6 @@ _edje_param_external_get(const Evas_Object *obj, const char *name, Edje_External
    return param;
 }
 
-static Edje_External_Param_Type
-_edje_param_external_type_get(const Evas_Object *obj, const char *name)
-{
-   const Edje_External_Param_Info *info;
-
-   info = _edje_external_param_info_get(obj, name);
-   if (!info) return EDJE_EXTERNAL_PARAM_TYPE_MAX;
-
-   return info->type;
-}
-
 /* simulate external properties for native objects */
 static Edje_External_Param *
 _edje_param_native_get(Edje_Real_Part *rp, const char *name, Edje_External_Param *param, void **free_ptr)
@@ -1688,19 +1677,32 @@ _edje_param_native_set(Edje_Real_Part *rp, const char *name, const Edje_External
    return EINA_FALSE;
 }
 
-static Edje_External_Param_Type
-_edje_param_native_type_get(const Edje_Real_Part *rp, const char *name)
+static const Edje_External_Param_Info *
+_edje_native_param_info_get(const Edje_Real_Part *rp, const char *name)
 {
    if ((rp->part->type == EDJE_PART_TYPE_TEXT) ||
        (rp->part->type == EDJE_PART_TYPE_TEXTBLOCK))
      {
-       if (!strcmp(name, "text")) return EDJE_EXTERNAL_PARAM_TYPE_STRING;
+       if (!strcmp(name, "text"))
+         {
+            static const Edje_External_Param_Info pi =
+              EDJE_EXTERNAL_PARAM_INFO_STRING("text");
+            return &pi;
+         }
        if (rp->part->type == EDJE_PART_TYPE_TEXTBLOCK)
          {
             if (!strcmp(name, "text_unescaped"))
-              return EDJE_EXTERNAL_PARAM_TYPE_STRING;
+              {
+                 static const Edje_External_Param_Info pi =
+                   EDJE_EXTERNAL_PARAM_INFO_STRING("text_unescaped");
+                 return &pi;
+              }
             if (!strcmp(name, "select_allow"))
-              return EDJE_EXTERNAL_PARAM_TYPE_BOOL;
+              {
+                 static const Edje_External_Param_Info pi =
+                   EDJE_EXTERNAL_PARAM_INFO_BOOL("text_unescaped");
+                 return &pi;
+              }
          }
      }
 
@@ -1709,29 +1711,68 @@ _edje_param_native_type_get(const Edje_Real_Part *rp, const char *name)
        if (!strncmp(name, "drag_", sizeof("drag_") - 1))
          {
             name += sizeof("drag_") - 1;
-            if ((!strcmp(name, "value_x")) ||
-                (!strcmp(name, "value_y")) ||
-                (!strcmp(name, "size_w")) ||
-                (!strcmp(name, "size_h")) ||
-                (!strcmp(name, "step_x")) ||
-                (!strcmp(name, "step_y")) ||
-                (!strcmp(name, "page_x")) ||
-                (!strcmp(name, "page_y")))
-              return EDJE_EXTERNAL_PARAM_TYPE_DOUBLE;
-            else
-              return EDJE_EXTERNAL_PARAM_TYPE_MAX;
+            if (!strcmp(name, "value_x"))
+              {
+                 static const Edje_External_Param_Info pi =
+                   EDJE_EXTERNAL_PARAM_INFO_DOUBLE("drag_value_x");
+                 return &pi;
+              }
+            if (!strcmp(name, "value_y"))
+              {
+                 static const Edje_External_Param_Info pi =
+                   EDJE_EXTERNAL_PARAM_INFO_DOUBLE("drag_value_y");
+                 return &pi;
+              }
+            if (!strcmp(name, "size_w"))
+              {
+                 static const Edje_External_Param_Info pi =
+                   EDJE_EXTERNAL_PARAM_INFO_DOUBLE("drag_size_w");
+                 return &pi;
+              }
+            if (!strcmp(name, "size_h"))
+              {
+                 static const Edje_External_Param_Info pi =
+                   EDJE_EXTERNAL_PARAM_INFO_DOUBLE("drag_size_h");
+                 return &pi;
+              }
+            if (!strcmp(name, "step_x"))
+              {
+                 static const Edje_External_Param_Info pi =
+                   EDJE_EXTERNAL_PARAM_INFO_DOUBLE("drag_step_x");
+                 return &pi;
+              }
+            if (!strcmp(name, "step_y"))
+              {
+                 static const Edje_External_Param_Info pi =
+                   EDJE_EXTERNAL_PARAM_INFO_DOUBLE("drag_step_y");
+                 return &pi;
+              }
+            if (!strcmp(name, "page_x"))
+              {
+                 static const Edje_External_Param_Info pi =
+                   EDJE_EXTERNAL_PARAM_INFO_DOUBLE("drag_page_x");
+                 return &pi;
+              }
+            if (!strcmp(name, "page_y"))
+              {
+                 static const Edje_External_Param_Info pi =
+                   EDJE_EXTERNAL_PARAM_INFO_DOUBLE("drag_page_y");
+                 return &pi;
+              }
+
+            return NULL;
          }
      }
 
-   return EDJE_EXTERNAL_PARAM_TYPE_MAX;
+   return NULL;
 }
 
 static Edje_External_Param *
-_edje_param_convert(Edje_External_Param *param, Edje_External_Param_Type type)
+_edje_param_convert(Edje_External_Param *param, const Edje_External_Param_Info *dst_info)
 {
-   if (param->type == type) return param;
+   if (param->type == dst_info->type) return param;
 
-   switch (type)
+   switch (dst_info->type)
      {
       case EDJE_EXTERNAL_PARAM_TYPE_BOOL:
       case EDJE_EXTERNAL_PARAM_TYPE_INT:
@@ -1743,14 +1784,18 @@ _edje_param_convert(Edje_External_Param *param, Edje_External_Param_Type type)
                 i = (int)param->d;
                 break;
              case EDJE_EXTERNAL_PARAM_TYPE_STRING:
+             case EDJE_EXTERNAL_PARAM_TYPE_CHOICE:
                 i = (param->s) ? atoi(param->s) : 0;
                 break;
              case EDJE_EXTERNAL_PARAM_TYPE_BOOL:
+             case EDJE_EXTERNAL_PARAM_TYPE_INT:
                 i = param->i;
              default:
                 return NULL;
             }
-          param->type = type;
+          if (dst_info->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL)
+            i = !!i;
+          param->type = dst_info->type;
           param->i = i;
           return param;
        }
@@ -1764,6 +1809,7 @@ _edje_param_convert(Edje_External_Param *param, Edje_External_Param_Type type)
                 d = (double)param->i;
                 break;
              case EDJE_EXTERNAL_PARAM_TYPE_STRING:
+             case EDJE_EXTERNAL_PARAM_TYPE_CHOICE:
                 d = (param->s) ? atof(param->s) : 0.0;
                 break;
              case EDJE_EXTERNAL_PARAM_TYPE_BOOL:
@@ -1771,7 +1817,7 @@ _edje_param_convert(Edje_External_Param *param, Edje_External_Param_Type type)
              default:
                 return NULL;
             }
-          param->type = type;
+          param->type = dst_info->type;
           param->d = d;
           return param;
        }
@@ -1788,35 +1834,117 @@ _edje_param_convert(Edje_External_Param *param, Edje_External_Param_Type type)
              case EDJE_EXTERNAL_PARAM_TYPE_DOUBLE:
                 if (!snprintf(s, sizeof(s), "%f", param->d)) return NULL;
                 break;
+             case EDJE_EXTERNAL_PARAM_TYPE_CHOICE:
+                param->type = dst_info->type;
+                return param;
              default:
                 return NULL;
             }
-          param->type = type;
+          param->type = dst_info->type;
           param->s = s;
           return param;
        }
 
+      case EDJE_EXTERNAL_PARAM_TYPE_CHOICE:
+       {
+          static char s[64];
+          const char *val;
+          switch (param->type)
+            {
+             case EDJE_EXTERNAL_PARAM_TYPE_BOOL:
+             case EDJE_EXTERNAL_PARAM_TYPE_INT:
+                if (!snprintf(s, sizeof(s), "%i", param->i)) return NULL;
+                val = s;
+                break;
+             case EDJE_EXTERNAL_PARAM_TYPE_DOUBLE:
+                if (!snprintf(s, sizeof(s), "%f", param->d)) return NULL;
+                val = s;
+                break;
+             case EDJE_EXTERNAL_PARAM_TYPE_STRING:
+                val = param->s;
+                break;
+             default:
+                return NULL;
+            }
+
+          param->type = dst_info->type;
+          if (param->s != val) param->s = val;
+          return param;
+       }
+
       default: return NULL;
      }
 }
 
+static Eina_Bool
+_edje_param_validate(const Edje_External_Param *param, const Edje_External_Param_Info *info)
+{
+   switch (info->type)
+     {
+      case EDJE_EXTERNAL_PARAM_TYPE_BOOL:
+        return ((param->i == 0) || (param->i == 1));
+
+      case EDJE_EXTERNAL_PARAM_TYPE_INT:
+        if ((info->info.i.min != EDJE_EXTERNAL_INT_UNSET) &&
+            (info->info.i.min > param->i))
+          return EINA_FALSE;
+
+        if ((info->info.i.max != EDJE_EXTERNAL_INT_UNSET) &&
+            (info->info.i.max < param->i))
+          return EINA_FALSE;
+
+        return EINA_TRUE;
+
+      case EDJE_EXTERNAL_PARAM_TYPE_DOUBLE:
+        if ((info->info.d.min != EDJE_EXTERNAL_DOUBLE_UNSET) &&
+            (info->info.d.min > param->d))
+          return EINA_FALSE;
+
+        if ((info->info.d.max != EDJE_EXTERNAL_DOUBLE_UNSET) &&
+            (info->info.d.max < param->d))
+          return EINA_FALSE;
+
+        return EINA_TRUE;
+
+      case EDJE_EXTERNAL_PARAM_TYPE_STRING:
+        if (!param->s) return EINA_FALSE;
+        if (info->info.s.accept_fmt)
+          INF("string 'accept_fmt' validation not implemented.");
+        if (info->info.s.deny_fmt)
+          INF("string 'deny_fmt' validation not implemented.");
+        return EINA_TRUE;
+
+      case EDJE_EXTERNAL_PARAM_TYPE_CHOICE:
+       {
+          const char **itr = info->info.c.choices;
+          if (!itr) return EINA_FALSE;
+          for (; *itr != NULL; itr++)
+            if (!strcmp(*itr, param->s))
+              return EINA_TRUE;
+          return EINA_FALSE;
+       }
+
+      default: return EINA_FALSE;
+     }
+}
+
 static void
 _edje_param_copy(Edje_Real_Part *src_part, const char *src_param, Edje_Real_Part *dst_part, const char *dst_param)
 {
    Edje_External_Param val;
-   Edje_External_Param_Type dst_type;
+   const Edje_External_Param_Info *dst_info;
    void *free_ptr = NULL;
 
    if ((!src_part) || (!src_param) || (!dst_part) || (!dst_param))
      return;
 
    if (dst_part->part->type == EDJE_PART_TYPE_EXTERNAL)
-     dst_type = _edje_param_external_type_get
+     dst_info = _edje_external_param_info_get
        (dst_part->swallowed_object, dst_param);
    else
-     dst_type = _edje_param_native_type_get(dst_part, dst_param);
+     dst_info = _edje_native_param_info_get(dst_part, dst_param);
 
-   if (dst_type == EDJE_EXTERNAL_PARAM_TYPE_MAX)
+   if (!dst_info)
      {
        ERR("cannot copy, invalid destination parameter '%s' of part '%s'",
            dst_param, dst_part->part->name);
@@ -1843,11 +1971,18 @@ _edje_param_copy(Edje_Real_Part *src_part, const char *src_param, Edje_Real_Part
          }
      }
 
-   if (!_edje_param_convert(&val, dst_type))
+   if (!_edje_param_convert(&val, dst_info))
      {
        ERR("cannot convert parameter type %s to requested type %s",
            edje_external_param_type_str(val.type),
-           edje_external_param_type_str(dst_type));
+           edje_external_param_type_str(dst_info->type));
+       goto end;
+     }
+
+   if (!_edje_param_validate(&val, dst_info))
+     {
+       ERR("incorrect parameter value failed validation for type %s",
+           edje_external_param_type_str(dst_info->type));
        goto end;
      }
 
@@ -1857,7 +1992,7 @@ _edje_param_copy(Edje_Real_Part *src_part, const char *src_param, Edje_Real_Part
        if (!_edje_external_param_set(dst_part->swallowed_object, &val))
          {
             ERR("failed to set parameter '%s' (%s) of part '%s'",
-                dst_param, edje_external_param_type_str(dst_type),
+                dst_param, edje_external_param_type_str(dst_info->type),
                 dst_part->part->name);
             goto end;
          }
@@ -1867,7 +2002,7 @@ _edje_param_copy(Edje_Real_Part *src_part, const char *src_param, Edje_Real_Part
        if (!_edje_param_native_set(dst_part, dst_param, &val))
          {
             ERR("failed to set parameter '%s' (%s) of part '%s'",
-                dst_param, edje_external_param_type_str(dst_type),
+                dst_param, edje_external_param_type_str(dst_info->type),
                 dst_part->part->name);
             goto end;
          }