jpeg pushed a commit to branch master. http://git.enlightenment.org/core/efl.git/commit/?id=9d48350ae40eaa1ea6247c402dee06bb31553484
commit 9d48350ae40eaa1ea6247c402dee06bb31553484 Author: Jean-Philippe Andre <[email protected]> Date: Tue May 23 16:29:16 2017 +0900 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 --- src/Makefile_Edje.am | 2 + src/lib/edje/edje_message_queue.c | 108 ++++++++++++++++++++++++- src/lib/edje/edje_object.eo | 17 ++-- src/tests/edje/data/test_messages.edc | 67 ++++++++++++++++ src/tests/edje/edje_test_edje.c | 144 ++++++++++++++++++++++++++++++++++ 5 files changed, 327 insertions(+), 11 deletions(-) diff --git a/src/Makefile_Edje.am b/src/Makefile_Edje.am index a4f5073..34a2cb7 100644 --- a/src/Makefile_Edje.am +++ b/src/Makefile_Edje.am @@ -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) diff --git a/src/lib/edje/edje_message_queue.c b/src/lib/edje/edje_message_queue.c index 7dfc062..31fed48 100644 --- a/src/lib/edje/edje_message_queue.c +++ b/src/lib/edje/edje_message_queue.c @@ -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 diff --git a/src/lib/edje/edje_object.eo b/src/lib/edje/edje_object.eo index c0870df..a9e3694 100644 --- a/src/lib/edje/edje_object.eo +++ b/src/lib/edje/edje_object.eo @@ -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]] diff --git a/src/tests/edje/data/test_messages.edc b/src/tests/edje/data/test_messages.edc new file mode 100644 index 0000000..bd207cd --- /dev/null +++ b/src/tests/edje/data/test_messages.edc @@ -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"); + } + } + } + } diff --git a/src/tests/edje/edje_test_edje.c b/src/tests/edje/edje_test_edje.c index e2723d8..d92c8c0 100644 --- a/src/tests/edje/edje_test_edje.c +++ b/src/tests/edje/edje_test_edje.c @@ -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); } --
