gegl r2688 - in trunk: . bin



Author: ok
Date: Sun Nov  2 21:49:33 2008
New Revision: 2688
URL: http://svn.gnome.org/viewvc/gegl?rev=2688&view=rev

Log:
* bin/Makefile.am: added rules to build commands for pie menu.
* bin/editor.c: reorganized path/stroke/pie-menu interaction code to
be a statemachine,.. editor.c is getting a bit bulky. Added code
to modify existing linewidth markers. The painting code currently has
the overhead of a simple dynamics engine.
* bin/gegl-node-editor.c: (type_editor_path):
* bin/gegl-view.c: (button_press_event):


Modified:
   trunk/ChangeLog
   trunk/bin/Makefile.am
   trunk/bin/editor.c
   trunk/bin/gegl-node-editor.c
   trunk/bin/gegl-view.c

Modified: trunk/bin/Makefile.am
==============================================================================
--- trunk/bin/Makefile.am	(original)
+++ trunk/bin/Makefile.am	Sun Nov  2 21:49:33 2008
@@ -38,6 +38,15 @@
 	gegl-path-smooth.h	\
         $(gui_sources)
 
+editor.o: editor-actions.inc
+editor-actions.inc: editor.c
+        echo ''> $@
+        for action in `cat $< | grep "^static gint [0-9a-z_A-Z]* (" | sed -e 's/^.* gint //' -e 's/ .*//'`;do \
+            echo "o(\""`echo $$action | sed -e 's/_/-/g' -e 's/action-//'`"\", $$action);" >> $@; \
+        done
+
+CLEANFILES = editor-actions.inc bkl-tasks.inc
+
 
 if HAVE_SPIRO
 gegl_SOURCES += gegl-path-spiro.h gegl-path-spiro.c

Modified: trunk/bin/editor.c
==============================================================================
--- trunk/bin/editor.c	(original)
+++ trunk/bin/editor.c	Sun Nov  2 21:49:33 2008
@@ -17,6 +17,8 @@
  */
 
 
+#define ACTIVE_COLOR cairo_set_source_rgba (cr, 1.0, 0.0, 0.0, 0.5)
+#define NORMAL_COLOR cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 0.5)
 
 #include "config.h"
 
@@ -25,6 +27,7 @@
 #include <limits.h>
 #include <stdlib.h>
 #include <string.h>
+#include <math.h>
 
 #include "gegl-bin-gui-types.h"
 
@@ -51,24 +54,26 @@
 
 #include "gegl-path.h"
 
-enum 
+typedef enum 
 {
   STATE_PICK = 0,
   STATE_STROKES,
+  STATE_MOVE,
+  STATE_PAN,
   STATE_EDIT_NODES,
-  STATE_EDIT_LINEWIDTH,
+  STATE_EDIT_WIDTH,
   STATE_EDIT_OPACITY,
   STATE_FREE_REPLACE,
   STATE_REDO_PART, /* redoes part of a path, starting on
                       the first intersection */
-};
+} GuiState;
 
 
 typedef struct _Tools Tools;
 struct _Tools
 {
 /* paint core globals */
-  gint         state; /* 0: modify, 1: add strokes, 2: */
+  GuiState     state; /* 0: modify, 1: add strokes, 2: */
   
   GeglNode *node;
   GeglPath *path;
@@ -77,8 +82,9 @@
   gint      drag_sub;
   gdouble   prevx;
   gdouble   prevy;
+  guint32   prevtime;
 
-  gboolean  in_stroke;
+  gboolean  in_drag;
   /* the pie menu code is written to handle only one pie menu
    * at a time for now
    */
@@ -86,9 +92,13 @@
   gdouble   menux;
   gdouble   menuy;
 
+  GeglPath *width_path;
+
   gint      menu_segments;
+  gint      menu_segment_active;
   gchar     menu_segment_label[10][10];
   GCallback menu_segment_callback[10];
+  gpointer  menu_segment_userdata[10];
 };
 
 Tools  tools;
@@ -96,18 +106,24 @@
 static void
 menu_clear (void)
 {
+  tools.menu_segment_active = -1;
   tools.menu_segments=0;
 }
 
 static void
-menu_add (const gchar *label, GCallback callback)
+menu_add (const gchar *label, GCallback callback, gpointer userdata)
 {
   strcpy (tools.menu_segment_label[tools.menu_segments], label);
   
   tools.menu_segment_callback[tools.menu_segments]=callback;
+  tools.menu_segment_userdata[tools.menu_segments]=userdata;
   tools.menu_segments++;
+  g_assert (tools.menu_segments < 10);
 }
 
+static gint
+do_command (const gchar *command);
+
 Editor editor;
 
 static gchar *blank_composition =
@@ -121,7 +137,8 @@
 
 
 static gboolean
