efl_ui_radio_group: migrate to Efl.Ui.Single_Selectable
authorMarcel Hollerbach <mail@marcel-hollerbach.de>
Thu, 22 Aug 2019 13:06:22 +0000 (15:06 +0200)
committerYeongjong Lee <yj34.lee@samsung.com>
Mon, 16 Sep 2019 01:23:00 +0000 (10:23 +0900)
with this the whole thing is migrated to single_selectable. The group is
added to the spec test suite. The elm_test case of radio_group now also has
a fallback option to demonstrate the usage of it.

This also fixes a broken testcase, where a flag was forgotten to be
checked.

ref T8024

Reviewed-by: Mike Blumenkrantz <michael.blumenkrantz@gmail.com>
Differential Revision: https://phab.enlightenment.org/D9706

src/bin/elementary/test_part_bg.c
src/bin/elementary/test_ui_image.c
src/bin/elementary/test_ui_radio.c
src/lib/elementary/efl_ui_radio_box.c
src/lib/elementary/efl_ui_radio_group.eo
src/lib/elementary/efl_ui_radio_group_impl.c
src/lib/elementary/efl_ui_radio_group_impl.eo
src/tests/elementary/efl_ui_test_radio_group.c
src/tests/elementary/spec/efl_test_single_selectable.c

index cb9dd4d..3f8f30b 100644 (file)
@@ -15,7 +15,7 @@ _reset_cb(void *data, const Efl_Event *ev EINA_UNUSED)
    Efl_Ui_Radio_Group *radio = data;
    Evas_Object *target;
 
-   radio = efl_ui_radio_group_selected_object_get(radio);
+   radio = efl_ui_single_selectable_last_selected_get(radio);
    target = evas_object_data_get(radio, "data");
 
    efl_gfx_color_set(efl_part(target, "background"), 0, 0, 0, 0);
@@ -29,7 +29,7 @@ _color_cb(void *data, const Efl_Event *ev EINA_UNUSED)
    Evas_Object *target;
    static Eina_Bool i;
 
-   radio = efl_ui_radio_group_selected_object_get(radio);
+   radio = efl_ui_single_selectable_last_selected_get(radio);
    target = evas_object_data_get(radio, "data");
    i ^= EINA_TRUE;
    efl_gfx_color_set(efl_part(target, "background"), (i) ? 255 : 0, (i) ? 0 : 255, 0, 255);
@@ -43,7 +43,7 @@ _scale_type_cb(void *data, const Efl_Event *ev EINA_UNUSED)
    Efl_Gfx_Image_Scale_Type type;
    char buf[PATH_MAX];
 
-   radio = efl_ui_radio_group_selected_object_get(radio);
+   radio = efl_ui_single_selectable_last_selected_get(radio);
    target = evas_object_data_get(radio, "data");
 
    snprintf(buf, sizeof(buf), "%s/images/plant_01.jpg", elm_app_data_dir_get());
index e3f1bd5..87ad9fb 100644 (file)
@@ -640,7 +640,7 @@ test_ui_image_prescale(void *data EINA_UNUSED, Eo *obj EINA_UNUSED, void *event_
    efl_pack(hbox, rd);
    efl_event_callback_add(hbox, EFL_UI_RADIO_GROUP_EVENT_VALUE_CHANGED, _cb_prescale_radio_changed, im);
 
-   efl_ui_radio_group_selected_object_set(hbox, rd);
+   efl_ui_selectable_selected_set(rd, EINA_TRUE);
 
    efl_pack(box, hbox);
 
index ec2740f..487c6aa 100644 (file)
@@ -77,12 +77,12 @@ _set_selected_btn_clicked(void *data, const Efl_Event *ev EINA_UNUSED)
 }
 
 static void
