--- /dev/null
+#include "e_intern.h"
+#include "e_view_intern.h"
+#include "e_view_smart.h"
+#include "e_canvas_intern.h"
+
+struct _E_View_Smart
+{
+ E_View view;
+
+ struct
+ {
+ struct wl_signal resize;
+ } events;
+
+ int width;
+ int height;
+
+ const E_View_Smart_Class *sc;
+ void *data;
+};
+
+static E_View_Smart *_view_smart_from_view(E_View *view);
+static void _view_smart_handle_destroy(E_View *view);
+static void _view_smart_evas_object_cb_resize(void *data, Evas *e, Evas_Object *obj, void *event_info);
+
+const static E_View_Impl view_smart_impl = {
+ .destroy = _view_smart_handle_destroy,
+};
+
+static E_View_Smart *
+_view_smart_from_view(E_View *view)
+{
+ E_View_Smart *smart;
+ assert(view->impl == &view_smart_impl);
+ return wl_container_of(view, smart, view);
+}
+
+static void
+_view_smart_handle_destroy(E_View *view)
+{
+ E_View_Smart *smart = _view_smart_from_view(view);
+
+ evas_object_event_callback_del(smart->view.eo, EVAS_CALLBACK_RESIZE, _view_smart_evas_object_cb_resize);
+
+ evas_object_del(view->eo);
+ free(smart);
+}
+
+static void
+_view_smart_size_set(E_View_Smart *smart, int width, int height)
+{
+ smart->width = width;
+ smart->height = height;
+
+ evas_object_resize(smart->view.eo, width, height);
+}
+
+static void
+_view_smart_cb_add(Evas_Object *eo)
+{
+ E_View_Smart *smart = (E_View_Smart *)evas_object_smart_data_get(eo);
+
+ if (!smart) return;
+ if (smart->sc) smart->sc->add(smart);
+}
+
+static void
+_view_smart_cb_del(Evas_Object *eo)
+{
+ E_View_Smart *smart = (E_View_Smart *)evas_object_smart_data_get(eo);
+
+ if (!smart) return;
+ if (smart->sc) smart->sc->del(smart);
+}
+
+static void
+_view_smart_cb_move(Evas_Object *eo, Evas_Coord x, Evas_Coord y)
+{
+ E_View_Smart *smart = (E_View_Smart *)evas_object_smart_data_get(eo);
+
+ if (!smart) return;
+ if (smart->sc) smart->sc->move(smart, x, y);
+}
+
+static void
+_view_smart_cb_resize(Evas_Object *eo, Evas_Coord w, Evas_Coord h)
+{
+ E_View_Smart *smart = (E_View_Smart *)evas_object_smart_data_get(eo);
+
+ if (!smart) return;
+ if (smart->sc) smart->sc->move(smart, w, h);
+}
+
+static void
+_view_smart_cb_show(Evas_Object *eo)
+{
+ E_View_Smart *smart = (E_View_Smart *)evas_object_smart_data_get(eo);
+
+ if (!smart) return;
+ if (smart->sc) smart->sc->show(smart);
+}
+static void
+_view_smart_cb_hide(Evas_Object *eo)
+{
+ E_View_Smart *smart = (E_View_Smart *)evas_object_smart_data_get(eo);
+
+ if (!smart) return;
+ if (smart->sc) smart->sc->hide(smart);
+}
+
+static void
+_view_smart_cb_color_set(Evas_Object *eo, int r, int g, int b, int a)
+{
+ E_View_Smart *smart = (E_View_Smart *)evas_object_smart_data_get(eo);
+
+ if (!smart) return;
+ if (smart->sc) smart->sc->color_set(smart, r, g, b, a);
+}
+
+static void
+_view_smart_cb_clip_set(Evas_Object *eo, Evas_Object *clip)
+{
+ E_View_Smart *smart = (E_View_Smart *)evas_object_smart_data_get(eo);
+
+ if (!smart) return;
+ if (smart->sc) smart->sc->clip_set(smart, evas_object_data_get(clip, "e_view"));
+}
+
+static void
+_view_smart_cb_clip_unset(Evas_Object *eo)
+{
+ E_View_Smart *smart = (E_View_Smart *)evas_object_smart_data_get(eo);
+
+ if (!smart) return;
+ if (smart->sc) smart->sc->clip_unset(smart);
+}
+
+static void
+_view_smart_cb_calculate(Evas_Object *eo)
+{
+ E_View_Smart *smart = (E_View_Smart *)evas_object_smart_data_get(eo);
+
+ if (!smart) return;
+ if (smart->sc) smart->sc->calculate(smart);
+}
+static void
+_view_smart_cb_member_add(Evas_Object *eo, Evas_Object *child)
+{
+ E_View_Smart *smart = (E_View_Smart *)evas_object_smart_data_get(eo);
+ E_View *child_view = evas_object_data_get(child, "e_view");
+
+ if (!smart || !child_view) return;
+ if (smart->sc) smart->sc->member_add(smart, child_view);
+}
+
+static void
+_view_smart_cb_member_del(Evas_Object *eo, Evas_Object *child)
+{
+ E_View_Smart *smart = (E_View_Smart *)evas_object_smart_data_get(eo);
+ E_View *child_view = evas_object_data_get(child, "e_view");
+
+ if (!smart || !child_view) return;
+ if (smart->sc) smart->sc->member_del(smart, child_view);
+}
+
+static void
+_view_smart_evas_object_cb_resize(void *data, Evas *e, Evas_Object *obj, void *event_info)
+{
+ E_View_Smart *smart = (E_View_Smart *)data;
+ int width, height;
+
+ // smart callback is called before resizing
+ // but event callback is called after resizing done.
+ evas_object_geometry_get(smart->view.eo, NULL, NULL, &width, &height);
+ if (width != smart->width || height!= smart->height)
+ {
+ ERR("e_view_smart(%p) size mismatched: %dx%d != %dx%d", smart,
+ smart->width, smart->height, width, height);
+
+ // FIXME: set the size of evas_object to the size of smart
+ // for avoiding regression.
+ smart->width = width;
+ smart->height = height;
+ }
+
+ wl_signal_emit_mutable(&smart->events.resize, smart);
+}
+
+E_API E_View_Smart *
+e_view_smart_create(E_View_Tree *parent, const E_View_Smart_Class *sc)
+{
+ E_Canvas *canvas;
+ E_View_Smart *smart;
+ Evas_Smart_Class* esc;
+ Evas_Smart *es;
+ Evas_Object *eo;
+
+ assert(parent != NULL);
+
+ esc = malloc(sizeof(Evas_Smart_Class));
+ if (!esc) return NULL;
+
+ esc->name = sc->name;
+ esc->version = EVAS_SMART_CLASS_VERSION;
+ esc->add = _view_smart_cb_add;
+ esc->del = _view_smart_cb_del;
+ esc->move = _view_smart_cb_move;
+ esc->resize = _view_smart_cb_resize;
+ esc->show = _view_smart_cb_show;
+ esc->hide = _view_smart_cb_hide;
+ esc->color_set = _view_smart_cb_color_set;
+ esc->clip_set = _view_smart_cb_clip_set;
+ esc->clip_unset = _view_smart_cb_clip_unset;
+ esc->calculate = _view_smart_cb_calculate;
+ esc->member_add = _view_smart_cb_member_add;
+ esc->member_del = _view_smart_cb_member_del;
+ esc->parent = NULL;
+ esc->callbacks = NULL;
+ esc->interfaces = NULL;
+ esc->data = NULL;
+
+ es = evas_smart_class_new(esc);
+ if (!es)
+ {
+ free(esc);
+ return NULL;
+ }
+
+ canvas = e_canvas_get(&parent->view);
+ eo = evas_object_smart_add(canvas->evas, es);
+ if (!eo)
+ {
+ free(esc);
+ evas_smart_free(es);
+ return NULL;
+ }
+
+ smart = malloc(sizeof(*smart));
+ if (!smart)
+ {
+ free(esc);
+ evas_object_del(eo);
+ evas_smart_free(es);
+ return NULL;
+ }
+
+ smart->sc = sc;
+ smart->data = NULL;
+ evas_object_smart_data_set(eo, smart);
+
+ e_view_init(&smart->view, E_VIEW_TYPE_SMART, (E_View_Impl*)&view_smart_impl, eo, parent);
+
+ _view_smart_size_set(smart, 0, 0);
+ wl_signal_init(&smart->events.resize);
+
+ evas_object_event_callback_add(smart->view.eo, EVAS_CALLBACK_RESIZE, _view_smart_evas_object_cb_resize, smart);
+
+ return smart;
+}
+
+E_API E_View *
+e_view_smart_view_get(E_View_Smart *smart)
+{
+ if (smart == NULL) return NULL;
+
+ return &smart->view;
+}
+
+E_API E_View_Smart *
+e_view_smart_try_from_view(E_View *view)
+{
+ if (view == NULL) return NULL;
+
+ if (view->impl != &view_smart_impl)
+ return NULL;
+
+ return _view_smart_from_view(view);
+}
+
+E_API void
+e_view_smart_size_set(E_View_Smart *smart, int width, int height)
+{
+ if (smart == NULL) return;
+ if (smart->width == width && smart->height == height)
+ return;
+
+ _view_smart_size_set(smart, width, height);
+}
+
+E_API void
+e_view_smart_size_get(E_View_Smart *smart, int *width, int *height)
+{
+ if (smart == NULL) return;
+
+ if (width) *width = smart->width;
+ if (height) *height = smart->height;
+}
+
+E_API void
+e_view_smart_resize_listener_add(E_View_Smart *smart, struct wl_listener *listener)
+{
+ wl_signal_add(&smart->events.resize, listener);
+}
+
+E_API void
+e_view_smart_data_set(E_View_Smart* smart, void *data)
+{
+ if (!smart) return;
+
+ smart->data = data;
+}
+
+E_API void *
+e_view_smart_data_get(E_View_Smart* smart)
+{
+ if (!smart) return NULL;
+
+ return smart->data;
+}
+
+E_API void
+e_view_smart_member_add(E_View_Smart* smart, E_View *member)
+{
+ evas_object_smart_member_add(member->eo, smart->view.eo);
+}
+
+E_API void
+e_view_smart_member_del(E_View *member)
+{
+ evas_object_smart_member_del(member->eo);
+}
--- /dev/null
+#ifndef E_VIEW_SMART_H
+#define E_VIEW_SMART_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <e_view.h>
+
+typedef struct _E_View_Smart E_View_Smart;
+
+/**< smart class's callback is called before object's action */
+typedef struct _E_View_Smart_Class
+{
+ const char *name; /**< the name string of the class */
+ void (*add)(E_View_Smart *o); /**< code to be run when adding object to a canvas */
+ void (*del)(E_View_Smart *o); /**< code to be run when removing object from a canvas */
+ void (*move)(E_View_Smart *o, int x, int y); /**< code to be run when moving object on a canvas. @a x and @a y will be new coordinates one applied to the object. use e_view_position_get() if you need the old values, during this call. after that, the old values will be lost. */
+ void (*resize)(E_View_Smart *o, int w, int h); /**< code to be run when resizing object on a canvas. @a w and @a h will be new dimensions one applied to the object. use e_view_<object>_size_get() if you need the old values, during this call. after that, the old values will be lost. */
+ void (*show)(E_View_Smart *o); /**< code to be run when showing object on a canvas */
+ void (*hide)(E_View_Smart *o); /**< code to be run when hiding object on a canvas */
+ void (*color_set)(E_View_Smart *o, int r, int g, int b, int a); /**< code to be run when setting color of object on a canvas. @a r, @a g, @a b and @a a will be new color components one applied to the object. use e_view_color_get() if you need the old values, during this call. after that, the old values will be lost. */
+ void (*clip_set)(E_View_Smart *o, E_View *clip); /**< code to be run when setting clipper of object on a canvas. @a clip will be new clipper one applied to the object. use e_view_clip_get() if you need the old one, during this call. after that, the old (object pointer) value will be lost. */
+ void (*clip_unset)(E_View_Smart *o); /**< code to be run when unsetting clipper of object on a canvas. if you need the pointer to a previous set clipper, during this call, use e_view_clip_get(). after that, the old (object pointer) value will be lost. */
+ void (*calculate)(E_View_Smart *o); /**< code to be run when object has rendering updates on a canvas */
+ void (*member_add)(E_View_Smart *o, E_View *child); /**< code to be run when a child member is added to object */
+ void (*member_del)(E_View_Smart *o, E_View *child); /**< code to be run when a child member is removed from object */
+} E_View_Smart_Class;
+
+E_API E_View_Smart* e_view_smart_create(E_View_Tree *parent, const E_View_Smart_Class *sc);
+
+E_API E_View *e_view_smart_view_get(E_View_Smart *smart);
+
+E_API E_View_Smart* e_view_smart_try_from_view(E_View *view);
+
+E_API void e_view_smart_size_set(E_View_Smart *smart, int width, int height);
+
+E_API void e_view_smart_size_get(E_View_Smart *smart, int *width, int *height);
+
+E_API void e_view_smart_resize_listener_add(E_View_Smart *smart, struct wl_listener *listener);
+
+E_API void e_view_smart_data_set(E_View_Smart* smart, void *data);
+
+E_API void *e_view_smart_data_get(E_View_Smart* smart);
+
+E_API void e_view_smart_member_add(E_View_Smart* smart, E_View *member);
+
+E_API void e_view_smart_member_del(E_View *member);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif