Introduce Efl.Ui.Radio_Group & Efl.Ui.Radio_Box

Radio_Group is a interface that manages that radio groups can be grouped inside a
external object, the current API of radio was considered confusing in
that regard. It is implemented in the Radio_Group_Internal class which
is private to EFL, a instance of it can be found with get due to the
class function in efl_ui_radio.eo. This architecture was taken like
this, in order to have implementation and interface seperated. With
those two seperated we can inherit from regular widgets, implement the
interface, and composite attach the internal object to the regular
widget. This makes a lot of things easier.

Radio_Box is a class which is extending Efl.Ui.Box, which has an
internal Radio_Group. This is extremly usefull for cases where you just
want to have a list of radio buttons in your UI. The radio group is also
exposed using composition to the internal object. Simular things can be
done for the table.

For now i did not add API to find the group of a radio button. However,
this can be quickly added if requested.

ref T7867

Reviewed-by: Mike Blumenkrantz <michael.blumenkrantz@gmail.com>
Reviewed-by: Xavi Artigas <xavierartigas@yahoo.es>
Differential Revision: https://phab.enlightenment.org/D9058
This commit is contained in:
Marcel Hollerbach 2019-05-29 13:03:37 +02:00
parent 42b293ae1f
commit c9177a9f8d
18 changed files with 829 additions and 47 deletions

View File

