aboutsummaryrefslogtreecommitdiffstats
path: root/egraph/egraph.c
diff options
context:
space:
mode:
Diffstat (limited to 'egraph/egraph.c')
-rw-r--r--egraph/egraph.c1275
1 files changed, 0 insertions, 1275 deletions
diff --git a/egraph/egraph.c b/egraph/egraph.c
deleted file mode 100644
index bffcebf..0000000
--- a/egraph/egraph.c
+++ /dev/null
@@ -1,1275 +0,0 @@
-#include <err.h>
-#include <Efx.h>
-#include <Edje.h>
-
-#include "Egraph.h"
-
-#define DEBUG 0
-
-#define TYPE_MAXLEN 30
-
-static void _smart_add(Evas_Object *obj);
-static void _smart_del(Evas_Object *obj);
-static void _smart_move(Evas_Object *obj, Evas_Coord x, Evas_Coord y);
-static void _smart_resize(Evas_Object *obj, Evas_Coord w, Evas_Coord h);
-static void _edge_v2_add(Egraph *eg, Egraph_Edge *e);
-static void _edge_add(Egraph *eg, Egraph_Edge *e);
-static void _edge_signal(Egraph *eg, Egraph_Edge *e, const char *signal);
-static void _edge_v2_del(Egraph *eg, Egraph_Edge *e);
-static void _edge_del(Egraph *eg, Egraph_Edge *e);
-static void _vertice_v2_add(Egraph *eg, Egraph_Vertice *v);
-static void _vertice_add(Egraph *eg, Egraph_Vertice *v);
-static void _vertice_v2_del(Egraph *eg, Egraph_Vertice *v);
-static void _vertice_del(Egraph *eg, Egraph_Vertice *v);
-static void _vertice_update_status(Egraph *eg, Egraph_Vertice *v);
-static void _vertice_signal(Egraph *eg, Egraph_Vertice *v, const char *signal);
-static void _vertice_geometry_update(Egraph *eg, Egraph_Vertice *v);
-static void _v2_update(Egraph *eg);
-static void _v3_update(Egraph *eg);
-static void _coords2_copy(Egraph *eg);
-static void _cb_blob_arrived(void *data, Efx_Map_Data *e, Evas_Object *obj);
-static void _blob_send(Evas_Object *blob,
- Egraph_Vertice *v, Evas_Coord x, Evas_Coord y);
-static void _layouting_schedule(Egraph *eg);
-static Eina_Bool _cb_layouting_start(void *data);
-static void _cb_layouting_run(void *data, Ecore_Thread *thread);
-static void _cb_layouting_end(void *data, Ecore_Thread *thread);
-static void _cb_layouting_cancel(void *data, Ecore_Thread *thread);
-static int _igraph_query_vid(igraph_t *g, int g_len, int id);
-static void _cb_vertice_move(void *data,
- Evas *evas, Evas_Object *obj, void *event_info);
-static void _reposition(Egraph *eg, int no_animation);
-static void _matrix_minmax_2v(const igraph_matrix_t *m, int row_count,
- float *c1min, float *c1max,
- float *c2min, float *c2max);
-static Evas_Object *_edje_obj_new(Egraph *eg, const char *group);
-static Evas_Object *_edje_obj_set(Egraph *eg, Evas_Object *o, const char *group);
-
-static const Evas_Smart_Cb_Description _smart_callbacks[] = {{NULL, NULL}};
-#define EGRAPH_DATA_GET(o, ptr) \
- Egraph * ptr = evas_object_smart_data_get(o)
-/* defines _egraph_parent_sc and _egraph_smart_class_new */
-EVAS_SMART_SUBCLASS_NEW("Egraph", _egraph,
- Evas_Smart_Class, Evas_Smart_Class,
- evas_object_smart_clipped_class_get, _smart_callbacks);
-
-static void
-_egraph_smart_set_user(Evas_Smart_Class *sc)
-{
- /* specializing these two */
- sc->add = _smart_add;
- sc->del = _smart_del;
- sc->move = _smart_move;
- /* clipped smart object has no hook on resizes or calculations */
- sc->resize = _smart_resize;
-}
-
-static void
-_smart_add(Evas_Object *obj)
-{
- EVAS_SMART_DATA_ALLOC(obj, Egraph);
-
- priv->evas = evas_object_evas_get(obj);
-
- _egraph_parent_sc->add(obj);
-}
-
-static void
-_smart_del(Evas_Object *obj)
-{
- EGRAPH_DATA_GET(obj, eg);
-
- igraph_destroy(&eg->graph);
- if (eg->layouting.running == 2)
- ecore_thread_cancel(eg->layouting.thread);
-
- _egraph_parent_sc->del(obj);
-}
-
-static void
-_smart_move(Evas_Object *obj, Evas_Coord x, Evas_Coord y)
-{
- EGRAPH_DATA_GET(obj, eg);
-
- _reposition(eg, 1);
-
- _egraph_parent_sc->move(obj, x, y);
-}
-
-static void
-_smart_resize(Evas_Object *obj, Evas_Coord w, Evas_Coord h)
-{
- EGRAPH_DATA_GET(obj, eg);
-
- _reposition(eg, 1);
-}
-
-Evas_Object *
-egraph_new(Evas *evas, int directed)
-{
- Evas_Object *obj = NULL;
- Evas_Object *rect;
- Egraph *eg;
- int i;
-
- EINA_SAFETY_ON_NULL_RETURN_VAL(evas, NULL);
-
- efx_init();
- eina_log_domain_level_set("efx", EINA_LOG_LEVEL_WARN);
-
- obj = evas_object_smart_add(evas, _egraph_smart_class_new());
- eg = evas_object_smart_data_get(obj);
- if (!eg) goto err;
- eg->obj = obj;
- rect = evas_object_rectangle_add(eg->evas);
- evas_object_color_set(rect, 0, 0, 0, 0);
- evas_object_smart_member_add(rect, obj);
- eg->split_vertice_edge = rect;
-
- eg->graph_directed = directed;
- eg->display_vertices = 1;
- eg->display_names = 1;
- eg->display_edges = 1;
- eg->use_animations = 1;
- eg->do_improvements = 1;
- egraph_theme_file_set(obj, NULL);
- eg->theme_edges = 1;
- eg->layout = EGRAPH_LAYOUT_DEFAULT;
-
- /* needed for igraph attribute handling */
- igraph_i_set_attribute_table(&igraph_cattribute_table);
-
- eg->vertices = eina_hash_int32_new(NULL);
- for (i=0; i<EGRAPH_VERTICES_MAX-1; i++)
- eg->vertices_freeids[i] = i;
- if (igraph_empty(&eg->graph, 0, directed))
- goto err;
- if (igraph_empty(&eg->graph2, 0, directed))
- goto err;
- igraph_matrix_init(&eg->coords, 0, 2);
- igraph_matrix_init(&eg->coords2, 0, 2);
- eg->graph_wmin = 0;
- eg->graph_wmax = 200;
- eg->graph_hmin = 0;
- eg->graph_hmax = 200;
- eg->vertice_max_w = 0;
- eg->vertice_max_h = 0;
-
- return obj;
-
-err:
- if (obj)
- evas_object_del(obj);
- return NULL;
-}
-
-void
-egraph_clear(Evas_Object *obj)
-{
- EGRAPH_DATA_GET(obj, eg);
- Eina_Iterator *it;
- Egraph_Vertice *v;
- void *data;
-
- it = eina_hash_iterator_tuple_new(eg->vertices);
- while (eina_iterator_next(it, &data)) {
- Eina_Hash_Tuple *t = data;
- v = t->data;
- egraph_vertice_del(obj, v);
- }
-}
-
-void
-egraph_theme_file_set(Evas_Object *obj, char *path)
-{
- EGRAPH_DATA_GET(obj, eg);
-
- if (eg->theme_path)
- free(eg->theme_path);
-
- if (!path) {
- char buf[256];
-
- snprintf(buf, sizeof(buf),
- "%s/egraph.edj",
- "/usr/local/share/egraph"); /* XXX use eina_prefix */
- path = buf;
- }
- eg->theme_path = strndup(path, 256);
-}
-
-void
-egraph_theme_edges_set(Evas_Object *obj, int set)
-{
- EGRAPH_DATA_GET(obj, eg);
-
- eg->theme_edges = set;
-}
-
-void
-egraph_layout_set(Evas_Object *obj, Egraph_Layout layout)
-{
- EGRAPH_DATA_GET(obj, eg);
-
- eg->layout = layout;
- _layouting_schedule(eg);
-}
-
-void
-egraph_display_vertices_set(Evas_Object *obj, int set)
-{
- EGRAPH_DATA_GET(obj, eg);
- Eina_Iterator *it;
- Egraph_Vertice *v;
- void *data;
-
- eg->display_vertices = set;
-
- it = eina_hash_iterator_tuple_new(eg->vertices);
- while (eina_iterator_next(it, &data)) {
- Eina_Hash_Tuple *t = data;
- v = t->data;
- if (v->o) {
- if (set == 0)
- evas_object_hide(v->o);
- else
- evas_object_show(v->o);
- }
- }
-
- _reposition(eg, 0);
-}
-
-void
-egraph_display_names_set(Evas_Object *obj, int set)
-{
- EGRAPH_DATA_GET(obj, eg);
- Eina_Iterator *it;
- Egraph_Vertice *v;
- void *data;
-
- eg->display_names = set;
-
- it = eina_hash_iterator_tuple_new(eg->vertices);
- while (eina_iterator_next(it, &data)) {
- Eina_Hash_Tuple *t = data;
- v = t->data;
- egraph_vertice_rename(obj, v, set ? v->name : NULL);
- }
-}
-
-void
-egraph_display_edges_set(Evas_Object *obj, int set)
-{
- EGRAPH_DATA_GET(obj, eg);
- Eina_List *l;
- Egraph_Edge *e;
-
- eg->display_edges = set;
-
- EINA_LIST_FOREACH(eg->edges, l, e) {
- if (e->o) {
- if (set == 0)
- evas_object_hide(e->o);
- else
- evas_object_show(e->o);
- }
- }
-}
-
-void
-egraph_use_animations_set(Evas_Object *obj, int set)
-{
- EGRAPH_DATA_GET(obj, eg);
-
- eg->use_animations = set;
-}
-
-void
-egraph_do_improvements_set(Evas_Object *obj, int set)
-{
- EGRAPH_DATA_GET(obj, eg);
-
- eg->do_improvements = set;
-}
-
-Egraph_Edge *
-egraph_edge_add(Evas_Object *obj, Egraph_Vertice *a, Egraph_Vertice *b,
- void *data)
-{
- EGRAPH_DATA_GET(obj, eg);
- Egraph_Edge *e;
-
- e = calloc(1, sizeof(Egraph_Edge));
- if (!e)
- err(1, "egraph_edge_add: cannot calloc");
- e->v3_new = 1;
- e->a = a;
- e->b = b;
- e->data = data;
- eg->edges = eina_list_append(eg->edges, e);
- if (DEBUG)
- printf("egraph_edge_add %d %d\n", e->a->id, e->b->id);
-
- egraph_edge_type_set(obj, e, "edge_normal");
-
- _layouting_schedule(eg);
- return e;
-}
-
-static void
-_edge_v2_add(Egraph *eg, Egraph_Edge *e)
-{
- int a_pos, b_pos;
-
- if (DEBUG)
- printf("_edge_v2_add %d %d\n", e->a->id, e->b->id);
-
- e->v2_new = 1;
- e->v3_new = 0;
-
- a_pos = _igraph_query_vid(&eg->graph2, eg->graph2_vcount, e->a->id);
- b_pos = _igraph_query_vid(&eg->graph2, eg->graph2_vcount, e->b->id);
- igraph_add_edge(&eg->graph2, a_pos, b_pos);
-}
-
-static void
-_edge_add(Egraph *eg, Egraph_Edge *e)
-{
- Evas_Object *eobj = NULL;
- int a_pos, b_pos;
-
- e->new = 1;
- e->v2_new = 0;
-
- a_pos = _igraph_query_vid(&eg->graph, eg->graph_vcount, e->a->id);
- b_pos = _igraph_query_vid(&eg->graph, eg->graph_vcount, e->b->id);
- igraph_add_edge(&eg->graph, a_pos, b_pos);
-
- if (eg->theme_edges) {
- eobj = _edje_obj_new(eg, e->type);
- if (eobj) {
- e->o_usetheme = 1;
- evas_object_resize(eobj, eg->vertice_max_w, eg->vertice_max_h); // XXX rm
- }
- }
- if (!eobj) {
- eobj = evas_object_line_add(eg->evas);
- evas_object_color_set(eobj, 255, 0, 0, 255);
- }
- evas_object_smart_member_add(eobj, eg->obj);
- evas_object_stack_below(eobj, eg->split_vertice_edge);
- e->o = eobj;
- _edge_signal(eg, e, "become_active");
-
- e->a->edges = eina_list_append(e->a->edges, e);
- e->b->edges = eina_list_append(e->b->edges, e);
- _vertice_update_status(eg, e->a);
- _vertice_update_status(eg, e->b);
-}
-
-void
-egraph_edge_type_set(Evas_Object *obj, Egraph_Edge *e, const char *type)
-{
- EGRAPH_DATA_GET(obj, eg);
-
- if (e->type)
- free(e->type);
-
- e->type = strndup(type, TYPE_MAXLEN);
- if (eg->theme_edges && e->o) {
- _edje_obj_set(eg, e->o, type);
- }
-}
-
-static void
-_edge_signal(Egraph *eg, Egraph_Edge *e, const char *signal)
-{
- if (eg->theme_edges && e->o);
- edje_object_signal_emit(e->o, signal, "");
-}
-
-void
-egraph_edge_del(Evas_Object *obj, Egraph_Edge *e)
-{
- EGRAPH_DATA_GET(obj, eg);
-
- // XXX DEBUG find mem corrupt, del already del edge
- if (!egraph_edge_find(obj, e->a, e->b))
- printf("XXX DEBUG: egraph_edge_del on unknown edge !!!\n");
- if (DEBUG)
- printf("egraph_edge_del: %d %d\n", e->a->id, e->b->id);
-
- e->v3_del = 1;
- _layouting_schedule(eg);
-}
-
-static void
-_edge_v2_del(Egraph *eg, Egraph_Edge *e)
-{
- igraph_es_t es;
- int a_pos, b_pos;
-
- if (e->v2_del == 1)
- return;
-
- if (DEBUG)
- printf("_edge_v2_del %d %d\n", e->a->id, e->b->id);
-
- e->v2_del = 1;
- e->v3_del = 0;
-
- if (!e->v3_new) {
- a_pos = _igraph_query_vid(&eg->graph2, eg->graph2_vcount, e->a->id);
- b_pos = _igraph_query_vid(&eg->graph2, eg->graph2_vcount, e->b->id);
- igraph_es_pairs_small(&es, eg->graph_directed, a_pos, b_pos, -1);
- igraph_delete_edges(&eg->graph2, es);
- }
-}
-
-static void
-_edge_del(Egraph *eg, Egraph_Edge *e)
-{
- igraph_es_t es;
- int a_pos, b_pos;
-
- if (!e->v3_new && !e->v2_new) {
- a_pos = _igraph_query_vid(&eg->graph, eg->graph_vcount, e->a->id);
- b_pos = _igraph_query_vid(&eg->graph, eg->graph_vcount, e->b->id);
- igraph_es_pairs_small(&es, eg->graph_directed, a_pos, b_pos, -1);
- igraph_delete_edges(&eg->graph, es);
-
- e->a->edges = eina_list_remove(e->a->edges, e);
- e->b->edges = eina_list_remove(e->b->edges, e);
- _vertice_update_status(eg, e->a);
- _vertice_update_status(eg, e->b);
-
- evas_object_del(e->o);
- }
- eg->edges = eina_list_remove(eg->edges, e);
- free(e);
-}
-
-Egraph_Edge *
-egraph_edge_find(Evas_Object *obj, Egraph_Vertice *a, Egraph_Vertice *b)
-{
- EGRAPH_DATA_GET(obj, eg);
- Egraph_Edge *e;
- Eina_List *l;
-
- EINA_LIST_FOREACH(eg->edges, l, e)
- if (!(e->v3_del || e->v2_del) &&
- ((e->a == a && e->b == b) ||
- (e->a == b && e->b == a)))
- return e;
- return NULL;
-}
-
-Egraph_Vertice *
-egraph_vertice_add(Evas_Object *obj, const char *name, void *data)
-{
- EGRAPH_DATA_GET(obj, eg);
- Egraph_Vertice *v;
- u_int32_t id;
-
- if (eg->vertices_count == EGRAPH_VERTICES_MAX) {
- printf("egraph error: maximum number of vertices reached !\n");
- return NULL;
- }
- v = calloc(1, sizeof(Egraph_Vertice));
- if (!v)
- err(1, "egraph_vertice_add: cannot calloc");
- id = eg->vertices_freeids[eg->vertices_count];
- v->id = id;
- eina_hash_add(eg->vertices, &id, v);
- eg->vertices_count++;
- v->v3_new = 1;
- if (DEBUG)
- printf("egraph_vertice_add %d\n", id);
-
- if (name)
- v->name = strndup(name, EGRAPH_VERTICE_NAME_MAXLEN);
- egraph_vertice_type_set(obj, v, "vertice_normal");
-
- v->data = data;
-
- _layouting_schedule(eg);
- return v;
-}
-
-static void
-_vertice_v2_add(Egraph *eg, Egraph_Vertice *v)
-{
- v->v2_new = 1;
- v->v3_new = 0;
-
- igraph_add_vertices(&eg->graph2, 1, 0);
- SETVAN(&eg->graph2, "id", eg->graph2_vcount, v->id);
- eg->graph2_vcount++;
-}
-
-static void
-_vertice_add(Egraph *eg, Egraph_Vertice *v)
-{
- Evas_Object *vobj = NULL;
-
- v->new = 1;
- v->v2_new = 0;
-
- vobj = _edje_obj_new(eg, v->type);
- if (!vobj) {
- printf("egraph: could not load theme for vertice !");
- v->v2_new = 1;
- v->new = 0;
- _vertice_v2_del(eg, v);
- return;
- }
- evas_object_smart_member_add(vobj, eg->obj);
- evas_object_stack_above(vobj, eg->split_vertice_edge);
- evas_object_event_callback_add(vobj, EVAS_CALLBACK_MOVE, _cb_vertice_move, v);
- v->o = vobj;
- _vertice_geometry_update(eg, v);
-
- igraph_add_vertices(&eg->graph, 1, 0);
- SETVAN(&eg->graph, "id", eg->graph_vcount, v->id);
- eg->graph_vcount++;
-
- if (v->name)
- egraph_vertice_rename(eg->obj, v, v->name);
-}
-
-void
-egraph_vertice_del(Evas_Object *obj, Egraph_Vertice *v)
-{
- EGRAPH_DATA_GET(obj, eg);
- Egraph_Edge *e;
- Eina_List *l;
-
- v->v3_del = 1;
-
- EINA_LIST_FOREACH(eg->edges, l, e)
- if (e->a == v || e->b == v)
- egraph_edge_del(obj, e);
-
- _layouting_schedule(eg);
-}
-
-static void
-_vertice_v2_del(Egraph *eg, Egraph_Vertice *v)
-{
- Egraph_Edge *e;
- Eina_List *l;
- int pos;
-
- if (v->v2_del == 1)
- return;
-
- v->v2_del = 1;
- v->v3_del = 0;
-
- if (DEBUG)
- printf("_vertice_v2_del %d\n", v->id);
- EINA_LIST_FOREACH(eg->edges, l, e)
- if (e->a == v || e->b == v)
- _edge_v2_del(eg, e);
-
- if (!v->v3_new) {
- pos = _igraph_query_vid(&eg->graph2, eg->graph2_vcount, v->id);
- igraph_delete_vertices(&eg->graph2, igraph_vss_1(pos));
- eg->graph2_vcount--;
- }
-}
-
-static void
-_vertice_del(Egraph *eg, Egraph_Vertice *v)
-{
- Egraph_Edge *e;
- Eina_List *l, *lprev;
- Evas_Object *blob;
- int pos;
-
- if (!v->v3_new && !v->v2_new) {
- EINA_LIST_FOREACH_SAFE(eg->edges, l, lprev, e)
- if (e->a == v || e->b == v)
- _edge_del(eg, e);
- eina_list_free(v->edges);
-
- pos = _igraph_query_vid(&eg->graph, eg->graph_vcount, v->id);
- igraph_delete_vertices(&eg->graph, igraph_vss_1(pos));
- eg->graph_vcount--;
-
- EINA_LIST_FOREACH(v->blobs_incoming, l, blob)
- evas_object_del(blob);
- eina_list_free(v->blobs_incoming);
-
- evas_object_del(v->o);
- }
-
- eina_hash_del(eg->vertices, &v->id, NULL);
- eg->vertices_count--;
- eg->vertices_freeids[eg->vertices_count] = v->id;
-
- free(v);
-}
-
-void
-egraph_vertice_type_set(Evas_Object *obj, Egraph_Vertice *v, const char *type)
-{
- EGRAPH_DATA_GET(obj, eg);
-
- if (v->type)
- free(v->type);
-
- v->type = strndup(type, TYPE_MAXLEN);
- if (v->o)
- _edje_obj_set(eg, v->o, type);
-}
-
-static void
-_vertice_update_status(Egraph *eg, Egraph_Vertice *v)
-{
- Eina_List *l;
- Egraph_Edge *e;
- int status = 0;
-
- if (v->is_group && (eina_list_count(v->edges) >= 1)) {
- status = 1; /* we are a group with childs */
- } else {
- EINA_LIST_FOREACH(v->edges, l, e) {
- if ((v == e->a && !e->b->is_group) ||
- (v == e->b && !e->a->is_group)) {
- status = 1; /* we are connected to at least on other non group node */
- break;
- }
- }
- }
-
- if (status != v->status) {
- if (status)
- _vertice_signal(eg, v, "become_active");
- else
- _vertice_signal(eg, v, "become_inactive");
- v->status = status;
- }
-}
-
-static void
-_vertice_signal(Egraph *eg, Egraph_Vertice *v, const char *signal)
-{
- if (v->o)
- edje_object_signal_emit(v->o, signal, "");
-}
-
-void
-egraph_vertice_rename(Evas_Object *obj, Egraph_Vertice *v, const char *name)
-{
- EGRAPH_DATA_GET(obj, eg);
-
- if (eg->display_names == 0)
- return;
-
- if (name) {
- if (v->name != name) {
- if (v->name)
- free(v->name);
- v->name = strndup(name, EGRAPH_VERTICE_NAME_MAXLEN);
- }
- }
- if (v->o) {
- if (v->name)
- edje_object_part_text_set(v->o, "label", v->name);
- else
- edje_object_part_text_set(v->o, "label", "");
- _vertice_geometry_update(eg, v);
- }
-}
-
-static void
-_vertice_geometry_update(Egraph *eg, Egraph_Vertice *v)
-{
- int w, h;
-
- edje_object_size_min_calc(v->o, &w, &h);
- if (DEBUG)
- printf("_vertice_geometry_update: %d %d\n", w, h);
- evas_object_resize(v->o, w, h);
- if (w > eg->vertice_max_w)
- eg->vertice_max_w = w;
- if (h > eg->vertice_max_h)
- eg->vertice_max_h = h;
- if (DEBUG)
- printf("_vertice_geometry_update: end %d %d\n",
- eg->vertice_max_w, eg->vertice_max_h);
-}
-
-void
-_color_int_to_rgb(u_int32_t color, int *r, int *g , int *b)
-{
- *r = (color & 0xFF000000) >> 24;
- *g = (color & 0x00FF0000) >> 16;
- *b = (color & 0x0000FF00) >> 8;
-}
-
-void
-egraph_vertice_send_blob(Evas_Object *obj,
- Egraph_Vertice *a, Egraph_Vertice *b,
- int size, u_int32_t color)
-{
- EGRAPH_DATA_GET(obj, eg);
- Evas_Object *blob;
- int ax, ay, aw, ah, bx, by, bw, bh;
- int cr, cg, cb;
-
- if (!a->o || !b->o)
- return;
- evas_object_geometry_get(a->o, &ax, &ay, &aw, &ah);
- evas_object_geometry_get(b->o, &bx, &by, &bw, &bh);
- _color_int_to_rgb(color, &cr, &cg, &cb);
-
- blob = _edje_obj_new(eg, "blob");
- if (!blob)
- blob = evas_object_rectangle_add(eg->evas);
- evas_object_color_set(blob, cr, cg, cb, 255);
- evas_object_smart_member_add(blob, eg->obj);
- evas_object_stack_above(blob, eg->split_vertice_edge);
- evas_object_move(blob, ax, ay);
- evas_object_resize(blob, size, size);
- evas_object_show(blob);
- b->blobs_incoming = eina_list_append(b->blobs_incoming, blob);
- _blob_send(blob, b, bx, by);
-}
-
-static void
-_cb_blob_arrived(void *data, Efx_Map_Data *e, Evas_Object *obj)
-{
- Egraph_Vertice *v;
-
- v = data;
- v->blobs_incoming = eina_list_remove(v->blobs_incoming, obj);
- evas_object_del(obj);
-}
-
-static void
-_blob_send(Evas_Object *blob, Egraph_Vertice *v, Evas_Coord x, Evas_Coord y)
-{
- if (DEBUG)
- printf("blob_send %d %d\n", x, y);
- efx_move(blob, EFX_EFFECT_SPEED_SINUSOIDAL,
- &(Evas_Point){ x, y }, 0.6, _cb_blob_arrived, v);
-}
-
-static void
-_layouting_schedule(Egraph *eg)
-{
- if (eg->layouting.running > 0) {
- eg->layouting.todo = 1;
- return;
- }
-
- eg->layouting.running = 1;
- ecore_timer_add(0.0, _cb_layouting_start, eg); /* delayed start */
-}
-
-static void
-_v2_update(Egraph *eg)
-{
- Eina_List *l, *lprev, *todel, *toadd;
- Eina_Iterator *it;
- Egraph_Vertice *v;
- Egraph_Edge *e;
- void *data;
-
- /* update graph and structs based on v2_add / v2_del */
- it = eina_hash_iterator_tuple_new(eg->vertices);
- todel = NULL; toadd = NULL;
- while (eina_iterator_next(it, &data)) {
- Eina_Hash_Tuple *t = data;
- v = t->data;
- if (v->v2_del)
- todel = eina_list_append(todel, v);
- else if (v->v2_new)
- toadd = eina_list_append(toadd, v);
- }
- eina_iterator_free(it);
- EINA_LIST_FOREACH(todel, l, v)
- _vertice_del(eg, v);
- EINA_LIST_FOREACH(toadd, l, v)
- _vertice_add(eg, v);
- todel = eina_list_free(todel);
- toadd = eina_list_free(toadd);
- EINA_LIST_FOREACH_SAFE(eg->edges, l, lprev, e) {
- if (e->v2_del)
- _edge_del(eg, e);
- else if (e->v2_new)
- _edge_add(eg, e);
- }
-}
-
-static void
-_v3_update(Egraph *eg)
-{
- Eina_List *l, *lprev;
- Eina_Iterator *it;
- Egraph_Vertice *v;
- Egraph_Edge *e;
- void *data;
- float ranx, rany;
- int changes_count = 0;
- int changes_diff = 0;
- int i, id;
-
- if (DEBUG)
- printf("_v3_update\n");
- /* update graph2 and structs based on v3_add / v3_del */
- it = eina_hash_iterator_tuple_new(eg->vertices);
- while (eina_iterator_next(it, &data)) {
- Eina_Hash_Tuple *t = data;
- v = t->data;
- if (v->v3_del) {
- _vertice_v2_del(eg, v); changes_diff--; changes_count++;
- } else if (v->v3_new) {
- _vertice_v2_add(eg, v); changes_diff++; changes_count++;
- }
- }
- eina_iterator_free(it);
- if (DEBUG)
- printf("_v3_update edges\n");
- EINA_LIST_FOREACH_SAFE(eg->edges, l, lprev, e) {
- if (e->v3_del) {
- _edge_v2_del(eg, e); changes_count++;
- } else if (e->v3_new) {
- _edge_v2_add(eg, e); changes_count++;
- }
- }
-
- /* set correct coords2 size */
- if (changes_diff > 0) {
- for (i=0; i<changes_diff; i++) {
- id = (eg->graph2_vcount - changes_diff) + i;
- igraph_matrix_add_rows(&eg->coords2, 1);
- ranx = eg->graph_wmin + fmod((float)random() / 1000, (float)((eg->graph_wmax + 1) - eg->graph_wmin));
- rany = eg->graph_hmin + fmod((float)random() / 1000, (float)((eg->graph_hmax + 1) - eg->graph_hmin));
- if (DEBUG)
- printf("ranx %6.3f rany %6.3f\n", ranx, rany);
- igraph_matrix_set(&eg->coords2, id, 0, ranx);
- igraph_matrix_set(&eg->coords2, id, 1, rany);
- }
- } else if (changes_diff < 0) {
- changes_diff = -changes_diff;
- for (i=0; i<changes_diff; i++) {
- id = (eg->graph2_vcount + changes_diff) - i;
- igraph_matrix_remove_row(&eg->coords2, 0);
- }
- }
-
- if (eg->layout == EGRAPH_LAYOUT_FRUCHTERMANREINGOLD) {
- /* set minimum and maximum for each node */
- /* XXX do that in layouting thread ? */
- if (DEBUG)
- printf("g wmin %d wmax %d hmin %d hmax %d\n",
- eg->graph_wmin, eg->graph_wmax, eg->graph_hmin, eg->graph_hmax);
- igraph_vector_init(&eg->graph2_wmin, eg->graph2_vcount);
- igraph_vector_init(&eg->graph2_wmax, eg->graph2_vcount);
- igraph_vector_init(&eg->graph2_hmin, eg->graph2_vcount);
- igraph_vector_init(&eg->graph2_hmax, eg->graph2_vcount);
- igraph_vector_fill(&eg->graph2_wmin, eg->graph_wmin);
- igraph_vector_fill(&eg->graph2_wmax, eg->graph_wmax);
- igraph_vector_fill(&eg->graph2_hmin, eg->graph_hmin);
- igraph_vector_fill(&eg->graph2_hmax, eg->graph_hmax);
- }
-
- eg->layouting.changes_diff = changes_diff;
-}
-
-static Eina_Bool
-_cb_layouting_start(void *data)
-{
- Egraph *eg;
-
- eg = data;
-
- eg->layouting.todo = 0;
-
- _v3_update(eg);
-
- eg->layouting.running = 2;
- eg->layouting.thread = ecore_thread_run(_cb_layouting_run, _cb_layouting_end,
- _cb_layouting_cancel, eg);
-
- return EINA_FALSE; /* no repeat */
-}
-
-void
-_cb_layouting_run(void *data, Ecore_Thread *thread)
-{
- Egraph *eg;
- int niter;
-
- eg = data;
-
- if (DEBUG)
- printf("[-] _cb_layouting_run begin (%d)\n", eg->layout);
-
- switch(eg->layout) {
- case EGRAPH_LAYOUT_KAMADAKAWAI:
- if (eg->layouting.improvement) {
- niter = 300;
- } else {
- if (eg->layouting.changes_diff == 0)
- niter = 1000;
- else
- niter = 1000 * eg->layouting.changes_diff;
- if (niter > 2000)
- niter = 2000;
- }
- /* http://igraph.sourceforge.net/doc/html/ch18s01.html#igraph_layout_kamada_kawai
- * int igraph_layout_kamada_kawai(const igraph_t *g, igraph_matrix_t *res,
- * igraph_integer_t niter, igraph_real_t sigma,
- * igraph_real_t initemp, igraph_real_t coolexp,
- * igraph_real_t kkconst, igraph_bool_t use_seed,
- * const igraph_vector_t *minx,
- * const igraph_vector_t *maxx,
- * const igraph_vector_t *miny,
- * const igraph_vector_t *maxy);
- * Defaults :
- * igraph_layout_kamada_kawai(&eg->graph2, &eg->coords2,
- * 1000, eg->vertices_count / 4, 10, 0.99,
- * eg->vertices_count ^ 2, 1,
- * NULL, NULL, NULL, NULL);
- */
- igraph_layout_kamada_kawai(&eg->graph2, &eg->coords2,
- niter, eg->graph2_vcount, 10, 0.99,
- eg->vertices_count ^ 2, 1,
- NULL, NULL, NULL, NULL);
- break;
-
- case EGRAPH_LAYOUT_GRAPHOPT:
- if (eg->layouting.improvement) {
- niter = 300;
- } else {
- if (eg->layouting.changes_diff == 0)
- niter = 100;
- else
- niter = 50 * eg->layouting.changes_diff;
- if (niter > 500)
- niter = 500;
- }
- /* http://igraph.sourceforge.net/doc/html/ch18s01.html#igraph_layout_graphopt
- * int igraph_layout_graphopt(const igraph_t *g, igraph_matrix_t *res,
- * igraph_integer_t niter,
- * igraph_real_t node_charge, igraph_real_t node_mass,
- * igraph_real_t spring_length,
- * igraph_real_t spring_constant,
- * igraph_real_t max_sa_movement,
- * igraph_bool_t use_seed);
- * Defaults :
- * igraph_layout_graphopt(&eg->graph2, &eg->coords2,
- * 1000, 0.001, 30, 0, 1, 5, 0);
- */
- igraph_layout_graphopt(&eg->graph2, &eg->coords2,
- niter, 0.003, 10, 10, 1, 5, 1);
- break;
-
- case EGRAPH_LAYOUT_FRUCHTERMANREINGOLD:
- niter = 1000;
- /* http://igraph.sourceforge.net/doc/html/ch18s01.html#igraph_layout_fruchterman_reingold
- * int igraph_layout_fruchterman_reingold(const igraph_t *graph, igraph_matrix_t *res,
- * igraph_integer_t niter, igraph_real_t maxdelta,
- * igraph_real_t area, igraph_real_t coolexp,
- * igraph_real_t repulserad, igraph_bool_t use_seed,
- * const igraph_vector_t *weight,
- * const igraph_vector_t *minx,
- * const igraph_vector_t *maxx,
- * const igraph_vector_t *miny,
- * const igraph_vector_t *maxy);
- * Defaults:
- * igraph_layout_fruchterman_reingold(&eg->graph2, &eg->coords2,
- * 500, eg->graph2_vcount,
- * sqrt(eg->graph2_vcount) * sqrt(eg->graph2_vcount), 1.5,
- * eg->graph2_vcount, 0,
- * NULL, NULL, NULL, NULL, NULL);
- */
- igraph_layout_fruchterman_reingold(&eg->graph2, &eg->coords2,
- niter, 0.05,
- sqrt(eg->graph2_vcount), 1.5,
- sqrt(eg->graph2_vcount) * eg->graph2_vcount, 1,
- NULL, NULL, NULL, NULL, NULL);
- //&eg->graph2_wmin, &eg->graph2_wmax,
- //&eg->graph2_hmin, &eg->graph2_hmax);
- break;
- }
- if (DEBUG)
- printf("[-] _cb_layouting_run end\n");
-}
-
-static void
-_coords2_copy(Egraph *eg)
-{
- igraph_matrix_copy(&eg->coords, &eg->coords2);
-}
-
-void
-_cb_layouting_end(void *data, Ecore_Thread *thread)
-{
- Egraph *eg;
-
- eg = data;
- _v2_update(eg);
- _coords2_copy(eg);
- _reposition(eg, 0);
- eg->layouting.running = 0;
- if (eg->layouting.todo) {
- eg->layouting.todo = 0;
- eg->layouting.improvement = 0;
- _layouting_schedule(eg);
- } else {
- if (eg->do_improvements) {
- if (eg->layouting.improvement < EGRAPH_LAYOUTING_IMPROVEMENTS) {
- eg->layouting.improvement++;
- _layouting_schedule(eg);
- } else {
- eg->layouting.improvement = 0;
- }
- }
- }
-}
-
-void
-_cb_layouting_cancel(void *data, Ecore_Thread *thread)
-{
- Egraph *eg;
-
- eg = data;
- eg->layouting.running = 0;
- eg->layouting.todo = 0;
- /* we are not in a clean state now, but it happends on exit only */
-}
-
-/* XXX slow ! possible to do edge/vertice delete on repositionning ? */
-static int
-_igraph_query_vid(igraph_t *g, int g_len, int id)
-{
- int i;
-
- for (i=0; i<g_len; i++) {
- if (VAN(g, "id", i) == id)
- return i;
- }
- printf("egraph: WARNING: _igraph_query_id %d not found !\n", id);
- return -1;
-}
-
-/* Apply vertice move to it's edges */
-static void
-_cb_vertice_move(void *data, Evas *evas, Evas_Object *obj, void *event_info)
-{
- EGRAPH_DATA_GET(evas_object_smart_parent_get(obj), eg);
- Egraph_Vertice *v;
- Egraph_Edge *e;
- Evas_Map *m;
- Eina_List *l;
- int x, y, w, h;
- int ax, ay, bx, by, aw, ah, bw, bh;
- int p0x, p0y, p1x, p1y, p2x, p2y, p3x, p3y;
- float a;
-
- v = data;
- evas_object_geometry_get(v->o, &x, &y, &w, &h);
-
- EINA_LIST_FOREACH(v->edges, l, e) {
- if (e->new) {
- if (eg->display_edges)
- evas_object_show(e->o);
- e->new = 0;
- }
- if (e->o_usetheme) {
- /* XXX we map the edges once per node = 2 times ... */
- evas_object_move(e->o, x, y);
- m = evas_map_new(4);
- evas_map_smooth_set(m, 1);
- evas_map_util_points_populate_from_object(m, e->o);
- evas_object_geometry_get(e->a->o, &ax, &ay, &aw, &ah);
- evas_object_geometry_get(e->b->o, &bx, &by, &bw, &bh);
- ax = ax + aw / 2; ay = ay + ah / 2;
- bx = bx + bw / 2; by = by + bh / 2;
- aw = aw / 2; ah = ah / 2;
- bw = bw / 2; bh = bh / 2;
- /* rotate edge endpoints */
- a = atan2(by - ay, bx - ax);
-#define ROTX(x, h, a) (-sin(a)*h + x)
-#define ROTY(y, h, a) (cos(a)*h + y)
- p0x = ROTX(ax, ah, a); p0y = ROTY(ay, ah, a);
- p1x = ROTX(ax, -ah, a); p1y = ROTY(ay, -ah, a);
- p2x = ROTX(bx, bh, a); p2y = ROTY(by, bh, a);
- p3x = ROTX(bx, -bh, a); p3y = ROTY(by, -bh, a);
- /* set edge endpoints */
- evas_map_point_coord_set(m, 0, p2x, p2y, 0);
- evas_map_point_coord_set(m, 1, p0x, p0y, 0);
- evas_map_point_coord_set(m, 2, p1x, p1y, 0);
- evas_map_point_coord_set(m, 3, p3x, p3y, 0);
- evas_object_map_set(e->o, m);
- evas_object_map_enable_set(e->o, EINA_TRUE); // XXX do at init
- evas_map_free(m);
- } else {
- evas_object_line_xy_get(e->o, &ax, &ay, &bx, &by);
- if (e->a == v) {
- ax = x + w/2;
- ay = y + h/2;
- } else {
- bx = x + w/2;
- by = y + h/2;
- }
- evas_object_line_xy_set(e->o, ax, ay, bx, by);
- }
- }
-}
-
-static void
-_reposition(Egraph *eg, int no_animation)
-{
- Egraph_Vertice *v;
- u_int32_t id;
- float gw_min, gw_max, gh_min, gh_max, factor_w, factor_h;
- float x, y;
- int obj_x, obj_y, obj_w, obj_h;
- int vcur;
-
- if (DEBUG)
- printf("[-] _reposition\n");
- if (eg->graph_vcount == 0)
- return;
-
- evas_object_geometry_get(eg->obj, &obj_x, &obj_y, &obj_w, &obj_h);
- _matrix_minmax_2v(&eg->coords, eg->graph_vcount,
- &gw_min, &gw_max, &gh_min, &gh_max);
- eg->graph_wmin = gw_min;
- eg->graph_wmax = gw_max;
- eg->graph_hmin = gh_min;
- eg->graph_hmax = gh_max;
-
- if (DEBUG)
- printf("gw_min %6.3f gw_max %6.3f gh_min %6.3f gh_max %6.3f\n",
- gw_min, gw_max, gh_min, gh_max);
- if (gw_max == gw_min)
- factor_w = 1;
- else
- factor_w = (obj_w - eg->vertice_max_w) / (gw_max - gw_min);
- if (gh_max == gh_min)
- factor_h = 1;
- else
- factor_h = (obj_h - eg->vertice_max_h) / (gh_max - gh_min);
- if (DEBUG)
- printf("factor_w %6.3f factor_h %6.3f\n", factor_w, factor_h);
-
- for (vcur=0; vcur<eg->graph_vcount; vcur++) {
- id = VAN(&eg->graph, "id", vcur);
-
- x = MATRIX(eg->coords, vcur, 0);
- y = MATRIX(eg->coords, vcur, 1);
- if (DEBUG)
- printf("%d: %6.3f %6.3f id %d\n", vcur, x, y, id);
- x = obj_x + ((x - gw_min) * factor_w);
- y = obj_y + ((y - gh_min) * factor_h);
- if (DEBUG)
- printf(" inobj: %6.3f %6.3f\n", x, y);
-
- v = eina_hash_find(eg->vertices, &id);
- if (eg->use_animations && !no_animation) {
- efx_move(v->o, EFX_EFFECT_SPEED_DECELERATE,
- &(Evas_Point){ x, y }, 0.5, NULL, NULL);
- }
- else
- evas_object_move(v->o, x, y);
- /* XXX fix blob repositionning
- Evas_Object *blob;
- Eina_List *l;
- EINA_LIST_FOREACH(v->blobs_incoming, l, blob)
- _blob_send(blob, v, x, y);
- */
- if (v->new) {
- evas_object_show(v->o);
- v->new = 0;
- }
- }
-}
-
-/**
- * Compute minimum and maximum of a matrices of 2 colum vectors
- *
- * @note igraph is crazy in the coconut
- */
-static void
-_matrix_minmax_2v(const igraph_matrix_t *m, int row_count,
- float *c1min, float *c1max, float *c2min, float *c2max)
-{
- float val;
- int row;
-
- *c1min=MATRIX(*m, 0, 0); *c1max=MATRIX(*m, 0, 0);
- *c2min=MATRIX(*m, 0, 1); *c2max=MATRIX(*m, 0, 1);
-
- for (row=1; row<row_count; row++) {
- val = MATRIX(*m, row, 0);
- if (val < *c1min) *c1min = val;
- else if (val > *c1max) *c1max = val;
- val = MATRIX(*m, row, 1);
- if (val < *c2min) *c2min = val;
- else if (val > *c2max) *c2max = val;
- }
-}
-
-static Evas_Object *
-_edje_obj_new(Egraph *eg, const char *group)
-{
- Evas_Object *obj;
-
- obj = edje_object_add(eg->evas);
- return _edje_obj_set(eg, obj, group);
-}
-
-static Evas_Object *
-_edje_obj_set(Egraph *eg, Evas_Object *obj, const char *group)
-{
- if (!obj || !edje_object_file_set(obj, eg->theme_path, group)) {
- int err = edje_object_load_error_get(obj);
- const char *errmsg = edje_load_error_str(err);
- if (DEBUG)
- fprintf(stderr, "Could not load the edje file - reason:%s\n", errmsg);
- return NULL;
- }
- return obj;
-}
-
-Egraph_Vertice *
-egraph_group_add(Evas_Object *obj, const char *name, void *data)
-{
- Egraph_Vertice *g;
-
- g = egraph_vertice_add(obj, name, data);
- g->is_group = 1;
- egraph_vertice_type_set(obj, g, "vertice_group");
- return g;
-}
-
-int
-egraph_group_vertice_attach(Evas_Object *obj,
- Egraph_Vertice *group, Egraph_Vertice *v)
-{
- Egraph_Edge *e;
-
- group->group_vertices = eina_list_append(group->group_vertices, v);
- e = egraph_edge_add(obj, group, v, NULL);
- egraph_edge_type_set(obj, e, "edge_group");
- return 1;
-}
-
-void
-egraph_group_vertice_detach(Evas_Object *obj,
- Egraph_Vertice *group, Egraph_Vertice *v)
-{
- Egraph_Edge *e;
-
- group->group_vertices = eina_list_remove(group->group_vertices, v);
- e = egraph_edge_find(obj, group, v);
- egraph_edge_del(obj, e);
-}