summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJean-Philippe Andre <jp.andre@samsung.com>2017-12-14 17:25:37 +0900
committerJean-Philippe Andre <jp.andre@samsung.com>2017-12-14 18:03:49 +0900
commita13e61a37b6859b99a09bd3c33c5caa359459451 (patch)
treeaf2131a320da42ed6157be6994be119dc05102cf
parent00bb3bd3c7781f76ca8010f44dc6998f6bbff89d (diff)
elm: Add "shadow" part to all widgets
This makes it possible to very easily create drop shadows and glow effects on any widget. This is absolutely not optimized, though the main performance bottleneck is that the proxy images get redrawn after just moving. @feature
-rw-r--r--src/Makefile_Elementary.am1
-rw-r--r--src/lib/elementary/Elementary.h1
-rw-r--r--src/lib/elementary/efl_ui_layout.c2
-rw-r--r--src/lib/elementary/efl_ui_widget_part_shadow.eo35
-rw-r--r--src/lib/elementary/elm_widget.c267
-rw-r--r--src/lib/elementary/elm_widget.eo3
-rw-r--r--src/lib/elementary/elm_widget.h1
7 files changed, 310 insertions, 0 deletions
diff --git a/src/Makefile_Elementary.am b/src/Makefile_Elementary.am
index d95ddd9774..7f3d733ebd 100644
--- a/src/Makefile_Elementary.am
+++ b/src/Makefile_Elementary.am
@@ -74,6 +74,7 @@ elm_public_eolian_files = \
74 lib/elementary/efl_ui_textpath_part.eo \ 74 lib/elementary/efl_ui_textpath_part.eo \
75 lib/elementary/efl_ui_widget_part.eo \ 75 lib/elementary/efl_ui_widget_part.eo \
76 lib/elementary/efl_ui_widget_part_bg.eo \ 76 lib/elementary/efl_ui_widget_part_bg.eo \
77 lib/elementary/efl_ui_widget_part_shadow.eo \
77 lib/elementary/efl_ui_win_part.eo \ 78 lib/elementary/efl_ui_win_part.eo \
78 lib/elementary/efl_access.eo \ 79 lib/elementary/efl_access.eo \
79 lib/elementary/efl_access_action.eo \ 80 lib/elementary/efl_access_action.eo \
diff --git a/src/lib/elementary/Elementary.h b/src/lib/elementary/Elementary.h
index c1422ae838..95c54b35ac 100644
--- a/src/lib/elementary/Elementary.h
+++ b/src/lib/elementary/Elementary.h
@@ -284,6 +284,7 @@ EAPI extern Elm_Version *elm_version;
284# include <efl_config_global.eo.h> 284# include <efl_config_global.eo.h>
285# include <efl_ui_widget_part.eo.h> 285# include <efl_ui_widget_part.eo.h>
286# include <efl_ui_widget_part_bg.eo.h> 286# include <efl_ui_widget_part_bg.eo.h>
287# include <efl_ui_widget_part_shadow.eo.h>
287# include <efl_ui_layout_part.eo.h> 288# include <efl_ui_layout_part.eo.h>
288# include <efl_ui_layout_part_box.eo.h> 289# include <efl_ui_layout_part_box.eo.h>
289# include <efl_ui_layout_part_content.eo.h> 290# include <efl_ui_layout_part_content.eo.h>
diff --git a/src/lib/elementary/efl_ui_layout.c b/src/lib/elementary/efl_ui_layout.c
index 5981fc1a54..0eda685bad 100644
--- a/src/lib/elementary/efl_ui_layout.c
+++ b/src/lib/elementary/efl_ui_layout.c
@@ -2448,6 +2448,8 @@ _efl_ui_layout_efl_part_part(const Eo *obj, Efl_Ui_Layout_Data *sd EINA_UNUSED,
2448 2448
2449 return ELM_PART_IMPLEMENT(EFL_UI_LAYOUT_PART_BG_CLASS, obj, part); 2449 return ELM_PART_IMPLEMENT(EFL_UI_LAYOUT_PART_BG_CLASS, obj, part);
2450 } 2450 }
2451 else if (eina_streq(part, "shadow"))
2452 return efl_part(efl_super(obj, MY_CLASS), part);
2451 2453
2452 if (type >= EFL_CANVAS_LAYOUT_PART_TYPE_LAST) 2454 if (type >= EFL_CANVAS_LAYOUT_PART_TYPE_LAST)
2453 { 2455 {
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..8947b9a0c7
--- /dev/null
+++ b/src/lib/elementary/efl_ui_widget_part_shadow.eo
@@ -0,0 +1,35 @@
1class Efl.Ui.Widget.Part_Shadow (Efl.Ui.Widget.Part, Efl.Gfx,
2 Efl.Gfx.Blur, Efl.Gfx.Filter)
3{
4 [[A drop-shadow or glow effect around any widget.
5
6 A simple drop-shadow effect can be applied to any widget by setting the
7 color and blur radius on this part.
8
9 For instance, a blue glow can be achieved with:
10 obj.shadow().color_set(0, 128, 255, 255);
11 obj.shadow().grow_set(2);
12 obj.shadow().radius_set(3, 3);
13
14 As another example, here's a black drop-shadow:
15 obj.shadow().color_set(0, 0, 0, 255);
16 obj.shadow().grow_set(1);
17 obj.shadow().radius_set(5, 5);
18 obj.shadow().offset_set(5, 5);
19
20 It is also possible to manually specify which @Efl.Gfx.Filter program to
21 use.
22 ]]
23 data: null;
24 implements {
25 Efl.Gfx.color { set; get; }
26 Efl.Gfx.Blur.radius { set; get; }
27 Efl.Gfx.Blur.offset { set; get; }
28 Efl.Gfx.Blur.grow { set; get; }
29 Efl.Gfx.Filter.filter_program { set; get; }
30 Efl.Gfx.Filter.filter_source { set; get; }
31 Efl.Gfx.Filter.filter_data { set; get; }
32 Efl.Gfx.Filter.filter_padding { get; }
33 Efl.Gfx.Filter.filter_state { set; get; }
34 }
35}
diff --git a/src/lib/elementary/elm_widget.c b/src/lib/elementary/elm_widget.c
index 83437d604b..d67ec8008b 100644
--- a/src/lib/elementary/elm_widget.c
+++ b/src/lib/elementary/elm_widget.c
@@ -114,6 +114,7 @@ static void
114_on_sub_obj_del(void *data, const Efl_Event *event); 114_on_sub_obj_del(void *data, const Efl_Event *event);
115static void _propagate_event(void *data, const Efl_Event *eo_event); 115static void _propagate_event(void *data, const Efl_Event *eo_event);
116static void _elm_widget_focus_tree_unfocusable_handle(Eo *obj); 116static void _elm_widget_focus_tree_unfocusable_handle(Eo *obj);
117static void _elm_widget_shadow_update(Elm_Widget *obj);
117 118
118EFL_CALLBACKS_ARRAY_DEFINE(elm_widget_subitems_callbacks, 119EFL_CALLBACKS_ARRAY_DEFINE(elm_widget_subitems_callbacks,
119 { EFL_EVENT_DEL, _on_sub_obj_del }); 120 { EFL_EVENT_DEL, _on_sub_obj_del });
@@ -795,6 +796,8 @@ _smart_reconfigure(Elm_Widget_Smart_Data *sd)
795 evas_object_move(sd->bg, sd->x, sd->y); 796 evas_object_move(sd->bg, sd->x, sd->y);
796 evas_object_resize(sd->bg, sd->w, sd->h); 797 evas_object_resize(sd->bg, sd->w, sd->h);
797 } 798 }
799 if (sd->has_shadow)
800 _elm_widget_shadow_update(sd->obj);
798} 801}
799 802
800EOLIAN static void 803EOLIAN static void
@@ -5625,6 +5628,268 @@ elm_widget_signal_callback_del(Eo *obj, const char *emission, const char *source
5625} 5628}
5626 5629
5627 5630
5631/* Widget Shadow Begin */
5632
5633typedef struct _Widget_Shadow
5634{
5635 Eo *widget;
5636 Eo *surface;
5637 struct {
5638 double rx, ry, ox, oy, grow;
5639 int r, g, b, a;
5640 } props;
5641 Eina_Stringshare *code, *name;
5642} Widget_Shadow;
5643
5644static void _widget_shadow_update(Widget_Shadow *shadow);
5645
5646static void
5647_widget_shadow_del_cb(void *data, const Efl_Event *ev EINA_UNUSED)
5648{
5649 Widget_Shadow *shadow = data;
5650
5651 efl_del(shadow->surface);
5652 free(shadow);
5653}
5654
5655static void
5656_widget_shadow_event_cb(void *data, const Efl_Event *ev EINA_UNUSED)
5657{
5658 Widget_Shadow *shadow = data;
5659 _widget_shadow_update(shadow);
5660}
5661
5662EFL_CALLBACKS_ARRAY_DEFINE(widget_shadow_cb,
5663{ EFL_EVENT_DEL, _widget_shadow_del_cb },
5664{ EFL_GFX_EVENT_MOVE, _widget_shadow_event_cb },
5665{ EFL_GFX_EVENT_RESIZE, _widget_shadow_event_cb },
5666{ EFL_GFX_EVENT_RESTACK, _widget_shadow_event_cb },
5667{ EFL_GFX_EVENT_HIDE, _widget_shadow_event_cb },
5668{ EFL_GFX_EVENT_SHOW, _widget_shadow_event_cb })
5669
5670static Widget_Shadow *
5671_widget_shadow_part_get(Eo *part_obj)
5672{
5673 Elm_Part_Data *pd = efl_data_scope_get(part_obj, EFL_UI_WIDGET_PART_CLASS);
5674 Widget_Shadow *shadow;
5675 Eo *widget = pd->obj;
5676
5677 shadow = efl_key_data_get(widget, "__elm_shadow");
5678 if (!shadow)
5679 {
5680 shadow = calloc(1, sizeof(*shadow));
5681 shadow->widget = pd->obj;
5682 efl_key_data_set(widget, "__elm_shadow", shadow);
5683 efl_event_callback_array_add(widget, widget_shadow_cb(), shadow);
5684 }
5685 return shadow;
5686}
5687
5688static void
5689_widget_shadow_update(Widget_Shadow *ws)
5690{
5691 int l = 0, r = 0, t = 0, b = 0;
5692 Eina_Rect srect, wrect, fill;
5693 char filter[1024];
5694
5695#define FILTER_FMT \
5696 "a = buffer { 'alpha' }" \
5697 "grow { %f, dst = a, alphaonly = true }" \
5698 "blur { src = a, rx = %f, ry = %f, color = color(%d,%d,%d,%d) }"
5699
5700 if (!ws->surface)
5701 {
5702 ws->surface = efl_add(EFL_CANVAS_PROXY_CLASS, ws->widget);
5703 efl_gfx_fill_auto_set(ws->surface, 1);
5704 efl_canvas_proxy_source_clip_set(ws->surface, EINA_FALSE);
5705 efl_canvas_proxy_source_events_set(ws->surface, EINA_FALSE);
5706 efl_canvas_proxy_source_set(ws->surface, ws->widget);
5707 }
5708
5709 if (!ws->code)
5710 {
5711 snprintf(filter, sizeof(filter), FILTER_FMT,
5712 ws->props.grow, ws->props.rx, ws->props.ry,
5713 ws->props.r, ws->props.g, ws->props.b, ws->props.a);
5714 }
5715
5716 efl_gfx_filter_program_set(ws->surface,
5717 ws->code ? ws->code : filter,
5718 ws->name ? ws->name : "shadow");
5719 efl_gfx_filter_padding_get(ws->surface, &l, &r, &t, &b);
5720
5721 wrect = efl_gfx_geometry_get(ws->widget);
5722 srect.x = wrect.x + (int) (-l + ws->props.ox);
5723 srect.y = wrect.y + (int) (-t + ws->props.oy);
5724 srect.w = wrect.w + (int) (l + r);
5725 srect.h = wrect.h + (int) (t + b);
5726 fill.size = wrect.size;
5727 fill.x = 0;
5728 fill.y = 0;
5729
5730 if ((!ws->props.a && !ws->code) ||
5731 !efl_gfx_visible_get(ws->widget))
5732 {
5733 efl_gfx_visible_set(ws->surface, EINA_FALSE);
5734 return;
5735 }
5736
5737 efl_canvas_object_clip_set(ws->surface, efl_canvas_object_clip_get(ws->widget));
5738 efl_canvas_group_member_add(efl_canvas_object_render_parent_get(ws->widget), ws->surface);
5739 efl_gfx_geometry_set(ws->surface, srect);
5740 efl_gfx_stack_below(ws->surface, ws->widget);
5741 efl_gfx_visible_set(ws->surface, EINA_TRUE);
5742}
5743
5744static void
5745_elm_widget_shadow_update(Elm_Widget *obj)
5746{
5747 Widget_Shadow *shadow = _widget_shadow_part_get(obj);
5748 _widget_shadow_update(shadow);
5749}
5750
5751EOLIAN static void
5752_efl_ui_widget_part_shadow_efl_gfx_blur_offset_set(Eo *obj, void *_pd EINA_UNUSED, double ox, double oy)
5753{
5754 Widget_Shadow *shadow = _widget_shadow_part_get(obj);
5755 shadow->props.ox = ox;
5756 shadow->props.oy = oy;
5757 _widget_shadow_update(shadow);
5758}
5759
5760EOLIAN static void
5761_efl_ui_widget_part_shadow_efl_gfx_blur_offset_get(Eo *obj, void *_pd EINA_UNUSED, double *ox, double *oy)
5762{
5763 Widget_Shadow *shadow = _widget_shadow_part_get(obj);
5764 if (ox) *ox = shadow->props.ox;
5765 if (oy) *oy = shadow->props.oy;
5766}
5767
5768EOLIAN static void
5769_efl_ui_widget_part_shadow_efl_gfx_blur_radius_set(Eo *obj, void *_pd EINA_UNUSED, double rx, double ry)
5770{
5771 Widget_Shadow *shadow = _widget_shadow_part_get(obj);
5772 shadow->props.rx = rx;
5773 shadow->props.ry = ry;
5774 _widget_shadow_update(shadow);
5775}
5776
5777EOLIAN static void
5778_efl_ui_widget_part_shadow_efl_gfx_blur_radius_get(Eo *obj, void *_pd EINA_UNUSED, double *rx, double *ry)
5779{
5780 Widget_Shadow *shadow = _widget_shadow_part_get(obj);
5781 if (rx) *rx = shadow->props.rx;
5782 if (ry) *ry = shadow->props.ry;
5783}
5784
5785EOLIAN static void
5786_efl_ui_widget_part_shadow_efl_gfx_color_set(Eo *obj, void *_pd EINA_UNUSED, int r, int g, int b, int a)
5787{
5788 Widget_Shadow *shadow = _widget_shadow_part_get(obj);
5789 shadow->props.r = r;
5790 shadow->props.g = g;
5791 shadow->props.b = b;
5792 shadow->props.a = a;
5793 _widget_shadow_update(shadow);
5794}
5795
5796EOLIAN static void
5797_efl_ui_widget_part_shadow_efl_gfx_color_get(Eo *obj, void *_pd EINA_UNUSED, int *r, int *g, int *b, int *a)
5798{
5799 Widget_Shadow *shadow = _widget_shadow_part_get(obj);
5800 if (r) *r = shadow->props.r;
5801 if (g) *g = shadow->props.g;
5802 if (b) *b = shadow->props.b;
5803 if (a) *a = shadow->props.a;
5804}
5805
5806EOLIAN static void
5807_efl_ui_widget_part_shadow_efl_gfx_blur_grow_set(Eo *obj, void *_pd EINA_UNUSED, double radius)
5808{
5809 Widget_Shadow *shadow = _widget_shadow_part_get(obj);
5810 shadow->props.grow = radius;
5811 _widget_shadow_update(shadow);
5812}
5813
5814EOLIAN static double
5815_efl_ui_widget_part_shadow_efl_gfx_blur_grow_get(Eo *obj, void *_pd EINA_UNUSED)
5816{
5817 Widget_Shadow *shadow = _widget_shadow_part_get(obj);
5818 return shadow->props.grow;
5819}
5820
5821EOLIAN static void
5822_efl_ui_widget_part_shadow_efl_gfx_filter_filter_program_set(Eo *obj, void *_pd EINA_UNUSED, const char *code, const char *name)
5823{
5824 Widget_Shadow *ws = _widget_shadow_part_get(obj);
5825 eina_stringshare_replace(&ws->code, code);
5826 eina_stringshare_replace(&ws->name, name);
5827 _widget_shadow_update(ws);
5828}
5829
5830EOLIAN static void
5831_efl_ui_widget_part_shadow_efl_gfx_filter_filter_program_get(Eo *obj, void *_pd EINA_UNUSED, const char **code, const char **name)
5832{
5833 Widget_Shadow *ws = _widget_shadow_part_get(obj);
5834 efl_gfx_filter_program_get(ws->surface, code, name);
5835}
5836
5837EOLIAN static void
5838_efl_ui_widget_part_shadow_efl_gfx_filter_filter_source_set(Eo *obj, void *_pd EINA_UNUSED, const char *name, Efl_Gfx *source)
5839{
5840 Widget_Shadow *ws = _widget_shadow_part_get(obj);
5841 _widget_shadow_update(ws);
5842 efl_gfx_filter_source_set(ws->surface, name, source);
5843}
5844
5845EOLIAN static Efl_Gfx *
5846_efl_ui_widget_part_shadow_efl_gfx_filter_filter_source_get(Eo *obj, void *_pd EINA_UNUSED, const char *name)
5847{
5848 Widget_Shadow *ws = _widget_shadow_part_get(obj);
5849 return efl_gfx_filter_source_get(ws->surface, name);
5850}
5851
5852EOLIAN static void
5853_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)
5854{
5855 Widget_Shadow *ws = _widget_shadow_part_get(obj);
5856 _widget_shadow_update(ws);
5857 efl_gfx_filter_data_set(ws->surface, name, value, execute);
5858}
5859
5860EOLIAN static void
5861_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)
5862{
5863 Widget_Shadow *ws = _widget_shadow_part_get(obj);
5864 efl_gfx_filter_data_get(ws->surface, name, value, execute);
5865}
5866
5867EOLIAN static void
5868_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)
5869{
5870 Widget_Shadow *ws = _widget_shadow_part_get(obj);
5871 efl_gfx_filter_padding_get(ws->surface, l, r, t, b);
5872}
5873
5874EOLIAN static void
5875_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)
5876{
5877 Widget_Shadow *ws = _widget_shadow_part_get(obj);
5878 efl_gfx_filter_state_set(ws->surface, cur_state, cur_val, next_state, next_val, pos);
5879}
5880
5881EOLIAN static void
5882_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)
5883{
5884 Widget_Shadow *ws = _widget_shadow_part_get(obj);
5885 efl_gfx_filter_state_get(ws->surface, cur_state, cur_val, next_state, next_val, pos);
5886}
5887
5888#include "efl_ui_widget_part_shadow.eo.c"
5889
5890/* Widget Shadow End */
5891
5892
5628/* Efl.Part implementation */ 5893/* Efl.Part implementation */
5629 5894
5630EOLIAN static Efl_Object * 5895EOLIAN static Efl_Object *
@@ -5632,6 +5897,8 @@ _elm_widget_efl_part_part(const Eo *obj, Elm_Widget_Smart_Data *wd EINA_UNUSED,
5632{ 5897{
5633 if (eina_streq(part, "background")) 5898 if (eina_streq(part, "background"))
5634 return ELM_PART_IMPLEMENT(EFL_UI_WIDGET_PART_BG_CLASS, obj, part); 5899 return ELM_PART_IMPLEMENT(EFL_UI_WIDGET_PART_BG_CLASS, obj, part);
5900 else if (eina_streq(part, "shadow"))
5901 return ELM_PART_IMPLEMENT(EFL_UI_WIDGET_PART_SHADOW_CLASS, obj, part);
5635 return ELM_PART_IMPLEMENT(EFL_UI_WIDGET_PART_CLASS, obj, part); 5902 return ELM_PART_IMPLEMENT(EFL_UI_WIDGET_PART_CLASS, obj, part);
5636} 5903}
5637 5904
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,
570 return: Efl.Ui.Focus.Manager; [[The focus manager.]] 570 return: Efl.Ui.Focus.Manager; [[The focus manager.]]
571 } 571 }
572 } 572 }
573 parts {
574 shadow: Efl.Ui.Widget.Part_Shadow;
575 }
573 implements { 576 implements {
574 class.constructor; 577 class.constructor;
575 Efl.Object.constructor; 578 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
465 Eina_Bool on_destroy: 1; /**< This is true when the widget is on destruction(general widget destructor). */ 465 Eina_Bool on_destroy: 1; /**< This is true when the widget is on destruction(general widget destructor). */
466 Eina_Bool provider_lookup : 1; /**< This is true when efl_provider_find is currently walking the tree */ 466 Eina_Bool provider_lookup : 1; /**< This is true when efl_provider_find is currently walking the tree */
467 Eina_Bool legacy : 1; /**< Widget was created with a legacy API, not efl_add() */ 467 Eina_Bool legacy : 1; /**< Widget was created with a legacy API, not efl_add() */
468 Eina_Bool has_shadow : 1;
468} Elm_Widget_Smart_Data; 469} Elm_Widget_Smart_Data;
469 470
470typedef Elm_Widget_Smart_Data Efl_Ui_Widget_Data; 471typedef Elm_Widget_Smart_Data Efl_Ui_Widget_Data;