edje: Implement EO API for message_send

Since this uses generic_value (aka Eina_Value), there is an
implicit type detection and conversion. I did not attempt to
cover all types (namely string+int and string+float and even
less sets of those) as I believe they aren't really used. Or
they most likely could be replaced by multiple messages rather
than a single message.

Note: should we pass ptr(generic_value) instead of generic_value?
The API looks a little odd in C when passing by value.

@feature
This commit is contained in:
Jean-Philippe Andre 2017-05-23 16:29:16 +09:00
parent e7abfba034
commit 9d48350ae4
5 changed files with 327 additions and 11 deletions

View File

@ -277,6 +277,7 @@ tests/edje/data/test_swallows.edc \
tests/edje/data/test_box.edc \
tests/edje/data/test_table.edc \
tests/edje/data/test_combine_keywords.edc \
tests/edje/data/test_messages.edc \
tests/edje/data/filter.lua
@ -317,6 +318,7 @@ EDJE_TEST_FILES = tests/edje/data/test_layout.edj \
tests/edje/data/test_box.edj \
tests/edje/data/test_table.edj \
tests/edje/data/test_combine_keywords.edj \
tests/edje/data/test_messages.edj \
$(NULL)
CLEANFILES += $(EDJE_TEST_FILES)

View File

@ -32,9 +32,113 @@ _edje_object_message_propagate_send(Evas_Object *obj, Edje_Message_Type type, in
}
EOLIAN void
_edje_object_message_send(Eo *obj, Edje *pd EINA_UNUSED, int id, const Eina_Value *val)
_edje_object_message_send(Eo *obj, Edje *pd EINA_UNUSED, int id, const Eina_Value val)
{
/* TODO */
const Eina_Value_Type *valtype;
Edje_Message_Type msgtype;
/* Note: Only primitive types & arrays of them are supported.
* This reduces complexity and I couldn't find many real uses for combo
* types (string+int or string+float).
*/
union {
Edje_Message_String str;
Edje_Message_Int i;
Edje_Message_Float f;
Edje_Message_String_Set ss;
Edje_Message_Int_Set is;
Edje_Message_Float_Set fs;
//Edje_Message_String_Int si;
//Edje_Message_String_Float sf;
//Edje_Message_String_Int_Set sis;
//Edje_Message_String_Float_Set sfs;
} msg, *pmsg;
valtype = eina_value_type_get(&val);
if (!valtype) goto bad_type;
pmsg = &msg;
if ((valtype == EINA_VALUE_TYPE_STRING) ||
(valtype == EINA_VALUE_TYPE_STRINGSHARE))
{
eina_value_get(&val, &msg.str.str);
msgtype = EDJE_MESSAGE_STRING;
}
else if (valtype == EINA_VALUE_TYPE_INT)
{
eina_value_get(&val, &msg.i.val);
msgtype = EDJE_MESSAGE_INT;
}
else if (valtype == EINA_VALUE_TYPE_FLOAT)
{
float f;
eina_value_get(&val, &f);
msg.f.val = (double) f;
msgtype = EDJE_MESSAGE_FLOAT;
}
else if (valtype == EINA_VALUE_TYPE_DOUBLE)
{
eina_value_get(&val, &msg.f.val);
msgtype = EDJE_MESSAGE_FLOAT;
}
else if (valtype == EINA_VALUE_TYPE_ARRAY)
{
Eina_Value_Array array = {};
size_t sz, k, count;
eina_value_get(&val, &array);
count = eina_inarray_count(array.array);
if ((array.subtype == EINA_VALUE_TYPE_STRING) ||
(array.subtype == EINA_VALUE_TYPE_STRINGSHARE))
{
sz = sizeof(char *);
msgtype = EDJE_MESSAGE_STRING_SET;
pmsg = alloca(sizeof(*pmsg) + sz * count);
pmsg->ss.count = count;
for (k = 0; k < count; k++)
pmsg->ss.str[k] = eina_inarray_nth(array.array, k);
}
else if (array.subtype == EINA_VALUE_TYPE_INT)
{
sz = sizeof(int);
msgtype = EDJE_MESSAGE_INT_SET;
pmsg = alloca(sizeof(*pmsg) + sz * count);
pmsg->is.count = count;
for (k = 0; k < count; k++)
pmsg->is.val[k] = *((int *) eina_inarray_nth(array.array, k));
}
else if (array.subtype == EINA_VALUE_TYPE_DOUBLE)
{
sz = sizeof(double);
msgtype = EDJE_MESSAGE_FLOAT_SET;
pmsg = alloca(sizeof(*pmsg) + sz * count);
pmsg->fs.count = count;
for (k = 0; k < count; k++)
pmsg->fs.val[k] = *((double *) eina_inarray_nth(array.array, k));
}
else if (array.subtype == EINA_VALUE_TYPE_FLOAT)
{
sz = sizeof(double);
msgtype = EDJE_MESSAGE_FLOAT_SET;
pmsg = alloca(sizeof(*pmsg) + sz * count);
pmsg->fs.count = count;
for (k = 0; k < count; k++)
pmsg->fs.val[k] = (double) *((float *) eina_inarray_nth(array.array, k));
}
else goto bad_type;
}
else goto bad_type;
_edje_object_message_propagate_send(obj, msgtype, id, pmsg, EINA_FALSE);
return;
bad_type:
ERR("Unsupported value type: %s. Only primitives types int, real "
"(float or double), string or arrays of those types are supported.",
eina_value_type_name_get(valtype));
return;
}
EOLIAN void

