[gegl] ui: code reorganization



commit 81b6184f71427aed9705e31066e33842f9ffc9b5
Author: Oyvind Kolas <pippin gimp org>
Date:   Mon Jul 27 00:57:11 2015 +0200

    ui: code reorganization
    
    Adjusted order of functions so that the most important ones for reading the
    code comes earlier.

 bin/mrg-ui.c | 1316 +++++++++++++++++++++++++++++-----------------------------
 1 files changed, 664 insertions(+), 652 deletions(-)
---
diff --git a/bin/mrg-ui.c b/bin/mrg-ui.c
index b56ca5f..d3c36b2 100644
--- a/bin/mrg-ui.c
+++ b/bin/mrg-ui.c
@@ -13,7 +13,7 @@
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
- * Copyright (C) 2015 Øyvind Kolås
+ * Copyright (C) 2015 Øyvind Kolås pippin gimp org
  */
 
 #define _BSD_SOURCE
@@ -83,6 +83,545 @@ struct _State {
 void   gegl_meta_set (const char *path, const char *meta_data);
 char * gegl_meta_get (const char *path);
 
+static char *suffix_path (const char *path);
+static char *unsuffix_path (const char *path);
+static int is_giev_path (const char *path);
+
+static void contrasty_stroke (cairo_t *cr);
+
+static void mrg_gegl_blit (Mrg *mrg,
+                          float x0, float y0,
+                          float width, float height,
+                          GeglNode *node,
+                          float u, float v,
+                          float scale,
+                           float preview_multiplier);
+
+static void load_path (State *o);
+
+static void go_next (State *o);
+static void go_prev (State *o);
+
+
+static void go_next_cb (MrgEvent *event, void *data1, void *data2);
+static void go_prev_cb (MrgEvent *event, void *data1, void *data2);
+
+static void leave_editor (State *o);
+
+static void drag_preview (MrgEvent *e);
+static void load_into_buffer (State *o, const char *path);
+
+static GeglNode *locate_node (State *o, const char *op_name);
+
+static void zoom_to_fit (State *o);
+
+static void zoom_to_fit_buffer (State *o);
+
+static void zoom_fit_cb (MrgEvent *e, void *data1, void *data2);
+static int deferred_zoom_to_fit (Mrg *mrg, void *data);
+
+static void pan_left_cb (MrgEvent *event, void *data1, void *data2);
+
+static void pan_right_cb (MrgEvent *event, void *data1, void *data2);
+
+static void pan_down_cb (MrgEvent *event, void *data1, void *data2);
+
+static void pan_up_cb (MrgEvent *event, void *data1, void *data2);
+
+static void get_coords (State *o, float screen_x, float screen_y, float *gegl_x, float *gegl_y);
+
+static void preview_more_cb (MrgEvent *event, void *data1, void *data2);
+
+static void preview_less_cb (MrgEvent *event, void *data1, void *data2);
+
+static void zoom_1_cb (MrgEvent *event, void *data1, void *data2);
+
+static void zoom_in_cb (MrgEvent *event, void *data1, void *data2);
+
+static void zoom_out_cb (MrgEvent *event, void *data1, void *data2);
+
+static void toggle_actions_cb (MrgEvent *event, void *data1, void *data2);
+
+static void toggle_fullscreen_cb (MrgEvent *event, void *data1, void *data2);
+
+
+static void activate_op_cb (MrgEvent *event, void *data1, void *data2);
+
+
+static void disable_filter_cb (MrgEvent *event, void *data1, void *data2);
+
+static void apply_filter_cb (MrgEvent *event, void *data1, void *data2);
+static void discard_cb (MrgEvent *event, void *data1, void *data2);
+static void save_cb (MrgEvent *event, void *data1, void *data2);
+
+
+
+
+static void toggle_show_controls_cb (MrgEvent *event, void *data1, void *data2);
+
+static void gegl_ui (Mrg *mrg, void *data);
+int mrg_ui_main (int argc, char **argv);
+
+void gegl_meta_set (const char *path, const char *meta_data);
+char * gegl_meta_get (const char *path); 
+
+static State *hack_state = NULL;  // XXX: this shoudl be factored away
+
+int mrg_ui_main (int argc, char **argv)
+{
+  Mrg *mrg = mrg_new (1024, 768, NULL);
+  State o = {NULL,};
+#ifdef USE_MIPMAPS
+  g_setenv ("GEGL_MIPMAP_RENDERING", "1", TRUE);
+#endif
+  g_setenv ("BABL_TOLERANCE", "0.1", TRUE);
+
+  gegl_init (&argc, &argv);
+  o.gegl           = gegl_node_new ();
+  o.mrg            = mrg;
+  o.scale          = 1.0;
+  o.render_quality = 1.0;
+  o.preview_quality = 4.0;
+
+  if (access (argv[1], F_OK) != -1)
+    o.path = strdup (argv[1]);
+  else
+    {
+      printf ("usage: %s <full-path-to-image>\n", argv[0]);
+      return -1;
+    }
+
+  load_path (&o);
+  mrg_set_ui (mrg, gegl_ui, &o);
+  hack_state = &o;  
+  mrg_main (mrg);
+
+  g_object_unref (o.gegl);
+  if (o.buffer)
+  {
+    g_object_unref (o.buffer);
+    o.buffer = NULL;
+  }
+  gegl_exit ();
+  return 0;
+}
+
+static void on_pan_drag (MrgEvent *e, void *data1, void *data2)
+{
+  State *o = data1;
+  if (e->type == MRG_DRAG_MOTION)
+  {
+    o->u -= (e->delta_x );
+    o->v -= (e->delta_y );
+    mrg_queue_draw (e->mrg, NULL);
+  }
+  drag_preview (e);
+}
+
+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_queue_draw (e->mrg, NULL);
+}
+
+static void draw_gegl_generic (State *state, Mrg *mrg, cairo_t *cr, GeglNode *node)
+{
+  const gchar* op_name = gegl_node_get_operation (node);
+  mrg_set_edge_left (mrg, mrg_width (mrg) * 0.1);
+  mrg_set_edge_top  (mrg, mrg_height (mrg) * 0.1);
+  mrg_set_font_size (mrg, mrg_height (mrg) * 0.07);
+  mrg_set_style (mrg, "color:white; background-color: transparent");
+
+  cairo_save (cr);
+  mrg_printf (mrg, "%s\n", op_name);
+  {
+    guint n_props;
+    GParamSpec **pspecs = gegl_operation_list_properties (op_name, &n_props);
+
+    if (pspecs)
+    {
+      int tot_pos = 0;
+      int pos_no = 0;
+
+      for (gint i = 0; i < n_props; i++)
+      {
+        if (g_type_is_a (pspecs[i]->value_type, G_TYPE_DOUBLE) ||
+            g_type_is_a (pspecs[i]->value_type, G_TYPE_INT) ||
+            g_type_is_a (pspecs[i]->value_type, G_TYPE_STRING) ||
+            g_type_is_a (pspecs[i]->value_type, G_TYPE_BOOLEAN))
+          tot_pos ++;
+      }
+
+      for (gint i = 0; i < n_props; i++)
+      {
+        mrg_set_xy (mrg, mrg_em(mrg), mrg_height (mrg) - mrg_em (mrg) * ((tot_pos-pos_no)));
+
+        if (g_type_is_a (pspecs[i]->value_type, G_TYPE_DOUBLE))
+        {
+          float xpos;
+          GeglParamSpecDouble *geglspec = (void*)pspecs[i];
+          gdouble value;
+          gegl_node_get (node, pspecs[i]->name, &value, NULL);
+
+          cairo_rectangle (cr, 0,
+             mrg_height (mrg) - mrg_em (mrg) * ((tot_pos-pos_no+1)),
+             mrg_width (mrg), mrg_em(mrg));
+          cairo_set_source_rgba (cr, 0,0,0, 0.5);
+
+          mrg_listen (mrg, MRG_DRAG, prop_double_drag_cb, node,(void*)pspecs[i]);
+
+          cairo_fill (cr);
+          xpos = (value - geglspec->ui_minimum) / (geglspec->ui_maximum - geglspec->ui_minimum);
+          cairo_rectangle (cr, xpos * mrg_width(mrg) - mrg_em(mrg)/4,
+              mrg_height (mrg) - mrg_em (mrg) * ((tot_pos-pos_no+1)),
+              mrg_em(mrg)/2, mrg_em(mrg));
+          cairo_set_source_rgba (cr, 1,1,1, 0.5);
+          cairo_fill (cr);
+
+          mrg_printf (mrg, "%s:%f\n", pspecs[i]->name, value);
+          pos_no ++;
+        }
+        else if (g_type_is_a (pspecs[i]->value_type, G_TYPE_INT))
+        {
+          gint value;
+          gegl_node_get (node, pspecs[i]->name, &value, NULL);
+          mrg_printf (mrg, "%s:%i\n", pspecs[i]->name, value);
+          pos_no ++;
+        }
+        else if (g_type_is_a (pspecs[i]->value_type, G_TYPE_STRING))
+        {
+          char *value = NULL;
+          gegl_node_get (node, pspecs[i]->name, &value, NULL);
+          pos_no ++;
+          mrg_printf (mrg, "%s:%s\n", pspecs[i]->name, value);
+          if (value) g_free (value);
+        }
+        else if (g_type_is_a (pspecs[i]->value_type, G_TYPE_BOOLEAN))
+        {
+          gboolean value = FALSE;
+          gegl_node_get (node, pspecs[i]->name, &value, NULL);
+          pos_no ++;
+          mrg_printf (mrg, "%s:%i\n", pspecs[i]->name, value);
+        }
+        
+      }
+      g_free (pspecs);
+    }
+  }
+
+  cairo_restore (cr);
+  mrg_set_style (mrg, "color:yellow; background-color: transparent");
+}
+
+static void crop_drag_ul (MrgEvent *e, void *data1, void *data2)
+{
+  GeglNode *node = data1;
+  double x,y,width,height;
+  double x0, y0, x1, y1;
+  gegl_node_get (node, "x", &x, "y", &y, "width", &width, "height", &height, NULL);
+  x0 = x; y0 = y; x1 = x0 + width; y1 = y + height;
+
+  if (e->type == MRG_DRAG_MOTION)
+  {
+    x0 += e->delta_x;
+    y0 += e->delta_y;
+
+    x=x0;
+    y=y0;
+    width = x1 - x0;
+    height = y1 - y0;
+    gegl_node_set (node, "x", x, "y", y, "width", width, "height", height, NULL);
+
+    mrg_queue_draw (e->mrg, NULL);
+  }
+
+  drag_preview (e);
+}
+
+static void crop_drag_lr (MrgEvent *e, void *data1, void *data2)
+{
+  GeglNode *node = data1;
+  double x,y,width,height;
+  double x0, y0, x1, y1;
+  gegl_node_get (node, "x", &x, "y", &y, "width", &width, "height", &height, NULL);
+  x0 = x; y0 = y; x1 = x0 + width; y1 = y + height;
+
+  if (e->type == MRG_DRAG_MOTION)
+  {
+    x1 += e->delta_x;
+    y1 += e->delta_y;
+
+    x=x0;
+    y=y0;
+    width = x1 - x0;
+    height = y1 - y0;
+    gegl_node_set (node, "x", x, "y", y, "width", width, "height", height, NULL);
+
+    mrg_queue_draw (e->mrg, NULL);
+  }
+
+  drag_preview (e);
+}
+
+static void crop_drag_rotate (MrgEvent *e, void *data1, void *data2)
+{
+  State *o = hack_state;
+  double degrees;
+  gegl_node_get (o->rotate, "degrees", &degrees, NULL);
+
+  if (e->type == MRG_DRAG_MOTION)
+  {
+    degrees += e->delta_x / 100.0;
+
+    gegl_node_set (o->rotate, "degrees", degrees, NULL);
+
+    mrg_queue_draw (e->mrg, NULL);
+  }
+
+  drag_preview (e);
+}
+
+static void draw_gegl_crop (State *o, Mrg *mrg, cairo_t *cr, GeglNode *node)
+{
+  const gchar* op_name = gegl_node_get_operation (node);
+  float dim = mrg_height (mrg) * 0.1 / o->scale;
+  double x,y,width,height;
+  double x0, y0, x1, y1;
+
+  mrg_set_edge_left (mrg, mrg_width (mrg) * 0.1);
+  mrg_set_edge_top  (mrg, mrg_height (mrg) * 0.1);
+  mrg_set_font_size (mrg, mrg_height (mrg) * 0.07);
+  mrg_set_style (mrg, "color:white; background-color: transparent");
+
+  cairo_save (cr);
+  mrg_printf (mrg, "%s\n", op_name);
+
+  cairo_translate (cr, -o->u, -o->v);
+  cairo_scale (cr, o->scale, o->scale);
+
+  gegl_node_get (node, "x", &x, "y", &y, "width", &width, "height", &height, NULL);
+  x0 = x; y0 = y; x1 = x0 + width; y1 = y + height;
+
+  cairo_rectangle (cr, x0, y0, dim, dim);
+  mrg_listen (mrg, MRG_DRAG, crop_drag_ul, node, NULL);
+  contrasty_stroke (cr);
+
+  cairo_rectangle (cr, x1-dim, y1-dim, dim, dim);
+  mrg_listen (mrg, MRG_DRAG, crop_drag_lr, node, NULL);
+  contrasty_stroke (cr);
+
+  cairo_rectangle (cr, x0+dim, y0+dim, width-dim-dim, height-dim-dim);
+  mrg_listen (mrg, MRG_DRAG, crop_drag_rotate, node, NULL);
+  cairo_new_path (cr);
+
+  cairo_restore (cr);
+  mrg_set_style (mrg, "color:yellow; background-color: transparent");
+}
+
+static void ui_op_draw_apply_disable (State *o)
+{
+  Mrg *mrg = o->mrg;
+  mrg_set_font_size (mrg, mrg_height (mrg) * 0.1);
+  mrg_set_xy (mrg, 0, mrg_em(mrg));
+  mrg_text_listen (mrg, MRG_PRESS, disable_filter_cb, o, NULL);
+  mrg_printf (mrg, "X");
+  mrg_text_listen_done (mrg);
+  mrg_set_xy (mrg, mrg_width(mrg) - mrg_em (mrg), mrg_em(mrg));
+  mrg_text_listen (mrg, MRG_PRESS, apply_filter_cb, o, NULL);
+  mrg_printf (mrg, "O");
+  mrg_text_listen_done (mrg);
+}
+
+static void ui_active_op (State *o)
+{
+  Mrg *mrg = o->mrg;
+  cairo_t *cr = mrg_cr (mrg);
+  char *opname = NULL;
+  g_object_get (o->active, "operation", &opname, NULL);
+
+  if (!strcmp (opname, "gegl:crop")) {
+    zoom_to_fit_buffer (o);
+    draw_gegl_crop (o, mrg, cr, o->active);
+    ui_op_draw_apply_disable (o);
+  }
+  else
+  {
+    draw_gegl_generic (o, mrg, cr, o->active);
+    ui_op_draw_apply_disable (o);
+  }
+}
+
+static void ui_debug_op_chain (State *o)
+{
+  Mrg *mrg = o->mrg;
+  GeglNode *iter;
+  mrg_set_edge_top  (mrg, mrg_height (mrg) * 0.2);
+  iter = o->sink;
+  while (iter)
+   {
+     char *opname = NULL;
+     g_object_get (iter, "operation", &opname, NULL);
+     if (iter == o->active)
+       mrg_printf (mrg, "[%s]", opname);
+     else
+       mrg_printf (mrg, "%s", opname);
+     mrg_printf (mrg, "\n");
+
+     g_free (opname);
+     iter = gegl_node_get_producer (iter, "input", NULL);
+   }
+}
+
+static void ui_actions (State *o)
+{
+  Mrg *mrg = o->mrg;
+  int i;
+  cairo_t *cr = mrg_cr (mrg);
+  mrg_set_edge_left (mrg, mrg_width (mrg) * 0.25);
+  mrg_set_edge_top  (mrg, mrg_height (mrg) * 0.1);
+  mrg_set_font_size (mrg, mrg_height (mrg) * 0.08);
+
+  for (i = 0; actions[i].label; i ++)
+    {
+      mrg_text_listen (mrg, MRG_PRESS, activate_op_cb, o, &actions[i]);
+      if (locate_node (o, actions[i].op_name))
+        mrg_printf (mrg, "-");
+      mrg_printf (mrg, "%s\n", actions[i].label);
+      mrg_text_listen_done (mrg);
+    }
+
+  mrg_print (mrg, "\n");
+  mrg_printf (mrg, "existing\n");
+  mrg_text_listen (mrg, MRG_PRESS, discard_cb, o, NULL);
+  mrg_printf (mrg, "discard\n");
+  mrg_text_listen_done (mrg);
+  cairo_scale (cr, mrg_width(mrg), mrg_height(mrg));
+  cairo_new_path (cr);
+  cairo_arc (cr, 0.9, 0.1, 0.1, 0.0, G_PI * 2);
+  mrg_listen (mrg, MRG_PRESS, toggle_actions_cb, o, NULL);
+  contrasty_stroke (cr);
+}
+
+static void ui_viewer (State *o)
+{
+  Mrg *mrg = o->mrg;
+  cairo_t *cr = mrg_cr (mrg);
+  cairo_rectangle (cr, 0,0, mrg_width(mrg), mrg_height(mrg));
+  mrg_listen (mrg, MRG_DRAG, on_pan_drag, o, NULL);
+  cairo_new_path (cr);
+  cairo_scale (cr, mrg_width(mrg), mrg_height(mrg));
+  cairo_move_to (cr, 0.2, 0.8);
+  cairo_line_to (cr, 0.2, 1.0);
+  cairo_line_to (cr, 0.0, 0.9);
+  cairo_close_path (cr);
+  mrg_listen (mrg, MRG_PRESS, go_prev_cb, o, NULL);
+  if (o->show_controls)
+    contrasty_stroke (cr);
+  else
+    cairo_new_path (cr);
+
+  cairo_move_to (cr, 0.8, 0.8);
+  cairo_line_to (cr, 0.8, 1.0);
+  cairo_line_to (cr, 1.0, 0.9);
+  cairo_close_path (cr);
+
+  mrg_listen (mrg, MRG_PRESS, go_next_cb, o, NULL);
+  if (o->show_controls)
+    contrasty_stroke (cr);
+  else
+    cairo_new_path (cr);
+
+  cairo_arc (cr, 0.9, 0.1, 0.1, 0.0, G_PI * 2);
+  mrg_listen (mrg, MRG_PRESS, toggle_actions_cb, o, NULL);
+
+  if (o->show_controls)
+    contrasty_stroke (cr);
+  else
+    cairo_new_path (cr);
+}
+
+static void toggle_show_controls_cb (MrgEvent *event, void *data1, void *data2)
+{
+  State *o = data1;
+  o->show_controls = !o->show_controls;
+  mrg_queue_draw (o->mrg, NULL);
+}
+
+static void gegl_ui (Mrg *mrg, void *data)
+{
+  State *o = data;
+  mrg_gegl_blit (mrg,
+                0, 0,
+                 mrg_width (mrg), mrg_height (mrg),
+                o->sink,
+                o->u, o->v,
+                o->scale,
+                 o->render_quality);
+  
+  if (o->show_controls)
+  {
+    mrg_printf (mrg, "%s\n", o->path);
+#if DEBUG_OP_LIST
+    ui_debug_op_chain (o);
+#endif
+  }
+
+  if (o->show_actions)
+  {
+    ui_actions (o);
+    mrg_add_binding (mrg, "return", NULL, NULL, toggle_actions_cb, o);
+  }
+  else if (o->active)
+  {
+    ui_active_op (o);
+    mrg_add_binding (mrg, "return", NULL, NULL, apply_filter_cb, o);
+    mrg_add_binding (mrg, "escape", NULL, NULL,     disable_filter_cb, o);
+  }
+  else
+  {
+    ui_viewer (o);
+    mrg_add_binding (mrg, "return", NULL, NULL, toggle_actions_cb, o);
+  }
+
+  mrg_add_binding (mrg, "left", NULL, NULL,      pan_left_cb, o);
+  mrg_add_binding (mrg, "right", NULL, NULL,     pan_right_cb, o);
+  mrg_add_binding (mrg, "up", NULL, NULL,        pan_up_cb, o);
+  mrg_add_binding (mrg, "down", NULL, NULL,      pan_down_cb, o);
+  mrg_add_binding (mrg, "+", NULL, NULL,         zoom_in_cb, o);
+  mrg_add_binding (mrg, "=", NULL, NULL,         zoom_in_cb, o);
+  mrg_add_binding (mrg, "-", NULL, NULL,         zoom_out_cb, o);
+  mrg_add_binding (mrg, "1", NULL, NULL,         zoom_1_cb, o);
+  mrg_add_binding (mrg, "m", NULL, NULL,         zoom_fit_cb, o);
+
+  mrg_add_binding (mrg, "control-q", NULL, NULL, mrg_quit_cb, o);
+  mrg_add_binding (mrg, "m", NULL, NULL,         zoom_fit_cb, o);
+  mrg_add_binding (mrg, "q", NULL, NULL,         mrg_quit_cb, o);
+  mrg_add_binding (mrg, "x", NULL, NULL,         discard_cb, o);
+  mrg_add_binding (mrg, "f", NULL, NULL,         toggle_fullscreen_cb, o);
+  mrg_add_binding (mrg, "F11", NULL, NULL,       toggle_fullscreen_cb, o);
+  mrg_add_binding (mrg, "tab", NULL, NULL,       toggle_show_controls_cb, o);
+  mrg_add_binding (mrg, "space", NULL, NULL,     go_next_cb , o);
+  mrg_add_binding (mrg, "n", NULL, NULL,         go_next_cb, o);
+  mrg_add_binding (mrg, "p", NULL, NULL,         go_prev_cb, o);
+  mrg_add_binding (mrg, "backspace", NULL, NULL, go_prev_cb, o);
+
+  mrg_add_binding (mrg, ",", NULL, NULL,         preview_less_cb, o);
+  mrg_add_binding (mrg, ".", NULL, NULL,         preview_more_cb, o);
+}
+
+/***********************************************/
+
 static char *suffix_path (const char *path)
 {
   char *ret, *last_dot;
@@ -105,21 +644,6 @@ static char *suffix_path (const char *path)
   return ret;
 }
 
