9 #include <glade/glade.h>
10 #include <libgnomeui/gnome-canvas.h>
11 #include <libgnomeui/gnome-canvas-rect-ellipse.h>
12 #include <libgnomeui/gnome-canvas-text.h>
13 #include <libgnomeui/gnome-canvas-line.h>
14 #include <libgnomeui/gnome-canvas-util.h>
18 #include "interface.h"
31 #define MAXBUFSIZE 1024
35 static GdkColormap *colormap = NULL;
36 static GdkColor timecolor;
44 #define INFINITY 1.0e10
46 node_t *nodes[MAX_NODES];
49 double k[MAX_NODES][MAX_NODES];
50 double d[MAX_NODES][MAX_NODES];
51 double l[MAX_NODES][MAX_NODES];
52 const double epsilon = 0.001;
54 static int inited = 0;
56 static int number_of_nodes = 0;
58 static GtkWidget *nodetree;
59 static GtkCTreeNode *subnets_ctn, *hosts_ctn, *conns_ctn;
61 static GnomeCanvasGroup *edge_group = NULL;
63 static int canvas_width;
64 static int canvas_height;
66 static GtkWidget *canvas = NULL;
68 GtkWidget *create_canvas(void)
72 gtk_widget_push_visual(gdk_rgb_get_visual());
73 gtk_widget_push_colormap(gdk_rgb_get_cmap());
75 canvas = gnome_canvas_new_aa();
77 gtk_widget_pop_visual();
78 gtk_widget_pop_colormap();
80 gnome_canvas_set_scroll_region(GNOME_CANVAS(canvas), -00.0, -00.0, 700, 500);
82 w = glade_xml_get_widget(xml, "scrolledwindow3");
85 fprintf(stderr, "Could not find widget `scrolledwindow3'\n");
88 gtk_container_add(GTK_CONTAINER(w), canvas);
89 gtk_widget_show_all(w);
92 canvas_height = 500.0;
97 void log_gtk(int level, int priority, char *fmt, va_list ap)
99 char buffer1[MAXBUFSIZE];
100 char buffer2[MAXBUFSIZE];
106 static int inited = 0;
111 w = glade_xml_get_widget(xml, "Messages");
115 /* Use vsnprintf instead of vasprintf: faster, no memory
116 fragmentation, cleanup is automatic, and there is a limit on the
117 input buffer anyway */
118 len = vsnprintf(buffer1, MAXBUFSIZE, fmt, ap);
120 buffer1[MAXBUFSIZE-1] = '\0';
121 if((p = strrchr(buffer1, '\n')))
126 snprintf(buffer2, MAXBUFSIZE, "%02d:%02d:%02d ",
127 tm->tm_hour, tm->tm_min, tm->tm_sec);
131 colormap = gdk_colormap_new(gdk_visual_get_system(), FALSE);
132 timecolor.red = 0xffff;
135 if(gdk_colormap_alloc_color(colormap, &timecolor, FALSE, TRUE) != TRUE)
137 fprintf(stderr, "Failed to allocate color\n");
142 gtk_text_freeze(GTK_TEXT(w));
145 gtk_text_insert(GTK_TEXT(w), NULL, NULL, NULL, "\n", 1);
147 gtk_text_insert(GTK_TEXT(w), NULL, &timecolor, NULL, buffer2, strlen(buffer2));
148 gtk_text_insert(GTK_TEXT(w), NULL, NULL, NULL, buffer1, len);
149 gtk_text_thaw(GTK_TEXT(w));
154 int init_interface(void)
161 nodetree = glade_xml_get_widget(xml, "NodeTree");
164 fprintf(stderr, _("Could not find widget `NodeTree'\n"));
168 gtk_clist_freeze(GTK_CLIST(nodetree));
171 hosts_ctn = gtk_ctree_insert_node(GTK_CTREE(nodetree),
173 NULL, NULL, NULL, NULL,
176 subnets_ctn = gtk_ctree_insert_node(GTK_CTREE(nodetree),
178 NULL, NULL, NULL, NULL,
180 l[0] = _("Connections");
181 conns_ctn = gtk_ctree_insert_node(GTK_CTREE(nodetree),
183 NULL, NULL, NULL, NULL,
186 gtk_clist_thaw(GTK_CLIST(nodetree));
190 gtk_signal_connect(GTK_OBJECT(nodetree), "button_press_event", if_nodetree_button_press_event, NULL);
192 log_add_hook(log_gtk);
193 log_del_hook(log_default);
198 static gint item_event(GnomeCanvasItem *item, GdkEvent *event, gpointer data)
200 static double item_x, old_x, new_x, item_y, old_y, new_y;
201 static int dragging = FALSE;
205 item_x = event->button.x;
206 item_y = event->button.y;
207 gnome_canvas_item_w2i(item->parent, &item_x, &item_y);
211 case GDK_BUTTON_PRESS:
212 switch(event->button.button)
218 fleur = gdk_cursor_new(GDK_FLEUR);
219 gnome_canvas_item_grab(item, GDK_POINTER_MOTION_MASK | GDK_BUTTON_RELEASE_MASK, fleur, event->button.time);
220 gdk_cursor_destroy(fleur);
229 case GDK_MOTION_NOTIFY:
230 if(dragging && (event->motion.state & GDK_BUTTON1_MASK))
234 gnome_canvas_item_move(item, new_x - old_x, new_y - old_y);
240 case GDK_BUTTON_RELEASE:
241 gnome_canvas_item_ungrab(item, event->button.time);
243 n = (node_t *)gtk_object_get_user_data(GTK_OBJECT(item));
257 void if_node_create(node_t *n)
259 GnomeCanvasGroup *group;
261 group = gnome_canvas_root(GNOME_CANVAS(canvas));
262 group = GNOME_CANVAS_GROUP(gnome_canvas_item_new(group,
263 gnome_canvas_group_get_type(),
268 gnome_canvas_item_new(group, gnome_canvas_ellipse_get_type(),
273 "fill_color_rgba", 0x5f9ea0ff,
274 "outline_color", "black",
278 gnome_canvas_item_new(group,
279 gnome_canvas_text_get_type(),
283 "anchor", GTK_ANCHOR_CENTER,
284 "fill_color", "white",
285 "font", "-*-verdana-medium-r-*-*-10-*-*-*-*-*-iso8859-1",
288 n->item = GNOME_CANVAS_ITEM(group);
290 gtk_object_set_user_data(GTK_OBJECT(group), (gpointer)n);
292 gtk_signal_connect(GTK_OBJECT(n->item), "event", (GtkSignalFunc) item_event, NULL);
294 gnome_canvas_item_hide(GNOME_CANVAS_ITEM(n->item));
297 void if_node_visible(node_t *n)
306 if(n->status.visible)
307 /* This node is already shown */
310 n->status.visible = 1;
312 newx = 250.0 + 200.0 * sin(number_of_nodes / 10.0 * M_PI);
313 newy = 150.0 - 100.0 * cos(number_of_nodes / 10.0 * M_PI);
314 gnome_canvas_item_move(GNOME_CANVAS_ITEM(n->item), newx - n->x, newy - n->y);
318 for(i = 0, avlnode = node_tree->head; avlnode; avlnode = avlnode->next, i++)
320 if(!((node_t*)(avlnode->data))->status.visible)
323 nodes[i] = (node_t *)(avlnode->data);
328 gnome_canvas_item_show(GNOME_CANVAS_ITEM(n->item));
329 gnome_canvas_update_now(GNOME_CANVAS(canvas));
331 /* (Re)start calculations */
336 void if_node_invisible(node_t *n)
344 if(!n->status.visible)
345 /* This node is already invisible */
348 n->status.visible = 0;
350 for(i = 0, avlnode = node_tree->head; avlnode; avlnode = avlnode->next, i++)
352 if(!((node_t*)(avlnode->data))->status.visible)
355 nodes[i] = (node_t *)(avlnode->data);
360 gnome_canvas_item_hide(GNOME_CANVAS_ITEM(n->item));
361 gnome_canvas_update_now(GNOME_CANVAS(canvas));
363 /* (Re)start calculations */
368 GtkCTreeNode *if_node_add(node_t *n)
377 gtk_clist_freeze(GTK_CLIST(nodetree));
378 n->host_ctn = gtk_ctree_insert_node(GTK_CTREE(nodetree),
379 hosts_ctn, NULL, l, 1,
380 NULL, NULL, NULL, NULL,
382 gtk_clist_thaw(GTK_CLIST(nodetree));
390 void if_node_del(node_t *n)
392 gtk_clist_freeze(GTK_CLIST(nodetree));
394 gtk_ctree_remove_node(GTK_CTREE(nodetree), n->host_ctn);
396 gtk_ctree_remove_node(GTK_CTREE(nodetree), n->conn_ctn);
398 gtk_ctree_remove_node(GTK_CTREE(nodetree), n->subnet_ctn);
399 gtk_clist_thaw(GTK_CLIST(nodetree));
401 if_node_invisible(n);
404 void if_subnet_add(subnet_t *subnet)
408 l[0] = net2str(subnet);
409 gtk_clist_freeze(GTK_CLIST(nodetree));
410 gtk_ctree_insert_node(GTK_CTREE(nodetree),
411 subnets_ctn, NULL, l, 1,
412 NULL, NULL, NULL, NULL,
414 gtk_clist_thaw(GTK_CLIST(nodetree));
417 void if_subnet_del(subnet_t *subnet)
421 void redraw_edges(void)
423 GnomeCanvasGroup *group;
424 GnomeCanvasPoints *points;
429 gtk_object_destroy(GTK_OBJECT(edge_group));
431 group = gnome_canvas_root(GNOME_CANVAS(canvas));
432 group = GNOME_CANVAS_GROUP(gnome_canvas_item_new(group,
433 gnome_canvas_group_get_type(),
438 for(avlnode = edge_tree->head; avlnode; avlnode = avlnode->next)
440 e = (edge_t *)avlnode->data;
442 if(!e->from.node->status.visible ||
443 !e->to.node->status.visible)
444 /* We shouldn't draw this line */
447 points = gnome_canvas_points_new(2);
449 points->coords[0] = e->from.node->x;
450 points->coords[1] = e->from.node->y;
451 points->coords[2] = e->to.node->x;
452 points->coords[3] = e->to.node->y;
453 gnome_canvas_item_new(group,
454 gnome_canvas_line_get_type(),
456 "fill_color_rgba", 0xe080c0ff,
459 gnome_canvas_points_unref(points);
462 gnome_canvas_update_now(GNOME_CANVAS(canvas));
467 void if_edge_add(edge_t *e)
475 void if_edge_del(edge_t *e)
483 void if_move_node(node_t *n, double dx, double dy)
489 gnome_canvas_item_move(GNOME_CANVAS_ITEM(n->item), newx - n->x, newy - n->y);
494 #define X_MARGIN 50.0
495 #define X_MARGIN_BUFFER 25.0
496 #define Y_MARGIN 20.0
497 #define Y_MARGIN_BUFFER 10.0
499 void set_zooming(void)
502 double minx, miny, maxx, maxy;
503 static double ominx = 0.0, ominy = 0.0, omaxx = 0.0, omaxy = 0.0;
505 minx = miny = maxx = maxy = 0.0;
506 for(i = 0; i < number_of_nodes; i++)
508 if(nodes[i]->x < minx)
511 if(nodes[i]->x > maxx)
514 if(nodes[i]->y < miny)
517 if(nodes[i]->y > maxy)
521 if(minx > ominx - X_MARGIN_BUFFER && ominx > minx)
523 if(maxx < omaxx + X_MARGIN_BUFFER && omaxx < maxx)
525 if(miny > ominy - Y_MARGIN_BUFFER && ominy > miny)
527 if(maxy < omaxy + Y_MARGIN_BUFFER && omaxy < maxy)
530 ominx = minx; ominy = miny; omaxx = maxx; omaxy = maxy;
532 /* ppux = canvas_width / (maxx - minx); */
533 /* ppuy = canvas_height / (maxy - miny); */
534 /* if(ppux < ppuy) */
539 /* gnome_canvas_set_pixels_per_unit(GNOME_CANVAS(canvas), ppu); */
540 gnome_canvas_set_scroll_region(GNOME_CANVAS(canvas), minx - X_MARGIN, miny - Y_MARGIN, maxx + X_MARGIN, maxy + Y_MARGIN);
541 gnome_canvas_update_now(GNOME_CANVAS(canvas));
544 double calculate_delta_m(int m)
546 double dedxm, dedym, xmxi, ymyi;
550 for(i = 0; i < number_of_nodes; i++)
558 dedxm += k[m][i] * (xmxi - ((l[m][i] * xmxi) / sqrt(xmxi * xmxi + ymyi * ymyi)));
559 dedym += k[m][i] * (xmxi - ((l[m][i] * xmxi) / sqrt(xmxi * xmxi + ymyi * ymyi)));
562 return sqrt(dedxm * dedxm + dedym * dedym);
565 void move_node(int m, double *dx, double *dy)
567 double d2edxm2, d2edym2, d2edxmdym, dedxm, dedym;
568 double xmxi, ymyi, denominator;
571 d2edxm2 = d2edym2 = d2edxmdym = dedxm = dedym = 0.0;
572 for(i = 0; i < number_of_nodes; i++)
580 denominator = pow(sqrt(xmxi * xmxi + ymyi * ymyi), 3.0);
582 d2edxm2 += k[m][i] * (1 - ((l[m][i] * ymyi * ymyi) / denominator));
583 d2edxmdym += k[m][i] * l[m][i] * xmxi * ymyi / denominator;
584 d2edym2 += k[m][i] * (1 - ((l[m][i] * xmxi * xmxi) / denominator));
585 dedxm += k[m][i] * (xmxi - ((l[m][i] * xmxi) / sqrt(xmxi * xmxi + ymyi * ymyi)));
586 dedym += k[m][i] * (ymyi - ((l[m][i] * ymyi) / sqrt(xmxi * xmxi + ymyi * ymyi)));
589 denominator = ((d2edxm2 * d2edym2) - (d2edxmdym * d2edxmdym));
590 *dx = (-(d2edym2 * dedxm) + (d2edxmdym * dedym)) / denominator;
591 *dy = ((d2edxmdym * dedxm) - (d2edxm2 * dedym)) / denominator;
594 void if_build_graph(void)
597 double delta_m, max_delta_m;
598 double dx, dy, s, L, max_d, old_x, old_y;
603 for(i = 0; i < number_of_nodes; i++)
609 /* Initialize Floyd */
610 for(i = 0; i < number_of_nodes; i++)
613 for(j = i + 1; j < number_of_nodes; j++)
615 e = lookup_edge(nodes[i], nodes[j]);
617 d[i][j] = d[j][i] = (double)e->weight;
619 d[i][j] = d[j][i] = INFINITY;
623 /* Floyd's shortest path algorithm */
624 for(i = 0; i < number_of_nodes; i++)
626 for(j = 0; j < number_of_nodes; j++)
631 if(d[j][i] < INFINITY)
633 for(p = 0; p < number_of_nodes; p++)
635 if(d[i][j] < INFINITY)
637 s = d[j][i] + d[i][p];
649 for(i = 0; i < number_of_nodes; i++)
650 for(j = i + 1; j < number_of_nodes; j++)
651 if(d[i][j] > max_d && d[i][j] < INFINITY)
654 L = 300.0 / log(max_d);
656 for(i = 0; i < number_of_nodes; i++)
658 for(j = i + 1; j < number_of_nodes; j++)
660 d[i][j] = d[j][i] = log(d[i][j]+1.0);
661 l[i][j] = l[j][i] = L * d[i][j];
662 k[i][j] = k[j][i] = K / (d[i][j] * d[i][j]);
670 /* Find node with maximal local energy */
671 for(i = 0; i < number_of_nodes; i++)
673 delta_m = calculate_delta_m(i);
674 if(delta_m > max_delta_m)
676 max_delta_m = delta_m;
681 if(max_delta_m <= epsilon)
685 int iter = 0, maxiter = 20;
686 delta_m = max_delta_m;
689 while(delta_m > epsilon && iter < maxiter)
691 move_node(max_i, &dx, &dy);
694 delta_m = calculate_delta_m(max_i);
698 if_move_node(nodes[max_i], x[max_i] - old_x, y[max_i] - old_y);
705 /* build_graph = 0; */