[gegl-gtk] operations: Use GeglGtkView widget in display operation



commit c93f2eb12b28cb24fb269dfe80eeb3f75e2cdb50
Author: Jon Nordby <jononor gmail com>
Date:   Mon Jun 27 02:09:16 2011 +0200

    operations: Use GeglGtkView widget in display operation
    
    Reduces code duplication.
    Currently the operation does not spin the GTK+ main
    loop. This needs to be fixed.
    
    Also adds an example for how to use the operation.

 examples/.gitignore            |    1 +
 examples/gegl-gtk-display-op.c |   60 +++++++++++++++
 gegl-gtk/Makefile.am           |    2 +-
 operations/Makefile.am         |   12 ++--
 operations/gegl-gtk-display.c  |  159 ++++++++++------------------------------
 5 files changed, 108 insertions(+), 126 deletions(-)
---
diff --git a/examples/.gitignore b/examples/.gitignore
index 727dec4..264e3fe 100644
--- a/examples/.gitignore
+++ b/examples/.gitignore
@@ -1,2 +1,3 @@
 gegl-gtk-paint
 gegl-gtk-basic
+gegl-gtk-display-op
diff --git a/examples/gegl-gtk-display-op.c b/examples/gegl-gtk-display-op.c
new file mode 100644
index 0000000..f0bba61
--- /dev/null
+++ b/examples/gegl-gtk-display-op.c
@@ -0,0 +1,60 @@
+/* This file is part of GEGL-GTK
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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) 2011 Jon Nordby <jononor gmail com>
+ */
+
+#include <string.h>
+#include <glib.h>
+#include <gegl.h>
+
+gint
+main (gint    argc,
+      gchar **argv)
+{
+  GeglNode *graph = NULL;
+  GeglNode *node = NULL;
+  GeglNode *display = NULL;
+
+  g_thread_init (NULL);
+  gegl_init (&argc, &argv);
+
+  if (argc != 2) {
+    g_print ("Usage: %s <FILENAME>\n", argv[0]);
+    exit(1);
+  }
+
+  /* Build graph that loads an image */
+  graph = gegl_node_new ();
+  node = gegl_node_new_child (graph,
+    "operation", "gegl:load",
+    "path", argv[1], NULL);
+  display = gegl_node_new_child (graph,
+    "operation", "gegl-gtk2:display", NULL);
+  gegl_node_link_many (node, display, NULL);
+
+  gegl_node_process (display);
+
+  /* FIXME: operation must spin the gtk mainloop itself */
+  while (gtk_events_pending ())
+    gtk_main_iteration ();
+
+  sleep (2);
+
+  /* Cleanup */
+  g_object_unref (graph);
+  gegl_exit ();
+  return 0;
+}
diff --git a/gegl-gtk/Makefile.am b/gegl-gtk/Makefile.am
index 7578d0b..df6a5dd 100644
--- a/gegl-gtk/Makefile.am
+++ b/gegl-gtk/Makefile.am
@@ -9,7 +9,7 @@ gegl_gtk_include_HEADERS = $(headers)
 
 gegl_gtk_SOURCES = $(headers) $(sources)
 gegl_gtk_LIBADD  = $(GTK_LIBS) $(GEGL_LIBS)
-gegl_gtk_CFLAGS  = $(INCLUDES)
+gegl_gtk_CFLAGS  = $(INCLUDES) $(CFLAGS)
 
 if HAVE_GTK2
 lib_LTLIBRARIES = libgegl-gtk2-0.1.la
diff --git a/operations/Makefile.am b/operations/Makefile.am
index 985baa5..ecc5b96 100644
--- a/operations/Makefile.am
+++ b/operations/Makefile.am
@@ -1,9 +1,10 @@
 
 ext_dir = $(GEGL_PLUGINS_DIR)
+libgeglgtk = $(top_builddir)/gegl-gtk/libgegl-gtk$(GEGL_GTK_GTK_VERSION)-$(GEGL_GTK_API_VERSION).la
 
