[gimp] app: Selection fill and "Fill Path" now multi-layer aware.



commit 6b829c7008e788124fcff8bf92277ff5174ad764
Author: Jehan <jehan girinstud io>
Date:   Sat Aug 1 13:12:21 2020 +0200

    app: Selection fill and "Fill Path" now multi-layer aware.
    
    This includes the actions "select-fill*" as well as the "Fill Path"
    feature in the Vector tool which were using common code.

 app/actions/items-commands.c | 28 +++++++++++++++-------------
 app/actions/select-actions.c | 26 +++++++++++++++++++++++---
 app/core/gimpitem.c          | 20 +++++++++++++++-----
 app/core/gimpitem.h          |  2 +-
 app/dialogs/fill-dialog.c    | 11 ++++++-----
 app/dialogs/fill-dialog.h    |  4 ++--
 app/tools/gimpvectortool.c   | 18 ++++++++++--------
 7 files changed, 72 insertions(+), 37 deletions(-)
---
diff --git a/app/actions/items-commands.c b/app/actions/items-commands.c
index 43e17d90c9..2ae86417b1 100644
--- a/app/actions/items-commands.c
+++ b/app/actions/items-commands.c
@@ -47,7 +47,7 @@
 
 static void   items_fill_callback   (GtkWidget         *dialog,
                                      GimpItem          *item,
-                                     GimpDrawable      *drawable,
+                                     GList             *drawables,
                                      GimpContext       *context,
                                      GimpFillOptions   *options,
                                      gpointer           user_data);
@@ -190,18 +190,18 @@ items_fill_cmd_callback (GimpAction  *action,
                          const gchar *dialog_help_id,
                          gpointer     data)
 {
-  GimpDrawable *drawable;
+  GList        *drawables;
   GtkWidget    *dialog;
   GtkWidget    *widget;
   return_if_no_widget (widget, data);
 
-  drawable = gimp_image_get_active_drawable (image);
+  drawables = gimp_image_get_selected_drawables (image);
 
-  if (! drawable)
+  if (! drawables)
     {
       gimp_message_literal (image->gimp,
                             G_OBJECT (widget), GIMP_MESSAGE_WARNING,
-                            _("There is no active layer or channel to fill."));
+                            _("There are no selected layers or channels to fill."));
       return;
     }
 
