Compare commits

...

7 Commits

Author SHA1 Message Date
Vitor Sousa 62e0d181a9 elementary: add test for Elm.Layout model connect 2016-07-05 19:40:21 -03:00
Vitor Sousa 83e498d1ab efl: Add Efl.Model.Container and Efl.Model.Item
Add the classes Efl.Model.Container and Efl.Model.Item to efl/interfaces

These classes are used to create Efl.Model objects with predefined
property values.
This is useful to create tests or in any situation where we want an
Efl.Model with explicit defined property values.
2016-07-05 19:39:25 -03:00
Larry Jr a856b2d8ce examples: added efl_ui_image_factory in layout_model_connect example 2016-07-05 14:13:03 -03:00
Larry Jr f04ff73dea elementary: add efl_ui_image_factory
new interface efl_ui_factory used to make new widget with model contents

efl_ui_model_connect(factory, "part_name", "property")
new_canvas = efl_ui_factory_create(factory, model)
2016-07-05 14:13:03 -03:00
Larry Jr 7cff7432cc elementary: add model connect in efl_ui_image 2016-07-05 14:13:03 -03:00
Larry Jr 132f8f1f37 elementary: add example layout_model_connect 2016-07-05 14:13:03 -03:00
Larry Jr ae26833fbd elementary: add model connect in elm_layout
add 2 new interfaces efl_ui_view and efl_ui_model_connect
now elm_layout can update elements from model connectected

efl_ui_view_model_set(layout, model)
efl_ui_model_connect(layout, "part_name", "property")
2016-07-05 14:13:03 -03:00
33 changed files with 1740 additions and 2 deletions

View File

@ -27,6 +27,9 @@ efl_eolian_files = \
lib/efl/interfaces/efl_gfx_filter.eo \
lib/efl/interfaces/efl_gfx_size_hint.eo \
lib/efl/interfaces/efl_model.eo \
lib/efl/interfaces/efl_model_item.eo \
lib/efl/interfaces/efl_model_container.eo \
lib/efl/interfaces/efl_model_container_item.eo \
lib/efl/interfaces/efl_animator.eo \
lib/efl/interfaces/efl_orientation.eo \
lib/efl/interfaces/efl_flipable.eo \
@ -42,6 +45,9 @@ 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_event.eo \
lib/efl/interfaces/efl_input_interface.eo \
lib/efl/interfaces/efl_input_state.eo \
@ -73,6 +79,7 @@ EXTRA_DIST2 += \
lib/efl/Makefile.am \
lib/efl/Makefile.in \
lib/efl/interfaces/efl_common_internal.h \
lib/efl/interfaces/efl_model_private.h \
$(efl_eolian_files) \
$(efl_eolian_type_files)
@ -84,6 +91,9 @@ lib_LTLIBRARIES += lib/efl/libefl.la
lib_efl_libefl_la_SOURCES = \
lib/efl/interfaces/efl_interfaces_main.c \
lib/efl/interfaces/efl_model_common.c \
lib/efl/interfaces/efl_model_item.c \
lib/efl/interfaces/efl_model_container.c \
lib/efl/interfaces/efl_model_container_item.c \
lib/efl/interfaces/efl_gfx_shape.c \
lib/efl/interfaces/efl_vpath_file.c \
lib/efl/interfaces/efl_vpath_manager.c \
@ -155,3 +165,26 @@ 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@ @USE_EFL_LIBS@ @USE_ECORE_LIBS@
tests_efl_efl_suite_DEPENDENCIES = @USE_EFL_INTERNAL_LIBS@
endif

View File

@ -142,6 +142,7 @@ elm_public_eolian_files = \
lib/elementary/efl_ui_text.eo \
lib/elementary/efl_ui_text_editable.eo \
lib/elementary/efl_config_global.eo \
lib/elementary/efl_ui_image_factory.eo \
$(NULL)
# Private classes (not exposed or shipped)
@ -697,6 +698,7 @@ lib_elementary_libelementary_la_SOURCES = \
lib/elementary/efl_ui_grid_static.c \
lib/elementary/efl_ui_grid_private.h \
lib/elementary/efl_ui_text.c \
lib/elementary/efl_ui_image_factory.c \
$(NULL)

