[gimp] plug-ins: goat-exercise improved to show a dialog.



commit 6ed3b4898c6f033413573c8249f2e7adb0f1df9c
Author: Jehan <jehan girinstud io>
Date:   Wed Aug 7 16:13:49 2019 +0200

    plug-ins: goat-exercise improved to show a dialog.
    
    This just adds a dialog before running the actual processing of data.
    - it also shows what the run-mode is for;
    - the purpose of the plug-in becomes explicit (plug-in creation
      documentation);
    - it shows some GTK+ code too.
    - last but not least, the code is actually shown for people to study,
      with a button to access the last version of the code on gitlab.
    
    This makes the plug-in a lot more useful and understandable this way.
    Other exercise plug-ins in other languages will have to do the same
    thing.

 plug-ins/goat-exercises/Makefile.am     |   3 +
 plug-ins/goat-exercises/goat-exercise.c | 128 ++++++++++++++++++++++++++++++--
 2 files changed, 126 insertions(+), 5 deletions(-)
---
diff --git a/plug-ins/goat-exercises/Makefile.am b/plug-ins/goat-exercises/Makefile.am
index 7c61a465d6..14ce1f3b01 100644
--- a/plug-ins/goat-exercises/Makefile.am
+++ b/plug-ins/goat-exercises/Makefile.am
@@ -36,6 +36,7 @@ AM_CPPFLAGS = \
 goat_exercise_libexecdir = $(gimpplugindir)/plug-ins/goat-exercise
 
 goat_exercise_libexec_PROGRAMS = goat-exercise
+goat_exercise_libexec_DATA = goat-exercise.c
 
 goat_exercise_SOURCES = \
        goat-exercise.c
@@ -46,6 +47,8 @@ goat_exercise_LDADD = \
        $(libgimpconfig)        \
        $(libgimpcolor)         \
        $(libgimpbase)          \
+       $(libgimpui)            \
+       $(libgimpwidgets)       \
        $(CAIRO_LIBS)           \
        $(GDK_PIXBUF_LIBS)      \
        $(GEGL_LIBS)            \
diff --git a/plug-ins/goat-exercises/goat-exercise.c b/plug-ins/goat-exercises/goat-exercise.c
index e04e4c9d30..3613f43729 100644
--- a/plug-ins/goat-exercises/goat-exercise.c
+++ b/plug-ins/goat-exercises/goat-exercise.c
@@ -27,7 +27,14 @@
 #include "libgimp/stdplugins-intl.h"
 
 
-#define PLUG_IN_PROC "plug-in-goat-exercise"
+#define PLUG_IN_BINARY "goat-exercise"
+#define PLUG_IN_SOURCE PLUG_IN_BINARY ".c"
+#define PLUG_IN_PROC   "plug-in-goat-exercise"
+#define PLUG_IN_ROLE   "goat-exercise-C"
+
+#define GOAT_URI       
"https://gitlab.gnome.org/GNOME/gimp/blob/master/plug-ins/goat-exercises/goat-exercise.c";
+#define GOAT_ERROR (goat_error_quark ())
+static GQuark  goat_error_quark (void) G_GNUC_CONST;
 
 
 typedef struct _Goat      Goat;
