summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ganv/Canvas.hpp21
-rw-r--r--ganv/canvas.h27
-rw-r--r--ganv/node.h3
-rw-r--r--ganv/wrap.hpp5
-rw-r--r--src/Canvas.cpp71
-rw-r--r--src/module.c16
-rw-r--r--src/node.c19
-rw-r--r--src/port.c10
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);
}
}
diff --git a/src/node.c b/src/node.c
index 5886dba..f49f688 100644
--- a/src/node.c
+++ b/src/node.c
@@ -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;
+}
diff --git a/src/port.c b/src/port.c
index f2594a2..e134e55 100644
--- a/src/port.c
+++ b/src/port.c
@@ -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;
}