[gegl] bin: implement double property editor and pan/zoom of graph
- From: Øyvind "pippin" Kolås <ok src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gegl] bin: implement double property editor and pan/zoom of graph
- Date: Thu, 24 Jan 2019 18:34:29 +0000 (UTC)
commit cd862c923f51bb398573691403c6b9c53db41c87
Author: Øyvind Kolås <pippin gimp org>
Date: Thu Jan 24 01:01:56 2019 +0100
bin: implement double property editor and pan/zoom of graph
bin/ui.c | 642 +++++++++++++++++++++++++++++++++++++++++++++------------------
1 file changed, 463 insertions(+), 179 deletions(-)
---
diff --git a/bin/ui.c b/bin/ui.c
index e80b09136..80b763646 100644
--- a/bin/ui.c
+++ b/bin/ui.c
@@ -38,11 +38,11 @@ const char *css =
"dl.bindings { font-size: 1.8vh; color:white; position:absolute;left:1em;top:60%;background-color:
rgba(0,0,0,0.7); width: 100%; height: 40%; padding-left: 1em; padding-top:1em;}\n"
"dt.binding { color:white; }\n"
-"div.graph {position:absolute; top: 0; left: 0; width:30%; height:50%; color:white; }\n"
+"div.graph {position:absolute; top: 0; left: 0; color:white; }\n"
-"div.node {border: 1px solid white; position: absolute; background-color: rgba(0,0,0,0.75); color:white;
padding-left:1em;padding-right:1em;height:1em;width:8em;padding-top:0.25em;}\n"
-
+"div.node, div.node-active {border: 1px solid gray; color:#000; position: absolute; background-color:
rgba(255,255,255,0.75); padding-left:1em;padding-right:1em;height:1em;width:8em;padding-top:0.25em;}\n"
+"div.node-active { color: #000; background-color: rgba(255,255,255,1.0); text-decoration: underline; }\n"
"div.props {}\n"
"a { color: yellow; text-decoration: none; }\n"
@@ -68,6 +68,18 @@ const char *css =
"";
+/* these are define here to be near the CSS */
+
+#define active_pad_color 1.0, 1.0, 1.0, 1.0
+#define active_pad_stroke_color 1.0, 0.0, 0.0, 1.0
+
+#define pad_color 0.0, 0.0, 0.0, 0.25
+#define pad_stroke_color 1.0, 1.0, 1.0, 1.0
+#define pad_radius 0.25
+#define active_pad_radius 0.5
+
+
+
void mrg_gegl_dirty (void);
@@ -249,9 +261,11 @@ struct _State {
float render_quality; /* default (and in code swapped for preview_quality during preview
rendering, this is the canonical read location for the value) */
float preview_quality;
- int graph_scroll;
-
+ float graph_pan_x;
+ float graph_pan_y;
int show_graph;
+ float graph_scale;
+
int show_controls;
int controls_timeout;
int frame_no;
@@ -320,7 +334,9 @@ Setting settings[]=
INT_PROP(frame_no, "current frame number in video/animation"),
FLOAT_PROP(scale, "display scale factor"),
INT_PROP(show_bindings, "show currently valid keybindings"),
- INT_PROP(graph_scroll, "vertical scroll offset of graph"),
+ FLOAT_PROP(graph_pan_x, "vertical scroll offset of graph"),
+ FLOAT_PROP(graph_pan_y, "horizontal scroll offset of graph"),
+ FLOAT_PROP(graph_scale, "graph scale factor"),
};
@@ -742,6 +758,7 @@ int mrg_ui_main (int argc, char **argv, char **ops)
o.gegl = gegl_node_new (); // so that we have an object to unref
o.mrg = mrg;
o.scale = 1.0;
+ o.graph_scale = 1.0;
o.render_quality = 1.0;
o.preview_quality = 1.0;
//o.preview_quality = 2.0;
@@ -826,18 +843,6 @@ static void on_viewer_motion (MrgEvent *e, void *data1, void *data2)
}
static int node_select_hack = 0;
-static void node_press (MrgEvent *e, void *data1, void *data2)
-{
- State *o = data2;
- GeglNode *new_active = data1;
-
- o->active = new_active;
- o->pad_active = PAD_OUTPUT;
- mrg_event_stop_propagate (e);
- node_select_hack = 1;
-
- mrg_queue_draw (e->mrg, NULL);
-}
static void on_pan_drag (MrgEvent *e, void *data1, void *data2)
@@ -1159,23 +1164,6 @@ static void on_move_drag (MrgEvent *e, void *data1, void *data2)
#if 0
-static void prop_double_drag_cb (MrgEvent *e, void *data1, void *data2)
-{
- GeglNode *node = data1;
- GParamSpec *pspec = data2;
- GeglParamSpecDouble *gspec = data2;
- gdouble value = 0.0;
- float range = gspec->ui_maximum - gspec->ui_minimum;
-
- value = e->x / mrg_width (e->mrg);
- value = value * range + gspec->ui_minimum;
- gegl_node_set (node, pspec->name, value, NULL);
-
- drag_preview (e);
- mrg_event_stop_propagate (e);
-
- mrg_queue_draw (e->mrg, NULL);
-}
static void prop_int_drag_cb (MrgEvent *e, void *data1, void *data2)
{
@@ -1207,15 +1195,6 @@ static void update_prop (const char *new_string, void *node_p)
}
-static void update_prop_double (const char *new_string, void *node_p)
-{
- GeglNode *node = node_p;
- gdouble value = g_strtod (new_string, NULL);
- gegl_node_set (node, edited_prop, value, NULL);
- renderer_dirty++;
- global_state->rev++;
-}
-
static void update_prop_int (const char *new_string, void *node_p)
{
GeglNode *node = node_p;
@@ -1225,19 +1204,6 @@ static void update_prop_int (const char *new_string, void *node_p)
global_state->rev++;
}
-static void prop_toggle_boolean (MrgEvent *e, void *data1, void *data2)
-{
- GeglNode *node = data1;
- const char *propname = data2;
- gboolean value;
- gegl_node_get (node, propname, &value, NULL);
- value = value ? FALSE : TRUE;
- gegl_node_set (node, propname, value, NULL);
- renderer_dirty++;
- global_state->rev++;
- mrg_event_stop_propagate (e);
-}
-
static void set_edited_prop (MrgEvent *e, void *data1, void *data2)
{
@@ -1266,8 +1232,8 @@ int cmd_todo (COMMAND_ARGS);/* "todo", -1, "", ""*/
int
cmd_todo (COMMAND_ARGS)
{
- printf ("scrolling graph\n");
- printf ("propeditor:int/double\n");
+ printf ("propeditor:int\n");
+ printf ("propeditor:color\n");
printf ("propeditor:string\n");
printf ("units in commandline\n");
printf ("crop mode\n");
@@ -2005,6 +1971,9 @@ draw_property_enum (State *o, Mrg *mrg, GeglNode *node, const GParamSpec *pspec)
mrg_end (mrg);
}
+/***************************************************************************/
+
+#if 1
static void
draw_property_int (State *o, Mrg *mrg, GeglNode *node, const GParamSpec *pspec)
{
@@ -2036,6 +2005,24 @@ draw_property_int (State *o, Mrg *mrg, GeglNode *node, const GParamSpec *pspec)
}
mrg_end (mrg);
}
+#else
+
+#endif
+
+/***************************************************************************/
+
+static void on_toggle_boolean (MrgEvent *e, void *data1, void *data2)
+{
+ GeglNode *node = data1;
+ const char *propname = data2;
+ gboolean value;
+ gegl_node_get (node, propname, &value, NULL);
+ value = value ? FALSE : TRUE;
+ gegl_node_set (node, propname, value, NULL);
+ renderer_dirty++;
+ global_state->rev++;
+ mrg_event_stop_propagate (e);
+}
static void
draw_property_boolean (State *o, Mrg *mrg, GeglNode *node, const GParamSpec *pspec)
@@ -2044,7 +2031,7 @@ draw_property_boolean (State *o, Mrg *mrg, GeglNode *node, const GParamSpec *psp
mrg_start (mrg, "div.property", NULL);
gegl_node_get (node, pspec->name, &value, NULL);
- mrg_text_listen (mrg, MRG_CLICK, prop_toggle_boolean, node, (void*)pspec->name);
+ mrg_text_listen (mrg, MRG_CLICK, on_toggle_boolean, node, (void*)pspec->name);
draw_key (o, mrg, pspec->name);
draw_value (o, mrg, value?"true":"false");
@@ -2053,35 +2040,109 @@ draw_property_boolean (State *o, Mrg *mrg, GeglNode *node, const GParamSpec *psp
mrg_end (mrg);
}
+/***************************************************************************/
+
+typedef struct PropDoubleDragData {
+ GeglNode *node;
+ const GParamSpec *pspec;
+ float width;
+ float height;
+ float x;
+ float y;
+
+ double ui_min;
+ double ui_max;
+ double min;
+ double max;
+ double ui_gamma;
+
+ gdouble value;
+} PropDoubleDragData;
+
+static void on_prop_double_drag (MrgEvent *e, void *data1, void *data2)
+{
+ PropDoubleDragData *drag_data = data1;
+ State *o = data2;
+
+ gdouble value, rel_pos;
+
+ rel_pos = (e->x - drag_data->x) / drag_data->width;
+ rel_pos = pow(rel_pos, drag_data->ui_gamma);
+ value = rel_pos * (drag_data->ui_max-drag_data->ui_min) + drag_data->ui_min;
+
+ gegl_node_set (drag_data->node, drag_data->pspec->name, value, NULL);
+
+ renderer_dirty++;
+ o->rev++;
+
+ mrg_event_stop_propagate (e);
+ mrg_queue_draw (e->mrg, NULL);
+}
+
static void
draw_property_double (State *o, Mrg *mrg, GeglNode *node, const GParamSpec *pspec)
{
- //GeglParamSpecDouble *geglspec = (void*)pspecs[i];
- gdouble value;
+ cairo_t*cr = mrg_cr (mrg);
+
+ MrgStyle *style;
+ PropDoubleDragData *drag_data = g_malloc0 (sizeof (PropDoubleDragData));
mrg_start (mrg, "div.property", NULL);//
- gegl_node_get (node, pspec->name, &value, NULL);
+ gegl_node_get (node, pspec->name, &drag_data->value, NULL);
+ style = mrg_style (mrg);
+ drag_data->node = node;
+ drag_data->pspec = pspec;
+ drag_data->x = mrg_x (mrg);
+ drag_data->y = mrg_y (mrg);
- if (edited_prop && !strcmp (edited_prop, pspec->name))
- {
- draw_key (o, mrg, pspec->name);
- mrg_text_listen (mrg, MRG_CLICK, unset_edited_prop, node, (void*)pspec->name);
- mrg_edit_start (mrg, update_prop_double, node);
+ drag_data->width = style->width;
+ drag_data->height = mrg_em (mrg) * 2;
- mrg_printf_xml (mrg, "<div class='propvalue'>%.3f</div>", value);
+ draw_key (o, mrg, pspec->name);
+ mrg_printf_xml (mrg, "<div class='propvalue'>%.3f</div>", drag_data->value);
- mrg_edit_end (mrg);
- mrg_text_listen_done (mrg);
+ cairo_new_path (cr);
+ cairo_rectangle (cr, drag_data->x, drag_data->y, drag_data->width, drag_data->height);
+ mrg_listen_full (mrg, MRG_DRAG, on_prop_double_drag, drag_data, o, (void*)g_free, NULL);
+
+ cairo_set_source_rgba (cr,1,1,1, .5);
+ cairo_set_line_width (cr, 2);
+ cairo_stroke (cr);
+
+ drag_data->min = G_PARAM_SPEC_DOUBLE (drag_data->pspec)->minimum;
+ drag_data->ui_min = drag_data->min;
+ drag_data->max = G_PARAM_SPEC_DOUBLE (drag_data->pspec)->maximum;
+ drag_data->ui_max = drag_data->max;
+
+ if (GEGL_IS_PARAM_SPEC_DOUBLE (drag_data->pspec))
+ {
+ GeglParamSpecDouble *gspec = (void*)drag_data->pspec;
+ drag_data->ui_min = gspec->ui_minimum;
+ drag_data->ui_max = gspec->ui_maximum;
+ drag_data->ui_gamma = gspec->ui_gamma;
+
+ if (drag_data->value > drag_data->ui_max)
+ drag_data->ui_max = drag_data->value;
+ if (drag_data->value < drag_data->ui_min)
+ drag_data->ui_min = drag_data->value;
}
else
{
- mrg_text_listen (mrg, MRG_CLICK, set_edited_prop, node, (void*)pspec->name);
- draw_key (o, mrg, pspec->name);
+ drag_data->ui_gamma = 1.0;
+ }
- mrg_printf_xml (mrg, "<div class='propvalue'>%.3f</div>", value);
+ cairo_rectangle (cr,
+ drag_data->x,
+ drag_data->y,
+ pow((drag_data->value-drag_data->ui_min) /
+ (drag_data->ui_max-drag_data->ui_min), 1.0/drag_data->ui_gamma)* drag_data->width,
+ drag_data->height);
+
+ cairo_fill (cr);
+
+
+ mrg_set_xy (mrg, drag_data->x, drag_data->y + drag_data->height);
- mrg_text_listen_done (mrg);
- }
mrg_end (mrg);
}
@@ -2701,7 +2762,7 @@ static GeglNode *gegl_node_get_ui_consumer (GeglNode *node, const char *output_p
count = gegl_node_get_consumers (node, output_pad, &nodes, &consumer_names);
for (i = 0; i < count; i++)
if (ret == nodes[i])
- *consumer_pad = consumer_names[i];
+ *consumer_pad = g_intern_string (consumer_names[i]);
g_free (nodes);
g_free (consumer_names);
}
@@ -2710,19 +2771,144 @@ static GeglNode *gegl_node_get_ui_consumer (GeglNode *node, const char *output_p
}
static GeglNode *node_pad_drag_node = NULL;
+static GeglNode *node_pad_drag_candidate = NULL;
static int node_pad_drag = -1;
static float node_pad_drag_x = 0;
static float node_pad_drag_y = 0;
+static float node_pad_drag_x_start = 0;
+static float node_pad_drag_y_start = 0;
+
+
+#if 0
+static void node_press (MrgEvent *e,
+ void *data1,
+ void *data2)
+{
+ State *o = data2;
+ GeglNode *new_active = data1;
-static void on_node_drag (MrgEvent *e, void *data1, void *data2)
+ o->active = new_active;
+ o->pad_active = PAD_OUTPUT;
+ mrg_event_stop_propagate (e);
+ node_select_hack = 1;
+
+ mrg_queue_draw (e->mrg, NULL);
+}
+#endif
+
+static void on_graph_drag (MrgEvent *e, void *data1, void *data2)
{
+ static float pinch_coord[4][2] = {0,};
+ static int pinch = 0;
+ static float orig_zoom = 1.0;
+
State *o = data1;
GeglNode *node = data2;
- static float dist_jitter = 6;
- static float dist_add_node = 50;
- static float dist_remove = 70;
- static float dist_connect_pad = 80;
+ //on_viewer_motion (e, data1, data2);
+ if (e->type == MRG_DRAG_RELEASE)
+ {
+ //float x = (e->x + o->u) / o->scale;
+ //float y = (e->y + o->v) / o->scale;
+ //GeglNode *picked = NULL;
+
+ if(node && hypotf (e->device_x - e->start_x, e->device_y - e->start_y) < 10)
+ {
+ o->active = node;
+ o->pad_active = PAD_OUTPUT;
+ }
+
+ node_select_hack = 0;
+ pinch = 0;
+ } else if (e->type == MRG_DRAG_PRESS)
+ {
+ node_select_hack = 1;
+
+
+ if (e->device_no == 5) /* 5 is second finger/touch point */
+ {
+ pinch_coord[1][0] = e->device_x;
+ pinch_coord[1][1] = e->device_y;
+ pinch_coord[2][0] = pinch_coord[0][0];
+ pinch_coord[2][1] = pinch_coord[0][1];
+ pinch_coord[3][0] = pinch_coord[1][0];
+ pinch_coord[3][1] = pinch_coord[1][1];
+ pinch = 1;
+
+
+ orig_zoom = o->graph_scale;
+ }
+ else if (e->device_no == 1 || e->device_no == 4) /* 1 is mouse pointer 4 is first finger */
+ {
+ pinch_coord[0][0] = e->device_x;
+ pinch_coord[0][1] = e->device_y;
+ }
+ } else if (e->type == MRG_DRAG_MOTION)
+ {
+ if (e->device_no == 1 || e->device_no == 4) /* 1 is mouse pointer 4 is first finger */
+ {
+ pinch_coord[0][0] = e->device_x;
+ pinch_coord[0][1] = e->device_y;
+ }
+ if (e->device_no == 5)
+ {
+ pinch_coord[1][0] = e->device_x;
+ pinch_coord[1][1] = e->device_y;
+ }
+
+ if (pinch)
+ {
+ float orig_dist = hypotf ( pinch_coord[2][0]- pinch_coord[3][0],
+ pinch_coord[2][1]- pinch_coord[3][1]);
+ float dist = hypotf (pinch_coord[0][0] - pinch_coord[1][0],
+ pinch_coord[0][1] - pinch_coord[1][1]);
+ {
+ float x, y;
+ float screen_cx = (pinch_coord[0][0] + pinch_coord[1][0])/2;
+ float screen_cy = (pinch_coord[0][1] + pinch_coord[1][1])/2;
+ //get_coords_graph (o, screen_cx, screen_cy, &x, &y);
+
+ x = (o->graph_pan_x + screen_cx) / o->graph_scale;
+ y = (o->graph_pan_y + screen_cy) / o->graph_scale;
+
+ o->graph_scale = orig_zoom * (dist / orig_dist);
+
+ o->graph_pan_x = x * o->graph_scale - screen_cx;
+ o->graph_pan_y = y * o->graph_scale - screen_cy;
+
+ o->graph_pan_x -= (e->delta_x * o->graph_scale )/2; /* doing half contribution of motion per finger */
+ o->graph_pan_y -= (e->delta_y * o->graph_scale )/2; /* is simple and roughly right */
+ }
+
+ }
+ else
+ {
+ if (e->device_no == 1 || e->device_no == 4)
+ {
+ o->graph_pan_x -= (e->delta_x * o->graph_scale);
+ o->graph_pan_y -= (e->delta_y * o->graph_scale);
+ }
+ }
+
+ //o->renderer_state = 0;
+ mrg_queue_draw (e->mrg, NULL);
+ }
+ mrg_event_stop_propagate (e);
+ node_select_hack = 0;
+ drag_preview (e);
+}
+
+static void on_active_node_drag (MrgEvent *e, void *data1, void *data2, int is_aux)
+{
+ State *o = data1;
+ GeglNode *node = data2;
+
+ float em = mrg_em (o->mrg);
+
+ float dist_jitter = em;
+ float dist_add_node = em*2;
+ float dist_remove = em*3;
+ float dist_connect_pad = em*4;
static float dist = 0;
static float angle = 0;
@@ -2735,6 +2921,7 @@ static void on_node_drag (MrgEvent *e, void *data1, void *data2)
{
case MRG_DRAG_PRESS:
dist = angle = 0.0;
+ node_pad_drag_candidate = NULL;
break;
case MRG_DRAG_RELEASE:
if (angle < -120 || angle > 120) // upwards
@@ -2742,15 +2929,18 @@ static void on_node_drag (MrgEvent *e, void *data1, void *data2)
if (dist > dist_add_node)
o->active = add_output (o, o->active, "gegl:nop");
}
- else if (angle < 15 && angle > -45) // down / slightly left
+ else if (angle < 60 && angle > -45) // down
{
- if (dist > dist_add_node)
- o->active = add_input (o, o->active, "gegl:nop");
- }
- else if (angle > 15 && angle <60) // right/down
- {
- if (dist > dist_add_node)
- o->active = add_aux (o, o->active, "gegl:nop");
+ if (is_aux)
+ {
+ if (dist > dist_add_node)
+ o->active = add_aux (o, o->active, "gegl:nop");
+ }
+ else
+ {
+ if (dist > dist_add_node)
+ o->active = add_input (o, o->active, "gegl:nop");
+ }
}
else if (angle < -45 && angle > -110) // left
{
@@ -2770,24 +2960,33 @@ static void on_node_drag (MrgEvent *e, void *data1, void *data2)
if (dist > dist_jitter)
o->pad_active = PAD_OUTPUT;
}
- else if (angle < 15 && angle > -45) // down / slightly left
+ else if (angle < 60 && angle > -45) // down
{
- if (dist > dist_jitter)
- o->pad_active = PAD_INPUT;
- if (dist > 100) // XXX all these dist comparisons need to be parametric
+ if (is_aux)
{
- node_pad_drag = PAD_INPUT;
- node_pad_drag_node = node;
+ if (dist > dist_jitter)
+ o->pad_active = PAD_AUX;
+
+ if (dist > dist_connect_pad)
+ {
+ node_pad_drag = PAD_AUX;
+ node_pad_drag_node = node;
+ }
+ }
+ else
+ {
+ if (dist > dist_jitter)
+ o->pad_active = PAD_INPUT;
+ if (dist > dist_connect_pad)
+ {
+ node_pad_drag = PAD_INPUT;
+ node_pad_drag_node = node;
+ }
}
- }
- else if (angle > 15 && angle <60) // right/down
- {
- if (dist > dist_jitter)
- o->pad_active = PAD_AUX;
}
else if (angle < -45 && angle > -110) // left
{
- if (dist > 70)
+ if (dist > dist_remove)
o->pad_active = -1; // makes dot vanish
else
o->pad_active = PAD_OUTPUT;
@@ -2812,7 +3011,44 @@ static void on_node_drag (MrgEvent *e, void *data1, void *data2)
break;
case MRG_DRAG_RELEASE:
node_pad_drag = -1;
+
+ if (node_pad_drag_candidate)
+ {
+ gegl_node_connect_to (node_pad_drag_candidate, "output", node_pad_drag_node, "input");
+ o->rev ++;
+ renderer_dirty = 1;
+ }
+ o->pad_active = PAD_OUTPUT;
+ node_pad_drag_candidate = NULL;
+
+ break;
+ case MRG_DRAG_MOTION:
+ node_pad_drag_x = e->x;
+ node_pad_drag_y = e->y;
+ break;
+ default:
+ break;
+ }
+ break;
+ case PAD_AUX:
+ switch (e->type)
+ {
+ case MRG_DRAG_PRESS:
+ node_pad_drag_x = e->x;
+ node_pad_drag_y = e->y;
+ break;
+ case MRG_DRAG_RELEASE:
+ node_pad_drag = -1;
+
+ if (node_pad_drag_candidate)
+ {
+ gegl_node_connect_to (node_pad_drag_candidate, "output", node_pad_drag_node, "aux");
+ o->rev ++;
+ renderer_dirty = 1;
+ }
o->pad_active = PAD_OUTPUT;
+ node_pad_drag_candidate = NULL;
+
break;
case MRG_DRAG_MOTION:
node_pad_drag_x = e->x;
@@ -2824,8 +3060,19 @@ static void on_node_drag (MrgEvent *e, void *data1, void *data2)
break;
}
mrg_event_stop_propagate (e);
+ mrg_queue_draw (e->mrg, NULL);
+}
+
+
+static void on_active_node_drag_input (MrgEvent *e, void *data1, void *data2)
+{
+ on_active_node_drag (e, data1, data2, 0);
}
+static void on_active_node_drag_aux (MrgEvent *e, void *data1, void *data2)
+{
+ on_active_node_drag (e, data1, data2, 1);
+}
typedef struct DrawEdge {
int has_alpha;
@@ -2940,7 +3187,7 @@ draw_node (State *o, int indent, int line_no, GeglNode *node, gboolean active)
char *opname = NULL;
GList *to_remove = NULL;
Mrg *mrg = o->mrg;
- //float em;
+ cairo_t *cr = mrg_cr (mrg);
float x = compute_node_x (mrg, indent, line_no);
float y = compute_node_y (mrg, indent, line_no);
@@ -2952,9 +3199,9 @@ draw_node (State *o, int indent, int line_no, GeglNode *node, gboolean active)
yd > mrg_height (mrg) * 0.8)
{
float blend_factor = 0.20;
- float new_scroll = (y - mrg_height(mrg)/2);
+ float new_scroll = ( (y*o->graph_scale) - mrg_height(mrg)/2);
- o->graph_scroll = (1.0-blend_factor) * o->graph_scroll +
+ o->graph_pan_y = (1.0-blend_factor) * o->graph_pan_y +
blend_factor * new_scroll;
mrg_queue_draw (mrg, NULL);
}
@@ -2981,7 +3228,10 @@ draw_node (State *o, int indent, int line_no, GeglNode *node, gboolean active)
g_object_get (node, "operation", &opname, NULL);
{
char style[1024];
- sprintf (style, "color:%s;left:%f;top:%f;%s", active?"yellow":"white", x, y,
active?"":"border-color:#ccc;");
+ sprintf (style, "left:%f;top:%f;", x, y);
+ if (active)
+ mrg_start_with_style (mrg, "div.node-active", NULL, style);
+ else
mrg_start_with_style (mrg, "div.node", NULL, style);
}
//em = mrg_em (mrg);
@@ -3013,75 +3263,39 @@ draw_node (State *o, int indent, int line_no, GeglNode *node, gboolean active)
{
MrgStyle *style = mrg_style (mrg);
- float em = mrg_em (mrg);
- cairo_rectangle (mrg_cr (mrg), style->left, style->top - 0.5 * em,
- style->width + style->padding_left + style->padding_right,
- style->height + style->padding_top + style->padding_bottom + 1 * em);
+ float x = style->left;
+ float y = style->top - 0.5 * mrg_em (mrg);
+ float width = style->width + style->padding_left + style->padding_right;
+ float height = style->height + style->padding_top + style->padding_bottom + 1 * mrg_em (mrg);
+
+ cairo_rectangle (mrg_cr (mrg), x, y, width, height);
+
+ if (node_pad_drag >= 0 && cairo_in_fill (mrg_cr (mrg), node_pad_drag_x, node_pad_drag_y) &&
+ node != node_pad_drag_node)
+ {
+ mrg_set_style (mrg, "border: 4px solid yellow;");
+ node_pad_drag_candidate = node;
+ }
if(active)
- mrg_listen (mrg, MRG_DRAG, on_node_drag, o, node);
+ {
+ cairo_new_path (mrg_cr (mrg));
+ cairo_rectangle (mrg_cr (mrg), x, y, width/2, height);
+ mrg_listen (mrg, MRG_DRAG, on_active_node_drag_input, o, node);
+
+ cairo_new_path (mrg_cr (mrg));
+ cairo_rectangle (mrg_cr (mrg), x + width/2, y, width/2, height);
+ mrg_listen (mrg, MRG_DRAG, on_active_node_drag_aux, o, node);
+ }
else
- mrg_listen (mrg, MRG_CLICK, node_press, node, o);
+ mrg_listen (mrg, MRG_DRAG, on_graph_drag, o, node);
+ cairo_new_path (mrg_cr (mrg));
+
}
mrg_end (mrg);
g_free (opname);
- if (gegl_node_has_pad (node, "input"))
- {
- cairo_t *cr = mrg_cr (mrg);
- cairo_new_path (cr);
- cairo_arc (cr, compute_pad_x (mrg, indent, line_no, 0),
- compute_pad_y (mrg, indent, line_no, 0), 0.3*mrg_em (mrg), 0, G_PI * 2);
- cairo_set_source_rgb (cr, 1.0,1.0,1.0);
- cairo_set_line_width (cr, 1.0f);
- if (active && o->pad_active == PAD_INPUT)
- {
- cairo_fill (cr);
- }
- else
- {
- cairo_new_path (cr);
- cairo_stroke (cr);
- }
- }
- if (gegl_node_has_pad (node, "aux"))
- {
- cairo_t *cr = mrg_cr (mrg);
- cairo_new_path (cr);
- cairo_arc (cr, compute_pad_x (mrg, indent, line_no, 1),
- compute_pad_y (mrg, indent, line_no, 1), 0.3*mrg_em (mrg), 0, G_PI * 2);
- cairo_set_source_rgb (cr, 1.0,1.0,1.0);
- cairo_set_line_width (cr, 1.0f);
-
- if (active && o->pad_active == PAD_AUX)
- {
- cairo_fill (cr);
- }
- else
- {
- cairo_new_path (cr);
- cairo_stroke (cr);
- }
- }
- if (gegl_node_has_pad (node, "output"))
- {
- cairo_t *cr = mrg_cr (mrg);
- cairo_new_path (cr);
- cairo_arc (cr, compute_pad_x (mrg, indent, line_no, 2),
- compute_pad_y (mrg, indent, line_no, 2), 0.3*mrg_em (mrg), 0, G_PI * 2);
- cairo_set_source_rgb (cr, 1.0,1.0,1.0);
- cairo_set_line_width (cr, 1.0f);
- if (active && o->pad_active == PAD_OUTPUT)
- {
- cairo_fill (cr);
- }
- else
- {
- cairo_new_path (cr);
- cairo_stroke (cr);
- }
- }
for (GList *i = edge_queue; i; i = i->next)
@@ -3133,8 +3347,10 @@ draw_node (State *o, int indent, int line_no, GeglNode *node, gboolean active)
cairo_stroke (cr);
to_remove = g_list_prepend (to_remove, edge);
+
}
}
+
while (to_remove)
{
DrawEdge *edge = to_remove->data;
@@ -3142,6 +3358,38 @@ draw_node (State *o, int indent, int line_no, GeglNode *node, gboolean active)
to_remove = g_list_remove (to_remove, edge);
}
+ if (node_pad_drag_node == node)
+ {
+ node_pad_drag_x_start =
+ compute_pad_x (mrg, indent, line_no, node_pad_drag);
+ node_pad_drag_y_start =
+ compute_pad_y (mrg, indent, line_no, node_pad_drag);
+ }
+
+ for (int pad_no = PAD_INPUT; pad_no <= PAD_OUTPUT; pad_no++)
+ {
+ const char *pad_names[3]={"input", "aux", "output"};
+
+ if (gegl_node_has_pad (node, pad_names[pad_no]))
+ {
+ gboolean is_active = active && o->pad_active == pad_no;
+
+ cairo_new_path (cr);
+ cairo_arc (cr, compute_pad_x (mrg, indent, line_no, pad_no),
+ compute_pad_y (mrg, indent, line_no, pad_no),
+ (is_active?active_pad_radius:pad_radius)*mrg_em (mrg),
+ 0, G_PI * 2);
+
+ cairo_set_line_width (cr, 1.0f);
+ if (is_active) cairo_set_source_rgba (cr, active_pad_color);
+ else cairo_set_source_rgba (cr, pad_color);
+ cairo_fill_preserve (cr);
+ if (is_active) cairo_set_source_rgba (cr, active_pad_stroke_color);
+ else cairo_set_source_rgba (cr, pad_stroke_color);
+ cairo_stroke (cr);
+ }
+ }
+
}
static void list_ops (State *o, GeglNode *iter, int indent, int *no)
@@ -3190,9 +3438,6 @@ static void list_ops (State *o, GeglNode *iter, int indent, int *no)
-
-
-
static void ui_debug_op_chain (State *o)
{
Mrg *mrg = o->mrg;
@@ -3200,7 +3445,9 @@ static void ui_debug_op_chain (State *o)
int no = 0;
mrg_start (mrg, "div.graph", NULL);
- cairo_translate (mrg_cr (mrg), mrg_width(mrg) * 0.7, -o->graph_scroll);
+
+ cairo_translate (mrg_cr (mrg), - o->graph_pan_x, -o->graph_pan_y);
+ cairo_scale (mrg_cr (mrg), o->graph_scale, o->graph_scale);
update_ui_consumers (o);
@@ -3211,17 +3458,34 @@ static void ui_debug_op_chain (State *o)
list_ops (o, iter, 0, &no);
+ if (node_pad_drag >= 0)
+ {
+ cairo_t *cr = mrg_cr (mrg);
+ cairo_new_path (cr);
+ cairo_move_to (cr, node_pad_drag_x_start,
+ node_pad_drag_y_start);
+ cairo_line_to (cr, node_pad_drag_x,
+ node_pad_drag_y);
+
+ cairo_set_line_width (cr, 3 + .75);
+ cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
+ cairo_set_source_rgba (cr, .0,.0,.0,.5);
+ cairo_stroke_preserve (cr);
+
+ cairo_set_line_width (cr, 3);
+ cairo_set_source_rgba (cr, 1, 0, 0, 1.0);
+ cairo_stroke (cr);
+ }
mrg_end (mrg);
if (o->active && !scrollback)
{
- //mrg_set_xy (mrg, mrg_width (mrg), 0);
mrg_start (mrg, "div.props", NULL);
- //mrg_set_style (mrg, "color:white; background-color: rgba(0,0,0,0.4)");
list_node_props (o, o->active, 1);
mrg_end (mrg);
}
+
}
@@ -3963,9 +4227,13 @@ static GList *commandline_get_completions (GeglNode *node,
const char *commandline)
{
const gchar *op_name = node?gegl_node_get_operation (node):"nop";
- const char *last = NULL;
- char *key = NULL;
+ const char *last = NULL; /* the string/piece being completed */
+
+ char *key = NULL; /* if what is being completed is a key/value pair */
const char *value = "";
+
+ char *prev = NULL;
+
GList *completions = NULL;
int count = 0;
int bail = 8;
@@ -3975,8 +4243,24 @@ static GList *commandline_get_completions (GeglNode *node,
}
last = strrchr (commandline, ' ');
- if (last) last ++;
- else last = commandline;
+ if (last)
+ {
+ const char *plast;
+ *(char*)last = '\0';
+ plast = strrchr (commandline, ' ');
+ if (plast)
+ {
+ prev = g_strdup (plast);
+ }
+ else
+ prev = g_strdup (commandline);
+ *(char*)last = ' ';
+ last ++;
+ }
+ else
+ {
+ last = commandline;
+ }
if (strchr (last, '='))
{
@@ -4126,6 +4410,8 @@ static GList *commandline_get_completions (GeglNode *node,
if (key)
g_free (key);
+ if (prev)
+ g_free (prev);
return g_list_reverse (completions);
}
@@ -5325,8 +5611,6 @@ static void get_coords (State *o, float screen_x, float screen_y, float *gegl_x,
*gegl_y = (o->v + screen_y) / scale;
}
-
-
static void scroll_cb (MrgEvent *event, void *data1, void *data2)
{
switch (event->scroll_direction)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]