From d961d48c953429d630ce33e09bf214e673151339 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Sun, 13 Jan 2013 23:43:56 +0000 Subject: Support resizing circles to fit label, and setting radius in ems. git-svn-id: http://svn.drobilla.net/lad/trunk/ganv@4969 a436a847-0d15-0410-975c-d299462d15a1 --- ganv/Circle.hpp | 7 ++--- src/circle.c | 84 +++++++++++++++++++++++++++++++++++++++++++++++++----- src/ganv-private.h | 3 +- src/ganv_bench.cpp | 4 +-- src/module.c | 3 +- src/node.c | 1 - 6 files changed, 84 insertions(+), 18 deletions(-) diff --git a/ganv/Circle.hpp b/ganv/Circle.hpp index 721b153..1ba9ae6 100644 --- a/ganv/Circle.hpp +++ b/ganv/Circle.hpp @@ -49,9 +49,7 @@ public: Circle(Canvas& canvas, const std::string& name, double x, - double y, - double radius, - bool show_title) + double y) : Node(&canvas, GANV_NODE( ganv_item_new( @@ -61,7 +59,6 @@ public: "y", y, "can-tail", TRUE, "can-head", TRUE, - "radius", radius, "fill-color", FILL_COLOUR, "border-color", BORDER_COLOUR, "label", name.c_str(), @@ -70,6 +67,8 @@ public: {} RW_PROPERTY(double, radius); + RW_PROPERTY(double, radius_ems); + RW_PROPERTY(gboolean, fit_label); GanvCircle* gobj() { return GANV_CIRCLE(_gobj); } const GanvCircle* gobj() const { return GANV_CIRCLE(_gobj); } diff --git a/src/circle.c b/src/circle.c index eb43166..a912214 100644 --- a/src/circle.c +++ b/src/circle.c @@ -16,6 +16,7 @@ #include #include +#include "ganv/canvas.h" #include "ganv/canvas-base.h" #include "ganv/circle.h" @@ -30,7 +31,9 @@ static GanvNodeClass* parent_class; enum { PROP_0, - PROP_RADIUS + PROP_RADIUS, + PROP_RADIUS_EMS, + PROP_FIT_LABEL }; static void @@ -40,9 +43,11 @@ ganv_circle_init(GanvCircle* circle) circle, GANV_TYPE_CIRCLE, GanvCircleImpl); memset(&circle->impl->coords, '\0', sizeof(GanvCircleCoords)); - circle->impl->coords.radius = 8.0; - circle->impl->coords.width = 2.0; - circle->impl->old_coords = circle->impl->coords; + circle->impl->coords.radius = 0.0; + circle->impl->coords.radius_ems = 1.0; + circle->impl->coords.width = 2.0; + circle->impl->old_coords = circle->impl->coords; + circle->impl->fit_label = TRUE; } static void @@ -56,6 +61,15 @@ ganv_circle_destroy(GtkObject* object) } } +static void +set_radius_ems(GanvCircle* circle, + double ems) +{ + GanvCanvas* canvas = GANV_CANVAS(GANV_ITEM(circle)->canvas); + const double points = ganv_canvas_get_font_size(canvas); + circle->impl->coords.radius = points * ems; +} + static void ganv_circle_set_property(GObject* object, guint prop_id, @@ -69,10 +83,16 @@ ganv_circle_set_property(GObject* object, switch (prop_id) { SET_CASE(RADIUS, double, circle->impl->coords.radius); + SET_CASE(RADIUS_EMS, double, circle->impl->coords.radius_ems); + SET_CASE(FIT_LABEL, boolean, circle->impl->fit_label); default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } + + if (prop_id == PROP_RADIUS_EMS) { + set_radius_ems(circle, circle->impl->coords.radius_ems); + } } static void @@ -88,6 +108,8 @@ ganv_circle_get_property(GObject* object, switch (prop_id) { GET_CASE(RADIUS, double, circle->impl->coords.radius); + GET_CASE(RADIUS_EMS, double, circle->impl->coords.radius_ems); + GET_CASE(FIT_LABEL, boolean, circle->impl->fit_label); default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; @@ -97,23 +119,53 @@ ganv_circle_get_property(GObject* object, static void ganv_circle_resize(GanvNode* self) { - GanvNode* node = GANV_NODE(self); + GanvNode* node = GANV_NODE(self); + GanvCircle* circle = GANV_CIRCLE(self); + GanvCanvas* canvas = GANV_CANVAS(GANV_ITEM(node)->canvas); if (node->impl->label) { if (node->impl->label->impl->needs_layout) { ganv_text_layout(node->impl->label); } + const double label_w = node->impl->label->impl->coords.width; + const double label_h = node->impl->label->impl->coords.height; + if (circle->impl->fit_label) { + // Resize to fit text + const double radius = MAX(label_w, label_h) / 2.0 + 3.0; + if (radius != circle->impl->coords.radius) { + ganv_item_set(GANV_ITEM(self), + "radius", radius, + NULL); + } + } + // Center label ganv_item_set(GANV_ITEM(node->impl->label), - "x", node->impl->label->impl->coords.width / -2.0, - "y", node->impl->label->impl->coords.height / -2.0, + "x", label_w / -2.0, + "y", label_h / -2.0, NULL); } if (parent_class->resize) { parent_class->resize(self); } + + ganv_canvas_for_each_edge_on( + canvas, node, (GanvEdgeFunc)ganv_edge_update_location, NULL); +} + +static void +ganv_circle_redraw_text(GanvNode* self) +{ + GanvCircle* circle = GANV_CIRCLE(self); + if (circle->impl->coords.radius_ems) { + set_radius_ems(circle, circle->impl->coords.radius_ems); + } + + if (parent_class->redraw_text) { + parent_class->redraw_text(self); + } } static gboolean @@ -349,12 +401,30 @@ ganv_circle_class_init(GanvCircleClass* klass) 0.0, G_PARAM_READWRITE)); + g_object_class_install_property( + gobject_class, PROP_RADIUS_EMS, g_param_spec_double( + "radius-ems", + _("Radius in ems"), + _("The radius of the circle in ems."), + 0, G_MAXDOUBLE, + 1.0, + G_PARAM_READWRITE)); + + g_object_class_install_property( + gobject_class, PROP_FIT_LABEL, g_param_spec_boolean( + "fit-label", + _("Fit label"), + _("If true, expand circle to fit its label"), + TRUE, + (GParamFlags)G_PARAM_READWRITE)); + object_class->destroy = ganv_circle_destroy; node_class->resize = ganv_circle_resize; node_class->is_within = ganv_circle_is_within; node_class->tail_vector = ganv_circle_vector; node_class->head_vector = ganv_circle_vector; + node_class->redraw_text = ganv_circle_redraw_text; item_class->update = ganv_circle_update; item_class->bounds = ganv_circle_bounds; diff --git a/src/ganv-private.h b/src/ganv-private.h index ddf6ab5..7bde036 100644 --- a/src/ganv-private.h +++ b/src/ganv-private.h @@ -47,13 +47,14 @@ struct _GanvBoxImpl { /* Circle */ typedef struct { - double x, y, radius; + double x, y, radius, radius_ems; double width; } GanvCircleCoords; struct _GanvCircleImpl { GanvCircleCoords coords; GanvCircleCoords old_coords; + gboolean fit_label; }; /* Edge */ diff --git a/src/ganv_bench.cpp b/src/ganv_bench.cpp index ee2ebfc..be758f0 100644 --- a/src/ganv_bench.cpp +++ b/src/ganv_bench.cpp @@ -70,9 +70,7 @@ make_circle(Canvas* canvas) snprintf(name, 8, "%d", rand() % 10000); Circle* e(new Circle(*canvas, name, rand() % (int)canvas->get_width(), - rand() % (int)canvas->get_height(), - 32.0, - 32.0)); + rand() % (int)canvas->get_height())); ins.push_back(e); outs.push_back(e); diff --git a/src/module.c b/src/module.c index 654038a..88dbb58 100644 --- a/src/module.c +++ b/src/module.c @@ -728,8 +728,7 @@ ganv_module_get_empty_port_breadth(const GanvModule* module) double ganv_module_get_empty_port_depth(const GanvModule* module) { - GanvCanvas* canvas = GANV_CANVAS( - GANV_ITEM(module)->canvas); + GanvCanvas* canvas = GANV_CANVAS(GANV_ITEM(module)->canvas); return ganv_canvas_get_font_size(canvas); } diff --git a/src/node.c b/src/node.c index aaf78f8..ff214ba 100644 --- a/src/node.c +++ b/src/node.c @@ -365,7 +365,6 @@ ganv_node_default_move(GanvNode* node, ganv_item_move(GANV_ITEM(node), dx, dy); ganv_canvas_for_each_edge_on( canvas, node, (GanvEdgeFunc)ganv_edge_update_location, NULL); - } static void -- cgit v1.2.1