[gegl/soc-2012-editor: 6/36] Can drag to connect nodes. Shows curve from node to cursor while connecting output->input



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]