View File

@ -116,6 +116,7 @@ layout_example.edc \
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 \
@ -313,6 +314,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,162 @@
// 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>
#include <Eio.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;
};
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;
eo_unref(priv->fileview);
eo_unref(priv->model);
}
static void
_list_selected_cb(void *data EINA_UNUSED, const Eo_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);
}
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;
}
EAPI_MAIN int
elm_main(int argc, char **argv)
{
Layout_Model_Data *priv;
Evas_Object *win, *panes, *bxr, *genlist, *bt;
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 = eo_add(EIO_MODEL_CLASS, NULL, eio_model_path_set(eo_self, dirname));
genlist = elm_genlist_add(win);
priv->fileview = eo_add(ELM_VIEW_LIST_CLASS, NULL, elm_view_list_genlist_set(eo_self, 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);
eo_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 */
bt = elm_button_add(win);
elm_box_pack_end(bxr, bt);
elm_object_text_set(bt, "update model");
evas_object_smart_callback_add(bt, "clicked", _update_cb, priv);
evas_object_show(bt);
/* Image widget */
img_factory = eo_add(EFL_UI_IMAGE_FACTORY_CLASS, win);
efl_ui_model_connect(img_factory, "", "path"); //connect to "path" property
priv->img = efl_ui_factory_create(img_factory, NULL);
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

@ -114,6 +114,10 @@ EAPI extern const Eo_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"
/* 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
@ -38,6 +39,9 @@ struct _Efl_Model_Children_Event
typedef struct _Efl_Model_Children_Event Efl_Model_Children_Event;
#include "interfaces/efl_model.eo.h"
#include "interfaces/efl_model_container.eo.h"
#include "interfaces/efl_model_container_item.eo.h"
#include "interfaces/efl_model_item.eo.h"
EAPI int efl_model_init(void);

View File

@ -27,6 +27,9 @@ interfaces/efl_gfx_gradient_radial.eo \
interfaces/efl_gfx_filter.eo \
interfaces/efl_gfx_size_hint.eo \
interfaces/efl_model.eo \
interfaces/efl_model_item.eo \
interfaces/efl_model_container.eo \
interfaces/efl_model_container_item.eo \
interfaces/efl_animator.eo \
interfaces/efl_orientation.eo \
interfaces/efl_flipable.eo \
@ -64,6 +67,9 @@ lib_LTLIBRARIES = libefl.la
libefl_la_SOURCES = \
interfaces/efl_interfaces_main.c \
interfaces/efl_model_common.c \
interfaces/efl_model_item.c \
interfaces/efl_model_container.c \
interfaces/efl_model_container_item.c \
interfaces/efl_gfx_shape.c \
interfaces/efl_vpath_file.c \
interfaces/efl_vpath_manager.c \

View File

@ -53,6 +53,9 @@ EAPI const Eo_Event_Description _EFL_GFX_PATH_CHANGED =
#include "interfaces/efl_flipable.eo.c"
#include "interfaces/efl_ui_spin.eo.c"
#include "interfaces/efl_ui_progress.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_event.eo.c"
#include "interfaces/efl_input_state.eo.c"

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()
@ -45,6 +48,9 @@ efl_model_init()
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,291 @@
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <Efl.h>
#include "interfaces/efl_model_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);
}
EOLIAN static Eo *
_efl_model_container_eo_base_constructor(Eo *obj, Efl_Model_Container_Data *sd)
{
obj = eo_constructor(eo_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;
}
EOLIAN static void
_efl_model_container_eo_base_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);
eo_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);
eo_destructor(eo_super(obj, MY_CLASS));
}
EOLIAN 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;
}
EOLIAN 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);
}
EOLIAN 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 = eo_add(EFL_MODEL_CONTAINER_ITEM_CLASS, obj,
efl_model_container_item_define(eo_self, sd, i));
sd->children = eina_list_append(sd->children, child);
cevt.child = child;
cevt.index = i;
eo_event_callback_call(obj, EFL_MODEL_EVENT_CHILD_ADDED, &cevt);
}
if (in_count > children_count)
eo_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;
}
EOLIAN 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;
}
EOLIAN static void
_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, Eina_Promise_Owner *promise_owner)
{
eina_promise_owner_error_set(promise_owner, EFL_MODEL_ERROR_NOT_FOUND);
}
EOLIAN static Eina_Promise *
_efl_model_container_efl_model_property_get(Eo *obj EINA_UNUSED, Efl_Model_Container_Data *sd EINA_UNUSED, const char *property EINA_UNUSED)
{
Eina_Promise_Owner *promise_owner = eina_promise_add();
Eina_Promise *rpromise = eina_promise_owner_promise_get(promise_owner);
eina_promise_owner_error_set(promise_owner, EFL_MODEL_ERROR_NOT_FOUND);
return rpromise;
}
EOLIAN static Eina_Promise *
_efl_model_container_efl_model_children_slice_get(Eo *obj EINA_UNUSED, Efl_Model_Container_Data *sd, unsigned int start, unsigned int count)
{
Eina_Promise_Owner *promise_owner = eina_promise_add();
Eina_Promise *rpromise = eina_promise_owner_promise_get(promise_owner);
Eina_Accessor* accessor = efl_model_list_slice(sd->children, start, count);
eina_promise_owner_value_set(promise_owner, accessor, (Eina_Promise_Free_Cb)&eina_accessor_free);
return rpromise;
}
EOLIAN static Eina_Promise *
_efl_model_container_efl_model_children_count_get(Eo *obj EINA_UNUSED, Efl_Model_Container_Data *sd)
{
Eina_Promise_Owner *promise_owner = eina_promise_add();
Eina_Promise *rpromise = eina_promise_owner_promise_get(promise_owner);
unsigned int *count = calloc(1, sizeof(unsigned int));
*count = eina_list_count(sd->children);
eina_promise_owner_value_set(promise_owner, count, &free);
return rpromise;
}
EOLIAN 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;
}
EOLIAN 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 "interfaces/efl_model_container.eo.c"

View File

@ -0,0 +1,68 @@
import eina_types;
class Efl.Model.Container (Eo.Base, 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.
As illustrated above:
|‾‾‾‾‾||‾‾‾‾‾||‾‾‾‾‾||‾‾‾‾‾| <br/>
cont1, property: "code" -> ["A"] ["B"] ["C"] ["D"] <br/>
cont2, property: "day" -> [ 8 ] [ 24] [ 14] <br/>
|_____||_____||_____||_____| <br/>
| | | | <br/>
child1 child2 child3 child4 <br/>
]]
methods {
child_property_value_type_get {
[[Get the type of the given property.]]
params {
name: string; [[Property name]]
}
return: 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: const(Eina.Value.Type)*; [[Property type]]
values: own(iterator<const(void_ptr)>); [[Values to be added]]
}
return: bool; [[$true on success, $false otherwise]]
}
}
implements {
Eo.Base.constructor;
Eo.Base.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,187 @@
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <Efl.h>
#include "interfaces/efl_model_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;
}
EOLIAN static void
_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_Promise_Owner *promise_owner)
{
Eina_Stringshare *prop_name;
Child_Property_Data *cpd;
void *data, *new_data;
if (!sd->parent_data)
{
eina_promise_owner_error_set(promise_owner, EFL_MODEL_ERROR_INVALID_OBJECT);
return;
}
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))
{
eina_promise_owner_error_set(promise_owner, EFL_MODEL_ERROR_NOT_FOUND);
return;
}
if (cpd->property_type != eina_value_type_get(value))
{
eina_promise_owner_error_set(promise_owner, EFL_MODEL_ERROR_INCORRECT_VALUE);
return;
}
data = calloc(1, cpd->property_type->value_size);
if (!data || !eina_value_pget(value, data))
{
if (data)
free(data);
eina_promise_owner_error_set(promise_owner, EFL_MODEL_ERROR_UNKNOWN);
return;
}
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))
eina_promise_owner_value_set(promise_owner, v, _item_value_free_cb);
else
{
if (v)
eina_value_free(v);
eina_promise_owner_error_set(promise_owner, EFL_MODEL_ERROR_UNKNOWN);
}
}
}
EOLIAN static Eina_Promise *
_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;
Eina_Promise_Owner *promise_owner = eina_promise_add();
Eina_Promise *rpromise = eina_promise_owner_promise_get(promise_owner);
if (!sd->parent_data)
{
eina_promise_owner_error_set(promise_owner, EFL_MODEL_ERROR_INVALID_OBJECT);
return rpromise;
}
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))
{
eina_promise_owner_error_set(promise_owner, EFL_MODEL_ERROR_NOT_FOUND);
return rpromise;
}
value = eina_value_new(cpd->property_type);
if (!value)
eina_promise_owner_error_set(promise_owner, 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)
eina_promise_owner_value_set(promise_owner, value, _item_value_free_cb);
else
{
eina_promise_owner_error_set(promise_owner, EFL_MODEL_ERROR_UNKNOWN);
eina_value_free(value);
}
}
return rpromise;
}
EOLIAN static Eina_Promise *
_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)
{
Eina_Promise_Owner *promise_owner = eina_promise_add();
Eina_Promise *rpromise = eina_promise_owner_promise_get(promise_owner);
eina_promise_owner_value_set(promise_owner, NULL, NULL);
return rpromise;
}
EOLIAN static Eina_Promise *
_efl_model_container_item_efl_model_children_count_get(Eo *obj EINA_UNUSED, Efl_Model_Container_Item_Data *sd EINA_UNUSED)
{
Eina_Promise_Owner *promise_owner = eina_promise_add();
Eina_Promise *rpromise = eina_promise_owner_promise_get(promise_owner);
unsigned int *count = calloc(1, sizeof(unsigned int));
*count = 0;
eina_promise_owner_value_set(promise_owner, count, &free);
return rpromise;
}
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 "interfaces/efl_model_container_item.eo.c"

View File

@ -0,0 +1,39 @@
import eina_types;
class Efl.Model.Container.Item (Eo.Base, 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,197 @@
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <Efl.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;
}
EOLIAN static Eo *
_efl_model_item_eo_base_constructor(Eo *obj, Efl_Model_Item_Data *sd)
{
obj = eo_constructor(eo_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;
}
EOLIAN static void
_efl_model_item_eo_base_destructor(Eo *obj, Efl_Model_Item_Data *sd)
{
Efl_Model *child;
EINA_LIST_FREE(sd->children, child)
{
if (child)
eo_parent_set(child, NULL);
}
eina_hash_foreach(sd->properties, _stringshared_keys_free, NULL);
eina_hash_free(sd->properties);
eina_array_free(sd->defined_properties);
eo_destructor(eo_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;
}
EOLIAN static void
_efl_model_item_efl_model_property_set(Eo *obj EINA_UNUSED, Efl_Model_Item_Data *sd, const char *property, const Eina_Value *value, Eina_Promise_Owner *promise_owner)
{
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;
}
eina_promise_owner_value_set(promise_owner, p_v, NULL);
return;
err4:
eina_value_free(p_v);
err3:
eina_array_pop(sd->defined_properties);
err2:
eina_stringshare_del(sshared);
err1:
eina_promise_owner_error_set(promise_owner, EFL_MODEL_ERROR_UNKNOWN);
}
EOLIAN static Eina_Promise *
_efl_model_item_efl_model_property_get(Eo *obj EINA_UNUSED, Efl_Model_Item_Data *sd, const char *property)
{
Eina_Promise_Owner *promise_owner = eina_promise_add();
Eina_Promise *rpromise = eina_promise_owner_promise_get(promise_owner);
Eina_Stringshare *sshare = eina_stringshare_add(property);
Eina_Value *p_v = eina_hash_find(sd->properties, sshare);
eina_stringshare_del(sshare);
if (p_v)
eina_promise_owner_value_set(promise_owner, p_v, NULL);
else
eina_promise_owner_error_set(promise_owner, EFL_MODEL_ERROR_NOT_FOUND);
return rpromise;
}
EOLIAN static Eina_Promise *
_efl_model_item_efl_model_children_slice_get(Eo *obj EINA_UNUSED, Efl_Model_Item_Data *sd, unsigned int start, unsigned int count)
{
Eina_Promise_Owner *promise_owner = eina_promise_add();
Eina_Promise *rpromise = eina_promise_owner_promise_get(promise_owner);
Eina_Accessor* accessor = efl_model_list_slice(sd->children, start, count);
eina_promise_owner_value_set(promise_owner, accessor, (Eina_Promise_Free_Cb)&eina_accessor_free);
return rpromise;
}
EOLIAN static Eina_Promise *
_efl_model_item_efl_model_children_count_get(Eo *obj EINA_UNUSED, Efl_Model_Item_Data *sd)
{
Eina_Promise_Owner *promise_owner = eina_promise_add();
Eina_Promise *rpromise = eina_promise_owner_promise_get(promise_owner);
unsigned int *count = calloc(1, sizeof(unsigned int));
*count = eina_list_count(sd->children);
eina_promise_owner_value_set(promise_owner, count, &free);
return rpromise;
}
EOLIAN static Eo *
_efl_model_item_efl_model_child_add(Eo *obj, Efl_Model_Item_Data *sd)
{
Efl_Model_Children_Event cevt;
Efl_Model *child = eo_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);
eo_event_callback_call(obj, EFL_MODEL_EVENT_CHILD_ADDED, &cevt);
eo_event_callback_call(obj, EFL_MODEL_EVENT_CHILDREN_COUNT_CHANGED, &cevt.index);
return child;
}
EOLIAN 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 = eo_ref(child);
cevt.index = i;
eo_parent_set(child, NULL);
eo_event_callback_call(obj, EFL_MODEL_EVENT_CHILD_REMOVED, &cevt);
eo_unref(child);
i = eina_list_count(sd->children);
eo_event_callback_call(obj, EFL_MODEL_EVENT_CHILDREN_COUNT_CHANGED, &i);
break;
}
++i;
}
}
#include "interfaces/efl_model_item.eo.c"

View File

@ -0,0 +1,26 @@
import eina_types;
class Efl.Model.Item (Eo.Base, 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 {
Eo.Base.constructor;
Eo.Base.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,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,12 @@
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;
}
return: Efl.Canvas;
}
}
}

View File

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

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

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

View File

@ -39,6 +39,7 @@ 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_sizing_eval(Eo *obj);
static void _efl_ui_image_model_properties_changed_cb(void *data, const Eo_Event *event);
static const Elm_Action key_actions[] = {
{"activate", _key_action_activate},
@ -632,6 +633,14 @@ _efl_ui_image_efl_canvas_group_group_del(Eo *obj, Efl_Ui_Image_Data *sd)
sd->async.th = NULL;
}
if (sd->model)
{
eo_event_callback_del(sd->model, EFL_MODEL_EVENT_PROPERTIES_CHANGED,
_efl_ui_image_model_properties_changed_cb, obj);
eo_unref(sd->model);
sd->model = NULL;
}
_async_open_data_free(sd->async.done);
_async_open_data_free(sd->async.todo);
eina_stringshare_del(sd->async.file);
@ -1693,6 +1702,107 @@ _efl_ui_image_icon_get(Eo *obj EINA_UNUSED, Efl_Ui_Image_Data *sd)
return sd->stdicon;
}
static void
_prop_promise_error_cb(void* data EINA_UNUSED, Eina_Error err EINA_UNUSED)
{
}
static void
_prop_promise_then_cb(void* data, void* v)
{
Eo *obj = data;
Eina_Value *value = v;
char *text;
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);
elm_image_file_set(obj, text, NULL);
}
else
{
text = eina_value_to_string(value);
elm_image_file_set(obj, text, NULL);
free(text);
}
}
static void
_efl_ui_image_model_properties_changed_cb(void *data, const Eo_Event *event)
{
Efl_Model_Property_Event *evt = event->info;
Eina_Array_Iterator it;
const char *prop;
unsigned int i;
EFL_UI_IMAGE_DATA_GET(data, pd);
if (!evt->changed_properties)
return;
if (pd->model && pd->prop_con)
{
EINA_ARRAY_ITER_NEXT(evt->changed_properties, i, prop, it)
{
if (!strcmp(pd->prop_con, prop))
{
Eina_Promise *promise = efl_model_property_get(pd->model, pd->prop_con);
eina_promise_then(promise, &_prop_promise_then_cb, &_prop_promise_error_cb, data);
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)
{
eo_event_callback_del(pd->model, EFL_MODEL_EVENT_PROPERTIES_CHANGED,
_efl_ui_image_model_properties_changed_cb, obj);
eo_unref(pd->model);
pd->model = NULL;
}
if (model)
{
pd->model = model;
eo_ref(pd->model);
eo_event_callback_add(pd->model, EFL_MODEL_EVENT_PROPERTIES_CHANGED,
_efl_ui_image_model_properties_changed_cb, obj);
}
if (pd->prop_con && pd->model)
{
Eina_Promise *promise = efl_model_property_get(pd->model, pd->prop_con);
eina_promise_then(promise, &_prop_promise_then_cb,
&_prop_promise_error_cb, obj);
}
}
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 EINA_UNUSED, const char *property)
{
eina_stringshare_replace(&pd->prop_con, property);
if (pd->model && pd->prop_con)
{
Eina_Promise *promise = efl_model_property_get(pd->model, pd->prop_con);
eina_promise_then(promise, &_prop_promise_then_cb,
&_prop_promise_error_cb, obj);
}
}
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)
{
event_prefix: efl_ui_image;
methods {
@ -165,6 +166,9 @@ class Efl.Ui.Image (Elm.Widget, Efl.Ui.Clickable, Efl.Ui.Draggable,
Efl.Canvas.Group.group_resize;
Efl.Ui.Draggable.drag_target.set;
Efl.Ui.Draggable.drag_target.get;
Efl.Ui.Model.Connect.connect;
Efl.Ui.View.model.set;
Efl.Ui.View.model.get;
Elm.Widget.theme_apply;
Elm.Widget.event;
Elm.Interface.Atspi_Image.extents.get;

View File

@ -0,0 +1,50 @@
#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;
static Eo *
_efl_ui_image_factory_eo_base_constructor(Eo *obj, Efl_Ui_Image_Factory_Data *pd)
{
obj = eo_constructor(eo_super(obj, MY_CLASS));
pd->property = NULL;
return obj;
}
static void
_efl_ui_image_factory_eo_base_destructor(Eo *obj EINA_UNUSED, Efl_Ui_Image_Factory_Data *pd)
{
eina_stringshare_del(pd->property);
pd->property = NULL;
}
static Efl_Canvas *
_efl_ui_image_factory_efl_ui_factory_create(Eo *obj EINA_UNUSED, Efl_Ui_Image_Factory_Data *pd, Efl_Model *model)
{
EINA_SAFETY_ON_NULL_RETURN_VAL(pd->property, NULL);
Efl_Canvas *ev = eo_add(EFL_UI_IMAGE_CLASS, eo_parent_get(obj));
efl_ui_view_model_set(ev, model);
efl_ui_model_connect(ev, NULL, pd->property);
return ev;
}
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,9 @@
class Efl.Ui.Image.Factory (Eo.Base, Efl.Ui.Factory)
{
implements {
Eo.Base.constructor;
Eo.Base.destructor;
Efl.Ui.Factory.create;
Efl.Ui.Model.Connect.connect;
}
}

View File

@ -78,6 +78,8 @@ struct _Efl_Ui_Image_Data
const char *stdicon;
Efl_Model *model;
Eina_Stringshare *prop_con;
struct {
int requested_size;

View File

@ -19,6 +19,7 @@
#define MY_CLASS_NAME_LEGACY "elm_layout"
Eo *_elm_layout_pack_proxy_get(Elm_Layout *obj, Evas_Object *pack, const char *part);
static void _efl_model_properties_changed_cb(void *, const Eo_Event *);
static const char SIG_THEME_CHANGED[] = "theme,changed";
const char SIG_LAYOUT_FOCUSED[] = "focused";
@ -107,6 +108,13 @@ struct _Elm_Layout_Sub_Object_Cursor
Eina_Bool engine_only : 1;
};
typedef struct _Elm_Layout_Sub_Property_Promise Elm_Layout_Sub_Property_Promise;
struct _Elm_Layout_Sub_Property_Promise
{
Elm_Layout_Smart_Data *pd;
Eina_Stringshare *name;
};
static void
_on_sub_object_size_hint_change(void *data,
Evas *e EINA_UNUSED,
@ -818,6 +826,15 @@ _elm_layout_efl_canvas_group_group_del(Eo *obj, Elm_Layout_Smart_Data *sd)
free(esd);
}
if(sd->model)
{
eo_event_callback_del(sd->model, EFL_MODEL_EVENT_PROPERTIES_CHANGED, _efl_model_properties_changed_cb, sd);
eo_unref(sd->model);
sd->model = NULL;
}
eina_hash_free(sd->prop_connect);
sd->prop_connect = NULL;
eina_stringshare_del(sd->klass);
eina_stringshare_del(sd->group);
@ -1332,6 +1349,30 @@ _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_Hash_Tuple *tuple;
Eina_Iterator *it = eina_hash_iterator_tuple_new(sd->prop_connect);
while (eina_iterator_next(it, (void **)&tuple))
{
if (tuple->data == sub_d->part)
{
Eina_Value v;
eina_value_setup(&v, EINA_VALUE_TYPE_STRING);
eina_value_set(&v, text);
efl_model_property_set(sd->model, tuple->key, &v, NULL);
eina_value_flush(&v);
break;
}
}
eina_iterator_free(it);
}
sd->view_updated = EINA_FALSE;
return EINA_TRUE;
}
@ -1909,6 +1950,150 @@ _elm_layout_eo_base_dbg_info_get(Eo *eo_obj, Elm_Layout_Smart_Data *_pd EINA_UNU
}
}
static void
_prop_promise_error_cb(void* data, Eina_Error err EINA_UNUSED)
{
Elm_Layout_Sub_Property_Promise *sub_pp = data;
eina_stringshare_del(sub_pp->name);
free(sub_pp);
}
static void
_prop_promise_then_cb(void* data, void* v)
{
Elm_Layout_Sub_Property_Promise *sub_pp = data;
Elm_Layout_Smart_Data *pd = sub_pp->pd;
Eina_Value *value = v;
char *text;
const Eina_Value_Type *vtype = eina_value_type_get(value);
pd->view_updated = EINA_TRUE;
if (vtype == EINA_VALUE_TYPE_STRING || vtype == EINA_VALUE_TYPE_STRINGSHARE)
{
eina_value_get(value, &text);
elm_layout_text_set(pd->obj, sub_pp->name, text);
}
else
{
text = eina_value_to_string(value);
elm_layout_text_set(pd->obj, sub_pp->name, text);
free(text);
}
eina_stringshare_del(sub_pp->name);
free(sub_pp);
}
static void
_efl_model_properties_changed_cb(void *data, const Eo_Event *event)
{
Elm_Layout_Smart_Data *pd = data;
Efl_Model_Property_Event *evt = event->info;
Elm_Layout_Sub_Property_Promise *sub_pp;
Eina_Stringshare *name;
Eina_Array_Iterator it;
Eina_Promise *promise;
const char *prop;
unsigned int i;
if (!evt->changed_properties)
return;
EINA_ARRAY_ITER_NEXT(evt->changed_properties, i, prop, it)
{
name = eina_hash_find(pd->prop_connect, prop);
if (name)
{
sub_pp = ELM_NEW(Elm_Layout_Sub_Property_Promise);
sub_pp->pd = pd;
sub_pp->name = name;
eina_stringshare_ref(sub_pp->name);
promise = efl_model_property_get(pd->model, prop);
eina_promise_then(promise, &_prop_promise_then_cb,
&_prop_promise_error_cb, sub_pp);
}
}
}
static Eina_Bool
_elm_layout_view_update_fn(const Eina_Hash *hash EINA_UNUSED, const void *key, void *data, void *fdata)
{
Elm_Layout_Smart_Data *pd = fdata;
Eina_Stringshare *prop = key;
Eina_Stringshare *name = data;
if (name)
{
Elm_Layout_Sub_Property_Promise *sub_pp = ELM_NEW(Elm_Layout_Sub_Property_Promise);
Eina_Promise *promise = efl_model_property_get(pd->model, prop);
sub_pp->pd = pd;
sub_pp->name = eina_stringshare_ref(name);
eina_promise_then(promise, &_prop_promise_then_cb,
&_prop_promise_error_cb, sub_pp);
}
return EINA_TRUE;
}
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)
{
eo_event_callback_del(pd->model, EFL_MODEL_EVENT_PROPERTIES_CHANGED, _efl_model_properties_changed_cb, pd);
eo_unref(pd->model);
pd->model = NULL;
}
if (model)
{
pd->model = model;
eo_ref(pd->model);
eo_event_callback_add(pd->model, EFL_MODEL_EVENT_PROPERTIES_CHANGED, _efl_model_properties_changed_cb, pd);
}
if (pd->prop_connect) eina_hash_foreach(pd->prop_connect, _elm_layout_view_update_fn, pd);
}
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_prop, ss_name));
if (pd->model)
{
Eina_Promise *promise;
Elm_Layout_Sub_Property_Promise *sub_pp = ELM_NEW(Elm_Layout_Sub_Property_Promise);
sub_pp->pd = pd;
sub_pp->name = eina_stringshare_ref(ss_name);
promise = efl_model_property_get(pd->model, ss_prop);
eina_promise_then(promise, &_prop_promise_then_cb,
&_prop_promise_error_cb, sub_pp);
}
}
EAPI Evas_Object *
elm_layout_add(Evas_Object *parent)
{

View File

@ -17,7 +17,7 @@ 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, Edje.Object)
class Elm.Layout (Elm.Widget, Efl.Part, Efl.Container, Efl.File, Edje.Object, Efl.Ui.View, Efl.Ui.Model.Connect)
{
legacy_prefix: elm_layout;
eo_prefix: elm_obj_layout;
@ -256,6 +256,9 @@ class Elm.Layout (Elm.Widget, Efl.Part, Efl.Container, Efl.File, Edje.Object)
Edje.Object.thaw;
Edje.Object.signal_callback_add;
Edje.Object.signal_callback_del;
Efl.Ui.View.model.set;
Efl.Ui.View.model.get;
Efl.Ui.Model.Connect.connect;
}
events {
theme,changed;

View File

@ -53,6 +53,8 @@ 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 list of properties connected to layout parts. */
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 +65,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

@ -40,3 +40,4 @@ enum @extern Eina.Xattr.Flags {
created [[This will only succeed if the extended attribute wasn't previously set]]
}
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,160 @@
/* 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 <Ecore.h>
#include <Efl.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
_container_property_get_then(void *data, void *values)
{
Eina_Iterator *value_itt = values;
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 (!eina_iterator_next(value_itt, (void**)&value_int) ||
!eina_iterator_next(value_itt, (void**)&value_str))
{
test_item_data->test_data->fail_flag = EINA_TRUE;
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;
}
}
static void
_children_slice_promise_then(void *data, void *value)
{
Eina_Accessor *children_accessor = value;
unsigned int i = 0;
Efl_Model *child;
if (children_accessor)
{
EINA_ACCESSOR_FOREACH(children_accessor, i, child)
{
Eina_Promise *promises[3] = {NULL,};
Eina_Promise *promise_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;
promises[0] = efl_model_property_get(child, "test_p_int");
promises[1] = efl_model_property_get(child, "test_p_str");
promise_all = eina_promise_all(eina_carray_iterator_new((void**)promises));
eina_promise_then(promise_all, _container_property_get_then, NULL, test_item_data);
}
}
}
START_TEST(efl_test_model_container_values)
{
Efl_Model_Container* model;
Eina_Promise *promise;
Test_Container_Data test_data;
int **cmp_int;
const char **cmp_str;
int i;
eo_init();
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 = eo_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(cmp_str[i]);
}
free(cmp_int);
free(cmp_str);
promise = 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;
eina_promise_then(promise, _children_slice_promise_then, NULL, &test_data);
ecore_main_loop_iterate();
ck_assert(!!test_data.pass_flag);
ck_assert(!test_data.fail_flag);
eo_shutdown();
}
END_TEST
void
efl_test_case_model_container(TCase *tc)
{
tcase_add_test(tc, efl_test_model_container_values);
}

View File

@ -87,9 +87,45 @@ START_TEST(elm_layout_edje_attach)
}
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 = eo_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 = eo_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, NULL);
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_edje_attach);
tcase_add_test(tc, elm_layout_model_connect);
}