[gimp/gimp-2-10] app: improve gegl:newsprint's GUI a lot



commit 3fc13bd4e71408d88b6f8f9a32601a66ecf0a180
Author: Michael Natterer <mitch gimp org>
Date:   Thu Jul 18 02:10:24 2019 +0200

    app: improve gegl:newsprint's GUI a lot
    
    Add some frames, a notebook for the channels and toggles to lock all
    channels' properties together.
    
    (cherry picked from commit ce44b04005a03517d506db34730e2196a71dcfcb)

 app/propgui/gimppropgui-newsprint.c | 388 +++++++++++++++++++++++++++++++++++-
 1 file changed, 385 insertions(+), 3 deletions(-)
---
diff --git a/app/propgui/gimppropgui-newsprint.c b/app/propgui/gimppropgui-newsprint.c
index dfc95f937e..ecdc0dcdef 100644
--- a/app/propgui/gimppropgui-newsprint.c
+++ b/app/propgui/gimppropgui-newsprint.c
@@ -23,6 +23,7 @@
 #include <gegl.h>
 #include <gtk/gtk.h>
 
+#include "libgimpmath/gimpmath.h"
 #include "libgimpwidgets/gimpwidgets.h"
 
 #include "propgui-types.h"
@@ -36,6 +37,91 @@
 #include "gimp-intl.h"
 
 
