diff options
-rw-r--r-- | ganv/Canvas.hpp | 21 | ||||
-rw-r--r-- | ganv/canvas.h | 27 | ||||
-rw-r--r-- | ganv/node.h | 3 | ||||
-rw-r--r-- | ganv/wrap.hpp | 5 | ||||
-rw-r--r-- | src/Canvas.cpp | 71 | ||||
-rw-r--r-- | src/module.c | 16 | ||||
-rw-r--r-- | src/node.c | 19 | ||||
-rw-r--r-- | src/port.c | 10 |
8 files changed, 114 insertions, 58 deletions
diff --git a/ganv/Canvas.hpp b/ganv/Canvas.hpp index 00c267c..886102b 100644 --- a/ganv/Canvas.hpp +++ b/ganv/Canvas.hpp @@ -72,17 +72,20 @@ public: METHOD2(ganv_canvas, for_each_node, GanvNodeFunc, f, void*, data) METHOD2(ganv_canvas, for_each_selected_node, GanvNodeFunc, f, void*, data) - METHOD2(ganv_canvas, for_each_edge_from, + METHOD3(ganv_canvas, for_each_edge_from, const GanvNode*, tail, - GanvEdgeFunc, f); + GanvEdgeFunc, f, + void*, data); - METHOD2(ganv_canvas, for_each_edge_to, + METHOD3(ganv_canvas, for_each_edge_to, const GanvNode*, head, - GanvEdgeFunc, f); + GanvEdgeFunc, f, + void*, data); - METHOD2(ganv_canvas, for_each_edge_on, + METHOD3(ganv_canvas, for_each_edge_on, const GanvNode*, node, - GanvEdgeFunc, f); + GanvEdgeFunc, f, + void*, data); METHOD0(ganv_canvas, get_move_cursor); @@ -101,10 +104,8 @@ public: void remove_edge(Edge* edge); - typedef void (*EdgePtrFunc)(GanvEdge* edge, void* data); - - void for_each_edge(EdgePtrFunc f, void* data); - void for_each_selected_edge(EdgePtrFunc f, void* data); + void for_each_edge(GanvEdgeFunc f, void* data); + void for_each_selected_edge(GanvEdgeFunc f, void* data); void get_scroll_offsets(int& cx, int& cy) const; void scroll_to(int x, int y); diff --git a/ganv/canvas.h b/ganv/canvas.h index bcc2e3d..bac6597 100644 --- a/ganv/canvas.h +++ b/ganv/canvas.h @@ -121,9 +121,23 @@ ganv_canvas_arrange(GanvCanvas* canvas); void ganv_canvas_export_dot(GanvCanvas* canvas, const char* filename); -typedef void (*GanvNodeFunc)(GanvNode* node, void* data); +/** + * A node function that takes a user data argument (for callbacks). + * + * Note that in the Gtk world it is considered safe to cast a function to a + * function with more arguments and call the resulting pointer, so functions + * like ganv_edge_select can safely be used where a GanvEdgeFunc is expected. + */ +typedef void (*GanvEdgeFunc)(GanvEdge* edge, void* data); -typedef void (*GanvEdgeFunc)(GanvEdge* edge); +/** + * A node function that takes a user data argument (for callbacks). + * + * Note that in the Gtk world it is considered safe to cast a function to a + * function with more arguments and call the resulting pointer, so functions + * like ganv_node_select can safely be used where a GanvNodeFunc is expected. + */ +typedef void (*GanvNodeFunc)(GanvNode* node, void* data); /** * ganv_canvas_for_each_node: @@ -167,7 +181,8 @@ ganv_canvas_for_each_edge(GanvCanvas* canvas, void ganv_canvas_for_each_edge_from(GanvCanvas* canvas, const GanvNode* tail, - GanvEdgeFunc f); + GanvEdgeFunc f, + void* data); /** * ganv_canvas_for_each_edge_to: @@ -178,7 +193,8 @@ ganv_canvas_for_each_edge_from(GanvCanvas* canvas, void ganv_canvas_for_each_edge_to(GanvCanvas* canvas, const GanvNode* head, - GanvEdgeFunc f); + GanvEdgeFunc f, + void* data); /** * ganv_canvas_for_each_edge_on: @@ -189,7 +205,8 @@ ganv_canvas_for_each_edge_to(GanvCanvas* canvas, void ganv_canvas_for_each_edge_on(GanvCanvas* canvas, const GanvNode* node, - GanvEdgeFunc f); + GanvEdgeFunc f, + void* data); /** * ganv_canvas_destroy: diff --git a/ganv/node.h b/ganv/node.h index d640167..13c9e5f 100644 --- a/ganv/node.h +++ b/ganv/node.h @@ -157,6 +157,9 @@ ganv_node_redraw_text(GanvNode* node); void ganv_node_disconnect(GanvNode* node); +gboolean +ganv_node_is_selected(GanvNode* node); + G_END_DECLS #endif /* GANV_NODE_H */ diff --git a/ganv/wrap.hpp b/ganv/wrap.hpp index db871b5..d29740e 100644 --- a/ganv/wrap.hpp +++ b/ganv/wrap.hpp @@ -70,6 +70,11 @@ prefix##_##name(gobj(), a1, a2); \ } +#define METHOD3(prefix, name, t1, a1, t2, a2, t3, a3) \ + virtual void name(t1 a1, t2 a2, t3 a3) { \ + prefix##_##name(gobj(), a1, a2, a3); \ + } + #define SIGNAL1(name, argtype) \ public: \ virtual bool on_##name(argtype arg) { \ diff --git a/src/Canvas.cpp b/src/Canvas.cpp index 17a28cf..057b841 100644 --- a/src/Canvas.cpp +++ b/src/Canvas.cpp @@ -167,9 +167,9 @@ struct GanvCanvasImpl { void set_zoom_and_font_size(double zoom, double points); void for_each_node(GanvNodeFunc f, void* data); - void for_each_edge_from(const GanvNode* tail, GanvEdgeFunc f); - void for_each_edge_to(const GanvNode* head, GanvEdgeFunc f); - void for_each_edge_on(const GanvNode* node, GanvEdgeFunc f); + void for_each_edge_from(const GanvNode* tail, GanvEdgeFunc f, void* data); + void for_each_edge_to(const GanvNode* head, GanvEdgeFunc f, void* data); + void for_each_edge_on(const GanvNode* node, GanvEdgeFunc f, void* data); void add_item(GanvNode* i); bool remove_item(GanvNode* i); @@ -322,7 +322,7 @@ GanvCanvasImpl::selection_move_finished() } static void -select_if_tail_is_selected(GanvEdge* edge) +select_if_tail_is_selected(GanvEdge* edge, void* data) { GanvNode* tail = edge->impl->tail; gboolean selected; @@ -338,7 +338,7 @@ select_if_tail_is_selected(GanvEdge* edge) } static void -select_if_head_is_selected(GanvEdge* edge) +select_if_head_is_selected(GanvEdge* edge, void* data) { GanvNode* head = edge->impl->head; gboolean selected; @@ -359,10 +359,12 @@ select_edges(GanvPort* port, void* data) GanvCanvasImpl* impl = (GanvCanvasImpl*)data; if (port->impl->is_input) { impl->for_each_edge_to(GANV_NODE(port), - select_if_tail_is_selected); + select_if_tail_is_selected, + NULL); } else { impl->for_each_edge_from(GANV_NODE(port), - select_if_head_is_selected); + select_if_head_is_selected, + NULL); } } @@ -400,6 +402,15 @@ GanvCanvasImpl::remove_item(GanvNode* item) return ret; } +static void +select_if_ends_are_selected(GanvEdge* edge, void* data) +{ + if (ganv_node_is_selected(ganv_edge_get_tail(edge)) && + ganv_node_is_selected(ganv_edge_get_head(edge))) { + ganv_edge_select(edge); + } +} + void GanvCanvasImpl::select_item(GanvNode* m) { @@ -409,7 +420,7 @@ GanvCanvasImpl::select_item(GanvNode* m) if (GANV_IS_MODULE(m)) { ganv_module_for_each_port(GANV_MODULE(m), select_edges, this); } else { - for_each_edge_on(m, ganv_edge_select); + for_each_edge_on(m, select_if_ends_are_selected, this); } g_object_set(m, "selected", TRUE, NULL); @@ -421,10 +432,12 @@ unselect_edges(GanvPort* port, void* data) GanvCanvasImpl* impl = (GanvCanvasImpl*)data; if (port->impl->is_input) { impl->for_each_edge_to(GANV_NODE(port), - ganv_edge_unselect); + (GanvEdgeFunc)ganv_edge_unselect, + NULL); } else { impl->for_each_edge_from(GANV_NODE(port), - ganv_edge_unselect); + (GanvEdgeFunc)ganv_edge_unselect, + NULL); } } @@ -435,7 +448,7 @@ GanvCanvasImpl::unselect_item(GanvNode* m) if (GANV_IS_MODULE(m)) { ganv_module_for_each_port(GANV_MODULE(m), unselect_edges, this); } else { - for_each_edge_on(m, ganv_edge_unselect); + for_each_edge_on(m, (GanvEdgeFunc)ganv_edge_unselect, NULL); } // Unselect item @@ -1341,36 +1354,39 @@ GanvCanvasImpl::for_each_node(GanvNodeFunc f, void GanvCanvasImpl::for_each_edge_from(const GanvNode* tail, - GanvEdgeFunc f) + GanvEdgeFunc f, + void* data) { for (GanvCanvasImpl::Edges::const_iterator i = first_edge_from(tail); i != _edges.end() && (*i)->impl->tail == tail;) { GanvCanvasImpl::Edges::const_iterator next = i; ++next; - f((*i)); + f((*i), data); i = next; } } void GanvCanvasImpl::for_each_edge_to(const GanvNode* head, - GanvEdgeFunc f) + GanvEdgeFunc f, + void* data) { for (GanvCanvasImpl::Edges::const_iterator i = first_edge_to(head); i != _dst_edges.end() && (*i)->impl->head == head;) { GanvCanvasImpl::Edges::const_iterator next = i; ++next; - f((*i)); + f((*i), data); i = next; } } void GanvCanvasImpl::for_each_edge_on(const GanvNode* node, - GanvEdgeFunc f) + GanvEdgeFunc f, + void* data) { - for_each_edge_from(node, f); - for_each_edge_to(node, f); + for_each_edge_from(node, f, data); + for_each_edge_to(node, f, data); } void @@ -1506,7 +1522,7 @@ Canvas::get_edge(Node* tail, Node* head) const } void -Canvas::for_each_edge(EdgePtrFunc f, void* data) +Canvas::for_each_edge(GanvEdgeFunc f, void* data) { for (GanvCanvasImpl::Edges::iterator i = impl()->_edges.begin(); i != impl()->_edges.end();) { @@ -1520,7 +1536,7 @@ Canvas::for_each_edge(EdgePtrFunc f, void* data) } void -Canvas::for_each_selected_edge(EdgePtrFunc f, void* data) +Canvas::for_each_selected_edge(GanvEdgeFunc f, void* data) { FOREACH_EDGE(impl()->_selected_edges, i) { f((*i), data); @@ -1989,25 +2005,28 @@ ganv_canvas_for_each_selected_node(GanvCanvas* canvas, void ganv_canvas_for_each_edge_from(GanvCanvas* canvas, const GanvNode* tail, - GanvEdgeFunc f) + GanvEdgeFunc f, + void* data) { - canvas->impl->for_each_edge_from(tail, f); + canvas->impl->for_each_edge_from(tail, f, data); } void ganv_canvas_for_each_edge_to(GanvCanvas* canvas, const GanvNode* head, - GanvEdgeFunc f) + GanvEdgeFunc f, + void* data) { - canvas->impl->for_each_edge_to(head, f); + canvas->impl->for_each_edge_to(head, f, data); } void ganv_canvas_for_each_edge_on(GanvCanvas* canvas, const GanvNode* node, - GanvEdgeFunc f) + GanvEdgeFunc f, + void* data) { - canvas->impl->for_each_edge_on(node, f); + canvas->impl->for_each_edge_on(node, f, data); } GdkCursor* diff --git a/src/module.c b/src/module.c index be79d88..98e7272 100644 --- a/src/module.c +++ b/src/module.c @@ -296,7 +296,8 @@ resize_right(GanvModule* module) last_was_input = TRUE; ganv_canvas_for_each_edge_to( - canvas, pnode, ganv_edge_update_location); + canvas, pnode, + (GanvEdgeFunc)ganv_edge_update_location, NULL); } else { if (!m.horiz || !last_was_input) { y = header_height + 2.0 + (i * (h + 2.0)); @@ -307,7 +308,8 @@ resize_right(GanvModule* module) last_was_input = FALSE; ganv_canvas_for_each_edge_from( - canvas, pnode, ganv_edge_update_location); + canvas, pnode, + (GanvEdgeFunc)ganv_edge_update_location, NULL); } } @@ -365,13 +367,15 @@ resize_down(GanvModule* module) if (p->impl->is_input) { in_x = PAD + (in_count++ * (port_breadth + PAD)); ganv_node_move_to(pnode, in_x, 0); - ganv_canvas_for_each_edge_to(canvas, pnode, - ganv_edge_update_location); + ganv_canvas_for_each_edge_to( + canvas, pnode, + (GanvEdgeFunc)ganv_edge_update_location, NULL); } else { out_x = PAD + (out_count++ * (port_breadth + PAD)); ganv_node_move_to(pnode, out_x, height - ganv_box_get_height(pbox)); - ganv_canvas_for_each_edge_from(canvas, pnode, - ganv_edge_update_location); + ganv_canvas_for_each_edge_from( + canvas, pnode, + (GanvEdgeFunc)ganv_edge_update_location, NULL); } } @@ -352,7 +352,8 @@ 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_disconnect); + ganv_canvas_for_each_edge_on( + canvas, node, (GanvEdgeFunc)ganv_edge_disconnect, NULL); } } @@ -363,8 +364,8 @@ ganv_node_default_move(GanvNode* node, { GanvCanvas* canvas = GANV_CANVAS(GANV_ITEM(node)->canvas); ganv_item_move(GANV_ITEM(node), dx, dy); - ganv_canvas_for_each_edge_on(canvas, node, - ganv_edge_update_location); + ganv_canvas_for_each_edge_on( + canvas, node, (GanvEdgeFunc)ganv_edge_update_location, NULL); } @@ -380,10 +381,10 @@ ganv_node_default_move_to(GanvNode* node, NULL); if (node->impl->can_tail) { ganv_canvas_for_each_edge_from( - canvas, node, ganv_edge_update_location); + canvas, node, (GanvEdgeFunc)ganv_edge_update_location, NULL); } else if (node->impl->can_head) { ganv_canvas_for_each_edge_to( - canvas, node, ganv_edge_update_location); + canvas, node, (GanvEdgeFunc)ganv_edge_update_location, NULL); } } @@ -782,3 +783,11 @@ ganv_node_disconnect(GanvNode* node) { GANV_NODE_GET_CLASS(node)->disconnect(node); } + +gboolean +ganv_node_is_selected(GanvNode* node) +{ + gboolean selected = FALSE; + g_object_get(node, "selected", &selected, NULL); + return selected; +} @@ -64,13 +64,11 @@ ganv_port_destroy(GtkObject* object) GanvCanvas* canvas = GANV_CANVAS(item->canvas); if (canvas) { if (port->impl->is_input) { - ganv_canvas_for_each_edge_to(canvas, - &port->box.node, - ganv_edge_remove); + ganv_canvas_for_each_edge_to( + canvas, &port->box.node, (GanvEdgeFunc)ganv_edge_remove, NULL); } else { - ganv_canvas_for_each_edge_from(canvas, - &port->box.node, - ganv_edge_remove); + ganv_canvas_for_each_edge_from( + canvas, &port->box.node, (GanvEdgeFunc)ganv_edge_remove, NULL); } item->canvas = NULL; } |