-static void contrasty_stroke (cairo_t *cr)
-{
-  double x0 = 6.0, y0 = 6.0;
-  double x1 = 4.0, y1 = 4.0;
-
-  cairo_device_to_user_distance (cr, &x0, &y0);
-  cairo_device_to_user_distance (cr, &x1, &y1);
-  cairo_set_source_rgba (cr, 0,0,0,0.5);
-  cairo_set_line_width (cr, y0);
-  cairo_stroke_preserve (cr);
-  cairo_set_source_rgba (cr, 1,1,1,0.5);
-  cairo_set_line_width (cr, y1);
-  cairo_stroke (cr);
-}
-
 static char *unsuffix_path (const char *path)
 {
   char *ret = NULL, *last_dot, *extension;
@@ -144,6 +668,21 @@ static int is_giev_path (const char *path)
   return 0;
 }
 
+static void contrasty_stroke (cairo_t *cr)
+{
+  double x0 = 6.0, y0 = 6.0;
+  double x1 = 4.0, y1 = 4.0;
+
+  cairo_device_to_user_distance (cr, &x0, &y0);
+  cairo_device_to_user_distance (cr, &x1, &y1);
+  cairo_set_source_rgba (cr, 0,0,0,0.5);
+  cairo_set_line_width (cr, y0);
+  cairo_stroke_preserve (cr);
+  cairo_set_source_rgba (cr, 1,1,1,0.5);
+  cairo_set_line_width (cr, y1);
+  cairo_stroke (cr);
+}
+
 static unsigned char *copy_buf = NULL;
 static int copy_buf_len = 0;
 
