[gegl-edit] Can now edit subgraphs



commit 57edaefeadc66b3b9dd6aa2c866b98e7b281df3b
Author: Isaac Wagner <isaacbw src gnome org>
Date:   Sat Aug 4 13:13:12 2012 -0400

    Can now edit subgraphs

 gegl-edit/contextmenu.ui           |   27 +++
 gegl-edit/contextmenu_canvas.ui    |   19 ++
 gegl-edit/gegl-edit.c              |  440 +++++++++++++++++++++++++++---------
 gegl-edit/gegl-gtk-property-view.c |    2 +-
 gegl-edit/gresource.xml            |    2 +
 gegl-edit/menubar.ui               |   37 +++-
 6 files changed, 414 insertions(+), 113 deletions(-)
---
diff --git a/gegl-edit/contextmenu.ui b/gegl-edit/contextmenu.ui
new file mode 100644
index 0000000..6067eda
--- /dev/null
+++ b/gegl-edit/contextmenu.ui
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <!-- interface-requires gtk+ 3.0 -->
+  <object class="GtkMenu" id="context">
+    <property name="visible">True</property>
+    <property name="can_focus">False</property>
+    <child>
+      <object class="GtkMenuItem" id="edit">
+        <property name="use_action_appearance">False</property>
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="label" translatable="yes">Edit</property>
+        <property name="use_underline">True</property>
+        <signal name="activate" handler="activated_context_edit" swapped="no"/>
+      </object>
+    </child>
+    <child>
+      <object class="GtkMenuItem" id="delete">
+        <property name="use_action_appearance">False</property>
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="label" translatable="yes">Delete</property>
+        <property name="use_underline">True</property>
+      </object>
+    </child>
+  </object>
+</interface>
diff --git a/gegl-edit/contextmenu_canvas.ui b/gegl-edit/contextmenu_canvas.ui
new file mode 100644
index 0000000..3f80ea0
--- /dev/null
+++ b/gegl-edit/contextmenu_canvas.ui
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <!-- interface-requires gtk+ 3.0 -->
+  <object class="GtkMenu" id="context_canvas">
+    <property name="visible">True</property>
+    <property name="can_focus">False</property>
+    <child>
+      <object class="GtkMenuItem" id="return">
+        <property name="use_action_appearance">False</property>
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="tooltip_text" translatable="yes">Return to the parent graph</property>
+        <property name="label" translatable="yes">Return</property>
+        <property name="use_underline">True</property>
+        <signal name="activate" handler="activated_context_return" swapped="no"/>
+      </object>
+    </child>
+  </object>
+</interface>
diff --git a/gegl-edit/gegl-edit.c b/gegl-edit/gegl-edit.c
index 7ff77ef..4b94ba5 100644
--- a/gegl-edit/gegl-edit.c
+++ b/gegl-edit/gegl-edit.c
@@ -7,28 +7,36 @@
 
 #include "resources.h"
 
+static void canvas_rightclicked(GraphGtkView *view, gpointer data);
 static void node_selected(GraphGtkView *view, GraphGtkNode *node, gpointer data);
 static void node_deselected(GraphGtkView *view, GraphGtkNode *node, gpointer data);
 static void node_doubleclicked(GraphGtkView *view, GraphGtkNode *node, gpointer data);
+static void node_rightclicked(GraphGtkView *view, GraphGtkNode *node, gpointer data);
 static void nodes_connected(GraphGtkView *view, GraphGtkNode *from, const gchar* output, GraphGtkNode *to, const gchar* input, gpointer data);
 static void nodes_disconnected(GraphGtkView *view, GraphGtkNode *from, const gchar* output, GraphGtkNode *to, const gchar* input, gpointer data);
 
 static GraphGtkNode* add_gegl_node_to_view(GraphGtkView *view, GeglNode *node);
+static void load_graph(GraphGtkView *view, GeglNode *node);
 
 static void update_images(GraphGtkView *view);
 static void update_bg_image(GraphGtkView *view);
 
 //Undocumented gegl functions
 GSList *gegl_node_get_input_pads(GeglNode*);
+GSList *gegl_node_get_pads(GeglNode *self);
 const gchar *gegl_pad_get_name(gpointer);
 GeglNode *gegl_node_get_nth_child (GeglNode*,gint);
 
 typedef struct CallbackData
 {
   GtkWidget	*window;
-  GraphGtkView	*view;
-  GeglNode	*gegl;
+  GraphGtkNode	*context;
+  GQueue	*graph_stack;
+  GQueue	*view_stack;
+  GtkWidget	*view_box;
   GtkWidget	*property_view;
+  GtkMenu       *popup;
+  GtkMenu       *popup2;
 } CallbackData;
 
 static void