-path_editor_keybinding (GdkEventKey *event);
+gui_keybinding (GdkEventKey *event);
+
 
 static gboolean
 cb_window_keybinding (GtkWidget *widget, GdkEventKey *event, gpointer data)
@@ -138,13 +155,12 @@
         }
       break;
       default:
-        return path_editor_keybinding (event);
+        return gui_keybinding (event);
         break;
     }
   return FALSE;
 }
 
-
 static void gegl_node_get_translation (GeglNode *node,
                                        gdouble  *x,
                                        gdouble  *y)
@@ -228,31 +244,34 @@
     }
 }
 
-static gboolean
-path_editor_keybinding (GdkEventKey *event)
+static gint insert_node (gint argc, gchar **argv)
 {
-  if (tools.state != STATE_EDIT_NODES)
-    return FALSE;
-  switch (event->keyval)
-    {
-      case GDK_i:
-        {
-          GeglPathItem knot = *gegl_path_get (tools.path, tools.selected_no);
-          knot.point[0].x += 10;
-          gegl_path_insert (tools.path, tools.selected_no, &knot);
-          tools.selected_no ++;
-        }
-        return TRUE;
-      case GDK_BackSpace:
-        gegl_path_remove (tools.path, tools.selected_no);
-        if (tools.selected_no>0)
-          tools.selected_no --;
-        else
-          tools.selected_no = 0;
-        return TRUE;
-      case GDK_m:
-        {
-          GeglPathItem knot = *gegl_path_get (tools.path, tools.selected_no);
+  GeglPathItem knot = *gegl_path_get (tools.path, tools.selected_no);
+  knot.point[0].x += 10;
+  gegl_path_insert (tools.path, tools.selected_no, &knot);
+  tools.selected_no ++;
+  return 0;
+}
+
+static gint remove_node (gint argc, gchar **argv)
+{
+  gegl_path_remove (tools.path, tools.selected_no);
+  if (tools.selected_no>0)
+    tools.selected_no --;
+  else
+    tools.selected_no = 0;
+  return 0;
+}
+
+static gint clear_path (gint argc, gchar **argv)
+{
+  gegl_path_clear (tools.path);
+  return 0;
+}
+
+static gint spiro_mode_change (gint argc, gchar **argv)
+{
+        GeglPathItem knot = *gegl_path_get (tools.path, tools.selected_no);
           switch (knot.type)
             {
               case 'v':
@@ -273,17 +292,12 @@
             }
           g_print ("setting %c\n", knot.type);
           gegl_path_replace (tools.path, tools.selected_no, &knot);
-        }
-        return TRUE;
-      default:
-        return FALSE;
-    }
-  return FALSE;
+ 
+  return 0;
 }
 
 
 
-
 static gboolean
 fill_press_event (GtkWidget      *widget,
                   GdkEventButton *event,
@@ -311,10 +325,6 @@
   ex = (event->x + x) / scale - tx;
   ey = (event->y + y) / scale - ty;
 
-  /*cairo_translate (cr, -x, -y);
-  cairo_scale (cr, scale, scale);
-  cairo_translate (cr, tx, ty);*/
-
   gegl_node_get (tools.node, "path", &vector, NULL);
 
   gegl_path_cairo_play (vector, cr);
@@ -332,8 +342,6 @@
 #define ACTIVE_ARC 6.0
 #define INACTIVE_ARC 3.0
 
-#define ACTIVE_COLOR cairo_set_source_rgba (cr, 1.0, 0.0, 0.0, 0.5)
-#define NORMAL_COLOR cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 0.5)
 
 
           if ( i == tools.selected_no + 1)
@@ -441,6 +449,7 @@
   return FALSE;
 }
 
+
 static gboolean
 fill_release_event (GtkWidget      *widget,
                       GdkEventButton *event,
@@ -528,9 +537,11 @@
   return FALSE;
 }
 
-static gboolean cairo_expose (GtkWidget *widget,
-                              GdkEvent  *event,
-                              gpointer   user_data)
+
+
+static gboolean fill_expose (GtkWidget *widget,
+                             GdkEvent  *event,
+                             gpointer   user_data)
 {
 
   gint   x, y;
@@ -628,7 +639,6 @@
           cairo_fill (cr);
         }
 
-
       get_loc (knot, &x, &y);
       cairo_move_to (cr, x, y);
       cairo_arc (cr, x, y, ACTIVE_ARC/scale, 0.0, 3.1415*2);
@@ -648,6 +658,317 @@
   return FALSE;
 }
 