@ -100,6 +100,7 @@ elementary_test_src = [
'test_ui_panes.c',
'test_ui_panel.c',
'test_ui_active_view.c',
'test_ui_radio.c',
'test_part_bg.c',
'test_part_shadow.c',
'test_photo.c',

View File

@ -391,6 +391,7 @@ void test_ui_active_view_plain(void *data, Evas_Object *obj, void *event_info);
void test_ui_active_view_scroll(void *data, Evas_Object *obj, void *event_info);
void test_ui_relative_layout(void *data, Evas_Object *obj, void *event_info);
void test_efl_ui_radio(void *data, Evas_Object *obj, void *event_info);
static void _list_udpate(void);
@ -1076,6 +1077,7 @@ add_tests:
ADD_TEST(NULL, "Selectors", "DaySelector", test_dayselector);
ADD_TEST(NULL, "Selectors", "Main menu", test_main_menu);
ADD_TEST(NULL, "Selectors", "Combobox", test_combobox);
ADD_TEST_EO(NULL, "Selectors", "Efl.Ui.Radio_Box", test_efl_ui_radio);
//------------------------------//
ADD_TEST(NULL, "Cursors", "Cursor", test_cursor);

View File

@ -0,0 +1,136 @@
#ifdef HAVE_CONFIG_H
# include "elementary_config.h"
#endif
#include <Efl_Ui.h>
const char *countries[] =
{
"Germany",
"USA",
"France",
"Korea",
"UK",
"Romania",
"Italy",
NULL,
};
#define MAX_INDEX 8
static void
_check_button_selection_changed_cb(void *data EINA_UNUSED, const Efl_Event *ev)
{
if (efl_ui_check_selected_get(ev->object))
printf("Object %p is now selected\n", ev->object);
else
printf("Object %p is now unselected\n", ev->object);
}
static Eina_Array*
create_radios(Efl_Ui_Win *win)
{
Eina_Array *arr = eina_array_new(5);
for (unsigned int i = 0; countries[i]; ++i)
{
Efl_Ui_Radio *rbtn = efl_add(EFL_UI_RADIO_CLASS, win);
efl_ui_radio_state_value_set(rbtn, i);
efl_text_set(rbtn, countries[i]);
efl_event_callback_add(rbtn, EFL_UI_CHECK_EVENT_SELECTED_CHANGED, _check_button_selection_changed_cb, NULL);
eina_array_push(arr, rbtn);
}
return arr;
}
static void
_value_changed_cb(void *data EINA_UNUSED, const Efl_Event *ev)
{
Efl_Ui_Radio_Group *g = ev->object;
int index = efl_ui_radio_group_selected_value_get(g);
if (index == -1)
{
printf("Nothing is selected anymore\n");
}
else
{
EINA_SAFETY_ON_FALSE_RETURN((index >= 0) && index < MAX_INDEX);
printf("Now selected value %s\n", countries[index]);
}
}
static void
_select_btn_clicked(void *data, const Efl_Event *ev EINA_UNUSED)
{
Efl_Ui_Check *c = data;
efl_ui_check_selected_set(c, EINA_TRUE);
}
static void
_set_selected_btn_clicked(void *data, const Efl_Event *ev EINA_UNUSED)
{
Efl_Ui_Radio_Group *group = data;
efl_ui_radio_group_selected_value_set(group, 0);
}
static void
_set_selected_object_btn_clicked(void *data, const Efl_Event *ev)
{
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"));
}
void test_efl_ui_radio(void *data EINA_UNUSED,
Evas_Object *obj EINA_UNUSED,
void *event_info EINA_UNUSED)
{
Efl_Ui_Win *win;
Efl_Ui_Table *table;
Efl_Ui_Box *bx;
Eina_Array *arr;
Efl_Ui_Button *o;
Efl_Ui_Radio *uk;
win = efl_add(EFL_UI_WIN_CLASS, efl_main_loop_get(),
efl_ui_win_type_set(efl_added, EFL_UI_WIN_TYPE_BASIC),
efl_text_set(efl_added, "Efl.Ui.Radio_Box"),
efl_ui_win_autodel_set(efl_added, EINA_TRUE));
table = efl_add(EFL_UI_TABLE_CLASS, win);
efl_content_set(win, table);
bx = efl_add(EFL_UI_RADIO_BOX_CLASS, table);
efl_pack_table(table, bx, 0, 0, 1, 3);
efl_event_callback_add(bx, EFL_UI_RADIO_GROUP_EVENT_VALUE_CHANGED, _value_changed_cb, NULL);
arr = create_radios(win);
for (unsigned int i = 0; i < eina_array_count(arr); ++i)
{
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);
efl_pack_table(table, o, 1, 0, 1, 1);
efl_text_set(o, "Selected France check");
efl_event_callback_add(o, EFL_UI_EVENT_CLICKED, _select_btn_clicked, eina_array_data_get(arr, 2));
o = efl_add(EFL_UI_BUTTON_CLASS, table);
efl_pack_table(table, o, 1, 1, 1, 1);
efl_text_set(o, "Set value for Germany");
efl_event_callback_add(o, EFL_UI_EVENT_CLICKED, _set_selected_btn_clicked, bx);
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_UI_EVENT_CLICKED, _set_selected_object_btn_clicked, bx);
eina_array_free(arr);
}

View File

@ -0,0 +1,46 @@
/*
* gcc -o efl_ui_radio_example_01 efl_ui_radio_example_01.c `pkg-config --cflags --libs elementary`
*/
#define EFL_BETA_API_SUPPORT 1
#include <Efl_Ui.h>
#include <Elementary.h>
const char *example_strings[] = {
"Seoul",
"Karlsruhe",
"New York",
"Hong Kong",
"Hamburg",
"Berlin",
"Paris",
NULL
};
EAPI_MAIN void
efl_main(void *data EINA_UNUSED, const Efl_Event *ev EINA_UNUSED)
{
Eo *win, *box;
elm_policy_set(ELM_POLICY_QUIT, ELM_POLICY_QUIT_LAST_WINDOW_CLOSED);
win = efl_add(EFL_UI_WIN_CLASS, efl_main_loop_get(),
efl_ui_win_type_set(efl_added, EFL_UI_WIN_TYPE_BASIC),
efl_text_set(efl_added, "Efl.Ui.Radio example"),
efl_ui_win_autodel_set(efl_added, EINA_TRUE)
);
box = efl_add(EFL_UI_RADIO_BOX_CLASS, win,
efl_content_set(win, efl_added));
for (int i = 0; example_strings[i]; ++i)
{
Eo *radio;
radio = efl_add(EFL_UI_RADIO_CLASS, box);
efl_text_set(radio, example_strings[i]);
efl_ui_radio_state_value_set(radio, i + 1);
efl_pack_end(box, radio);
}
}
EFL_MAIN()