-_set_selected_object_btn_clicked(void *data, const Efl_Event *ev)
+_set_fallback_radio_btn_clicked(void *data, const Efl_Event *ev EINA_UNUSED)
 {
-   Efl_Ui_Radio_Group *group = data;
-
-   efl_ui_radio_group_selected_value_set(group, 3);
-   efl_ui_radio_group_selected_object_set(group, efl_key_data_get(ev->object, "uk"));
+   if (!efl_ui_single_selectable_fallback_selection_get(data))
+     efl_ui_single_selectable_fallback_selection_set(data, efl_pack_content_get(data, 4));
+   else
+     efl_ui_single_selectable_fallback_selection_set(data, NULL);
 }
 
 void test_efl_ui_radio(void *data EINA_UNUSED,
@@ -94,7 +94,6 @@ void test_efl_ui_radio(void *data EINA_UNUSED,
    Efl_Ui_Box *bx;
    Eina_Array *arr;
    Efl_Ui_Button *o;
-   Efl_Ui_Radio *uk = NULL;
 
    win = efl_add(EFL_UI_WIN_CLASS, efl_main_loop_get(),
                  efl_ui_win_type_set(efl_added, EFL_UI_WIN_TYPE_BASIC),
@@ -112,8 +111,6 @@ void test_efl_ui_radio(void *data EINA_UNUSED,
      {
         Efl_Ui_Radio *r = eina_array_data_get(arr, i);
         efl_pack_end(bx, r);
-        if (i == 4)
-          uk = r;
      }
 
    o = efl_add(EFL_UI_BUTTON_CLASS, table);
@@ -128,9 +125,8 @@ void test_efl_ui_radio(void *data EINA_UNUSED,
 
    o = efl_add(EFL_UI_BUTTON_CLASS, table);
    efl_pack_table(table, o, 1, 2, 1, 1);
-   efl_text_set(o, "Set object for UK");
-   efl_key_data_set(o, "uk", uk);
-   efl_event_callback_add(o, EFL_INPUT_EVENT_CLICKED, _set_selected_object_btn_clicked, bx);
+   efl_text_set(o, "Fallback set to UK");
+   efl_event_callback_add(o, EFL_INPUT_EVENT_CLICKED, _set_fallback_radio_btn_clicked, bx);
 
    eina_array_free(arr);
 }
index b58e76f..92918ea 100644 (file)
@@ -119,6 +119,7 @@ _efl_ui_radio_box_efl_object_constructor(Eo *obj, Efl_Ui_Radio_Box_Data *pd)
 {
    pd->group = efl_new(EFL_UI_RADIO_GROUP_IMPL_CLASS, NULL);
    efl_composite_attach(obj, pd->group);
+   efl_event_callback_forwarder_add(pd->group, EFL_UI_SINGLE_SELECTABLE_EVENT_SELECTION_CHANGED, obj);
    efl_event_callback_forwarder_add(pd->group, EFL_UI_RADIO_GROUP_EVENT_VALUE_CHANGED, obj);
    return efl_constructor(efl_super(obj, MY_CLASS));
 }
index 34f0d7b..5651e23 100644 (file)
@@ -1,19 +1,10 @@
-interface @beta Efl.Ui.Radio_Group
+interface @beta Efl.Ui.Radio_Group extends Efl.Ui.Single_Selectable
 {
    [[Interface for manually handling a group of @Efl.Ui.Radio buttons.
 
      See the documentation of @Efl.Ui.Radio for an explanation of radio button grouping.
    ]]
    methods {
-      @property selected_object {
-        [[Currently selected button in a radio button group, or $NULL if no button is selected.
-
-          See also @.selected_value.
-        ]]
-        values {
-          selected_object : Efl.Ui.Radio; [[The currently selected radio button in the group, or $NULL.]]
-        }
-      }
       @property selected_value {
         [[The value associated with the currently selected button in the group.
           Give each radio button in the group a different value using @Efl.Ui.Radio.state_value.
index 14dc5a4..622924b 100644 (file)
@@ -11,41 +11,35 @@ static Eina_Hash *radio_group_map;
 
 typedef struct {
    Efl_Ui_Radio *selected;
+   Efl_Ui_Radio *fallback_object;
    Eina_List *registered_set;
+   Eina_Bool in_value_change;
 } Efl_Ui_Radio_Group_Impl_Data;
 
+
 EOLIAN static void
-_efl_ui_radio_group_impl_efl_ui_radio_group_selected_object_set(Eo *obj EINA_UNUSED, Efl_Ui_Radio_Group_Impl_Data *pd, Efl_Ui_Radio *selected_object)
+_efl_ui_radio_group_impl_efl_ui_single_selectable_fallback_selection_set(Eo *obj EINA_UNUSED, Efl_Ui_Radio_Group_Impl_Data *pd, Efl_Ui_Selectable *fallback)
 {
-   int new_value = -1;
-   Eo *old_selected;
-
-   if (pd->selected == selected_object) return;
+   pd->fallback_object = fallback;
 
-   old_selected = pd->selected;
-   pd->selected = selected_object;
-
-   //it is essential to *first* set pd->selected to the new state before calling this
-   //otherwise this here will be called again, and the event will get emitted twice
-   if (old_selected && efl_alive_get(old_selected))
-    efl_ui_selectable_selected_set(old_selected, EINA_FALSE);
+   if (!pd->selected)
+     efl_ui_selectable_selected_set(pd->fallback_object, EINA_TRUE);
+}
 
-   if (pd->selected)
-     {
-        efl_ui_selectable_selected_set(pd->selected, EINA_TRUE);
-        new_value = efl_ui_radio_state_value_get(pd->selected);
-     }
-   efl_event_callback_call(obj, EFL_UI_RADIO_GROUP_EVENT_VALUE_CHANGED, &new_value);
+EOLIAN static Efl_Ui_Selectable*
+_efl_ui_radio_group_impl_efl_ui_single_selectable_fallback_selection_get(const Eo *obj EINA_UNUSED, Efl_Ui_Radio_Group_Impl_Data *pd)
+{
+   return pd->fallback_object;
 }
 
 EOLIAN static Efl_Ui_Radio*
-_efl_ui_radio_group_impl_efl_ui_radio_group_selected_object_get(const Eo *obj EINA_UNUSED, Efl_Ui_Radio_Group_Impl_Data *pd)
+_efl_ui_radio_group_impl_efl_ui_single_selectable_last_selected_get(const Eo *obj EINA_UNUSED, Efl_Ui_Radio_Group_Impl_Data *pd)
 {
    return pd->selected;
 }
 
 EOLIAN static void
-_efl_ui_radio_group_impl_efl_ui_radio_group_selected_value_set(Eo *obj, Efl_Ui_Radio_Group_Impl_Data *pd, int selected_value)
+_efl_ui_radio_group_impl_efl_ui_radio_group_selected_value_set(Eo *obj EINA_UNUSED, Efl_Ui_Radio_Group_Impl_Data *pd, int selected_value)
 {
    Efl_Ui_Radio *reged;
    Eina_List *n;
@@ -54,7 +48,7 @@ _efl_ui_radio_group_impl_efl_ui_radio_group_selected_value_set(Eo *obj, Efl_Ui_R
      {
         if (efl_ui_radio_state_value_get(reged) == selected_value)
           {
-             efl_ui_radio_group_selected_object_set(obj, reged);
+             efl_ui_selectable_selected_set(reged, EINA_TRUE);
              return;
           }
      }
@@ -70,18 +64,43 @@ _efl_ui_radio_group_impl_efl_ui_radio_group_selected_value_get(const Eo *obj EIN
 static void
 _selected_cb(void *data, const Efl_Event *ev)
 {
+   Efl_Ui_Radio_Group_Impl_Data *pd = efl_data_scope_safe_get(data, EFL_UI_RADIO_GROUP_IMPL_CLASS);
    if (efl_ui_selectable_selected_get(ev->object))
      {
-        efl_ui_radio_group_selected_object_set(data, ev->object);
+        if (pd->selected)
+          {
+             pd->in_value_change = EINA_TRUE;
+             efl_ui_selectable_selected_set(pd->selected, EINA_FALSE);
+          }
+        pd->in_value_change = EINA_FALSE;
+        EINA_SAFETY_ON_FALSE_RETURN(!pd->selected);
+        pd->selected = ev->object;
      }
    else
      {
         //if something was unselected, we need to make sure that we are unsetting the internal pointer to NULL
-        if (efl_ui_radio_group_selected_object_get(data) == ev->object)
+        if (pd->selected == ev->object)
+          {
+             pd->selected = NULL;
+          }
+        //checkout if we want to do fallback handling
+        if (!pd->in_value_change)
           {
-             efl_ui_radio_group_selected_object_set(data, NULL);
+             if (!pd->selected && pd->fallback_object)
+               efl_ui_selectable_selected_set(pd->fallback_object, EINA_TRUE);
           }
      }
+
+   if (!pd->in_value_change)
+     {
+        int value;
+        if (pd->selected)
+          value = efl_ui_radio_state_value_get(pd->selected);
+        else
+          value = -1;
+        efl_event_callback_call(data, EFL_UI_RADIO_GROUP_EVENT_VALUE_CHANGED, &value);
+        efl_event_callback_call(data, EFL_UI_SINGLE_SELECTABLE_EVENT_SELECTION_CHANGED, NULL);
+     }
 }
 
 static void
@@ -123,7 +142,7 @@ EOLIAN static void
 _efl_ui_radio_group_impl_efl_ui_radio_group_unregister(Eo *obj, Efl_Ui_Radio_Group_Impl_Data *pd, Efl_Ui_Radio *radio)
 {
    if (pd->selected == radio)
-     efl_ui_radio_group_selected_object_set(obj, NULL);
+     efl_ui_selectable_selected_set(pd->selected, EINA_FALSE);
 
    efl_event_callback_array_del(radio, radio_btn_cb(), obj);
    pd->registered_set = eina_list_remove(pd->registered_set, radio);
index bc41093..7de7899 100644 (file)
@@ -5,9 +5,10 @@ class @beta Efl.Ui.Radio_Group_Impl extends Efl.Object implements Efl.Ui.Radio_G
    implements {
       class.constructor;
       Efl.Object.destructor;
-      Efl.Ui.Radio_Group.selected_object {get; set;}
       Efl.Ui.Radio_Group.selected_value {get; set;}
       Efl.Ui.Radio_Group.register;
       Efl.Ui.Radio_Group.unregister;
+      Efl.Ui.Single_Selectable.last_selected {get;}
+      Efl.Ui.Single_Selectable.fallback_selection {set; get;}
    }
 }
index 664819d..5b00b02 100644 (file)
@@ -65,20 +65,20 @@ EFL_START_TEST(active_selected_value_setting)
    efl_ui_radio_group_register(radio_group, r2);
 
    ck_assert_int_eq(efl_ui_radio_group_selected_value_get(radio_group), -1);
-   ck_assert_ptr_eq(efl_ui_radio_group_selected_object_get(radio_group), NULL);
+   ck_assert_ptr_eq(efl_ui_single_selectable_last_selected_get(radio_group), NULL);
 
    RESET_EVT
    efl_ui_radio_group_selected_value_set(radio_group, 1);
    ck_assert_int_eq(efl_ui_radio_group_selected_value_get(radio_group), 1);
-   ck_assert_ptr_eq(efl_ui_radio_group_selected_object_get(radio_group), r1);
+   ck_assert_ptr_eq(efl_ui_single_selectable_last_selected_get(radio_group), r1);
    ck_assert_int_eq(efl_ui_selectable_selected_get(r1), EINA_TRUE);
    ck_assert_int_eq(efl_ui_selectable_selected_get(r2), EINA_FALSE);
    EXPECT_EVT(1,1);
 
    RESET_EVT
-   efl_ui_radio_group_selected_object_set(radio_group, r2);
+   efl_ui_selectable_selected_set(r2, EINA_TRUE);
    ck_assert_int_eq(efl_ui_radio_group_selected_value_get(radio_group), 2);
-   ck_assert_ptr_eq(efl_ui_radio_group_selected_object_get(radio_group), r2);
+   ck_assert_ptr_eq(efl_ui_single_selectable_last_selected_get(radio_group), r2);
    ck_assert_int_eq(efl_ui_selectable_selected_get(r1), EINA_FALSE);
    ck_assert_int_eq(efl_ui_selectable_selected_get(r2), EINA_TRUE);
    EXPECT_EVT(1,2);
@@ -96,20 +96,20 @@ EFL_START_TEST(active_selection_setting)
    efl_ui_radio_group_register(radio_group, r2);
 
    ck_assert_int_eq(efl_ui_radio_group_selected_value_get(radio_group), -1);
-   ck_assert_ptr_eq(efl_ui_radio_group_selected_object_get(radio_group), NULL);
+   ck_assert_ptr_eq(efl_ui_single_selectable_last_selected_get(radio_group), NULL);
 
    RESET_EVT
-   efl_ui_radio_group_selected_object_set(radio_group, r1);
+   efl_ui_selectable_selected_set(r1, EINA_TRUE);
    ck_assert_int_eq(efl_ui_radio_group_selected_value_get(radio_group), 1);
-   ck_assert_ptr_eq(efl_ui_radio_group_selected_object_get(radio_group), r1);
+   ck_assert_ptr_eq(efl_ui_single_selectable_last_selected_get(radio_group), r1);
    ck_assert_int_eq(efl_ui_selectable_selected_get(r1), EINA_TRUE);
    ck_assert_int_eq(efl_ui_selectable_selected_get(r2), EINA_FALSE);
    EXPECT_EVT(1,1);
 
    RESET_EVT
-   efl_ui_radio_group_selected_object_set(radio_group, r2);
+   efl_ui_selectable_selected_set(r2, EINA_TRUE);
    ck_assert_int_eq(efl_ui_radio_group_selected_value_get(radio_group), 2);
-   ck_assert_ptr_eq(efl_ui_radio_group_selected_object_get(radio_group), r2);
+   ck_assert_ptr_eq(efl_ui_single_selectable_last_selected_get(radio_group), r2);
    ck_assert_int_eq(efl_ui_selectable_selected_get(r1), EINA_FALSE);
    ck_assert_int_eq(efl_ui_selectable_selected_get(r2), EINA_TRUE);
    EXPECT_EVT(1,2);
@@ -126,10 +126,10 @@ EFL_START_TEST(active_selection_object_setting)
 
    RESET_EVT
    ck_assert_int_eq(efl_ui_radio_group_selected_value_get(radio_group), -1);
-   ck_assert_ptr_eq(efl_ui_radio_group_selected_object_get(radio_group), NULL);
+   ck_assert_ptr_eq(efl_ui_single_selectable_last_selected_get(radio_group), NULL);
    efl_ui_selectable_selected_set(r, EINA_TRUE);
    ck_assert_int_eq(efl_ui_radio_group_selected_value_get(radio_group), 1);
-   ck_assert_ptr_eq(efl_ui_radio_group_selected_object_get(radio_group), r);
+   ck_assert_ptr_eq(efl_ui_single_selectable_last_selected_get(radio_group), r);
    EXPECT_EVT(1,1);
 }
 EFL_END_TEST
@@ -143,14 +143,14 @@ EFL_START_TEST(unregister_setted)
    efl_ui_radio_group_register(radio_group, radio());
 
    RESET_EVT
-   efl_ui_radio_group_selected_object_set(radio_group, r);
+   efl_ui_selectable_selected_set(r, EINA_TRUE);
    ck_assert_int_eq(efl_ui_radio_group_selected_value_get(radio_group), 1);
-   ck_assert_ptr_eq(efl_ui_radio_group_selected_object_get(radio_group), r);
+   ck_assert_ptr_eq(efl_ui_single_selectable_last_selected_get(radio_group), r);
    EXPECT_EVT(1,1);
    RESET_EVT
    efl_ui_radio_group_unregister(radio_group, r);
    ck_assert_int_eq(efl_ui_radio_group_selected_value_get(radio_group), -1);
-   ck_assert_ptr_eq(efl_ui_radio_group_selected_object_get(radio_group), NULL);
+   ck_assert_ptr_eq(efl_ui_single_selectable_last_selected_get(radio_group), NULL);
    EXPECT_EVT(1,-1);
 }
 EFL_END_TEST
@@ -163,14 +163,14 @@ EFL_START_TEST(delete_setted)
    efl_ui_radio_group_register(radio_group, r);
    efl_ui_radio_group_register(radio_group, radio());
    RESET_EVT
-   efl_ui_radio_group_selected_object_set(radio_group, r);
+   efl_ui_selectable_selected_set(r, EINA_TRUE);
    ck_assert_int_eq(efl_ui_radio_group_selected_value_get(radio_group), 1);
-   ck_assert_ptr_eq(efl_ui_radio_group_selected_object_get(radio_group), r);
+   ck_assert_ptr_eq(efl_ui_single_selectable_last_selected_get(radio_group), r);
    EXPECT_EVT(1,1);
    RESET_EVT
    efl_del(r);
    ck_assert_int_eq(efl_ui_radio_group_selected_value_get(radio_group), -1);
-   ck_assert_ptr_eq(efl_ui_radio_group_selected_object_get(radio_group), NULL);
+   ck_assert_ptr_eq(efl_ui_single_selectable_last_selected_get(radio_group), NULL);
    EXPECT_EVT(1,-1);
 }
 EFL_END_TEST
@@ -185,12 +185,12 @@ EFL_START_TEST(external_setting)
    RESET_EVT
    efl_ui_selectable_selected_set(r, EINA_TRUE);
    ck_assert_int_eq(efl_ui_radio_group_selected_value_get(radio_group), 1);
-   ck_assert_ptr_eq(efl_ui_radio_group_selected_object_get(radio_group), r);
+   ck_assert_ptr_eq(efl_ui_single_selectable_last_selected_get(radio_group), r);
    EXPECT_EVT(1,1);
    RESET_EVT
    efl_ui_selectable_selected_set(r, EINA_FALSE);
    ck_assert_int_eq(efl_ui_radio_group_selected_value_get(radio_group), -1);
-   ck_assert_ptr_eq(efl_ui_radio_group_selected_object_get(radio_group), NULL);
+   ck_assert_ptr_eq(efl_ui_single_selectable_last_selected_get(radio_group), NULL);
    EXPECT_EVT(1,-1);
 }
 EFL_END_TEST
index fd4b5e0..5ec40b2 100644 (file)
@@ -8,10 +8,11 @@
 
 /* spec-meta-start
       {"test-interface":"Efl.Ui.Single_Selectable",
-       "test-widgets": ["Efl.Ui.Grid", "Efl.Ui.List"],
+       "test-widgets": ["Efl.Ui.Grid", "Efl.Ui.List", "Efl.Ui.Radio_Box"],
        "custom-mapping" : {
           "Efl.Ui.Grid" : "EFL_UI_GRID_DEFAULT_ITEM_CLASS",
-          "Efl.Ui.List" : "EFL_UI_LIST_DEFAULT_ITEM_CLASS"
+          "Efl.Ui.List" : "EFL_UI_LIST_DEFAULT_ITEM_CLASS",
+          "Efl.Ui.Radio_Box" : "EFL_UI_RADIO_CLASS"
         }
       }
 
@@ -49,9 +50,17 @@ EFL_START_TEST(last_selectable_check)
 
    efl_ui_selectable_selected_set(c2, EINA_TRUE);
    ck_assert_ptr_eq(efl_ui_single_selectable_last_selected_get(widget), c2);
+   if (c == 0) efl_loop_begin(efl_main_loop_get());
+   ck_assert_int_eq(c, 1);
+   c = 0;
+
    efl_ui_selectable_selected_set(c1, EINA_FALSE);
    ck_assert_ptr_eq(efl_ui_single_selectable_last_selected_get(widget), c2);
    efl_ui_selectable_selected_set(c2, EINA_FALSE);
+   if (c == 0) efl_loop_begin(efl_main_loop_get());
+   ck_assert_int_eq(c, 1);
+   c = 0;
+
    ck_assert_ptr_eq(efl_ui_single_selectable_last_selected_get(widget), NULL);
 }
 EFL_END_TEST