+typedef enum
+{
+  COLOR_MODEL_WHITE_ON_BLACK,
+  COLOR_MODEL_BLACK_ON_WHITE,
+  COLOR_MODEL_RGB,
+  COLOR_MODEL_CMYK,
+
+  N_COLOR_MODELS
+} ColorModel;
+
+typedef enum
+{
+  PATTERN_LINE,
+  PATTERN_CIRCLE,
+  PATTERN_DIAMOND,
+  PATTERN_PSCIRCLE,
+  PATTERN_CROSS,
+
+  N_PATTERNS
+} Pattern;
+
+
+typedef struct _Newsprint Newsprint;
+
+struct _Newsprint
+{
+  GObject   *config;
+  GtkWidget *notebook;
+  GtkWidget *pattern_check;
+  GtkWidget *period_check;
+  GtkWidget *angle_check;
+};
+
+
+/*  local function prototypes  */
+
+static void   newsprint_color_model_notify    (GObject          *config,
+                                               const GParamSpec *pspec,
+                                               GtkWidget        *label);
+static void   newsprint_model_prop_notify     (GObject          *config,
+                                               const GParamSpec *pspec,
+                                               Newsprint        *np);
+static void   newsprint_lock_patterns_toggled (GtkWidget        *widget,
+                                               Newsprint        *np);
+static void   newsprint_lock_periods_toggled  (GtkWidget        *widget,
+                                               Newsprint        *np);
+static void   newsprint_lock_angles_toggled   (GtkWidget        *widget,
+                                               Newsprint        *np);
+
+
+static const gchar *label_strings[N_COLOR_MODELS][4] =
+{
+  { NULL,       NULL,          NULL,         N_("White") },
+  { NULL,       NULL,          NULL,         N_("Black") },
+  { N_("Red"),  N_("Green"),   N_("Blue"),   NULL        },
+  { N_("Cyan"), N_("Magenta"), N_("Yellow"), N_("Black") }
+};
+
+static const gchar *pattern_props[] =
+{
+  "pattern2",
+  "pattern3",
+  "pattern4",
+  "pattern"
+};
+
+static const gchar *period_props[] =
+{
+  "period2",
+  "period3",
+  "period4",
+  "period"
+};
+
+static const gchar *angle_props[] =
+{
+  "angle2",
+  "angle3",
+  "angle4",
+  "angle"
+};
+
+
+/*  public functions  */
+
 GtkWidget *
 _gimp_prop_gui_new_newsprint (GObject                  *config,
                               GParamSpec              **param_specs,
@@ -46,17 +132,313 @@ _gimp_prop_gui_new_newsprint (GObject                  *config,
                               GimpCreateControllerFunc  create_controller_func,
                               gpointer                  creator)
 {
+  Newsprint *np;
+  GtkWidget *main_vbox;
+  GtkWidget *frame;
+  GtkWidget *vbox;
+  GtkWidget *hbox;
+  GtkWidget *combo;
+  GtkWidget *labels[4];
+  GtkWidget *pages[4];
+  GtkWidget *check;
+  gint       i;
+
   g_return_val_if_fail (G_IS_OBJECT (config), NULL);
   g_return_val_if_fail (param_specs != NULL, NULL);
   g_return_val_if_fail (n_param_specs > 0, NULL);
   g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
 
-  return _gimp_prop_gui_new_generic (config,
-                                     param_specs,
-                                     n_param_specs,
+  np = g_new0 (Newsprint, 1);
+
+  np->config = config;
+
+  main_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 4);
+
+  g_object_set_data_full (G_OBJECT (main_vbox), "newsprint", np,
+                          (GDestroyNotify) g_free);
+
+  frame = gimp_frame_new (_("Channels"));
+  gtk_box_pack_start (GTK_BOX (main_vbox), frame, FALSE, FALSE, 0);
+  gtk_widget_show (frame);
+
+  vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2);
+  gtk_container_add (GTK_CONTAINER (frame), vbox);
+  gtk_widget_show (vbox);
+
+  combo = _gimp_prop_gui_new_generic (config,
+                                      param_specs + 0, 1,
+                                      area,
+                                      context,
+                                      create_picker_func,
+                                      create_controller_func,
+                                      creator);
+  gtk_box_pack_start (GTK_BOX (vbox), combo, FALSE, FALSE, 0);
+  gtk_widget_show (combo);
+
+  np->notebook = gtk_notebook_new ();
+  gtk_box_pack_start (GTK_BOX (vbox), np->notebook, FALSE, FALSE, 0);
+  gtk_widget_show (np->notebook);
+
+  for (i = 0; i < 4; i++)
+    {
+      GtkWidget   *widget;
+      const gchar *unused;
+      gint         remaining;
+
+      labels[i] = gtk_label_new (NULL);
+      pages[i]  = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2);
+
+      g_object_set_data (G_OBJECT (labels[i]), "channel", GINT_TO_POINTER (i));
+
+      g_signal_connect_object (config, "notify::color-model",
+                               G_CALLBACK (newsprint_color_model_notify),
+                               G_OBJECT (labels[i]), 0);
+
+      newsprint_color_model_notify (config, NULL, labels[i]);
+
+      gtk_container_set_border_width (GTK_CONTAINER (pages[i]), 6);
+      gtk_notebook_append_page (GTK_NOTEBOOK (np->notebook),
+                                pages[i], labels[i]);
+
+      widget = gimp_prop_widget_new_from_pspec (config,
+                                                param_specs[1 + 3 * i],
+                                                area, context,
+                                                create_picker_func,
+                                                create_controller_func,
+                                                creator, &unused);
+      gtk_box_pack_start (GTK_BOX (pages[i]), widget, FALSE, FALSE, 0);
+      gtk_widget_show (widget);
+
+      g_object_bind_property (G_OBJECT (widget),   "visible",
+                              G_OBJECT (pages[i]), "visible",
+                              G_BINDING_SYNC_CREATE);
+
+      if (i == 3)
+        remaining = 3;
+      else
+        remaining = 2;
+
+      widget = _gimp_prop_gui_new_generic (config,
+                                           param_specs + 2 + 3 * i, remaining,
+                                           area, context,
+                                           create_picker_func,
+                                           create_controller_func,
+                                           creator);
+      gtk_box_pack_start (GTK_BOX (pages[i]), widget, FALSE, FALSE, 0);
+      gtk_widget_show (widget);
+    }
+
+  hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 4);
+  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
+  gtk_widget_show (hbox);
+
+  np->pattern_check = check =
+    gtk_check_button_new_with_label (_("Lock patterns"));
+  gtk_box_pack_start (GTK_BOX (hbox), check, FALSE, FALSE, 0);
+  gtk_widget_show (check);
+
+  g_signal_connect (check, "toggled",
+                    G_CALLBACK (newsprint_lock_patterns_toggled),
+                    np);
+
+  np->period_check = check =
+    gtk_check_button_new_with_label (_("Lock periods"));
+  gtk_box_pack_start (GTK_BOX (hbox), check, FALSE, FALSE, 0);
+  gtk_widget_show (check);
+
+  g_signal_connect (check, "toggled",
+                    G_CALLBACK (newsprint_lock_periods_toggled),
+                    np);
+
+  np->angle_check = check =
+    gtk_check_button_new_with_label (_("Lock angles"));
+  gtk_box_pack_start (GTK_BOX (hbox), check, FALSE, FALSE, 0);
+  gtk_widget_show (check);
+
+  g_signal_connect (check, "toggled",
+                    G_CALLBACK (newsprint_lock_angles_toggled),
+                    np);
+
+  frame = gimp_frame_new (_("Quality"));
+  gtk_box_pack_start (GTK_BOX (main_vbox), frame, FALSE, FALSE, 0);
+  gtk_widget_show (frame);
+
+  vbox = _gimp_prop_gui_new_generic (config,
+                                     param_specs + 14, 1,
                                      area,
                                      context,
                                      create_picker_func,
                                      create_controller_func,
                                      creator);
