From 9ce9a936d4150e51b77bf1ab89263afbcc729a7e Mon Sep 17 00:00:00 2001 From: David Robillard Date: Wed, 7 Dec 2011 03:48:34 +0000 Subject: Support creating modules via pure GObject construction. git-svn-id: http://svn.drobilla.net/lad/trunk/ganv@3826 a436a847-0d15-0410-975c-d299462d15a1 --- ganv/module.h | 3 +++ ganv/text.h | 1 + src/Canvas.cpp | 2 +- src/boilerplate.h | 5 ++++- src/ganv_test.py | 3 ++- src/module.c | 36 ++++++++++++++++++++++-------------- src/node.c | 49 +++++++++++++++++++++++++++++++++++++------------ src/text.c | 35 +++++++++++++++++++++++------------ 8 files changed, 93 insertions(+), 41 deletions(-) diff --git a/ganv/module.h b/ganv/module.h index e4b4e79..3bf6192 100644 --- a/ganv/module.h +++ b/ganv/module.h @@ -59,6 +59,9 @@ GanvModule* ganv_module_new(GanvCanvas* canvas, const char* first_prop_name, ...); +guint +ganv_module_num_ports(const GanvModule* module); + void ganv_module_add_port(GanvModule* module, GanvPort* port); diff --git a/ganv/text.h b/ganv/text.h index 0fc7ca0..5d0d464 100644 --- a/ganv/text.h +++ b/ganv/text.h @@ -48,6 +48,7 @@ struct _GanvText GanvTextCoords coords; GanvTextCoords old_coords; guint color; + gboolean needs_layout; }; struct _GanvTextClass { diff --git a/src/Canvas.cpp b/src/Canvas.cpp index 2faf2a5..841c3cf 100644 --- a/src/Canvas.cpp +++ b/src/Canvas.cpp @@ -379,7 +379,7 @@ GanvCanvasImpl::remove_item(GanvNode* item) // Remove children ports from selection if item is a module if (GANV_IS_MODULE(item)) { GanvModule* const module = GANV_MODULE(item); - for (unsigned i = 0; i < module->ports->len; ++i) { + for (unsigned i = 0; i < ganv_module_num_ports(module); ++i) { unselect_port((GanvPort*)g_ptr_array_index( module->ports, i)); } diff --git a/src/boilerplate.h b/src/boilerplate.h index 73a0cd5..a893eb1 100644 --- a/src/boilerplate.h +++ b/src/boilerplate.h @@ -26,7 +26,10 @@ typedef gpointer gobject; const g##type tmp = g_value_get_##type(value); \ if (field != tmp) { \ field = tmp; \ - gnome_canvas_item_request_update(GNOME_CANVAS_ITEM(object)); \ + GnomeCanvasItem* item = GNOME_CANVAS_ITEM(object); \ + if (item->canvas) { \ + gnome_canvas_item_request_update(item); \ + } \ } \ break; \ } diff --git a/src/ganv_test.py b/src/ganv_test.py index 1d08ba4..8ba784d 100755 --- a/src/ganv_test.py +++ b/src/ganv_test.py @@ -7,7 +7,8 @@ win.set_title("Ganv Python Test") win.connect("destroy", lambda obj: Gtk.main_quit()) canvas = Ganv.Canvas.new(1024, 768) - +module = Ganv.Module(canvas=canvas, + label="Test") win.add(canvas) win.show_all() win.present() diff --git a/src/module.c b/src/module.c index acb0a6d..994c229 100644 --- a/src/module.c +++ b/src/module.c @@ -67,11 +67,14 @@ ganv_module_destroy(GtkObject* object) g_return_if_fail(object != NULL); g_return_if_fail(GANV_IS_MODULE(object)); - g_ptr_array_free(GANV_MODULE(object)->ports, TRUE); - GanvModule* module = GANV_MODULE(object); - FOREACH_PORT(module->ports, p) { - gtk_object_destroy(GTK_OBJECT(*p)); + + if (module->ports) { + FOREACH_PORT(module->ports, p) { + gtk_object_destroy(GTK_OBJECT(*p)); + } + g_ptr_array_free(module->ports, TRUE); + module->ports = NULL; } if (GTK_OBJECT_CLASS(parent_class)->destroy) { @@ -285,6 +288,9 @@ resize_horiz(GanvModule* module) double title_w, title_h; title_size(module, &title_w, &title_h); + printf("MEASURED: %lf\n", m.width); + printf("TITLE W: %lf\n", title_w); + // Basic height contains title, icon double header_height = 2.0 + title_h; @@ -534,7 +540,7 @@ ganv_module_class_init(GanvModuleClass* class) GObjectClass* gobject_class = (GObjectClass*)class; GtkObjectClass* object_class = (GtkObjectClass*)class; GnomeCanvasItemClass* item_class = (GnomeCanvasItemClass*)class; - GanvNodeClass* node_class = (GanvNodeClass*)class; + GanvNodeClass* node_class = (GanvNodeClass*)class; parent_class = GANV_BOX_CLASS(g_type_class_peek_parent(class)); @@ -552,23 +558,25 @@ ganv_module_class_init(GanvModuleClass* class) GanvModule* ganv_module_new(GanvCanvas* canvas, - const char* first_prop_name, ...) + const char* first_property_name, ...) { GanvModule* module = GANV_MODULE( - g_object_new(ganv_module_get_type(), NULL)); + g_object_new(ganv_module_get_type(), "canvas", canvas, NULL)); - GnomeCanvasItem* item = GNOME_CANVAS_ITEM(module); va_list args; - va_start(args, first_prop_name); - gnome_canvas_item_construct(item, - gnome_canvas_root(GNOME_CANVAS(canvas)), - first_prop_name, args); + va_start(args, first_property_name); + g_object_set_valist(G_OBJECT(module), first_property_name, args); va_end(args); - ganv_canvas_add_node(canvas, GANV_NODE(module)); return module; } +guint +ganv_module_num_ports(const GanvModule* module) +{ + return module->ports ? module->ports->len : 0; +} + void ganv_module_add_port(GanvModule* module, GanvPort* port) @@ -635,7 +643,7 @@ ganv_module_add_port(GanvModule* module, GNOME_CANVAS_ITEM(module)->canvas); place_title(module, canvas->direction); - + gnome_canvas_item_request_update(GNOME_CANVAS_ITEM(module)); } void diff --git a/src/node.c b/src/node.c index b121f41..87dc482 100644 --- a/src/node.c +++ b/src/node.c @@ -29,6 +29,7 @@ static GnomeCanvasGroupClass* parent_class; enum { PROP_0, + PROP_CANVAS, PROP_PARTNER, PROP_LABEL, PROP_DASH_LENGTH, @@ -93,6 +94,7 @@ ganv_node_destroy(GtkObject* object) ganv_node_disconnect(node); if (item->canvas) { ganv_canvas_remove_node(GANV_CANVAS(item->canvas), node); + item->canvas = NULL; } node->partner = NULL; @@ -111,7 +113,8 @@ ganv_node_set_property(GObject* object, g_return_if_fail(object != NULL); g_return_if_fail(GANV_IS_NODE(object)); - GanvNode* node = GANV_NODE(object); + GanvNode* node = GANV_NODE(object); + GnomeCanvasItem* item = GNOME_CANVAS_ITEM(object); switch (prop_id) { SET_CASE(PARTNER, object, node->partner); @@ -120,13 +123,23 @@ ganv_node_set_property(GObject* object, SET_CASE(BORDER_WIDTH, double, node->border_width); SET_CASE(FILL_COLOR, uint, node->fill_color); SET_CASE(BORDER_COLOR, uint, node->border_color); - SET_CASE(CAN_TAIL, boolean, node->can_tail) - SET_CASE(CAN_HEAD, boolean, node->can_head) - SET_CASE(SELECTED, boolean, node->selected) - SET_CASE(HIGHLIGHTED, boolean, node->highlighted) - SET_CASE(DRAGGABLE, boolean, node->draggable) + SET_CASE(CAN_TAIL, boolean, node->can_tail); + SET_CASE(CAN_HEAD, boolean, node->can_head); + SET_CASE(SELECTED, boolean, node->selected); + SET_CASE(HIGHLIGHTED, boolean, node->highlighted); + SET_CASE(DRAGGABLE, boolean, node->draggable); + case PROP_CANVAS: + if (!item->parent) { + GnomeCanvas* canvas = GNOME_CANVAS(g_value_get_object(value)); + g_object_set(object, "parent", gnome_canvas_root(canvas), NULL); + ganv_canvas_add_node(GANV_CANVAS(canvas), node); + } else { + g_warning("Cannot change `canvas' property after construction"); + } + break; case PROP_LABEL: ganv_node_set_label(node, g_value_get_string(value)); + gnome_canvas_item_request_update(GNOME_CANVAS_ITEM(object)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); @@ -143,7 +156,8 @@ ganv_node_get_property(GObject* object, g_return_if_fail(object != NULL); g_return_if_fail(GANV_IS_NODE(object)); - GanvNode* node = GANV_NODE(object); + GanvNode* node = GANV_NODE(object); + GnomeCanvasItem* item = GNOME_CANVAS_ITEM(object); typedef char* gstring; @@ -155,11 +169,14 @@ ganv_node_get_property(GObject* object, GET_CASE(BORDER_WIDTH, double, node->border_width); GET_CASE(FILL_COLOR, uint, node->fill_color); GET_CASE(BORDER_COLOR, uint, node->border_color); - GET_CASE(CAN_TAIL, boolean, node->can_tail) - GET_CASE(CAN_HEAD, boolean, node->can_head) - GET_CASE(SELECTED, boolean, node->selected) - GET_CASE(HIGHLIGHTED, boolean, node->highlighted) - GET_CASE(DRAGGABLE, boolean, node->draggable) + GET_CASE(CAN_TAIL, boolean, node->can_tail); + GET_CASE(CAN_HEAD, boolean, node->can_head); + GET_CASE(SELECTED, boolean, node->selected); + GET_CASE(HIGHLIGHTED, boolean, node->highlighted); + GET_CASE(DRAGGABLE, boolean, node->draggable); + case PROP_CANVAS: + g_value_set_object(value, item->canvas); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; @@ -424,6 +441,14 @@ ganv_node_class_init(GanvNodeClass* class) gobject_class->set_property = ganv_node_set_property; gobject_class->get_property = ganv_node_get_property; + g_object_class_install_property( + gobject_class, PROP_CANVAS, g_param_spec_object( + "canvas", + _("canvas"), + _("the canvas this node is on."), + GANV_TYPE_CANVAS, + G_PARAM_READWRITE)); + g_object_class_install_property( gobject_class, PROP_PARTNER, g_param_spec_object( "partner", diff --git a/src/text.c b/src/text.c index 0e2985e..0b1def7 100644 --- a/src/text.c +++ b/src/text.c @@ -49,9 +49,10 @@ ganv_text_init(GanvText* text) text->coords.height = 1.0; text->old_coords = text->coords; - text->surface = NULL; - text->text = NULL; - text->color = 0xFFFFFFFF; + text->surface = NULL; + text->text = NULL; + text->color = 0xFFFFFFFF; + text->needs_layout = FALSE; } static void @@ -80,11 +81,11 @@ ganv_text_destroy(GtkObject* object) static void ganv_text_layout(GanvText* text) { - GnomeCanvasItem* item = GNOME_CANVAS_ITEM(text); - GanvCanvas* canvas = GANV_CANVAS(item->canvas); - GtkWidget* widget = GTK_WIDGET(canvas); - double font_size = ganv_canvas_get_font_size(canvas); - guint color = 0xFFFFFFFF; + GnomeCanvasItem* item = GNOME_CANVAS_ITEM(text); + GanvCanvas* canvas = GANV_CANVAS(item->canvas); + GtkWidget* widget = GTK_WIDGET(canvas); + double font_size = ganv_canvas_get_font_size(canvas); + guint color = 0xFFFFFFFF; GtkStyle* style = gtk_rc_get_style(widget); PangoFontDescription* font = pango_font_description_copy(style->font_desc); @@ -129,6 +130,7 @@ ganv_text_layout(GanvText* text) g_object_unref(layout); pango_font_description_free(font); + text->needs_layout = FALSE; gnome_canvas_item_request_update(GNOME_CANVAS_ITEM(text)); } @@ -152,7 +154,7 @@ ganv_text_set_property(GObject* object, case PROP_TEXT: free(text->text); text->text = g_value_dup_string(value); - ganv_text_layout(text); + text->needs_layout = TRUE; break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); @@ -171,13 +173,18 @@ ganv_text_get_property(GObject* object, GanvText* text = GANV_TEXT(object); + if (text->needs_layout && (prop_id == PROP_WIDTH + || prop_id == PROP_HEIGHT)) { + ganv_text_layout(text); + } + switch (prop_id) { - GET_CASE(TEXT, string, text->text) - GET_CASE(X, double, text->coords.x); + GET_CASE(TEXT, string, text->text); + GET_CASE(X, double, text->coords.x); GET_CASE(Y, double, text->coords.y); GET_CASE(WIDTH, double, text->coords.width); GET_CASE(HEIGHT, double, text->coords.height); - GET_CASE(COLOR, uint, text->color) + GET_CASE(COLOR, uint, text->color); default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; @@ -191,6 +198,10 @@ ganv_text_bounds_item(GnomeCanvasItem* item, { GanvText* text = GANV_TEXT(item); + if (text->needs_layout) { + ganv_text_layout(text); + } + *x1 = MIN(text->coords.x, text->coords.x + text->coords.width); *y1 = MIN(text->coords.y, text->coords.y + text->coords.height); *x2 = MAX(text->coords.x, text->coords.x + text->coords.width); -- cgit v1.2.1