View File

@ -117,7 +117,8 @@ examples = [
'efl_canvas_layout_text',
'efl_ui_theme_example_01',
'efl_ui_theme_example_02',
'efl_ui_slideshow_example'
'efl_ui_slideshow_example',
'efl_ui_radio_example_01',
]
foreach example : examples

View File

@ -373,6 +373,7 @@ ELM_LAYOUT_TEXT_ALIASES_IMPLEMENT(MY_CLASS_PFX)
ELM_LAYOUT_TEXT_ALIASES_OPS(MY_CLASS_PFX)
#include "efl_ui_radio.eo.c"
#include "efl_ui_radio_group.eo.c"
#include "efl_ui_radio_eo.legacy.c"
#include "efl_ui_radio_legacy_eo.h"

View File

@ -19,52 +19,6 @@ class @beta Efl.Ui.Radio extends Efl.Ui.Check implements Efl.Access.Widget.Actio
value: int; [[The value to use if this radio object is selected.]]
}
}
@property value_pointer {
set {
[[Set a convenience pointer to an integer, which changes when radio group
value changes.
This sets a pointer to an integer that in addition to the radio
object state will also be modified directly. To stop setting the
object pointed to, simply use NULL as the valuep argument. If
valuep is not NULL then when called, the radio object
state will also be modified to reflect the value of the integer
valuep points to, just like calling elm_radio_value_set().
]]
}
values {
valuep: ptr(int); [[Pointer to the integer to modify]]
}
}
@property selected_object {
get {
[[Get the selected radio object.]]
return: Efl.Canvas.Object; [[The selected radio object]]
}
}
group_add {
[[Add this radio to a group of other radio objects
Radio objects work in groups. Each member should have a different
integer value assigned. In order to have them work as a group, they
need to know about each other. This adds the given radio object to
the group of which the group object indicated is a member.
]]
params {
@in group: Efl.Ui.Radio; [[Any radio object whose group the obj is
to join.]]
}
}
@property group_value {
[[Change the value of the group.
This will enable the radio button in the group that is assosiated with this value. A value which is not assosiated with any radio button will result in every radio button beeing disabled.
]]
values {
value : int; [[The value of the radio button in the group which should be enabled.]]
}
}
}
implements {
Efl.Object.constructor;

View File

@ -0,0 +1,127 @@
#ifdef HAVE_CONFIG_H
# include "elementary_config.h"
#endif
#include <Elementary.h>
#include "elm_priv.h"
#define MY_CLASS EFL_UI_RADIO_BOX_CLASS
typedef struct {
Eina_Bool in_pack;
Efl_Ui_Radio_Group *group;
} Efl_Ui_Radio_Box_Data;
static inline Eina_Bool
register_safe_in_group_begin(Eo *subobj, Efl_Ui_Radio_Box_Data *pd)
{
EINA_SAFETY_ON_FALSE_RETURN_VAL(efl_isa(subobj, EFL_UI_RADIO_CLASS), EINA_FALSE);
if (!pd->in_pack)
efl_ui_radio_group_register(pd->group, subobj);
pd->in_pack = EINA_TRUE;
return EINA_TRUE;
}
static inline Eina_Bool
register_safe_group_end(Eo *subobj, Efl_Ui_Radio_Box_Data *pd, Eina_Bool result)
{
if (!result)
efl_ui_radio_group_unregister(pd->group, subobj);
pd->in_pack = EINA_FALSE;
return result;
}
#define REGISTER_SAFE(f) \
Eina_Bool result; \
if (!register_safe_in_group_begin(subobj, pd)) \
return EINA_FALSE; \
result = f ; \
return register_safe_group_end(subobj, pd, result);
static void
unpack_from_logical(Eo *obj, Efl_Ui_Radio_Box_Data *pd)
{
int length = efl_content_count(obj);
for (int i = 0; i < length; ++i)
{
efl_ui_radio_group_unregister(pd->group, efl_pack_content_get(obj, i));
}
}
EOLIAN static Eina_Bool
_efl_ui_radio_box_efl_pack_pack_clear(Eo *obj, Efl_Ui_Radio_Box_Data *pd)
{
unpack_from_logical(obj, pd);
return efl_pack_clear(efl_super(obj, MY_CLASS));
}
EOLIAN static Eina_Bool
_efl_ui_radio_box_efl_pack_unpack_all(Eo *obj, Efl_Ui_Radio_Box_Data *pd)
{
unpack_from_logical(obj, pd);
return efl_pack_unpack_all(efl_super(obj, MY_CLASS));
}
EOLIAN static Eina_Bool
_efl_ui_radio_box_efl_pack_unpack(Eo *obj, Efl_Ui_Radio_Box_Data *pd, Efl_Gfx_Entity *subobj)
{
efl_ui_radio_group_unregister(pd->group, subobj);
return efl_pack_unpack(efl_super(obj, MY_CLASS), subobj);
}
EOLIAN static Efl_Gfx_Entity*
_efl_ui_radio_box_efl_pack_linear_pack_unpack_at(Eo *obj, Efl_Ui_Radio_Box_Data *pd, int index)
{
efl_ui_radio_group_unregister(pd->group, efl_pack_content_get(obj, index));
return efl_pack_unpack_at(efl_super(obj, MY_CLASS), index);
}
EOLIAN static Eina_Bool
_efl_ui_radio_box_efl_pack_pack(Eo *obj, Efl_Ui_Radio_Box_Data *pd, Efl_Gfx_Entity *subobj)
{
REGISTER_SAFE(efl_pack(efl_super(obj, MY_CLASS), subobj))
}
EOLIAN static Eina_Bool
_efl_ui_radio_box_efl_pack_linear_pack_begin(Eo *obj, Efl_Ui_Radio_Box_Data *pd, Efl_Gfx_Entity *subobj)
{
REGISTER_SAFE(efl_pack_begin(efl_super(obj, MY_CLASS), subobj))
}
EOLIAN static Eina_Bool
_efl_ui_radio_box_efl_pack_linear_pack_end(Eo *obj, Efl_Ui_Radio_Box_Data *pd, Efl_Gfx_Entity *subobj)
{
REGISTER_SAFE(efl_pack_end(efl_super(obj, MY_CLASS), subobj))
}
EOLIAN static Eina_Bool
_efl_ui_radio_box_efl_pack_linear_pack_before(Eo *obj, Efl_Ui_Radio_Box_Data *pd, Efl_Gfx_Entity *subobj, const Efl_Gfx_Entity *existing)
{
REGISTER_SAFE(efl_pack_before(efl_super(obj, MY_CLASS), subobj, existing));
}
EOLIAN static Eina_Bool
_efl_ui_radio_box_efl_pack_linear_pack_after(Eo *obj, Efl_Ui_Radio_Box_Data *pd, Efl_Gfx_Entity *subobj, const Efl_Gfx_Entity *existing)
{
REGISTER_SAFE(efl_pack_after(efl_super(obj, MY_CLASS), subobj, existing));
}
EOLIAN static Eina_Bool
_efl_ui_radio_box_efl_pack_linear_pack_at(Eo *obj, Efl_Ui_Radio_Box_Data *pd, Efl_Gfx_Entity *subobj, int index)
{
REGISTER_SAFE(efl_pack_at(efl_super(obj, MY_CLASS), subobj, index));
}
EOLIAN static Efl_Object*
_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_RADIO_GROUP_EVENT_VALUE_CHANGED, obj);
return efl_constructor(efl_super(obj, MY_CLASS));
}
#include "efl_ui_radio_box.eo.c"