-LIBS            = $(GTK_LIBS) $(GEGL_LIBS)
-CFLAGS			= $(GTK_CFLAGS) $(GEGL_CFLAGS)
-LDFLAGS			= -avoid-version -export-dynamic -module
+op_LIBS            = $(GTK_LIBS) $(GEGL_LIBS) $(libgeglgtk)
+op_CFLAGS			= $(GTK_CFLAGS) $(GEGL_CFLAGS)
+op_LDFLAGS			= -avoid-version -export-dynamic -module
 
 CFILES          = $(wildcard $(srcdir)/*.c)
 plugins         = $(subst gegl-gtk-,gegl-gtk GEGL_GTK_GTK_VERSION@-, $(subst $(srcdir)/,,$(CFILES:.c=.la)))
@@ -20,9 +21,8 @@ gegl_lt_ccld_v_0 = @echo "  CCLD   " $@;
 all-local: $(plugins)
 
 gegl-gtk GEGL_GTK_GTK_VERSION@-%.la: gegl-gtk-%.c
-	$(gegl_lt_cc_v) $(LIBTOOL) --quiet --tag=CC --mode=compile $(CC) $(DEFS) -I. -I$(top_builddir) -I$(srcdir) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o $  lo $<
-	$(gegl_lt_ccld_v) $(LIBTOOL) --quiet --tag=CC --mode=link $(CC) $(AM_LDFLAGS) $(LDFLAGS) $(CFLAGS) -o $@ -rpath $(ext_dir) $  lo $(LIBS) $(MATH_LIB)
-
+	$(gegl_lt_cc_v) $(LIBTOOL) --quiet --tag=CC --mode=compile $(CC) $(DEFS) -I. -I$(top_builddir) -I$(top_srcdir)/gegl-gtk -I$(srcdir) $(AM_CPPFLAGS) $(CPPFLAGS) $(op_CFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o $  lo $<
+	$(gegl_lt_ccld_v) $(LIBTOOL) --quiet --tag=CC --mode=link $(CC) $(AM_LDFLAGS) $(op_LDFLAGS) $(op_CFLAGS) $(CFLAGS) -o $@ -rpath $(ext_dir) $  lo $(op_LIBS) $(MATH_LIB)
 
 clean-local:
 	rm -f *.la
diff --git a/operations/gegl-gtk-display.c b/operations/gegl-gtk-display.c
index 5019c65..cf4804d 100644
--- a/operations/gegl-gtk-display.c
+++ b/operations/gegl-gtk-display.c
@@ -32,75 +32,22 @@ gegl_chant_string  (window_title, _("Window Title"), "",
 
 #include <gegl.h>
 #include <gegl-chant.h>
+
 #include <gtk/gtk.h>
+#include <gegl-gtk.h>
 
 typedef struct
 {
   GtkWidget *window;
-  GtkWidget *drawing_area;
+  GtkWidget *view_widget;
+  GeglNode  *node;
+  GeglNode  *input;
   gint       width;
   gint       height;
-  guchar    *buf;
 } Priv;
 
-
-static void
-draw_implementation (Priv *priv, cairo_t *cr)
-{
-  cairo_surface_t *surface = NULL;
-
-  if (!priv->buf)
-    return;
-
-  surface = cairo_image_surface_create_for_data (priv->buf,
-                                                 CAIRO_FORMAT_ARGB32,
-                                                 priv->width, priv->height,
-                                                 priv->width*4);
-
-  cairo_set_source_surface (cr, surface, 0.0, 0.0);
-  cairo_paint (cr);
-
-  cairo_surface_finish (surface);
-}
-
-#ifdef HAVE_GTK2
-static gboolean
-expose_event (GtkWidget *widget, GdkEventExpose * event, gpointer user_data)
-{
-  GeglChantO *o = GEGL_CHANT_PROPERTIES (g_object_get_data (G_OBJECT (widget), "op"));
-  Priv       *priv = (Priv*)o->chant_data;
-  cairo_t *cr = gdk_cairo_create (widget->window);
-
-  if (event->area.x + event->area.width > priv->width)
-    event->area.width = priv->width - event->area.x;
-  if (event->area.y + event->area.height > priv->height)
-    event->area.height = priv->height - event->area.y;
-
-  cairo_rectangle (cr, event->area.x, event->area.y,
-                   event->area.width, event->area.height);
-  cairo_clip (cr);
-
-  draw_implementation (priv, cr);
-  cairo_destroy (cr);
-
-  return TRUE;
-}
-#endif
-
-#ifdef HAVE_GTK3
-static gboolean
-draw (GtkWidget * widget, cairo_t *cr, gpointer user_data)
-{
-  GeglChantO *o = GEGL_CHANT_PROPERTIES (g_object_get_data (G_OBJECT (widget), "op"));
-  Priv       *priv = (Priv*)o->chant_data;
-
-  draw_implementation (priv, cr);
-
-  return TRUE;
-}
-#endif
-
-static Priv *init_priv (GeglOperation *operation)
+static Priv *
+init_priv (GeglOperation *operation)
 {
   GeglChantO *o = GEGL_CHANT_PROPERTIES (operation);
 
@@ -112,90 +59,69 @@ static Priv *init_priv (GeglOperation *operation)
       gtk_init (0, 0);
 
       priv->window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
-      priv->drawing_area = gtk_drawing_area_new ();
-      gtk_container_add (GTK_CONTAINER (priv->window), priv->drawing_area);
+      priv->view_widget = g_object_new (GEGL_GTK_TYPE_VIEW, NULL);
+      gtk_container_add (GTK_CONTAINER (priv->window), priv->view_widget);
       priv->width = -1;
       priv->height = -1;
-      gtk_widget_set_size_request (priv->drawing_area, priv->width, priv->height);
+      gtk_widget_set_size_request (priv->view_widget, priv->width, priv->height);
       gtk_window_set_title (GTK_WINDOW (priv->window), o->window_title);
 
-#ifdef HAVE_GTK2
-      g_signal_connect (G_OBJECT (priv->drawing_area), "expose_event",
-                        G_CALLBACK (expose_event), priv);
-#endif
-
-#ifdef HAVE_GTK3
-      g_signal_connect (G_OBJECT (priv->drawing_area), "draw",
-                        G_CALLBACK (draw), priv);
-#endif
-
-      g_object_set_data (G_OBJECT (priv->drawing_area), "op", operation);
+      priv->node = NULL;
+      priv->input = NULL;
 
       gtk_widget_show_all (priv->window);
-
-      priv->buf = NULL;
     }
   return (Priv*)(o->chant_data);
 }
 
-static gboolean
-process (GeglOperation       *operation,
-         GeglBuffer          *input,
-         const GeglRectangle *result)
+static void
+set_window_attributes (GeglOperation *operation, const GeglRectangle *result)
 {
   GeglChantO *o = GEGL_CHANT_PROPERTIES (operation);
   Priv       *priv = init_priv (operation);
-  GeglBuffer *source = NULL;
-  Babl       *format = NULL;
-
-  g_assert (input);
 
   if (priv->width != result->width  ||
       priv->height != result->height)
     {
       priv->width = result->width ;
       priv->height = result->height;
-      gtk_widget_set_size_request (priv->drawing_area, priv->width, priv->height);
-
-      if (priv->buf)
-        g_free (priv->buf);
-      priv->buf = g_malloc (priv->width * priv->height * 4);
+      gtk_widget_set_size_request (priv->view_widget, priv->width, priv->height);
     }
-
-  source = gegl_buffer_create_sub_buffer (input, result);
-
-  format = babl_format_new (babl_model ("RGBA"), babl_type ("u8"),
-                            babl_component ("B"),
-                            babl_component ("G"),
-                            babl_component ("R"),
-                            babl_component ("A"),
-                            NULL);
-  gegl_buffer_get (source, 1.0, NULL, format,
-                   priv->buf, GEGL_AUTO_ROWSTRIDE);
-  gtk_widget_queue_draw (priv->drawing_area);
+  
 
   if (priv->window)
     {
       gtk_window_resize (GTK_WINDOW (priv->window), priv->width, priv->height);
-      if (o->window_title[0]!='\0')
+      if (o->window_title && o->window_title[0]!='\0')
         {
           gtk_window_set_title (GTK_WINDOW (priv->window), o->window_title);
         }
       else
         {
           gtk_window_set_title (GTK_WINDOW (priv->window),
-           gegl_node_get_debug_name (gegl_node_get_producer(operation->node, "input", NULL))
-           );
+          gegl_node_get_debug_name (gegl_node_get_producer(operation->node, "input", NULL))
+          );
         }
+  }
+}
 
-      while (gtk_events_pending ())
-        {
-          gtk_main_iteration ();
-        }
-    }
-  g_object_unref (source);
+/* Create an input proxy, and initial display operation, and link together.
+ * These will be passed control when process is called later. */
+static void
+attach (GeglOperation *operation)
+{
+  Priv       *priv = init_priv (operation);
 
-  return  TRUE;
+  g_assert (!priv->input);
+  g_assert (!priv->node);
+
+  priv->input = gegl_node_get_input_proxy (operation->node, "input");
+  priv->node = gegl_node_new_child (operation->node,
+                                    "operation", "gegl:nop",
+                                    NULL);
+
+  gegl_node_link (priv->input, priv->node);
+  g_object_set (G_OBJECT (priv->view_widget), "node", priv->node, NULL);
 }
 
 static void
@@ -207,8 +133,6 @@ dispose (GObject *object)
   if (priv)
     {
       gtk_widget_destroy (priv->window);
-      if (priv->buf)
-        g_free (priv->buf);
       g_free (priv);
       o->chant_data = NULL;
     }
@@ -220,13 +144,10 @@ dispose (GObject *object)
 static void
 gegl_chant_class_init (GeglChantClass *klass)
 {
-  GeglOperationClass     *operation_class;
-  GeglOperationSinkClass *sink_class;
-
-  operation_class = GEGL_OPERATION_CLASS (klass);
-  sink_class      = GEGL_OPERATION_SINK_CLASS (klass);
+  GeglOperationClass     *operation_class = GEGL_OPERATION_CLASS (klass);
+  GeglOperationSinkClass *sink_class = GEGL_OPERATION_SINK_CLASS (klass);
 
-  sink_class->process = process;
+  operation_class->attach = attach;
   G_OBJECT_CLASS (klass)->dispose = dispose;
 
 #ifdef HAVE_GTK2



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