@@ -223,7 +762,89 @@ foo++;
   cairo_restore (cr);
 }
 
-static void load_path (State *o);
+static void load_path (State *o)
+{
+  char *path;
+  char *meta;
+  if (is_giev_path (o->path))
+  {
+    if (o->giev_path)
+      free (o->giev_path);
+    o->giev_path = o->path;
+    o->path = unsuffix_path (o->giev_path);
+  }
+  else
+  {
+    if (o->giev_path)
+      free (o->giev_path);
+    o->giev_path = suffix_path (o->path);
+  }
+  path  = o->path;
+
+  if (access (o->giev_path, F_OK) != -1)
+    path = o->giev_path;
+
+  g_object_unref (o->gegl);
+  o->gegl = NULL;
+
+  meta = gegl_meta_get (path);
+  if (meta)
+  {
+    GSList *nodes, *n;
+    o->gegl = gegl_node_new_from_xml (meta, NULL);
+    o->sink = gegl_node_new_child (o->gegl,
+                       "operation", "gegl:nop", NULL);
+    o->source = NULL;
+    gegl_node_link_many (
+      gegl_node_get_producer (o->gegl, "input", NULL), o->sink, NULL);
+    nodes = gegl_node_get_children (o->gegl);
+    for (n = nodes; n; n=n->next)
+    {
+      const char *op_name = gegl_node_get_operation (n->data);
+      if (!strcmp (op_name, "gegl:load"))
+      {
+        GeglNode *load;
+        gchar *path;
+        gegl_node_get (n->data, "path", &path, NULL);
+        load_into_buffer (o, path);
+        gegl_node_set (n->data, "operation", "gegl:nop", NULL);
+        o->source = n->data;
+        load = gegl_node_new_child (o->gegl, "operation", "gegl:buffer-source",
+                                              "buffer", o->buffer, NULL);
+        gegl_node_link_many (load, o->source, NULL);
+        g_free (path);
+        break;
+      }
+    }
+    o->save = gegl_node_new_child (o->gegl,
+                 "operation", "gegl:save",
+                 "path", path,
+                 NULL);
+  }
+  else
+  {
+    o->gegl = gegl_node_new ();
+    o->sink = gegl_node_new_child (o->gegl,
+                       "operation", "gegl:nop", NULL);
+    o->source = gegl_node_new_child (o->gegl,
+                       "operation", "gegl:nop", NULL);
+    load_into_buffer (o, path);
+    o->load = gegl_node_new_child (o->gegl,
+                             "operation", "gegl:buffer-source",
+                              NULL);
+    o->save         = gegl_node_new_child (o->gegl,
+                    "operation", "gegl:save",
+                    "path", o->giev_path,
+                    NULL);
+    gegl_node_link_many (o->load, o->source, o->sink, NULL);
+    gegl_node_set (o->load, "buffer", o->buffer, NULL);
+  }
+  zoom_to_fit (o);
+
+  mrg_queue_draw (o->mrg, NULL);
+  o->rev = 0;
+}
+
 
 static void go_next (State *o)
 {
@@ -315,8 +936,6 @@ static void go_prev (State *o)
   }
 }
 
