summaryrefslogtreecommitdiffstats
path: root/src/module.c
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2015-02-21 23:32:24 +0000
committerDavid Robillard <d@drobilla.net>2015-02-21 23:32:24 +0000
commitef71a1da33a3c68cad782029cacbc1d01328b4d6 (patch)
treef5bb6f29c467bf91c0ab8ca5072a81408522a311 /src/module.c
parent23682cbf1f98f35d4341efe354bee6f770d482e2 (diff)
downloadganv-ef71a1da33a3c68cad782029cacbc1d01328b4d6.tar.gz
ganv-ef71a1da33a3c68cad782029cacbc1d01328b4d6.tar.bz2
ganv-ef71a1da33a3c68cad782029cacbc1d01328b4d6.zip
Add API to specify module port order.
Also fix various redundant resize/update issues, improve performance. git-svn-id: http://svn.drobilla.net/lad/trunk/ganv@5592 a436a847-0d15-0410-975c-d299462d15a1
Diffstat (limited to 'src/module.c')
-rw-r--r--src/module.c123
1 files changed, 68 insertions, 55 deletions
diff --git a/src/module.c b/src/module.c
index 550ee48..46cdfff 100644
--- a/src/module.c
+++ b/src/module.c
@@ -63,7 +63,7 @@ ganv_module_init(GanvModule* module)
impl->embed_height = 0;
impl->widest_input = 0.0;
impl->widest_output = 0.0;
- impl->must_resize = TRUE;
+ impl->must_reorder = FALSE;
}
static void
@@ -256,16 +256,15 @@ place_title(GanvModule* module, GanvDirection dir)
if (!canvas_title) {
return;
- } else if (dir == GANV_DIRECTION_RIGHT) {
- ganv_item_set(GANV_ITEM(canvas_title),
- "x", (ganv_box_get_width(box) - title_w) / 2.0,
- "y", 1.0,
- NULL);
+ }
+
+ GanvItem* t = GANV_ITEM(canvas_title);
+ if (dir == GANV_DIRECTION_RIGHT) {
+ t->impl->x = (ganv_box_get_width(box) - title_w) / 2.0;
+ t->impl->y = 1.0;
} else {
- ganv_item_set(GANV_ITEM(canvas_title),
- "x", (ganv_box_get_width(box) - title_w) / 2.0,
- "y", ganv_module_get_empty_port_depth(module) + 1.0,
- NULL);
+ t->impl->x = (ganv_box_get_width(box) - title_w) / 2.0;
+ t->impl->y = ganv_module_get_empty_port_depth(module) + 1.0;
}
}
@@ -392,7 +391,7 @@ resize_down(GanvModule* module)
// Offset to shift ports to make borders line up
const double border_off = (GANV_NODE(module)->impl->border_width -
pnode->impl->border_width) / 2.0;
-
+
if (p->impl->is_input) {
in_x = EDGE_PAD + (in_count++ * (port_breadth + PAD + 1.0));
ganv_node_move_to(pnode, in_x, -border_off);
@@ -436,12 +435,11 @@ measure_ports(GanvModule* module)
}
static void
-layout(GanvNode* self)
+ganv_module_resize(GanvNode* self)
{
- GanvModule* module = GANV_MODULE(self);
- GanvModuleImpl* impl = module->impl;
- GanvNode* node = GANV_NODE(self);
- GanvCanvas* canvas = ganv_item_get_canvas(GANV_ITEM(module));
+ GanvModule* module = GANV_MODULE(self);
+ GanvNode* node = GANV_NODE(self);
+ GanvCanvas* canvas = ganv_item_get_canvas(GANV_ITEM(module));
double label_w = 0.0;
double label_h = 0.0;
@@ -466,16 +464,8 @@ layout(GanvNode* self)
break;
}
- impl->must_resize = FALSE;
-}
-
-static void
-ganv_module_resize(GanvNode* self)
-{
- layout(self);
-
- if (parent_class->parent_class.resize) {
- parent_class->parent_class.resize(self);
+ if (GANV_NODE_CLASS(parent_class)->resize) {
+ GANV_NODE_CLASS(parent_class)->resize(self);
}
}
@@ -495,9 +485,9 @@ static void
ganv_module_add_port(GanvModule* module,
GanvPort* port)
{
- GanvCanvas* canvas = ganv_item_get_canvas(GANV_ITEM(module));
- GanvModuleImpl* impl = module->impl;
+ GanvModuleImpl* impl = module->impl;
+ // Update widest input/output measurements if necessary
const double width = ganv_port_get_natural_width(port);
if (port->impl->is_input && width > impl->widest_input) {
impl->widest_input = width;
@@ -505,11 +495,12 @@ ganv_module_add_port(GanvModule* module,
impl->widest_output = width;
}
- impl->must_resize = TRUE;
-
+ // Add to port array
g_ptr_array_add(impl->ports, port);
- place_title(module, ganv_canvas_get_direction(canvas));
- ganv_item_request_update(GANV_ITEM(module));
+
+ // Request update with resize and reorder
+ GANV_NODE(module)->impl->must_resize = TRUE;
+ impl->must_reorder = TRUE;
}
static void
@@ -540,8 +531,7 @@ ganv_module_remove_port(GanvModule* module,
}
}
- module->impl->must_resize = TRUE;
- ganv_item_request_update(GANV_ITEM(module));
+ GANV_NODE(module)->impl->must_resize = TRUE;
} else {
fprintf(stderr, "Failed to find port to remove\n");
}
@@ -553,6 +543,10 @@ ganv_module_add(GanvItem* item, GanvItem* child)
if (GANV_IS_PORT(child)) {
ganv_module_add_port(GANV_MODULE(item), GANV_PORT(child));
}
+ ganv_item_request_update(item);
+ if (GANV_ITEM_CLASS(parent_class)->add) {
+ GANV_ITEM_CLASS(parent_class)->add(item, child);
+ }
}
static void
@@ -561,16 +555,34 @@ ganv_module_remove(GanvItem* item, GanvItem* child)
if (GANV_IS_PORT(child)) {
ganv_module_remove_port(GANV_MODULE(item), GANV_PORT(child));
}
+ ganv_item_request_update(item);
+ if (GANV_ITEM_CLASS(parent_class)->remove) {
+ GANV_ITEM_CLASS(parent_class)->remove(item, child);
+ }
+}
+
+static int
+ptr_sort(const GanvPort** a, const GanvPort** b, const PortOrderCtx* ctx)
+{
+ return ctx->port_cmp(*a, *b, ctx->data);
}
static void
ganv_module_update(GanvItem* item, int flags)
{
- GanvNode* node = GANV_NODE(item);
GanvModule* module = GANV_MODULE(item);
+ GanvCanvas* canvas = ganv_item_get_canvas(item);
+
+ if (module->impl->must_reorder) {
+ // Sort ports array
+ PortOrderCtx ctx = ganv_canvas_get_port_order(canvas);
+ if (ctx.port_cmp) {
+ g_ptr_array_sort_with_data(module->impl->ports,
+ (GCompareDataFunc)ptr_sort,
- if (module->impl->must_resize) {
- layout(node);
+ &ctx);
+ }
+ module->impl->must_reorder = FALSE;
}
if (module->impl->embed_item) {
@@ -578,9 +590,6 @@ ganv_module_update(GanvItem* item, int flags)
ganv_item_move(GANV_ITEM(module->impl->embed_item), 0.0, 0.0);
}
- GanvItemClass* item_class = GANV_ITEM_CLASS(parent_class);
- item_class->update(item, flags);
-
FOREACH_PORT(module->impl->ports, p) {
ganv_item_invoke_update(GANV_ITEM(*p), flags);
}
@@ -588,6 +597,8 @@ ganv_module_update(GanvItem* item, int flags)
if (module->impl->embed_item) {
ganv_item_invoke_update(GANV_ITEM(module->impl->embed_item), flags);
}
+
+ GANV_ITEM_CLASS(parent_class)->update(item, flags);
}
static void
@@ -763,10 +774,9 @@ on_embed_size_request(GtkWidget* widget,
return;
}
- impl->embed_width = r->width;
- impl->embed_height = r->height;
-
- impl->must_resize = TRUE;
+ impl->embed_width = r->width;
+ impl->embed_height = r->height;
+ GANV_NODE(module)->impl->must_resize = TRUE;
GtkAllocation allocation;
allocation.width = r->width;
@@ -784,43 +794,46 @@ ganv_module_embed(GanvModule* module,
GtkWidget* widget)
{
GanvModuleImpl* impl = module->impl;
+ if (!widget && !impl->embed_item) {
+ return;
+ }
if (impl->embed_item) {
+ // Free existing embedded widget
gtk_object_destroy(GTK_OBJECT(impl->embed_item));
impl->embed_item = NULL;
}
if (!widget) {
- impl->embed_width = 0;
- impl->embed_height = 0;
- impl->must_resize = TRUE;
+ // Removing an existing embedded widget
+ impl->embed_width = 0;
+ impl->embed_height = 0;
+ GANV_NODE(module)->impl->must_resize = TRUE;
+ ganv_item_request_update(GANV_ITEM(module));
return;
}
double title_w, title_h;
title_size(module, &title_w, &title_h);
- const double y = 4.0 + title_h;
impl->embed_item = ganv_item_new(
GANV_ITEM(module),
ganv_widget_get_type(),
"x", 2.0,
- "y", y,
+ "y", 4.0 + title_h,
"widget", widget,
NULL);
- gtk_widget_show_all(widget);
-
GtkRequisition r;
+ gtk_widget_show_all(widget);
gtk_widget_size_request(widget, &r);
on_embed_size_request(widget, &r, module);
-
ganv_item_show(impl->embed_item);
g_signal_connect(widget, "size-request",
G_CALLBACK(on_embed_size_request), module);
- layout(GANV_NODE(module));
+ GANV_NODE(module)->impl->must_resize = TRUE;
ganv_item_request_update(GANV_ITEM(module));
}
@@ -831,8 +844,8 @@ ganv_module_set_direction(GanvModule* module,
FOREACH_PORT(module->impl->ports, p) {
ganv_port_set_direction(*p, direction);
}
- module->impl->must_resize = TRUE;
- ganv_module_resize(GANV_NODE(module));
+ GANV_NODE(module)->impl->must_resize = TRUE;
+ ganv_item_request_update(GANV_ITEM(module));
}
void