summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2015-02-11 06:29:41 +0000
committerDavid Robillard <d@drobilla.net>2015-02-11 06:29:41 +0000
commit57a15af0c0503ee430612f3f6eb4dc76b6e91eae (patch)
tree41aceaba3cd347e879069ecf44985089abc1c7ef
parent3d6bb8063387331e9e8acb2423632a0c722c3038 (diff)
downloadganv-57a15af0c0503ee430612f3f6eb4dc76b6e91eae.tar.gz
ganv-57a15af0c0503ee430612f3f6eb4dc76b6e91eae.tar.bz2
ganv-57a15af0c0503ee430612f3f6eb4dc76b6e91eae.zip
Clip control rectangles to radiused ports.
git-svn-id: http://svn.drobilla.net/lad/trunk/ganv@5554 a436a847-0d15-0410-975c-d299462d15a1
-rw-r--r--src/box.c69
-rw-r--r--src/ganv-private.h4
-rw-r--r--src/port.c47
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
@@ -359,6 +359,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,
gboolean world);
diff --git a/src/port.c b/src/port.c
index 8871f54..8411a11 100644
--- a/src/port.c
+++ b/src/port.c
@@ -126,6 +126,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);
}