efl: add efl_model and efl_ui_view classes

Efl.Model.Container and Efl.Model.Item to efl/interfaces are used
to create Efl.Model objects with predefined property values.
This is useful to any situation where we want an Efl.Model with
explicit defined property values.

Efl.Ui.View and Efl.Ui.Factory are used to connect Efl.Models with
Widgets, Elm.Layout and Efl.Ui.Image has changed to use news interfaces

Signed-off-by: Cedric BAIL <cedric@osg.samsung.com>
This commit is contained in:
Larry Jr 2017-01-31 18:17:58 -02:00 committed by Cedric BAIL
parent de83cc77d3
commit 093c592188
35 changed files with 2045 additions and 2 deletions

View File

@ -26,6 +26,9 @@ ecore_eolian_files_public = \
ecore_eolian_files = \
$(ecore_eolian_files_public) \
lib/ecore/efl_promise.eo \
lib/ecore/efl_model_item.eo \
lib/ecore/efl_model_container.eo \
lib/ecore/efl_model_container_item.eo \
$(ecore_eolian_files_legacy)
ecore_eolian_type_files = \
@ -86,6 +89,10 @@ lib/ecore/efl_io_file.c \
lib/ecore/efl_io_copier.c \
lib/ecore/efl_io_buffered_stream.c \
lib/ecore/efl_promise.c \
lib/ecore/efl_model_item.c \
lib/ecore/efl_model_container.c \
lib/ecore/efl_model_container_item.c \
lib/ecore/efl_model_container_private.h \
lib/ecore/ecore_pipe.c \
lib/ecore/ecore_poller.c \
lib/ecore/ecore_time.c \

View File

@ -43,6 +43,10 @@ efl_eolian_files = \
lib/efl/interfaces/efl_vpath_file_core.eo \
lib/efl/interfaces/efl_ui_spin.eo \
lib/efl/interfaces/efl_ui_progress.eo \
lib/efl/interfaces/efl_ui_view.eo \
lib/efl/interfaces/efl_ui_model_connect.eo \
lib/efl/interfaces/efl_ui_factory.eo \
lib/efl/interfaces/efl_ui_model_factory_connect.eo \
lib/efl/interfaces/efl_screen.eo \
lib/efl/interfaces/efl_io_closer.eo \
lib/efl/interfaces/efl_io_positioner.eo \
@ -171,3 +175,33 @@ bin_efl_efl_debug_CPPFLAGS = -I$(top_builddir)/src/bin/efl @EINA_CFLAGS@ @ECORE_
bin_efl_efl_debug_LDADD = @EFL_LIBS@ @USE_EINA_INTERNAL_LIBS@ @USE_ECORE_INTERNAL_LIBS@ @USE_ECORE_CON_INTERNAL_LIBS@
bin_efl_efl_debug_DEPENDENCIES = @USE_EINA_INTERNAL_LIBS@ @USE_ECORE_INTERNAL_LIBS@ @USE_ECORE_CON_INTERNAL_LIBS@
if EFL_ENABLE_TESTS
check_PROGRAMS += tests/efl/efl_suite
TESTS += tests/efl/efl_suite
tests_efl_efl_suite_SOURCES = \
tests/efl/efl_suite.c \
tests/efl/efl_test_model_container.c \
tests/efl/efl_suite.h
tests_efl_efl_suite_CPPFLAGS = -I$(top_builddir)/src/lib/efl \
-DTESTS_SRC_DIR=\"$(top_srcdir)/src/tests/efl\" \
-DTESTS_BUILD_DIR=\"$(top_builddir)/src/tests/efl\" \
@CHECK_CFLAGS@ \
@ECORE_CFLAGS@ \
@EFL_CFLAGS@
tests_efl_efl_suite_LDADD = @CHECK_LIBS@ \
@EFL_LIBS@ \
@USE_EFL_LIBS@ \
@USE_ECORE_LIBS@ -lecore
tests_efl_efl_suite_DEPENDENCIES = \
@USE_EFL_INTERNAL_LIBS@ \
@USE_ECORE_INTERNAL_LIBS@
endif

View File

@ -117,6 +117,7 @@ elm_public_eolian_files = \
lib/elementary/efl_ui_text_editable.eo \
lib/elementary/efl_config_global.eo \
lib/elementary/efl_ui_clock.eo \
lib/elementary/efl_ui_image_factory.eo \
$(NULL)
# Private classes (not exposed or shipped)
@ -667,6 +668,7 @@ lib_elementary_libelementary_la_SOURCES = \
lib/elementary/efl_ui_text.c \
lib/elementary/efl_ui_clock.c \
lib/elementary/efl_ui_clock_private.h \
lib/elementary/efl_ui_image_factory.c \
$(NULL)

View File

@ -117,6 +117,7 @@ label_example_01.c \
layout_example_01.c \
layout_example_02.c \
layout_example_03.c \
layout_model_connect.c \
list_example_01.c \
list_example_02.c \
list_example_03.c \
@ -318,6 +319,7 @@ label_example_01 \
layout_example_01 \
layout_example_02 \
layout_example_03 \
layout_model_connect \
list_example_01 \
list_example_02 \
list_example_03 \

View File