@@ -146,17 +153,113 @@ goat_run (GimpProcedure        *procedure,
           gpointer              run_data)
 {
   GimpPDBStatusType status = GIMP_PDB_SUCCESS;
+  GimpRunMode       run_mode;
   gint32            drawable_id;
   gint              x, y, width, height;
 
-  INIT_I18N();
-  gegl_init (NULL, NULL);
-
   g_printerr ("goat run %d %d %d\n",
               g_value_get_enum           (gimp_value_array_index (args, 0)),
               gimp_value_get_image_id    (gimp_value_array_index (args, 1)),
               gimp_value_get_drawable_id (gimp_value_array_index (args, 2)));
 
+  INIT_I18N();
+
+  /* In interactive mode, display a dialog to advertize the exercise. */
+  run_mode = g_value_get_enum (gimp_value_array_index (args, 0));
+  if (run_mode == GIMP_RUN_INTERACTIVE)
+    {
+      GtkTextBuffer    *buffer;
+      GtkWidget        *dialog;
+      GtkWidget        *box;
+      GtkWidget        *widget;
+      GtkWidget        *scrolled;
+      GFile            *file;
+      GFileInputStream *input;
+      gchar            *head_text;
+      gchar            *dir;
+      gchar            *path;
+      GdkGeometry       geometry;
+      gchar             source_text[4096];
+      gssize            read;
+      gint              response;
+
+      gimp_ui_init (PLUG_IN_BINARY, FALSE);
+      dialog = gimp_dialog_new (_("Exercise a goat (C)"), PLUG_IN_ROLE,
+                                NULL, GTK_DIALOG_USE_HEADER_BAR,
+                                gimp_standard_help_func, PLUG_IN_PROC,
+
+                                _("_Cancel"), GTK_RESPONSE_CANCEL,
+                                _("_Source"), GTK_RESPONSE_APPLY,
+                                _("_Run"),    GTK_RESPONSE_OK,
+
+                                NULL);
+      geometry.min_aspect = 0.5;
+      geometry.max_aspect = 1.0;
+      gtk_window_set_geometry_hints (GTK_WINDOW (dialog), NULL,
+                                     &geometry, GDK_HINT_ASPECT);
+
+      box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2);
+      gtk_container_add (GTK_CONTAINER (gtk_dialog_get_content_area (GTK_DIALOG (dialog))),
+                         box);
+      gtk_widget_show (box);
+
+      head_text = g_strdup_printf (_("This plug-in is an exercise in '%s' "
+                                "to demo plug-in creation.\n"
+                                "Check out the last version "
+                                "of the source code online by "
+                                "clicking the \"Source\" button."),
+                              "C");
+      widget = gtk_label_new (head_text);
+      g_free (head_text);
+      gtk_box_pack_start (GTK_BOX (box), widget, FALSE, FALSE, 1);
+      gtk_widget_show (widget);
+
+      scrolled = gtk_scrolled_window_new (NULL, NULL);
+      gtk_box_pack_start (GTK_BOX (box), scrolled, TRUE, TRUE, 1);
+      gtk_widget_set_vexpand (GTK_WIDGET (scrolled), TRUE);
+      gtk_widget_show (scrolled);
+
+      dir  = g_path_get_dirname (__FILE__);
+      path = g_build_filename (dir, PLUG_IN_SOURCE, NULL);
+      file = g_file_new_for_path (path);
+      g_free (dir);
+      g_free (path);
+
+      widget = gtk_text_view_new ();
+      gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (widget), GTK_WRAP_WORD);
+      gtk_text_view_set_editable (GTK_TEXT_VIEW (widget), FALSE);
+      buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (widget));
+      input = g_file_read (file, NULL, NULL);
+
+      while ((read = g_input_stream_read (G_INPUT_STREAM (input), source_text, 4096, NULL, NULL)) &&
+             read != -1)
+        gtk_text_buffer_insert_at_cursor (buffer, source_text, read);
+
+      g_object_unref (file);
+      gtk_container_add (GTK_CONTAINER (scrolled), widget);
+      gtk_widget_show (widget);
+
+      while ((response = gimp_dialog_run (GIMP_DIALOG (dialog))))
+        {
+          if (response == GTK_RESPONSE_OK)
+            {
+              gtk_widget_destroy (dialog);
+              break;
+            }
+          else if (response == GTK_RESPONSE_APPLY)
+            {
+              /* Show the code. */
+              g_app_info_launch_default_for_uri (GOAT_URI, NULL, NULL);
+              continue;
+            }
+          else /* CANCEL, CLOSE, DELETE_EVENT */
+            {
+              gtk_widget_destroy (dialog);
+              return gimp_procedure_new_return_values (procedure, GIMP_PDB_CANCEL, NULL);
+            }
+        }
+    }
+
   drawable_id = gimp_value_get_drawable_id (gimp_value_array_index (args, 2));
 
   if (gimp_drawable_mask_intersect (drawable_id, &x, &y, &width, &height))
@@ -164,6 +267,8 @@ goat_run (GimpProcedure        *procedure,
       GeglBuffer *buffer;
       GeglBuffer *shadow_buffer;
 
+      gegl_init (NULL, NULL);
+
       buffer        = gimp_drawable_get_buffer (drawable_id);
       shadow_buffer = gimp_drawable_get_shadow_buffer (drawable_id);
 
@@ -175,9 +280,22 @@ goat_run (GimpProcedure        *procedure,
       gimp_drawable_merge_shadow (drawable_id, TRUE);
       gimp_drawable_update (drawable_id, x, y, width, height);
       gimp_displays_flush ();
+
+      gegl_exit ();
+    }
+  else
+    {
+      return gimp_procedure_new_return_values (procedure, GIMP_PDB_CALLING_ERROR,
+                                               g_error_new (GOAT_ERROR, 0,
+                                                            "No pixels to process in the selected area."));
     }
 
-  gegl_exit ();
 
   return gimp_procedure_new_return_values (procedure, status, NULL);
 }
+
+static GQuark
+goat_error_quark (void)
+{
+  return g_quark_from_static_string ("goat-error-quark");
+}


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