[gimp] gui: Add pixel density selector to canvas size dialog ...



commit b21865328c320204d738db53730e3704739380ef
Author: Stanislav Grinkov <43956-stanislavgrinkov users noreply gitlab gnome org>
Date:   Sun Feb 7 22:06:41 2021 +0600

    gui: Add pixel density selector to canvas size dialog ...
    
    which will be shown when selected template pixel density don't
    match the image pixel density.
    
    Then user can either keep current image ppi and scale the
    template or set image ppi to match the template ppi.
    
    Density selector displayed only when template and image ppi
    differs and template unit is matches one of real world units
    (e.g. inch, mm, etc).
    
    Closes: GNOME/gimp#1140

 app/actions/image-commands.c  |  32 +++++-
 app/actions/layers-commands.c |  14 ++-
 app/dialogs/resize-dialog.c   | 233 +++++++++++++++++++++++++++++++++++++++---
 app/dialogs/resize-dialog.h   |   3 +
 4 files changed, 260 insertions(+), 22 deletions(-)
---
diff --git a/app/actions/image-commands.c b/app/actions/image-commands.c
index 585ae6c1ff..5c30bcb4cf 100644
--- a/app/actions/image-commands.c
+++ b/app/actions/image-commands.c
@@ -138,6 +138,9 @@ static void   image_resize_callback            (GtkWidget              *dialog,
                                                 GimpUnit                unit,
                                                 gint                    offset_x,
                                                 gint                    offset_y,
+                                                gdouble                 xres,
+                                                gdouble                 yres,
+                                                GimpUnit                res_unit,
                                                 GimpFillType            fill_type,
                                                 GimpItemSet             layer_set,
                                                 gboolean                resize_text_layers,
@@ -1362,6 +1365,9 @@ image_resize_callback (GtkWidget    *dialog,
                        GimpUnit      unit,
                        gint          offset_x,
                        gint          offset_y,
+                       gdouble       xres,
+                       gdouble       yres,
+                       GimpUnit      res_unit,
                        GimpFillType  fill_type,
                        GimpItemSet   layer_set,
                        gboolean      resize_text_layers,
@@ -1376,6 +1382,10 @@ image_resize_callback (GtkWidget    *dialog,
       GimpImage        *image  = GIMP_IMAGE (viewable);
       GimpDialogConfig *config = GIMP_DIALOG_CONFIG (image->gimp->config);
       GimpProgress     *progress;
+      gdouble           old_xres;
+      gdouble           old_yres;
+      GimpUnit          old_res_unit;
+      gboolean          update_resolution;
 
       g_object_set (config,
                     "image-resize-fill-type",          fill_type,
@@ -1392,9 +1402,26 @@ image_resize_callback (GtkWidget    *dialog,
       progress = gimp_progress_start (GIMP_PROGRESS (display), FALSE,
                                       _("Resizing"));
 
+      gimp_image_get_resolution (image, &old_xres, &old_yres);
+      old_res_unit = gimp_image_get_unit (image);
+
+      update_resolution = xres     != old_xres ||
+                          yres     != old_yres ||
+                          res_unit != old_res_unit;
+
+      if (update_resolution)
+        {
+          gimp_image_undo_group_start (image,
+                                       GIMP_UNDO_GROUP_IMAGE_SCALE,
+                                       _("Change Canvas Size"));
+          gimp_image_set_resolution (image, xres, yres);
+          gimp_image_set_unit (image, res_unit);
+        }
+
       gimp_image_resize_with_layers (image,
                                      context, fill_type,
-                                     width, height, offset_x, offset_y,
+                                     width, height,
+                                     offset_x, offset_y,
                                      layer_set,
                                      resize_text_layers,
                                      progress);
@@ -1402,6 +1429,9 @@ image_resize_callback (GtkWidget    *dialog,
       if (progress)
         gimp_progress_end (progress);
 
+      if (update_resolution)
+        gimp_image_undo_group_end (image);
+
       gimp_image_flush (image);
     }
   else
diff --git a/app/actions/layers-commands.c b/app/actions/layers-commands.c
index b83dc8f862..32073bfd65 100644
--- a/app/actions/layers-commands.c
+++ b/app/actions/layers-commands.c
@@ -159,9 +159,12 @@ static void   layers_resize_callback          (GtkWidget             *dialog,
                                                GimpUnit               unit,
                                                gint                   offset_x,
                                                gint                   offset_y,
+                                               gdouble                unused0,
+                                               gdouble                unused1,
+                                               GimpUnit               unused2,
                                                GimpFillType           fill_type,
-                                               GimpItemSet            unused,
-                                               gboolean               unused2,
+                                               GimpItemSet            unused3,
+                                               gboolean               unused4,
                                                gpointer               data);
 
 static gint   layers_mode_index               (GimpLayerMode          layer_mode,
@@ -2542,9 +2545,12 @@ layers_resize_callback (GtkWidget    *dialog,
                         GimpUnit      unit,
                         gint          offset_x,
                         gint          offset_y,
+                        gdouble       unused0,
+                        gdouble       unused1,
+                        GimpUnit      unused2,
                         GimpFillType  fill_type,
-                        GimpItemSet   unused,
-                        gboolean      unused2,
+                        GimpItemSet   unused3,
+                        gboolean      unused4,
                         gpointer      user_data)
 {
   layer_resize_unit = unit;
diff --git a/app/dialogs/resize-dialog.c b/app/dialogs/resize-dialog.c
index c4e72db686..48eafda839 100644
--- a/app/dialogs/resize-dialog.c
+++ b/app/dialogs/resize-dialog.c
@@ -36,6 +36,7 @@
 #include "widgets/gimphelp-ids.h"
 #include "widgets/gimpsizebox.h"
 #include "widgets/gimpviewabledialog.h"
+#include "widgets/gimpwidgets-constructors.h"
 
 #include "resize-dialog.h"
 
@@ -59,6 +60,9 @@ struct _ResizeDialog
   GimpResizeCallback  callback;
   gpointer            user_data;
 
+  gdouble             old_xres;
+  gdouble             old_yres;
+  GimpUnit            old_res_unit;
   gint                old_width;
   gint                old_height;
   GimpUnit            old_unit;
@@ -72,6 +76,11 @@ struct _ResizeDialog
   GtkWidget          *layer_set_combo;
   GtkWidget          *fill_type_combo;
   GtkWidget          *text_layers_button;
+
+  GtkWidget          *ppi_box;
+  GtkWidget          *ppi_image;
+  GtkWidget          *ppi_template;
+  GimpTemplate       *template;
 };
 
 
@@ -99,6 +108,11 @@ static void   template_changed       (GimpContext  *context,
                                       GimpTemplate *template,
                                       ResizeDialog *private);
 
+static void   reset_template_clicked (GtkWidget    *button,
+                                      ResizeDialog *private);
+static void   ppi_select_toggled     (GtkWidget    *radio,
+                                      ResizeDialog *private);
+
 /*  public function  */
 
 GtkWidget *
@@ -128,6 +142,8 @@ resize_dialog_new (GimpViewable       *viewable,
   GtkWidget     *combo;
   GtkWidget     *label;
   GtkWidget     *template_selector;
+  GtkWidget     *ppi_image;
+  GtkWidget     *ppi_template;
   GtkAdjustment *adjustment;
   GdkPixbuf     *pixbuf;
   GtkSizeGroup  *size_group   = NULL;
@@ -175,6 +191,12 @@ resize_dialog_new (GimpViewable       *viewable,
                                               "resize-dialog",
                                               context);
 
+  gimp_image_get_resolution (image, &xres, &yres);
+
+  private->old_xres     = xres;
+  private->old_yres     = yres;
+  private->old_res_unit = gimp_image_get_unit (image);
+
   private->viewable           = viewable;
   private->fill_type          = fill_type;
   private->layer_set          = layer_set;
@@ -251,14 +273,74 @@ resize_dialog_new (GimpViewable       *viewable,
                     G_CALLBACK (template_changed),
                     private);
 
+  /* reset template button */
+  button = gimp_icon_button_new (GIMP_ICON_RESET, NULL);
+  gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
+  gtk_image_set_from_icon_name (GTK_IMAGE (gtk_bin_get_child (GTK_BIN (button))),
+                                GIMP_ICON_RESET, GTK_ICON_SIZE_MENU);
+  gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
+  gtk_widget_show (button);
+
+  g_signal_connect (button,
+                    "clicked",
+                    G_CALLBACK (reset_template_clicked),
+                    private);
+
+  gimp_help_set_help_data (button,
+                           _("Reset the template selection"),
+                           NULL);
+
+  /* ppi selector box */
+  private->ppi_box = vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
+  gtk_box_pack_start (GTK_BOX (main_vbox), vbox, FALSE, FALSE, 0);
+
+  label = gtk_label_new (_("Template and image print resolution don't match.\n"
+                           "Choose how to scale the canvas:"));
+  gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
+  gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_CENTER);
+  gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
+  gtk_widget_show (label);
+
+  hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
+  gtk_box_set_homogeneous (GTK_BOX (hbox), TRUE);
+  gtk_widget_show (hbox);
+
+  /* actual label text is set inside template_change fn. */
+  ppi_image    = gtk_radio_button_new_with_label (NULL, "");
+  ppi_template = gtk_radio_button_new_with_label (NULL, "");
+
+  private->ppi_image    = ppi_image;
+  private->ppi_template = ppi_template;
+
+  gtk_radio_button_join_group (GTK_RADIO_BUTTON (ppi_template),
+                               GTK_RADIO_BUTTON (ppi_image));
+
+  gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (ppi_image), FALSE);
+  gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (ppi_template), FALSE);
+
+  gtk_box_pack_start (GTK_BOX (hbox), ppi_image, FALSE, FALSE, 0);
+  gtk_box_pack_start (GTK_BOX (hbox), ppi_template, FALSE, FALSE, 0);
+
+  gtk_widget_show (ppi_image);
+  gtk_widget_show (ppi_template);
+
+  g_signal_connect (G_OBJECT (ppi_image),
+                    "toggled",
+                    G_CALLBACK (ppi_select_toggled),
+                    private);
+
+  g_signal_connect (G_OBJECT (ppi_template),
+                    "toggled",
+                    G_CALLBACK (ppi_select_toggled),
+                    private);
+
   /* size select frame */
   frame = gimp_frame_new (size_title);
   gtk_box_pack_start (GTK_BOX (main_vbox), frame, FALSE, FALSE, 0);
   gtk_widget_show (frame);
 
   /* size box */
-  gimp_image_get_resolution (image, &xres, &yres);
-
   private->box = g_object_new (GIMP_TYPE_SIZE_BOX,
                                "width",           width,
                                "height",          height,
@@ -271,6 +353,7 @@ resize_dialog_new (GimpViewable       *viewable,
   gtk_container_add (GTK_CONTAINER (frame), private->box);
   gtk_widget_show (private->box);
 
+  /* offset frame */
   frame = gimp_frame_new (_("Offset"));
   gtk_box_pack_start (GTK_BOX (main_vbox), frame, FALSE, FALSE, 0);
   gtk_widget_show (frame);
@@ -451,6 +534,9 @@ resize_dialog_response (GtkWidget    *dialog,
   GimpUnit       unit;
   gint           width;
   gint           height;
+  gdouble        xres;
+  gdouble        yres;
+  GimpUnit       res_unit;
 
   switch (response_id)
     {
@@ -460,9 +546,12 @@ resize_dialog_response (GtkWidget    *dialog,
 
     case GTK_RESPONSE_OK:
       g_object_get (private->box,
-                    "width",  &width,
-                    "height", &height,
-                    "unit",   &unit,
+                    "width",           &width,
+                    "height",          &height,
+                    "unit",            &unit,
+                    "xresolution",     &xres,
+                    "yresolution",     &yres,
+                    "resolution-unit", &res_unit,
                     NULL);
 
       private->callback (dialog,
@@ -473,6 +562,9 @@ resize_dialog_response (GtkWidget    *dialog,
                          unit,
                          gimp_size_entry_get_refval (entry, 0),
                          gimp_size_entry_get_refval (entry, 1),
+                         xres,
+                         yres,
+                         res_unit,
                          private->fill_type,
                          private->layer_set,
                          private->resize_text_layers,
@@ -493,9 +585,12 @@ resize_dialog_reset (ResizeDialog *private)
                 NULL);
 
   g_object_set (private->box,
-                "width",       private->old_width,
-                "height",      private->old_height,
-                "unit",        private->old_unit,
+                "width",           private->old_width,
+                "height",          private->old_height,
+                "unit",            private->old_unit,
+                "xresolution",     private->old_xres,
+                "yresolution",     private->old_yres,
+                "resolution-unit", private->old_res_unit,
                 NULL);
 
   if (private->layer_set_combo)
@@ -604,22 +699,126 @@ template_changed (GimpContext  *context,
                   GimpTemplate *template,
                   ResizeDialog *private)
 {
-  gint     width;
-  gint     height;
-  GimpUnit unit;
+  GimpUnit unit = private->old_unit;
+
+  private->template = template;
+
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (private->ppi_image), TRUE);
+  gtk_widget_hide (private->ppi_box);
+
+  if (template != NULL)
+    {
+      gdouble  xres;
+      gdouble  yres;
+      GimpUnit res_unit;
+      gboolean resolution_mismatch;
+
+      unit     = gimp_template_get_unit            (template);
+      xres     = gimp_template_get_resolution_x    (template);
+      yres     = gimp_template_get_resolution_y    (template);
+      res_unit = gimp_template_get_resolution_unit (template);
+
+      resolution_mismatch = xres     != private->old_xres ||
+                            yres     != private->old_yres ||
+                            res_unit != private->old_res_unit;
+
+      if (resolution_mismatch &&
+          unit != GIMP_UNIT_PIXEL)
+        {
+          gchar *text;
+
+          text = g_strdup_printf (_("Scale template to %.2f ppi"),
+                                  private->old_xres);
+          gtk_button_set_label (GTK_BUTTON (private->ppi_image), text);
+          g_free (text);
+
+          text = g_strdup_printf (_("Set image to %.2f ppi"),
+                                  xres);
+          gtk_button_set_label (GTK_BUTTON (private->ppi_template), text);
+          g_free (text);
+
+          gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (private->ppi_image),
+                                        TRUE);
+
+          gtk_widget_show (private->ppi_box);
+        }
+    }
 
-  if (! template)
-    return;
+  ppi_select_toggled (NULL, private);
+
+  gimp_size_entry_set_unit (GIMP_SIZE_ENTRY (private->offset), unit);
+}
+
+static void
+ppi_select_toggled (GtkWidget    *radio,
+                    ResizeDialog *private)
+{
+  gint             width;
+  gint             height;
+  GimpUnit         unit;
+  gdouble          xres;
+  gdouble          yres;
+  GimpUnit         res_unit;
+  GtkToggleButton *image_button;
+  gboolean         use_image_ppi;
+
+  width    = private->old_width;
+  height   = private->old_height;
+  xres     = private->old_xres;
+  yres     = private->old_yres;
+  res_unit = private->old_res_unit;
+  unit     = private->old_unit;
+
+  image_button  = GTK_TOGGLE_BUTTON (private->ppi_image);
+  use_image_ppi = gtk_toggle_button_get_active (image_button);
+
+  if (private->template != NULL)
+    {
+      width    = gimp_template_get_width           (private->template);
+      height   = gimp_template_get_height          (private->template);
+      unit     = gimp_template_get_unit            (private->template);
+      xres     = gimp_template_get_resolution_x    (private->template);
+      yres     = gimp_template_get_resolution_y    (private->template);
+      res_unit = gimp_template_get_resolution_unit (private->template);
+    }
 
-  width  = gimp_template_get_width (template);
-  height = gimp_template_get_height (template);
-  unit   = gimp_template_get_unit (template);
+  if (private->template != NULL &&
+      unit != GIMP_UNIT_PIXEL)
+    {
+      if (use_image_ppi)
+        {
+          width  = ceil (width  * (private->old_xres / xres));
+          height = ceil (height * (private->old_yres / yres));
+
+          xres = private->old_xres;
+          yres = private->old_yres;
+        }
+
+      g_object_set (private->box,
+                    "xresolution",     xres,
+                    "yresolution",     yres,
+                    "resolution-unit", res_unit,
+                    NULL);
+    }
+  else
+    {
+      g_object_set (private->box,
+                    "xresolution",     private->old_xres,
+                    "yresolution",     private->old_yres,
+                    "resolution-unit", private->old_res_unit,
+                    NULL);
+    }
 
   g_object_set (private->box,
                 "width",  width,
                 "height", height,
                 "unit",   unit,
                 NULL);
+}
 
-  gimp_size_entry_set_unit (GIMP_SIZE_ENTRY (private->offset), unit);
+static void
+reset_template_clicked (GtkWidget    *button,
+                        ResizeDialog *private)
+{
+  gimp_context_set_template (private->context, NULL);
 }
diff --git a/app/dialogs/resize-dialog.h b/app/dialogs/resize-dialog.h
index ddbe5ce1c8..223b43cc6d 100644
--- a/app/dialogs/resize-dialog.h
+++ b/app/dialogs/resize-dialog.h
@@ -27,6 +27,9 @@ typedef void (* GimpResizeCallback) (GtkWidget    *dialog,
                                      GimpUnit      unit,
                                      gint          offset_x,
                                      gint          offset_y,
+                                     gdouble       xres,
+                                     gdouble       yres,
+                                     GimpUnit      res_unit,
                                      GimpFillType  fill_type,
                                      GimpItemSet   layer_set,
                                      gboolean      resize_text_layers,


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