View File

@ -0,0 +1,21 @@
class @beta Efl.Ui.Radio_Box extends Efl.Ui.Box implements Efl.Ui.Radio_Group
{
methods {
}
implements {
Efl.Pack.pack_clear;
Efl.Pack.unpack_all;
Efl.Pack.unpack;
Efl.Pack.pack;
Efl.Pack_Linear.pack_begin;
Efl.Pack_Linear.pack_end;
Efl.Pack_Linear.pack_before;
Efl.Pack_Linear.pack_after;
Efl.Pack_Linear.pack_at;
Efl.Pack_Linear.pack_unpack_at;
Efl.Object.constructor;
}
composite {
Efl.Ui.Radio_Group;
}
}

View File

@ -1 +1,7 @@
#define _EFL_UI_RADIO_EO_CLASS_TYPE
typedef Eo Efl_Ui_Radio;
#include "efl_ui_radio_group.eo.h"
#include "efl_ui_radio_group_impl.eo.h"
#include "efl_ui_radio.eo.h"
#include "efl_ui_radio_box.eo.h"

View File

@ -0,0 +1,50 @@
interface @beta Efl.Ui.Radio_Group
{
[[A object for organising a group of radio buttons
A group of radio buttons is a set of pair-wise different values. (Where values are the assosiated values of each radio button)
At any point of time only 1 or 0 buttons can be selected. If a new button is selected, the previous selected button will be unselected.
]]
methods {
@property selected_object {
[[Which object is currently selected in the group
$NULL if no object is selected.
]]
values {
selected_object : Efl.Ui.Radio; [[The selected radio button in the group, $NULL for no object]]
}
}
@property selected_value {
[[Each group has a selected value, representing which radio group is selected.
A value of -1 here does represent that no button is selected.
Possible values here are only those that are assisiated with a registered radio button.
]]
values {
selected_value : int; [[The value of the selection state]]
}
}
register {
[[Register a new radio button to this group.
The assosiated value of the radio button must not collide with any other assosiated value of registered buttons.
]]
params {
radio : Efl.Ui.Radio; [[The radio button to regsiter]]
}
}
unregister {
[[Unregsiter a before registered button from this group.
if the button was selected before, no object will be selected afterwards.
]]
params {
radio : Efl.Ui.Radio; [[The radio button to unregister]]
}
}
}
events {
value,changed : int; [[Emitted each time the $selected_value has changed.]]
}
}

