[gimp] app: add menu items and a dialog for GimpItem::fill()
- From: Michael Natterer <mitch src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp] app: add menu items and a dialog for GimpItem::fill()
- Date: Tue, 15 Mar 2016 20:09:08 +0000 (UTC)
commit 49ffbbbbc0fa7e958f3ade393d177f96b95938a4
Author: Michael Natterer <mitch gimp org>
Date: Tue Mar 15 20:52:22 2016 +0100
app: add menu items and a dialog for GimpItem::fill()
which are essentially a copy of the stroking GUI. We now can fill the
exact shape outlined by stroking selections and paths. Suggestions for
the menu item labels are welcome.
app/actions/select-actions.c | 14 +++
app/actions/select-commands.c | 77 +++++++++++++++
app/actions/select-commands.h | 5 +
app/actions/vectors-actions.c | 18 ++++
app/actions/vectors-commands.c | 79 ++++++++++++++++-
app/actions/vectors-commands.h | 5 +
app/dialogs/Makefile.am | 2 +
app/dialogs/fill-dialog.c | 200 ++++++++++++++++++++++++++++++++++++++++
app/dialogs/fill-dialog.h | 33 +++++++
app/widgets/gimphelp-ids.h | 2 +
menus/image-menu.xml.in | 2 +
po/POTFILES.in | 1 +
12 files changed, 437 insertions(+), 1 deletions(-)
---
diff --git a/app/actions/select-actions.c b/app/actions/select-actions.c
index 02af2af..ea30175 100644
--- a/app/actions/select-actions.c
+++ b/app/actions/select-actions.c
@@ -113,6 +113,18 @@ static const GimpActionEntry select_actions[] =
G_CALLBACK (select_save_cmd_callback),
GIMP_HELP_SELECTION_TO_CHANNEL },
+ { "select-fill", GIMP_STOCK_TOOL_BUCKET_FILL,
+ NC_("select-action", "_Fill Selection Outline..."), NULL,
+ NC_("select-action", "Fill the selection outline"),
+ G_CALLBACK (select_fill_cmd_callback),
+ GIMP_HELP_SELECTION_FILL },
+
+ { "select-fill-last-values", GIMP_STOCK_TOOL_BUCKET_FILL,
+ NC_("select-action", "_Fill Selection Outline"), NULL,
+ NC_("select-action", "Fill the selection outline with last used values"),
+ G_CALLBACK (select_fill_last_vals_cmd_callback),
+ GIMP_HELP_SELECTION_FILL },
+
{ "select-stroke", GIMP_STOCK_SELECTION_STROKE,
NC_("select-action", "_Stroke Selection..."), NULL,
NC_("select-action", "Paint along the selection outline"),
@@ -178,6 +190,8 @@ select_actions_update (GimpActionGroup *group,
SET_SENSITIVE ("select-flood", drawable && sel);
SET_SENSITIVE ("select-save", drawable && !fs);
+ SET_SENSITIVE ("select-fill", writable && !children && sel);
+ SET_SENSITIVE ("select-fill-last-values", writable && !children && sel);
SET_SENSITIVE ("select-stroke", writable && !children && sel);
SET_SENSITIVE ("select-stroke-last-values", writable && !children && sel);
diff --git a/app/actions/select-commands.c b/app/actions/select-commands.c
index 1f8398c..cc35eb7 100644
--- a/app/actions/select-commands.c
+++ b/app/actions/select-commands.c
@@ -39,6 +39,7 @@
#include "display/gimpdisplay.h"
#include "display/gimpdisplayshell.h"
+#include "dialogs/fill-dialog.h"
#include "dialogs/stroke-dialog.h"
#include "actions.h"
@@ -339,6 +340,82 @@ select_save_cmd_callback (GtkAction *action,
}
void
+select_fill_cmd_callback (GtkAction *action,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpDrawable *drawable;
+ GtkWidget *widget;
+ GtkWidget *dialog;
+ return_if_no_image (image, data);
+ return_if_no_widget (widget, data);
+
+ drawable = gimp_image_get_active_drawable (image);
+
+ if (! drawable)
+ {
+ gimp_message_literal (image->gimp,
+ G_OBJECT (widget), GIMP_MESSAGE_WARNING,
+ _("There is no active layer or channel to fill."));
+ return;
+ }
+
+ dialog = fill_dialog_new (GIMP_ITEM (gimp_image_get_mask (image)),
+ action_data_get_context (data),
+ _("Fill Selection Outline"),
+ GIMP_STOCK_TOOL_BUCKET_FILL,
+ GIMP_HELP_SELECTION_FILL,
+ widget);
+ gtk_widget_show (dialog);
+}
+
+void
+select_fill_last_vals_cmd_callback (GtkAction *action,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpDrawable *drawable;
+ GtkWidget *widget;
+ GimpFillOptions *options;
+ GError *error = NULL;
+ return_if_no_image (image, data);
+ return_if_no_widget (widget, data);
+
+ drawable = gimp_image_get_active_drawable (image);
+
+ if (! drawable)
+ {
+ gimp_message_literal (image->gimp,
+ G_OBJECT (widget), GIMP_MESSAGE_WARNING,
+ _("There is no active layer or channel to fill."));
+ return;
+ }
+
+ options = g_object_get_data (G_OBJECT (image->gimp), "saved-fill-options");
+
+ if (options)
+ g_object_ref (options);
+ else
+ options = gimp_fill_options_new (image->gimp,
+ action_data_get_context (data), TRUE);
+
+ if (! gimp_item_fill (GIMP_ITEM (gimp_image_get_mask (image)),
+ drawable, options, TRUE, NULL, &error))
+ {
+ gimp_message_literal (image->gimp,
+ G_OBJECT (widget), GIMP_MESSAGE_WARNING,
+ error->message);
+ g_clear_error (&error);
+ }
+ else
+ {
+ gimp_image_flush (image);
+ }
+
+ g_object_unref (options);
+}
+
+void
select_stroke_cmd_callback (GtkAction *action,
gpointer data)
{
diff --git a/app/actions/select-commands.h b/app/actions/select-commands.h
index 3691491..eb74759 100644
--- a/app/actions/select-commands.h
+++ b/app/actions/select-commands.h
@@ -41,6 +41,11 @@ void select_flood_cmd_callback (GtkAction *action,
gpointer data);
void select_save_cmd_callback (GtkAction *action,
gpointer data);
+
+void select_fill_cmd_callback (GtkAction *action,
+ gpointer data);
+void select_fill_last_vals_cmd_callback (GtkAction *action,
+ gpointer data);
void select_stroke_cmd_callback (GtkAction *action,
gpointer data);
void select_stroke_last_vals_cmd_callback (GtkAction *action,
diff --git a/app/actions/vectors-actions.c b/app/actions/vectors-actions.c
index 1c22289..537f1d6 100644
--- a/app/actions/vectors-actions.c
+++ b/app/actions/vectors-actions.c
@@ -108,6 +108,18 @@ static const GimpActionEntry vectors_actions[] =
G_CALLBACK (vectors_lower_to_bottom_cmd_callback),
GIMP_HELP_PATH_LOWER_TO_BOTTOM },
+ { "vectors-fill", GIMP_STOCK_TOOL_BUCKET_FILL,
+ NC_("vectors-action", "Fill Path..."), NULL,
+ NC_("vectors-action", "Fill the path"),
+ G_CALLBACK (vectors_fill_cmd_callback),
+ GIMP_HELP_PATH_FILL },
+
+ { "vectors-fill-last-values", GIMP_STOCK_TOOL_BUCKET_FILL,
+ NC_("vectors-action", "Fill Path"), NULL,
+ NC_("vectors-action", "Fill the path with last values"),
+ G_CALLBACK (vectors_fill_last_vals_cmd_callback),
+ GIMP_HELP_PATH_FILL },
+
{ "vectors-stroke", GIMP_STOCK_PATH_STROKE,
NC_("vectors-action", "Stro_ke Path..."), NULL,
NC_("vectors-action", "Paint along the path"),
@@ -345,6 +357,12 @@ vectors_actions_update (GimpActionGroup *group,
SET_SENSITIVE ("vectors-selection-to-vectors", image && !mask_empty);
SET_SENSITIVE ("vectors-selection-to-vectors-short", image && !mask_empty);
SET_SENSITIVE ("vectors-selection-to-vectors-advanced", image && !mask_empty);
+ SET_SENSITIVE ("vectors-fill", vectors &&
+ dr_writable &&
+ !dr_children);
+ SET_SENSITIVE ("vectors-fill-last-values", vectors &&
+ dr_writable &&
+ !dr_children);
SET_SENSITIVE ("vectors-stroke", vectors &&
dr_writable &&
!dr_children);
diff --git a/app/actions/vectors-commands.c b/app/actions/vectors-commands.c
index 5d4292f..7e010a3 100644
--- a/app/actions/vectors-commands.c
+++ b/app/actions/vectors-commands.c
@@ -56,6 +56,7 @@
#include "tools/gimpvectortool.h"
#include "tools/tool_manager.h"
+#include "dialogs/fill-dialog.h"
#include "dialogs/stroke-dialog.h"
#include "dialogs/vectors-export-dialog.h"
#include "dialogs/vectors-import-dialog.h"
@@ -369,6 +370,83 @@ vectors_selection_to_vectors_cmd_callback (GtkAction *action,
}
void
+vectors_fill_cmd_callback (GtkAction *action,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpVectors *vectors;
+ GimpDrawable *drawable;
+ GtkWidget *widget;
+ GtkWidget *dialog;
+ return_if_no_vectors (image, vectors, data);
+ return_if_no_widget (widget, data);
+
+ drawable = gimp_image_get_active_drawable (image);
+
+ if (! drawable)
+ {
+ gimp_message_literal (image->gimp,
+ G_OBJECT (widget), GIMP_MESSAGE_WARNING,
+ _("There is no active layer or channel to fill."));
+ return;
+ }
+
+ dialog = fill_dialog_new (GIMP_ITEM (vectors),
+ action_data_get_context (data),
+ _("Fill Path"),
+ GIMP_STOCK_TOOL_BUCKET_FILL,
+ GIMP_HELP_PATH_FILL,
+ widget);
+ gtk_widget_show (dialog);
+}
+
+void
+vectors_fill_last_vals_cmd_callback (GtkAction *action,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpVectors *vectors;
+ GimpDrawable *drawable;
+ GtkWidget *widget;
+ GimpFillOptions *options;
+ GError *error = NULL;
+ return_if_no_vectors (image, vectors, data);
+ return_if_no_widget (widget, data);
+
+ drawable = gimp_image_get_active_drawable (image);
+
+ if (! drawable)
+ {
+ gimp_message_literal (image->gimp,
+ G_OBJECT (widget), GIMP_MESSAGE_WARNING,
+ _("There is no active layer or channel to fill."));
+ return;
+ }
+
+ options = g_object_get_data (G_OBJECT (image->gimp), "saved-fill-options");
+
+ if (options)
+ g_object_ref (options);
+ else
+ options = gimp_fill_options_new (image->gimp,
+ action_data_get_context (data), TRUE);
+
+ if (! gimp_item_fill (GIMP_ITEM (vectors),
+ drawable, options, TRUE, NULL, &error))
+ {
+ gimp_message_literal (image->gimp, G_OBJECT (widget),
+ GIMP_MESSAGE_WARNING, error->message);
+ g_clear_error (&error);
+ }
+ else
+ {
+ gimp_image_flush (image);
+ }
+
+ g_object_unref (options);
+}
+
+void
vectors_stroke_cmd_callback (GtkAction *action,
gpointer data)
{
@@ -424,7 +502,6 @@ vectors_stroke_last_vals_cmd_callback (GtkAction *action,
return;
}
-
options = g_object_get_data (G_OBJECT (image->gimp), "saved-stroke-options");
if (options)
diff --git a/app/actions/vectors-commands.h b/app/actions/vectors-commands.h
index af485c3..8b92989 100644
--- a/app/actions/vectors-commands.h
+++ b/app/actions/vectors-commands.h
@@ -49,6 +49,11 @@ void vectors_to_selection_cmd_callback (GtkAction *action,
void vectors_selection_to_vectors_cmd_callback (GtkAction *action,
gint value,
gpointer data);
+
+void vectors_fill_cmd_callback (GtkAction *action,
+ gpointer data);
+void vectors_fill_last_vals_cmd_callback (GtkAction *action,
+ gpointer data);
void vectors_stroke_cmd_callback (GtkAction *action,
gpointer data);
void vectors_stroke_last_vals_cmd_callback (GtkAction *action,
diff --git a/app/dialogs/Makefile.am b/app/dialogs/Makefile.am
index 411e495..8374b9b 100644
--- a/app/dialogs/Makefile.am
+++ b/app/dialogs/Makefile.am
@@ -44,6 +44,8 @@ libappdialogs_a_sources = \
file-open-location-dialog.h \
file-save-dialog.c \
file-save-dialog.h \
+ fill-dialog.c \
+ fill-dialog.h \
grid-dialog.h \
grid-dialog.c \
image-merge-layers-dialog.c \
diff --git a/app/dialogs/fill-dialog.c b/app/dialogs/fill-dialog.c
new file mode 100644
index 0000000..1eb0f02
--- /dev/null
+++ b/app/dialogs/fill-dialog.c
@@ -0,0 +1,200 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * fill-dialog.c
+ * Copyright (C) 2016 Michael Natterer <mitch gimp org>
+ *
+ * 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/>.
+ */
+
+#include "config.h"
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpconfig/gimpconfig.h"
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "dialogs-types.h"
+
+#include "core/gimp.h"
+#include "core/gimpdrawable.h"
+#include "core/gimpimage.h"
+#include "core/gimpfilloptions.h"
+
+#include "widgets/gimpfilleditor.h"
+#include "widgets/gimpviewabledialog.h"
+
+#include "fill-dialog.h"
+
+#include "gimp-intl.h"
+
+
+#define RESPONSE_RESET 1
+
+
+/* local functions */
+
+static void fill_dialog_response (GtkWidget *widget,
+ gint response_id,
+ GtkWidget *dialog);
+
+
+/* public function */
+
+GtkWidget *
+fill_dialog_new (GimpItem *item,
+ GimpContext *context,
+ const gchar *title,
+ const gchar *icon_name,
+ const gchar *help_id,
+ GtkWidget *parent)
+{
+ GimpFillOptions *options;
+ GimpFillOptions *saved_options;
+ GtkWidget *dialog;
+ GtkWidget *main_vbox;
+ GtkWidget *fill_editor;
+
+ g_return_val_if_fail (GIMP_IS_ITEM (item), NULL);
+ g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
+ g_return_val_if_fail (icon_name != NULL, NULL);
+ g_return_val_if_fail (help_id != NULL, NULL);
+ g_return_val_if_fail (parent == NULL || GTK_IS_WIDGET (parent), NULL);
+
+ options = gimp_fill_options_new (context->gimp, context, TRUE);
+
+ saved_options = g_object_get_data (G_OBJECT (context->gimp),
+ "saved-fill-options");
+
+ if (saved_options)
+ gimp_config_sync (G_OBJECT (saved_options), G_OBJECT (options), 0);
+
+ dialog = gimp_viewable_dialog_new (GIMP_VIEWABLE (item), context,
+ title, "gimp-fill-options",
+ icon_name,
+ _("Choose Fill Style"),
+ parent,
+ gimp_standard_help_func,
+ help_id,
+
+ GIMP_STOCK_RESET, RESPONSE_RESET,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ _("_Fill"), GTK_RESPONSE_OK,
+
+ NULL);
+
+ gtk_dialog_set_alternative_button_order (GTK_DIALOG (dialog),
+ RESPONSE_RESET,
+ GTK_RESPONSE_OK,
+ GTK_RESPONSE_CANCEL,
+ -1);
+
+ gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
+
+ g_signal_connect (dialog, "response",
+ G_CALLBACK (fill_dialog_response),
+ dialog);
+
+ g_object_set_data (G_OBJECT (dialog), "gimp-item", item);
+ g_object_set_data_full (G_OBJECT (dialog), "gimp-fill-options", options,
+ (GDestroyNotify) g_object_unref);
+
+ main_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
+ gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 12);
+ gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))),
+ main_vbox, TRUE, TRUE, 0);
+ gtk_widget_show (main_vbox);
+
+ fill_editor = gimp_fill_editor_new (options, FALSE);
+ gtk_box_pack_start (GTK_BOX (main_vbox), fill_editor, FALSE, FALSE, 0);
+ gtk_widget_show (fill_editor);
+
+ return dialog;
+}
+
+
+/* private functions */
+
+static void
+fill_dialog_response (GtkWidget *widget,
+ gint response_id,
+ GtkWidget *dialog)
+{
+ GimpFillOptions *options;
+ GimpItem *item;
+ GimpImage *image;
+ GimpContext *context;
+
+ item = g_object_get_data (G_OBJECT (dialog), "gimp-item");
+ options = g_object_get_data (G_OBJECT (dialog), "gimp-fill-options");
+
+ image = gimp_item_get_image (item);
+ context = GIMP_VIEWABLE_DIALOG (dialog)->context;
+
+ switch (response_id)
+ {
+ case RESPONSE_RESET:
+ gimp_config_reset (GIMP_CONFIG (options));
+ break;
+
+ case GTK_RESPONSE_OK:
+ {
+ GimpDrawable *drawable = gimp_image_get_active_drawable (image);
+ GimpFillOptions *saved_options;
+ GError *error = NULL;
+
+ if (! drawable)
+ {
+ gimp_message_literal (context->gimp, G_OBJECT (widget),
+ GIMP_MESSAGE_WARNING,
+ _("There is no active layer or channel "
+ "to fill."));
+ return;
+ }
+
+ saved_options = g_object_get_data (G_OBJECT (context->gimp),
+ "saved-fill-options");
+
+ if (saved_options)
+ g_object_ref (saved_options);
+ else
+ saved_options = gimp_fill_options_new (context->gimp, context, TRUE);
+
+ gimp_config_sync (G_OBJECT (options), G_OBJECT (saved_options), 0);
+
+ g_object_set_data_full (G_OBJECT (context->gimp), "saved-fill-options",
+ saved_options,
+ (GDestroyNotify) g_object_unref);
+
+ if (! gimp_item_fill (item, drawable, options, TRUE, NULL, &error))
+ {
+ gimp_message_literal (context->gimp,
+ G_OBJECT (widget),
+ GIMP_MESSAGE_WARNING,
+ error ? error->message : "NULL");
+
+ g_clear_error (&error);
+ return;
+ }
+
+ gimp_image_flush (image);
+ }
+ /* fallthrough */
+
+ default:
+ gtk_widget_destroy (dialog);
+ break;
+ }
+}
diff --git a/app/dialogs/fill-dialog.h b/app/dialogs/fill-dialog.h
new file mode 100644
index 0000000..da3e900
--- /dev/null
+++ b/app/dialogs/fill-dialog.h
@@ -0,0 +1,33 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * fill-dialog.h
+ * Copyright (C) 2016 Michael Natterer <mitch gimp org>
+ *
+ * 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/>.
+ */
+
+#ifndef __FILL_DIALOG_H__
+#define __FILL_DIALOG_H__
+
+
+GtkWidget * fill_dialog_new (GimpItem *item,
+ GimpContext *context,
+ const gchar *title,
+ const gchar *icon_name,
+ const gchar *help_id,
+ GtkWidget *parent);
+
+
+#endif /* __FILL_DIALOG_H__ */
diff --git a/app/widgets/gimphelp-ids.h b/app/widgets/gimphelp-ids.h
index dfc1e3a..bae40f2 100644
--- a/app/widgets/gimphelp-ids.h
+++ b/app/widgets/gimphelp-ids.h
@@ -75,6 +75,7 @@
#define GIMP_HELP_SELECTION_GROW "gimp-selection-grow"
#define GIMP_HELP_SELECTION_BORDER "gimp-selection-border"
#define GIMP_HELP_SELECTION_FLOOD "gimp-selection-flood"
+#define GIMP_HELP_SELECTION_FILL "gimp-selection-fill"
#define GIMP_HELP_SELECTION_STROKE "gimp-selection-stroke"
#define GIMP_HELP_SELECTION_TO_CHANNEL "gimp-selection-to-channel"
#define GIMP_HELP_SELECTION_TO_PATH "gimp-selection-to-path"
@@ -258,6 +259,7 @@
#define GIMP_HELP_PATH_SELECTION_ADD "gimp-path-selection-add"
#define GIMP_HELP_PATH_SELECTION_SUBTRACT "gimp-path-selection-subtract"
#define GIMP_HELP_PATH_SELECTION_INTERSECT "gimp-path-selection-intersect"
+#define GIMP_HELP_PATH_FILL "gimp-path-fill"
#define GIMP_HELP_PATH_STROKE "gimp-path-stroke"
#define GIMP_HELP_PATH_COPY "gimp-path-copy"
#define GIMP_HELP_PATH_PASTE "gimp-path-paste"
diff --git a/menus/image-menu.xml.in b/menus/image-menu.xml.in
index 037324c..1ea7b45 100644
--- a/menus/image-menu.xml.in
+++ b/menus/image-menu.xml.in
@@ -213,6 +213,8 @@
<menuitem action="edit-fill-fg" />
<menuitem action="edit-fill-bg" />
<menuitem action="edit-fill-pattern" />
+ <menuitem action="select-fill" />
+ <menuitem action="vectors-fill" />
</placeholder>
<placeholder name="Stroke">
<menuitem action="select-stroke" />
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 130b0dc..d8bdd03 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -200,6 +200,7 @@ app/dialogs/fade-dialog.c
app/dialogs/file-open-dialog.c
app/dialogs/file-open-location-dialog.c
app/dialogs/file-save-dialog.c
+app/dialogs/fill-dialog.c
app/dialogs/grid-dialog.c
app/dialogs/image-merge-layers-dialog.c
app/dialogs/image-new-dialog.c
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]