elementary: rework Efl.Ui.Layout boolean signal-connection to Models
authorVitor Sousa <vitorsousa@expertisesolutions.com.br>
Tue, 6 Nov 2018 13:23:21 +0000 (11:23 -0200)
committerHermet Park <hermetpark@gmail.com>
Wed, 5 Dec 2018 05:52:40 +0000 (14:52 +0900)
Add new feature to specify signal connection to boolean properties of Models.
This also fix some '%v' substitution problems.

Parsing EINA_VALUE_TYPE_BOOL as boolean in Efl.Ui.Layout signal updates from
Models (instead of EINA_VALUE_TYPE_UCHAR). UCHAR no longer has special handling
and falls to the general result of eina_value_to_string() as other types do.

Use EINA_VALUE_TYPE_BOOL instead of EINA_VALUE_TYPE_UCHAR to signal selection on
click events to the Model.

Update examples to make usage of the new property connection feature in order to
model selection of items on Views.

src/examples/elementary/efl_ui_list_view_example_1.c
src/lib/elementary/efl_ui_layout.c

index f509af1..f0a6adc 100644 (file)
@@ -71,9 +71,10 @@ _make_model(Evas_Object *win)
 EAPI_MAIN int
 elm_main(int argc, char **argv)
 {
-   Efl_Ui_Layout_Factory *factory;
+   Efl_Ui_Factory *factory;
    Evas_Object *win, *li;
    Eo *model;
+   Efl_Model_Composite_Selection *selmodel;
 
    win = elm_win_util_standard_add("list_view", "List_View");
    elm_policy_set(ELM_POLICY_QUIT, ELM_POLICY_QUIT_LAST_WINDOW_CLOSED);
@@ -81,15 +82,20 @@ elm_main(int argc, char **argv)
    elm_win_autodel_set(win, EINA_TRUE);
 
    model = _make_model(win);
+   selmodel = efl_add(EFL_MODEL_COMPOSITE_SELECTION_CLASS, efl_main_loop_get()
+     , efl_ui_view_model_set(efl_added, model)
+   );
 
    factory = efl_add(EFL_UI_LAYOUT_FACTORY_CLASS, win);
    efl_ui_model_connect(factory, "signal/elm,state,%v", "odd_style");
+   efl_ui_model_connect(factory, "signal/efl,state,%{selected;unselected}", "selected");
    efl_ui_model_connect(factory, "efl.text", "name");
    efl_ui_layout_factory_theme_config(factory, "list_item", NULL, "default");
 
-   li = efl_add(EFL_UI_LIST_VIEW_CLASS, win);
-   efl_ui_list_view_layout_factory_set(li, factory);
-   efl_ui_view_model_set(li, model);
+   li = efl_add(EFL_UI_LIST_VIEW_CLASS, win
+     , efl_ui_list_view_layout_factory_set(efl_added, factory)
+     , efl_ui_view_model_set(efl_added, selmodel)
+   );
 
    efl_event_callback_add(li, EFL_UI_LIST_VIEW_EVENT_ITEM_REALIZED, _realized_cb, NULL);
 //   efl_event_callback_add(li, EFL_UI_LIST_VIEW_EVENT_ITEM_UNREALIZED, _unrealized_cb, NULL);
index 16f3f80..a46c716 100644 (file)
@@ -2167,7 +2167,9 @@ _efl_ui_layout_view_model_signal_update(Efl_Ui_Layout_Data *pd, const char *sign
 {
    Eina_Value *v = NULL;
    Eina_Strbuf *buf;
-   char *value;
+   char *value = NULL;
+   Eina_Bool eval = EINA_FALSE;
+   Eina_Bool is_bool = EINA_FALSE;
 
    v = efl_model_property_get(pd->connect.model, fetch);
    if (!v) return;
@@ -2181,26 +2183,55 @@ _efl_ui_layout_view_model_signal_update(Efl_Ui_Layout_Data *pd, const char *sign
         return;
      }
 
-   // FIXME: previous implementation would just do that for signal/part == "selected"
-   if (eina_value_type_get(v) == EINA_VALUE_TYPE_UCHAR)
-     {
-        Eina_Bool bl;
-
-        eina_value_bool_get(v, &bl);
-        if (bl) value = strdup("selected");
-        else value = strdup("unselected");
-     }
-   else
+   is_bool = (eina_value_type_get(v) == EINA_VALUE_TYPE_BOOL);
+   if (is_bool)
      {
-        value = eina_value_to_string(v);
+        eina_value_bool_get(v, &eval);
      }
+   value = eina_value_to_string(v);
 
    buf = eina_strbuf_new();
    // FIXME: is it really the form of signal we want to send ?
-   eina_strbuf_append_printf(buf, "%s%s", signal, value);
+   const char *ini = signal;
+   for (;;)
+     {
+        const char *last = ini;
+        ini = strstr(last, "%{");
+        if (!ini)
+          {
+             eina_strbuf_append(buf, last);
+             break;
+          }
+        if (!is_bool)
+          {
+             ERR("Using signal connection `%%{;}' with a property that is not boolean. Signal: `%s'; Property: `%s'.", signal, fetch);
+             goto on_error;
+          }
+        eina_strbuf_append_length(buf, last, (size_t)(ini-last));
+        const char *sep = strchr(ini+2, ';');
+        if (!sep)
+          {
+             ERR("Could not find separator `;'.");
+             goto on_error;
+          }
+        const char *fin = strchr(sep+1, '}');
+        if (!fin)
+          {
+             ERR("Could not find terminator `}'.");
+             goto on_error;
+          }
+        if (eval)
+          eina_strbuf_append_length(buf, ini+2, (size_t)(sep-(ini+2)));
+        else
+          eina_strbuf_append_length(buf, sep+1, (size_t)(fin-(sep+1)));
+        ini = fin+1;
+     }
+   eina_strbuf_replace_all(buf, "%v", value);
+
    elm_layout_signal_emit(pd->obj, eina_strbuf_string_get(buf),
                           elm_widget_is_legacy(pd->obj) ? "elm" : "efl");
 
+on_error:
    eina_strbuf_free(buf);
    eina_value_free(v);
    free(value);