diff options
author | Larry Jr <larry.olj@gmail.com> | 2014-07-21 23:38:02 -0300 |
---|---|---|
committer | Larry Jr <larry.olj@gmail.com> | 2015-03-19 15:34:51 -0300 |
commit | e1f04888591449a278ec1af8e7ec8c27c2a9b0df (patch) | |
tree | a0e1ebac4bde2a5bccca1e651bcf77851b5ae2fb | |
parent | 0754f4da4db90fc21fee7dada31c50e02137648d (diff) | |
download | elementary-e1f04888591449a278ec1af8e7ec8c27c2a9b0df.tar.gz |
Created Views for Emodel MVC.
Summary:
Elm_View_List: Use Genlist to show children and his properties
Elm_View_Form: Make a connection between a Widget and a property
-rw-r--r-- | configure.ac | 7 | ||||
-rw-r--r-- | src/examples/.gitignore | 2 | ||||
-rw-r--r-- | src/examples/Makefile.am | 4 | ||||
-rw-r--r-- | src/examples/filemvc.c | 212 | ||||
-rw-r--r-- | src/examples/fileviewlist.c | 77 | ||||
-rw-r--r-- | src/lib/Elementary.h.in | 2 | ||||
-rw-r--r-- | src/lib/Makefile.am | 6 | ||||
-rw-r--r-- | src/lib/elm_view_form.c | 259 | ||||
-rw-r--r-- | src/lib/elm_view_form.eo | 38 | ||||
-rw-r--r-- | src/lib/elm_view_form.h | 5 | ||||
-rw-r--r-- | src/lib/elm_view_list.c | 433 | ||||
-rw-r--r-- | src/lib/elm_view_list.eo | 77 | ||||
-rw-r--r-- | src/lib/elm_view_list.h | 9 |
13 files changed, 1130 insertions, 1 deletions
diff --git a/configure.ac b/configure.ac index 96d20efc3..1e36c628a 100644 --- a/configure.ac +++ b/configure.ac @@ -228,11 +228,12 @@ requirement_elm_pc_only="\ ecore-imf >= efl_version \ ecore-con >= efl_version \ eio >= efl_version \ + emodel >= efl_version \ eldbus >= efl_version \ efreet >= efl_version \ efreet-mime >= efl_version \ efreet-trash >= efl_version \ - eio >= efl_version \ + emodel >= efl_version \ " requirement_elm_pc="\ @@ -269,6 +270,8 @@ if test "x${HAVE_CXX11}" = "x1" -a "x${want_cxx11}" = "xyes"; then eo-cxx >= efl_version eina-cxx >= efl_version evas-cxx >= efl_version + emodel-cxx >= efl_version + eio-cxx >= efl_version ], [ requirement_elm_pc="${requirement_elm_pc} \ @@ -276,6 +279,8 @@ if test "x${HAVE_CXX11}" = "x1" -a "x${want_cxx11}" = "xyes"; then eo-cxx >= efl_version \ eina-cxx >= efl_version \ evas-cxx >= efl_version \ + emodel-cxx >= efl_version \ + eio-cxx >= efl_version \ " have_cxx11="yes" LDFLAGS="${LDFLAGS} -fPIC -DPIC" diff --git a/src/examples/.gitignore b/src/examples/.gitignore index fd9fc399b..98a343b64 100644 --- a/src/examples/.gitignore +++ b/src/examples/.gitignore @@ -32,6 +32,8 @@ /fileselector_button_example /fileselector_entry_example /fileselector_example +/fileviewlist +/filemvc /flip_example_01 /flipselector_example /frame_example_01 diff --git a/src/examples/Makefile.am b/src/examples/Makefile.am index 23d09bee8..31494a745 100644 --- a/src/examples/Makefile.am +++ b/src/examples/Makefile.am @@ -72,6 +72,8 @@ entry_example.c \ fileselector_button_example.c \ fileselector_entry_example.c \ fileselector_example.c \ +fileviewlist.c \ +filemvc.c \ flip_example_01.c \ flipselector_example.c \ frame_example_01.c \ @@ -225,6 +227,8 @@ entry_example \ fileselector_button_example \ fileselector_entry_example \ fileselector_example \ +fileviewlist \ +filemvc \ flip_example_01 \ flipselector_example \ frame_example_01 \ diff --git a/src/examples/filemvc.c b/src/examples/filemvc.c new file mode 100644 index 000000000..47e969db5 --- /dev/null +++ b/src/examples/filemvc.c @@ -0,0 +1,212 @@ +//#ifdef HAVE_CONFIG_H +# include "../../elementary_config.h" +//#endif + +#include <Elementary.h> +#include <Emodel.h> +#include <Eio.h> +#include <eio_model.eo.h> +#include <stdio.h> +#include <Eio.h> +#include <elm_view_form.h> + +#define EMODEL_TEST_FILENAME_PATH "/tmp" + +struct _Emodel_Test_Filemvc_Data +{ + Eo *fileview; + Eo *treeview; + Eo *formview; + Eo *treemodel; + Evas_Object *thumb; + char imagedefault_path[256]; +}; +typedef struct _Emodel_Test_Filemvc_Data Emodel_Test_Filemvc_Data; + +static void +_cleanup_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) +{ + Emodel_Test_Filemvc_Data *priv = (Emodel_Test_Filemvc_Data *)data; + eo_unref(priv->fileview); + eo_unref(priv->treeview); + eo_unref(priv->formview); + eo_unref(priv->treemodel); +} + +static Eina_Bool +_filter_cb(void *data EINA_UNUSED, Eio_File *handler EINA_UNUSED, const Eina_File_Direct_Info *info) +{ + if (info->type == EINA_FILE_DIR && info->path[info->name_start] != '.') return EINA_TRUE; + + return EINA_FALSE; +} + +static Eina_Bool +_list_selected_cb(void *data EINA_UNUSED, Eo *obj EINA_UNUSED, const Eo_Event_Description *desc EINA_UNUSED, void *event_info EINA_UNUSED) +{ + Emodel_Test_Filemvc_Data *priv = data; + Eo *child = event_info; + ethumb_client_file_free(elm_thumb_ethumb_client_get()); + + printf("LIST selected model\n"); + eo_do(priv->formview, elm_view_form_model_set(child)); + return EINA_TRUE; +} + +static Eina_Bool +_tree_selected_cb(void *data, Eo *obj EINA_UNUSED, const Eo_Event_Description *desc EINA_UNUSED, void *event_info) +{ + printf("TREE selected model\n"); + Emodel_Test_Filemvc_Data *priv = data; + Eo *child = event_info; + Eina_Value vpath; + Eo *model; + char *path; + + eo_do(child, emodel_property_get("path", &vpath)); + eina_value_get(&vpath, &path); + model = eo_add(EIO_MODEL_CLASS, NULL, eio_model_path_set(path)); + eo_do(model, emodel_load()); + eo_do(priv->fileview, elm_view_list_model_set(model)); + eina_value_flush(&vpath); +// eo_unref(model); + return EINA_TRUE; +} + +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 +_thumb_error_cb(void *data, Evas_Object *o EINA_UNUSED, void *event_info EINA_UNUSED) +{ + Emodel_Test_Filemvc_Data *priv = data; + printf("thumbnail generation error.\n"); + elm_thumb_file_set(priv->thumb, priv->imagedefault_path, NULL); + elm_thumb_reload(priv->thumb); +} + +EAPI_MAIN int +elm_main(int argc, char **argv) +{ + Emodel_Test_Filemvc_Data priv; + Evas_Object *win, *panes, *bxr, *genlist, *vpanes; + Evas_Object *entry; + char *dirname; + + memset(&priv, 0, sizeof(Emodel_Test_Filemvc_Data)); + elm_app_info_set(elm_main, "elementary", "images/logo.png"); + sprintf(priv.imagedefault_path, "%s/images/logo.png", elm_app_data_dir_get()); + + //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); +// elm_box_horizontal_set(box, EINA_TRUE); + evas_object_size_hint_weight_set(panes, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + elm_win_resize_object_add(win, panes); + + ecore_init(); + eio_init(); + + if(argv[1] != NULL) dirname = argv[1]; + else dirname = EMODEL_TEST_FILENAME_PATH; + + //treemodel + priv.treemodel = eo_add(EIO_MODEL_CLASS, NULL, eio_model_path_set(dirname)); + eo_do(priv.treemodel, eio_model_children_filter_set(_filter_cb, NULL)); + eo_do(priv.treemodel, emodel_load()); + + //treeview + genlist = elm_genlist_add(win); + priv.treeview = eo_add(ELM_VIEW_LIST_CLASS, NULL, elm_view_list_constructor(genlist, ELM_GENLIST_ITEM_TREE, NULL)); + eo_do(priv.treeview, elm_view_list_property_connect("filename", "elm.text"), + elm_view_list_property_connect("icon", "elm.swallow.icon"), + elm_view_list_model_set(priv.treemodel)); + _widget_init(genlist); + elm_object_part_content_set(panes, "left", genlist); + eo_do(panes, elm_obj_panes_content_left_size_set(0.3)); + + vpanes = elm_panes_add(win); + _widget_init(vpanes); + elm_object_part_content_set(panes, "right", vpanes); + eo_do(priv.treeview, eo_event_callback_add(ELM_VIEW_LIST_EVENT_MODEL_SELECTED, _tree_selected_cb, &priv)); + //listview + genlist = elm_genlist_add(win); + priv.fileview = eo_add(ELM_VIEW_LIST_CLASS, NULL, elm_view_list_constructor(genlist, ELM_GENLIST_ITEM_NONE, "double_label")); + eo_do(priv.fileview, elm_view_list_property_connect("filename", "elm.text"), + elm_view_list_property_connect("mtime", "elm.text.sub")); + + evas_object_event_callback_add(win, EVAS_CALLBACK_DEL, _cleanup_cb, &priv); + _widget_init(genlist); + elm_object_part_content_set(vpanes, "left", genlist); + + eo_do(priv.fileview, eo_event_callback_add(ELM_VIEW_LIST_EVENT_MODEL_SELECTED, _list_selected_cb, &priv)); + + //formview + bxr = elm_box_add(win); + _widget_init(bxr); + elm_object_part_content_set(vpanes, "right", bxr); + priv.formview = eo_add(ELM_VIEW_FORM_CLASS, NULL, elm_view_form_constructor(NULL)); + + /*Label widget */ + eo_do(priv.formview, elm_view_form_widget_add("filename", _label_init(win, bxr, "File Name"))); + + _label_init(win, bxr, "Size:"); + eo_do(priv.formview, elm_view_form_widget_add("size", _label_init(win, bxr, ""))); + + _label_init(win, bxr, "Modified:"); + eo_do(priv.formview, elm_view_form_widget_add("mtime", _label_init(win, bxr, ""))); + + /* Entry widget */ + entry = elm_entry_add(win); + elm_entry_single_line_set(entry, EINA_TRUE); + evas_object_size_hint_weight_set(entry, EVAS_HINT_FILL, EVAS_HINT_FILL); + elm_box_pack_end(bxr, entry); + evas_object_show(entry); + eo_do(priv.formview, elm_view_form_widget_add("path", entry)); + + /* Thumb widget */ + elm_need_ethumb(); + priv.thumb = elm_thumb_add(win); + _widget_init(priv.thumb); + elm_box_pack_end(bxr, priv.thumb); + elm_thumb_editable_set(priv.thumb, EINA_FALSE); + eo_do(priv.formview, elm_view_form_widget_add("path", priv.thumb)); + evas_object_smart_callback_add(priv.thumb, "generate,error", _thumb_error_cb, &priv); + evas_object_smart_callback_add(priv.thumb, "load,error", _thumb_error_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() + diff --git a/src/examples/fileviewlist.c b/src/examples/fileviewlist.c new file mode 100644 index 000000000..d3a6ab93c --- /dev/null +++ b/src/examples/fileviewlist.c @@ -0,0 +1,77 @@ +//Compile with: +// gcc -o fileviewlist fileviewlist.c `pkg-config --cflags --libs emodel` + +//#ifdef HAVE_CONFIG_H +# include "../../elementary_config.h" +//#endif + +#include <Elementary.h> +#include <Emodel.h> +#include <Eio.h> +#include <eio_model.eo.h> +#include <stdio.h> + +#define EMODEL_TEST_FILENAME_PATH "/tmp" + +struct _Emodel_Test_Fileview_Data +{ + Eo *filemodel; + Eo *fileview; +}; +typedef struct _Emodel_Test_Fileview_Data Emodel_Test_Fileview_Data; + +static void +_cleanup_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) +{ + Emodel_Test_Fileview_Data *priv = (Emodel_Test_Fileview_Data *)data; + eo_unref(priv->fileview); + eo_unref(priv->filemodel); +} + +EAPI_MAIN int +elm_main(int argc, char **argv) +{ + Emodel_Test_Fileview_Data priv; + Evas_Object *win = NULL; + Evas_Object *genlist = NULL; + char *dirname; + + memset(&priv, 0, sizeof(Emodel_Test_Fileview_Data)); + + ecore_init(); + eio_init(); + + if(argv[1] != NULL) dirname = argv[1]; + else dirname = EMODEL_TEST_FILENAME_PATH; + + 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); + + genlist = elm_genlist_add(win); + evas_object_size_hint_weight_set(genlist, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + evas_object_show(genlist); + + priv.filemodel = eo_add(EIO_MODEL_CLASS, NULL, eio_model_path_set(dirname)); + priv.fileview = eo_add(ELM_VIEW_LIST_CLASS, NULL, + elm_view_list_constructor(genlist, ELM_GENLIST_ITEM_TREE, "double_label")); + eo_do(priv.fileview, elm_view_list_model_set(priv.filemodel)); + eo_do(priv.filemodel, emodel_load()); + evas_object_event_callback_add(win, EVAS_CALLBACK_DEL, _cleanup_cb, &priv); + + eo_do(priv.fileview, elm_view_list_property_connect("filename", "elm.text"), + elm_view_list_property_connect("mtime", "elm.text.sub")); + + evas_object_resize(win, 320, 520); + elm_win_resize_object_add(win, genlist); + evas_object_show(win); + + elm_run(); + + elm_shutdown(); + ecore_shutdown(); + + return 0; +} +ELM_MAIN() + diff --git a/src/lib/Elementary.h.in b/src/lib/Elementary.h.in index 6e87bf0bb..5c5753bf0 100644 --- a/src/lib/Elementary.h.in +++ b/src/lib/Elementary.h.in @@ -258,6 +258,8 @@ EAPI extern Elm_Version *elm_version; #include <elm_toolbar.h> #include <elm_transit.h> #include <elm_video.h> +#include <elm_view_list.h> +#include <elm_view_form.h> #include <elm_web.h> #include <elm_win.h> diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am index cd283800e..d032ff93c 100644 --- a/src/lib/Makefile.am +++ b/src/lib/Makefile.am @@ -376,6 +376,8 @@ elm_transit.h \ elm_video.h \ elm_video_eo.h \ elm_video_legacy.h \ +elm_view_list.h \ +elm_view_form.h \ elm_web.h \ elm_web_common.h \ elm_web_eo.h \ @@ -492,6 +494,8 @@ elm_transit.c \ elm_util.c \ elm_url.c \ elm_video.c \ +elm_view_list.c \ +elm_view_form.c \ elm_web2.c \ elm_widget.c \ elm_win.c \ @@ -601,6 +605,8 @@ elm_table.eo \ elm_thumb.eo \ elm_toolbar.eo \ elm_video.eo \ +elm_view_list.eo \ +elm_view_form.eo \ elm_web.eo \ elm_widget.eo \ elm_win.eo \ diff --git a/src/lib/elm_view_form.c b/src/lib/elm_view_form.c new file mode 100644 index 000000000..24a33cebf --- /dev/null +++ b/src/lib/elm_view_form.c @@ -0,0 +1,259 @@ +#ifdef HAVE_CONFIG_H +# include "elementary_config.h" +#endif +#include <Eo.h> +#include <Emodel.h> +#include <Elementary.h> + +#include "elm_view_form.h" +#include "elm_view_list.h" + +#include "elm_priv.h" +#include <assert.h> + +#define MY_CLASS ELM_VIEW_FORM_CLASS +#define MY_CLASS_NAME "View_Form" + +typedef struct _Elm_View_Form_Data Elm_View_Form_Data; +typedef struct _Elm_View_Form_Widget Elm_View_Form_Widget; + +/** + * @brief Local-use callbacks + */ +typedef void (*Elm_View_Form_Event_Cb)(Elm_View_Form_Widget *, Elm_View_Form_Data *, Evas_Object *); +typedef void (*Elm_View_Form_Widget_Object_Set_Cb)(Eo *, Evas_Object *, Eina_Value *, const char *); + +struct _Elm_View_Form_Widget +{ + Eina_Stringshare *widget_propname; + Evas_Object *widget_obj; + Elm_View_Form_Event_Cb widget_obj_value_update_cb; + Elm_View_Form_Widget_Object_Set_Cb widget_obj_set_cb; +}; + +struct _Elm_View_Form_Data +{ + Eo *model_obj; + Eina_Value *properties; + Eina_List *l; +}; + +static Eina_Bool +_emodel_properties_change_cb(void *data, Eo *obj EINA_UNUSED, const Eo_Event_Description *desc EINA_UNUSED, void *event_info) +{ + const Emodel_Property_Event *evt = event_info; + Elm_View_Form_Data *priv = data; + Emodel_Property_Pair *pair = NULL; + Eina_List *l, *fe = NULL; + Elm_View_Form_Widget *w = NULL; + + EINA_SAFETY_ON_NULL_RETURN_VAL(priv, EINA_TRUE); + EINA_SAFETY_ON_NULL_RETURN_VAL(evt, EINA_TRUE); + + //update all widgets with this property + EINA_LIST_FOREACH(priv->l, l, w) + { + EINA_LIST_FOREACH(evt->changed_properties, fe, pair) + { + if(w->widget_propname == pair->property) + { + w->widget_obj_set_cb(priv->model_obj, w->widget_obj, &pair->value, pair->property); + break; + } + } + } + + return EINA_TRUE; +} + +static void +_update_model_properties(Elm_View_Form_Data *priv) +{ + Eina_Value value; + Eina_List *l; + Elm_View_Form_Widget *w; + //update all widgets property + EINA_LIST_FOREACH(priv->l, l, w) + { + eo_do(priv->model_obj, emodel_property_get(w->widget_propname, &value)); + w->widget_obj_set_cb(priv->model_obj, w->widget_obj, &value, w->widget_propname); + eina_value_flush(&value); + } +} + +/** + * @brief Set widget. + * Works, so far, for widget(s): Entry, Label + */ +static void +_elm_evas_object_text_set_cb(Eo *obj EINA_UNUSED, Evas_Object *widget, Eina_Value *value, const char *propname EINA_UNUSED) +{ + char *text = eina_value_to_string(value); + const char *c_text = elm_object_text_get(widget); + EINA_SAFETY_ON_NULL_RETURN(text); + + if (strcmp(text, c_text) != 0) + { + elm_object_text_set(widget, text); + } + free(text); +} + +static void +_elm_evas_object_thumb_set_cb(Eo *obj EINA_UNUSED, Evas_Object *thumb, Eina_Value *value, const char *propname EINA_UNUSED) +{ + char *filename = eina_value_to_string(value); + EINA_SAFETY_ON_NULL_RETURN(filename); + EINA_SAFETY_ON_TRUE_RETURN(strlen(filename) >= PATH_MAX); + + elm_thumb_file_set(thumb, filename, NULL); + elm_thumb_reload(thumb); + free(filename); +} + +/** + * @brief Evas object callback implementation. + * Updates Widget's value if not the same object + * and the widget itself. + */ +static void +_elm_evas_object_text_changed_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED) +{ + Eina_Value value; + Eina_List *l; + Elm_View_Form_Data *priv = (Elm_View_Form_Data *)data; + Elm_View_Form_Widget *w = NULL; + + EINA_LIST_FOREACH(priv->l, l, w) + { + if (w->widget_obj == obj) + break; + } + + EINA_SAFETY_ON_NULL_RETURN(w); + eina_value_setup(&value, EINA_VALUE_TYPE_STRING); + eina_value_set(&value, elm_object_text_get(obj)); + eo_do(priv->model_obj, emodel_property_set(w->widget_propname, value)); + eina_value_flush(&value); +} +/** + * @brief Add new widget object. + * Adds new widget object on the list + * and perform initial setup. + */ +static Eina_Bool +_elm_view_widget_add(Elm_View_Form_Data *priv, const char *propname, Evas_Object *widget_obj) +{ + Eina_Value value; + Elm_View_Form_Widget *w = calloc(1, sizeof(Elm_View_Form_Widget)); + EINA_SAFETY_ON_NULL_RETURN_VAL(w, EINA_FALSE); + + w->widget_propname = eina_stringshare_add(propname); + w->widget_obj = widget_obj; + priv->l = eina_list_append(priv->l, w); + + if(eo_isa(widget_obj, ELM_ENTRY_CLASS)) + { + w->widget_obj_set_cb = _elm_evas_object_text_set_cb; + evas_object_event_callback_add(w->widget_obj, EVAS_CALLBACK_KEY_DOWN, _elm_evas_object_text_changed_cb, priv); + } + else if(eo_isa(widget_obj, ELM_LABEL_CLASS)) + { + w->widget_obj_set_cb = _elm_evas_object_text_set_cb; + } + else if(eo_isa(widget_obj, ELM_THUMB_CLASS)) + { + w->widget_obj_set_cb = _elm_evas_object_thumb_set_cb; + } + else + { + // Widget yet not supported + EINA_SAFETY_ON_NULL_RETURN_VAL(NULL, EINA_FALSE); + } + + if (eo_do(priv->model_obj, emodel_property_get(propname, &value)) == EINA_TRUE) + { + w->widget_obj_set_cb(priv->model_obj, w->widget_obj, &value, w->widget_propname); + eina_value_flush(&value); + } + + return EINA_TRUE; +} +/** + * Helper functions - End + */ + + +/** + * @brief constructor + */ +static void +_elm_view_form_constructor(Eo *obj, Elm_View_Form_Data *_pd, Eo *model) +{ + Elm_View_Form_Data *priv = (Elm_View_Form_Data *)_pd; + eo_do_super(obj, MY_CLASS, eo_constructor()); + priv->model_obj = model; + if (priv->model_obj != NULL) + { + eo_ref(priv->model_obj); + eo_do(priv->model_obj, eo_event_callback_add(EMODEL_EVENT_PROPERTIES_CHANGED, _emodel_properties_change_cb, priv)); + } +} + +static void +_elm_view_form_eo_base_constructor(Eo *obj, Elm_View_Form_Data *_pd EINA_UNUSED) +{ + eo_error_set(obj); + fprintf(stderr, "only custom constructor can be used with '%s' class", MY_CLASS_NAME); +} + + +/** + * @brief destructor + */ +static void +_elm_view_form_eo_base_destructor(Eo *obj, Elm_View_Form_Data *priv) +{ + Elm_View_Form_Widget *w = NULL; + EINA_LIST_FREE(priv->l, w) + { + eina_stringshare_del(w->widget_propname); + free(w); + } + + eo_do_super(obj, MY_CLASS, eo_destructor()); +} + + +static void +_elm_view_form_model_set(Eo *obj EINA_UNUSED, Elm_View_Form_Data *priv, Eo *model) +{ + if (priv->model_obj != NULL) + { + eo_do(priv->model_obj, eo_event_callback_del(EMODEL_EVENT_PROPERTIES_CHANGED, _emodel_properties_change_cb, priv)); + eo_unref(priv->model_obj); + } + + priv->model_obj = model; + + if (priv->model_obj != NULL) + { + eo_ref(priv->model_obj); + eo_do(priv->model_obj, eo_event_callback_add(EMODEL_EVENT_PROPERTIES_CHANGED, _emodel_properties_change_cb, priv)); + _update_model_properties(priv); + } +} + +static void +_elm_view_form_widget_add(Eo *obj EINA_UNUSED, Elm_View_Form_Data *priv, const char *propname, Evas_Object *evas) +{ + Eina_Bool status; + + EINA_SAFETY_ON_NULL_RETURN(evas); + EINA_SAFETY_ON_NULL_RETURN(propname); + + status = _elm_view_widget_add(priv, propname, evas); + EINA_SAFETY_ON_FALSE_RETURN(status); +} + +#include "elm_view_form.eo.c" diff --git a/src/lib/elm_view_form.eo b/src/lib/elm_view_form.eo new file mode 100644 index 000000000..aa6528d85 --- /dev/null +++ b/src/lib/elm_view_form.eo @@ -0,0 +1,38 @@ +class Elm_View_Form (Eo.Base) +{ + legacy_prefix: null; + methods { + constructor { + /*@ Constructor wrapper + @def elm_view_form_constructor + @since 1.11 */ + params { + @in Eo *model; /*@ Emodel object */ + } + } + model_set { + /*@ Set model + @def elm_view_form_model_set + @since 1.11 */ + params { + @in Eo *model; /*@ Emodel object */ + } + } + widget_add { + /*@ Add new widget + @def elm_view_form_widget_add + @since 1.11 */ + params { + @in const(char)* propname; /*@ Property name */ + @in Evas_Object *evas; /*@ Evas widget */ + } + } + } + implements { + Eo.Base.destructor; + Eo.Base.constructor; + } + constructors { + .constructor; + } +} diff --git a/src/lib/elm_view_form.h b/src/lib/elm_view_form.h new file mode 100644 index 000000000..08764682e --- /dev/null +++ b/src/lib/elm_view_form.h @@ -0,0 +1,5 @@ +#ifndef ELM_VIEW_FORM_H +#define ELM_VIEW_FORM_H + +#include <elm_view_form.eo.h> +#endif diff --git a/src/lib/elm_view_list.c b/src/lib/elm_view_list.c new file mode 100644 index 000000000..aeb6c4c5f --- /dev/null +++ b/src/lib/elm_view_list.c @@ -0,0 +1,433 @@ +#ifdef HAVE_CONFIG_H +# include "elementary_config.h" +#endif +#include <Eo.h> +#include <Emodel.h> +#include <Elementary.h> + +#include "elm_priv.h" +#include <assert.h> + +#define MY_CLASS ELM_VIEW_LIST_CLASS +#define MY_CLASS_NAME "View List" + +struct _Elm_View_List_Data; +typedef struct _Elm_View_List_Data Elm_View_List_Data; + +struct _View_List_ItemData; +typedef struct _View_List_ItemData View_List_ItemData; + +struct _Elm_View_List_Data +{ + Eo *view; + Evas_Object *genlist; + View_List_ItemData *rootdata; + Elm_Genlist_Item_Class *itc; + Elm_Genlist_Item_Type itype; + Eina_Hash *prop_con; + Eo *model; +}; + +struct _View_List_ItemData +{ + Elm_View_List_Data *priv; + Elm_Object_Item *item; + Eo *model; + View_List_ItemData *parent; + Emodel_Load_Status status; +}; + +static void _emodel_load_children(View_List_ItemData *); +static Eina_Bool _emodel_load_status_change_cb(void *, Eo *, const Eo_Event_Description *, void *); +static Eina_Bool _emodel_children_count_change_cb(void *, Eo *, const Eo_Event_Description *, void *); +static Eina_Bool _emodel_properties_change_cb(void *, Eo *, const Eo_Event_Description *, void *); + +/* --- Genlist Callbacks --- */ +static void +_item_sel_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) +{ + View_List_ItemData *idata = data; + + EINA_SAFETY_ON_NULL_RETURN(data); + + eo_do(idata->priv->view, eo_event_callback_call(ELM_VIEW_LIST_EVENT_MODEL_SELECTED, idata->model)); +} + +static void +_item_del(void *data, Evas_Object *obj EINA_UNUSED) +{ + View_List_ItemData *idata = data; + if (idata) { + eo_do(idata->model, eo_event_callback_del(EMODEL_EVENT_PROPERTIES_CHANGED, _emodel_properties_change_cb, idata)); + eo_do(idata->model, eo_event_callback_del(EMODEL_EVENT_LOAD_STATUS, _emodel_load_status_change_cb, idata)); + eo_do(idata->model, eo_event_callback_del(EMODEL_EVENT_CHILDREN_COUNT_CHANGED, _emodel_children_count_change_cb, idata)); + eo_unref(idata->model); + idata->model = NULL; + idata->item = NULL; + idata->parent = NULL; + idata->priv = NULL; + } + free(idata); +} + +static Evas_Object * +_item_content_get(void *data, Evas_Object *obj EINA_UNUSED, const char *part) +{ + //XXX: Add a Custon content function?? + Eina_Value value; + const Eina_Value_Type *vtype; + Evas_Object *content = NULL; + View_List_ItemData *idata = data; + EINA_SAFETY_ON_NULL_RETURN_VAL(data, NULL); + EINA_SAFETY_ON_NULL_RETURN_VAL(part, NULL); + Elm_View_List_Data *priv = idata->priv; + + const char *prop = eina_hash_find(priv->prop_con, part); + if (prop == NULL) prop = part; + + eina_value_setup(&value, EINA_VALUE_TYPE_STRING); + eo_do(idata->model, emodel_property_get(prop, &value)); + vtype = eina_value_type_get(&value); + if (vtype == EINA_VALUE_TYPE_STRING || vtype == EINA_VALUE_TYPE_STRINGSHARE) + { + char *content_s; + eina_value_get(&value, &content_s); + content = elm_icon_add(obj); + if (elm_icon_standard_set(content, content_s)) + { + evas_object_size_hint_aspect_set(content, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1); + } + else + { + evas_object_del(content); + content = NULL; + } + } else + if (vtype == EINA_VALUE_TYPE_BLOB) + { + Eina_Value_Blob out; + eina_value_get(&value, &out); + if (out.memory != NULL) + { + content = elm_image_add(obj); + + elm_image_memfile_set(content, out.memory, out.size, NULL, NULL); + } + } + eina_value_flush(&value); + + return content; +} + +static char * +_item_text_get(void *data, Evas_Object *obj EINA_UNUSED, const char *part) +{ + Eina_Value value; + char *text = NULL; + View_List_ItemData *idata = data; + + EINA_SAFETY_ON_NULL_RETURN_VAL(data, NULL); + EINA_SAFETY_ON_NULL_RETURN_VAL(part, NULL); + Elm_View_List_Data *priv = idata->priv; + EINA_SAFETY_ON_NULL_RETURN_VAL(idata->model, NULL); + + const char *prop = eina_hash_find(priv->prop_con, part); + if (prop == NULL) prop = part; + + eina_value_setup(&value, EINA_VALUE_TYPE_STRING); + eo_do(idata->model, emodel_property_get(prop, &value)); + if (eina_value_type_get(&value) == EINA_VALUE_TYPE_STRING) + { + text = eina_value_to_string(&value); + } + eina_value_flush(&value); + + return text; +} + +static void +_expand_request_cb(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info) +{ + Elm_Object_Item *item = event_info; + View_List_ItemData *idata = elm_object_item_data_get(item); + Emodel_Load_Status st; + + eo_do(idata->model, st = emodel_load_status_get()); + eo_do(idata->model, eo_event_callback_add(EMODEL_EVENT_LOAD_STATUS, _emodel_load_status_change_cb, idata)); + eo_do(idata->model, eo_event_callback_add(EMODEL_EVENT_CHILDREN_COUNT_CHANGED, _emodel_children_count_change_cb, idata)); + if (st & EMODEL_LOAD_STATUS_LOADED_CHILDREN) + { + _emodel_load_children(idata); + } + else + { + eo_do(idata->model, emodel_children_load()); + } +} + +static void +_contract_request_cb(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info) +{ + Elm_Object_Item *item = event_info; + View_List_ItemData *idata = elm_object_item_data_get(item); + + eo_do(idata->model, eo_event_callback_del(EMODEL_EVENT_LOAD_STATUS, _emodel_load_status_change_cb, idata)); + eo_do(idata->model, eo_event_callback_del(EMODEL_EVENT_CHILDREN_COUNT_CHANGED, _emodel_children_count_change_cb, idata)); + elm_genlist_item_expanded_set(item, EINA_FALSE); +} + +static void +_contracted_cb(void *data EINA_UNUSED, Evas_Object *o EINA_UNUSED, void *event_info) +{ + Elm_Object_Item *glit = event_info; + elm_genlist_item_subitems_clear(glit); +} + +static void +_genlist_deleted(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED) +{ + Elm_View_List_Data *priv = data; + + if (priv && priv->genlist && priv->genlist == obj) + { + evas_object_smart_callback_del(priv->genlist, "expand,request", _expand_request_cb); + evas_object_smart_callback_del(priv->genlist, "contract,request", _contract_request_cb); + evas_object_smart_callback_del(priv->genlist, "contracted", _contracted_cb); + eo_unref(priv->genlist); + priv->genlist = NULL; + } +} + + +/* --- Emodel Callbacks --- */ +static Eina_Bool +_emodel_properties_change_cb(void *data, Eo *obj EINA_UNUSED, const Eo_Event_Description *desc EINA_UNUSED, void *event_info) +{ + View_List_ItemData *idata = data; + Emodel_Property_Event *evt = event_info; + + EINA_SAFETY_ON_NULL_RETURN_VAL(idata, EINA_TRUE); + EINA_SAFETY_ON_NULL_RETURN_VAL(evt, EINA_TRUE); + + if (idata->item) + elm_genlist_item_update(idata->item); + + return EINA_TRUE; +} + +static void +_emodel_load_children(View_List_ItemData *pdata) +{ + Eo *child; + Eina_Accessor *accessor; + Elm_View_List_Data *priv = pdata->priv; + unsigned int total, i; + + eo_do(pdata->model, emodel_children_count_get(&total)); + if (total == 0) + return; + + eo_do(pdata->model, emodel_children_slice_get(0 ,0 ,(Eina_Accessor **)&accessor)); + + EINA_SAFETY_ON_NULL_RETURN(accessor); + + EINA_ACCESSOR_FOREACH(accessor, i, child) + { + View_List_ItemData *idata = malloc(sizeof(View_List_ItemData)); + memset(idata, 0, sizeof(View_List_ItemData)); + EINA_SAFETY_ON_NULL_RETURN(idata); + idata->priv = priv; + idata->parent = pdata; + idata->model = child; + eo_ref(child); + eo_do(child, eo_event_callback_add(EMODEL_EVENT_PROPERTIES_CHANGED, _emodel_properties_change_cb, idata)); + eo_do(child, emodel_properties_load()); + idata->item = elm_genlist_item_append(priv->genlist, priv->itc, idata, pdata->item, + priv->itype, _item_sel_cb, idata); + } + + if (pdata->item) + { + elm_genlist_item_expanded_set(pdata->item, EINA_TRUE); + } +} + +static Eina_Bool +_emodel_children_count_change_cb(void *data, Eo *obj EINA_UNUSED, const Eo_Event_Description *desc EINA_UNUSED, void *event_info EINA_UNUSED) +{ + View_List_ItemData *idata = data; + EINA_SAFETY_ON_NULL_RETURN_VAL(idata, EINA_FALSE); + EINA_SAFETY_ON_NULL_RETURN_VAL(idata->priv, EINA_FALSE); + EINA_SAFETY_ON_NULL_RETURN_VAL(idata->priv->genlist, EINA_FALSE); + + eo_do(idata->priv->genlist, elm_obj_genlist_clear()); + + _emodel_load_children(idata); + + return EINA_TRUE; +} + +static Eina_Bool +_emodel_load_status_change_cb(void *data, Eo *obj EINA_UNUSED, const Eo_Event_Description *desc EINA_UNUSED, void *event_info) +{ + View_List_ItemData *idata = data; + Emodel_Load *load = event_info; + +/* if ((load->status & EMODEL_LOAD_STATUS_LOADED_CHILDREN) + && !(data->status & EMODEL_LOAD_STATUS_LOADED_CHILDREN)) + { + _emodel_load_children(idata); + } + else +*/ + if (load->status & EMODEL_LOAD_STATUS_UNLOADED) + { + if (idata->item) + elm_genlist_item_expanded_set(idata->item, EINA_FALSE); + } + + idata->status = load->status; + return EINA_TRUE; +} + +static void +_priv_model_set(Elm_View_List_Data *priv, Eo *model) +{ + Emodel_Load_Status load_st; + + if (priv->model != NULL) + { + eo_do(priv->model, eo_event_callback_del(EMODEL_EVENT_LOAD_STATUS, + _emodel_load_status_change_cb, priv->rootdata)); + eo_do(priv->model, eo_event_callback_del(EMODEL_EVENT_CHILDREN_COUNT_CHANGED, + _emodel_children_count_change_cb, priv->rootdata)); + eo_do(priv->genlist, elm_obj_genlist_clear()); + eo_unref(priv->model); + priv->model = NULL; + } + + if (model == NULL) + return; + + priv->model = model; + priv->rootdata->model = priv->model; + eo_ref(priv->model); + + eo_do(priv->model, eo_event_callback_add(EMODEL_EVENT_LOAD_STATUS, + _emodel_load_status_change_cb, priv->rootdata)); + eo_do(priv->model, eo_event_callback_add(EMODEL_EVENT_CHILDREN_COUNT_CHANGED, + _emodel_children_count_change_cb, priv->rootdata)); + eo_do(priv->model, load_st = emodel_load_status_get()); + if (load_st & EMODEL_LOAD_STATUS_LOADED_CHILDREN) + { + _emodel_load_children(priv->rootdata); + } +} + +/** + * @brief Elm View List Class impl. + */ +static void +_elm_view_list_constructor(Eo *obj, Elm_View_List_Data *priv, Evas_Object *genlist, Elm_Genlist_Item_Type itype, const char *istyle) +{ + eo_do_super(obj, MY_CLASS, eo_constructor()); + + priv->view = obj; + priv->genlist = genlist; + priv->itype = itype; + EINA_SAFETY_ON_NULL_RETURN(priv->genlist); + eo_ref(priv->genlist); + + priv->rootdata = calloc(1, sizeof(View_List_ItemData)); + priv->rootdata->priv = priv; + + priv->itc = elm_genlist_item_class_new(); + priv->itc->item_style = strdup(istyle); + priv->itc->func.text_get = _item_text_get; + priv->itc->func.content_get = _item_content_get; + priv->itc->func.state_get = NULL; + priv->itc->func.del = _item_del; + priv->prop_con = eina_hash_string_superfast_new(free); + + evas_object_smart_callback_add(priv->genlist, "expand,request", _expand_request_cb, priv); + evas_object_smart_callback_add(priv->genlist, "contract,request", _contract_request_cb, priv); + evas_object_smart_callback_add(priv->genlist, "contracted", _contracted_cb, priv); + evas_object_event_callback_add(priv->genlist, EVAS_CALLBACK_DEL, _genlist_deleted, priv); +} + + +static void +_elm_view_list_eo_base_destructor(Eo *obj, Elm_View_List_Data *priv) +{ + EINA_SAFETY_ON_NULL_RETURN(priv); + EINA_SAFETY_ON_NULL_RETURN(obj); + + eo_do(priv->model, eo_event_callback_del(EMODEL_EVENT_LOAD_STATUS, + _emodel_load_status_change_cb, priv->rootdata)); + eo_do(priv->model, eo_event_callback_del(EMODEL_EVENT_CHILDREN_COUNT_CHANGED, + _emodel_children_count_change_cb, priv->rootdata)); + + eo_do(priv->genlist, elm_obj_genlist_clear()); + elm_genlist_item_class_free(priv->itc); + + eina_hash_free(priv->prop_con); + free(priv->rootdata); + priv->rootdata = NULL; + if (priv->genlist) { + evas_object_event_callback_del(priv->genlist, EVAS_CALLBACK_DEL, _genlist_deleted); + evas_object_smart_callback_del(priv->genlist, "expand,request", _expand_request_cb); + evas_object_smart_callback_del(priv->genlist, "contract,request", _contract_request_cb); + evas_object_smart_callback_del(priv->genlist, "contracted", _contracted_cb); + eo_unref(priv->genlist); + } + + eo_unref(priv->model); + + eo_do_super(obj, MY_CLASS, eo_destructor()); +} + +static void +_elm_view_list_evas_object_get(Eo *obj, Elm_View_List_Data *priv, Evas_Object **widget) +{ + EINA_SAFETY_ON_NULL_RETURN(priv); + EINA_SAFETY_ON_NULL_RETURN(obj); + EINA_SAFETY_ON_NULL_RETURN(widget); + + *widget = priv->genlist; +} + +static void +_elm_view_list_property_connect(Eo *obj EINA_UNUSED, Elm_View_List_Data *priv, const char *property, const char *part) +{ + EINA_SAFETY_ON_NULL_RETURN(priv); + + EINA_SAFETY_ON_NULL_RETURN(priv->prop_con); + EINA_SAFETY_ON_NULL_RETURN(property); + EINA_SAFETY_ON_NULL_RETURN(part); + + free(eina_hash_set(priv->prop_con, part, strdup(property))); +} + +static void +_elm_view_list_model_set(Eo *obj EINA_UNUSED, Elm_View_List_Data *priv, Emodel *model) +{ + EINA_SAFETY_ON_NULL_RETURN(priv); + EINA_SAFETY_ON_NULL_RETURN(model); + _priv_model_set(priv, model); +} + +static void +_elm_view_list_model_unset(Eo *obj EINA_UNUSED, Elm_View_List_Data *priv) +{ + EINA_SAFETY_ON_NULL_RETURN(priv); + _priv_model_set(priv, NULL); +} + +static void +_elm_view_list_model_get(Eo *obj EINA_UNUSED, Elm_View_List_Data *priv, Eo **model) +{ + EINA_SAFETY_ON_NULL_RETURN(priv); + EINA_SAFETY_ON_NULL_RETURN(model); + *model = priv->model; +} +#include "elm_view_list.eo.c" diff --git a/src/lib/elm_view_list.eo b/src/lib/elm_view_list.eo new file mode 100644 index 000000000..8516ce4d3 --- /dev/null +++ b/src/lib/elm_view_list.eo @@ -0,0 +1,77 @@ +class Elm_View_List (Eo.Base) +{ + legacy_prefix: null; + methods { + constructor { + /*@ Constructor wrapper + * + * @def elm_view_list_constructor + * @since 1.11 + */ + params { + Evas_Object * genlist; /*@ Genlist object */ + @in Elm_Genlist_Item_Type item_type; /*@ Item type */ + @in const(char)*item_style; /*@ The current item style name. @c NULL would be default. */ + } + } + evas_object_get { + /*@ Return evas object + * + * @def elm_view_list_evas_object_get + * @since 1.11 + */ + params { + @out Evas_Object *widget; /*@ Returned widget */ + } + } + property_connect { + /*@ Connect property + * + * @def elm_view_list_property_connect + * @since 1.11 + */ + params { + @in const(char)* property; /*@ Property name */ + @in const(char)* part; /*@ Edje's theme part */ + } + } + model_set { + /*@ Set model + * + * @def elm_view_list_model_set + * @since 1.11 + */ + params { + @in Emodel *model; /*@ New Emodel to set */ + } + } + model_unset { + /*@ Unset model + * + * @def elm_view_list_model_unset + * @since 1.11 + */ + } + model_get { + /*@ Get model + * + * @def elm_view_list_model_get + * @since 1.11 + */ + params { + @out Eo *model; /*@ Returned Emodel */ + } + } + } + + events { + model,selected; /*@ Event dispatch when a model is selected */ + } + + implements { + Eo.Base.destructor; + } + constructors { + .constructor; + } +} diff --git a/src/lib/elm_view_list.h b/src/lib/elm_view_list.h new file mode 100644 index 000000000..f1542defa --- /dev/null +++ b/src/lib/elm_view_list.h @@ -0,0 +1,9 @@ + +#ifdef EFL_EO_API_SUPPORT +#ifndef ELM_VIEW_LIST_H +#define ELM_VIEW_LIST_H + +#include <Emodel.h> +#include <elm_view_list.eo.h> +#endif +#endif // ELM_VIEW_LIST_H |