@@ -212,7 +212,7 @@ items_fill_cmd_callback (GimpAction  *action,
       GimpDialogConfig *config = GIMP_DIALOG_CONFIG (image->gimp->config);
 
       dialog = fill_dialog_new (item,
-                                drawable,
+                                drawables,
                                 action_data_get_context (data),
                                 dialog_title,
                                 dialog_icon_name,
@@ -226,6 +226,7 @@ items_fill_cmd_callback (GimpAction  *action,
     }
 
   gtk_window_present (GTK_WINDOW (dialog));
+  g_list_free (drawables);
 }
 
 void
@@ -234,25 +235,25 @@ items_fill_last_vals_cmd_callback (GimpAction *action,
                                    GimpItem   *item,
                                    gpointer    data)
 {
-  GimpDrawable     *drawable;
+  GList            *drawables;
   GimpDialogConfig *config;
   GtkWidget        *widget;
   GError           *error = NULL;
   return_if_no_widget (widget, data);
 
-  drawable = gimp_image_get_active_drawable (image);
+  drawables = gimp_image_get_selected_drawables (image);
 
-  if (! drawable)
+  if (! drawables)
     {
       gimp_message_literal (image->gimp,
                             G_OBJECT (widget), GIMP_MESSAGE_WARNING,
-                            _("There is no active layer or channel to fill."));
+                            _("There are no selected layers or channels to fill."));
       return;
     }
 
   config = GIMP_DIALOG_CONFIG (image->gimp->config);
 
-  if (! gimp_item_fill (item, drawable,
+  if (! gimp_item_fill (item, drawables,
                         config->fill_options, TRUE, NULL, &error))
     {
       gimp_message_literal (image->gimp, G_OBJECT (widget),
@@ -263,6 +264,7 @@ items_fill_last_vals_cmd_callback (GimpAction *action,
     {
       gimp_image_flush (image);
     }
+  g_list_free (drawables);
 }
 
 void
@@ -358,7 +360,7 @@ items_stroke_last_vals_cmd_callback (GimpAction *action,
 static void
 items_fill_callback (GtkWidget       *dialog,
                      GimpItem        *item,
-                     GimpDrawable    *drawable,
+                     GList           *drawables,
                      GimpContext     *context,
                      GimpFillOptions *options,
                      gpointer         user_data)
@@ -370,7 +372,7 @@ items_fill_callback (GtkWidget       *dialog,
   gimp_config_sync (G_OBJECT (options),
                     G_OBJECT (config->fill_options), 0);
 
-  if (! gimp_item_fill (item, drawable, options, TRUE, NULL, &error))
+  if (! gimp_item_fill (item, drawables, options, TRUE, NULL, &error))
     {
       gimp_message_literal (context->gimp,
                             G_OBJECT (dialog),
diff --git a/app/actions/select-actions.c b/app/actions/select-actions.c
index 100d5f3d6b..96c8c79ac9 100644
--- a/app/actions/select-actions.c
+++ b/app/actions/select-actions.c
@@ -120,7 +120,7 @@ static const GimpActionEntry select_actions[] =
     GIMP_HELP_SELECTION_FILL },
 
   { "select-fill-last-values", GIMP_ICON_TOOL_BUCKET_FILL,
-    NC_("select-action", "_Fill Selection Outline"), NULL,
+    NC_("select-action", "_Fill Selection Outline with last values"), NULL,
     NC_("select-action", "Fill the selection outline with last used values"),
     select_fill_last_vals_cmd_callback,
     GIMP_HELP_SELECTION_FILL },
@@ -158,9 +158,27 @@ select_actions_update (GimpActionGroup *group,
   gboolean      writable = FALSE;
   gboolean      children = FALSE;
 
+  GList        *drawables    = NULL;
+  GList        *iter;
+  gboolean      all_writable = TRUE;
+  gboolean      no_groups    = TRUE;
+
   if (image)
     {
       drawable = gimp_image_get_active_drawable (image);
+      drawables = gimp_image_get_selected_drawables (image);
+
+      for (iter = drawables; iter; iter = iter->next)
+        {
+          if (gimp_item_is_content_locked (iter->data))
+            all_writable = FALSE;
+
+          if (gimp_viewable_get_children (iter->data))
+            no_groups = FALSE;
+
+          if (! all_writable && ! no_groups)
+            break;
+        }
 
       if (drawable)
         {
@@ -190,10 +208,12 @@ select_actions_update (GimpActionGroup *group,
   SET_SENSITIVE ("select-flood",   image && sel);
 
   SET_SENSITIVE ("select-save",               image && !fs);
-  SET_SENSITIVE ("select-fill",               writable && !children && sel);
-  SET_SENSITIVE ("select-fill-last-values",   writable && !children && sel);
+  SET_SENSITIVE ("select-fill",               drawables && all_writable && no_groups && sel);
+  SET_SENSITIVE ("select-fill-last-values",   drawables && all_writable && no_groups && sel);
   SET_SENSITIVE ("select-stroke",             writable && !children && sel);
   SET_SENSITIVE ("select-stroke-last-values", writable && !children && sel);
 
 #undef SET_SENSITIVE
+
+  g_list_free (drawables);
 }
diff --git a/app/core/gimpitem.c b/app/core/gimpitem.c
index 724bde7342..5177c3741e 100644
--- a/app/core/gimpitem.c
+++ b/app/core/gimpitem.c
@@ -1775,25 +1775,30 @@ gimp_item_get_clip (GimpItem            *item,
 
 gboolean
 gimp_item_fill (GimpItem        *item,
-                GimpDrawable    *drawable,
+                GList           *drawables,
                 GimpFillOptions *fill_options,
                 gboolean         push_undo,
                 GimpProgress    *progress,
                 GError         **error)
 {
   GimpItemClass *item_class;
+  GList         *iter;
   gboolean       retval = FALSE;
 
   g_return_val_if_fail (GIMP_IS_ITEM (item), FALSE);
   g_return_val_if_fail (gimp_item_is_attached (item), FALSE);
-  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), FALSE);
-  g_return_val_if_fail (gimp_item_is_attached (GIMP_ITEM (drawable)), FALSE);
   g_return_val_if_fail (GIMP_IS_FILL_OPTIONS (fill_options), FALSE);
   g_return_val_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress), FALSE);
   g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
 
   item_class = GIMP_ITEM_GET_CLASS (item);
 
+  for (iter = drawables; iter; iter = iter->next)
+    {
+      g_return_val_if_fail (GIMP_IS_DRAWABLE (iter->data), FALSE);
+      g_return_val_if_fail (gimp_item_is_attached (GIMP_ITEM (iter->data)), FALSE);
+    }
+
   if (item_class->fill)
     {
       GimpImage *image = gimp_item_get_image (item);
@@ -1802,8 +1807,13 @@ gimp_item_fill (GimpItem        *item,
         gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_PAINT,
                                      item_class->fill_desc);
 
-      retval = item_class->fill (item, drawable, fill_options, push_undo,
-                                 progress, error);
+      for (iter = drawables; iter; iter = iter->next)
+        {
+          retval = item_class->fill (item, iter->data, fill_options,
+                                     push_undo, progress, error);
+          if (! retval)
+            break;
+        }
 
       if (push_undo)
         gimp_image_undo_group_end (image);
diff --git a/app/core/gimpitem.h b/app/core/gimpitem.h
index 4b7a9de24c..f72beb8cfe 100644
--- a/app/core/gimpitem.h
+++ b/app/core/gimpitem.h
@@ -296,7 +296,7 @@ GimpTransformResize   gimp_item_get_clip     (GimpItem           *item,
                                               GimpTransformResize clip_result);
 
 gboolean        gimp_item_fill               (GimpItem           *item,
-                                              GimpDrawable       *drawable,
+                                              GList              *drawables,
                                               GimpFillOptions    *fill_options,
                                               gboolean            push_undo,
                                               GimpProgress       *progress,
diff --git a/app/dialogs/fill-dialog.c b/app/dialogs/fill-dialog.c
index 2a0d5551c0..a94bf0dd5e 100644
--- a/app/dialogs/fill-dialog.c
+++ b/app/dialogs/fill-dialog.c
@@ -47,7 +47,7 @@ typedef struct _FillDialog FillDialog;
 struct _FillDialog
 {
   GimpItem         *item;
-  GimpDrawable     *drawable;
+  GList            *drawables;
   GimpContext      *context;
   GimpFillOptions  *options;
   GimpFillCallback  callback;
@@ -67,7 +67,7 @@ static void  fill_dialog_response (GtkWidget  *dialog,
 
 GtkWidget *
 fill_dialog_new (GimpItem         *item,
-                 GimpDrawable     *drawable,
+                 GList            *drawables,
                  GimpContext      *context,
                  const gchar      *title,
                  const gchar      *icon_name,
@@ -83,7 +83,7 @@ fill_dialog_new (GimpItem         *item,
   GtkWidget  *fill_editor;
 
   g_return_val_if_fail (GIMP_IS_ITEM (item), NULL);
-  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL);
+  g_return_val_if_fail (drawables, NULL);
   g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
   g_return_val_if_fail (GIMP_IS_FILL_OPTIONS (options), NULL);
   g_return_val_if_fail (icon_name != NULL, NULL);
@@ -94,7 +94,7 @@ fill_dialog_new (GimpItem         *item,
   private = g_slice_new0 (FillDialog);
 
   private->item      = item;
-  private->drawable  = drawable;
+  private->drawables = g_list_copy (drawables);
   private->context   = context;
   private->options   = gimp_fill_options_new (context->gimp, context, TRUE);
   private->callback  = callback;
@@ -152,6 +152,7 @@ static void
 fill_dialog_free (FillDialog *private)
 {
   g_object_unref (private->options);
+  g_list_free (private->drawables);
 
   g_slice_free (FillDialog, private);
 }
@@ -170,7 +171,7 @@ fill_dialog_response (GtkWidget  *dialog,
     case GTK_RESPONSE_OK:
       private->callback (dialog,
                          private->item,
-                         private->drawable,
+                         private->drawables,
                          private->context,
                          private->options,
                          private->user_data);
diff --git a/app/dialogs/fill-dialog.h b/app/dialogs/fill-dialog.h
index 35570cb698..671fe90af3 100644
--- a/app/dialogs/fill-dialog.h
+++ b/app/dialogs/fill-dialog.h
@@ -24,14 +24,14 @@
 
 typedef void (* GimpFillCallback) (GtkWidget       *dialog,
                                    GimpItem        *item,
-                                   GimpDrawable    *drawable,
+                                   GList           *drawables,
                                    GimpContext     *context,
                                    GimpFillOptions *options,
                                    gpointer         user_data);
 
 
 GtkWidget * fill_dialog_new (GimpItem         *item,
-                             GimpDrawable     *drawable,
+                             GList            *drawables,
                              GimpContext      *context,
                              const gchar      *title,
                              const gchar      *icon_name,
diff --git a/app/tools/gimpvectortool.c b/app/tools/gimpvectortool.c
index 7e40e22291..97b4c4a41d 100644
--- a/app/tools/gimpvectortool.c
+++ b/app/tools/gimpvectortool.c
@@ -133,7 +133,7 @@ static void     gimp_vector_tool_fill_vectors    (GimpVectorTool        *vector_
                                                   GtkWidget             *button);
 static void     gimp_vector_tool_fill_callback   (GtkWidget             *dialog,
                                                   GimpItem              *item,
-                                                  GimpDrawable          *drawable,
+                                                  GList                 *drawables,
                                                   GimpContext           *context,
                                                   GimpFillOptions       *options,
                                                   gpointer               data);
@@ -718,7 +718,7 @@ gimp_vector_tool_fill_vectors (GimpVectorTool *vector_tool,
 {
   GimpDialogConfig *config;
   GimpImage        *image;
-  GimpDrawable     *drawable;
+  GList            *drawables;
   GtkWidget        *dialog;
 
   if (! vector_tool->vectors)
@@ -728,18 +728,18 @@ gimp_vector_tool_fill_vectors (GimpVectorTool *vector_tool,
 
   config = GIMP_DIALOG_CONFIG (image->gimp->config);
 
-  drawable = gimp_image_get_active_drawable (image);
+  drawables = gimp_image_get_selected_drawables (image);
 
-  if (! drawable)
+  if (! drawables)
     {
       gimp_tool_message (GIMP_TOOL (vector_tool),
                          GIMP_TOOL (vector_tool)->display,
-                         _("There is no active layer or channel to fill"));
+                         _("There are no selected layers or channels to fill."));
       return;
     }
 
   dialog = fill_dialog_new (GIMP_ITEM (vector_tool->vectors),
-                            drawable,
+                            drawables,
                             GIMP_CONTEXT (GIMP_TOOL_GET_OPTIONS (vector_tool)),
                             _("Fill Path"),
                             GIMP_ICON_TOOL_BUCKET_FILL,
@@ -749,12 +749,14 @@ gimp_vector_tool_fill_vectors (GimpVectorTool *vector_tool,
                             gimp_vector_tool_fill_callback,
                             vector_tool);
   gtk_widget_show (dialog);
+
+  g_list_free (drawables);
 }
 
 static void
 gimp_vector_tool_fill_callback (GtkWidget       *dialog,
                                 GimpItem        *item,
-                                GimpDrawable    *drawable,
+                                GList           *drawables,
                                 GimpContext     *context,
                                 GimpFillOptions *options,
                                 gpointer         data)
@@ -766,7 +768,7 @@ gimp_vector_tool_fill_callback (GtkWidget       *dialog,
   gimp_config_sync (G_OBJECT (options),
                     G_OBJECT (config->fill_options), 0);
 
-  if (! gimp_item_fill (item, drawable, options,
+  if (! gimp_item_fill (item, drawables, options,
                         TRUE, NULL, &error))
     {
       gimp_message_literal (context->gimp,


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