From c5b87e27f09a82228c61cd47714cc760ab01132c Mon Sep 17 00:00:00 2001 From: Jean-Philippe Andre Date: Wed, 13 Dec 2017 17:44:17 +0900 Subject: __WIP__ --- src/Makefile_Elementary.am | 1 + src/bin/elementary/test.c | 11 +- src/bin/elementary/test_progressbar.c | 25 +++ src/lib/elementary/Elementary.h | 1 + src/lib/elementary/efl_ui_layout.c | 2 + src/lib/elementary/efl_ui_widget_part_shadow.eo | 31 +++ src/lib/elementary/elm_widget.c | 267 ++++++++++++++++++++++++ src/lib/elementary/elm_widget.eo | 3 + src/lib/elementary/elm_widget.h | 1 + src/lib/evas/canvas/efl_canvas_proxy.c | 3 +- 10 files changed, 340 insertions(+), 5 deletions(-) create mode 100644 src/lib/elementary/efl_ui_widget_part_shadow.eo diff --git a/src/Makefile_Elementary.am b/src/Makefile_Elementary.am index 4c78215646..49e2d6818b 100644 --- a/src/Makefile_Elementary.am +++ b/src/Makefile_Elementary.am @@ -74,6 +74,7 @@ elm_public_eolian_files = \ lib/elementary/efl_ui_textpath_part.eo \ lib/elementary/efl_ui_widget_part.eo \ lib/elementary/efl_ui_widget_part_bg.eo \ + lib/elementary/efl_ui_widget_part_shadow.eo \ lib/elementary/efl_ui_win_part.eo \ lib/elementary/efl_access.eo \ lib/elementary/efl_access_action.eo \ diff --git a/src/bin/elementary/test.c b/src/bin/elementary/test.c index 8a592ab7d2..f336c3eb70 100644 --- a/src/bin/elementary/test.c +++ b/src/bin/elementary/test.c @@ -507,11 +507,14 @@ _menu_create(const char *option_str) elm_object_part_content_set(bt, "icon", ic); evas_object_show(ic); } - else if (t->is_eo) + if (t->is_eo) { - ic = efl_add(EFL_UI_IMAGE_CLASS, win, - efl_ui_image_icon_set(efl_added, "user-bookmarks")); - elm_object_part_content_set(bt, "icon", ic); + Eo *shadow = efl_ref(efl_part(bt, "shadow")); + efl_gfx_color_set(shadow, 0, 128, 255, 255); + efl_ui_widget_part_shadow_offset_set(shadow, 0, 0); + efl_ui_widget_part_shadow_radius_set(shadow, 3, 3); + efl_ui_widget_part_shadow_grow_set(shadow, 2); + efl_unref(shadow); } elm_box_pack_end(tbx2, bt); evas_object_show(bt); diff --git a/src/bin/elementary/test_progressbar.c b/src/bin/elementary/test_progressbar.c index 91282c0cde..1d2f325e5b 100644 --- a/src/bin/elementary/test_progressbar.c +++ b/src/bin/elementary/test_progressbar.c @@ -185,10 +185,28 @@ test_progressbar(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *eve evas_object_show(pb); pd->pb5 = pb; +#define FILTER_CODE \ + "a = buffer { 'alpha' }" \ + "grow { 4, dst = a }" \ + "blur { 20, src = a, color = 'red' }" \ + "blur { 6, src = a, color = 'red' }" \ + "blur { 6, src = input, color = 'orange' }" \ + "blur { 2, src = input, color = 'cyan' }" + +#define FILTER2 \ + "blend { ox = -8, oy = -5, color = color(255, 255, 255, 64) } " \ + "blend { ox = 5, oy = 5, color = color(255, 255, 255, 64) } " \ + "blend { ox = -2, oy = 8, color = color(255, 255, 255, 64) } " \ + + efl_gfx_filter_program_set(efl_part(pb, "shadow"), FILTER2, "blur"); + ic2 = elm_icon_add(win); elm_image_file_set(ic2, buf, NULL); evas_object_size_hint_aspect_set(ic2, EVAS_ASPECT_CONTROL_HORIZONTAL, 1, 1); + + efl_gfx_filter_program_set(efl_part(ic2, "shadow"), FILTER_CODE, "blur"); + pb = elm_progressbar_add(win); elm_progressbar_horizontal_set(pb, EINA_FALSE); elm_object_text_set(pb, "Label"); @@ -213,6 +231,13 @@ test_progressbar(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *eve evas_object_show(pb); pd->pb7 = pb; + Eo *shadow = efl_ref(efl_part(pb, "shadow")); + efl_gfx_color_set(shadow, 0, 255, 255, 255); + efl_ui_widget_part_shadow_offset_set(shadow, 0, 0); + efl_ui_widget_part_shadow_radius_set(shadow, 10, 10); + efl_ui_widget_part_shadow_grow_set(shadow, 5); + efl_unref(shadow); + bt_bx = elm_box_add(win); elm_box_horizontal_set(bt_bx, EINA_TRUE); evas_object_size_hint_weight_set(bt_bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); diff --git a/src/lib/elementary/Elementary.h b/src/lib/elementary/Elementary.h index 66b3c8fd14..b6b8654225 100644 --- a/src/lib/elementary/Elementary.h +++ b/src/lib/elementary/Elementary.h @@ -283,6 +283,7 @@ EAPI extern Elm_Version *elm_version; # include # include # include +# include # include # include # include diff --git a/src/lib/elementary/efl_ui_layout.c b/src/lib/elementary/efl_ui_layout.c index 24fb83fd6c..8d47fe8dcc 100644 --- a/src/lib/elementary/efl_ui_layout.c +++ b/src/lib/elementary/efl_ui_layout.c @@ -2418,6 +2418,8 @@ _efl_ui_layout_efl_part_part(const Eo *obj, Efl_Ui_Layout_Data *sd EINA_UNUSED, return ELM_PART_IMPLEMENT(EFL_UI_LAYOUT_PART_BG_CLASS, obj, part); } + else if (eina_streq(part, "shadow")) + return efl_part(efl_super(obj, MY_CLASS), part); if (type >= EFL_CANVAS_LAYOUT_PART_TYPE_LAST) { diff --git a/src/lib/elementary/efl_ui_widget_part_shadow.eo b/src/lib/elementary/efl_ui_widget_part_shadow.eo new file mode 100644 index 0000000000..9581658ad6 --- /dev/null +++ b/src/lib/elementary/efl_ui_widget_part_shadow.eo @@ -0,0 +1,31 @@ +class Efl.Ui.Widget.Part_Shadow (Efl.Ui.Widget.Part, Efl.Gfx, Efl.Gfx.Filter) +{ + data: null; + methods { + @property offset { + values { + ox: double; + oy: double; + } + } + @property radius { + values { + rx: double; + ry: double; + } + } + @property grow { + values { + radius: double; + } + } + } + implements { + Efl.Gfx.color { set; get; } + Efl.Gfx.Filter.filter_program { set; get; } + Efl.Gfx.Filter.filter_source { set; get; } + Efl.Gfx.Filter.filter_data { set; get; } + Efl.Gfx.Filter.filter_padding { get; } + Efl.Gfx.Filter.filter_state { set; get; } + } +} diff --git a/src/lib/elementary/elm_widget.c b/src/lib/elementary/elm_widget.c index 83437d604b..9f363a2cbe 100644 --- a/src/lib/elementary/elm_widget.c +++ b/src/lib/elementary/elm_widget.c @@ -114,6 +114,7 @@ static void _on_sub_obj_del(void *data, const Efl_Event *event); static void _propagate_event(void *data, const Efl_Event *eo_event); static void _elm_widget_focus_tree_unfocusable_handle(Eo *obj); +static void _elm_widget_shadow_update(Elm_Widget *obj); EFL_CALLBACKS_ARRAY_DEFINE(elm_widget_subitems_callbacks, { EFL_EVENT_DEL, _on_sub_obj_del }); @@ -795,6 +796,8 @@ _smart_reconfigure(Elm_Widget_Smart_Data *sd) evas_object_move(sd->bg, sd->x, sd->y); evas_object_resize(sd->bg, sd->w, sd->h); } + if (sd->has_shadow) + _elm_widget_shadow_update(sd->obj); } EOLIAN static void @@ -5625,6 +5628,268 @@ elm_widget_signal_callback_del(Eo *obj, const char *emission, const char *source } +/* Widget Shadow Begin */ + +typedef struct _Widget_Shadow +{ + Eo *widget; + Eo *surface; + struct { + double rx, ry, ox, oy, grow; + int r, g, b, a; + } props; + Eina_Stringshare *code, *name; +} Widget_Shadow; + +static void _widget_shadow_update(Widget_Shadow *shadow); + +static void +_widget_shadow_del_cb(void *data, const Efl_Event *ev EINA_UNUSED) +{ + Widget_Shadow *shadow = data; + + efl_del(shadow->surface); + free(shadow); +} + +static void +_widget_shadow_event_cb(void *data, const Efl_Event *ev EINA_UNUSED) +{ + Widget_Shadow *shadow = data; + _widget_shadow_update(shadow); +} + +EFL_CALLBACKS_ARRAY_DEFINE(widget_shadow_cb, +{ EFL_EVENT_DEL, _widget_shadow_del_cb }, +{ EFL_GFX_EVENT_MOVE, _widget_shadow_event_cb }, +{ EFL_GFX_EVENT_RESIZE, _widget_shadow_event_cb }, +{ EFL_GFX_EVENT_RESTACK, _widget_shadow_event_cb }, +{ EFL_GFX_EVENT_HIDE, _widget_shadow_event_cb }, +{ EFL_GFX_EVENT_SHOW, _widget_shadow_event_cb }) + +static Widget_Shadow * +_widget_shadow_part_get(Eo *part_obj) +{ + Elm_Part_Data *pd = efl_data_scope_get(part_obj, EFL_UI_WIDGET_PART_CLASS); + Widget_Shadow *shadow; + Eo *widget = pd->obj; + + shadow = efl_key_data_get(widget, "__elm_shadow"); + if (!shadow) + { + shadow = calloc(1, sizeof(*shadow)); + shadow->widget = pd->obj; + efl_key_data_set(widget, "__elm_shadow", shadow); + efl_event_callback_array_add(widget, widget_shadow_cb(), shadow); + } + return shadow; +} + +static void +_widget_shadow_update(Widget_Shadow *ws) +{ + int l = 0, r = 0, t = 0, b = 0; + Eina_Rect srect, wrect, fill; + char filter[1024]; + +#define FILTER_FMT \ + "a = buffer { 'alpha' }" \ + "grow { %f, dst = a }" \ + "blur { src = a, rx = %f, ry = %f, color = color(%d,%d,%d,%d) }" + + if (!ws->surface) + { + ws->surface = efl_add(EFL_CANVAS_PROXY_CLASS, ws->widget); + efl_gfx_fill_auto_set(ws->surface, 1); + efl_canvas_proxy_source_clip_set(ws->surface, EINA_FALSE); + efl_canvas_proxy_source_events_set(ws->surface, EINA_FALSE); + efl_canvas_proxy_source_set(ws->surface, ws->widget); + } + + if (!ws->code) + { + snprintf(filter, sizeof(filter), FILTER_FMT, + ws->props.grow, ws->props.rx, ws->props.ry, + ws->props.r, ws->props.g, ws->props.b, ws->props.a); + } + + efl_gfx_filter_program_set(ws->surface, + ws->code ? ws->code : filter, + ws->name ? ws->name : "shadow"); + efl_gfx_filter_padding_get(ws->surface, &l, &r, &t, &b); + + wrect = efl_gfx_geometry_get(ws->widget); + srect.x = wrect.x + (int) (-l + ws->props.ox); + srect.y = wrect.y + (int) (-t + ws->props.oy); + srect.w = wrect.w + (int) (l + r); + srect.h = wrect.h + (int) (t + b); + fill.size = wrect.size; + fill.x = 0; + fill.y = 0; + + if ((!ws->props.a && !ws->code) || + !efl_gfx_visible_get(ws->widget)) + { + efl_gfx_visible_set(ws->surface, EINA_FALSE); + return; + } + + efl_canvas_object_clip_set(ws->surface, efl_canvas_object_clip_get(ws->widget)); + efl_canvas_group_member_add(efl_canvas_object_render_parent_get(ws->widget), ws->surface); + efl_gfx_geometry_set(ws->surface, srect); + efl_gfx_stack_below(ws->surface, ws->widget); + efl_gfx_visible_set(ws->surface, EINA_TRUE); +} + +static void +_elm_widget_shadow_update(Elm_Widget *obj) +{ + Widget_Shadow *shadow = _widget_shadow_part_get(obj); + _widget_shadow_update(shadow); +} + +EOLIAN static void +_efl_ui_widget_part_shadow_offset_set(Eo *obj, void *_pd EINA_UNUSED, double ox, double oy) +{ + Widget_Shadow *shadow = _widget_shadow_part_get(obj); + shadow->props.ox = ox; + shadow->props.oy = oy; + _widget_shadow_update(shadow); +} + +EOLIAN static void +_efl_ui_widget_part_shadow_offset_get(Eo *obj, void *_pd EINA_UNUSED, double *ox, double *oy) +{ + Widget_Shadow *shadow = _widget_shadow_part_get(obj); + if (ox) *ox = shadow->props.ox; + if (oy) *oy = shadow->props.oy; +} + +EOLIAN static void +_efl_ui_widget_part_shadow_radius_set(Eo *obj, void *_pd EINA_UNUSED, double rx, double ry) +{ + Widget_Shadow *shadow = _widget_shadow_part_get(obj); + shadow->props.rx = rx; + shadow->props.ry = ry; + _widget_shadow_update(shadow); +} + +EOLIAN static void +_efl_ui_widget_part_shadow_radius_get(Eo *obj, void *_pd EINA_UNUSED, double *rx, double *ry) +{ + Widget_Shadow *shadow = _widget_shadow_part_get(obj); + if (rx) *rx = shadow->props.rx; + if (ry) *ry = shadow->props.ry; +} + +EOLIAN static void +_efl_ui_widget_part_shadow_efl_gfx_color_set(Eo *obj, void *_pd EINA_UNUSED, int r, int g, int b, int a) +{ + Widget_Shadow *shadow = _widget_shadow_part_get(obj); + shadow->props.r = r; + shadow->props.g = g; + shadow->props.b = b; + shadow->props.a = a; + _widget_shadow_update(shadow); +} + +EOLIAN static void +_efl_ui_widget_part_shadow_efl_gfx_color_get(Eo *obj, void *_pd EINA_UNUSED, int *r, int *g, int *b, int *a) +{ + Widget_Shadow *shadow = _widget_shadow_part_get(obj); + if (r) *r = shadow->props.r; + if (g) *g = shadow->props.g; + if (b) *b = shadow->props.b; + if (a) *a = shadow->props.a; +} + +EOLIAN static void +_efl_ui_widget_part_shadow_grow_set(Eo *obj, void *_pd EINA_UNUSED, double radius) +{ + Widget_Shadow *shadow = _widget_shadow_part_get(obj); + shadow->props.grow = radius; + _widget_shadow_update(shadow); +} + +EOLIAN static double +_efl_ui_widget_part_shadow_grow_get(Eo *obj, void *_pd EINA_UNUSED) +{ + Widget_Shadow *shadow = _widget_shadow_part_get(obj); + return shadow->props.grow; +} + +EOLIAN static void +_efl_ui_widget_part_shadow_efl_gfx_filter_filter_program_set(Eo *obj, void *_pd EINA_UNUSED, const char *code, const char *name) +{ + Widget_Shadow *ws = _widget_shadow_part_get(obj); + eina_stringshare_replace(&ws->code, code); + eina_stringshare_replace(&ws->name, name); + _widget_shadow_update(ws); +} + +EOLIAN static void +_efl_ui_widget_part_shadow_efl_gfx_filter_filter_program_get(Eo *obj, void *_pd EINA_UNUSED, const char **code, const char **name) +{ + Widget_Shadow *ws = _widget_shadow_part_get(obj); + efl_gfx_filter_program_get(ws->surface, code, name); +} + +EOLIAN static void +_efl_ui_widget_part_shadow_efl_gfx_filter_filter_source_set(Eo *obj, void *_pd EINA_UNUSED, const char *name, Efl_Gfx *source) +{ + Widget_Shadow *ws = _widget_shadow_part_get(obj); + _widget_shadow_update(ws); + efl_gfx_filter_source_set(ws->surface, name, source); +} + +EOLIAN static Efl_Gfx * +_efl_ui_widget_part_shadow_efl_gfx_filter_filter_source_get(Eo *obj, void *_pd EINA_UNUSED, const char *name) +{ + Widget_Shadow *ws = _widget_shadow_part_get(obj); + return efl_gfx_filter_source_get(ws->surface, name); +} + +EOLIAN static void +_efl_ui_widget_part_shadow_efl_gfx_filter_filter_data_set(Eo *obj, void *_pd EINA_UNUSED, const char *name, const char *value, Eina_Bool execute) +{ + Widget_Shadow *ws = _widget_shadow_part_get(obj); + _widget_shadow_update(ws); + efl_gfx_filter_data_set(ws->surface, name, value, execute); +} + +EOLIAN static void +_efl_ui_widget_part_shadow_efl_gfx_filter_filter_data_get(Eo *obj, void *_pd EINA_UNUSED, const char *name, const char **value, Eina_Bool *execute) +{ + Widget_Shadow *ws = _widget_shadow_part_get(obj); + efl_gfx_filter_data_get(ws->surface, name, value, execute); +} + +EOLIAN static void +_efl_ui_widget_part_shadow_efl_gfx_filter_filter_padding_get(Eo *obj, void *_pd EINA_UNUSED, int *l, int *r, int *t, int *b) +{ + Widget_Shadow *ws = _widget_shadow_part_get(obj); + efl_gfx_filter_padding_get(ws->surface, l, r, t, b); +} + +EOLIAN static void +_efl_ui_widget_part_shadow_efl_gfx_filter_filter_state_set(Eo *obj, void *_pd EINA_UNUSED, const char *cur_state, double cur_val, const char *next_state, double next_val, double pos) +{ + Widget_Shadow *ws = _widget_shadow_part_get(obj); + efl_gfx_filter_state_set(ws->surface, cur_state, cur_val, next_state, next_val, pos); +} + +EOLIAN static void +_efl_ui_widget_part_shadow_efl_gfx_filter_filter_state_get(Eo *obj, void *_pd EINA_UNUSED, const char **cur_state, double *cur_val, const char **next_state, double *next_val, double *pos) +{ + Widget_Shadow *ws = _widget_shadow_part_get(obj); + efl_gfx_filter_state_get(ws->surface, cur_state, cur_val, next_state, next_val, pos); +} + +#include "efl_ui_widget_part_shadow.eo.c" + +/* Widget Shadow End */ + + /* Efl.Part implementation */ EOLIAN static Efl_Object * @@ -5632,6 +5897,8 @@ _elm_widget_efl_part_part(const Eo *obj, Elm_Widget_Smart_Data *wd EINA_UNUSED, { if (eina_streq(part, "background")) return ELM_PART_IMPLEMENT(EFL_UI_WIDGET_PART_BG_CLASS, obj, part); + else if (eina_streq(part, "shadow")) + return ELM_PART_IMPLEMENT(EFL_UI_WIDGET_PART_SHADOW_CLASS, obj, part); return ELM_PART_IMPLEMENT(EFL_UI_WIDGET_PART_CLASS, obj, part); } diff --git a/src/lib/elementary/elm_widget.eo b/src/lib/elementary/elm_widget.eo index 92071374b5..b8c093af06 100644 --- a/src/lib/elementary/elm_widget.eo +++ b/src/lib/elementary/elm_widget.eo @@ -570,6 +570,9 @@ abstract Elm.Widget (Efl.Canvas.Group, Efl.Access, return: Efl.Ui.Focus.Manager; [[The focus manager.]] } } + parts { + shadow: Efl.Ui.Widget.Part_Shadow; + } implements { class.constructor; Efl.Object.constructor; diff --git a/src/lib/elementary/elm_widget.h b/src/lib/elementary/elm_widget.h index 23e1a5ec4c..b7975a45da 100644 --- a/src/lib/elementary/elm_widget.h +++ b/src/lib/elementary/elm_widget.h @@ -465,6 +465,7 @@ typedef struct _Elm_Widget_Smart_Data Eina_Bool on_destroy: 1; /**< This is true when the widget is on destruction(general widget destructor). */ Eina_Bool provider_lookup : 1; /**< This is true when efl_provider_find is currently walking the tree */ Eina_Bool legacy : 1; /**< Widget was created with a legacy API, not efl_add() */ + Eina_Bool has_shadow : 1; } Elm_Widget_Smart_Data; typedef Elm_Widget_Smart_Data Efl_Ui_Widget_Data; diff --git a/src/lib/evas/canvas/efl_canvas_proxy.c b/src/lib/evas/canvas/efl_canvas_proxy.c index ab46ff391e..60049ecaaf 100644 --- a/src/lib/evas/canvas/efl_canvas_proxy.c +++ b/src/lib/evas/canvas/efl_canvas_proxy.c @@ -219,7 +219,8 @@ _evas_image_proxy_set(Evas_Object *eo_proxy, Evas_Object *eo_src) Evas_Object_Protected_Data *proxy = efl_data_scope_get(eo_proxy, EFL_CANVAS_OBJECT_CLASS); Evas_Image_Data *o = efl_data_scope_get(eo_proxy, EFL_CANVAS_IMAGE_INTERNAL_CLASS); - efl_file_set(eo_proxy, NULL, NULL); + if (o->legacy_type) + efl_file_set(eo_proxy, NULL, NULL); EINA_COW_WRITE_BEGIN(evas_object_proxy_cow, proxy->proxy, Evas_Object_Proxy_Data, proxy_write) proxy_write->is_proxy = EINA_TRUE; -- cgit v1.2.1