+static gboolean
+width_press_event (GtkWidget      *widget,
+                   GdkEventButton *event,
+                   gpointer        data)
+{
+  gint   x, y;
+  gdouble scale;
+  gdouble tx, ty;
+  gdouble ex, ey;
+
+  cairo_t *cr = gdk_cairo_create (widget->window);
+  GeglPath *vector;
+
+  g_object_get (G_OBJECT (widget),
+                "x", &x,
+                "y", &y,
+                "scale", &scale,
+                NULL);
+  gegl_node_get_translation (GEGL_NODE (tools.node), &tx, &ty);
+
+  ex = (event->x + x) / scale - tx;
+  ey = (event->y + y) / scale - ty;
+
+  gegl_node_get (tools.node, "path", &vector, NULL);
+
+    {
+  GeglPath *width_profile;
+  gdouble linewidth;
+  const GeglPathItem *knot;
+  gint i;
+  gint n;
+
+  gegl_node_get (tools.node, "linewidth", &linewidth, NULL);
+
+  width_profile = gegl_path_get_parameter_path (vector, "linewidth");
+
+  if (width_profile)
+    {
+      n= gegl_path_get_count (width_profile);
+      for (i=0;i<n;i++)
+        {
+          gdouble x, y;
+          knot = gegl_path_get (width_profile, i);
+          if (knot->type == '_')
+            {
+              gegl_path_calc (vector, knot->point[0].x, &x, &y);
+              cairo_new_path (cr);
+              cairo_move_to (cr, x, y);
+              cairo_arc (cr, x, y, linewidth * knot->point[0].y/2, 0, 2*3.1415);
+              if (cairo_in_fill (cr, ex, ey))
+                {
+                  if (tools.selected_no != i)
+                    gtk_widget_queue_draw (widget);
+                  tools.selected_no = i;
+                  tools.drag_no = i;
+                  tools.drag_sub = 0;
+                  tools.prevx = ex;
+                  tools.prevy = ey;
+                }
+            }
+        }
+    }
+    }
+
+  g_object_unref (vector);
+  cairo_destroy (cr);
+
+  return FALSE;
+}
+
+
+static gboolean
+width_release_event (GtkWidget      *widget,
+                     GdkEventButton *event,
+                     gpointer        data)
+{
+  tools.drag_no = -1;
+  return FALSE;
+}
+
+static gboolean
+width_motion_notify_event (GtkWidget      *widget,
+                           GdkEventMotion *event,
+                           gpointer        data)
+{
+  if (tools.drag_no != -1)
+    {
+      gint   x, y;
+      gdouble scale;
+      gdouble tx, ty;
+      gdouble ex, ey;
+      gdouble rx, ry;
+      GeglPath *width_profile;
+      gdouble linewidth;
+      const GeglPathItem *knot;
+      GeglPathItem new_knot;
+      gint i;
+      gint n;
+      gdouble cx, cy;
+
+      GeglPath *vector;
+
+      g_object_get (G_OBJECT (widget),
+                    "x", &x,
+                    "y", &y,
+                    "scale", &scale,
+                    NULL);
+      gegl_node_get_translation (tools.node, &tx, &ty);
+
+      ex = (event->x + x) / scale - tx;
+      ey = (event->y + y) / scale - ty;
+
+      rx = tools.prevx - ex;
+      ry = tools.prevy - ey;
+
+      /* get original coordinates of path point */
+
+      gegl_node_get (tools.node, "path", &vector, NULL);
+
+      gegl_node_get (tools.node, "linewidth", &linewidth, NULL);
+
+      width_profile = gegl_path_get_parameter_path (vector, "linewidth");
+
+      if (width_profile)
+        {
+          knot = gegl_path_get (width_profile, tools.drag_no);
+          if (knot->type == '_')
+            {
+              gdouble radius;
+              new_knot = *knot;
+              gegl_path_calc (vector, knot->point[0].x, &cx, &cy);
+              radius = sqrt ((ex-cx)*(ex-cx)+((ey-cy)*(ey-cy)));
+
+              new_knot.point[0].y = radius / (linewidth/2);
+              if (new_knot.point[0].y > 1.0)
+                new_knot.point[0].y = 1.0;
+              else if (new_knot.point[0].y < 0.05)
+                new_knot.point[0].y = 0.05;
+
+              gegl_path_replace (width_profile, tools.drag_no, &new_knot);
+            }
+        }
+     }
+
+  return FALSE;
+}
+
+static gboolean cairo_expose_width (GtkWidget *widget,
+                                    GdkEvent  *event,
+                                    gpointer   user_data)
+{
+
+  gint   x, y;
+  gdouble scale;
+  gdouble tx, ty;
+  gdouble linewidth;
+
+  cairo_t *cr = gdk_cairo_create (widget->window);
+  GeglPath *vector;
+  GeglPath *width_profile;
+  const GeglPathItem *knot;
+  gint i;
+  gint n;
+
+  g_object_get (G_OBJECT (widget),
+                "x", &x,
+                "y", &y,
+                "scale", &scale,
+                NULL);
+  gegl_node_get_translation (GEGL_NODE (tools.node), &tx, &ty);
+
+  cairo_translate (cr, -x, -y);
+  cairo_scale (cr, scale, scale);
+  cairo_translate (cr, tx, ty);
+
+  gegl_node_get (tools.node, "path", &vector, "linewidth", &linewidth, NULL);
+
+
+  width_profile = gegl_path_get_parameter_path (vector, "linewidth");
+  if (width_profile == NULL)
+    {
+      width_profile = gegl_path_add_parameter_path (vector, "linewidth");
+      gegl_path_append (width_profile, '_', 0.0, 0.2);
+      gegl_path_append (width_profile, '_', 10.0, 0.2);
+      gegl_path_append (width_profile, '_', 45.0, 0.7);
+      gegl_path_append (width_profile, '_', 80.0, 0.4);
+      gegl_path_append (width_profile, '_', 90.0, 1.0);
+      gegl_path_append (width_profile, '_', 120.0, 1.0);
+      gegl_path_append (width_profile, '_', 250.0, 1.0);
+      gegl_path_append (width_profile, '_', 270.0, 0.5);
+      gegl_path_append (width_profile, '_', 275.0, 0.5);
+      gegl_path_append (width_profile, '_', 280.0, 1.0);
+    }
+
+  cairo_new_path (cr);
+  gegl_path_cairo_play (vector, cr);
+
+  cairo_set_line_width (cr, 3.5/scale);
+  cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 1.0);
+  cairo_stroke_preserve (cr);
+  cairo_set_line_width (cr, 2.0/scale);
+  cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 0.5);
+  cairo_stroke (cr);
+
+    {
+      n= gegl_path_get_count (width_profile);
+      for (i=0;i<n;i++)
+        {
+          gdouble x, y;
+          knot = gegl_path_get (width_profile, i);
+          if (knot->type == '_')
+            {
+              gegl_path_calc (vector, knot->point[0].x, &x, &y);
+              cairo_new_path (cr);
+              cairo_move_to (cr, x, y);
+              cairo_arc (cr, x, y, linewidth * knot->point[0].y/2, 0, 2*3.1415);
+
+              if ( i == tools.selected_no)
+                {
+                  ACTIVE_COLOR;
+                }
+              else
+                {
+                  NORMAL_COLOR;
+                }
+
+              cairo_fill (cr);
+            }
+        }
+    }
+
+  g_object_unref (vector);
+
+  cairo_destroy (cr);
+  return FALSE;
+}
+
+static gboolean
+gui_keybinding (GdkEventKey *event)
+{
+  switch (tools.state)
+    {
+      case STATE_PICK:
+        return FALSE;
+      case STATE_EDIT_NODES:
+        switch (event->keyval)
+          {
+            case GDK_i: do_command ("insert-node"); return TRUE;
+            case GDK_BackSpace: do_command ("remove-node"); return TRUE;
+            case GDK_s: do_command ("spiro-mode-change"); return TRUE;
+            default:
+              return FALSE;
+          }
+      default:
+        break;
+    }
+  return FALSE;
+}
+
+static void path_slice (cairo_t *cr,
+                        gint x, gint y,
+                        gint inner, gint outher,
+                        gdouble adjustment,
+                        gint segment, gint n)
+{
+  gdouble margin = 0.05 * (3.1415*2)/n;
+
+  cairo_new_path (cr);
+  cairo_arc (cr, x, y, outher, segment*(3.1415*2)/n + margin, (segment+1)*(3.1415*2)/n -margin);
+  margin *= adjustment;
+  cairo_arc_negative (cr, x, y, inner, (segment+1)*(3.1415*2)/n - margin, (segment)*(3.1415*2)/n + margin);
+  cairo_close_path (cr);
+}
+
+static gint set_state (gint argc, char **argv)
+{
+  if (argv[1]==NULL)
+    return 0;
+  tools.drag_no = -1;
+  if (g_str_equal (argv[1], "pick"))
+    {
+      tools.state = STATE_PICK;
+      gtk_widget_queue_draw (editor.view);
+    }
+  else if (g_str_equal (argv[1], "move"))
+    {
+      tools.state = STATE_MOVE;
+      gtk_widget_queue_draw (editor.view);
+    }
+  else if (g_str_equal (argv[1], "strokes"))
+    {
+      tools.state = STATE_STROKES;
+      gtk_widget_queue_draw (editor.view);
+    }
+  else if (g_str_equal (argv[1], "edit-nodes"))
+    {
+      tools.state = STATE_EDIT_NODES;
+      gtk_widget_queue_draw (editor.view);
+    }
+  else if (g_str_equal (argv[1], "edit-width"))
+    {
+      tools.state = STATE_EDIT_WIDTH;
+      gtk_widget_queue_draw (editor.view);
+    }
+  else
+    {
+      g_warning ("doesn't handle state change to %s\n", argv[1]);
+      return -1;
+    }
+  return 0;
+}
 
 static gboolean cairo_gui_expose (GtkWidget *widget,
                                   GdkEvent  *event,
@@ -655,14 +976,46 @@
 {
   switch (tools.state)
     {
+      case STATE_MOVE:
       case STATE_PICK:
+        {
+          gint x, y;
+          gdouble scale;
+          gdouble tx, ty;
+          cairo_t *cr = gdk_cairo_create (widget->window);
+          cairo_save (cr);
+          g_object_get (G_OBJECT (widget),
+                        "x", &x,
+                        "y", &y,
+                        "scale", &scale,
+                        NULL);
+
+          if (tools.node)
+            {
+              GeglRectangle bounds;
+          gegl_node_get_translation (GEGL_NODE (tools.node), &tx, &ty);
+
+          cairo_translate (cr, -x, -y);
+          if(1)cairo_scale (cr, scale, scale);
+          cairo_translate (cr, tx, ty);
+              ACTIVE_COLOR;
+              bounds = gegl_node_get_bounding_box (tools.node);
+              cairo_rectangle (cr, bounds.x, bounds.y, bounds.width, bounds.height);
+              cairo_stroke (cr);
+            }
+          cairo_restore (cr);
+
+          cairo_destroy (cr);
+        }
         break;
       case STATE_EDIT_NODES:
-        cairo_expose (widget, event, user_data);
+        fill_expose (widget, event, user_data);
+        break;
+      case STATE_EDIT_WIDTH:
+        cairo_expose_width (widget, event, user_data);
         break;
       case STATE_STROKES:
         break;
-      case STATE_EDIT_LINEWIDTH:
       case STATE_EDIT_OPACITY:
       case STATE_FREE_REPLACE:
       default:
@@ -708,20 +1061,25 @@
         for (segment=0;segment<segments;segment++)
           {
             cairo_text_extents_t text_extents;
-            gdouble margin = 0.05 * (3.1415*2)/segments;
-            cairo_new_path (cr);
-            cairo_arc (cr, x, y, outher, segment*(3.1415*2)/segments + margin, (segment+1)*(3.1415*2)/segments -margin);
-            margin *= adjustment;
-            cairo_arc_negative (cr, x, y, inner, (segment+1)*(3.1415*2)/segments - margin, (segment)*(3.1415*2)/segments + margin);
-            cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 1.0);
-            cairo_stroke_preserve (cr);
-            cairo_set_source_rgba (cr, 0.0, 1.0, 1.0, 1.0);
-            cairo_fill (cr);
+
+            cairo_save (cr);
+            path_slice (cr, x, y, inner, outher, adjustment, segment, segments);
+
+            cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 0.7);
+            if (segment == tools.menu_segment_active)
+              ACTIVE_COLOR;
+            cairo_fill_preserve (cr);
+
+            cairo_set_line_width (cr, 4.0);
+            cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 0.2);
+            cairo_clip_preserve (cr);
+            cairo_stroke (cr);
+            cairo_restore (cr);
 
             cairo_new_path (cr);
             cairo_arc (cr, x, y, middle, (segment+0.5)*(3.1415*2)/segments,
                                          (segment+0.5)*(3.1415*2)/segments);
-            cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 1.0);
+            cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 1.0);
 
             cairo_select_font_face (cr, "Sans", CAIRO_FONT_SLANT_NORMAL,
                                                 CAIRO_FONT_WEIGHT_NORMAL);
