[gegl/soc-2012-editor: 6/36] Can drag to connect nodes. Shows curve from node to cursor while connecting output->input
- From: Isaac Wagner <isaacbw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gegl/soc-2012-editor: 6/36] Can drag to connect nodes. Shows curve from node to cursor while connecting output->input
- Date: Thu, 5 Jul 2012 21:56:43 +0000 (UTC)
commit 1e8372d71462114211b54c8860f873424dbdbc1d
Author: Isaac Wagner <isaacbw src gnome org>
Date: Wed Jun 6 00:35:08 2012 -0400
Can drag to connect nodes. Shows curve from node to cursor while connecting output->input
bin/editor/gegl-node-widget.c | 196 ++++++++++++++++++++++++++++++++---------
bin/editor/gegl-node-widget.h | 16 ++--
2 files changed, 165 insertions(+), 47 deletions(-)
---
diff --git a/bin/editor/gegl-node-widget.c b/bin/editor/gegl-node-widget.c
index 53d0718..202f940 100644
--- a/bin/editor/gegl-node-widget.c
+++ b/bin/editor/gegl-node-widget.c
@@ -11,9 +11,9 @@ static GParamSpec *obj_properties[N_PROPERTIES] = { NULL, };
static void
gegl_node_widget_set_property (GObject *object,
- guint property_id,
- const GValue *value,
- GParamSpec *pspec)
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
{
GeglNodeWidget *self = GEGL_NODE_WIDGET(object);
@@ -27,9 +27,9 @@ gegl_node_widget_set_property (GObject *object,
static void
gegl_node_widget_get_property (GObject *object,
- guint property_id,
- GValue *value,
- GParamSpec *pspec)
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
{
GeglNodeWidget* self = GEGL_NODE_WIDGET(object);
@@ -70,6 +70,73 @@ connect_pads(NodePad* a, NodePad* b)
b->connected = a;
}
+NodePad*
+get_pad_at(gint px, gint py, GeglNodeWidget* editor)
+{
+ NodePad* result = NULL;
+
+ EditorNode* node = editor->first_node;
+ for(;node != NULL; node = node->next)
+ {
+ gint x, y;
+ gint width, height;
+
+ if(node == editor->dragged_node)
+ {
+ x = node->x+editor->px-editor->dx;
+ y = node->y+editor->py-editor->dy;
+ }
+ else
+ {
+ x = node->x;
+ y = node->y;
+ }
+
+ //TODO: be more intelligent about minimum size (should be based on number of inputs/outputs so that they all fit properly)
+ if(node->width < 100)
+ node->width = 100;
+ if(node->height < 50)
+ node->height = 50;
+
+ if(node == editor->resized_node)
+ {
+ width = node->width+editor->px-editor->dx;
+ height = node->height+editor->py-editor->dy;
+ }
+ else
+ {
+ width = node->width;
+ height = node->height;
+ }
+
+ if(width < 100)
+ width = 100;
+ if(height < 50)
+ height = 50;
+
+ gint title_height = node->title_height;
+
+ int i = 0;
+ NodePad* pad = node->inputs;
+ for(;pad!=NULL;pad = pad->next, i++)
+ {
+ if(px > x && py > y+(title_height)+10+20*i && px < x+10 && py < y+(title_height)+20+20*i)
+ result = pad;
+ }
+
+ i = 0;
+ pad = node->outputs;
+ for(;pad!=NULL;pad = pad->next, i++)
+ {
+ if(px > x+width-10 && px < x+width &&
+ py > y+(title_height)+10+20*i &&
+ py < y+(title_height)+20+20*i)
+ result = pad;
+ }
+ }
+ return result;
+}
+
void
get_pad_position_input(NodePad* pad, gint* x, gint* y, cairo_t* cr, GeglNodeWidget* editor)
{
@@ -124,6 +191,7 @@ draw_node(EditorNode* node, cairo_t *cr, GeglNodeWidget* editor)
y = node->y;
}
+ //TODO: be more intelligent about minimum size (should be based on number of inputs/outputs so that they all fit properly)
if(node->width < 100)
node->width = 100;
if(node->height < 50)
@@ -165,6 +233,7 @@ draw_node(EditorNode* node, cairo_t *cr, GeglNodeWidget* editor)
cairo_text_extents_t te;
cairo_text_extents(cr, node->title, &te);
gint title_height = te.height+5;
+ node->title_height = title_height;
//draw the line separating the title
cairo_move_to(cr, x, y+te.height+5);
@@ -222,6 +291,7 @@ draw_node(EditorNode* node, cairo_t *cr, GeglNodeWidget* editor)
cairo_reset_clip(cr);
+ //TODO: render all connections underneath all nodes
if(pad->connected)
{
gint fx, fy;
@@ -244,6 +314,26 @@ draw_node(EditorNode* node, cairo_t *cr, GeglNodeWidget* editor)
cairo_stroke(cr);
}
+ else if(pad == editor->dragged_pad)
+ {
+ gint fx, fy;
+ fx = x+width-5;
+ fy = y+(title_height)+15+20*i;
+
+ gint tx = editor->px, ty = editor->py;
+
+ cairo_move_to(cr, fx, fy);
+ if(tx - fx > 200)
+ cairo_curve_to(cr, (fx+tx)/2, fy,
+ (fx+tx)/2, ty,
+ tx, ty);
+ else
+ cairo_curve_to(cr, fx+100, fy,
+ tx-100, ty,
+ tx, ty);
+ cairo_stroke(cr);
+
+ }
}
}
@@ -261,6 +351,7 @@ gegl_node_widget_draw(GtkWidget *widget, cairo_t *cr)
draw_node(node, cr, editor);
}
+
return FALSE;
}
@@ -287,6 +378,7 @@ gegl_node_widget_motion(GtkWidget* widget, GdkEventMotion* event)
/* redraw */
gtk_widget_queue_draw(widget);
+
return FALSE;
}
@@ -299,48 +391,62 @@ gegl_node_widget_button_press(GtkWidget* widget, GdkEventButton* event)
editor->dx = editor->px;
editor->dy = editor->py;
- EditorNode* node = editor->first_node;
- EditorNode* focus = NULL;
- for(;node != NULL; node = node->next)
+ editor->dragged_pad = NULL;
+
+ NodePad* pad = get_pad_at(editor->px, editor->py, editor);
+ if(pad)
+ {
+ editor->dragged_pad = pad;
+ if(pad->connected) {
+ pad->connected->connected = NULL;
+ pad->connected = NULL;
+ }
+ }
+ else
{
- if(editor->px > node->x && editor->px < node->x+node->width &&
- editor->py > node->y && editor->py < node->y+node->height)
+ EditorNode* node = editor->first_node;
+ EditorNode* focus = NULL;
+ for(;node != NULL; node = node->next)
{
- if(editor->px >= node->x+node->width-15 &&
- editor->py >= node->y+node->height-15+(node->x+node->width-editor->px))
+ if(editor->px > node->x && editor->px < node->x+node->width &&
+ editor->py > node->y && editor->py < node->y+node->height)
{
- editor->dragged_node = NULL;
- editor->resized_node = node;
+ if(editor->px >= node->x+node->width-15 &&
+ editor->py >= node->y+node->height-15+(node->x+node->width-editor->px))
+ {
+ editor->dragged_node = NULL;
+ editor->resized_node = node;
+ }
+ else
+ {
+ editor->resized_node = NULL;
+ editor->dragged_node = node;
+ }
+
+ focus = node;
}
- else
- {
- editor->resized_node = NULL;
- editor->dragged_node = node;
- }
-
- focus = node;
}
- }
- if(focus && focus->next != NULL)
- {
- if(focus == editor->first_node)
+ if(focus && focus->next != NULL)
{
- editor->first_node = focus->next;
- }
+ if(focus == editor->first_node)
+ {
+ editor->first_node = focus->next;
+ }
- EditorNode* node = editor->first_node;
+ EditorNode* node = editor->first_node;
- for(;node->next != NULL; node = node->next)
- {
- if(node->next == focus)
+ for(;node->next != NULL; node = node->next)
{
- node->next = focus->next;
+ if(node->next == focus)
+ {
+ node->next = focus->next;
+ }
}
- }
- focus->next = NULL;
- node->next = focus;
+ focus->next = NULL;
+ node->next = focus;
+ }
}
gtk_widget_queue_draw(widget);
@@ -370,6 +476,15 @@ gegl_node_widget_button_release(GtkWidget* widget, GdkEventButton* event)
editor->resized_node = NULL;
}
+ if(editor->dragged_pad)
+ {
+ NodePad* pad = get_pad_at(editor->px, editor->py, editor);
+ if(pad && pad != editor->dragged_pad) {
+ connect_pads(pad, editor->dragged_pad);
+ }
+ editor->dragged_pad = NULL;
+ }
+
return FALSE;
}
@@ -399,6 +514,7 @@ gegl_node_widget_init(GeglNodeWidget* self)
self->first_node = NULL;
self->dragged_node = NULL;
+ self->dragged_pad = NULL;
self->resized_node = NULL;
EditorNode* node = new_editor_node(NULL);
@@ -459,10 +575,10 @@ gegl_node_widget_init(GeglNodeWidget* self)
connect_pads(self->first_node->inputs, node->outputs);
/* = new_editor_node(self->first_node);
- node->x = 50;
- node = new_editor_node(node);
- node->x = 100;
- node->y = 14;*/
+ node->x = 50;
+ node = new_editor_node(node);
+ node->x = 100;
+ node->y = 14;*/
}
GtkWidget*
diff --git a/bin/editor/gegl-node-widget.h b/bin/editor/gegl-node-widget.h
index 1b3d6b7..a803c02 100644
--- a/bin/editor/gegl-node-widget.h
+++ b/bin/editor/gegl-node-widget.h
@@ -18,23 +18,24 @@ typedef struct _GeglNodeWidget GeglNodeWidget;
typedef struct _GeglNodeWidgetClass GeglNodeWidgetClass;
typedef struct _EditorNode EditorNode;
-typedef struct _NodePad NodePad;
+typedef struct _NodePad NodePad;
struct _NodePad
{
- gchar* name;
- NodePad *connected; //the pad that this is connected to. NULL if none
- NodePad *next; //the next pad in the linked list
- EditorNode* node;
+ gchar* name;
+ NodePad *connected; //the pad that this is connected to. NULL if none
+ NodePad *next; //the next pad in the linked list
+ EditorNode* node;
};
struct _EditorNode
{
gint x, y, width, height;
gchar* title;
+ gint title_height;
EditorNode *next;
- NodePad* inputs;
- NodePad* outputs;
+ NodePad* inputs;
+ NodePad* outputs;
};
EditorNode* new_editor_node(EditorNode* prev);
@@ -51,6 +52,7 @@ struct _GeglNodeWidget
EditorNode* first_node;
EditorNode* dragged_node;
EditorNode* resized_node;
+ NodePad* dragged_pad;
};
struct _GeglNodeWidgetClass
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]