View File

@ -0,0 +1,152 @@
#ifdef HAVE_CONFIG_H
# include "elementary_config.h"
#endif
#include <Elementary.h>
#include "elm_priv.h"
#define MY_CLASS EFL_UI_RADIO_GROUP_IMPL_CLASS
static Eina_Hash *radio_group_map;
typedef struct {
Efl_Ui_Radio *selected;
Eina_List *registered_set;
} 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)
{
int new_value = -1;
Eo *old_selected;
if (pd->selected == selected_object) return;
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_check_selected_set(old_selected, EINA_FALSE);
if (pd->selected)
{
efl_ui_check_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_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)
{
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 *reged;
Eina_List *n;
EINA_LIST_FOREACH(pd->registered_set, n, reged)
{
if (efl_ui_radio_state_value_get(reged) == selected_value)
{
efl_ui_radio_group_selected_object_set(obj, reged);
return;
}
}
ERR("Value %d not assosiated with any radio button", selected_value);
}
EOLIAN static int
_efl_ui_radio_group_impl_efl_ui_radio_group_selected_value_get(const Eo *obj EINA_UNUSED, Efl_Ui_Radio_Group_Impl_Data *pd)
{
return pd->selected ? efl_ui_radio_state_value_get(pd->selected) : -1;
}
static void
_selected_cb(void *data, const Efl_Event *ev)
{
if (efl_ui_check_selected_get(ev->object))
{
efl_ui_radio_group_selected_object_set(data, 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)
{
efl_ui_radio_group_selected_object_set(data, NULL);
}
}
}
static void
_invalidate_cb(void *data, const Efl_Event *ev)
{
efl_ui_radio_group_unregister(data, ev->object);
}
EFL_CALLBACKS_ARRAY_DEFINE(radio_btn_cb,
{EFL_UI_CHECK_EVENT_SELECTED_CHANGED, _selected_cb},
{EFL_EVENT_INVALIDATE, _invalidate_cb},
)
EOLIAN static void
_efl_ui_radio_group_impl_efl_ui_radio_group_register(Eo *obj, Efl_Ui_Radio_Group_Impl_Data *pd, Efl_Ui_Radio *radio)
{
Efl_Ui_Radio *reged;
Eina_List *n;
if (eina_hash_find(radio_group_map, &radio))
{
ERR("Radio button %p is already part of another group", radio);
return;
}
EINA_LIST_FOREACH(pd->registered_set, n, reged)
{
EINA_SAFETY_ON_TRUE_RETURN(radio == reged);
EINA_SAFETY_ON_TRUE_RETURN(efl_ui_radio_state_value_get(radio) == efl_ui_radio_state_value_get(reged));
}
EINA_SAFETY_ON_TRUE_RETURN(efl_ui_radio_state_value_get(radio) == -1);
pd->registered_set = eina_list_append(pd->registered_set, radio);
eina_hash_add(radio_group_map, &radio, obj);
efl_event_callback_array_add(radio, radio_btn_cb(), obj);
}
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_event_callback_array_del(radio, radio_btn_cb(), obj);
pd->registered_set = eina_list_remove(pd->registered_set, radio);
eina_hash_del(radio_group_map, &radio, obj);
}
EOLIAN static void
_efl_ui_radio_group_impl_efl_object_destructor(Eo *obj, Efl_Ui_Radio_Group_Impl_Data *pd)
{
Eo *radio;
EINA_LIST_FREE(pd->registered_set, radio)
{
efl_event_callback_array_del(radio, radio_btn_cb(), obj);
eina_hash_del(radio_group_map, &radio, obj);
}
efl_destructor(efl_super(obj, MY_CLASS));
}
void
_efl_ui_radio_group_impl_class_constructor(Efl_Class *klass EINA_UNUSED)
{
radio_group_map = eina_hash_pointer_new(NULL);
}
#include "efl_ui_radio_group_impl.eo.c"