-static void save_cb (MrgEvent *event, void *data1, void *data2);
-
 static void go_next_cb (MrgEvent *event, void *data1, void *data2)
 {
   State *o = data1;
@@ -337,12 +956,20 @@ static void go_prev_cb (MrgEvent *event, void *data1, void *data2)
   mrg_event_stop_propagate (event);
 }
 
-static void on_pan_drag (MrgEvent *e, void *data1, void *data2)
+static void leave_editor (State *o)
 {
-  State *o = data1;
+  char *opname = NULL;
+  g_object_get (o->active, "operation", &opname, NULL);
+  if (!strcmp (opname, "gegl:crop"))
+   {
+      zoom_to_fit (o);
+   }
+}
 
+static void drag_preview (MrgEvent *e)
+{
+  State *o = hack_state;
   static float old_factor = 1;
-
   switch (e->type)
   {
     case MRG_DRAG_PRESS:
@@ -354,11 +981,6 @@ static void on_pan_drag (MrgEvent *e, void *data1, void *data2)
       o->render_quality = old_factor;
       mrg_queue_draw (e->mrg, NULL);
       break;
-    case MRG_DRAG_MOTION:
-    o->u -= (e->delta_x );
-    o->v -= (e->delta_y );
-    mrg_queue_draw (e->mrg, NULL);
-    break;
     default:
     break;
   }
@@ -394,6 +1016,20 @@ static void load_into_buffer (State *o, const char *path)
   o->buffer = tempbuf;
 }
 
