diff --git a/src/Makefile_Edje.am b/src/Makefile_Edje.am index a4f5073ed1..34a2cb7549 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 7dfc062bfa..31fed480dc 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 c0870df104..a9e3694537 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 0000000000..bd207cd81f --- /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 e2723d8ee5..d92c8c051c 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); }