+  gtk_container_add (GTK_CONTAINER (frame), vbox);
+  gtk_widget_show (vbox);
+
+  frame = gimp_frame_new (_("Effects"));
+  gtk_box_pack_start (GTK_BOX (main_vbox), frame, FALSE, FALSE, 0);
+  gtk_widget_show (frame);
+
+  vbox = _gimp_prop_gui_new_generic (config,
+                                     param_specs + 15, 3,
+                                     area,
+                                     context,
+                                     create_picker_func,
+                                     create_controller_func,
+                                     creator);
+  gtk_container_add (GTK_CONTAINER (frame), vbox);
+  gtk_widget_show (vbox);
+
+  g_signal_connect (config, "notify",
+                    G_CALLBACK (newsprint_model_prop_notify),
+                    np);
+
+  return main_vbox;
+}
+
+
+/*  private functions  */
+
+static void
+newsprint_color_model_notify (GObject          *config,
+                              const GParamSpec *pspec,
+                              GtkWidget        *label)
+{
+  ColorModel  model;
+  gint        channel;
+
+  g_object_get (config,
+                "color-model", &model,
+                NULL);
+
+  channel =
+    GPOINTER_TO_INT (g_object_get_data (G_OBJECT (label), "channel"));
+
+  if (label_strings[model][channel])
+    gtk_label_set_text (GTK_LABEL (label),
+                        gettext (label_strings[model][channel]));
+}
+
+static gboolean
+newsprint_sync_model_props (Newsprint         *np,
+                            const GParamSpec  *pspec,
+                            const gchar      **props,
+                            gint               n_props)
+{
+  gint i;
+
+  for (i = 0; i < n_props; i++)
+    {
+      if (! strcmp (pspec->name, props[i]))
+        {
+          GValue value = G_VALUE_INIT;
+          gint   j;
+
+          g_value_init (&value, pspec->value_type);
+
+          g_object_get_property (np->config, pspec->name, &value);
+
+          for (j = 0; j < n_props; j++)
+            {
+              if (i != j)
+                {
+                  g_signal_handlers_block_by_func (np->config,
+                                                   newsprint_model_prop_notify,
+                                                   np);
+
+                  g_object_set_property (np->config, props[j], &value);
+
+                  g_signal_handlers_unblock_by_func (np->config,
+                                                     newsprint_model_prop_notify,
+                                                     np);
+                }
+            }
+
+          g_value_unset (&value);
+
+          return TRUE;
+        }
+    }
+
+  return FALSE;
+}
+
+static void
+newsprint_model_prop_notify (GObject          *config,
+                             const GParamSpec *pspec,
+                             Newsprint        *np)
+{
+
+  if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (np->pattern_check)) &&
+      newsprint_sync_model_props (np, pspec,
+                                  pattern_props, G_N_ELEMENTS (pattern_props)))
+    return;
+
+  if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (np->period_check)) &&
+      newsprint_sync_model_props (np, pspec,
+                                  period_props, G_N_ELEMENTS (period_props)))
+    return;
+
+  if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (np->angle_check)) &&
+      newsprint_sync_model_props (np, pspec,
+                                  angle_props, G_N_ELEMENTS (angle_props)))
+    return;
+}
+
+static void
+newsprint_lock_patterns_toggled (GtkWidget *widget,
+                                 Newsprint *np)
+
+{
+  if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)))
+    {
+      GParamSpec *pspec;
+      gint        channel;
+
+      channel = gtk_notebook_get_current_page (GTK_NOTEBOOK (np->notebook));
+
+      pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (np->config),
+                                            pattern_props[channel]);
+
+      newsprint_sync_model_props (np, pspec,
+                                  pattern_props, G_N_ELEMENTS (pattern_props));
+    }
+}
+
+static void
+newsprint_lock_periods_toggled (GtkWidget *widget,
+                                Newsprint *np)
+
+{
+  if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)))
+    {
+      GParamSpec *pspec;
+      gint        channel;
+
+      channel = gtk_notebook_get_current_page (GTK_NOTEBOOK (np->notebook));
+
+      pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (np->config),
+                                            period_props[channel]);
+
+      newsprint_sync_model_props (np, pspec,
+                                  period_props, G_N_ELEMENTS (period_props));
+    }
+}
+
+static void
+newsprint_lock_angles_toggled (GtkWidget *widget,
+                               Newsprint *np)
+
+{
+  if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)))
+    {
+      GParamSpec *pspec;
+      gint        channel;
+
+      channel = gtk_notebook_get_current_page (GTK_NOTEBOOK (np->notebook));
+
+      pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (np->config),
+                                            angle_props[channel]);
+
+      newsprint_sync_model_props (np, pspec,
+                                  angle_props, G_N_ELEMENTS (angle_props));
+    }
 }


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