#include "e.h" typedef struct _E_Widget_Data E_Widget_Data; struct _E_Widget_Data { Evas_Object *o_cslider; Evas_Object *o_grad; Evas_Object *o_event; Eina_List *o_hgrad; Evas_Coord x, y, w, h; int vertical; int fixed; E_Color_Component mode; int valnum; E_Color *color; E_Color *prev; int dragging; }; static void _e_wid_del_hook(Evas_Object *obj); static void _e_wid_focus_hook(Evas_Object *obj); static void _e_wid_disable_hook(Evas_Object *obj); static void _e_wid_focus_steal(void *data, Evas *e, Evas_Object *obj, void *event_info); static void _e_wid_value_set(Evas_Object *obj, double vx); static void _e_wid_update(E_Widget_Data *wd); static void _e_wid_update_standard(E_Widget_Data *wd); static void _e_wid_update_fixed(E_Widget_Data *wd); static void _e_wid_move(void *data, Evas *e, Evas_Object *obj, void *event_info); static void _e_wid_resize(void *data, Evas *e, Evas_Object *obj, void *event_info); static void _e_wid_cb_down(void *data, Evas *e, Evas_Object *obj, void *event_info); static void _e_wid_cb_move(void *data, Evas *e, Evas_Object *obj, void *event_info); static void _e_wid_cb_up(void *data, Evas *e, Evas_Object *obj, void *event_info); Evas_Object * e_widget_cslider_add(Evas *evas, E_Color_Component mode, E_Color *color, int vertical, int fixed) { Evas_Object *obj, *o; E_Widget_Data *wd; Evas_Coord mw, mh; obj = e_widget_add(evas); e_widget_del_hook_set(obj, _e_wid_del_hook); e_widget_focus_hook_set(obj, _e_wid_focus_hook); e_widget_disable_hook_set(obj, _e_wid_disable_hook); wd = calloc(1, sizeof(E_Widget_Data)); e_widget_data_set(obj, wd); wd->vertical = vertical; wd->fixed = fixed; wd->mode = mode; wd->color = color; wd->prev = calloc(1, sizeof (E_Color)); wd->o_hgrad = NULL; o = edje_object_add(evas); wd->o_cslider = o; e_theme_edje_object_set(o, "base/theme/widgets", "e/widgets/cslider"); if (wd->vertical) edje_object_signal_emit(o, "e,state,direction,v", "e"); else edje_object_signal_emit(o, "e,state,direction,h", "e"); evas_object_show(o); edje_object_size_min_calc(o, &mw, &mh); e_widget_size_min_set(obj, mw, mh); e_widget_sub_object_add(obj, o); evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_DOWN, _e_wid_focus_steal, obj); e_widget_resize_object_set(obj, o); /* add gradient obj */ o = evas_object_rectangle_add(evas); e_widget_sub_object_add(obj, o); evas_object_event_callback_add(o, EVAS_CALLBACK_MOVE, _e_wid_move, wd); evas_object_event_callback_add(o, EVAS_CALLBACK_RESIZE, _e_wid_resize, wd); evas_object_show(o); evas_object_color_set(o, 0, 0, 0, 0); wd->o_event = o; edje_object_part_swallow(wd->o_cslider, "e.swallow.content", o); o = evas_object_rectangle_add(evas); e_widget_sub_object_add(obj, o); evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_DOWN, _e_wid_cb_down, obj); evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_MOVE, _e_wid_cb_move, obj); evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_UP, _e_wid_cb_up, obj); evas_object_show(o); evas_object_color_set(o, 255, 255, 255, 255); wd->o_grad = o; _e_wid_update(wd); return obj; } static void _e_wid_move(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__) { E_Widget_Data *wd; Evas_Coord x, y; wd = data; evas_object_geometry_get(obj, &x, &y, NULL, NULL); evas_object_move(wd->o_grad, x, y); _e_wid_update(wd); } static void _e_wid_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__) { E_Widget_Data *wd; Evas_Coord w, h; wd = data; evas_object_geometry_get(obj, NULL, NULL, &w, &h); evas_object_resize(wd->o_grad, w, h); _e_wid_update(wd); } static void _e_wid_value_set(Evas_Object *o, double vx) { E_Widget_Data *wd; wd = e_widget_data_get(o); switch (wd->mode) { case E_COLOR_COMPONENT_R: wd->color->r = 255 * vx; e_color_update_rgb(wd->color); break; case E_COLOR_COMPONENT_G: wd->color->g = 255 * vx; e_color_update_rgb(wd->color); break; case E_COLOR_COMPONENT_B: wd->color->b = 255 * vx; e_color_update_rgb(wd->color); break; case E_COLOR_COMPONENT_H: wd->color->h = 360 * vx; e_color_update_hsv(wd->color); break; case E_COLOR_COMPONENT_S: wd->color->s = vx; e_color_update_hsv(wd->color); break; case E_COLOR_COMPONENT_V: wd->color->v = vx; e_color_update_hsv(wd->color); break; case E_COLOR_COMPONENT_MAX: break; } _e_wid_update(wd); e_widget_change(o); } void e_widget_cslider_color_value_set(Evas_Object *obj, E_Color *val) { E_Widget_Data *wd; wd = e_widget_data_get(obj); wd->color = val; _e_wid_update(wd); } void e_widget_cslider_update(Evas_Object *obj) { E_Widget_Data *wd; wd = e_widget_data_get(obj); _e_wid_update(wd); } void e_widget_cslider_mode_set(Evas_Object *obj, E_Color_Component mode) { E_Widget_Data *wd; wd = e_widget_data_get(obj); if (wd->mode == mode) return; wd->mode = mode; _e_wid_update(wd); } static void _e_wid_update(E_Widget_Data *wd) { Evas_Coord x, y, w, h; Eina_Bool changed = EINA_FALSE; evas_object_geometry_get(wd->o_event, &x, &y, &w, &h); if (x != wd->x || y != wd->y || w != wd->w || h != wd->h) changed = EINA_TRUE; if (memcmp(wd->color, wd->prev, sizeof (E_Color))) changed = EINA_TRUE; if (changed) { Evas_Object *o; if (wd->fixed) _e_wid_update_fixed(wd); else _e_wid_update_standard(wd); wd->x = x; wd->y = y; wd->w = w; wd->h = h; memcpy(wd->prev, wd->color, sizeof (E_Color)); if (wd->mode != E_COLOR_COMPONENT_H) { EINA_LIST_FREE(wd->o_hgrad, o) evas_object_del(o); evas_object_show(wd->o_grad); } else { evas_object_hide(wd->o_grad); } } } static void _e_wid_gradient_set(Evas_Object *o, Eina_Bool orientation, int rf, int gf, int bf, int rt, int gt, int bt) { Evas_Map *m; m = evas_map_new(4); evas_map_util_points_populate_from_object(m, o); if (orientation) { evas_map_point_color_set(m, 0, rf, gf, bf, 255); evas_map_point_color_set(m, 1, rf, gf, bf, 255); evas_map_point_color_set(m, 2, rt, gt, bt, 255); evas_map_point_color_set(m, 3, rt, gt, bt, 255); } else { /* Rotate by 270° */ evas_map_point_color_set(m, 0, rf, gf, bf, 255); evas_map_point_color_set(m, 1, rt, gt, bt, 255); evas_map_point_color_set(m, 2, rt, gt, bt, 255); evas_map_point_color_set(m, 3, rf, gf, bf, 255); } evas_object_map_enable_set(o, 1); evas_object_map_set(o, m); evas_map_free(m); } static void _e_wid_update_standard(E_Widget_Data *wd) { Evas_Object *o; Eina_List *l; Evas_Coord x, y, w, h; int r, g, b; int rd, gd, bd; int max, min; unsigned int i; float vx = 0; int *grad[7][3] = { { &max, &min, &min }, { &max, &max, &min }, { &min, &max, &min }, { &min, &max, &max }, { &min, &min, &max }, { &max, &min, &max }, { &max, &min, &min } }; if (!wd->color) return; switch (wd->mode) { case E_COLOR_COMPONENT_R: _e_wid_gradient_set(wd->o_grad, wd->vertical, 0, wd->color->g, wd->color->b, 255, wd->color->g, wd->color->b); vx = wd->color->r / 255.0; break; case E_COLOR_COMPONENT_G: _e_wid_gradient_set(wd->o_grad, wd->vertical, wd->color->r, 0, wd->color->b, wd->color->r, 255, wd->color->b); vx = wd->color->g / 255.0; break; case E_COLOR_COMPONENT_B: _e_wid_gradient_set(wd->o_grad, wd->vertical, wd->color->r, wd->color->g, 0, wd->color->r, wd->color->g, 255); vx = wd->color->b / 255.0; break; case E_COLOR_COMPONENT_H: evas_color_hsv_to_rgb(0, wd->color->s, wd->color->v, &max, &min, NULL); if (!wd->o_hgrad) { Evas *e; e = evas_object_evas_get(wd->o_grad); for (i = 0; i < 6; ++i) wd->o_hgrad = eina_list_append(wd->o_hgrad, evas_object_rectangle_add(e)); } evas_object_geometry_get(wd->o_grad, &x, &y, &w, &h); evas_object_hide(wd->o_grad); i = 0; EINA_LIST_FOREACH(wd->o_hgrad, l, o) { if (wd->vertical) { evas_object_move(o, x, y + (i * h) / 6); evas_object_resize(o, w, h / 6); } else { evas_object_move(o, x + (i * w) / 6, y); evas_object_resize(o, w / 6, h); } _e_wid_gradient_set(o, wd->vertical, *grad[i][0], *grad[i][1], *grad[i][2], *grad[i + 1][0], *grad[i + 1][1], *grad[i + 1][2]); evas_object_show(o); i++; } vx = wd->color->h / 360.0; break; case E_COLOR_COMPONENT_S: evas_color_hsv_to_rgb(wd->color->h, 0, wd->color->v, &r, &g, &b); evas_color_hsv_to_rgb(wd->color->h, 1, wd->color->v, &rd, &gd, &bd); _e_wid_gradient_set(wd->o_grad, wd->vertical, r, g, b, rd, gd, bd); vx = wd->color->s; break; case E_COLOR_COMPONENT_V: evas_color_hsv_to_rgb(wd->color->h, wd->color->s, 0, &r, &g, &b); evas_color_hsv_to_rgb(wd->color->h, wd->color->s, 1, &rd, &gd, &bd); _e_wid_gradient_set(wd->o_grad, wd->vertical, r, g, b, rd, gd, bd); vx = wd->color->v; break; case E_COLOR_COMPONENT_MAX: break; } edje_object_part_drag_value_set(wd->o_cslider, "e.dragable.cursor", vx, vx); } void _e_wid_update_fixed(E_Widget_Data *wd) { #define GMAX 255 #define GMIN 0 Evas_Object *o; Eina_List *l; Evas_Coord x, y, w, h; unsigned int i; float vx = 0; int grad[7][3] = { { GMAX, GMIN, GMIN }, { GMAX, GMIN, GMAX }, { GMIN, GMIN, GMAX }, { GMIN, GMAX, GMAX }, { GMIN, GMAX, GMIN }, { GMAX, GMAX, GMIN }, { GMAX, GMIN, GMIN } }; if (!wd) return; switch (wd->mode) { case E_COLOR_COMPONENT_R: _e_wid_gradient_set(wd->o_grad, wd->vertical, 255, 0, 0, 0, 0, 0); vx = wd->color->r / 255.0; break; case E_COLOR_COMPONENT_G: _e_wid_gradient_set(wd->o_grad, wd->vertical, 0, 255, 0, 0, 0, 0); vx = wd->color->g / 255.0; break; case E_COLOR_COMPONENT_B: _e_wid_gradient_set(wd->o_grad, wd->vertical, 0, 0, 255, 0, 0, 0); vx = wd->color->b / 255.0; break; case E_COLOR_COMPONENT_H: /* * Color Stops: * 0 x n n * 60 x x n * 120 n x n * 180 n x x * 240 n n x * 300 x n x * 360 x n n */ if (!wd->o_hgrad) { Evas *e; e = evas_object_evas_get(wd->o_grad); for (i = 0; i < 6; ++i) wd->o_hgrad = eina_list_append(wd->o_hgrad, evas_object_rectangle_add(e)); } evas_object_geometry_get(wd->o_grad, &x, &y, &w, &h); evas_object_hide(wd->o_grad); i = 0; EINA_LIST_FOREACH(wd->o_hgrad, l, o) { if (wd->vertical) { evas_object_move(o, x, y + (i * h) / 6); evas_object_resize(o, w, h / 6); } else { evas_object_move(o, x + (i * w) / 6, y); evas_object_resize(o, w / 6, h); } _e_wid_gradient_set(o, wd->vertical, grad[i][0], grad[i][1], grad[i][2], grad[i + 1][0], grad[i + 1][1], grad[i + 1][2]); evas_object_show(o); i++; } vx = wd->color->h / 360.0; break; case E_COLOR_COMPONENT_S: _e_wid_gradient_set(wd->o_grad, wd->vertical, 255, 255, 255, 0, 0, 0); vx = wd->color->s; break; case E_COLOR_COMPONENT_V: _e_wid_gradient_set(wd->o_grad, wd->vertical, 255, 255, 255, 0, 0, 0); vx = wd->color->v; break; case E_COLOR_COMPONENT_MAX: break; } edje_object_part_drag_value_set(wd->o_cslider, "e.dragable.cursor", vx, vx); #undef GMAX #undef GMIN } static void _e_wid_del_hook(Evas_Object *obj) { E_Widget_Data *wd; wd = e_widget_data_get(obj); free(wd); } static void _e_wid_focus_hook(Evas_Object *obj) { E_Widget_Data *wd; wd = e_widget_data_get(obj); if (e_widget_focus_get(obj)) { edje_object_signal_emit(wd->o_cslider, "e,state,focused", "e"); evas_object_focus_set(wd->o_cslider, 1); } else { edje_object_signal_emit(wd->o_cslider, "e,state,unfocused", "e"); evas_object_focus_set(wd->o_cslider, 0); } } static void _e_wid_disable_hook(Evas_Object *obj) { E_Widget_Data *wd; wd = e_widget_data_get(obj); if (e_widget_disabled_get(obj)) edje_object_signal_emit(wd->o_cslider, "e,state,disabled", "e"); else edje_object_signal_emit(wd->o_cslider, "e,state,enabled", "e"); } static void _e_wid_focus_steal(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) { e_widget_focus_steal(data); } static void _e_wid_cb_down(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info) { Evas_Event_Mouse_Down *ev; Evas_Object *o_wid; E_Widget_Data *wd; Evas_Coord ox, oy, ow, oh; double val; ev = event_info; o_wid = data; wd = e_widget_data_get(o_wid); wd->dragging = 1; evas_object_geometry_get(wd->o_grad, &ox, &oy, &ow, &oh); if (wd->vertical) val = 1 - ((ev->canvas.y - oy) / (double)oh); else val = (ev->canvas.x - ox) / (double)ow; if (val > 1) val = 1; if (val < 0) val = 0; _e_wid_value_set(o_wid, val); } static void _e_wid_cb_up(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) { Evas_Object *o_wid; E_Widget_Data *wd; o_wid = data; wd = e_widget_data_get(o_wid); wd->dragging = 0; } static void _e_wid_cb_move(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info) { Evas_Event_Mouse_Move *ev; Evas_Object *o_wid; E_Widget_Data *wd; o_wid = data; wd = e_widget_data_get(o_wid); ev = event_info; if (wd->dragging == 1) { Evas_Coord ox, oy, ow, oh; double val; evas_object_geometry_get(wd->o_grad, &ox, &oy, &ow, &oh); if (wd->vertical) val = 1 - ((ev->cur.canvas.y - oy) / (double)oh); else val = (ev->cur.canvas.x - ox) / (double)ow; if (val > 1) val = 1; if (val < 0) val = 0; _e_wid_value_set(o_wid, val); } }