@ -0,0 +1,176 @@
// gcc -o layout_model_connect layout_model_connect.c `pkg-config --cflags --libs elementary`
#ifdef HAVE_CONFIG_H
# include "config.h"
#else
# define EFL_BETA_API_SUPPORT 1
# define EFL_EO_API_SUPPORT 1
#endif
#include <Elementary.h>
#include <Efl.h>
#include <Eio.h>
#include <stdio.h>
#define EFL_MODEL_TEST_FILENAME_PATH "/tmp"
struct _Layout_Model_Data
{
Eo *fileview;
Eo *model;
Evas_Object *label;
Evas_Object *entry;
Evas_Object *img;
Evas_Object *bt;
};
typedef struct _Layout_Model_Data Layout_Model_Data;
static void
_cleanup_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
{
Layout_Model_Data *priv = (Layout_Model_Data*)data;
efl_unref(priv->fileview);
efl_unref(priv->model);
}
static void
_list_selected_cb(void *data EINA_UNUSED, const Efl_Event *event)
{
Layout_Model_Data *priv = data;
Eo *child = event->info;
printf("LIST selected model\n");
efl_ui_view_model_set(priv->label, child);
efl_ui_view_model_set(priv->entry, child);
efl_ui_view_model_set(priv->img, child);
efl_ui_view_model_set(priv->bt, child);
}
static void
_update_cb(void *data, Evas_Object *obj, void *ev)
{
Layout_Model_Data *priv = data;
const char *text = elm_object_text_get(priv->entry);
elm_layout_text_set(priv->label, "default", text);
}
static void
_widget_init(Evas_Object *widget)
{
evas_object_size_hint_weight_set(widget, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
evas_object_size_hint_align_set(widget, EVAS_HINT_FILL, EVAS_HINT_FILL);
evas_object_show(widget);
}
Evas_Object *
_label_init(Evas_Object *win, Evas_Object *box, const char *text)
{
Evas_Object *widget = elm_label_add(win);
elm_label_line_wrap_set(widget, ELM_WRAP_CHAR);
elm_object_text_set(widget, text);
elm_box_pack_end(box, widget);
evas_object_size_hint_weight_set(widget, EVAS_HINT_FILL, EVAS_HINT_FILL);
evas_object_size_hint_align_set(widget, EVAS_HINT_FILL, EVAS_HINT_FILL);
evas_object_show(widget);
return widget;
}
static void
_signal_cb(void *data,
Evas_Object *obj EINA_UNUSED,
const char *emission,
const char *source)
{
printf(">> Signal callback emission='%s' source='%s'\n", emission, source);
}
EAPI_MAIN int
elm_main(int argc, char **argv)
{
Layout_Model_Data *priv;
Evas_Object *win, *panes, *bxr, *genlist;
Eo *img_factory;
char *dirname;
priv = alloca(sizeof(Layout_Model_Data));
memset(priv, 0, sizeof(Layout_Model_Data));
//win
win = elm_win_util_standard_add("viewlist", "Viewlist");
elm_policy_set(ELM_POLICY_QUIT, ELM_POLICY_QUIT_LAST_WINDOW_CLOSED);
elm_win_autodel_set(win, EINA_TRUE);
panes = elm_panes_add(win);
evas_object_size_hint_weight_set(panes, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
elm_win_resize_object_add(win, panes);
if (argv[1] != NULL) dirname = argv[1];
else dirname = EFL_MODEL_TEST_FILENAME_PATH;
priv->model = efl_add(EIO_MODEL_CLASS, NULL, eio_model_path_set(efl_added, dirname));
genlist = elm_genlist_add(win);
priv->fileview = efl_add(ELM_VIEW_LIST_CLASS, NULL, elm_view_list_genlist_set(efl_added, genlist, ELM_GENLIST_ITEM_NONE, NULL));
elm_view_list_property_connect(priv->fileview, "filename", "elm.text");
elm_view_list_model_set(priv->fileview, priv->model);
_widget_init(genlist);
elm_object_part_content_set(panes, "left", genlist);
elm_obj_panes_content_left_size_set(panes, 0.3);
efl_event_callback_add(priv->fileview, ELM_VIEW_LIST_EVENT_MODEL_SELECTED, _list_selected_cb, priv);
bxr = elm_box_add(win);
_widget_init(bxr);
elm_object_part_content_set(panes, "right", bxr);
/*Label widget */
_label_init(win, bxr, "FILENAME:");
priv->label = _label_init(win, bxr, "");
efl_ui_model_connect(priv->label, "default", "path"); //connect "default" to "filename" property
/* Entry widget */
priv->entry = elm_entry_add(win);
efl_ui_model_connect(priv->entry, "elm.text", "path"); //connect "elm.text" to "path" property
elm_entry_single_line_set(priv->entry, EINA_TRUE);
elm_box_pack_end(bxr, priv->entry);
evas_object_size_hint_weight_set(priv->entry, EVAS_HINT_FILL, 0);
evas_object_size_hint_align_set(priv->entry, EVAS_HINT_FILL, EVAS_HINT_FILL);
evas_object_show(priv->entry);
/* Button widget */
priv->bt = elm_button_add(win);
elm_box_pack_end(bxr, priv->bt);
elm_object_text_set(priv->bt, "update model");
evas_object_smart_callback_add(priv->bt, "clicked", _update_cb, priv);
edje_obj_signal_callback_add(priv->bt, "test*" , "*", _signal_cb, priv);
efl_ui_model_connect(priv->bt, "signal/test-%v", "size");
evas_object_show(priv->bt);
/* Image widget */
img_factory = efl_add(EFL_UI_IMAGE_FACTORY_CLASS, win);
efl_ui_model_connect(img_factory, "", "path"); //connect to "path" property
efl_ui_model_factory_connect(priv->bt, "icon", img_factory);
priv->img = efl_ui_factory_create(img_factory, NULL, win);
elm_box_pack_end(bxr, priv->img);
evas_object_size_hint_weight_set(priv->img, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
evas_object_size_hint_align_set(priv->img, EVAS_HINT_FILL, EVAS_HINT_FILL);
evas_object_show(priv->img);
evas_object_event_callback_add(win, EVAS_CALLBACK_DEL, _cleanup_cb, priv);
//showall
evas_object_resize(win, 800, 400);
evas_object_show(panes);
evas_object_show(win);
elm_run();
elm_shutdown();
ecore_shutdown();
return 0;
}
ELM_MAIN()

View File

@ -112,6 +112,20 @@ EAPI Efl_Future *efl_future_iterator_race(Eina_Iterator *it);
#include "efl_io_copier.eo.h"
#include "efl_io_buffered_stream.eo.h"
/**
* @}
*/
/**
* @ingroup Ecore_Model_Group
*
* @{
*/
#include "efl_model_item.eo.h"
#include "efl_model_container.eo.h"
#include "efl_model_container_item.eo.h"
/**
* @}
*/

View File

@ -0,0 +1,298 @@
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <Efl.h>
#include <Eina.h>
#include <Eo.h>
#include <Ecore.h>
#include "efl_model_container_private.h"
#define MY_CLASS EFL_MODEL_CONTAINER_CLASS
void *
_value_copy_alloc(void *v, const Eina_Value_Type *type)
{
if (!v)
return v;
if (type == EINA_VALUE_TYPE_STRINGSHARE)
return (void*) eina_stringshare_ref(v);
else if (type == EINA_VALUE_TYPE_STRING)
return (void*) strdup(v);
else
{
void *ret = malloc(type->value_size);
memcpy(ret, v, type->value_size);
return ret;
}
}
void
_value_free(void *v, const Eina_Value_Type *type)
{
if (!v)
return;
if (type == EINA_VALUE_TYPE_STRINGSHARE)
return eina_stringshare_del(v);
else
free(v);
}
static void
_values_free(Eina_Array *values, const Eina_Value_Type *type)
{
unsigned int i;
void *v;
Eina_Array_Iterator it;
EINA_ARRAY_ITER_NEXT(values, i, v, it)
{
_value_free(v, type);
}
eina_array_free(values);
}
static Eina_Bool
_stringshared_keys_free(const Eina_Hash *hash EINA_UNUSED, const void *key, void *data EINA_UNUSED, void *fdata EINA_UNUSED)
{
eina_stringshare_del(key);
return EINA_TRUE;
}
static void
_property_data_free_cb(void *data)
{
Child_Property_Data *cpd = data;
_values_free(cpd->property_values, cpd->property_type);
free(cpd);
}
static Efl_Object *
_efl_model_container_efl_object_constructor(Eo *obj, Efl_Model_Container_Data *sd)
{
obj = efl_constructor(efl_super(obj, MY_CLASS));
if (!obj)
return NULL;
sd->obj = obj;
sd->property_data = eina_hash_stringshared_new(_property_data_free_cb);
sd->defined_properties = eina_array_new(8);
return obj;
}
static void
_efl_model_container_efl_object_destructor(Eo *obj, Efl_Model_Container_Data *sd)
{
Efl_Model *child;
EINA_LIST_FREE(sd->children, child)
{
if (child)
{
efl_model_container_item_invalidate(child);
efl_parent_set(child, NULL);
}
}
eina_array_free(sd->defined_properties);
eina_hash_foreach(sd->property_data, _stringshared_keys_free, NULL);
eina_hash_free(sd->property_data);
efl_destructor(efl_super(obj, MY_CLASS));
}
static const Eina_Value_Type *
_efl_model_container_child_property_value_type_get(Eo *obj EINA_UNUSED, Efl_Model_Container_Data *sd, const char *property)
{
Eina_Stringshare *sshared = eina_stringshare_add(property);
Child_Property_Data *cpd = eina_hash_find(sd->property_data, sshared);
eina_stringshare_del(sshared);
if (!cpd)
return NULL;
return cpd->property_type;
}
static Eina_Iterator *
_efl_model_container_child_property_values_get(Eo *obj EINA_UNUSED, Efl_Model_Container_Data *sd, const char *property)
{
Eina_Stringshare *sshared = eina_stringshare_add(property);
Child_Property_Data *cpd = eina_hash_find(sd->property_data, sshared);
eina_stringshare_del(sshared);
if (!cpd)
return NULL;
return eina_array_iterator_new(cpd->property_values);
}
static Eina_Bool
_efl_model_container_child_property_add(Eo *obj, Efl_Model_Container_Data *sd, const char *name, const Eina_Value_Type *type, Eina_Iterator *values)
{
Eina_Array *arr = NULL;
void *data = NULL;
Eina_Stringshare *prop_name = NULL;
Child_Property_Data *cpd = NULL;
unsigned int i, in_count, children_count;
if (!type || !values)
{
EINA_LOG_WARN("Invalid input data");
eina_error_set(EFL_MODEL_ERROR_INCORRECT_VALUE);
return EINA_FALSE;
}
arr = eina_array_new(32);
if (!arr)
{
eina_error_set(EFL_MODEL_ERROR_UNKNOWN);
return EINA_FALSE;
}
EINA_ITERATOR_FOREACH(values, data)
{
void *new_data = _value_copy_alloc(data, type);
if ((data && !new_data) || !eina_array_push(arr, new_data))
{
if (new_data)
_value_free(new_data, type);
goto error;
}
}
eina_iterator_free(values);
prop_name = eina_stringshare_add(name);
cpd = eina_hash_find(sd->property_data, prop_name);
if (!cpd)
{
cpd = calloc(1, sizeof(Child_Property_Data));
if (!cpd)
goto error;
cpd->property_type = type;
cpd->property_values = arr;
if (!eina_array_push(sd->defined_properties, prop_name))
goto error;
if (!eina_hash_direct_add(sd->property_data, prop_name, cpd))
{
eina_array_pop(sd->defined_properties);
goto error;
}
}
else
{
eina_stringshare_del(prop_name);
_values_free(cpd->property_values, cpd->property_type);
cpd->property_type = type;
cpd->property_values = arr;
}
in_count = eina_array_count(arr);
children_count = eina_list_count(sd->children);
for (i = children_count; i < in_count; ++i)
{
Efl_Model_Children_Event cevt;
Efl_Model *child;
child = efl_add(EFL_MODEL_CONTAINER_ITEM_CLASS, obj,
efl_model_container_item_define(efl_added, sd, i));
sd->children = eina_list_append(sd->children, child);
cevt.child = child;
cevt.index = i;
efl_event_callback_call(obj, EFL_MODEL_EVENT_CHILD_ADDED, &cevt);
}
if (in_count > children_count)
efl_event_callback_call(obj, EFL_MODEL_EVENT_CHILDREN_COUNT_CHANGED, &in_count);
return EINA_TRUE;
error:
if (prop_name)
eina_stringshare_del(prop_name);
if (cpd)
free(cpd);
if (arr)
_values_free(arr, type);
eina_error_set(EFL_MODEL_ERROR_UNKNOWN);
return EINA_FALSE;
}
static const Eina_Array *
_efl_model_container_efl_model_properties_get(Eo *obj EINA_UNUSED, Efl_Model_Container_Data *sd EINA_UNUSED)
{
return sd->defined_properties;
}
Efl_Future *
_efl_model_container_efl_model_property_set(Eo *obj EINA_UNUSED, Efl_Model_Container_Data *sd EINA_UNUSED, const char *property EINA_UNUSED, const Eina_Value *value EINA_UNUSED)
{
Efl_Promise *promise = efl_add(EFL_PROMISE_CLASS, ecore_main_loop_get());
Efl_Future* future = efl_promise_future_get(promise);
efl_promise_failed_set(promise, EFL_MODEL_ERROR_NOT_FOUND);
return future;
}
Efl_Future *
_efl_model_container_efl_model_property_get(Eo *obj EINA_UNUSED, Efl_Model_Container_Data *sd EINA_UNUSED, const char *property EINA_UNUSED)
{
Efl_Promise *promise = efl_add(EFL_PROMISE_CLASS, ecore_main_loop_get());
Efl_Future* future = efl_promise_future_get(promise);
efl_promise_failed_set(promise, EFL_MODEL_ERROR_NOT_FOUND);
return future;
}
static Efl_Future *
_efl_model_container_efl_model_children_slice_get(Eo *obj EINA_UNUSED, Efl_Model_Container_Data *sd, unsigned int start, unsigned int count)
{
Efl_Promise *promise = efl_add(EFL_PROMISE_CLASS, ecore_main_loop_get());
Efl_Future* future = efl_promise_future_get(promise);
Eina_Accessor* accessor = efl_model_list_slice(sd->children, start, count);
efl_promise_value_set(promise, accessor, (Eina_Free_Cb)&eina_accessor_free);
return future;
}
static Efl_Future *
_efl_model_container_efl_model_children_count_get(Eo *obj EINA_UNUSED, Efl_Model_Container_Data *sd)
{
Efl_Promise *promise = efl_add(EFL_PROMISE_CLASS, ecore_main_loop_get());
Efl_Future* future = efl_promise_future_get(promise);
unsigned int *count = calloc(1, sizeof(unsigned int));
*count = eina_list_count(sd->children);
efl_promise_value_set(promise, count, &free);
return future;
}
static Eo *
_efl_model_container_efl_model_child_add(Eo *obj EINA_UNUSED, Efl_Model_Container_Data *sd EINA_UNUSED)
{
EINA_LOG_WARN("child_add not supported by Efl.Model.Container");
eina_error_set(EFL_MODEL_ERROR_NOT_SUPPORTED);
return NULL;
}
static void
_efl_model_container_efl_model_child_del(Eo *obj EINA_UNUSED, Efl_Model_Container_Data *sd EINA_UNUSED, Eo *child EINA_UNUSED)
{
EINA_LOG_WARN("child_del not supported by Efl.Model.Container");
eina_error_set(EFL_MODEL_ERROR_NOT_SUPPORTED);
}
#include "efl_model_container.eo.c"

View File

@ -0,0 +1,60 @@
import eina_types;
class Efl.Model.Container (Efl.Object, Efl.Model)
{
[[
Class used to create data models from Eina containers.
Each container supplied represent a series of property values, each item
being the property value for a child object (@Efl.Model.Container.Item).
The data in the given containers are copied and stored internally.
Several containers can be supplied, and the number of allocated children is
based on the container with the biggest size.
]]
methods {
child_property_value_type_get {
[[Get the type of the given property.]]
params {
name: string; [[Property name]]
}
return: ptr(const(Eina.Value.Type)); [[Property type]]
}
child_property_values_get {
[[Get the values for the given property.]]
params {
name: string; [[Property name]]
}
return: free(own(iterator<void_ptr>), eina_iterator_free) @warn_unused;
[[The currently wrapped values]]
}
child_property_add {
[[Add the given property to child objects and supply the values.
Each item will represent the value of the given property in the
respective child within the data model.
New children objects are allocated as necessary.
Value type is required for compatibility with the @Efl.Model API.]]
params {
name: string; [[Property name]]
type: ptr(const(Eina.Value.Type)); [[Property type]]
values: own(iterator<const(void_ptr)>); [[Values to be added]]
}
return: bool; [[$true on success, $false otherwise]]
}
}
implements {
Efl.Object.constructor;
Efl.Object.destructor;
Efl.Model.properties { get; }
Efl.Model.property_set;
Efl.Model.property_get;
Efl.Model.child_add;
Efl.Model.child_del;
Efl.Model.children_slice_get;
Efl.Model.children_count_get;
}
}

View File

@ -0,0 +1,192 @@
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <Efl.h>
#include <Ecore.h>
#include "efl_model_container_private.h"
#define MY_CLASS EFL_MODEL_CONTAINER_ITEM_CLASS
static void
_item_value_free_cb(void *data)
{
eina_value_free(data);
}
EOLIAN static void
_efl_model_container_item_define(Eo *obj EINA_UNUSED, Efl_Model_Container_Item_Data *sd, void *parent_data, unsigned int index)
{
sd->parent_data = parent_data;
sd->index = index;
}
EOLIAN static void
_efl_model_container_item_invalidate(Eo *obj EINA_UNUSED, Efl_Model_Container_Item_Data *sd)
{
sd->parent_data = NULL;
sd->index = 0;
}
EOLIAN static const Eina_Array *
_efl_model_container_item_efl_model_properties_get(Eo *obj EINA_UNUSED, Efl_Model_Container_Item_Data *sd)
{
if (!sd->parent_data)
return NULL;
return sd->parent_data->defined_properties;
}
Efl_Future *
_efl_model_container_item_efl_model_property_set(Eo *obj EINA_UNUSED, Efl_Model_Container_Item_Data *sd, const char *property, const Eina_Value *value)
{
Eina_Stringshare *prop_name;
Child_Property_Data *cpd;
void *data, *new_data;
Efl_Promise *promise = efl_add(EFL_PROMISE_CLASS, ecore_main_loop_get());
Efl_Future* future = efl_promise_future_get(promise);
if (!sd->parent_data)
{
efl_promise_failed_set(promise, EFL_MODEL_ERROR_INVALID_OBJECT);
return future;
}
prop_name = eina_stringshare_add(property);
cpd = eina_hash_find(sd->parent_data->property_data, prop_name);
eina_stringshare_del(prop_name);
if (!cpd || !cpd->property_values ||
sd->index >= eina_array_count_get(cpd->property_values))
{
efl_promise_failed_set(promise, EFL_MODEL_ERROR_NOT_FOUND);
return future;
}
if (cpd->property_type != eina_value_type_get(value))
{
efl_promise_failed_set(promise, EFL_MODEL_ERROR_INCORRECT_VALUE);
return future;
}
data = calloc(1, cpd->property_type->value_size);
if (!data || !eina_value_pget(value, data))
{
if (data)
free(data);
efl_promise_failed_set(promise, EFL_MODEL_ERROR_UNKNOWN);
return future;
}
new_data = _value_copy_alloc(data, cpd->property_type);
free(data);
_value_free(eina_array_data_get(cpd->property_values, sd->index), cpd->property_type);
eina_array_data_set(cpd->property_values, sd->index, new_data);
{
Eina_Value *v = eina_value_new(cpd->property_type);
if (v && eina_value_copy(value, v))
efl_promise_value_set(promise, v, _item_value_free_cb);
else
{
if (v)
eina_value_free(v);
efl_promise_failed_set(promise, EFL_MODEL_ERROR_UNKNOWN);
}
}
return future;
}
Efl_Future *
_efl_model_container_item_efl_model_property_get(Eo *obj EINA_UNUSED, Efl_Model_Container_Item_Data *sd, const char *property)
{
Eina_Stringshare *prop_name;
Child_Property_Data *cpd;
Eina_Value *value;
Efl_Promise *promise = efl_add(EFL_PROMISE_CLASS, ecore_main_loop_get());
Efl_Future* future = efl_promise_future_get(promise);
if (!sd->parent_data)
{
efl_promise_failed_set(promise, EFL_MODEL_ERROR_INVALID_OBJECT);
return future;
}
prop_name = eina_stringshare_add(property);
cpd = eina_hash_find(sd->parent_data->property_data, prop_name);
eina_stringshare_del(prop_name);
if (!cpd || !cpd->property_values ||
sd->index >= eina_array_count_get(cpd->property_values))
{
efl_promise_failed_set(promise, EFL_MODEL_ERROR_NOT_FOUND);
return future;
}
value = eina_value_new(cpd->property_type);
if (!value)
efl_promise_failed_set(promise, EFL_MODEL_ERROR_UNKNOWN);
else
{
Eina_Bool r = EINA_FALSE;
void *data = eina_array_data_get(cpd->property_values, sd->index);
if (cpd->property_type == EINA_VALUE_TYPE_STRINGSHARE ||
cpd->property_type == EINA_VALUE_TYPE_STRING)
r = eina_value_set(value, data);
else
r = eina_value_pset(value, data);
if (r)
efl_promise_value_set(promise, value, _item_value_free_cb);
else
{
efl_promise_failed_set(promise, EFL_MODEL_ERROR_UNKNOWN);
eina_value_free(value);
}
}
return future;
}
EOLIAN static Efl_Future *
_efl_model_container_item_efl_model_children_slice_get(Eo *obj EINA_UNUSED, Efl_Model_Container_Item_Data *sd EINA_UNUSED, unsigned int start EINA_UNUSED, unsigned int count EINA_UNUSED)
{
Efl_Promise *promise = efl_add(EFL_PROMISE_CLASS, ecore_main_loop_get());
Efl_Future* future = efl_promise_future_get(promise);
efl_promise_value_set(promise, NULL, NULL);
return future;
}
EOLIAN static Efl_Future *
_efl_model_container_item_efl_model_children_count_get(Eo *obj EINA_UNUSED, Efl_Model_Container_Item_Data *sd EINA_UNUSED)
{
Efl_Promise *promise = efl_add(EFL_PROMISE_CLASS, ecore_main_loop_get());
Efl_Future* future = efl_promise_future_get(promise);
unsigned int *count = calloc(1, sizeof(unsigned int));
*count = 0;
efl_promise_value_set(promise, count, &free);
return future;
}
EOLIAN static Eo *
_efl_model_container_item_efl_model_child_add(Eo *obj EINA_UNUSED, Efl_Model_Container_Item_Data *sd EINA_UNUSED)
{
EINA_LOG_WARN("child_add not supported by Efl.Model.Container.Item");
eina_error_set(EFL_MODEL_ERROR_NOT_SUPPORTED);
return NULL;
}
EOLIAN static void
_efl_model_container_item_efl_model_child_del(Eo *obj EINA_UNUSED, Efl_Model_Container_Item_Data *sd EINA_UNUSED, Eo *child EINA_UNUSED)
{
EINA_LOG_WARN("child_del not supported by Efl.Model.Container.Item");
eina_error_set(EFL_MODEL_ERROR_NOT_SUPPORTED);
}
#include "efl_model_container_item.eo.c"

View File

@ -0,0 +1,39 @@
import eina_types;
class Efl.Model.Container.Item (Efl.Object, Efl.Model)
{
[[
Used as a child of @Efl.Model.Container.
Provides the @Efl.Model API for elements of @Efl.Model.Container.
Should not be used in another context, so do not manually create objects
of this class.
]]
methods {
define {
[[Define @Efl.Model.Container.Item internal data.]]
params {
parent_data: void_ptr; [[Pointer to the private data of the
@Efl.Model.Container parent object.]]
index: uint; [[Index of this item within the @Efl.Model.Container
children.]]
}
}
invalidate {
[[Invalidate the object preventing it from using the given parent
data.]]
}
}
implements {
Efl.Model.properties { get; }
Efl.Model.property_set;
Efl.Model.property_get;
Efl.Model.child_add;
Efl.Model.child_del;
Efl.Model.children_slice_get;
Efl.Model.children_count_get;
}
constructors {
.define;
}
}

View File

@ -0,0 +1,32 @@
#ifndef EFL_MODEL_PRIVATE_H__
# define EFL_MODEL_PRIVATE_H__
typedef struct _Child_Property_Data Child_Property_Data;
struct _Child_Property_Data
{
const Eina_Value_Type *property_type;
Eina_Array *property_values;
};
typedef struct _Efl_Model_Container_Data Efl_Model_Container_Data;
struct _Efl_Model_Container_Data
{
Eo *obj;
Eina_Hash *property_data;
Eina_Array *defined_properties;
Eina_List *children;
};
typedef struct _Efl_Model_Container_Item_Data Efl_Model_Container_Item_Data;
struct _Efl_Model_Container_Item_Data
{
Efl_Model_Container_Data *parent_data;
unsigned int index;
};
void *_value_copy_alloc(void *v, const Eina_Value_Type *type);
void _value_free(void *v, const Eina_Value_Type *type);
#endif

View File

@ -0,0 +1,202 @@
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <Efl.h>
#include <Ecore.h>
#define MY_CLASS EFL_MODEL_ITEM_CLASS
typedef struct _Efl_Model_Item_Data Efl_Model_Item_Data;
struct _Efl_Model_Item_Data
{
Eina_Hash *properties;
Eina_Array *defined_properties;
Eina_List *children;
};
static void
_item_value_free_cb(void *data)
{
eina_value_free(data);
}
static Eina_Bool
_stringshared_keys_free(const Eina_Hash *hash EINA_UNUSED, const void *key, void *data EINA_UNUSED, void *fdata EINA_UNUSED)
{
eina_stringshare_del(key);
return EINA_TRUE;
}
static Efl_Object *
_efl_model_item_efl_object_constructor(Eo *obj, Efl_Model_Item_Data *sd)
{
obj = efl_constructor(efl_super(obj, MY_CLASS));
if (!obj)
return NULL;
sd->properties = eina_hash_stringshared_new(_item_value_free_cb);
sd->defined_properties = eina_array_new(8);
return obj;
}
static void
_efl_model_item_efl_object_destructor(Eo *obj, Efl_Model_Item_Data *sd)
{
Efl_Model *child;
EINA_LIST_FREE(sd->children, child)
{
if (child)
efl_parent_set(child, NULL);
}
eina_hash_foreach(sd->properties, _stringshared_keys_free, NULL);
eina_hash_free(sd->properties);
eina_array_free(sd->defined_properties);
efl_destructor(efl_super(obj, MY_CLASS));
}
EOLIAN static const Eina_Array *
_efl_model_item_efl_model_properties_get(Eo *obj EINA_UNUSED, Efl_Model_Item_Data *sd)
{
return sd->defined_properties;
}
static Efl_Future*
_efl_model_item_efl_model_property_set(Eo *obj EINA_UNUSED, Efl_Model_Item_Data *sd, const char *property, const Eina_Value *value)
{
Efl_Promise *promise = efl_add(EFL_PROMISE_CLASS, ecore_main_loop_get());
Efl_Future* future = efl_promise_future_get(promise);
Eina_Stringshare *sshared = eina_stringshare_add(property);
Eina_Value *p_v = eina_hash_find(sd->properties, sshared);
if (p_v)
{
eina_stringshare_del(sshared);
if (!eina_value_copy(value, p_v))
goto err1;
}
else
{
if (!eina_array_push(sd->defined_properties, sshared))
goto err2;
p_v = eina_value_new(eina_value_type_get(value));
if (!p_v)
goto err3;
if (!eina_value_copy(value, p_v) ||
!eina_hash_direct_add(sd->properties, sshared, p_v))
goto err4;
}
efl_promise_value_set(promise, p_v, NULL);
return future;
err4:
eina_value_free(p_v);
err3:
eina_array_pop(sd->defined_properties);
err2:
eina_stringshare_del(sshared);
err1:
efl_promise_failed_set(promise, EFL_MODEL_ERROR_UNKNOWN);
return future;
}
static Efl_Future *
_efl_model_item_efl_model_property_get(Eo *obj EINA_UNUSED, Efl_Model_Item_Data *sd, const char *property)
{
Efl_Promise *promise = efl_add(EFL_PROMISE_CLASS, ecore_main_loop_get());
Efl_Future *rfuture = efl_promise_future_get(promise);
Eina_Stringshare *sshare = eina_stringshare_add(property);
Eina_Value *p_v = eina_hash_find(sd->properties, sshare);
eina_stringshare_del(sshare);
if (p_v)
efl_promise_value_set(promise, p_v, NULL);
else
efl_promise_failed_set(promise, EFL_MODEL_ERROR_NOT_FOUND);
return rfuture;
}
static Efl_Future *
_efl_model_item_efl_model_children_slice_get(Eo *obj EINA_UNUSED, Efl_Model_Item_Data *sd, unsigned int start, unsigned int count)
{
Efl_Promise *promise = efl_add(EFL_PROMISE_CLASS, ecore_main_loop_get());
Efl_Future *rfuture = efl_promise_future_get(promise);
Eina_Accessor* accessor = efl_model_list_slice(sd->children, start, count);
efl_promise_value_set(promise, accessor, (Eina_Free_Cb)&eina_accessor_free);
return rfuture;
}
static Efl_Future *
_efl_model_item_efl_model_children_count_get(Eo *obj EINA_UNUSED, Efl_Model_Item_Data *sd)
{
Efl_Promise *promise = efl_add(EFL_PROMISE_CLASS, ecore_main_loop_get());
Efl_Future *rfuture = efl_promise_future_get(promise);
unsigned int *count = calloc(1, sizeof(unsigned int));
*count = eina_list_count(sd->children);
efl_promise_value_set(promise, count, &free);
return rfuture;
}
static Eo *
_efl_model_item_efl_model_child_add(Eo *obj, Efl_Model_Item_Data *sd)
{
Efl_Model_Children_Event cevt;
Efl_Model *child = efl_add(EFL_MODEL_ITEM_CLASS, obj);
if (!child)
{
EINA_LOG_ERR("Could not allocate Efl.Model.Item");
eina_error_set(EFL_MODEL_ERROR_UNKNOWN);
return NULL;
}
sd->children = eina_list_append(sd->children, child);
cevt.child = child;
cevt.index = eina_list_count(sd->children);
efl_event_callback_call(obj, EFL_MODEL_EVENT_CHILD_ADDED, &cevt);
efl_event_callback_call(obj, EFL_MODEL_EVENT_CHILDREN_COUNT_CHANGED, &cevt.index);
return child;
}
static void
_efl_model_item_efl_model_child_del(Eo *obj, Efl_Model_Item_Data *sd, Eo *child)
{
Eina_List *l;
Efl_Model *data;
unsigned int i = 0;
EINA_LIST_FOREACH(sd->children, l, data)
{
if (data == child)
{
Efl_Model_Children_Event cevt;
sd->children = eina_list_remove_list(sd->children, l);
cevt.child = efl_ref(child);
cevt.index = i;
efl_parent_set(child, NULL);
efl_event_callback_call(obj, EFL_MODEL_EVENT_CHILD_REMOVED, &cevt);
efl_unref(child);
i = eina_list_count(sd->children);
efl_event_callback_call(obj, EFL_MODEL_EVENT_CHILDREN_COUNT_CHANGED, &i);
break;
}
++i;
}
}
#include "efl_model_item.eo.c"

View File

@ -0,0 +1,26 @@
import eina_types;
class Efl.Model.Item (Efl.Object, Efl.Model)
{
[[
Generic model that allows any property to be manually set.
Also children of the same type can be added and deleted.
Intended to be used in scenarios where the user needs a manually defined
data model, like in tests.
It does not model anything in particular and does not affect anything else
in the system.
]]
implements {
Efl.Object.constructor;
Efl.Object.destructor;
Efl.Model.properties { get; }
Efl.Model.property_set;
Efl.Model.property_get;
Efl.Model.child_add;
Efl.Model.child_del;
Efl.Model.children_slice_get;
Efl.Model.children_count_get;
}
}

View File

@ -120,6 +120,11 @@ EAPI extern const Efl_Event_Description _EFL_GFX_PATH_CHANGED;
#include "interfaces/efl_canvas.eo.h"
#include "interfaces/efl_ui_view.eo.h"
#include "interfaces/efl_ui_model_connect.eo.h"
#include "interfaces/efl_ui_factory.eo.h"
#include "interfaces/efl_ui_model_factory_connect.eo.h"
/* Packing & containers */
#include "interfaces/efl_container.eo.h"
#include "interfaces/efl_pack.eo.h"

View File

@ -10,6 +10,7 @@ EAPI extern Eina_Error EFL_MODEL_ERROR_READ_ONLY;
EAPI extern Eina_Error EFL_MODEL_ERROR_INIT_FAILED;
EAPI extern Eina_Error EFL_MODEL_ERROR_INCORRECT_VALUE;
EAPI extern Eina_Error EFL_MODEL_ERROR_PERMISSION_DENIED;
EAPI extern Eina_Error EFL_MODEL_ERROR_INVALID_OBJECT;
/**
* @struct _Efl_Model_Children_Event

View File

@ -55,6 +55,10 @@ EAPI const Efl_Event_Description _EFL_GFX_PATH_CHANGED =
#include "interfaces/efl_ui_progress.eo.c"
#include "interfaces/efl_ui_menu.eo.c"
#include "interfaces/efl_ui_item.eo.c"
#include "interfaces/efl_ui_view.eo.c"
#include "interfaces/efl_ui_model_connect.eo.c"
#include "interfaces/efl_ui_factory.eo.c"
#include "interfaces/efl_ui_model_factory_connect.eo.c"
EAPI void
__efl_internal_init(void)

View File

@ -12,6 +12,7 @@ EAPI Eina_Error EFL_MODEL_ERROR_READ_ONLY = 0;
EAPI Eina_Error EFL_MODEL_ERROR_INIT_FAILED = 0;
EAPI Eina_Error EFL_MODEL_ERROR_PERMISSION_DENIED = 0;
EAPI Eina_Error EFL_MODEL_ERROR_INCORRECT_VALUE = 0;
EAPI Eina_Error EFL_MODEL_ERROR_INVALID_OBJECT = 0;
static const char EFL_MODEL_ERROR_UNKNOWN_STR[] = "Unknown Error";
static const char EFL_MODEL_ERROR_NOT_SUPPORTED_STR[] = "Operation not supported";
@ -20,6 +21,8 @@ static const char EFL_MODEL_ERROR_READ_ONLY_STR[] = "Value read only";
static const char EFL_MODEL_ERROR_INIT_FAILED_STR[] = "Init failed";
static const char EFL_MODEL_ERROR_PERMISSION_DENIED_STR[] = "Permission denied";
static const char EFL_MODEL_ERROR_INCORRECT_VALUE_STR[] = "Incorrect value";
static const char EFL_MODEL_ERROR_INVALID_OBJECT_STR[] = "Object is invalid";
EAPI int
efl_model_init(void)
@ -45,6 +48,9 @@ efl_model_init(void)
EFL_MODEL_ERROR_PERMISSION_DENIED = eina_error_msg_static_register(
EFL_MODEL_ERROR_PERMISSION_DENIED_STR);
EFL_MODEL_ERROR_INVALID_OBJECT = eina_error_msg_static_register(
EFL_MODEL_ERROR_INVALID_OBJECT_STR);
return EINA_TRUE;
}

View File

@ -0,0 +1,19 @@
interface Efl.Ui.Factory (Efl.Ui.Model.Connect)
{
methods {
create {
[[Create a UI object from the necessary properties in the specified model.]]
params {
model: Efl.Model;
parent: Efl.Canvas;
}
return: Efl.Canvas;
}
release {
[[Release a UI object and disconnec from models.]]
params {
ui_view: Efl.Canvas;
}
}
}
}

View File

@ -0,0 +1,11 @@
interface Efl.Ui.Model.Connect
{
methods {
connect {
params {
name: string;
property: string;
}
}
}
}

View File

@ -0,0 +1,11 @@
interface Efl.Ui.Model.Factory.Connect
{
methods {
connect {
params {
name: string;
factory: Efl.Ui.Factory;
}
}
}
}

View File

@ -0,0 +1,12 @@
interface Efl.Ui.View ()
{
methods {
@property model {
[[Model that is/will be ]]
get {} set {}
values {
model: Efl.Model;
}
}
}
}

View File

@ -265,6 +265,7 @@ EAPI extern Elm_Version *elm_version;
# include <efl_ui_text.eo.h>
# include <efl_ui_text_editable.eo.h>
# include <efl_ui_clock.eo.h>
# include <efl_ui_image_factory.eo.h>
#endif
/* include deprecated calls last of all */

View File

@ -47,6 +47,8 @@ static const Evas_Smart_Cb_Description _smart_callbacks[] = {
static Eina_Bool _key_action_activate(Evas_Object *obj, const char *params);
static Eina_Bool _efl_ui_image_smart_internal_file_set(Eo *obj, Efl_Ui_Image_Data *sd, const char *file, const Eina_File *f, const char *key);
static void _efl_ui_image_remote_copier_cancel(Eo *obj, Efl_Ui_Image_Data *sd);
void _efl_ui_image_sizing_eval(Evas_Object *obj);
static void _efl_ui_image_model_properties_changed_cb(void *data, const Efl_Event *event);
static const Elm_Action key_actions[] = {
{"activate", _key_action_activate},
@ -566,6 +568,21 @@ _efl_ui_image_efl_canvas_group_group_del(Eo *obj, Efl_Ui_Image_Data *sd)
if (sd->remote.copier) _efl_ui_image_remote_copier_cancel(obj, sd);
if (sd->remote.binbuf) ELM_SAFE_FREE(sd->remote.binbuf, eina_binbuf_free);
ELM_SAFE_FREE(sd->remote.key, eina_stringshare_del);
if (sd->pfuture)
{
efl_future_cancel(sd->pfuture);
sd->pfuture = NULL;
}
if (sd->model)
{
efl_event_callback_del(sd->model, EFL_MODEL_EVENT_PROPERTIES_CHANGED,
_efl_ui_image_model_properties_changed_cb, obj);
efl_unref(sd->model);
sd->model = NULL;
}
efl_canvas_group_del(efl_super(obj, MY_CLASS));
}
@ -1724,6 +1741,187 @@ _efl_ui_image_icon_get(Eo *obj EINA_UNUSED, Efl_Ui_Image_Data *sd)
return sd->stdicon;
}
static void
_prop_future_error_cb(void* data, Efl_Event const* event EINA_UNUSED)
{
Eo *obj = data;
EFL_UI_IMAGE_DATA_GET(obj, pd);
pd->pfuture = NULL;
}
static void
_prop_key_future_then_cb(void* data, Efl_Event const * event)
{
Eo *obj = data;
Eina_Accessor *acc = (Eina_Accessor *)((Efl_Future_Event_Success*)event->info)->value;
Eina_Value *value;
char *filename, *key;
EFL_UI_IMAGE_DATA_GET(obj, pd);
pd->pfuture = NULL;
if (eina_accessor_data_get(acc, 0, (void **)&value) && value)
{
filename = eina_value_to_string(value);
}
else return;
if (eina_accessor_data_get(acc, 1, (void **)&value) && value)
{
key = eina_value_to_string(value);
}
else
{
free(filename);
return;
}
elm_image_file_set(obj, filename, key);
free(filename);
free(key);
}
static void
_prop_future_then_cb(void* data, Efl_Event const * event)
{
Eo *obj = data;
Eina_Value *value = (Eina_Value*)((Efl_Future_Event_Success*)event->info)->value;
char *text;
EFL_UI_IMAGE_DATA_GET(obj, pd);
pd->pfuture = NULL;
const Eina_Value_Type *vtype = eina_value_type_get(value);
if (vtype == EINA_VALUE_TYPE_STRING || vtype == EINA_VALUE_TYPE_STRINGSHARE)
{
eina_value_get(value, &text);
if (pd->con_icon) efl_ui_image_icon_set(obj, text);
else elm_image_file_set(obj, text, NULL);
}
else
{
text = eina_value_to_string(value);
if (pd->con_icon) efl_ui_image_icon_set(obj, text);
else elm_image_file_set(obj, text, NULL);
free(text);
}
}
void
_update_viewmodel(Eo *obj, Efl_Ui_Image_Data *pd)
{
if (pd->model && pd->prop_con)
{
if (pd->pfuture) efl_future_cancel(pd->pfuture);
pd->pfuture = efl_model_property_get(pd->model, pd->prop_con);
if (pd->prop_key)
{
const Eina_Array *properties;
Eina_Array_Iterator it;
char *property;
unsigned int i = 0;
properties = efl_model_properties_get(pd->model);
EINA_ARRAY_ITER_NEXT(properties, i, property, it)
{
if (strcmp(property, pd->prop_key) == 0)
{
Efl_Future *futures[2] = {NULL,};
futures[0] = pd->pfuture;
futures[1] = efl_model_property_get(pd->model, pd->prop_key);
pd->pfuture = efl_future_all(futures[0], futures[1]);
efl_future_then(pd->pfuture, &_prop_key_future_then_cb,
&_prop_future_error_cb, NULL, obj);
return;
}
}
}
efl_future_then(pd->pfuture, &_prop_future_then_cb,
&_prop_future_error_cb, NULL, obj);
}
}
static void
_efl_ui_image_model_properties_changed_cb(void *data, const Efl_Event *event)
{
Efl_Model_Property_Event *evt = event->info;
Eo *obj = data;
EFL_UI_IMAGE_DATA_GET(obj, pd);
if (!evt->changed_properties)
return;
if (pd->model && pd->prop_con)
{
Eina_Array_Iterator it;
const char *prop;
unsigned int i;
EINA_ARRAY_ITER_NEXT(evt->changed_properties, i, prop, it)
{
if (!strcmp(pd->prop_con, prop) || (pd->prop_key && !strcmp(pd->prop_key, prop)))
{
_update_viewmodel(obj, pd);
return;
}
}
}
}
EOLIAN static void
_efl_ui_image_efl_ui_view_model_set(Eo *obj, Efl_Ui_Image_Data *pd, Efl_Model *model)
{
if (pd->model)
{
efl_event_callback_del(pd->model, EFL_MODEL_EVENT_PROPERTIES_CHANGED,
_efl_ui_image_model_properties_changed_cb, obj);
efl_unref(pd->model);
pd->model = NULL;
}
if (model)
{
pd->model = model;
efl_ref(pd->model);
efl_event_callback_add(pd->model, EFL_MODEL_EVENT_PROPERTIES_CHANGED,
_efl_ui_image_model_properties_changed_cb, obj);
}
_update_viewmodel(obj, pd);
}
EOLIAN static Efl_Model *
_efl_ui_image_efl_ui_view_model_get(Eo *obj EINA_UNUSED, Efl_Ui_Image_Data *pd)
{
return pd->model;
}
EOLIAN static void
_efl_ui_image_efl_ui_model_connect_connect(Eo *obj, Efl_Ui_Image_Data *pd, const char *name, const char *property)
{
if (strcmp(name, "filename") == 0)
{
pd->con_icon = EINA_FALSE;
eina_stringshare_replace(&pd->prop_con, property);
}
else if (strcmp(name, "icon") == 0)
{
pd->con_icon = EINA_TRUE;
eina_stringshare_replace(&pd->prop_con, property);
eina_stringshare_replace(&pd->prop_key, NULL);
}
else if (strcmp(name, "key") == 0)
{
eina_stringshare_replace(&pd->prop_key, property);
}
else return;
_update_viewmodel(obj, pd);
}
EAPI void
elm_image_smooth_set(Evas_Object *obj, Eina_Bool smooth)
{

View File

@ -45,7 +45,8 @@ struct Efl.Ui.Image.Error
class Efl.Ui.Image (Elm.Widget, Efl.Ui.Clickable, Efl.Ui.Draggable,
Efl.File, Efl.Image, Efl.Image.Load, Efl.Player, Efl.Gfx.View,
Elm.Interface.Atspi_Image, Elm.Interface.Atspi_Widget_Action,
Edje.Object, Efl.Orientation, Efl.Flipable)
Edje.Object, Efl.Orientation, Efl.Flipable,
Efl.Ui.View, Efl.Ui.Model.Connect)
{
[[ Efl UI image class]]
event_prefix: efl_ui_image;
@ -143,6 +144,8 @@ class Efl.Ui.Image (Elm.Widget, Efl.Ui.Clickable, Efl.Ui.Draggable,
Efl.Canvas.Group.group_del;
Efl.Canvas.Group.group_member_add;
Efl.Ui.Draggable.drag_target { get; set; }
Efl.Ui.Model.Connect.connect;
Efl.Ui.View.model { get; set; }
Elm.Widget.theme_apply;
Elm.Widget.widget_event;
Elm.Interface.Atspi_Image.extents { get; }

View File

@ -0,0 +1,59 @@
#ifdef HAVE_CONFIG_H
# include "elementary_config.h"
#endif
#include <Elementary.h>
#include "elm_priv.h"
#define MY_CLASS EFL_UI_IMAGE_FACTORY_CLASS
#define MY_CLASS_NAME "Efl.Ui.Image_Factory"
typedef struct _Efl_Ui_Image_Factory_Data
{
Eina_Stringshare *property;
} Efl_Ui_Image_Factory_Data;
EOLIAN static Eo *
_efl_ui_image_factory_efl_object_constructor(Eo *obj, Efl_Ui_Image_Factory_Data *pd)
{
obj = efl_constructor(efl_super(obj, MY_CLASS));
pd->property = NULL;
return obj;
}
EOLIAN static void
_efl_ui_image_factory_efl_object_destructor(Eo *obj EINA_UNUSED, Efl_Ui_Image_Factory_Data *pd)
{
eina_stringshare_del(pd->property);
pd->property = NULL;
efl_destructor(efl_super(obj, MY_CLASS));
}
EOLIAN static Efl_Canvas *
_efl_ui_image_factory_efl_ui_factory_create(Eo *obj EINA_UNUSED, Efl_Ui_Image_Factory_Data *pd, Efl_Model *model, Efl_Canvas *parent)
{
EINA_SAFETY_ON_NULL_RETURN_VAL(pd->property, NULL);
EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
Efl_Canvas *ui_view = efl_add(EFL_UI_IMAGE_CLASS, parent);
efl_ui_view_model_set(ui_view, model);
efl_ui_model_connect(ui_view, "filename", pd->property);
return ui_view;
}
EOLIAN static void
_efl_ui_image_factory_efl_ui_factory_release(Eo *obj EINA_UNUSED, Efl_Ui_Image_Factory_Data *pd EINA_UNUSED, Efl_Canvas *ui_view)
{
efl_parent_set(ui_view, NULL);
}
EOLIAN static void
_efl_ui_image_factory_efl_ui_model_connect_connect(Eo *obj EINA_UNUSED, Efl_Ui_Image_Factory_Data *pd, const char *name EINA_UNUSED, const char *property)
{
eina_stringshare_replace(&pd->property, property);
}
#include "efl_ui_image_factory.eo.c"

View File

@ -0,0 +1,10 @@
class Efl.Ui.Image.Factory (Efl.Object, Efl.Ui.Factory)
{
implements {
Efl.Object.constructor;
Efl.Object.destructor;
Efl.Ui.Factory.create;
Efl.Ui.Factory.release;
Efl.Ui.Model.Connect.connect;
}
}

View File

@ -80,6 +80,10 @@ struct _Efl_Ui_Image_Data
const char *stdicon;
Efl_Model *model;
Efl_Future *pfuture;
Eina_Stringshare *prop_con;
Eina_Stringshare *prop_key;
struct {
int requested_size;
@ -98,6 +102,7 @@ struct _Efl_Ui_Image_Data
Eina_Bool async_enable : 1;
Eina_Bool scale_up : 1;
Eina_Bool scale_down : 1;
Eina_Bool con_icon : 1;
};
/**

View File

@ -22,11 +22,14 @@
#define MY_CLASS_NAME_LEGACY "elm_layout"
Eo *_elm_layout_pack_proxy_get(Elm_Layout *obj, Edje_Part_Type type, const char *part);
static void _efl_model_properties_changed_cb(void *, const Efl_Event *);
static const char SIG_THEME_CHANGED[] = "theme,changed";
const char SIG_LAYOUT_FOCUSED[] = "focused";
const char SIG_LAYOUT_UNFOCUSED[] = "unfocused";
const char SIGNAL_PREFIX[] = "signal/";
/* smart callbacks coming from elm layout objects: */
static const Evas_Smart_Cb_Description _smart_callbacks[] = {
{SIG_THEME_CHANGED, ""},
@ -106,6 +109,13 @@ struct _Elm_Layout_Sub_Object_Cursor
Eina_Bool engine_only : 1;
};
typedef struct _Elm_Layout_Sub_Property_Future Elm_Layout_Sub_Property_Future;
struct _Elm_Layout_Sub_Property_Future
{
Elm_Layout_Smart_Data *pd;
Eina_Array *name_arr;
};
static void
_on_sub_object_size_hint_change(void *data,
Evas *e EINA_UNUSED,
@ -793,6 +803,17 @@ _elm_layout_efl_canvas_group_group_del(Eo *obj, Elm_Layout_Smart_Data *sd)
free(esd);
}
if(sd->model)
{
efl_event_callback_del(sd->model, EFL_MODEL_EVENT_PROPERTIES_CHANGED, _efl_model_properties_changed_cb, sd);
efl_unref(sd->model);
sd->model = NULL;
}
eina_hash_free(sd->prop_connect);
sd->prop_connect = NULL;
eina_hash_free(sd->factories);
sd->factories = NULL;
eina_stringshare_del(sd->klass);
eina_stringshare_del(sd->group);
@ -1323,6 +1344,20 @@ _elm_layout_text_set(Eo *obj, Elm_Layout_Smart_Data *sd, const char *part, const
sub_d->obj = _elm_access_edje_object_part_object_register
(obj, elm_layout_edje_get(obj), part);
if (sd->model && !sd->view_updated)
{
Eina_Stringshare *prop = eina_hash_find(sd->prop_connect, sub_d->part);
if (prop)
{
Eina_Value v;
eina_value_setup(&v, EINA_VALUE_TYPE_STRING);
eina_value_set(&v, text);
efl_model_property_set(sd->model, prop, &v);
eina_value_flush(&v);
}
}
sd->view_updated = EINA_FALSE;
return EINA_TRUE;
}
@ -1896,6 +1931,291 @@ _elm_layout_efl_object_dbg_info_get(Eo *eo_obj, Elm_Layout_Smart_Data *_pd EINA_
}
}
static void
_prop_future_error_cb(void* data, Efl_Event const*event EINA_UNUSED)
{
Elm_Layout_Sub_Property_Future *sub_pp = data;
Eina_Array_Iterator iterator;
Eina_Stringshare *name;
unsigned int i = 0;
EINA_ARRAY_ITER_NEXT(sub_pp->name_arr, i, name, iterator)
eina_stringshare_del(name);
eina_array_free(sub_pp->name_arr);
free(sub_pp);
}
static void
_view_update(Elm_Layout_Smart_Data *pd, const char *name, const char *property)
{
const char *source;
Eina_Strbuf *buf;
if (strncmp(SIGNAL_PREFIX, name, sizeof(SIGNAL_PREFIX) -1) != 0)
{
elm_layout_text_set(pd->obj, name, property);
return;
}
ELM_WIDGET_DATA_GET_OR_RETURN(pd->obj, wd);
source = efl_class_name_get(efl_class_get(pd->model));
buf = eina_strbuf_new();
eina_strbuf_append(buf, name);
eina_strbuf_remove(buf, 0, sizeof(SIGNAL_PREFIX)-1);
eina_strbuf_replace_all(buf, "%v", property);
edje_object_signal_emit(wd->resize_obj, eina_strbuf_string_get(buf), source);
eina_strbuf_free(buf);
}
static void
_prop_future_then_cb(void* data, Efl_Event const*event)
{
Elm_Layout_Sub_Property_Future *sub_pp = data;
Elm_Layout_Smart_Data *pd = sub_pp->pd;
Eina_Accessor *value_acc = (Eina_Accessor *)((Efl_Future_Event_Success*)event->info)->value;
Eina_Value *value;
Eina_Stringshare *name;
char *text;
unsigned int i = 0;
unsigned int acc_i = 0;
while (eina_accessor_data_get(value_acc, acc_i, (void **)&value))
{
const Eina_Value_Type *vtype = eina_value_type_get(value);
name = eina_array_data_get(sub_pp->name_arr, i);
pd->view_updated = EINA_TRUE;
if (vtype == EINA_VALUE_TYPE_STRING || vtype == EINA_VALUE_TYPE_STRINGSHARE)
{
eina_value_get(value, &text);
_view_update(pd, name, text);
}
else
{
text = eina_value_to_string(value);
_view_update(pd, name, text);
free(text);
}
eina_stringshare_del(name);
++acc_i;
}
eina_array_free(sub_pp->name_arr);
free(sub_pp);
}
static void
_elm_layout_view_model_update(Elm_Layout_Smart_Data *pd)
{
Elm_Layout_Sub_Property_Future *sub_pp;
Efl_Future **future_arr, **f, *future_all;
Eina_Hash_Tuple *tuple;
Eina_Iterator *it_p;
int size;
if (!pd->prop_connect) return;
size = eina_hash_population(pd->prop_connect);
if (size == 0) return;
future_arr = alloca((size + 1) * sizeof(Efl_Future*));
f = future_arr;
sub_pp = ELM_NEW(Elm_Layout_Sub_Property_Future);
sub_pp->pd = pd;
sub_pp->name_arr = eina_array_new(size);
it_p = eina_hash_iterator_tuple_new(pd->prop_connect);
while (eina_iterator_next(it_p, (void **)&tuple))
{
*f = efl_model_property_get(pd->model, tuple->data);
eina_array_push(sub_pp->name_arr, eina_stringshare_ref(tuple->key));
f++;
}
eina_iterator_free(it_p);
*f = NULL;
future_all = efl_future_iterator_all(eina_carray_iterator_new((void**)future_arr));
efl_future_then(future_all, &_prop_future_then_cb, &_prop_future_error_cb, NULL, sub_pp);
}
static void
_efl_model_properties_changed_cb(void *data, const Efl_Event *event)
{
Elm_Layout_Smart_Data *pd = data;
Efl_Model_Property_Event *evt = event->info;
Eina_Stringshare *ss_prop;
Eina_Hash_Tuple *tuple;
Eina_Array *names, *futures;
Eina_Iterator *it_p;
const char *prop;
Eina_Array_Iterator it;
unsigned int i;
if (!evt->changed_properties || !pd->prop_connect) return;
names = eina_array_new(1);
futures = eina_array_new(1);
EINA_ARRAY_ITER_NEXT(evt->changed_properties, i, prop, it)
{
ss_prop = eina_stringshare_add(prop);
it_p = eina_hash_iterator_tuple_new(pd->prop_connect);
while (eina_iterator_next(it_p, (void **)&tuple))
{
if (tuple->data == ss_prop)
{
eina_array_push(names, eina_stringshare_ref(tuple->key));
eina_array_push(futures, efl_model_property_get(pd->model, prop));
}
}
eina_iterator_free(it_p);
eina_stringshare_del(ss_prop);
}
if (eina_array_count(names))
{
Elm_Layout_Sub_Property_Future *sub_pp;
Efl_Future *future_all;
sub_pp = ELM_NEW(Elm_Layout_Sub_Property_Future);
sub_pp->pd = pd;
sub_pp->name_arr = names;
future_all = efl_future_iterator_all(eina_array_iterator_new(futures));
efl_future_then(future_all, &_prop_future_then_cb, &_prop_future_error_cb, NULL, sub_pp);
}
else
eina_array_free(names);
eina_array_free(futures);
}
EOLIAN static void
_elm_layout_efl_ui_view_model_set(Eo *obj EINA_UNUSED, Elm_Layout_Smart_Data *pd, Efl_Model *model)
{
if (pd->model)
{
efl_event_callback_del(pd->model, EFL_MODEL_EVENT_PROPERTIES_CHANGED, _efl_model_properties_changed_cb, pd);
efl_unref(pd->model);
pd->model = NULL;
}
if (model)
{
pd->model = model;
efl_ref(pd->model);
efl_event_callback_add(pd->model, EFL_MODEL_EVENT_PROPERTIES_CHANGED, _efl_model_properties_changed_cb, pd);
}
if (pd->prop_connect)
_elm_layout_view_model_update(pd);
if (pd->factories)
{
Eina_Hash_Tuple *tuple;
Eina_Stringshare *name;
Efl_Ui_Factory *factory;
Efl_Canvas *content;
Eina_Iterator *it_p = eina_hash_iterator_tuple_new(pd->factories);
while (eina_iterator_next(it_p, (void **)&tuple))
{
name = tuple->key;
factory = tuple->data;
content = elm_layout_content_get(pd->obj, name);
if (content && efl_isa(content, EFL_UI_VIEW_INTERFACE))
{
efl_ui_view_model_set(content, pd->model);
}
else
{
efl_ui_factory_release(factory, content);
content = efl_ui_factory_create(factory, pd->model, pd->obj);
elm_layout_content_set(pd->obj, name, content);
}
}
eina_iterator_free(it_p);
}
}
EOLIAN static Efl_Model *
_elm_layout_efl_ui_view_model_get(Eo *obj EINA_UNUSED, Elm_Layout_Smart_Data *pd)
{
return pd->model;
}
EOLIAN static void
_elm_layout_efl_ui_model_connect_connect(Eo *obj EINA_UNUSED, Elm_Layout_Smart_Data *pd, const char *name, const char *property)
{
EINA_SAFETY_ON_NULL_RETURN(name);
Eina_Stringshare *ss_name, *ss_prop;
if (!_elm_layout_part_aliasing_eval(obj, pd, &name, EINA_TRUE))
return;
ss_name = eina_stringshare_add(name);
ss_prop = eina_stringshare_add(property);
if (!pd->prop_connect)
{
pd->prop_connect = eina_hash_stringshared_new(EINA_FREE_CB(eina_stringshare_del));
}
eina_stringshare_del(eina_hash_set(pd->prop_connect, ss_name, ss_prop));
if (pd->model)
{
Elm_Layout_Sub_Property_Future *sub_pp = ELM_NEW(Elm_Layout_Sub_Property_Future);
Efl_Future *futures[2] = {NULL,};
Efl_Future *future_all = NULL;
sub_pp->pd = pd;
sub_pp->name_arr = eina_array_new(1);
eina_array_push(sub_pp->name_arr, eina_stringshare_ref(ss_name));
futures[0] = efl_model_property_get(pd->model, ss_prop);
future_all = efl_future_iterator_all(eina_carray_iterator_new((void**)futures));
efl_future_then(future_all, &_prop_future_then_cb, &_prop_future_error_cb, NULL, sub_pp);
}
}
EOLIAN static void
_elm_layout_efl_ui_model_factory_connect_connect(Eo *obj EINA_UNUSED, Elm_Layout_Smart_Data *pd,
const char *name, Efl_Ui_Factory *factory)
{
EINA_SAFETY_ON_NULL_RETURN(name);
Eina_Stringshare *ss_name;
Efl_Ui_Factory *old_factory;
Evas_Object *new_ev, *old_ev;
if (!_elm_layout_part_aliasing_eval(obj, pd, &name, EINA_TRUE))
return;
ss_name = eina_stringshare_add(name);
if (!pd->factories)
pd->factories = eina_hash_stringshared_new(EINA_FREE_CB(efl_unref));
new_ev = efl_ui_factory_create(factory, pd->model, obj);
EINA_SAFETY_ON_NULL_RETURN(new_ev);
old_factory = eina_hash_set(pd->factories, ss_name, efl_ref(factory));
if (old_factory)
{
old_ev = elm_layout_content_get(obj, name);
if (old_ev)
efl_ui_factory_release(old_factory, old_ev);
efl_unref(old_factory);
}
elm_layout_content_set(obj, name, new_ev);
}
EAPI Evas_Object *
elm_layout_add(Evas_Object *parent)
{

View File

@ -17,7 +17,8 @@ struct Elm.Layout_Part_Alias_Description
real_part: string; [[Target part name for the alias set on Elm.Layout_Part_Proxies_Description::real_part. An example of usage would be "default" on that field, with "elm.content.swallow" on this one]]
}
class Elm.Layout (Elm.Widget, Efl.Part, Efl.Container, Efl.File)
class Elm.Layout (Elm.Widget, Efl.Part, Efl.Container, Efl.File,
Efl.Ui.View, Efl.Ui.Model.Connect, Efl.Ui.Model.Factory.Connect)
{
[[Elementary layout class]]
legacy_prefix: elm_layout;
@ -355,6 +356,9 @@ class Elm.Layout (Elm.Widget, Efl.Part, Efl.Container, Efl.File)
Efl.Container.content { get; set; }
Efl.Container.content_unset;
Efl.Part.part;
Efl.Ui.View.model { get; set; }
Efl.Ui.Model.Connect.connect;
Efl.Ui.Model.Factory.Connect.connect;
}
events {
theme,changed; [[Called when theme changed]]

View File

@ -53,6 +53,9 @@ typedef struct _Elm_Layout_Smart_Data
Eina_List *subs; /**< List of Elm_Layout_Sub_Object_Data structs, to hold the actual sub objects such as text, content and the children of box and table. */
Eina_List *edje_signals; /**< The list of edje signal callbacks. */
Eina_List *parts_cursors; /**< The list of cursor names of layout parts. This is a list of Elm_Layout_Sub_Object_Cursor struct. */
Eina_Hash *prop_connect; /**< The hash of properties connected to layout parts. */
Eina_Hash *factories; /**< The hash with parts connected to factories. */
Efl_Model *model; /**< The model */
const char *klass; /**< 1st identifier of an edje object group which is used in theme_set. klass and group are used together. */
const char *group; /**< 2nd identifier of an edje object group which is used in theme_set. klass and group are used together. */
int frozen; /**< Layout freeze counter */
@ -63,6 +66,7 @@ typedef struct _Elm_Layout_Smart_Data
Eina_Bool can_access : 1; /**< This is true when all text(including textblock) parts can be accessible by accessibility. */
Eina_Bool destructed_is : 1; /**< This flag indicates if Elm_Layout destructor was called. This is needed to avoid unnecessary calculation of subobject deletion during layout object's deletion. */
Eina_Bool file_set : 1; /**< This flag indicates if Elm_Layout source is set from a file*/
Eina_Bool view_updated : 1; /**< This flag indicates to Elm_Layout don't update model in text_set */
} Elm_Layout_Smart_Data;
/**

View File

@ -59,3 +59,5 @@ struct @extern Eina.Rw_Slice {
len: size; [[Length of the memory segment]]
mem: void_ptr; [[Pointer to memory segment]]
}
struct @extern Eina.Value.Type;

51
src/tests/efl/efl_suite.c Normal file
View File

@ -0,0 +1,51 @@
/* EINA - EFL data type library
* Copyright (C) 2008 Cedric Bail
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library;
* if not, see <http://www.gnu.org/licenses/>.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <Eina.h>
#include "efl_suite.h"
#include "../efl_check.h"
static const Efl_Test_Case etc[] = {
{ "Efl_Model_Container", efl_test_case_model_container },
{ NULL, NULL }
};
int
main(int argc, char **argv)
{
int failed_count;
if (!_efl_test_option_disp(argc, argv, etc))
return 0;
putenv("EFL_RUN_IN_TREE=1");
eina_init();
failed_count = _efl_suite_build_and_run(argc - 1, (const char **)argv + 1,
"Efl", etc);
eina_shutdown();
return (failed_count == 0) ? 0 : 255;
}

26
src/tests/efl/efl_suite.h Normal file
View File

@ -0,0 +1,26 @@
/* EFL - EFL library
* Copyright (C) 2008 Cedric Bail
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library;
* if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef EFL_SUITE_H_
#define EFL_SUITE_H_
#include <check.h>
void efl_test_case_model_container(TCase *tc);
#endif /* EFL_SUITE_H_ */

View File

@ -0,0 +1,171 @@
/* EFL - EFL library
* Copyright (C) 2013 Cedric Bail
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library;
* if not, see <http://www.gnu.org/licenses/>.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "efl_suite.h"
#include <Efl.h>
#include <Ecore.h>
typedef struct _Test_Container_Data {
int item_count;
Eina_Bool pass_flag;
Eina_Bool fail_flag;
} Test_Container_Data;
typedef struct _Test_Container_Item_Data {
Test_Container_Data* test_data;
unsigned int index;
} Test_Container_Item_Data;
const int base_int[7] = {10, 11, 12, 13, 14, 0, 16};
const char * const base_str[7] = {"A", "B", "C", "D", "E", "", "GH"};
static void
_future_error_then(void *data EINA_UNUSED, Efl_Event const* event EINA_UNUSED)
{
ck_abort_msg("Promise failed");
}
static void
_container_property_get_then(void *data, Efl_Event const *event)
{
Eina_Accessor *value_itt = (Eina_Accessor*)((Efl_Future_Event_Success*)event->info)->value;
Test_Container_Item_Data *test_item_data = data;
Eina_Value *value_int = NULL;
Eina_Value *value_str = NULL;
int cmp_int = 0;
const char *cmp_str = NULL;
test_item_data->test_data->item_count++;
if (!value_itt || !eina_accessor_data_get(value_itt, 0, (void**)&value_int) ||
!eina_accessor_data_get(value_itt, 1, (void**)&value_str))
{
test_item_data->test_data->fail_flag = EINA_TRUE;
ecore_main_loop_quit();
return;
}
eina_value_get(value_int, &cmp_int);
eina_value_get(value_str, &cmp_str);
if (cmp_int != base_int[test_item_data->index] ||
strcmp(cmp_str, base_str[test_item_data->index]) != 0)
{
test_item_data->test_data->fail_flag = EINA_TRUE;
}
if (test_item_data->test_data->item_count == 7)
{
test_item_data->test_data->pass_flag = EINA_TRUE;
}
ecore_main_loop_quit();
}
static void
_children_slice_future_then(void *data, Efl_Event const *event)
{
Eina_Accessor *children_accessor = (Eina_Accessor *)((Efl_Future_Event_Success*)event->info)->value;
unsigned int i = 0;
Efl_Model *child;
if (children_accessor)
{
EINA_ACCESSOR_FOREACH(children_accessor, i, child)
{
Efl_Future *futures[3] = {NULL,};
Efl_Future *future_all = NULL;
Test_Container_Item_Data *test_item_data = calloc(1, sizeof(Test_Container_Item_Data));
test_item_data->test_data = data;
test_item_data->index = i;
futures[0] = efl_model_property_get(child, "test_p_int");
futures[1] = efl_model_property_get(child, "test_p_str");
future_all = efl_future_all(futures[0], futures[1]);
efl_future_then(future_all, _container_property_get_then, _future_error_then, NULL, test_item_data);
}
}
}
START_TEST(efl_test_model_container_values)
{
Efl_Model_Container* model;
Efl_Future *future;
Test_Container_Data test_data;
int **cmp_int;
const char **cmp_str;
int i;
fail_if(!ecore_init(), "ERROR: Cannot init Ecore!\n");
fail_if(!efl_object_init(), "ERROR: Cannot init EO!\n");
cmp_int = calloc(8, sizeof(int*));
cmp_str = calloc(8, sizeof(const char*));
for (i = 0; i < 7; ++i)
{
cmp_int[i] = calloc(1, sizeof(int));
*(cmp_int[i]) = base_int[i];
cmp_str[i] = strdup(base_str[i]);
}
model = efl_add(EFL_MODEL_CONTAINER_CLASS, NULL);
efl_model_container_child_property_add(model, "test_p_int", EINA_VALUE_TYPE_INT,
eina_carray_iterator_new((void**)cmp_int));
efl_model_container_child_property_add(model, "test_p_str", EINA_VALUE_TYPE_STRING,
eina_carray_iterator_new((void**)cmp_str));
for (i = 0; i < 7; ++i)
{
free(cmp_int[i]);
free((void*)cmp_str[i]);
}
free(cmp_int);
free(cmp_str);
future = efl_model_children_slice_get(model, 0, 0);
test_data.item_count = 0;
test_data.pass_flag = EINA_FALSE;
test_data.fail_flag = EINA_FALSE;
efl_future_then(future, _children_slice_future_then, _future_error_then, NULL, &test_data);
ecore_main_loop_iterate();
ck_assert(!!test_data.pass_flag);
ck_assert(!test_data.fail_flag);
ecore_shutdown();
}
END_TEST
void
efl_test_case_model_container(TCase *tc)
{
tcase_add_test(tc, efl_test_model_container_values);
}

View File

@ -57,8 +57,44 @@ START_TEST(elm_layout_swallows)
}
END_TEST
START_TEST(elm_layout_model_connect)
{
char buf[PATH_MAX];
Evas_Object *win, *ly;
Efl_Model_Item *model;
Eina_Value v;
const char *part_text;
const char text_value[] = "A random string for elm_layout_model_connect test";
elm_init(1, NULL);
win = elm_win_add(NULL, "layout", ELM_WIN_BASIC);
ly = efl_add(ELM_LAYOUT_CLASS, win);
snprintf(buf, sizeof(buf), "%s/objects/test.edj", ELM_TEST_DATA_DIR);
elm_layout_file_set(ly, buf, "layout");
evas_object_show(ly);
model = efl_add(EFL_MODEL_ITEM_CLASS, win);
ck_assert(!!eina_value_setup(&v, EINA_VALUE_TYPE_STRING));
ck_assert(!!eina_value_set(&v, text_value));
efl_model_property_set(model, "text_property", &v);
efl_ui_model_connect(ly, "text", "text_property");
efl_ui_view_model_set(ly, model);
ecore_main_loop_iterate_may_block(EINA_TRUE);
part_text = elm_layout_text_get(ly, "text");
ck_assert_str_eq(part_text, text_value);
elm_shutdown();
}
END_TEST
void elm_test_layout(TCase *tc)
{
tcase_add_test(tc, elm_atspi_role_get);
tcase_add_test(tc, elm_layout_swallows);
tcase_add_test(tc, elm_layout_model_connect);
}