+static GeglNode *locate_node (State *o, const char *op_name)
+{
+  GeglNode *iter = o->sink;
+  while (iter)
+   {
+     char *opname = NULL;
+     g_object_get (iter, "operation", &opname, NULL);
+     if (!strcmp (opname, op_name))
+       return iter;
+     g_free (opname);
+     iter = gegl_node_get_producer (iter, "input", NULL);
+   }
+  return NULL;
+}
 static void zoom_to_fit (State *o)
 {
   Mrg *mrg = o->mrg;
@@ -428,13 +1064,10 @@ static void zoom_to_fit_buffer (State *o)
   if (scale2 < scale) scale = scale2;
 
   o->scale = scale;
-
   o->u = -(mrg_width (mrg) - rect.width * scale) / 2;
   o->v = -(mrg_height (mrg) - rect.height * scale) / 2;
-  
   o->u += rect.x * scale;
   o->v += rect.y * scale;
-
   mrg_queue_draw (mrg, NULL);
 }
 
@@ -461,7 +1094,6 @@ static void pan_right_cb (MrgEvent *event, void *data1, void *data2)
 {
   State *o = data1;
   float amount = mrg_width (event->mrg) * 0.1;
-
   o->u = o->u + amount;
   mrg_queue_draw (o->mrg, NULL);
 }  
@@ -470,7 +1102,6 @@ static void pan_down_cb (MrgEvent *event, void *data1, void *data2)
 {
   State *o = data1;
   float amount = mrg_width (event->mrg) * 0.1;
-
   o->v = o->v + amount;
   mrg_queue_draw (o->mrg, NULL);
 }  
@@ -479,9 +1110,7 @@ static void pan_up_cb (MrgEvent *event, void *data1, void *data2)
 {
   State *o = data1;
   float amount = mrg_width (event->mrg) * 0.1;
-
   o->v = o->v - amount;
-
   mrg_queue_draw (o->mrg, NULL);
 }  
 
@@ -505,7 +1134,6 @@ static void preview_less_cb (MrgEvent *event, void *data1, void *data2)
   o->render_quality /= 2;
   if (o->render_quality <= 1.0)
     o->render_quality = 1.0;
-
   mrg_queue_draw (o->mrg, NULL);
 }
 
@@ -557,30 +1185,14 @@ static void toggle_fullscreen_cb (MrgEvent *event, void *data1, void *data2)
   mrg_add_timeout (event->mrg, 250, deferred_zoom_to_fit, o);
 }
 
