summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2012-04-24 01:44:43 +0000
committerDavid Robillard <d@drobilla.net>2012-04-24 01:44:43 +0000
commit89c5346a3377a2075954acc436d3d843183ad31a (patch)
treec5d690b2a63b1a4720ccf34eea91f1b7a4b39183
parent2bae5abe2bf3068e4a36113e104168ba31928386 (diff)
downloadganv-89c5346a3377a2075954acc436d3d843183ad31a.tar.gz
ganv-89c5346a3377a2075954acc436d3d843183ad31a.tar.bz2
ganv-89c5346a3377a2075954acc436d3d843183ad31a.zip
Fix downward signal flow display (i.e. port labels disabled).
git-svn-id: http://svn.drobilla.net/lad/trunk/ganv@4260 a436a847-0d15-0410-975c-d299462d15a1
-rw-r--r--ganv/Canvas.hpp6
-rw-r--r--ganv/Module.hpp5
-rw-r--r--ganv/canvas.h16
-rw-r--r--ganv/module.h4
-rw-r--r--ganv/node.h1
-rw-r--r--ganv/port.h4
-rw-r--r--src/Canvas.cpp49
-rw-r--r--src/edge.c8
-rw-r--r--src/ganv-private.h2
-rw-r--r--src/ganv_bench.cpp1
-rw-r--r--src/module.c44
-rw-r--r--src/node.c40
-rw-r--r--src/port.c85
13 files changed, 200 insertions, 65 deletions
diff --git a/ganv/Canvas.hpp b/ganv/Canvas.hpp
index e017d70..477277d 100644
--- a/ganv/Canvas.hpp
+++ b/ganv/Canvas.hpp
@@ -111,10 +111,8 @@ public:
RW_PROPERTY(GanvDirection, direction);
- typedef void (*NodeFunction)(GanvNode* node, void* data);
-
- void for_each_node(NodeFunction f, void* data);
- void for_each_selected_node(NodeFunction f, void* data);
+ void for_each_node(GanvNodeFunction f, void* data);
+ void for_each_selected_node(GanvNodeFunction f, void* data);
typedef void (*EdgePtrFunction)(GanvEdge* edge, void* data);
diff --git a/ganv/Module.hpp b/ganv/Module.hpp
index b734ba2..9b294c9 100644
--- a/ganv/Module.hpp
+++ b/ganv/Module.hpp
@@ -43,8 +43,7 @@ public:
const std::string& name,
double x = 0,
double y = 0,
- bool show_title = true,
- bool show_port_labels = true)
+ bool show_title = true)
: Box(&canvas, GANV_BOX(
ganv_item_new(
GANV_ITEM(canvas.root()),
@@ -120,7 +119,7 @@ public:
guint num_ports() const { return ganv_module_num_ports(gobj()); }
RW_PROPERTY(gboolean, stacked)
- RW_PROPERTY(gboolean, show_port_labels)
+
METHODRET0(ganv_module, double, get_empty_port_breadth)
METHODRET0(ganv_module, double, get_empty_port_depth)
diff --git a/ganv/canvas.h b/ganv/canvas.h
index bbf6b97..352c13c 100644
--- a/ganv/canvas.h
+++ b/ganv/canvas.h
@@ -98,11 +98,27 @@ void
ganv_canvas_set_font_size(GanvCanvas* canvas, double points);
void
+ganv_canvas_set_direction(GanvCanvas* canvas, GanvDirection dir);
+
+void
ganv_canvas_clear_selection(GanvCanvas* canvas);
+typedef void (*GanvNodeFunction)(GanvNode* node, void* data);
+
typedef void (*GanvEdgeFunction)(GanvEdge* edge);
/**
+ * ganv_canvas_for_each_node:
+ * @canvas: The canvas.
+ * @f: (scope call): A function to call on every node on @canvas.
+ * @data: Data to pass to @f.
+ */
+void
+ganv_canvas_for_each_node(GanvCanvas* canvas,
+ GanvNodeFunction f,
+ void* data);
+
+/**
* ganv_canvas_for_each_edge_from:
* @canvas: The canvas.
* @tail: The tail to enumerate every edge for.
diff --git a/ganv/module.h b/ganv/module.h
index 16c5258..de36f4e 100644
--- a/ganv/module.h
+++ b/ganv/module.h
@@ -75,6 +75,10 @@ void
ganv_module_embed(GanvModule* module,
GtkWidget* widget);
+void
+ganv_module_set_direction(GanvModule* module,
+ GanvDirection direction);
+
/**
* ganv_module_for_each_port:
* @module: The module.
diff --git a/ganv/node.h b/ganv/node.h
index a18a361..9150945 100644
--- a/ganv/node.h
+++ b/ganv/node.h
@@ -134,6 +134,7 @@ GanvNode*
ganv_node_get_partner(const GanvNode* node);
void ganv_node_set_label(GanvNode* node, const char* str);
+void ganv_node_set_show_label(GanvNode* node, gboolean show);
void
ganv_node_move(GanvNode* node,
diff --git a/ganv/port.h b/ganv/port.h
index 402c67a..af5cc6b 100644
--- a/ganv/port.h
+++ b/ganv/port.h
@@ -49,6 +49,10 @@ ganv_port_new(GanvModule* module,
const char* first_prop_name, ...);
void
+ganv_port_set_direction(GanvPort* port,
+ GanvDirection direction);
+
+void
ganv_port_show_control(GanvPort* port);
void
diff --git a/src/Canvas.cpp b/src/Canvas.cpp
index c383654..f42997c 100644
--- a/src/Canvas.cpp
+++ b/src/Canvas.cpp
@@ -164,6 +164,7 @@ struct GanvCanvasImpl {
void resize(double width, double height);
+ void for_each_node(GanvNodeFunction f, void* data);
void for_each_edge_from(const GanvNode* tail, GanvEdgeFunction f);
void for_each_edge_to(const GanvNode* head, GanvEdgeFunction f);
void for_each_edge_on(const GanvNode* node, GanvEdgeFunction f);
@@ -520,9 +521,10 @@ GanvCanvasImpl::layout_dot(bool use_length_hints, const std::string& filename)
agsafeset(pnode, (char*)"shape", (char*)"box", NULL);
agsafeset(pnode, (char*)"margin", (char*)"0", NULL);
agsafeset(pnode, (char*)"pin", (char*)"true", NULL);
- agsafeset(pnode, (char*)"label",
- (char*)ganv_node_get_label(GANV_NODE(port)),
- NULL);
+ const char* port_label = ganv_node_get_label(GANV_NODE(port));
+ if (_gcanvas->direction == GANV_DIRECTION_RIGHT && port_label) {
+ agsafeset(pnode, (char*)"label", (char*)port_label, NULL);
+ }
// Fix position (we don't want ports to be arranged)
// (TODO: I don't think dot actually supports this...)
@@ -1288,6 +1290,15 @@ GanvCanvasImpl::move_contents_to_internal(double x, double y, double min_x, doub
}
void
+GanvCanvasImpl::for_each_node(GanvNodeFunction f,
+ void* data)
+{
+ FOREACH_ITEM(_items, i) {
+ f(*i, data);
+ }
+}
+
+void
GanvCanvasImpl::for_each_edge_from(const GanvNode* tail,
GanvEdgeFunction f)
{
@@ -1663,7 +1674,7 @@ Canvas::resize(double width, double height)
}
void
-Canvas::for_each_node(NodeFunction f, void* data)
+Canvas::for_each_node(GanvNodeFunction f, void* data)
{
FOREACH_ITEM(impl()->_items, i) {
f(*i, data);
@@ -1671,7 +1682,7 @@ Canvas::for_each_node(NodeFunction f, void* data)
}
void
-Canvas::for_each_selected_node(NodeFunction f, void* data)
+Canvas::for_each_selected_node(GanvNodeFunction f, void* data)
{
FOREACH_ITEM(impl()->_selected_items, i) {
f(*i, data);
@@ -1791,6 +1802,9 @@ ganv_canvas_set_property(GObject* object,
case PROP_HEIGHT:
ganv_canvas_resize(canvas, canvas->width, g_value_get_double(value));
break;
+ case PROP_DIRECTION:
+ ganv_canvas_set_direction(canvas, (GanvDirection)g_value_get_enum(value));
+ break;
case PROP_LOCKED: {
const gboolean tmp = g_value_get_boolean(value);
if (canvas->locked != tmp) {
@@ -1947,6 +1961,23 @@ ganv_canvas_set_font_size(GanvCanvas* canvas, double points)
g_object_set(canvas, "font-size", points, NULL);
}
+static void
+set_node_direction(GanvNode* node, void* data)
+{
+ if (GANV_IS_MODULE(node)) {
+ ganv_module_set_direction(GANV_MODULE(node), *(GanvDirection*)data);
+ }
+}
+
+void
+ganv_canvas_set_direction(GanvCanvas* canvas, GanvDirection dir)
+{
+ if (canvas->direction != dir) {
+ canvas->direction = dir;
+ ganv_canvas_for_each_node(canvas, set_node_direction, &dir);
+ }
+}
+
void
ganv_canvas_clear_selection(GanvCanvas* canvas)
{
@@ -2041,6 +2072,14 @@ ganv_canvas_unselect_edge(GanvCanvas* canvas,
}
void
+ganv_canvas_for_each_node(GanvCanvas* canvas,
+ GanvNodeFunction f,
+ void* data)
+{
+ canvas->impl->for_each_node(f, data);
+}
+
+void
ganv_canvas_for_each_edge_from(GanvCanvas* canvas,
const GanvNode* tail,
GanvEdgeFunction f)
diff --git a/src/edge.c b/src/edge.c
index d1586c0..2668c41 100644
--- a/src/edge.c
+++ b/src/edge.c
@@ -273,10 +273,10 @@ ganv_edge_update(GanvItem* item, int flags)
coords->handle_x = coords->x1 + (dx / 2.0);
coords->handle_y = coords->y1 + (dy / 2.0);
- coords->cx1 = coords->x1 + (coords->cx1 * (ceilf(fabs(dx)) / 4.0));
- coords->cy1 += coords->y1;
- coords->cx2 = coords->x2 + (coords->cx2 * (ceilf(fabs(dx)) / 4.0));
- coords->cy2 += coords->y2;
+ coords->cx1 = coords->x1 + (coords->cx1 * (ceilf(fabs(dx)) / 4.0));
+ coords->cy1 = coords->y1 + (coords->cy1 * (ceilf(fabs(dy)) / 4.0));
+ coords->cx2 = coords->x2 + (coords->cx2 * (ceilf(fabs(dx)) / 4.0));
+ coords->cy2 = coords->y2 + (coords->cy2 * (ceilf(fabs(dy)) / 4.0));
// Update old coordinates
impl->old_coords = impl->coords;
diff --git a/src/ganv-private.h b/src/ganv-private.h
index 35943e0..485e2f0 100644
--- a/src/ganv-private.h
+++ b/src/ganv-private.h
@@ -92,7 +92,6 @@ struct _GanvModuleImpl
int embed_height;
double widest_input;
double widest_output;
- gboolean show_port_labels;
gboolean must_resize;
};
@@ -111,6 +110,7 @@ struct _GanvNodeImpl {
gboolean selected;
gboolean highlighted;
gboolean draggable;
+ gboolean show_label;
};
/* Port */
diff --git a/src/ganv_bench.cpp b/src/ganv_bench.cpp
index c962c6a..b4bda63 100644
--- a/src/ganv_bench.cpp
+++ b/src/ganv_bench.cpp
@@ -40,7 +40,6 @@ make_module(Canvas* canvas)
Module* m(new Module(*canvas, name,
rand() % (int)canvas->get_width(),
rand() % (int)canvas->get_height(),
- true,
true));
int n_ins = rand() % MAX_NUM_PORTS;
diff --git a/src/module.c b/src/module.c
index b441d72..3dfcd13 100644
--- a/src/module.c
+++ b/src/module.c
@@ -43,7 +43,6 @@ static GanvBoxClass* parent_class;
enum {
PROP_0,
- PROP_SHOW_PORT_LABELS
};
static void
@@ -64,7 +63,6 @@ ganv_module_init(GanvModule* module)
impl->embed_height = 0;
impl->widest_input = 0.0;
impl->widest_output = 0.0;
- impl->show_port_labels = FALSE;
impl->must_resize = TRUE;
}
@@ -99,23 +97,7 @@ ganv_module_set_property(GObject* object,
g_return_if_fail(object != NULL);
g_return_if_fail(GANV_IS_MODULE(object));
- GanvModule* module = GANV_MODULE(object);
- GanvModuleImpl* impl = module->impl;
-
switch (prop_id) {
- case PROP_SHOW_PORT_LABELS: {
- const gboolean tmp = g_value_get_boolean(value);
- if (impl->show_port_labels != tmp) {
- impl->show_port_labels = tmp;
- impl->must_resize = TRUE;
- /* FIXME
- FOREACH_PORT_CONST(gobj()->ports, p) {
- (*p)->show_label(b);
- }*/
- ganv_item_request_update(GANV_ITEM(object));
- }
- break;
- }
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
break;
@@ -131,11 +113,7 @@ ganv_module_get_property(GObject* object,
g_return_if_fail(object != NULL);
g_return_if_fail(GANV_IS_MODULE(object));
- GanvModule* module = GANV_MODULE(object);
- GanvModuleImpl* impl = module->impl;
-
switch (prop_id) {
- GET_CASE(SHOW_PORT_LABELS, boolean, impl->show_port_labels);
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
break;
@@ -217,7 +195,7 @@ measure(GanvModule* module, Metrics* m)
m->input_width = impl->widest_input;
m->output_width = impl->widest_output;
double expand_w = (m->horiz ? (m->width / 2.0) : m->width) - hor_pad;
- if (impl->show_port_labels && !impl->embed_item) {
+ if (!impl->embed_item) {
m->input_width = MAX(impl->widest_input, expand_w);
m->output_width = MAX(impl->widest_output, expand_w);
}
@@ -256,25 +234,26 @@ measure(GanvModule* module, Metrics* m)
static void
place_title(GanvModule* module, GanvDirection dir)
{
- GanvBox* box = GANV_BOX(module);
+ GanvBox* box = GANV_BOX(module);
+ GanvText* canvas_title = GANV_NODE(module)->impl->label;
+ GanvModuleImpl* impl = module->impl;
double title_w, title_h;
title_size(module, &title_w, &title_h);
- GanvText* canvas_title = GANV_NODE(module)->impl->label;
- GanvModuleImpl* impl = module->impl;
-
if (!canvas_title) {
return;
} else if (dir == GANV_DIRECTION_RIGHT) {
if (impl->icon_box) {
ganv_item_set(GANV_ITEM(canvas_title),
"x", MODULE_ICON_SIZE + 1.0,
+ "y", 2.0,
NULL);
} else {
ganv_item_set(GANV_ITEM(canvas_title),
"x", ((ganv_box_get_width(box) / 2.0)
- (title_w / 2.0)),
+ "y", 2.0,
NULL);
}
} else {
@@ -878,6 +857,17 @@ ganv_module_embed(GanvModule* module,
}
void
+ganv_module_set_direction(GanvModule* module,
+ GanvDirection direction)
+{
+ FOREACH_PORT(module->impl->ports, p) {
+ ganv_port_set_direction(*p, direction);
+ }
+ module->impl->must_resize = TRUE;
+ ganv_module_resize(GANV_NODE(module));
+}
+
+void
ganv_module_for_each_port(GanvModule* module,
GanvPortFunction f,
void* data)
diff --git a/src/node.c b/src/node.c
index a8db7c4..25afd90 100644
--- a/src/node.c
+++ b/src/node.c
@@ -34,6 +34,7 @@ enum {
PROP_CANVAS,
PROP_PARTNER,
PROP_LABEL,
+ PROP_SHOW_LABEL,
PROP_DASH_LENGTH,
PROP_DASH_OFFSET,
PROP_BORDER_WIDTH,
@@ -66,6 +67,7 @@ ganv_node_init(GanvNode* node)
impl->selected = FALSE;
impl->highlighted = FALSE;
impl->draggable = FALSE;
+ impl->show_label = TRUE;
}
static void
@@ -151,7 +153,9 @@ ganv_node_set_property(GObject* object,
break;
case PROP_LABEL:
ganv_node_set_label(node, g_value_get_string(value));
- ganv_item_request_update(GANV_ITEM(object));
+ break;
+ case PROP_SHOW_LABEL:
+ ganv_node_set_show_label(node, g_value_get_boolean(value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
@@ -259,7 +263,7 @@ void
ganv_node_set_label(GanvNode* node, const char* str)
{
GanvNodeImpl* impl = node->impl;
- if (str[0] == '\0' || !str) {
+ if (!str || str[0] == '\0') {
if (impl->label) {
gtk_object_destroy(GTK_OBJECT(impl->label));
impl->label = NULL;
@@ -276,10 +280,28 @@ ganv_node_set_label(GanvNode* node, const char* str)
NULL));
}
- GanvNodeClass* klass = GANV_NODE_GET_CLASS(node);
- if (klass->resize) {
- klass->resize(node);
+ if (impl->show_label) {
+ GanvNodeClass* klass = GANV_NODE_GET_CLASS(node);
+ if (klass->resize) {
+ klass->resize(node);
+ }
+
+ ganv_item_request_update(GANV_ITEM(node));
+ }
+}
+
+void
+ganv_node_set_show_label(GanvNode* node, gboolean show)
+{
+ if (node->impl->label) {
+ if (show) {
+ ganv_item_show(GANV_ITEM(node->impl->label));
+ } else {
+ ganv_item_hide(GANV_ITEM(node->impl->label));
+ }
}
+ node->impl->show_label = show;
+ ganv_item_request_update(GANV_ITEM(node));
}
static void
@@ -496,6 +518,14 @@ ganv_node_class_init(GanvNodeClass* class)
G_PARAM_READWRITE));
g_object_class_install_property(
+ gobject_class, PROP_SHOW_LABEL, g_param_spec_boolean(
+ "show-label",
+ _("Show label"),
+ _("Whether or not to show the label."),
+ 0,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property(
gobject_class, PROP_DASH_LENGTH, g_param_spec_double(
"dash-length",
_("Border dash length"),
diff --git a/src/port.c b/src/port.c
index 6ce37d0..5e9d13e 100644
--- a/src/port.c
+++ b/src/port.c
@@ -137,7 +137,10 @@ ganv_port_draw(GanvItem* item,
GanvNode* node = GANV_NODE(item);
if (node->impl->label) {
GanvItem* label_item = GANV_ITEM(node->impl->label);
- GANV_ITEM_GET_CLASS(label_item)->draw(label_item, cr, cx, cy, width, height);
+ if (label_item->object.flags & GANV_ITEM_VISIBLE) {
+ GANV_ITEM_GET_CLASS(label_item)->draw(
+ label_item, cr, cx, cy, width, height);
+ }
}
}
@@ -149,15 +152,26 @@ ganv_port_tail_vector(const GanvNode* self,
double* dx,
double* dy)
{
- GanvPort* port = GANV_PORT(self);
+ GanvPort* port = GANV_PORT(self);
+ GanvCanvas* canvas = GANV_CANVAS(GANV_ITEM(self)->canvas);
double px, py;
g_object_get(G_OBJECT(self), "x", &px, "y", &py, NULL);
- *x = px + ganv_box_get_width(&port->box);
- *y = py + ganv_box_get_height(&port->box) / 2.0;
- *dx = 1.0;
- *dy = 0.0;
+ switch (canvas->direction) {
+ case GANV_DIRECTION_RIGHT:
+ *x = px + ganv_box_get_width(&port->box);
+ *y = py + ganv_box_get_height(&port->box) / 2.0;
+ *dx = 1.0;
+ *dy = 0.0;
+ break;
+ case GANV_DIRECTION_DOWN:
+ *x = px + ganv_box_get_width(&port->box) / 2.0;
+ *y = py + ganv_box_get_height(&port->box);
+ *dx = 0.0;
+ *dy = 1.0;
+ break;
+ }
ganv_item_i2w(GANV_ITEM(self)->parent, x, y);
}
@@ -170,15 +184,26 @@ ganv_port_head_vector(const GanvNode* self,
double* dx,
double* dy)
{
- GanvPort* port = GANV_PORT(self);
+ GanvPort* port = GANV_PORT(self);
+ GanvCanvas* canvas = GANV_CANVAS(GANV_ITEM(self)->canvas);
double px, py;
g_object_get(G_OBJECT(self), "x", &px, "y", &py, NULL);
- *x = px;
- *y = py + ganv_box_get_height(&port->box) / 2.0;
- *dx = -1.0;
- *dy = 0.0;
+ switch (canvas->direction) {
+ case GANV_DIRECTION_RIGHT:
+ *x = px;
+ *y = py + ganv_box_get_height(&port->box) / 2.0;
+ *dx = -1.0;
+ *dy = 0.0;
+ break;
+ case GANV_DIRECTION_DOWN:
+ *x = px + ganv_box_get_width(&port->box) / 2.0;
+ *y = 0.0;
+ *dx = 0.0;
+ *dy = -1.0;
+ break;
+ }
ganv_item_i2w(GANV_ITEM(self)->parent, x, y);
}
@@ -186,10 +211,11 @@ ganv_port_head_vector(const GanvNode* self,
static void
ganv_port_resize(GanvNode* self)
{
- GanvPort* port = GANV_PORT(self);
- GanvNode* node = GANV_NODE(self);
+ GanvPort* port = GANV_PORT(self);
+ GanvNode* node = GANV_NODE(self);
+ GanvText* label = node->impl->label;
- if (node->impl->label) {
+ if (label && GANV_ITEM(label)->object.flags & GANV_ITEM_VISIBLE) {
double label_w, label_h;
g_object_get(node->impl->label,
"width", &label_w,
@@ -323,10 +349,38 @@ ganv_port_new(GanvModule* module,
node->impl->draggable = FALSE;
node->impl->border_width = 1.0;
+ GanvCanvas* canvas = GANV_CANVAS(GANV_ITEM(port)->canvas);
+ ganv_port_set_direction(port, canvas->direction);
+
return port;
}
void
+ganv_port_set_direction(GanvPort* port,
+ GanvDirection direction)
+{
+ GanvNode* node = GANV_NODE(port);
+ GanvBox* box = GANV_BOX(port);
+ gboolean is_input = port->impl->is_input;
+ switch (direction) {
+ case GANV_DIRECTION_RIGHT:
+ box->impl->radius_tl = (is_input ? 0.0 : 4.0);
+ box->impl->radius_tr = (is_input ? 4.0 : 0.0);
+ box->impl->radius_br = (is_input ? 4.0 : 0.0);
+ box->impl->radius_bl = (is_input ? 0.0 : 4.0);
+ break;
+ case GANV_DIRECTION_DOWN:
+ box->impl->radius_tl = (is_input ? 0.0 : 4.0);
+ box->impl->radius_tr = (is_input ? 0.0 : 4.0);
+ box->impl->radius_br = (is_input ? 4.0 : 0.0);
+ box->impl->radius_bl = (is_input ? 4.0 : 0.0);
+ break;
+ }
+ ganv_node_set_show_label(node, direction == GANV_DIRECTION_RIGHT);
+ ganv_node_resize(node);
+}
+
+void
ganv_port_show_control(GanvPort* port)
{
GanvPortControl* control = (GanvPortControl*)malloc(sizeof(GanvPortControl));
@@ -450,9 +504,10 @@ double
ganv_port_get_natural_width(const GanvPort* port)
{
GanvCanvas* const canvas = GANV_CANVAS(GANV_ITEM(port)->canvas);
+ GanvText* const label = port->box.node.impl->label;
if (canvas->direction == GANV_DIRECTION_DOWN) {
return ganv_module_get_empty_port_breadth(ganv_port_get_module(port));
- } else if (port->box.node.impl->label) {
+ } else if (label && (GANV_ITEM(label)->object.flags & GANV_ITEM_VISIBLE)) {
double label_w;
g_object_get(port->box.node.impl->label, "width", &label_w, NULL);
return label_w + (PORT_LABEL_HPAD * 2.0);