From 57a15af0c0503ee430612f3f6eb4dc76b6e91eae Mon Sep 17 00:00:00 2001 From: David Robillard Date: Wed, 11 Feb 2015 06:29:41 +0000 Subject: Clip control rectangles to radiused ports. git-svn-id: http://svn.drobilla.net/lad/trunk/ganv@5554 a436a847-0d15-0410-975c-d299462d15a1 --- src/box.c | 69 +++++++++++++++++++++++++++++++----------------------- src/ganv-private.h | 4 ++++ src/port.c | 47 ++++++++++++++++++++++++++++++------- 3 files changed, 83 insertions(+), 37 deletions(-) diff --git a/src/box.c b/src/box.c index 95a6a67..1210104 100644 --- a/src/box.c +++ b/src/box.c @@ -52,11 +52,12 @@ ganv_box_init(GanvBox* box) memset(&box->impl->coords, '\0', sizeof(GanvBoxCoords)); - box->impl->old_coords = box->impl->coords; - box->impl->radius_tl = 0.0; - box->impl->radius_tr = 0.0; - box->impl->radius_br = 0.0; - box->impl->radius_bl = 0.0; + box->impl->coords.border_width = GANV_NODE(box)->impl->border_width; + box->impl->old_coords = box->impl->coords; + box->impl->radius_tl = 0.0; + box->impl->radius_tr = 0.0; + box->impl->radius_br = 0.0; + box->impl->radius_bl = 0.0; } static void @@ -199,6 +200,38 @@ ganv_box_update(GanvItem* item, int flags) ganv_box_request_redraw(item, &impl->coords, FALSE); } +void +ganv_box_path(GanvBox* box, + cairo_t* cr, double x1, double y1, double x2, double y2) +{ + static const double degrees = G_PI / 180.0; + + GanvBoxImpl* impl = box->impl; + + if (impl->radius_tl == 0.0 && impl->radius_tr == 0.0 + && impl->radius_br == 0.0 && impl->radius_bl == 0.0) { + // Simple rectangle + cairo_rectangle(cr, x1, y1, x2 - x1, y2 - y1); + } else { + // Rounded rectangle + cairo_new_sub_path(cr); + cairo_arc(cr, + x2 - impl->radius_tr, + y1 + impl->radius_tr, + impl->radius_tr, -90 * degrees, 0 * degrees); + cairo_arc(cr, + x2 - impl->radius_br, y2 - impl->radius_br, + impl->radius_br, 0 * degrees, 90 * degrees); + cairo_arc(cr, + x1 + impl->radius_bl, y2 - impl->radius_bl, + impl->radius_bl, 90 * degrees, 180 * degrees); + cairo_arc(cr, + x1 + impl->radius_tl, y1 + impl->radius_tl, + impl->radius_tl, 180 * degrees, 270 * degrees); + cairo_close_path(cr); + } +} + static void ganv_box_draw(GanvItem* item, cairo_t* cr, double cx, double cy, double cw, double ch) @@ -218,34 +251,12 @@ ganv_box_draw(GanvItem* item, double r, g, b, a; - static const double degrees = G_PI / 180.0; - for (int i = (impl->coords.stacked ? 1 : 0); i >= 0; --i) { const double x = 0.0 - (STACKED_OFFSET * i); const double y = 0.0 - (STACKED_OFFSET * i); - if (impl->radius_tl == 0.0 && impl->radius_tr == 0.0 - && impl->radius_br == 0.0 && impl->radius_bl == 0.0) { - // Simple rectangle - cairo_rectangle(cr, x1 - x, y1 - y, x2 - x1, y2 - y1); - } else { - // Rounded rectangle - cairo_new_sub_path(cr); - cairo_arc(cr, - x2 - x - impl->radius_tr, - y1 - y + impl->radius_tr, - impl->radius_tr, -90 * degrees, 0 * degrees); - cairo_arc(cr, - x2 - x - impl->radius_br, y2 - y - impl->radius_br, - impl->radius_br, 0 * degrees, 90 * degrees); - cairo_arc(cr, - x1 - x + impl->radius_bl, y2 - y - impl->radius_bl, - impl->radius_bl, 90 * degrees, 180 * degrees); - cairo_arc(cr, - x1 - x + impl->radius_tl, y1 - y + impl->radius_tl, - impl->radius_tl, 180 * degrees, 270 * degrees); - cairo_close_path(cr); - } + // Trace basic box path + ganv_box_path(box, cr, x1 - x, y1 - y, x2 - x, y2 - y); // Fill color_to_rgba(fill_color, &r, &g, &b, &a); diff --git a/src/ganv-private.h b/src/ganv-private.h index 2fc6c00..a682dbb 100644 --- a/src/ganv-private.h +++ b/src/ganv-private.h @@ -358,6 +358,10 @@ ganv_edge_tick(GanvEdge* edge, double seconds); /* Box */ +void +ganv_box_path(GanvBox* box, + cairo_t* cr, double x1, double y1, double x2, double y2); + void ganv_box_request_redraw(GanvItem* item, const GanvBoxCoords* coords, diff --git a/src/port.c b/src/port.c index 8871f54..8411a11 100644 --- a/src/port.c +++ b/src/port.c @@ -125,6 +125,21 @@ ganv_port_get_property(GObject* object, } } +static void +ganv_port_update(GanvItem* item, int flags) +{ + GanvPort* port = GANV_PORT(item); + GanvPortImpl* impl = port->impl; + + if (impl->control) { + const double border_width = GANV_NODE(item)->impl->border_width; + impl->control->rect->impl->coords.border_width = border_width; + } + + GanvItemClass* item_class = GANV_ITEM_CLASS(parent_class); + item_class->update(item, flags); +} + static void ganv_port_draw(GanvItem* item, cairo_t* cr, double cx, double cy, double cw, double ch) @@ -137,8 +152,21 @@ ganv_port_draw(GanvItem* item, item_class->draw(item, cr, cx, cy, cw, ch); if (port->impl->control) { + // Clip to port boundaries (to stay within radiused borders) + cairo_save(cr); + const double pad = GANV_NODE(port)->impl->border_width / 2.0; + GanvBoxCoords coords = GANV_BOX(port)->impl->coords; + ganv_item_i2w_pair(GANV_ITEM(port), + &coords.x1, &coords.y1, &coords.x2, &coords.y2); + ganv_box_path(GANV_BOX(port), cr, + coords.x1 - pad, coords.y1 - pad, + coords.x2 + pad, coords.y2 + pad); + cairo_clip(cr); + GanvItem* const rect = GANV_ITEM(port->impl->control->rect); GANV_ITEM_GET_CLASS(rect)->draw(rect, cr, cx, cy, cw, ch); + + cairo_restore(cr); } if (ganv_canvas_get_direction(canvas) == GANV_DIRECTION_DOWN || @@ -378,8 +406,9 @@ ganv_port_class_init(GanvPortClass* klass) object_class->destroy = ganv_port_destroy; - item_class->event = ganv_port_event; - item_class->draw = ganv_port_draw; + item_class->update = ganv_port_update; + item_class->event = ganv_port_event; + item_class->draw = ganv_port_draw; node_class->tail_vector = ganv_port_tail_vector; node_class->head_vector = ganv_port_head_vector; @@ -449,11 +478,13 @@ ganv_port_set_direction(GanvPort* port, void ganv_port_show_control(GanvPort* port) { + GanvNode* node = GANV_NODE(port); + + guint color = highlight_color(node->impl->fill_color, 0x40); + GanvPortControl* control = (GanvPortControl*)malloc(sizeof(GanvPortControl)); port->impl->control = control; - guint control_col = highlight_color(GANV_NODE(port)->impl->fill_color, 0x40); - control->value = 0.0f; control->min = 0.0f; control->max = 0.0f; @@ -467,9 +498,9 @@ ganv_port_show_control(GanvPort* port) "y1", 0.0, "x2", 0.0, "y2", ganv_box_get_height(&port->box), - "fill-color", control_col, - "border-color", control_col, - "border-width", 0.0, + "fill-color", color, + "border-color", color, + "border-width", 0.0,//node->impl->border_width, "managed", TRUE, NULL)); ganv_item_show(GANV_ITEM(control->rect)); @@ -553,7 +584,7 @@ ganv_port_update_control_slider(GanvPort* port, float value, gboolean force) // Redraw port impl->control->value = value; - ganv_box_set_width(impl->control->rect, MAX(0.0, w - 1.0)); + ganv_box_set_width(impl->control->rect, MAX(0.0, w)); ganv_box_request_redraw( GANV_ITEM(port), &GANV_BOX(port)->impl->coords, FALSE); } -- cgit v1.2.1