@@ -63,15 +71,19 @@ main (gint	  argc,
 
   CallbackData *data = g_new(CallbackData, 1);
   data->window = window;
-  data->view = GRAPH_GTK_VIEW(view);
-  data->gegl = gegl;
+  data->view_stack = g_queue_new();
+  g_queue_push_head(data->view_stack, GRAPH_GTK_VIEW(view));
+  data->graph_stack = g_queue_new();
+  g_queue_push_head(data->graph_stack, gegl);
   data->property_view = GTK_WIDGET(props);
 
   g_signal_connect(props, "property-changed", G_CALLBACK(property_changed), view);
 
+  g_signal_connect(view, "canvas-rightclicked", G_CALLBACK(canvas_rightclicked), data);
   g_signal_connect(view, "node-selected", G_CALLBACK(node_selected), data);
   g_signal_connect(view, "node-deselected", G_CALLBACK(node_deselected), data);
   g_signal_connect(view, "node-doubleclicked", G_CALLBACK(node_doubleclicked), data);
+  g_signal_connect(view, "node-rightclicked", G_CALLBACK(node_rightclicked), data);
   g_signal_connect(view, "nodes-connected", G_CALLBACK(nodes_connected), data);
   g_signal_connect(view, "nodes-disconnected", G_CALLBACK(nodes_disconnected), data);
 
@@ -84,6 +96,14 @@ main (gint	  argc,
   //Build the menubar from misc/menubar.glade
   GtkBuilder *builder = gtk_builder_new();
 
+  add_ui_to_builder(resource, builder, "/gegl-edit/contextmenu.ui", data);
+  GtkMenu *popup = GTK_MENU(gtk_builder_get_object(builder, "context"));
+  data->popup = popup;
+
+  add_ui_to_builder(resource, builder, "/gegl-edit/contextmenu_canvas.ui", data);
+  GtkMenu *popup2 = GTK_MENU(gtk_builder_get_object(builder, "context_canvas"));
+  data->popup2 = popup2;
+
   add_ui_to_builder(resource, builder, "/gegl-edit/menubar.ui", data);
   
   GtkWidget *menubar = GTK_WIDGET(gtk_builder_get_object(builder, "menu_bar"));
@@ -93,7 +113,11 @@ main (gint	  argc,
   GtkWidget* pane = gtk_hpaned_new();
   gtk_paned_set_position(GTK_PANED(pane), 450);
 
-  gtk_paned_pack1(GTK_PANED(pane), view, TRUE, TRUE);
+  GtkWidget *box = gtk_vbox_new(TRUE, 0);
+  gtk_box_pack_start(GTK_BOX(box), view, TRUE, TRUE, 0);
+  data->view_box = box;
+
+  gtk_paned_pack1(GTK_PANED(pane), GTK_WIDGET(box), TRUE, TRUE);
   gtk_paned_pack2(GTK_PANED(pane), props, TRUE, TRUE);
 
   gtk_box_pack_start(GTK_BOX(vbox), pane, TRUE, TRUE, 0);
@@ -105,6 +129,17 @@ main (gint	  argc,
 
 ////////GraphGtk callbacks////////
 static void
+canvas_rightclicked(GraphGtkView *view, gpointer user_data)
+{
+  g_print("canvas_rightclicked\n");
+  CallbackData *data = (CallbackData*)user_data;
+  if(g_queue_get_length(data->graph_stack) > 1)
+    {
+      gtk_menu_popup(data->popup2, NULL, NULL, NULL, NULL, 3, gtk_get_current_event_time());
+    }
+}
+
+static void
 node_selected(GraphGtkView *view, GraphGtkNode *view_node, gpointer user_data)
 {
   CallbackData *data = (CallbackData*)user_data;
@@ -119,22 +154,38 @@ node_deselected(GraphGtkView *view, GraphGtkNode *node, gpointer user_data)
   CallbackData *data = (CallbackData*)user_data;
   GtkWidget *props = data->property_view;
   gegl_gtk_property_view_set_node(GEGL_GTK_PROPERTY_VIEW(data->property_view), NULL);
-  graph_gtk_view_set_bg(data->view, NULL);
+  graph_gtk_view_set_bg(g_queue_peek_head(data->view_stack), NULL);
 }
 
 static void
-node_doubleclicked(GraphGtkView *view, GraphGtkNode *view_node, gpointer data)
+node_rightclicked(GraphGtkView *view, GraphGtkNode *view_node, gpointer user_data)
 {
-  GeglNode *node = GEGL_NODE(view_node->user_data);
+  CallbackData *data = (CallbackData*)user_data;
 
-  if(!view_node->show_image)
+  if(GEGL_IS_NODE(view_node->user_data))
     {
-      graph_gtk_node_show_image(view_node, TRUE);
-      update_images(view);
+      data->context = view_node;
+      gtk_menu_popup(data->popup, NULL, NULL, NULL, NULL, 3, gtk_get_current_event_time());
+      //open menu
     }
-  else
+}
+
+static void
+node_doubleclicked(GraphGtkView *view, GraphGtkNode *view_node, gpointer data)
+{
+  if(GEGL_IS_NODE(view_node->user_data))
     {
-      graph_gtk_node_show_image(view_node, FALSE);
+      GeglNode *node = GEGL_NODE(view_node->user_data);
+
+      if(!view_node->show_image)
+	{
+	  graph_gtk_node_show_image(view_node, TRUE);
+	  update_images(view);
+	}
+      else
+	{
+	  graph_gtk_node_show_image(view_node, FALSE);
+	}
     }
 }
 
@@ -143,24 +194,206 @@ nodes_connected(GraphGtkView *view, GraphGtkNode *from, const gchar* output, Gra
 {
   CallbackData *data = (CallbackData*)user_data;
 
-  gegl_node_connect_to(from->user_data, output, to->user_data, input);
+  if(GEGL_IS_NODE(from->user_data) && GEGL_IS_NODE(to->user_data))
+    {
+      gegl_node_connect_to(from->user_data, output, to->user_data, input);
 
-  update_images(view);
+      update_images(view);
+    }
 }
 
 static void
 nodes_disconnected(GraphGtkView *view, GraphGtkNode *from, const gchar* output, GraphGtkNode *to, const gchar* input, gpointer user_data)
 {
-  gegl_node_disconnect(to->user_data, input);
-  update_images(view);
+  if(GEGL_IS_NODE(to->user_data))
+    {
+      gegl_node_disconnect(to->user_data, input);
+      update_images(view);
+    }
 }
 
 
 //////////Gtk+ callbacks//////////
+G_MODULE_EXPORT void activated_context_return(GtkMenuItem *menuitem, gpointer user_data)
+{
+  CallbackData *data = user_data;
+  GtkWidget *view = GTK_WIDGET(g_queue_pop_head(data->view_stack));
+  gtk_container_remove(GTK_CONTAINER(data->view_box), view);
+  gtk_box_pack_start(GTK_BOX(data->view_box), GTK_WIDGET(g_queue_peek_head(data->view_stack)), TRUE, TRUE, 0);
+  gtk_widget_destroy(view);
+
+  GeglNode *node =   g_queue_pop_head(data->graph_stack);
+
+  GraphGtkNode *view_node = NULL;
+  GList *list;
+  for(list = GRAPH_GTK_VIEW(g_queue_peek_head(data->view_stack))->nodes; list != NULL; list = list->next)
+    {
+      GraphGtkNode *n = list->data;
+      g_print("checking %s\n", n->name);
+      if(n->user_data == node)
+	view_node = n;
+    }
+
+  g_assert(view_node);
+
+  graph_gtk_node_remove_pads(view_node);
+
+  GSList *pads;
+  for(pads = gegl_node_get_pads(node); pads != NULL; pads = pads->next)
+    {
+      graph_gtk_node_add_pad(view_node, gegl_pad_get_name(pads->data), gegl_pad_is_output(pads->data));
+    }
+}
+
+G_MODULE_EXPORT void activated_context_edit(GtkMenuItem *menuitem, gpointer user_data)
+{
+  CallbackData *data = user_data;
+  if(data->context)
+    {
+      GtkWidget *view = graph_gtk_view_new();
+      load_graph(GRAPH_GTK_VIEW(view), data->context->user_data);
+
+      g_object_ref(g_queue_peek_head(data->view_stack));
+      gtk_container_remove(GTK_CONTAINER(data->view_box), g_queue_peek_head(data->view_stack));
+      gtk_box_pack_start(GTK_BOX(data->view_box), view, TRUE, TRUE, 0);
+      gtk_widget_show(view);
+
+      g_queue_push_head(data->view_stack, view);
+      g_queue_push_head(data->graph_stack, data->context->user_data);
+      g_print("views: %d, graphs: %d\n", g_queue_get_length(data->view_stack), g_queue_get_length(data->graph_stack));
+
+      g_signal_connect(view, "canvas-rightclicked", G_CALLBACK(canvas_rightclicked), data);
+      g_signal_connect(view, "node-selected", G_CALLBACK(node_selected), data);
+      g_signal_connect(view, "node-deselected", G_CALLBACK(node_deselected), data);
+      g_signal_connect(view, "node-doubleclicked", G_CALLBACK(node_doubleclicked), data);
+      g_signal_connect(view, "node-rightclicked", G_CALLBACK(node_rightclicked), data);
+      g_signal_connect(view, "nodes-connected", G_CALLBACK(nodes_connected), data);
+      g_signal_connect(view, "nodes-disconnected", G_CALLBACK(nodes_disconnected), data);
+    }
+}
+
+G_MODULE_EXPORT void activated_context_delete(GtkMenuItem *menuitem, gpointer user_data)
+{
+  CallbackData *data = user_data;
+  graph_gtk_view_remove_node(g_queue_peek_head(data->view_stack), data->context);
+}
+
+G_MODULE_EXPORT void activated_add_subgraph(GtkMenuItem *menuitem, gpointer user_data)
+{
+  CallbackData *data = user_data;
+  GtkWidget* dialog = gtk_dialog_new_with_buttons ("Add Subgraph",
+						   GTK_WINDOW(data->window),
+						   GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
+						   GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
+						   GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
+						   NULL);
+
+  //gtk_window_set_default_size(GTK_WINDOW(dialog), 350, 80);
+
+  GtkWidget* vbox = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
+
+  GtkWidget* name_label = gtk_label_new("Name");
+  GtkWidget* name_entry = gtk_entry_new();
+  gtk_box_pack_start(GTK_BOX(vbox), name_label, FALSE, FALSE, 0);
+  gtk_box_pack_start(GTK_BOX(vbox), name_entry, FALSE, FALSE, 0);
+
+  gtk_widget_show_all(vbox);
+
+  gint result = gtk_dialog_run(GTK_DIALOG(dialog));
+
+  if(result == GTK_RESPONSE_ACCEPT)
+    {
+      const gchar *name = gtk_entry_get_text(GTK_ENTRY(name_entry));
+      GraphGtkNode *node = graph_gtk_node_new();
+      graph_gtk_node_set_name(node, name);
+      GeglNode *subgraph = gegl_node_new();
+      node->user_data = subgraph;
+      graph_gtk_view_add_node(g_queue_peek_head(data->view_stack), node);
+    }
+
+  gtk_widget_destroy(dialog);
+}
+
+G_MODULE_EXPORT void activated_add_input(GtkMenuItem *menuitem, gpointer user_data)
+{
+  CallbackData *data = user_data;
+
+  GtkWidget* dialog = gtk_dialog_new_with_buttons ("Add Input",
+						   GTK_WINDOW(data->window),
+						   GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
+						   GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
+						   GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
+						   NULL);
+
+  //gtk_window_set_default_size(GTK_WINDOW(dialog), 350, 80);
+
+  GtkWidget* vbox = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
+
+  GtkWidget* name_label = gtk_label_new("Name");
+  GtkWidget* name_entry = gtk_entry_new();
+  gtk_box_pack_start(GTK_BOX(vbox), name_label, FALSE, FALSE, 0);
+  gtk_box_pack_start(GTK_BOX(vbox), name_entry, FALSE, FALSE, 0);
+
+  gtk_widget_show_all(vbox);
+
+  gint result = gtk_dialog_run(GTK_DIALOG(dialog));
+
+  if(result == GTK_RESPONSE_ACCEPT)
+    {
+      const gchar *name = gtk_entry_get_text(GTK_ENTRY(name_entry));
+      GraphGtkNode *node = graph_gtk_node_new();
+      graph_gtk_node_set_name(node, name);
+      graph_gtk_node_add_pad(node, "output", TRUE);
+      graph_gtk_view_add_node(g_queue_peek_head(data->view_stack), node);
+      GeglNode *proxy = gegl_node_get_input_proxy(g_queue_peek_head(data->graph_stack), name);
+      node->user_data = proxy;
+    }
+
+  gtk_widget_destroy(dialog);
+}
+
+G_MODULE_EXPORT void activated_add_output(GtkMenuItem *menuitem, gpointer user_data)
+{
+  CallbackData *data = user_data;
+
+  GtkWidget* dialog = gtk_dialog_new_with_buttons ("Add Output",
+						   GTK_WINDOW(data->window),
+						   GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
+						   GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
+						   GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
+						   NULL);
+
+  //gtk_window_set_default_size(GTK_WINDOW(dialog), 350, 80);
+
+  GtkWidget* vbox = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
+
+  GtkWidget* name_label = gtk_label_new("Name");
+  GtkWidget* name_entry = gtk_entry_new();
+  gtk_box_pack_start(GTK_BOX(vbox), name_label, FALSE, FALSE, 0);
+  gtk_box_pack_start(GTK_BOX(vbox), name_entry, FALSE, FALSE, 0);
+
+  gtk_widget_show_all(vbox);
+
+  gint result = gtk_dialog_run(GTK_DIALOG(dialog));
+
+  if(result == GTK_RESPONSE_ACCEPT)
+    {
+      const gchar *name = gtk_entry_get_text(GTK_ENTRY(name_entry));
+      GraphGtkNode *node = graph_gtk_node_new();
+      graph_gtk_node_set_name(node, name);
+      graph_gtk_node_add_pad(node, "input", FALSE);
+      graph_gtk_view_add_node(g_queue_peek_head(data->view_stack), node);
+      GeglNode *proxy = gegl_node_get_output_proxy(g_queue_peek_head(data->graph_stack), name);
+      node->user_data = proxy;
+    }
+
+  gtk_widget_destroy(dialog);
+}
+
 G_MODULE_EXPORT void activated_open(GtkMenuItem *menuitem, gpointer user_data)
 {
   CallbackData *data = user_data;
-  GraphGtkView *view = data->view;
+  GraphGtkView *view = g_queue_peek_head(data->view_stack);
 
   GtkFileChooserDialog	*file_select = GTK_FILE_CHOOSER_DIALOG(gtk_file_chooser_dialog_new("Save As", GTK_WINDOW(data->window), 
 											   GTK_FILE_CHOOSER_ACTION_OPEN, 
@@ -173,52 +406,7 @@ G_MODULE_EXPORT void activated_open(GtkMenuItem *menuitem, gpointer user_data)
       const gchar	*filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(file_select));
       GeglNode* gegl = gegl_node_new_from_file(filename);
 
-      GHashTable *hash_table = g_hash_table_new(g_direct_hash, g_direct_equal);
-
-      GSList *list = gegl_node_get_children(gegl);
-      for(;list != NULL; list = list->next)
-	{
-	  GeglNode* node = GEGL_NODE(list->data);
-	  g_print("Loading %s\n", gegl_node_get_operation(node));
-	  GraphGtkNode *view_node = add_gegl_node_to_view(data->view, node);
-	  g_hash_table_insert(hash_table, node, view_node);
-	}
-
-      for(list = gegl_node_get_children(gegl); list != NULL; list = list->next)
-	{
-	  GeglNode* node = GEGL_NODE(list->data);
-
-	  GraphGtkNode *from = g_hash_table_lookup(hash_table, node);
-	  if(!from)
-	    break;
-
-	  g_print("from: %s\n", from->name);
-
-	  if(!gegl_node_has_pad(node, "output")) 
-	    {
-	      g_print("No output\n");
-	      break;
-	    }
-
-	  GeglNode** nodes;
-	  const gchar** pads;
-	  gint num = gegl_node_get_consumers(node, "output", &nodes, &pads);
-	  
-	  int i;
-	  g_print("%s: %d consumer(s)\n", gegl_node_get_operation(node), num);
-	  for(i = 0; i < num; i++)
-	    {
-	      GraphGtkNode *to = g_hash_table_lookup(hash_table, nodes[i]);
-	      if(!to)
-		break;
-
-	      g_print("to: %s\n", to->name);
-	      g_print("Connecting to consumer (%s to %s): output->%s\n", gegl_node_get_operation(node), gegl_node_get_operation(nodes[i]), pads[i]);
-	      graph_gtk_node_connect_to(from, "output", to, pads[i]);
-	    }
-	}
-
-      g_hash_table_destroy(hash_table);
+      load_graph(view, gegl);
     }
 
   gtk_widget_destroy(GTK_WIDGET(file_select));
@@ -253,7 +441,7 @@ G_MODULE_EXPORT void activated_save_as(GtkMenuItem *menuitem, gpointer user_data
       const gchar	*filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(file_select));
 
       //Try to guess at an output
-      GeglNode* first = gegl_node_get_nth_child(data->gegl, 0);
+      GeglNode* first = gegl_node_get_nth_child(g_queue_peek_head(data->graph_stack), 0);
       GeglNode* last = getFinalNode(first);
 
       g_print("Final node: %s\n", gegl_node_get_operation(last));
@@ -275,14 +463,14 @@ G_MODULE_EXPORT void activated_save(GtkMenuItem *menuitem, gpointer user_data)
 G_MODULE_EXPORT void activated_delete(GtkMenuItem *menuitem, gpointer user_data)
 {
   CallbackData *data = user_data;
-  graph_gtk_view_remove_selected_nodes(data->view);
+  graph_gtk_view_remove_selected_nodes(g_queue_peek_head(data->view_stack));
 }
 
 G_MODULE_EXPORT void activated_process_selected(GtkMenuItem *menuitem, gpointer user_data)
 {
   CallbackData *data = user_data;
-  GeglNode *gegl = data->gegl;
-  GraphGtkView *view = data->view;
+  GeglNode *gegl = g_queue_peek_head(data->graph_stack);
+  GraphGtkView *view = g_queue_peek_head(data->view_stack);
 
   GList *nodes;
   for(nodes = view->selected_nodes; nodes != NULL; nodes = nodes->next)
@@ -298,7 +486,7 @@ G_MODULE_EXPORT void activated_process_selected(GtkMenuItem *menuitem, gpointer
 G_MODULE_EXPORT void activated_process_all(GtkMenuItem *menuitem, gpointer user_data)
 {
   CallbackData *data = user_data;
-  GeglNode *gegl = data->gegl;
+  GeglNode *gegl = g_queue_peek_head(data->graph_stack);
 
   GSList *nodes;
   for(nodes = gegl_node_get_children(gegl); nodes != NULL; nodes = nodes->next)
@@ -367,9 +555,9 @@ G_MODULE_EXPORT void activated_add(GtkMenuItem *menuitem, gpointer user_data)
 	{
 	  gchar* operation;
 	  gtk_tree_model_get(model, &itr, 0, &operation, -1);
-	  GeglNode *node = gegl_node_create_child(data->gegl, operation);
+	  GeglNode *node = gegl_node_create_child(g_queue_peek_head(data->graph_stack), operation);
 
-	  add_gegl_node_to_view(data->view, node);
+	  add_gegl_node_to_view(g_queue_peek_head(data->view_stack), node);
 	}
     }
 
@@ -380,38 +568,41 @@ static void update_bg_image(GraphGtkView *view)
 {
   if(view->selected_nodes)
     {
-      GeglNode *node = GEGL_NODE(GRAPH_GTK_NODE(view->selected_nodes->data)->user_data);
-      g_print("%s\n", gegl_node_get_operation(node));
-      const GeglRectangle roi = gegl_node_get_bounding_box(node);
-      if(!gegl_rectangle_is_infinite_plane(&roi))
+      if(GEGL_IS_NODE(GRAPH_GTK_NODE(view->selected_nodes->data)->user_data))
 	{
-	  const Babl *cairo_argb32 = babl_format("cairo-ARGB32");
-
-	  gdouble scale = 1.0;//150.0/roi.width;
-	  GeglRectangle scaled;
-	  scaled.x = 0;
-	  scaled.y = 0;
-	  scaled.width = roi.width*scale;
-	  scaled.height = roi.height*scale;
-
-	  gint stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, scaled.width);
-	  guchar* buf = (guchar*)malloc(stride*scaled.height);
-
-	  //make buffer in memory
-	  gegl_node_blit(node,
-			 scale,
-			 &scaled,
-			 cairo_argb32,
-			 buf,
-			 GEGL_AUTO_ROWSTRIDE,
-			 GEGL_BLIT_CACHE);
-
-	  cairo_surface_t*	image = 
-	    cairo_image_surface_create_for_data(buf, CAIRO_FORMAT_ARGB32, 
-						scaled.width, scaled.height, 
-						stride);
-
-	  graph_gtk_view_set_bg(view, image);
+	  GeglNode *node = GEGL_NODE(GRAPH_GTK_NODE(view->selected_nodes->data)->user_data);
+	  g_print("%s\n", gegl_node_get_operation(node));
+	  const GeglRectangle roi = gegl_node_get_bounding_box(node);
+	  if(!gegl_rectangle_is_infinite_plane(&roi))
+	    {
+	      const Babl *cairo_argb32 = babl_format("cairo-ARGB32");
+
+	      gdouble scale = 1.0;//150.0/roi.width;
+	      GeglRectangle scaled;
+	      scaled.x = 0;
+	      scaled.y = 0;
+	      scaled.width = roi.width*scale;
+	      scaled.height = roi.height*scale;
+
+	      gint stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, scaled.width);
+	      guchar* buf = (guchar*)malloc(stride*scaled.height);
+
+	      //make buffer in memory
+	      gegl_node_blit(node,
+			     scale,
+			     &scaled,
+			     cairo_argb32,
+			     buf,
+			     GEGL_AUTO_ROWSTRIDE,
+			     GEGL_BLIT_CACHE);
+
+	      cairo_surface_t*	image = 
+		cairo_image_surface_create_for_data(buf, CAIRO_FORMAT_ARGB32, 
+						    scaled.width, scaled.height, 
+						    stride);
+
+	      graph_gtk_view_set_bg(view, image);
+	    }
 	}
     }
 }
@@ -425,7 +616,7 @@ static void update_images(GraphGtkView *view)
     {
       view_node = GRAPH_GTK_NODE(list->data);
 
-      if(view_node->show_image)
+      if(view_node->show_image && GEGL_IS_NODE(view_node->user_data))
 	{
 	  if(view_node->image)
 	    cairo_surface_destroy(view_node->image);
@@ -492,3 +683,46 @@ add_gegl_node_to_view(GraphGtkView *view, GeglNode *node)
 
   return view_node;
 }
+
+static void load_graph(GraphGtkView *view, GeglNode *gegl)
+{
+  GHashTable *hash_table = g_hash_table_new(g_direct_hash, g_direct_equal);
+
+  GSList *list = gegl_node_get_children(gegl);
+  for(;list != NULL; list = list->next)
+    {
+      GeglNode* node = GEGL_NODE(list->data);
+      g_print("Loading %s\n", gegl_node_get_operation(node));
+      GraphGtkNode *view_node = add_gegl_node_to_view(view, node);
+      g_hash_table_insert(hash_table, node, view_node);
+    }
+
+  for(list = gegl_node_get_children(gegl); list != NULL; list = list->next)
+    {
+      GeglNode* node = GEGL_NODE(list->data);
+
+      GraphGtkNode *from = g_hash_table_lookup(hash_table, node);
+
+      if(!from)
+	break;
+
+      if(!gegl_node_has_pad(node, "output")) 
+	break;
+
+      GeglNode** nodes;
+      const gchar** pads;
+      gint num = gegl_node_get_consumers(node, "output", &nodes, &pads);
+	  
+      int i;
+      for(i = 0; i < num; i++)
+	{
+	  GraphGtkNode *to = g_hash_table_lookup(hash_table, nodes[i]);
+	  if(!to)
+	    break;
+
+	  graph_gtk_node_connect_to(from, "output", to, pads[i]);
+	}
+    }
+
+  g_hash_table_destroy(hash_table);
+}
diff --git a/gegl-edit/gegl-gtk-property-view.c b/gegl-edit/gegl-gtk-property-view.c
index a7fc3b4..a019a3b 100644
--- a/gegl-edit/gegl-gtk-property-view.c
+++ b/gegl-edit/gegl-gtk-property-view.c
@@ -201,7 +201,7 @@ rebuild_contents(GeglGtkPropertyView *self)
       gtk_container_remove(GTK_CONTAINER(self), GTK_WIDGET(child->data));
     }
 
-  if(node)
+  if(node && gegl_node_get_operation(node))
     {
       guint		n_props;
       GParamSpec**	properties = gegl_operation_list_properties(gegl_node_get_operation(node), &n_props);
diff --git a/gegl-edit/gresource.xml b/gegl-edit/gresource.xml
index 6bcaef6..5e7e45e 100644
--- a/gegl-edit/gresource.xml
+++ b/gegl-edit/gresource.xml
@@ -2,5 +2,7 @@
 <gresources>
   <gresource prefix="/gegl-edit/">
     <file preprocess="xml-stripblanks">menubar.ui</file>
+    <file preprocess="xml-stripblanks">contextmenu.ui</file>
+    <file preprocess="xml-stripblanks">contextmenu_canvas.ui</file>
   </gresource>
 </gresources>
diff --git a/gegl-edit/menubar.ui b/gegl-edit/menubar.ui
index 14853ed..8976574 100644
--- a/gegl-edit/menubar.ui
+++ b/gegl-edit/menubar.ui
@@ -1,17 +1,17 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <interface>
   <!-- interface-requires gtk+ 3.0 -->
-  <object class="GtkImage" id="image1">
+  <object class="GtkImage" id="image2">
     <property name="visible">True</property>
     <property name="can_focus">False</property>
-    <property name="xalign">0.4699999988079071</property>
+    <property name="xalign">0.49000000953674316</property>
+    <property name="yalign">0.41999998688697815</property>
     <property name="stock">gtk-add</property>
   </object>
-  <object class="GtkImage" id="image2">
+  <object class="GtkImage" id="image1">
     <property name="visible">True</property>
     <property name="can_focus">False</property>
-    <property name="xalign">0.49000000953674316</property>
-    <property name="yalign">0.41999998688697815</property>
+    <property name="xalign">0.4699999988079071</property>
     <property name="stock">gtk-add</property>
   </object>
   <object class="GtkImage" id="image3">
@@ -42,6 +42,11 @@
     <property name="yalign">0.49000000953674316</property>
     <property name="stock">gtk-yes</property>
   </object>
+  <object class="GtkImage" id="image8">
+    <property name="visible">True</property>
+    <property name="can_focus">False</property>
+    <property name="stock">gtk-add</property>
+  </object>
   <object class="GtkMenuBar" id="menu_bar">
     <property name="visible">True</property>
     <property name="can_focus">False</property>
@@ -146,6 +151,17 @@
               </object>
             </child>
             <child>
+              <object class="GtkImageMenuItem" id="add subgraph">
+                <property name="label" translatable="yes">Add Subgraph</property>
+                <property name="use_action_appearance">False</property>
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="image">image8</property>
+                <property name="use_stock">False</property>
+                <signal name="activate" handler="activated_add_subgraph" swapped="no"/>
+              </object>
+            </child>
+            <child>
               <object class="GtkImageMenuItem" id="delete">
                 <property name="label" translatable="yes">Delete</property>
                 <property name="use_action_appearance">False</property>
@@ -170,30 +186,32 @@
                 <property name="use_action_appearance">False</property>
                 <property name="visible">True</property>
                 <property name="can_focus">False</property>
-                <property name="label" translatable="yes">Meta-op</property>
+                <property name="label" translatable="yes">Graph</property>
                 <property name="use_underline">True</property>
                 <child type="submenu">
                   <object class="GtkMenu" id="menu3">
                     <property name="visible">True</property>
                     <property name="can_focus">False</property>
                     <child>
-                      <object class="GtkImageMenuItem" id="imagemenuitem3">
+                      <object class="GtkImageMenuItem" id="add input">
                         <property name="label" translatable="yes">Add Input</property>
                         <property name="use_action_appearance">False</property>
                         <property name="visible">True</property>
                         <property name="can_focus">False</property>
                         <property name="image">image1</property>
                         <property name="use_stock">False</property>
+                        <signal name="activate" handler="activated_add_input" swapped="no"/>
                       </object>
                     </child>
                     <child>
-                      <object class="GtkImageMenuItem" id="imagemenuitem4">
+                      <object class="GtkImageMenuItem" id="add output">
                         <property name="label" translatable="yes">Add Output</property>
                         <property name="use_action_appearance">False</property>
                         <property name="visible">True</property>
                         <property name="can_focus">False</property>
                         <property name="image">image2</property>
                         <property name="use_stock">False</property>
+                        <signal name="activate" handler="activated_add_output" swapped="no"/>
                       </object>
                     </child>
                     <child>
@@ -204,6 +222,7 @@
                         <property name="can_focus">False</property>
                         <property name="image">image3</property>
                         <property name="use_stock">False</property>
+                        <signal name="activate" handler="activated_metaop_properties" swapped="no"/>
                       </object>
                     </child>
                   </object>
@@ -219,7 +238,7 @@
         <property name="use_action_appearance">False</property>
         <property name="visible">True</property>
         <property name="can_focus">False</property>
-        <property name="label" translatable="yes">_Graph</property>
+        <property name="label" translatable="yes">_Gegl</property>
         <property name="use_underline">True</property>
         <child type="submenu">
           <object class="GtkMenu" id="menu4">



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