View File

@ -466,18 +466,17 @@ class Edje.Object (Efl.Canvas.Group.Clipped, Efl.File, Efl.Container, Efl.Part,
This function sends an Edje message to obj and to all of its
child objects, if it has any (swallowed objects are one kind of
child object). type and msg must be matched accordingly,
as documented in #Edje_Message_Type.
child object). Only a few types are supported:
- int,
- float/double,
- string/stringshare,
- arrays of int, float, double or strings.
The id argument as a form of code and theme defining a common
interface on message communication. One should define the same IDs
on both code and EDC declaration (see \@ref edcref "the syntax" for
EDC files), to individualize messages (binding them to a given
context).
The function to handle messages arriving from obj is set with
edje_object_message_handler_set().]]
on both code and EDC declaration, to individualize messages
(binding them to a given context).
]]
params {
@in id: int; [[A identification number for the message to be sent]]
@in msg: const(generic_value); [[The message's payload]]

View File

@ -0,0 +1,67 @@
collections {
group { "test_group";
parts {
rect { "bg";
desc { "default";
color: 0 0 0 255;
}
}
text { "text";
desc { "default";
text {
font: "Sans";
size: 24;
text: "HELLO";
}
}
}
}
// Messages IDs:
// 0. string, text string
// 1. int, text size
// 2. int set, bg color (4 ints)
// 3. float, sends signal
script {
public message(Msg_Type:type, id, ...) {
if ((type == MSG_STRING) && (id == 0)) {
new str[64], buf[64];
getsarg(2, str, sizeof(str));
set_text(PART:"text", str);
snprintf(buf, sizeof(buf), "str %s", str);
emit(buf, "edc");
}
else if ((type == MSG_INT) && (id == 1)) {
new i, buf[64];
i = getarg(2);
set_state_val(PART:"text", STATE_TEXT_SIZE, i);
snprintf(buf, sizeof(buf), "int %d", i);
emit(buf, "edc");
}
else if ((type == MSG_FLOAT) && (id == 2)) {
new f, buf[64];
f = getarg(2);
snprintf(buf, sizeof(buf), "float %f", f);
emit(buf, "edc");
}
else if ((type == MSG_INT_SET) && (id == 3)) {
new r, g, b, a, buf[64];
r = getarg(2);
g = getarg(3);
b = getarg(4);
a = getarg(5);
set_state_val(PART:"bg", STATE_COLOR, r, g, b, a);
snprintf(buf, sizeof(buf), "int set %d %d %d %d", r, g, b, a);
emit(buf, "edc");
}
}
}
}

View File

@ -725,6 +725,148 @@ START_TEST(edje_test_combine_keywords)
}
END_TEST
static void
_message_signal_reply_cb(void *data, Evas_Object *obj EINA_UNUSED,
const char *emission, const char *source)
{
int *id = data;
fprintf(stderr, "source %s emit %s id %d\n", source, emission, *id);
fflush(stderr);
ck_assert_str_eq(source, "edc");
ck_assert_ptr_nonnull(emission);
if (!strncmp(emission, "int set", 7))
ck_assert_str_eq(emission, "int set 7 12 42 255");
else if (!strncmp(emission, "int", 3))
ck_assert_str_eq(emission, "int 42");
else if (!strncmp(emission, "float", 5))
{
char buf[64];
sprintf(buf, "float %f", 0.12);
ck_assert_str_eq(emission, buf);
}
else if (!strncmp(emission, "str", 3))
ck_assert_str_eq(emission, "str hello world");
else ck_abort_msg("Invalid emission!");
(*id)++;
}
START_TEST(edje_test_message_send_legacy)
{
Evas *evas;
Evas_Object *obj;
Edje_Message_Int msgi;
Edje_Message_Float msgf;
Edje_Message_String msgs;
Edje_Message_Int_Set *msgis;
int id = 0;
/* Ugly calls to process:
*
* 1. Send edje message (async)
* 2. Process edje message (sync)
* 3. EDC program emits edje signal (async)
* 4. Process edje signal (sync)
* 5. Finally reached signal cb
*/
evas = EDJE_TEST_INIT_EVAS();
obj = edje_object_add(evas);
fail_unless(edje_object_file_set(obj, test_layout_get("test_messages.edj"), "test_group"));
edje_object_signal_callback_add(obj, "*", "edc", _message_signal_reply_cb, &id);
msgs.str = "hello world";
edje_object_message_send(obj, EDJE_MESSAGE_STRING, 0, &msgs);
edje_message_signal_process();
ck_assert_int_eq(id, 1);
msgi.val = 42;
edje_object_message_send(obj, EDJE_MESSAGE_INT, 1, &msgi);
edje_message_signal_process();
ck_assert_int_eq(id, 2);
msgf.val = 0.12;
edje_object_message_send(obj, EDJE_MESSAGE_FLOAT, 2, &msgf);
edje_message_signal_process();
ck_assert_int_eq(id, 3);
msgis = alloca(sizeof(*msgis) + 4 * sizeof(msgis->val));
msgis->count = 4;
msgis->val[0] = 7;
msgis->val[1] = 12;
msgis->val[2] = 42;
msgis->val[3] = 255;
edje_object_message_send(obj, EDJE_MESSAGE_INT_SET, 3, msgis);
edje_message_signal_process();
ck_assert_int_eq(id, 4);
evas_object_del(obj);
EDJE_TEST_FREE_EVAS();
}
END_TEST
START_TEST(edje_test_message_send_eo)
{
Evas *evas;
Evas_Object *obj;
Eina_Value v, *va;
int id = 0;
evas = EDJE_TEST_INIT_EVAS();
obj = efl_add(EDJE_OBJECT_CLASS, evas,
efl_file_set(efl_added, test_layout_get("test_messages.edj"), "test_group"));
// FIXME: EO API HERE
edje_object_signal_callback_add(obj, "*", "edc", _message_signal_reply_cb, &id);
// NOTE: edje_object_message_signal_process may or may not be in EO (TBD)
eina_value_setup(&v, EINA_VALUE_TYPE_STRING);
eina_value_set(&v, "hello world");
edje_obj_message_send(obj, 0, v);
eina_value_flush(&v);
edje_message_signal_process();
edje_object_calc_force(obj);
ck_assert_int_eq(id, 1);
eina_value_setup(&v, EINA_VALUE_TYPE_INT);
eina_value_set(&v, 42);
edje_obj_message_send(obj, 1, v);
eina_value_flush(&v);
edje_message_signal_process();
edje_object_calc_force(obj);
ck_assert_int_eq(id, 2);
eina_value_setup(&v, EINA_VALUE_TYPE_FLOAT);
eina_value_set(&v, 0.12);
edje_obj_message_send(obj, 2, v);
eina_value_flush(&v);
edje_message_signal_process();
edje_object_calc_force(obj);
ck_assert_int_eq(id, 3);
va = eina_value_array_new(EINA_VALUE_TYPE_INT, 4);
eina_value_array_append(va, 7);
eina_value_array_append(va, 12);
eina_value_array_append(va, 42);
eina_value_array_append(va, 255);
edje_obj_message_send(obj, 3, *va);
eina_value_free(va);
edje_message_signal_process();
edje_object_calc_force(obj);
ck_assert_int_eq(id, 4);
efl_del(obj);
EDJE_TEST_FREE_EVAS();
}
END_TEST
void edje_test_edje(TCase *tc)
{
tcase_add_test(tc, edje_test_edje_init);
@ -746,4 +888,6 @@ void edje_test_edje(TCase *tc)
tcase_add_test(tc, edje_test_table);
tcase_add_test(tc, edje_test_table_eoapi);
tcase_add_test(tc, edje_test_combine_keywords);
tcase_add_test(tc, edje_test_message_send_legacy);
tcase_add_test(tc, edje_test_message_send_eo);
}