From a4811c2f8ca7d8e32d1230b58e8140b60fcee2a3 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Fri, 9 Mar 2012 22:31:06 +0000 Subject: Fix "disconnect all". git-svn-id: http://svn.drobilla.net/lad/trunk/ganv@4036 a436a847-0d15-0410-975c-d299462d15a1 --- ganv/Edge.hpp | 8 ++++---- ganv/canvas.h | 9 +++++++++ ganv/edge.h | 14 ++++++++++++++ src/Canvas.cpp | 39 +++++++++++++++++++++++++++++++++------ src/edge.c | 11 ++++++++++- src/ganv_test.c | 39 +++++++++++++++++++++++++++++++++++++-- src/node.c | 2 +- 7 files changed, 108 insertions(+), 14 deletions(-) diff --git a/ganv/Edge.hpp b/ganv/Edge.hpp index ee2423c..6912eb2 100644 --- a/ganv/Edge.hpp +++ b/ganv/Edge.hpp @@ -46,7 +46,6 @@ public: bool show_arrowhead = false, bool curved = true) : Item(GANV_ITEM( - g_object_ref( ganv_edge_new( canvas.gobj(), tail->gobj(), @@ -54,11 +53,12 @@ public: "color", color, "curved", (gboolean)curved, "arrowhead", (gboolean)show_arrowhead, - NULL)))) - {} + NULL))) + { + } Edge(GanvEdge* gobj) - : Item(GANV_ITEM(g_object_ref(gobj))) + : Item(GANV_ITEM(gobj)) {} virtual ~Edge() { diff --git a/ganv/canvas.h b/ganv/canvas.h index ddd420b..bbf6b97 100644 --- a/ganv/canvas.h +++ b/ganv/canvas.h @@ -77,6 +77,15 @@ void ganv_canvas_add_node(GanvCanvas* canvas, GanvNode* node); +void +ganv_canvas_disconnect_edge(GanvCanvas* canvas, + GanvEdge* edge); + +void +ganv_canvas_remove_edge_between(GanvCanvas* canvas, + GanvNode* tail, + GanvNode* head); + /** Get the default font size in points. */ double ganv_canvas_get_default_font_size(const GanvCanvas* canvas); diff --git a/ganv/edge.h b/ganv/edge.h index 9a409b2..2d51c89 100644 --- a/ganv/edge.h +++ b/ganv/edge.h @@ -71,6 +71,20 @@ ganv_edge_highlight(GanvEdge* edge); void ganv_edge_unhighlight(GanvEdge* edge); +/** + * ganv_edge_disconnect: + * Disconnect the edge. This will disconnect the edge just as if it had been + * disconnected by the user via the canvas. The canvas disconnect signal will + * be emitted, allowing the application to control disconnect logic. + */ +void +ganv_edge_disconnect(GanvEdge* edge); + +/** + * ganv_edge_remove: + * Remove the edge from the canvas. This will only remove the edge visually, + * it will not emit the canvas disconnect signal to notify the application. + */ void ganv_edge_remove(GanvEdge* edge); diff --git a/src/Canvas.cpp b/src/Canvas.cpp index 15dedef..e353945 100644 --- a/src/Canvas.cpp +++ b/src/Canvas.cpp @@ -188,6 +188,9 @@ struct GanvCanvasImpl { void remove_edge(GanvEdge* c); bool are_connected(const GanvNode* tail, const GanvNode* head); + GanvEdge* + get_edge_between(const GanvNode* tail, + const GanvNode* head); typedef std::set Edges; typedef std::set DstEdges; @@ -598,9 +601,20 @@ GanvCanvasImpl::remove_edge(GanvEdge* edge) _selected_edges.erase(edge); _edges.erase(edge); _dst_edges.erase(edge); + gtk_object_destroy(GTK_OBJECT(edge)); } } +GanvEdge* +GanvCanvasImpl::get_edge_between(const GanvNode* tail, + const GanvNode* head) +{ + GanvEdgeKey key; + make_edge_search_key(&key, tail, head); + Edges::const_iterator i = _edges.find((GanvEdge*)&key); + return (i != _edges.end()) ? *i : NULL; +} + /** Return whether there is a edge between item1 and item2. * * Note that edges are directed, so this may return false when there @@ -610,9 +624,7 @@ bool GanvCanvasImpl::are_connected(const GanvNode* tail, const GanvNode* head) { - GanvEdgeKey key; - make_edge_search_key(&key, tail, head); - return (_edges.find((GanvEdge*)&key) != _edges.end()); + return get_edge_between(tail, head) != NULL; } void @@ -1500,12 +1512,11 @@ Canvas::set_default_placement(Node* i) } void -Canvas::remove_edge(Node* item1, - Node* item2) +Canvas::remove_edge(Node* item1, Node* item2) { Edge* edge = get_edge(item1, item2); if (edge) { - gtk_object_destroy(GTK_OBJECT(edge->gobj())); + impl()->remove_edge(edge->gobj()); } } @@ -1952,6 +1963,22 @@ ganv_canvas_add_node(GanvCanvas* canvas, canvas->impl->add_item(node); } +void +ganv_canvas_remove_edge_between(GanvCanvas* canvas, + GanvNode* tail, + GanvNode* head) +{ + canvas->impl->remove_edge(canvas->impl->get_edge_between(tail, head)); +} + +void +ganv_canvas_disconnect_edge(GanvCanvas* canvas, + GanvEdge* edge) +{ + g_signal_emit(canvas, signal_disconnect, 0, + edge->impl->tail, edge->impl->head, NULL); +} + void ganv_canvas_remove_node(GanvCanvas* canvas, GanvNode* node) diff --git a/src/edge.c b/src/edge.c index 8d43f46..65690cd 100644 --- a/src/edge.c +++ b/src/edge.c @@ -88,7 +88,6 @@ ganv_edge_destroy(GtkObject* object) GanvEdge* edge = GANV_EDGE(object); GanvCanvas* canvas = GANV_CANVAS(edge->item.canvas); if (canvas && !edge->impl->ghost) { - ganv_canvas_remove_edge(canvas, edge); edge->item.canvas = NULL; } edge->item.parent = NULL; @@ -641,6 +640,16 @@ ganv_edge_tick(GanvEdge* edge, NULL); } +void +ganv_edge_disconnect(GanvEdge* edge) +{ + if (!edge->impl->ghost) { + ganv_canvas_disconnect_edge( + GANV_CANVAS(edge->item.canvas), + edge); + } +} + void ganv_edge_remove(GanvEdge* edge) { diff --git a/src/ganv_test.c b/src/ganv_test.c index a1fba2a..fce3ede 100644 --- a/src/ganv_test.c +++ b/src/ganv_test.c @@ -18,12 +18,23 @@ #include "ganv/ganv.h" static void -on_window_destroy(GtkWidget* widget, - gpointer data) +on_window_destroy(GtkWidget* widget, gpointer data) { gtk_main_quit(); } +static void +on_connect(GanvCanvas* canvas, GanvNode* tail, GanvNode* head, void* data) +{ + ganv_edge_new(canvas, tail, head, "color", 0xFFFFFFFF, NULL); +} + +static void +on_disconnect(GanvCanvas* canvas, GanvNode* tail, GanvNode* head, void* data) +{ + ganv_canvas_remove_edge_between(canvas, tail, head); +} + int main(int argc, char** argv) { @@ -44,6 +55,10 @@ main(int argc, char** argv) "label", "test", NULL); + GanvPort* port = ganv_port_new(module, FALSE, + "label", "Signal", + NULL); + GanvPort* cport = ganv_port_new(module, TRUE, "label", "Control", NULL); @@ -61,6 +76,26 @@ main(int argc, char** argv) ganv_item_show(GANV_ITEM(module)); ganv_item_raise_to_top(GANV_ITEM(module)); + GanvModule* module2 = ganv_module_new(canvas, + "x", 200.0, + "y", 10.0, + "draggable", TRUE, + "label", "test2", + NULL); + + GanvPort* port2 = ganv_port_new(module2, TRUE, + "label", "Signal", + NULL); + + g_signal_connect(canvas, "connect", + G_CALLBACK(on_connect), canvas); + + g_signal_connect(canvas, "disconnect", + G_CALLBACK(on_disconnect), canvas); + + ganv_item_show(GANV_ITEM(module2)); + ganv_item_raise_to_top(GANV_ITEM(module2)); + gtk_widget_show_all(GTK_WIDGET(win)); gtk_window_present(win); gtk_main(); diff --git a/src/node.c b/src/node.c index a59bde3..e2b6213 100644 --- a/src/node.c +++ b/src/node.c @@ -299,7 +299,7 @@ ganv_node_default_disconnect(GanvNode* node) { GanvCanvas* canvas = GANV_CANVAS(GANV_ITEM(node)->canvas); if (canvas) { - ganv_canvas_for_each_edge_on(canvas, node, ganv_edge_remove); + ganv_canvas_for_each_edge_on(canvas, node, ganv_edge_disconnect); } } -- cgit v1.2.1