enlightenment-module-desksa.../src/gadgets/core.c

1663 lines
49 KiB
C

#include "e_mod_main.h"
#include "gadget.h"
#define SNAP_DISTANCE 5
#define Z_GADGET_TYPE 0xE31337
#define IS_HORIZ(orient) \
((orient) == Z_GADGET_SITE_ORIENT_HORIZONTAL)
#define IS_VERT(orient) \
((orient) == Z_GADGET_SITE_ORIENT_VERTICAL)
#define ZGS_GET(obj) \
Z_Gadget_Site *zgs; \
zgs = evas_object_data_get((obj), "__z_gadget_site"); \
if (!zgs) abort()
typedef struct Z_Gadget_Config Z_Gadget_Config;
typedef struct Z_Gadget_Site
{
Eina_Stringshare *name;
Eina_Bool autoadd;
Z_Gadget_Site_Gravity gravity;
Z_Gadget_Site_Orient orient;
Z_Gadget_Site_Anchor anchor;
Eina_List *gadgets;
Evas_Object *layout;
Evas_Object *events;
Z_Gadget_Style_Cb style_cb;
int cur_size;
Z_Gadget_Config *action;
Ecore_Event_Handler *move_handler;
Ecore_Event_Handler *mouse_up_handler;
} Z_Gadget_Site;
struct Z_Gadget_Config
{
int id;
Eina_Stringshare *type;
E_Object *e_obj_inherit;
Evas_Object *display;
Evas_Object *gadget;
struct
{
Evas_Object *obj;
int minw, minh;
Eina_Stringshare *name;
} style;
Z_Gadget_Configure_Cb configure;
Z_Gadget_Configure_Cb wizard;
Evas_Object *cfg_object;
Z_Gadget_Site *site;
E_Menu *menu;
double x, y; //fixed % positioning
double w, h; //fixed % sizing
Evas_Point offset; //offset from mouse down
Evas_Point down; //coords from mouse down
Z_Gadget_Config *over; //gadget is animating over another gadget during drag
Eina_Bool moving : 1;
Eina_Bool resizing : 1;
};
typedef struct Z_Gadget_Sites
{
Eina_List *sites;
} Z_Gadget_Sites;
static Eina_Hash *gadget_types;
static Z_Gadget_Sites *sites;
static Ecore_Event_Handler *comp_add_handler;
static E_Action *move_act;
static E_Action *resize_act;
static E_Action *configure_act;
static E_Action *menu_act;
static E_Config_DD *edd_sites;
static E_Config_DD *edd_site;
static E_Config_DD *edd_gadget;
static void
_gadget_free(Z_Gadget_Config *zgc)
{
evas_object_del(zgc->display);
eina_stringshare_del(zgc->type);
eina_stringshare_del(zgc->style.name);
free(zgc);
}
static Z_Gadget_Config *
_gadget_at_xy(Z_Gadget_Site *zgs, int x, int y, Z_Gadget_Config *exclude)
{
Eina_List *l;
Z_Gadget_Config *zgc, *saved = NULL;
EINA_LIST_FOREACH(zgs->gadgets, l, zgc)
{
int ox, oy, ow, oh;
if (!zgc->gadget) continue;
evas_object_geometry_get(zgc->display, &ox, &oy, &ow, &oh);
if (E_INSIDE(x, y, ox, oy, ow, oh))
{
if (zgc == exclude) saved = zgc;
else return zgc;
}
}
return saved;
}
static void
_gravity_apply(Evas_Object *ly, Z_Gadget_Site_Gravity gravity)
{
double ax = 0.5, ay = 0.5;
switch (gravity)
{
case Z_GADGET_SITE_GRAVITY_LEFT:
ax = 0;
break;
case Z_GADGET_SITE_GRAVITY_RIGHT:
ax = 1;
break;
default: break;
}
switch (gravity)
{
case Z_GADGET_SITE_GRAVITY_TOP:
ay = 0;
break;
case Z_GADGET_SITE_GRAVITY_BOTTOM:
ay = 1;
break;
default: break;
}
elm_box_align_set(ly, ax, ay);
}
static void
_gadget_reparent(Z_Gadget_Site *zgs, Z_Gadget_Config *zgc)
{
if (!zgs->orient)
{
evas_object_layer_set(zgc->display, evas_object_layer_get(zgs->layout));
return;
}
switch (zgs->gravity)
{
case Z_GADGET_SITE_GRAVITY_NONE:
/* fake */
break;
case Z_GADGET_SITE_GRAVITY_LEFT:
case Z_GADGET_SITE_GRAVITY_TOP:
elm_box_pack_end(zgs->layout, zgc->display);
break;
default:
/* right aligned: pack on left */
elm_box_pack_start(zgs->layout, zgc->display);
}
}
static void
_gadget_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
{
Z_Gadget_Config *zgc = data;
if (!e_object_is_del(zgc->e_obj_inherit))
e_object_del(zgc->e_obj_inherit);
}
static void
_gadget_object_free(E_Object *eobj)
{
Z_Gadget_Config *zgc;
Evas_Object *g;
g = e_object_data_get(eobj);
zgc = evas_object_data_get(g, "__z_gadget");
evas_object_smart_callback_call(zgc->site->layout, "gadget_removed", zgc->gadget);
evas_object_event_callback_del_full(zgc->gadget, EVAS_CALLBACK_DEL, _gadget_del, zgc);
if (zgc->gadget != zgc->display)
evas_object_event_callback_del_full(zgc->display, EVAS_CALLBACK_DEL, _gadget_del, zgc);
E_FREE_FUNC(zgc->gadget, evas_object_del);
E_FREE_FUNC(zgc->cfg_object, evas_object_del);
E_FREE_FUNC(zgc->style.obj, evas_object_del);
E_FREE(zgc->e_obj_inherit);
}
static void
_gadget_object_create(Z_Gadget_Config *zgc)
{
Z_Gadget_Create_Cb cb;
Evas_Object *g;
cb = eina_hash_find(gadget_types, zgc->type);
if (!cb) return; //can't create yet
/* if id is < 0, gadget creates dummy config for demo use
* if id is 0, gadget creates new config and returns id
* otherwise, config of `id` is applied to created object
*/
g = cb(zgc->site->layout, &zgc->id, zgc->site->orient);
EINA_SAFETY_ON_NULL_RETURN(g);
zgc->e_obj_inherit = E_OBJECT_ALLOC(E_Object, Z_GADGET_TYPE, _gadget_object_free);
e_object_data_set(zgc->e_obj_inherit, g);
zgc->gadget = zgc->display = g;
evas_object_data_set(g, "__z_gadget", zgc);
if (zgc->site->style_cb)
zgc->site->style_cb(zgc->site->layout, zgc->style.name, g);
evas_object_event_callback_add(g, EVAS_CALLBACK_DEL, _gadget_del, zgc);
_gadget_reparent(zgc->site, zgc);
evas_object_raise(zgc->site->events);
evas_object_smart_callback_call(zgc->site->layout, "gadget_created", g);
evas_object_smart_callback_call(zgc->site->layout, "gadget_gravity", g);
evas_object_show(zgc->display);
}
static void
_site_gadget_resize(Evas_Object *g, int w, int h, Evas_Coord *ww, Evas_Coord *hh, Evas_Coord *ow, Evas_Coord *oh)
{
Evas_Coord mnw, mnh, mxw, mxh;
Z_Gadget_Config *zgc;
Evas_Aspect_Control aspect;
int ax, ay;
zgc = evas_object_data_get(g, "__z_gadget");
w -= zgc->style.minw;
h -= zgc->style.minh;
evas_object_size_hint_min_get(g, &mnw, &mnh);
evas_object_size_hint_max_get(g, &mxw, &mxh);
evas_object_size_hint_aspect_get(g, &aspect, &ax, &ay);
if (IS_HORIZ(zgc->site->orient))
{
*ww = mnw, *hh = h;
if (!(*ww)) *ww = *hh;
}
else if (IS_VERT(zgc->site->orient))
{
*hh = mnh, *ww = w;
if (!(*hh)) *hh = *ww;
}
else
{
*ww = mnw, *hh = mnh;
if (!(*ww)) *ww = w;
if (!(*hh)) *hh = h;
}
if (aspect && ax && ay)
{
switch (aspect)
{
case EVAS_ASPECT_CONTROL_HORIZONTAL:
*hh = (*ww * ay / ax);
break;
case EVAS_ASPECT_CONTROL_VERTICAL:
*ww = (*hh * ax / ay);
break;
default:
if (IS_HORIZ(zgc->site->orient))
*ww = (*hh * ax / ay);
else if (IS_VERT(zgc->site->orient))
*hh = (*ww * ay / ax);
else
{
double ar = ax / (double) ay;
if (ar > 1.0)
*hh = (*ww * ay / ax);
else
*ww = (*hh * ax / ay);
}
}
}
*ww += zgc->style.minw;
*hh += zgc->style.minh;
*ow = *ww, *oh = *hh;
if ((!ax) && (!ay))
{
if ((mxw >= 0) && (mxw < *ow)) *ow = mxw;
if ((mxh >= 0) && (mxh < *oh)) *oh = mxh;
}
evas_object_resize(zgc->display, *ow, *oh);
}
static void
_site_move(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
{
int x, y, w, h;
Z_Gadget_Site *zgs = data;
evas_object_geometry_get(obj, &x, &y, &w, &h);
evas_object_geometry_set(zgs->events, x, y, w, h);
if (!zgs->orient)
evas_object_smart_need_recalculate_set(zgs->layout, 1);
}
static void
_site_layout_orient(Evas_Object *o, Z_Gadget_Site *zgs)
{
Evas_Coord x, y, w, h, xx, yy;
Eina_List *l;
double ax, ay;
Z_Gadget_Config *zgc;
evas_object_geometry_get(o, &x, &y, &w, &h);
evas_object_geometry_set(zgs->events, x, y, w, h);
evas_object_box_align_get(o, &ax, &ay);
xx = x;
yy = y;
/* do layout for rest of gadgets now to avoid fixed gadgets */
if (zgs->gravity % 2)//left/top
{
EINA_LIST_FOREACH(zgs->gadgets, l, zgc)
{
Evas_Coord gx = xx, gy = yy;
int ww, hh, ow, oh;
if (!zgc->display) continue;
_site_gadget_resize(zgc->gadget, w, h, &ww, &hh, &ow, &oh);
if (IS_HORIZ(zgs->orient))
gx += (Evas_Coord)(((double)(ww - ow)) * 0.5),
gy += (h / 2) - (oh / 2);
else if (IS_VERT(zgs->orient))
gy += (Evas_Coord)(((double)(hh - oh)) * 0.5),
gx += (w / 2) - (ow / 2);
if (zgc->over)
evas_object_stack_above(zgc->display, zgc->over->gadget);
if (zgs->orient && ((zgc->x > -1) || (zgc->y > -1)))
{
if (IS_HORIZ(zgs->orient))
evas_object_move(zgc->display, zgc->x * (double)w, gy);
else
evas_object_move(zgc->display, gx, zgc->y * (double)h);
}
else
evas_object_move(zgc->display, gx, gy);
if (IS_HORIZ(zgs->orient))
xx += ow;
else
yy += oh;
}
}
else if (zgs->gravity)
{
if (IS_HORIZ(zgs->orient))
xx += w;
else
yy += h;
EINA_LIST_REVERSE_FOREACH(zgs->gadgets, l, zgc)
{
Evas_Coord gx = xx, gy = yy;
int ww, hh, ow, oh;
if (!zgc->display) continue;
_site_gadget_resize(zgc->gadget, w, h, &ww, &hh, &ow, &oh);
if (IS_HORIZ(zgs->orient))
gx -= (Evas_Coord)(((double)(ww - ow)) * 0.5) + ow,
gy += (h / 2) - (oh / 2);
else
gy -= (Evas_Coord)(((double)(hh - oh)) * 0.5) + oh,
gx += (w / 2) - (ow / 2);
evas_object_move(zgc->display, gx, gy);
if (IS_HORIZ(zgs->orient))
xx -= ow;
else
yy -= oh;
}
}
if (IS_HORIZ(zgs->orient))
zgs->cur_size = abs((ax * w) - xx) - x;
else if (IS_VERT(zgs->orient))
zgs->cur_size = abs((ay * h) - yy) - y;
evas_object_size_hint_min_set(o,
IS_HORIZ(zgs->orient) ? zgs->cur_size : w,
IS_VERT(zgs->orient) ? zgs->cur_size : h);
}
static void
_site_layout(Evas_Object *o, Evas_Object_Box_Data *priv EINA_UNUSED, void *data)
{
Z_Gadget_Site *zgs = data;
Evas_Coord x, y, w, h, xx, yy;//, px, py;
Eina_List *l;
double ax, ay;
Z_Gadget_Config *zgc;
evas_object_geometry_get(o, &x, &y, &w, &h);
evas_object_geometry_set(zgs->events, x, y, w, h);
evas_object_box_align_get(o, &ax, &ay);
xx = x;
yy = y;
if (zgs->orient)
{
_site_layout_orient(o, zgs);
return;
}
EINA_LIST_FOREACH(zgs->gadgets, l, zgc)
{
Evas_Coord gx = xx, gy = yy;
int ww, hh, ow, oh;
if (!zgc->display) continue;
_site_gadget_resize(zgc->gadget, w * zgc->w, h * zgc->h, &ww, &hh, &ow, &oh);
if (zgc->x > -1.0)
{
gx = zgc->x * w;
gx += (Evas_Coord)(((double)(ww - ow)) * 0.5 * -ax);
}
if (zgc->y > -1.0)
{
gy = zgc->y * h;
gy += (Evas_Coord)(((double)(hh - oh)) * 0.5 * -ay);
}
if (zgs->gravity)
{
#if 0//FIXME
if (zgs->gravity % 2)//left/top
{
if (gx < px) gx = px;
}
else if (
{
if (gx > px) gx = px;
}
if (zgs->gravity % 2)//left/top
{
if (gy < py) gy = py;
}
else
{
if (gy > py) gy = py;
}
#endif
}
evas_object_move(zgc->display, gx, gy);
#if 0//FIXME
if (zgs->gravity is horizontal or something)
px = gx + (-ax * ow);
else
py = gy + (-ay * oh);
#endif
if (eina_list_count(zgs->gadgets) == 1)
evas_object_size_hint_min_set(o, ow, oh);
}
}
static Eina_Bool
_gadget_mouse_resize(Z_Gadget_Config *zgc, int t EINA_UNUSED, Ecore_Event_Mouse_Move *ev)
{
int x, y, w, h;//site geom
int ox, oy, ow, oh;//gadget geom
double gw, gh;
evas_object_geometry_get(zgc->site->layout, &x, &y, &w, &h);
evas_object_geometry_get(zgc->display, &ox, &oy, &ow, &oh);
gw = zgc->w * w;
gh = zgc->h * h;
gw += (ev->x - zgc->down.x);
gh += (ev->y - zgc->down.y);
zgc->w = gw / w;
zgc->h = gh / h;
zgc->down.x = ev->x;
zgc->down.y = ev->y;
elm_box_recalculate(zgc->site->layout);
e_config_save_queue();
return ECORE_CALLBACK_RENEW;
}
static Eina_Bool
_gadget_mouse_move(Z_Gadget_Config *zgc, int t EINA_UNUSED, Ecore_Event_Mouse_Move *ev)
{
int x, y, w, h;//site geom
int mx, my;//mouse coords normalized for layout orientation
int gw, gh;//"relative" region size
int *rw, *rh;//"relative" region size aliasing
int ox, oy, ow, oh;//gadget geom
Z_Gadget_Config *z;
evas_object_geometry_get(zgc->site->layout, &x, &y, &w, &h);
gw = w, gh = h;
mx = ev->x;
my = ev->y;
evas_object_geometry_get(zgc->display, &ox, &oy, &ow, &oh);
if (!zgc->site->orient)
{
ox = E_CLAMP(mx - zgc->offset.x - x, x, x + w);
oy = E_CLAMP(my - zgc->offset.y - y, y, y + w);
zgc->x = ox / (double)w;
zgc->y = oy / (double)h;
evas_object_move(zgc->display, ox, oy);
e_config_save_queue();
return ECORE_CALLBACK_RENEW;
}
rw = &gw;
rh = &gh;
/* normalize constrained axis to get a valid coordinate */
if (IS_HORIZ(zgc->site->orient))
{
my = y + 1;
*rw = zgc->site->cur_size;
}
else if (IS_VERT(zgc->site->orient))
{
mx = x + 1;
*rh = zgc->site->cur_size;
}
#define OUT \
fprintf(stderr, "OUT %d\n", __LINE__)
if (E_INSIDE(mx, my, x, y, w, h))
{
/* dragging inside site */
int sx = x, sy = y;
double ax, ay;
/* adjust contiguous site geometry for gravity */
elm_box_align_get(zgc->site->layout, &ax, &ay);
if (IS_HORIZ(zgc->site->orient))
sx = x + ((w - zgc->site->cur_size) * ax);
else if (IS_VERT(zgc->site->orient))
sy = y + ((h - zgc->site->cur_size) * ay);
if (E_INSIDE(mx, my, sx, sy, *rw + SNAP_DISTANCE, *rh + SNAP_DISTANCE))
{
/* dragging inside relative area */
int ggx, ggy, ggw, ggh;
Eina_List *l;
Eina_Bool left = EINA_FALSE;//moving gadget is "left" of this gadget
EINA_LIST_FOREACH(zgc->site->gadgets, l, z)
{
if (z == zgc)
{
left = EINA_TRUE;
continue;
}
evas_object_geometry_get(z->gadget, &ggx, &ggy, &ggw, &ggh);
if (E_INTERSECTS(ox, oy, ow, oh, ggx, ggy, ggw, ggh)) break;
}
if (z && (z != zgc))
{
/* found a gadget that is not the current gadget */
int *pmx, *pggx, *pggw, *px, *pw, *offx;
double *zx;
if (IS_HORIZ(zgc->site->orient))
pmx = &mx, pggx = &ggx, pggw = &ggw,
px = &x, pw = &w, zx = &zgc->x, offx = &zgc->offset.x;
else
pmx = &my, pggx = &ggy, pggw = &ggh,
px = &y, pw = &h, zx = &zgc->y, offx = &zgc->offset.y;
if (left)
{
if (*pmx >= *pggx + (*pggw / 2)) // more than halfway over
{
if (eina_list_data_get(l->next) != zgc)
{
zgc->site->gadgets = eina_list_remove(zgc->site->gadgets, zgc);
zgc->site->gadgets = eina_list_append_relative_list(zgc->site->gadgets, zgc, l);
zgc->over = NULL;
*zx = -1.0;
OUT;
}
}
else // less
{
*zx = (double)(*pmx - *px - *offx) / (double)*pw;
zgc->over = z;
OUT;
}
}
else
{
if (*pmx <= *pggx + (*pggw / 2)) // more than halfway over
{
if (eina_list_data_get(l->prev) != zgc)
{
zgc->site->gadgets = eina_list_remove(zgc->site->gadgets, zgc);
zgc->site->gadgets = eina_list_prepend_relative_list(zgc->site->gadgets, zgc, l);
zgc->over = NULL;
*zx = -1.0;
OUT;
}
}
else // less
{
*zx = (double)(*pmx - *px - *offx) / (double)*pw;
zgc->over = z;
OUT;
}
}
}
else if (E_INSIDE(mx, my, sx, sy, *rw, *rh))
{
/* no found gadget: dragging over current gadget's area */
if (IS_HORIZ(zgc->site->orient))
{
/* clamp to site geometry */
if (mx - x - zgc->offset.x > 0)
{
if (mx - x - zgc->offset.x + ow <= w)
{zgc->x = (double)(mx - x - zgc->offset.x) / w;OUT;}
else
{zgc->x = -1;OUT;}
}
else
{zgc->x = -1;OUT;}
}
else if (IS_VERT(zgc->site->orient))
{
/* clamp to site geometry */
if (my - y - zgc->offset.y > 0)
{
if (my - y - zgc->offset.y + oh <= h)
{zgc->y = (double)(my - y - zgc->offset.y) / h;OUT;}
else
{zgc->y = -1;OUT;}
}
else
{zgc->y = -1;OUT;}
}
zgc->over = NULL;
}
else
{
if (eina_list_data_get(zgc->site->gadgets) == zgc)
{
/* first gadget in site dragging past itself:
* lock position
*/
if (IS_HORIZ(zgc->site->orient))
zgc->x = -1;
else if (IS_VERT(zgc->site->orient))
zgc->y = -1;
}
else
{
zgc->site->gadgets = eina_list_remove(zgc->site->gadgets, zgc);
zgc->site->gadgets = eina_list_append(zgc->site->gadgets, zgc);
if (IS_HORIZ(zgc->site->orient))
zgc->x = -1;
else if (IS_VERT(zgc->site->orient))
zgc->y = -1;
}
}
}
else
{
/* dragging outside relative area */
if (!((zgc->x > -1) || (zgc->y > -1)))
{
zgc->site->gadgets = eina_list_remove(zgc->site->gadgets, zgc);
zgc->site->gadgets = eina_list_append(zgc->site->gadgets, zgc);
}
if (IS_HORIZ(zgc->site->orient))
zgc->x = (double)(mx - zgc->offset.x - ((1 - ax) * zgc->site->cur_size)) / (double)w;
else if (IS_VERT(zgc->site->orient))
zgc->y = (double)(my - zgc->offset.y - ((1 - ay) * zgc->site->cur_size)) / (double)h;
OUT;
}
}
else
{
/* dragging to edge of site */
Eina_Bool left;
double *fx;
if (IS_HORIZ(zgc->site->orient))
{
fx = &zgc->x;
left = mx <= x;
}
else
{
fx = &zgc->y;
left = my <= y;
}
if (left)
{
if (zgc->site->gravity % 2) //left/top
{
*fx = -1.0;
zgc->site->gadgets = eina_list_remove(zgc->site->gadgets, zgc);
zgc->site->gadgets = eina_list_prepend(zgc->site->gadgets, zgc);OUT;
}
else
{
*fx = 0.0;
zgc->site->gadgets = eina_list_remove(zgc->site->gadgets, zgc);
zgc->site->gadgets = eina_list_append(zgc->site->gadgets, zgc);OUT;
}
}
else
{
if (zgc->site->gravity % 2) //left/top
{
*fx = 1.0;
zgc->site->gadgets = eina_list_remove(zgc->site->gadgets, zgc);
zgc->site->gadgets = eina_list_prepend(zgc->site->gadgets, zgc);OUT;
}
else
{
*fx = -1.0;
zgc->site->gadgets = eina_list_remove(zgc->site->gadgets, zgc);
zgc->site->gadgets = eina_list_append(zgc->site->gadgets, zgc);OUT;
}
}
}
e_config_save_queue();
elm_box_recalculate(zgc->site->layout);
return ECORE_CALLBACK_RENEW;
}
static void
_gadget_act_resize_end(E_Object *obj, const char *params EINA_UNUSED, E_Binding_Event_Mouse_Button *ev EINA_UNUSED)
{
Z_Gadget_Config *zgc;
Evas_Object *g;
g = e_object_data_get(obj);
zgc = evas_object_data_get(g, "__z_gadget");
zgc->moving = 0;
E_FREE_FUNC(zgc->site->move_handler, ecore_event_handler_del);
}
static void
_gadget_act_move_end(E_Object *obj, const char *params EINA_UNUSED, E_Binding_Event_Mouse_Button *ev EINA_UNUSED)
{
Z_Gadget_Config *zgc;
Evas_Object *g;
Eina_Bool recalc = EINA_FALSE;
g = e_object_data_get(obj);
zgc = evas_object_data_get(g, "__z_gadget");
zgc->moving = 0;
if (zgc->over)
{
OUT;
/* FIXME: animate */
zgc->x = zgc->y = -1.0;
zgc->over = NULL;
recalc = 1;
}
if (recalc)
elm_box_recalculate(zgc->site->layout);
E_FREE_FUNC(zgc->site->move_handler, ecore_event_handler_del);
}
static void
_gadget_act_move(E_Object *obj, const char *params EINA_UNUSED, E_Binding_Event_Mouse_Button *ev EINA_UNUSED)
{
Z_Gadget_Config *zgc;
Evas_Object *g;
if (obj->type != Z_GADGET_TYPE) return;
g = e_object_data_get(obj);
zgc = evas_object_data_get(g, "__z_gadget");
zgc->moving = 1;
if (!zgc->site->move_handler)
zgc->site->move_handler = ecore_event_handler_add(ECORE_EVENT_MOUSE_MOVE, (Ecore_Event_Handler_Cb)_gadget_mouse_move, zgc);
}
static void
_gadget_act_resize(E_Object *obj, const char *params EINA_UNUSED, E_Binding_Event_Mouse_Button *ev EINA_UNUSED)
{
Z_Gadget_Config *zgc;
Evas_Object *g;
if (obj->type != Z_GADGET_TYPE) return;
g = e_object_data_get(obj);
zgc = evas_object_data_get(g, "__z_gadget");
if (zgc->site->orient) return;
zgc->resizing = 1;
if (!zgc->site->move_handler)
zgc->site->move_handler = ecore_event_handler_add(ECORE_EVENT_MOUSE_MOVE, (Ecore_Event_Handler_Cb)_gadget_mouse_resize, zgc);
}
static void
_gadget_act_configure_object_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
{
Z_Gadget_Config *zgc = data;
zgc->cfg_object = NULL;
}
static void
_gadget_configure(Z_Gadget_Config *zgc)
{
if (!zgc->configure) return;
if (zgc->cfg_object)
{
evas_object_raise(zgc->cfg_object);
evas_object_show(zgc->cfg_object);
return;
}
zgc->cfg_object = zgc->configure(zgc->gadget);
if (!zgc->cfg_object) return;
evas_object_event_callback_add(zgc->cfg_object, EVAS_CALLBACK_DEL, _gadget_act_configure_object_del, zgc);
}
static void
_gadget_act_configure(E_Object *obj, const char *params EINA_UNUSED, E_Binding_Event_Mouse_Button *ev EINA_UNUSED)
{
Z_Gadget_Config *zgc;
Evas_Object *g;
if (obj->type != Z_GADGET_TYPE) return;
g = e_object_data_get(obj);
zgc = evas_object_data_get(g, "__z_gadget");
_gadget_configure(zgc);
}
static void
_gadget_menu_remove(void *data, E_Menu *m EINA_UNUSED, E_Menu_Item *mi EINA_UNUSED)
{
Z_Gadget_Config *zgc = data;
evas_object_smart_callback_call(zgc->site->layout, "gadget_removed", zgc->display);
zgc->site->gadgets = eina_list_remove(zgc->site->gadgets, zgc);
_gadget_free(zgc);
e_config_save_queue();
}
static void
_gadget_menu_configure(void *data, E_Menu *m EINA_UNUSED, E_Menu_Item *mi EINA_UNUSED)
{
_gadget_configure(data);
}
static void
_gadget_style_menu_item_del(void *mi)
{
eina_stringshare_del(e_object_data_get(mi));
}
static void
_gadget_menu_style(void *data, E_Menu *m EINA_UNUSED, E_Menu_Item *mi)
{
Z_Gadget_Config *zgc = data;
Eina_Stringshare *style = e_object_data_get(E_OBJECT(mi));
eina_stringshare_refplace(&zgc->style.name, style);
if (zgc->site->style_cb)
zgc->site->style_cb(zgc->site->layout, style, zgc->gadget);
}
static void
_gadget_act_menu(E_Object *obj, const char *params EINA_UNUSED, E_Binding_Event_Mouse_Button *ev)
{
Z_Gadget_Config *zgc;
Evas_Object *g;
E_Menu_Item *mi;
E_Menu *subm;
int x, y;
if (obj->type != Z_GADGET_TYPE) return;
g = e_object_data_get(obj);
zgc = evas_object_data_get(g, "__z_gadget");
zgc->menu = e_menu_new();
evas_object_smart_callback_call(g, "gadget_menu", zgc->menu);
if (zgc->configure)
{
mi = e_menu_item_new(zgc->menu);
e_menu_item_label_set(mi, _("Settings"));
e_util_menu_item_theme_icon_set(mi, "configure");
e_menu_item_callback_set(mi, _gadget_menu_configure, zgc);
}
if (zgc->menu->items)
{
mi = e_menu_item_new(zgc->menu);
e_menu_item_separator_set(mi, 1);
}
subm = e_menu_new();
evas_object_smart_callback_call(zgc->site->layout, "gadget_style_menu", subm);
if (e_object_data_get(E_OBJECT(subm)))
{
Eina_List *styles = e_object_data_get(E_OBJECT(subm));
Eina_Stringshare *style;
mi = e_menu_item_new(zgc->menu);
e_menu_item_label_set(mi, _("Look"));
e_util_menu_item_theme_icon_set(mi, "preferences-look");
e_menu_item_submenu_set(mi, subm);
e_object_unref(E_OBJECT(subm));
EINA_LIST_FREE(styles, style)
{
char buf[1024];
if (eina_streq(style, "base"))
{
eina_stringshare_del(style);
continue;
}
mi = e_menu_item_new(subm);
strncpy(buf, style, sizeof(buf) - 1);
buf[0] = toupper(buf[0]);
e_menu_item_label_set(mi, buf);
snprintf(buf, sizeof(buf), "enlightenment/%s", style);
e_util_menu_item_theme_icon_set(mi, buf);
e_menu_item_radio_group_set(mi, 1);
e_menu_item_radio_set(mi, 1);
e_menu_item_toggle_set(mi, style == zgc->style.name);
e_menu_item_disabled_set(mi, mi->toggle);
e_object_data_set(E_OBJECT(mi), style);
E_OBJECT_DEL_SET(mi, _gadget_style_menu_item_del);
e_menu_item_callback_set(mi, _gadget_menu_style, zgc);
}
}
else
e_object_del(E_OBJECT(subm));
mi = e_menu_item_new(zgc->menu);
evas_object_smart_callback_call(zgc->site->layout, "gadget_owner_menu", mi);
if (mi->label)
{
mi = e_menu_item_new(zgc->menu);
e_menu_item_separator_set(mi, 1);
}
else
e_object_del(E_OBJECT(mi));
mi = e_menu_item_new(zgc->menu);
e_menu_item_label_set(mi, _("Remove"));
e_util_menu_item_theme_icon_set(mi, "list-remove");
e_menu_item_callback_set(mi, _gadget_menu_remove, zgc);
evas_pointer_canvas_xy_get(e_comp->evas, &x, &y);
e_menu_activate_mouse(zgc->menu,
e_zone_current_get(),
x, y, 1, 1,
E_MENU_POP_DIRECTION_AUTO, ev->timestamp);
evas_object_smart_callback_call(zgc->site->layout, "gadget_popup", zgc->menu->comp_object);
}
static Eina_Bool
_site_mouse_up(Z_Gadget_Site *zgs, int t EINA_UNUSED, Ecore_Event_Mouse_Button *ev)
{
if (e_bindings_mouse_up_ecore_event_handle(E_BINDING_CONTEXT_ANY, zgs->action->e_obj_inherit, ev))
{
evas_object_pointer_mode_set(zgs->events, EVAS_OBJECT_POINTER_MODE_NOGRAB);
zgs->action = NULL;
E_FREE_FUNC(zgs->mouse_up_handler, ecore_event_handler_del);
}
return ECORE_CALLBACK_RENEW;
}
static void
_site_mouse_down(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info)
{
Z_Gadget_Site *zgs = data;
Evas_Event_Mouse_Down *ev = event_info;
Z_Gadget_Config *zgc;
E_Action *act;
zgc = _gadget_at_xy(zgs, ev->output.x, ev->output.y, NULL);
if (!zgc) return;
act = e_bindings_mouse_down_evas_event_handle(E_BINDING_CONTEXT_ANY, zgc->e_obj_inherit, event_info);
if (!act) return;
ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
if (act->func.end_mouse)
{
int x, y;
evas_object_pointer_mode_set(obj, EVAS_OBJECT_POINTER_MODE_NOGRAB_NO_REPEAT_UPDOWN);
zgs->action = zgc;
if (!zgs->mouse_up_handler)
zgs->mouse_up_handler = ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_UP, (Ecore_Event_Handler_Cb)_site_mouse_up, zgs);
evas_object_geometry_get(zgc->display, &x, &y, NULL, NULL);
zgc->offset.x = ev->canvas.x - x;
zgc->offset.y = ev->canvas.y - y;
zgc->down.x = ev->canvas.x;
zgc->down.y = ev->canvas.y;
}
}
static void
_site_drop(void *data, Evas_Object *obj EINA_UNUSED, void *event_info)
{
Z_Gadget_Site *zgs = data, *drop;
Eina_List *l;
Z_Gadget_Config *zgc, *dzgc;
int mx, my;
int x, y, w, h;
drop = evas_object_data_get(event_info, "__z_gadget_site");
evas_pointer_canvas_xy_get(e_comp->evas, &mx, &my);
evas_object_geometry_get(zgs->layout, &x, &y, &w, &h);
if (!E_INSIDE(mx, my, x, y, w, h)) return;
EINA_LIST_FOREACH(zgs->gadgets, l, zgc)
{
if (!zgc->display) continue;
evas_object_geometry_get(zgc->display, &x, &y, &w, &h);
if (E_INSIDE(mx, my, x, y, w, h)) break;
}
if (zgc)
{
Eina_Bool pre = EINA_FALSE;
if (IS_HORIZ(zgs->orient))
{
if (mx <= x + (w / 2))
pre = EINA_TRUE;
}
else if (IS_VERT(zgs->orient))
{
if (my <= y + (h / 2))
pre = EINA_TRUE;
}
else {} //FIXME
if (zgs->orient)
{
Eina_List *ll;
if (pre)
EINA_LIST_REVERSE_FOREACH(drop->gadgets, ll, dzgc)
{
evas_object_del(dzgc->gadget);
zgs->gadgets = eina_list_prepend_relative_list(zgs->gadgets, dzgc, l);
dzgc->site = zgs;
_gadget_object_create(dzgc);
evas_object_smart_callback_call(zgs->layout, "gadget_added", dzgc->display);
}
else
EINA_LIST_REVERSE_FOREACH(drop->gadgets, ll, dzgc)
{
evas_object_del(dzgc->gadget);
zgs->gadgets = eina_list_append_relative_list(zgs->gadgets, dzgc, l);
dzgc->site = zgs;
_gadget_object_create(dzgc);
evas_object_smart_callback_call(zgs->layout, "gadget_added", dzgc->display);
}
}
else
{
int dx, dy, dw, dh, gx, gy, gw, gh;
/* FIXME: this should place _(around)_ the gadget that got dropped on */
evas_object_geometry_get(drop->layout, &dx, &dy, &dw, &dh);
evas_object_geometry_get(zgs->layout, &x, &y, &w, &h);
EINA_LIST_FOREACH(drop->gadgets, l, dzgc)
{
/* calculate positioning offsets and normalize based on drop point */
evas_object_geometry_get(dzgc->display, &gx, &gy, &gw, &gh);
evas_object_del(dzgc->gadget);
zgs->gadgets = eina_list_append(zgs->gadgets, dzgc);
dzgc->x = ((gx - dx) / (double)dw) + ((mx - x) / (double)w);
dzgc->y = ((gy - dy) / (double)dh) + ((my - y) / (double)h);
dzgc->w = gw / (double)dw;
dzgc->h = gh / (double)dh;
dzgc->site = zgs;
_gadget_object_create(dzgc);
evas_object_smart_callback_call(zgs->layout, "gadget_added", dzgc->display);
}
}
}
else
{
if (zgs->orient)
{
if (mx >= x) //right of all exiting gadgets
{
EINA_LIST_FOREACH(drop->gadgets, l, dzgc)
{
evas_object_del(dzgc->gadget);
zgs->gadgets = eina_list_append(zgs->gadgets, dzgc);
dzgc->site = zgs;
_gadget_object_create(dzgc);
evas_object_smart_callback_call(zgs->layout, "gadget_added", dzgc->display);
}
}
else
{
EINA_LIST_REVERSE_FOREACH(drop->gadgets, l, dzgc)
{
evas_object_del(dzgc->gadget);
zgs->gadgets = eina_list_prepend(zgs->gadgets, dzgc);
dzgc->site = zgs;
_gadget_object_create(dzgc);
evas_object_smart_callback_call(zgs->layout, "gadget_added", dzgc->display);
}
}
}
else
{
int dx, dy, dw, dh, gx, gy, gw, gh;
evas_object_geometry_get(drop->layout, &dx, &dy, &dw, &dh);
evas_object_geometry_get(zgs->layout, &x, &y, &w, &h);
EINA_LIST_FOREACH(drop->gadgets, l, dzgc)
{
/* calculate positioning offsets and normalize based on drop point */
evas_object_geometry_get(dzgc->display, &gx, &gy, &gw, &gh);
evas_object_del(dzgc->gadget);
zgs->gadgets = eina_list_append(zgs->gadgets, dzgc);
dzgc->x = ((gx - dx) / (double)dw) + ((mx - x) / (double)w);
dzgc->y = ((gy - dy) / (double)dh) + ((my - y) / (double)h);
dzgc->w = gw / (double)w;
dzgc->h = gh / (double)h;
dzgc->site = zgs;
_gadget_object_create(dzgc);
evas_object_smart_callback_call(zgs->layout, "gadget_added", dzgc->display);
}
}
}
drop->gadgets = eina_list_free(drop->gadgets);
evas_object_smart_need_recalculate_set(zgs->layout, 1);
e_config_save_queue();
}
static void
_site_restack(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
{
Z_Gadget_Site *zgs = data;
if (!evas_object_smart_parent_get(zgs->layout))
{
Eina_List *l;
Z_Gadget_Config *zgc;
int layer;
layer = evas_object_layer_get(obj);
if (!zgs->orient)
{
EINA_LIST_FOREACH(zgs->gadgets, l, zgc)
if (zgc->display)
evas_object_layer_set(zgc->display, layer);
}
evas_object_layer_set(zgs->events, layer);
}
evas_object_raise(zgs->events);
}
static void
_site_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
{
Z_Gadget_Site *zgs = data;
Z_Gadget_Config *zgc;
Eina_List *l;
E_FREE_FUNC(zgs->events, evas_object_del);
zgs->layout = NULL;
zgs->cur_size = 0;
zgs->action = NULL;
zgs->style_cb = NULL;
E_FREE_FUNC(zgs->move_handler, ecore_event_handler_del);
E_FREE_FUNC(zgs->mouse_up_handler, ecore_event_handler_del);
EINA_LIST_FOREACH(zgs->gadgets, l, zgc)
evas_object_del(zgc->gadget);
if (zgs->name) return;
eina_stringshare_del(zgs->name);
free(zgs);
}
static void
_site_style(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
{
Z_Gadget_Site *zgs = data;
Z_Gadget_Config *zgc;
Eina_List *l;
if (!zgs->style_cb) return;
EINA_LIST_FOREACH(zgs->gadgets, l, zgc)
zgc->site->style_cb(zgc->site->layout, zgc->style.name, zgc->gadget);
}
static void
_site_create(Z_Gadget_Site *zgs)
{
zgs->layout = elm_box_add(e_comp->elm);
elm_box_horizontal_set(zgs->layout, zgs->orient == Z_GADGET_SITE_ORIENT_HORIZONTAL);
_gravity_apply(zgs->layout, zgs->gravity);
if (!zgs->orient)
{
/* add dummy content to allow recalc to work */
elm_box_pack_end(zgs->layout, elm_box_add(zgs->layout));
}
elm_box_layout_set(zgs->layout, _site_layout, zgs, NULL);
evas_object_event_callback_add(zgs->layout, EVAS_CALLBACK_DEL, _site_del, zgs);
evas_object_event_callback_add(zgs->layout, EVAS_CALLBACK_RESTACK, _site_restack, zgs);
zgs->events = evas_object_rectangle_add(e_comp->evas);
evas_object_name_set(zgs->events, "zgs->events");
evas_object_event_callback_add(zgs->layout, EVAS_CALLBACK_MOVE, _site_move, zgs);
evas_object_smart_callback_add(zgs->layout, "gadget_site_dropped", _site_drop, zgs);
evas_object_smart_callback_add(zgs->layout, "gadget_site_style", _site_style, zgs);
evas_object_pointer_mode_set(zgs->events, EVAS_OBJECT_POINTER_MODE_NOGRAB);
evas_object_color_set(zgs->events, 0, 0, 0, 0);
evas_object_repeat_events_set(zgs->events, 1);
evas_object_show(zgs->events);
evas_object_event_callback_add(zgs->events, EVAS_CALLBACK_MOUSE_DOWN, _site_mouse_down, zgs);
evas_object_data_set(zgs->layout, "__z_gadget_site", zgs);
E_LIST_FOREACH(zgs->gadgets, _gadget_object_create);
evas_object_layer_set(zgs->events, evas_object_layer_get(zgs->layout));
evas_object_raise(zgs->events);
}
static void
_site_auto_add(Z_Gadget_Site *zgs, Evas_Object *comp_object)
{
int x, y, w, h;
_site_create(zgs);
e_comp_object_util_del_list_append(comp_object, zgs->layout);
evas_object_layer_set(zgs->layout, evas_object_layer_get(comp_object));
evas_object_stack_above(zgs->layout, comp_object);
evas_object_geometry_get(comp_object, &x, &y, &w, &h);
evas_object_geometry_set(zgs->layout, x, y, w, h);
}
static Eina_Bool
_site_auto_comp_object_handler(void *d EINA_UNUSED, int t EINA_UNUSED, E_Event_Comp_Object *ev)
{
const char *name;
Eina_List *l;
Z_Gadget_Site *zgs;
name = evas_object_name_get(ev->comp_object);
if (!name) return ECORE_CALLBACK_RENEW;
EINA_LIST_FOREACH(sites->sites, l, zgs)
if (zgs->autoadd && eina_streq(zgs->name, name))
{
if (!zgs->layout)
_site_auto_add(zgs, ev->comp_object);
break;
}
return ECORE_CALLBACK_RENEW;
}
static Evas_Object *
_site_util_add(Z_Gadget_Site_Orient orient, const char *name, Eina_Bool autoadd)
{
Z_Gadget_Site *zgs;
Eina_List *l;
Evas_Object *parent;
if (name)
{
EINA_LIST_FOREACH(sites->sites, l, zgs)
if (eina_streq(zgs->name, name))
{
if (zgs->layout) return zgs->layout;
goto out;
}
}
zgs = E_NEW(Z_Gadget_Site, 1);
zgs->name = eina_stringshare_add(name);
zgs->orient = orient;
zgs->autoadd = autoadd;
switch (orient)
{
case Z_GADGET_SITE_ORIENT_HORIZONTAL:
zgs->gravity = Z_GADGET_SITE_GRAVITY_LEFT;
break;
case Z_GADGET_SITE_ORIENT_VERTICAL:
zgs->gravity = Z_GADGET_SITE_GRAVITY_TOP;
break;
default: break;
}
if (name)
sites->sites = eina_list_append(sites->sites, zgs);
out:
if (autoadd)
{
parent = evas_object_name_find(e_comp->evas, name);
if (parent)
_site_auto_add(zgs, parent);
}
else
_site_create(zgs);
return zgs->layout;
}
Z_API Evas_Object *
z_gadget_site_add(Z_Gadget_Site_Orient orient, const char *name)
{
return _site_util_add(orient, name, 0);
}
Z_API Evas_Object *
z_gadget_site_auto_add(Z_Gadget_Site_Orient orient, const char *name)
{
return _site_util_add(orient, name, 1);
}
Z_API void
z_gadget_site_del(Evas_Object *obj)
{
ZGS_GET(obj);
sites->sites = eina_list_remove(sites->sites, zgs);
evas_object_del(zgs->layout);
eina_stringshare_del(zgs->name);
free(zgs);
}
Z_API Z_Gadget_Site_Anchor
z_gadget_site_anchor_get(Evas_Object *obj)
{
ZGS_GET(obj);
return zgs->anchor;
}
Z_API void
z_gadget_site_owner_setup(Evas_Object *obj, Z_Gadget_Site_Anchor an, Z_Gadget_Style_Cb cb)
{
Evas_Object *parent;
ZGS_GET(obj);
zgs->anchor = an;
zgs->style_cb = cb;
evas_object_smart_callback_call(obj, "gadget_anchor", NULL);
parent = evas_object_smart_parent_get(obj);
if (parent)
evas_object_smart_member_add(zgs->events, parent);
else
evas_object_smart_member_del(zgs->events);
}
Z_API Z_Gadget_Site_Orient
z_gadget_site_orient_get(Evas_Object *obj)
{
ZGS_GET(obj);
return zgs->orient;
}
Z_API Z_Gadget_Site_Gravity
z_gadget_site_gravity_get(Evas_Object *obj)
{
ZGS_GET(obj);
return zgs->gravity;
}
Z_API void
z_gadget_site_gravity_set(Evas_Object *obj, Z_Gadget_Site_Gravity gravity)
{
ZGS_GET(obj);
zgs->gravity = gravity;
evas_object_smart_need_recalculate_set(zgs->layout, 1);
}
Z_API Eina_List *
z_gadget_site_gadgets_list(Evas_Object *obj)
{
Eina_List *l, *list = NULL;
Z_Gadget_Config *zgc;
ZGS_GET(obj);
EINA_LIST_FOREACH(zgs->gadgets, l, zgc)
if (zgc->display)
list = eina_list_append(list, zgc->display);
return list;
}
Z_API void
z_gadget_site_gadget_add(Evas_Object *obj, const char *type, Eina_Bool demo)
{
Z_Gadget_Config *zgc;
int id = 0;
EINA_SAFETY_ON_NULL_RETURN(gadget_types);
ZGS_GET(obj);
demo = !!demo;
id -= demo;
zgc = E_NEW(Z_Gadget_Config, 1);
zgc->id = id;
zgc->type = eina_stringshare_add(type);
zgc->x = zgc->y = -1;
zgc->site = zgs;
if (zgc->site->orient)
zgc->w = zgc->h = -1;
else
{
int w, h;
evas_object_geometry_get(zgc->site->layout, NULL, NULL, &w, &h);
zgc->w = (96 * e_scale) / (double)w;
zgc->h = (96 * e_scale) / (double)h;
}
_gadget_object_create(zgc);
if (zgc->display)
{
zgc->site->gadgets = eina_list_append(zgc->site->gadgets, zgc);
e_config_save_queue();
return;
}
eina_stringshare_del(zgc->type);
free(zgc);
}
Z_API Evas_Object *
z_gadget_site_get(Evas_Object *g)
{
Z_Gadget_Config *zgc;
EINA_SAFETY_ON_NULL_RETURN_VAL(g, NULL);
zgc = evas_object_data_get(g, "__z_gadget");
EINA_SAFETY_ON_NULL_RETURN_VAL(zgc, NULL);
return zgc->site->layout;
}
Z_API void
z_gadget_configure_cb_set(Evas_Object *g, Z_Gadget_Configure_Cb cb)
{
Z_Gadget_Config *zgc;
EINA_SAFETY_ON_NULL_RETURN(g);
zgc = evas_object_data_get(g, "__z_gadget");
EINA_SAFETY_ON_NULL_RETURN(zgc);
zgc->configure = cb;
}
Z_API void
z_gadget_configure(Evas_Object *g)
{
Z_Gadget_Config *zgc;
EINA_SAFETY_ON_NULL_RETURN(g);
zgc = evas_object_data_get(g, "__z_gadget");
EINA_SAFETY_ON_NULL_RETURN(zgc);
_gadget_configure(zgc);
}
Z_API Eina_Bool
z_gadget_has_wizard(Evas_Object *g)
{
Z_Gadget_Config *zgc;
EINA_SAFETY_ON_NULL_RETURN_VAL(g, EINA_FALSE);
zgc = evas_object_data_get(g, "__z_gadget");
EINA_SAFETY_ON_NULL_RETURN_VAL(zgc, EINA_FALSE);
return !!zgc->wizard;
}
Z_API Eina_Stringshare *
z_gadget_type_get(Evas_Object *g)
{
Z_Gadget_Config *zgc;
EINA_SAFETY_ON_NULL_RETURN_VAL(g, NULL);
zgc = evas_object_data_get(g, "__z_gadget");
EINA_SAFETY_ON_NULL_RETURN_VAL(zgc, NULL);
return zgc->type;
}
Z_API void
z_gadget_type_add(const char *type, Z_Gadget_Create_Cb callback)
{
if (!gadget_types) gadget_types = eina_hash_string_superfast_new(NULL);
eina_hash_add(gadget_types, type, callback);
}
Z_API void
z_gadget_type_del(const char *type)
{
Eina_List *l, *ll;
Z_Gadget_Site *zgs;
Z_Gadget_Config *zgc;
char buf[1024];
strncpy(buf, type, sizeof(buf));
if (!gadget_types) return;
EINA_LIST_FOREACH(sites->sites, l, zgs)
{
EINA_LIST_FOREACH(zgs->gadgets, ll, zgc)
if (eina_streq(buf, zgc->type))
evas_object_del(zgc->gadget);
}
}
Z_API Eina_Iterator *
z_gadget_type_iterator_get(void)
{
return gadget_types ? eina_hash_iterator_key_new(gadget_types) : NULL;
}
Z_API Evas_Object *
z_gadget_util_layout_style_init(Evas_Object *g, Evas_Object *style)
{
Z_Gadget_Config *zgc;
Evas_Object *prev;
const char *grp;
EINA_SAFETY_ON_NULL_RETURN_VAL(g, NULL);
zgc = evas_object_data_get(g, "__z_gadget");
EINA_SAFETY_ON_NULL_RETURN_VAL(zgc, NULL);
prev = zgc->style.obj;
zgc->style.obj = style;
if (style)
{
elm_layout_file_get(style, NULL, &grp);
eina_stringshare_replace(&zgc->style.name, strrchr(grp, '/') + 1);
evas_object_event_callback_add(style, EVAS_CALLBACK_DEL, _gadget_del, zgc);
}
else
eina_stringshare_replace(&zgc->style.name, NULL);
if (prev)
evas_object_event_callback_del_full(prev, EVAS_CALLBACK_DEL, _gadget_del, zgc);
e_config_save_queue();
zgc->display = style ?: zgc->gadget;
E_FILL(zgc->display);
E_EXPAND(zgc->display);
if (zgc->site->gravity)
{
elm_box_pack_before(zgc->site->layout, zgc->display, prev ?: zgc->gadget);
if (prev)
elm_box_unpack(zgc->site->layout, prev);
}
evas_object_raise(zgc->site->events);
if (!style) return prev;
evas_object_data_set(style, "__z_gadget", zgc);
elm_layout_sizing_eval(style);
evas_object_smart_calculate(style);
evas_object_size_hint_min_get(style, &zgc->style.minw, &zgc->style.minh);
evas_object_show(style);
return prev;
}
/* FIXME */
static void
gadget_save(void)
{
e_config_domain_save("gadget_sites", edd_sites, sites);
}
Z_API void
z_gadget_init(void)
{
edd_gadget = E_CONFIG_DD_NEW("Z_Gadget_Config", Z_Gadget_Config);
E_CONFIG_VAL(edd_gadget, Z_Gadget_Config, id, INT);
E_CONFIG_VAL(edd_gadget, Z_Gadget_Config, type, STR);
E_CONFIG_VAL(edd_gadget, Z_Gadget_Config, style.name, STR);
E_CONFIG_VAL(edd_gadget, Z_Gadget_Config, x, DOUBLE);
E_CONFIG_VAL(edd_gadget, Z_Gadget_Config, y, DOUBLE);
E_CONFIG_VAL(edd_gadget, Z_Gadget_Config, w, DOUBLE);
E_CONFIG_VAL(edd_gadget, Z_Gadget_Config, h, DOUBLE);
edd_site = E_CONFIG_DD_NEW("Z_Gadget_Site", Z_Gadget_Site);
E_CONFIG_VAL(edd_site, Z_Gadget_Site, gravity, UINT);
E_CONFIG_VAL(edd_site, Z_Gadget_Site, orient, UINT);
E_CONFIG_VAL(edd_site, Z_Gadget_Site, anchor, UINT);
E_CONFIG_VAL(edd_site, Z_Gadget_Site, autoadd, UCHAR);
E_CONFIG_VAL(edd_site, Z_Gadget_Site, name, STR);
E_CONFIG_LIST(edd_site, Z_Gadget_Site, gadgets, edd_gadget);
edd_sites = E_CONFIG_DD_NEW("Z_Gadget_Sites", Z_Gadget_Sites);
E_CONFIG_LIST(edd_sites, Z_Gadget_Sites, sites, edd_site);
sites = e_config_domain_load("gadget_sites", edd_sites);
if (sites)
{
Eina_List *l;
Z_Gadget_Site *zgs;
EINA_LIST_FOREACH(sites->sites, l, zgs)
{
Eina_List *ll;
Z_Gadget_Config *zgc;
EINA_LIST_FOREACH(zgs->gadgets, ll, zgc)
zgc->site = zgs;
}
}
else
sites = E_NEW(Z_Gadget_Sites, 1);
move_act = e_action_add("gadget_move");
e_action_predef_name_set(D_("Gadgets"), D_("Move gadget"), "gadget_move", NULL, NULL, 0);
move_act->func.go_mouse = _gadget_act_move;
move_act->func.end_mouse = _gadget_act_move_end;
resize_act = e_action_add("gadget_resize");
e_action_predef_name_set(D_("Gadgets"), D_("Resize gadget"), "gadget_resize", NULL, NULL, 0);
resize_act->func.go_mouse = _gadget_act_resize;
resize_act->func.end_mouse = _gadget_act_resize_end;
configure_act = e_action_add("gadget_configure");
e_action_predef_name_set(D_("Gadgets"), D_("Configure gadget"), "gadget_configure", NULL, NULL, 0);
configure_act->func.go_mouse = _gadget_act_configure;
menu_act = e_action_add("gadget_menu");
e_action_predef_name_set(D_("Gadgets"), D_("Gadget menu"), "gadget_menu", NULL, NULL, 0);
menu_act->func.go_mouse = _gadget_act_menu;
comp_add_handler = ecore_event_handler_add(E_EVENT_COMP_OBJECT_ADD, (Ecore_Event_Handler_Cb)_site_auto_comp_object_handler, NULL);
save_cbs = eina_list_append(save_cbs, gadget_save);
}
Z_API void
z_gadget_shutdown(void)
{
Z_Gadget_Site *zgs;
E_CONFIG_DD_FREE(edd_gadget);
E_CONFIG_DD_FREE(edd_site);
E_CONFIG_DD_FREE(edd_sites);
EINA_LIST_FREE(sites->sites, zgs)
{
E_FREE_LIST(zgs->gadgets, _gadget_free);
evas_object_del(zgs->layout);
eina_stringshare_del(zgs->name);
free(zgs);
}
E_FREE(sites);
e_action_del("gadget_move");
e_action_del("gadget_resize");
e_action_del("gadget_configure");
e_action_del("gadget_menu");
e_action_predef_name_del(D_("Gadgets"), D_("Move gadget"));
e_action_predef_name_del(D_("Gadgets"), D_("Resize gadget"));
e_action_predef_name_del(D_("Gadgets"), D_("Configure gadget"));
e_action_predef_name_del(D_("Gadgets"), D_("Gadget menu"));
move_act = resize_act = configure_act = menu_act = NULL;
}