@@ -765,7 +1123,8 @@
 
   gegl_path_clear (vector);
   gegl_path_append (vector, 'M', ex, ey);
-  tools.in_stroke = TRUE;
+  tools.in_drag = TRUE;
+  tools.width_path = gegl_path_add_parameter_path (vector, "linewidth");
   g_object_unref (vector);
   return TRUE;
 }
@@ -808,7 +1167,7 @@
       tools.node = stroke;
     }
 
-  tools.in_stroke = FALSE;
+  tools.in_drag = FALSE;
   return FALSE;
 }
 
@@ -818,13 +1177,15 @@
                             GdkEventMotion *event,
                             gpointer        data)
 {
-  if (tools.in_stroke)
+  static gint foo = 0;
+  if (tools.in_drag)
     {
       gint   x, y;
       gdouble scale;
       gdouble tx, ty;
       gdouble ex, ey;
       gdouble rx, ry;
+      foo ++;
 
       g_object_get (G_OBJECT (widget),
                     "x", &x,
@@ -841,8 +1202,29 @@
 
       gegl_path_append (tools.path, 'L', ex, ey);
 
+      if(foo%3==0){
+        gdouble magnitude = 1.0;
+
+        gdouble rt = (event->time - tools.prevtime)/1000.0;
+        gdouble speed = sqrt (rx*rx + ry*ry)/rt;
+#define MAXS 400
+
+        if (speed > MAXS )
+          speed = MAXS ;
+        magnitude = 1.0-(speed / MAXS);
+        if (magnitude > 1.0)
+          magnitude = 1.0;
+
+        magnitude = pow (magnitude, 0.2);
+        if (magnitude < 0.05)
+          magnitude = 0.05;
+
+        gegl_path_append (tools.width_path, '_', -1.0, magnitude);
+      }
+
       tools.prevx = ex;
       tools.prevy = ey;
+      tools.prevtime = event->time;
       return TRUE;
 
     }
@@ -876,9 +1258,38 @@
             tools.menux = (event->x + x);
             tools.menuy = (event->y + y);
             menu_clear ();
-            menu_add ("foo", NULL);
-            menu_add ("bar", NULL);
-            menu_add ("baz", NULL);
+
+            
+            switch (tools.state)
+              {
+                case STATE_PICK:
+                  menu_add ("paint", G_CALLBACK (do_command), "set-state strokes");
+                  menu_add ("path",  G_CALLBACK (do_command), "set-state edit-nodes");
+                  menu_add ("width",  G_CALLBACK (do_command), "set-state edit-width");
+                  menu_add ("move",  G_CALLBACK (do_command), "set-state move");
+                  /* check the current curve type,. */
+                  break;
+                case STATE_EDIT_NODES:
+                  menu_add ("+", G_CALLBACK (do_command), "insert-node");
+                  menu_add ("del", G_CALLBACK (do_command), "remove-node");
+                  menu_add ("--", G_CALLBACK (do_command), "help");
+                  menu_add ("smooth", G_CALLBACK (do_command), "help");
+                  menu_add ("spiro", G_CALLBACK (do_command), "help");
+                  menu_add ("pick", G_CALLBACK (do_command), "set-state pick");
+                  break;
+                case STATE_EDIT_WIDTH:
+                case STATE_STROKES:
+                case STATE_EDIT_OPACITY:
+                case STATE_FREE_REPLACE:
+                default:
+                  menu_add ("paint", G_CALLBACK (do_command), "set-state strokes");
+                  menu_add ("path",  G_CALLBACK (do_command), "set-state edit-nodes");
+                  menu_add ("width",  G_CALLBACK (do_command), "set-state edit-width");
+                  menu_add ("move",  G_CALLBACK (do_command), "set-state move");
+                  menu_add ("pick", G_CALLBACK (do_command), "set-state pick");
+                  break;
+              }
+
           }
       gtk_widget_queue_draw (widget);
       return TRUE;
@@ -887,12 +1298,48 @@
   switch (tools.state)
     {
       case STATE_PICK:
+      case STATE_MOVE:
+        {
+          GeglNode *node;
+          GeglNode *detected;
+          gint   x, y;
+          gdouble scale;
+          gdouble tx, ty, ex, ey;
+
+          g_object_get (G_OBJECT (widget),
+                        "x", &x,
+                        "y", &y,
+                        "scale", &scale,
+                        "node", &node,
+                      NULL);
+          detected = gegl_node_detect (node, (x + event->x) / scale,
+                                             (y + event->y) / scale);
+
+
+
+          gegl_node_get_translation (GEGL_NODE (tools.node), &tx, &ty);
+
+          ex = (event->x + x) / scale - tx;
+          ey = (event->y + y) / scale - ty;
+
+          tools.prevx = ex;
+          tools.prevy = ey;
+          tools.prevtime = event->time;
+
+          g_object_unref (node);
+          if (detected)
+            {
+              tree_editor_set_active (editor.tree_editor, detected);
+            }
+          tools.in_drag = TRUE;
+        }
         break;
       case STATE_EDIT_NODES:
         return fill_press_event (widget, event, data);
+      case STATE_EDIT_WIDTH:
+        return width_press_event (widget, event, data);
       case STATE_STROKES:
         return stroke_press_event (widget, event, data);
-      case STATE_EDIT_LINEWIDTH:
       case STATE_EDIT_OPACITY:
       case STATE_FREE_REPLACE:
       default:
@@ -903,21 +1350,123 @@
   return FALSE;
 }
 
+static void move_rel (GeglNode *node,
+                      gdouble   relx,
+                      gdouble   rely)
+{
+  GeglNode *shift;
+ 
+  for (shift = node; shift && !g_str_equal (gegl_node_get_operation (shift), "gegl:shift");shift=gegl_previous_sibling (shift))
+    {
+    }
+
+  if (!shift)
+    {
+      shift = gegl_add_sibling ("gegl:shift");
+        {
+
+          GtkTreeSelection *selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tree_editor_get_treeview (editor.tree_editor)));
+          GtkTreeIter iter;
+          iter.user_data = node;
+          gtk_tree_selection_select_iter (selection, &iter);
+        }
+    }
+    {
+      gdouble x, y;
+      gegl_node_get (shift, "x", &x, "y", &y, NULL);
+      x+=relx;
+      y+=rely;
+      gegl_node_set (shift, "x", x, "y", y, NULL);
+    }
+}
 
 static gboolean
 gui_motion_event (GtkWidget      *widget,
                   GdkEventMotion *event,
                   gpointer        data)
 {
+  if (tools.menu_active)
+    {
+      gint segment;
+      gint segments = tools.menu_segments;
+
+      gint inner = 35;
+      gint outher = 100;
+      gdouble adjustment = 3.0; /* adjustments to make the margin produce
+                                   a straight line from the centre
+                                   (set by trial and error) */
+
+      gint x, y;
+      gdouble scale;
+      cairo_t *cr = gdk_cairo_create (widget->window);
+      g_object_get (G_OBJECT (widget),
+                    "x", &x,
+                    "y", &y,
+                    "scale", &scale,
+                    NULL);
+
+      {
+        gboolean found_it = FALSE;
+        for (segment=0;segment<segments;segment++)
+          {
+            path_slice (cr, tools.menux, tools.menuy, inner/3, outher, adjustment, segment, segments);
+
+            if (cairo_in_fill (cr, event->x + x, event->y + y))
+              {
+                if (tools.menu_segment_active != segment)
+                  {
+                    tools.menu_segment_active = segment;
+                    gtk_widget_queue_draw (widget);
+                  }
+               found_it = TRUE;
+               break;
+             }
+          }
+        if (!found_it)
+          {
+            if (tools.menu_segment_active != -1)
+              gtk_widget_queue_draw (widget);
+            tools.menu_segment_active = -1;
+          }
+      }
+      cairo_destroy (cr);
+    }
+
   switch (tools.state)
     {
       case STATE_PICK:
         break;
+      case STATE_MOVE:
+        if (tools.in_drag)
+          {
+            gint   x, y;
+            gdouble scale;
+            gdouble tx, ty, ex, ey;
+
+            g_object_get (G_OBJECT (widget),
+                          "x", &x,
+                          "y", &y,
+                          "scale", &scale,
+                          NULL);
+
+            gegl_node_get_translation (GEGL_NODE (tools.node), &tx, &ty);
+
+            ex = (event->x + x) / scale - tx;
+            ey = (event->y + y) / scale - ty;
+
+            move_rel (tools.node, ex-tools.prevx, ey-tools.prevy);
+
+
+            tools.prevx = ex;
+            tools.prevy = ey;
+          }
+        break;
       case STATE_STROKES:
         return stroke_motion_notify_event (widget, event, data);
       case STATE_EDIT_NODES:
         return fill_motion_notify_event (widget, event, data);
-      case STATE_EDIT_LINEWIDTH:
+      case STATE_EDIT_WIDTH:
+        return width_motion_notify_event (widget, event, data);
       case STATE_EDIT_OPACITY:
       case STATE_FREE_REPLACE:
       default:
@@ -933,15 +1482,34 @@
                    GdkEventButton *event,
                    gpointer        data)
 {
+  if (tools.menu_active)
+      {
+        gint active = tools.menu_segment_active;
+
+        tools.menu_active = FALSE;
+        if (active >= 0)
+          {
+            void (*cb) (gpointer) = (void*)tools.menu_segment_callback[active];
+
+            if (cb)
+             cb (tools.menu_segment_userdata[active]);
+          }
+        gtk_widget_queue_draw (widget);
+      }
+
   switch (tools.state)
     {
+      case STATE_MOVE:
+        tools.in_drag=FALSE;
+        break;
       case STATE_PICK:
         break;
       case STATE_EDIT_NODES:
         return fill_release_event (widget, event, data);
       case STATE_STROKES:
         return stroke_release_event (widget, event, data);
-      case STATE_EDIT_LINEWIDTH:
+      case STATE_EDIT_WIDTH:
+        return width_release_event (widget, event, data);
       case STATE_EDIT_OPACITY:
       case STATE_FREE_REPLACE:
       default:
@@ -960,6 +1528,7 @@
     return;
 
   opname = gegl_node_get_operation (node);
+  tools.node = node;
 
   if (g_str_equal (opname, "gegl:fill"))
     {
@@ -967,61 +1536,32 @@
       gegl_node_get (node, "path", &vector, NULL);
 
       tools.path = vector;
-      tools.node = node;
 
       g_object_unref (vector);
-      tools.state = STATE_EDIT_NODES;
     }
    else if(g_str_equal (opname, "gegl:stroke"))
     {
       GeglPath *vector;
       gegl_node_get (node, "path", &vector, NULL);
-      if (!vector)
+      if (vector)
+        {
+          tools.path = vector;
+          g_object_unref (vector);
+        }
+      else
         {
           vector = gegl_path_new ();
           gegl_node_set (node, "path", vector, NULL);
+          tools.path = vector;
         }
-      tools.path = vector;
-      tools.node = node;
-      g_object_unref (vector);
-      tools.state = STATE_STROKES;
     }
   else
     {
-      tools.state = STATE_PICK;
       tools.path = NULL;
     }
   gtk_widget_queue_draw (GTK_WIDGET (view));
 }
 
-
-
-static void cb_detected_event (GeglView *view,
-                               GeglNode *node,
-                               gpointer  userdata)
-{
-#if 0
-  gchar *name;
-  gchar *operation;
-
-  gegl_node_get (node, "name", &name, "operation", &operation, NULL);
-  g_print ("%s: %p %s:%s(%p)\n", G_STRLOC, view, operation, name, node);
-
-
-  if (g_str_equal (operation, "gegl:fill"))
-    {
-      GeglPath *vector;
-
-      gegl_node_get (node, "path", &vector, NULL);
-      g_object_unref (vector);
-    }
-
-  g_free (name);
-  g_free (operation);
-#endif
-  tree_editor_set_active (GTK_WIDGET (userdata), node);
-}
-
 static void editor_set_gegl (GeglNode    *gegl);
 static GtkWidget *create_menubar (Editor *editor);
 static GtkWidget *
@@ -1086,9 +1626,6 @@
   gtk_widget_set_size_request (property_scroll, -1, 100);
   gtk_widget_set_size_request (view, 89, 55);
 
-  g_signal_connect (view, "detected",
-                    G_CALLBACK (cb_detected_event), editor->tree_editor);
-
   g_signal_connect (self, "delete-event",
                     G_CALLBACK (cb_window_delete_event), NULL);
 
@@ -2178,3 +2715,66 @@
 {
   gegl_view_repaint (GEGL_VIEW (editor.view));
 }
+
+
+typedef struct Command {
+  gchar *command;
+  gint (*callback) (gint argc, gchar **argv);
+} Command;
+
+static GList *commands = NULL;
+
+static gint help (gint argc, gchar **argv)
+{
+  GList *iter;
+  g_print ("Available commands:\n  ");
+  for (iter=commands;iter;iter=iter->next)
+    {
+      Command *c = iter->data;
+      g_print ("%s ", c->command);
+    }
+  g_print ("\n");
+  return 0;
+}
+
+static gint
+do_command_argv (gint argc, gchar **argv)
+{
+  GList *iter;
+  if (commands == NULL)
+    {
+      #define o(cmd, cb) do{Command *c=g_new0(Command, 1);\
+        c->command=g_strdup(cmd);\
+        c->callback=(void*)(cb);\
+        commands = g_list_append (commands, c);\
+      }while(0)
+      #include "editor-actions.inc"
+      #undef o
+    }
+  for (iter=commands;iter;iter=iter->next)
+    {
+      Command *c = iter->data;
+      if (g_str_equal (c->command, argv[0]))
+        {
+          return c->callback (argc, argv);
+        }
+    }
+  g_print ("unknown command %s\n", argv[0]);
+  return help(0, NULL);
+}
+
+static gint
+do_command (const gchar *command)
+{
+  gint    argc;
+  gint    retval;
+  gchar **argv = NULL;
+
+  if (command[0] == '\0')
+    return FALSE;
+
+  g_shell_parse_argv (command, &argc, &argv, NULL);
+  retval = do_command_argv (argc, argv);
+  g_strfreev (argv);
+  return retval;
+}

Modified: trunk/bin/gegl-node-editor.c
==============================================================================
--- trunk/bin/gegl-node-editor.c	(original)
+++ trunk/bin/gegl-node-editor.c	Sun Nov  2 21:49:33 2008
@@ -855,9 +855,12 @@
       GeglPath *vector;
 
       gegl_node_get (node, param_spec->name, &vector, NULL);
-      value = gegl_path_to_string (vector);
-      gtk_entry_set_text (GTK_ENTRY (entry), value);
-      g_object_unref (vector);
+      if (vector)
+        {
+          value = gegl_path_to_string (vector);
+          gtk_entry_set_text (GTK_ENTRY (entry), value);
+          g_object_unref (vector);
+        }
       g_free (value);
     }
 

Modified: trunk/bin/gegl-view.c
==============================================================================
--- trunk/bin/gegl-view.c	(original)
+++ trunk/bin/gegl-view.c	Sun Nov  2 21:49:33 2008
@@ -315,6 +315,8 @@
   gint      x    = event->x;
   gint      y    = event->y;
 
+  return FALSE;
+
   priv->screen_x = x;
   priv->screen_y = y;
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]