-static GeglNode *locate_node (State *o, const char *op_name)
-{
-  GeglNode *iter = o->sink;
-  while (iter)
-   {
-     char *opname = NULL;
-     g_object_get (iter, "operation", &opname, NULL);
-     if (!strcmp (opname, op_name))
-       return iter;
-     g_free (opname);
-     iter = gegl_node_get_producer (iter, "input", NULL);
-   }
-  return NULL;
-}
 
 static void activate_op_cb (MrgEvent *event, void *data1, void *data2)
 {
   State *o = data1;
   GeglNode *found;
   ActionData *ad = data2;
-
   o->show_actions = 0;
   o->rev ++;
-
   found = locate_node (o, ad->op_name);
   if (found)
     {
@@ -634,16 +1246,6 @@ static void activate_op_cb (MrgEvent *event, void *data1, void *data2)
   mrg_queue_draw (o->mrg, NULL);
 }
 
-static void leave_editor (State *o)
-{
-  char *opname = NULL;
-  g_object_get (o->active, "operation", &opname, NULL);
-  if (!strcmp (opname, "gegl:crop"))
-   {
-      zoom_to_fit (o);
-   }
-}
-
 static void disable_filter_cb (MrgEvent *event, void *data1, void *data2)
 {
   State *o = data1;
@@ -666,6 +1268,7 @@ static void disable_filter_cb (MrgEvent *event, void *data1, void *data2)
   o->active = NULL;
   mrg_queue_draw (o->mrg, NULL);
 }
+
 static void  apply_filter_cb (MrgEvent *event, void *data1, void *data2)
 {
   State *o = data1;
@@ -704,316 +1307,6 @@ static void discard_cb (MrgEvent *event, void *data1, void *data2)
   free (old_path);
 }
 
-static State *hack_state = NULL;
-static void prop_double_drag_cb (MrgEvent *e, void *data1, void *data2)
-{
-  GeglNode *node = data1;
-  GParamSpec *pspec = data2;
-  State *o = hack_state;
-  static float old_factor = 1;
-  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);
-
-  switch (e->type)
-  {
-    case MRG_DRAG_PRESS:
-      old_factor = o->render_quality;
-      if (o->render_quality < o->preview_quality)
-        o->render_quality = o->preview_quality;
-      break;
-    case MRG_DRAG_RELEASE:
-      o->render_quality = old_factor;
-      mrg_queue_draw (e->mrg, NULL);
-      break;
-    default:
-    break;
-  }
-
-  mrg_queue_draw (e->mrg, NULL);
-}
-
-static void draw_gegl_generic (State *state, Mrg *mrg, cairo_t *cr, GeglNode *node)
-{
-  const gchar* op_name = gegl_node_get_operation (node);
-  mrg_set_edge_left (mrg, mrg_width (mrg) * 0.1);
-  mrg_set_edge_top  (mrg, mrg_height (mrg) * 0.1);
-  mrg_set_font_size (mrg, mrg_height (mrg) * 0.07);
-  mrg_set_style (mrg, "color:white; background-color: transparent");
-
-  cairo_save (cr);
-  mrg_printf (mrg, "%s\n", op_name);
-  {
-    guint n_props;
-    GParamSpec **pspecs = gegl_operation_list_properties (op_name, &n_props);
-
-    if (pspecs)
-    {
-      int tot_pos = 0;
-      int pos_no = 0;
-
-      for (gint i = 0; i < n_props; i++)
-      {
-        if (g_type_is_a (pspecs[i]->value_type, G_TYPE_DOUBLE) ||
-            g_type_is_a (pspecs[i]->value_type, G_TYPE_INT) ||
-            g_type_is_a (pspecs[i]->value_type, G_TYPE_STRING) ||
-            g_type_is_a (pspecs[i]->value_type, G_TYPE_BOOLEAN))
-          tot_pos ++;
-      }
-
-      for (gint i = 0; i < n_props; i++)
-      {
-        mrg_set_xy (mrg, mrg_em(mrg), mrg_height (mrg) - mrg_em (mrg) * ((tot_pos-pos_no)));
-
-
-        if (g_type_is_a (pspecs[i]->value_type, G_TYPE_DOUBLE))
-        {
-          float xpos;
-          GeglParamSpecDouble *geglspec = (void*)pspecs[i];
-          gdouble value;
-          gegl_node_get (node, pspecs[i]->name, &value, NULL);
-
-          cairo_rectangle (cr, 0,
-             mrg_height (mrg) - mrg_em (mrg) * ((tot_pos-pos_no+1)),
-             mrg_width (mrg), mrg_em(mrg));
-          cairo_set_source_rgba (cr, 0,0,0, 0.5);
-
-          mrg_listen (mrg, MRG_DRAG, prop_double_drag_cb, node,(void*)pspecs[i]);
-
-          cairo_fill (cr);
-          xpos = (value - geglspec->ui_minimum) / (geglspec->ui_maximum - geglspec->ui_minimum);
-          cairo_rectangle (cr, xpos * mrg_width(mrg) - mrg_em(mrg)/4,
-              mrg_height (mrg) - mrg_em (mrg) * ((tot_pos-pos_no+1)),
-              mrg_em(mrg)/2, mrg_em(mrg));
-          cairo_set_source_rgba (cr, 1,1,1, 0.5);
-          cairo_fill (cr);
-
-          mrg_printf (mrg, "%s:%f\n", pspecs[i]->name, value);
-          pos_no ++;
-        }
-        else if (g_type_is_a (pspecs[i]->value_type, G_TYPE_INT))
-        {
-          gint value;
-          gegl_node_get (node, pspecs[i]->name, &value, NULL);
-          mrg_printf (mrg, "%s:%i\n", pspecs[i]->name, value);
-          pos_no ++;
-        }
-        else if (g_type_is_a (pspecs[i]->value_type, G_TYPE_STRING))
-        {
-          char *value = NULL;
-          gegl_node_get (node, pspecs[i]->name, &value, NULL);
-          pos_no ++;
-          mrg_printf (mrg, "%s:%s\n", pspecs[i]->name, value);
-          if (value) g_free (value);
-        }
-        else if (g_type_is_a (pspecs[i]->value_type, G_TYPE_BOOLEAN))
-        {
-          gboolean value = FALSE;
-          gegl_node_get (node, pspecs[i]->name, &value, NULL);
-          pos_no ++;
-          mrg_printf (mrg, "%s:%i\n", pspecs[i]->name, value);
-        }
-        
-      }
-      g_free (pspecs);
-    }
-  }
-
-  cairo_restore (cr);
-  mrg_set_style (mrg, "color:yellow; background-color: transparent");
-}
-
-static void crop_drag_ul (MrgEvent *e, void *data1, void *data2)
-{
-  GeglNode *node = data1;
-  State *o = hack_state;
-  static float old_factor = 1;
-
-  double x,y,width,height;
-  double x0, y0, x1, y1;
-  gegl_node_get (node, "x", &x, "y", &y, "width", &width, "height", &height, NULL);
-  x0 = x; y0 = y; x1 = x0 + width; y1 = y + height;
-
-  if (e->type == MRG_DRAG_MOTION)
-  {
-    x0 += e->delta_x;
-    y0 += e->delta_y;
-
-    x=x0;
-    y=y0;
-    width = x1 - x0;
-    height = y1 - y0;
-    gegl_node_set (node, "x", x, "y", y, "width", width, "height", height, NULL);
-
-    mrg_queue_draw (e->mrg, NULL);
-  }
-
-  switch (e->type)
-  {
-    case MRG_DRAG_PRESS:
-      old_factor = o->render_quality;
-      if (o->render_quality < o->preview_quality)
-        o->render_quality = o->preview_quality;
-      break;
-    case MRG_DRAG_RELEASE:
-      o->render_quality = old_factor;
-      mrg_queue_draw (e->mrg, NULL);
-      break;
-    default:
-    break;
-  }
-}
-
-static void crop_drag_lr (MrgEvent *e, void *data1, void *data2)
-{
-  GeglNode *node = data1;
-  State *o = hack_state;
-  static float old_factor = 1;
-
-  double x,y,width,height;
-  double x0, y0, x1, y1;
-  gegl_node_get (node, "x", &x, "y", &y, "width", &width, "height", &height, NULL);
-  x0 = x; y0 = y; x1 = x0 + width; y1 = y + height;
-
-  if (e->type == MRG_DRAG_MOTION)
-  {
-    x1 += e->delta_x;
-    y1 += e->delta_y;
-
-    x=x0;
-    y=y0;
-    width = x1 - x0;
-    height = y1 - y0;
-    gegl_node_set (node, "x", x, "y", y, "width", width, "height", height, NULL);
-
-    mrg_queue_draw (e->mrg, NULL);
-  }
-
-
-  switch (e->type)
-  {
-    case MRG_DRAG_PRESS:
-      old_factor = o->render_quality;
-      if (o->render_quality < o->preview_quality)
-        o->render_quality = o->preview_quality;
-      break;
-    case MRG_DRAG_RELEASE:
-      o->render_quality = old_factor;
-      mrg_queue_draw (e->mrg, NULL);
-      break;
-    default:
-    break;
-  }
-}
-
-
-static void crop_drag_rotate (MrgEvent *e, void *data1, void *data2)
-{
-  State *o = hack_state;
-  static float old_factor = 1;
-
-  double degrees;
-  gegl_node_get (o->rotate, "degrees", &degrees, NULL);
-
-  if (e->type == MRG_DRAG_MOTION)
-  {
-    degrees += e->delta_x / 100.0;
-
-    gegl_node_set (o->rotate, "degrees", degrees, NULL);
-
-    mrg_queue_draw (e->mrg, NULL);
-  }
-
-  switch (e->type)
-  {
-    case MRG_DRAG_PRESS:
-      old_factor = o->render_quality;
-      if (o->render_quality < o->preview_quality)
-        o->render_quality = o->preview_quality;
-      break;
-    case MRG_DRAG_RELEASE:
-      o->render_quality = old_factor;
-      mrg_queue_draw (e->mrg, NULL);
-      break;
-    default:
-    break;
-  }
-}
-
-static void draw_gegl_crop (State *o, Mrg *mrg, cairo_t *cr, GeglNode *node)
-{
-  const gchar* op_name = gegl_node_get_operation (node);
-  float dim = mrg_height (mrg) * 0.1 / o->scale;
-  double x,y,width,height;
-  double x0, y0, x1, y1;
-
-  mrg_set_edge_left (mrg, mrg_width (mrg) * 0.1);
-  mrg_set_edge_top  (mrg, mrg_height (mrg) * 0.1);
-  mrg_set_font_size (mrg, mrg_height (mrg) * 0.07);
-  mrg_set_style (mrg, "color:white; background-color: transparent");
-
-  cairo_save (cr);
-  mrg_printf (mrg, "%s\n", op_name);
-
-  cairo_translate (cr, -o->u, -o->v);
-  cairo_scale (cr, o->scale, o->scale);
-
-  gegl_node_get (node, "x", &x, "y", &y, "width", &width, "height", &height, NULL);
-  x0 = x; y0 = y; x1 = x0 + width; y1 = y + height;
-
-  cairo_rectangle (cr, x0, y0, dim, dim);
-  mrg_listen (mrg, MRG_DRAG, crop_drag_ul, node, NULL);
-  contrasty_stroke (cr);
-
-  cairo_rectangle (cr, x1-dim, y1-dim, dim, dim);
-  mrg_listen (mrg, MRG_DRAG, crop_drag_lr, node, NULL);
-  contrasty_stroke (cr);
-
-  cairo_rectangle (cr, x0+dim, y0+dim, width-dim-dim, height-dim-dim);
-  mrg_listen (mrg, MRG_DRAG, crop_drag_rotate, node, NULL);
-  cairo_new_path (cr);
-
-  cairo_restore (cr);
-  mrg_set_style (mrg, "color:yellow; background-color: transparent");
-}
-
-static void ui_op_draw_apply_disable (State *o)
-{
-  Mrg *mrg = o->mrg;
-  mrg_set_font_size (mrg, mrg_height (mrg) * 0.1);
-  mrg_set_xy (mrg, 0, mrg_em(mrg));
-  mrg_text_listen (mrg, MRG_PRESS, disable_filter_cb, o, NULL);
-  mrg_printf (mrg, "X");
-  mrg_text_listen_done (mrg);
-  mrg_set_xy (mrg, mrg_width(mrg) - mrg_em (mrg), mrg_em(mrg));
-  mrg_text_listen (mrg, MRG_PRESS, apply_filter_cb, o, NULL);
-  mrg_printf (mrg, "O");
-  mrg_text_listen_done (mrg);
-}
-
-static void ui_active_op (State *o)
-{
-  Mrg *mrg = o->mrg;
-  cairo_t *cr = mrg_cr (mrg);
-  char *opname = NULL;
-  g_object_get (o->active, "operation", &opname, NULL);
-
-  if (!strcmp (opname, "gegl:crop")) {
-    zoom_to_fit_buffer (o);
-    draw_gegl_crop (o, mrg, cr, o->active);
-    ui_op_draw_apply_disable (o);
-  }
-  else
-  {
-    draw_gegl_generic (o, mrg, cr, o->active);
-    ui_op_draw_apply_disable (o);
-  }
-}
-
 static void save_cb (MrgEvent *event, void *data1, void *data2)
 {
   GeglNode *load;
@@ -1038,164 +1331,6 @@ static void save_cb (MrgEvent *event, void *data1, void *data2)
   o->rev = 0;
 }
 