View File

@ -0,0 +1,11 @@
class @beta Efl.Ui.Radio_Group_Impl extends Efl.Object implements Efl.Ui.Radio_Group
{
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;
}
}

View File

@ -57,6 +57,9 @@ pub_eo_files = [
'efl_ui_panes.eo',
'efl_ui_progressbar.eo',
'efl_ui_radio.eo',
'efl_ui_radio_group.eo',
'efl_ui_radio_box.eo',
'efl_ui_radio_group_impl.eo',
'efl_ui_slider.eo',
'efl_ui_slider_interval.eo',
'efl_ui_spin.eo',
@ -813,6 +816,8 @@ elementary_src = [
'elm_prefs_data.c',
'efl_ui_progressbar.c',
'efl_ui_radio.c',
'efl_ui_radio_group_impl.c',
'efl_ui_radio_box.c',
'elm_route.c',
'elm_scroller.c',
'elm_segment_control.c',

View File

@ -27,6 +27,7 @@ static const Efl_Test_Case etc[] = {
{ "efl_ui_widget", efl_ui_test_widget },
{ "efl_ui_active_view", efl_ui_test_active_view},
{ "efl_ui_check", efl_ui_test_check },
{ "efl_ui_radio_group", efl_ui_test_radio_group },
{ NULL, NULL }
};

View File

@ -36,6 +36,7 @@ void efl_ui_model(TCase *tc);
void efl_ui_test_widget(TCase *tc);
void efl_ui_test_active_view(TCase *tc);
void efl_ui_test_check(TCase *tc);
void efl_ui_test_radio_group(TCase *tc);
void loop_timer_interval_set(Eo *obj, double in);

View File

@ -0,0 +1,266 @@
#ifdef HAVE_CONFIG_H
# include "elementary_config.h"
#endif
#include <Efl_Ui.h>
#include "efl_ui_suite.h"
#include "suite_helpers.h"
static Eo *win, *radio_group;
int state_values = 0;
typedef struct {
int called;
int value;
} Group_Changed_Called;
Group_Changed_Called changed_evt;
#define RESET_EVT \
changed_evt.called = 0; \
changed_evt.value = 200000000;
#define EXPECT_EVT(c, v) \
ck_assert_int_eq(changed_evt.called, c); \
ck_assert_int_eq(changed_evt.value, v);
static void
_group_value_changed_cb(void *data EINA_UNUSED, const Efl_Event *ev)
{
changed_evt.called ++;
changed_evt.value = *((int*)ev->info);
}
static void
check_setup()
{
win = win_add();
radio_group = efl_new(EFL_UI_RADIO_GROUP_IMPL_CLASS, NULL);
efl_event_callback_add(radio_group, EFL_UI_RADIO_GROUP_EVENT_VALUE_CHANGED, _group_value_changed_cb, NULL);
}
static void
check_teardown()
{
efl_unref(radio_group);
if (win)
{
efl_del(win);
win = NULL;
}
}
static Eo*
radio(void)
{
state_values += 1;
return efl_add(EFL_UI_RADIO_CLASS, win, efl_ui_radio_state_value_set(efl_added, state_values));
}
EFL_START_TEST(active_selected_value_setting)
{
Eo *r1 = radio();
Eo *r2 = radio();
efl_ui_radio_group_register(radio_group, radio());
efl_ui_radio_group_register(radio_group, radio());
efl_ui_radio_group_register(radio_group, r1);
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);
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_int_eq(efl_ui_check_selected_get(r1), EINA_TRUE);
ck_assert_int_eq(efl_ui_check_selected_get(r2), EINA_FALSE);
EXPECT_EVT(1,1);
RESET_EVT
efl_ui_radio_group_selected_object_set(radio_group, r2);
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_int_eq(efl_ui_check_selected_get(r1), EINA_FALSE);
ck_assert_int_eq(efl_ui_check_selected_get(r2), EINA_TRUE);
EXPECT_EVT(1,2);
}
EFL_END_TEST
EFL_START_TEST(active_selection_setting)
{
Eo *r1 = radio();
Eo *r2 = radio();
efl_ui_radio_group_register(radio_group, radio());
efl_ui_radio_group_register(radio_group, radio());
efl_ui_radio_group_register(radio_group, r1);
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);
RESET_EVT
efl_ui_radio_group_selected_object_set(radio_group, r1);
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_int_eq(efl_ui_check_selected_get(r1), EINA_TRUE);
ck_assert_int_eq(efl_ui_check_selected_get(r2), EINA_FALSE);
EXPECT_EVT(1,1);
RESET_EVT
efl_ui_radio_group_selected_object_set(radio_group, r2);
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_int_eq(efl_ui_check_selected_get(r1), EINA_FALSE);
ck_assert_int_eq(efl_ui_check_selected_get(r2), EINA_TRUE);
EXPECT_EVT(1,2);
}
EFL_END_TEST
EFL_START_TEST(active_selection_object_setting)
{
Eo *r = radio();
efl_ui_radio_group_register(radio_group, radio());
efl_ui_radio_group_register(radio_group, radio());
efl_ui_radio_group_register(radio_group, r);
efl_ui_radio_group_register(radio_group, radio());
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);
efl_ui_check_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);
EXPECT_EVT(1,1);
}
EFL_END_TEST
EFL_START_TEST(unregister_setted)
{
Eo *r = radio();
efl_ui_radio_group_register(radio_group, radio());
efl_ui_radio_group_register(radio_group, radio());
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);
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);
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);
EXPECT_EVT(1,-1);
}
EFL_END_TEST
EFL_START_TEST(delete_setted)
{
Eo *r = radio();
efl_ui_radio_group_register(radio_group, radio());
efl_ui_radio_group_register(radio_group, radio());
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);
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);
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);
EXPECT_EVT(1,-1);
}
EFL_END_TEST
EFL_START_TEST(external_setting)
{
Eo *r = radio();
efl_ui_radio_group_register(radio_group, radio());
efl_ui_radio_group_register(radio_group, radio());
efl_ui_radio_group_register(radio_group, r);
efl_ui_radio_group_register(radio_group, radio());
RESET_EVT
efl_ui_check_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);
EXPECT_EVT(1,1);
RESET_EVT
efl_ui_check_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);
EXPECT_EVT(1,-1);
}
EFL_END_TEST
EFL_START_TEST(pairwise_different_error)
{
Eo *r = radio();
Eo *r1 = radio();
Eo *r2 = radio();
efl_ui_radio_state_value_set(r, -1);
efl_ui_radio_state_value_set(r1, 14);
efl_ui_radio_state_value_set(r2, 14);
EXPECT_ERROR_START;
efl_ui_radio_group_register(radio_group, r);
EXPECT_ERROR_END;
efl_ui_radio_group_register(radio_group, r1);
EXPECT_ERROR_START;
efl_ui_radio_group_register(radio_group, r2);
EXPECT_ERROR_END;
}
EFL_END_TEST
EFL_START_TEST(group_double_registeration)
{
Eo *r = radio();
efl_ui_radio_group_register(radio_group, r);
EXPECT_ERROR_START;
efl_ui_radio_group_register(radio_group, r);
EXPECT_ERROR_END;
}
EFL_END_TEST
EFL_START_TEST(group_registeration_in_two_groups)
{
Eo *radio_group2 = efl_new(EFL_UI_RADIO_GROUP_IMPL_CLASS, NULL);
Eo *r = radio();
efl_ui_radio_group_register(radio_group, r);
EXPECT_ERROR_START;
efl_ui_radio_group_register(radio_group2, r);
EXPECT_ERROR_END;
}
EFL_END_TEST
EFL_START_TEST(group_invalid_value)
{
Eo *radio_group2 = efl_new(EFL_UI_RADIO_GROUP_IMPL_CLASS, NULL);
Eo *r = radio();
efl_ui_radio_group_register(radio_group, r);
EXPECT_ERROR_START;
efl_ui_radio_group_selected_value_set(radio_group2, 1000);
EXPECT_ERROR_END;
}
EFL_END_TEST
void efl_ui_test_radio_group(TCase *tc)
{
tcase_add_checked_fixture(tc, fail_on_errors_setup, fail_on_errors_teardown);
tcase_add_checked_fixture(tc, check_setup, check_teardown);
tcase_add_test(tc, active_selected_value_setting);
tcase_add_test(tc, active_selection_setting);
tcase_add_test(tc, active_selection_object_setting);
tcase_add_test(tc, pairwise_different_error);
tcase_add_test(tc, group_double_registeration);
tcase_add_test(tc, group_registeration_in_two_groups);
tcase_add_test(tc, unregister_setted);
tcase_add_test(tc, external_setting);
tcase_add_test(tc, delete_setted);
tcase_add_test(tc, group_invalid_value);
}

View File

@ -140,6 +140,7 @@ efl_ui_suite_src = [
'efl_ui_test_widget.c',
'efl_ui_test_active_view.c',
'efl_ui_test_check.c',
'efl_ui_test_radio_group.c',
]
efl_ui_suite = executable('efl_ui_suite',