700 lines
15 KiB
C
700 lines
15 KiB
C
#include "Evas_private.h"
|
|
#include "Evas.h"
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
#include <string.h>
|
|
|
|
#define SPANS_COMMON(x1, w1, x2, w2) \
|
|
(!((((x2) + (w2)) <= (x1)) || ((x2) >= ((x1) + (w1)))))
|
|
#define RECTS_INTERSECT(x, y, w, h, xx, yy, ww, hh) \
|
|
((SPANS_COMMON((x), (w), (xx), (ww))) && (SPANS_COMMON((y), (h), (yy), (hh))))
|
|
|
|
Evas_Layer
|
|
_evas_get_object_layer(Evas e, Evas_Object o)
|
|
{
|
|
Evas_List l;
|
|
|
|
for (l = e->layers; l; l = l->next)
|
|
{
|
|
Evas_Layer layer;
|
|
|
|
layer = l->data;
|
|
if (layer->layer == o->current.layer) return layer;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
void
|
|
_evas_remove_data(Evas e, Evas_Object o)
|
|
{
|
|
Evas_List l;
|
|
|
|
if (o->data)
|
|
{
|
|
for (l = o->data; l; l = l->next)
|
|
{
|
|
Evas_Data d;
|
|
|
|
d = l->data;
|
|
if (d->key)
|
|
free(d->key);
|
|
free(d);
|
|
}
|
|
evas_list_free(o->data);
|
|
}
|
|
}
|
|
|
|
void
|
|
_evas_remove_callbacks(Evas e, Evas_Object o)
|
|
{
|
|
Evas_List l;
|
|
|
|
if (o->callbacks)
|
|
{
|
|
for (l = o->callbacks; l; l = l->next)
|
|
{
|
|
Evas_Callback cb;
|
|
|
|
cb = l->data;
|
|
free(cb);
|
|
}
|
|
evas_list_free(o->callbacks);
|
|
}
|
|
}
|
|
|
|
void
|
|
_evas_real_del_object(Evas e, Evas_Object o)
|
|
{
|
|
Evas_List l;
|
|
|
|
for (l = e->layers; l; l = l->next)
|
|
{
|
|
Evas_Layer layer;
|
|
|
|
layer = l->data;
|
|
if (layer->layer == o->current.layer)
|
|
{
|
|
layer->objects = evas_list_remove(layer->objects, o);
|
|
_evas_callback_call(e, o, CALLBACK_FREE, 0, 0, 0);
|
|
if (e->mouse.object == o) e->mouse.object = NULL;
|
|
if (e->mouse.button_object == o) e->mouse.button_object = NULL;
|
|
_evas_remove_callbacks(e, o);
|
|
_evas_remove_data(e, o);
|
|
if (o->name) free(o->name);
|
|
o->object_renderer_data_free(e, o);
|
|
o->object_free(o);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
_evas_layer_free(Evas e, Evas_Layer layer)
|
|
{
|
|
if (layer->objects)
|
|
{
|
|
Evas_List l;
|
|
|
|
for (l = layer->objects; l; l = l->next)
|
|
{
|
|
Evas_Object o;
|
|
|
|
o = l->data;
|
|
_evas_callback_call(e, o, CALLBACK_FREE, 0, 0, 0);
|
|
_evas_cleanup_clip(e, o);
|
|
if (e->mouse.object == o) e->mouse.object = NULL;
|
|
if (e->mouse.button_object == o) e->mouse.button_object = NULL;
|
|
_evas_remove_callbacks(e, o);
|
|
_evas_remove_data(e, o);
|
|
o->object_renderer_data_free(e, o);
|
|
o->object_free(o);
|
|
}
|
|
evas_list_free(layer->objects);
|
|
}
|
|
free(layer);
|
|
}
|
|
|
|
void
|
|
_evas_cleanup_clip(Evas e, Evas_Object o)
|
|
{
|
|
if (o->clip.list)
|
|
{
|
|
Evas_List l;
|
|
|
|
for (l = o->clip.list; l; l = l->next)
|
|
{
|
|
Evas_Object o2;
|
|
|
|
o2 = l->data;
|
|
o2->clip.object = NULL;
|
|
o2->clip.changed = 1;
|
|
o2->changed = 1;
|
|
e->changed = 1;
|
|
}
|
|
evas_list_free(o->clip.list);
|
|
o->clip.list = NULL;
|
|
}
|
|
if (o->clip.object)
|
|
o->clip.object->clip.list = evas_list_remove(o->clip.object->clip.list, o);
|
|
}
|
|
|
|
int
|
|
_evas_point_in_object(Evas e, Evas_Object o, int x, int y)
|
|
{
|
|
double cx, cy;
|
|
double ox, oy, ow, oh;
|
|
|
|
if (o->delete_me) return 0;
|
|
cx = evas_screen_x_to_world(e, x);
|
|
cy = evas_screen_x_to_world(e, y);
|
|
ox = o->current.x; oy = o->current.y;
|
|
ow = o->current.w; oh = o->current.h;
|
|
_evas_get_current_clipped_geometry(e, o, &ox, &oy, &ow, &oh);
|
|
if ((cx >= ox) && (cx < (ox + ow)) && (cy >= oy) && (cy < (oy + oh)))
|
|
return 1;
|
|
return 0;
|
|
}
|
|
|
|
void
|
|
evas_set_clip(Evas e, Evas_Object o, Evas_Object clip)
|
|
{
|
|
if (!e) return;
|
|
o = TO_OBJECT(e, o);
|
|
if (!o) return;
|
|
if (!clip) return;
|
|
|
|
if (o->clip.object == clip) return;
|
|
e->changed = 1;
|
|
o->changed = 1;
|
|
o->clip.changed = 1;
|
|
if (o->clip.object)
|
|
o->clip.object->clip.list = evas_list_remove(o->clip.object->clip.list, o);
|
|
o->clip.object = clip;
|
|
clip->clip.list = evas_list_prepend(clip->clip.list, o);
|
|
}
|
|
|
|
void
|
|
evas_unset_clip(Evas e, Evas_Object o)
|
|
{
|
|
if (!e) return;
|
|
o = TO_OBJECT(e, o);
|
|
if (!o) return;
|
|
|
|
if (o->clip.object)
|
|
{
|
|
e->changed = 1;
|
|
o->changed = 1;
|
|
o->clip.changed = 1;
|
|
o->clip.object->clip.list = evas_list_remove(o->clip.object->clip.list, o);
|
|
o->clip.object = NULL;
|
|
}
|
|
}
|
|
|
|
Evas_Object
|
|
evas_get_clip_object(Evas e, Evas_Object o)
|
|
{
|
|
if (!e) return NULL;
|
|
o = TO_OBJECT(e, o);
|
|
if (!o) return NULL;
|
|
|
|
return o->clip.object;
|
|
}
|
|
|
|
Evas_List
|
|
evas_get_clip_list(Evas e, Evas_Object o)
|
|
{
|
|
if (!e) return NULL;
|
|
o = TO_OBJECT(e, o);
|
|
if (!o) return NULL;
|
|
|
|
return o->clip.list;
|
|
}
|
|
|
|
/* deleting objects */
|
|
void
|
|
evas_del_object(Evas e, Evas_Object o)
|
|
{
|
|
if (!e) return;
|
|
o = TO_OBJECT(e, o);
|
|
if (!o) return;
|
|
_evas_cleanup_clip(e, o);
|
|
e->changed = 1;
|
|
evas_hide(e, o);
|
|
o->delete_me = 1;
|
|
}
|
|
|
|
/* layer stacking for object */
|
|
void
|
|
evas_set_layer(Evas e, Evas_Object o, int layer_num)
|
|
{
|
|
Evas_Layer layer;
|
|
Evas_List l;
|
|
int removed;
|
|
|
|
if (!e) return;
|
|
o = TO_OBJECT(e, o);
|
|
if (!o) return;
|
|
if (layer_num == o->current.layer) return;
|
|
removed = 0;
|
|
for (l = e->layers; l; l = l->next)
|
|
{
|
|
layer = l->data;
|
|
if (layer->layer == o->current.layer)
|
|
{
|
|
layer->objects = evas_list_remove(layer->objects, o);
|
|
removed = 1;
|
|
if (!layer->objects)
|
|
{
|
|
e->layers = evas_list_remove(e->layers, layer);
|
|
_evas_layer_free(e, layer);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
if (!removed) return;
|
|
o->changed = 1;
|
|
e->changed = 1;
|
|
o->current.layer = layer_num;
|
|
|
|
for (l = e->layers; l; l = l->next)
|
|
{
|
|
layer = l->data;
|
|
if (layer->layer == o->current.layer)
|
|
{
|
|
layer->objects = evas_list_append(layer->objects, o);
|
|
if ((o->current.visible) &&
|
|
(_evas_point_in_object(e, o, e->mouse.x, e->mouse.y)))
|
|
evas_event_move(e, e->mouse.x, e->mouse.y);
|
|
return;
|
|
}
|
|
if (layer->layer > o->current.layer)
|
|
{
|
|
Evas_Layer layer_new;
|
|
|
|
layer_new = malloc(sizeof(struct _Evas_Layer));
|
|
memset(layer_new, 0, sizeof(struct _Evas_Layer));
|
|
e->layers = evas_list_prepend_relative(e->layers, layer_new, layer);
|
|
layer_new->objects = evas_list_append(layer_new->objects, o);
|
|
layer_new->layer = o->current.layer;
|
|
if ((o->current.visible) &&
|
|
(_evas_point_in_object(e, o, e->mouse.x, e->mouse.y)))
|
|
evas_event_move(e, e->mouse.x, e->mouse.y);
|
|
return;
|
|
}
|
|
}
|
|
layer = malloc(sizeof(struct _Evas_Layer));
|
|
memset(layer, 0, sizeof(struct _Evas_Layer));
|
|
e->layers = evas_list_append(e->layers, layer);
|
|
layer->objects = evas_list_append(layer->objects, o);
|
|
layer->layer = o->current.layer;
|
|
if ((o->current.visible) &&
|
|
(_evas_point_in_object(e, o, e->mouse.x, e->mouse.y)))
|
|
evas_event_move(e, e->mouse.x, e->mouse.y);
|
|
}
|
|
|
|
int
|
|
evas_get_layer(Evas e, Evas_Object o)
|
|
{
|
|
Evas_Layer layer;
|
|
Evas_List l;
|
|
int removed;
|
|
|
|
if (!e) return 0;
|
|
o = TO_OBJECT(e, o);
|
|
if (!o) return 0;
|
|
return o->current.layer;
|
|
}
|
|
|
|
void
|
|
evas_set_layer_store(Evas e, int l, int store)
|
|
{
|
|
if (!e) return;
|
|
/* FIXME: find layer and set store flag */
|
|
/* e->changed = 1; */
|
|
}
|
|
|
|
Evas_List
|
|
evas_objects_in_rect(Evas e, double x, double y, double w, double h)
|
|
{
|
|
Evas_List l, ll, objs;
|
|
Evas_Layer layer;
|
|
|
|
if (!e) return NULL;
|
|
if (w < 0) w = 0;
|
|
if (h < 0) h = 0;
|
|
objs = NULL;
|
|
for (l = e->layers; l ; l = l->next)
|
|
{
|
|
layer = l->data;
|
|
|
|
for (ll = layer->objects; ll; ll = ll->next)
|
|
{
|
|
Evas_Object ob;
|
|
|
|
ob = ll->data;
|
|
if ((ob->current.visible) && (!ob->pass_events) && (!ob->delete_me) && (!ob->clip.list))
|
|
{
|
|
double ox, oy, ow, oh;
|
|
|
|
ox = ob->current.x; oy = ob->current.y;
|
|
ow = ob->current.w; oh = ob->current.h;
|
|
_evas_get_current_clipped_geometry(e, ob, &ox, &oy, &ow, &oh);
|
|
if (RECTS_INTERSECT(x, y, w, h, ox, oy, ow, oh))
|
|
objs = evas_list_prepend(objs, ll->data);
|
|
}
|
|
}
|
|
}
|
|
return objs;
|
|
}
|
|
|
|
Evas_List
|
|
evas_objects_at_position(Evas e, double x, double y)
|
|
{
|
|
Evas_List l, ll, objs;
|
|
Evas_Layer layer;
|
|
|
|
if (!e) return NULL;
|
|
objs = NULL;
|
|
for (l = e->layers; l ; l = l->next)
|
|
{
|
|
layer = l->data;
|
|
|
|
for (ll = layer->objects; ll; ll = ll->next)
|
|
{
|
|
Evas_Object ob;
|
|
|
|
ob = ll->data;
|
|
if ((ob->current.visible) && (!ob->pass_events) && (!ob->delete_me) && (!ob->clip.list))
|
|
{
|
|
double ox, oy, ow, oh;
|
|
|
|
ox = ob->current.x; oy = ob->current.y;
|
|
ow = ob->current.w; oh = ob->current.h;
|
|
_evas_get_current_clipped_geometry(e, ob, &ox, &oy, &ow, &oh);
|
|
if (RECTS_INTERSECT(x, y, 1, 1, ox, oy, ow, oh))
|
|
objs = evas_list_prepend(objs, ll->data);
|
|
}
|
|
}
|
|
}
|
|
return objs;
|
|
}
|
|
|
|
Evas_Object
|
|
evas_object_in_rect(Evas e, double x, double y, double w, double h)
|
|
{
|
|
Evas_List l, ll;
|
|
Evas_Layer layer;
|
|
Evas_Object o;
|
|
|
|
if (!e) return NULL;
|
|
o = NULL;
|
|
for (l = e->layers; l ; l = l->next)
|
|
{
|
|
layer = l->data;
|
|
|
|
for (ll = layer->objects; ll; ll = ll->next)
|
|
{
|
|
Evas_Object ob;
|
|
|
|
ob = ll->data;
|
|
if ((ob->current.visible) && (!ob->pass_events) && (!ob->delete_me) && (!ob->clip.list))
|
|
{
|
|
double ox, oy, ow, oh;
|
|
|
|
ox = ob->current.x; oy = ob->current.y;
|
|
ow = ob->current.w; oh = ob->current.h;
|
|
_evas_get_current_clipped_geometry(e, ob, &ox, &oy, &ow, &oh);
|
|
if (RECTS_INTERSECT(x, y, w, h, ox, oy, ow, oh))
|
|
o = ob;
|
|
}
|
|
}
|
|
}
|
|
return o;
|
|
}
|
|
|
|
Evas_Object
|
|
evas_object_at_position(Evas e, double x, double y)
|
|
{
|
|
Evas_List l, ll;
|
|
Evas_Layer layer;
|
|
Evas_Object o;
|
|
|
|
if (!e) return NULL;
|
|
o = NULL;
|
|
for (l = e->layers; l ; l = l->next)
|
|
{
|
|
layer = l->data;
|
|
|
|
for (ll = layer->objects; ll; ll = ll->next)
|
|
{
|
|
Evas_Object ob;
|
|
|
|
ob = ll->data;
|
|
if ((ob->current.visible) && (!ob->pass_events) && (!ob->delete_me) && (!ob->clip.list))
|
|
{
|
|
double ox, oy, ow, oh;
|
|
|
|
ox = ob->current.x; oy = ob->current.y;
|
|
ow = ob->current.w; oh = ob->current.h;
|
|
_evas_get_current_clipped_geometry(e, ob, &ox, &oy, &ow, &oh);
|
|
if (RECTS_INTERSECT(x, y, 1.0, 1.0, ox, oy, ow, oh))
|
|
o = ob;
|
|
}
|
|
}
|
|
}
|
|
return o;
|
|
}
|
|
|
|
/* stacking within a layer */
|
|
void
|
|
evas_raise(Evas e, Evas_Object o)
|
|
{
|
|
Evas_Layer layer;
|
|
|
|
if (!e) return;
|
|
o = TO_OBJECT(e, o);
|
|
if (!o) return;
|
|
layer = _evas_get_object_layer(e, o);
|
|
if (layer)
|
|
{
|
|
o->current.stacking = 1;
|
|
layer->objects = evas_list_remove(layer->objects, o);
|
|
layer->objects = evas_list_append(layer->objects, o);
|
|
o->changed = 1;
|
|
e->changed = 1;
|
|
if ((o->current.visible) &&
|
|
(_evas_point_in_object(e, o, e->mouse.x, e->mouse.y)))
|
|
evas_event_move(e, e->mouse.x, e->mouse.y);
|
|
}
|
|
}
|
|
|
|
void
|
|
evas_lower(Evas e, Evas_Object o)
|
|
{
|
|
Evas_Layer layer;
|
|
|
|
if (!e) return;
|
|
if (!o) return;
|
|
layer = _evas_get_object_layer(e, o);
|
|
if (layer)
|
|
{
|
|
o->current.stacking = 1;
|
|
layer->objects = evas_list_remove(layer->objects, o);
|
|
layer->objects = evas_list_prepend(layer->objects, o);
|
|
o->changed = 1;
|
|
e->changed = 1;
|
|
if ((o->current.visible) &&
|
|
(_evas_point_in_object(e, o, e->mouse.x, e->mouse.y)))
|
|
evas_event_move(e, e->mouse.x, e->mouse.y);
|
|
}
|
|
}
|
|
|
|
void
|
|
evas_stack_above(Evas e, Evas_Object o, Evas_Object above)
|
|
{
|
|
Evas_Layer layer;
|
|
|
|
if (!e) return;
|
|
o = TO_OBJECT(e, o);
|
|
if (!o) return;
|
|
layer = _evas_get_object_layer(e, o);
|
|
if (layer)
|
|
{
|
|
o->current.stacking = 1;
|
|
layer->objects = evas_list_remove(layer->objects, o);
|
|
layer->objects = evas_list_append_relative(layer->objects, o, above);
|
|
o->changed = 1;
|
|
e->changed = 1;
|
|
if ((o->current.visible) &&
|
|
(_evas_point_in_object(e, o, e->mouse.x, e->mouse.y)))
|
|
evas_event_move(e, e->mouse.x, e->mouse.y);
|
|
}
|
|
}
|
|
|
|
void
|
|
evas_stack_below(Evas e, Evas_Object o, Evas_Object below)
|
|
{
|
|
Evas_Layer layer;
|
|
|
|
if (!e) return;
|
|
o = TO_OBJECT(e, o);
|
|
if (!o) return;
|
|
layer = _evas_get_object_layer(e, o);
|
|
if (layer)
|
|
{
|
|
o->current.stacking = 1;
|
|
layer->objects = evas_list_remove(layer->objects, o);
|
|
layer->objects = evas_list_prepend_relative(layer->objects, o, below);
|
|
o->changed = 1;
|
|
e->changed = 1;
|
|
if ((o->current.visible) &&
|
|
(_evas_point_in_object(e, o, e->mouse.x, e->mouse.y)))
|
|
evas_event_move(e, e->mouse.x, e->mouse.y);
|
|
}
|
|
}
|
|
|
|
/* object geoemtry */
|
|
void
|
|
evas_move(Evas e, Evas_Object o, double x, double y)
|
|
{
|
|
int event_update = 0;
|
|
|
|
if (!e) return;
|
|
o = TO_OBJECT(e, o);
|
|
if (!o) return;
|
|
if ((o->type == OBJECT_LINE)) return;
|
|
if ((x == o->current.x) && (y == o->current.y)) return;
|
|
if ((o->current.visible) &&
|
|
(_evas_point_in_object(e, o, e->mouse.x, e->mouse.y)))
|
|
event_update = 1;
|
|
if ((o->type == OBJECT_POLYGON))
|
|
{
|
|
Evas_Object_Poly oo;
|
|
Evas_List l;
|
|
Evas_Point p;
|
|
double dx, dy;
|
|
|
|
dx = x - o->current.x;
|
|
dy = y - o->current.y;
|
|
o->current.x = x;
|
|
o->current.y = y;
|
|
oo = o;
|
|
for (l = oo->current.points; l; l = l->next)
|
|
{
|
|
p = l->data;
|
|
p->x += dx;
|
|
p->y += dy;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
o->current.x = x;
|
|
o->current.y = y;
|
|
}
|
|
o->changed = 1;
|
|
e->changed = 1;
|
|
if ((o->current.visible) &&
|
|
((_evas_point_in_object(e, o, e->mouse.x, e->mouse.y)) ||
|
|
(event_update)))
|
|
evas_event_move(e, e->mouse.x, e->mouse.y);
|
|
}
|
|
|
|
void
|
|
evas_resize(Evas e, Evas_Object o, double w, double h)
|
|
{
|
|
int event_update = 0;
|
|
|
|
if (!e) return;
|
|
o = TO_OBJECT(e, o);
|
|
if (!o) return;
|
|
if ((o->type == OBJECT_LINE)) return;
|
|
if ((o->type == OBJECT_TEXT)) return;
|
|
if ((o->type == OBJECT_POLYGON)) return;
|
|
if (w < 0) w = 0;
|
|
if (h < 0) h = 0;
|
|
if ((w == o->current.w) && (h == o->current.h)) return;
|
|
if ((o->current.visible) &&
|
|
(_evas_point_in_object(e, o, e->mouse.x, e->mouse.y)))
|
|
event_update = 1;
|
|
o->current.w = w;
|
|
o->current.h = h;
|
|
o->changed = 1;
|
|
e->changed = 1;
|
|
if ((o->current.visible) &&
|
|
((_evas_point_in_object(e, o, e->mouse.x, e->mouse.y)) ||
|
|
(event_update)))
|
|
evas_event_move(e, e->mouse.x, e->mouse.y);
|
|
}
|
|
|
|
void
|
|
evas_get_geometry(Evas e, Evas_Object o, double *x, double *y, double *w, double *h)
|
|
{
|
|
if (!e) return;
|
|
o = TO_OBJECT(e, o);
|
|
if (!o) return;
|
|
if (x) *x = o->current.x;
|
|
if (y) *y = o->current.y;
|
|
if (w) *w = o->current.w;
|
|
if (h) *h = o->current.h;
|
|
e->changed = 1;
|
|
}
|
|
|
|
/* object visibility */
|
|
void
|
|
evas_show(Evas e, Evas_Object o)
|
|
{
|
|
if (!e) return;
|
|
o = TO_OBJECT(e, o);
|
|
if (!o) return;
|
|
o->current.visible = 1;
|
|
o->changed = 1;
|
|
e->changed = 1;
|
|
if (_evas_point_in_object(e, o, e->mouse.x, e->mouse.y))
|
|
evas_event_move(e, e->mouse.x, e->mouse.y);
|
|
}
|
|
|
|
void
|
|
evas_hide(Evas e, Evas_Object o)
|
|
{
|
|
if (!e) return;
|
|
o = TO_OBJECT(e, o);
|
|
if (!o) return;
|
|
o->current.visible = 0;
|
|
o->changed = 1;
|
|
e->changed = 1;
|
|
if (_evas_point_in_object(e, o, e->mouse.x, e->mouse.y))
|
|
evas_event_move(e, e->mouse.x, e->mouse.y);
|
|
if (e->mouse.object == o) e->mouse.object = NULL;
|
|
if (e->mouse.button_object == o) e->mouse.button_object = NULL;
|
|
}
|
|
|
|
Evas_Object
|
|
evas_object_get_named(Evas e, char *name)
|
|
{
|
|
Evas_List l, ll;
|
|
Evas_Layer layer;
|
|
Evas_Object o;
|
|
|
|
if (!e) return NULL;
|
|
if (!name) return NULL;
|
|
for (l = e->layers; l ; l = l->next)
|
|
{
|
|
layer = l->data;
|
|
|
|
for (ll = layer->objects; ll; ll = ll->next)
|
|
{
|
|
o = ll->data;
|
|
if (!o->delete_me)
|
|
{
|
|
if ((o->name) && (!strcmp(name, o->name))) return o;
|
|
}
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
void
|
|
evas_object_set_name(Evas e, Evas_Object o, char *name)
|
|
{
|
|
if (!e) return;
|
|
o = TO_OBJECT(e, o);
|
|
if (!o) return;
|
|
if (o->name) free(o->name);
|
|
o->name = NULL;
|
|
if (name)
|
|
{
|
|
o->name = malloc(strlen(name) + 1);
|
|
strcpy(o->name, name);
|
|
}
|
|
}
|
|
|
|
char *
|
|
evas_object_get_name(Evas e, Evas_Object o)
|
|
{
|
|
if (!e) return NULL;
|
|
o = TO_OBJECT(e, o);
|
|
if (!o) return NULL;
|
|
return o->name;
|
|
}
|