-static void ui_debug_op_chain (State *o)
-{
-  Mrg *mrg = o->mrg;
-  GeglNode *iter;
-  mrg_set_edge_top  (mrg, mrg_height (mrg) * 0.2);
-  iter = o->sink;
-  while (iter)
-   {
-     char *opname = NULL;
-     g_object_get (iter, "operation", &opname, NULL);
-     if (iter == o->active)
-       mrg_printf (mrg, "[%s]", opname);
-     else
-       mrg_printf (mrg, "%s", opname);
-     mrg_printf (mrg, "\n");
-
-     g_free (opname);
-     iter = gegl_node_get_producer (iter, "input", NULL);
-   }
-}
-
-static void ui_actions (State *o)
-{
-  Mrg *mrg = o->mrg;
-  int i;
-  cairo_t *cr = mrg_cr (mrg);
-  mrg_set_edge_left (mrg, mrg_width (mrg) * 0.25);
-  mrg_set_edge_top  (mrg, mrg_height (mrg) * 0.1);
-  mrg_set_font_size (mrg, mrg_height (mrg) * 0.08);
-
-  for (i = 0; actions[i].label; i ++)
-    {
-      mrg_text_listen (mrg, MRG_PRESS, activate_op_cb, o, &actions[i]);
-      if (locate_node (o, actions[i].op_name))
-        mrg_printf (mrg, "-");
-      mrg_printf (mrg, "%s\n", actions[i].label);
-      mrg_text_listen_done (mrg);
-    }
-
-  mrg_print (mrg, "\n");
-  mrg_printf (mrg, "existing\n");
-  mrg_text_listen (mrg, MRG_PRESS, discard_cb, o, NULL);
-  mrg_printf (mrg, "discard\n");
-  mrg_text_listen_done (mrg);
-  cairo_scale (cr, mrg_width(mrg), mrg_height(mrg));
-  cairo_new_path (cr);
-  cairo_arc (cr, 0.9, 0.1, 0.1, 0.0, G_PI * 2);
-  mrg_listen (mrg, MRG_PRESS, toggle_actions_cb, o, NULL);
-  contrasty_stroke (cr);
-}
-
-static void ui_viewer (State *o)
-{
-  Mrg *mrg = o->mrg;
-  cairo_t *cr = mrg_cr (mrg);
-  cairo_rectangle (cr, 0,0, mrg_width(mrg), mrg_height(mrg));
-  mrg_listen (mrg, MRG_DRAG, on_pan_drag, o, NULL);
-  cairo_new_path (cr);
-  cairo_scale (cr, mrg_width(mrg), mrg_height(mrg));
-  cairo_move_to (cr, 0.2, 0.8);
-  cairo_line_to (cr, 0.2, 1.0);
-  cairo_line_to (cr, 0.0, 0.9);
-  cairo_close_path (cr);
-  mrg_listen (mrg, MRG_PRESS, go_prev_cb, o, NULL);
-  if (o->show_controls)
-    contrasty_stroke (cr);
-  else
-    cairo_new_path (cr);
-
-  cairo_move_to (cr, 0.8, 0.8);
-  cairo_line_to (cr, 0.8, 1.0);
-  cairo_line_to (cr, 1.0, 0.9);
-  cairo_close_path (cr);
-
-  mrg_listen (mrg, MRG_PRESS, go_next_cb, o, NULL);
-  if (o->show_controls)
-    contrasty_stroke (cr);
-  else
-    cairo_new_path (cr);
-
-  cairo_arc (cr, 0.9, 0.1, 0.1, 0.0, G_PI * 2);
-  mrg_listen (mrg, MRG_PRESS, toggle_actions_cb, o, NULL);
-
-  if (o->show_controls)
-    contrasty_stroke (cr);
-  else
-    cairo_new_path (cr);
-}
-
-static void toggle_show_controls_cb (MrgEvent *event, void *data1, void *data2)
-{
-  State *o = data1;
-  o->show_controls = !o->show_controls;
-  mrg_queue_draw (o->mrg, NULL);
-}
-
-static void ui (Mrg *mrg, void *data)
-{
-  State *o = data;
-  mrg_gegl_blit (mrg,
-                0, 0,
-                 mrg_width (mrg), mrg_height (mrg),
-                o->sink,
-                o->u, o->v,
-                o->scale,
-                 o->render_quality);
-  
-  if (o->show_controls)
-  {
-    mrg_printf (mrg, "%s\n", o->path);
-#if DEBUG_OP_LIST
-    ui_debug_op_chain (o);
-#endif
-  }
-
-  if (o->show_actions)
-  {
-    ui_actions (o);
-    mrg_add_binding (mrg, "return", NULL, NULL, toggle_actions_cb, o);
-  }
-  else if (o->active)
-  {
-    ui_active_op (o);
-    mrg_add_binding (mrg, "return", NULL, NULL, apply_filter_cb, o);
-    mrg_add_binding (mrg, "escape", NULL, NULL,     disable_filter_cb, o);
-  }
-  else
-  {
-    ui_viewer (o);
-    mrg_add_binding (mrg, "return", NULL, NULL, toggle_actions_cb, o);
-  }
-
-  mrg_add_binding (mrg, "left", NULL, NULL,      pan_left_cb, o);
-  mrg_add_binding (mrg, "right", NULL, NULL,     pan_right_cb, o);
-  mrg_add_binding (mrg, "up", NULL, NULL,        pan_up_cb, o);
-  mrg_add_binding (mrg, "down", NULL, NULL,      pan_down_cb, o);
-  mrg_add_binding (mrg, "+", NULL, NULL,         zoom_in_cb, o);
-  mrg_add_binding (mrg, "=", NULL, NULL,         zoom_in_cb, o);
-  mrg_add_binding (mrg, "-", NULL, NULL,         zoom_out_cb, o);
-  mrg_add_binding (mrg, "1", NULL, NULL,         zoom_1_cb, o);
-  mrg_add_binding (mrg, "m", NULL, NULL,         zoom_fit_cb, o);
-
-  mrg_add_binding (mrg, "control-q", NULL, NULL, mrg_quit_cb, o);
-  mrg_add_binding (mrg, "m", NULL, NULL,         zoom_fit_cb, o);
-  mrg_add_binding (mrg, "q", NULL, NULL,         mrg_quit_cb, o);
-  mrg_add_binding (mrg, "x", NULL, NULL,         discard_cb, o);
-  mrg_add_binding (mrg, "f", NULL, NULL,         toggle_fullscreen_cb, o);
-  mrg_add_binding (mrg, "F11", NULL, NULL,       toggle_fullscreen_cb, o);
-  mrg_add_binding (mrg, "tab", NULL, NULL,       toggle_show_controls_cb, o);
-  mrg_add_binding (mrg, "space", NULL, NULL,     go_next_cb , o);
-  mrg_add_binding (mrg, "n", NULL, NULL,         go_next_cb, o);
-  mrg_add_binding (mrg, "p", NULL, NULL,         go_prev_cb, o);
-  mrg_add_binding (mrg, "backspace", NULL, NULL, go_prev_cb, o);
-
-  mrg_add_binding (mrg, ",", NULL, NULL,         preview_less_cb, o);
-  mrg_add_binding (mrg, ".", NULL, NULL,         preview_more_cb, o);
-}
-
 #if 0
 void gegl_node_defaults (GeglNode *node)
 {
@@ -1233,129 +1368,6 @@ void gegl_node_defaults (GeglNode *node)
  * creates live gegl pipeline, or nops.. rigs up o->giev_path to be
  * the location where default saves ends up.
  */
-static void load_path (State *o)
-{
-  char *path;
-  char *meta;
-  if (is_giev_path (o->path))
-  {
-    if (o->giev_path)
-      free (o->giev_path);
-    o->giev_path = o->path;
-    o->path = unsuffix_path (o->giev_path);
-  }
-  else
-  {
-    if (o->giev_path)
-      free (o->giev_path);
-    o->giev_path = suffix_path (o->path);
-  }
-  path  = o->path;
-
-  if (access (o->giev_path, F_OK) != -1)
-    path = o->giev_path;
-
-  g_object_unref (o->gegl);
-  o->gegl = NULL;
-
-  meta = gegl_meta_get (path);
-  if (meta)
-  {
-    GSList *nodes, *n;
-    o->gegl = gegl_node_new_from_xml (meta, NULL);
-    o->sink = gegl_node_new_child (o->gegl,
-                       "operation", "gegl:nop", NULL);
-    o->source = NULL;
-    gegl_node_link_many (
-      gegl_node_get_producer (o->gegl, "input", NULL), o->sink, NULL);
-    nodes = gegl_node_get_children (o->gegl);
-    for (n = nodes; n; n=n->next)
-    {
-      const char *op_name = gegl_node_get_operation (n->data);
-      if (!strcmp (op_name, "gegl:load"))
-      {
-        GeglNode *load;
-        gchar *path;
-        gegl_node_get (n->data, "path", &path, NULL);
-        load_into_buffer (o, path);
-        gegl_node_set (n->data, "operation", "gegl:nop", NULL);
-        o->source = n->data;
-        load = gegl_node_new_child (o->gegl, "operation", "gegl:buffer-source",
-                                              "buffer", o->buffer, NULL);
-        gegl_node_link_many (load, o->source, NULL);
-        g_free (path);
-        break;
-      }
-    }
-    o->save = gegl_node_new_child (o->gegl,
-                 "operation", "gegl:save",
-                 "path", path,
-                 NULL);
-  }
-  else
-  {
-    o->gegl = gegl_node_new ();
-    o->sink = gegl_node_new_child (o->gegl,
-                       "operation", "gegl:nop", NULL);
-    o->source = gegl_node_new_child (o->gegl,
-                       "operation", "gegl:nop", NULL);
-    load_into_buffer (o, path);
-    o->load = gegl_node_new_child (o->gegl,
-                             "operation", "gegl:buffer-source",
-                              NULL);
-    o->save         = gegl_node_new_child (o->gegl,
-                    "operation", "gegl:save",
-                    "path", o->giev_path,
-                    NULL);
-    gegl_node_link_many (o->load, o->source, o->sink, NULL);
-    gegl_node_set (o->load, "buffer", o->buffer, NULL);
-  }
-  zoom_to_fit (o);
-
-  mrg_queue_draw (o->mrg, NULL);
-  o->rev = 0;
-}
-
-int mrg_ui_main (int argc, char **argv);
-int mrg_ui_main (int argc, char **argv)
-{
-  Mrg *mrg = mrg_new (1024, 768, NULL);
-  State o = {NULL,};
-#ifdef USE_MIPMAPS
-  g_setenv ("GEGL_MIPMAP_RENDERING", "1", TRUE);
-#endif
-  g_setenv ("BABL_TOLERANCE", "0.1", TRUE);
-
-  gegl_init (&argc, &argv);
-  o.gegl           = gegl_node_new ();
-  o.mrg            = mrg;
-  o.scale          = 1.0;
-  o.render_quality = 1.0;
-  o.preview_quality = 4.0;
-
-  if (access (argv[1], F_OK) != -1)
-    o.path = strdup (argv[1]);
-  else
-    {
-      printf ("usage: %s <full-path-to-image>\n", argv[0]);
-      return -1;
-    }
-
-  load_path (&o);
-  mrg_set_ui (mrg, ui, &o);
-  hack_state = &o;
-  mrg_main (mrg);
-
-  g_object_unref (o.gegl);
-  if (o.buffer)
-  {
-    g_object_unref (o.buffer);
-    o.buffer = NULL;
-  }
-  gegl_exit ();
-  return 0;
-}
-
 void
 gegl_meta_set (const char *path,
                const char *meta_data)



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