Begining of wire implementation
[gmodulargraph.git] / src / gtkgraph-demo.c
blob27c22d285e5a96e50d0f803b7e6fb49b5232b543
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
2 /*
3 * gtkgraph-demo.c
4 * Copyright (C) Nikita Zlobin 2011 <nick87720z@gmail.com>
5 *
6 * gtkgraph is free software: you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * gtkgraph is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 * See the GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program. If not, see <http://www.gnu.org/licenses/>.
20 #define _GNU_SOURCE
22 #include <goocanvas.h>
23 #include <math.h>
24 #include <stdint.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <stdio.h>
29 static gboolean on_root_buttonPress_event (GooCanvasItem * item, GooCanvasItem * target, GdkEventButton * event, gpointer data);
30 static gboolean on_root_buttonRelease_event (GooCanvasItem * item, GooCanvasItem * target, GdkEventButton * event, gpointer data);
31 static gboolean on_root_dragged (GooCanvasItem * item, GooCanvasItem * target, GdkEventMotion * event, gpointer data);
33 static gboolean on_module_enterNotify_event (GooCanvasItem * item, GooCanvasItem * target, GdkEventCrossing * event, gpointer data);
34 static gboolean on_module_leaveNotify_event (GooCanvasItem * item, GooCanvasItem * target, GdkEventCrossing * event, gpointer data);
36 static gboolean on_module_notify_width (GooCanvasItem * item, GParamSpec * event, gpointer data);
37 static gboolean on_module_notify_height (GooCanvasItem * item, GParamSpec * event, gpointer data);
39 static gboolean on_module_buttonPress_event (GooCanvasItem * item, GooCanvasItem * target, GdkEventButton * event, gpointer data);
40 static gboolean on_module_buttonRelease_event (GooCanvasItem * item, GooCanvasItem * target, GdkEventButton * event, gpointer data);
41 static gboolean on_module_dragged (GooCanvasItem * item, GooCanvasItem * target, GdkEventMotion * event, gpointer data);
43 static gboolean on_module_text_notify (GooCanvasItem * item, GParamSpec * event, gpointer data);
44 static gboolean on_port_text_notify (GooCanvasItem * item, GParamSpec * event, gpointer data);
46 static gboolean wire_entered (GooCanvasItem * item, GooCanvasItem * target, GdkEventCrossing * event, gpointer data);
47 static gboolean wire_left (GooCanvasItem * item, GooCanvasItem * target, GdkEventCrossing * event, gpointer data);
49 double border_threshold = 1.0;
51 #define drag_button 1
53 typedef
54 struct {
55 struct {
56 unsigned color;
57 float rounding;
58 struct {
59 unsigned threshold;
60 unsigned border_color;
61 } border;
62 struct {
63 unsigned shadow_color;
64 float shadow_size;
65 } shadow;
66 struct {
67 unsigned alignment;
68 char * font;
69 } caption;
70 } moduleBox;
71 } GModularGraphStyle;
73 typedef
74 struct {
75 GooCanvasItem * box; /* Background */
76 GooCanvasItem * outer_border;
77 GooCanvasItem * inner_border;
79 GtkOrientation * orientation;
81 GooCanvasItem * caption;
82 GooCanvasItem * group; /* Just a logical container, without any look */
83 GooCanvasItem * layout; /* Used to organize elements (caption, ports) */
85 /* List of ports groups */
86 GList * ports;
88 /* Dragging data */
89 double drag_hold_x, drag_hold_y;
90 unsigned drag_cb;
91 } GModularGraph_Module;
93 #define G_MODULAR_GRAPH_MODULE(p) ((GModularGraph_Module *) (p))
95 typedef enum {
96 G_MODULAR_GRAPH_PORT_DIRECTION_IN = 1,
97 G_MODULAR_GRAPH_PORT_DIRECTION_OUT
98 } GModularGraphPortDirection;
100 typedef
101 struct {
102 GList * ports;
103 GModularGraphPortDirection direction;
105 unsigned width;
106 unsigned p_count;
107 GooCanvasItem * container;
108 } GModularGraphPortsGroup;
110 #define G_MODULAR_GRAPH_PORTS_GROUP(p) ((GModularGraphPortsGroup *) (p))
112 typedef
113 struct {
114 GooCanvasItem * box;
115 GooCanvasItem * text;
116 GooCanvasItem * group;
117 GModularGraphPortsGroup * ports_group;
118 double min_width;
120 double wire_x, wire_y;
121 double direction; /* In deegreens. Also affects wire direction. */
122 } GModularGraph_Port;
124 #define G_MODULAR_GRAPH_PORT(p) ((GModularGraph_Port *) (p))
126 typedef
127 struct {
128 GooCanvasItem * path_b;
129 GooCanvasItem * path_t;
131 //char ** cmd_v;
132 //unsigned * cmd_len;
134 double x1, y1, cx1, cy1;
135 double x2, y2, cx2, cy2;
137 double angle1, angle2; /* In degreens */
138 unsigned color;
139 } GModularGraph_Wire;
141 #define G_MODULAR_GRAPH_WIRE(p) ((GModularGraph_Wire *) (p))
143 /* Canvas data */
144 GtkWidget * canvas;
145 GooCanvasItem * root_item;
146 static double rounding = 3;
148 static GModularGraph_Module * module[2] = {NULL, NULL};
150 void g_modular_graph_module_add_ports_group (GModularGraphPortsGroup ** ret, GModularGraph_Module * module, GModularGraphPortDirection direction);
152 static void canvas_text_size (GooCanvasItem * item, double * w, double * h)
154 PangoRectangle rect;
156 goo_canvas_text_get_natural_extents (GOO_CANVAS_TEXT (item), NULL, & rect);
157 if (w) *w = (double) PANGO_PIXELS (rect.width);
158 if (h) *h = (double) PANGO_PIXELS (rect.height);
161 static inline void
162 text_wanted_size (GooCanvasItem * item, double * w, double * h)
164 canvas_text_size (item, w, h);
165 if (w) *w += rounding * 2;
168 static void module_update_size (GModularGraph_Module * module)
170 double w = 0, h = 0;
171 double x = 0, y = 0;
172 GooCanvasBounds bounds;
174 g_object_get (module->layout, "x", & x, "y", & y, NULL);
175 goo_canvas_item_get_bounds (module->layout, & bounds);
176 w = bounds.x2 - bounds.x1 + x;
177 h = bounds.y2 - bounds.y1 + y;
179 double text_w, text_h;
180 text_wanted_size (module->caption, & text_w, & text_h);
181 if (w < text_w) w = text_w;
182 h += rounding;
183 w --; // Strangely, without this line right side of border is placed later by 1 pixel, relatively to output ports borders
184 g_object_set (module->box, "width", w, "height", h, NULL);
187 GModularGraph_Module * g_modular_graph_module_new (GooCanvasItem * parent,
188 char * caption, char * tooltip,
189 int placing, int x, int y)
191 GModularGraph_Module * module;
192 unsigned width = 50, height = 20;
194 /* Fundament */
195 module = calloc (1, sizeof (GModularGraph_Module));
196 module->group = goo_canvas_group_new (parent, "x", (double) x, "y", (double) y, "tooltip", tooltip, NULL);
198 /* Decoration */
199 module->outer_border = goo_canvas_rect_new (module->group,
200 - border_threshold / 2, - border_threshold / 2,
201 width + border_threshold, height + border_threshold,
202 "radius-x", rounding + border_threshold / 2, "radius-y", rounding + border_threshold / 2,
203 "stroke-color-rgba", 0x0000005f, NULL);
205 module->box = goo_canvas_rect_new (module->group,
206 border_threshold / 2, border_threshold / 2,
207 width - border_threshold, height - border_threshold,
208 "radius-x", rounding, "radius-y", rounding,
209 "stroke-color", "gray45", "fill-color", "gray30",
210 NULL);
212 module->inner_border = goo_canvas_rect_new (module->group,
213 border_threshold * 1.5, border_threshold * 1.5,
214 width - border_threshold * 3, height - border_threshold * 3,
215 "radius-x", rounding - border_threshold / 2, "radius-y", rounding - border_threshold / 2,
216 "stroke-color", "gray33", NULL);
218 g_signal_connect (G_OBJECT (module->box), "notify::width", G_CALLBACK (on_module_notify_width), module);
219 g_signal_connect (G_OBJECT (module->box), "notify::height", G_CALLBACK (on_module_notify_height), module);
221 /* Caption */
222 module->caption = goo_canvas_text_new (module->group, "",
223 rounding, 0, -1, GTK_ANCHOR_NORTH_WEST,
224 "font", "sans 8",
225 "fill-color", "white", NULL);
226 g_signal_connect (G_OBJECT (module->caption), "notify::text", G_CALLBACK (on_module_text_notify), module);
228 /* Predefined groups */
229 module->layout = goo_canvas_table_new (module->group, "y", 15.0, "column-spacing", 5.0, NULL);
230 g_modular_graph_module_add_ports_group (NULL, module, G_MODULAR_GRAPH_PORT_DIRECTION_IN);
231 g_modular_graph_module_add_ports_group (NULL, module, G_MODULAR_GRAPH_PORT_DIRECTION_OUT);
233 /* Dragging capabilities */
234 g_signal_connect (G_OBJECT (module->group), "button-press-event", G_CALLBACK (on_module_buttonPress_event), module);
235 g_signal_connect (G_OBJECT (module->group), "button-release-event", G_CALLBACK (on_module_buttonRelease_event), module);
237 /* Mouse over */
238 g_signal_connect (G_OBJECT (module->group), "enter-notify-event", G_CALLBACK (on_module_enterNotify_event), module);
239 g_signal_connect (G_OBJECT (module->group), "leave-notify-event", G_CALLBACK (on_module_leaveNotify_event), module);
241 g_object_set (G_OBJECT (module->caption), "text", caption, NULL);
242 return module;
245 void g_modular_graph_module_add_ports_group (GModularGraphPortsGroup ** ret, GModularGraph_Module * module, GModularGraphPortDirection direction)
247 GModularGraphPortsGroup * group;
248 GooCanvasItem * parent;
250 if (direction == G_MODULAR_GRAPH_PORT_DIRECTION_IN || direction == G_MODULAR_GRAPH_PORT_DIRECTION_OUT)
251 parent = module->layout;
252 else parent = module->group;
254 group = calloc (1, sizeof(GModularGraphPortsGroup));
255 group->direction = direction;
256 group->container = goo_canvas_table_new (parent, "x", 0.0, "y", 0.0, "row-spacing", 1.0, "column-spacing", 0.0,
257 //"clip-path", "M 0 0 h 100 v 20 h -20 Z",
258 //"horz-grid-line-width", 1.0, "vert-grid-line-width", 1.0,
259 "stroke-color", "yellow", NULL);
260 if (direction == G_MODULAR_GRAPH_PORT_DIRECTION_IN)
261 goo_canvas_item_set_child_properties (module->layout, group->container, "column", 0, "x-align", 0.0, NULL);
262 else if (direction == G_MODULAR_GRAPH_PORT_DIRECTION_OUT)
263 goo_canvas_item_set_child_properties (module->layout, group->container, "column", 1, "x-align", 1.0, NULL);
265 goo_canvas_item_set_child_properties (module->layout, group->container, "y-align", 0.0, NULL);
267 module->ports = g_list_append (module->ports, group);
269 if (ret) * ret = group;
272 static double ports_group_update_width (GModularGraphPortsGroup * group)
274 double min_width = 0;
275 GList * sib = group->ports;
277 while (1)
279 if (G_MODULAR_GRAPH_PORT (sib->data)->min_width > min_width)
280 min_width = G_MODULAR_GRAPH_PORT (sib->data)->min_width;
282 if (! sib->next) break;
283 sib = sib->next;
285 sib = group->ports;
286 while (1)
288 g_object_set (G_MODULAR_GRAPH_PORT (sib->data)->box, "width", min_width, NULL);
289 if (! sib->next) break;
290 sib = sib->next;
292 return min_width;
295 void g_modular_graph_module_add_port (GModularGraph_Port ** ret,
296 GModularGraph_Module * module,
297 int direction,
298 char * name, char * tooltip)
300 /* Create ports group */
301 GModularGraphPortsGroup * group = NULL;
302 if (module->ports)
304 GList * elem = module->ports;
305 while (1)
307 if (G_MODULAR_GRAPH_PORTS_GROUP (elem->data)->direction == direction)
309 group = elem->data;
310 break;
312 if (! elem->next) break;
313 elem = elem->next;
316 if (! group)
318 g_modular_graph_module_add_ports_group (& group, module, direction);
321 GModularGraph_Port * port = calloc (1, sizeof (GModularGraph_Port));
323 /* Decoration */
324 port->box = goo_canvas_rect_new (group->container,
325 0.5, 0.5, 50, 5,
326 "tooltip", tooltip,
327 //"radius-x", rounding,
328 //"radius-y", rounding,
329 "line-width", border_threshold,
330 "stroke-color", "gray70",
331 "fill-color", "gray60",
332 NULL);
333 /* Caption */
334 port->text = goo_canvas_text_new (group->container, "",
335 rounding, 0, -1, GTK_ANCHOR_NORTH_WEST,
336 "tooltip", tooltip,
337 "font", "sans 8",
338 "fill-color", "gray90", NULL);
339 goo_canvas_item_set_child_properties (group->container, port->box, "row", group->p_count, "x-expand", TRUE, "x-fill", TRUE, NULL);
340 goo_canvas_item_set_child_properties (group->container, port->text, "row", group->p_count, "x-expand", TRUE, "x-fill", TRUE,
341 "left-padding", rounding, "x-align", 0.5, NULL);
343 g_signal_connect (G_OBJECT (port->text), "notify::text", G_CALLBACK (on_port_text_notify), port);
345 /* Add port to group */
346 port->ports_group = group;
347 if (! g_list_find (group->ports, port))
348 group->ports = g_list_append (group->ports, port);
350 /* Complete initialization */
351 g_object_set (G_OBJECT (port->text), "text", name, NULL);
352 module_update_size (module);
354 group->p_count++;
355 if (ret) *ret = port;
358 typedef
359 union {
360 struct {
361 uint8_t alpha;
362 uint8_t blue;
363 uint8_t green;
364 uint8_t red;
366 uint32_t value;
367 } Color;
369 GModularGraph_Wire * g_modular_graph_wire_new (double x1, double y1, double angle1, double x2, double y2, double angle2, char * tooltip, unsigned color)
371 char * wire_data;
372 GModularGraph_Wire * wire;
373 wire = calloc (1, sizeof (GModularGraph_Wire));
374 wire->x1 = x1, wire->y1 = y1;
375 wire->x2 = x2, wire->y2 = y2;
376 wire->angle1 = angle1;
377 wire->angle2 = angle2;
379 wire->cx1 = wire->x1 + cos (wire->angle1 * G_PI / 180) * 50;
380 wire->cy1 = wire->y1 + sin (wire->angle1 * G_PI / 180) * 50;
381 wire->cx2 = wire->x2 + cos (wire->angle2 * G_PI / 180) * 50;
382 wire->cy2 = wire->y2 + sin (wire->angle2 * G_PI / 180) * 50;
383 asprintf (& wire_data, "M%i,%i C%i,%i %i,%i %i,%i",
384 (int) wire->x1, (int) wire->y1,
385 (int) wire->cx1, (int) wire->cy1,
386 (int) wire->cx2, (int) wire->cy2,
387 (int) wire->x2, (int) wire->y2);
389 wire->path_b = goo_canvas_path_new (root_item,
390 wire_data,
391 "line-width", 2.0,
392 "stroke-color-rgba", color, NULL);
394 Color color_t = {.value = 0xff0000f0};
395 color_t.red = color_t.red + (0xff - color_t.red) * 0.8;
396 color_t.green = color_t.green + (0xff - color_t.green) * 0.8;
397 color_t.blue = color_t.blue + (0xff - color_t.blue) * 0.8;
398 wire->path_t = goo_canvas_path_new (root_item,
399 wire_data,
400 "line-width", 1.0,
401 "stroke-color-rgba", color_t.value, NULL);
403 g_signal_connect (G_OBJECT (wire->path_t), "enter-notify-event", G_CALLBACK (wire_entered), NULL);
404 g_signal_connect (G_OBJECT (wire->path_t), "leave-notify-event", G_CALLBACK (wire_left), NULL);
405 g_object_set (wire->path_t, "tooltip", tooltip, NULL);
407 return wire;
410 int main( int argc, char ** argv )
412 GtkWidget * win;
413 GtkWidget * scroller;
415 gtk_init (& argc, & argv);
416 win = gtk_window_new (GTK_WINDOW_TOPLEVEL);
417 g_signal_connect (G_OBJECT (win), "delete-event", G_CALLBACK (gtk_main_quit), NULL);
419 scroller = gtk_scrolled_window_new (NULL, NULL);
420 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scroller), GTK_SHADOW_IN);
421 gtk_container_add (GTK_CONTAINER (win), scroller);
423 /* Create canvas widget */
424 canvas = goo_canvas_new ();
425 gtk_widget_set_size_request (canvas, 600, 450);
426 goo_canvas_set_bounds (GOO_CANVAS (canvas), 0, 0, 1000, 1000);
427 g_object_set (G_OBJECT (canvas), "automatic-bounds", TRUE, NULL);
429 gtk_container_add (GTK_CONTAINER (scroller), canvas);
431 /* Root */
432 root_item = goo_canvas_get_root_item (GOO_CANVAS (canvas));
433 g_object_set (G_OBJECT (root_item), "antialias", CAIRO_ANTIALIAS_SUBPIXEL, NULL);
434 g_object_set (G_OBJECT (root_item), "line-join", CAIRO_LINE_JOIN_ROUND, NULL);
435 g_object_set (G_OBJECT (root_item), "line-cap", CAIRO_LINE_CAP_ROUND, NULL);
436 g_object_set (G_OBJECT (root_item), "line-width", border_threshold, NULL);
437 g_signal_connect (G_OBJECT (root_item), "button-press-enter", G_CALLBACK (on_root_buttonPress_event), NULL);
438 g_signal_connect (G_OBJECT (root_item), "button-press-enter", G_CALLBACK (on_root_buttonRelease_event), NULL);
440 module[0] = g_modular_graph_module_new (root_item, "Module 1", "Module 1 tip", 0, 50, 50);
441 g_modular_graph_module_add_port (NULL, module[0], G_MODULAR_GRAPH_PORT_DIRECTION_IN, "in-1", "Port 1 tip");
442 g_modular_graph_module_add_port (NULL, module[0], G_MODULAR_GRAPH_PORT_DIRECTION_IN, "in-2", "Port 2 tip");
443 module[1] = g_modular_graph_module_new (root_item, "Module 2", "Module 2 tip", 0, 200, 10);
444 g_modular_graph_module_add_port (NULL, module[1], G_MODULAR_GRAPH_PORT_DIRECTION_IN, "in-1", "Port 1 tip");
445 g_modular_graph_module_add_port (NULL, module[1], G_MODULAR_GRAPH_PORT_DIRECTION_IN, "in-2", "Port 2 tip");
446 g_modular_graph_module_add_port (NULL, module[1], G_MODULAR_GRAPH_PORT_DIRECTION_IN, "input-3", "Port 3 tip");
447 g_modular_graph_module_add_port (NULL, module[1], G_MODULAR_GRAPH_PORT_DIRECTION_OUT, "out-1", "Out 1 tip");
448 g_modular_graph_module_add_port (NULL, module[1], G_MODULAR_GRAPH_PORT_DIRECTION_OUT, "out-2", "Out 2 tip");
450 /* 2. Connection */
451 g_modular_graph_wire_new (50, 100, 0.0, 300, 300, 180, "Test wire", 0x5f0000ff);
452 g_modular_graph_wire_new (50, 300, 0.0, 300, 100, 180, "Test wire", 0x5f0000ff);
454 /* * * * */
456 gtk_widget_set_has_tooltip (canvas, TRUE);
458 gtk_widget_show_all (win);
459 gtk_main ();
460 return 0;
463 /* Helpers (nothing yet) */
465 /* Root callbacks */
467 static gboolean on_root_buttonPress_event (GooCanvasItem * item, GooCanvasItem * target, GdkEventButton * event, gpointer data)
469 return FALSE;
472 static gboolean on_root_buttonRelease_event (GooCanvasItem * item, GooCanvasItem * target, GdkEventButton * event, gpointer data)
474 return FALSE;
477 static gboolean on_root_dragged (GooCanvasItem * item, GooCanvasItem * target, GdkEventMotion * event, gpointer data)
479 return FALSE;
482 /* Module callbacks */
484 static gboolean on_module_enterNotify_event (GooCanvasItem * item, GooCanvasItem * target, GdkEventCrossing * event, gpointer data)
486 char
487 * inner_border_color = "gray40",
488 * outer_border_color = "gray70";
489 g_object_set (G_MODULAR_GRAPH_MODULE (data)->inner_border, "stroke-color", inner_border_color, NULL);
490 g_object_set (G_MODULAR_GRAPH_MODULE (data)->box, "stroke-color", outer_border_color, NULL);
491 return FALSE;
494 static gboolean on_module_leaveNotify_event (GooCanvasItem * item, GooCanvasItem * target, GdkEventCrossing * event, gpointer data)
496 char
497 * inner_border_color = "gray33",
498 * outer_border_color = "gray45";
499 g_object_set (G_MODULAR_GRAPH_MODULE (data)->inner_border, "stroke-color", inner_border_color, NULL);
500 g_object_set (G_MODULAR_GRAPH_MODULE (data)->box, "stroke-color", outer_border_color, NULL);
501 return FALSE;
504 static gboolean on_module_notify_width (GooCanvasItem * item, GParamSpec * event, gpointer data)
506 double w;
507 g_object_get (G_MODULAR_GRAPH_MODULE (data)->box, "width", & w, NULL);
508 g_object_set (G_MODULAR_GRAPH_MODULE (data)->inner_border, "width", w - border_threshold * 2, NULL);
509 g_object_set (G_MODULAR_GRAPH_MODULE (data)->outer_border, "width", w + border_threshold * 2, NULL);
510 return FALSE;
513 static gboolean on_module_notify_height (GooCanvasItem * item, GParamSpec * event, gpointer data)
515 double h;
516 g_object_get (G_MODULAR_GRAPH_MODULE (data)->box, "height", & h, NULL);
517 g_object_set (G_MODULAR_GRAPH_MODULE (data)->inner_border, "height", h - border_threshold * 2, NULL);
518 g_object_set (G_MODULAR_GRAPH_MODULE (data)->outer_border, "height", h + border_threshold * 2, NULL);
519 return FALSE;
522 #define DRAG_CB( mod ) (G_MODULAR_GRAPH_MODULE( mod )->drag_cb)
523 #define DRAG_HOLD_X( mod ) (G_MODULAR_GRAPH_MODULE( mod )->drag_hold_x)
524 #define DRAG_HOLD_Y( mod ) (G_MODULAR_GRAPH_MODULE( mod )->drag_hold_y)
526 static gboolean drag_redraw = TRUE;
527 static unsigned drag_redraw_timeout_id = 0;
529 static gboolean drag_redraw_timeout (gpointer data)
531 drag_redraw = TRUE;
532 return TRUE;
535 static
536 gboolean on_module_buttonPress_event (GooCanvasItem * item, GooCanvasItem * target, GdkEventButton * event, gpointer data)
538 if (event->button == drag_button)
540 g_object_get (G_OBJECT (item),
541 "x", & DRAG_HOLD_X (data),
542 "y", & DRAG_HOLD_Y (data), NULL);
543 DRAG_HOLD_X (data) = event->x - DRAG_HOLD_X (data);
544 DRAG_HOLD_Y (data) = event->y - DRAG_HOLD_Y (data);
546 DRAG_CB (data) = g_signal_connect (G_OBJECT (root_item), "motion-notify-event", G_CALLBACK (on_module_dragged), data);
547 drag_redraw_timeout_id = g_timeout_add (30, drag_redraw_timeout, NULL);
549 return FALSE;
552 static
553 gboolean on_module_buttonRelease_event (GooCanvasItem * item, GooCanvasItem * target, GdkEventButton * event, gpointer data)
555 if (event->button == drag_button)
557 g_source_remove (drag_redraw_timeout_id);
558 drag_redraw_timeout_id = 0;
559 if (DRAG_CB (data))
560 g_signal_handler_disconnect (G_OBJECT (root_item), DRAG_CB (data));
562 return FALSE;
565 static
566 gboolean on_module_dragged (GooCanvasItem * item, GooCanvasItem * target, GdkEventMotion * event, gpointer data)
568 if (drag_redraw)
570 g_object_set (G_MODULAR_GRAPH_MODULE (data)->group, "x", event->x - DRAG_HOLD_X (data), NULL);
571 g_object_set (G_MODULAR_GRAPH_MODULE (data)->group, "y", event->y - DRAG_HOLD_Y (data), NULL);
572 drag_redraw = FALSE;
574 return FALSE;
577 static gboolean on_module_text_notify (GooCanvasItem * item, GParamSpec * event, gpointer data)
579 double w, h;
580 text_wanted_size (item, &w, &h);
582 g_object_set (G_MODULAR_GRAPH_MODULE (data)->box, "width", w, NULL);
583 g_object_set (G_MODULAR_GRAPH_MODULE (data)->box, "height", h, NULL);
585 return FALSE;
588 /* Port callbacks */
590 static gboolean on_port_text_notify (GooCanvasItem * item, GParamSpec * event, gpointer data)
592 double w, h;
593 text_wanted_size (item, &w, &h);
594 if (G_MODULAR_GRAPH_PORT (data)->min_width == w) return FALSE;
596 G_MODULAR_GRAPH_PORT (data)->min_width = w;
597 ports_group_update_width (G_MODULAR_GRAPH_PORT (data)->ports_group);
598 g_object_set (G_MODULAR_GRAPH_PORT (data)->box, "height", h, NULL);
600 return FALSE;
603 /* Wire callbacks */
605 static
606 gboolean wire_entered (GooCanvasItem *item,
607 GooCanvasItem *target,
608 GdkEventCrossing *event,
609 gpointer data)
611 g_object_set (item, "stroke-color", "white", NULL);
612 return FALSE;
615 static
616 gboolean wire_left (GooCanvasItem *item,
617 GooCanvasItem *target,
618 GdkEventCrossing *event,
619 gpointer data)
621 g_object_set (item, "stroke-color", "violet", NULL);
622 return FALSE;