summaryrefslogtreecommitdiffstats
path: root/app/actions
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 18:30:19 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 18:30:19 +0000
commit5c1676dfe6d2f3c837a5e074117b45613fd29a72 (patch)
treecbffb45144febf451e54061db2b21395faf94bfe /app/actions
parentInitial commit. (diff)
downloadgimp-upstream/2.10.34.tar.xz
gimp-upstream/2.10.34.zip
Adding upstream version 2.10.34.upstream/2.10.34upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'app/actions')
-rw-r--r--app/actions/Makefile.am202
-rw-r--r--app/actions/Makefile.in1489
-rw-r--r--app/actions/actions-types.h54
-rw-r--r--app/actions/actions.c737
-rw-r--r--app/actions/actions.h120
-rw-r--r--app/actions/brush-editor-actions.c87
-rw-r--r--app/actions/brush-editor-actions.h27
-rw-r--r--app/actions/brushes-actions.c149
-rw-r--r--app/actions/brushes-actions.h27
-rw-r--r--app/actions/buffers-actions.c136
-rw-r--r--app/actions/buffers-actions.h27
-rw-r--r--app/actions/buffers-commands.c138
-rw-r--r--app/actions/buffers-commands.h33
-rw-r--r--app/actions/channels-actions.c348
-rw-r--r--app/actions/channels-actions.h27
-rw-r--r--app/actions/channels-commands.c567
-rw-r--r--app/actions/channels-commands.h77
-rw-r--r--app/actions/colormap-actions.c173
-rw-r--r--app/actions/colormap-actions.h27
-rw-r--r--app/actions/colormap-commands.c96
-rw-r--r--app/actions/colormap-commands.h33
-rw-r--r--app/actions/context-actions.c1294
-rw-r--r--app/actions/context-actions.h27
-rw-r--r--app/actions/context-commands.c975
-rw-r--r--app/actions/context-commands.h140
-rw-r--r--app/actions/cursor-info-actions.c81
-rw-r--r--app/actions/cursor-info-actions.h27
-rw-r--r--app/actions/cursor-info-commands.c41
-rw-r--r--app/actions/cursor-info-commands.h27
-rw-r--r--app/actions/dashboard-actions.c230
-rw-r--r--app/actions/dashboard-actions.h27
-rw-r--r--app/actions/dashboard-commands.c406
-rw-r--r--app/actions/dashboard-commands.h48
-rw-r--r--app/actions/data-commands.c304
-rw-r--r--app/actions/data-commands.h48
-rw-r--r--app/actions/data-editor-commands.c43
-rw-r--r--app/actions/data-editor-commands.h27
-rw-r--r--app/actions/debug-actions.c107
-rw-r--r--app/actions/debug-actions.h27
-rw-r--r--app/actions/debug-commands.c430
-rw-r--r--app/actions/debug-commands.h46
-rw-r--r--app/actions/dialogs-actions.c368
-rw-r--r--app/actions/dialogs-actions.h38
-rw-r--r--app/actions/dialogs-commands.c78
-rw-r--r--app/actions/dialogs-commands.h30
-rw-r--r--app/actions/dock-actions.c141
-rw-r--r--app/actions/dock-actions.h27
-rw-r--r--app/actions/dock-commands.c85
-rw-r--r--app/actions/dock-commands.h30
-rw-r--r--app/actions/dockable-actions.c375
-rw-r--r--app/actions/dockable-actions.h27
-rw-r--r--app/actions/dockable-commands.c298
-rw-r--r--app/actions/dockable-commands.h49
-rw-r--r--app/actions/documents-actions.c143
-rw-r--r--app/actions/documents-actions.h27
-rw-r--r--app/actions/documents-commands.c410
-rw-r--r--app/actions/documents-commands.h54
-rw-r--r--app/actions/drawable-actions.c231
-rw-r--r--app/actions/drawable-actions.h27
-rw-r--r--app/actions/drawable-commands.c304
-rw-r--r--app/actions/drawable-commands.h50
-rw-r--r--app/actions/dynamics-actions.c137
-rw-r--r--app/actions/dynamics-actions.h27
-rw-r--r--app/actions/dynamics-editor-actions.c89
-rw-r--r--app/actions/dynamics-editor-actions.h27
-rw-r--r--app/actions/edit-actions.c417
-rw-r--r--app/actions/edit-actions.h27
-rw-r--r--app/actions/edit-commands.c721
-rw-r--r--app/actions/edit-commands.h76
-rw-r--r--app/actions/error-console-actions.c152
-rw-r--r--app/actions/error-console-actions.h27
-rw-r--r--app/actions/error-console-commands.c201
-rw-r--r--app/actions/error-console-commands.h43
-rw-r--r--app/actions/file-actions.c452
-rw-r--r--app/actions/file-actions.h27
-rw-r--r--app/actions/file-commands.c837
-rw-r--r--app/actions/file-commands.h63
-rw-r--r--app/actions/filters-actions.c1229
-rw-r--r--app/actions/filters-actions.h27
-rw-r--r--app/actions/filters-commands.c265
-rw-r--r--app/actions/filters-commands.h37
-rw-r--r--app/actions/fonts-actions.c73
-rw-r--r--app/actions/fonts-actions.h27
-rw-r--r--app/actions/gimpgeglprocedure.c476
-rw-r--r--app/actions/gimpgeglprocedure.h70
-rw-r--r--app/actions/gradient-editor-actions.c906
-rw-r--r--app/actions/gradient-editor-actions.h27
-rw-r--r--app/actions/gradient-editor-commands.c738
-rw-r--r--app/actions/gradient-editor-commands.h99
-rw-r--r--app/actions/gradients-actions.c150
-rw-r--r--app/actions/gradients-actions.h27
-rw-r--r--app/actions/gradients-commands.c151
-rw-r--r--app/actions/gradients-commands.h27
-rw-r--r--app/actions/help-actions.c66
-rw-r--r--app/actions/help-actions.h27
-rw-r--r--app/actions/help-commands.c57
-rw-r--r--app/actions/help-commands.h30
-rw-r--r--app/actions/image-actions.c497
-rw-r--r--app/actions/image-actions.h27
-rw-r--r--app/actions/image-commands.c1581
-rw-r--r--app/actions/image-commands.h101
-rw-r--r--app/actions/images-actions.c98
-rw-r--r--app/actions/images-actions.h27
-rw-r--r--app/actions/images-commands.c117
-rw-r--r--app/actions/images-commands.h33
-rw-r--r--app/actions/items-actions.c142
-rw-r--r--app/actions/items-actions.h29
-rw-r--r--app/actions/items-commands.c419
-rw-r--r--app/actions/items-commands.h72
-rw-r--r--app/actions/layers-actions.c1027
-rw-r--r--app/actions/layers-actions.h27
-rw-r--r--app/actions/layers-commands.c1749
-rw-r--r--app/actions/layers-commands.h173
-rw-r--r--app/actions/mypaint-brushes-actions.c142
-rw-r--r--app/actions/mypaint-brushes-actions.h27
-rw-r--r--app/actions/palette-editor-actions.c183
-rw-r--r--app/actions/palette-editor-actions.h27
-rw-r--r--app/actions/palette-editor-commands.c96
-rw-r--r--app/actions/palette-editor-commands.h37
-rw-r--r--app/actions/palettes-actions.c159
-rw-r--r--app/actions/palettes-actions.h27
-rw-r--r--app/actions/palettes-commands.c152
-rw-r--r--app/actions/palettes-commands.h30
-rw-r--r--app/actions/patterns-actions.c149
-rw-r--r--app/actions/patterns-actions.h27
-rw-r--r--app/actions/plug-in-actions.c517
-rw-r--r--app/actions/plug-in-actions.h27
-rw-r--r--app/actions/plug-in-commands.c221
-rw-r--r--app/actions/plug-in-commands.h31
-rw-r--r--app/actions/procedure-commands.c326
-rw-r--r--app/actions/procedure-commands.h46
-rw-r--r--app/actions/quick-mask-actions.c138
-rw-r--r--app/actions/quick-mask-actions.h27
-rw-r--r--app/actions/quick-mask-commands.c182
-rw-r--r--app/actions/quick-mask-commands.h33
-rw-r--r--app/actions/sample-points-actions.c81
-rw-r--r--app/actions/sample-points-actions.h27
-rw-r--r--app/actions/sample-points-commands.c41
-rw-r--r--app/actions/sample-points-commands.h27
-rw-r--r--app/actions/select-actions.c199
-rw-r--r--app/actions/select-actions.h27
-rw-r--r--app/actions/select-commands.c685
-rw-r--r--app/actions/select-commands.h70
-rw-r--r--app/actions/templates-actions.c105
-rw-r--r--app/actions/templates-actions.h27
-rw-r--r--app/actions/templates-commands.c345
-rw-r--r--app/actions/templates-commands.h39
-rw-r--r--app/actions/text-editor-actions.c148
-rw-r--r--app/actions/text-editor-actions.h27
-rw-r--r--app/actions/text-editor-commands.c153
-rw-r--r--app/actions/text-editor-commands.h33
-rw-r--r--app/actions/text-tool-actions.c229
-rw-r--r--app/actions/text-tool-actions.h27
-rw-r--r--app/actions/text-tool-commands.c229
-rw-r--r--app/actions/text-tool-commands.h51
-rw-r--r--app/actions/tool-options-actions.c238
-rw-r--r--app/actions/tool-options-actions.h27
-rw-r--r--app/actions/tool-options-commands.c268
-rw-r--r--app/actions/tool-options-commands.h47
-rw-r--r--app/actions/tool-preset-editor-actions.c105
-rw-r--r--app/actions/tool-preset-editor-actions.h27
-rw-r--r--app/actions/tool-preset-editor-commands.c90
-rw-r--r--app/actions/tool-preset-editor-commands.h30
-rw-r--r--app/actions/tool-presets-actions.c155
-rw-r--r--app/actions/tool-presets-actions.h27
-rw-r--r--app/actions/tool-presets-commands.c95
-rw-r--r--app/actions/tool-presets-commands.h30
-rw-r--r--app/actions/tools-actions.c800
-rw-r--r--app/actions/tools-actions.h27
-rw-r--r--app/actions/tools-commands.c820
-rw-r--r--app/actions/tools-commands.h120
-rw-r--r--app/actions/vectors-actions.c465
-rw-r--r--app/actions/vectors-actions.h27
-rw-r--r--app/actions/vectors-commands.c892
-rw-r--r--app/actions/vectors-commands.h112
-rw-r--r--app/actions/view-actions.c1211
-rw-r--r--app/actions/view-actions.h27
-rw-r--r--app/actions/view-commands.c1281
-rw-r--r--app/actions/view-commands.h181
-rw-r--r--app/actions/window-actions.c297
-rw-r--r--app/actions/window-actions.h28
-rw-r--r--app/actions/window-commands.c158
-rw-r--r--app/actions/window-commands.h33
-rw-r--r--app/actions/windows-actions.c618
-rw-r--r--app/actions/windows-actions.h28
-rw-r--r--app/actions/windows-commands.c225
-rw-r--r--app/actions/windows-commands.h53
187 files changed, 39388 insertions, 0 deletions
diff --git a/app/actions/Makefile.am b/app/actions/Makefile.am
new file mode 100644
index 0000000..fd80ce2
--- /dev/null
+++ b/app/actions/Makefile.am
@@ -0,0 +1,202 @@
+## Process this file with automake to produce Makefile.in
+
+AM_CPPFLAGS = \
+ -DG_LOG_DOMAIN=\"Gimp-Actions\" \
+ -I$(top_builddir) \
+ -I$(top_srcdir) \
+ -I$(top_builddir)/app \
+ -I$(top_srcdir)/app \
+ $(GEGL_CFLAGS) \
+ $(GTK_CFLAGS) \
+ -I$(includedir)
+
+noinst_LIBRARIES = libappactions.a
+
+libappactions_a_SOURCES = \
+ actions-types.h \
+ actions.c \
+ actions.h \
+ \
+ gimpgeglprocedure.c \
+ gimpgeglprocedure.h \
+ \
+ brush-editor-actions.c \
+ brush-editor-actions.h \
+ brushes-actions.c \
+ brushes-actions.h \
+ buffers-actions.c \
+ buffers-actions.h \
+ buffers-commands.c \
+ buffers-commands.h \
+ channels-actions.c \
+ channels-actions.h \
+ channels-commands.c \
+ channels-commands.h \
+ colormap-actions.c \
+ colormap-actions.h \
+ colormap-commands.c \
+ colormap-commands.h \
+ context-actions.c \
+ context-actions.h \
+ context-commands.c \
+ context-commands.h \
+ cursor-info-actions.c \
+ cursor-info-actions.h \
+ cursor-info-commands.c \
+ cursor-info-commands.h \
+ dashboard-actions.c \
+ dashboard-actions.h \
+ dashboard-commands.c \
+ dashboard-commands.h \
+ data-commands.c \
+ data-commands.h \
+ data-editor-commands.c \
+ data-editor-commands.h \
+ debug-actions.c \
+ debug-actions.h \
+ debug-commands.c \
+ debug-commands.h \
+ dialogs-actions.c \
+ dialogs-actions.h \
+ dialogs-commands.c \
+ dialogs-commands.h \
+ dock-actions.c \
+ dock-actions.h \
+ dock-commands.c \
+ dock-commands.h \
+ dockable-actions.c \
+ dockable-actions.h \
+ dockable-commands.c \
+ dockable-commands.h \
+ documents-actions.c \
+ documents-actions.h \
+ documents-commands.c \
+ documents-commands.h \
+ drawable-actions.c \
+ drawable-actions.h \
+ drawable-commands.c \
+ drawable-commands.h \
+ dynamics-actions.c \
+ dynamics-actions.h \
+ dynamics-editor-actions.c \
+ dynamics-editor-actions.h \
+ edit-actions.c \
+ edit-actions.h \
+ edit-commands.c \
+ edit-commands.h \
+ error-console-actions.c \
+ error-console-actions.h \
+ error-console-commands.c \
+ error-console-commands.h \
+ file-actions.c \
+ file-actions.h \
+ file-commands.c \
+ file-commands.h \
+ filters-actions.c \
+ filters-actions.h \
+ filters-commands.c \
+ filters-commands.h \
+ fonts-actions.c \
+ fonts-actions.h \
+ gradient-editor-actions.c \
+ gradient-editor-actions.h \
+ gradient-editor-commands.c \
+ gradient-editor-commands.h \
+ gradients-actions.c \
+ gradients-actions.h \
+ gradients-commands.c \
+ gradients-commands.h \
+ help-actions.c \
+ help-actions.h \
+ help-commands.c \
+ help-commands.h \
+ image-actions.c \
+ image-actions.h \
+ image-commands.c \
+ image-commands.h \
+ images-actions.c \
+ images-actions.h \
+ images-commands.c \
+ images-commands.h \
+ items-commands.c \
+ items-commands.h \
+ items-actions.c \
+ items-actions.h \
+ layers-actions.c \
+ layers-actions.h \
+ layers-commands.c \
+ layers-commands.h \
+ mypaint-brushes-actions.c \
+ mypaint-brushes-actions.h \
+ palette-editor-actions.c \
+ palette-editor-actions.h \
+ palette-editor-commands.c \
+ palette-editor-commands.h \
+ palettes-actions.c \
+ palettes-actions.h \
+ palettes-commands.c \
+ palettes-commands.h \
+ patterns-actions.c \
+ patterns-actions.h \
+ plug-in-actions.c \
+ plug-in-actions.h \
+ plug-in-commands.c \
+ plug-in-commands.h \
+ procedure-commands.c \
+ procedure-commands.h \
+ quick-mask-actions.c \
+ quick-mask-actions.h \
+ quick-mask-commands.c \
+ quick-mask-commands.h \
+ sample-points-actions.c \
+ sample-points-actions.h \
+ sample-points-commands.c \
+ sample-points-commands.h \
+ select-actions.c \
+ select-actions.h \
+ select-commands.c \
+ select-commands.h \
+ templates-actions.c \
+ templates-actions.h \
+ templates-commands.c \
+ templates-commands.h \
+ text-editor-actions.c \
+ text-editor-actions.h \
+ text-editor-commands.c \
+ text-editor-commands.h \
+ text-tool-actions.c \
+ text-tool-actions.h \
+ text-tool-commands.c \
+ text-tool-commands.h \
+ tool-options-actions.c \
+ tool-options-actions.h \
+ tool-options-commands.c \
+ tool-options-commands.h \
+ tool-presets-actions.c \
+ tool-presets-actions.h \
+ tool-presets-commands.c \
+ tool-presets-commands.h \
+ tool-preset-editor-actions.c \
+ tool-preset-editor-actions.h \
+ tool-preset-editor-commands.c \
+ tool-preset-editor-commands.h \
+ tools-actions.c \
+ tools-actions.h \
+ tools-commands.c \
+ tools-commands.h \
+ vectors-actions.c \
+ vectors-actions.h \
+ vectors-commands.c \
+ vectors-commands.h \
+ view-actions.c \
+ view-actions.h \
+ view-commands.c \
+ view-commands.h \
+ window-actions.c \
+ window-actions.h \
+ window-commands.c \
+ window-commands.h \
+ windows-actions.c \
+ windows-actions.h \
+ windows-commands.c \
+ windows-commands.h
diff --git a/app/actions/Makefile.in b/app/actions/Makefile.in
new file mode 100644
index 0000000..0ca776d
--- /dev/null
+++ b/app/actions/Makefile.in
@@ -0,0 +1,1489 @@
+# Makefile.in generated by automake 1.16.3 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2020 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+am__is_gnu_make = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = app/actions
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
+ $(top_srcdir)/m4macros/alsa.m4 \
+ $(top_srcdir)/m4macros/ax_compare_version.m4 \
+ $(top_srcdir)/m4macros/ax_cxx_compile_stdcxx.m4 \
+ $(top_srcdir)/m4macros/ax_gcc_func_attribute.m4 \
+ $(top_srcdir)/m4macros/ax_prog_cc_for_build.m4 \
+ $(top_srcdir)/m4macros/ax_prog_perl_version.m4 \
+ $(top_srcdir)/m4macros/detectcflags.m4 \
+ $(top_srcdir)/m4macros/pythondev.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+LIBRARIES = $(noinst_LIBRARIES)
+ARFLAGS = cru
+AM_V_AR = $(am__v_AR_@AM_V@)
+am__v_AR_ = $(am__v_AR_@AM_DEFAULT_V@)
+am__v_AR_0 = @echo " AR " $@;
+am__v_AR_1 =
+libappactions_a_AR = $(AR) $(ARFLAGS)
+libappactions_a_LIBADD =
+am_libappactions_a_OBJECTS = actions.$(OBJEXT) \
+ gimpgeglprocedure.$(OBJEXT) brush-editor-actions.$(OBJEXT) \
+ brushes-actions.$(OBJEXT) buffers-actions.$(OBJEXT) \
+ buffers-commands.$(OBJEXT) channels-actions.$(OBJEXT) \
+ channels-commands.$(OBJEXT) colormap-actions.$(OBJEXT) \
+ colormap-commands.$(OBJEXT) context-actions.$(OBJEXT) \
+ context-commands.$(OBJEXT) cursor-info-actions.$(OBJEXT) \
+ cursor-info-commands.$(OBJEXT) dashboard-actions.$(OBJEXT) \
+ dashboard-commands.$(OBJEXT) data-commands.$(OBJEXT) \
+ data-editor-commands.$(OBJEXT) debug-actions.$(OBJEXT) \
+ debug-commands.$(OBJEXT) dialogs-actions.$(OBJEXT) \
+ dialogs-commands.$(OBJEXT) dock-actions.$(OBJEXT) \
+ dock-commands.$(OBJEXT) dockable-actions.$(OBJEXT) \
+ dockable-commands.$(OBJEXT) documents-actions.$(OBJEXT) \
+ documents-commands.$(OBJEXT) drawable-actions.$(OBJEXT) \
+ drawable-commands.$(OBJEXT) dynamics-actions.$(OBJEXT) \
+ dynamics-editor-actions.$(OBJEXT) edit-actions.$(OBJEXT) \
+ edit-commands.$(OBJEXT) error-console-actions.$(OBJEXT) \
+ error-console-commands.$(OBJEXT) file-actions.$(OBJEXT) \
+ file-commands.$(OBJEXT) filters-actions.$(OBJEXT) \
+ filters-commands.$(OBJEXT) fonts-actions.$(OBJEXT) \
+ gradient-editor-actions.$(OBJEXT) \
+ gradient-editor-commands.$(OBJEXT) gradients-actions.$(OBJEXT) \
+ gradients-commands.$(OBJEXT) help-actions.$(OBJEXT) \
+ help-commands.$(OBJEXT) image-actions.$(OBJEXT) \
+ image-commands.$(OBJEXT) images-actions.$(OBJEXT) \
+ images-commands.$(OBJEXT) items-commands.$(OBJEXT) \
+ items-actions.$(OBJEXT) layers-actions.$(OBJEXT) \
+ layers-commands.$(OBJEXT) mypaint-brushes-actions.$(OBJEXT) \
+ palette-editor-actions.$(OBJEXT) \
+ palette-editor-commands.$(OBJEXT) palettes-actions.$(OBJEXT) \
+ palettes-commands.$(OBJEXT) patterns-actions.$(OBJEXT) \
+ plug-in-actions.$(OBJEXT) plug-in-commands.$(OBJEXT) \
+ procedure-commands.$(OBJEXT) quick-mask-actions.$(OBJEXT) \
+ quick-mask-commands.$(OBJEXT) sample-points-actions.$(OBJEXT) \
+ sample-points-commands.$(OBJEXT) select-actions.$(OBJEXT) \
+ select-commands.$(OBJEXT) templates-actions.$(OBJEXT) \
+ templates-commands.$(OBJEXT) text-editor-actions.$(OBJEXT) \
+ text-editor-commands.$(OBJEXT) text-tool-actions.$(OBJEXT) \
+ text-tool-commands.$(OBJEXT) tool-options-actions.$(OBJEXT) \
+ tool-options-commands.$(OBJEXT) tool-presets-actions.$(OBJEXT) \
+ tool-presets-commands.$(OBJEXT) \
+ tool-preset-editor-actions.$(OBJEXT) \
+ tool-preset-editor-commands.$(OBJEXT) tools-actions.$(OBJEXT) \
+ tools-commands.$(OBJEXT) vectors-actions.$(OBJEXT) \
+ vectors-commands.$(OBJEXT) view-actions.$(OBJEXT) \
+ view-commands.$(OBJEXT) window-actions.$(OBJEXT) \
+ window-commands.$(OBJEXT) windows-actions.$(OBJEXT) \
+ windows-commands.$(OBJEXT)
+libappactions_a_OBJECTS = $(am_libappactions_a_OBJECTS)
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/actions.Po \
+ ./$(DEPDIR)/brush-editor-actions.Po \
+ ./$(DEPDIR)/brushes-actions.Po ./$(DEPDIR)/buffers-actions.Po \
+ ./$(DEPDIR)/buffers-commands.Po \
+ ./$(DEPDIR)/channels-actions.Po \
+ ./$(DEPDIR)/channels-commands.Po \
+ ./$(DEPDIR)/colormap-actions.Po \
+ ./$(DEPDIR)/colormap-commands.Po \
+ ./$(DEPDIR)/context-actions.Po ./$(DEPDIR)/context-commands.Po \
+ ./$(DEPDIR)/cursor-info-actions.Po \
+ ./$(DEPDIR)/cursor-info-commands.Po \
+ ./$(DEPDIR)/dashboard-actions.Po \
+ ./$(DEPDIR)/dashboard-commands.Po ./$(DEPDIR)/data-commands.Po \
+ ./$(DEPDIR)/data-editor-commands.Po \
+ ./$(DEPDIR)/debug-actions.Po ./$(DEPDIR)/debug-commands.Po \
+ ./$(DEPDIR)/dialogs-actions.Po ./$(DEPDIR)/dialogs-commands.Po \
+ ./$(DEPDIR)/dock-actions.Po ./$(DEPDIR)/dock-commands.Po \
+ ./$(DEPDIR)/dockable-actions.Po \
+ ./$(DEPDIR)/dockable-commands.Po \
+ ./$(DEPDIR)/documents-actions.Po \
+ ./$(DEPDIR)/documents-commands.Po \
+ ./$(DEPDIR)/drawable-actions.Po \
+ ./$(DEPDIR)/drawable-commands.Po \
+ ./$(DEPDIR)/dynamics-actions.Po \
+ ./$(DEPDIR)/dynamics-editor-actions.Po \
+ ./$(DEPDIR)/edit-actions.Po ./$(DEPDIR)/edit-commands.Po \
+ ./$(DEPDIR)/error-console-actions.Po \
+ ./$(DEPDIR)/error-console-commands.Po \
+ ./$(DEPDIR)/file-actions.Po ./$(DEPDIR)/file-commands.Po \
+ ./$(DEPDIR)/filters-actions.Po ./$(DEPDIR)/filters-commands.Po \
+ ./$(DEPDIR)/fonts-actions.Po ./$(DEPDIR)/gimpgeglprocedure.Po \
+ ./$(DEPDIR)/gradient-editor-actions.Po \
+ ./$(DEPDIR)/gradient-editor-commands.Po \
+ ./$(DEPDIR)/gradients-actions.Po \
+ ./$(DEPDIR)/gradients-commands.Po ./$(DEPDIR)/help-actions.Po \
+ ./$(DEPDIR)/help-commands.Po ./$(DEPDIR)/image-actions.Po \
+ ./$(DEPDIR)/image-commands.Po ./$(DEPDIR)/images-actions.Po \
+ ./$(DEPDIR)/images-commands.Po ./$(DEPDIR)/items-actions.Po \
+ ./$(DEPDIR)/items-commands.Po ./$(DEPDIR)/layers-actions.Po \
+ ./$(DEPDIR)/layers-commands.Po \
+ ./$(DEPDIR)/mypaint-brushes-actions.Po \
+ ./$(DEPDIR)/palette-editor-actions.Po \
+ ./$(DEPDIR)/palette-editor-commands.Po \
+ ./$(DEPDIR)/palettes-actions.Po \
+ ./$(DEPDIR)/palettes-commands.Po \
+ ./$(DEPDIR)/patterns-actions.Po ./$(DEPDIR)/plug-in-actions.Po \
+ ./$(DEPDIR)/plug-in-commands.Po \
+ ./$(DEPDIR)/procedure-commands.Po \
+ ./$(DEPDIR)/quick-mask-actions.Po \
+ ./$(DEPDIR)/quick-mask-commands.Po \
+ ./$(DEPDIR)/sample-points-actions.Po \
+ ./$(DEPDIR)/sample-points-commands.Po \
+ ./$(DEPDIR)/select-actions.Po ./$(DEPDIR)/select-commands.Po \
+ ./$(DEPDIR)/templates-actions.Po \
+ ./$(DEPDIR)/templates-commands.Po \
+ ./$(DEPDIR)/text-editor-actions.Po \
+ ./$(DEPDIR)/text-editor-commands.Po \
+ ./$(DEPDIR)/text-tool-actions.Po \
+ ./$(DEPDIR)/text-tool-commands.Po \
+ ./$(DEPDIR)/tool-options-actions.Po \
+ ./$(DEPDIR)/tool-options-commands.Po \
+ ./$(DEPDIR)/tool-preset-editor-actions.Po \
+ ./$(DEPDIR)/tool-preset-editor-commands.Po \
+ ./$(DEPDIR)/tool-presets-actions.Po \
+ ./$(DEPDIR)/tool-presets-commands.Po \
+ ./$(DEPDIR)/tools-actions.Po ./$(DEPDIR)/tools-commands.Po \
+ ./$(DEPDIR)/vectors-actions.Po ./$(DEPDIR)/vectors-commands.Po \
+ ./$(DEPDIR)/view-actions.Po ./$(DEPDIR)/view-commands.Po \
+ ./$(DEPDIR)/window-actions.Po ./$(DEPDIR)/window-commands.Po \
+ ./$(DEPDIR)/windows-actions.Po ./$(DEPDIR)/windows-commands.Po
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+AM_V_lt = $(am__v_lt_@AM_V@)
+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+am__v_lt_1 =
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo " CC " $@;
+am__v_CC_1 =
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo " CCLD " $@;
+am__v_CCLD_1 =
+SOURCES = $(libappactions_a_SOURCES)
+DIST_SOURCES = $(libappactions_a_SOURCES)
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates. Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+ BEGIN { nonempty = 0; } \
+ { items[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique. This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+ list='$(am__tagged_files)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+AA_LIBS = @AA_LIBS@
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+ALL_LINGUAS = @ALL_LINGUAS@
+ALSA_CFLAGS = @ALSA_CFLAGS@
+ALSA_LIBS = @ALSA_LIBS@
+ALTIVEC_EXTRA_CFLAGS = @ALTIVEC_EXTRA_CFLAGS@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+APPSTREAM_UTIL = @APPSTREAM_UTIL@
+AR = @AR@
+AS = @AS@
+ATK_CFLAGS = @ATK_CFLAGS@
+ATK_LIBS = @ATK_LIBS@
+ATK_REQUIRED_VERSION = @ATK_REQUIRED_VERSION@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BABL_CFLAGS = @BABL_CFLAGS@
+BABL_LIBS = @BABL_LIBS@
+BABL_REQUIRED_VERSION = @BABL_REQUIRED_VERSION@
+BUG_REPORT_URL = @BUG_REPORT_URL@
+BUILD_EXEEXT = @BUILD_EXEEXT@
+BUILD_OBJEXT = @BUILD_OBJEXT@
+BZIP2_LIBS = @BZIP2_LIBS@
+CAIRO_CFLAGS = @CAIRO_CFLAGS@
+CAIRO_LIBS = @CAIRO_LIBS@
+CAIRO_PDF_CFLAGS = @CAIRO_PDF_CFLAGS@
+CAIRO_PDF_LIBS = @CAIRO_PDF_LIBS@
+CAIRO_PDF_REQUIRED_VERSION = @CAIRO_PDF_REQUIRED_VERSION@
+CAIRO_REQUIRED_VERSION = @CAIRO_REQUIRED_VERSION@
+CATALOGS = @CATALOGS@
+CATOBJEXT = @CATOBJEXT@
+CC = @CC@
+CCAS = @CCAS@
+CCASDEPMODE = @CCASDEPMODE@
+CCASFLAGS = @CCASFLAGS@
+CCDEPMODE = @CCDEPMODE@
+CC_FOR_BUILD = @CC_FOR_BUILD@
+CC_VERSION = @CC_VERSION@
+CFLAGS = @CFLAGS@
+CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CPPFLAGS_FOR_BUILD = @CPPFLAGS_FOR_BUILD@
+CPP_FOR_BUILD = @CPP_FOR_BUILD@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DATADIRNAME = @DATADIRNAME@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DESKTOP_DATADIR = @DESKTOP_DATADIR@
+DESKTOP_FILE_VALIDATE = @DESKTOP_FILE_VALIDATE@
+DLLTOOL = @DLLTOOL@
+DOC_SHOOTER = @DOC_SHOOTER@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+FILE_AA = @FILE_AA@
+FILE_EXR = @FILE_EXR@
+FILE_HEIF = @FILE_HEIF@
+FILE_JP2_LOAD = @FILE_JP2_LOAD@
+FILE_JPEGXL = @FILE_JPEGXL@
+FILE_MNG = @FILE_MNG@
+FILE_PDF_SAVE = @FILE_PDF_SAVE@
+FILE_PS = @FILE_PS@
+FILE_WMF = @FILE_WMF@
+FILE_XMC = @FILE_XMC@
+FILE_XPM = @FILE_XPM@
+FONTCONFIG_CFLAGS = @FONTCONFIG_CFLAGS@
+FONTCONFIG_LIBS = @FONTCONFIG_LIBS@
+FONTCONFIG_REQUIRED_VERSION = @FONTCONFIG_REQUIRED_VERSION@
+FREETYPE2_REQUIRED_VERSION = @FREETYPE2_REQUIRED_VERSION@
+FREETYPE_CFLAGS = @FREETYPE_CFLAGS@
+FREETYPE_LIBS = @FREETYPE_LIBS@
+GDBUS_CODEGEN = @GDBUS_CODEGEN@
+GDK_PIXBUF_CFLAGS = @GDK_PIXBUF_CFLAGS@
+GDK_PIXBUF_CSOURCE = @GDK_PIXBUF_CSOURCE@
+GDK_PIXBUF_LIBS = @GDK_PIXBUF_LIBS@
+GDK_PIXBUF_REQUIRED_VERSION = @GDK_PIXBUF_REQUIRED_VERSION@
+GEGL = @GEGL@
+GEGL_CFLAGS = @GEGL_CFLAGS@
+GEGL_LIBS = @GEGL_LIBS@
+GEGL_MAJOR_MINOR_VERSION = @GEGL_MAJOR_MINOR_VERSION@
+GEGL_REQUIRED_VERSION = @GEGL_REQUIRED_VERSION@
+GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
+GEXIV2_CFLAGS = @GEXIV2_CFLAGS@
+GEXIV2_LIBS = @GEXIV2_LIBS@
+GEXIV2_REQUIRED_VERSION = @GEXIV2_REQUIRED_VERSION@
+GIMP_API_VERSION = @GIMP_API_VERSION@
+GIMP_APP_VERSION = @GIMP_APP_VERSION@
+GIMP_BINARY_AGE = @GIMP_BINARY_AGE@
+GIMP_COMMAND = @GIMP_COMMAND@
+GIMP_DATA_VERSION = @GIMP_DATA_VERSION@
+GIMP_FULL_NAME = @GIMP_FULL_NAME@
+GIMP_INTERFACE_AGE = @GIMP_INTERFACE_AGE@
+GIMP_MAJOR_VERSION = @GIMP_MAJOR_VERSION@
+GIMP_MICRO_VERSION = @GIMP_MICRO_VERSION@
+GIMP_MINOR_VERSION = @GIMP_MINOR_VERSION@
+GIMP_MKENUMS = @GIMP_MKENUMS@
+GIMP_MODULES = @GIMP_MODULES@
+GIMP_PACKAGE_REVISION = @GIMP_PACKAGE_REVISION@
+GIMP_PKGCONFIG_VERSION = @GIMP_PKGCONFIG_VERSION@
+GIMP_PLUGINS = @GIMP_PLUGINS@
+GIMP_PLUGIN_VERSION = @GIMP_PLUGIN_VERSION@
+GIMP_REAL_VERSION = @GIMP_REAL_VERSION@
+GIMP_RELEASE = @GIMP_RELEASE@
+GIMP_SYSCONF_VERSION = @GIMP_SYSCONF_VERSION@
+GIMP_TOOL_VERSION = @GIMP_TOOL_VERSION@
+GIMP_UNSTABLE = @GIMP_UNSTABLE@
+GIMP_USER_VERSION = @GIMP_USER_VERSION@
+GIMP_VERSION = @GIMP_VERSION@
+GIO_CFLAGS = @GIO_CFLAGS@
+GIO_LIBS = @GIO_LIBS@
+GIO_UNIX_CFLAGS = @GIO_UNIX_CFLAGS@
+GIO_UNIX_LIBS = @GIO_UNIX_LIBS@
+GIO_WINDOWS_CFLAGS = @GIO_WINDOWS_CFLAGS@
+GIO_WINDOWS_LIBS = @GIO_WINDOWS_LIBS@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_COMPILE_RESOURCES = @GLIB_COMPILE_RESOURCES@
+GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
+GLIB_LIBS = @GLIB_LIBS@
+GLIB_MKENUMS = @GLIB_MKENUMS@
+GLIB_REQUIRED_VERSION = @GLIB_REQUIRED_VERSION@
+GMODULE_NO_EXPORT_CFLAGS = @GMODULE_NO_EXPORT_CFLAGS@
+GMODULE_NO_EXPORT_LIBS = @GMODULE_NO_EXPORT_LIBS@
+GMOFILES = @GMOFILES@
+GMSGFMT = @GMSGFMT@
+GOBJECT_QUERY = @GOBJECT_QUERY@
+GREP = @GREP@
+GS_LIBS = @GS_LIBS@
+GTKDOC_CHECK = @GTKDOC_CHECK@
+GTKDOC_CHECK_PATH = @GTKDOC_CHECK_PATH@
+GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@
+GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@
+GTKDOC_MKPDF = @GTKDOC_MKPDF@
+GTKDOC_REBASE = @GTKDOC_REBASE@
+GTK_CFLAGS = @GTK_CFLAGS@
+GTK_LIBS = @GTK_LIBS@
+GTK_MAC_INTEGRATION_CFLAGS = @GTK_MAC_INTEGRATION_CFLAGS@
+GTK_MAC_INTEGRATION_LIBS = @GTK_MAC_INTEGRATION_LIBS@
+GTK_REQUIRED_VERSION = @GTK_REQUIRED_VERSION@
+GTK_UPDATE_ICON_CACHE = @GTK_UPDATE_ICON_CACHE@
+GUDEV_CFLAGS = @GUDEV_CFLAGS@
+GUDEV_LIBS = @GUDEV_LIBS@
+HARFBUZZ_CFLAGS = @HARFBUZZ_CFLAGS@
+HARFBUZZ_LIBS = @HARFBUZZ_LIBS@
+HARFBUZZ_REQUIRED_VERSION = @HARFBUZZ_REQUIRED_VERSION@
+HAVE_CXX14 = @HAVE_CXX14@
+HAVE_FINITE = @HAVE_FINITE@
+HAVE_ISFINITE = @HAVE_ISFINITE@
+HAVE_VFORK = @HAVE_VFORK@
+HOST_GLIB_COMPILE_RESOURCES = @HOST_GLIB_COMPILE_RESOURCES@
+HTML_DIR = @HTML_DIR@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INSTOBJEXT = @INSTOBJEXT@
+INTLLIBS = @INTLLIBS@
+INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@
+INTLTOOL_MERGE = @INTLTOOL_MERGE@
+INTLTOOL_PERL = @INTLTOOL_PERL@
+INTLTOOL_REQUIRED_VERSION = @INTLTOOL_REQUIRED_VERSION@
+INTLTOOL_UPDATE = @INTLTOOL_UPDATE@
+INTLTOOL_V_MERGE = @INTLTOOL_V_MERGE@
+INTLTOOL_V_MERGE_OPTIONS = @INTLTOOL_V_MERGE_OPTIONS@
+INTLTOOL__v_MERGE_ = @INTLTOOL__v_MERGE_@
+INTLTOOL__v_MERGE_0 = @INTLTOOL__v_MERGE_0@
+INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@
+ISO_CODES_LOCALEDIR = @ISO_CODES_LOCALEDIR@
+ISO_CODES_LOCATION = @ISO_CODES_LOCATION@
+JPEG_LIBS = @JPEG_LIBS@
+JSON_GLIB_CFLAGS = @JSON_GLIB_CFLAGS@
+JSON_GLIB_LIBS = @JSON_GLIB_LIBS@
+JXL_CFLAGS = @JXL_CFLAGS@
+JXL_LIBS = @JXL_LIBS@
+JXL_THREADS_CFLAGS = @JXL_THREADS_CFLAGS@
+JXL_THREADS_LIBS = @JXL_THREADS_LIBS@
+LCMS_CFLAGS = @LCMS_CFLAGS@
+LCMS_LIBS = @LCMS_LIBS@
+LCMS_REQUIRED_VERSION = @LCMS_REQUIRED_VERSION@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LDFLAGS_FOR_BUILD = @LDFLAGS_FOR_BUILD@
+LIBBACKTRACE_LIBS = @LIBBACKTRACE_LIBS@
+LIBHEIF_CFLAGS = @LIBHEIF_CFLAGS@
+LIBHEIF_LIBS = @LIBHEIF_LIBS@
+LIBHEIF_REQUIRED_VERSION = @LIBHEIF_REQUIRED_VERSION@
+LIBJXL_REQUIRED_VERSION = @LIBJXL_REQUIRED_VERSION@
+LIBLZMA_REQUIRED_VERSION = @LIBLZMA_REQUIRED_VERSION@
+LIBMYPAINT_CFLAGS = @LIBMYPAINT_CFLAGS@
+LIBMYPAINT_LIBS = @LIBMYPAINT_LIBS@
+LIBMYPAINT_REQUIRED_VERSION = @LIBMYPAINT_REQUIRED_VERSION@
+LIBOBJS = @LIBOBJS@
+LIBPNG_REQUIRED_VERSION = @LIBPNG_REQUIRED_VERSION@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUNWIND_CFLAGS = @LIBUNWIND_CFLAGS@
+LIBUNWIND_LIBS = @LIBUNWIND_LIBS@
+LIBUNWIND_REQUIRED_VERSION = @LIBUNWIND_REQUIRED_VERSION@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_CURRENT_MINUS_AGE = @LT_CURRENT_MINUS_AGE@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+LT_VERSION_INFO = @LT_VERSION_INFO@
+LZMA_CFLAGS = @LZMA_CFLAGS@
+LZMA_LIBS = @LZMA_LIBS@
+MAIL = @MAIL@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MIME_INFO_CFLAGS = @MIME_INFO_CFLAGS@
+MIME_INFO_LIBS = @MIME_INFO_LIBS@
+MIME_TYPES = @MIME_TYPES@
+MKDIR_P = @MKDIR_P@
+MKINSTALLDIRS = @MKINSTALLDIRS@
+MMX_EXTRA_CFLAGS = @MMX_EXTRA_CFLAGS@
+MNG_CFLAGS = @MNG_CFLAGS@
+MNG_LIBS = @MNG_LIBS@
+MSGFMT = @MSGFMT@
+MSGFMT_OPTS = @MSGFMT_OPTS@
+MSGMERGE = @MSGMERGE@
+MYPAINT_BRUSHES_CFLAGS = @MYPAINT_BRUSHES_CFLAGS@
+MYPAINT_BRUSHES_LIBS = @MYPAINT_BRUSHES_LIBS@
+NATIVE_GLIB_CFLAGS = @NATIVE_GLIB_CFLAGS@
+NATIVE_GLIB_LIBS = @NATIVE_GLIB_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENEXR_CFLAGS = @OPENEXR_CFLAGS@
+OPENEXR_LIBS = @OPENEXR_LIBS@
+OPENEXR_REQUIRED_VERSION = @OPENEXR_REQUIRED_VERSION@
+OPENJPEG_CFLAGS = @OPENJPEG_CFLAGS@
+OPENJPEG_LIBS = @OPENJPEG_LIBS@
+OPENJPEG_REQUIRED_VERSION = @OPENJPEG_REQUIRED_VERSION@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PANGOCAIRO_CFLAGS = @PANGOCAIRO_CFLAGS@
+PANGOCAIRO_LIBS = @PANGOCAIRO_LIBS@
+PANGOCAIRO_REQUIRED_VERSION = @PANGOCAIRO_REQUIRED_VERSION@
+PATHSEP = @PATHSEP@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PERL_REQUIRED_VERSION = @PERL_REQUIRED_VERSION@
+PERL_VERSION = @PERL_VERSION@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PNG_CFLAGS = @PNG_CFLAGS@
+PNG_LIBS = @PNG_LIBS@
+POFILES = @POFILES@
+POPPLER_CFLAGS = @POPPLER_CFLAGS@
+POPPLER_DATA_CFLAGS = @POPPLER_DATA_CFLAGS@
+POPPLER_DATA_LIBS = @POPPLER_DATA_LIBS@
+POPPLER_DATA_REQUIRED_VERSION = @POPPLER_DATA_REQUIRED_VERSION@
+POPPLER_LIBS = @POPPLER_LIBS@
+POPPLER_REQUIRED_VERSION = @POPPLER_REQUIRED_VERSION@
+POSUB = @POSUB@
+PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@
+PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@
+PYBIN_PATH = @PYBIN_PATH@
+PYCAIRO_CFLAGS = @PYCAIRO_CFLAGS@
+PYCAIRO_LIBS = @PYCAIRO_LIBS@
+PYGIMP_EXTRA_CFLAGS = @PYGIMP_EXTRA_CFLAGS@
+PYGTK_CFLAGS = @PYGTK_CFLAGS@
+PYGTK_CODEGEN = @PYGTK_CODEGEN@
+PYGTK_DEFSDIR = @PYGTK_DEFSDIR@
+PYGTK_LIBS = @PYGTK_LIBS@
+PYLINK_LIBS = @PYLINK_LIBS@
+PYTHON = @PYTHON@
+PYTHON2_REQUIRED_VERSION = @PYTHON2_REQUIRED_VERSION@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_INCLUDES = @PYTHON_INCLUDES@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RANLIB = @RANLIB@
+RSVG_REQUIRED_VERSION = @RSVG_REQUIRED_VERSION@
+RT_LIBS = @RT_LIBS@
+SCREENSHOT_LIBS = @SCREENSHOT_LIBS@
+SED = @SED@
+SENDMAIL = @SENDMAIL@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SOCKET_LIBS = @SOCKET_LIBS@
+SSE2_EXTRA_CFLAGS = @SSE2_EXTRA_CFLAGS@
+SSE4_1_EXTRA_CFLAGS = @SSE4_1_EXTRA_CFLAGS@
+SSE_EXTRA_CFLAGS = @SSE_EXTRA_CFLAGS@
+STRIP = @STRIP@
+SVG_CFLAGS = @SVG_CFLAGS@
+SVG_LIBS = @SVG_LIBS@
+SYMPREFIX = @SYMPREFIX@
+TIFF_LIBS = @TIFF_LIBS@
+USE_NLS = @USE_NLS@
+VERSION = @VERSION@
+WEBKIT_CFLAGS = @WEBKIT_CFLAGS@
+WEBKIT_LIBS = @WEBKIT_LIBS@
+WEBKIT_REQUIRED_VERSION = @WEBKIT_REQUIRED_VERSION@
+WEBPDEMUX_CFLAGS = @WEBPDEMUX_CFLAGS@
+WEBPDEMUX_LIBS = @WEBPDEMUX_LIBS@
+WEBPMUX_CFLAGS = @WEBPMUX_CFLAGS@
+WEBPMUX_LIBS = @WEBPMUX_LIBS@
+WEBP_CFLAGS = @WEBP_CFLAGS@
+WEBP_LIBS = @WEBP_LIBS@
+WEBP_REQUIRED_VERSION = @WEBP_REQUIRED_VERSION@
+WEB_PAGE = @WEB_PAGE@
+WIN32_LARGE_ADDRESS_AWARE = @WIN32_LARGE_ADDRESS_AWARE@
+WINDRES = @WINDRES@
+WMF_CFLAGS = @WMF_CFLAGS@
+WMF_CONFIG = @WMF_CONFIG@
+WMF_LIBS = @WMF_LIBS@
+WMF_REQUIRED_VERSION = @WMF_REQUIRED_VERSION@
+XDG_EMAIL = @XDG_EMAIL@
+XFIXES_CFLAGS = @XFIXES_CFLAGS@
+XFIXES_LIBS = @XFIXES_LIBS@
+XGETTEXT = @XGETTEXT@
+XGETTEXT_REQUIRED_VERSION = @XGETTEXT_REQUIRED_VERSION@
+XMC_CFLAGS = @XMC_CFLAGS@
+XMC_LIBS = @XMC_LIBS@
+XMKMF = @XMKMF@
+XMLLINT = @XMLLINT@
+XMU_LIBS = @XMU_LIBS@
+XPM_LIBS = @XPM_LIBS@
+XSLTPROC = @XSLTPROC@
+XVFB_RUN = @XVFB_RUN@
+X_CFLAGS = @X_CFLAGS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_LIBS = @X_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
+Z_LIBS = @Z_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CC_FOR_BUILD = @ac_ct_CC_FOR_BUILD@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+gimpdatadir = @gimpdatadir@
+gimpdir = @gimpdir@
+gimplocaledir = @gimplocaledir@
+gimpplugindir = @gimpplugindir@
+gimpsysconfdir = @gimpsysconfdir@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+intltool__v_merge_options_ = @intltool__v_merge_options_@
+intltool__v_merge_options_0 = @intltool__v_merge_options_0@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+manpage_gimpdir = @manpage_gimpdir@
+mkdir_p = @mkdir_p@
+ms_librarian = @ms_librarian@
+mypaint_brushes_dir = @mypaint_brushes_dir@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+AM_CPPFLAGS = \
+ -DG_LOG_DOMAIN=\"Gimp-Actions\" \
+ -I$(top_builddir) \
+ -I$(top_srcdir) \
+ -I$(top_builddir)/app \
+ -I$(top_srcdir)/app \
+ $(GEGL_CFLAGS) \
+ $(GTK_CFLAGS) \
+ -I$(includedir)
+
+noinst_LIBRARIES = libappactions.a
+libappactions_a_SOURCES = \
+ actions-types.h \
+ actions.c \
+ actions.h \
+ \
+ gimpgeglprocedure.c \
+ gimpgeglprocedure.h \
+ \
+ brush-editor-actions.c \
+ brush-editor-actions.h \
+ brushes-actions.c \
+ brushes-actions.h \
+ buffers-actions.c \
+ buffers-actions.h \
+ buffers-commands.c \
+ buffers-commands.h \
+ channels-actions.c \
+ channels-actions.h \
+ channels-commands.c \
+ channels-commands.h \
+ colormap-actions.c \
+ colormap-actions.h \
+ colormap-commands.c \
+ colormap-commands.h \
+ context-actions.c \
+ context-actions.h \
+ context-commands.c \
+ context-commands.h \
+ cursor-info-actions.c \
+ cursor-info-actions.h \
+ cursor-info-commands.c \
+ cursor-info-commands.h \
+ dashboard-actions.c \
+ dashboard-actions.h \
+ dashboard-commands.c \
+ dashboard-commands.h \
+ data-commands.c \
+ data-commands.h \
+ data-editor-commands.c \
+ data-editor-commands.h \
+ debug-actions.c \
+ debug-actions.h \
+ debug-commands.c \
+ debug-commands.h \
+ dialogs-actions.c \
+ dialogs-actions.h \
+ dialogs-commands.c \
+ dialogs-commands.h \
+ dock-actions.c \
+ dock-actions.h \
+ dock-commands.c \
+ dock-commands.h \
+ dockable-actions.c \
+ dockable-actions.h \
+ dockable-commands.c \
+ dockable-commands.h \
+ documents-actions.c \
+ documents-actions.h \
+ documents-commands.c \
+ documents-commands.h \
+ drawable-actions.c \
+ drawable-actions.h \
+ drawable-commands.c \
+ drawable-commands.h \
+ dynamics-actions.c \
+ dynamics-actions.h \
+ dynamics-editor-actions.c \
+ dynamics-editor-actions.h \
+ edit-actions.c \
+ edit-actions.h \
+ edit-commands.c \
+ edit-commands.h \
+ error-console-actions.c \
+ error-console-actions.h \
+ error-console-commands.c \
+ error-console-commands.h \
+ file-actions.c \
+ file-actions.h \
+ file-commands.c \
+ file-commands.h \
+ filters-actions.c \
+ filters-actions.h \
+ filters-commands.c \
+ filters-commands.h \
+ fonts-actions.c \
+ fonts-actions.h \
+ gradient-editor-actions.c \
+ gradient-editor-actions.h \
+ gradient-editor-commands.c \
+ gradient-editor-commands.h \
+ gradients-actions.c \
+ gradients-actions.h \
+ gradients-commands.c \
+ gradients-commands.h \
+ help-actions.c \
+ help-actions.h \
+ help-commands.c \
+ help-commands.h \
+ image-actions.c \
+ image-actions.h \
+ image-commands.c \
+ image-commands.h \
+ images-actions.c \
+ images-actions.h \
+ images-commands.c \
+ images-commands.h \
+ items-commands.c \
+ items-commands.h \
+ items-actions.c \
+ items-actions.h \
+ layers-actions.c \
+ layers-actions.h \
+ layers-commands.c \
+ layers-commands.h \
+ mypaint-brushes-actions.c \
+ mypaint-brushes-actions.h \
+ palette-editor-actions.c \
+ palette-editor-actions.h \
+ palette-editor-commands.c \
+ palette-editor-commands.h \
+ palettes-actions.c \
+ palettes-actions.h \
+ palettes-commands.c \
+ palettes-commands.h \
+ patterns-actions.c \
+ patterns-actions.h \
+ plug-in-actions.c \
+ plug-in-actions.h \
+ plug-in-commands.c \
+ plug-in-commands.h \
+ procedure-commands.c \
+ procedure-commands.h \
+ quick-mask-actions.c \
+ quick-mask-actions.h \
+ quick-mask-commands.c \
+ quick-mask-commands.h \
+ sample-points-actions.c \
+ sample-points-actions.h \
+ sample-points-commands.c \
+ sample-points-commands.h \
+ select-actions.c \
+ select-actions.h \
+ select-commands.c \
+ select-commands.h \
+ templates-actions.c \
+ templates-actions.h \
+ templates-commands.c \
+ templates-commands.h \
+ text-editor-actions.c \
+ text-editor-actions.h \
+ text-editor-commands.c \
+ text-editor-commands.h \
+ text-tool-actions.c \
+ text-tool-actions.h \
+ text-tool-commands.c \
+ text-tool-commands.h \
+ tool-options-actions.c \
+ tool-options-actions.h \
+ tool-options-commands.c \
+ tool-options-commands.h \
+ tool-presets-actions.c \
+ tool-presets-actions.h \
+ tool-presets-commands.c \
+ tool-presets-commands.h \
+ tool-preset-editor-actions.c \
+ tool-preset-editor-actions.h \
+ tool-preset-editor-commands.c \
+ tool-preset-editor-commands.h \
+ tools-actions.c \
+ tools-actions.h \
+ tools-commands.c \
+ tools-commands.h \
+ vectors-actions.c \
+ vectors-actions.h \
+ vectors-commands.c \
+ vectors-commands.h \
+ view-actions.c \
+ view-actions.h \
+ view-commands.c \
+ view-commands.h \
+ window-actions.c \
+ window-actions.h \
+ window-commands.c \
+ window-commands.h \
+ windows-actions.c \
+ windows-actions.h \
+ windows-commands.c \
+ windows-commands.h
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu app/actions/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu app/actions/Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstLIBRARIES:
+ -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
+
+libappactions.a: $(libappactions_a_OBJECTS) $(libappactions_a_DEPENDENCIES) $(EXTRA_libappactions_a_DEPENDENCIES)
+ $(AM_V_at)-rm -f libappactions.a
+ $(AM_V_AR)$(libappactions_a_AR) libappactions.a $(libappactions_a_OBJECTS) $(libappactions_a_LIBADD)
+ $(AM_V_at)$(RANLIB) libappactions.a
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/actions.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/brush-editor-actions.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/brushes-actions.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/buffers-actions.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/buffers-commands.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/channels-actions.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/channels-commands.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/colormap-actions.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/colormap-commands.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/context-actions.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/context-commands.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cursor-info-actions.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cursor-info-commands.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dashboard-actions.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dashboard-commands.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/data-commands.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/data-editor-commands.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/debug-actions.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/debug-commands.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dialogs-actions.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dialogs-commands.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dock-actions.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dock-commands.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dockable-actions.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dockable-commands.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/documents-actions.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/documents-commands.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/drawable-actions.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/drawable-commands.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dynamics-actions.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dynamics-editor-actions.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/edit-actions.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/edit-commands.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/error-console-actions.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/error-console-commands.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/file-actions.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/file-commands.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/filters-actions.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/filters-commands.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fonts-actions.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpgeglprocedure.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gradient-editor-actions.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gradient-editor-commands.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gradients-actions.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gradients-commands.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/help-actions.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/help-commands.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/image-actions.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/image-commands.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/images-actions.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/images-commands.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/items-actions.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/items-commands.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/layers-actions.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/layers-commands.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mypaint-brushes-actions.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/palette-editor-actions.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/palette-editor-commands.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/palettes-actions.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/palettes-commands.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/patterns-actions.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plug-in-actions.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plug-in-commands.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/procedure-commands.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/quick-mask-actions.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/quick-mask-commands.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sample-points-actions.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sample-points-commands.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/select-actions.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/select-commands.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/templates-actions.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/templates-commands.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/text-editor-actions.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/text-editor-commands.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/text-tool-actions.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/text-tool-commands.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tool-options-actions.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tool-options-commands.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tool-preset-editor-actions.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tool-preset-editor-commands.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tool-presets-actions.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tool-presets-commands.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tools-actions.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tools-commands.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vectors-actions.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vectors-commands.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/view-actions.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/view-commands.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/window-actions.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/window-commands.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/windows-actions.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/windows-commands.Po@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.c.o:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(am__tagged_files)
+ $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ set x; \
+ here=`pwd`; \
+ $(am__define_uniq_tagged_files); \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ $(am__define_uniq_tagged_files); \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+ list='$(am__tagged_files)'; \
+ case "$(srcdir)" in \
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+ *) sdir=$(subdir)/$(srcdir) ;; \
+ esac; \
+ for i in $$list; do \
+ if test -f "$$i"; then \
+ echo "$(subdir)/$$i"; \
+ else \
+ echo "$$sdir/$$i"; \
+ fi; \
+ done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LIBRARIES)
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-noinstLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/actions.Po
+ -rm -f ./$(DEPDIR)/brush-editor-actions.Po
+ -rm -f ./$(DEPDIR)/brushes-actions.Po
+ -rm -f ./$(DEPDIR)/buffers-actions.Po
+ -rm -f ./$(DEPDIR)/buffers-commands.Po
+ -rm -f ./$(DEPDIR)/channels-actions.Po
+ -rm -f ./$(DEPDIR)/channels-commands.Po
+ -rm -f ./$(DEPDIR)/colormap-actions.Po
+ -rm -f ./$(DEPDIR)/colormap-commands.Po
+ -rm -f ./$(DEPDIR)/context-actions.Po
+ -rm -f ./$(DEPDIR)/context-commands.Po
+ -rm -f ./$(DEPDIR)/cursor-info-actions.Po
+ -rm -f ./$(DEPDIR)/cursor-info-commands.Po
+ -rm -f ./$(DEPDIR)/dashboard-actions.Po
+ -rm -f ./$(DEPDIR)/dashboard-commands.Po
+ -rm -f ./$(DEPDIR)/data-commands.Po
+ -rm -f ./$(DEPDIR)/data-editor-commands.Po
+ -rm -f ./$(DEPDIR)/debug-actions.Po
+ -rm -f ./$(DEPDIR)/debug-commands.Po
+ -rm -f ./$(DEPDIR)/dialogs-actions.Po
+ -rm -f ./$(DEPDIR)/dialogs-commands.Po
+ -rm -f ./$(DEPDIR)/dock-actions.Po
+ -rm -f ./$(DEPDIR)/dock-commands.Po
+ -rm -f ./$(DEPDIR)/dockable-actions.Po
+ -rm -f ./$(DEPDIR)/dockable-commands.Po
+ -rm -f ./$(DEPDIR)/documents-actions.Po
+ -rm -f ./$(DEPDIR)/documents-commands.Po
+ -rm -f ./$(DEPDIR)/drawable-actions.Po
+ -rm -f ./$(DEPDIR)/drawable-commands.Po
+ -rm -f ./$(DEPDIR)/dynamics-actions.Po
+ -rm -f ./$(DEPDIR)/dynamics-editor-actions.Po
+ -rm -f ./$(DEPDIR)/edit-actions.Po
+ -rm -f ./$(DEPDIR)/edit-commands.Po
+ -rm -f ./$(DEPDIR)/error-console-actions.Po
+ -rm -f ./$(DEPDIR)/error-console-commands.Po
+ -rm -f ./$(DEPDIR)/file-actions.Po
+ -rm -f ./$(DEPDIR)/file-commands.Po
+ -rm -f ./$(DEPDIR)/filters-actions.Po
+ -rm -f ./$(DEPDIR)/filters-commands.Po
+ -rm -f ./$(DEPDIR)/fonts-actions.Po
+ -rm -f ./$(DEPDIR)/gimpgeglprocedure.Po
+ -rm -f ./$(DEPDIR)/gradient-editor-actions.Po
+ -rm -f ./$(DEPDIR)/gradient-editor-commands.Po
+ -rm -f ./$(DEPDIR)/gradients-actions.Po
+ -rm -f ./$(DEPDIR)/gradients-commands.Po
+ -rm -f ./$(DEPDIR)/help-actions.Po
+ -rm -f ./$(DEPDIR)/help-commands.Po
+ -rm -f ./$(DEPDIR)/image-actions.Po
+ -rm -f ./$(DEPDIR)/image-commands.Po
+ -rm -f ./$(DEPDIR)/images-actions.Po
+ -rm -f ./$(DEPDIR)/images-commands.Po
+ -rm -f ./$(DEPDIR)/items-actions.Po
+ -rm -f ./$(DEPDIR)/items-commands.Po
+ -rm -f ./$(DEPDIR)/layers-actions.Po
+ -rm -f ./$(DEPDIR)/layers-commands.Po
+ -rm -f ./$(DEPDIR)/mypaint-brushes-actions.Po
+ -rm -f ./$(DEPDIR)/palette-editor-actions.Po
+ -rm -f ./$(DEPDIR)/palette-editor-commands.Po
+ -rm -f ./$(DEPDIR)/palettes-actions.Po
+ -rm -f ./$(DEPDIR)/palettes-commands.Po
+ -rm -f ./$(DEPDIR)/patterns-actions.Po
+ -rm -f ./$(DEPDIR)/plug-in-actions.Po
+ -rm -f ./$(DEPDIR)/plug-in-commands.Po
+ -rm -f ./$(DEPDIR)/procedure-commands.Po
+ -rm -f ./$(DEPDIR)/quick-mask-actions.Po
+ -rm -f ./$(DEPDIR)/quick-mask-commands.Po
+ -rm -f ./$(DEPDIR)/sample-points-actions.Po
+ -rm -f ./$(DEPDIR)/sample-points-commands.Po
+ -rm -f ./$(DEPDIR)/select-actions.Po
+ -rm -f ./$(DEPDIR)/select-commands.Po
+ -rm -f ./$(DEPDIR)/templates-actions.Po
+ -rm -f ./$(DEPDIR)/templates-commands.Po
+ -rm -f ./$(DEPDIR)/text-editor-actions.Po
+ -rm -f ./$(DEPDIR)/text-editor-commands.Po
+ -rm -f ./$(DEPDIR)/text-tool-actions.Po
+ -rm -f ./$(DEPDIR)/text-tool-commands.Po
+ -rm -f ./$(DEPDIR)/tool-options-actions.Po
+ -rm -f ./$(DEPDIR)/tool-options-commands.Po
+ -rm -f ./$(DEPDIR)/tool-preset-editor-actions.Po
+ -rm -f ./$(DEPDIR)/tool-preset-editor-commands.Po
+ -rm -f ./$(DEPDIR)/tool-presets-actions.Po
+ -rm -f ./$(DEPDIR)/tool-presets-commands.Po
+ -rm -f ./$(DEPDIR)/tools-actions.Po
+ -rm -f ./$(DEPDIR)/tools-commands.Po
+ -rm -f ./$(DEPDIR)/vectors-actions.Po
+ -rm -f ./$(DEPDIR)/vectors-commands.Po
+ -rm -f ./$(DEPDIR)/view-actions.Po
+ -rm -f ./$(DEPDIR)/view-commands.Po
+ -rm -f ./$(DEPDIR)/window-actions.Po
+ -rm -f ./$(DEPDIR)/window-commands.Po
+ -rm -f ./$(DEPDIR)/windows-actions.Po
+ -rm -f ./$(DEPDIR)/windows-commands.Po
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -f ./$(DEPDIR)/actions.Po
+ -rm -f ./$(DEPDIR)/brush-editor-actions.Po
+ -rm -f ./$(DEPDIR)/brushes-actions.Po
+ -rm -f ./$(DEPDIR)/buffers-actions.Po
+ -rm -f ./$(DEPDIR)/buffers-commands.Po
+ -rm -f ./$(DEPDIR)/channels-actions.Po
+ -rm -f ./$(DEPDIR)/channels-commands.Po
+ -rm -f ./$(DEPDIR)/colormap-actions.Po
+ -rm -f ./$(DEPDIR)/colormap-commands.Po
+ -rm -f ./$(DEPDIR)/context-actions.Po
+ -rm -f ./$(DEPDIR)/context-commands.Po
+ -rm -f ./$(DEPDIR)/cursor-info-actions.Po
+ -rm -f ./$(DEPDIR)/cursor-info-commands.Po
+ -rm -f ./$(DEPDIR)/dashboard-actions.Po
+ -rm -f ./$(DEPDIR)/dashboard-commands.Po
+ -rm -f ./$(DEPDIR)/data-commands.Po
+ -rm -f ./$(DEPDIR)/data-editor-commands.Po
+ -rm -f ./$(DEPDIR)/debug-actions.Po
+ -rm -f ./$(DEPDIR)/debug-commands.Po
+ -rm -f ./$(DEPDIR)/dialogs-actions.Po
+ -rm -f ./$(DEPDIR)/dialogs-commands.Po
+ -rm -f ./$(DEPDIR)/dock-actions.Po
+ -rm -f ./$(DEPDIR)/dock-commands.Po
+ -rm -f ./$(DEPDIR)/dockable-actions.Po
+ -rm -f ./$(DEPDIR)/dockable-commands.Po
+ -rm -f ./$(DEPDIR)/documents-actions.Po
+ -rm -f ./$(DEPDIR)/documents-commands.Po
+ -rm -f ./$(DEPDIR)/drawable-actions.Po
+ -rm -f ./$(DEPDIR)/drawable-commands.Po
+ -rm -f ./$(DEPDIR)/dynamics-actions.Po
+ -rm -f ./$(DEPDIR)/dynamics-editor-actions.Po
+ -rm -f ./$(DEPDIR)/edit-actions.Po
+ -rm -f ./$(DEPDIR)/edit-commands.Po
+ -rm -f ./$(DEPDIR)/error-console-actions.Po
+ -rm -f ./$(DEPDIR)/error-console-commands.Po
+ -rm -f ./$(DEPDIR)/file-actions.Po
+ -rm -f ./$(DEPDIR)/file-commands.Po
+ -rm -f ./$(DEPDIR)/filters-actions.Po
+ -rm -f ./$(DEPDIR)/filters-commands.Po
+ -rm -f ./$(DEPDIR)/fonts-actions.Po
+ -rm -f ./$(DEPDIR)/gimpgeglprocedure.Po
+ -rm -f ./$(DEPDIR)/gradient-editor-actions.Po
+ -rm -f ./$(DEPDIR)/gradient-editor-commands.Po
+ -rm -f ./$(DEPDIR)/gradients-actions.Po
+ -rm -f ./$(DEPDIR)/gradients-commands.Po
+ -rm -f ./$(DEPDIR)/help-actions.Po
+ -rm -f ./$(DEPDIR)/help-commands.Po
+ -rm -f ./$(DEPDIR)/image-actions.Po
+ -rm -f ./$(DEPDIR)/image-commands.Po
+ -rm -f ./$(DEPDIR)/images-actions.Po
+ -rm -f ./$(DEPDIR)/images-commands.Po
+ -rm -f ./$(DEPDIR)/items-actions.Po
+ -rm -f ./$(DEPDIR)/items-commands.Po
+ -rm -f ./$(DEPDIR)/layers-actions.Po
+ -rm -f ./$(DEPDIR)/layers-commands.Po
+ -rm -f ./$(DEPDIR)/mypaint-brushes-actions.Po
+ -rm -f ./$(DEPDIR)/palette-editor-actions.Po
+ -rm -f ./$(DEPDIR)/palette-editor-commands.Po
+ -rm -f ./$(DEPDIR)/palettes-actions.Po
+ -rm -f ./$(DEPDIR)/palettes-commands.Po
+ -rm -f ./$(DEPDIR)/patterns-actions.Po
+ -rm -f ./$(DEPDIR)/plug-in-actions.Po
+ -rm -f ./$(DEPDIR)/plug-in-commands.Po
+ -rm -f ./$(DEPDIR)/procedure-commands.Po
+ -rm -f ./$(DEPDIR)/quick-mask-actions.Po
+ -rm -f ./$(DEPDIR)/quick-mask-commands.Po
+ -rm -f ./$(DEPDIR)/sample-points-actions.Po
+ -rm -f ./$(DEPDIR)/sample-points-commands.Po
+ -rm -f ./$(DEPDIR)/select-actions.Po
+ -rm -f ./$(DEPDIR)/select-commands.Po
+ -rm -f ./$(DEPDIR)/templates-actions.Po
+ -rm -f ./$(DEPDIR)/templates-commands.Po
+ -rm -f ./$(DEPDIR)/text-editor-actions.Po
+ -rm -f ./$(DEPDIR)/text-editor-commands.Po
+ -rm -f ./$(DEPDIR)/text-tool-actions.Po
+ -rm -f ./$(DEPDIR)/text-tool-commands.Po
+ -rm -f ./$(DEPDIR)/tool-options-actions.Po
+ -rm -f ./$(DEPDIR)/tool-options-commands.Po
+ -rm -f ./$(DEPDIR)/tool-preset-editor-actions.Po
+ -rm -f ./$(DEPDIR)/tool-preset-editor-commands.Po
+ -rm -f ./$(DEPDIR)/tool-presets-actions.Po
+ -rm -f ./$(DEPDIR)/tool-presets-commands.Po
+ -rm -f ./$(DEPDIR)/tools-actions.Po
+ -rm -f ./$(DEPDIR)/tools-commands.Po
+ -rm -f ./$(DEPDIR)/vectors-actions.Po
+ -rm -f ./$(DEPDIR)/vectors-commands.Po
+ -rm -f ./$(DEPDIR)/view-actions.Po
+ -rm -f ./$(DEPDIR)/view-commands.Po
+ -rm -f ./$(DEPDIR)/window-actions.Po
+ -rm -f ./$(DEPDIR)/window-commands.Po
+ -rm -f ./$(DEPDIR)/windows-actions.Po
+ -rm -f ./$(DEPDIR)/windows-commands.Po
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-noinstLIBRARIES \
+ cscopelist-am ctags ctags-am distclean distclean-compile \
+ distclean-generic distclean-libtool distclean-tags distdir dvi \
+ dvi-am html html-am info info-am install install-am \
+ install-data install-data-am install-dvi install-dvi-am \
+ install-exec install-exec-am install-html install-html-am \
+ install-info install-info-am install-man install-pdf \
+ install-pdf-am install-ps install-ps-am install-strip \
+ installcheck installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ tags tags-am uninstall uninstall-am
+
+.PRECIOUS: Makefile
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/app/actions/actions-types.h b/app/actions/actions-types.h
new file mode 100644
index 0000000..383aada
--- /dev/null
+++ b/app/actions/actions-types.h
@@ -0,0 +1,54 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __ACTIONS_TYPES_H__
+#define __ACTIONS_TYPES_H__
+
+
+#include "dialogs/dialogs-types.h"
+#include "tools/tools-types.h"
+
+
+typedef enum
+{
+ GIMP_ACTION_SELECT_SET = 0,
+ GIMP_ACTION_SELECT_SET_TO_DEFAULT = -1,
+ GIMP_ACTION_SELECT_FIRST = -2,
+ GIMP_ACTION_SELECT_LAST = -3,
+ GIMP_ACTION_SELECT_SMALL_PREVIOUS = -4,
+ GIMP_ACTION_SELECT_SMALL_NEXT = -5,
+ GIMP_ACTION_SELECT_PREVIOUS = -6,
+ GIMP_ACTION_SELECT_NEXT = -7,
+ GIMP_ACTION_SELECT_SKIP_PREVIOUS = -8,
+ GIMP_ACTION_SELECT_SKIP_NEXT = -9,
+ GIMP_ACTION_SELECT_PERCENT_PREVIOUS = -10,
+ GIMP_ACTION_SELECT_PERCENT_NEXT = -11
+} GimpActionSelectType;
+
+typedef enum
+{
+ GIMP_SAVE_MODE_SAVE,
+ GIMP_SAVE_MODE_SAVE_AS,
+ GIMP_SAVE_MODE_SAVE_A_COPY,
+ GIMP_SAVE_MODE_SAVE_AND_CLOSE,
+ GIMP_SAVE_MODE_EXPORT,
+ GIMP_SAVE_MODE_EXPORT_AS,
+ GIMP_SAVE_MODE_OVERWRITE
+} GimpSaveMode;
+
+
+#endif /* __ACTIONS_TYPES_H__ */
diff --git a/app/actions/actions.c b/app/actions/actions.c
new file mode 100644
index 0000000..cf8d6dc
--- /dev/null
+++ b/app/actions/actions.c
@@ -0,0 +1,737 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "actions-types.h"
+
+#include "core/gimp.h"
+#include "core/gimpcontainer.h"
+#include "core/gimpcontext.h"
+#include "core/gimpimage.h"
+#include "core/gimptooloptions.h"
+#include "core/gimptoolinfo.h"
+
+#include "widgets/gimpactionfactory.h"
+#include "widgets/gimpactiongroup.h"
+#include "widgets/gimpcontainereditor.h"
+#include "widgets/gimpcontainerview.h"
+#include "widgets/gimpdock.h"
+#include "widgets/gimpdockable.h"
+#include "widgets/gimpdockwindow.h"
+#include "widgets/gimpimageeditor.h"
+#include "widgets/gimpitemtreeview.h"
+
+#include "display/gimpdisplay.h"
+#include "display/gimpdisplayshell.h"
+#include "display/gimpimagewindow.h"
+#include "display/gimpnavigationeditor.h"
+#include "display/gimpstatusbar.h"
+
+#include "dialogs/dialogs.h"
+
+#include "actions.h"
+#include "brush-editor-actions.h"
+#include "brushes-actions.h"
+#include "buffers-actions.h"
+#include "channels-actions.h"
+#include "colormap-actions.h"
+#include "context-actions.h"
+#include "cursor-info-actions.h"
+#include "dashboard-actions.h"
+#include "debug-actions.h"
+#include "dialogs-actions.h"
+#include "dock-actions.h"
+#include "dockable-actions.h"
+#include "documents-actions.h"
+#include "drawable-actions.h"
+#include "dynamics-actions.h"
+#include "dynamics-editor-actions.h"
+#include "edit-actions.h"
+#include "error-console-actions.h"
+#include "file-actions.h"
+#include "filters-actions.h"
+#include "fonts-actions.h"
+#include "gradient-editor-actions.h"
+#include "gradients-actions.h"
+#include "help-actions.h"
+#include "image-actions.h"
+#include "images-actions.h"
+#include "layers-actions.h"
+#include "mypaint-brushes-actions.h"
+#include "palette-editor-actions.h"
+#include "palettes-actions.h"
+#include "patterns-actions.h"
+#include "plug-in-actions.h"
+#include "quick-mask-actions.h"
+#include "sample-points-actions.h"
+#include "select-actions.h"
+#include "templates-actions.h"
+#include "text-editor-actions.h"
+#include "text-tool-actions.h"
+#include "tool-options-actions.h"
+#include "tool-presets-actions.h"
+#include "tool-preset-editor-actions.h"
+#include "tools-actions.h"
+#include "vectors-actions.h"
+#include "view-actions.h"
+#include "windows-actions.h"
+
+#include "gimp-intl.h"
+
+
+/* global variables */
+
+GimpActionFactory *global_action_factory = NULL;
+
+
+/* private variables */
+
+static const GimpActionFactoryEntry action_groups[] =
+{
+ { "brush-editor", N_("Brush Editor"), GIMP_ICON_BRUSH,
+ brush_editor_actions_setup,
+ brush_editor_actions_update },
+ { "brushes", N_("Brushes"), GIMP_ICON_BRUSH,
+ brushes_actions_setup,
+ brushes_actions_update },
+ { "buffers", N_("Buffers"), GIMP_ICON_BUFFER,
+ buffers_actions_setup,
+ buffers_actions_update },
+ { "channels", N_("Channels"), GIMP_ICON_CHANNEL,
+ channels_actions_setup,
+ channels_actions_update },
+ { "colormap", N_("Colormap"), GIMP_ICON_COLORMAP,
+ colormap_actions_setup,
+ colormap_actions_update },
+ { "context", N_("Context"), GIMP_ICON_DIALOG_TOOL_OPTIONS /* well... */,
+ context_actions_setup,
+ context_actions_update },
+ { "cursor-info", N_("Pointer Information"), NULL,
+ cursor_info_actions_setup,
+ cursor_info_actions_update },
+ { "dashboard", N_("Dashboard"), GIMP_ICON_DIALOG_DASHBOARD,
+ dashboard_actions_setup,
+ dashboard_actions_update },
+ { "debug", N_("Debug"), NULL,
+ debug_actions_setup,
+ debug_actions_update },
+ { "dialogs", N_("Dialogs"), NULL,
+ dialogs_actions_setup,
+ dialogs_actions_update },
+ { "dock", N_("Dock"), NULL,
+ dock_actions_setup,
+ dock_actions_update },
+ { "dockable", N_("Dockable"), NULL,
+ dockable_actions_setup,
+ dockable_actions_update },
+ { "documents", N_("Document History"), NULL,
+ documents_actions_setup,
+ documents_actions_update },
+ { "drawable", N_("Drawable"), GIMP_ICON_LAYER,
+ drawable_actions_setup,
+ drawable_actions_update },
+ { "dynamics", N_("Paint Dynamics"), GIMP_ICON_DYNAMICS,
+ dynamics_actions_setup,
+ dynamics_actions_update },
+ { "dynamics-editor", N_("Paint Dynamics Editor"), GIMP_ICON_DYNAMICS,
+ dynamics_editor_actions_setup,
+ dynamics_editor_actions_update },
+ { "edit", N_("Edit"), GIMP_ICON_EDIT,
+ edit_actions_setup,
+ edit_actions_update },
+ { "error-console", N_("Error Console"), GIMP_ICON_DIALOG_WARNING,
+ error_console_actions_setup,
+ error_console_actions_update },
+ { "file", N_("File"), "text-x-generic",
+ file_actions_setup,
+ file_actions_update },
+ { "filters", N_("Filters"), GIMP_ICON_GEGL,
+ filters_actions_setup,
+ filters_actions_update },
+ { "fonts", N_("Fonts"), GIMP_ICON_FONT,
+ fonts_actions_setup,
+ fonts_actions_update },
+ { "gradient-editor", N_("Gradient Editor"), GIMP_ICON_GRADIENT,
+ gradient_editor_actions_setup,
+ gradient_editor_actions_update },
+ { "gradients", N_("Gradients"), GIMP_ICON_GRADIENT,
+ gradients_actions_setup,
+ gradients_actions_update },
+ { "tool-presets", N_("Tool Presets"), GIMP_ICON_TOOL_PRESET,
+ tool_presets_actions_setup,
+ tool_presets_actions_update },
+ { "tool-preset-editor", N_("Tool Preset Editor"), GIMP_ICON_TOOL_PRESET,
+ tool_preset_editor_actions_setup,
+ tool_preset_editor_actions_update },
+ { "help", N_("Help"), "help-browser",
+ help_actions_setup,
+ help_actions_update },
+ { "image", N_("Image"), GIMP_ICON_IMAGE,
+ image_actions_setup,
+ image_actions_update },
+ { "images", N_("Images"), GIMP_ICON_IMAGE,
+ images_actions_setup,
+ images_actions_update },
+ { "layers", N_("Layers"), GIMP_ICON_LAYER,
+ layers_actions_setup,
+ layers_actions_update },
+ { "mypaint-brushes", N_("MyPaint Brushes"), GIMP_ICON_MYPAINT_BRUSH,
+ mypaint_brushes_actions_setup,
+ mypaint_brushes_actions_update },
+ { "palette-editor", N_("Palette Editor"), GIMP_ICON_PALETTE,
+ palette_editor_actions_setup,
+ palette_editor_actions_update },
+ { "palettes", N_("Palettes"), GIMP_ICON_PALETTE,
+ palettes_actions_setup,
+ palettes_actions_update },
+ { "patterns", N_("Patterns"), GIMP_ICON_PATTERN,
+ patterns_actions_setup,
+ patterns_actions_update },
+ { "plug-in", N_("Plug-ins"), GIMP_ICON_PLUGIN,
+ plug_in_actions_setup,
+ plug_in_actions_update },
+ { "quick-mask", N_("Quick Mask"), GIMP_ICON_QUICK_MASK_ON,
+ quick_mask_actions_setup,
+ quick_mask_actions_update },
+ { "sample-points", N_("Sample Points"), GIMP_ICON_SAMPLE_POINT,
+ sample_points_actions_setup,
+ sample_points_actions_update },
+ { "select", N_("Select"), GIMP_ICON_SELECTION,
+ select_actions_setup,
+ select_actions_update },
+ { "templates", N_("Templates"), GIMP_ICON_TEMPLATE,
+ templates_actions_setup,
+ templates_actions_update },
+ { "text-tool", N_("Text Tool"), GIMP_ICON_EDIT,
+ text_tool_actions_setup,
+ text_tool_actions_update },
+ { "text-editor", N_("Text Editor"), GIMP_ICON_EDIT,
+ text_editor_actions_setup,
+ text_editor_actions_update },
+ { "tool-options", N_("Tool Options"), GIMP_ICON_DIALOG_TOOL_OPTIONS,
+ tool_options_actions_setup,
+ tool_options_actions_update },
+ { "tools", N_("Tools"), GIMP_ICON_DIALOG_TOOLS,
+ tools_actions_setup,
+ tools_actions_update },
+ { "vectors", N_("Paths"), GIMP_ICON_PATH,
+ vectors_actions_setup,
+ vectors_actions_update },
+ { "view", N_("View"), GIMP_ICON_VISIBLE,
+ view_actions_setup,
+ view_actions_update },
+ { "windows", N_("Windows"), NULL,
+ windows_actions_setup,
+ windows_actions_update }
+};
+
+
+/* public functions */
+
+void
+actions_init (Gimp *gimp)
+{
+ gint i;
+
+ g_return_if_fail (GIMP_IS_GIMP (gimp));
+ g_return_if_fail (global_action_factory == NULL);
+
+ global_action_factory = gimp_action_factory_new (gimp);
+
+ for (i = 0; i < G_N_ELEMENTS (action_groups); i++)
+ gimp_action_factory_group_register (global_action_factory,
+ action_groups[i].identifier,
+ gettext (action_groups[i].label),
+ action_groups[i].icon_name,
+ action_groups[i].setup_func,
+ action_groups[i].update_func);
+}
+
+void
+actions_exit (Gimp *gimp)
+{
+ g_return_if_fail (GIMP_IS_GIMP (gimp));
+ g_return_if_fail (global_action_factory != NULL);
+ g_return_if_fail (global_action_factory->gimp == gimp);
+
+ g_clear_object (&global_action_factory);
+}
+
+Gimp *
+action_data_get_gimp (gpointer data)
+{
+ Gimp *result = NULL;
+ static gboolean recursion = FALSE;
+
+ if (! data || recursion)
+ return NULL;
+
+ recursion = TRUE;
+
+ if (GIMP_IS_GIMP (data))
+ result = data;
+
+ if (! result)
+ {
+ GimpDisplay *display = action_data_get_display (data);
+
+ if (display)
+ result = display->gimp;
+ }
+
+ if (! result)
+ {
+ GimpContext *context = action_data_get_context (data);
+
+ if (context)
+ result = context->gimp;
+ }
+
+ recursion = FALSE;
+
+ return result;
+}
+
+GimpContext *
+action_data_get_context (gpointer data)
+{
+ GimpContext *result = NULL;
+ static gboolean recursion = FALSE;
+
+ if (! data || recursion)
+ return NULL;
+
+ recursion = TRUE;
+
+ if (GIMP_IS_DOCK (data))
+ result = gimp_dock_get_context ((GimpDock *) data);
+ else if (GIMP_IS_DOCK_WINDOW (data))
+ result = gimp_dock_window_get_context (((GimpDockWindow *) data));
+ else if (GIMP_IS_CONTAINER_VIEW (data))
+ result = gimp_container_view_get_context ((GimpContainerView *) data);
+ else if (GIMP_IS_CONTAINER_EDITOR (data))
+ result = gimp_container_view_get_context (((GimpContainerEditor *) data)->view);
+ else if (GIMP_IS_IMAGE_EDITOR (data))
+ result = ((GimpImageEditor *) data)->context;
+ else if (GIMP_IS_NAVIGATION_EDITOR (data))
+ result = ((GimpNavigationEditor *) data)->context;
+
+ if (! result)
+ {
+ Gimp *gimp = action_data_get_gimp (data);
+
+ if (gimp)
+ result = gimp_get_user_context (gimp);
+ }
+
+ recursion = FALSE;
+
+ return result;
+}
+
+GimpImage *
+action_data_get_image (gpointer data)
+{
+ GimpImage *result = NULL;
+ static gboolean recursion = FALSE;
+
+ if (! data || recursion)
+ return NULL;
+
+ recursion = TRUE;
+
+ if (GIMP_IS_ITEM_TREE_VIEW (data))
+ result = gimp_item_tree_view_get_image ((GimpItemTreeView *) data);
+ else if (GIMP_IS_IMAGE_EDITOR (data))
+ result = ((GimpImageEditor *) data)->image;
+
+ if (! result)
+ {
+ GimpDisplay *display = action_data_get_display (data);
+
+ if (display)
+ result = gimp_display_get_image (display);
+ }
+
+ if (! result)
+ {
+ GimpContext *context = action_data_get_context (data);
+
+ if (context)
+ result = gimp_context_get_image (context);
+ }
+
+ recursion = FALSE;
+
+ return result;
+}
+
+GimpDisplay *
+action_data_get_display (gpointer data)
+{
+ GimpDisplay *result = NULL;
+ static gboolean recursion = FALSE;
+
+ if (! data || recursion)
+ return NULL;
+
+ recursion = TRUE;
+
+ if (GIMP_IS_DISPLAY (data))
+ result = data;
+ else if (GIMP_IS_IMAGE_WINDOW (data))
+ {
+ GimpDisplayShell *shell = gimp_image_window_get_active_shell (data);
+ result = shell ? shell->display : NULL;
+ }
+
+ if (! result)
+ {
+ GimpContext *context = action_data_get_context (data);
+
+ if (context)
+ result = gimp_context_get_display (context);
+ }
+
+ recursion = FALSE;
+
+ return result;
+}
+
+GimpDisplayShell *
+action_data_get_shell (gpointer data)
+{
+ GimpDisplayShell *result = NULL;
+ static gboolean recursion = FALSE;
+
+ if (! data || recursion)
+ return NULL;
+
+ recursion = TRUE;
+
+ if (! result)
+ {
+ GimpDisplay *display = action_data_get_display (data);
+
+ if (display)
+ result = gimp_display_get_shell (display);
+ }
+
+ recursion = FALSE;
+
+ return result;
+}
+
+GtkWidget *
+action_data_get_widget (gpointer data)
+{
+ GtkWidget *result = NULL;
+ static gboolean recursion = FALSE;
+
+ if (! data || recursion)
+ return NULL;
+
+ recursion = TRUE;
+
+ if (GTK_IS_WIDGET (data))
+ result = data;
+
+ if (! result)
+ {
+ GimpDisplay *display = action_data_get_display (data);
+
+ if (display)
+ result = GTK_WIDGET (gimp_display_get_shell (display));
+ }
+
+ if (! result)
+ result = dialogs_get_toolbox ();
+
+ recursion = FALSE;
+
+ return result;
+}
+
+gint
+action_data_sel_count (gpointer data)
+{
+ if (GIMP_IS_CONTAINER_EDITOR (data))
+ {
+ GimpContainerEditor *editor;
+
+ editor = GIMP_CONTAINER_EDITOR (data);
+ return gimp_container_view_get_selected (editor->view, NULL);
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+gdouble
+action_select_value (GimpActionSelectType select_type,
+ gdouble value,
+ gdouble min,
+ gdouble max,
+ gdouble def,
+ gdouble small_inc,
+ gdouble inc,
+ gdouble skip_inc,
+ gdouble delta_factor,
+ gboolean wrap)
+{
+ switch (select_type)
+ {
+ case GIMP_ACTION_SELECT_SET_TO_DEFAULT:
+ value = def;
+ break;
+
+ case GIMP_ACTION_SELECT_FIRST:
+ value = min;
+ break;
+
+ case GIMP_ACTION_SELECT_LAST:
+ value = max;
+ break;
+
+ case GIMP_ACTION_SELECT_SMALL_PREVIOUS:
+ value -= small_inc;
+ break;
+
+ case GIMP_ACTION_SELECT_SMALL_NEXT:
+ value += small_inc;
+ break;
+
+ case GIMP_ACTION_SELECT_PREVIOUS:
+ value -= inc;
+ break;
+
+ case GIMP_ACTION_SELECT_NEXT:
+ value += inc;
+ break;
+
+ case GIMP_ACTION_SELECT_SKIP_PREVIOUS:
+ value -= skip_inc;
+ break;
+
+ case GIMP_ACTION_SELECT_SKIP_NEXT:
+ value += skip_inc;
+ break;
+
+ case GIMP_ACTION_SELECT_PERCENT_PREVIOUS:
+ g_return_val_if_fail (delta_factor >= 0.0, value);
+ value /= (1.0 + delta_factor);
+ break;
+
+ case GIMP_ACTION_SELECT_PERCENT_NEXT:
+ g_return_val_if_fail (delta_factor >= 0.0, value);
+ value *= (1.0 + delta_factor);
+ break;
+
+ default:
+ if ((gint) select_type >= 0)
+ value = (gdouble) select_type * (max - min) / 1000.0 + min;
+ else
+ g_return_val_if_reached (value);
+ break;
+ }
+
+ if (wrap)
+ {
+ while (value < min)
+ value = max - (min - value);
+
+ while (value > max)
+ value = min + (value - max);
+ }
+ else
+ {
+ value = CLAMP (value, min, max);
+ }
+
+ return value;
+}
+
+void
+action_select_property (GimpActionSelectType select_type,
+ GimpDisplay *display,
+ GObject *object,
+ const gchar *property_name,
+ gdouble small_inc,
+ gdouble inc,
+ gdouble skip_inc,
+ gdouble delta_factor,
+ gboolean wrap)
+{
+ GParamSpec *pspec;
+
+ g_return_if_fail (display == NULL || GIMP_IS_DISPLAY (display));
+ g_return_if_fail (G_IS_OBJECT (object));
+ g_return_if_fail (property_name != NULL);
+
+ pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (object),
+ property_name);
+
+ if (G_IS_PARAM_SPEC_DOUBLE (pspec))
+ {
+ gdouble value;
+
+ g_object_get (object, property_name, &value, NULL);
+
+ value = action_select_value (select_type,
+ value,
+ G_PARAM_SPEC_DOUBLE (pspec)->minimum,
+ G_PARAM_SPEC_DOUBLE (pspec)->maximum,
+ G_PARAM_SPEC_DOUBLE (pspec)->default_value,
+ small_inc, inc, skip_inc, delta_factor, wrap);
+
+ g_object_set (object, property_name, value, NULL);
+
+ if (display)
+ {
+ const gchar *blurb = g_param_spec_get_blurb (pspec);
+
+ if (blurb)
+ {
+ /* value description and new value shown in the status bar */
+ action_message (display, object, _("%s: %.2f"), blurb, value);
+ }
+ }
+ }
+ else if (G_IS_PARAM_SPEC_INT (pspec))
+ {
+ gint value;
+
+ g_object_get (object, property_name, &value, NULL);
+
+ value = action_select_value (select_type,
+ value,
+ G_PARAM_SPEC_INT (pspec)->minimum,
+ G_PARAM_SPEC_INT (pspec)->maximum,
+ G_PARAM_SPEC_INT (pspec)->default_value,
+ small_inc, inc, skip_inc, delta_factor, wrap);
+
+ g_object_set (object, property_name, value, NULL);
+
+ if (display)
+ {
+ const gchar *blurb = g_param_spec_get_blurb (pspec);
+
+ if (blurb)
+ {
+ /* value description and new value shown in the status bar */
+ action_message (display, object, _("%s: %d"), blurb, value);
+ }
+ }
+ }
+ else
+ {
+ g_return_if_reached ();
+ }
+}
+
+GimpObject *
+action_select_object (GimpActionSelectType select_type,
+ GimpContainer *container,
+ GimpObject *current)
+{
+ gint select_index;
+ gint n_children;
+
+ g_return_val_if_fail (GIMP_IS_CONTAINER (container), NULL);
+ g_return_val_if_fail (current == NULL || GIMP_IS_OBJECT (current), NULL);
+
+ if (! current)
+ return NULL;
+
+ n_children = gimp_container_get_n_children (container);
+
+ if (n_children == 0)
+ return NULL;
+
+ switch (select_type)
+ {
+ case GIMP_ACTION_SELECT_FIRST:
+ select_index = 0;
+ break;
+
+ case GIMP_ACTION_SELECT_LAST:
+ select_index = n_children - 1;
+ break;
+
+ case GIMP_ACTION_SELECT_PREVIOUS:
+ select_index = gimp_container_get_child_index (container, current) - 1;
+ break;
+
+ case GIMP_ACTION_SELECT_NEXT:
+ select_index = gimp_container_get_child_index (container, current) + 1;
+ break;
+
+ case GIMP_ACTION_SELECT_SKIP_PREVIOUS:
+ select_index = gimp_container_get_child_index (container, current) - 10;
+ break;
+
+ case GIMP_ACTION_SELECT_SKIP_NEXT:
+ select_index = gimp_container_get_child_index (container, current) + 10;
+ break;
+
+ default:
+ if ((gint) select_type >= 0)
+ select_index = (gint) select_type;
+ else
+ g_return_val_if_reached (current);
+ break;
+ }
+
+ select_index = CLAMP (select_index, 0, n_children - 1);
+
+ return gimp_container_get_child_by_index (container, select_index);
+}
+
+void
+action_message (GimpDisplay *display,
+ GObject *object,
+ const gchar *format,
+ ...)
+{
+ GimpDisplayShell *shell = gimp_display_get_shell (display);
+ GimpStatusbar *statusbar = gimp_display_shell_get_statusbar (shell);
+ const gchar *icon_name = NULL;
+ va_list args;
+
+ if (GIMP_IS_TOOL_OPTIONS (object))
+ {
+ GimpToolInfo *tool_info = GIMP_TOOL_OPTIONS (object)->tool_info;
+
+ icon_name = gimp_viewable_get_icon_name (GIMP_VIEWABLE (tool_info));
+ }
+ else if (GIMP_IS_VIEWABLE (object))
+ {
+ icon_name = gimp_viewable_get_icon_name (GIMP_VIEWABLE (object));
+ }
+
+ va_start (args, format);
+ gimp_statusbar_push_temp_valist (statusbar, GIMP_MESSAGE_INFO,
+ icon_name, format, args);
+ va_end (args);
+}
diff --git a/app/actions/actions.h b/app/actions/actions.h
new file mode 100644
index 0000000..10e1e22
--- /dev/null
+++ b/app/actions/actions.h
@@ -0,0 +1,120 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __ACTIONS_H__
+#define __ACTIONS_H__
+
+
+extern GimpActionFactory *global_action_factory;
+
+
+void actions_init (Gimp *gimp);
+void actions_exit (Gimp *gimp);
+
+Gimp * action_data_get_gimp (gpointer data);
+GimpContext * action_data_get_context (gpointer data);
+GimpImage * action_data_get_image (gpointer data);
+GimpDisplay * action_data_get_display (gpointer data);
+GimpDisplayShell * action_data_get_shell (gpointer data);
+GtkWidget * action_data_get_widget (gpointer data);
+gint action_data_sel_count (gpointer data);
+
+gdouble action_select_value (GimpActionSelectType select_type,
+ gdouble value,
+ gdouble min,
+ gdouble max,
+ gdouble def,
+ gdouble small_inc,
+ gdouble inc,
+ gdouble skip_inc,
+ gdouble delta_factor,
+ gboolean wrap);
+void action_select_property (GimpActionSelectType select_type,
+ GimpDisplay *display,
+ GObject *object,
+ const gchar *property_name,
+ gdouble small_inc,
+ gdouble inc,
+ gdouble skip_inc,
+ gdouble delta_factor,
+ gboolean wrap);
+GimpObject * action_select_object (GimpActionSelectType select_type,
+ GimpContainer *container,
+ GimpObject *current);
+void action_message (GimpDisplay *display,
+ GObject *object,
+ const gchar *format,
+ ...) G_GNUC_PRINTF(3,4);
+
+
+#define return_if_no_gimp(gimp,data) \
+ gimp = action_data_get_gimp (data); \
+ if (! gimp) \
+ return
+
+#define return_if_no_context(context,data) \
+ context = action_data_get_context (data); \
+ if (! context) \
+ return
+
+#define return_if_no_image(image,data) \
+ image = action_data_get_image (data); \
+ if (! image) \
+ return
+
+#define return_if_no_display(display,data) \
+ display = action_data_get_display (data); \
+ if (! display) \
+ return
+
+#define return_if_no_shell(shell,data) \
+ shell = action_data_get_shell (data); \
+ if (! shell) \
+ return
+
+#define return_if_no_widget(widget,data) \
+ widget = action_data_get_widget (data); \
+ if (! widget) \
+ return
+
+
+#define return_if_no_drawable(image,drawable,data) \
+ return_if_no_image (image,data); \
+ drawable = gimp_image_get_active_drawable (image); \
+ if (! drawable) \
+ return
+
+#define return_if_no_layer(image,layer,data) \
+ return_if_no_image (image,data); \
+ layer = gimp_image_get_active_layer (image); \
+ if (! layer) \
+ return
+
+#define return_if_no_channel(image,channel,data) \
+ return_if_no_image (image,data); \
+ channel = gimp_image_get_active_channel (image); \
+ if (! channel) \
+ return
+
+#define return_if_no_vectors(image,vectors,data) \
+ return_if_no_image (image,data); \
+ vectors = gimp_image_get_active_vectors (image); \
+ if (! vectors) \
+ return
+
+
+#endif /* __ACTIONS_H__ */
diff --git a/app/actions/brush-editor-actions.c b/app/actions/brush-editor-actions.c
new file mode 100644
index 0000000..f90de3a
--- /dev/null
+++ b/app/actions/brush-editor-actions.c
@@ -0,0 +1,87 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "actions-types.h"
+
+#include "core/gimp.h"
+#include "core/gimpcontext.h"
+
+#include "widgets/gimpactiongroup.h"
+#include "widgets/gimphelp-ids.h"
+#include "widgets/gimpbrusheditor.h"
+
+#include "brush-editor-actions.h"
+#include "data-editor-commands.h"
+
+#include "gimp-intl.h"
+
+
+static const GimpActionEntry brush_editor_actions[] =
+{
+ { "brush-editor-popup", GIMP_ICON_BRUSH,
+ NC_("brush-editor-action", "Brush Editor Menu"), NULL, NULL, NULL,
+ GIMP_HELP_BRUSH_EDITOR_DIALOG }
+};
+
+static const GimpToggleActionEntry brush_editor_toggle_actions[] =
+{
+ { "brush-editor-edit-active", GIMP_ICON_LINKED,
+ NC_("brush-editor-action", "Edit Active Brush"), NULL, NULL,
+ data_editor_edit_active_cmd_callback,
+ FALSE,
+ GIMP_HELP_BRUSH_EDITOR_EDIT_ACTIVE }
+};
+
+
+void
+brush_editor_actions_setup (GimpActionGroup *group)
+{
+ gimp_action_group_add_actions (group, "brush-editor-action",
+ brush_editor_actions,
+ G_N_ELEMENTS (brush_editor_actions));
+
+ gimp_action_group_add_toggle_actions (group, "brush-editor-action",
+ brush_editor_toggle_actions,
+ G_N_ELEMENTS (brush_editor_toggle_actions));
+}
+
+void
+brush_editor_actions_update (GimpActionGroup *group,
+ gpointer user_data)
+{
+ GimpDataEditor *data_editor = GIMP_DATA_EDITOR (user_data);
+ gboolean edit_active = FALSE;
+
+ edit_active = gimp_data_editor_get_edit_active (data_editor);
+
+#define SET_SENSITIVE(action,condition) \
+ gimp_action_group_set_action_sensitive (group, action, (condition) != 0)
+#define SET_ACTIVE(action,condition) \
+ gimp_action_group_set_action_active (group, action, (condition) != 0)
+
+ SET_ACTIVE ("brush-editor-edit-active", edit_active);
+
+#undef SET_SENSITIVE
+#undef SET_ACTIVE
+}
diff --git a/app/actions/brush-editor-actions.h b/app/actions/brush-editor-actions.h
new file mode 100644
index 0000000..9b4eb6f
--- /dev/null
+++ b/app/actions/brush-editor-actions.h
@@ -0,0 +1,27 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __BRUSH_EDITOR_ACTIONS_H__
+#define __BRUSH_EDITOR_ACTIONS_H__
+
+
+void brush_editor_actions_setup (GimpActionGroup *group);
+void brush_editor_actions_update (GimpActionGroup *group,
+ gpointer data);
+
+
+#endif /* __BRUSH_EDITOR_ACTIONS_H__ */
diff --git a/app/actions/brushes-actions.c b/app/actions/brushes-actions.c
new file mode 100644
index 0000000..87daed6
--- /dev/null
+++ b/app/actions/brushes-actions.c
@@ -0,0 +1,149 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "actions-types.h"
+
+#include "core/gimpbrushgenerated.h"
+#include "core/gimpcontext.h"
+
+#include "widgets/gimpactiongroup.h"
+#include "widgets/gimphelp-ids.h"
+
+#include "actions.h"
+#include "brushes-actions.h"
+#include "data-commands.h"
+
+#include "gimp-intl.h"
+
+
+static const GimpActionEntry brushes_actions[] =
+{
+ { "brushes-popup", GIMP_ICON_BRUSH,
+ NC_("brushes-action", "Brushes Menu"), NULL, NULL, NULL,
+ GIMP_HELP_BRUSH_DIALOG },
+
+ { "brushes-open-as-image", GIMP_ICON_DOCUMENT_OPEN,
+ NC_("brushes-action", "_Open Brush as Image"), NULL,
+ NC_("brushes-action", "Open brush as image"),
+ data_open_as_image_cmd_callback,
+ GIMP_HELP_BRUSH_OPEN_AS_IMAGE },
+
+ { "brushes-new", GIMP_ICON_DOCUMENT_NEW,
+ NC_("brushes-action", "_New Brush"), NULL,
+ NC_("brushes-action", "Create a new brush"),
+ data_new_cmd_callback,
+ GIMP_HELP_BRUSH_NEW },
+
+ { "brushes-duplicate", GIMP_ICON_OBJECT_DUPLICATE,
+ NC_("brushes-action", "D_uplicate Brush"), NULL,
+ NC_("brushes-action", "Duplicate this brush"),
+ data_duplicate_cmd_callback,
+ GIMP_HELP_BRUSH_DUPLICATE },
+
+ { "brushes-copy-location", GIMP_ICON_EDIT_COPY,
+ NC_("brushes-action", "Copy Brush _Location"), NULL,
+ NC_("brushes-action", "Copy brush file location to clipboard"),
+ data_copy_location_cmd_callback,
+ GIMP_HELP_BRUSH_COPY_LOCATION },
+
+ { "brushes-show-in-file-manager", GIMP_ICON_FILE_MANAGER,
+ NC_("brushes-action", "Show in _File Manager"), NULL,
+ NC_("brushes-action", "Show brush file location in the file manager"),
+ data_show_in_file_manager_cmd_callback,
+ GIMP_HELP_BRUSH_SHOW_IN_FILE_MANAGER },
+
+ { "brushes-delete", GIMP_ICON_EDIT_DELETE,
+ NC_("brushes-action", "_Delete Brush"), NULL,
+ NC_("brushes-action", "Delete this brush"),
+ data_delete_cmd_callback,
+ GIMP_HELP_BRUSH_DELETE },
+
+ { "brushes-refresh", GIMP_ICON_VIEW_REFRESH,
+ NC_("brushes-action", "_Refresh Brushes"), NULL,
+ NC_("brushes-action", "Refresh brushes"),
+ data_refresh_cmd_callback,
+ GIMP_HELP_BRUSH_REFRESH }
+};
+
+static const GimpStringActionEntry brushes_edit_actions[] =
+{
+ { "brushes-edit", GIMP_ICON_EDIT,
+ NC_("brushes-action", "_Edit Brush..."), NULL,
+ NC_("brushes-action", "Edit this brush"),
+ "gimp-brush-editor",
+ GIMP_HELP_BRUSH_EDIT }
+};
+
+
+void
+brushes_actions_setup (GimpActionGroup *group)
+{
+ gimp_action_group_add_actions (group, "brushes-action",
+ brushes_actions,
+ G_N_ELEMENTS (brushes_actions));
+
+ gimp_action_group_add_string_actions (group, "brushes-action",
+ brushes_edit_actions,
+ G_N_ELEMENTS (brushes_edit_actions),
+ data_edit_cmd_callback);
+}
+
+void
+brushes_actions_update (GimpActionGroup *group,
+ gpointer user_data)
+{
+ GimpContext *context = action_data_get_context (user_data);
+ GimpBrush *brush = NULL;
+ GimpData *data = NULL;
+ GFile *file = NULL;
+
+ if (context)
+ {
+ brush = gimp_context_get_brush (context);
+
+ if (action_data_sel_count (user_data) > 1)
+ {
+ brush = NULL;
+ }
+
+ if (brush)
+ {
+ data = GIMP_DATA (brush);
+
+ file = gimp_data_get_file (data);
+ }
+ }
+
+#define SET_SENSITIVE(action,condition) \
+ gimp_action_group_set_action_sensitive (group, action, (condition) != 0)
+
+ SET_SENSITIVE ("brushes-edit", brush);
+ SET_SENSITIVE ("brushes-open-as-image", file && ! GIMP_IS_BRUSH_GENERATED (brush));
+ SET_SENSITIVE ("brushes-duplicate", brush && gimp_data_is_duplicatable (data));
+ SET_SENSITIVE ("brushes-copy-location", file);
+ SET_SENSITIVE ("brushes-show-in-file-manager", file);
+ SET_SENSITIVE ("brushes-delete", brush && gimp_data_is_deletable (data));
+
+#undef SET_SENSITIVE
+}
diff --git a/app/actions/brushes-actions.h b/app/actions/brushes-actions.h
new file mode 100644
index 0000000..1d292a2
--- /dev/null
+++ b/app/actions/brushes-actions.h
@@ -0,0 +1,27 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __BRUSHES_ACTIONS_H__
+#define __BRUSHES_ACTIONS_H__
+
+
+void brushes_actions_setup (GimpActionGroup *group);
+void brushes_actions_update (GimpActionGroup *group,
+ gpointer data);
+
+
+#endif /* __BRUSHES_ACTIONS_H__ */
diff --git a/app/actions/buffers-actions.c b/app/actions/buffers-actions.c
new file mode 100644
index 0000000..6fbd2c1
--- /dev/null
+++ b/app/actions/buffers-actions.c
@@ -0,0 +1,136 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "actions-types.h"
+
+#include "core/gimpcontext.h"
+
+#include "widgets/gimpactiongroup.h"
+#include "widgets/gimphelp-ids.h"
+
+#include "actions.h"
+#include "buffers-actions.h"
+#include "buffers-commands.h"
+
+#include "gimp-intl.h"
+
+
+static const GimpActionEntry buffers_actions[] =
+{
+ { "buffers-popup", GIMP_ICON_BUFFER,
+ NC_("buffers-action", "Buffers Menu"), NULL, NULL, NULL,
+ GIMP_HELP_BUFFER_DIALOG },
+
+ { "buffers-paste-as-new-image", GIMP_ICON_EDIT_PASTE_AS_NEW,
+ NC_("buffers-action", "Paste Buffer as _New Image"), NULL,
+ NC_("buffers-action", "Paste the selected buffer as a new image"),
+ buffers_paste_as_new_image_cmd_callback,
+ GIMP_HELP_BUFFER_PASTE_AS_NEW_IMAGE },
+
+ { "buffers-delete", GIMP_ICON_EDIT_DELETE,
+ NC_("buffers-action", "_Delete Buffer"), NULL,
+ NC_("buffers-action", "Delete the selected buffer"),
+ buffers_delete_cmd_callback,
+ GIMP_HELP_BUFFER_DELETE }
+};
+
+static const GimpEnumActionEntry buffers_paste_actions[] =
+{
+ { "buffers-paste", GIMP_ICON_EDIT_PASTE,
+ NC_("buffers-action", "_Paste Buffer"), NULL,
+ NC_("buffers-action", "Paste the selected buffer"),
+ GIMP_PASTE_TYPE_FLOATING, FALSE,
+ GIMP_HELP_BUFFER_PASTE },
+
+ { "buffers-paste-in-place", GIMP_ICON_EDIT_PASTE,
+ NC_("buffers-action", "Paste Buffer In Pl_ace"), NULL,
+ NC_("buffers-action", "Paste the selected buffer at its original position"),
+ GIMP_PASTE_TYPE_FLOATING_IN_PLACE, FALSE,
+ GIMP_HELP_BUFFER_PASTE_IN_PLACE },
+
+ { "buffers-paste-into", GIMP_ICON_EDIT_PASTE_INTO,
+ NC_("buffers-action", "Paste Buffer _Into The Selection"), NULL,
+ NC_("buffers-action", "Paste the selected buffer into the selection"),
+ GIMP_PASTE_TYPE_FLOATING_INTO, FALSE,
+ GIMP_HELP_BUFFER_PASTE_INTO },
+
+ { "buffers-paste-into-in-place", GIMP_ICON_EDIT_PASTE_INTO,
+ NC_("buffers-action", "Paste Buffer Into The Selection In Place"), NULL,
+ NC_("buffers-action",
+ "Paste the selected buffer into the selection at its original position"),
+ GIMP_PASTE_TYPE_FLOATING_INTO_IN_PLACE, FALSE,
+ GIMP_HELP_BUFFER_PASTE_INTO_IN_PLACE },
+
+ { "buffers-paste-as-new-layer", GIMP_ICON_EDIT_PASTE_AS_NEW,
+ NC_("buffers-action", "Paste Buffer as New _Layer"), NULL,
+ NC_("buffers-action", "Paste the selected buffer as a new layer"),
+ GIMP_PASTE_TYPE_NEW_LAYER, FALSE,
+ GIMP_HELP_BUFFER_PASTE_AS_NEW_LAYER },
+
+ { "buffers-paste-as-new-layer-in-place", GIMP_ICON_EDIT_PASTE_AS_NEW,
+ NC_("buffers-action", "Paste Buffer as New Layer in Place"), NULL,
+ NC_("buffers-action",
+ "Paste the selected buffer as a new layer at its original position"),
+ GIMP_PASTE_TYPE_NEW_LAYER_IN_PLACE, FALSE,
+ GIMP_HELP_BUFFER_PASTE_AS_NEW_LAYER_IN_PLACE },
+};
+
+
+void
+buffers_actions_setup (GimpActionGroup *group)
+{
+ gimp_action_group_add_actions (group, "buffers-action",
+ buffers_actions,
+ G_N_ELEMENTS (buffers_actions));
+
+ gimp_action_group_add_enum_actions (group, "buffers-action",
+ buffers_paste_actions,
+ G_N_ELEMENTS (buffers_paste_actions),
+ buffers_paste_cmd_callback);
+}
+
+void
+buffers_actions_update (GimpActionGroup *group,
+ gpointer data)
+{
+ GimpContext *context = action_data_get_context (data);
+ GimpBuffer *buffer = NULL;
+
+ if (context)
+ buffer = gimp_context_get_buffer (context);
+
+#define SET_SENSITIVE(action,condition) \
+ gimp_action_group_set_action_sensitive (group, action, (condition) != 0)
+
+ SET_SENSITIVE ("buffers-paste", buffer);
+ SET_SENSITIVE ("buffers-paste-in-place", buffer);
+ SET_SENSITIVE ("buffers-paste-into", buffer);
+ SET_SENSITIVE ("buffers-paste-into-in-place", buffer);
+ SET_SENSITIVE ("buffers-paste-as-new-layer", buffer);
+ SET_SENSITIVE ("buffers-paste-as-new-layer-in-place", buffer);
+ SET_SENSITIVE ("buffers-paste-as-new-image", buffer);
+ SET_SENSITIVE ("buffers-delete", buffer);
+
+#undef SET_SENSITIVE
+}
diff --git a/app/actions/buffers-actions.h b/app/actions/buffers-actions.h
new file mode 100644
index 0000000..6a02344
--- /dev/null
+++ b/app/actions/buffers-actions.h
@@ -0,0 +1,27 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __BUFFERS_ACTIONS_H__
+#define __BUFFERS_ACTIONS_H__
+
+
+void buffers_actions_setup (GimpActionGroup *group);
+void buffers_actions_update (GimpActionGroup *group,
+ gpointer data);
+
+
+#endif /* __BUFFERS_ACTIONS_H__ */
diff --git a/app/actions/buffers-commands.c b/app/actions/buffers-commands.c
new file mode 100644
index 0000000..d3398df
--- /dev/null
+++ b/app/actions/buffers-commands.c
@@ -0,0 +1,138 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "actions-types.h"
+
+#include "core/gimp.h"
+#include "core/gimp-edit.h"
+#include "core/gimpcontainer.h"
+#include "core/gimpcontext.h"
+#include "core/gimpimage.h"
+
+#include "widgets/gimpcontainereditor.h"
+#include "widgets/gimpcontainerview.h"
+#include "widgets/gimpcontainerview-utils.h"
+
+#include "display/gimpdisplay.h"
+#include "display/gimpdisplayshell.h"
+#include "display/gimpdisplayshell-transform.h"
+
+#include "buffers-commands.h"
+
+#include "gimp-intl.h"
+
+
+/* public functions */
+
+void
+buffers_paste_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpContainerEditor *editor = GIMP_CONTAINER_EDITOR (data);
+ GimpContainer *container;
+ GimpContext *context;
+ GimpBuffer *buffer;
+ GimpPasteType paste_type = (GimpPasteType) g_variant_get_int32 (value);
+
+ container = gimp_container_view_get_container (editor->view);
+ context = gimp_container_view_get_context (editor->view);
+
+ buffer = gimp_context_get_buffer (context);
+
+ if (buffer && gimp_container_have (container, GIMP_OBJECT (buffer)))
+ {
+ GimpDisplay *display = gimp_context_get_display (context);
+ GimpImage *image = NULL;
+ gint x = -1;
+ gint y = -1;
+ gint width = -1;
+ gint height = -1;
+
+ if (display)
+ {
+ GimpDisplayShell *shell = gimp_display_get_shell (display);
+
+ gimp_display_shell_untransform_viewport (
+ shell,
+ ! gimp_display_shell_get_infinite_canvas (shell),
+ &x, &y, &width, &height);
+
+ image = gimp_display_get_image (display);
+ }
+ else
+ {
+ image = gimp_context_get_image (context);
+ }
+
+ if (image)
+ {
+ gimp_edit_paste (image, gimp_image_get_active_drawable (image),
+ GIMP_OBJECT (buffer), paste_type,
+ x, y, width, height);
+
+ gimp_image_flush (image);
+ }
+ }
+}
+
+void
+buffers_paste_as_new_image_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpContainerEditor *editor = GIMP_CONTAINER_EDITOR (data);
+ GimpContainer *container;
+ GimpContext *context;
+ GimpBuffer *buffer;
+
+ container = gimp_container_view_get_container (editor->view);
+ context = gimp_container_view_get_context (editor->view);
+
+ buffer = gimp_context_get_buffer (context);
+
+ if (buffer && gimp_container_have (container, GIMP_OBJECT (buffer)))
+ {
+ GtkWidget *widget = GTK_WIDGET (editor);
+ GimpImage *new_image;
+
+ new_image = gimp_edit_paste_as_new_image (context->gimp,
+ GIMP_OBJECT (buffer));
+ gimp_create_display (context->gimp, new_image,
+ GIMP_UNIT_PIXEL, 1.0,
+ G_OBJECT (gtk_widget_get_screen (widget)),
+ gimp_widget_get_monitor (widget));
+ g_object_unref (new_image);
+ }
+}
+
+void
+buffers_delete_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpContainerEditor *editor = GIMP_CONTAINER_EDITOR (data);
+
+ gimp_container_view_remove_active (editor->view);
+}
diff --git a/app/actions/buffers-commands.h b/app/actions/buffers-commands.h
new file mode 100644
index 0000000..a5e7339
--- /dev/null
+++ b/app/actions/buffers-commands.h
@@ -0,0 +1,33 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __BUFFERS_COMMANDS_H__
+#define __BUFFERS_COMMANDS_H__
+
+
+void buffers_paste_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void buffers_paste_as_new_image_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void buffers_delete_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+
+#endif /* __BUFFERS_COMMANDS_H__ */
diff --git a/app/actions/channels-actions.c b/app/actions/channels-actions.c
new file mode 100644
index 0000000..533e794
--- /dev/null
+++ b/app/actions/channels-actions.c
@@ -0,0 +1,348 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "actions-types.h"
+
+#include "core/gimpimage.h"
+#include "core/gimpitem.h"
+
+#include "widgets/gimpactiongroup.h"
+#include "widgets/gimpcomponenteditor.h"
+#include "widgets/gimphelp-ids.h"
+
+#include "actions.h"
+#include "channels-actions.h"
+#include "channels-commands.h"
+#include "items-actions.h"
+
+#include "gimp-intl.h"
+
+
+static const GimpActionEntry channels_actions[] =
+{
+ { "channels-popup", GIMP_ICON_DIALOG_CHANNELS,
+ NC_("channels-action", "Channels Menu"), NULL, NULL, NULL,
+ GIMP_HELP_CHANNEL_DIALOG },
+
+ { "channels-color-tag-menu", NULL,
+ NC_("channels-action", "Color Tag"), NULL, NULL, NULL,
+ GIMP_HELP_CHANNEL_COLOR_TAG },
+
+ { "channels-edit-attributes", GIMP_ICON_EDIT,
+ NC_("channels-action", "_Edit Channel Attributes..."), NULL,
+ NC_("channels-action", "Edit the channel's name, color and opacity"),
+ channels_edit_attributes_cmd_callback,
+ GIMP_HELP_CHANNEL_EDIT },
+
+ { "channels-new", GIMP_ICON_DOCUMENT_NEW,
+ NC_("channels-action", "_New Channel..."), NULL,
+ NC_("channels-action", "Create a new channel"),
+ channels_new_cmd_callback,
+ GIMP_HELP_CHANNEL_NEW },
+
+ { "channels-new-last-values", GIMP_ICON_DOCUMENT_NEW,
+ NC_("channels-action", "_New Channel"), NULL,
+ NC_("channels-action", "Create a new channel with last used values"),
+ channels_new_last_vals_cmd_callback,
+ GIMP_HELP_CHANNEL_NEW },
+
+ { "channels-duplicate", GIMP_ICON_OBJECT_DUPLICATE,
+ NC_("channels-action", "D_uplicate Channel"), NULL,
+ NC_("channels-action",
+ "Create a duplicate of this channel and add it to the image"),
+ channels_duplicate_cmd_callback,
+ GIMP_HELP_CHANNEL_DUPLICATE },
+
+ { "channels-delete", GIMP_ICON_EDIT_DELETE,
+ NC_("channels-action", "_Delete Channel"), NULL,
+ NC_("channels-action", "Delete this channel"),
+ channels_delete_cmd_callback,
+ GIMP_HELP_CHANNEL_DELETE },
+
+ { "channels-raise", GIMP_ICON_GO_UP,
+ NC_("channels-action", "_Raise Channel"), NULL,
+ NC_("channels-action", "Raise this channel one step in the channel stack"),
+ channels_raise_cmd_callback,
+ GIMP_HELP_CHANNEL_RAISE },
+
+ { "channels-raise-to-top", GIMP_ICON_GO_TOP,
+ NC_("channels-action", "Raise Channel to _Top"), NULL,
+ NC_("channels-action",
+ "Raise this channel to the top of the channel stack"),
+ channels_raise_to_top_cmd_callback,
+ GIMP_HELP_CHANNEL_RAISE_TO_TOP },
+
+ { "channels-lower", GIMP_ICON_GO_DOWN,
+ NC_("channels-action", "_Lower Channel"), NULL,
+ NC_("channels-action", "Lower this channel one step in the channel stack"),
+ channels_lower_cmd_callback,
+ GIMP_HELP_CHANNEL_LOWER },
+
+ { "channels-lower-to-bottom", GIMP_ICON_GO_BOTTOM,
+ NC_("channels-action", "Lower Channel to _Bottom"), NULL,
+ NC_("channels-action",
+ "Lower this channel to the bottom of the channel stack"),
+ channels_lower_to_bottom_cmd_callback,
+ GIMP_HELP_CHANNEL_LOWER_TO_BOTTOM }
+};
+
+static const GimpToggleActionEntry channels_toggle_actions[] =
+{
+ { "channels-visible", GIMP_ICON_VISIBLE,
+ NC_("channels-action", "Toggle Channel _Visibility"), NULL, NULL,
+ channels_visible_cmd_callback,
+ FALSE,
+ GIMP_HELP_CHANNEL_VISIBLE },
+
+ { "channels-linked", GIMP_ICON_LINKED,
+ NC_("channels-action", "Toggle Channel _Linked State"), NULL, NULL,
+ channels_linked_cmd_callback,
+ FALSE,
+ GIMP_HELP_CHANNEL_LINKED },
+
+ { "channels-lock-content", NULL /* GIMP_ICON_LOCK */,
+ NC_("channels-action", "L_ock Pixels of Channel"), NULL, NULL,
+ channels_lock_content_cmd_callback,
+ FALSE,
+ GIMP_HELP_CHANNEL_LOCK_PIXELS },
+
+ { "channels-lock-position", GIMP_ICON_TOOL_MOVE,
+ NC_("channels-action", "L_ock Position of Channel"), NULL, NULL,
+ channels_lock_position_cmd_callback,
+ FALSE,
+ GIMP_HELP_CHANNEL_LOCK_POSITION }
+};
+
+static const GimpEnumActionEntry channels_color_tag_actions[] =
+{
+ { "channels-color-tag-none", GIMP_ICON_EDIT_CLEAR,
+ NC_("channels-action", "None"), NULL,
+ NC_("channels-action", "Channel Color Tag: Clear"),
+ GIMP_COLOR_TAG_NONE, FALSE,
+ GIMP_HELP_CHANNEL_COLOR_TAG },
+
+ { "channels-color-tag-blue", NULL,
+ NC_("channels-action", "Blue"), NULL,
+ NC_("channels-action", "Channel Color Tag: Set to Blue"),
+ GIMP_COLOR_TAG_BLUE, FALSE,
+ GIMP_HELP_CHANNEL_COLOR_TAG },
+
+ { "channels-color-tag-green", NULL,
+ NC_("channels-action", "Green"), NULL,
+ NC_("channels-action", "Channel Color Tag: Set to Green"),
+ GIMP_COLOR_TAG_GREEN, FALSE,
+ GIMP_HELP_CHANNEL_COLOR_TAG },
+
+ { "channels-color-tag-yellow", NULL,
+ NC_("channels-action", "Yellow"), NULL,
+ NC_("channels-action", "Channel Color Tag: Set to Yellow"),
+ GIMP_COLOR_TAG_YELLOW, FALSE,
+ GIMP_HELP_CHANNEL_COLOR_TAG },
+
+ { "channels-color-tag-orange", NULL,
+ NC_("channels-action", "Orange"), NULL,
+ NC_("channels-action", "Channel Color Tag: Set to Orange"),
+ GIMP_COLOR_TAG_ORANGE, FALSE,
+ GIMP_HELP_CHANNEL_COLOR_TAG },
+
+ { "channels-color-tag-brown", NULL,
+ NC_("channels-action", "Brown"), NULL,
+ NC_("channels-action", "Channel Color Tag: Set to Brown"),
+ GIMP_COLOR_TAG_BROWN, FALSE,
+ GIMP_HELP_CHANNEL_COLOR_TAG },
+
+ { "channels-color-tag-red", NULL,
+ NC_("channels-action", "Red"), NULL,
+ NC_("channels-action", "Channel Color Tag: Set to Red"),
+ GIMP_COLOR_TAG_RED, FALSE,
+ GIMP_HELP_CHANNEL_COLOR_TAG },
+
+ { "channels-color-tag-violet", NULL,
+ NC_("channels-action", "Violet"), NULL,
+ NC_("channels-action", "Channel Color Tag: Set to Violet"),
+ GIMP_COLOR_TAG_VIOLET, FALSE,
+ GIMP_HELP_CHANNEL_COLOR_TAG },
+
+ { "channels-color-tag-gray", NULL,
+ NC_("channels-action", "Gray"), NULL,
+ NC_("channels-action", "Channel Color Tag: Set to Gray"),
+ GIMP_COLOR_TAG_GRAY, FALSE,
+ GIMP_HELP_CHANNEL_COLOR_TAG }
+};
+
+static const GimpEnumActionEntry channels_to_selection_actions[] =
+{
+ { "channels-selection-replace", GIMP_ICON_SELECTION_REPLACE,
+ NC_("channels-action", "Channel to Sele_ction"), NULL,
+ NC_("channels-action", "Replace the selection with this channel"),
+ GIMP_CHANNEL_OP_REPLACE, FALSE,
+ GIMP_HELP_CHANNEL_SELECTION_REPLACE },
+
+ { "channels-selection-add", GIMP_ICON_SELECTION_ADD,
+ NC_("channels-action", "_Add to Selection"), NULL,
+ NC_("channels-action", "Add this channel to the current selection"),
+ GIMP_CHANNEL_OP_ADD, FALSE,
+ GIMP_HELP_CHANNEL_SELECTION_ADD },
+
+ { "channels-selection-subtract", GIMP_ICON_SELECTION_SUBTRACT,
+ NC_("channels-action", "_Subtract from Selection"), NULL,
+ NC_("channels-action", "Subtract this channel from the current selection"),
+ GIMP_CHANNEL_OP_SUBTRACT, FALSE,
+ GIMP_HELP_CHANNEL_SELECTION_SUBTRACT },
+
+ { "channels-selection-intersect", GIMP_ICON_SELECTION_INTERSECT,
+ NC_("channels-action", "_Intersect with Selection"), NULL,
+ NC_("channels-action", "Intersect this channel with the current selection"),
+ GIMP_CHANNEL_OP_INTERSECT, FALSE,
+ GIMP_HELP_CHANNEL_SELECTION_INTERSECT }
+};
+
+static const GimpEnumActionEntry channels_select_actions[] =
+{
+ { "channels-select-top", NULL,
+ NC_("channels-action", "Select _Top Channel"), NULL,
+ NC_("channels-action", "Select the topmost channel"),
+ GIMP_ACTION_SELECT_FIRST, FALSE,
+ GIMP_HELP_CHANNEL_TOP },
+
+ { "channels-select-bottom", NULL,
+ NC_("channels-action", "Select _Bottom Channel"), NULL,
+ NC_("channels-action", "Select the bottommost channel"),
+ GIMP_ACTION_SELECT_LAST, FALSE,
+ GIMP_HELP_CHANNEL_BOTTOM },
+
+ { "channels-select-previous", NULL,
+ NC_("channels-action", "Select _Previous Channel"), NULL,
+ NC_("channels-action", "Select the channel above the current channel"),
+ GIMP_ACTION_SELECT_PREVIOUS, FALSE,
+ GIMP_HELP_CHANNEL_PREVIOUS },
+
+ { "channels-select-next", NULL,
+ NC_("channels-action", "Select _Next Channel"), NULL,
+ NC_("channels-action", "Select the channel below the current channel"),
+ GIMP_ACTION_SELECT_NEXT, FALSE,
+ GIMP_HELP_CHANNEL_NEXT }
+};
+
+
+void
+channels_actions_setup (GimpActionGroup *group)
+{
+ gimp_action_group_add_actions (group, "channels-action",
+ channels_actions,
+ G_N_ELEMENTS (channels_actions));
+
+ gimp_action_group_add_toggle_actions (group, "channels-action",
+ channels_toggle_actions,
+ G_N_ELEMENTS (channels_toggle_actions));
+
+ gimp_action_group_add_enum_actions (group, "channels-action",
+ channels_color_tag_actions,
+ G_N_ELEMENTS (channels_color_tag_actions),
+ channels_color_tag_cmd_callback);
+
+ gimp_action_group_add_enum_actions (group, "channels-action",
+ channels_to_selection_actions,
+ G_N_ELEMENTS (channels_to_selection_actions),
+ channels_to_selection_cmd_callback);
+
+ gimp_action_group_add_enum_actions (group, "channels-action",
+ channels_select_actions,
+ G_N_ELEMENTS (channels_select_actions),
+ channels_select_cmd_callback);
+
+ items_actions_setup (group, "channels");
+}
+
+void
+channels_actions_update (GimpActionGroup *group,
+ gpointer data)
+{
+ GimpImage *image = action_data_get_image (data);
+ GimpChannel *channel = NULL;
+ gboolean fs = FALSE;
+ gboolean component = FALSE;
+ GList *next = NULL;
+ GList *prev = NULL;
+
+ if (image)
+ {
+ fs = (gimp_image_get_floating_selection (image) != NULL);
+
+ if (GIMP_IS_COMPONENT_EDITOR (data))
+ {
+ if (GIMP_COMPONENT_EDITOR (data)->clicked_component != -1)
+ component = TRUE;
+ }
+ else
+ {
+ channel = gimp_image_get_active_channel (image);
+
+ if (channel)
+ {
+ GList *channel_list;
+ GList *list;
+
+ channel_list = gimp_item_get_container_iter (GIMP_ITEM (channel));
+
+ list = g_list_find (channel_list, channel);
+
+ if (list)
+ {
+ prev = g_list_previous (list);
+ next = g_list_next (list);
+ }
+ }
+ }
+ }
+
+#define SET_SENSITIVE(action,condition) \
+ gimp_action_group_set_action_sensitive (group, action, (condition) != 0)
+
+ SET_SENSITIVE ("channels-edit-attributes", !fs && channel);
+
+ SET_SENSITIVE ("channels-new", !fs && image);
+ SET_SENSITIVE ("channels-new-last-values", !fs && image);
+ SET_SENSITIVE ("channels-duplicate", !fs && (channel || component));
+ SET_SENSITIVE ("channels-delete", !fs && channel);
+
+ SET_SENSITIVE ("channels-raise", !fs && channel && prev);
+ SET_SENSITIVE ("channels-raise-to-top", !fs && channel && prev);
+ SET_SENSITIVE ("channels-lower", !fs && channel && next);
+ SET_SENSITIVE ("channels-lower-to-bottom", !fs && channel && next);
+
+ SET_SENSITIVE ("channels-selection-replace", !fs && (channel || component));
+ SET_SENSITIVE ("channels-selection-add", !fs && (channel || component));
+ SET_SENSITIVE ("channels-selection-subtract", !fs && (channel || component));
+ SET_SENSITIVE ("channels-selection-intersect", !fs && (channel || component));
+
+ SET_SENSITIVE ("channels-select-top", !fs && channel && prev);
+ SET_SENSITIVE ("channels-select-bottom", !fs && channel && next);
+ SET_SENSITIVE ("channels-select-previous", !fs && channel && prev);
+ SET_SENSITIVE ("channels-select-next", !fs && channel && next);
+
+#undef SET_SENSITIVE
+
+ items_actions_update (group, "channels", GIMP_ITEM (channel));
+}
diff --git a/app/actions/channels-actions.h b/app/actions/channels-actions.h
new file mode 100644
index 0000000..382eae1
--- /dev/null
+++ b/app/actions/channels-actions.h
@@ -0,0 +1,27 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __CHANNELS_ACTIONS_H__
+#define __CHANNELS_ACTIONS_H__
+
+
+void channels_actions_setup (GimpActionGroup *group);
+void channels_actions_update (GimpActionGroup *group,
+ gpointer data);
+
+
+#endif /* __CHANNELS_ACTIONS_H__ */
diff --git a/app/actions/channels-commands.c b/app/actions/channels-commands.c
new file mode 100644
index 0000000..6701242
--- /dev/null
+++ b/app/actions/channels-commands.c
@@ -0,0 +1,567 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <string.h>
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpbase/gimpbase.h"
+#include "libgimpcolor/gimpcolor.h"
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "actions-types.h"
+
+#include "config/gimpdialogconfig.h"
+
+#include "core/gimp.h"
+#include "core/gimpchannel.h"
+#include "core/gimpchannel-select.h"
+#include "core/gimpcontext.h"
+#include "core/gimpdrawable-fill.h"
+#include "core/gimpimage.h"
+#include "core/gimpimage-undo.h"
+
+#include "widgets/gimpaction.h"
+#include "widgets/gimpcolorpanel.h"
+#include "widgets/gimpcomponenteditor.h"
+#include "widgets/gimpdock.h"
+#include "widgets/gimphelp-ids.h"
+
+#include "dialogs/dialogs.h"
+#include "dialogs/channel-options-dialog.h"
+
+#include "actions.h"
+#include "channels-commands.h"
+#include "items-commands.h"
+
+#include "gimp-intl.h"
+
+
+#define RGBA_EPSILON 1e-6
+
+
+/* local function prototypes */
+
+static void channels_new_callback (GtkWidget *dialog,
+ GimpImage *image,
+ GimpChannel *channel,
+ GimpContext *context,
+ const gchar *channel_name,
+ const GimpRGB *channel_color,
+ gboolean save_selection,
+ gboolean channel_visible,
+ gboolean channel_linked,
+ GimpColorTag channel_color_tag,
+ gboolean channel_lock_content,
+ gboolean channel_lock_position,
+ gpointer user_data);
+static void channels_edit_attributes_callback (GtkWidget *dialog,
+ GimpImage *image,
+ GimpChannel *channel,
+ GimpContext *context,
+ const gchar *channel_name,
+ const GimpRGB *channel_color,
+ gboolean save_selection,
+ gboolean channel_visible,
+ gboolean channel_linked,
+ GimpColorTag channel_color_tag,
+ gboolean channel_lock_content,
+ gboolean channel_lock_position,
+ gpointer user_data);
+
+
+/* public functions */
+
+void
+channels_edit_attributes_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpChannel *channel;
+ GtkWidget *widget;
+ GtkWidget *dialog;
+ return_if_no_channel (image, channel, data);
+ return_if_no_widget (widget, data);
+
+#define EDIT_DIALOG_KEY "gimp-channel-edit-attributes-dialog"
+
+ dialog = dialogs_get_dialog (G_OBJECT (channel), EDIT_DIALOG_KEY);
+
+ if (! dialog)
+ {
+ GimpItem *item = GIMP_ITEM (channel);
+
+ dialog = channel_options_dialog_new (image, channel,
+ action_data_get_context (data),
+ widget,
+ _("Channel Attributes"),
+ "gimp-channel-edit",
+ GIMP_ICON_EDIT,
+ _("Edit Channel Attributes"),
+ GIMP_HELP_CHANNEL_EDIT,
+ _("Edit Channel Color"),
+ _("_Fill opacity:"),
+ FALSE,
+ gimp_object_get_name (channel),
+ &channel->color,
+ gimp_item_get_visible (item),
+ gimp_item_get_linked (item),
+ gimp_item_get_color_tag (item),
+ gimp_item_get_lock_content (item),
+ gimp_item_get_lock_position (item),
+ channels_edit_attributes_callback,
+ NULL);
+
+ dialogs_attach_dialog (G_OBJECT (channel), EDIT_DIALOG_KEY, dialog);
+ }
+
+ gtk_window_present (GTK_WINDOW (dialog));
+}
+
+void
+channels_new_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GtkWidget *widget;
+ GtkWidget *dialog;
+ return_if_no_image (image, data);
+ return_if_no_widget (widget, data);
+
+#define NEW_DIALOG_KEY "gimp-channel-new-dialog"
+
+ dialog = dialogs_get_dialog (G_OBJECT (image), NEW_DIALOG_KEY);
+
+ if (! dialog)
+ {
+ GimpDialogConfig *config = GIMP_DIALOG_CONFIG (image->gimp->config);
+
+ dialog = channel_options_dialog_new (image, NULL,
+ action_data_get_context (data),
+ widget,
+ _("New Channel"),
+ "gimp-channel-new",
+ GIMP_ICON_CHANNEL,
+ _("Create a New Channel"),
+ GIMP_HELP_CHANNEL_NEW,
+ _("New Channel Color"),
+ _("_Fill opacity:"),
+ TRUE,
+ config->channel_new_name,
+ &config->channel_new_color,
+ TRUE,
+ FALSE,
+ GIMP_COLOR_TAG_NONE,
+ FALSE,
+ FALSE,
+ channels_new_callback,
+ NULL);
+
+ dialogs_attach_dialog (G_OBJECT (image), NEW_DIALOG_KEY, dialog);
+ }
+
+ gtk_window_present (GTK_WINDOW (dialog));
+}
+
+void
+channels_new_last_vals_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpChannel *channel;
+ GimpDialogConfig *config;
+ return_if_no_image (image, data);
+
+ config = GIMP_DIALOG_CONFIG (image->gimp->config);
+
+ channel = gimp_channel_new (image,
+ gimp_image_get_width (image),
+ gimp_image_get_height (image),
+ config->channel_new_name,
+ &config->channel_new_color);
+
+ gimp_drawable_fill (GIMP_DRAWABLE (channel),
+ action_data_get_context (data),
+ GIMP_FILL_TRANSPARENT);
+
+ gimp_image_add_channel (image, channel,
+ GIMP_IMAGE_ACTIVE_PARENT, -1, TRUE);
+ gimp_image_flush (image);
+}
+
+void
+channels_raise_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpChannel *channel;
+ return_if_no_channel (image, channel, data);
+
+ gimp_image_raise_item (image, GIMP_ITEM (channel), NULL);
+ gimp_image_flush (image);
+}
+
+void
+channels_raise_to_top_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpChannel *channel;
+ return_if_no_channel (image, channel, data);
+
+ gimp_image_raise_item_to_top (image, GIMP_ITEM (channel));
+ gimp_image_flush (image);
+}
+
+void
+channels_lower_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpChannel *channel;
+ return_if_no_channel (image, channel, data);
+
+ gimp_image_lower_item (image, GIMP_ITEM (channel), NULL);
+ gimp_image_flush (image);
+}
+
+void
+channels_lower_to_bottom_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpChannel *channel;
+ return_if_no_channel (image, channel, data);
+
+ gimp_image_lower_item_to_bottom (image, GIMP_ITEM (channel));
+ gimp_image_flush (image);
+}
+
+void
+channels_duplicate_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpChannel *new_channel;
+ GimpChannel *parent = GIMP_IMAGE_ACTIVE_PARENT;
+
+ if (GIMP_IS_COMPONENT_EDITOR (data))
+ {
+ GimpChannelType component;
+ const gchar *desc;
+ gchar *name;
+ return_if_no_image (image, data);
+
+ component = GIMP_COMPONENT_EDITOR (data)->clicked_component;
+
+ gimp_enum_get_value (GIMP_TYPE_CHANNEL_TYPE, component,
+ NULL, NULL, &desc, NULL);
+
+ name = g_strdup_printf (_("%s Channel Copy"), desc);
+
+ new_channel = gimp_channel_new_from_component (image, component,
+ name, NULL);
+
+ /* copied components are invisible by default so subsequent copies
+ * of components don't affect each other
+ */
+ gimp_item_set_visible (GIMP_ITEM (new_channel), FALSE, FALSE);
+
+ g_free (name);
+ }
+ else
+ {
+ GimpChannel *channel;
+ return_if_no_channel (image, channel, data);
+
+ new_channel =
+ GIMP_CHANNEL (gimp_item_duplicate (GIMP_ITEM (channel),
+ G_TYPE_FROM_INSTANCE (channel)));
+
+ /* use the actual parent here, not GIMP_IMAGE_ACTIVE_PARENT because
+ * the latter would add a duplicated group inside itself instead of
+ * above it
+ */
+ parent = gimp_channel_get_parent (channel);
+ }
+
+ gimp_image_add_channel (image, new_channel, parent, -1, TRUE);
+ gimp_image_flush (image);
+}
+
+void
+channels_delete_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpChannel *channel;
+ return_if_no_channel (image, channel, data);
+
+ gimp_image_remove_channel (image, channel, TRUE, NULL);
+ gimp_image_flush (image);
+}
+
+void
+channels_to_selection_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpChannelOps op;
+ GimpImage *image;
+
+ op = (GimpChannelOps) g_variant_get_int32 (value);
+
+ if (GIMP_IS_COMPONENT_EDITOR (data))
+ {
+ GimpChannelType component;
+ return_if_no_image (image, data);
+
+ component = GIMP_COMPONENT_EDITOR (data)->clicked_component;
+
+ gimp_channel_select_component (gimp_image_get_mask (image), component,
+ op, FALSE, 0.0, 0.0);
+ }
+ else
+ {
+ GimpChannel *channel;
+ return_if_no_channel (image, channel, data);
+
+ gimp_item_to_selection (GIMP_ITEM (channel),
+ op, TRUE, FALSE, 0.0, 0.0);
+ }
+
+ gimp_image_flush (image);
+}
+
+void
+channels_visible_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpChannel *channel;
+ return_if_no_channel (image, channel, data);
+
+ items_visible_cmd_callback (action, value, image, GIMP_ITEM (channel));
+}
+
+void
+channels_linked_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpChannel *channel;
+ return_if_no_channel (image, channel, data);
+
+ items_linked_cmd_callback (action, value, image, GIMP_ITEM (channel));
+}
+
+void
+channels_lock_content_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpChannel *channel;
+ return_if_no_channel (image, channel, data);
+
+ items_lock_content_cmd_callback (action, value, image, GIMP_ITEM (channel));
+}
+
+void
+channels_lock_position_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpChannel *channel;
+ return_if_no_channel (image, channel, data);
+
+ items_lock_position_cmd_callback (action, value, image, GIMP_ITEM (channel));
+}
+
+void
+channels_color_tag_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpChannel *channel;
+ GimpColorTag color_tag;
+ return_if_no_channel (image, channel, data);
+
+ color_tag = (GimpColorTag) g_variant_get_int32 (value);
+
+ items_color_tag_cmd_callback (action, image, GIMP_ITEM (channel),
+ color_tag);
+}
+
+void
+channels_select_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpChannel *channel;
+ GimpChannel *channel2;
+ GimpContainer *container;
+ GimpActionSelectType select_type;
+ return_if_no_channel (image, channel, data);
+
+ select_type = (GimpActionSelectType) g_variant_get_int32 (value);
+
+ container = gimp_image_get_channels (image);
+ channel2 = (GimpChannel *) action_select_object (select_type, container,
+ (GimpObject *) channel);
+
+ if (channel2 && channel2 != channel)
+ {
+ gimp_image_set_active_channel (image, channel2);
+ gimp_image_flush (image);
+ }
+}
+
+/* private functions */
+
+static void
+channels_new_callback (GtkWidget *dialog,
+ GimpImage *image,
+ GimpChannel *channel,
+ GimpContext *context,
+ const gchar *channel_name,
+ const GimpRGB *channel_color,
+ gboolean save_selection,
+ gboolean channel_visible,
+ gboolean channel_linked,
+ GimpColorTag channel_color_tag,
+ gboolean channel_lock_content,
+ gboolean channel_lock_position,
+ gpointer user_data)
+{
+ GimpDialogConfig *config = GIMP_DIALOG_CONFIG (image->gimp->config);
+
+ g_object_set (config,
+ "channel-new-name", channel_name,
+ "channel-new-color", channel_color,
+ NULL);
+
+ if (save_selection)
+ {
+ GimpChannel *selection = gimp_image_get_mask (image);
+
+ channel = GIMP_CHANNEL (gimp_item_duplicate (GIMP_ITEM (selection),
+ GIMP_TYPE_CHANNEL));
+
+ gimp_object_set_name (GIMP_OBJECT (channel),
+ config->channel_new_name);
+ gimp_channel_set_color (channel, &config->channel_new_color, FALSE);
+ }
+ else
+ {
+ channel = gimp_channel_new (image,
+ gimp_image_get_width (image),
+ gimp_image_get_height (image),
+ config->channel_new_name,
+ &config->channel_new_color);
+
+ gimp_drawable_fill (GIMP_DRAWABLE (channel), context,
+ GIMP_FILL_TRANSPARENT);
+ }
+
+ gimp_item_set_visible (GIMP_ITEM (channel), channel_visible, FALSE);
+ gimp_item_set_linked (GIMP_ITEM (channel), channel_linked, FALSE);
+ gimp_item_set_color_tag (GIMP_ITEM (channel), channel_color_tag, FALSE);
+ gimp_item_set_lock_content (GIMP_ITEM (channel), channel_lock_content, FALSE);
+ gimp_item_set_lock_position (GIMP_ITEM (channel), channel_lock_position, FALSE);
+
+ gimp_image_add_channel (image, channel,
+ GIMP_IMAGE_ACTIVE_PARENT, -1, TRUE);
+ gimp_image_flush (image);
+
+ gtk_widget_destroy (dialog);
+}
+
+static void
+channels_edit_attributes_callback (GtkWidget *dialog,
+ GimpImage *image,
+ GimpChannel *channel,
+ GimpContext *context,
+ const gchar *channel_name,
+ const GimpRGB *channel_color,
+ gboolean save_selection,
+ gboolean channel_visible,
+ gboolean channel_linked,
+ GimpColorTag channel_color_tag,
+ gboolean channel_lock_content,
+ gboolean channel_lock_position,
+ gpointer user_data)
+{
+ GimpItem *item = GIMP_ITEM (channel);
+
+ if (strcmp (channel_name, gimp_object_get_name (channel)) ||
+ gimp_rgba_distance (channel_color, &channel->color) > RGBA_EPSILON ||
+ channel_visible != gimp_item_get_visible (item) ||
+ channel_linked != gimp_item_get_linked (item) ||
+ channel_color_tag != gimp_item_get_color_tag (item) ||
+ channel_lock_content != gimp_item_get_lock_content (item) ||
+ channel_lock_position != gimp_item_get_lock_position (item))
+ {
+ gimp_image_undo_group_start (image,
+ GIMP_UNDO_GROUP_ITEM_PROPERTIES,
+ _("Channel Attributes"));
+
+ if (strcmp (channel_name, gimp_object_get_name (channel)))
+ gimp_item_rename (GIMP_ITEM (channel), channel_name, NULL);
+
+ if (gimp_rgba_distance (channel_color, &channel->color) > RGBA_EPSILON)
+ gimp_channel_set_color (channel, channel_color, TRUE);
+
+ if (channel_visible != gimp_item_get_visible (item))
+ gimp_item_set_visible (item, channel_visible, TRUE);
+
+ if (channel_linked != gimp_item_get_linked (item))
+ gimp_item_set_linked (item, channel_linked, TRUE);
+
+ if (channel_color_tag != gimp_item_get_color_tag (item))
+ gimp_item_set_color_tag (item, channel_color_tag, TRUE);
+
+ if (channel_lock_content != gimp_item_get_lock_content (item))
+ gimp_item_set_lock_content (item, channel_lock_content, TRUE);
+
+ if (channel_lock_position != gimp_item_get_lock_position (item))
+ gimp_item_set_lock_position (item, channel_lock_position, TRUE);
+
+ gimp_image_undo_group_end (image);
+
+ gimp_image_flush (image);
+ }
+
+ gtk_widget_destroy (dialog);
+}
diff --git a/app/actions/channels-commands.h b/app/actions/channels-commands.h
new file mode 100644
index 0000000..6dd7d79
--- /dev/null
+++ b/app/actions/channels-commands.h
@@ -0,0 +1,77 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __CHANNELS_COMMANDS_H__
+#define __CHANNELS_COMMANDS_H__
+
+
+void channels_edit_attributes_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void channels_new_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void channels_new_last_vals_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+void channels_raise_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void channels_raise_to_top_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void channels_lower_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void channels_lower_to_bottom_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+void channels_duplicate_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void channels_delete_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void channels_to_selection_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+void channels_visible_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void channels_linked_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void channels_lock_content_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void channels_lock_position_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+void channels_color_tag_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+void channels_select_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+
+#endif /* __CHANNELS_COMMANDS_H__ */
diff --git a/app/actions/colormap-actions.c b/app/actions/colormap-actions.c
new file mode 100644
index 0000000..1c5d59f
--- /dev/null
+++ b/app/actions/colormap-actions.c
@@ -0,0 +1,173 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "actions-types.h"
+
+#include "core/gimpcontext.h"
+#include "core/gimpdrawable.h"
+#include "core/gimpimage.h"
+#include "core/gimpimage-colormap.h"
+
+#include "widgets/gimpactiongroup.h"
+#include "widgets/gimphelp-ids.h"
+
+#include "actions.h"
+#include "colormap-actions.h"
+#include "colormap-commands.h"
+
+#include "gimp-intl.h"
+
+
+static const GimpActionEntry colormap_actions[] =
+{
+ { "colormap-popup", GIMP_ICON_COLORMAP,
+ NC_("colormap-action", "Colormap Menu"), NULL, NULL, NULL,
+ GIMP_HELP_INDEXED_PALETTE_DIALOG },
+
+ { "colormap-edit-color", GIMP_ICON_EDIT,
+ NC_("colormap-action", "_Edit Color..."), NULL,
+ NC_("colormap-action", "Edit this color"),
+ colormap_edit_color_cmd_callback,
+ GIMP_HELP_INDEXED_PALETTE_EDIT }
+};
+
+static const GimpEnumActionEntry colormap_add_color_actions[] =
+{
+ { "colormap-add-color-from-fg", GIMP_ICON_LIST_ADD,
+ NC_("colormap-action", "_Add Color from FG"), "",
+ NC_("colormap-action", "Add current foreground color"),
+ FALSE, FALSE,
+ GIMP_HELP_INDEXED_PALETTE_ADD },
+
+ { "colormap-add-color-from-bg", GIMP_ICON_LIST_ADD,
+ NC_("colormap-action", "_Add Color from BG"), "",
+ NC_("colormap-action", "Add current background color"),
+ TRUE, FALSE,
+ GIMP_HELP_INDEXED_PALETTE_ADD }
+};
+
+static const GimpEnumActionEntry colormap_to_selection_actions[] =
+{
+ { "colormap-selection-replace", GIMP_ICON_SELECTION_REPLACE,
+ NC_("colormap-action", "_Select this Color"), NULL,
+ NC_("colormap-action", "Select all pixels with this color"),
+ GIMP_CHANNEL_OP_REPLACE, FALSE,
+ GIMP_HELP_INDEXED_PALETTE_SELECTION_REPLACE },
+
+ { "colormap-selection-add", GIMP_ICON_SELECTION_ADD,
+ NC_("colormap-action", "_Add to Selection"), NULL,
+ NC_("colormap-action", "Add all pixels with this color to the current selection"),
+ GIMP_CHANNEL_OP_ADD, FALSE,
+ GIMP_HELP_INDEXED_PALETTE_SELECTION_ADD },
+
+ { "colormap-selection-subtract", GIMP_ICON_SELECTION_SUBTRACT,
+ NC_("colormap-action", "_Subtract from Selection"), NULL,
+ NC_("colormap-action", "Subtract all pixels with this color from the current selection"),
+ GIMP_CHANNEL_OP_SUBTRACT, FALSE,
+ GIMP_HELP_INDEXED_PALETTE_SELECTION_SUBTRACT },
+
+ { "colormap-selection-intersect", GIMP_ICON_SELECTION_INTERSECT,
+ NC_("colormap-action", "_Intersect with Selection"), NULL,
+ NC_("colormap-action", "Intersect all pixels with this color with the current selection"),
+ GIMP_CHANNEL_OP_INTERSECT, FALSE,
+ GIMP_HELP_INDEXED_PALETTE_SELECTION_INTERSECT }
+};
+
+void
+colormap_actions_setup (GimpActionGroup *group)
+{
+ gimp_action_group_add_actions (group, "colormap-action",
+ colormap_actions,
+ G_N_ELEMENTS (colormap_actions));
+
+ gimp_action_group_add_enum_actions (group, "colormap-action",
+ colormap_add_color_actions,
+ G_N_ELEMENTS (colormap_add_color_actions),
+ colormap_add_color_cmd_callback);
+
+ gimp_action_group_add_enum_actions (group, "colormap-action",
+ colormap_to_selection_actions,
+ G_N_ELEMENTS (colormap_to_selection_actions),
+ colormap_to_selection_cmd_callback);
+}
+
+void
+colormap_actions_update (GimpActionGroup *group,
+ gpointer data)
+{
+ GimpImage *image = action_data_get_image (data);
+ GimpContext *context = action_data_get_context (data);
+ gboolean indexed = FALSE;
+ gboolean drawable_indexed = FALSE;
+ gint num_colors = 0;
+ GimpRGB fg;
+ GimpRGB bg;
+
+ if (image)
+ {
+ indexed = (gimp_image_get_base_type (image) == GIMP_INDEXED);
+
+ if (indexed)
+ {
+ GimpDrawable *drawable = gimp_image_get_active_drawable (image);
+
+ num_colors = gimp_image_get_colormap_size (image);
+ drawable_indexed = gimp_drawable_is_indexed (drawable);
+ }
+ }
+
+ if (context)
+ {
+ gimp_context_get_foreground (context, &fg);
+ gimp_context_get_background (context, &bg);
+ }
+
+#define SET_SENSITIVE(action,condition) \
+ gimp_action_group_set_action_sensitive (group, action, (condition) != 0)
+#define SET_COLOR(action,color) \
+ gimp_action_group_set_action_color (group, action, color, FALSE);
+
+ SET_SENSITIVE ("colormap-edit-color",
+ indexed && num_colors > 0);
+
+ SET_SENSITIVE ("colormap-add-color-from-fg",
+ indexed && num_colors < 256);
+ SET_SENSITIVE ("colormap-add-color-from-bg",
+ indexed && num_colors < 256);
+
+ SET_COLOR ("colormap-add-color-from-fg", context ? &fg : NULL);
+ SET_COLOR ("colormap-add-color-from-bg", context ? &bg : NULL);
+
+ SET_SENSITIVE ("colormap-selection-replace",
+ drawable_indexed && num_colors > 0);
+ SET_SENSITIVE ("colormap-selection-add",
+ drawable_indexed && num_colors > 0);
+ SET_SENSITIVE ("colormap-selection-subtract",
+ drawable_indexed && num_colors > 0);
+ SET_SENSITIVE ("colormap-selection-intersect",
+ drawable_indexed && num_colors > 0);
+
+#undef SET_SENSITIVE
+#undef SET_COLOR
+}
diff --git a/app/actions/colormap-actions.h b/app/actions/colormap-actions.h
new file mode 100644
index 0000000..0451632
--- /dev/null
+++ b/app/actions/colormap-actions.h
@@ -0,0 +1,27 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __COLORMAP_ACTIONS_H__
+#define __COLORMAP_ACTIONS_H__
+
+
+void colormap_actions_setup (GimpActionGroup *group);
+void colormap_actions_update (GimpActionGroup *group,
+ gpointer data);
+
+
+#endif /* __COLORMAP_ACTIONS_H__ */
diff --git a/app/actions/colormap-commands.c b/app/actions/colormap-commands.c
new file mode 100644
index 0000000..226197f
--- /dev/null
+++ b/app/actions/colormap-commands.c
@@ -0,0 +1,96 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "actions-types.h"
+
+#include "core/gimpchannel-select.h"
+#include "core/gimpcontext.h"
+#include "core/gimpimage.h"
+#include "core/gimpimage-colormap.h"
+
+#include "widgets/gimpcolormapeditor.h"
+
+#include "actions.h"
+#include "colormap-commands.h"
+
+
+/* public functions */
+
+void
+colormap_edit_color_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpColormapEditor *editor = GIMP_COLORMAP_EDITOR (data);
+
+ gimp_colormap_editor_edit_color (editor);
+}
+
+void
+colormap_add_color_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpContext *context;
+ GimpImage *image;
+ gboolean background;
+ return_if_no_context (context, data);
+ return_if_no_image (image, data);
+
+ background = (gboolean) g_variant_get_int32 (value);
+
+ if (gimp_image_get_colormap_size (image) < 256)
+ {
+ GimpRGB color;
+
+ if (background)
+ gimp_context_get_background (context, &color);
+ else
+ gimp_context_get_foreground (context, &color);
+
+ gimp_image_add_colormap_entry (image, &color);
+ gimp_image_flush (image);
+ }
+}
+
+void
+colormap_to_selection_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpColormapEditor *editor;
+ GimpImage *image;
+ GimpChannelOps op;
+ return_if_no_image (image, data);
+
+ editor = GIMP_COLORMAP_EDITOR (data);
+
+ op = (GimpChannelOps) g_variant_get_int32 (value);
+
+ gimp_channel_select_by_index (gimp_image_get_mask (image),
+ gimp_image_get_active_drawable (image),
+ editor->col_index,
+ op,
+ FALSE, 0.0, 0.0);
+
+ gimp_image_flush (image);
+}
diff --git a/app/actions/colormap-commands.h b/app/actions/colormap-commands.h
new file mode 100644
index 0000000..8aa4e52
--- /dev/null
+++ b/app/actions/colormap-commands.h
@@ -0,0 +1,33 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __COLORMAP_COMMANDS_H__
+#define __COLORMAP_COMMANDS_H__
+
+
+void colormap_edit_color_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void colormap_add_color_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void colormap_to_selection_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+
+#endif /* __COLORMAP_COMMANDS_H__ */
diff --git a/app/actions/context-actions.c b/app/actions/context-actions.c
new file mode 100644
index 0000000..aef16ab
--- /dev/null
+++ b/app/actions/context-actions.c
@@ -0,0 +1,1294 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "actions-types.h"
+
+#include "core/gimp.h"
+#include "core/gimpbrushgenerated.h"
+#include "core/gimpcontext.h"
+#include "core/gimplist.h"
+
+#include "widgets/gimpactiongroup.h"
+#include "widgets/gimphelp-ids.h"
+
+#include "actions.h"
+#include "context-actions.h"
+#include "context-commands.h"
+
+#include "gimp-intl.h"
+
+
+/* local function prototypes */
+
+static const GimpActionEntry context_actions[] =
+{
+ { "context-menu", NULL, NC_("context-action",
+ "_Context") },
+ { "context-colors-menu", GIMP_ICON_COLORS_DEFAULT, NC_("context-action",
+ "_Colors") },
+ { "context-opacity-menu", GIMP_ICON_TRANSPARENCY, NC_("context-action",
+ "_Opacity") },
+ { "context-paint-mode-menu", GIMP_ICON_TOOL_PENCIL, NC_("context-action",
+ "Paint _Mode") },
+ { "context-tool-menu", GIMP_ICON_DIALOG_TOOLS, NC_("context-action",
+ "_Tool") },
+ { "context-brush-menu", GIMP_ICON_BRUSH, NC_("context-action",
+ "_Brush") },
+ { "context-pattern-menu", GIMP_ICON_PATTERN, NC_("context-action",
+ "_Pattern") },
+ { "context-palette-menu", GIMP_ICON_PALETTE, NC_("context-action",
+ "_Palette") },
+ { "context-gradient-menu", GIMP_ICON_GRADIENT, NC_("context-action",
+ "_Gradient") },
+ { "context-font-menu", GIMP_ICON_FONT, NC_("context-action",
+ "_Font") },
+
+ { "context-brush-shape-menu", NULL, NC_("context-action",
+ "_Shape") },
+ { "context-brush-radius-menu", NULL, NC_("context-action",
+ "_Radius") },
+ { "context-brush-spikes-menu", NULL, NC_("context-action",
+ "S_pikes") },
+ { "context-brush-hardness-menu", NULL, NC_("context-action",
+ "_Hardness") },
+ { "context-brush-aspect-menu", NULL, NC_("context-action",
+ "_Aspect Ratio")},
+ { "context-brush-angle-menu", NULL, NC_("context-action",
+ "A_ngle") },
+
+ { "context-colors-default", GIMP_ICON_COLORS_DEFAULT,
+ NC_("context-action", "_Default Colors"), "D",
+ NC_("context-action",
+ "Set foreground color to black, background color to white"),
+ context_colors_default_cmd_callback,
+ GIMP_HELP_TOOLBOX_DEFAULT_COLORS },
+
+ { "context-colors-swap", GIMP_ICON_COLORS_SWAP,
+ NC_("context-action", "S_wap Colors"), "X",
+ NC_("context-action", "Exchange foreground and background colors"),
+ context_colors_swap_cmd_callback,
+ GIMP_HELP_TOOLBOX_SWAP_COLORS }
+};
+
+static GimpEnumActionEntry context_palette_foreground_actions[] =
+{
+ { "context-palette-foreground-set", GIMP_ICON_PALETTE,
+ NC_("context-action", "Foreground: Set Color From Palette"), NULL, NULL,
+ GIMP_ACTION_SELECT_SET, FALSE,
+ NULL },
+ { "context-palette-foreground-first", GIMP_ICON_PALETTE,
+ NC_("context-action", "Foreground: Use First Palette Color"), NULL, NULL,
+ GIMP_ACTION_SELECT_FIRST, FALSE,
+ NULL },
+ { "context-palette-foreground-last", GIMP_ICON_PALETTE,
+ NC_("context-action", "Foreground: Use Last Palette Color"), NULL, NULL,
+ GIMP_ACTION_SELECT_LAST, FALSE,
+ NULL },
+ { "context-palette-foreground-previous", GIMP_ICON_PALETTE,
+ NC_("context-action", "Foreground: Use Previous Palette Color"), NULL, NULL,
+ GIMP_ACTION_SELECT_PREVIOUS, FALSE,
+ NULL },
+ { "context-palette-foreground-next", GIMP_ICON_PALETTE,
+ NC_("context-action", "Foreground: Use Next Palette Color"), NULL, NULL,
+ GIMP_ACTION_SELECT_NEXT, FALSE,
+ NULL },
+ { "context-palette-foreground-previous-skip", GIMP_ICON_PALETTE,
+ NC_("context-action", "Foreground: Skip Back Palette Color"), NULL, NULL,
+ GIMP_ACTION_SELECT_SKIP_PREVIOUS, FALSE,
+ NULL },
+ { "context-palette-foreground-next-skip", GIMP_ICON_PALETTE,
+ NC_("context-action", "Foreground: Skip Forward Palette Color"), NULL, NULL,
+ GIMP_ACTION_SELECT_SKIP_NEXT, FALSE,
+ NULL }
+};
+
+static GimpEnumActionEntry context_palette_background_actions[] =
+{
+ { "context-palette-background-set", GIMP_ICON_PALETTE,
+ NC_("context-action", "Background: Set Color From Palette"), NULL, NULL,
+ GIMP_ACTION_SELECT_SET, FALSE,
+ NULL },
+ { "context-palette-background-first", GIMP_ICON_PALETTE,
+ NC_("context-action", "Background: Use First Palette Color"), NULL, NULL,
+ GIMP_ACTION_SELECT_FIRST, FALSE,
+ NULL },
+ { "context-palette-background-last", GIMP_ICON_PALETTE,
+ NC_("context-action", "Background: Use Last Palette Color"), NULL, NULL,
+ GIMP_ACTION_SELECT_LAST, FALSE,
+ NULL },
+ { "context-palette-background-previous", GIMP_ICON_PALETTE,
+ NC_("context-action", "Background: Use Previous Palette Color"), NULL, NULL,
+ GIMP_ACTION_SELECT_PREVIOUS, FALSE,
+ NULL },
+ { "context-palette-background-next", GIMP_ICON_PALETTE,
+ NC_("context-action", "Background: Use Next Palette Color"), NULL, NULL,
+ GIMP_ACTION_SELECT_NEXT, FALSE,
+ NULL },
+ { "context-palette-background-previous-skip", GIMP_ICON_PALETTE,
+ NC_("context-action", "Background: Skip Back Palette Color"), NULL, NULL,
+ GIMP_ACTION_SELECT_SKIP_PREVIOUS, FALSE,
+ NULL },
+ { "context-palette-background-next-skip", GIMP_ICON_PALETTE,
+ NC_("context-action", "Background: Skip Forward Palette Color"), NULL, NULL,
+ GIMP_ACTION_SELECT_SKIP_NEXT, FALSE,
+ NULL }
+};
+
+static GimpEnumActionEntry context_colormap_foreground_actions[] =
+{
+ { "context-colormap-foreground-set", GIMP_ICON_COLORMAP,
+ NC_("context-action", "Foreground: Set Color From Colormap"), NULL, NULL,
+ GIMP_ACTION_SELECT_SET, FALSE,
+ NULL },
+ { "context-colormap-foreground-first", GIMP_ICON_COLORMAP,
+ NC_("context-action", "Foreground: Use First Color From Colormap"), NULL, NULL,
+ GIMP_ACTION_SELECT_FIRST, FALSE,
+ NULL },
+ { "context-colormap-foreground-last", GIMP_ICON_COLORMAP,
+ NC_("context-action", "Foreground: Use Last Color From Colormap"), NULL, NULL,
+ GIMP_ACTION_SELECT_LAST, FALSE,
+ NULL },
+ { "context-colormap-foreground-previous", GIMP_ICON_COLORMAP,
+ NC_("context-action", "Foreground: Use Previous Color From Colormap"), NULL, NULL,
+ GIMP_ACTION_SELECT_PREVIOUS, FALSE,
+ NULL },
+ { "context-colormap-foreground-next", GIMP_ICON_COLORMAP,
+ NC_("context-action", "Foreground: Use Next Color From Colormap"), NULL, NULL,
+ GIMP_ACTION_SELECT_NEXT, FALSE,
+ NULL },
+ { "context-colormap-foreground-previous-skip", GIMP_ICON_COLORMAP,
+ NC_("context-action", "Foreground: Skip Back Color From Colormap"), NULL, NULL,
+ GIMP_ACTION_SELECT_SKIP_PREVIOUS, FALSE,
+ NULL },
+ { "context-colormap-foreground-next-skip", GIMP_ICON_COLORMAP,
+ NC_("context-action", "Foreground: Skip Forward Color From Colormap"), NULL, NULL,
+ GIMP_ACTION_SELECT_SKIP_NEXT, FALSE,
+ NULL }
+};
+
+static GimpEnumActionEntry context_colormap_background_actions[] =
+{
+ { "context-colormap-background-set", GIMP_ICON_COLORMAP,
+ NC_("context-action", "Background: Set Color From Colormap"), NULL, NULL,
+ GIMP_ACTION_SELECT_SET, FALSE,
+ NULL },
+ { "context-colormap-background-first", GIMP_ICON_COLORMAP,
+ NC_("context-action", "Background: Use First Color From Colormap"), NULL, NULL,
+ GIMP_ACTION_SELECT_FIRST, FALSE,
+ NULL },
+ { "context-colormap-background-last", GIMP_ICON_COLORMAP,
+ NC_("context-action", "Background: Use Last Color From Colormap"), NULL, NULL,
+ GIMP_ACTION_SELECT_LAST, FALSE,
+ NULL },
+ { "context-colormap-background-previous", GIMP_ICON_COLORMAP,
+ NC_("context-action", "Background: Use Previous Color From Colormap"), NULL, NULL,
+ GIMP_ACTION_SELECT_PREVIOUS, FALSE,
+ NULL },
+ { "context-colormap-background-next", GIMP_ICON_COLORMAP,
+ NC_("context-action", "Background: Use Next Color From Colormap"), NULL, NULL,
+ GIMP_ACTION_SELECT_NEXT, FALSE,
+ NULL },
+ { "context-colormap-background-previous-skip", GIMP_ICON_COLORMAP,
+ NC_("context-action", "Background: Skip Back Color From Colormap"), NULL, NULL,
+ GIMP_ACTION_SELECT_SKIP_PREVIOUS, FALSE,
+ NULL },
+ { "context-colormap-background-next-skip", GIMP_ICON_COLORMAP,
+ NC_("context-action", "Background: Skip Forward Color From Colormap"), NULL, NULL,
+ GIMP_ACTION_SELECT_SKIP_NEXT, FALSE,
+ NULL }
+};
+
+static GimpEnumActionEntry context_swatch_foreground_actions[] =
+{
+ { "context-swatch-foreground-set", GIMP_ICON_PALETTE,
+ NC_("context-action", "Foreground: Set Color From Swatch"), NULL, NULL,
+ GIMP_ACTION_SELECT_SET, FALSE,
+ NULL },
+ { "context-swatch-foreground-first", GIMP_ICON_PALETTE,
+ NC_("context-action", "Foreground: Use First Color From Swatch"), NULL, NULL,
+ GIMP_ACTION_SELECT_FIRST, FALSE,
+ NULL },
+ { "context-swatch-foreground-last", GIMP_ICON_PALETTE,
+ NC_("context-action", "Foreground: Use Last Color From Swatch"), NULL, NULL,
+ GIMP_ACTION_SELECT_LAST, FALSE,
+ NULL },
+ { "context-swatch-foreground-previous", GIMP_ICON_PALETTE,
+ NC_("context-action", "Foreground: Use Previous Color From Swatch"), "9", NULL,
+ GIMP_ACTION_SELECT_PREVIOUS, FALSE,
+ NULL },
+ { "context-swatch-foreground-next", GIMP_ICON_PALETTE,
+ NC_("context-action", "Foreground: Use Next Color From Swatch"), "0", NULL,
+ GIMP_ACTION_SELECT_NEXT, FALSE,
+ NULL },
+ { "context-swatch-foreground-previous-skip", GIMP_ICON_PALETTE,
+ NC_("context-action", "Foreground: Skip Back Color From Swatch"), NULL, NULL,
+ GIMP_ACTION_SELECT_SKIP_PREVIOUS, FALSE,
+ NULL },
+ { "context-swatch-foreground-next-skip", GIMP_ICON_PALETTE,
+ NC_("context-action", "Foreground: Skip Forward Color From Swatch"), NULL, NULL,
+ GIMP_ACTION_SELECT_SKIP_NEXT, FALSE,
+ NULL }
+};
+
+static GimpEnumActionEntry context_swatch_background_actions[] =
+{
+ { "context-swatch-background-set", GIMP_ICON_PALETTE,
+ NC_("context-action", "Background: Set Color From Swatch"), NULL, NULL,
+ GIMP_ACTION_SELECT_SET, FALSE,
+ NULL },
+ { "context-swatch-background-first", GIMP_ICON_PALETTE,
+ NC_("context-action", "Background: Use First Color From Swatch"), NULL, NULL,
+ GIMP_ACTION_SELECT_FIRST, FALSE,
+ NULL },
+ { "context-swatch-background-last", GIMP_ICON_PALETTE,
+ NC_("context-action", "Background: Use Last Color From Swatch"), NULL, NULL,
+ GIMP_ACTION_SELECT_LAST, FALSE,
+ NULL },
+ { "context-swatch-background-previous", GIMP_ICON_PALETTE,
+ NC_("context-action", "Background: Use Previous Color From Swatch"), NULL, NULL,
+ GIMP_ACTION_SELECT_PREVIOUS, FALSE,
+ NULL },
+ { "context-swatch-background-next", GIMP_ICON_PALETTE,
+ NC_("context-action", "Background: Use Next Color From Swatch"), NULL, NULL,
+ GIMP_ACTION_SELECT_NEXT, FALSE,
+ NULL },
+ { "context-swatch-background-previous-skip", GIMP_ICON_PALETTE,
+ NC_("context-action", "Background: Skip Color Back From Swatch"), NULL, NULL,
+ GIMP_ACTION_SELECT_SKIP_PREVIOUS, FALSE,
+ NULL },
+ { "context-swatch-background-next-skip", GIMP_ICON_PALETTE,
+ NC_("context-action", "Background: Skip Color Forward From Swatch"), NULL, NULL,
+ GIMP_ACTION_SELECT_SKIP_NEXT, FALSE,
+ NULL }
+};
+
+static const GimpEnumActionEntry context_foreground_red_actions[] =
+{
+ { "context-foreground-red-set", GIMP_ICON_CHANNEL_RED,
+ NC_("context-action", "Foreground Red: Set"), NULL, NULL,
+ GIMP_ACTION_SELECT_SET, TRUE,
+ NULL },
+ { "context-foreground-red-minimum", GIMP_ICON_CHANNEL_RED,
+ NC_("context-action", "Foreground Red: Set to Minimum"), NULL, NULL,
+ GIMP_ACTION_SELECT_FIRST, FALSE,
+ NULL },
+ { "context-foreground-red-maximum", GIMP_ICON_CHANNEL_RED,
+ NC_("context-action", "Foreground Red: Set to Maximum"), NULL, NULL,
+ GIMP_ACTION_SELECT_LAST, FALSE,
+ NULL },
+ { "context-foreground-red-decrease", GIMP_ICON_CHANNEL_RED,
+ NC_("context-action", "Foreground Red: Decrease by 1%"), NULL, NULL,
+ GIMP_ACTION_SELECT_PREVIOUS, FALSE,
+ NULL },
+ { "context-foreground-red-increase", GIMP_ICON_CHANNEL_RED,
+ NC_("context-action", "Foreground Red: Increase by 1%"), NULL, NULL,
+ GIMP_ACTION_SELECT_NEXT, FALSE,
+ NULL },
+ { "context-foreground-red-decrease-skip", GIMP_ICON_CHANNEL_RED,
+ NC_("context-action", "Foreground Red: Decrease by 10%"), NULL, NULL,
+ GIMP_ACTION_SELECT_SKIP_PREVIOUS, FALSE,
+ NULL },
+ { "context-foreground-red-increase-skip", GIMP_ICON_CHANNEL_RED,
+ NC_("context-action", "Foreground Red: Increase by 10%"), NULL, NULL,
+ GIMP_ACTION_SELECT_SKIP_NEXT, FALSE,
+ NULL }
+};
+
+static const GimpEnumActionEntry context_foreground_green_actions[] =
+{
+ { "context-foreground-green-set", GIMP_ICON_CHANNEL_GREEN,
+ NC_("context-action", "Foreground Green: Set"), NULL, NULL,
+ GIMP_ACTION_SELECT_SET, TRUE,
+ NULL },
+ { "context-foreground-green-minimum", GIMP_ICON_CHANNEL_GREEN,
+ NC_("context-action", "Foreground Green: Set to Minimum"), NULL, NULL,
+ GIMP_ACTION_SELECT_FIRST, FALSE,
+ NULL },
+ { "context-foreground-green-maximum", GIMP_ICON_CHANNEL_GREEN,
+ NC_("context-action", "Foreground Green: Set to Maximum"), NULL, NULL,
+ GIMP_ACTION_SELECT_LAST, FALSE,
+ NULL },
+ { "context-foreground-green-decrease", GIMP_ICON_CHANNEL_GREEN,
+ NC_("context-action", "Foreground Green: Decrease by 1%"), NULL, NULL,
+ GIMP_ACTION_SELECT_PREVIOUS, FALSE,
+ NULL },
+ { "context-foreground-green-increase", GIMP_ICON_CHANNEL_GREEN,
+ NC_("context-action", "Foreground Green: Increase by 1%"), NULL, NULL,
+ GIMP_ACTION_SELECT_NEXT, FALSE,
+ NULL },
+ { "context-foreground-green-decrease-skip", GIMP_ICON_CHANNEL_GREEN,
+ NC_("context-action", "Foreground Green: Decrease by 10%"), NULL, NULL,
+ GIMP_ACTION_SELECT_SKIP_PREVIOUS, FALSE,
+ NULL },
+ { "context-foreground-green-increase-skip", GIMP_ICON_CHANNEL_GREEN,
+ NC_("context-action", "Foreground Green: Increase by 10%"), NULL, NULL,
+ GIMP_ACTION_SELECT_SKIP_NEXT, FALSE,
+ NULL }
+};
+
+static const GimpEnumActionEntry context_foreground_blue_actions[] =
+{
+ { "context-foreground-blue-set", GIMP_ICON_CHANNEL_BLUE,
+ NC_("context-action", "Foreground Blue: Set"), NULL, NULL,
+ GIMP_ACTION_SELECT_SET, TRUE,
+ NULL },
+ { "context-foreground-blue-minimum", GIMP_ICON_CHANNEL_BLUE,
+ NC_("context-action", "Foreground Blue: Set to Minimum"), NULL, NULL,
+ GIMP_ACTION_SELECT_FIRST, FALSE,
+ NULL },
+ { "context-foreground-blue-maximum", GIMP_ICON_CHANNEL_BLUE,
+ NC_("context-action", "Foreground Blue: Set to Maximum"), NULL, NULL,
+ GIMP_ACTION_SELECT_LAST, FALSE,
+ NULL },
+ { "context-foreground-blue-decrease", GIMP_ICON_CHANNEL_BLUE,
+ NC_("context-action", "Foreground Blue: Decrease by 1%"), NULL, NULL,
+ GIMP_ACTION_SELECT_PREVIOUS, FALSE,
+ NULL },
+ { "context-foreground-blue-increase", GIMP_ICON_CHANNEL_BLUE,
+ NC_("context-action", "Foreground Blue: Increase by 1%"), NULL, NULL,
+ GIMP_ACTION_SELECT_NEXT, FALSE,
+ NULL },
+ { "context-foreground-blue-decrease-skip", GIMP_ICON_CHANNEL_BLUE,
+ NC_("context-action", "Foreground Blue: Decrease by 10%"), NULL, NULL,
+ GIMP_ACTION_SELECT_SKIP_PREVIOUS, FALSE,
+ NULL },
+ { "context-foreground-blue-increase-skip", GIMP_ICON_CHANNEL_BLUE,
+ NC_("context-action", "Foreground Blue: Increase by 10%"), NULL, NULL,
+ GIMP_ACTION_SELECT_SKIP_NEXT, FALSE,
+ NULL }
+};
+
+static const GimpEnumActionEntry context_background_red_actions[] =
+{
+ { "context-background-red-set", GIMP_ICON_CHANNEL_RED,
+ NC_("context-action", "Background Red: Set"), NULL, NULL,
+ GIMP_ACTION_SELECT_SET, TRUE,
+ NULL },
+ { "context-background-red-minimum", GIMP_ICON_CHANNEL_RED,
+ NC_("context-action", "Background Red: Set to Minimum"), NULL, NULL,
+ GIMP_ACTION_SELECT_FIRST, FALSE,
+ NULL },
+ { "context-background-red-maximum", GIMP_ICON_CHANNEL_RED,
+ NC_("context-action", "Background Red: Set to Maximum"), NULL, NULL,
+ GIMP_ACTION_SELECT_LAST, FALSE,
+ NULL },
+ { "context-background-red-decrease", GIMP_ICON_CHANNEL_RED,
+ NC_("context-action", "Background Red: Decrease by 1%"), NULL, NULL,
+ GIMP_ACTION_SELECT_PREVIOUS, FALSE,
+ NULL },
+ { "context-background-red-increase", GIMP_ICON_CHANNEL_RED,
+ NC_("context-action", "Background Red: Increase by 1%"), NULL, NULL,
+ GIMP_ACTION_SELECT_NEXT, FALSE,
+ NULL },
+ { "context-background-red-decrease-skip", GIMP_ICON_CHANNEL_RED,
+ NC_("context-action", "Background Red: Decrease by 10%"), NULL, NULL,
+ GIMP_ACTION_SELECT_SKIP_PREVIOUS, FALSE,
+ NULL },
+ { "context-background-red-increase-skip", GIMP_ICON_CHANNEL_RED,
+ NC_("context-action", "Background Red: Increase by 10%"), NULL, NULL,
+ GIMP_ACTION_SELECT_SKIP_NEXT, FALSE,
+ NULL }
+};
+
+static const GimpEnumActionEntry context_background_green_actions[] =
+{
+ { "context-background-green-set", GIMP_ICON_CHANNEL_GREEN,
+ NC_("context-action", "Background Green: Set"), NULL, NULL,
+ GIMP_ACTION_SELECT_SET, TRUE,
+ NULL },
+ { "context-background-green-minimum", GIMP_ICON_CHANNEL_GREEN,
+ NC_("context-action", "Background Green: Set to Minimum"), NULL, NULL,
+ GIMP_ACTION_SELECT_FIRST, FALSE,
+ NULL },
+ { "context-background-green-maximum", GIMP_ICON_CHANNEL_GREEN,
+ NC_("context-action", "Background Green: Set to Maximum"), NULL, NULL,
+ GIMP_ACTION_SELECT_LAST, FALSE,
+ NULL },
+ { "context-background-green-decrease", GIMP_ICON_CHANNEL_GREEN,
+ NC_("context-action", "Background Green: Decrease by 1%"), NULL, NULL,
+ GIMP_ACTION_SELECT_PREVIOUS, FALSE,
+ NULL },
+ { "context-background-green-increase", GIMP_ICON_CHANNEL_GREEN,
+ NC_("context-action", "Background Green: Increase by 1%"), NULL, NULL,
+ GIMP_ACTION_SELECT_NEXT, FALSE,
+ NULL },
+ { "context-background-green-decrease-skip", GIMP_ICON_CHANNEL_GREEN,
+ NC_("context-action", "Background Green: Decrease by 10%"), NULL, NULL,
+ GIMP_ACTION_SELECT_SKIP_PREVIOUS, FALSE,
+ NULL },
+ { "context-background-green-increase-skip", GIMP_ICON_CHANNEL_GREEN,
+ NC_("context-action", "Background Green: Increase by 10%"), NULL, NULL,
+ GIMP_ACTION_SELECT_SKIP_NEXT, FALSE,
+ NULL }
+};
+
+static const GimpEnumActionEntry context_background_blue_actions[] =
+{
+ { "context-background-blue-set", GIMP_ICON_CHANNEL_BLUE,
+ NC_("context-action", "Background Blue: Set"), NULL, NULL,
+ GIMP_ACTION_SELECT_SET, TRUE,
+ NULL },
+ { "context-background-blue-minimum", GIMP_ICON_CHANNEL_BLUE,
+ NC_("context-action", "Background Blue: Set to Minimum"), NULL, NULL,
+ GIMP_ACTION_SELECT_FIRST, FALSE,
+ NULL },
+ { "context-background-blue-maximum", GIMP_ICON_CHANNEL_BLUE,
+ NC_("context-action", "Background Blue: Set to Maximum"), NULL, NULL,
+ GIMP_ACTION_SELECT_LAST, FALSE,
+ NULL },
+ { "context-background-blue-decrease", GIMP_ICON_CHANNEL_BLUE,
+ NC_("context-action", "Background Blue: Decrease by 1%"), NULL, NULL,
+ GIMP_ACTION_SELECT_PREVIOUS, FALSE,
+ NULL },
+ { "context-background-blue-increase", GIMP_ICON_CHANNEL_BLUE,
+ NC_("context-action", "Background Blue: Increase by 1%"), NULL, NULL,
+ GIMP_ACTION_SELECT_NEXT, FALSE,
+ NULL },
+ { "context-background-blue-decrease-skip", GIMP_ICON_CHANNEL_BLUE,
+ NC_("context-action", "Background Blue: Decrease by 10%"), NULL, NULL,
+ GIMP_ACTION_SELECT_SKIP_PREVIOUS, FALSE,
+ NULL },
+ { "context-background-blue-increase-skip", GIMP_ICON_CHANNEL_BLUE,
+ NC_("context-action", "Background Blue: Increase by 10%"), NULL, NULL,
+ GIMP_ACTION_SELECT_SKIP_NEXT, FALSE,
+ NULL }
+};
+
+static const GimpEnumActionEntry context_foreground_hue_actions[] =
+{
+ { "context-foreground-hue-set", GIMP_ICON_TOOL_HUE_SATURATION,
+ NC_("context-action", "Foreground Hue: Set"), NULL, NULL,
+ GIMP_ACTION_SELECT_SET, TRUE,
+ NULL },
+ { "context-foreground-hue-minimum", GIMP_ICON_TOOL_HUE_SATURATION,
+ NC_("context-action", "Foreground Hue: Set to Minimum"), NULL, NULL,
+ GIMP_ACTION_SELECT_FIRST, FALSE,
+ NULL },
+ { "context-foreground-hue-maximum", GIMP_ICON_TOOL_HUE_SATURATION,
+ NC_("context-action", "Foreground Hue: Set to Maximum"), NULL, NULL,
+ GIMP_ACTION_SELECT_LAST, FALSE,
+ NULL },
+ { "context-foreground-hue-decrease", GIMP_ICON_TOOL_HUE_SATURATION,
+ NC_("context-action", "Foreground Hue: Decrease by 1%"), NULL, NULL,
+ GIMP_ACTION_SELECT_PREVIOUS, FALSE,
+ NULL },
+ { "context-foreground-hue-increase", GIMP_ICON_TOOL_HUE_SATURATION,
+ NC_("context-action", "Foreground Hue: Increase by 1%"), NULL, NULL,
+ GIMP_ACTION_SELECT_NEXT, FALSE,
+ NULL },
+ { "context-foreground-hue-decrease-skip", GIMP_ICON_TOOL_HUE_SATURATION,
+ NC_("context-action", "Foreground Hue: Decrease by 10%"), NULL, NULL,
+ GIMP_ACTION_SELECT_SKIP_PREVIOUS, FALSE,
+ NULL },
+ { "context-foreground-hue-increase-skip", GIMP_ICON_TOOL_HUE_SATURATION,
+ NC_("context-action", "Foreground Hue: Increase by 10%"), NULL, NULL,
+ GIMP_ACTION_SELECT_SKIP_NEXT, FALSE,
+ NULL }
+};
+
+static const GimpEnumActionEntry context_foreground_saturation_actions[] =
+{
+ { "context-foreground-saturation-set", GIMP_ICON_TOOL_HUE_SATURATION,
+ NC_("context-action", "Foreground Saturation: Set"), NULL, NULL,
+ GIMP_ACTION_SELECT_SET, TRUE,
+ NULL },
+ { "context-foreground-saturation-minimum", GIMP_ICON_TOOL_HUE_SATURATION,
+ NC_("context-action", "Foreground Saturation: Set to Minimum"), NULL, NULL,
+ GIMP_ACTION_SELECT_FIRST, FALSE,
+ NULL },
+ { "context-foreground-saturation-maximum", GIMP_ICON_TOOL_HUE_SATURATION,
+ NC_("context-action", "Foreground Saturation: Set to Maximum"), NULL, NULL,
+ GIMP_ACTION_SELECT_LAST, FALSE,
+ NULL },
+ { "context-foreground-saturation-decrease", GIMP_ICON_TOOL_HUE_SATURATION,
+ NC_("context-action", "Foreground Saturation: Decrease by 1%"), NULL, NULL,
+ GIMP_ACTION_SELECT_PREVIOUS, FALSE,
+ NULL },
+ { "context-foreground-saturation-increase", GIMP_ICON_TOOL_HUE_SATURATION,
+ NC_("context-action", "Foreground Saturation: Increase by 1%"), NULL, NULL,
+ GIMP_ACTION_SELECT_NEXT, FALSE,
+ NULL },
+ { "context-foreground-saturation-decrease-skip", GIMP_ICON_TOOL_HUE_SATURATION,
+ NC_("context-action", "Foreground Saturation: Decrease by 10%"), NULL, NULL,
+ GIMP_ACTION_SELECT_SKIP_PREVIOUS, FALSE,
+ NULL },
+ { "context-foreground-saturation-increase-skip", GIMP_ICON_TOOL_HUE_SATURATION,
+ NC_("context-action", "Foreground Saturation: Increase by 10%"), NULL, NULL,
+ GIMP_ACTION_SELECT_SKIP_NEXT, FALSE,
+ NULL }
+};
+
+static const GimpEnumActionEntry context_foreground_value_actions[] =
+{
+ { "context-foreground-value-set", GIMP_ICON_TOOL_HUE_SATURATION,
+ NC_("context-action", "Foreground Value: Set"), NULL, NULL,
+ GIMP_ACTION_SELECT_SET, TRUE,
+ NULL },
+ { "context-foreground-value-minimum", GIMP_ICON_TOOL_HUE_SATURATION,
+ NC_("context-action", "Foreground Value: Set to Minimum"), NULL, NULL,
+ GIMP_ACTION_SELECT_FIRST, FALSE,
+ NULL },
+ { "context-foreground-value-maximum", GIMP_ICON_TOOL_HUE_SATURATION,
+ NC_("context-action", "Foreground Value: Set to Maximum"), NULL, NULL,
+ GIMP_ACTION_SELECT_LAST, FALSE,
+ NULL },
+ { "context-foreground-value-decrease", GIMP_ICON_TOOL_HUE_SATURATION,
+ NC_("context-action", "Foreground Value: Decrease by 1%"), NULL, NULL,
+ GIMP_ACTION_SELECT_PREVIOUS, FALSE,
+ NULL },
+ { "context-foreground-value-increase", GIMP_ICON_TOOL_HUE_SATURATION,
+ NC_("context-action", "Foreground Value: Increase by 1%"), NULL, NULL,
+ GIMP_ACTION_SELECT_NEXT, FALSE,
+ NULL },
+ { "context-foreground-value-decrease-skip", GIMP_ICON_TOOL_HUE_SATURATION,
+ NC_("context-action", "Foreground Value: Decrease by 10%"), NULL, NULL,
+ GIMP_ACTION_SELECT_SKIP_PREVIOUS, FALSE,
+ NULL },
+ { "context-foreground-value-increase-skip", GIMP_ICON_TOOL_HUE_SATURATION,
+ NC_("context-action", "Foreground Value: Increase by 10%"), NULL, NULL,
+ GIMP_ACTION_SELECT_SKIP_NEXT, FALSE,
+ NULL }
+};
+
+static const GimpEnumActionEntry context_background_hue_actions[] =
+{
+ { "context-background-hue-set", GIMP_ICON_TOOL_HUE_SATURATION,
+ NC_("context-action", "Background Hue: Set"), NULL, NULL,
+ GIMP_ACTION_SELECT_SET, TRUE,
+ NULL },
+ { "context-background-hue-minimum", GIMP_ICON_TOOL_HUE_SATURATION,
+ NC_("context-action", "Background Hue: Set to Minimum"), NULL, NULL,
+ GIMP_ACTION_SELECT_FIRST, FALSE,
+ NULL },
+ { "context-background-hue-maximum", GIMP_ICON_TOOL_HUE_SATURATION,
+ NC_("context-action", "Background Hue: Set to Maximum"), NULL, NULL,
+ GIMP_ACTION_SELECT_LAST, FALSE,
+ NULL },
+ { "context-background-hue-decrease", GIMP_ICON_TOOL_HUE_SATURATION,
+ NC_("context-action", "Background Hue: Decrease by 1%"), NULL, NULL,
+ GIMP_ACTION_SELECT_PREVIOUS, FALSE,
+ NULL },
+ { "context-background-hue-increase", GIMP_ICON_TOOL_HUE_SATURATION,
+ NC_("context-action", "Background Hue: Increase by 1%"), NULL, NULL,
+ GIMP_ACTION_SELECT_NEXT, FALSE,
+ NULL },
+ { "context-background-hue-decrease-skip", GIMP_ICON_TOOL_HUE_SATURATION,
+ NC_("context-action", "Background Hue: Decrease by 10%"), NULL, NULL,
+ GIMP_ACTION_SELECT_SKIP_PREVIOUS, FALSE,
+ NULL },
+ { "context-background-hue-increase-skip", GIMP_ICON_TOOL_HUE_SATURATION,
+ NC_("context-action", "Background Hue: Increase by 10%"), NULL, NULL,
+ GIMP_ACTION_SELECT_SKIP_NEXT, FALSE,
+ NULL }
+};
+
+static const GimpEnumActionEntry context_background_saturation_actions[] =
+{
+ { "context-background-saturation-set", GIMP_ICON_TOOL_HUE_SATURATION,
+ NC_("context-action", "Background Saturation: Set"), NULL, NULL,
+ GIMP_ACTION_SELECT_SET, TRUE,
+ NULL },
+ { "context-background-saturation-minimum", GIMP_ICON_TOOL_HUE_SATURATION,
+ NC_("context-action", "Background Saturation: Set to Minimum"), NULL, NULL,
+ GIMP_ACTION_SELECT_FIRST, FALSE,
+ NULL },
+ { "context-background-saturation-maximum", GIMP_ICON_TOOL_HUE_SATURATION,
+ NC_("context-action", "Background Saturation: Set to Maximum"), NULL, NULL,
+ GIMP_ACTION_SELECT_LAST, FALSE,
+ NULL },
+ { "context-background-saturation-decrease", GIMP_ICON_TOOL_HUE_SATURATION,
+ NC_("context-action", "Background Saturation: Decrease by 1%"), NULL, NULL,
+ GIMP_ACTION_SELECT_PREVIOUS, FALSE,
+ NULL },
+ { "context-background-saturation-increase", GIMP_ICON_TOOL_HUE_SATURATION,
+ NC_("context-action", "Background Saturation: Increase by 1%"), NULL, NULL,
+ GIMP_ACTION_SELECT_NEXT, FALSE,
+ NULL },
+ { "context-background-saturation-decrease-skip", GIMP_ICON_TOOL_HUE_SATURATION,
+ NC_("context-action", "Background Saturation: Decrease by 10%"), NULL, NULL,
+ GIMP_ACTION_SELECT_SKIP_PREVIOUS, FALSE,
+ NULL },
+ { "context-background-saturation-increase-skip", GIMP_ICON_TOOL_HUE_SATURATION,
+ NC_("context-action", "Background Saturation: Increase by 10%"), NULL, NULL,
+ GIMP_ACTION_SELECT_SKIP_NEXT, FALSE,
+ NULL }
+};
+
+static const GimpEnumActionEntry context_background_value_actions[] =
+{
+ { "context-background-value-set", GIMP_ICON_TOOL_HUE_SATURATION,
+ NC_("context-action", "Background Value: Set"), NULL, NULL,
+ GIMP_ACTION_SELECT_SET, TRUE,
+ NULL },
+ { "context-background-value-minimum", GIMP_ICON_TOOL_HUE_SATURATION,
+ NC_("context-action", "Background Value: Set to Minimum"), NULL, NULL,
+ GIMP_ACTION_SELECT_FIRST, FALSE,
+ NULL },
+ { "context-background-value-maximum", GIMP_ICON_TOOL_HUE_SATURATION,
+ NC_("context-action", "Background Value: Set to Maximum"), NULL, NULL,
+ GIMP_ACTION_SELECT_LAST, FALSE,
+ NULL },
+ { "context-background-value-decrease", GIMP_ICON_TOOL_HUE_SATURATION,
+ NC_("context-action", "Background Value: Decrease by 1%"), NULL, NULL,
+ GIMP_ACTION_SELECT_PREVIOUS, FALSE,
+ NULL },
+ { "context-background-value-increase", GIMP_ICON_TOOL_HUE_SATURATION,
+ NC_("context-action", "Background Value: Increase by 1%"), NULL, NULL,
+ GIMP_ACTION_SELECT_NEXT, FALSE,
+ NULL },
+ { "context-background-value-decrease-skip", GIMP_ICON_TOOL_HUE_SATURATION,
+ NC_("context-action", "Background Value: Decrease by 10%"), NULL, NULL,
+ GIMP_ACTION_SELECT_SKIP_PREVIOUS, FALSE,
+ NULL },
+ { "context-background-value-increase-skip", GIMP_ICON_TOOL_HUE_SATURATION,
+ NC_("context-action", "Background Value: Increase by 10%"), NULL, NULL,
+ GIMP_ACTION_SELECT_SKIP_NEXT, FALSE,
+ NULL }
+};
+
+static const GimpEnumActionEntry context_opacity_actions[] =
+{
+ { "context-opacity-set", GIMP_ICON_TRANSPARENCY,
+ NC_("context-action", "Tool Opacity: Set Transparency"), NULL, NULL,
+ GIMP_ACTION_SELECT_SET, TRUE,
+ NULL },
+ { "context-opacity-transparent", GIMP_ICON_TRANSPARENCY,
+ NC_("context-action", "Tool Opacity: Make Completely Transparent"), NULL, NULL,
+ GIMP_ACTION_SELECT_FIRST, FALSE,
+ NULL },
+ { "context-opacity-opaque", GIMP_ICON_TRANSPARENCY,
+ NC_("context-action", "Tool Opacity: Make Completely Opaque"), NULL, NULL,
+ GIMP_ACTION_SELECT_LAST, FALSE,
+ NULL },
+ { "context-opacity-decrease", GIMP_ICON_TRANSPARENCY,
+ NC_("context-action", "Tool Opacity: Make 1% More Transparent"), NULL, NULL,
+ GIMP_ACTION_SELECT_PREVIOUS, FALSE,
+ NULL },
+ { "context-opacity-increase", GIMP_ICON_TRANSPARENCY,
+ NC_("context-action", "Tool Opacity: Make 1% More Opaque"), NULL, NULL,
+ GIMP_ACTION_SELECT_NEXT, FALSE,
+ NULL },
+ { "context-opacity-decrease-skip", GIMP_ICON_TRANSPARENCY,
+ NC_("context-action", "Tool Opacity: Make 10% More Transparent"), NULL, NULL,
+ GIMP_ACTION_SELECT_SKIP_PREVIOUS, FALSE,
+ NULL },
+ { "context-opacity-increase-skip", GIMP_ICON_TRANSPARENCY,
+ NC_("context-action", "Tool Opacity: Make 10% More Opaque"), NULL, NULL,
+ GIMP_ACTION_SELECT_SKIP_NEXT, FALSE,
+ NULL }
+};
+
+static const GimpEnumActionEntry context_paint_mode_actions[] =
+{
+ { "context-paint-mode-first", GIMP_ICON_TOOL_PENCIL,
+ NC_("context-action", "Tool Paint Mode: Select First"), NULL, NULL,
+ GIMP_ACTION_SELECT_FIRST, FALSE,
+ NULL },
+ { "context-paint-mode-last", GIMP_ICON_TOOL_PENCIL,
+ NC_("context-action", "Tool Paint Mode: Select Last"), NULL, NULL,
+ GIMP_ACTION_SELECT_LAST, FALSE,
+ NULL },
+ { "context-paint-mode-previous", GIMP_ICON_TOOL_PENCIL,
+ NC_("context-action", "Tool Paint Mode: Select Previous"), NULL, NULL,
+ GIMP_ACTION_SELECT_PREVIOUS, FALSE,
+ NULL },
+ { "context-paint-mode-next", GIMP_ICON_TOOL_PENCIL,
+ NC_("context-action", "Tool Paint Mode: Select Next"), NULL, NULL,
+ GIMP_ACTION_SELECT_NEXT, FALSE,
+ NULL }
+};
+
+static const GimpEnumActionEntry context_tool_select_actions[] =
+{
+ { "context-tool-select-set", GIMP_ICON_DIALOG_TOOLS,
+ NC_("context-action", "Tool Selection: Choose by Index"), NULL, NULL,
+ GIMP_ACTION_SELECT_SET, TRUE,
+ NULL },
+ { "context-tool-select-first", GIMP_ICON_DIALOG_TOOLS,
+ NC_("context-action", "Tool Selection: Switch to First"), NULL, NULL,
+ GIMP_ACTION_SELECT_FIRST, FALSE,
+ NULL },
+ { "context-tool-select-last", GIMP_ICON_DIALOG_TOOLS,
+ NC_("context-action", "Tool Selection: Switch to Last"), NULL, NULL,
+ GIMP_ACTION_SELECT_LAST, FALSE,
+ NULL },
+ { "context-tool-select-previous", GIMP_ICON_DIALOG_TOOLS,
+ NC_("context-action", "Tool Selection: Switch to Previous"), NULL, NULL,
+ GIMP_ACTION_SELECT_PREVIOUS, FALSE,
+ NULL },
+ { "context-tool-select-next", GIMP_ICON_DIALOG_TOOLS,
+ NC_("context-action", "Tool Selection: Switch to Next"), NULL, NULL,
+ GIMP_ACTION_SELECT_NEXT, FALSE,
+ NULL }
+};
+
+static const GimpEnumActionEntry context_brush_select_actions[] =
+{
+ { "context-brush-select-set", GIMP_ICON_BRUSH,
+ NC_("context-action", "Brush Selection: Select by Index"), NULL, NULL,
+ GIMP_ACTION_SELECT_SET, TRUE,
+ NULL },
+ { "context-brush-select-first", GIMP_ICON_BRUSH,
+ NC_("context-action", "Brush Selection: Switch to First"), NULL, NULL,
+ GIMP_ACTION_SELECT_FIRST, FALSE,
+ NULL },
+ { "context-brush-select-last", GIMP_ICON_BRUSH,
+ NC_("context-action", "Brush Selection: Switch to Last"), NULL, NULL,
+ GIMP_ACTION_SELECT_LAST, FALSE,
+ NULL },
+ { "context-brush-select-previous", GIMP_ICON_BRUSH,
+ NC_("context-action", "Brush Selection: Switch to Previous"), NULL, NULL,
+ GIMP_ACTION_SELECT_PREVIOUS, FALSE,
+ NULL },
+ { "context-brush-select-next", GIMP_ICON_BRUSH,
+ NC_("context-action", "Brush Selection: Switch to Next"), NULL, NULL,
+ GIMP_ACTION_SELECT_NEXT, FALSE,
+ NULL }
+};
+
+static const GimpEnumActionEntry context_pattern_select_actions[] =
+{
+ { "context-pattern-select-set", GIMP_ICON_PATTERN,
+ NC_("context-action", "Pattern Selection: Select by Index"), NULL, NULL,
+ GIMP_ACTION_SELECT_SET, TRUE,
+ NULL },
+ { "context-pattern-select-first", GIMP_ICON_PATTERN,
+ NC_("context-action", "Pattern Selection: Switch to First"), NULL, NULL,
+ GIMP_ACTION_SELECT_FIRST, FALSE,
+ NULL },
+ { "context-pattern-select-last", GIMP_ICON_PATTERN,
+ NC_("context-action", "Pattern Selection: Switch to Last"), NULL, NULL,
+ GIMP_ACTION_SELECT_LAST, FALSE,
+ NULL },
+ { "context-pattern-select-previous", GIMP_ICON_PATTERN,
+ NC_("context-action", "Pattern Selection: Switch to Previous"), NULL, NULL,
+ GIMP_ACTION_SELECT_PREVIOUS, FALSE,
+ NULL },
+ { "context-pattern-select-next", GIMP_ICON_PATTERN,
+ NC_("context-action", "Pattern Selection: Switch to Next"), NULL, NULL,
+ GIMP_ACTION_SELECT_NEXT, FALSE,
+ NULL }
+};
+
+static const GimpEnumActionEntry context_palette_select_actions[] =
+{
+ { "context-palette-select-set", GIMP_ICON_PALETTE,
+ NC_("context-action", "Palette Selection: Select by Index"), NULL, NULL,
+ GIMP_ACTION_SELECT_SET, TRUE,
+ NULL },
+ { "context-palette-select-first", GIMP_ICON_PALETTE,
+ NC_("context-action", "Palette Selection: Switch to First"), NULL, NULL,
+ GIMP_ACTION_SELECT_FIRST, FALSE,
+ NULL },
+ { "context-palette-select-last", GIMP_ICON_PALETTE,
+ NC_("context-action", "Palette Selection: Switch to Last"), NULL, NULL,
+ GIMP_ACTION_SELECT_LAST, FALSE,
+ NULL },
+ { "context-palette-select-previous", GIMP_ICON_PALETTE,
+ NC_("context-action", "Palette Selection: Switch to Previous"), NULL, NULL,
+ GIMP_ACTION_SELECT_PREVIOUS, FALSE,
+ NULL },
+ { "context-palette-select-next", GIMP_ICON_PALETTE,
+ NC_("context-action", "Palette Selection: Switch to Next"), NULL, NULL,
+ GIMP_ACTION_SELECT_NEXT, FALSE,
+ NULL }
+};
+
+static const GimpEnumActionEntry context_gradient_select_actions[] =
+{
+ { "context-gradient-select-set", GIMP_ICON_GRADIENT,
+ NC_("context-action", "Gradient Selection: Select by Index"), NULL, NULL,
+ GIMP_ACTION_SELECT_SET, TRUE,
+ NULL },
+ { "context-gradient-select-first", GIMP_ICON_GRADIENT,
+ NC_("context-action", "Gradient Selection: Switch to First"), NULL, NULL,
+ GIMP_ACTION_SELECT_FIRST, FALSE,
+ NULL },
+ { "context-gradient-select-last", GIMP_ICON_GRADIENT,
+ NC_("context-action", "Gradient Selection: Switch to Last"), NULL, NULL,
+ GIMP_ACTION_SELECT_LAST, FALSE,
+ NULL },
+ { "context-gradient-select-previous", GIMP_ICON_GRADIENT,
+ NC_("context-action", "Gradient Selection: Switch to Previous"), NULL, NULL,
+ GIMP_ACTION_SELECT_PREVIOUS, FALSE,
+ NULL },
+ { "context-gradient-select-next", GIMP_ICON_GRADIENT,
+ NC_("context-action", "Gradient Selection: Switch to Next"), NULL, NULL,
+ GIMP_ACTION_SELECT_NEXT, FALSE,
+ NULL }
+};
+
+static const GimpEnumActionEntry context_font_select_actions[] =
+{
+ { "context-font-select-set", GIMP_ICON_FONT,
+ NC_("context-action", "Font Selection: Select by Index"), NULL, NULL,
+ GIMP_ACTION_SELECT_SET, TRUE,
+ NULL },
+ { "context-font-select-first", GIMP_ICON_FONT,
+ NC_("context-action", "Font Selection: Switch to First"), NULL, NULL,
+ GIMP_ACTION_SELECT_FIRST, FALSE,
+ NULL },
+ { "context-font-select-last", GIMP_ICON_FONT,
+ NC_("context-action", "Font Selection: Switch to Last"), NULL, NULL,
+ GIMP_ACTION_SELECT_LAST, FALSE,
+ NULL },
+ { "context-font-select-previous", GIMP_ICON_FONT,
+ NC_("context-action", "Font Selection: Switch to Previous"), NULL, NULL,
+ GIMP_ACTION_SELECT_PREVIOUS, FALSE,
+ NULL },
+ { "context-font-select-next", GIMP_ICON_FONT,
+ NC_("context-action", "Font Selection: Switch to Next"), NULL, NULL,
+ GIMP_ACTION_SELECT_NEXT, FALSE,
+ NULL }
+};
+
+static const GimpEnumActionEntry context_brush_spacing_actions[] =
+{
+ { "context-brush-spacing-set", GIMP_ICON_BRUSH,
+ NC_("context-action", "Brush Spacing (Editor): Set"), NULL, NULL,
+ GIMP_ACTION_SELECT_SET, TRUE,
+ NULL },
+ { "context-brush-spacing-minimum", GIMP_ICON_BRUSH,
+ NC_("context-action", "Brush Spacing (Editor): Set to Minimum"), NULL, NULL,
+ GIMP_ACTION_SELECT_FIRST, FALSE,
+ NULL },
+ { "context-brush-spacing-maximum", GIMP_ICON_BRUSH,
+ NC_("context-action", "Brush Spacing (Editor): Set to Maximum"), NULL, NULL,
+ GIMP_ACTION_SELECT_LAST, FALSE,
+ NULL },
+ { "context-brush-spacing-decrease", GIMP_ICON_BRUSH,
+ NC_("context-action", "Brush Spacing (Editor): Decrease by 1"), NULL, NULL,
+ GIMP_ACTION_SELECT_PREVIOUS, FALSE,
+ NULL },
+ { "context-brush-spacing-increase", GIMP_ICON_BRUSH,
+ NC_("context-action", "Brush Spacing (Editor): Increase by 1"), NULL, NULL,
+ GIMP_ACTION_SELECT_NEXT, FALSE,
+ NULL },
+ { "context-brush-spacing-decrease-skip", GIMP_ICON_BRUSH,
+ NC_("context-action", "Brush Spacing (Editor): Decrease by 10"), NULL, NULL,
+ GIMP_ACTION_SELECT_SKIP_PREVIOUS, FALSE,
+ NULL },
+ { "context-brush-spacing-increase-skip", GIMP_ICON_BRUSH,
+ NC_("context-action", "Brush Spacing (Editor): Increase by 10"), NULL, NULL,
+ GIMP_ACTION_SELECT_SKIP_NEXT, FALSE,
+ NULL }
+};
+
+static const GimpEnumActionEntry context_brush_shape_actions[] =
+{
+ { "context-brush-shape-circle", GIMP_ICON_BRUSH,
+ NC_("context-action", "Brush Shape (Editor): Use Circular"), NULL, NULL,
+ GIMP_BRUSH_GENERATED_CIRCLE, FALSE,
+ NULL },
+ { "context-brush-shape-square", GIMP_ICON_BRUSH,
+ NC_("context-action", "Brush Shape (Editor): Use Square"), NULL, NULL,
+ GIMP_BRUSH_GENERATED_SQUARE, FALSE,
+ NULL },
+ { "context-brush-shape-diamond", GIMP_ICON_BRUSH,
+ NC_("context-action", "Brush Shape (Editor): Use Diamond"), NULL, NULL,
+ GIMP_BRUSH_GENERATED_DIAMOND, FALSE,
+ NULL }
+};
+
+static const GimpEnumActionEntry context_brush_radius_actions[] =
+{
+ { "context-brush-radius-set", GIMP_ICON_BRUSH,
+ NC_("context-action", "Brush Radius (Editor): Set"), NULL, NULL,
+ GIMP_ACTION_SELECT_SET, TRUE,
+ NULL },
+ { "context-brush-radius-minimum", GIMP_ICON_BRUSH,
+ NC_("context-action", "Brush Radius (Editor): Set to Minimum"), NULL, NULL,
+ GIMP_ACTION_SELECT_FIRST, FALSE,
+ NULL },
+ { "context-brush-radius-maximum", GIMP_ICON_BRUSH,
+ NC_("context-action", "Brush Radius (Editor): Set to Maximum"), NULL, NULL,
+ GIMP_ACTION_SELECT_LAST, FALSE,
+ NULL },
+ { "context-brush-radius-decrease-less", GIMP_ICON_BRUSH,
+ NC_("context-action", "Brush Radius (Editor): Decrease by 0.1"), NULL, NULL,
+ GIMP_ACTION_SELECT_SMALL_PREVIOUS, FALSE,
+ NULL },
+ { "context-brush-radius-increase-less", GIMP_ICON_BRUSH,
+ NC_("context-action", "Brush Radius (Editor): Increase by 0.1"), NULL, NULL,
+ GIMP_ACTION_SELECT_SMALL_NEXT, FALSE,
+ NULL },
+ { "context-brush-radius-decrease", GIMP_ICON_BRUSH,
+ NC_("context-action", "Brush Radius (Editor): Decrease by 1"), NULL, NULL,
+ GIMP_ACTION_SELECT_PREVIOUS, FALSE,
+ NULL },
+ { "context-brush-radius-increase", GIMP_ICON_BRUSH,
+ NC_("context-action", "Brush Radius (Editor): Increase by 1"), NULL, NULL,
+ GIMP_ACTION_SELECT_NEXT, FALSE,
+ NULL },
+ { "context-brush-radius-decrease-skip", GIMP_ICON_BRUSH,
+ NC_("context-action", "Brush Radius (Editor): Decrease by 10"), NULL, NULL,
+ GIMP_ACTION_SELECT_SKIP_PREVIOUS, FALSE,
+ NULL },
+ { "context-brush-radius-increase-skip", GIMP_ICON_BRUSH,
+ NC_("context-action", "Brush Radius (Editor): Increase by 10"), NULL, NULL,
+ GIMP_ACTION_SELECT_SKIP_NEXT, FALSE,
+ NULL },
+ { "context-brush-radius-decrease-percent", GIMP_ICON_BRUSH,
+ NC_("context-action", "Brush Radius (Editor): Decrease Relative"), NULL, NULL,
+ GIMP_ACTION_SELECT_PERCENT_PREVIOUS, FALSE,
+ NULL },
+ { "context-brush-radius-increase-percent", GIMP_ICON_BRUSH,
+ NC_("context-action", "Brush Radius (Editor): Increase Relative"), NULL, NULL,
+ GIMP_ACTION_SELECT_PERCENT_NEXT, FALSE,
+ NULL }
+};
+
+static const GimpEnumActionEntry context_brush_spikes_actions[] =
+{
+ { "context-brush-spikes-set", GIMP_ICON_BRUSH,
+ NC_("context-action", "Brush Spikes (Editor): Set"), NULL, NULL,
+ GIMP_ACTION_SELECT_SET, TRUE,
+ NULL },
+ { "context-brush-spikes-minimum", GIMP_ICON_BRUSH,
+ NC_("context-action", "Brush Spikes (Editor): Set to Minimum"), NULL, NULL,
+ GIMP_ACTION_SELECT_FIRST, FALSE,
+ NULL },
+ { "context-brush-spikes-maximum", GIMP_ICON_BRUSH,
+ NC_("context-action", "Brush Spikes (Editor): Set to Maximum"), NULL, NULL,
+ GIMP_ACTION_SELECT_LAST, FALSE,
+ NULL },
+ { "context-brush-spikes-decrease", GIMP_ICON_BRUSH,
+ NC_("context-action", "Brush Spikes (Editor): Decrease by 1"), NULL, NULL,
+ GIMP_ACTION_SELECT_PREVIOUS, FALSE,
+ NULL },
+ { "context-brush-spikes-increase", GIMP_ICON_BRUSH,
+ NC_("context-action", "Brush Spikes (Editor): Increase by 1"), NULL, NULL,
+ GIMP_ACTION_SELECT_NEXT, FALSE,
+ NULL },
+ { "context-brush-spikes-decrease-skip", GIMP_ICON_BRUSH,
+ NC_("context-action", "Brush Spikes (Editor): Decrease by 4"), NULL, NULL,
+ GIMP_ACTION_SELECT_SKIP_PREVIOUS, FALSE,
+ NULL },
+ { "context-brush-spikes-increase-skip", GIMP_ICON_BRUSH,
+ NC_("context-action", "Brush Spikes (Editor): Increase by 4"), NULL, NULL,
+ GIMP_ACTION_SELECT_SKIP_NEXT, FALSE,
+ NULL }
+};
+
+static const GimpEnumActionEntry context_brush_hardness_actions[] =
+{
+ { "context-brush-hardness-set", GIMP_ICON_BRUSH,
+ NC_("context-action", "Brush Hardness (Editor): Set"), NULL, NULL,
+ GIMP_ACTION_SELECT_SET, TRUE,
+ NULL },
+ { "context-brush-hardness-minimum", GIMP_ICON_BRUSH,
+ NC_("context-action", "Brush Hardness (Editor): Set to Minimum"), NULL, NULL,
+ GIMP_ACTION_SELECT_FIRST, FALSE,
+ NULL },
+ { "context-brush-hardness-maximum", GIMP_ICON_BRUSH,
+ NC_("context-action", "Brush Hardness (Editor): Set to Maximum"), NULL, NULL,
+ GIMP_ACTION_SELECT_LAST, FALSE,
+ NULL },
+ { "context-brush-hardness-decrease", GIMP_ICON_BRUSH,
+ NC_("context-action", "Brush Hardness (Editor): Decrease by 0.01"), NULL, NULL,
+ GIMP_ACTION_SELECT_PREVIOUS, FALSE,
+ NULL },
+ { "context-brush-hardness-increase", GIMP_ICON_BRUSH,
+ NC_("context-action", "Brush Hardness (Editor): Increase by 0.01"), NULL, NULL,
+ GIMP_ACTION_SELECT_NEXT, FALSE,
+ NULL },
+ { "context-brush-hardness-decrease-skip", GIMP_ICON_BRUSH,
+ NC_("context-action", "Brush Hardness (Editor): Decrease by 0.1"), NULL, NULL,
+ GIMP_ACTION_SELECT_SKIP_PREVIOUS, FALSE,
+ NULL },
+ { "context-brush-hardness-increase-skip", GIMP_ICON_BRUSH,
+ NC_("context-action", "Brush Hardness (Editor): Increase by 0.1"), NULL, NULL,
+ GIMP_ACTION_SELECT_SKIP_NEXT, FALSE,
+ NULL }
+};
+
+static const GimpEnumActionEntry context_brush_aspect_actions[] =
+{
+ { "context-brush-aspect-set", GIMP_ICON_BRUSH,
+ NC_("context-action", "Brush Aspect Ratio (Editor): Set"), NULL, NULL,
+ GIMP_ACTION_SELECT_SET, TRUE,
+ NULL },
+ { "context-brush-aspect-minimum", GIMP_ICON_BRUSH,
+ NC_("context-action", "Brush Aspect Ratio (Editor): Set to Minimum"), NULL, NULL,
+ GIMP_ACTION_SELECT_FIRST, FALSE,
+ NULL },
+ { "context-brush-aspect-maximum", GIMP_ICON_BRUSH,
+ NC_("context-action", "Brush Aspect Ratio (Editor): Set to Maximum"), NULL, NULL,
+ GIMP_ACTION_SELECT_LAST, FALSE,
+ NULL },
+ { "context-brush-aspect-decrease", GIMP_ICON_BRUSH,
+ NC_("context-action", "Brush Aspect Ratio (Editor): Decrease by 0.1"), NULL, NULL,
+ GIMP_ACTION_SELECT_PREVIOUS, FALSE,
+ NULL },
+ { "context-brush-aspect-increase", GIMP_ICON_BRUSH,
+ NC_("context-action", "Brush Aspect Ratio (Editor): Increase by 0.1"), NULL, NULL,
+ GIMP_ACTION_SELECT_NEXT, FALSE,
+ NULL },
+ { "context-brush-aspect-decrease-skip", GIMP_ICON_BRUSH,
+ NC_("context-action", "Brush Aspect Ratio (Editor): Decrease by 1"), NULL, NULL,
+ GIMP_ACTION_SELECT_SKIP_PREVIOUS, FALSE,
+ NULL },
+ { "context-brush-aspect-increase-skip", GIMP_ICON_BRUSH,
+ NC_("context-action", "Brush Aspect Ratio (Editor): Increase by 1"), NULL, NULL,
+ GIMP_ACTION_SELECT_SKIP_NEXT, FALSE,
+ NULL }
+};
+
+static const GimpEnumActionEntry context_brush_angle_actions[] =
+{
+ { "context-brush-angle-set", GIMP_ICON_BRUSH,
+ NC_("context-action", "Brush Angle (Editor): Set"), NULL, NULL,
+ GIMP_ACTION_SELECT_SET, TRUE,
+ NULL },
+ { "context-brush-angle-minimum", GIMP_ICON_BRUSH,
+ NC_("context-action", "Brush Angle (Editor): Make Horizontal"), NULL, NULL,
+ GIMP_ACTION_SELECT_FIRST, FALSE,
+ NULL },
+ { "context-brush-angle-maximum", GIMP_ICON_BRUSH,
+ NC_("context-action", "Brush Angle (Editor): Make Vertical"), NULL, NULL,
+ GIMP_ACTION_SELECT_LAST, FALSE,
+ NULL },
+ { "context-brush-angle-decrease", GIMP_ICON_BRUSH,
+ NC_("context-action", "Brush Angle (Editor): Rotate Right by 1°"), NULL, NULL,
+ GIMP_ACTION_SELECT_PREVIOUS, FALSE,
+ NULL },
+ { "context-brush-angle-increase", GIMP_ICON_BRUSH,
+ NC_("context-action", "Brush Angle (Editor): Rotate Left by 1°"), NULL, NULL,
+ GIMP_ACTION_SELECT_NEXT, FALSE,
+ NULL },
+ { "context-brush-angle-decrease-skip", GIMP_ICON_BRUSH,
+ NC_("context-action", "Brush Angle (Editor): Rotate Right by 15°"), NULL, NULL,
+ GIMP_ACTION_SELECT_SKIP_PREVIOUS, FALSE,
+ NULL },
+ { "context-brush-angle-increase-skip", GIMP_ICON_BRUSH,
+ NC_("context-action", "Brush Angle (Editor): Rotate Left by 15°"), NULL, NULL,
+ GIMP_ACTION_SELECT_SKIP_NEXT, FALSE,
+ NULL }
+};
+
+
+void
+context_actions_setup (GimpActionGroup *group)
+{
+ gimp_action_group_add_actions (group, "context-action",
+ context_actions,
+ G_N_ELEMENTS (context_actions));
+
+ gimp_action_group_add_enum_actions (group, "context-action",
+ context_palette_foreground_actions,
+ G_N_ELEMENTS (context_palette_foreground_actions),
+ context_palette_foreground_cmd_callback);
+ gimp_action_group_add_enum_actions (group, "context-action",
+ context_palette_background_actions,
+ G_N_ELEMENTS (context_palette_background_actions),
+ context_palette_background_cmd_callback);
+
+ gimp_action_group_add_enum_actions (group, "context-action",
+ context_colormap_foreground_actions,
+ G_N_ELEMENTS (context_colormap_foreground_actions),
+ context_colormap_foreground_cmd_callback);
+ gimp_action_group_add_enum_actions (group, "context-action",
+ context_colormap_background_actions,
+ G_N_ELEMENTS (context_colormap_background_actions),
+ context_colormap_background_cmd_callback);
+
+ gimp_action_group_add_enum_actions (group, "context-action",
+ context_swatch_foreground_actions,
+ G_N_ELEMENTS (context_swatch_foreground_actions),
+ context_swatch_foreground_cmd_callback);
+ gimp_action_group_add_enum_actions (group, "context-action",
+ context_swatch_background_actions,
+ G_N_ELEMENTS (context_swatch_background_actions),
+ context_swatch_background_cmd_callback);
+
+
+ gimp_action_group_add_enum_actions (group, "context-action",
+ context_foreground_red_actions,
+ G_N_ELEMENTS (context_foreground_red_actions),
+ context_foreground_red_cmd_callback);
+ gimp_action_group_add_enum_actions (group, "context-action",
+ context_foreground_green_actions,
+ G_N_ELEMENTS (context_foreground_green_actions),
+ context_foreground_green_cmd_callback);
+ gimp_action_group_add_enum_actions (group, "context-action",
+ context_foreground_blue_actions,
+ G_N_ELEMENTS (context_foreground_blue_actions),
+ context_foreground_blue_cmd_callback);
+
+ gimp_action_group_add_enum_actions (group, "context-action",
+ context_foreground_hue_actions,
+ G_N_ELEMENTS (context_foreground_hue_actions),
+ context_foreground_hue_cmd_callback);
+ gimp_action_group_add_enum_actions (group, "context-action",
+ context_foreground_saturation_actions,
+ G_N_ELEMENTS (context_foreground_saturation_actions),
+ context_foreground_saturation_cmd_callback);
+ gimp_action_group_add_enum_actions (group, "context-action",
+ context_foreground_value_actions,
+ G_N_ELEMENTS (context_foreground_value_actions),
+ context_foreground_value_cmd_callback);
+
+ gimp_action_group_add_enum_actions (group, "context-action",
+ context_background_red_actions,
+ G_N_ELEMENTS (context_background_red_actions),
+ context_background_red_cmd_callback);
+ gimp_action_group_add_enum_actions (group, "context-action",
+ context_background_green_actions,
+ G_N_ELEMENTS (context_background_green_actions),
+ context_background_green_cmd_callback);
+ gimp_action_group_add_enum_actions (group, "context-action",
+ context_background_blue_actions,
+ G_N_ELEMENTS (context_background_blue_actions),
+ context_background_blue_cmd_callback);
+
+ gimp_action_group_add_enum_actions (group, "context-action",
+ context_background_hue_actions,
+ G_N_ELEMENTS (context_background_hue_actions),
+ context_background_hue_cmd_callback);
+ gimp_action_group_add_enum_actions (group, "context-action",
+ context_background_saturation_actions,
+ G_N_ELEMENTS (context_background_saturation_actions),
+ context_background_saturation_cmd_callback);
+ gimp_action_group_add_enum_actions (group, "context-action",
+ context_background_value_actions,
+ G_N_ELEMENTS (context_background_value_actions),
+ context_background_value_cmd_callback);
+
+ gimp_action_group_add_enum_actions (group, "context-action",
+ context_opacity_actions,
+ G_N_ELEMENTS (context_opacity_actions),
+ context_opacity_cmd_callback);
+ gimp_action_group_add_enum_actions (group, "context-action",
+ context_paint_mode_actions,
+ G_N_ELEMENTS (context_paint_mode_actions),
+ context_paint_mode_cmd_callback);
+
+ gimp_action_group_add_enum_actions (group, "context-action",
+ context_tool_select_actions,
+ G_N_ELEMENTS (context_tool_select_actions),
+ context_tool_select_cmd_callback);
+ gimp_action_group_add_enum_actions (group, "context-action",
+ context_brush_select_actions,
+ G_N_ELEMENTS (context_brush_select_actions),
+ context_brush_select_cmd_callback);
+ gimp_action_group_add_enum_actions (group, "context-action",
+ context_pattern_select_actions,
+ G_N_ELEMENTS (context_pattern_select_actions),
+ context_pattern_select_cmd_callback);
+ gimp_action_group_add_enum_actions (group, "context-action",
+ context_palette_select_actions,
+ G_N_ELEMENTS (context_palette_select_actions),
+ context_palette_select_cmd_callback);
+ gimp_action_group_add_enum_actions (group, "context-action",
+ context_gradient_select_actions,
+ G_N_ELEMENTS (context_gradient_select_actions),
+ context_gradient_select_cmd_callback);
+ gimp_action_group_add_enum_actions (group, "context-action",
+ context_font_select_actions,
+ G_N_ELEMENTS (context_font_select_actions),
+ context_font_select_cmd_callback);
+
+ gimp_action_group_add_enum_actions (group, "context-action",
+ context_brush_spacing_actions,
+ G_N_ELEMENTS (context_brush_spacing_actions),
+ context_brush_spacing_cmd_callback);
+ gimp_action_group_add_enum_actions (group, "context-action",
+ context_brush_shape_actions,
+ G_N_ELEMENTS (context_brush_shape_actions),
+ context_brush_shape_cmd_callback);
+ gimp_action_group_add_enum_actions (group, "context-action",
+ context_brush_radius_actions,
+ G_N_ELEMENTS (context_brush_radius_actions),
+ context_brush_radius_cmd_callback);
+ gimp_action_group_add_enum_actions (group, "context-action",
+ context_brush_spikes_actions,
+ G_N_ELEMENTS (context_brush_spikes_actions),
+ context_brush_spikes_cmd_callback);
+ gimp_action_group_add_enum_actions (group, "context-action",
+ context_brush_hardness_actions,
+ G_N_ELEMENTS (context_brush_hardness_actions),
+ context_brush_hardness_cmd_callback);
+ gimp_action_group_add_enum_actions (group, "context-action",
+ context_brush_aspect_actions,
+ G_N_ELEMENTS (context_brush_aspect_actions),
+ context_brush_aspect_cmd_callback);
+ gimp_action_group_add_enum_actions (group, "context-action",
+ context_brush_angle_actions,
+ G_N_ELEMENTS (context_brush_angle_actions),
+ context_brush_angle_cmd_callback);
+}
+
+void
+context_actions_update (GimpActionGroup *group,
+ gpointer data)
+{
+#if 0
+ GimpContext *context = action_data_get_context (data);
+ gboolean generated = FALSE;
+ gdouble radius = 0.0;
+ gint spikes = 0;
+ gdouble hardness = 0.0;
+ gdouble aspect = 0.0;
+ gdouble angle = 0.0;
+
+ if (context)
+ {
+ GimpBrush *brush = gimp_context_get_brush (context);
+
+ if (GIMP_IS_BRUSH_GENERATED (brush))
+ {
+ GimpBrushGenerated *gen = GIMP_BRUSH_GENERATED (brush);
+
+ generated = TRUE;
+
+ radius = gimp_brush_generated_get_radius (gen);
+ spikes = gimp_brush_generated_get_spikes (gen);
+ hardness = gimp_brush_generated_get_hardness (gen);
+ aspect = gimp_brush_generated_get_aspect_ratio (gen);
+ angle = gimp_brush_generated_get_angle (gen);
+ }
+ }
+
+#define SET_SENSITIVE(action,condition) \
+ gimp_action_group_set_action_sensitive (group, "context-" action, (condition) != 0)
+
+ SET_SENSITIVE ("brush-radius-minimum", generated && radius > 1.0);
+ SET_SENSITIVE ("brush-radius-decrease", generated && radius > 1.0);
+ SET_SENSITIVE ("brush-radius-decrease-skip", generated && radius > 1.0);
+
+ SET_SENSITIVE ("brush-radius-maximum", generated && radius < 4000.0);
+ SET_SENSITIVE ("brush-radius-increase", generated && radius < 4000.0);
+ SET_SENSITIVE ("brush-radius-increase-skip", generated && radius < 4000.0);
+
+ SET_SENSITIVE ("brush-angle-minimum", generated);
+ SET_SENSITIVE ("brush-angle-decrease", generated);
+ SET_SENSITIVE ("brush-angle-decrease-skip", generated);
+
+ SET_SENSITIVE ("brush-angle-maximum", generated);
+ SET_SENSITIVE ("brush-angle-increase", generated);
+ SET_SENSITIVE ("brush-angle-increase-skip", generated);
+#undef SET_SENSITIVE
+
+#endif
+}
diff --git a/app/actions/context-actions.h b/app/actions/context-actions.h
new file mode 100644
index 0000000..f2ad085
--- /dev/null
+++ b/app/actions/context-actions.h
@@ -0,0 +1,27 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __CONTEXT_ACTIONS_H__
+#define __CONTEXT_ACTIONS_H__
+
+
+void context_actions_setup (GimpActionGroup *group);
+void context_actions_update (GimpActionGroup *group,
+ gpointer data);
+
+
+#endif /* __CONTEXT_ACTIONS_H__ */
diff --git a/app/actions/context-commands.c b/app/actions/context-commands.c
new file mode 100644
index 0000000..61d9e90
--- /dev/null
+++ b/app/actions/context-commands.c
@@ -0,0 +1,975 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <string.h>
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpbase/gimpbase.h"
+#include "libgimpcolor/gimpcolor.h"
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "actions-types.h"
+
+#include "operations/layer-modes/gimp-layer-modes.h"
+
+#include "core/gimp.h"
+#include "core/gimpbrushgenerated.h"
+#include "core/gimpcontext.h"
+#include "core/gimpdatafactory.h"
+#include "core/gimplist.h"
+#include "core/gimptoolinfo.h"
+
+#include "paint/gimppaintoptions.h"
+
+#include "widgets/gimpdialogfactory.h"
+#include "widgets/gimpsessioninfo.h"
+#include "widgets/gimppaletteeditor.h"
+#include "widgets/gimpcolormapeditor.h"
+
+#include "actions.h"
+#include "context-commands.h"
+
+#include "gimp-intl.h"
+
+
+/* local function prototypes */
+
+static void context_select_object (GimpActionSelectType select_type,
+ GimpContext *context,
+ GimpContainer *container);
+static gint context_paint_mode_index (GimpLayerMode paint_mode,
+ const GimpLayerMode *modes,
+ gint n_modes);
+
+static void context_select_color (GimpActionSelectType select_type,
+ GimpRGB *color,
+ gboolean use_colormap,
+ gboolean use_palette);
+
+static gint context_get_color_index (gboolean use_colormap,
+ gboolean use_palette,
+ const GimpRGB *color);
+static gint context_max_color_index (gboolean use_colormap,
+ gboolean use_palette);
+static gboolean context_set_color_index (gint index,
+ gboolean use_colormap,
+ gboolean use_palette,
+ GimpRGB *color);
+
+static GimpPaletteEditor * context_get_palette_editor (void);
+static GimpColormapEditor * context_get_colormap_editor (void);
+
+
+/* public functions */
+
+void
+context_colors_default_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpContext *context;
+ return_if_no_context (context, data);
+
+ gimp_context_set_default_colors (context);
+}
+
+void
+context_colors_swap_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpContext *context;
+ return_if_no_context (context, data);
+
+ gimp_context_swap_colors (context);
+}
+
+#define SELECT_COLOR_CMD_CALLBACK(name, fgbg, use_colormap, use_palette) \
+void \
+context_##name##_##fgbg##ground_cmd_callback (GimpAction *action, \
+ GVariant *value, \
+ gpointer data) \
+{ \
+ GimpContext *context; \
+ GimpRGB color; \
+ GimpActionSelectType select_type; \
+ return_if_no_context (context, data); \
+ \
+ select_type = (GimpActionSelectType) g_variant_get_int32 (value); \
+ \
+ gimp_context_get_##fgbg##ground (context, &color); \
+ context_select_color (select_type, &color, \
+ use_colormap, use_palette); \
+ gimp_context_set_##fgbg##ground (context, &color); \
+}
+
+SELECT_COLOR_CMD_CALLBACK (palette, fore, FALSE, TRUE)
+SELECT_COLOR_CMD_CALLBACK (palette, back, FALSE, TRUE)
+SELECT_COLOR_CMD_CALLBACK (colormap, fore, TRUE, FALSE)
+SELECT_COLOR_CMD_CALLBACK (colormap, back, TRUE, FALSE)
+SELECT_COLOR_CMD_CALLBACK (swatch, fore, TRUE, TRUE)
+SELECT_COLOR_CMD_CALLBACK (swatch, back, TRUE, TRUE)
+
+void
+context_foreground_red_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpContext *context;
+ GimpRGB color;
+ GimpActionSelectType select_type;
+ return_if_no_context (context, data);
+
+ select_type = (GimpActionSelectType) g_variant_get_int32 (value);
+
+ gimp_context_get_foreground (context, &color);
+ color.r = action_select_value (select_type,
+ color.r,
+ 0.0, 1.0, 1.0,
+ 1.0 / 255.0, 0.01, 0.1, 0.0, FALSE);
+ gimp_context_set_foreground (context, &color);
+}
+
+void
+context_foreground_green_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpContext *context;
+ GimpRGB color;
+ GimpActionSelectType select_type;
+ return_if_no_context (context, data);
+
+ select_type = (GimpActionSelectType) g_variant_get_int32 (value);
+
+ gimp_context_get_foreground (context, &color);
+ color.g = action_select_value (select_type,
+ color.g,
+ 0.0, 1.0, 1.0,
+ 1.0 / 255.0, 0.01, 0.1, 0.0, FALSE);
+ gimp_context_set_foreground (context, &color);
+}
+
+void
+context_foreground_blue_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpContext *context;
+ GimpRGB color;
+ GimpActionSelectType select_type;
+ return_if_no_context (context, data);
+
+ select_type = (GimpActionSelectType) g_variant_get_int32 (value);
+
+ gimp_context_get_foreground (context, &color);
+ color.b = action_select_value (select_type,
+ color.b,
+ 0.0, 1.0, 1.0,
+ 1.0 / 255.0, 0.01, 0.1, 0.0, FALSE);
+ gimp_context_set_foreground (context, &color);
+}
+
+void
+context_background_red_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpContext *context;
+ GimpRGB color;
+ GimpActionSelectType select_type;
+ return_if_no_context (context, data);
+
+ select_type = (GimpActionSelectType) g_variant_get_int32 (value);
+
+ gimp_context_get_background (context, &color);
+ color.r = action_select_value (select_type,
+ color.r,
+ 0.0, 1.0, 1.0,
+ 1.0 / 255.0, 0.01, 0.1, 0.0, FALSE);
+ gimp_context_set_background (context, &color);
+}
+
+void
+context_background_green_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpContext *context;
+ GimpRGB color;
+ GimpActionSelectType select_type;
+ return_if_no_context (context, data);
+
+ select_type = (GimpActionSelectType) g_variant_get_int32 (value);
+
+ gimp_context_get_background (context, &color);
+ color.g = action_select_value (select_type,
+ color.g,
+ 0.0, 1.0, 1.0,
+ 1.0 / 255.0, 0.01, 0.1, 0.0, FALSE);
+ gimp_context_set_background (context, &color);
+}
+
+void
+context_background_blue_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpContext *context;
+ GimpRGB color;
+ GimpActionSelectType select_type;
+ return_if_no_context (context, data);
+
+ select_type = (GimpActionSelectType) g_variant_get_int32 (value);
+
+ gimp_context_get_background (context, &color);
+ color.b = action_select_value (select_type,
+ color.b,
+ 0.0, 1.0, 1.0,
+ 1.0 / 255.0, 0.01, 0.1, 0.0, FALSE);
+ gimp_context_set_background (context, &color);
+}
+
+void
+context_foreground_hue_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpContext *context;
+ GimpRGB color;
+ GimpHSV hsv;
+ GimpActionSelectType select_type;
+ return_if_no_context (context, data);
+
+ select_type = (GimpActionSelectType) g_variant_get_int32 (value);
+
+ gimp_context_get_foreground (context, &color);
+ gimp_rgb_to_hsv (&color, &hsv);
+ hsv.h = action_select_value (select_type,
+ hsv.h,
+ 0.0, 1.0, 1.0,
+ 1.0 / 360.0, 0.01, 0.1, 0.0, FALSE);
+ gimp_hsv_to_rgb (&hsv, &color);
+ gimp_context_set_foreground (context, &color);
+}
+
+void
+context_foreground_saturation_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpContext *context;
+ GimpRGB color;
+ GimpHSV hsv;
+ GimpActionSelectType select_type;
+ return_if_no_context (context, data);
+
+ select_type = (GimpActionSelectType) g_variant_get_int32 (value);
+
+ gimp_context_get_foreground (context, &color);
+ gimp_rgb_to_hsv (&color, &hsv);
+ hsv.s = action_select_value (select_type,
+ hsv.s,
+ 0.0, 1.0, 1.0,
+ 0.01, 0.01, 0.1, 0.0, FALSE);
+ gimp_hsv_to_rgb (&hsv, &color);
+ gimp_context_set_foreground (context, &color);
+}
+
+void
+context_foreground_value_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpContext *context;
+ GimpRGB color;
+ GimpHSV hsv;
+ GimpActionSelectType select_type;
+ return_if_no_context (context, data);
+
+ select_type = (GimpActionSelectType) g_variant_get_int32 (value);
+
+ gimp_context_get_foreground (context, &color);
+ gimp_rgb_to_hsv (&color, &hsv);
+ hsv.v = action_select_value (select_type,
+ hsv.v,
+ 0.0, 1.0, 1.0,
+ 0.01, 0.01, 0.1, 0.0, FALSE);
+ gimp_hsv_to_rgb (&hsv, &color);
+ gimp_context_set_foreground (context, &color);
+}
+
+void
+context_background_hue_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpContext *context;
+ GimpRGB color;
+ GimpHSV hsv;
+ GimpActionSelectType select_type;
+ return_if_no_context (context, data);
+
+ select_type = (GimpActionSelectType) g_variant_get_int32 (value);
+
+ gimp_context_get_background (context, &color);
+ gimp_rgb_to_hsv (&color, &hsv);
+ hsv.h = action_select_value (select_type,
+ hsv.h,
+ 0.0, 1.0, 1.0,
+ 1.0 / 360.0, 0.01, 0.1, 0.0, FALSE);
+ gimp_hsv_to_rgb (&hsv, &color);
+ gimp_context_set_background (context, &color);
+}
+
+void
+context_background_saturation_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpContext *context;
+ GimpRGB color;
+ GimpHSV hsv;
+ GimpActionSelectType select_type;
+ return_if_no_context (context, data);
+
+ select_type = (GimpActionSelectType) g_variant_get_int32 (value);
+
+ gimp_context_get_background (context, &color);
+ gimp_rgb_to_hsv (&color, &hsv);
+ hsv.s = action_select_value (select_type,
+ hsv.s,
+ 0.0, 1.0, 1.0,
+ 0.01, 0.01, 0.1, 0.0, FALSE);
+ gimp_hsv_to_rgb (&hsv, &color);
+ gimp_context_set_background (context, &color);
+}
+
+void
+context_background_value_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpContext *context;
+ GimpRGB color;
+ GimpHSV hsv;
+ GimpActionSelectType select_type;
+ return_if_no_context (context, data);
+
+ select_type = (GimpActionSelectType) g_variant_get_int32 (value);
+
+ gimp_context_get_background (context, &color);
+ gimp_rgb_to_hsv (&color, &hsv);
+ hsv.v = action_select_value (select_type,
+ hsv.v,
+ 0.0, 1.0, 1.0,
+ 0.01, 0.01, 0.1, 0.0, FALSE);
+ gimp_hsv_to_rgb (&hsv, &color);
+ gimp_context_set_background (context, &color);
+}
+
+void
+context_opacity_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpContext *context;
+ GimpToolInfo *tool_info;
+ GimpActionSelectType select_type;
+ return_if_no_context (context, data);
+
+ select_type = (GimpActionSelectType) g_variant_get_int32 (value);
+
+ tool_info = gimp_context_get_tool (context);
+
+ if (tool_info && GIMP_IS_TOOL_OPTIONS (tool_info->tool_options))
+ {
+ action_select_property (select_type,
+ action_data_get_display (data),
+ G_OBJECT (tool_info->tool_options),
+ "opacity",
+ 1.0 / 255.0, 0.01, 0.1, 0.1, FALSE);
+ }
+}
+
+void
+context_paint_mode_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpContext *context;
+ GimpToolInfo *tool_info;
+ GimpLayerMode *modes;
+ gint n_modes;
+ GimpLayerMode paint_mode;
+ gint index;
+ GimpActionSelectType select_type;
+ return_if_no_context (context, data);
+
+ select_type = (GimpActionSelectType) g_variant_get_int32 (value);
+
+ paint_mode = gimp_context_get_paint_mode (context);
+
+ modes = gimp_layer_mode_get_context_array (paint_mode,
+ GIMP_LAYER_MODE_CONTEXT_PAINT,
+ &n_modes);
+ index = context_paint_mode_index (paint_mode, modes, n_modes);
+ index = action_select_value (select_type,
+ index, 0, n_modes - 1, 0,
+ 0.0, 1.0, 1.0, 0.0, FALSE);
+ paint_mode = modes[index];
+ g_free (modes);
+
+ gimp_context_set_paint_mode (context, paint_mode);
+
+ tool_info = gimp_context_get_tool (context);
+
+ if (tool_info && GIMP_IS_TOOL_OPTIONS (tool_info->tool_options))
+ {
+ GimpDisplay *display;
+ const char *value_desc;
+
+ gimp_enum_get_value (GIMP_TYPE_LAYER_MODE, paint_mode,
+ NULL, NULL, &value_desc, NULL);
+
+ display = action_data_get_display (data);
+
+ if (value_desc && display)
+ {
+ action_message (display, G_OBJECT (tool_info->tool_options),
+ _("Paint Mode: %s"), value_desc);
+ }
+ }
+}
+
+void
+context_tool_select_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpContext *context;
+ GimpActionSelectType select_type;
+ return_if_no_context (context, data);
+
+ select_type = (GimpActionSelectType) g_variant_get_int32 (value);
+
+ context_select_object (select_type,
+ context, context->gimp->tool_info_list);
+}
+
+void
+context_brush_select_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpContext *context;
+ GimpActionSelectType select_type;
+ return_if_no_context (context, data);
+
+ select_type = (GimpActionSelectType) g_variant_get_int32 (value);
+
+ context_select_object (select_type,
+ context,
+ gimp_data_factory_get_container (context->gimp->brush_factory));
+}
+
+void
+context_pattern_select_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpContext *context;
+ GimpActionSelectType select_type;
+ return_if_no_context (context, data);
+
+ select_type = (GimpActionSelectType) g_variant_get_int32 (value);
+
+ context_select_object (select_type,
+ context,
+ gimp_data_factory_get_container (context->gimp->pattern_factory));
+}
+
+void
+context_palette_select_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpContext *context;
+ GimpActionSelectType select_type;
+ return_if_no_context (context, data);
+
+ select_type = (GimpActionSelectType) g_variant_get_int32 (value);
+
+ context_select_object (select_type,
+ context,
+ gimp_data_factory_get_container (context->gimp->palette_factory));
+}
+
+void
+context_gradient_select_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpContext *context;
+ GimpActionSelectType select_type;
+ return_if_no_context (context, data);
+
+ select_type = (GimpActionSelectType) g_variant_get_int32 (value);
+
+ context_select_object (select_type,
+ context,
+ gimp_data_factory_get_container (context->gimp->gradient_factory));
+}
+
+void
+context_font_select_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpContext *context;
+ GimpActionSelectType select_type;
+ return_if_no_context (context, data);
+
+ select_type = (GimpActionSelectType) g_variant_get_int32 (value);
+
+ context_select_object (select_type,
+ context,
+ gimp_data_factory_get_container (context->gimp->font_factory));
+}
+
+void
+context_brush_spacing_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpContext *context;
+ GimpBrush *brush;
+ GimpActionSelectType select_type;
+ return_if_no_context (context, data);
+
+ select_type = (GimpActionSelectType) g_variant_get_int32 (value);
+
+ brush = gimp_context_get_brush (context);
+
+ if (GIMP_IS_BRUSH (brush) && gimp_data_is_writable (GIMP_DATA (brush)))
+ {
+ action_select_property (select_type,
+ action_data_get_display (data),
+ G_OBJECT (brush),
+ "spacing",
+ 1.0, 5.0, 20.0, 0.1, FALSE);
+ }
+}
+
+void
+context_brush_shape_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpContext *context;
+ GimpBrush *brush;
+ GimpBrushGeneratedShape shape;
+ return_if_no_context (context, data);
+
+ shape = (GimpBrushGeneratedShape) g_variant_get_int32 (value);
+
+ brush = gimp_context_get_brush (context);
+
+ if (GIMP_IS_BRUSH_GENERATED (brush) &&
+ gimp_data_is_writable (GIMP_DATA (brush)))
+ {
+ GimpBrushGenerated *generated = GIMP_BRUSH_GENERATED (brush);
+ GimpDisplay *display;
+ const char *value_desc;
+
+ gimp_brush_generated_set_shape (generated, shape);
+
+ gimp_enum_get_value (GIMP_TYPE_BRUSH_GENERATED_SHAPE, shape,
+ NULL, NULL, &value_desc, NULL);
+ display = action_data_get_display (data);
+
+ if (value_desc && display)
+ {
+ action_message (display, G_OBJECT (brush),
+ _("Brush Shape: %s"), value_desc);
+ }
+ }
+}
+
+void
+context_brush_radius_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpContext *context;
+ GimpBrush *brush;
+ GimpActionSelectType select_type;
+ return_if_no_context (context, data);
+
+ select_type = (GimpActionSelectType) g_variant_get_int32 (value);
+
+ brush = gimp_context_get_brush (context);
+
+ if (GIMP_IS_BRUSH_GENERATED (brush) &&
+ gimp_data_is_writable (GIMP_DATA (brush)))
+ {
+ GimpBrushGenerated *generated = GIMP_BRUSH_GENERATED (brush);
+ GimpDisplay *display;
+ gdouble radius;
+ gdouble min_radius;
+
+ radius = gimp_brush_generated_get_radius (generated);
+
+ /* If the user uses a high precision radius adjustment command
+ * then we allow a minimum radius of 0.1 px, otherwise we set the
+ * minimum radius to 1.0 px and adjust the radius to 1.0 px if it
+ * is less than 1.0 px. This prevents irritating 0.1, 1.1, 2.1 etc
+ * radius sequences when 1.0 px steps are used.
+ */
+ switch (select_type)
+ {
+ case GIMP_ACTION_SELECT_SMALL_PREVIOUS:
+ case GIMP_ACTION_SELECT_SMALL_NEXT:
+ case GIMP_ACTION_SELECT_PERCENT_PREVIOUS:
+ case GIMP_ACTION_SELECT_PERCENT_NEXT:
+ min_radius = 0.1;
+ break;
+
+ default:
+ min_radius = 1.0;
+
+ if (radius < 1.0)
+ radius = 1.0;
+ break;
+ }
+
+ radius = action_select_value (select_type,
+ radius,
+ min_radius, 4000.0, min_radius,
+ 0.1, 1.0, 10.0, 0.05, FALSE);
+ gimp_brush_generated_set_radius (generated, radius);
+
+ display = action_data_get_display (data);
+
+ if (display)
+ {
+ action_message (action_data_get_display (data), G_OBJECT (brush),
+ _("Brush Radius: %2.2f"), radius);
+ }
+ }
+}
+
+void
+context_brush_spikes_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpContext *context;
+ GimpBrush *brush;
+ GimpActionSelectType select_type;
+ return_if_no_context (context, data);
+
+ select_type = (GimpActionSelectType) g_variant_get_int32 (value);
+
+ brush = gimp_context_get_brush (context);
+
+ if (GIMP_IS_BRUSH_GENERATED (brush) &&
+ gimp_data_is_writable (GIMP_DATA (brush)))
+ {
+ action_select_property (select_type,
+ action_data_get_display (data),
+ G_OBJECT (brush),
+ "spikes",
+ 0.0, 1.0, 4.0, 0.1, FALSE);
+ }
+}
+
+void
+context_brush_hardness_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpContext *context;
+ GimpBrush *brush;
+ GimpActionSelectType select_type;
+ return_if_no_context (context, data);
+
+ select_type = (GimpActionSelectType) g_variant_get_int32 (value);
+
+ brush = gimp_context_get_brush (context);
+
+ if (GIMP_IS_BRUSH_GENERATED (brush) &&
+ gimp_data_is_writable (GIMP_DATA (brush)))
+ {
+ action_select_property (select_type,
+ action_data_get_display (data),
+ G_OBJECT (brush),
+ "hardness",
+ 0.001, 0.01, 0.1, 0.1, FALSE);
+ }
+}
+
+void
+context_brush_aspect_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpContext *context;
+ GimpBrush *brush;
+ GimpActionSelectType select_type;
+ return_if_no_context (context, data);
+
+ select_type = (GimpActionSelectType) g_variant_get_int32 (value);
+
+ brush = gimp_context_get_brush (context);
+
+ if (GIMP_IS_BRUSH_GENERATED (brush) &&
+ gimp_data_is_writable (GIMP_DATA (brush)))
+ {
+ action_select_property (select_type,
+ action_data_get_display (data),
+ G_OBJECT (brush),
+ "aspect-ratio",
+ 0.1, 1.0, 4.0, 0.1, FALSE);
+ }
+}
+
+void
+context_brush_angle_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpContext *context;
+ GimpBrush *brush;
+ GimpActionSelectType select_type;
+ return_if_no_context (context, data);
+
+ select_type = (GimpActionSelectType) g_variant_get_int32 (value);
+
+ brush = gimp_context_get_brush (context);
+
+ if (GIMP_IS_BRUSH_GENERATED (brush) &&
+ gimp_data_is_writable (GIMP_DATA (brush)))
+ {
+ GimpBrushGenerated *generated = GIMP_BRUSH_GENERATED (brush);
+ GimpDisplay *display;
+ gdouble angle;
+
+ angle = gimp_brush_generated_get_angle (generated);
+
+ if (select_type == GIMP_ACTION_SELECT_FIRST)
+ angle = 0.0;
+ else if (select_type == GIMP_ACTION_SELECT_LAST)
+ angle = 90.0;
+ else
+ angle = action_select_value (select_type,
+ angle,
+ 0.0, 180.0, 0.0,
+ 0.1, 1.0, 15.0, 0.1, TRUE);
+
+ gimp_brush_generated_set_angle (generated, angle);
+
+ display = action_data_get_display (data);
+
+ if (display)
+ {
+ action_message (action_data_get_display (data), G_OBJECT (brush),
+ _("Brush Angle: %2.2f"), angle);
+ }
+ }
+}
+
+
+/* private functions */
+
+static void
+context_select_object (GimpActionSelectType select_type,
+ GimpContext *context,
+ GimpContainer *container)
+{
+ GimpObject *current;
+
+ current =
+ gimp_context_get_by_type (context,
+ gimp_container_get_children_type (container));
+
+ current = action_select_object (select_type, container, current);
+
+ if (current)
+ gimp_context_set_by_type (context,
+ gimp_container_get_children_type (container),
+ current);
+}
+
+static gint
+context_paint_mode_index (GimpLayerMode paint_mode,
+ const GimpLayerMode *modes,
+ gint n_modes)
+{
+ gint i = 0;
+
+ while (i < (n_modes - 1) && modes[i] != paint_mode)
+ i++;
+
+ return i;
+}
+
+static void
+context_select_color (GimpActionSelectType select_type,
+ GimpRGB *color,
+ gboolean use_colormap,
+ gboolean use_palette)
+{
+ gint index;
+ gint max;
+
+ index = context_get_color_index (use_colormap, use_palette, color);
+ max = context_max_color_index (use_colormap, use_palette);
+
+ index = action_select_value (select_type,
+ index,
+ 0, max, 0,
+ 0, 1, 4, 0, FALSE);
+
+ context_set_color_index (index, use_colormap, use_palette, color);
+}
+
+static gint
+context_get_color_index (gboolean use_colormap,
+ gboolean use_palette,
+ const GimpRGB *color)
+{
+ if (use_colormap)
+ {
+ GimpColormapEditor *editor = context_get_colormap_editor ();
+
+ if (editor)
+ {
+ gint index = gimp_colormap_editor_get_index (editor, color);
+
+ if (index != -1)
+ return index;
+ }
+ }
+
+ if (use_palette)
+ {
+ GimpPaletteEditor *editor = context_get_palette_editor ();
+
+ if (editor)
+ {
+ gint index = gimp_palette_editor_get_index (editor, color);
+
+ if (index != -1)
+ return index;
+ }
+ }
+
+ return 0;
+}
+
+static gint
+context_max_color_index (gboolean use_colormap,
+ gboolean use_palette)
+{
+ if (use_colormap)
+ {
+ GimpColormapEditor *editor = context_get_colormap_editor ();
+
+ if (editor)
+ {
+ gint index = gimp_colormap_editor_max_index (editor);
+
+ if (index != -1)
+ return index;
+ }
+ }
+
+ if (use_palette)
+ {
+ GimpPaletteEditor *editor = context_get_palette_editor ();
+
+ if (editor)
+ {
+ gint index = gimp_palette_editor_max_index (editor);
+
+ if (index != -1)
+ return index;
+ }
+ }
+
+ return 0;
+}
+
+static gboolean
+context_set_color_index (gint index,
+ gboolean use_colormap,
+ gboolean use_palette,
+ GimpRGB *color)
+{
+ if (use_colormap)
+ {
+ GimpColormapEditor *editor = context_get_colormap_editor ();
+
+ if (editor && gimp_colormap_editor_set_index (editor, index, color))
+ return TRUE;
+ }
+
+ if (use_palette)
+ {
+ GimpPaletteEditor *editor = context_get_palette_editor ();
+
+ if (editor && gimp_palette_editor_set_index (editor, index, color))
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static GimpPaletteEditor *
+context_get_palette_editor (void)
+{
+ GtkWidget *widget;
+
+ g_return_val_if_fail (GIMP_IS_DIALOG_FACTORY (gimp_dialog_factory_get_singleton ()), NULL);
+
+ widget = gimp_dialog_factory_find_widget (gimp_dialog_factory_get_singleton (),
+ "gimp-palette-editor");
+ if (widget)
+ return GIMP_PALETTE_EDITOR (gtk_bin_get_child (GTK_BIN (widget)));
+
+ return NULL;
+}
+
+static GimpColormapEditor *
+context_get_colormap_editor (void)
+{
+ GtkWidget *widget;
+
+ g_return_val_if_fail (GIMP_IS_DIALOG_FACTORY (gimp_dialog_factory_get_singleton ()), NULL);
+
+ widget = gimp_dialog_factory_find_widget (gimp_dialog_factory_get_singleton (),
+ "gimp-indexed-palette");
+ if (widget)
+ return GIMP_COLORMAP_EDITOR (gtk_bin_get_child (GTK_BIN (widget)));
+
+ return NULL;
+}
diff --git a/app/actions/context-commands.h b/app/actions/context-commands.h
new file mode 100644
index 0000000..76fe716
--- /dev/null
+++ b/app/actions/context-commands.h
@@ -0,0 +1,140 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __CONTEXT_COMMANDS_H__
+#define __CONTEXT_COMMANDS_H__
+
+
+
+void context_colors_default_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void context_colors_swap_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+void context_palette_foreground_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void context_palette_background_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+void context_colormap_foreground_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void context_colormap_background_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+void context_swatch_foreground_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void context_swatch_background_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+void context_foreground_red_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void context_foreground_green_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void context_foreground_blue_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+void context_background_red_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void context_background_green_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void context_background_blue_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+void context_foreground_hue_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void context_foreground_saturation_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void context_foreground_value_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+void context_background_hue_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void context_background_saturation_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void context_background_value_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+void context_opacity_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void context_paint_mode_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+void context_tool_select_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void context_brush_select_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void context_pattern_select_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void context_palette_select_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void context_gradient_select_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void context_font_select_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+void context_brush_spacing_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void context_brush_shape_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void context_brush_radius_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void context_brush_spikes_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void context_brush_hardness_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void context_brush_aspect_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void context_brush_angle_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+
+#endif /* __CONTEXT_COMMANDS_H__ */
diff --git a/app/actions/cursor-info-actions.c b/app/actions/cursor-info-actions.c
new file mode 100644
index 0000000..bef1106
--- /dev/null
+++ b/app/actions/cursor-info-actions.c
@@ -0,0 +1,81 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "actions-types.h"
+
+#include "widgets/gimpactiongroup.h"
+#include "widgets/gimphelp-ids.h"
+
+#include "display/gimpcursorview.h"
+
+#include "cursor-info-actions.h"
+#include "cursor-info-commands.h"
+
+#include "gimp-intl.h"
+
+
+static const GimpActionEntry cursor_info_actions[] =
+{
+ { "cursor-info-popup", GIMP_ICON_CURSOR,
+ NC_("cursor-info-action", "Pointer Information Menu"), NULL, NULL, NULL,
+ GIMP_HELP_POINTER_INFO_DIALOG }
+};
+
+static const GimpToggleActionEntry cursor_info_toggle_actions[] =
+{
+ { "cursor-info-sample-merged", NULL,
+ NC_("cursor-info-action", "_Sample Merged"), "",
+ NC_("cursor-info-action", "Use the composite color of all visible layers"),
+ cursor_info_sample_merged_cmd_callback,
+ TRUE,
+ GIMP_HELP_POINTER_INFO_SAMPLE_MERGED }
+};
+
+
+void
+cursor_info_actions_setup (GimpActionGroup *group)
+{
+ gimp_action_group_add_actions (group, "cursor-info-action",
+ cursor_info_actions,
+ G_N_ELEMENTS (cursor_info_actions));
+
+ gimp_action_group_add_toggle_actions (group, "cursor-info-action",
+ cursor_info_toggle_actions,
+ G_N_ELEMENTS (cursor_info_toggle_actions));
+}
+
+void
+cursor_info_actions_update (GimpActionGroup *group,
+ gpointer data)
+{
+ GimpCursorView *view = GIMP_CURSOR_VIEW (data);
+
+#define SET_ACTIVE(action,condition) \
+ gimp_action_group_set_action_active (group, action, (condition) != 0)
+
+ SET_ACTIVE ("cursor-info-sample-merged",
+ gimp_cursor_view_get_sample_merged (view));
+
+#undef SET_ACTIVE
+}
diff --git a/app/actions/cursor-info-actions.h b/app/actions/cursor-info-actions.h
new file mode 100644
index 0000000..58b3f71
--- /dev/null
+++ b/app/actions/cursor-info-actions.h
@@ -0,0 +1,27 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __CURSOR_INFO_ACIONS_H__
+#define __CURSOR_INFO_ACIONS_H__
+
+
+void cursor_info_actions_setup (GimpActionGroup *group);
+void cursor_info_actions_update (GimpActionGroup *group,
+ gpointer data);
+
+
+#endif /* __CURSOR_INFO_ACTIONS_H__ */
diff --git a/app/actions/cursor-info-commands.c b/app/actions/cursor-info-commands.c
new file mode 100644
index 0000000..b5f760b
--- /dev/null
+++ b/app/actions/cursor-info-commands.c
@@ -0,0 +1,41 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "actions-types.h"
+
+#include "display/gimpcursorview.h"
+
+#include "cursor-info-commands.h"
+
+
+/* public functions */
+
+void
+cursor_info_sample_merged_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpCursorView *view = GIMP_CURSOR_VIEW (data);
+ gboolean active = g_variant_get_boolean (value);
+
+ gimp_cursor_view_set_sample_merged (view, active);
+}
diff --git a/app/actions/cursor-info-commands.h b/app/actions/cursor-info-commands.h
new file mode 100644
index 0000000..3562e15
--- /dev/null
+++ b/app/actions/cursor-info-commands.h
@@ -0,0 +1,27 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __CURSOR_INFO_COMMANDS_H__
+#define __CURSOR_INFO_COMMANDS_H__
+
+
+void cursor_info_sample_merged_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+
+#endif /* __CURSOR_INFO_COMMANDS_H__ */
diff --git a/app/actions/dashboard-actions.c b/app/actions/dashboard-actions.c
new file mode 100644
index 0000000..e471307
--- /dev/null
+++ b/app/actions/dashboard-actions.c
@@ -0,0 +1,230 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "actions-types.h"
+
+#include "widgets/gimpactiongroup.h"
+#include "widgets/gimpdashboard.h"
+#include "widgets/gimphelp-ids.h"
+
+#include "dashboard-actions.h"
+#include "dashboard-commands.h"
+
+#include "gimp-intl.h"
+
+
+static const GimpActionEntry dashboard_actions[] =
+{
+ { "dashboard-popup", GIMP_ICON_DIALOG_DASHBOARD,
+ NC_("dashboard-action", "Dashboard Menu"), NULL, NULL, NULL,
+ GIMP_HELP_DASHBOARD_DIALOG },
+
+ { "dashboard-groups", NULL,
+ NC_("dashboard-action", "_Groups") },
+ { "dashboard-update-interval", NULL,
+ NC_("dashboard-action", "_Update Interval") },
+ { "dashboard-history-duration", NULL,
+ NC_("dashboard-action", "_History Duration") },
+
+ { "dashboard-log-record", GIMP_ICON_RECORD,
+ NC_("dashboard-action", "_Start/Stop Recording..."), NULL,
+ NC_("dashboard-action", "Start/stop recording performance log"),
+ dashboard_log_record_cmd_callback,
+ GIMP_HELP_DASHBOARD_LOG_RECORD },
+ { "dashboard-log-add-marker", GIMP_ICON_MARKER,
+ NC_("dashboard-action", "_Add Marker..."), NULL,
+ NC_("dashboard-action", "Add an event marker "
+ "to the performance log"),
+ dashboard_log_add_marker_cmd_callback,
+ GIMP_HELP_DASHBOARD_LOG_ADD_MARKER },
+ { "dashboard-log-add-empty-marker", GIMP_ICON_MARKER,
+ NC_("dashboard-action", "Add _Empty Marker"), NULL,
+ NC_("dashboard-action", "Add an empty event marker "
+ "to the performance log"),
+ dashboard_log_add_empty_marker_cmd_callback,
+ GIMP_HELP_DASHBOARD_LOG_ADD_EMPTY_MARKER },
+
+ { "dashboard-reset", GIMP_ICON_RESET,
+ NC_("dashboard-action", "_Reset"), NULL,
+ NC_("dashboard-action", "Reset cumulative data"),
+ dashboard_reset_cmd_callback,
+ GIMP_HELP_DASHBOARD_RESET },
+};
+
+static const GimpToggleActionEntry dashboard_toggle_actions[] =
+{
+ { "dashboard-low-swap-space-warning", NULL,
+ NC_("dashboard-action", "_Low Swap Space Warning"), NULL,
+ NC_("dashboard-action", "Raise the dashboard when "
+ "the swap size approaches its limit"),
+ dashboard_low_swap_space_warning_cmd_callback,
+ FALSE,
+ GIMP_HELP_DASHBOARD_LOW_SWAP_SPACE_WARNING }
+};
+
+static const GimpRadioActionEntry dashboard_update_interval_actions[] =
+{
+ { "dashboard-update-interval-0-25-sec", NULL,
+ NC_("dashboard-update-interval", "0.25 Seconds"), NULL, NULL,
+ GIMP_DASHBOARD_UPDATE_INTERVAL_0_25_SEC,
+ GIMP_HELP_DASHBOARD_UPDATE_INTERVAL },
+
+ { "dashboard-update-interval-0-5-sec", NULL,
+ NC_("dashboard-update-interval", "0.5 Seconds"), NULL, NULL,
+ GIMP_DASHBOARD_UPDATE_INTERVAL_0_5_SEC,
+ GIMP_HELP_DASHBOARD_UPDATE_INTERVAL },
+
+ { "dashboard-update-interval-1-sec", NULL,
+ NC_("dashboard-update-interval", "1 Second"), NULL, NULL,
+ GIMP_DASHBOARD_UPDATE_INTERVAL_1_SEC,
+ GIMP_HELP_DASHBOARD_UPDATE_INTERVAL },
+
+ { "dashboard-update-interval-2-sec", NULL,
+ NC_("dashboard-update-interval", "2 Seconds"), NULL, NULL,
+ GIMP_DASHBOARD_UPDATE_INTERVAL_2_SEC,
+ GIMP_HELP_DASHBOARD_UPDATE_INTERVAL },
+
+ { "dashboard-update-interval-4-sec", NULL,
+ NC_("dashboard-update-interval", "4 Seconds"), NULL, NULL,
+ GIMP_DASHBOARD_UPDATE_INTERVAL_4_SEC,
+ GIMP_HELP_DASHBOARD_UPDATE_INTERVAL }
+};
+
+static const GimpRadioActionEntry dashboard_history_duration_actions[] =
+{
+ { "dashboard-history-duration-15-sec", NULL,
+ NC_("dashboard-history-duration", "15 Seconds"), NULL, NULL,
+ GIMP_DASHBOARD_HISTORY_DURATION_15_SEC,
+ GIMP_HELP_DASHBOARD_HISTORY_DURATION },
+
+ { "dashboard-history-duration-30-sec", NULL,
+ NC_("dashboard-history-duration", "30 Seconds"), NULL, NULL,
+ GIMP_DASHBOARD_HISTORY_DURATION_30_SEC,
+ GIMP_HELP_DASHBOARD_HISTORY_DURATION },
+
+ { "dashboard-history-duration-60-sec", NULL,
+ NC_("dashboard-history-duration", "60 Seconds"), NULL, NULL,
+ GIMP_DASHBOARD_HISTORY_DURATION_60_SEC,
+ GIMP_HELP_DASHBOARD_HISTORY_DURATION },
+
+ { "dashboard-history-duration-120-sec", NULL,
+ NC_("dashboard-history-duration", "120 Seconds"), NULL, NULL,
+ GIMP_DASHBOARD_HISTORY_DURATION_120_SEC,
+ GIMP_HELP_DASHBOARD_HISTORY_DURATION },
+
+ { "dashboard-history-duration-240-sec", NULL,
+ NC_("dashboard-history-duration", "240 Seconds"), NULL, NULL,
+ GIMP_DASHBOARD_HISTORY_DURATION_240_SEC,
+ GIMP_HELP_DASHBOARD_HISTORY_DURATION }
+};
+
+
+void
+dashboard_actions_setup (GimpActionGroup *group)
+{
+ gimp_action_group_add_actions (group, "dashboard-action",
+ dashboard_actions,
+ G_N_ELEMENTS (dashboard_actions));
+
+ gimp_action_group_add_toggle_actions (group, "dashboard-action",
+ dashboard_toggle_actions,
+ G_N_ELEMENTS (dashboard_toggle_actions));
+
+ gimp_action_group_add_radio_actions (group, "dashboard-update-interval",
+ dashboard_update_interval_actions,
+ G_N_ELEMENTS (dashboard_update_interval_actions),
+ NULL,
+ 0,
+ dashboard_update_interval_cmd_callback);
+
+ gimp_action_group_add_radio_actions (group, "dashboard-history-duration",
+ dashboard_history_duration_actions,
+ G_N_ELEMENTS (dashboard_history_duration_actions),
+ NULL,
+ 0,
+ dashboard_history_duration_cmd_callback);
+}
+
+void
+dashboard_actions_update (GimpActionGroup *group,
+ gpointer data)
+{
+ GimpDashboard *dashboard = GIMP_DASHBOARD (data);
+ gboolean recording;
+
+ recording = gimp_dashboard_log_is_recording (dashboard);
+
+#define SET_SENSITIVE(action,condition) \
+ gimp_action_group_set_action_sensitive (group, action, (condition) != 0)
+#define SET_ACTIVE(action,condition) \
+ gimp_action_group_set_action_active (group, action, (condition) != 0)
+
+ switch (gimp_dashboard_get_update_interval (dashboard))
+ {
+ case GIMP_DASHBOARD_UPDATE_INTERVAL_0_25_SEC:
+ SET_ACTIVE ("dashboard-update-interval-0-25-sec", TRUE);
+ break;
+ case GIMP_DASHBOARD_UPDATE_INTERVAL_0_5_SEC:
+ SET_ACTIVE ("dashboard-update-interval-0-5-sec", TRUE);
+ break;
+ case GIMP_DASHBOARD_UPDATE_INTERVAL_1_SEC:
+ SET_ACTIVE ("dashboard-update-interval-1-sec", TRUE);
+ break;
+ case GIMP_DASHBOARD_UPDATE_INTERVAL_2_SEC:
+ SET_ACTIVE ("dashboard-update-interval-2-sec", TRUE);
+ break;
+ case GIMP_DASHBOARD_UPDATE_INTERVAL_4_SEC:
+ SET_ACTIVE ("dashboard-update-interval-4-sec", TRUE);
+ break;
+ }
+
+ switch (gimp_dashboard_get_history_duration (dashboard))
+ {
+ case GIMP_DASHBOARD_HISTORY_DURATION_15_SEC:
+ SET_ACTIVE ("dashboard-history-duration-15-sec", TRUE);
+ break;
+ case GIMP_DASHBOARD_HISTORY_DURATION_30_SEC:
+ SET_ACTIVE ("dashboard-history-duration-30-sec", TRUE);
+ break;
+ case GIMP_DASHBOARD_HISTORY_DURATION_60_SEC:
+ SET_ACTIVE ("dashboard-history-duration-60-sec", TRUE);
+ break;
+ case GIMP_DASHBOARD_HISTORY_DURATION_120_SEC:
+ SET_ACTIVE ("dashboard-history-duration-120-sec", TRUE);
+ break;
+ case GIMP_DASHBOARD_HISTORY_DURATION_240_SEC:
+ SET_ACTIVE ("dashboard-history-duration-240-sec", TRUE);
+ break;
+ }
+
+ SET_SENSITIVE ("dashboard-log-add-marker", recording);
+ SET_SENSITIVE ("dashboard-log-add-empty-marker", recording);
+ SET_SENSITIVE ("dashboard-reset", !recording);
+
+ SET_ACTIVE ("dashboard-low-swap-space-warning",
+ gimp_dashboard_get_low_swap_space_warning (dashboard));
+
+#undef SET_SENSITIVE
+#undef SET_ACTIVE
+}
diff --git a/app/actions/dashboard-actions.h b/app/actions/dashboard-actions.h
new file mode 100644
index 0000000..b2f8342
--- /dev/null
+++ b/app/actions/dashboard-actions.h
@@ -0,0 +1,27 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __DASHBOARD_ACTIONS_H__
+#define __DASHBOARD_ACTIONS_H__
+
+
+void dashboard_actions_setup (GimpActionGroup *group);
+void dashboard_actions_update (GimpActionGroup *group,
+ gpointer data);
+
+
+#endif /* __DASHBOARD_ACTIONS_H__ */
diff --git a/app/actions/dashboard-commands.c b/app/actions/dashboard-commands.c
new file mode 100644
index 0000000..c1112aa
--- /dev/null
+++ b/app/actions/dashboard-commands.c
@@ -0,0 +1,406 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "actions-types.h"
+
+#include "core/gimp.h"
+
+#include "widgets/gimpdashboard.h"
+#include "widgets/gimphelp-ids.h"
+#include "widgets/gimpuimanager.h"
+
+#include "dialogs/dialogs.h"
+
+#include "dashboard-commands.h"
+
+#include "gimp-intl.h"
+
+
+typedef struct
+{
+ GFile *folder;
+ GimpDashboardLogParams params;
+} DashboardLogDialogInfo;
+
+
+/* local function prototypes */
+
+static void dashboard_log_record_response (GtkWidget *dialog,
+ int response_id,
+ GimpDashboard *dashboard);
+
+static void dashboard_log_add_marker_response (GtkWidget *dialog,
+ const gchar *description,
+ GimpDashboard *dashboard);
+
+static DashboardLogDialogInfo * dashboard_log_dialog_info_new (GimpDashboard *dashboard);
+static void dashboard_log_dialog_info_free (DashboardLogDialogInfo *info);
+
+
+/* public functions */
+
+
+void
+dashboard_update_interval_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpDashboard *dashboard = GIMP_DASHBOARD (data);
+ GimpDashboardUpdateInteval update_interval;
+
+ update_interval = g_variant_get_int32 (value);
+
+ gimp_dashboard_set_update_interval (dashboard, update_interval);
+}
+
+void
+dashboard_history_duration_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpDashboard *dashboard = GIMP_DASHBOARD (data);
+ GimpDashboardHistoryDuration history_duration;
+
+ history_duration = g_variant_get_int32 (value);
+
+ gimp_dashboard_set_history_duration (dashboard, history_duration);
+}
+
+void
+dashboard_log_record_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpDashboard *dashboard = GIMP_DASHBOARD (data);
+
+ if (! gimp_dashboard_log_is_recording (dashboard))
+ {
+ GtkWidget *dialog;
+
+ #define LOG_RECORD_KEY "gimp-dashboard-log-record-dialog"
+
+ dialog = dialogs_get_dialog (G_OBJECT (dashboard), LOG_RECORD_KEY);
+
+ if (! dialog)
+ {
+ GtkFileFilter *filter;
+ DashboardLogDialogInfo *info;
+ GtkWidget *hbox;
+ GtkWidget *hbox2;
+ GtkWidget *label;
+ GtkWidget *spinbutton;
+ GtkWidget *toggle;
+
+ dialog = gtk_file_chooser_dialog_new (
+ "Record Performance Log", NULL, GTK_FILE_CHOOSER_ACTION_SAVE,
+
+ _("_Cancel"), GTK_RESPONSE_CANCEL,
+ _("_Record"), GTK_RESPONSE_OK,
+
+ NULL);
+
+ gtk_dialog_set_default_response (GTK_DIALOG (dialog),
+ GTK_RESPONSE_OK);
+ gtk_dialog_set_alternative_button_order (GTK_DIALOG (dialog),
+ GTK_RESPONSE_OK,
+ GTK_RESPONSE_CANCEL,
+ -1);
+
+ gtk_window_set_screen (
+ GTK_WINDOW (dialog),
+ gtk_widget_get_screen (GTK_WIDGET (dashboard)));
+ gtk_window_set_role (GTK_WINDOW (dialog),
+ "gimp-dashboard-log-record");
+ gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE);
+
+ gtk_file_chooser_set_do_overwrite_confirmation (
+ GTK_FILE_CHOOSER (dialog), TRUE);
+
+ filter = gtk_file_filter_new ();
+ gtk_file_filter_set_name (filter, _("All Files"));
+ gtk_file_filter_add_pattern (filter, "*");
+ gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
+
+ filter = gtk_file_filter_new ();
+ gtk_file_filter_set_name (filter, _("Log Files (*.log)"));
+ gtk_file_filter_add_pattern (filter, "*.log");
+ gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
+
+ gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (dialog), filter);
+
+ info = g_object_get_data (G_OBJECT (dashboard),
+ "gimp-dashboard-log-dialog-info");
+
+ if (! info)
+ {
+ info = dashboard_log_dialog_info_new (dashboard);
+
+ g_object_set_data_full (
+ G_OBJECT (dashboard),
+ "gimp-dashboard-log-dialog-info", info,
+ (GDestroyNotify) dashboard_log_dialog_info_free);
+ }
+
+ if (info->folder)
+ {
+ gtk_file_chooser_set_current_folder_file (
+ GTK_FILE_CHOOSER (dialog), info->folder, NULL);
+ }
+
+ gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog),
+ "gimp-performance.log");
+
+ hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 8);
+ gtk_file_chooser_set_extra_widget (GTK_FILE_CHOOSER (dialog), hbox);
+ gtk_widget_show (hbox);
+
+ hbox2 = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+ gimp_help_set_help_data (hbox2, _("Log samples per second"), NULL);
+ gtk_box_pack_start (GTK_BOX (hbox), hbox2, FALSE, FALSE, 0);
+ gtk_widget_show (hbox2);
+
+ label = gtk_label_new_with_mnemonic (_("Sample fre_quency:"));
+ gtk_box_pack_start (GTK_BOX (hbox2), label, FALSE, FALSE, 0);
+ gtk_widget_show (label);
+
+ spinbutton = gimp_spin_button_new_with_range (1, 1000, 1);
+ gtk_box_pack_start (GTK_BOX (hbox2), spinbutton, FALSE, FALSE, 0);
+ gtk_widget_show (spinbutton);
+
+ gtk_spin_button_set_value (GTK_SPIN_BUTTON (spinbutton),
+ info->params.sample_frequency);
+
+ g_signal_connect (gtk_spin_button_get_adjustment (
+ GTK_SPIN_BUTTON (spinbutton)),
+ "value-changed",
+ G_CALLBACK (gimp_int_adjustment_update),
+ &info->params.sample_frequency);
+
+ gtk_label_set_mnemonic_widget (GTK_LABEL (label), spinbutton);
+
+ toggle = gtk_check_button_new_with_mnemonic (_("_Backtrace"));
+ gimp_help_set_help_data (toggle, _("Include backtraces in log"),
+ NULL);
+ gtk_box_pack_start (GTK_BOX (hbox), toggle, FALSE, FALSE, 0);
+ gtk_widget_show (toggle);
+
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle),
+ info->params.backtrace);
+
+ g_signal_connect (toggle, "toggled",
+ G_CALLBACK (gimp_toggle_button_update),
+ &info->params.backtrace);
+
+ toggle = gtk_check_button_new_with_mnemonic (_("_Messages"));
+ gimp_help_set_help_data (toggle,
+ _("Include diagnostic messages in log"),
+ NULL);
+ gtk_box_pack_start (GTK_BOX (hbox), toggle, FALSE, FALSE, 0);
+ gtk_widget_show (toggle);
+
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle),
+ info->params.messages);
+
+ g_signal_connect (toggle, "toggled",
+ G_CALLBACK (gimp_toggle_button_update),
+ &info->params.messages);
+
+ toggle = gtk_check_button_new_with_mnemonic (_("Progressi_ve"));
+ gimp_help_set_help_data (toggle,
+ _("Produce complete log "
+ "even if not properly terminated"),
+ NULL);
+ gtk_box_pack_start (GTK_BOX (hbox), toggle, FALSE, FALSE, 0);
+ gtk_widget_show (toggle);
+
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle),
+ info->params.progressive);
+
+ g_signal_connect (toggle, "toggled",
+ G_CALLBACK (gimp_toggle_button_update),
+ &info->params.progressive);
+
+ g_signal_connect (dialog, "response",
+ G_CALLBACK (dashboard_log_record_response),
+ dashboard);
+ g_signal_connect (dialog, "delete-event",
+ G_CALLBACK (gtk_true),
+ NULL);
+
+ gimp_help_connect (dialog, gimp_standard_help_func,
+ GIMP_HELP_DASHBOARD_LOG_RECORD, NULL);
+
+ dialogs_attach_dialog (G_OBJECT (dashboard), LOG_RECORD_KEY, dialog);
+
+ g_signal_connect_object (dashboard, "destroy",
+ G_CALLBACK (gtk_widget_destroy),
+ dialog,
+ G_CONNECT_SWAPPED);
+
+ #undef LOG_RECORD_KEY
+ }
+
+ gtk_window_present (GTK_WINDOW (dialog));
+ }
+ else
+ {
+ GError *error = NULL;
+
+ if (! gimp_dashboard_log_stop_recording (dashboard, &error))
+ {
+ gimp_message_literal (
+ gimp_editor_get_ui_manager (GIMP_EDITOR (dashboard))->gimp,
+ NULL, GIMP_MESSAGE_ERROR, error->message);
+ }
+ }
+}
+
+void
+dashboard_log_add_marker_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpDashboard *dashboard = GIMP_DASHBOARD (data);
+ GtkWidget *dialog;
+
+ #define LOG_ADD_MARKER_KEY "gimp-dashboard-log-add-marker-dialog"
+
+ dialog = dialogs_get_dialog (G_OBJECT (dashboard), LOG_ADD_MARKER_KEY);
+
+ if (! dialog)
+ {
+ dialog = gimp_query_string_box (
+ _("Add Marker"), GTK_WIDGET (dashboard),
+ gimp_standard_help_func, GIMP_HELP_DASHBOARD_LOG_ADD_MARKER,
+ _("Enter a description for the marker"),
+ NULL,
+ G_OBJECT (dashboard), "destroy",
+ (GimpQueryStringCallback) dashboard_log_add_marker_response,
+ dashboard);
+
+ dialogs_attach_dialog (G_OBJECT (dashboard), LOG_ADD_MARKER_KEY, dialog);
+
+ #undef LOG_ADD_MARKER_KEY
+ }
+
+ gtk_window_present (GTK_WINDOW (dialog));
+}
+
+void
+dashboard_log_add_empty_marker_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpDashboard *dashboard = GIMP_DASHBOARD (data);
+
+ gimp_dashboard_log_add_marker (dashboard, NULL);
+}
+
+void
+dashboard_reset_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpDashboard *dashboard = GIMP_DASHBOARD (data);
+
+ gimp_dashboard_reset (dashboard);
+}
+
+void
+dashboard_low_swap_space_warning_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpDashboard *dashboard = GIMP_DASHBOARD (data);
+ gboolean low_swap_space_warning = g_variant_get_boolean (value);
+
+ gimp_dashboard_set_low_swap_space_warning (dashboard, low_swap_space_warning);
+}
+
+
+/* private functions */
+
+static void
+dashboard_log_record_response (GtkWidget *dialog,
+ int response_id,
+ GimpDashboard *dashboard)
+{
+ if (response_id == GTK_RESPONSE_OK)
+ {
+ GFile *file;
+ DashboardLogDialogInfo *info;
+ GError *error = NULL;
+
+ file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog));
+
+ info = g_object_get_data (G_OBJECT (dashboard),
+ "gimp-dashboard-log-dialog-info");
+
+ g_return_if_fail (info != NULL);
+
+ g_set_object (&info->folder, g_file_get_parent (file));
+
+ if (! gimp_dashboard_log_start_recording (dashboard,
+ file, &info->params,
+ &error))
+ {
+ gimp_message_literal (
+ gimp_editor_get_ui_manager (GIMP_EDITOR (dashboard))->gimp,
+ NULL, GIMP_MESSAGE_ERROR, error->message);
+
+ g_clear_error (&error);
+ }
+
+ g_object_unref (file);
+ }
+
+ gtk_widget_destroy (dialog);
+}
+
+static void
+dashboard_log_add_marker_response (GtkWidget *dialog,
+ const gchar *description,
+ GimpDashboard *dashboard)
+{
+ gimp_dashboard_log_add_marker (dashboard, description);
+}
+
+static DashboardLogDialogInfo *
+dashboard_log_dialog_info_new (GimpDashboard *dashboard)
+{
+ DashboardLogDialogInfo *info = g_slice_new (DashboardLogDialogInfo);
+
+ info->folder = NULL;
+ info->params = *gimp_dashboard_log_get_default_params (dashboard);
+
+ return info;
+}
+
+static void
+dashboard_log_dialog_info_free (DashboardLogDialogInfo *info)
+{
+ g_clear_object (&info->folder);
+
+ g_slice_free (DashboardLogDialogInfo, info);
+}
diff --git a/app/actions/dashboard-commands.h b/app/actions/dashboard-commands.h
new file mode 100644
index 0000000..a97b7f1
--- /dev/null
+++ b/app/actions/dashboard-commands.h
@@ -0,0 +1,48 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __DASHBOARD_COMMANDS_H__
+#define __DASHBOARD_COMMANDS_H__
+
+
+void dashboard_update_interval_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void dashboard_history_duration_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+void dashboard_log_record_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void dashboard_log_add_marker_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void dashboard_log_add_empty_marker_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+void dashboard_reset_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+void dashboard_low_swap_space_warning_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+
+#endif /* __DASHBOARD_COMMANDS_H__ */
diff --git a/app/actions/data-commands.c b/app/actions/data-commands.c
new file mode 100644
index 0000000..9d71bda
--- /dev/null
+++ b/app/actions/data-commands.c
@@ -0,0 +1,304 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpbase/gimpbase.h"
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "actions-types.h"
+
+#include "core/gimp.h"
+#include "core/gimpcontainer.h"
+#include "core/gimpcontext.h"
+#include "core/gimpdata.h"
+#include "core/gimpdatafactory.h"
+
+#include "file/file-open.h"
+
+#include "widgets/gimpclipboard.h"
+#include "widgets/gimpcontainerview.h"
+#include "widgets/gimpdataeditor.h"
+#include "widgets/gimpdatafactoryview.h"
+#include "widgets/gimpdialogfactory.h"
+#include "widgets/gimpmessagebox.h"
+#include "widgets/gimpmessagedialog.h"
+#include "widgets/gimpwidgets-utils.h"
+#include "widgets/gimpwindowstrategy.h"
+#include "widgets/gimpwidgets-utils.h"
+
+#include "dialogs/data-delete-dialog.h"
+
+#include "actions.h"
+#include "data-commands.h"
+
+#include "gimp-intl.h"
+
+
+/* public functions */
+
+void
+data_open_as_image_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer user_data)
+{
+ GimpDataFactoryView *view = GIMP_DATA_FACTORY_VIEW (user_data);
+ GimpContext *context;
+ GimpData *data;
+
+ context =
+ gimp_container_view_get_context (GIMP_CONTAINER_EDITOR (view)->view);
+
+ data = (GimpData *)
+ gimp_context_get_by_type (context,
+ gimp_data_factory_view_get_children_type (view));
+
+ if (data && gimp_data_get_file (data))
+ {
+ GFile *file = gimp_data_get_file (data);
+ GtkWidget *widget = GTK_WIDGET (view);
+ GimpImage *image;
+ GimpPDBStatusType status;
+ GError *error = NULL;
+
+ image = file_open_with_display (context->gimp, context, NULL,
+ file, FALSE,
+ G_OBJECT (gtk_widget_get_screen (widget)),
+ gimp_widget_get_monitor (widget),
+ &status, &error);
+
+ if (! image && status != GIMP_PDB_CANCEL)
+ {
+ gimp_message (context->gimp, G_OBJECT (view),
+ GIMP_MESSAGE_ERROR,
+ _("Opening '%s' failed:\n\n%s"),
+ gimp_file_get_utf8_name (file), error->message);
+ g_clear_error (&error);
+ }
+ }
+}
+
+void
+data_new_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer user_data)
+{
+ GimpDataFactoryView *view = GIMP_DATA_FACTORY_VIEW (user_data);
+
+ if (gimp_data_factory_view_has_data_new_func (view))
+ {
+ GimpDataFactory *factory;
+ GimpContext *context;
+ GimpData *data;
+
+ factory = gimp_data_factory_view_get_data_factory (view);
+
+ context =
+ gimp_container_view_get_context (GIMP_CONTAINER_EDITOR (view)->view);
+
+ data = gimp_data_factory_data_new (factory, context, _("Untitled"));
+
+ if (data)
+ {
+ gimp_context_set_by_type (context,
+ gimp_data_factory_view_get_children_type (view),
+ GIMP_OBJECT (data));
+
+ gtk_button_clicked (GTK_BUTTON (gimp_data_factory_view_get_edit_button (view)));
+ }
+ }
+}
+
+void
+data_duplicate_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer user_data)
+{
+ GimpDataFactoryView *view = GIMP_DATA_FACTORY_VIEW (user_data);
+ GimpContext *context;
+ GimpData *data;
+
+ context = gimp_container_view_get_context (GIMP_CONTAINER_EDITOR (view)->view);
+
+ data = (GimpData *)
+ gimp_context_get_by_type (context,
+ gimp_data_factory_view_get_children_type (view));
+
+ if (data && gimp_data_factory_view_have (view, GIMP_OBJECT (data)))
+ {
+ GimpData *new_data;
+
+ new_data = gimp_data_factory_data_duplicate (gimp_data_factory_view_get_data_factory (view), data);
+
+ if (new_data)
+ {
+ gimp_context_set_by_type (context,
+ gimp_data_factory_view_get_children_type (view),
+ GIMP_OBJECT (new_data));
+
+ gtk_button_clicked (GTK_BUTTON (gimp_data_factory_view_get_edit_button (view)));
+ }
+ }
+}
+
+void
+data_copy_location_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer user_data)
+{
+ GimpDataFactoryView *view = GIMP_DATA_FACTORY_VIEW (user_data);
+ GimpContext *context;
+ GimpData *data;
+
+ context = gimp_container_view_get_context (GIMP_CONTAINER_EDITOR (view)->view);
+
+ data = (GimpData *)
+ gimp_context_get_by_type (context,
+ gimp_data_factory_view_get_children_type (view));
+
+ if (data)
+ {
+ GFile *file = gimp_data_get_file (data);
+
+ if (file)
+ {
+ gchar *uri = g_file_get_uri (file);
+
+ gimp_clipboard_set_text (context->gimp, uri);
+ g_free (uri);
+ }
+ }
+}
+
+void
+data_show_in_file_manager_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer user_data)
+{
+ GimpDataFactoryView *view = GIMP_DATA_FACTORY_VIEW (user_data);
+ GimpContext *context;
+ GimpData *data;
+
+ context = gimp_container_view_get_context (GIMP_CONTAINER_EDITOR (view)->view);
+
+ data = (GimpData *)
+ gimp_context_get_by_type (context,
+ gimp_data_factory_view_get_children_type (view));
+
+ if (data)
+ {
+ GFile *file = gimp_data_get_file (data);
+
+ if (file)
+ {
+ GError *error = NULL;
+
+ if (! gimp_file_show_in_file_manager (file, &error))
+ {
+ gimp_message (context->gimp, G_OBJECT (view),
+ GIMP_MESSAGE_ERROR,
+ _("Can't show file in file manager: %s"),
+ error->message);
+ g_clear_error (&error);
+ }
+ }
+ }
+}
+
+void
+data_delete_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer user_data)
+{
+ GimpDataFactoryView *view = GIMP_DATA_FACTORY_VIEW (user_data);
+ GimpContext *context;
+ GimpData *data;
+
+ context =
+ gimp_container_view_get_context (GIMP_CONTAINER_EDITOR (view)->view);
+
+ data = (GimpData *)
+ gimp_context_get_by_type (context,
+ gimp_data_factory_view_get_children_type (view));
+
+ if (data &&
+ gimp_data_is_deletable (data) &&
+ gimp_data_factory_view_have (view, GIMP_OBJECT (data)))
+ {
+ GimpDataFactory *factory;
+ GtkWidget *dialog;
+
+ factory = gimp_data_factory_view_get_data_factory (view);
+
+ dialog = data_delete_dialog_new (factory, data, context,
+ GTK_WIDGET (view));
+ gtk_widget_show (dialog);
+ }
+}
+
+void
+data_refresh_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer user_data)
+{
+ GimpDataFactoryView *view = GIMP_DATA_FACTORY_VIEW (user_data);
+ Gimp *gimp;
+ return_if_no_gimp (gimp, user_data);
+
+ gimp_set_busy (gimp);
+ gimp_data_factory_data_refresh (gimp_data_factory_view_get_data_factory (view),
+ action_data_get_context (user_data));
+ gimp_unset_busy (gimp);
+}
+
+void
+data_edit_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer user_data)
+{
+ GimpDataFactoryView *view = GIMP_DATA_FACTORY_VIEW (user_data);
+ GimpContext *context;
+ GimpData *data;
+
+ context = gimp_container_view_get_context (GIMP_CONTAINER_EDITOR (view)->view);
+
+ data = (GimpData *)
+ gimp_context_get_by_type (context,
+ gimp_data_factory_view_get_children_type (view));
+
+ if (data && gimp_data_factory_view_have (view, GIMP_OBJECT (data)))
+ {
+ GdkScreen *screen = gtk_widget_get_screen (GTK_WIDGET (view));
+ gint monitor = gimp_widget_get_monitor (GTK_WIDGET (view));
+ GtkWidget *dockable;
+
+ dockable =
+ gimp_window_strategy_show_dockable_dialog (GIMP_WINDOW_STRATEGY (gimp_get_window_strategy (context->gimp)),
+ context->gimp,
+ gimp_dialog_factory_get_singleton (),
+ screen,
+ monitor,
+ g_variant_get_string (value,
+ NULL));
+
+ gimp_data_editor_set_data (GIMP_DATA_EDITOR (gtk_bin_get_child (GTK_BIN (dockable))),
+ data);
+ }
+}
diff --git a/app/actions/data-commands.h b/app/actions/data-commands.h
new file mode 100644
index 0000000..a9bb4af
--- /dev/null
+++ b/app/actions/data-commands.h
@@ -0,0 +1,48 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __DATA_COMMANDS_H__
+#define __DATA_COMMANDS_H__
+
+
+void data_open_as_image_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void data_new_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void data_duplicate_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void data_copy_location_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void data_show_in_file_manager_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void data_delete_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void data_refresh_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void data_edit_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+
+#endif /* __DATA_COMMANDS_H__ */
diff --git a/app/actions/data-editor-commands.c b/app/actions/data-editor-commands.c
new file mode 100644
index 0000000..0c8383c
--- /dev/null
+++ b/app/actions/data-editor-commands.c
@@ -0,0 +1,43 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "actions-types.h"
+
+#include "widgets/gimpdataeditor.h"
+
+#include "data-editor-commands.h"
+
+
+/* public functions */
+
+void
+data_editor_edit_active_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpDataEditor *editor = GIMP_DATA_EDITOR (data);
+ gboolean edit_active;
+
+ edit_active = g_variant_get_boolean (value);
+
+ gimp_data_editor_set_edit_active (editor, edit_active);
+}
diff --git a/app/actions/data-editor-commands.h b/app/actions/data-editor-commands.h
new file mode 100644
index 0000000..c70743d
--- /dev/null
+++ b/app/actions/data-editor-commands.h
@@ -0,0 +1,27 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __DATA_EDITOR_COMMANDS_H__
+#define __DATA_EDITOR_COMMANDS_H__
+
+
+void data_editor_edit_active_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+
+#endif /* __DATA_EDITOR_COMMANDS_H__ */
diff --git a/app/actions/debug-actions.c b/app/actions/debug-actions.c
new file mode 100644
index 0000000..70ceb0d
--- /dev/null
+++ b/app/actions/debug-actions.c
@@ -0,0 +1,107 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "actions-types.h"
+
+#include "core/gimp.h"
+
+#include "widgets/gimpactiongroup.h"
+
+#include "debug-actions.h"
+#include "debug-commands.h"
+
+
+static const GimpActionEntry debug_actions[] =
+{
+ { "debug-menu", NULL, "_Debug" },
+
+ { "debug-mem-profile", NULL,
+ "_Memory Profile", NULL, NULL,
+ debug_mem_profile_cmd_callback,
+ NULL },
+
+ { "debug-benchmark-projection", NULL,
+ "Benchmark _Projection", NULL,
+ "Invalidates the entire projection, measures the time it takes to "
+ "validate (render) the part that is visible in the active display, "
+ "and print the result to stdout.",
+ debug_benchmark_projection_cmd_callback,
+ NULL },
+
+ { "debug-show-image-graph", NULL,
+ "Show Image _Graph", NULL,
+ "Creates a new image showing the GEGL graph of this image",
+ debug_show_image_graph_cmd_callback,
+ NULL },
+
+ { "debug-dump-items", NULL,
+ "_Dump Items", NULL, NULL,
+ debug_dump_menus_cmd_callback,
+ NULL },
+
+ { "debug-dump-managers", NULL,
+ "Dump _UI Managers", NULL, NULL,
+ debug_dump_managers_cmd_callback,
+ NULL },
+
+ { "debug-dump-keyboard-shortcuts", NULL,
+ "Dump _Keyboard Shortcuts", NULL, NULL,
+ debug_dump_keyboard_shortcuts_cmd_callback,
+ NULL },
+
+ { "debug-dump-attached-data", NULL,
+ "Dump Attached Data", NULL, NULL,
+ debug_dump_attached_data_cmd_callback,
+ NULL }
+};
+
+void
+debug_actions_setup (GimpActionGroup *group)
+{
+ gint i;
+
+ gimp_action_group_add_actions (group, NULL,
+ debug_actions,
+ G_N_ELEMENTS (debug_actions));
+
+#define SET_VISIBLE(action,condition) \
+ gimp_action_group_set_action_visible (group, action, (condition) != 0)
+
+ for (i = 0; i < G_N_ELEMENTS (debug_actions); i++)
+ SET_VISIBLE (debug_actions[i].name, group->gimp->show_debug_menu);
+
+#undef SET_VISIBLE
+}
+
+void
+debug_actions_update (GimpActionGroup *group,
+ gpointer data)
+{
+#define SET_SENSITIVE(action,condition) \
+ gimp_action_group_set_action_sensitive (group, action, (condition) != 0)
+
+ SET_SENSITIVE ("debug-show-image-graph", gegl_has_operation ("gegl:introspect"));
+
+#undef SET_SENSITIVE
+}
diff --git a/app/actions/debug-actions.h b/app/actions/debug-actions.h
new file mode 100644
index 0000000..c00780c
--- /dev/null
+++ b/app/actions/debug-actions.h
@@ -0,0 +1,27 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __DEBUG_ACTIONS_H__
+#define __DEBUG_ACTIONS_H__
+
+
+void debug_actions_setup (GimpActionGroup *group);
+void debug_actions_update (GimpActionGroup *group,
+ gpointer data);
+
+
+#endif /* __DEBUG_ACTIONS_H__ */
diff --git a/app/actions/debug-commands.c b/app/actions/debug-commands.c
new file mode 100644
index 0000000..c00c1fe
--- /dev/null
+++ b/app/actions/debug-commands.c
@@ -0,0 +1,430 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <string.h>
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpbase/gimpbase.h"
+
+#include "actions-types.h"
+
+#include "core/gimp.h"
+#include "core/gimp-utils.h"
+#include "core/gimpcontext.h"
+#include "core/gimpimage.h"
+#include "core/gimpprojectable.h"
+#include "core/gimpprojection.h"
+
+#include "gegl/gimp-gegl-utils.h"
+
+#include "widgets/gimpaction.h"
+#include "widgets/gimpactiongroup.h"
+#include "widgets/gimpmenufactory.h"
+#include "widgets/gimpuimanager.h"
+
+#include "display/gimpdisplay.h"
+#include "display/gimpdisplayshell.h"
+#include "display/gimpimagewindow.h"
+
+#include "menus/menus.h"
+
+#include "actions.h"
+#include "debug-commands.h"
+
+
+/* local function prototypes */
+
+static gboolean debug_benchmark_projection (GimpDisplay *display);
+static gboolean debug_show_image_graph (GimpImage *source_image);
+
+static void debug_dump_menus_recurse_menu (GtkWidget *menu,
+ gint depth,
+ gchar *path);
+
+static void debug_print_qdata (GimpObject *object);
+static void debug_print_qdata_foreach (GQuark key_id,
+ gpointer data,
+ gpointer user_data);
+
+static gboolean debug_accel_find_func (GtkAccelKey *key,
+ GClosure *closure,
+ gpointer data);
+
+
+/* public functions */
+
+void
+debug_mem_profile_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ extern gboolean gimp_debug_memsize;
+ Gimp *gimp;
+ return_if_no_gimp (gimp, data);
+
+ gimp_debug_memsize = TRUE;
+
+ gimp_object_get_memsize (GIMP_OBJECT (gimp), NULL);
+
+ gimp_debug_memsize = FALSE;
+}
+
+void
+debug_benchmark_projection_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpDisplay *display;
+ return_if_no_display (display, data);
+
+ g_idle_add ((GSourceFunc) debug_benchmark_projection, g_object_ref (display));
+}
+
+void
+debug_show_image_graph_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *source_image = NULL;
+ return_if_no_image (source_image, data);
+
+ g_idle_add ((GSourceFunc) debug_show_image_graph, g_object_ref (source_image));
+}
+
+void
+debug_dump_menus_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GList *list;
+
+ for (list = gimp_menu_factory_get_registered_menus (global_menu_factory);
+ list;
+ list = g_list_next (list))
+ {
+ GimpMenuFactoryEntry *entry = list->data;
+ GList *managers;
+
+ managers = gimp_ui_managers_from_name (entry->identifier);
+
+ if (managers)
+ {
+ GimpUIManager *manager = managers->data;
+ GList *list;
+
+ for (list = manager->registered_uis; list; list = g_list_next (list))
+ {
+ GimpUIManagerUIEntry *ui_entry = list->data;
+
+ if (GTK_IS_MENU_SHELL (ui_entry->widget))
+ {
+ g_print ("\n\n"
+ "========================================\n"
+ "Menu: %s%s\n"
+ "========================================\n\n",
+ entry->identifier, ui_entry->ui_path);
+
+ debug_dump_menus_recurse_menu (ui_entry->widget, 1,
+ entry->identifier);
+ g_print ("\n");
+ }
+ }
+ }
+ }
+}
+
+void
+debug_dump_managers_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GList *list;
+
+ for (list = gimp_menu_factory_get_registered_menus (global_menu_factory);
+ list;
+ list = g_list_next (list))
+ {
+ GimpMenuFactoryEntry *entry = list->data;
+ GList *managers;
+
+ managers = gimp_ui_managers_from_name (entry->identifier);
+
+ if (managers)
+ {
+ g_print ("\n\n"
+ "========================================\n"
+ "UI Manager: %s\n"
+ "========================================\n\n",
+ entry->identifier);
+
+ g_print ("%s\n", gimp_ui_manager_get_ui (managers->data));
+ }
+ }
+}
+
+void
+debug_dump_keyboard_shortcuts_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpDisplay *display;
+ GimpImageWindow *window;
+ GimpUIManager *manager;
+ GtkAccelGroup *accel_group;
+ GList *group_it;
+ GList *strings = NULL;
+ return_if_no_display (display, data);
+
+ window = gimp_display_shell_get_window (gimp_display_get_shell (display));
+ manager = gimp_image_window_get_ui_manager (window);
+
+ accel_group = gimp_ui_manager_get_accel_group (manager);
+
+ /* Gather formatted strings of keyboard shortcuts */
+ for (group_it = gimp_ui_manager_get_action_groups (manager);
+ group_it;
+ group_it = g_list_next (group_it))
+ {
+ GimpActionGroup *group = group_it->data;
+ GList *actions = NULL;
+ GList *action_it = NULL;
+
+ actions = gimp_action_group_list_actions (group);
+ actions = g_list_sort (actions, (GCompareFunc) gimp_action_name_compare);
+
+ for (action_it = actions; action_it; action_it = g_list_next (action_it))
+ {
+ GimpAction *action = action_it->data;
+ const gchar *name = gimp_action_get_name (action);
+ GClosure *accel_closure = NULL;
+
+ if (strstr (name, "-menu") ||
+ strstr (name, "-popup") ||
+ name[0] == '<')
+ continue;
+
+ accel_closure = gimp_action_get_accel_closure (action);
+
+ if (accel_closure)
+ {
+ GtkAccelKey *key = gtk_accel_group_find (accel_group,
+ debug_accel_find_func,
+ accel_closure);
+ if (key &&
+ key->accel_key &&
+ key->accel_flags & GTK_ACCEL_VISIBLE)
+ {
+ const gchar *label_tmp;
+ gchar *label;
+ gchar *key_string;
+
+ label_tmp = gimp_action_get_label (action);
+ label = gimp_strip_uline (label_tmp);
+ key_string = gtk_accelerator_get_label (key->accel_key,
+ key->accel_mods);
+
+ strings = g_list_prepend (strings,
+ g_strdup_printf ("%-20s %s",
+ key_string, label));
+
+ g_free (key_string);
+ g_free (label);
+ }
+ }
+ }
+
+ g_list_free (actions);
+ }
+
+ /* Sort and prints the strings */
+ {
+ GList *string_it = NULL;
+
+ strings = g_list_sort (strings, (GCompareFunc) strcmp);
+
+ for (string_it = strings; string_it; string_it = g_list_next (string_it))
+ {
+ g_print ("%s\n", (gchar *) string_it->data);
+ g_free (string_it->data);
+ }
+
+ g_list_free (strings);
+ }
+}
+
+void
+debug_dump_attached_data_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ Gimp *gimp = action_data_get_gimp (data);
+ GimpContext *user_context = gimp_get_user_context (gimp);
+
+ debug_print_qdata (GIMP_OBJECT (gimp));
+ debug_print_qdata (GIMP_OBJECT (user_context));
+}
+
+
+/* private functions */
+
+static gboolean
+debug_benchmark_projection (GimpDisplay *display)
+{
+ GimpImage *image = gimp_display_get_image (display);
+
+ if (image)
+ {
+ GimpProjection *projection = gimp_image_get_projection (image);
+
+ gimp_projection_stop_rendering (projection);
+
+ GIMP_TIMER_START ();
+
+ gimp_image_invalidate_all (image);
+ gimp_projection_flush_now (projection, TRUE);
+
+ GIMP_TIMER_END ("Validation of the entire projection");
+
+ g_object_unref (display);
+ }
+
+ return FALSE;
+}
+
+static gboolean
+debug_show_image_graph (GimpImage *source_image)
+{
+ GeglNode *image_graph;
+ GeglNode *output_node;
+ GimpImage *new_image;
+ GeglNode *introspect;
+ GeglNode *sink;
+ GeglBuffer *buffer;
+ gchar *new_name;
+
+ image_graph = gimp_projectable_get_graph (GIMP_PROJECTABLE (source_image));
+
+ output_node = gegl_node_get_output_proxy (image_graph, "output");
+
+ introspect = gegl_node_new_child (NULL,
+ "operation", "gegl:introspect",
+ "node", output_node,
+ NULL);
+ sink = gegl_node_new_child (NULL,
+ "operation", "gegl:buffer-sink",
+ "buffer", &buffer,
+ NULL);
+
+ gegl_node_link_many (introspect, sink, NULL);
+ gegl_node_process (sink);
+
+ new_name = g_strdup_printf ("%s GEGL graph",
+ gimp_image_get_display_name (source_image));
+
+ new_image = gimp_create_image_from_buffer (source_image->gimp,
+ buffer, new_name);
+ gimp_image_set_file (new_image, g_file_new_for_uri (new_name));
+
+ g_free (new_name);
+
+ g_object_unref (buffer);
+
+ g_object_unref (sink);
+ g_object_unref (introspect);
+
+ g_object_unref (source_image);
+
+ return FALSE;
+}
+
+static void
+debug_dump_menus_recurse_menu (GtkWidget *menu,
+ gint depth,
+ gchar *path)
+{
+ GList *children;
+ GList *list;
+
+ children = gtk_container_get_children (GTK_CONTAINER (menu));
+
+ for (list = children; list; list = g_list_next (list))
+ {
+ GtkWidget *menu_item = GTK_WIDGET (list->data);
+ GtkWidget *child = gtk_bin_get_child (GTK_BIN (menu_item));
+
+ if (GTK_IS_LABEL (child))
+ {
+ GtkWidget *submenu;
+ const gchar *label;
+ gchar *full_path;
+ gchar *help_page;
+ gchar *format_str;
+
+ label = gtk_label_get_text (GTK_LABEL (child));
+ full_path = g_strconcat (path, "/", label, NULL);
+
+ help_page = g_object_get_data (G_OBJECT (menu_item), "gimp-help-id");
+ help_page = g_strdup (help_page);
+
+ format_str = g_strdup_printf ("%%%ds%%%ds %%-20s %%s\n",
+ depth * 2, depth * 2 - 40);
+ g_print (format_str,
+ "", label, "", help_page ? help_page : "");
+ g_free (format_str);
+ g_free (help_page);
+
+ submenu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (menu_item));
+
+ if (submenu)
+ debug_dump_menus_recurse_menu (submenu, depth + 1, full_path);
+
+ g_free (full_path);
+ }
+ }
+
+ g_list_free (children);
+}
+
+static void
+debug_print_qdata (GimpObject *object)
+{
+ g_print ("\nData attached to '%s':\n\n", gimp_object_get_name (object));
+ g_datalist_foreach (&G_OBJECT (object)->qdata,
+ debug_print_qdata_foreach,
+ NULL);
+ g_print ("\n");
+}
+
+static void
+debug_print_qdata_foreach (GQuark key_id,
+ gpointer data,
+ gpointer user_data)
+{
+ g_print ("%s: %p\n", g_quark_to_string (key_id), data);
+}
+
+static gboolean
+debug_accel_find_func (GtkAccelKey *key,
+ GClosure *closure,
+ gpointer data)
+{
+ return (GClosure *) data == closure;
+}
diff --git a/app/actions/debug-commands.h b/app/actions/debug-commands.h
new file mode 100644
index 0000000..12c7dd2
--- /dev/null
+++ b/app/actions/debug-commands.h
@@ -0,0 +1,46 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __DEBUG_COMMANDS_H__
+#define __DEBUG_COMMANDS_H__
+
+
+void debug_mem_profile_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void debug_benchmark_projection_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void debug_show_image_graph_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void debug_dump_menus_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void debug_dump_managers_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void debug_dump_keyboard_shortcuts_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void debug_dump_attached_data_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+
+
+#endif /* __DEBUG_COMMANDS_H__ */
diff --git a/app/actions/dialogs-actions.c b/app/actions/dialogs-actions.c
new file mode 100644
index 0000000..188752b
--- /dev/null
+++ b/app/actions/dialogs-actions.c
@@ -0,0 +1,368 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "actions-types.h"
+
+#include "core/gimp.h"
+
+#include "widgets/gimpactiongroup.h"
+#include "widgets/gimpdialogfactory.h"
+#include "widgets/gimphelp-ids.h"
+#include "widgets/gimpsessioninfo.h"
+#include "widgets/gimptoolbox.h"
+
+#include "display/gimpimagewindow.h"
+
+#include "actions.h"
+#include "dialogs-actions.h"
+#include "dialogs-commands.h"
+
+#include "gimp-intl.h"
+
+
+const GimpStringActionEntry dialogs_dockable_actions[] =
+{
+ { "dialogs-toolbox", NULL,
+ NC_("windows-action", "Tool_box"), "<primary>B",
+ NULL /* set in dialogs_actions_update() */,
+ "gimp-toolbox",
+ GIMP_HELP_TOOLBOX },
+
+ { "dialogs-tool-options", GIMP_ICON_DIALOG_TOOL_OPTIONS,
+ NC_("dialogs-action", "Tool _Options"), NULL,
+ NC_("dialogs-action", "Open the tool options dialog"),
+ "gimp-tool-options",
+ GIMP_HELP_TOOL_OPTIONS_DIALOG },
+
+ { "dialogs-device-status", GIMP_ICON_DIALOG_DEVICE_STATUS,
+ NC_("dialogs-action", "_Device Status"), NULL,
+ NC_("dialogs-action", "Open the device status dialog"),
+ "gimp-device-status",
+ GIMP_HELP_DEVICE_STATUS_DIALOG },
+
+ { "dialogs-symmetry", GIMP_ICON_SYMMETRY,
+ NC_("dialogs-action", "_Symmetry Painting"), NULL,
+ NC_("dialogs-action", "Open the symmetry dialog"),
+ "gimp-symmetry-editor",
+ GIMP_HELP_SYMMETRY_DIALOG },
+
+ { "dialogs-layers", GIMP_ICON_DIALOG_LAYERS,
+ NC_("dialogs-action", "_Layers"), "<primary>L",
+ NC_("dialogs-action", "Open the layers dialog"),
+ "gimp-layer-list",
+ GIMP_HELP_LAYER_DIALOG },
+
+ { "dialogs-channels", GIMP_ICON_DIALOG_CHANNELS,
+ NC_("dialogs-action", "_Channels"), NULL,
+ NC_("dialogs-action", "Open the channels dialog"),
+ "gimp-channel-list",
+ GIMP_HELP_CHANNEL_DIALOG },
+
+ { "dialogs-vectors", GIMP_ICON_DIALOG_PATHS,
+ NC_("dialogs-action", "_Paths"), NULL,
+ NC_("dialogs-action", "Open the paths dialog"),
+ "gimp-vectors-list",
+ GIMP_HELP_PATH_DIALOG },
+
+ { "dialogs-indexed-palette", GIMP_ICON_COLORMAP,
+ NC_("dialogs-action", "Color_map"), NULL,
+ NC_("dialogs-action", "Open the colormap dialog"),
+ "gimp-indexed-palette",
+ GIMP_HELP_INDEXED_PALETTE_DIALOG },
+
+ { "dialogs-histogram", GIMP_ICON_HISTOGRAM,
+ NC_("dialogs-action", "Histogra_m"), NULL,
+ NC_("dialogs-action", "Open the histogram dialog"),
+ "gimp-histogram-editor",
+ GIMP_HELP_HISTOGRAM_DIALOG },
+
+ { "dialogs-selection-editor", GIMP_ICON_SELECTION,
+ NC_("dialogs-action", "_Selection Editor"), NULL,
+ NC_("dialogs-action", "Open the selection editor"),
+ "gimp-selection-editor",
+ GIMP_HELP_SELECTION_DIALOG },
+
+ { "dialogs-navigation", GIMP_ICON_DIALOG_NAVIGATION,
+ NC_("dialogs-action", "Na_vigation"), NULL,
+ NC_("dialogs-action", "Open the display navigation dialog"),
+ "gimp-navigation-view",
+ GIMP_HELP_NAVIGATION_DIALOG },
+
+ { "dialogs-undo-history", GIMP_ICON_DIALOG_UNDO_HISTORY,
+ NC_("dialogs-action", "Undo _History"), NULL,
+ NC_("dialogs-action", "Open the undo history dialog"),
+ "gimp-undo-history",
+ GIMP_HELP_UNDO_DIALOG },
+
+ { "dialogs-cursor", GIMP_ICON_CURSOR,
+ NC_("dialogs-action", "_Pointer"), NULL,
+ NC_("dialogs-action", "Open the pointer information dialog"),
+ "gimp-cursor-view",
+ GIMP_HELP_POINTER_INFO_DIALOG },
+
+ { "dialogs-sample-points", GIMP_ICON_SAMPLE_POINT,
+ NC_("dialogs-action", "_Sample Points"), NULL,
+ NC_("dialogs-action", "Open the sample points dialog"),
+ "gimp-sample-point-editor",
+ GIMP_HELP_SAMPLE_POINT_DIALOG },
+
+ { "dialogs-colors", GIMP_ICON_COLORS_DEFAULT,
+ NC_("dialogs-action", "Colo_rs"), NULL,
+ NC_("dialogs-action", "Open the FG/BG color dialog"),
+ "gimp-color-editor",
+ GIMP_HELP_COLOR_DIALOG },
+
+ { "dialogs-brushes", GIMP_ICON_BRUSH,
+ NC_("dialogs-action", "_Brushes"), "<primary><shift>B",
+ NC_("dialogs-action", "Open the brushes dialog"),
+ "gimp-brush-grid|gimp-brush-list",
+ GIMP_HELP_BRUSH_DIALOG },
+
+ { "dialogs-brush-editor", GIMP_ICON_BRUSH,
+ NC_("dialogs-action", "Brush Editor"), NULL,
+ NC_("dialogs-action", "Open the brush editor"),
+ "gimp-brush-editor",
+ GIMP_HELP_BRUSH_EDIT },
+
+ { "dialogs-dynamics", GIMP_ICON_DYNAMICS,
+ NC_("dialogs-action", "Paint D_ynamics"), NULL,
+ NC_("dialogs-action", "Open paint dynamics dialog"),
+ "gimp-dynamics-list|gimp-dynamics-grid",
+ GIMP_HELP_DYNAMICS_DIALOG },
+
+ { "dialogs-dynamics-editor", GIMP_ICON_DYNAMICS,
+ NC_("dialogs-action", "Paint Dynamics Editor"), NULL,
+ NC_("dialogs-action", "Open the paint dynamics editor"),
+ "gimp-dynamics-editor",
+ GIMP_HELP_DYNAMICS_EDITOR_DIALOG },
+
+ { "dialogs-mypaint-brushes", GIMP_ICON_MYPAINT_BRUSH,
+ NC_("dialogs-action", "_MyPaint Brushes"), NULL,
+ NC_("dialogs-action", "Open the mypaint brushes dialog"),
+ "gimp-mypaint-brush-grid|gimp-mapyint-brush-list",
+ GIMP_HELP_MYPAINT_BRUSH_DIALOG },
+
+ { "dialogs-patterns", GIMP_ICON_PATTERN,
+ NC_("dialogs-action", "P_atterns"), "<primary><shift>P",
+ NC_("dialogs-action", "Open the patterns dialog"),
+ "gimp-pattern-grid|gimp-pattern-list",
+ GIMP_HELP_PATTERN_DIALOG },
+
+ { "dialogs-gradients", GIMP_ICON_GRADIENT,
+ NC_("dialogs-action", "_Gradients"), "<primary>G",
+ NC_("dialogs-action", "Open the gradients dialog"),
+ "gimp-gradient-list|gimp-gradient-grid",
+ GIMP_HELP_GRADIENT_DIALOG },
+
+ { "dialogs-gradient-editor", GIMP_ICON_GRADIENT,
+ NC_("dialogs-action", "Gradient Editor"), NULL,
+ NC_("dialogs-action", "Open the gradient editor"),
+ "gimp-gradient-editor",
+ GIMP_HELP_GRADIENT_EDIT },
+
+ { "dialogs-palettes", GIMP_ICON_PALETTE,
+ NC_("dialogs-action", "Pal_ettes"), NULL,
+ NC_("dialogs-action", "Open the palettes dialog"),
+ "gimp-palette-list|gimp-palette-grid",
+ GIMP_HELP_PALETTE_DIALOG },
+
+ { "dialogs-palette-editor", GIMP_ICON_PALETTE,
+ NC_("dialogs-action", "Palette _Editor"), NULL,
+ NC_("dialogs-action", "Open the palette editor"),
+ "gimp-palette-editor",
+ GIMP_HELP_PALETTE_EDIT },
+
+ { "dialogs-tool-presets", GIMP_ICON_TOOL_PRESET,
+ NC_("dialogs-action", "Tool Pre_sets"), NULL,
+ NC_("dialogs-action", "Open tool presets dialog"),
+ "gimp-tool-preset-list|gimp-tool-preset-grid",
+ GIMP_HELP_TOOL_PRESET_DIALOG },
+
+ { "dialogs-fonts", GIMP_ICON_FONT,
+ NC_("dialogs-action", "_Fonts"), NULL,
+ NC_("dialogs-action", "Open the fonts dialog"),
+ "gimp-font-list|gimp-font-grid",
+ GIMP_HELP_FONT_DIALOG },
+
+ { "dialogs-buffers", GIMP_ICON_BUFFER,
+ NC_("dialogs-action", "B_uffers"), "",
+ NC_("dialogs-action", "Open the named buffers dialog"),
+ "gimp-buffer-list|gimp-buffer-grid",
+ GIMP_HELP_BUFFER_DIALOG },
+
+ { "dialogs-images", GIMP_ICON_DIALOG_IMAGES,
+ NC_("dialogs-action", "_Images"), NULL,
+ NC_("dialogs-action", "Open the images dialog"),
+ "gimp-image-list|gimp-image-grid",
+ GIMP_HELP_IMAGE_DIALOG },
+
+ { "dialogs-document-history", GIMP_ICON_DOCUMENT_OPEN_RECENT,
+ NC_("dialogs-action", "Document Histor_y"), "",
+ NC_("dialogs-action", "Open the document history dialog"),
+ "gimp-document-list|gimp-document-grid",
+ GIMP_HELP_DOCUMENT_DIALOG },
+
+ { "dialogs-templates", GIMP_ICON_TEMPLATE,
+ NC_("dialogs-action", "_Templates"), "",
+ NC_("dialogs-action", "Open the image templates dialog"),
+ "gimp-template-list|gimp-template-grid",
+ GIMP_HELP_TEMPLATE_DIALOG },
+
+ { "dialogs-error-console", GIMP_ICON_DIALOG_WARNING,
+ NC_("dialogs-action", "Error Co_nsole"), NULL,
+ NC_("dialogs-action", "Open the error console"),
+ "gimp-error-console",
+ GIMP_HELP_ERRORS_DIALOG },
+
+ { "dialogs-dashboard", GIMP_ICON_DIALOG_DASHBOARD,
+ NC_("dialogs-action", "_Dashboard"), NULL,
+ NC_("dialogs-action", "Open the dashboard"),
+ "gimp-dashboard",
+ GIMP_HELP_ERRORS_DIALOG }
+};
+
+gint n_dialogs_dockable_actions = G_N_ELEMENTS (dialogs_dockable_actions);
+
+static const GimpStringActionEntry dialogs_toplevel_actions[] =
+{
+ { "dialogs-preferences", GIMP_ICON_PREFERENCES_SYSTEM,
+ NC_("dialogs-action", "_Preferences"), NULL,
+ NC_("dialogs-action", "Open the preferences dialog"),
+ "gimp-preferences-dialog",
+ GIMP_HELP_PREFS_DIALOG },
+
+ { "dialogs-input-devices", GIMP_ICON_INPUT_DEVICE,
+ NC_("dialogs-action", "_Input Devices"), NULL,
+ NC_("dialogs-action", "Open the input devices editor"),
+ "gimp-input-devices-dialog",
+ GIMP_HELP_INPUT_DEVICES },
+
+ { "dialogs-keyboard-shortcuts", GIMP_ICON_CHAR_PICKER,
+ NC_("dialogs-action", "_Keyboard Shortcuts"), NULL,
+ NC_("dialogs-action", "Open the keyboard shortcuts editor"),
+ "gimp-keyboard-shortcuts-dialog",
+ GIMP_HELP_KEYBOARD_SHORTCUTS },
+
+ { "dialogs-module-dialog", GIMP_ICON_SYSTEM_RUN,
+ NC_("dialogs-action", "_Modules"), NULL,
+ NC_("dialogs-action", "Open the module manager dialog"),
+ "gimp-module-dialog",
+ GIMP_HELP_MODULE_DIALOG },
+
+ { "dialogs-tips", GIMP_ICON_DIALOG_INFORMATION,
+ NC_("dialogs-action", "_Tip of the Day"), NULL,
+ NC_("dialogs-action", "Show some helpful tips on using GIMP"),
+ "gimp-tips-dialog",
+ GIMP_HELP_TIPS_DIALOG },
+
+ { "dialogs-about", GIMP_ICON_HELP_ABOUT,
+#if defined(G_OS_WIN32)
+ NC_("dialogs-action", "About GIMP"),
+#elif defined(PLATFORM_OSX)
+ NC_("dialogs-action", "About"),
+#else /* UNIX: use GNOME HIG */
+ NC_("dialogs-action", "_About"),
+#endif
+ NULL,
+ NC_("dialogs-action", "About GIMP"),
+ "gimp-about-dialog",
+ GIMP_HELP_ABOUT_DIALOG },
+
+ { "dialogs-action-search", GIMP_ICON_TOOL_ZOOM,
+ NC_("dialogs-action", "_Search and Run a Command"), "slash",
+ NC_("dialogs-action", "Search commands by keyword, and run them"),
+ "gimp-action-search-dialog",
+ GIMP_HELP_ACTION_SEARCH_DIALOG }
+};
+
+
+gboolean
+dialogs_actions_toolbox_exists (Gimp *gimp)
+{
+ GimpDialogFactory *factory = gimp_dialog_factory_get_singleton ();
+ gboolean toolbox_found = FALSE;
+ GList *iter;
+
+ /* First look in session managed windows */
+ toolbox_found =
+ gimp_dialog_factory_find_widget (factory, "gimp-toolbox-window") != NULL;
+
+ /* Then in image windows */
+ if (! toolbox_found)
+ {
+ GList *windows = gimp ? gimp_get_image_windows (gimp) : NULL;
+
+ for (iter = windows; iter; iter = g_list_next (iter))
+ {
+ GimpImageWindow *window = GIMP_IMAGE_WINDOW (windows->data);
+
+ if (gimp_image_window_has_toolbox (window))
+ {
+ toolbox_found = TRUE;
+ break;
+ }
+ }
+
+ g_list_free (windows);
+ }
+
+ return toolbox_found;
+}
+
+void
+dialogs_actions_setup (GimpActionGroup *group)
+{
+ gimp_action_group_add_string_actions (group, "dialogs-action",
+ dialogs_dockable_actions,
+ G_N_ELEMENTS (dialogs_dockable_actions),
+ dialogs_create_dockable_cmd_callback);
+
+ gimp_action_group_add_string_actions (group, "dialogs-action",
+ dialogs_toplevel_actions,
+ G_N_ELEMENTS (dialogs_toplevel_actions),
+ dialogs_create_toplevel_cmd_callback);
+}
+
+void
+dialogs_actions_update (GimpActionGroup *group,
+ gpointer data)
+{
+ Gimp *gimp = action_data_get_gimp (data);
+ const gchar *toolbox_label = NULL;
+ const gchar *toolbox_tooltip = NULL;
+
+ if (dialogs_actions_toolbox_exists (gimp))
+ {
+ toolbox_label = _("Tool_box");
+ toolbox_tooltip = _("Raise the toolbox");
+ }
+ else
+ {
+ toolbox_label = _("New Tool_box");
+ toolbox_tooltip = _("Create a new toolbox");
+ }
+
+ gimp_action_group_set_action_label (group, "dialogs-toolbox", toolbox_label);
+ gimp_action_group_set_action_tooltip (group, "dialogs-toolbox", toolbox_tooltip);
+}
diff --git a/app/actions/dialogs-actions.h b/app/actions/dialogs-actions.h
new file mode 100644
index 0000000..b424bdd
--- /dev/null
+++ b/app/actions/dialogs-actions.h
@@ -0,0 +1,38 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __DIALOGS_ACTIONS_H__
+#define __DIALOGS_ACTIONS_H__
+
+
+/* this check is needed for the extern declaration below to be correct */
+#ifndef __GIMP_ACTION_GROUP_H__
+#error "widgets/gimpactiongroup.h must be included prior to dialogs-actions.h"
+#endif
+
+extern const GimpStringActionEntry dialogs_dockable_actions[];
+extern gint n_dialogs_dockable_actions;
+
+
+void dialogs_actions_setup (GimpActionGroup *group);
+void dialogs_actions_update (GimpActionGroup *group,
+ gpointer data);
+
+gboolean dialogs_actions_toolbox_exists (Gimp *gimp);
+
+
+#endif /* __DIALOGS_ACTIONS_H__ */
diff --git a/app/actions/dialogs-commands.c b/app/actions/dialogs-commands.c
new file mode 100644
index 0000000..5804bcc
--- /dev/null
+++ b/app/actions/dialogs-commands.c
@@ -0,0 +1,78 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "actions-types.h"
+
+#include "core/gimp.h"
+
+#include "widgets/gimpdialogfactory.h"
+#include "widgets/gimpwidgets-utils.h"
+#include "widgets/gimpwindowstrategy.h"
+
+#include "actions.h"
+#include "dialogs-commands.h"
+
+
+/* public functions */
+
+void
+dialogs_create_toplevel_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GtkWidget *widget;
+ const gchar *identifier;
+ return_if_no_widget (widget, data);
+
+ identifier = g_variant_get_string (value, NULL);
+
+ if (identifier)
+ gimp_dialog_factory_dialog_new (gimp_dialog_factory_get_singleton (),
+ gtk_widget_get_screen (widget),
+ gimp_widget_get_monitor (widget),
+ NULL /*ui_manager*/,
+ identifier, -1, TRUE);
+}
+
+void
+dialogs_create_dockable_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ Gimp *gimp;
+ GtkWidget *widget;
+ const gchar *identifier;
+ return_if_no_gimp (gimp, data);
+ return_if_no_widget (widget, data);
+
+ identifier = g_variant_get_string (value, NULL);
+
+ if (identifier)
+ gimp_window_strategy_show_dockable_dialog (GIMP_WINDOW_STRATEGY (gimp_get_window_strategy (gimp)),
+ gimp,
+ gimp_dialog_factory_get_singleton (),
+ gtk_widget_get_screen (widget),
+ gimp_widget_get_monitor (widget),
+ identifier);
+}
diff --git a/app/actions/dialogs-commands.h b/app/actions/dialogs-commands.h
new file mode 100644
index 0000000..22abafc
--- /dev/null
+++ b/app/actions/dialogs-commands.h
@@ -0,0 +1,30 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __DIALOGS_COMMANDS_H__
+#define __DIALOGS_COMMANDS_H__
+
+
+void dialogs_create_toplevel_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void dialogs_create_dockable_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+
+#endif /* __DIALOGS_COMMANDS_H__ */
diff --git a/app/actions/dock-actions.c b/app/actions/dock-actions.c
new file mode 100644
index 0000000..1f7dc38
--- /dev/null
+++ b/app/actions/dock-actions.c
@@ -0,0 +1,141 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "actions-types.h"
+
+#include "widgets/gimpactiongroup.h"
+#include "widgets/gimpdockwindow.h"
+#include "widgets/gimphelp-ids.h"
+#include "widgets/gimpmenudock.h"
+
+#include "display/gimpimagewindow.h"
+
+#include "actions.h"
+#include "dock-actions.h"
+#include "dock-commands.h"
+#include "window-actions.h"
+#include "window-commands.h"
+
+#include "gimp-intl.h"
+
+
+static const GimpActionEntry dock_actions[] =
+{
+ { "dock-move-to-screen-menu", GIMP_ICON_WINDOW_MOVE_TO_SCREEN,
+ NC_("dock-action", "M_ove to Screen"), NULL, NULL, NULL,
+ GIMP_HELP_DOCK_CHANGE_SCREEN },
+
+ { "dock-close", GIMP_ICON_WINDOW_CLOSE,
+ NC_("dock-action", "Close Dock"), "", NULL,
+ window_close_cmd_callback,
+ GIMP_HELP_DOCK_CLOSE },
+
+ { "dock-open-display", NULL,
+ NC_("dock-action", "_Open Display..."), NULL,
+ NC_("dock-action", "Connect to another display"),
+ window_open_display_cmd_callback,
+ NULL }
+};
+
+static const GimpToggleActionEntry dock_toggle_actions[] =
+{
+ { "dock-show-image-menu", NULL,
+ NC_("dock-action", "_Show Image Selection"), NULL, NULL,
+ dock_toggle_image_menu_cmd_callback,
+ TRUE,
+ GIMP_HELP_DOCK_IMAGE_MENU },
+
+ { "dock-auto-follow-active", NULL,
+ NC_("dock-action", "Auto _Follow Active Image"), NULL, NULL,
+ dock_toggle_auto_cmd_callback,
+ TRUE,
+ GIMP_HELP_DOCK_AUTO_BUTTON }
+};
+
+
+void
+dock_actions_setup (GimpActionGroup *group)
+{
+ gimp_action_group_add_actions (group, "dock-action",
+ dock_actions,
+ G_N_ELEMENTS (dock_actions));
+
+ gimp_action_group_add_toggle_actions (group, "dock-action",
+ dock_toggle_actions,
+ G_N_ELEMENTS (dock_toggle_actions));
+
+ window_actions_setup (group, GIMP_HELP_DOCK_CHANGE_SCREEN);
+}
+
+void
+dock_actions_update (GimpActionGroup *group,
+ gpointer data)
+{
+ GtkWidget *widget = action_data_get_widget (data);
+ GtkWidget *toplevel = NULL;
+
+ if (widget)
+ toplevel = gtk_widget_get_toplevel (widget);
+
+#define SET_ACTIVE(action,active) \
+ gimp_action_group_set_action_active (group, action, (active) != 0)
+#define SET_VISIBLE(action,active) \
+ gimp_action_group_set_action_visible (group, action, (active) != 0)
+
+ if (GIMP_IS_DOCK_WINDOW (toplevel))
+ {
+ GimpDockWindow *dock_window = GIMP_DOCK_WINDOW (toplevel);
+ gboolean show_image_menu = ! gimp_dock_window_has_toolbox (dock_window);
+
+ if (show_image_menu)
+ {
+ SET_VISIBLE ("dock-show-image-menu", TRUE);
+ SET_VISIBLE ("dock-auto-follow-active", TRUE);
+
+ SET_ACTIVE ("dock-show-image-menu",
+ gimp_dock_window_get_show_image_menu (dock_window));
+ SET_ACTIVE ("dock-auto-follow-active",
+ gimp_dock_window_get_auto_follow_active (dock_window));
+ }
+ else
+ {
+ SET_VISIBLE ("dock-show-image-menu", FALSE);
+ SET_VISIBLE ("dock-auto-follow-active", FALSE);
+ }
+
+ /* update the window actions only in the context of their
+ * own window (not in the context of some display or NULL)
+ * (see view-actions.c)
+ */
+ window_actions_update (group, toplevel);
+ }
+ else if (GIMP_IS_IMAGE_WINDOW (toplevel))
+ {
+ SET_VISIBLE ("dock-show-image-menu", FALSE);
+ SET_VISIBLE ("dock-auto-follow-active", FALSE);
+ }
+
+#undef SET_ACTIVE
+#undef SET_VISIBLE
+}
diff --git a/app/actions/dock-actions.h b/app/actions/dock-actions.h
new file mode 100644
index 0000000..9e26c36
--- /dev/null
+++ b/app/actions/dock-actions.h
@@ -0,0 +1,27 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __DOCK_ACTIONS_H__
+#define __DOCK_ACTIONS_H__
+
+
+void dock_actions_setup (GimpActionGroup *group);
+void dock_actions_update (GimpActionGroup *group,
+ gpointer data);
+
+
+#endif /* __DOCK_ACTIONS_H__ */
diff --git a/app/actions/dock-commands.c b/app/actions/dock-commands.c
new file mode 100644
index 0000000..35508d5
--- /dev/null
+++ b/app/actions/dock-commands.c
@@ -0,0 +1,85 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "actions-types.h"
+
+#include "widgets/gimpdockwindow.h"
+#include "widgets/gimpdockwindow.h"
+
+#include "actions.h"
+#include "dock-commands.h"
+
+
+static GimpDockWindow *
+dock_commands_get_dock_window_from_widget (GtkWidget *widget)
+{
+ GtkWidget *toplevel = gtk_widget_get_toplevel (widget);
+ GimpDockWindow *dock_window = NULL;
+
+ if (GIMP_IS_DOCK_WINDOW (toplevel))
+ dock_window = GIMP_DOCK_WINDOW (toplevel);
+
+ return dock_window;
+}
+
+
+/* public functions */
+
+void
+dock_toggle_image_menu_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GtkWidget *widget = NULL;
+ GimpDockWindow *dock_window = NULL;
+ return_if_no_widget (widget, data);
+
+ dock_window = dock_commands_get_dock_window_from_widget (widget);
+
+ if (dock_window)
+ {
+ gboolean active = g_variant_get_boolean (value);
+
+ gimp_dock_window_set_show_image_menu (dock_window, active);
+ }
+}
+
+void
+dock_toggle_auto_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GtkWidget *widget = NULL;
+ GimpDockWindow *dock_window = NULL;
+ return_if_no_widget (widget, data);
+
+ dock_window = dock_commands_get_dock_window_from_widget (widget);
+
+ if (dock_window)
+ {
+ gboolean active = g_variant_get_boolean (value);
+
+ gimp_dock_window_set_auto_follow_active (dock_window, active);
+ }
+}
diff --git a/app/actions/dock-commands.h b/app/actions/dock-commands.h
new file mode 100644
index 0000000..73120de
--- /dev/null
+++ b/app/actions/dock-commands.h
@@ -0,0 +1,30 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __DOCK_COMMANDS_H__
+#define __DOCK_COMMANDS_H__
+
+
+void dock_toggle_image_menu_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void dock_toggle_auto_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+
+#endif /* __DOCK_COMMANDS_H__ */
diff --git a/app/actions/dockable-actions.c b/app/actions/dockable-actions.c
new file mode 100644
index 0000000..d80ca33
--- /dev/null
+++ b/app/actions/dockable-actions.c
@@ -0,0 +1,375 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gegl.h>
+#include <string.h>
+
+#include <gtk/gtk.h>
+
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "actions-types.h"
+
+#include "widgets/gimpactiongroup.h"
+#include "widgets/gimpcontainerview.h"
+#include "widgets/gimpcontainerview-utils.h"
+#include "widgets/gimpdialogfactory.h"
+#include "widgets/gimpdock.h"
+#include "widgets/gimpdockable.h"
+#include "widgets/gimpdockbook.h"
+#include "widgets/gimpdocked.h"
+#include "widgets/gimphelp-ids.h"
+
+#include "dialogs-actions.h"
+#include "dockable-actions.h"
+#include "dockable-commands.h"
+
+#include "gimp-intl.h"
+
+
+static const GimpActionEntry dockable_actions[] =
+{
+ { "dockable-popup", NULL,
+ NC_("dockable-action", "Dialogs Menu"), NULL, NULL, NULL,
+ GIMP_HELP_DOCK },
+
+ { "dockable-menu", "image-missing", "" },
+ { "dockable-add-tab-menu", NULL, NC_("dockable-action",
+ "_Add Tab") },
+ { "dockable-preview-size-menu", NULL, NC_("dockable-action",
+ "_Preview Size") },
+ { "dockable-tab-style-menu", NULL, NC_("dockable-action",
+ "_Tab Style") },
+
+ { "dockable-close-tab", "window-close",
+ NC_("dockable-action", "_Close Tab"), "", NULL,
+ dockable_close_tab_cmd_callback,
+ GIMP_HELP_DOCK_TAB_CLOSE },
+
+ { "dockable-detach-tab", GIMP_ICON_DETACH,
+ NC_("dockable-action", "_Detach Tab"), "", NULL,
+ dockable_detach_tab_cmd_callback,
+ GIMP_HELP_DOCK_TAB_DETACH }
+};
+
+#define VIEW_SIZE(action,label,size) \
+ { "dockable-preview-size-" action, NULL, \
+ (label), NULL, NULL, \
+ (size), \
+ GIMP_HELP_DOCK_PREVIEW_SIZE }
+#define TAB_STYLE(action,label,style) \
+ { "dockable-tab-style-" action, NULL, \
+ (label), NULL, NULL, \
+ (style), \
+ GIMP_HELP_DOCK_TAB_STYLE }
+
+static const GimpRadioActionEntry dockable_view_size_actions[] =
+{
+ VIEW_SIZE ("tiny",
+ NC_("preview-size", "_Tiny"), GIMP_VIEW_SIZE_TINY),
+ VIEW_SIZE ("extra-small",
+ NC_("preview-size", "E_xtra Small"), GIMP_VIEW_SIZE_EXTRA_SMALL),
+ VIEW_SIZE ("small",
+ NC_("preview-size", "_Small"), GIMP_VIEW_SIZE_SMALL),
+ VIEW_SIZE ("medium",
+ NC_("preview-size", "_Medium"), GIMP_VIEW_SIZE_MEDIUM),
+ VIEW_SIZE ("large",
+ NC_("preview-size", "_Large"), GIMP_VIEW_SIZE_LARGE),
+ VIEW_SIZE ("extra-large",
+ NC_("preview-size", "Ex_tra Large"), GIMP_VIEW_SIZE_EXTRA_LARGE),
+ VIEW_SIZE ("huge",
+ NC_("preview-size", "_Huge"), GIMP_VIEW_SIZE_HUGE),
+ VIEW_SIZE ("enormous",
+ NC_("preview-size", "_Enormous"), GIMP_VIEW_SIZE_ENORMOUS),
+ VIEW_SIZE ("gigantic",
+ NC_("preview-size", "_Gigantic"), GIMP_VIEW_SIZE_GIGANTIC)
+};
+
+static const GimpRadioActionEntry dockable_tab_style_actions[] =
+{
+ TAB_STYLE ("icon",
+ NC_("tab-style", "_Icon"), GIMP_TAB_STYLE_ICON),
+ TAB_STYLE ("preview",
+ NC_("tab-style", "Current _Status"), GIMP_TAB_STYLE_PREVIEW),
+ TAB_STYLE ("name",
+ NC_("tab-style", "_Text"), GIMP_TAB_STYLE_NAME),
+ TAB_STYLE ("icon-name",
+ NC_("tab-style", "I_con & Text"), GIMP_TAB_STYLE_ICON_NAME),
+ TAB_STYLE ("preview-name",
+ NC_("tab-style", "St_atus & Text"), GIMP_TAB_STYLE_PREVIEW_NAME),
+ TAB_STYLE ("automatic",
+ NC_("tab-style", "Automatic"), GIMP_TAB_STYLE_AUTOMATIC)
+};
+
+#undef VIEW_SIZE
+#undef TAB_STYLE
+
+
+static const GimpToggleActionEntry dockable_toggle_actions[] =
+{
+ { "dockable-lock-tab", NULL,
+ NC_("dockable-action", "Loc_k Tab to Dock"), NULL,
+ NC_("dockable-action",
+ "Protect this tab from being dragged with the mouse pointer"),
+ dockable_lock_tab_cmd_callback,
+ FALSE,
+ GIMP_HELP_DOCK_TAB_LOCK },
+
+ { "dockable-show-button-bar", NULL,
+ NC_("dockable-action", "Show _Button Bar"), NULL, NULL,
+ dockable_show_button_bar_cmd_callback,
+ TRUE,
+ GIMP_HELP_DOCK_SHOW_BUTTON_BAR }
+};
+
+static const GimpRadioActionEntry dockable_view_type_actions[] =
+{
+ { "dockable-view-type-list", NULL,
+ NC_("dockable-action", "View as _List"), NULL, NULL,
+ GIMP_VIEW_TYPE_LIST,
+ GIMP_HELP_DOCK_VIEW_AS_LIST },
+
+ { "dockable-view-type-grid", NULL,
+ NC_("dockable-action", "View as _Grid"), NULL, NULL,
+ GIMP_VIEW_TYPE_GRID,
+ GIMP_HELP_DOCK_VIEW_AS_GRID }
+};
+
+
+void
+dockable_actions_setup (GimpActionGroup *group)
+{
+ gimp_action_group_add_actions (group, "dockable-action",
+ dockable_actions,
+ G_N_ELEMENTS (dockable_actions));
+
+ gimp_action_group_add_toggle_actions (group, "dockable-action",
+ dockable_toggle_actions,
+ G_N_ELEMENTS (dockable_toggle_actions));
+
+ gimp_action_group_add_string_actions (group, "dialogs-action",
+ dialogs_dockable_actions,
+ n_dialogs_dockable_actions,
+ dockable_add_tab_cmd_callback);
+
+ gimp_action_group_add_radio_actions (group, "preview-size",
+ dockable_view_size_actions,
+ G_N_ELEMENTS (dockable_view_size_actions),
+ NULL,
+ GIMP_VIEW_SIZE_MEDIUM,
+ dockable_view_size_cmd_callback);
+
+ gimp_action_group_add_radio_actions (group, "tab-style",
+ dockable_tab_style_actions,
+ G_N_ELEMENTS (dockable_tab_style_actions),
+ NULL,
+ GIMP_TAB_STYLE_AUTOMATIC,
+ dockable_tab_style_cmd_callback);
+
+ gimp_action_group_add_radio_actions (group, "dockable-action",
+ dockable_view_type_actions,
+ G_N_ELEMENTS (dockable_view_type_actions),
+ NULL,
+ GIMP_VIEW_TYPE_LIST,
+ dockable_toggle_view_cmd_callback);
+}
+
+void
+dockable_actions_update (GimpActionGroup *group,
+ gpointer data)
+{
+ GimpDockable *dockable;
+ GimpDockbook *dockbook;
+ GimpDocked *docked;
+ GimpDock *dock;
+ GimpDialogFactoryEntry *entry;
+ GimpContainerView *view;
+ GimpViewType view_type = -1;
+ gboolean list_view_available = FALSE;
+ gboolean grid_view_available = FALSE;
+ gboolean locked = FALSE;
+ GimpViewSize view_size = -1;
+ GimpTabStyle tab_style = -1;
+ gint n_pages = 0;
+ gint n_books = 0;
+ GimpDockedInterface *docked_iface = NULL;
+
+ if (GIMP_IS_DOCKBOOK (data))
+ {
+ gint page_num;
+
+ dockbook = GIMP_DOCKBOOK (data);
+
+ page_num = gtk_notebook_get_current_page (GTK_NOTEBOOK (dockbook));
+
+ dockable = (GimpDockable *)
+ gtk_notebook_get_nth_page (GTK_NOTEBOOK (dockbook), page_num);
+ }
+ else if (GIMP_IS_DOCKABLE (data))
+ {
+ dockable = GIMP_DOCKABLE (data);
+ dockbook = gimp_dockable_get_dockbook (dockable);
+ }
+ else
+ {
+ return;
+ }
+
+ docked = GIMP_DOCKED (gtk_bin_get_child (GTK_BIN (dockable)));
+ dock = gimp_dockbook_get_dock (dockbook);
+
+
+ gimp_dialog_factory_from_widget (GTK_WIDGET (dockable), &entry);
+
+ if (entry)
+ {
+ gchar *identifier;
+ gchar *substring = NULL;
+
+ identifier = g_strdup (entry->identifier);
+
+ if ((substring = strstr (identifier, "grid")))
+ view_type = GIMP_VIEW_TYPE_GRID;
+ else if ((substring = strstr (identifier, "list")))
+ view_type = GIMP_VIEW_TYPE_LIST;
+
+ if (substring)
+ {
+ memcpy (substring, "list", 4);
+ if (gimp_dialog_factory_find_entry (gimp_dock_get_dialog_factory (dock),
+ identifier))
+ list_view_available = TRUE;
+
+ memcpy (substring, "grid", 4);
+ if (gimp_dialog_factory_find_entry (gimp_dock_get_dialog_factory (dock),
+ identifier))
+ grid_view_available = TRUE;
+ }
+
+ g_free (identifier);
+ }
+
+ view = gimp_container_view_get_by_dockable (dockable);
+
+ if (view)
+ view_size = gimp_container_view_get_view_size (view, NULL);
+
+ tab_style = gimp_dockable_get_tab_style (dockable);
+
+ n_pages = gtk_notebook_get_n_pages (GTK_NOTEBOOK (dockbook));
+ n_books = g_list_length (gimp_dock_get_dockbooks (dock));
+
+#define SET_ACTIVE(action,active) \
+ gimp_action_group_set_action_active (group, action, (active) != 0)
+#define SET_VISIBLE(action,active) \
+ gimp_action_group_set_action_visible (group, action, (active) != 0)
+#define SET_SENSITIVE(action,sensitive) \
+ gimp_action_group_set_action_sensitive (group, action, (sensitive) != 0)
+
+
+ locked = gimp_dockable_is_locked (dockable);
+
+ SET_SENSITIVE ("dockable-detach-tab", (! locked &&
+ (n_pages > 1 || n_books > 1)));
+
+ SET_ACTIVE ("dockable-lock-tab", locked);
+
+ SET_VISIBLE ("dockable-preview-size-menu", view_size != -1);
+
+ if (view_size != -1)
+ {
+ if (view_size >= GIMP_VIEW_SIZE_GIGANTIC)
+ {
+ SET_ACTIVE ("dockable-preview-size-gigantic", TRUE);
+ }
+ else if (view_size >= GIMP_VIEW_SIZE_ENORMOUS)
+ {
+ SET_ACTIVE ("dockable-preview-size-enormous", TRUE);
+ }
+ else if (view_size >= GIMP_VIEW_SIZE_HUGE)
+ {
+ SET_ACTIVE ("dockable-preview-size-huge", TRUE);
+ }
+ else if (view_size >= GIMP_VIEW_SIZE_EXTRA_LARGE)
+ {
+ SET_ACTIVE ("dockable-preview-size-extra-large", TRUE);
+ }
+ else if (view_size >= GIMP_VIEW_SIZE_LARGE)
+ {
+ SET_ACTIVE ("dockable-preview-size-large", TRUE);
+ }
+ else if (view_size >= GIMP_VIEW_SIZE_MEDIUM)
+ {
+ SET_ACTIVE ("dockable-preview-size-medium", TRUE);
+ }
+ else if (view_size >= GIMP_VIEW_SIZE_SMALL)
+ {
+ SET_ACTIVE ("dockable-preview-size-small", TRUE);
+ }
+ else if (view_size >= GIMP_VIEW_SIZE_EXTRA_SMALL)
+ {
+ SET_ACTIVE ("dockable-preview-size-extra-small", TRUE);
+ }
+ else if (view_size >= GIMP_VIEW_SIZE_TINY)
+ {
+ SET_ACTIVE ("dockable-preview-size-tiny", TRUE);
+ }
+ }
+
+ if (tab_style == GIMP_TAB_STYLE_ICON)
+ SET_ACTIVE ("dockable-tab-style-icon", TRUE);
+ else if (tab_style == GIMP_TAB_STYLE_PREVIEW)
+ SET_ACTIVE ("dockable-tab-style-preview", TRUE);
+ else if (tab_style == GIMP_TAB_STYLE_NAME)
+ SET_ACTIVE ("dockable-tab-style-name", TRUE);
+ else if (tab_style == GIMP_TAB_STYLE_ICON_NAME)
+ SET_ACTIVE ("dockable-tab-style-icon-name", TRUE);
+ else if (tab_style == GIMP_TAB_STYLE_PREVIEW_NAME)
+ SET_ACTIVE ("dockable-tab-style-preview-name", TRUE);
+ else if (tab_style == GIMP_TAB_STYLE_AUTOMATIC)
+ SET_ACTIVE ("dockable-tab-style-automatic", TRUE);
+
+ docked_iface = GIMP_DOCKED_GET_INTERFACE (docked);
+ SET_SENSITIVE ("dockable-tab-style-preview",
+ docked_iface->get_preview);
+ SET_SENSITIVE ("dockable-tab-style-preview-name",
+ docked_iface->get_preview);
+
+ SET_VISIBLE ("dockable-view-type-grid", view_type != -1);
+ SET_VISIBLE ("dockable-view-type-list", view_type != -1);
+
+ if (view_type != -1)
+ {
+ if (view_type == GIMP_VIEW_TYPE_LIST)
+ SET_ACTIVE ("dockable-view-type-list", TRUE);
+ else
+ SET_ACTIVE ("dockable-view-type-grid", TRUE);
+
+ SET_SENSITIVE ("dockable-view-type-grid", grid_view_available);
+ SET_SENSITIVE ("dockable-view-type-list", list_view_available);
+ }
+
+ SET_VISIBLE ("dockable-show-button-bar", gimp_docked_has_button_bar (docked));
+ SET_ACTIVE ("dockable-show-button-bar",
+ gimp_docked_get_show_button_bar (docked));
+
+#undef SET_ACTIVE
+#undef SET_VISIBLE
+#undef SET_SENSITIVE
+}
diff --git a/app/actions/dockable-actions.h b/app/actions/dockable-actions.h
new file mode 100644
index 0000000..d70872d
--- /dev/null
+++ b/app/actions/dockable-actions.h
@@ -0,0 +1,27 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __DOCKABLE_ACTIONS_H__
+#define __DOCKABLE_ACTIONS_H__
+
+
+void dockable_actions_setup (GimpActionGroup *group);
+void dockable_actions_update (GimpActionGroup *group,
+ gpointer data);
+
+
+#endif /* __DOCKABLE_ACTIONS_H__ */
diff --git a/app/actions/dockable-commands.c b/app/actions/dockable-commands.c
new file mode 100644
index 0000000..60229e3
--- /dev/null
+++ b/app/actions/dockable-commands.c
@@ -0,0 +1,298 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <string.h>
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "actions-types.h"
+
+#include "widgets/gimpcontainerview.h"
+#include "widgets/gimpcontainerview-utils.h"
+#include "widgets/gimpdialogfactory.h"
+#include "widgets/gimpdock.h"
+#include "widgets/gimpdockable.h"
+#include "widgets/gimpdockbook.h"
+#include "widgets/gimpdocked.h"
+#include "widgets/gimpsessioninfo.h"
+
+#include "dockable-commands.h"
+
+
+static GimpDockable * dockable_get_current (GimpDockbook *dockbook);
+
+
+/* public functions */
+
+void
+dockable_add_tab_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpDockbook *dockbook = GIMP_DOCKBOOK (data);
+
+ gimp_dockbook_add_from_dialog_factory (dockbook,
+ g_variant_get_string (value, NULL),
+ -1);
+}
+
+void
+dockable_close_tab_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpDockbook *dockbook = GIMP_DOCKBOOK (data);
+ GimpDockable *dockable = dockable_get_current (dockbook);
+
+ if (dockable)
+ {
+ g_object_ref (dockable);
+ gimp_dockbook_remove (dockbook, dockable);
+ gtk_widget_destroy (GTK_WIDGET (dockable));
+ g_object_unref (dockable);
+ }
+}
+
+void
+dockable_detach_tab_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpDockbook *dockbook = GIMP_DOCKBOOK (data);
+ GimpDockable *dockable = dockable_get_current (dockbook);
+
+ if (dockable)
+ gimp_dockable_detach (dockable);
+}
+
+void
+dockable_lock_tab_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpDockbook *dockbook = GIMP_DOCKBOOK (data);
+ GimpDockable *dockable = dockable_get_current (dockbook);
+
+ if (dockable)
+ {
+ gboolean lock = g_variant_get_boolean (value);
+
+ gimp_dockable_set_locked (dockable, lock);
+ }
+}
+
+void
+dockable_toggle_view_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpDockbook *dockbook = GIMP_DOCKBOOK (data);
+ GimpDockable *dockable;
+ GimpViewType view_type;
+ gint page_num;
+
+ view_type = (GimpViewType) g_variant_get_int32 (value);
+
+ page_num = gtk_notebook_get_current_page (GTK_NOTEBOOK (dockbook));
+
+ dockable = (GimpDockable *)
+ gtk_notebook_get_nth_page (GTK_NOTEBOOK (dockbook), page_num);
+
+ if (dockable)
+ {
+ GimpDialogFactoryEntry *entry;
+
+ gimp_dialog_factory_from_widget (GTK_WIDGET (dockable), &entry);
+
+ if (entry)
+ {
+ gchar *identifier;
+ gchar *substring = NULL;
+
+ identifier = g_strdup (entry->identifier);
+
+ substring = strstr (identifier, "grid");
+
+ if (substring && view_type == GIMP_VIEW_TYPE_GRID)
+ {
+ g_free (identifier);
+ return;
+ }
+
+ if (! substring)
+ {
+ substring = strstr (identifier, "list");
+
+ if (substring && view_type == GIMP_VIEW_TYPE_LIST)
+ {
+ g_free (identifier);
+ return;
+ }
+ }
+
+ if (substring)
+ {
+ GimpContainerView *old_view;
+ GtkWidget *new_dockable;
+ GimpDock *dock;
+ gint view_size = -1;
+
+ if (view_type == GIMP_VIEW_TYPE_LIST)
+ memcpy (substring, "list", 4);
+ else if (view_type == GIMP_VIEW_TYPE_GRID)
+ memcpy (substring, "grid", 4);
+
+ old_view = gimp_container_view_get_by_dockable (dockable);
+
+ if (old_view)
+ view_size = gimp_container_view_get_view_size (old_view, NULL);
+
+ dock = gimp_dockbook_get_dock (dockbook);
+ new_dockable = gimp_dialog_factory_dockable_new (gimp_dock_get_dialog_factory (dock),
+ dock,
+ identifier,
+ view_size);
+
+ if (new_dockable)
+ {
+ GimpDocked *old;
+ GimpDocked *new;
+ gboolean show;
+
+ gimp_dockable_set_locked (GIMP_DOCKABLE (new_dockable),
+ gimp_dockable_is_locked (dockable));
+
+ old = GIMP_DOCKED (gtk_bin_get_child (GTK_BIN (dockable)));
+ new = GIMP_DOCKED (gtk_bin_get_child (GTK_BIN (new_dockable)));
+
+ show = gimp_docked_get_show_button_bar (old);
+ gimp_docked_set_show_button_bar (new, show);
+
+ /* Maybe gimp_dialog_factory_dockable_new() returned
+ * an already existing singleton dockable, so check
+ * if it already is attached to a dockbook.
+ */
+ if (! gimp_dockable_get_dockbook (GIMP_DOCKABLE (new_dockable)))
+ {
+ gimp_dockbook_add (dockbook, GIMP_DOCKABLE (new_dockable),
+ page_num);
+
+ g_object_ref (dockable);
+ gimp_dockbook_remove (dockbook, dockable);
+ gtk_widget_destroy (GTK_WIDGET (dockable));
+ g_object_unref (dockable);
+
+ gtk_notebook_set_current_page (GTK_NOTEBOOK (dockbook),
+ page_num);
+ }
+ }
+ }
+
+ g_free (identifier);
+ }
+ }
+}
+
+void
+dockable_view_size_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpDockbook *dockbook = GIMP_DOCKBOOK (data);
+ GimpDockable *dockable = dockable_get_current (dockbook);
+ gint view_size;
+
+ view_size = g_variant_get_int32 (value);
+
+ if (dockable)
+ {
+ GimpContainerView *view = gimp_container_view_get_by_dockable (dockable);
+
+ if (view)
+ {
+ gint old_size;
+ gint border_width;
+
+ old_size = gimp_container_view_get_view_size (view, &border_width);
+
+ if (old_size != view_size)
+ gimp_container_view_set_view_size (view, view_size, border_width);
+ }
+ }
+}
+
+void
+dockable_tab_style_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpDockbook *dockbook = GIMP_DOCKBOOK (data);
+ GimpDockable *dockable = dockable_get_current (dockbook);
+ GimpTabStyle tab_style;
+
+ tab_style = (GimpTabStyle) g_variant_get_int32 (value);
+
+ if (dockable && gimp_dockable_get_tab_style (dockable) != tab_style)
+ {
+ GtkWidget *tab_widget;
+
+ gimp_dockable_set_tab_style (dockable, tab_style);
+
+ tab_widget = gimp_dockbook_create_tab_widget (dockbook, dockable);
+
+ gtk_notebook_set_tab_label (GTK_NOTEBOOK (dockbook),
+ GTK_WIDGET (dockable),
+ tab_widget);
+ }
+}
+
+void
+dockable_show_button_bar_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpDockbook *dockbook = GIMP_DOCKBOOK (data);
+ GimpDockable *dockable = dockable_get_current (dockbook);
+
+ if (dockable)
+ {
+ GimpDocked *docked;
+ gboolean show;
+
+ docked = GIMP_DOCKED (gtk_bin_get_child (GTK_BIN (dockable)));
+ show = g_variant_get_boolean (value);
+
+ gimp_docked_set_show_button_bar (docked, show);
+ }
+}
+
+
+/* private functions */
+
+static GimpDockable *
+dockable_get_current (GimpDockbook *dockbook)
+{
+ gint page_num = gtk_notebook_get_current_page (GTK_NOTEBOOK (dockbook));
+
+ return (GimpDockable *) gtk_notebook_get_nth_page (GTK_NOTEBOOK (dockbook),
+ page_num);
+}
diff --git a/app/actions/dockable-commands.h b/app/actions/dockable-commands.h
new file mode 100644
index 0000000..3ffb848
--- /dev/null
+++ b/app/actions/dockable-commands.h
@@ -0,0 +1,49 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __DOCKABLE_COMMANDS_H__
+#define __DOCKABLE_COMMANDS_H__
+
+
+void dockable_add_tab_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void dockable_close_tab_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void dockable_detach_tab_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void dockable_lock_tab_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+void dockable_toggle_view_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void dockable_view_size_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void dockable_tab_style_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void dockable_show_button_bar_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+
+#endif /* __DOCKABLE_COMMANDS_H__ */
diff --git a/app/actions/documents-actions.c b/app/actions/documents-actions.c
new file mode 100644
index 0000000..80c0371
--- /dev/null
+++ b/app/actions/documents-actions.c
@@ -0,0 +1,143 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "actions-types.h"
+
+#include "core/gimpcontext.h"
+
+#include "widgets/gimpactiongroup.h"
+#include "widgets/gimphelp-ids.h"
+
+#include "actions.h"
+#include "documents-actions.h"
+#include "documents-commands.h"
+
+#include "gimp-intl.h"
+
+
+static const GimpActionEntry documents_actions[] =
+{
+ { "documents-popup", GIMP_ICON_DOCUMENT_OPEN_RECENT,
+ NC_("documents-action", "Documents Menu"), NULL, NULL, NULL,
+ GIMP_HELP_DOCUMENT_DIALOG },
+
+ { "documents-open", GIMP_ICON_DOCUMENT_OPEN,
+ NC_("documents-action", "_Open Image"), NULL,
+ NC_("documents-action", "Open the selected entry"),
+ documents_open_cmd_callback,
+ GIMP_HELP_DOCUMENT_OPEN },
+
+ { "documents-raise-or-open", NULL,
+ NC_("documents-action", "_Raise or Open Image"), NULL,
+ NC_("documents-action", "Raise window if already open"),
+ documents_raise_or_open_cmd_callback,
+ GIMP_HELP_DOCUMENT_OPEN },
+
+ { "documents-file-open-dialog", NULL,
+ NC_("documents-action", "File Open _Dialog"), NULL,
+ NC_("documents-action", "Open image dialog"),
+ documents_file_open_dialog_cmd_callback,
+ GIMP_HELP_DOCUMENT_OPEN },
+
+ { "documents-copy-location", GIMP_ICON_EDIT_COPY,
+ NC_("documents-action", "Copy Image _Location"), NULL,
+ NC_("documents-action", "Copy image location to clipboard"),
+ documents_copy_location_cmd_callback,
+ GIMP_HELP_DOCUMENT_COPY_LOCATION },
+
+ { "documents-show-in-file-manager", GIMP_ICON_FILE_MANAGER,
+ NC_("documents-action", "Show in _File Manager"), NULL,
+ NC_("documents-action", "Show image location in the file manager"),
+ documents_show_in_file_manager_cmd_callback,
+ GIMP_HELP_DOCUMENT_SHOW_IN_FILE_MANAGER },
+
+ { "documents-remove", GIMP_ICON_LIST_REMOVE,
+ NC_("documents-action", "Remove _Entry"), NULL,
+ NC_("documents-action", "Remove the selected entry"),
+ documents_remove_cmd_callback,
+ GIMP_HELP_DOCUMENT_REMOVE },
+
+ { "documents-clear", GIMP_ICON_SHRED,
+ NC_("documents-action", "_Clear History"), NULL,
+ NC_("documents-action", "Clear the entire document history"),
+ documents_clear_cmd_callback,
+ GIMP_HELP_DOCUMENT_CLEAR },
+
+ { "documents-recreate-preview", GIMP_ICON_VIEW_REFRESH,
+ NC_("documents-action", "Recreate _Preview"), NULL,
+ NC_("documents-action", "Recreate preview"),
+ documents_recreate_preview_cmd_callback,
+ GIMP_HELP_DOCUMENT_REFRESH },
+
+ { "documents-reload-previews", NULL,
+ NC_("documents-action", "Reload _all Previews"), NULL,
+ NC_("documents-action", "Reload all previews"),
+ documents_reload_previews_cmd_callback,
+ GIMP_HELP_DOCUMENT_REFRESH },
+
+ { "documents-remove-dangling", NULL,
+ NC_("documents-action", "Remove Dangling E_ntries"), NULL,
+ NC_("documents-action",
+ "Remove entries for which the corresponding file is not available"),
+ documents_remove_dangling_cmd_callback,
+ GIMP_HELP_DOCUMENT_REFRESH }
+};
+
+
+void
+documents_actions_setup (GimpActionGroup *group)
+{
+ gimp_action_group_add_actions (group, "documents-action",
+ documents_actions,
+ G_N_ELEMENTS (documents_actions));
+}
+
+void
+documents_actions_update (GimpActionGroup *group,
+ gpointer data)
+{
+ GimpContext *context;
+ GimpImagefile *imagefile = NULL;
+
+ context = action_data_get_context (data);
+
+ if (context)
+ imagefile = gimp_context_get_imagefile (context);
+
+#define SET_SENSITIVE(action,condition) \
+ gimp_action_group_set_action_sensitive (group, action, (condition) != 0)
+
+ SET_SENSITIVE ("documents-open", imagefile);
+ SET_SENSITIVE ("documents-raise-or-open", imagefile);
+ SET_SENSITIVE ("documents-file-open-dialog", TRUE);
+ SET_SENSITIVE ("documents-copy-location", imagefile);
+ SET_SENSITIVE ("documents-show-in-file-manager", imagefile);
+ SET_SENSITIVE ("documents-remove", imagefile);
+ SET_SENSITIVE ("documents-clear", TRUE);
+ SET_SENSITIVE ("documents-recreate-preview", imagefile);
+ SET_SENSITIVE ("documents-reload-previews", imagefile);
+ SET_SENSITIVE ("documents-remove-dangling", imagefile);
+
+#undef SET_SENSITIVE
+}
diff --git a/app/actions/documents-actions.h b/app/actions/documents-actions.h
new file mode 100644
index 0000000..3d31f27
--- /dev/null
+++ b/app/actions/documents-actions.h
@@ -0,0 +1,27 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __DOCUMENTS_ACTIONS_H__
+#define __DOCUMENTS_ACTIONS_H__
+
+
+void documents_actions_setup (GimpActionGroup *group);
+void documents_actions_update (GimpActionGroup *group,
+ gpointer data);
+
+
+#endif /* __DOCUMENTS_ACTIONS_H__ */
diff --git a/app/actions/documents-commands.c b/app/actions/documents-commands.c
new file mode 100644
index 0000000..b85d065
--- /dev/null
+++ b/app/actions/documents-commands.c
@@ -0,0 +1,410 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <string.h>
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpbase/gimpbase.h"
+#include "libgimpthumb/gimpthumb.h"
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "actions-types.h"
+
+#include "config/gimpcoreconfig.h"
+
+#include "core/gimp.h"
+#include "core/gimpcontainer.h"
+#include "core/gimpcontext.h"
+#include "core/gimpimagefile.h"
+
+#include "file/file-open.h"
+
+#include "widgets/gimpclipboard.h"
+#include "widgets/gimpcontainerview.h"
+#include "widgets/gimpcontainerview-utils.h"
+#include "widgets/gimpdocumentview.h"
+#include "widgets/gimpmessagebox.h"
+#include "widgets/gimpmessagedialog.h"
+#include "widgets/gimpwidgets-utils.h"
+
+#include "display/gimpdisplay.h"
+#include "display/gimpdisplay-foreach.h"
+#include "display/gimpdisplayshell.h"
+
+#include "documents-commands.h"
+#include "file-commands.h"
+
+#include "gimp-intl.h"
+
+
+typedef struct
+{
+ const gchar *name;
+ gboolean found;
+} RaiseClosure;
+
+
+/* local function prototypes */
+
+static void documents_open_image (GtkWidget *editor,
+ GimpContext *context,
+ GimpImagefile *imagefile);
+static void documents_raise_display (GimpDisplay *display,
+ RaiseClosure *closure);
+
+
+
+/* public functions */
+
+void
+documents_open_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpContainerEditor *editor = GIMP_CONTAINER_EDITOR (data);
+ GimpContext *context;
+ GimpContainer *container;
+ GimpImagefile *imagefile;
+
+ context = gimp_container_view_get_context (editor->view);
+ container = gimp_container_view_get_container (editor->view);
+
+ imagefile = gimp_context_get_imagefile (context);
+
+ if (imagefile && gimp_container_have (container, GIMP_OBJECT (imagefile)))
+ {
+ documents_open_image (GTK_WIDGET (editor), context, imagefile);
+ }
+ else
+ {
+ file_file_open_dialog (context->gimp, NULL, GTK_WIDGET (editor));
+ }
+}
+
+void
+documents_raise_or_open_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpContainerEditor *editor = GIMP_CONTAINER_EDITOR (data);
+ GimpContext *context;
+ GimpContainer *container;
+ GimpImagefile *imagefile;
+
+ context = gimp_container_view_get_context (editor->view);
+ container = gimp_container_view_get_container (editor->view);
+
+ imagefile = gimp_context_get_imagefile (context);
+
+ if (imagefile && gimp_container_have (container, GIMP_OBJECT (imagefile)))
+ {
+ RaiseClosure closure;
+
+ closure.name = gimp_object_get_name (imagefile);
+ closure.found = FALSE;
+
+ gimp_container_foreach (context->gimp->displays,
+ (GFunc) documents_raise_display,
+ &closure);
+
+ if (! closure.found)
+ documents_open_image (GTK_WIDGET (editor), context, imagefile);
+ }
+}
+
+void
+documents_file_open_dialog_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpContainerEditor *editor = GIMP_CONTAINER_EDITOR (data);
+ GimpContext *context;
+ GimpContainer *container;
+ GimpImagefile *imagefile;
+
+ context = gimp_container_view_get_context (editor->view);
+ container = gimp_container_view_get_container (editor->view);
+
+ imagefile = gimp_context_get_imagefile (context);
+
+ if (imagefile && gimp_container_have (container, GIMP_OBJECT (imagefile)))
+ {
+ file_file_open_dialog (context->gimp,
+ gimp_imagefile_get_file (imagefile),
+ GTK_WIDGET (editor));
+ }
+}
+
+void
+documents_copy_location_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpContainerEditor *editor = GIMP_CONTAINER_EDITOR (data);
+ GimpContext *context;
+ GimpImagefile *imagefile;
+
+ context = gimp_container_view_get_context (editor->view);
+ imagefile = gimp_context_get_imagefile (context);
+
+ if (imagefile)
+ gimp_clipboard_set_text (context->gimp,
+ gimp_object_get_name (imagefile));
+}
+
+void
+documents_show_in_file_manager_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpContainerEditor *editor = GIMP_CONTAINER_EDITOR (data);
+ GimpContext *context;
+ GimpImagefile *imagefile;
+
+ context = gimp_container_view_get_context (editor->view);
+ imagefile = gimp_context_get_imagefile (context);
+
+ if (imagefile)
+ {
+ GFile *file = g_file_new_for_uri (gimp_object_get_name (imagefile));
+ GError *error = NULL;
+
+ if (! gimp_file_show_in_file_manager (file, &error))
+ {
+ gimp_message (context->gimp, G_OBJECT (editor),
+ GIMP_MESSAGE_ERROR,
+ _("Can't show file in file manager: %s"),
+ error->message);
+ g_clear_error (&error);
+ }
+
+ g_object_unref (file);
+ }
+}
+
+void
+documents_remove_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpContainerEditor *editor = GIMP_CONTAINER_EDITOR (data);
+ GimpContext *context = gimp_container_view_get_context (editor->view);
+ GimpImagefile *imagefile = gimp_context_get_imagefile (context);
+ const gchar *uri;
+
+ uri = gimp_object_get_name (imagefile);
+
+ gtk_recent_manager_remove_item (gtk_recent_manager_get_default (), uri, NULL);
+
+ gimp_container_view_remove_active (editor->view);
+}
+
+void
+documents_clear_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpContainerEditor *editor = GIMP_CONTAINER_EDITOR (data);
+ GimpContext *context = gimp_container_view_get_context (editor->view);
+ Gimp *gimp = context->gimp;
+ GtkWidget *dialog;
+
+ dialog = gimp_message_dialog_new (_("Clear Document History"),
+ GIMP_ICON_SHRED,
+ GTK_WIDGET (editor),
+ GTK_DIALOG_MODAL |
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ gimp_standard_help_func, NULL,
+
+ _("_Cancel"), GTK_RESPONSE_CANCEL,
+ _("Cl_ear"), GTK_RESPONSE_OK,
+
+ NULL);
+
+ gtk_dialog_set_alternative_button_order (GTK_DIALOG (dialog),
+ GTK_RESPONSE_OK,
+ GTK_RESPONSE_CANCEL,
+ -1);
+
+ g_signal_connect_object (gtk_widget_get_toplevel (GTK_WIDGET (editor)),
+ "unmap",
+ G_CALLBACK (gtk_widget_destroy),
+ dialog, G_CONNECT_SWAPPED);
+
+ gimp_message_box_set_primary_text (GIMP_MESSAGE_DIALOG (dialog)->box,
+ _("Clear the Recent Documents list?"));
+
+ gimp_message_box_set_text (GIMP_MESSAGE_DIALOG (dialog)->box,
+ _("Clearing the document history will "
+ "permanently remove all images from "
+ "the recent documents list."));
+
+ if (gimp_dialog_run (GIMP_DIALOG (dialog)) == GTK_RESPONSE_OK)
+ {
+ GtkRecentManager *manager = gtk_recent_manager_get_default ();
+ GList *items;
+ GList *list;
+
+ items = gtk_recent_manager_get_items (manager);
+
+ for (list = items; list; list = list->next)
+ {
+ GtkRecentInfo *info = list->data;
+
+ if (gtk_recent_info_has_application (info,
+ "GNU Image Manipulation Program"))
+ {
+ gtk_recent_manager_remove_item (manager,
+ gtk_recent_info_get_uri (info),
+ NULL);
+ }
+
+ gtk_recent_info_unref (info);
+ }
+
+ g_list_free (items);
+
+ gimp_container_clear (gimp->documents);
+ }
+
+ gtk_widget_destroy (dialog);
+}
+
+void
+documents_recreate_preview_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpContainerEditor *editor = GIMP_CONTAINER_EDITOR (data);
+ GimpContext *context;
+ GimpContainer *container;
+ GimpImagefile *imagefile;
+
+ context = gimp_container_view_get_context (editor->view);
+ container = gimp_container_view_get_container (editor->view);
+
+ imagefile = gimp_context_get_imagefile (context);
+
+ if (imagefile && gimp_container_have (container, GIMP_OBJECT (imagefile)))
+ {
+ GError *error = NULL;
+
+ if (! gimp_imagefile_create_thumbnail (imagefile,
+ context, NULL,
+ context->gimp->config->thumbnail_size,
+ FALSE, &error))
+ {
+ gimp_message_literal (context->gimp,
+ NULL , GIMP_MESSAGE_ERROR,
+ error->message);
+ g_clear_error (&error);
+ }
+ }
+}
+
+void
+documents_reload_previews_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpContainerEditor *editor = GIMP_CONTAINER_EDITOR (data);
+ GimpContainer *container;
+
+ container = gimp_container_view_get_container (editor->view);
+
+ gimp_container_foreach (container,
+ (GFunc) gimp_imagefile_update,
+ editor->view);
+}
+
+static void
+documents_remove_dangling_foreach (GimpImagefile *imagefile,
+ GimpContainer *container)
+{
+ GimpThumbnail *thumbnail = gimp_imagefile_get_thumbnail (imagefile);
+
+ if (gimp_thumbnail_peek_image (thumbnail) == GIMP_THUMB_STATE_NOT_FOUND)
+ {
+ const gchar *uri = gimp_object_get_name (imagefile);
+
+ gtk_recent_manager_remove_item (gtk_recent_manager_get_default (), uri,
+ NULL);
+
+ gimp_container_remove (container, GIMP_OBJECT (imagefile));
+ }
+}
+
+void
+documents_remove_dangling_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpContainerEditor *editor = GIMP_CONTAINER_EDITOR (data);
+ GimpContainer *container;
+
+ container = gimp_container_view_get_container (editor->view);
+
+ gimp_container_foreach (container,
+ (GFunc) documents_remove_dangling_foreach,
+ container);
+}
+
+
+/* private functions */
+
+static void
+documents_open_image (GtkWidget *editor,
+ GimpContext *context,
+ GimpImagefile *imagefile)
+{
+ GFile *file;
+ GimpImage *image;
+ GimpPDBStatusType status;
+ GError *error = NULL;
+
+ file = gimp_imagefile_get_file (imagefile);
+
+ image = file_open_with_display (context->gimp, context, NULL, file, FALSE,
+ G_OBJECT (gtk_widget_get_screen (editor)),
+ gimp_widget_get_monitor (editor),
+ &status, &error);
+
+ if (! image && status != GIMP_PDB_CANCEL)
+ {
+ gimp_message (context->gimp, G_OBJECT (editor), GIMP_MESSAGE_ERROR,
+ _("Opening '%s' failed:\n\n%s"),
+ gimp_file_get_utf8_name (file), error->message);
+ g_clear_error (&error);
+ }
+}
+
+static void
+documents_raise_display (GimpDisplay *display,
+ RaiseClosure *closure)
+{
+ const gchar *uri = gimp_object_get_name (gimp_display_get_image (display));
+
+ if (! g_strcmp0 (closure->name, uri))
+ {
+ closure->found = TRUE;
+ gimp_display_shell_present (gimp_display_get_shell (display));
+ }
+}
diff --git a/app/actions/documents-commands.h b/app/actions/documents-commands.h
new file mode 100644
index 0000000..6db47c5
--- /dev/null
+++ b/app/actions/documents-commands.h
@@ -0,0 +1,54 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __DOCUMENTS_COMMANDS_H__
+#define __DOCUMENTS_COMMANDS_H__
+
+
+void documents_open_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void documents_raise_or_open_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void documents_file_open_dialog_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void documents_copy_location_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void documents_show_in_file_manager_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void documents_remove_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void documents_clear_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void documents_recreate_preview_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void documents_reload_previews_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void documents_remove_dangling_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+
+#endif /* __DOCUMENTS_COMMANDS_H__ */
diff --git a/app/actions/drawable-actions.c b/app/actions/drawable-actions.c
new file mode 100644
index 0000000..a4b6233
--- /dev/null
+++ b/app/actions/drawable-actions.c
@@ -0,0 +1,231 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "actions-types.h"
+
+#include "core/gimp.h"
+#include "core/gimpcontext.h"
+#include "core/gimpimage.h"
+#include "core/gimplayermask.h"
+
+#include "widgets/gimpactiongroup.h"
+#include "widgets/gimphelp-ids.h"
+
+#include "actions.h"
+#include "drawable-actions.h"
+#include "drawable-commands.h"
+
+#include "gimp-intl.h"
+
+
+static const GimpActionEntry drawable_actions[] =
+{
+ { "drawable-equalize", NULL,
+ NC_("drawable-action", "_Equalize"), NULL,
+ NC_("drawable-action", "Automatic contrast enhancement"),
+ drawable_equalize_cmd_callback,
+ GIMP_HELP_LAYER_EQUALIZE },
+
+ { "drawable-levels-stretch", NULL,
+ NC_("drawable-action", "_White Balance"), NULL,
+ NC_("drawable-action", "Automatic white balance correction"),
+ drawable_levels_stretch_cmd_callback,
+ GIMP_HELP_LAYER_WHITE_BALANCE }
+};
+
+static const GimpToggleActionEntry drawable_toggle_actions[] =
+{
+ { "drawable-visible", GIMP_ICON_VISIBLE,
+ NC_("drawable-action", "Toggle Drawable _Visibility"), NULL, NULL,
+ drawable_visible_cmd_callback,
+ FALSE,
+ GIMP_HELP_LAYER_VISIBLE },
+
+ { "drawable-linked", GIMP_ICON_LINKED,
+ NC_("drawable-action", "Toggle Drawable _Linked State"), NULL, NULL,
+ drawable_linked_cmd_callback,
+ FALSE,
+ GIMP_HELP_LAYER_LINKED },
+
+ { "drawable-lock-content", NULL /* GIMP_ICON_LOCK */,
+ NC_("drawable-action", "L_ock Pixels of Drawable"), NULL,
+ NC_("drawable-action",
+ "Keep the pixels on this drawable from being modified"),
+ drawable_lock_content_cmd_callback,
+ FALSE,
+ GIMP_HELP_LAYER_LOCK_PIXELS },
+
+ { "drawable-lock-position", GIMP_ICON_TOOL_MOVE,
+ NC_("drawable-action", "L_ock Position of Drawable"), NULL,
+ NC_("drawable-action",
+ "Keep the position on this drawable from being modified"),
+ drawable_lock_position_cmd_callback,
+ FALSE,
+ GIMP_HELP_LAYER_LOCK_POSITION },
+};
+
+static const GimpEnumActionEntry drawable_flip_actions[] =
+{
+ { "drawable-flip-horizontal", GIMP_ICON_OBJECT_FLIP_HORIZONTAL,
+ NC_("drawable-action", "Flip _Horizontally"), NULL,
+ NC_("drawable-action", "Flip drawable horizontally"),
+ GIMP_ORIENTATION_HORIZONTAL, FALSE,
+ GIMP_HELP_LAYER_FLIP_HORIZONTAL },
+
+ { "drawable-flip-vertical", GIMP_ICON_OBJECT_FLIP_VERTICAL,
+ NC_("drawable-action", "Flip _Vertically"), NULL,
+ NC_("drawable-action", "Flip drawable vertically"),
+ GIMP_ORIENTATION_VERTICAL, FALSE,
+ GIMP_HELP_LAYER_FLIP_VERTICAL }
+};
+
+static const GimpEnumActionEntry drawable_rotate_actions[] =
+{
+ { "drawable-rotate-90", GIMP_ICON_OBJECT_ROTATE_90,
+ NC_("drawable-action", "Rotate 90° _clockwise"), NULL,
+ NC_("drawable-action", "Rotate drawable 90 degrees to the right"),
+ GIMP_ROTATE_90, FALSE,
+ GIMP_HELP_LAYER_ROTATE_90 },
+
+ { "drawable-rotate-180", GIMP_ICON_OBJECT_ROTATE_180,
+ NC_("drawable-action", "Rotate _180°"), NULL,
+ NC_("drawable-action", "Turn drawable upside-down"),
+ GIMP_ROTATE_180, FALSE,
+ GIMP_HELP_LAYER_ROTATE_180 },
+
+ { "drawable-rotate-270", GIMP_ICON_OBJECT_ROTATE_270,
+ NC_("drawable-action", "Rotate 90° counter-clock_wise"), NULL,
+ NC_("drawable-action", "Rotate drawable 90 degrees to the left"),
+ GIMP_ROTATE_270, FALSE,
+ GIMP_HELP_LAYER_ROTATE_270 }
+};
+
+
+void
+drawable_actions_setup (GimpActionGroup *group)
+{
+ gimp_action_group_add_actions (group, "drawable-action",
+ drawable_actions,
+ G_N_ELEMENTS (drawable_actions));
+
+ gimp_action_group_add_toggle_actions (group, "drawable-action",
+ drawable_toggle_actions,
+ G_N_ELEMENTS (drawable_toggle_actions));
+
+ gimp_action_group_add_enum_actions (group, "drawable-action",
+ drawable_flip_actions,
+ G_N_ELEMENTS (drawable_flip_actions),
+ drawable_flip_cmd_callback);
+
+ gimp_action_group_add_enum_actions (group, "drawable-action",
+ drawable_rotate_actions,
+ G_N_ELEMENTS (drawable_rotate_actions),
+ drawable_rotate_cmd_callback);
+
+#define SET_ALWAYS_SHOW_IMAGE(action,show) \
+ gimp_action_group_set_action_always_show_image (group, action, show)
+
+ SET_ALWAYS_SHOW_IMAGE ("drawable-rotate-90", TRUE);
+ SET_ALWAYS_SHOW_IMAGE ("drawable-rotate-180", TRUE);
+ SET_ALWAYS_SHOW_IMAGE ("drawable-rotate-270", TRUE);
+
+#undef SET_ALWAYS_SHOW_IMAGE
+}
+
+void
+drawable_actions_update (GimpActionGroup *group,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpDrawable *drawable = NULL;
+ gboolean is_rgb = FALSE;
+ gboolean visible = FALSE;
+ gboolean linked = FALSE;
+ gboolean locked = FALSE;
+ gboolean can_lock = FALSE;
+ gboolean locked_pos = FALSE;
+ gboolean can_lock_pos = FALSE;
+ gboolean writable = FALSE;
+ gboolean movable = FALSE;
+ gboolean children = FALSE;
+
+ image = action_data_get_image (data);
+
+ if (image)
+ {
+ drawable = gimp_image_get_active_drawable (image);
+
+ if (drawable)
+ {
+ GimpItem *item;
+
+ is_rgb = gimp_drawable_is_rgb (drawable);
+
+ if (GIMP_IS_LAYER_MASK (drawable))
+ item = GIMP_ITEM (gimp_layer_mask_get_layer (GIMP_LAYER_MASK (drawable)));
+ else
+ item = GIMP_ITEM (drawable);
+
+ visible = gimp_item_get_visible (item);
+ linked = gimp_item_get_linked (item);
+ locked = gimp_item_get_lock_content (item);
+ can_lock = gimp_item_can_lock_content (item);
+ writable = ! gimp_item_is_content_locked (item);
+ locked_pos = gimp_item_get_lock_position (item);
+ can_lock_pos = gimp_item_can_lock_position (item);
+ movable = ! gimp_item_is_position_locked (item);
+
+ if (gimp_viewable_get_children (GIMP_VIEWABLE (drawable)))
+ children = TRUE;
+ }
+ }
+
+#define SET_SENSITIVE(action,condition) \
+ gimp_action_group_set_action_sensitive (group, action, (condition) != 0)
+#define SET_ACTIVE(action,condition) \
+ gimp_action_group_set_action_active (group, action, (condition) != 0)
+
+ SET_SENSITIVE ("drawable-equalize", writable && !children);
+ SET_SENSITIVE ("drawable-levels-stretch", writable && !children && is_rgb);
+
+ SET_SENSITIVE ("drawable-visible", drawable);
+ SET_SENSITIVE ("drawable-linked", drawable);
+ SET_SENSITIVE ("drawable-lock-content", can_lock);
+ SET_SENSITIVE ("drawable-lock-position", can_lock_pos);
+
+ SET_ACTIVE ("drawable-visible", visible);
+ SET_ACTIVE ("drawable-linked", linked);
+ SET_ACTIVE ("drawable-lock-content", locked);
+ SET_ACTIVE ("drawable-lock-position", locked_pos);
+
+ SET_SENSITIVE ("drawable-flip-horizontal", writable && movable);
+ SET_SENSITIVE ("drawable-flip-vertical", writable && movable);
+
+ SET_SENSITIVE ("drawable-rotate-90", writable && movable);
+ SET_SENSITIVE ("drawable-rotate-180", writable && movable);
+ SET_SENSITIVE ("drawable-rotate-270", writable && movable);
+
+#undef SET_SENSITIVE
+#undef SET_ACTIVE
+}
diff --git a/app/actions/drawable-actions.h b/app/actions/drawable-actions.h
new file mode 100644
index 0000000..1b6e38c
--- /dev/null
+++ b/app/actions/drawable-actions.h
@@ -0,0 +1,27 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __DRAWABLE_ACTIONS_H__
+#define __DRAWABLE_ACTIONS_H__
+
+
+void drawable_actions_setup (GimpActionGroup *group);
+void drawable_actions_update (GimpActionGroup *group,
+ gpointer data);
+
+
+#endif /* __DRAWABLE_ACTIONS_H__ */
diff --git a/app/actions/drawable-commands.c b/app/actions/drawable-commands.c
new file mode 100644
index 0000000..7ea70e8
--- /dev/null
+++ b/app/actions/drawable-commands.c
@@ -0,0 +1,304 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "actions-types.h"
+
+#include "core/gimp.h"
+#include "core/gimpdrawable-equalize.h"
+#include "core/gimpdrawable-levels.h"
+#include "core/gimpdrawable-operation.h"
+#include "core/gimpimage.h"
+#include "core/gimpimage-undo.h"
+#include "core/gimpitem-linked.h"
+#include "core/gimpitemundo.h"
+#include "core/gimplayermask.h"
+#include "core/gimpprogress.h"
+
+#include "dialogs/dialogs.h"
+
+#include "actions.h"
+#include "drawable-commands.h"
+
+#include "gimp-intl.h"
+
+
+/* public functions */
+
+void
+drawable_equalize_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpDrawable *drawable;
+ return_if_no_drawable (image, drawable, data);
+
+ gimp_drawable_equalize (drawable, TRUE);
+ gimp_image_flush (image);
+}
+
+void
+drawable_levels_stretch_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpDrawable *drawable;
+ GimpDisplay *display;
+ GtkWidget *widget;
+ return_if_no_drawable (image, drawable, data);
+ return_if_no_display (display, data);
+ return_if_no_widget (widget, data);
+
+ if (! gimp_drawable_is_rgb (drawable))
+ {
+ gimp_message_literal (image->gimp,
+ G_OBJECT (widget), GIMP_MESSAGE_WARNING,
+ _("White Balance operates only on RGB color "
+ "layers."));
+ return;
+ }
+
+ gimp_drawable_levels_stretch (drawable, GIMP_PROGRESS (display));
+ gimp_image_flush (image);
+}
+
+void
+drawable_linked_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpDrawable *drawable;
+ gboolean linked;
+ return_if_no_drawable (image, drawable, data);
+
+ linked = g_variant_get_boolean (value);
+
+ if (GIMP_IS_LAYER_MASK (drawable))
+ drawable =
+ GIMP_DRAWABLE (gimp_layer_mask_get_layer (GIMP_LAYER_MASK (drawable)));
+
+ if (linked != gimp_item_get_linked (GIMP_ITEM (drawable)))
+ {
+ GimpUndo *undo;
+ gboolean push_undo = TRUE;
+
+ undo = gimp_image_undo_can_compress (image, GIMP_TYPE_ITEM_UNDO,
+ GIMP_UNDO_ITEM_LINKED);
+
+ if (undo && GIMP_ITEM_UNDO (undo)->item == GIMP_ITEM (drawable))
+ push_undo = FALSE;
+
+ gimp_item_set_linked (GIMP_ITEM (drawable), linked, push_undo);
+ gimp_image_flush (image);
+ }
+}
+
+void
+drawable_visible_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpDrawable *drawable;
+ gboolean visible;
+ return_if_no_drawable (image, drawable, data);
+
+ visible = g_variant_get_boolean (value);
+
+ if (GIMP_IS_LAYER_MASK (drawable))
+ drawable =
+ GIMP_DRAWABLE (gimp_layer_mask_get_layer (GIMP_LAYER_MASK (drawable)));
+
+ if (visible != gimp_item_get_visible (GIMP_ITEM (drawable)))
+ {
+ GimpUndo *undo;
+ gboolean push_undo = TRUE;
+
+ undo = gimp_image_undo_can_compress (image, GIMP_TYPE_ITEM_UNDO,
+ GIMP_UNDO_ITEM_VISIBILITY);
+
+ if (undo && GIMP_ITEM_UNDO (undo)->item == GIMP_ITEM (drawable))
+ push_undo = FALSE;
+
+ gimp_item_set_visible (GIMP_ITEM (drawable), visible, push_undo);
+ gimp_image_flush (image);
+ }
+}
+
+void
+drawable_lock_content_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpDrawable *drawable;
+ gboolean locked;
+ return_if_no_drawable (image, drawable, data);
+
+ locked = g_variant_get_boolean (value);
+
+ if (GIMP_IS_LAYER_MASK (drawable))
+ drawable =
+ GIMP_DRAWABLE (gimp_layer_mask_get_layer (GIMP_LAYER_MASK (drawable)));
+
+ if (locked != gimp_item_get_lock_content (GIMP_ITEM (drawable)))
+ {
+#if 0
+ GimpUndo *undo;
+#endif
+ gboolean push_undo = TRUE;
+
+#if 0
+ undo = gimp_image_undo_can_compress (image, GIMP_TYPE_ITEM_UNDO,
+ GIMP_UNDO_ITEM_VISIBILITY);
+
+ if (undo && GIMP_ITEM_UNDO (undo)->item == GIMP_ITEM (drawable))
+ push_undo = FALSE;
+#endif
+
+ gimp_item_set_lock_content (GIMP_ITEM (drawable), locked, push_undo);
+ gimp_image_flush (image);
+ }
+}
+
+void
+drawable_lock_position_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpDrawable *drawable;
+ gboolean locked;
+ return_if_no_drawable (image, drawable, data);
+
+ locked = g_variant_get_boolean (value);
+
+ if (GIMP_IS_LAYER_MASK (drawable))
+ drawable =
+ GIMP_DRAWABLE (gimp_layer_mask_get_layer (GIMP_LAYER_MASK (drawable)));
+
+ if (locked != gimp_item_get_lock_position (GIMP_ITEM (drawable)))
+ {
+ GimpUndo *undo;
+ gboolean push_undo = TRUE;
+
+ undo = gimp_image_undo_can_compress (image, GIMP_TYPE_ITEM_UNDO,
+ GIMP_UNDO_ITEM_LOCK_POSITION);
+
+ if (undo && GIMP_ITEM_UNDO (undo)->item == GIMP_ITEM (drawable))
+ push_undo = FALSE;
+
+ gimp_item_set_lock_position (GIMP_ITEM (drawable), locked, push_undo);
+ gimp_image_flush (image);
+ }
+}
+
+void
+drawable_flip_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpDrawable *drawable;
+ GimpItem *item;
+ GimpContext *context;
+ gint off_x, off_y;
+ gdouble axis = 0.0;
+ GimpOrientationType orientation;
+ return_if_no_drawable (image, drawable, data);
+ return_if_no_context (context, data);
+
+ orientation = (GimpOrientationType) g_variant_get_int32 (value);
+
+ item = GIMP_ITEM (drawable);
+
+ gimp_item_get_offset (item, &off_x, &off_y);
+
+ switch (orientation)
+ {
+ case GIMP_ORIENTATION_HORIZONTAL:
+ axis = ((gdouble) off_x + (gdouble) gimp_item_get_width (item) / 2.0);
+ break;
+
+ case GIMP_ORIENTATION_VERTICAL:
+ axis = ((gdouble) off_y + (gdouble) gimp_item_get_height (item) / 2.0);
+ break;
+
+ default:
+ break;
+ }
+
+ if (gimp_item_get_linked (item))
+ {
+ gimp_item_linked_flip (item, context, orientation, axis, FALSE);
+ }
+ else
+ {
+ gimp_item_flip (item, context, orientation, axis,
+ gimp_item_get_clip (item, FALSE));
+ }
+
+ gimp_image_flush (image);
+}
+
+void
+drawable_rotate_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpDrawable *drawable;
+ GimpContext *context;
+ GimpItem *item;
+ gint off_x, off_y;
+ gdouble center_x, center_y;
+ GimpRotationType rotation_type;
+ return_if_no_drawable (image, drawable, data);
+ return_if_no_context (context, data);
+
+ rotation_type = (GimpRotationType) g_variant_get_int32 (value);
+
+ item = GIMP_ITEM (drawable);
+
+ gimp_item_get_offset (item, &off_x, &off_y);
+
+ center_x = ((gdouble) off_x + (gdouble) gimp_item_get_width (item) / 2.0);
+ center_y = ((gdouble) off_y + (gdouble) gimp_item_get_height (item) / 2.0);
+
+ if (gimp_item_get_linked (item))
+ {
+ gimp_item_linked_rotate (item, context, rotation_type,
+ center_x, center_y, FALSE);
+ }
+ else
+ {
+ gimp_item_rotate (item, context,
+ rotation_type, center_x, center_y,
+ gimp_item_get_clip (item, FALSE));
+ }
+
+ gimp_image_flush (image);
+}
diff --git a/app/actions/drawable-commands.h b/app/actions/drawable-commands.h
new file mode 100644
index 0000000..1f8ae79
--- /dev/null
+++ b/app/actions/drawable-commands.h
@@ -0,0 +1,50 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __DRAWABLE_COMMANDS_H__
+#define __DRAWABLE_COMMANDS_H__
+
+
+void drawable_equalize_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void drawable_levels_stretch_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+void drawable_linked_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void drawable_visible_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void drawable_lock_content_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void drawable_lock_position_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+void drawable_flip_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void drawable_rotate_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+
+#endif /* __DRAWABLE_COMMANDS_H__ */
diff --git a/app/actions/dynamics-actions.c b/app/actions/dynamics-actions.c
new file mode 100644
index 0000000..ce6b005
--- /dev/null
+++ b/app/actions/dynamics-actions.c
@@ -0,0 +1,137 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "actions-types.h"
+
+#include "core/gimpcontext.h"
+#include "core/gimpdata.h"
+
+#include "widgets/gimpactiongroup.h"
+#include "widgets/gimphelp-ids.h"
+
+#include "actions.h"
+#include "data-commands.h"
+#include "dynamics-actions.h"
+
+#include "gimp-intl.h"
+
+
+static const GimpActionEntry dynamics_actions[] =
+{
+ { "dynamics-popup", GIMP_ICON_DYNAMICS,
+ NC_("dynamics-action", "Paint Dynamics Menu"), NULL, NULL, NULL,
+ GIMP_HELP_DYNAMICS_DIALOG },
+
+ { "dynamics-new", GIMP_ICON_DOCUMENT_NEW,
+ NC_("dynamics-action", "_New Dynamics"), NULL,
+ NC_("dynamics-action", "Create a new dynamics"),
+ data_new_cmd_callback,
+ GIMP_HELP_DYNAMICS_NEW },
+
+ { "dynamics-duplicate", GIMP_ICON_OBJECT_DUPLICATE,
+ NC_("dynamics-action", "D_uplicate Dynamics"), NULL,
+ NC_("dynamics-action", "Duplicate this dynamics"),
+ data_duplicate_cmd_callback,
+ GIMP_HELP_DYNAMICS_DUPLICATE },
+
+ { "dynamics-copy-location", GIMP_ICON_EDIT_COPY,
+ NC_("dynamics-action", "Copy Dynamics _Location"), NULL,
+ NC_("dynamics-action", "Copy dynamics file location to clipboard"),
+ data_copy_location_cmd_callback,
+ GIMP_HELP_DYNAMICS_COPY_LOCATION },
+
+ { "dynamics-show-in-file-manager", GIMP_ICON_FILE_MANAGER,
+ NC_("dynamics-action", "Show in _File Manager"), NULL,
+ NC_("dynamics-action", "Show dynamics file location in the file manager"),
+ data_show_in_file_manager_cmd_callback,
+ GIMP_HELP_DYNAMICS_SHOW_IN_FILE_MANAGER },
+
+ { "dynamics-delete", GIMP_ICON_EDIT_DELETE,
+ NC_("dynamics-action", "_Delete Dynamics"), NULL,
+ NC_("dynamics-action", "Delete this dynamics"),
+ data_delete_cmd_callback,
+ GIMP_HELP_DYNAMICS_DELETE },
+
+ { "dynamics-refresh", GIMP_ICON_VIEW_REFRESH,
+ NC_("dynamics-action", "_Refresh Dynamics"), NULL,
+ NC_("dynamics-action", "Refresh dynamics"),
+ data_refresh_cmd_callback,
+ GIMP_HELP_DYNAMICS_REFRESH }
+};
+
+static const GimpStringActionEntry dynamics_edit_actions[] =
+{
+ { "dynamics-edit", GIMP_ICON_EDIT,
+ NC_("dynamics-action", "_Edit Dynamics..."), NULL,
+ NC_("dynamics-action", "Edit this dynamics"),
+ "gimp-dynamics-editor",
+ GIMP_HELP_DYNAMICS_EDIT }
+};
+
+
+void
+dynamics_actions_setup (GimpActionGroup *group)
+{
+ gimp_action_group_add_actions (group, "dynamics-action",
+ dynamics_actions,
+ G_N_ELEMENTS (dynamics_actions));
+
+ gimp_action_group_add_string_actions (group, "dynamics-action",
+ dynamics_edit_actions,
+ G_N_ELEMENTS (dynamics_edit_actions),
+ data_edit_cmd_callback);
+}
+
+void
+dynamics_actions_update (GimpActionGroup *group,
+ gpointer user_data)
+{
+ GimpContext *context = action_data_get_context (user_data);
+ GimpDynamics *dynamics = NULL;
+ GimpData *data = NULL;
+ GFile *file = NULL;
+
+ if (context)
+ {
+ dynamics = gimp_context_get_dynamics (context);
+
+ if (dynamics)
+ {
+ data = GIMP_DATA (dynamics);
+
+ file = gimp_data_get_file (data);
+ }
+ }
+
+#define SET_SENSITIVE(action,condition) \
+ gimp_action_group_set_action_sensitive (group, action, (condition) != 0)
+
+ SET_SENSITIVE ("dynamics-edit", dynamics);
+ SET_SENSITIVE ("dynamics-duplicate", dynamics && gimp_data_is_duplicatable (data));
+ SET_SENSITIVE ("dynamics-copy-location", file);
+ SET_SENSITIVE ("dynamics-show-in-file-manager", file);
+ SET_SENSITIVE ("dynamics-delete", dynamics && gimp_data_is_deletable (data));
+
+#undef SET_SENSITIVE
+}
diff --git a/app/actions/dynamics-actions.h b/app/actions/dynamics-actions.h
new file mode 100644
index 0000000..515f6b3
--- /dev/null
+++ b/app/actions/dynamics-actions.h
@@ -0,0 +1,27 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __DYNAMICS_ACTIONS_H__
+#define __DYNAMICS_ACTIONS_H__
+
+
+void dynamics_actions_setup (GimpActionGroup *group);
+void dynamics_actions_update (GimpActionGroup *group,
+ gpointer user_data);
+
+
+#endif /* __DYNAMICS_ACTIONS_H__ */
diff --git a/app/actions/dynamics-editor-actions.c b/app/actions/dynamics-editor-actions.c
new file mode 100644
index 0000000..0b38d3c
--- /dev/null
+++ b/app/actions/dynamics-editor-actions.c
@@ -0,0 +1,89 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "actions-types.h"
+
+#include "core/gimp.h"
+#include "core/gimpcontext.h"
+
+#include "widgets/gimpactiongroup.h"
+#include "widgets/gimpdataeditor.h"
+#include "widgets/gimphelp-ids.h"
+
+#include "data-editor-commands.h"
+#include "dynamics-editor-actions.h"
+
+#include "gimp-intl.h"
+
+
+static const GimpActionEntry dynamics_editor_actions[] =
+{
+ { "dynamics-editor-popup", GIMP_ICON_DYNAMICS,
+ NC_("dynamics-editor-action", "Paint Dynamics Editor Menu"), NULL, NULL, NULL,
+ GIMP_HELP_BRUSH_EDITOR_DIALOG }
+};
+
+
+static const GimpToggleActionEntry dynamics_editor_toggle_actions[] =
+{
+ { "dynamics-editor-edit-active", GIMP_ICON_LINKED,
+ NC_("dynamics-editor-action", "Edit Active Dynamics"), NULL, NULL,
+ data_editor_edit_active_cmd_callback,
+ FALSE,
+ GIMP_HELP_BRUSH_EDITOR_EDIT_ACTIVE }
+};
+
+
+void
+dynamics_editor_actions_setup (GimpActionGroup *group)
+{
+ gimp_action_group_add_actions (group, "dynamics-editor-action",
+ dynamics_editor_actions,
+ G_N_ELEMENTS (dynamics_editor_actions));
+
+ gimp_action_group_add_toggle_actions (group, "dynamics-editor-action",
+ dynamics_editor_toggle_actions,
+ G_N_ELEMENTS (dynamics_editor_toggle_actions));
+
+}
+
+void
+dynamics_editor_actions_update (GimpActionGroup *group,
+ gpointer user_data)
+{
+ GimpDataEditor *data_editor = GIMP_DATA_EDITOR (user_data);
+ gboolean edit_active = FALSE;
+
+ edit_active = gimp_data_editor_get_edit_active (data_editor);
+
+#define SET_SENSITIVE(action,condition) \
+ gimp_action_group_set_action_sensitive (group, action, (condition) != 0)
+#define SET_ACTIVE(action,condition) \
+ gimp_action_group_set_action_active (group, action, (condition) != 0)
+
+ SET_ACTIVE ("dynamics-editor-edit-active", edit_active);
+
+#undef SET_SENSITIVE
+#undef SET_ACTIVE
+}
diff --git a/app/actions/dynamics-editor-actions.h b/app/actions/dynamics-editor-actions.h
new file mode 100644
index 0000000..2f79c6d
--- /dev/null
+++ b/app/actions/dynamics-editor-actions.h
@@ -0,0 +1,27 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __DYNAMICS_EDITOR_ACTIONS_H__
+#define __DYNAMICS_EDITOR_ACTIONS_H__
+
+
+void dynamics_editor_actions_setup (GimpActionGroup *group);
+void dynamics_editor_actions_update (GimpActionGroup *group,
+ gpointer data);
+
+
+#endif /* __DYNAMICS_EDITOR_ACTIONS_H__ */
diff --git a/app/actions/edit-actions.c b/app/actions/edit-actions.c
new file mode 100644
index 0000000..caf28b7
--- /dev/null
+++ b/app/actions/edit-actions.c
@@ -0,0 +1,417 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "actions-types.h"
+
+#include "core/gimp.h"
+#include "core/gimpchannel.h"
+#include "core/gimpcontext.h"
+#include "core/gimpimage.h"
+#include "core/gimpimage-undo.h"
+#include "core/gimplayer.h"
+#include "core/gimplist.h"
+#include "core/gimptoolinfo.h"
+#include "core/gimpundostack.h"
+
+#include "widgets/gimpaction.h"
+#include "widgets/gimpactiongroup.h"
+#include "widgets/gimphelp-ids.h"
+
+#include "tools/tool_manager.h"
+
+#include "actions.h"
+#include "edit-actions.h"
+#include "edit-commands.h"
+
+#include "gimp-intl.h"
+
+
+/* local function prototypes */
+
+static void edit_actions_foreground_changed (GimpContext *context,
+ const GimpRGB *color,
+ GimpActionGroup *group);
+static void edit_actions_background_changed (GimpContext *context,
+ const GimpRGB *color,
+ GimpActionGroup *group);
+static void edit_actions_pattern_changed (GimpContext *context,
+ GimpPattern *pattern,
+ GimpActionGroup *group);
+
+
+static const GimpActionEntry edit_actions[] =
+{
+ { "edit-menu", NULL, NC_("edit-action", "_Edit") },
+ { "edit-paste-as-menu", NULL, NC_("edit-action", "Paste _as") },
+ { "edit-buffer-menu", NULL, NC_("edit-action", "_Buffer") },
+
+ { "undo-popup",
+ "edit-undo", NC_("edit-action", "Undo History Menu"), NULL, NULL, NULL,
+ GIMP_HELP_UNDO_DIALOG },
+
+ { "edit-undo", GIMP_ICON_EDIT_UNDO,
+ NC_("edit-action", "_Undo"), "<primary>Z",
+ NC_("edit-action", "Undo the last operation"),
+ edit_undo_cmd_callback,
+ GIMP_HELP_EDIT_UNDO },
+
+ { "edit-redo", GIMP_ICON_EDIT_REDO,
+ NC_("edit-action", "_Redo"), "<primary>Y",
+ NC_("edit-action", "Redo the last operation that was undone"),
+ edit_redo_cmd_callback,
+ GIMP_HELP_EDIT_REDO },
+
+ { "edit-strong-undo", GIMP_ICON_EDIT_UNDO,
+ NC_("edit-action", "Strong Undo"), "<primary><shift>Z",
+ NC_("edit-action", "Undo the last operation, skipping visibility changes"),
+ edit_strong_undo_cmd_callback,
+ GIMP_HELP_EDIT_STRONG_UNDO },
+
+ { "edit-strong-redo", GIMP_ICON_EDIT_REDO,
+ NC_("edit-action", "Strong Redo"), "<primary><shift>Y",
+ NC_("edit-action",
+ "Redo the last operation that was undone, skipping visibility changes"),
+ edit_strong_redo_cmd_callback,
+ GIMP_HELP_EDIT_STRONG_REDO },
+
+ { "edit-undo-clear", GIMP_ICON_SHRED,
+ NC_("edit-action", "_Clear Undo History"), NULL,
+ NC_("edit-action", "Remove all operations from the undo history"),
+ edit_undo_clear_cmd_callback,
+ GIMP_HELP_EDIT_UNDO_CLEAR },
+
+ { "edit-cut", GIMP_ICON_EDIT_CUT,
+ NC_("edit-action", "Cu_t"), "<primary>X",
+ NC_("edit-action", "Move the selected pixels to the clipboard"),
+ edit_cut_cmd_callback,
+ GIMP_HELP_EDIT_CUT },
+
+ { "edit-copy", GIMP_ICON_EDIT_COPY,
+ NC_("edit-action", "_Copy"), "<primary>C",
+ NC_("edit-action", "Copy the selected pixels to the clipboard"),
+ edit_copy_cmd_callback,
+ GIMP_HELP_EDIT_COPY },
+
+ { "edit-copy-visible", NULL, /* GIMP_ICON_COPY_VISIBLE, */
+ NC_("edit-action", "Copy _Visible"), "<primary><shift>C",
+ NC_("edit-action", "Copy what is visible in the selected region"),
+ edit_copy_visible_cmd_callback,
+ GIMP_HELP_EDIT_COPY_VISIBLE },
+
+ { "edit-paste-as-new-image", GIMP_ICON_EDIT_PASTE_AS_NEW,
+ NC_("edit-action", "From _Clipboard"), "<primary><shift>V",
+ NC_("edit-action", "Create a new image from the content of the clipboard"),
+ edit_paste_as_new_image_cmd_callback,
+ GIMP_HELP_EDIT_PASTE_AS_NEW_IMAGE },
+
+ { "edit-paste-as-new-image-short", GIMP_ICON_EDIT_PASTE_AS_NEW,
+ NC_("edit-action", "_New Image"), NULL,
+ NC_("edit-action", "Create a new image from the content of the clipboard"),
+ edit_paste_as_new_image_cmd_callback,
+ GIMP_HELP_EDIT_PASTE_AS_NEW_IMAGE },
+
+ { "edit-named-cut", GIMP_ICON_EDIT_CUT,
+ NC_("edit-action", "Cu_t Named..."), NULL,
+ NC_("edit-action", "Move the selected pixels to a named buffer"),
+ edit_named_cut_cmd_callback,
+ GIMP_HELP_BUFFER_CUT },
+
+ { "edit-named-copy", GIMP_ICON_EDIT_COPY,
+ NC_("edit-action", "_Copy Named..."), NULL,
+ NC_("edit-action", "Copy the selected pixels to a named buffer"),
+ edit_named_copy_cmd_callback,
+ GIMP_HELP_BUFFER_COPY },
+
+ { "edit-named-copy-visible", NULL, /* GIMP_ICON_COPY_VISIBLE, */
+ NC_("edit-action", "Copy _Visible Named..."), "",
+ NC_("edit-action",
+ "Copy what is visible in the selected region to a named buffer"),
+ edit_named_copy_visible_cmd_callback,
+ GIMP_HELP_BUFFER_COPY },
+
+ { "edit-named-paste", GIMP_ICON_EDIT_PASTE,
+ NC_("edit-action", "_Paste Named..."), NULL,
+ NC_("edit-action", "Paste the content of a named buffer"),
+ edit_named_paste_cmd_callback,
+ GIMP_HELP_BUFFER_PASTE },
+
+ { "edit-clear", GIMP_ICON_EDIT_CLEAR,
+ NC_("edit-action", "Cl_ear"), "Delete",
+ NC_("edit-action", "Clear the selected pixels"),
+ edit_clear_cmd_callback,
+ GIMP_HELP_EDIT_CLEAR }
+};
+
+static const GimpEnumActionEntry edit_paste_actions[] =
+{
+ { "edit-paste", GIMP_ICON_EDIT_PASTE,
+ NC_("edit-action", "_Paste"), "<primary>V",
+ NC_("edit-action", "Paste the content of the clipboard"),
+ GIMP_PASTE_TYPE_FLOATING, FALSE,
+ GIMP_HELP_EDIT_PASTE },
+
+ { "edit-paste-in-place", GIMP_ICON_EDIT_PASTE,
+ NC_("edit-action", "Paste In P_lace"), "<primary><alt>V",
+ NC_("edit-action",
+ "Paste the content of the clipboard at its original position"),
+ GIMP_PASTE_TYPE_FLOATING_IN_PLACE, FALSE,
+ GIMP_HELP_EDIT_PASTE_IN_PLACE },
+
+ { "edit-paste-into", GIMP_ICON_EDIT_PASTE_INTO,
+ NC_("edit-action", "Paste _Into Selection"), NULL,
+ NC_("edit-action",
+ "Paste the content of the clipboard into the current selection"),
+ GIMP_PASTE_TYPE_FLOATING_INTO, FALSE,
+ GIMP_HELP_EDIT_PASTE_INTO },
+
+ { "edit-paste-into-in-place", GIMP_ICON_EDIT_PASTE_INTO,
+ NC_("edit-action", "Paste Int_o Selection In Place"), NULL,
+ NC_("edit-action",
+ "Paste the content of the clipboard into the current selection "
+ "at its original position"),
+ GIMP_PASTE_TYPE_FLOATING_INTO_IN_PLACE, FALSE,
+ GIMP_HELP_EDIT_PASTE_INTO_IN_PLACE },
+
+ { "edit-paste-as-new-layer", GIMP_ICON_EDIT_PASTE_AS_NEW,
+ NC_("edit-action", "New _Layer"), NULL,
+ NC_("edit-action", "Create a new layer from the content of the clipboard"),
+ GIMP_PASTE_TYPE_NEW_LAYER, FALSE,
+ GIMP_HELP_EDIT_PASTE_AS_NEW_LAYER },
+
+ { "edit-paste-as-new-layer-in-place", GIMP_ICON_EDIT_PASTE_AS_NEW,
+ NC_("edit-action", "New Layer In _Place"), NULL,
+ NC_("edit-action",
+ "Create a new layer from the content of the clipboard "
+ "and place it at its original position"),
+ GIMP_PASTE_TYPE_NEW_LAYER_IN_PLACE, FALSE,
+ GIMP_HELP_EDIT_PASTE_AS_NEW_LAYER_IN_PLACE }
+};
+
+static const GimpEnumActionEntry edit_fill_actions[] =
+{
+ { "edit-fill-fg", GIMP_ICON_TOOL_BUCKET_FILL,
+ NC_("edit-action", "Fill with _FG Color"), "<primary>comma",
+ NC_("edit-action", "Fill the selection using the foreground color"),
+ GIMP_FILL_FOREGROUND, FALSE,
+ GIMP_HELP_EDIT_FILL_FG },
+
+ { "edit-fill-bg", GIMP_ICON_TOOL_BUCKET_FILL,
+ NC_("edit-action", "Fill with B_G Color"), "<primary>period",
+ NC_("edit-action", "Fill the selection using the background color"),
+ GIMP_FILL_BACKGROUND, FALSE,
+ GIMP_HELP_EDIT_FILL_BG },
+
+ { "edit-fill-pattern", GIMP_ICON_PATTERN,
+ NC_("edit-action", "Fill _with Pattern"), "<primary>semicolon",
+ NC_("edit-action", "Fill the selection using the active pattern"),
+ GIMP_FILL_PATTERN, FALSE,
+ GIMP_HELP_EDIT_FILL_PATTERN }
+};
+
+
+void
+edit_actions_setup (GimpActionGroup *group)
+{
+ GimpContext *context = gimp_get_user_context (group->gimp);
+ GimpRGB color;
+ GimpPattern *pattern;
+ GimpAction *action;
+
+ gimp_action_group_add_actions (group, "edit-action",
+ edit_actions,
+ G_N_ELEMENTS (edit_actions));
+
+ gimp_action_group_add_enum_actions (group, "edit-action",
+ edit_paste_actions,
+ G_N_ELEMENTS (edit_paste_actions),
+ edit_paste_cmd_callback);
+
+ gimp_action_group_add_enum_actions (group, "edit-action",
+ edit_fill_actions,
+ G_N_ELEMENTS (edit_fill_actions),
+ edit_fill_cmd_callback);
+
+ action = gimp_action_group_get_action (group,
+ "edit-paste-as-new-image-short");
+ gimp_action_set_accel_path (action,
+ "<Actions>/edit/edit-paste-as-new-image");
+
+ gimp_action_group_set_action_context (group, "edit-fill-fg", context);
+ gimp_action_group_set_action_context (group, "edit-fill-bg", context);
+ gimp_action_group_set_action_context (group, "edit-fill-pattern", context);
+
+ g_signal_connect_object (context, "foreground-changed",
+ G_CALLBACK (edit_actions_foreground_changed),
+ group, 0);
+ g_signal_connect_object (context, "background-changed",
+ G_CALLBACK (edit_actions_background_changed),
+ group, 0);
+ g_signal_connect_object (context, "pattern-changed",
+ G_CALLBACK (edit_actions_pattern_changed),
+ group, 0);
+
+ gimp_context_get_foreground (context, &color);
+ edit_actions_foreground_changed (context, &color, group);
+
+ gimp_context_get_background (context, &color);
+ edit_actions_background_changed (context, &color, group);
+
+ pattern = gimp_context_get_pattern (context);
+ edit_actions_pattern_changed (context, pattern, group);
+
+#define SET_ALWAYS_SHOW_IMAGE(action,show) \
+ gimp_action_group_set_action_always_show_image (group, action, show)
+
+ SET_ALWAYS_SHOW_IMAGE ("edit-fill-fg", TRUE);
+ SET_ALWAYS_SHOW_IMAGE ("edit-fill-bg", TRUE);
+ SET_ALWAYS_SHOW_IMAGE ("edit-fill-pattern", TRUE);
+
+#undef SET_ALWAYS_SHOW_IMAGE
+}
+
+void
+edit_actions_update (GimpActionGroup *group,
+ gpointer data)
+{
+ GimpImage *image = action_data_get_image (data);
+ GimpDisplay *display = action_data_get_display (data);
+ GimpDrawable *drawable = NULL;
+ gchar *undo_name = NULL;
+ gchar *redo_name = NULL;
+ gboolean writable = FALSE;
+ gboolean children = FALSE;
+ gboolean undo_enabled = FALSE;
+
+ if (image)
+ {
+ drawable = gimp_image_get_active_drawable (image);
+
+ if (drawable)
+ {
+ writable = ! gimp_item_is_content_locked (GIMP_ITEM (drawable));
+
+ if (gimp_viewable_get_children (GIMP_VIEWABLE (drawable)))
+ children = TRUE;
+ }
+
+ undo_enabled = gimp_image_undo_is_enabled (image);
+
+ if (undo_enabled)
+ {
+ GimpUndoStack *undo_stack = gimp_image_get_undo_stack (image);
+ GimpUndoStack *redo_stack = gimp_image_get_redo_stack (image);
+ GimpUndo *undo = gimp_undo_stack_peek (undo_stack);
+ GimpUndo *redo = gimp_undo_stack_peek (redo_stack);
+ const gchar *tool_undo = NULL;
+ const gchar *tool_redo = NULL;
+
+ if (display)
+ {
+ tool_undo = tool_manager_can_undo_active (image->gimp, display);
+ tool_redo = tool_manager_can_redo_active (image->gimp, display);
+ }
+
+ if (tool_undo)
+ undo_name = g_strdup_printf (_("_Undo %s"), tool_undo);
+ else if (undo)
+ undo_name = g_strdup_printf (_("_Undo %s"),
+ gimp_object_get_name (undo));
+
+ if (tool_redo)
+ redo_name = g_strdup_printf (_("_Redo %s"), tool_redo);
+ else if (redo)
+ redo_name = g_strdup_printf (_("_Redo %s"),
+ gimp_object_get_name (redo));
+ }
+ }
+
+
+#define SET_LABEL(action,label) \
+ gimp_action_group_set_action_label (group, action, (label))
+#define SET_SENSITIVE(action,condition) \
+ gimp_action_group_set_action_sensitive (group, action, (condition) != 0)
+
+ SET_LABEL ("edit-undo", undo_name ? undo_name : _("_Undo"));
+ SET_LABEL ("edit-redo", redo_name ? redo_name : _("_Redo"));
+
+ SET_SENSITIVE ("edit-undo", undo_enabled && undo_name);
+ SET_SENSITIVE ("edit-redo", undo_enabled && redo_name);
+ SET_SENSITIVE ("edit-strong-undo", undo_enabled && undo_name);
+ SET_SENSITIVE ("edit-strong-redo", undo_enabled && redo_name);
+ SET_SENSITIVE ("edit-undo-clear", undo_enabled && (undo_name || redo_name));
+
+ g_free (undo_name);
+ g_free (redo_name);
+
+ SET_SENSITIVE ("edit-cut", writable && !children);
+ SET_SENSITIVE ("edit-copy", drawable);
+ SET_SENSITIVE ("edit-copy-visible", image);
+ /* "edit-paste" is always active */
+ SET_SENSITIVE ("edit-paste-in-place", image);
+ SET_SENSITIVE ("edit-paste-into", image);
+ SET_SENSITIVE ("edit-paste-into-in-place", image);
+ SET_SENSITIVE ("edit-paste-as-new-layer", image);
+ SET_SENSITIVE ("edit-paste-as-new-layer-in-place", image);
+
+ SET_SENSITIVE ("edit-named-cut", writable && !children);
+ SET_SENSITIVE ("edit-named-copy", drawable);
+ SET_SENSITIVE ("edit-named-copy-visible", drawable);
+ /* "edit-named-paste" is always active */
+
+ SET_SENSITIVE ("edit-clear", writable && !children);
+ SET_SENSITIVE ("edit-fill-fg", writable && !children);
+ SET_SENSITIVE ("edit-fill-bg", writable && !children);
+ SET_SENSITIVE ("edit-fill-pattern", writable && !children);
+
+#undef SET_LABEL
+#undef SET_SENSITIVE
+}
+
+
+/* private functions */
+
+static void
+edit_actions_foreground_changed (GimpContext *context,
+ const GimpRGB *color,
+ GimpActionGroup *group)
+{
+ gimp_action_group_set_action_color (group, "edit-fill-fg", color, FALSE);
+}
+
+static void
+edit_actions_background_changed (GimpContext *context,
+ const GimpRGB *color,
+ GimpActionGroup *group)
+{
+ gimp_action_group_set_action_color (group, "edit-fill-bg", color, FALSE);
+}
+
+static void
+edit_actions_pattern_changed (GimpContext *context,
+ GimpPattern *pattern,
+ GimpActionGroup *group)
+{
+ gimp_action_group_set_action_viewable (group, "edit-fill-pattern",
+ GIMP_VIEWABLE (pattern));
+}
diff --git a/app/actions/edit-actions.h b/app/actions/edit-actions.h
new file mode 100644
index 0000000..89978b3
--- /dev/null
+++ b/app/actions/edit-actions.h
@@ -0,0 +1,27 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __EDIT_ACTIONS_H__
+#define __EDIT_ACTIONS_H__
+
+
+void edit_actions_setup (GimpActionGroup *group);
+void edit_actions_update (GimpActionGroup *group,
+ gpointer data);
+
+
+#endif /* __EDIT_ACTIONS_H__ */
diff --git a/app/actions/edit-commands.c b/app/actions/edit-commands.c
new file mode 100644
index 0000000..6042f86
--- /dev/null
+++ b/app/actions/edit-commands.c
@@ -0,0 +1,721 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <string.h>
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpbase/gimpbase.h"
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "actions-types.h"
+
+#include "core/gimp.h"
+#include "core/gimp-edit.h"
+#include "core/gimpbuffer.h"
+#include "core/gimpcontainer.h"
+#include "core/gimpdrawable.h"
+#include "core/gimpdrawable-edit.h"
+#include "core/gimpfilloptions.h"
+#include "core/gimplayer.h"
+#include "core/gimplayer-new.h"
+#include "core/gimpimage.h"
+#include "core/gimpimage-undo.h"
+
+#include "vectors/gimpvectors-import.h"
+
+#include "widgets/gimpclipboard.h"
+#include "widgets/gimphelp-ids.h"
+#include "widgets/gimpdialogfactory.h"
+#include "widgets/gimpmessagebox.h"
+#include "widgets/gimpmessagedialog.h"
+#include "widgets/gimpwidgets-utils.h"
+#include "widgets/gimpwindowstrategy.h"
+
+#include "display/gimpdisplay.h"
+#include "display/gimpdisplayshell.h"
+#include "display/gimpdisplayshell-transform.h"
+
+#include "tools/gimptools-utils.h"
+#include "tools/tool_manager.h"
+
+#include "actions.h"
+#include "edit-commands.h"
+
+#include "gimp-intl.h"
+
+
+/* local function prototypes */
+
+static gboolean check_drawable_alpha (GimpDrawable *drawable,
+ gpointer data);
+static void edit_paste (GimpDisplay *display,
+ GimpPasteType paste_type,
+ gboolean try_svg);
+static void cut_named_buffer_callback (GtkWidget *widget,
+ const gchar *name,
+ gpointer data);
+static void copy_named_buffer_callback (GtkWidget *widget,
+ const gchar *name,
+ gpointer data);
+static void copy_named_visible_buffer_callback (GtkWidget *widget,
+ const gchar *name,
+ gpointer data);
+
+
+/* public functions */
+
+void
+edit_undo_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpDisplay *display;
+ return_if_no_image (image, data);
+ return_if_no_display (display, data);
+
+ if (tool_manager_undo_active (image->gimp, display) ||
+ gimp_image_undo (image))
+ {
+ gimp_image_flush (image);
+ }
+}
+
+void
+edit_redo_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpDisplay *display;
+ return_if_no_image (image, data);
+ return_if_no_display (display, data);
+
+ if (tool_manager_redo_active (image->gimp, display) ||
+ gimp_image_redo (image))
+ {
+ gimp_image_flush (image);
+ }
+}
+
+void
+edit_strong_undo_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ return_if_no_image (image, data);
+
+ if (gimp_image_strong_undo (image))
+ gimp_image_flush (image);
+}
+
+void
+edit_strong_redo_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ return_if_no_image (image, data);
+
+ if (gimp_image_strong_redo (image))
+ gimp_image_flush (image);
+}
+
+void
+edit_undo_clear_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpUndoStack *undo_stack;
+ GimpUndoStack *redo_stack;
+ GtkWidget *widget;
+ GtkWidget *dialog;
+ gchar *size;
+ gint64 memsize;
+ gint64 guisize;
+ return_if_no_image (image, data);
+ return_if_no_widget (widget, data);
+
+ dialog = gimp_message_dialog_new (_("Clear Undo History"),
+ GIMP_ICON_DIALOG_WARNING,
+ widget,
+ GTK_DIALOG_MODAL |
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ gimp_standard_help_func,
+ GIMP_HELP_EDIT_UNDO_CLEAR,
+
+ _("_Cancel"), GTK_RESPONSE_CANCEL,
+ _("Cl_ear"), GTK_RESPONSE_OK,
+
+ NULL);
+
+ gtk_dialog_set_alternative_button_order (GTK_DIALOG (dialog),
+ GTK_RESPONSE_OK,
+ GTK_RESPONSE_CANCEL,
+ -1);
+
+ g_signal_connect_object (gtk_widget_get_toplevel (widget), "unmap",
+ G_CALLBACK (gtk_widget_destroy),
+ dialog, G_CONNECT_SWAPPED);
+
+ g_signal_connect_object (image, "disconnect",
+ G_CALLBACK (gtk_widget_destroy),
+ dialog, G_CONNECT_SWAPPED);
+
+ gimp_message_box_set_primary_text (GIMP_MESSAGE_DIALOG (dialog)->box,
+ _("Really clear image's undo history?"));
+
+ undo_stack = gimp_image_get_undo_stack (image);
+ redo_stack = gimp_image_get_redo_stack (image);
+
+ memsize = gimp_object_get_memsize (GIMP_OBJECT (undo_stack), &guisize);
+ memsize += guisize;
+ memsize += gimp_object_get_memsize (GIMP_OBJECT (redo_stack), &guisize);
+ memsize += guisize;
+
+ size = g_format_size (memsize);
+
+ gimp_message_box_set_text (GIMP_MESSAGE_DIALOG (dialog)->box,
+ _("Clearing the undo history of this "
+ "image will gain %s of memory."), size);
+ g_free (size);
+
+ if (gimp_dialog_run (GIMP_DIALOG (dialog)) == GTK_RESPONSE_OK)
+ {
+ gimp_image_undo_disable (image);
+ gimp_image_undo_enable (image);
+ gimp_image_flush (image);
+ }
+
+ gtk_widget_destroy (dialog);
+}
+
+void
+edit_cut_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpDrawable *drawable;
+ GimpObject *cut;
+ GError *error = NULL;
+ return_if_no_drawable (image, drawable, data);
+
+ if (! check_drawable_alpha (drawable, data))
+ return;
+
+ cut = gimp_edit_cut (image, drawable, action_data_get_context (data),
+ &error);
+
+ if (cut)
+ {
+ GimpDisplay *display = action_data_get_display (data);
+
+ if (display)
+ gimp_message_literal (image->gimp,
+ G_OBJECT (display), GIMP_MESSAGE_INFO,
+ GIMP_IS_IMAGE (cut) ?
+ _("Cut layer to the clipboard.") :
+ _("Cut pixels to the clipboard."));
+
+ gimp_image_flush (image);
+ }
+ else
+ {
+ gimp_message_literal (image->gimp,
+ G_OBJECT (action_data_get_display (data)),
+ GIMP_MESSAGE_WARNING,
+ error->message);
+ g_clear_error (&error);
+ }
+}
+
+void
+edit_copy_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpDrawable *drawable;
+ GimpObject *copy;
+ GError *error = NULL;
+ return_if_no_drawable (image, drawable, data);
+
+ copy = gimp_edit_copy (image, drawable, action_data_get_context (data),
+ &error);
+
+ if (copy)
+ {
+ GimpDisplay *display = action_data_get_display (data);
+
+ if (display)
+ gimp_message_literal (image->gimp,
+ G_OBJECT (display), GIMP_MESSAGE_INFO,
+ GIMP_IS_IMAGE (copy) ?
+ _("Copied layer to the clipboard.") :
+ _("Copied pixels to the clipboard."));
+
+ gimp_image_flush (image);
+ }
+ else
+ {
+ gimp_message_literal (image->gimp,
+ G_OBJECT (action_data_get_display (data)),
+ GIMP_MESSAGE_WARNING,
+ error->message);
+ g_clear_error (&error);
+ }
+}
+
+void
+edit_copy_visible_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GError *error = NULL;
+ return_if_no_image (image, data);
+
+ if (gimp_edit_copy_visible (image, action_data_get_context (data), &error))
+ {
+ GimpDisplay *display = action_data_get_display (data);
+
+ if (display)
+ gimp_message_literal (image->gimp,
+ G_OBJECT (display), GIMP_MESSAGE_INFO,
+ _("Copied pixels to the clipboard."));
+
+ gimp_image_flush (image);
+ }
+ else
+ {
+ gimp_message_literal (image->gimp,
+ G_OBJECT (action_data_get_display (data)),
+ GIMP_MESSAGE_WARNING,
+ error->message);
+ g_clear_error (&error);
+ }
+}
+
+void
+edit_paste_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpDisplay *display = action_data_get_display (data);
+ GimpPasteType paste_type = (GimpPasteType) g_variant_get_int32 (value);
+
+ if (paste_type == GIMP_PASTE_TYPE_FLOATING)
+ {
+ if (! display || ! gimp_display_get_image (display))
+ {
+ edit_paste_as_new_image_cmd_callback (action, value, data);
+ return;
+ }
+ }
+
+ if (! display)
+ return;
+
+ switch (paste_type)
+ {
+ case GIMP_PASTE_TYPE_FLOATING:
+ case GIMP_PASTE_TYPE_FLOATING_IN_PLACE:
+ case GIMP_PASTE_TYPE_FLOATING_INTO:
+ case GIMP_PASTE_TYPE_FLOATING_INTO_IN_PLACE:
+ edit_paste (display, paste_type, TRUE);
+ break;
+
+ case GIMP_PASTE_TYPE_NEW_LAYER:
+ case GIMP_PASTE_TYPE_NEW_LAYER_IN_PLACE:
+ edit_paste (display, paste_type, FALSE);
+ break;
+ }
+}
+
+void
+edit_paste_as_new_image_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ Gimp *gimp;
+ GtkWidget *widget;
+ GimpObject *paste;
+ GimpImage *image = NULL;
+ return_if_no_gimp (gimp, data);
+ return_if_no_widget (widget, data);
+
+ paste = gimp_clipboard_get_object (gimp);
+
+ if (paste)
+ {
+ image = gimp_edit_paste_as_new_image (gimp, paste);
+ g_object_unref (paste);
+ }
+
+ if (image)
+ {
+ gimp_create_display (gimp, image, GIMP_UNIT_PIXEL, 1.0,
+ G_OBJECT (gtk_widget_get_screen (widget)),
+ gimp_widget_get_monitor (widget));
+ g_object_unref (image);
+ }
+ else
+ {
+ gimp_message_literal (gimp, NULL, GIMP_MESSAGE_WARNING,
+ _("There is no image data in the clipboard "
+ "to paste."));
+ }
+}
+
+void
+edit_named_cut_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GtkWidget *widget;
+ GtkWidget *dialog;
+ return_if_no_image (image, data);
+ return_if_no_widget (widget, data);
+
+ dialog = gimp_query_string_box (_("Cut Named"), widget,
+ gimp_standard_help_func,
+ GIMP_HELP_BUFFER_CUT,
+ _("Enter a name for this buffer"),
+ NULL,
+ G_OBJECT (image), "disconnect",
+ cut_named_buffer_callback, image);
+ gtk_widget_show (dialog);
+}
+
+void
+edit_named_copy_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GtkWidget *widget;
+ GtkWidget *dialog;
+ return_if_no_image (image, data);
+ return_if_no_widget (widget, data);
+
+ dialog = gimp_query_string_box (_("Copy Named"), widget,
+ gimp_standard_help_func,
+ GIMP_HELP_BUFFER_COPY,
+ _("Enter a name for this buffer"),
+ NULL,
+ G_OBJECT (image), "disconnect",
+ copy_named_buffer_callback, image);
+ gtk_widget_show (dialog);
+}
+
+void
+edit_named_copy_visible_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GtkWidget *widget;
+ GtkWidget *dialog;
+ return_if_no_image (image, data);
+ return_if_no_widget (widget, data);
+
+ dialog = gimp_query_string_box (_("Copy Visible Named"), widget,
+ gimp_standard_help_func,
+ GIMP_HELP_BUFFER_COPY,
+ _("Enter a name for this buffer"),
+ NULL,
+ G_OBJECT (image), "disconnect",
+ copy_named_visible_buffer_callback, image);
+ gtk_widget_show (dialog);
+}
+
+void
+edit_named_paste_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ Gimp *gimp;
+ GtkWidget *widget;
+ return_if_no_gimp (gimp, data);
+ return_if_no_widget (widget, data);
+
+ gimp_window_strategy_show_dockable_dialog (GIMP_WINDOW_STRATEGY (gimp_get_window_strategy (gimp)),
+ gimp,
+ gimp_dialog_factory_get_singleton (),
+ gtk_widget_get_screen (widget),
+ gimp_widget_get_monitor (widget),
+ "gimp-buffer-list|gimp-buffer-grid");
+}
+
+void
+edit_clear_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpDrawable *drawable;
+ return_if_no_drawable (image, drawable, data);
+
+ if (! check_drawable_alpha (drawable, data))
+ return;
+
+ gimp_drawable_edit_clear (drawable, action_data_get_context (data));
+ gimp_image_flush (image);
+}
+
+void
+edit_fill_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpDrawable *drawable;
+ GimpFillType fill_type;
+ GimpFillOptions *options;
+ GError *error = NULL;
+ return_if_no_drawable (image, drawable, data);
+
+ fill_type = (GimpFillType) g_variant_get_int32 (value);
+
+ options = gimp_fill_options_new (action_data_get_gimp (data), NULL, FALSE);
+
+ if (gimp_fill_options_set_by_fill_type (options,
+ action_data_get_context (data),
+ fill_type, &error))
+ {
+ gimp_drawable_edit_fill (drawable, options, NULL);
+ gimp_image_flush (image);
+ }
+ else
+ {
+ gimp_message_literal (image->gimp, NULL, GIMP_MESSAGE_WARNING,
+ error->message);
+ g_clear_error (&error);
+ }
+
+ g_object_unref (options);
+}
+
+
+/* private functions */
+
+static gboolean
+check_drawable_alpha (GimpDrawable *drawable,
+ gpointer data)
+{
+ if (gimp_drawable_has_alpha (drawable) &&
+ GIMP_IS_LAYER (drawable) &&
+ gimp_layer_get_lock_alpha (GIMP_LAYER (drawable)))
+ {
+ Gimp *gimp = action_data_get_gimp (data);
+ GimpDisplay *display = action_data_get_display (data);
+
+ if (gimp && display)
+ {
+ gimp_message_literal (
+ gimp, G_OBJECT (display), GIMP_MESSAGE_WARNING,
+ _("The active layer's alpha channel is locked."));
+
+ gimp_tools_blink_lock_box (gimp, GIMP_ITEM (drawable));
+ }
+
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static void
+edit_paste (GimpDisplay *display,
+ GimpPasteType paste_type,
+ gboolean try_svg)
+{
+ GimpImage *image = gimp_display_get_image (display);
+ GimpObject *paste;
+
+ if (try_svg)
+ {
+ gchar *svg;
+ gsize svg_size;
+
+ svg = gimp_clipboard_get_svg (display->gimp, &svg_size);
+
+ if (svg)
+ {
+ if (gimp_vectors_import_buffer (image, svg, svg_size,
+ TRUE, FALSE,
+ GIMP_IMAGE_ACTIVE_PARENT, -1,
+ NULL, NULL))
+ {
+ gimp_image_flush (image);
+ }
+
+ g_free (svg);
+
+ return;
+ }
+ }
+
+ paste = gimp_clipboard_get_object (display->gimp);
+
+ if (paste)
+ {
+ GimpDisplayShell *shell = gimp_display_get_shell (display);
+ GimpDrawable *drawable = gimp_image_get_active_drawable (image);
+ gint x, y;
+ gint width, height;
+
+ if (drawable &&
+ paste_type != GIMP_PASTE_TYPE_NEW_LAYER &&
+ paste_type != GIMP_PASTE_TYPE_NEW_LAYER_IN_PLACE)
+ {
+ if (gimp_viewable_get_children (GIMP_VIEWABLE (drawable)))
+ {
+ gimp_message_literal (display->gimp, G_OBJECT (display),
+ GIMP_MESSAGE_INFO,
+ _("Pasted as new layer because the "
+ "target is a layer group."));
+ }
+ else if (gimp_item_is_content_locked (GIMP_ITEM (drawable)))
+ {
+ gimp_message_literal (display->gimp, G_OBJECT (display),
+ GIMP_MESSAGE_INFO,
+ _("Pasted as new layer because the "
+ "target's pixels are locked."));
+ }
+
+ /* the actual paste-type conversion happens in gimp_edit_paste() */
+ }
+
+ gimp_display_shell_untransform_viewport (
+ shell,
+ ! gimp_display_shell_get_infinite_canvas (shell),
+ &x, &y, &width, &height);
+
+ if (gimp_edit_paste (image, drawable, paste,
+ paste_type, x, y, width, height))
+ {
+ gimp_image_flush (image);
+ }
+
+ g_object_unref (paste);
+ }
+ else
+ {
+ gimp_message_literal (display->gimp, G_OBJECT (display),
+ GIMP_MESSAGE_WARNING,
+ _("There is no image data in the clipboard "
+ "to paste."));
+ }
+}
+
+static void
+cut_named_buffer_callback (GtkWidget *widget,
+ const gchar *name,
+ gpointer data)
+{
+ GimpImage *image = GIMP_IMAGE (data);
+ GimpDrawable *drawable = gimp_image_get_active_drawable (image);
+ GError *error = NULL;
+
+ if (! drawable)
+ {
+ gimp_message_literal (image->gimp, NULL, GIMP_MESSAGE_WARNING,
+ _("There is no active layer or channel to cut from."));
+ return;
+ }
+
+ if (! (name && strlen (name)))
+ name = _("(Unnamed Buffer)");
+
+ if (gimp_edit_named_cut (image, name, drawable,
+ gimp_get_user_context (image->gimp), &error))
+ {
+ gimp_image_flush (image);
+ }
+ else
+ {
+ gimp_message_literal (image->gimp, NULL, GIMP_MESSAGE_WARNING,
+ error->message);
+ g_clear_error (&error);
+ }
+}
+
+static void
+copy_named_buffer_callback (GtkWidget *widget,
+ const gchar *name,
+ gpointer data)
+{
+ GimpImage *image = GIMP_IMAGE (data);
+ GimpDrawable *drawable = gimp_image_get_active_drawable (image);
+ GError *error = NULL;
+
+ if (! drawable)
+ {
+ gimp_message_literal (image->gimp, NULL, GIMP_MESSAGE_WARNING,
+ _("There is no active layer or channel to copy from."));
+ return;
+ }
+
+ if (! (name && strlen (name)))
+ name = _("(Unnamed Buffer)");
+
+ if (gimp_edit_named_copy (image, name, drawable,
+ gimp_get_user_context (image->gimp), &error))
+ {
+ gimp_image_flush (image);
+ }
+ else
+ {
+ gimp_message_literal (image->gimp, NULL, GIMP_MESSAGE_WARNING,
+ error->message);
+ g_clear_error (&error);
+ }
+}
+
+static void
+copy_named_visible_buffer_callback (GtkWidget *widget,
+ const gchar *name,
+ gpointer data)
+{
+ GimpImage *image = GIMP_IMAGE (data);
+ GError *error = NULL;
+
+ if (! (name && strlen (name)))
+ name = _("(Unnamed Buffer)");
+
+ if (gimp_edit_named_copy_visible (image, name,
+ gimp_get_user_context (image->gimp),
+ &error))
+ {
+ gimp_image_flush (image);
+ }
+ else
+ {
+ gimp_message_literal (image->gimp, NULL, GIMP_MESSAGE_WARNING,
+ error->message);
+ g_clear_error (&error);
+ }
+}
diff --git a/app/actions/edit-commands.h b/app/actions/edit-commands.h
new file mode 100644
index 0000000..2185854
--- /dev/null
+++ b/app/actions/edit-commands.h
@@ -0,0 +1,76 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __EDIT_COMMANDS_H__
+#define __EDIT_COMMANDS_H__
+
+
+void edit_undo_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void edit_redo_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void edit_strong_undo_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void edit_strong_redo_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void edit_undo_clear_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+void edit_cut_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void edit_copy_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void edit_copy_visible_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+void edit_paste_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void edit_paste_as_new_image_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+void edit_named_cut_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void edit_named_copy_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void edit_named_copy_visible_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void edit_named_paste_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+void edit_clear_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void edit_fill_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+
+#endif /* __EDIT_COMMANDS_H__ */
diff --git a/app/actions/error-console-actions.c b/app/actions/error-console-actions.c
new file mode 100644
index 0000000..e82b55a
--- /dev/null
+++ b/app/actions/error-console-actions.c
@@ -0,0 +1,152 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "actions-types.h"
+
+#include "widgets/gimpactiongroup.h"
+#include "widgets/gimperrorconsole.h"
+#include "widgets/gimphelp-ids.h"
+
+#include "error-console-actions.h"
+#include "error-console-commands.h"
+
+#include "gimp-intl.h"
+
+
+static const GimpActionEntry error_console_actions[] =
+{
+ { "error-console-popup", GIMP_ICON_DIALOG_WARNING,
+ NC_("error-console-action", "Error Console Menu"), NULL, NULL, NULL,
+ GIMP_HELP_ERRORS_DIALOG },
+
+ { "error-console-clear", GIMP_ICON_EDIT_CLEAR,
+ NC_("error-console-action", "_Clear"), NULL,
+ NC_("error-console-action", "Clear error console"),
+ error_console_clear_cmd_callback,
+ GIMP_HELP_ERRORS_CLEAR },
+
+ { "error-console-select-all", NULL,
+ NC_("error-console-action", "Select _All"), "",
+ NC_("error-console-action", "Select all error messages"),
+ error_console_select_all_cmd_callback,
+ GIMP_HELP_ERRORS_SELECT_ALL },
+
+ { "error-console-highlight", NULL,
+ NC_("error-console-action", "_Highlight"), NULL, NULL, NULL,
+ GIMP_HELP_ERRORS_HIGHLIGHT }
+};
+
+static const GimpEnumActionEntry error_console_save_actions[] =
+{
+ { "error-console-save-all", GIMP_ICON_DOCUMENT_SAVE_AS,
+ NC_("error-console-action", "_Save Error Log to File..."), NULL,
+ NC_("error-console-action", "Write all error messages to a file"),
+ FALSE, FALSE,
+ GIMP_HELP_ERRORS_SAVE },
+
+ { "error-console-save-selection", GIMP_ICON_DOCUMENT_SAVE_AS,
+ NC_("error-console-action", "Save S_election to File..."), NULL,
+ NC_("error-console-action", "Write the selected error messages to a file"),
+ TRUE, FALSE,
+ GIMP_HELP_ERRORS_SAVE }
+};
+
+static const GimpToggleActionEntry error_console_highlight_actions[] =
+{
+ { "error-console-highlight-error", NULL,
+ NC_("error-console-action", "_Errors"), NULL,
+ NC_("error-console-action", "Highlight error console on errors"),
+ error_console_highlight_error_cmd_callback,
+ FALSE,
+ GIMP_HELP_ERRORS_HIGHLIGHT },
+
+ { "error-console-highlight-warning", NULL,
+ NC_("error-console-action", "_Warnings"), NULL,
+ NC_("error-console-action", "Highlight error console on warnings"),
+ error_console_highlight_warning_cmd_callback,
+ FALSE,
+ GIMP_HELP_ERRORS_HIGHLIGHT },
+
+ { "error-console-highlight-info", NULL,
+ NC_("error-console-action", "_Messages"), NULL,
+ NC_("error-console-action", "Highlight error console on messages"),
+ error_console_highlight_info_cmd_callback,
+ FALSE,
+ GIMP_HELP_ERRORS_HIGHLIGHT }
+};
+
+
+void
+error_console_actions_setup (GimpActionGroup *group)
+{
+ gimp_action_group_add_actions (group, "error-console-action",
+ error_console_actions,
+ G_N_ELEMENTS (error_console_actions));
+
+ gimp_action_group_add_enum_actions (group, "error-console-action",
+ error_console_save_actions,
+ G_N_ELEMENTS (error_console_save_actions),
+ error_console_save_cmd_callback);
+
+ gimp_action_group_add_toggle_actions (group, "error-console-action",
+ error_console_highlight_actions,
+ G_N_ELEMENTS (error_console_highlight_actions));
+}
+
+void
+error_console_actions_update (GimpActionGroup *group,
+ gpointer data)
+{
+ GimpErrorConsole *console = GIMP_ERROR_CONSOLE (data);
+ gboolean selection;
+
+ selection = gtk_text_buffer_get_selection_bounds (console->text_buffer,
+ NULL, NULL);
+
+#define SET_ACTIVE(action,condition) \
+ gimp_action_group_set_action_active (group, action, (condition) != 0)
+#define SET_SENSITIVE(action,condition) \
+ gimp_action_group_set_action_sensitive (group, action, (condition) != 0)
+
+ SET_SENSITIVE ("error-console-clear", TRUE);
+ SET_SENSITIVE ("error-console-select-all", TRUE);
+ SET_SENSITIVE ("error-console-save-all", TRUE);
+ SET_SENSITIVE ("error-console-save-selection", selection);
+ SET_SENSITIVE ("error-console-highlight", TRUE);
+
+ SET_SENSITIVE ("error-console-highlight-error", TRUE);
+ SET_ACTIVE ("error-console-highlight-error",
+ console->highlight[GIMP_MESSAGE_ERROR]);
+
+ SET_SENSITIVE ("error-console-highlight-warning", TRUE);
+ SET_ACTIVE ("error-console-highlight-warning",
+ console->highlight[GIMP_MESSAGE_WARNING]);
+
+ SET_SENSITIVE ("error-console-highlight-info", TRUE);
+ SET_ACTIVE ("error-console-highlight-info",
+ console->highlight[GIMP_MESSAGE_INFO]);
+
+#undef SET_ACTIVE
+#undef SET_SENSITIVE
+}
diff --git a/app/actions/error-console-actions.h b/app/actions/error-console-actions.h
new file mode 100644
index 0000000..c7a2dde
--- /dev/null
+++ b/app/actions/error-console-actions.h
@@ -0,0 +1,27 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __ERROR_CONSOLE_ACIONS_H__
+#define __ERROR_CONSOLE_ACIONS_H__
+
+
+void error_console_actions_setup (GimpActionGroup *group);
+void error_console_actions_update (GimpActionGroup *group,
+ gpointer data);
+
+
+#endif /* __ERROR_CONSOLE_ACTIONS_H__ */
diff --git a/app/actions/error-console-commands.c b/app/actions/error-console-commands.c
new file mode 100644
index 0000000..4d70981
--- /dev/null
+++ b/app/actions/error-console-commands.c
@@ -0,0 +1,201 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpbase/gimpbase.h"
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "actions-types.h"
+
+#include "core/gimp.h"
+
+#include "widgets/gimperrorconsole.h"
+#include "widgets/gimphelp-ids.h"
+#include "widgets/gimptextbuffer.h"
+
+#include "error-console-commands.h"
+
+#include "gimp-intl.h"
+
+
+/* local function prototypes */
+
+static void error_console_save_response (GtkWidget *dialog,
+ gint response_id,
+ GimpErrorConsole *console);
+
+
+/* public functions */
+
+void
+error_console_clear_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpErrorConsole *console = GIMP_ERROR_CONSOLE (data);
+ GtkTextIter start_iter;
+ GtkTextIter end_iter;
+
+ gtk_text_buffer_get_bounds (console->text_buffer, &start_iter, &end_iter);
+ gtk_text_buffer_delete (console->text_buffer, &start_iter, &end_iter);
+}
+
+void
+error_console_select_all_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpErrorConsole *console = GIMP_ERROR_CONSOLE (data);
+ GtkTextIter start_iter;
+ GtkTextIter end_iter;
+
+ gtk_text_buffer_get_bounds (console->text_buffer, &start_iter, &end_iter);
+ gtk_text_buffer_select_range (console->text_buffer, &start_iter, &end_iter);
+}
+
+void
+error_console_save_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpErrorConsole *console = GIMP_ERROR_CONSOLE (data);
+ gboolean selection = (gboolean) g_variant_get_int32 (value);
+
+ if (selection &&
+ ! gtk_text_buffer_get_selection_bounds (console->text_buffer,
+ NULL, NULL))
+ {
+ gimp_message_literal (console->gimp,
+ G_OBJECT (console), GIMP_MESSAGE_WARNING,
+ _("Cannot save. Nothing is selected."));
+ return;
+ }
+
+ if (! console->file_dialog)
+ {
+ GtkWidget *dialog;
+
+ dialog = console->file_dialog =
+ gtk_file_chooser_dialog_new (_("Save Error Log to File"), NULL,
+ GTK_FILE_CHOOSER_ACTION_SAVE,
+
+ _("_Cancel"), GTK_RESPONSE_CANCEL,
+ _("_Save"), GTK_RESPONSE_OK,
+
+ NULL);
+
+ gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
+ gtk_dialog_set_alternative_button_order (GTK_DIALOG (dialog),
+ GTK_RESPONSE_OK,
+ GTK_RESPONSE_CANCEL,
+ -1);
+
+ console->save_selection = selection;
+
+ g_object_add_weak_pointer (G_OBJECT (dialog),
+ (gpointer) &console->file_dialog);
+
+ gtk_window_set_screen (GTK_WINDOW (dialog),
+ gtk_widget_get_screen (GTK_WIDGET (console)));
+ gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE);
+ gtk_window_set_role (GTK_WINDOW (dialog), "gimp-save-errors");
+
+ gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog),
+ TRUE);
+
+ g_signal_connect (dialog, "response",
+ G_CALLBACK (error_console_save_response),
+ console);
+ g_signal_connect (dialog, "delete-event",
+ G_CALLBACK (gtk_true),
+ NULL);
+
+ gimp_help_connect (dialog, gimp_standard_help_func,
+ GIMP_HELP_ERRORS_DIALOG, NULL);
+ }
+
+ gtk_window_present (GTK_WINDOW (console->file_dialog));
+}
+
+void
+error_console_highlight_error_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpErrorConsole *console = GIMP_ERROR_CONSOLE (data);
+ gboolean active = g_variant_get_boolean (value);
+
+ console->highlight[GIMP_MESSAGE_ERROR] = active;
+}
+
+void
+error_console_highlight_warning_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpErrorConsole *console = GIMP_ERROR_CONSOLE (data);
+ gboolean active = g_variant_get_boolean (value);
+
+ console->highlight[GIMP_MESSAGE_WARNING] = active;
+}
+
+void
+error_console_highlight_info_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpErrorConsole *console = GIMP_ERROR_CONSOLE (data);
+ gboolean active = g_variant_get_boolean (value);
+
+ console->highlight[GIMP_MESSAGE_INFO] = active;
+}
+
+
+/* private functions */
+
+static void
+error_console_save_response (GtkWidget *dialog,
+ gint response_id,
+ GimpErrorConsole *console)
+{
+ if (response_id == GTK_RESPONSE_OK)
+ {
+ GFile *file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog));
+ GError *error = NULL;
+
+ if (! gimp_text_buffer_save (GIMP_TEXT_BUFFER (console->text_buffer),
+ file,
+ console->save_selection, &error))
+ {
+ gimp_message (console->gimp, G_OBJECT (dialog), GIMP_MESSAGE_ERROR,
+ _("Error writing file '%s':\n%s"),
+ gimp_file_get_utf8_name (file),
+ error->message);
+ g_clear_error (&error);
+ g_object_unref (file);
+ return;
+ }
+
+ g_object_unref (file);
+ }
+
+ gtk_widget_destroy (dialog);
+}
diff --git a/app/actions/error-console-commands.h b/app/actions/error-console-commands.h
new file mode 100644
index 0000000..6913a9b
--- /dev/null
+++ b/app/actions/error-console-commands.h
@@ -0,0 +1,43 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __ERROR_CONSOLE_COMMANDS_H__
+#define __ERROR_CONSOLE_COMMANDS_H__
+
+
+void error_console_clear_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void error_console_select_all_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void error_console_save_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+void error_console_highlight_error_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void error_console_highlight_warning_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void error_console_highlight_info_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+
+#endif /* __ERROR_CONSOLE_COMMANDS_H__ */
diff --git a/app/actions/file-actions.c b/app/actions/file-actions.c
new file mode 100644
index 0000000..b767750
--- /dev/null
+++ b/app/actions/file-actions.c
@@ -0,0 +1,452 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpbase/gimpbase.h"
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "actions-types.h"
+
+#include "config/gimpguiconfig.h"
+
+#include "core/gimp.h"
+#include "core/gimpcontainer.h"
+#include "core/gimpimage.h"
+#include "core/gimpimagefile.h"
+#include "core/gimpviewable.h"
+
+#include "file/gimp-file.h"
+
+#include "plug-in/gimppluginmanager-file.h"
+
+#include "widgets/gimpaction.h"
+#include "widgets/gimpactiongroup.h"
+#include "widgets/gimpactionimpl.h"
+#include "widgets/gimphelp-ids.h"
+
+#include "display/gimpdisplay.h"
+
+#include "actions.h"
+#include "file-actions.h"
+#include "file-commands.h"
+
+#include "gimp-intl.h"
+
+
+/* local function prototypes */
+
+static void file_actions_last_opened_update (GimpContainer *container,
+ GimpImagefile *unused,
+ GimpActionGroup *group);
+static void file_actions_last_opened_reorder (GimpContainer *container,
+ GimpImagefile *unused1,
+ gint unused2,
+ GimpActionGroup *group);
+static void file_actions_close_all_update (GimpContainer *images,
+ GimpObject *unused,
+ GimpActionGroup *group);
+static gchar * file_actions_create_label (const gchar *format,
+ GFile *file);
+
+
+static const GimpActionEntry file_actions[] =
+{
+ { "file-menu", NULL, NC_("file-action", "_File") },
+ { "file-create-menu", NULL, NC_("file-action", "Crea_te") },
+ { "file-open-recent-menu", NULL, NC_("file-action", "Open _Recent") },
+
+ { "file-open", GIMP_ICON_IMAGE_OPEN,
+ NC_("file-action", "_Open..."), "<primary>O",
+ NC_("file-action", "Open an image file"),
+ file_open_cmd_callback,
+ GIMP_HELP_FILE_OPEN },
+
+ { "file-open-as-layers", GIMP_ICON_LAYER,
+ NC_("file-action", "Op_en as Layers..."), "<primary><alt>O",
+ NC_("file-action", "Open an image file as layers"),
+ file_open_as_layers_cmd_callback,
+ GIMP_HELP_FILE_OPEN_AS_LAYER },
+
+ { "file-open-location", GIMP_ICON_WEB,
+ NC_("file-action", "Open _Location..."), NULL,
+ NC_("file-action", "Open an image file from a specified location"),
+ file_open_location_cmd_callback,
+ GIMP_HELP_FILE_OPEN_LOCATION },
+
+ { "file-create-template", NULL,
+ NC_("file-action", "Create _Template..."), NULL,
+ NC_("file-action", "Create a new template from this image"),
+ file_create_template_cmd_callback,
+ GIMP_HELP_FILE_CREATE_TEMPLATE },
+
+ { "file-revert", GIMP_ICON_IMAGE_RELOAD,
+ NC_("file-action", "Re_vert"), NULL,
+ NC_("file-action", "Reload the image file from disk"),
+ file_revert_cmd_callback,
+ GIMP_HELP_FILE_REVERT },
+
+ { "file-close-all", GIMP_ICON_CLOSE_ALL,
+ NC_("file-action", "C_lose All"), "<primary><shift>W",
+ NC_("file-action", "Close all opened images"),
+ file_close_all_cmd_callback,
+ GIMP_HELP_FILE_CLOSE_ALL },
+
+ { "file-copy-location", GIMP_ICON_EDIT_COPY,
+ NC_("file-action", "Copy _Image Location"), NULL,
+ NC_("file-action", "Copy image file location to clipboard"),
+ file_copy_location_cmd_callback,
+ GIMP_HELP_FILE_COPY_LOCATION },
+
+ { "file-show-in-file-manager", GIMP_ICON_FILE_MANAGER,
+ NC_("file-action", "Show in _File Manager"), "<primary><alt>F",
+ NC_("file-action", "Show image file location in the file manager"),
+ file_show_in_file_manager_cmd_callback,
+ GIMP_HELP_FILE_SHOW_IN_FILE_MANAGER },
+
+ { "file-quit", GIMP_ICON_APPLICATION_EXIT,
+ NC_("file-action", "_Quit"), "<primary>Q",
+ NC_("file-action", "Quit the GNU Image Manipulation Program"),
+ file_quit_cmd_callback,
+ GIMP_HELP_FILE_QUIT }
+};
+
+static const GimpEnumActionEntry file_save_actions[] =
+{
+ { "file-save", GIMP_ICON_DOCUMENT_SAVE,
+ NC_("file-action", "_Save"), "<primary>S",
+ NC_("file-action", "Save this image"),
+ GIMP_SAVE_MODE_SAVE, FALSE,
+ GIMP_HELP_FILE_SAVE },
+
+ { "file-save-as", GIMP_ICON_DOCUMENT_SAVE_AS,
+ NC_("file-action", "Save _As..."), "<primary><shift>S",
+ NC_("file-action", "Save this image with a different name"),
+ GIMP_SAVE_MODE_SAVE_AS, FALSE,
+ GIMP_HELP_FILE_SAVE_AS },
+
+ { "file-save-a-copy", NULL,
+ NC_("file-action", "Save a Cop_y..."), NULL,
+ NC_("file-action",
+ "Save a copy of this image, without affecting the source file "
+ "(if any) or the current state of the image"),
+ GIMP_SAVE_MODE_SAVE_A_COPY, FALSE,
+ GIMP_HELP_FILE_SAVE_A_COPY },
+
+ { "file-save-and-close", NULL,
+ NC_("file-action", "Save and Close..."), NULL,
+ NC_("file-action", "Save this image and close its window"),
+ GIMP_SAVE_MODE_SAVE_AND_CLOSE, FALSE,
+ GIMP_HELP_FILE_SAVE },
+
+ { "file-export", NULL,
+ NC_("file-action", "E_xport..."), "<primary>E",
+ NC_("file-action", "Export the image"),
+ GIMP_SAVE_MODE_EXPORT, FALSE,
+ GIMP_HELP_FILE_EXPORT },
+
+ { "file-overwrite", NULL,
+ NC_("file-action", "Over_write"), "",
+ NC_("file-action", "Export the image back to the imported file in the import format"),
+ GIMP_SAVE_MODE_OVERWRITE, FALSE,
+ GIMP_HELP_FILE_OVERWRITE },
+
+ { "file-export-as", NULL,
+ NC_("file-action", "E_xport As..."), "<primary><shift>E",
+ NC_("file-action", "Export the image to various file formats such as PNG or JPEG"),
+ GIMP_SAVE_MODE_EXPORT_AS, FALSE,
+ GIMP_HELP_FILE_EXPORT_AS }
+};
+
+void
+file_actions_setup (GimpActionGroup *group)
+{
+ GimpEnumActionEntry *entries;
+ gint n_entries;
+ gint i;
+
+ gimp_action_group_add_actions (group, "file-action",
+ file_actions,
+ G_N_ELEMENTS (file_actions));
+
+ gimp_action_group_add_enum_actions (group, "file-action",
+ file_save_actions,
+ G_N_ELEMENTS (file_save_actions),
+ file_save_cmd_callback);
+
+ n_entries = GIMP_GUI_CONFIG (group->gimp->config)->last_opened_size;
+
+ entries = g_new0 (GimpEnumActionEntry, n_entries);
+
+ for (i = 0; i < n_entries; i++)
+ {
+ entries[i].name = g_strdup_printf ("file-open-recent-%02d",
+ i + 1);
+ entries[i].icon_name = GIMP_ICON_DOCUMENT_OPEN,
+ entries[i].label = entries[i].name;
+ entries[i].tooltip = NULL;
+ entries[i].value = i;
+ entries[i].value_variable = FALSE;
+
+ if (i < 9)
+ entries[i].accelerator = g_strdup_printf ("<primary>%d", i + 1);
+ else if (i == 9)
+ entries[i].accelerator = g_strdup ("<primary>0");
+ else
+ entries[i].accelerator = NULL;
+ }
+
+ gimp_action_group_add_enum_actions (group, NULL, entries, n_entries,
+ file_open_recent_cmd_callback);
+
+ for (i = 0; i < n_entries; i++)
+ {
+ gimp_action_group_set_action_visible (group, entries[i].name, FALSE);
+ gimp_action_group_set_action_always_show_image (group, entries[i].name,
+ TRUE);
+ gimp_action_group_set_action_context (group, entries[i].name,
+ gimp_get_user_context (group->gimp));
+
+ g_free ((gchar *) entries[i].name);
+ if (entries[i].accelerator)
+ g_free ((gchar *) entries[i].accelerator);
+ }
+
+ g_free (entries);
+
+ g_signal_connect_object (group->gimp->documents, "add",
+ G_CALLBACK (file_actions_last_opened_update),
+ group, 0);
+ g_signal_connect_object (group->gimp->documents, "remove",
+ G_CALLBACK (file_actions_last_opened_update),
+ group, 0);
+ g_signal_connect_object (group->gimp->documents, "reorder",
+ G_CALLBACK (file_actions_last_opened_reorder),
+ group, 0);
+
+ file_actions_last_opened_update (group->gimp->documents, NULL, group);
+
+ /* also listen to image adding/removal so we catch the case where
+ * the last image is closed but its display stays open.
+ */
+ g_signal_connect_object (group->gimp->images, "add",
+ G_CALLBACK (file_actions_close_all_update),
+ group, 0);
+ g_signal_connect_object (group->gimp->images, "remove",
+ G_CALLBACK (file_actions_close_all_update),
+ group, 0);
+
+ file_actions_close_all_update (group->gimp->displays, NULL, group);
+}
+
+void
+file_actions_update (GimpActionGroup *group,
+ gpointer data)
+{
+ Gimp *gimp = action_data_get_gimp (data);
+ GimpImage *image = action_data_get_image (data);
+ GimpDrawable *drawable = NULL;
+ GFile *file = NULL;
+ GFile *source = NULL;
+ GFile *export = NULL;
+ gboolean show_overwrite = FALSE;
+
+ if (image)
+ {
+ drawable = gimp_image_get_active_drawable (image);
+
+ file = gimp_image_get_file (image);
+ source = gimp_image_get_imported_file (image);
+ export = gimp_image_get_exported_file (image);
+ }
+
+ show_overwrite =
+ (source &&
+ gimp_plug_in_manager_file_procedure_find (gimp->plug_in_manager,
+ GIMP_FILE_PROCEDURE_GROUP_EXPORT,
+ source, NULL));
+
+#define SET_VISIBLE(action,condition) \
+ gimp_action_group_set_action_visible (group, action, (condition) != 0)
+#define SET_SENSITIVE(action,condition) \
+ gimp_action_group_set_action_sensitive (group, action, (condition) != 0)
+
+ SET_SENSITIVE ("file-save", drawable);
+ SET_SENSITIVE ("file-save-as", drawable);
+ SET_SENSITIVE ("file-save-a-copy", drawable);
+ SET_SENSITIVE ("file-save-and-close", drawable);
+ SET_SENSITIVE ("file-revert", file || source);
+ SET_SENSITIVE ("file-export", drawable);
+ SET_VISIBLE ("file-export", ! show_overwrite);
+ SET_SENSITIVE ("file-overwrite", show_overwrite);
+ SET_VISIBLE ("file-overwrite", show_overwrite);
+ SET_SENSITIVE ("file-export-as", drawable);
+ SET_SENSITIVE ("file-create-template", image);
+ SET_SENSITIVE ("file-copy-location", file || source || export);
+ SET_SENSITIVE ("file-show-in-file-manager", file || source || export);
+
+ if (file)
+ {
+ gimp_action_group_set_action_label (group,
+ "file-save",
+ C_("file-action", "_Save"));
+ }
+ else
+ {
+ gimp_action_group_set_action_label (group,
+ "file-save",
+ C_("file-action", "_Save..."));
+ }
+
+ if (export)
+ {
+ gchar *label = file_actions_create_label (_("Export to %s"), export);
+ gimp_action_group_set_action_label (group, "file-export", label);
+ g_free (label);
+ }
+ else if (show_overwrite)
+ {
+ gchar *label = file_actions_create_label (_("Over_write %s"), source);
+ gimp_action_group_set_action_label (group, "file-overwrite", label);
+ g_free (label);
+ }
+ else
+ {
+ gimp_action_group_set_action_label (group,
+ "file-export",
+ C_("file-action", "E_xport..."));
+ }
+
+ /* needed for the empty display */
+ SET_SENSITIVE ("file-close-all", image);
+
+#undef SET_SENSITIVE
+}
+
+
+/* private functions */
+
+static void
+file_actions_last_opened_update (GimpContainer *container,
+ GimpImagefile *unused,
+ GimpActionGroup *group)
+{
+ gint num_documents;
+ gint i;
+ gint n = GIMP_GUI_CONFIG (group->gimp->config)->last_opened_size;
+
+ num_documents = gimp_container_get_n_children (container);
+
+ for (i = 0; i < n; i++)
+ {
+ GimpAction *action;
+ gchar *name = g_strdup_printf ("file-open-recent-%02d", i + 1);
+
+ action = gimp_action_group_get_action (group, name);
+
+ if (i < num_documents)
+ {
+ GimpImagefile *imagefile = (GimpImagefile *)
+ gimp_container_get_child_by_index (container, i);
+
+ if (GIMP_ACTION_IMPL (action)->viewable != (GimpViewable *) imagefile)
+ {
+ GFile *file;
+ const gchar *name;
+ gchar *basename;
+ gchar *escaped;
+
+ file = gimp_imagefile_get_file (imagefile);
+
+ name = gimp_file_get_utf8_name (file);
+ basename = g_path_get_basename (name);
+
+ escaped = gimp_escape_uline (basename);
+
+ g_free (basename);
+
+ g_object_set (action,
+ "label", escaped,
+ "tooltip", name,
+ "visible", TRUE,
+ "viewable", imagefile,
+ NULL);
+
+ g_free (escaped);
+ }
+ }
+ else
+ {
+ g_object_set (action,
+ "label", name,
+ "tooltip", NULL,
+ "visible", FALSE,
+ "viewable", NULL,
+ NULL);
+ }
+
+ g_free (name);
+ }
+}
+
+static void
+file_actions_last_opened_reorder (GimpContainer *container,
+ GimpImagefile *unused1,
+ gint unused2,
+ GimpActionGroup *group)
+{
+ file_actions_last_opened_update (container, unused1, group);
+}
+
+static void
+file_actions_close_all_update (GimpContainer *images,
+ GimpObject *unused,
+ GimpActionGroup *group)
+{
+ GimpContainer *container = group->gimp->displays;
+ gint n_displays = gimp_container_get_n_children (container);
+ gboolean sensitive = (n_displays > 0);
+
+ if (n_displays == 1)
+ {
+ GimpDisplay *display;
+
+ display = GIMP_DISPLAY (gimp_container_get_first_child (container));
+
+ if (! gimp_display_get_image (display))
+ sensitive = FALSE;
+ }
+
+ gimp_action_group_set_action_sensitive (group, "file-close-all", sensitive);
+}
+
+static gchar *
+file_actions_create_label (const gchar *format,
+ GFile *file)
+{
+ gchar *basename = g_path_get_basename (gimp_file_get_utf8_name (file));
+ gchar *escaped_basename = gimp_escape_uline (basename);
+ gchar *label = g_strdup_printf (format, escaped_basename);
+
+ g_free (escaped_basename);
+ g_free (basename);
+
+ return label;
+}
diff --git a/app/actions/file-actions.h b/app/actions/file-actions.h
new file mode 100644
index 0000000..7029a9a
--- /dev/null
+++ b/app/actions/file-actions.h
@@ -0,0 +1,27 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __FILE_ACTIONS_H__
+#define __FILE_ACTIONS_H__
+
+
+void file_actions_setup (GimpActionGroup *group);
+void file_actions_update (GimpActionGroup *group,
+ gpointer data);
+
+
+#endif /* __FILE_ACTIONS_H__ */
diff --git a/app/actions/file-commands.c b/app/actions/file-commands.c
new file mode 100644
index 0000000..9e72f3e
--- /dev/null
+++ b/app/actions/file-commands.c
@@ -0,0 +1,837 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <string.h>
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpbase/gimpbase.h"
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "actions-types.h"
+
+#include "config/gimpguiconfig.h"
+
+#include "core/gimp.h"
+#include "core/gimpcontainer.h"
+#include "core/gimpimage.h"
+#include "core/gimpimagefile.h"
+#include "core/gimpprogress.h"
+#include "core/gimptemplate.h"
+
+#include "plug-in/gimppluginmanager-file.h"
+
+#include "file/file-open.h"
+#include "file/file-save.h"
+#include "file/gimp-file.h"
+
+#include "widgets/gimpactiongroup.h"
+#include "widgets/gimpclipboard.h"
+#include "widgets/gimpdialogfactory.h"
+#include "widgets/gimpexportdialog.h"
+#include "widgets/gimpfiledialog.h"
+#include "widgets/gimphelp-ids.h"
+#include "widgets/gimpmessagebox.h"
+#include "widgets/gimpmessagedialog.h"
+#include "widgets/gimpopendialog.h"
+#include "widgets/gimpsavedialog.h"
+#include "widgets/gimpwidgets-utils.h"
+
+#include "display/gimpdisplay.h"
+#include "display/gimpdisplay-foreach.h"
+
+#include "dialogs/dialogs.h"
+#include "dialogs/file-save-dialog.h"
+
+#include "actions.h"
+#include "file-commands.h"
+
+#include "gimp-intl.h"
+
+
+/* local function prototypes */
+
+static void file_open_dialog_show (Gimp *gimp,
+ GtkWidget *parent,
+ const gchar *title,
+ GimpImage *image,
+ GFile *file,
+ gboolean open_as_layers);
+static GtkWidget * file_save_dialog_show (Gimp *gimp,
+ GimpImage *image,
+ GtkWidget *parent,
+ const gchar *title,
+ gboolean save_a_copy,
+ gboolean close_after_saving,
+ GimpDisplay *display);
+static GtkWidget * file_export_dialog_show (Gimp *gimp,
+ GimpImage *image,
+ GtkWidget *parent);
+static void file_save_dialog_response (GtkWidget *dialog,
+ gint response_id,
+ gpointer data);
+static void file_export_dialog_response (GtkWidget *dialog,
+ gint response_id,
+ gpointer data);
+static void file_new_template_callback (GtkWidget *widget,
+ const gchar *name,
+ gpointer data);
+static void file_revert_confirm_response (GtkWidget *dialog,
+ gint response_id,
+ GimpDisplay *display);
+
+
+
+/* public functions */
+
+
+void
+file_open_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ Gimp *gimp;
+ GtkWidget *widget;
+ GimpImage *image;
+ return_if_no_gimp (gimp, data);
+ return_if_no_widget (widget, data);
+
+ image = action_data_get_image (data);
+
+ file_open_dialog_show (gimp, widget,
+ _("Open Image"),
+ image, NULL, FALSE);
+}
+
+void
+file_open_as_layers_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ Gimp *gimp;
+ GtkWidget *widget;
+ GimpDisplay *display;
+ GimpImage *image = NULL;
+ return_if_no_gimp (gimp, data);
+ return_if_no_widget (widget, data);
+
+ display = action_data_get_display (data);
+
+ if (display)
+ image = gimp_display_get_image (display);
+
+ file_open_dialog_show (gimp, widget,
+ _("Open Image as Layers"),
+ image, NULL, TRUE);
+}
+
+void
+file_open_location_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GtkWidget *widget;
+ return_if_no_widget (widget, data);
+
+ gimp_dialog_factory_dialog_new (gimp_dialog_factory_get_singleton (),
+ gtk_widget_get_screen (widget),
+ gimp_widget_get_monitor (widget),
+ NULL /*ui_manager*/,
+ "gimp-file-open-location-dialog", -1, TRUE);
+}
+
+void
+file_open_recent_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ Gimp *gimp;
+ GimpImagefile *imagefile;
+ gint index;
+ gint num_entries;
+ return_if_no_gimp (gimp, data);
+
+ index = g_variant_get_int32 (value);
+
+ num_entries = gimp_container_get_n_children (gimp->documents);
+
+ if (index >= num_entries)
+ return;
+
+ imagefile = (GimpImagefile *)
+ gimp_container_get_child_by_index (gimp->documents, index);
+
+ if (imagefile)
+ {
+ GFile *file;
+ GimpDisplay *display;
+ GtkWidget *widget;
+ GimpProgress *progress;
+ GimpImage *image;
+ GimpPDBStatusType status;
+ GError *error = NULL;
+ return_if_no_display (display, data);
+ return_if_no_widget (widget, data);
+
+ g_object_ref (display);
+ g_object_ref (imagefile);
+
+ file = gimp_imagefile_get_file (imagefile);
+
+ progress = gimp_display_get_image (display) ?
+ NULL : GIMP_PROGRESS (display);
+
+ image = file_open_with_display (gimp, action_data_get_context (data),
+ progress,
+ file, FALSE,
+ G_OBJECT (gtk_widget_get_screen (widget)),
+ gimp_widget_get_monitor (widget),
+ &status, &error);
+
+ if (! image && status != GIMP_PDB_CANCEL)
+ {
+ gimp_message (gimp, G_OBJECT (display), GIMP_MESSAGE_ERROR,
+ _("Opening '%s' failed:\n\n%s"),
+ gimp_file_get_utf8_name (file), error->message);
+ g_clear_error (&error);
+ }
+
+ g_object_unref (imagefile);
+ g_object_unref (display);
+ }
+}
+
+void
+file_save_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ Gimp *gimp;
+ GimpDisplay *display;
+ GimpImage *image;
+ GtkWidget *widget;
+ GimpSaveMode save_mode;
+ GFile *file = NULL;
+ gboolean saved = FALSE;
+ return_if_no_gimp (gimp, data);
+ return_if_no_display (display, data);
+ return_if_no_widget (widget, data);
+
+ image = gimp_display_get_image (display);
+
+ save_mode = (GimpSaveMode) g_variant_get_int32 (value);
+
+ if (! gimp_image_get_active_drawable (image))
+ return;
+
+ file = gimp_image_get_file (image);
+
+ switch (save_mode)
+ {
+ case GIMP_SAVE_MODE_SAVE:
+ case GIMP_SAVE_MODE_SAVE_AND_CLOSE:
+ /* Only save if the image has been modified, or if it is new. */
+ if ((gimp_image_is_dirty (image) ||
+ ! GIMP_GUI_CONFIG (image->gimp->config)->trust_dirty_flag) ||
+ file == NULL)
+ {
+ GimpPlugInProcedure *save_proc = gimp_image_get_save_proc (image);
+
+ if (file && ! save_proc)
+ {
+ save_proc =
+ gimp_plug_in_manager_file_procedure_find (image->gimp->plug_in_manager,
+ GIMP_FILE_PROCEDURE_GROUP_SAVE,
+ file, NULL);
+ }
+
+ if (file && save_proc)
+ {
+ saved = file_save_dialog_save_image (GIMP_PROGRESS (display),
+ gimp, image, file,
+ save_proc,
+ GIMP_RUN_WITH_LAST_VALS,
+ TRUE, FALSE, FALSE,
+ gimp_image_get_xcf_compression (image),
+ TRUE);
+ break;
+ }
+
+ /* fall thru */
+ }
+ else
+ {
+ gimp_message_literal (image->gimp,
+ G_OBJECT (display), GIMP_MESSAGE_INFO,
+ _("No changes need to be saved"));
+ saved = TRUE;
+ break;
+ }
+
+ case GIMP_SAVE_MODE_SAVE_AS:
+ file_save_dialog_show (gimp, image, widget,
+ _("Save Image"), FALSE,
+ save_mode == GIMP_SAVE_MODE_SAVE_AND_CLOSE, display);
+ break;
+
+ case GIMP_SAVE_MODE_SAVE_A_COPY:
+ file_save_dialog_show (gimp, image, widget,
+ _("Save a Copy of the Image"), TRUE,
+ FALSE, display);
+ break;
+
+ case GIMP_SAVE_MODE_EXPORT_AS:
+ file_export_dialog_show (gimp, image, widget);
+ break;
+
+ case GIMP_SAVE_MODE_EXPORT:
+ case GIMP_SAVE_MODE_OVERWRITE:
+ {
+ GFile *file = NULL;
+ GimpPlugInProcedure *export_proc = NULL;
+ gboolean overwrite = FALSE;
+
+ if (save_mode == GIMP_SAVE_MODE_EXPORT)
+ {
+ file = gimp_image_get_exported_file (image);
+ export_proc = gimp_image_get_export_proc (image);
+
+ if (! file)
+ {
+ /* Behave as if Export As... was invoked */
+ file_export_dialog_show (gimp, image, widget);
+ break;
+ }
+
+ overwrite = FALSE;
+ }
+ else if (save_mode == GIMP_SAVE_MODE_OVERWRITE)
+ {
+ file = gimp_image_get_imported_file (image);
+
+ overwrite = TRUE;
+ }
+
+ if (file && ! export_proc)
+ {
+ export_proc =
+ gimp_plug_in_manager_file_procedure_find (image->gimp->plug_in_manager,
+ GIMP_FILE_PROCEDURE_GROUP_EXPORT,
+ file, NULL);
+ }
+
+ if (file && export_proc)
+ {
+ saved = file_save_dialog_save_image (GIMP_PROGRESS (display),
+ gimp, image, file,
+ export_proc,
+ GIMP_RUN_WITH_LAST_VALS,
+ FALSE,
+ overwrite, ! overwrite,
+ FALSE, TRUE);
+ }
+ }
+ break;
+ }
+
+ if (save_mode == GIMP_SAVE_MODE_SAVE_AND_CLOSE &&
+ saved &&
+ ! gimp_image_is_dirty (image))
+ {
+ gimp_display_close (display);
+ }
+}
+
+void
+file_create_template_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpDisplay *display;
+ GimpImage *image;
+ GtkWidget *dialog;
+ return_if_no_display (display, data);
+
+ image = gimp_display_get_image (display);
+
+ dialog = gimp_query_string_box (_("Create New Template"),
+ GTK_WIDGET (gimp_display_get_shell (display)),
+ gimp_standard_help_func,
+ GIMP_HELP_FILE_CREATE_TEMPLATE,
+ _("Enter a name for this template"),
+ NULL,
+ G_OBJECT (image), "disconnect",
+ file_new_template_callback, image);
+ gtk_widget_show (dialog);
+}
+
+void
+file_revert_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpDisplay *display;
+ GimpImage *image;
+ GtkWidget *dialog;
+ GFile *file;
+ return_if_no_display (display, data);
+
+ image = gimp_display_get_image (display);
+
+ file = gimp_image_get_file (image);
+
+ if (! file)
+ file = gimp_image_get_imported_file (image);
+
+ if (! file)
+ {
+ gimp_message_literal (image->gimp,
+ G_OBJECT (display), GIMP_MESSAGE_ERROR,
+ _("Revert failed. "
+ "No file name associated with this image."));
+ return;
+ }
+
+#define REVERT_DIALOG_KEY "gimp-revert-confirm-dialog"
+
+ dialog = dialogs_get_dialog (G_OBJECT (image), REVERT_DIALOG_KEY);
+
+ if (! dialog)
+ {
+ dialog =
+ gimp_message_dialog_new (_("Revert Image"), GIMP_ICON_DOCUMENT_REVERT,
+ GTK_WIDGET (gimp_display_get_shell (display)),
+ 0,
+ gimp_standard_help_func, GIMP_HELP_FILE_REVERT,
+
+ _("_Cancel"), GTK_RESPONSE_CANCEL,
+ _("_Revert"), GTK_RESPONSE_OK,
+
+ NULL);
+
+ gtk_dialog_set_alternative_button_order (GTK_DIALOG (dialog),
+ GTK_RESPONSE_OK,
+ GTK_RESPONSE_CANCEL,
+ -1);
+
+ g_signal_connect_object (display, "disconnect",
+ G_CALLBACK (gtk_widget_destroy),
+ dialog, G_CONNECT_SWAPPED);
+
+ g_signal_connect (dialog, "response",
+ G_CALLBACK (file_revert_confirm_response),
+ display);
+
+ gimp_message_box_set_primary_text (GIMP_MESSAGE_DIALOG (dialog)->box,
+ _("Revert '%s' to '%s'?"),
+ gimp_image_get_display_name (image),
+ gimp_file_get_utf8_name (file));
+
+ gimp_message_box_set_text (GIMP_MESSAGE_DIALOG (dialog)->box,
+ _("By reverting the image to the state saved "
+ "on disk, you will lose all changes, "
+ "including all undo information."));
+
+ dialogs_attach_dialog (G_OBJECT (image), REVERT_DIALOG_KEY, dialog);
+ }
+
+ gtk_window_present (GTK_WINDOW (dialog));
+}
+
+void
+file_close_all_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ Gimp *gimp;
+ return_if_no_gimp (gimp, data);
+
+ if (! gimp_displays_dirty (gimp))
+ {
+ gimp_displays_close (gimp);
+ }
+ else
+ {
+ GtkWidget *widget;
+ return_if_no_widget (widget, data);
+
+ gimp_dialog_factory_dialog_raise (gimp_dialog_factory_get_singleton (),
+ gtk_widget_get_screen (widget),
+ gimp_widget_get_monitor (widget),
+ "gimp-close-all-dialog", -1);
+ }
+}
+
+void
+file_copy_location_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ Gimp *gimp;
+ GimpDisplay *display;
+ GimpImage *image;
+ GFile *file;
+ return_if_no_gimp (gimp, data);
+ return_if_no_display (display, data);
+
+ image = gimp_display_get_image (display);
+
+ file = gimp_image_get_any_file (image);
+
+ if (file)
+ {
+ gchar *uri = g_file_get_uri (file);
+
+ gimp_clipboard_set_text (gimp, uri);
+ g_free (uri);
+ }
+}
+
+void
+file_show_in_file_manager_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ Gimp *gimp;
+ GimpDisplay *display;
+ GimpImage *image;
+ GFile *file;
+ return_if_no_gimp (gimp, data);
+ return_if_no_display (display, data);
+
+ image = gimp_display_get_image (display);
+
+ file = gimp_image_get_any_file (image);
+
+ if (file)
+ {
+ GError *error = NULL;
+
+ if (! gimp_file_show_in_file_manager (file, &error))
+ {
+ gimp_message (gimp, G_OBJECT (display), GIMP_MESSAGE_ERROR,
+ _("Can't show file in file manager: %s"),
+ error->message);
+ g_clear_error (&error);
+ }
+ }
+}
+
+void
+file_quit_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ Gimp *gimp;
+ return_if_no_gimp (gimp, data);
+
+ gimp_exit (gimp, FALSE);
+}
+
+void
+file_file_open_dialog (Gimp *gimp,
+ GFile *file,
+ GtkWidget *parent)
+{
+ file_open_dialog_show (gimp, parent,
+ _("Open Image"),
+ NULL, file, FALSE);
+}
+
+
+/* private functions */
+
+static void
+file_open_dialog_show (Gimp *gimp,
+ GtkWidget *parent,
+ const gchar *title,
+ GimpImage *image,
+ GFile *file,
+ gboolean open_as_layers)
+{
+ GtkWidget *dialog;
+
+ dialog = gimp_dialog_factory_dialog_new (gimp_dialog_factory_get_singleton (),
+ gtk_widget_get_screen (parent),
+ gimp_widget_get_monitor (parent),
+ NULL /*ui_manager*/,
+ "gimp-file-open-dialog", -1, FALSE);
+
+ if (dialog)
+ {
+ if (! file && image)
+ file = gimp_image_get_file (image);
+
+ if (! file)
+ file = g_object_get_data (G_OBJECT (gimp),
+ GIMP_FILE_OPEN_LAST_FILE_KEY);
+
+ if (file)
+ {
+ gtk_file_chooser_set_file (GTK_FILE_CHOOSER (dialog), file, NULL);
+ }
+ else if (gimp->default_folder)
+ {
+ gtk_file_chooser_set_current_folder_file (GTK_FILE_CHOOSER (dialog),
+ gimp->default_folder, NULL);
+ }
+
+ gtk_window_set_title (GTK_WINDOW (dialog), title);
+
+ gimp_open_dialog_set_image (GIMP_OPEN_DIALOG (dialog),
+ image, open_as_layers);
+
+ gtk_window_set_transient_for (GTK_WINDOW (dialog),
+ GTK_WINDOW (gtk_widget_get_toplevel (parent)));
+
+ gtk_window_present (GTK_WINDOW (dialog));
+ }
+}
+
+static GtkWidget *
+file_save_dialog_show (Gimp *gimp,
+ GimpImage *image,
+ GtkWidget *parent,
+ const gchar *title,
+ gboolean save_a_copy,
+ gboolean close_after_saving,
+ GimpDisplay *display)
+{
+ GtkWidget *dialog;
+
+#define SAVE_DIALOG_KEY "gimp-file-save-dialog"
+
+ dialog = dialogs_get_dialog (G_OBJECT (image), SAVE_DIALOG_KEY);
+
+ if (! dialog)
+ {
+ dialog = gimp_dialog_factory_dialog_new (gimp_dialog_factory_get_singleton (),
+ gtk_widget_get_screen (parent),
+ gimp_widget_get_monitor (parent),
+ NULL /*ui_manager*/,
+ "gimp-file-save-dialog",
+ -1, FALSE);
+
+ if (dialog)
+ {
+ gtk_window_set_transient_for (GTK_WINDOW (dialog),
+ GTK_WINDOW (gtk_widget_get_toplevel (parent)));
+
+ dialogs_attach_dialog (G_OBJECT (image), SAVE_DIALOG_KEY, dialog);
+ g_signal_connect_object (image, "disconnect",
+ G_CALLBACK (gtk_widget_destroy),
+ dialog, G_CONNECT_SWAPPED);
+
+ g_signal_connect (dialog, "response",
+ G_CALLBACK (file_save_dialog_response),
+ image);
+ }
+ }
+
+ if (dialog)
+ {
+ gtk_window_set_title (GTK_WINDOW (dialog), title);
+
+ gimp_save_dialog_set_image (GIMP_SAVE_DIALOG (dialog),
+ image, save_a_copy,
+ close_after_saving, GIMP_OBJECT (display));
+
+ gtk_window_present (GTK_WINDOW (dialog));
+ }
+
+ return dialog;
+}
+
+static void
+file_save_dialog_response (GtkWidget *dialog,
+ gint response_id,
+ gpointer data)
+{
+ if (response_id == FILE_SAVE_RESPONSE_OTHER_DIALOG)
+ {
+ GimpFileDialog *file_dialog = GIMP_FILE_DIALOG (dialog);
+ GtkWindow *parent;
+ GtkWidget *other;
+ GFile *file;
+ gchar *folder;
+ gchar *basename;
+
+ parent = gtk_window_get_transient_for (GTK_WINDOW (dialog));
+ file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog));
+ folder = g_path_get_dirname (gimp_file_get_utf8_name (file));
+ basename = g_path_get_basename (gimp_file_get_utf8_name (file));
+ g_object_unref (file);
+
+ other = file_export_dialog_show (GIMP_FILE_DIALOG (file_dialog)->image->gimp,
+ GIMP_FILE_DIALOG (file_dialog)->image,
+ GTK_WIDGET (parent));
+
+ gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (other), folder);
+ gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (other), basename);
+
+ g_free (folder);
+ g_free (basename);
+ }
+}
+
+static GtkWidget *
+file_export_dialog_show (Gimp *gimp,
+ GimpImage *image,
+ GtkWidget *parent)
+{
+ GtkWidget *dialog;
+
+#define EXPORT_DIALOG_KEY "gimp-file-export-dialog"
+
+ dialog = dialogs_get_dialog (G_OBJECT (image), EXPORT_DIALOG_KEY);
+
+ if (! dialog)
+ {
+ dialog = gimp_dialog_factory_dialog_new (gimp_dialog_factory_get_singleton (),
+ gtk_widget_get_screen (parent),
+ gimp_widget_get_monitor (parent),
+ NULL /*ui_manager*/,
+ "gimp-file-export-dialog",
+ -1, FALSE);
+
+ if (dialog)
+ {
+ gtk_window_set_transient_for (GTK_WINDOW (dialog),
+ GTK_WINDOW (gtk_widget_get_toplevel (parent)));
+
+ dialogs_attach_dialog (G_OBJECT (image), EXPORT_DIALOG_KEY, dialog);
+ g_signal_connect_object (image, "disconnect",
+ G_CALLBACK (gtk_widget_destroy),
+ dialog, G_CONNECT_SWAPPED);
+
+ g_signal_connect (dialog, "response",
+ G_CALLBACK (file_export_dialog_response),
+ image);
+ }
+ }
+
+ if (dialog)
+ {
+ gimp_export_dialog_set_image (GIMP_EXPORT_DIALOG (dialog), image);
+
+ gtk_window_present (GTK_WINDOW (dialog));
+ }
+
+ return dialog;
+}
+
+static void
+file_export_dialog_response (GtkWidget *dialog,
+ gint response_id,
+ gpointer data)
+{
+ if (response_id == FILE_SAVE_RESPONSE_OTHER_DIALOG)
+ {
+ GimpFileDialog *file_dialog = GIMP_FILE_DIALOG (dialog);
+ GtkWindow *parent;
+ GtkWidget *other;
+ GFile *file;
+ gchar *folder;
+ gchar *basename;
+
+ parent = gtk_window_get_transient_for (GTK_WINDOW (dialog));
+ file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog));
+ folder = g_path_get_dirname (gimp_file_get_utf8_name (file));
+ basename = g_path_get_basename (gimp_file_get_utf8_name (file));
+ g_object_unref (file);
+
+ other = file_save_dialog_show (GIMP_FILE_DIALOG (file_dialog)->image->gimp,
+ GIMP_FILE_DIALOG (file_dialog)->image,
+ GTK_WIDGET (parent),
+ _("Save Image"),
+ FALSE, FALSE, NULL);
+
+ gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (other), folder);
+ gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (other), basename);
+
+ g_free (folder);
+ g_free (basename);
+ }
+}
+
+static void
+file_new_template_callback (GtkWidget *widget,
+ const gchar *name,
+ gpointer data)
+{
+ GimpTemplate *template;
+ GimpImage *image;
+
+ image = (GimpImage *) data;
+
+ if (! (name && strlen (name)))
+ name = _("(Unnamed Template)");
+
+ template = gimp_template_new (name);
+ gimp_template_set_from_image (template, image);
+ gimp_container_add (image->gimp->templates, GIMP_OBJECT (template));
+ g_object_unref (template);
+}
+
+static void
+file_revert_confirm_response (GtkWidget *dialog,
+ gint response_id,
+ GimpDisplay *display)
+{
+ GimpImage *old_image = gimp_display_get_image (display);
+
+ gtk_widget_destroy (dialog);
+
+ if (response_id == GTK_RESPONSE_OK)
+ {
+ Gimp *gimp = old_image->gimp;
+ GimpImage *new_image;
+ GFile *file;
+ GimpPDBStatusType status;
+ GError *error = NULL;
+
+ file = gimp_image_get_file (old_image);
+
+ if (! file)
+ file = gimp_image_get_imported_file (old_image);
+
+ new_image = file_open_image (gimp, gimp_get_user_context (gimp),
+ GIMP_PROGRESS (display),
+ file, file, FALSE, NULL,
+ GIMP_RUN_INTERACTIVE,
+ &status, NULL, &error);
+
+ if (new_image)
+ {
+ gimp_displays_reconnect (gimp, old_image, new_image);
+ gimp_image_flush (new_image);
+
+ /* the displays own the image now */
+ g_object_unref (new_image);
+ }
+ else if (status != GIMP_PDB_CANCEL)
+ {
+ gimp_message (gimp, G_OBJECT (display), GIMP_MESSAGE_ERROR,
+ _("Reverting to '%s' failed:\n\n%s"),
+ gimp_file_get_utf8_name (file), error->message);
+ g_clear_error (&error);
+ }
+ }
+}
diff --git a/app/actions/file-commands.h b/app/actions/file-commands.h
new file mode 100644
index 0000000..47c8750
--- /dev/null
+++ b/app/actions/file-commands.h
@@ -0,0 +1,63 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __FILE_COMMANDS_H__
+#define __FILE_COMMANDS_H__
+
+
+void file_open_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void file_open_as_layers_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void file_open_location_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void file_open_recent_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+void file_save_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void file_create_template_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+void file_revert_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void file_close_all_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void file_copy_location_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void file_show_in_file_manager_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void file_quit_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+void file_file_open_dialog (Gimp *gimp,
+ GFile *file,
+ GtkWidget *parent);
+
+
+#endif /* __FILE_COMMANDS_H__ */
diff --git a/app/actions/filters-actions.c b/app/actions/filters-actions.c
new file mode 100644
index 0000000..b20c433
--- /dev/null
+++ b/app/actions/filters-actions.c
@@ -0,0 +1,1229 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "actions-types.h"
+
+#include "core/gimp-filter-history.h"
+#include "core/gimpimage.h"
+#include "core/gimplayermask.h"
+
+#include "pdb/gimpprocedure.h"
+
+#include "widgets/gimpaction.h"
+#include "widgets/gimpactiongroup.h"
+#include "widgets/gimphelp-ids.h"
+#include "widgets/gimpuimanager.h"
+
+#include "actions.h"
+#include "filters-actions.h"
+#include "filters-commands.h"
+
+#include "gimp-intl.h"
+
+
+/* local function prototypes */
+
+static void filters_actions_set_tooltips (GimpActionGroup *group,
+ const GimpStringActionEntry *entries,
+ gint n_entries);
+static void filters_actions_history_changed (Gimp *gimp,
+ GimpActionGroup *group);
+
+
+/* private variables */
+
+static const GimpActionEntry filters_menu_actions[] =
+{
+ { "filters-menu", NULL, NC_("filters-action",
+ "Filte_rs") },
+ { "filters-recent-menu", NULL, NC_("filters-action",
+ "Recently _Used") },
+ { "filters-blur-menu", NULL, NC_("filters-action",
+ "_Blur") },
+ { "filters-noise-menu", NULL, NC_("filters-action",
+ "_Noise") },
+ { "filters-edge-detect-menu", NULL, NC_("filters-action",
+ "Edge-De_tect") },
+ { "filters-enhance-menu", NULL, NC_("filters-action",
+ "En_hance") },
+ { "filters-combine-menu", NULL, NC_("filters-action",
+ "C_ombine") },
+ { "filters-generic-menu", NULL, NC_("filters-action",
+ "_Generic") },
+ { "filters-light-shadow-menu", NULL, NC_("filters-action",
+ "_Light and Shadow") },
+ { "filters-distorts-menu", NULL, NC_("filters-action",
+ "_Distorts") },
+ { "filters-artistic-menu", NULL, NC_("filters-action",
+ "_Artistic") },
+ { "filters-decor-menu", NULL, NC_("filters-action",
+ "_Decor") },
+ { "filters-map-menu", NULL, NC_("filters-action",
+ "_Map") },
+ { "filters-render-menu", NULL, NC_("filters-action",
+ "_Render") },
+ { "filters-render-clouds-menu", NULL, NC_("filters-action",
+ "_Clouds") },
+ { "filters-render-fractals-menu", NULL, NC_("filters-action",
+ "_Fractals") },
+ { "filters-render-nature-menu", NULL, NC_("filters-action",
+ "_Nature") },
+ { "filters-render-noise-menu", NULL, NC_("filters-action",
+ "N_oise") },
+ { "filters-render-pattern-menu", NULL, NC_("filters-action",
+ "_Pattern") },
+ { "filters-web-menu", NULL, NC_("filters-action",
+ "_Web") },
+ { "filters-animation-menu", NULL, NC_("filters-action",
+ "An_imation") }
+};
+
+static const GimpStringActionEntry filters_actions[] =
+{
+ { "filters-antialias", GIMP_ICON_GEGL,
+ NC_("filters-action", "_Antialias"), NULL, NULL,
+ "gegl:antialias",
+ GIMP_HELP_FILTER_ANTIALIAS },
+
+ { "filters-color-enhance", GIMP_ICON_GEGL,
+ NC_("filters-action", "_Color Enhance"), NULL, NULL,
+ "gegl:color-enhance",
+ GIMP_HELP_FILTER_COLOR_ENHANCE },
+
+ { "filters-invert-linear", GIMP_ICON_INVERT,
+ NC_("filters-action", "L_inear Invert"), NULL, NULL,
+ "gegl:invert-linear",
+ GIMP_HELP_FILTER_INVERT_LINEAR },
+
+ { "filters-invert-perceptual", GIMP_ICON_INVERT,
+ NC_("filters-action", "In_vert"), NULL, NULL,
+ "gegl:invert-gamma",
+ GIMP_HELP_FILTER_INVERT_PERCEPTUAL },
+
+ { "filters-invert-value", GIMP_ICON_INVERT,
+ NC_("filters-action", "_Value Invert"), NULL, NULL,
+ "gegl:value-invert",
+ GIMP_HELP_FILTER_INVERT_VALUE },
+
+ { "filters-stretch-contrast-hsv", GIMP_ICON_GEGL,
+ NC_("filters-action", "_Stretch Contrast HSV"), NULL, NULL,
+ "gegl:stretch-contrast-hsv",
+ GIMP_HELP_FILTER_STRETCH_CONTRAST_HSV }
+};
+
+static const GimpStringActionEntry filters_settings_actions[] =
+{
+ { "filters-dilate", GIMP_ICON_GEGL,
+ NC_("filters-action", "_Dilate"), NULL,
+ NC_("filters-action", "Grow lighter areas of the image"),
+ "gegl:value-propagate\n"
+ "(mode white)"
+ "(lower-threshold 0.000000)"
+ "(upper-threshold 1.000000)"
+ "(rate 1.000000)"
+ "(top yes)"
+ "(left yes)"
+ "(right yes)"
+ "(bottom yes)"
+ "(value yes)"
+ "(alpha no)",
+ GIMP_HELP_FILTER_DILATE },
+
+ { "filters-erode", GIMP_ICON_GEGL,
+ NC_("filters-action", "_Erode"), NULL,
+ NC_("filters-action", "Grow darker areas of the image"),
+ "gegl:value-propagate\n"
+ "(mode black)"
+ "(lower-threshold 0.000000)"
+ "(upper-threshold 1.000000)"
+ "(rate 1.000000)"
+ "(top yes)"
+ "(left yes)"
+ "(right yes)"
+ "(bottom yes)"
+ "(value yes)"
+ "(alpha no)",
+ GIMP_HELP_FILTER_ERODE }
+};
+
+static const GimpStringActionEntry filters_interactive_actions[] =
+{
+ { "filters-alien-map", GIMP_ICON_GEGL,
+ NC_("filters-action", "_Alien Map..."), NULL, NULL,
+ "gegl:alien-map",
+ GIMP_HELP_FILTER_ALIEN_MAP },
+
+ { "filters-apply-canvas", GIMP_ICON_GEGL,
+ NC_("filters-action", "_Apply Canvas..."), NULL, NULL,
+ "gegl:texturize-canvas",
+ GIMP_HELP_FILTER_APPLY_CANVAS },
+
+ { "filters-apply-lens", GIMP_ICON_GEGL,
+ NC_("filters-action", "Apply _Lens..."), NULL, NULL,
+ "gegl:apply-lens",
+ GIMP_HELP_FILTER_APPLY_LENS },
+
+ { "filters-bayer-matrix", GIMP_ICON_GEGL,
+ NC_("filters-action", "_Bayer Matrix..."), NULL, NULL,
+ "gegl:bayer-matrix",
+ GIMP_HELP_FILTER_BAYER_MATRIX },
+
+ { "filters-bloom", GIMP_ICON_GEGL,
+ NC_("filters-action", "_Bloom..."), NULL, NULL,
+ "gegl:bloom",
+ GIMP_HELP_FILTER_BLOOM },
+
+ { "filters-brightness-contrast", GIMP_ICON_TOOL_BRIGHTNESS_CONTRAST,
+ NC_("filters-action", "B_rightness-Contrast..."), NULL, NULL,
+ "gimp:brightness-contrast",
+ GIMP_HELP_TOOL_BRIGHTNESS_CONTRAST },
+
+ { "filters-bump-map", GIMP_ICON_GEGL,
+ NC_("filters-action", "_Bump Map..."), NULL, NULL,
+ "gegl:bump-map",
+ GIMP_HELP_FILTER_BUMP_MAP },
+
+ { "filters-c2g", GIMP_ICON_GEGL,
+ NC_("filters-action", "_Color to Gray..."), NULL, NULL,
+ "gegl:c2g",
+ GIMP_HELP_FILTER_C2G },
+
+ { "filters-cartoon", GIMP_ICON_GEGL,
+ NC_("filters-action", "Ca_rtoon..."), NULL, NULL,
+ "gegl:cartoon",
+ GIMP_HELP_FILTER_CARTOON },
+
+ { "filters-channel-mixer", GIMP_ICON_GEGL,
+ NC_("filters-action", "_Channel Mixer..."), NULL, NULL,
+ "gegl:channel-mixer",
+ GIMP_HELP_FILTER_CHANNEL_MIXER },
+
+ { "filters-checkerboard", GIMP_ICON_GEGL,
+ NC_("filters-action", "_Checkerboard..."), NULL, NULL,
+ "gegl:checkerboard",
+ GIMP_HELP_FILTER_CHECKERBOARD },
+
+ { "filters-color-balance", GIMP_ICON_TOOL_COLOR_BALANCE,
+ NC_("filters-action", "Color _Balance..."), NULL, NULL,
+ "gimp:color-balance",
+ GIMP_HELP_TOOL_COLOR_BALANCE },
+
+ { "filters-color-exchange", GIMP_ICON_GEGL,
+ NC_("filters-action", "_Color Exchange..."), NULL, NULL,
+ "gegl:color-exchange",
+ GIMP_HELP_FILTER_COLOR_EXCHANGE },
+
+ { "filters-colorize", GIMP_ICON_TOOL_COLORIZE,
+ NC_("filters-action", "Colori_ze..."), NULL, NULL,
+ "gimp:colorize",
+ GIMP_HELP_TOOL_COLORIZE },
+
+ { "filters-dither", GIMP_ICON_GEGL,
+ NC_("filters-action", "Dithe_r..."), NULL, NULL,
+ "gegl:dither",
+ GIMP_HELP_FILTER_DITHER },
+
+ { "filters-color-rotate", GIMP_ICON_GEGL,
+ NC_("filters-action", "_Rotate Colors..."), NULL, NULL,
+ "gegl:color-rotate",
+ GIMP_HELP_FILTER_COLOR_ROTATE },
+
+ { "filters-color-temperature", GIMP_ICON_TOOL_COLOR_TEMPERATURE,
+ NC_("filters-action", "Color T_emperature..."), NULL, NULL,
+ "gegl:color-temperature",
+ GIMP_HELP_FILTER_COLOR_TEMPERATURE },
+
+ { "filters-color-to-alpha", GIMP_ICON_GEGL,
+ NC_("filters-action", "Color to _Alpha..."), NULL, NULL,
+ "gegl:color-to-alpha",
+ GIMP_HELP_FILTER_COLOR_TO_ALPHA },
+
+ { "filters-component-extract", GIMP_ICON_GEGL,
+ NC_("filters-action", "_Extract Component..."), NULL, NULL,
+ "gegl:component-extract",
+ GIMP_HELP_FILTER_COMPONENT_EXTRACT },
+
+ { "filters-convolution-matrix", GIMP_ICON_GEGL,
+ NC_("filters-action", "_Convolution Matrix..."), NULL, NULL,
+ "gegl:convolution-matrix",
+ GIMP_HELP_FILTER_CONVOLUTION_MATRIX },
+
+ { "filters-cubism", GIMP_ICON_GEGL,
+ NC_("filters-action", "_Cubism..."), NULL, NULL,
+ "gegl:cubism",
+ GIMP_HELP_FILTER_CUBISM },
+
+ { "filters-curves", GIMP_ICON_TOOL_CURVES,
+ NC_("filters-action", "_Curves..."), NULL, NULL,
+ "gimp:curves",
+ GIMP_HELP_TOOL_CURVES },
+
+ { "filters-deinterlace", GIMP_ICON_GEGL,
+ NC_("filters-action", "_Deinterlace..."), NULL, NULL,
+ "gegl:deinterlace",
+ GIMP_HELP_FILTER_DEINTERLACE },
+
+ { "filters-desaturate", GIMP_ICON_TOOL_DESATURATE,
+ NC_("filters-action", "_Desaturate..."), NULL, NULL,
+ "gimp:desaturate",
+ GIMP_HELP_FILTER_DESATURATE },
+
+ { "filters-difference-of-gaussians", GIMP_ICON_GEGL,
+ NC_("filters-action", "Difference of _Gaussians..."), NULL, NULL,
+ "gegl:difference-of-gaussians",
+ GIMP_HELP_FILTER_DIFFERENCE_OF_GAUSSIANS },
+
+ { "filters-diffraction-patterns", GIMP_ICON_GEGL,
+ NC_("filters-action", "D_iffraction Patterns..."), NULL, NULL,
+ "gegl:diffraction-patterns",
+ GIMP_HELP_FILTER_DIFFRACTION_PATTERNS },
+
+ { "filters-displace", GIMP_ICON_GEGL,
+ NC_("filters-action", "_Displace..."), NULL, NULL,
+ "gegl:displace",
+ GIMP_HELP_FILTER_DISPLACE },
+
+ { "filters-distance-map", GIMP_ICON_GEGL,
+ NC_("filters-action", "Distance _Map..."), NULL, NULL,
+ "gegl:distance-transform",
+ GIMP_HELP_FILTER_DISTANCE_MAP },
+
+ { "filters-dropshadow", GIMP_ICON_GEGL,
+ NC_("filters-action", "_Drop Shadow..."), NULL, NULL,
+ "gegl:dropshadow",
+ GIMP_HELP_FILTER_DROPSHADOW },
+
+ { "filters-edge", GIMP_ICON_GEGL,
+ NC_("filters-action", "_Edge..."), NULL, NULL,
+ "gegl:edge",
+ GIMP_HELP_FILTER_EDGE },
+
+ { "filters-edge-laplace", GIMP_ICON_GEGL,
+ NC_("filters-action", "_Laplace"), NULL, NULL,
+ "gegl:edge-laplace",
+ GIMP_HELP_FILTER_EDGE_LAPLACE },
+
+ { "filters-edge-neon", GIMP_ICON_GEGL,
+ NC_("filters-action", "_Neon..."), NULL, NULL,
+ "gegl:edge-neon",
+ GIMP_HELP_FILTER_EDGE_NEON },
+
+ { "filters-edge-sobel", GIMP_ICON_GEGL,
+ NC_("filters-action", "_Sobel..."), NULL, NULL,
+ "gegl:edge-sobel",
+ GIMP_HELP_FILTER_EDGE_SOBEL },
+
+ { "filters-emboss", GIMP_ICON_GEGL,
+ NC_("filters-action", "_Emboss..."), NULL, NULL,
+ "gegl:emboss",
+ GIMP_HELP_FILTER_EMBOSS },
+
+ { "filters-engrave", GIMP_ICON_GEGL,
+ NC_("filters-action", "En_grave..."), NULL, NULL,
+ "gegl:engrave",
+ GIMP_HELP_FILTER_ENGRAVE },
+
+ { "filters-exposure", GIMP_ICON_TOOL_EXPOSURE,
+ NC_("filters-action", "E_xposure..."), NULL, NULL,
+ "gegl:exposure",
+ GIMP_HELP_FILTER_EXPOSURE },
+
+ { "filters-fattal-2002", GIMP_ICON_GEGL,
+ NC_("filters-action", "_Fattal et al. 2002..."), NULL, NULL,
+ "gegl:fattal02",
+ GIMP_HELP_FILTER_FATTAL_2002 },
+
+ { "filters-focus-blur", GIMP_ICON_GEGL,
+ NC_("filters-action", "_Focus Blur..."), NULL, NULL,
+ "gegl:focus-blur",
+ GIMP_HELP_FILTER_FOCUS_BLUR },
+
+ { "filters-fractal-trace", GIMP_ICON_GEGL,
+ NC_("filters-action", "_Fractal Trace..."), NULL, NULL,
+ "gegl:fractal-trace",
+ GIMP_HELP_FILTER_FRACTAL_TRACE },
+
+ { "filters-gaussian-blur", GIMP_ICON_GEGL,
+ NC_("filters-action", "_Gaussian Blur..."), NULL, NULL,
+ "gegl:gaussian-blur",
+ GIMP_HELP_FILTER_GAUSSIAN_BLUR },
+
+ { "filters-gaussian-blur-selective", GIMP_ICON_GEGL,
+ NC_("filters-action", "_Selective Gaussian Blur..."), NULL, NULL,
+ "gegl:gaussian-blur-selective",
+ GIMP_HELP_FILTER_GAUSSIAN_BLUR_SELECTIVE },
+
+ { "filters-gegl-graph", GIMP_ICON_GEGL,
+ NC_("filters-action", "_GEGL graph..."), NULL, NULL,
+ "gegl:gegl",
+ GIMP_HELP_FILTER_GEGL_GRAPH },
+
+ { "filters-grid", GIMP_ICON_GRID,
+ NC_("filters-action", "_Grid..."), NULL, NULL,
+ "gegl:grid",
+ GIMP_HELP_FILTER_GRID },
+
+ { "filters-high-pass", GIMP_ICON_GEGL,
+ NC_("filters-action", "_High Pass..."), NULL, NULL,
+ "gegl:high-pass",
+ GIMP_HELP_FILTER_HIGH_PASS },
+
+ { "filters-hue-chroma", GIMP_ICON_GEGL,
+ NC_("filters-action", "Hue-_Chroma..."), NULL, NULL,
+ "gegl:hue-chroma",
+ GIMP_HELP_FILTER_HUE_CHROMA },
+
+ { "filters-hue-saturation", GIMP_ICON_TOOL_HUE_SATURATION,
+ NC_("filters-action", "Hue-_Saturation..."), NULL, NULL,
+ "gimp:hue-saturation",
+ GIMP_HELP_TOOL_HUE_SATURATION },
+
+ { "filters-illusion", GIMP_ICON_GEGL,
+ NC_("filters-action", "_Illusion..."), NULL, NULL,
+ "gegl:illusion",
+ GIMP_HELP_FILTER_ILLUSION },
+
+ { "filters-image-gradient", GIMP_ICON_GEGL,
+ NC_("filters-action", "_Image Gradient..."), NULL, NULL,
+ "gegl:image-gradient",
+ GIMP_HELP_FILTER_IMAGE_GRADIENT },
+
+ { "filters-kaleidoscope", GIMP_ICON_GEGL,
+ NC_("filters-action", "_Kaleidoscope..."), NULL, NULL,
+ "gegl:mirrors",
+ GIMP_HELP_FILTER_KALEIDOSCOPE },
+
+ { "filters-lens-blur", GIMP_ICON_GEGL,
+ NC_("filters-action", "Le_ns Blur..."), NULL, NULL,
+ "gegl:lens-blur",
+ GIMP_HELP_FILTER_LENS_BLUR },
+
+ { "filters-lens-distortion", GIMP_ICON_GEGL,
+ NC_("filters-action", "Le_ns Distortion..."), NULL, NULL,
+ "gegl:lens-distortion",
+ GIMP_HELP_FILTER_LENS_DISTORTION },
+
+ { "filters-lens-flare", GIMP_ICON_GEGL,
+ NC_("filters-action", "Lens _Flare..."), NULL, NULL,
+ "gegl:lens-flare",
+ GIMP_HELP_FILTER_LENS_FLARE },
+
+ { "filters-levels", GIMP_ICON_TOOL_LEVELS,
+ NC_("filters-action", "_Levels..."), NULL, NULL,
+ "gimp:levels",
+ GIMP_HELP_TOOL_LEVELS },
+
+ { "filters-linear-sinusoid", GIMP_ICON_TOOL_LEVELS,
+ NC_("filters-action", "_Linear Sinusoid..."), NULL, NULL,
+ "gegl:linear-sinusoid",
+ GIMP_HELP_FILTER_LINEAR_SINUSOID },
+
+ { "filters-little-planet", GIMP_ICON_GEGL,
+ NC_("filters-action", "_Little Planet..."), NULL, NULL,
+ "gegl:stereographic-projection",
+ GIMP_HELP_FILTER_LITTLE_PLANET },
+
+ { "filters-long-shadow", GIMP_ICON_GEGL,
+ NC_("filters-action", "_Long Shadow..."), NULL, NULL,
+ "gegl:long-shadow",
+ GIMP_HELP_FILTER_LONG_SHADOW },
+
+ { "filters-mantiuk-2006", GIMP_ICON_GEGL,
+ NC_("filters-action", "_Mantiuk 2006..."), NULL, NULL,
+ "gegl:mantiuk06",
+ GIMP_HELP_FILTER_MANTIUK_2006 },
+
+ { "filters-maze", GIMP_ICON_GEGL,
+ NC_("filters-action", "_Maze..."), NULL, NULL,
+ "gegl:maze",
+ GIMP_HELP_FILTER_MAZE },
+
+ { "filters-mean-curvature-blur", GIMP_ICON_GEGL,
+ NC_("filters-action", "Mean C_urvature Blur..."), NULL, NULL,
+ "gegl:mean-curvature-blur",
+ GIMP_HELP_FILTER_MEAN_CURVATURE_BLUR },
+
+ { "filters-median-blur", GIMP_ICON_GEGL,
+ NC_("filters-action", "_Median Blur..."), NULL, NULL,
+ "gegl:median-blur",
+ GIMP_HELP_FILTER_MEDIAN_BLUR },
+
+ { "filters-mono-mixer", GIMP_ICON_GEGL,
+ NC_("filters-action", "_Mono Mixer..."), NULL, NULL,
+ "gegl:mono-mixer",
+ GIMP_HELP_FILTER_MONO_MIXER },
+
+ { "filters-mosaic", GIMP_ICON_GEGL,
+ NC_("filters-action", "_Mosaic..."), NULL, NULL,
+ "gegl:mosaic",
+ GIMP_HELP_FILTER_MOSAIC },
+
+ { "filters-motion-blur-circular", GIMP_ICON_GEGL,
+ NC_("filters-action", "_Circular Motion Blur..."), NULL, NULL,
+ "gegl:motion-blur-circular",
+ GIMP_HELP_FILTER_MOTION_BLUR_CIRCULAR },
+
+ { "filters-motion-blur-linear", GIMP_ICON_GEGL,
+ NC_("filters-action", "_Linear Motion Blur..."), NULL, NULL,
+ "gegl:motion-blur-linear",
+ GIMP_HELP_FILTER_MOTION_BLUR_LINEAR },
+
+ { "filters-motion-blur-zoom", GIMP_ICON_GEGL,
+ NC_("filters-action", "_Zoom Motion Blur..."), NULL, NULL,
+ "gegl:motion-blur-zoom",
+ GIMP_HELP_FILTER_MOTION_BLUR_ZOOM },
+
+ { "filters-noise-cell", GIMP_ICON_GEGL,
+ NC_("filters-action", "_Cell Noise..."), NULL, NULL,
+ "gegl:cell-noise",
+ GIMP_HELP_FILTER_NOISE_CELL },
+
+ { "filters-newsprint", GIMP_ICON_GEGL,
+ NC_("filters-action", "_Newsprint..."), NULL, NULL,
+ "gegl:newsprint",
+ GIMP_HELP_FILTER_NEWSPRINT },
+
+ { "filters-noise-cie-lch", GIMP_ICON_GEGL,
+ NC_("filters-action", "_CIE lch Noise..."), NULL, NULL,
+ "gegl:noise-cie-lch",
+ GIMP_HELP_FILTER_NOISE_CIE_LCH },
+
+ { "filters-noise-hsv", GIMP_ICON_GEGL,
+ NC_("filters-action", "HS_V Noise..."), NULL, NULL,
+ "gegl:noise-hsv",
+ GIMP_HELP_FILTER_NOISE_HSV },
+
+ { "filters-noise-hurl", GIMP_ICON_GEGL,
+ NC_("filters-action", "_Hurl..."), NULL, NULL,
+ "gegl:noise-hurl",
+ GIMP_HELP_FILTER_NOISE_HURL },
+
+ { "filters-noise-perlin", GIMP_ICON_GEGL,
+ NC_("filters-action", "Perlin _Noise..."), NULL, NULL,
+ "gegl:perlin-noise",
+ GIMP_HELP_FILTER_NOISE_PERLIN },
+
+ { "filters-noise-pick", GIMP_ICON_GEGL,
+ NC_("filters-action", "_Pick..."), NULL, NULL,
+ "gegl:noise-pick",
+ GIMP_HELP_FILTER_NOISE_PICK },
+
+ { "filters-noise-rgb", GIMP_ICON_GEGL,
+ NC_("filters-action", "_RGB Noise..."), NULL, NULL,
+ "gegl:noise-rgb",
+ GIMP_HELP_FILTER_NOISE_RGB },
+
+ { "filters-noise-reduction", GIMP_ICON_GEGL,
+ NC_("filters-action", "Noise R_eduction..."), NULL, NULL,
+ "gegl:noise-reduction",
+ GIMP_HELP_FILTER_NOISE_REDUCTION },
+
+ { "filters-noise-simplex", GIMP_ICON_GEGL,
+ NC_("filters-action", "_Simplex Noise..."), NULL, NULL,
+ "gegl:simplex-noise",
+ GIMP_HELP_FILTER_NOISE_SIMPLEX },
+
+ { "filters-noise-slur", GIMP_ICON_GEGL,
+ NC_("filters-action", "_Slur..."), NULL, NULL,
+ "gegl:noise-slur",
+ GIMP_HELP_FILTER_NOISE_SLUR },
+
+ { "filters-noise-solid", GIMP_ICON_GEGL,
+ NC_("filters-action", "_Solid Noise..."), NULL, NULL,
+ "gegl:noise-solid",
+ GIMP_HELP_FILTER_NOISE_SOLID },
+
+ { "filters-noise-spread", GIMP_ICON_GEGL,
+ NC_("filters-action", "Sp_read..."), NULL, NULL,
+ "gegl:noise-spread",
+ GIMP_HELP_FILTER_NOISE_SPREAD },
+
+ { "filters-normal-map", GIMP_ICON_GEGL,
+ NC_("filters-action", "_Normal Map..."), NULL, NULL,
+ "gegl:normal-map",
+ GIMP_HELP_FILTER_NORMAL_MAP },
+
+ { "filters-offset", GIMP_ICON_TOOL_OFFSET,
+ NC_("filters-action", "_Offset..."), "<primary><shift>O", NULL,
+ "gimp:offset",
+ GIMP_HELP_TOOL_OFFSET },
+
+ { "filters-oilify", GIMP_ICON_GEGL,
+ NC_("filters-action", "Oili_fy..."), NULL, NULL,
+ "gegl:oilify",
+ GIMP_HELP_FILTER_OILIFY },
+
+ { "filters-panorama-projection", GIMP_ICON_GEGL,
+ NC_("filters-action", "_Panorama Projection..."), NULL, NULL,
+ "gegl:panorama-projection",
+ GIMP_HELP_FILTER_PANORAMA_PROJECTION },
+
+ { "filters-photocopy", GIMP_ICON_GEGL,
+ NC_("filters-action", "_Photocopy..."), NULL, NULL,
+ "gegl:photocopy",
+ GIMP_HELP_FILTER_PHOTOCOPY },
+
+ { "filters-pixelize", GIMP_ICON_GEGL,
+ NC_("filters-action", "_Pixelize..."), NULL, NULL,
+ "gegl:pixelize",
+ GIMP_HELP_FILTER_PIXELIZE },
+
+ { "filters-plasma", GIMP_ICON_GEGL,
+ NC_("filters-action", "_Plasma..."), NULL, NULL,
+ "gegl:plasma",
+ GIMP_HELP_FILTER_PLASMA },
+
+ { "filters-polar-coordinates", GIMP_ICON_GEGL,
+ NC_("filters-action", "P_olar Coordinates..."), NULL, NULL,
+ "gegl:polar-coordinates",
+ GIMP_HELP_FILTER_POLAR_COORDINATES },
+
+ { "filters-posterize", GIMP_ICON_TOOL_POSTERIZE,
+ NC_("filters-action", "_Posterize..."), NULL, NULL,
+ "gimp:posterize",
+ GIMP_HELP_FILTER_POSTERIZE },
+
+ { "filters-recursive-transform", GIMP_ICON_GEGL,
+ NC_("filters-action", "_Recursive Transform..."), NULL, NULL,
+ "gegl:recursive-transform",
+ GIMP_HELP_FILTER_RECURSIVE_TRANSFORM },
+
+ { "filters-red-eye-removal", GIMP_ICON_GEGL,
+ NC_("filters-action", "_Red Eye Removal..."), NULL, NULL,
+ "gegl:red-eye-removal",
+ GIMP_HELP_FILTER_RED_EYE_REMOVAL },
+
+ { "filters-reinhard-2005", GIMP_ICON_GEGL,
+ NC_("filters-action", "_Reinhard 2005..."), NULL, NULL,
+ "gegl:reinhard05",
+ GIMP_HELP_FILTER_REINHARD_2005 },
+
+ { "filters-rgb-clip", GIMP_ICON_GEGL,
+ NC_("filters-action", "RGB _Clip..."), NULL, NULL,
+ "gegl:rgb-clip",
+ GIMP_HELP_FILTER_RGB_CLIP },
+
+ { "filters-ripple", GIMP_ICON_GEGL,
+ NC_("filters-action", "_Ripple..."), NULL, NULL,
+ "gegl:ripple",
+ GIMP_HELP_FILTER_RIPPLE },
+
+ { "filters-saturation", GIMP_ICON_GEGL,
+ NC_("filters-action", "Sat_uration..."), NULL, NULL,
+ "gegl:saturation",
+ GIMP_HELP_FILTER_SATURATION },
+
+ { "filters-semi-flatten", GIMP_ICON_GEGL,
+ NC_("filters-action", "_Semi-Flatten..."), NULL, NULL,
+ "gimp:semi-flatten",
+ GIMP_HELP_FILTER_SEMI_FLATTEN },
+
+ { "filters-sepia", GIMP_ICON_GEGL,
+ NC_("filters-action", "_Sepia..."), NULL, NULL,
+ "gegl:sepia",
+ GIMP_HELP_FILTER_SEPIA },
+
+ { "filters-shadows-highlights", GIMP_ICON_TOOL_SHADOWS_HIGHLIGHTS,
+ NC_("filters-action", "S_hadows-Highlights..."), NULL, NULL,
+ "gegl:shadows-highlights",
+ GIMP_HELP_FILTER_SHADOWS_HIGHLIGHTS },
+
+ { "filters-shift", GIMP_ICON_GEGL,
+ NC_("filters-action", "_Shift..."), NULL, NULL,
+ "gegl:shift",
+ GIMP_HELP_FILTER_SHIFT },
+
+ { "filters-sinus", GIMP_ICON_GEGL,
+ NC_("filters-action", "_Sinus..."), NULL, NULL,
+ "gegl:sinus",
+ GIMP_HELP_FILTER_SINUS },
+
+ { "filters-slic", GIMP_ICON_GEGL,
+ NC_("filters-action", "_Simple Linear Iterative Clustering..."), NULL, NULL,
+ "gegl:slic",
+ GIMP_HELP_FILTER_SLIC },
+
+ { "filters-snn-mean", GIMP_ICON_GEGL,
+ NC_("filters-action", "_Symmetric Nearest Neighbor..."), NULL, NULL,
+ "gegl:snn-mean",
+ GIMP_HELP_FILTER_SNN_MEAN },
+
+ { "filters-softglow", GIMP_ICON_GEGL,
+ NC_("filters-action", "_Softglow..."), NULL, NULL,
+ "gegl:softglow",
+ GIMP_HELP_FILTER_SOFTGLOW },
+
+ { "filters-spherize", GIMP_ICON_GEGL,
+ NC_("filters-action", "Spheri_ze..."), NULL, NULL,
+ "gegl:spherize",
+ GIMP_HELP_FILTER_SPHERIZE },
+
+ { "filters-spiral", GIMP_ICON_GEGL,
+ NC_("filters-action", "S_piral..."), NULL, NULL,
+ "gegl:spiral",
+ GIMP_HELP_FILTER_SPIRAL },
+
+ { "filters-stretch-contrast", GIMP_ICON_GEGL,
+ NC_("filters-action", "_Stretch Contrast..."), NULL, NULL,
+ "gegl:stretch-contrast",
+ GIMP_HELP_FILTER_STRETCH_CONTRAST },
+
+ { "filters-stress", GIMP_ICON_GEGL,
+ NC_("filters-action", "_Stress..."), NULL, NULL,
+ "gegl:stress",
+ GIMP_HELP_FILTER_STRESS },
+
+ { "filters-supernova", GIMP_ICON_GEGL,
+ NC_("filters-action", "Super_nova..."), NULL, NULL,
+ "gegl:supernova",
+ GIMP_HELP_FILTER_SUPERNOVA },
+
+ { "filters-threshold", GIMP_ICON_TOOL_THRESHOLD,
+ NC_("filters-action", "_Threshold..."), NULL, NULL,
+ "gimp:threshold",
+ GIMP_HELP_TOOL_THRESHOLD },
+
+ { "filters-threshold-alpha", GIMP_ICON_GEGL,
+ NC_("filters-action", "_Threshold Alpha..."), NULL, NULL,
+ "gimp:threshold-alpha",
+ GIMP_HELP_FILTER_THRESHOLD_ALPHA },
+
+ { "filters-tile-glass", GIMP_ICON_GEGL,
+ NC_("filters-action", "_Glass Tile..."), NULL, NULL,
+ "gegl:tile-glass",
+ GIMP_HELP_FILTER_TILE_GLASS },
+
+ { "filters-tile-paper", GIMP_ICON_GEGL,
+ NC_("filters-action", "_Paper Tile..."), NULL, NULL,
+ "gegl:tile-paper",
+ GIMP_HELP_FILTER_TILE_PAPER },
+
+ { "filters-tile-seamless", GIMP_ICON_GEGL,
+ NC_("filters-action", "_Tile Seamless..."), NULL, NULL,
+ "gegl:tile-seamless",
+ GIMP_HELP_FILTER_TILE_SEAMLESS },
+
+ { "filters-unsharp-mask", GIMP_ICON_GEGL,
+ NC_("filters-action", "Sharpen (_Unsharp Mask)..."), NULL, NULL,
+ "gegl:unsharp-mask",
+ GIMP_HELP_FILTER_UNSHARP_MASK },
+
+ { "filters-value-propagate", GIMP_ICON_GEGL,
+ NC_("filters-action", "_Value Propagate..."), NULL, NULL,
+ "gegl:value-propagate",
+ GIMP_HELP_FILTER_VALUE_PROPAGATE },
+
+ { "filters-variable-blur", GIMP_ICON_GEGL,
+ NC_("filters-action", "_Variable Blur..."), NULL, NULL,
+ "gegl:variable-blur",
+ GIMP_HELP_FILTER_VARIABLE_BLUR },
+
+ { "filters-video-degradation", GIMP_ICON_GEGL,
+ NC_("filters-action", "Vi_deo Degradation..."), NULL, NULL,
+ "gegl:video-degradation",
+ GIMP_HELP_FILTER_VIDEO_DEGRADATION },
+
+ { "filters-vignette", GIMP_ICON_GEGL,
+ NC_("filters-action", "_Vignette..."), NULL, NULL,
+ "gegl:vignette",
+ GIMP_HELP_FILTER_VIGNETTE },
+
+ { "filters-waterpixels", GIMP_ICON_GEGL,
+ NC_("filters-action", "_Waterpixels..."), NULL, NULL,
+ "gegl:waterpixels",
+ GIMP_HELP_FILTER_WATERPIXELS },
+
+ { "filters-waves", GIMP_ICON_GEGL,
+ NC_("filters-action", "_Waves..."), NULL, NULL,
+ "gegl:waves",
+ GIMP_HELP_FILTER_WAVES },
+
+ { "filters-whirl-pinch", GIMP_ICON_GEGL,
+ NC_("filters-action", "W_hirl and Pinch..."), NULL, NULL,
+ "gegl:whirl-pinch",
+ GIMP_HELP_FILTER_WHIRL_PINCH },
+
+ { "filters-wind", GIMP_ICON_GEGL,
+ NC_("filters-action", "W_ind..."), NULL, NULL,
+ "gegl:wind",
+ GIMP_HELP_FILTER_WIND }
+};
+
+static const GimpEnumActionEntry filters_repeat_actions[] =
+{
+ { "filters-repeat", GIMP_ICON_SYSTEM_RUN,
+ NC_("filters-action", "Re_peat Last"), "<primary>F",
+ NC_("filters-action",
+ "Rerun the last used filter using the same settings"),
+ GIMP_RUN_WITH_LAST_VALS, FALSE,
+ GIMP_HELP_FILTER_REPEAT },
+
+ { "filters-reshow", GIMP_ICON_DIALOG_RESHOW_FILTER,
+ NC_("filters-action", "R_e-Show Last"), "<primary><shift>F",
+ NC_("filters-action", "Show the last used filter dialog again"),
+ GIMP_RUN_INTERACTIVE, FALSE,
+ GIMP_HELP_FILTER_RESHOW }
+};
+
+
+void
+filters_actions_setup (GimpActionGroup *group)
+{
+ GimpProcedureActionEntry *entries;
+ gint n_entries;
+ gint i;
+
+ gimp_action_group_add_actions (group, "filters-action",
+ filters_menu_actions,
+ G_N_ELEMENTS (filters_menu_actions));
+
+ gimp_action_group_add_string_actions (group, "filters-action",
+ filters_actions,
+ G_N_ELEMENTS (filters_actions),
+ filters_apply_cmd_callback);
+ filters_actions_set_tooltips (group, filters_actions,
+ G_N_ELEMENTS (filters_actions));
+
+ gimp_action_group_add_string_actions (group, "filters-action",
+ filters_settings_actions,
+ G_N_ELEMENTS (filters_settings_actions),
+ filters_apply_cmd_callback);
+ filters_actions_set_tooltips (group, filters_settings_actions,
+ G_N_ELEMENTS (filters_settings_actions));
+
+ gimp_action_group_add_string_actions (group, "filters-action",
+ filters_interactive_actions,
+ G_N_ELEMENTS (filters_interactive_actions),
+ filters_apply_interactive_cmd_callback);
+ filters_actions_set_tooltips (group, filters_interactive_actions,
+ G_N_ELEMENTS (filters_interactive_actions));
+
+ gimp_action_group_add_enum_actions (group, "filters-action",
+ filters_repeat_actions,
+ G_N_ELEMENTS (filters_repeat_actions),
+ filters_repeat_cmd_callback);
+
+ n_entries = gimp_filter_history_size (group->gimp);
+
+ entries = g_new0 (GimpProcedureActionEntry, n_entries);
+
+ for (i = 0; i < n_entries; i++)
+ {
+ entries[i].name = g_strdup_printf ("filters-recent-%02d", i + 1);
+ entries[i].icon_name = NULL;
+ entries[i].label = "";
+ entries[i].accelerator = "";
+ entries[i].tooltip = NULL;
+ entries[i].procedure = NULL;
+ entries[i].help_id = GIMP_HELP_FILTER_RESHOW;
+ }
+
+ gimp_action_group_add_procedure_actions (group, entries, n_entries,
+ filters_history_cmd_callback);
+
+ for (i = 0; i < n_entries; i++)
+ {
+ gimp_action_group_set_action_visible (group, entries[i].name, FALSE);
+ g_free ((gchar *) entries[i].name);
+ }
+
+ g_free (entries);
+
+ g_signal_connect_object (group->gimp, "filter-history-changed",
+ G_CALLBACK (filters_actions_history_changed),
+ group, 0);
+
+ filters_actions_history_changed (group->gimp, group);
+}
+
+void
+filters_actions_update (GimpActionGroup *group,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpDrawable *drawable = NULL;
+ gboolean writable = FALSE;
+ gboolean gray = FALSE;
+ gboolean alpha = FALSE;
+ gboolean supports_alpha = FALSE;
+
+ image = action_data_get_image (data);
+
+ if (image)
+ {
+ drawable = gimp_image_get_active_drawable (image);
+
+ if (drawable)
+ {
+ GimpItem *item;
+
+ gray = gimp_drawable_is_gray (drawable);
+ alpha = gimp_drawable_has_alpha (drawable);
+ supports_alpha = gimp_drawable_supports_alpha (drawable);
+
+ if (GIMP_IS_LAYER_MASK (drawable))
+ item = GIMP_ITEM (gimp_layer_mask_get_layer (GIMP_LAYER_MASK (drawable)));
+ else
+ item = GIMP_ITEM (drawable);
+
+ writable = ! gimp_item_is_content_locked (item);
+
+ if (gimp_viewable_get_children (GIMP_VIEWABLE (drawable)))
+ writable = FALSE;
+ }
+ }
+
+#define SET_SENSITIVE(action,condition) \
+ gimp_action_group_set_action_sensitive (group, action, (condition) != 0)
+
+ SET_SENSITIVE ("filters-alien-map", writable);
+ SET_SENSITIVE ("filters-antialias", writable);
+ SET_SENSITIVE ("filters-apply-canvas", writable);
+ SET_SENSITIVE ("filters-apply-lens", writable);
+ SET_SENSITIVE ("filters-bayer-matrix", writable);
+ SET_SENSITIVE ("filters-bloom", writable);
+ SET_SENSITIVE ("filters-brightness-contrast", writable);
+ SET_SENSITIVE ("filters-bump-map", writable);
+ SET_SENSITIVE ("filters-c2g", writable && !gray);
+ SET_SENSITIVE ("filters-cartoon", writable);
+ SET_SENSITIVE ("filters-channel-mixer", writable);
+ SET_SENSITIVE ("filters-checkerboard", writable);
+ SET_SENSITIVE ("filters-color-balance", writable && !gray);
+ SET_SENSITIVE ("filters-color-enhance", writable && !gray);
+ SET_SENSITIVE ("filters-color-exchange", writable);
+ SET_SENSITIVE ("filters-colorize", writable && !gray);
+ SET_SENSITIVE ("filters-dither", writable);
+ SET_SENSITIVE ("filters-color-rotate", writable);
+ SET_SENSITIVE ("filters-color-temperature", writable && !gray);
+ SET_SENSITIVE ("filters-color-to-alpha", writable && supports_alpha);
+ SET_SENSITIVE ("filters-component-extract", writable);
+ SET_SENSITIVE ("filters-convolution-matrix", writable);
+ SET_SENSITIVE ("filters-cubism", writable);
+ SET_SENSITIVE ("filters-curves", writable);
+ SET_SENSITIVE ("filters-deinterlace", writable);
+ SET_SENSITIVE ("filters-desaturate", writable && !gray);
+ SET_SENSITIVE ("filters-difference-of-gaussians", writable);
+ SET_SENSITIVE ("filters-diffraction-patterns", writable);
+ SET_SENSITIVE ("filters-dilate", writable);
+ SET_SENSITIVE ("filters-displace", writable);
+ SET_SENSITIVE ("filters-distance-map", writable);
+ SET_SENSITIVE ("filters-dropshadow", writable && alpha);
+ SET_SENSITIVE ("filters-edge", writable);
+ SET_SENSITIVE ("filters-edge-laplace", writable);
+ SET_SENSITIVE ("filters-edge-neon", writable);
+ SET_SENSITIVE ("filters-edge-sobel", writable);
+ SET_SENSITIVE ("filters-emboss", writable);
+ SET_SENSITIVE ("filters-engrave", writable);
+ SET_SENSITIVE ("filters-erode", writable);
+ SET_SENSITIVE ("filters-exposure", writable);
+ SET_SENSITIVE ("filters-fattal-2002", writable);
+ SET_SENSITIVE ("filters-focus-blur", writable);
+ SET_SENSITIVE ("filters-fractal-trace", writable);
+ SET_SENSITIVE ("filters-gaussian-blur", writable);
+ SET_SENSITIVE ("filters-gaussian-blur-selective", writable);
+ SET_SENSITIVE ("filters-gegl-graph", writable);
+ SET_SENSITIVE ("filters-grid", writable);
+ SET_SENSITIVE ("filters-high-pass", writable);
+ SET_SENSITIVE ("filters-hue-chroma", writable);
+ SET_SENSITIVE ("filters-hue-saturation", writable && !gray);
+ SET_SENSITIVE ("filters-illusion", writable);
+ SET_SENSITIVE ("filters-invert-linear", writable);
+ SET_SENSITIVE ("filters-invert-perceptual", writable);
+ SET_SENSITIVE ("filters-invert-value", writable);
+ SET_SENSITIVE ("filters-image-gradient", writable);
+ SET_SENSITIVE ("filters-kaleidoscope", writable);
+ SET_SENSITIVE ("filters-lens-blur", writable);
+ SET_SENSITIVE ("filters-lens-distortion", writable);
+ SET_SENSITIVE ("filters-lens-flare", writable);
+ SET_SENSITIVE ("filters-levels", writable);
+ SET_SENSITIVE ("filters-linear-sinusoid", writable);
+ SET_SENSITIVE ("filters-little-planet", writable);
+ SET_SENSITIVE ("filters-long-shadow", writable && alpha);
+ SET_SENSITIVE ("filters-mantiuk-2006", writable);
+ SET_SENSITIVE ("filters-maze", writable);
+ SET_SENSITIVE ("filters-mean-curvature-blur", writable);
+ SET_SENSITIVE ("filters-median-blur", writable);
+ SET_SENSITIVE ("filters-mono-mixer", writable && !gray);
+ SET_SENSITIVE ("filters-mosaic", writable);
+ SET_SENSITIVE ("filters-motion-blur-circular", writable);
+ SET_SENSITIVE ("filters-motion-blur-linear", writable);
+ SET_SENSITIVE ("filters-motion-blur-zoom", writable);
+ SET_SENSITIVE ("filters-newsprint", writable);
+ SET_SENSITIVE ("filters-noise-cell", writable);
+ SET_SENSITIVE ("filters-noise-cie-lch", writable);
+ SET_SENSITIVE ("filters-noise-hsv", writable && !gray);
+ SET_SENSITIVE ("filters-noise-hurl", writable);
+ SET_SENSITIVE ("filters-noise-perlin", writable);
+ SET_SENSITIVE ("filters-noise-pick", writable);
+ SET_SENSITIVE ("filters-noise-reduction", writable);
+ SET_SENSITIVE ("filters-noise-rgb", writable);
+ SET_SENSITIVE ("filters-noise-simplex", writable);
+ SET_SENSITIVE ("filters-noise-slur", writable);
+ SET_SENSITIVE ("filters-noise-solid", writable);
+ SET_SENSITIVE ("filters-noise-spread", writable);
+ SET_SENSITIVE ("filters-normal-map", writable);
+ SET_SENSITIVE ("filters-offset", writable);
+ SET_SENSITIVE ("filters-oilify", writable);
+ SET_SENSITIVE ("filters-panorama-projection", writable);
+ SET_SENSITIVE ("filters-photocopy", writable);
+ SET_SENSITIVE ("filters-pixelize", writable);
+ SET_SENSITIVE ("filters-plasma", writable);
+ SET_SENSITIVE ("filters-polar-coordinates", writable);
+ SET_SENSITIVE ("filters-posterize", writable);
+ SET_SENSITIVE ("filters-recursive-transform", writable);
+ SET_SENSITIVE ("filters-red-eye-removal", writable && !gray);
+ SET_SENSITIVE ("filters-reinhard-2005", writable);
+ SET_SENSITIVE ("filters-rgb-clip", writable);
+ SET_SENSITIVE ("filters-ripple", writable);
+ SET_SENSITIVE ("filters-saturation", writable && !gray);
+ SET_SENSITIVE ("filters-semi-flatten", writable && alpha);
+ SET_SENSITIVE ("filters-sepia", writable && !gray);
+ SET_SENSITIVE ("filters-shadows-highlights", writable);
+ SET_SENSITIVE ("filters-shift", writable);
+ SET_SENSITIVE ("filters-sinus", writable);
+ SET_SENSITIVE ("filters-slic", writable);
+ SET_SENSITIVE ("filters-snn-mean", writable);
+ SET_SENSITIVE ("filters-softglow", writable);
+ SET_SENSITIVE ("filters-spherize", writable);
+ SET_SENSITIVE ("filters-spiral", writable);
+ SET_SENSITIVE ("filters-stretch-contrast", writable);
+ SET_SENSITIVE ("filters-stretch-contrast-hsv", writable);
+ SET_SENSITIVE ("filters-stress", writable);
+ SET_SENSITIVE ("filters-supernova", writable);
+ SET_SENSITIVE ("filters-threshold", writable);
+ SET_SENSITIVE ("filters-threshold-alpha", writable && alpha);
+ SET_SENSITIVE ("filters-tile-glass", writable);
+ SET_SENSITIVE ("filters-tile-paper", writable);
+ SET_SENSITIVE ("filters-tile-seamless", writable);
+ SET_SENSITIVE ("filters-unsharp-mask", writable);
+ SET_SENSITIVE ("filters-value-propagate", writable);
+ SET_SENSITIVE ("filters-variable-blur", writable);
+ SET_SENSITIVE ("filters-video-degradation", writable);
+ SET_SENSITIVE ("filters-vignette", writable);
+ SET_SENSITIVE ("filters-waterpixels", writable);
+ SET_SENSITIVE ("filters-waves", writable);
+ SET_SENSITIVE ("filters-whirl-pinch", writable);
+ SET_SENSITIVE ("filters-wind", writable);
+
+#undef SET_SENSITIVE
+
+ {
+ GimpProcedure *proc = gimp_filter_history_nth (group->gimp, 0);
+ gint i;
+
+ if (proc &&
+ gimp_procedure_get_sensitive (proc, GIMP_OBJECT (drawable), NULL))
+ {
+ gimp_action_group_set_action_sensitive (group, "filters-repeat", TRUE);
+ gimp_action_group_set_action_sensitive (group, "filters-reshow", TRUE);
+ }
+ else
+ {
+ gimp_action_group_set_action_sensitive (group, "filters-repeat", FALSE);
+ gimp_action_group_set_action_sensitive (group, "filters-reshow", FALSE);
+ }
+
+ for (i = 0; i < gimp_filter_history_length (group->gimp); i++)
+ {
+ gchar *name = g_strdup_printf ("filters-recent-%02d", i + 1);
+ gboolean sensitive;
+
+ proc = gimp_filter_history_nth (group->gimp, i);
+
+ sensitive = gimp_procedure_get_sensitive (proc, GIMP_OBJECT (drawable),
+ NULL);
+
+ gimp_action_group_set_action_sensitive (group, name, sensitive);
+
+ g_free (name);
+ }
+ }
+}
+
+static void
+filters_actions_set_tooltips (GimpActionGroup *group,
+ const GimpStringActionEntry *entries,
+ gint n_entries)
+{
+ gint i;
+
+ for (i = 0; i < n_entries; i++)
+ {
+ const GimpStringActionEntry *entry = entries + i;
+ const gchar *description;
+
+ description = gegl_operation_get_key (entry->value, "description");
+
+ if (description)
+ gimp_action_group_set_action_tooltip (group, entry->name,
+ description);
+ }
+}
+
+static GimpActionGroup *
+filters_actions_get_plug_in_group (GimpActionGroup *group)
+{
+ GList *list;
+
+ for (list = gimp_ui_managers_from_name ("<Image>");
+ list;
+ list = g_list_next (list))
+ {
+ GimpUIManager *manager = list->data;
+
+ /* if this is our UI manager */
+ if (gimp_ui_manager_get_action_group (manager, "filters") == group)
+ return gimp_ui_manager_get_action_group (manager, "plug-in");
+ }
+
+ /* this happens during initial UI manager construction */
+ return NULL;
+}
+
+static void
+filters_actions_history_changed (Gimp *gimp,
+ GimpActionGroup *group)
+{
+ GimpProcedure *proc;
+ GimpActionGroup *plug_in_group;
+ gint i;
+
+ plug_in_group = filters_actions_get_plug_in_group (group);
+
+ proc = gimp_filter_history_nth (gimp, 0);
+
+ if (proc)
+ {
+ GimpAction *actual_action = NULL;
+ const gchar *label;
+ gchar *repeat;
+ gchar *reshow;
+ gboolean sensitive = FALSE;
+
+ label = gimp_procedure_get_label (proc);
+
+ repeat = g_strdup_printf (_("Re_peat \"%s\""), label);
+ reshow = g_strdup_printf (_("R_e-Show \"%s\""), label);
+
+ gimp_action_group_set_action_label (group, "filters-repeat", repeat);
+ gimp_action_group_set_action_label (group, "filters-reshow", reshow);
+
+ g_free (repeat);
+ g_free (reshow);
+
+ if (g_str_has_prefix (gimp_object_get_name (proc), "filters-"))
+ {
+ actual_action =
+ gimp_action_group_get_action (group,
+ gimp_object_get_name (proc));
+ }
+ else if (plug_in_group)
+ {
+ /* copy the sensitivity of the plug-in procedure's actual
+ * action instead of calling filters_actions_update()
+ * because doing the latter would set the sensitivity of
+ * this image's action on all images' actions. See bug
+ * #517683.
+ */
+ actual_action =
+ gimp_action_group_get_action (plug_in_group,
+ gimp_object_get_name (proc));
+ }
+
+ if (actual_action)
+ sensitive = gimp_action_get_sensitive (actual_action);
+
+ gimp_action_group_set_action_sensitive (group, "filters-repeat",
+ sensitive);
+ gimp_action_group_set_action_sensitive (group, "filters-reshow",
+ sensitive);
+ }
+ else
+ {
+ gimp_action_group_set_action_label (group, "filters-repeat",
+ _("Repeat Last"));
+ gimp_action_group_set_action_label (group, "filters-reshow",
+ _("Re-Show Last"));
+
+ gimp_action_group_set_action_sensitive (group, "filters-repeat", FALSE);
+ gimp_action_group_set_action_sensitive (group, "filters-reshow", FALSE);
+ }
+
+ for (i = 0; i < gimp_filter_history_length (gimp); i++)
+ {
+ GimpAction *action;
+ GimpAction *actual_action = NULL;
+ const gchar *label;
+ gchar *name;
+ gboolean sensitive = FALSE;
+
+ name = g_strdup_printf ("filters-recent-%02d", i + 1);
+ action = gimp_action_group_get_action (group, name);
+ g_free (name);
+
+ proc = gimp_filter_history_nth (gimp, i);
+
+ label = gimp_procedure_get_menu_label (proc);
+
+ if (g_str_has_prefix (gimp_object_get_name (proc), "filters-"))
+ {
+ actual_action =
+ gimp_action_group_get_action (group,
+ gimp_object_get_name (proc));
+ }
+ else if (plug_in_group)
+ {
+ /* see comment above */
+ actual_action =
+ gimp_action_group_get_action (plug_in_group,
+ gimp_object_get_name (proc));
+ }
+
+ if (actual_action)
+ sensitive = gimp_action_get_sensitive (actual_action);
+
+ g_object_set (action,
+ "visible", TRUE,
+ "sensitive", sensitive,
+ "procedure", proc,
+ "label", label,
+ "icon-name", gimp_viewable_get_icon_name (GIMP_VIEWABLE (proc)),
+ "tooltip", gimp_procedure_get_blurb (proc),
+ NULL);
+ }
+
+ for (; i < gimp_filter_history_size (gimp); i++)
+ {
+ GimpAction *action;
+ gchar *name = g_strdup_printf ("filters-recent-%02d", i + 1);
+
+ action = gimp_action_group_get_action (group, name);
+ g_free (name);
+
+ g_object_set (action,
+ "visible", FALSE,
+ "procedure", NULL,
+ NULL);
+ }
+}
diff --git a/app/actions/filters-actions.h b/app/actions/filters-actions.h
new file mode 100644
index 0000000..f197b86
--- /dev/null
+++ b/app/actions/filters-actions.h
@@ -0,0 +1,27 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __FILTERS_ACTIONS_H__
+#define __FILTERS_ACTIONS_H__
+
+
+void filters_actions_setup (GimpActionGroup *group);
+void filters_actions_update (GimpActionGroup *group,
+ gpointer data);
+
+
+#endif /* __FILTERS_ACTIONS_H__ */
diff --git a/app/actions/filters-commands.c b/app/actions/filters-commands.c
new file mode 100644
index 0000000..6ca0529
--- /dev/null
+++ b/app/actions/filters-commands.c
@@ -0,0 +1,265 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <string.h>
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpbase/gimpbase.h"
+#include "libgimpconfig/gimpconfig.h"
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "actions-types.h"
+
+#include "operations/gimp-operation-config.h"
+#include "operations/gimpoperationsettings.h"
+
+#include "core/gimp.h"
+#include "core/gimp-filter-history.h"
+#include "core/gimpimage.h"
+#include "core/gimpprogress.h"
+
+#include "widgets/gimpaction.h"
+
+#include "actions.h"
+#include "filters-commands.h"
+#include "gimpgeglprocedure.h"
+#include "procedure-commands.h"
+
+
+/* local function prototypes */
+
+static gchar * filters_parse_operation (Gimp *gimp,
+ const gchar *operation_str,
+ const gchar *icon_name,
+ GimpObject **settings);
+
+static void filters_run_procedure (Gimp *gimp,
+ GimpDisplay *display,
+ GimpProcedure *procedure,
+ GimpRunMode run_mode);
+
+
+/* public functions */
+
+void
+filters_apply_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpDrawable *drawable;
+ gchar *operation;
+ GimpObject *settings;
+ GimpProcedure *procedure;
+ return_if_no_drawable (image, drawable, data);
+
+ operation = filters_parse_operation (image->gimp,
+ g_variant_get_string (value, NULL),
+ gimp_action_get_icon_name (action),
+ &settings);
+
+ procedure = gimp_gegl_procedure_new (image->gimp,
+ GIMP_RUN_NONINTERACTIVE, settings,
+ operation,
+ gimp_action_get_name (action),
+ gimp_action_get_label (action),
+ gimp_action_get_tooltip (action),
+ gimp_action_get_icon_name (action),
+ gimp_action_get_help_id (action));
+
+ g_free (operation);
+
+ if (settings)
+ g_object_unref (settings);
+
+ gimp_filter_history_add (image->gimp, procedure);
+ filters_history_cmd_callback (NULL,
+ g_variant_new_uint64 (GPOINTER_TO_SIZE (procedure)),
+ data);
+
+ g_object_unref (procedure);
+}
+
+void
+filters_apply_interactive_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpDrawable *drawable;
+ GimpProcedure *procedure;
+ return_if_no_drawable (image, drawable, data);
+
+ procedure = gimp_gegl_procedure_new (image->gimp,
+ GIMP_RUN_INTERACTIVE, NULL,
+ g_variant_get_string (value, NULL),
+ gimp_action_get_name (action),
+ gimp_action_get_label (action),
+ gimp_action_get_tooltip (action),
+ gimp_action_get_icon_name (action),
+ gimp_action_get_help_id (action));
+
+ gimp_filter_history_add (image->gimp, procedure);
+ filters_history_cmd_callback (NULL,
+ g_variant_new_uint64 (GPOINTER_TO_SIZE (procedure)),
+ data);
+
+ g_object_unref (procedure);
+}
+
+void
+filters_repeat_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpDrawable *drawable;
+ GimpDisplay *display;
+ GimpProcedure *procedure;
+ GimpRunMode run_mode;
+ return_if_no_drawable (image, drawable, data);
+ return_if_no_display (display, data);
+
+ run_mode = (GimpRunMode) g_variant_get_int32 (value);
+
+ procedure = gimp_filter_history_nth (image->gimp, 0);
+
+ if (procedure)
+ filters_run_procedure (image->gimp, display, procedure, run_mode);
+}
+
+void
+filters_history_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ Gimp *gimp;
+ GimpDisplay *display;
+ GimpProcedure *procedure;
+ gsize hack;
+ return_if_no_gimp (gimp, data);
+ return_if_no_display (display, data);
+
+ hack = g_variant_get_uint64 (value);
+
+ procedure = GSIZE_TO_POINTER (hack);
+
+ filters_run_procedure (gimp, display, procedure, GIMP_RUN_INTERACTIVE);
+}
+
+
+/* private functions */
+
+static gchar *
+filters_parse_operation (Gimp *gimp,
+ const gchar *operation_str,
+ const gchar *icon_name,
+ GimpObject **settings)
+{
+ const gchar *newline = strchr (operation_str, '\n');
+
+ *settings = NULL;
+
+ if (newline)
+ {
+ gchar *operation;
+ const gchar *serialized;
+
+ operation = g_strndup (operation_str, newline - operation_str);
+ serialized = newline + 1;
+
+ if (*serialized)
+ {
+ GError *error = NULL;
+
+ *settings =
+ g_object_new (gimp_operation_config_get_type (gimp, operation,
+ icon_name,
+ GIMP_TYPE_OPERATION_SETTINGS),
+ NULL);
+
+ if (! gimp_config_deserialize_string (GIMP_CONFIG (*settings),
+ serialized, -1, NULL,
+ &error))
+ {
+ g_warning ("filters_parse_operation: deserializing hardcoded "
+ "operation settings failed: %s",
+ error->message);
+ g_clear_error (&error);
+
+ g_object_unref (*settings);
+ *settings = NULL;
+ }
+ }
+
+ return operation;
+ }
+
+ return g_strdup (operation_str);
+}
+
+static void
+filters_run_procedure (Gimp *gimp,
+ GimpDisplay *display,
+ GimpProcedure *procedure,
+ GimpRunMode run_mode)
+{
+ GimpObject *settings = NULL;
+ GimpValueArray *args;
+
+ if (GIMP_IS_GEGL_PROCEDURE (procedure))
+ {
+ GimpGeglProcedure *gegl_procedure = GIMP_GEGL_PROCEDURE (procedure);
+
+ if (gegl_procedure->default_run_mode == GIMP_RUN_NONINTERACTIVE)
+ run_mode = GIMP_RUN_NONINTERACTIVE;
+
+ settings = gegl_procedure->default_settings;
+ }
+
+ args = procedure_commands_get_display_args (procedure, display, settings);
+
+ if (args)
+ {
+ gboolean success = FALSE;
+
+ if (run_mode == GIMP_RUN_NONINTERACTIVE)
+ {
+ success =
+ procedure_commands_run_procedure (procedure, gimp,
+ GIMP_PROGRESS (display),
+ args);
+ }
+ else
+ {
+ success =
+ procedure_commands_run_procedure_async (procedure, gimp,
+ GIMP_PROGRESS (display),
+ run_mode, args,
+ display);
+ }
+
+ if (success)
+ gimp_filter_history_add (gimp, procedure);
+
+ gimp_value_array_unref (args);
+ }
+}
diff --git a/app/actions/filters-commands.h b/app/actions/filters-commands.h
new file mode 100644
index 0000000..68cb2ea
--- /dev/null
+++ b/app/actions/filters-commands.h
@@ -0,0 +1,37 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __FILTERS_COMMANDS_H__
+#define __FILTERS_COMMANDS_H__
+
+
+void filters_apply_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void filters_apply_interactive_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+void filters_repeat_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void filters_history_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+
+#endif /* __FILTERS_COMMANDS_H__ */
diff --git a/app/actions/fonts-actions.c b/app/actions/fonts-actions.c
new file mode 100644
index 0000000..5191dcc
--- /dev/null
+++ b/app/actions/fonts-actions.c
@@ -0,0 +1,73 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "actions-types.h"
+
+#include "core/gimpcontext.h"
+
+#include "text/gimpfont.h"
+
+#include "widgets/gimpactiongroup.h"
+#include "widgets/gimphelp-ids.h"
+
+#include "actions.h"
+#include "data-commands.h"
+#include "fonts-actions.h"
+
+#include "gimp-intl.h"
+
+
+static const GimpActionEntry fonts_actions[] =
+{
+ { "fonts-popup", GIMP_ICON_FONT,
+ NC_("fonts-action", "Fonts Menu"), NULL, NULL, NULL,
+ GIMP_HELP_FONT_DIALOG },
+
+ { "fonts-refresh", GIMP_ICON_VIEW_REFRESH,
+ NC_("fonts-action", "_Rescan Font List"), NULL,
+ NC_("fonts-action", "Rescan the installed fonts"),
+ data_refresh_cmd_callback,
+ GIMP_HELP_FONT_REFRESH }
+};
+
+
+void
+fonts_actions_setup (GimpActionGroup *group)
+{
+ gimp_action_group_add_actions (group, "fonts-action",
+ fonts_actions,
+ G_N_ELEMENTS (fonts_actions));
+}
+
+void
+fonts_actions_update (GimpActionGroup *group,
+ gpointer data)
+{
+#define SET_SENSITIVE(action,condition) \
+ gimp_action_group_set_action_sensitive (group, action, (condition) != 0)
+
+ SET_SENSITIVE ("fonts-refresh", TRUE);
+
+#undef SET_SENSITIVE
+}
diff --git a/app/actions/fonts-actions.h b/app/actions/fonts-actions.h
new file mode 100644
index 0000000..f4651d5
--- /dev/null
+++ b/app/actions/fonts-actions.h
@@ -0,0 +1,27 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __FONTS_ACTIONS_H__
+#define __FONTS_ACTIONS_H__
+
+
+void fonts_actions_setup (GimpActionGroup *group);
+void fonts_actions_update (GimpActionGroup *group,
+ gpointer data);
+
+
+#endif /* __FONTS_ACTIONS_H__ */
diff --git a/app/actions/gimpgeglprocedure.c b/app/actions/gimpgeglprocedure.c
new file mode 100644
index 0000000..b9f243f
--- /dev/null
+++ b/app/actions/gimpgeglprocedure.c
@@ -0,0 +1,476 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * gimpgeglprocedure.c
+ * Copyright (C) 2016-2018 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <string.h>
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpbase/gimpbase.h"
+#include "libgimpconfig/gimpconfig.h"
+
+#include "actions-types.h"
+
+#include "config/gimpguiconfig.h"
+
+#include "operations/gimp-operation-config.h"
+#include "operations/gimpoperationsettings.h"
+
+#include "core/gimp.h"
+#include "core/gimp-memsize.h"
+#include "core/gimpcontainer.h"
+#include "core/gimpcontext.h"
+#include "core/gimpdrawable-operation.h"
+#include "core/gimpimage.h"
+#include "core/gimplayermask.h"
+#include "core/gimpparamspecs.h"
+#include "core/gimpsettings.h"
+#include "core/gimptoolinfo.h"
+
+#include "display/gimpdisplay.h"
+
+#include "tools/gimpoperationtool.h"
+#include "tools/tool_manager.h"
+
+#include "gimpgeglprocedure.h"
+
+#include "gimp-intl.h"
+
+
+static void gimp_gegl_procedure_finalize (GObject *object);
+
+static gint64 gimp_gegl_procedure_get_memsize (GimpObject *object,
+ gint64 *gui_size);
+
+static gchar * gimp_gegl_procedure_get_description (GimpViewable *viewable,
+ gchar **tooltip);
+
+static const gchar * gimp_gegl_procedure_get_label (GimpProcedure *procedure);
+static const gchar * gimp_gegl_procedure_get_menu_label (GimpProcedure *procedure);
+static const gchar * gimp_gegl_procedure_get_help_id (GimpProcedure *procedure);
+static gboolean gimp_gegl_procedure_get_sensitive (GimpProcedure *procedure,
+ GimpObject *object,
+ const gchar **tooltip);
+static GimpValueArray * gimp_gegl_procedure_execute (GimpProcedure *procedure,
+ Gimp *gimp,
+ GimpContext *context,
+ GimpProgress *progress,
+ GimpValueArray *args,
+ GError **error);
+static void gimp_gegl_procedure_execute_async (GimpProcedure *procedure,
+ Gimp *gimp,
+ GimpContext *context,
+ GimpProgress *progress,
+ GimpValueArray *args,
+ GimpObject *display);
+
+
+G_DEFINE_TYPE (GimpGeglProcedure, gimp_gegl_procedure,
+ GIMP_TYPE_PROCEDURE)
+
+#define parent_class gimp_gegl_procedure_parent_class
+
+
+static void
+gimp_gegl_procedure_class_init (GimpGeglProcedureClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GimpObjectClass *gimp_object_class = GIMP_OBJECT_CLASS (klass);
+ GimpViewableClass *viewable_class = GIMP_VIEWABLE_CLASS (klass);
+ GimpProcedureClass *proc_class = GIMP_PROCEDURE_CLASS (klass);
+
+ object_class->finalize = gimp_gegl_procedure_finalize;
+
+ gimp_object_class->get_memsize = gimp_gegl_procedure_get_memsize;
+
+ viewable_class->default_icon_name = "gimp-gegl";
+ viewable_class->get_description = gimp_gegl_procedure_get_description;
+
+ proc_class->get_label = gimp_gegl_procedure_get_label;
+ proc_class->get_menu_label = gimp_gegl_procedure_get_menu_label;
+ proc_class->get_help_id = gimp_gegl_procedure_get_help_id;
+ proc_class->get_sensitive = gimp_gegl_procedure_get_sensitive;
+ proc_class->execute = gimp_gegl_procedure_execute;
+ proc_class->execute_async = gimp_gegl_procedure_execute_async;
+}
+
+static void
+gimp_gegl_procedure_init (GimpGeglProcedure *proc)
+{
+}
+
+static void
+gimp_gegl_procedure_finalize (GObject *object)
+{
+ GimpGeglProcedure *proc = GIMP_GEGL_PROCEDURE (object);
+
+ g_clear_object (&proc->default_settings);
+
+ g_clear_pointer (&proc->menu_label, g_free);
+ g_clear_pointer (&proc->label, g_free);
+ g_clear_pointer (&proc->help_id, g_free);
+
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static gint64
+gimp_gegl_procedure_get_memsize (GimpObject *object,
+ gint64 *gui_size)
+{
+ GimpGeglProcedure *proc = GIMP_GEGL_PROCEDURE (object);
+ gint64 memsize = 0;
+
+ memsize += gimp_string_get_memsize (proc->menu_label);
+ memsize += gimp_string_get_memsize (proc->label);
+
+ return memsize + GIMP_OBJECT_CLASS (parent_class)->get_memsize (object,
+ gui_size);
+}
+
+static gchar *
+gimp_gegl_procedure_get_description (GimpViewable *viewable,
+ gchar **tooltip)
+{
+ GimpProcedure *procedure = GIMP_PROCEDURE (viewable);
+
+ if (tooltip)
+ *tooltip = g_strdup (gimp_procedure_get_blurb (procedure));
+
+ return g_strdup (gimp_procedure_get_label (procedure));
+}
+
+static const gchar *
+gimp_gegl_procedure_get_label (GimpProcedure *procedure)
+{
+ GimpGeglProcedure *proc = GIMP_GEGL_PROCEDURE (procedure);
+ gchar *ellipsis;
+ gchar *label;
+
+ if (proc->label)
+ return proc->label;
+
+ label = gimp_strip_uline (gimp_procedure_get_menu_label (procedure));
+
+ ellipsis = strstr (label, "...");
+
+ if (! ellipsis)
+ ellipsis = strstr (label, "\342\200\246" /* U+2026 HORIZONTAL ELLIPSIS */);
+
+ if (ellipsis && ellipsis == (label + strlen (label) - 3))
+ *ellipsis = '\0';
+
+ proc->label = label;
+
+ return proc->label;
+}
+
+static const gchar *
+gimp_gegl_procedure_get_menu_label (GimpProcedure *procedure)
+{
+ GimpGeglProcedure *proc = GIMP_GEGL_PROCEDURE (procedure);
+
+ if (proc->menu_label)
+ return proc->menu_label;
+
+ return GIMP_PROCEDURE_CLASS (parent_class)->get_menu_label (procedure);
+}
+
+static const gchar *
+gimp_gegl_procedure_get_help_id (GimpProcedure *procedure)
+{
+ GimpGeglProcedure *proc = GIMP_GEGL_PROCEDURE (procedure);
+
+ return proc->help_id;
+}
+
+static gboolean
+gimp_gegl_procedure_get_sensitive (GimpProcedure *procedure,
+ GimpObject *object,
+ const gchar **tooltip)
+{
+ GimpDrawable *drawable = GIMP_DRAWABLE (object);
+ gboolean sensitive = FALSE;
+
+ if (drawable)
+ {
+ GimpItem *item;
+
+ if (GIMP_IS_LAYER_MASK (drawable))
+ item = GIMP_ITEM (gimp_layer_mask_get_layer (GIMP_LAYER_MASK (drawable)));
+ else
+ item = GIMP_ITEM (drawable);
+
+ sensitive = ! gimp_item_is_content_locked (item);
+
+ if (gimp_viewable_get_children (GIMP_VIEWABLE (drawable)))
+ sensitive = FALSE;
+ }
+
+ return sensitive;
+}
+
+static GimpValueArray *
+gimp_gegl_procedure_execute (GimpProcedure *procedure,
+ Gimp *gimp,
+ GimpContext *context,
+ GimpProgress *progress,
+ GimpValueArray *args,
+ GError **error)
+{
+ GimpImage *image;
+ GimpDrawable *drawable;
+ GObject *config;
+ GeglNode *node;
+
+ image = gimp_value_get_image (gimp_value_array_index (args, 1), gimp);
+ drawable = gimp_value_get_drawable (gimp_value_array_index (args, 2), gimp);
+ config = g_value_get_object (gimp_value_array_index (args, 3));
+
+ node = gegl_node_new_child (NULL,
+ "operation", procedure->original_name,
+ NULL);
+
+ gimp_drawable_apply_operation_with_config (
+ drawable,
+ progress, gimp_procedure_get_label (procedure),
+ node, config);
+
+ g_object_unref (node);
+
+ gimp_image_flush (image);
+
+ return gimp_procedure_get_return_values (procedure, TRUE, NULL);
+}
+
+static void
+gimp_gegl_procedure_execute_async (GimpProcedure *procedure,
+ Gimp *gimp,
+ GimpContext *context,
+ GimpProgress *progress,
+ GimpValueArray *args,
+ GimpObject *display)
+{
+ GimpRunMode run_mode;
+ GimpObject *settings;
+ GimpTool *active_tool;
+ const gchar *tool_name;
+
+ run_mode = g_value_get_int (gimp_value_array_index (args, 0));
+ settings = g_value_get_object (gimp_value_array_index (args, 3));
+
+ if (! settings &&
+ (run_mode != GIMP_RUN_INTERACTIVE ||
+ GIMP_GUI_CONFIG (gimp->config)->filter_tool_use_last_settings))
+ {
+ /* if we didn't get settings passed, get the last used settings */
+
+ GType config_type;
+ GimpContainer *container;
+
+ config_type = G_VALUE_TYPE (gimp_value_array_index (args, 3));
+
+ container = gimp_operation_config_get_container (gimp, config_type,
+ (GCompareFunc)
+ gimp_settings_compare);
+
+ settings = gimp_container_get_child_by_index (container, 0);
+
+ /* only use the settings if they are automatically created
+ * "last used" values, not if they were saved explicitly and
+ * have a zero timestamp; and if they are not a separator.
+ */
+ if (settings &&
+ (GIMP_SETTINGS (settings)->time == 0 ||
+ ! gimp_object_get_name (settings)))
+ {
+ settings = NULL;
+ }
+ }
+
+ if (run_mode == GIMP_RUN_NONINTERACTIVE ||
+ run_mode == GIMP_RUN_WITH_LAST_VALS)
+ {
+ if (settings || run_mode == GIMP_RUN_NONINTERACTIVE)
+ {
+ g_value_set_object (gimp_value_array_index (args, 3), settings);
+ gimp_procedure_execute (procedure, gimp, context, progress,
+ args, NULL);
+ return;
+ }
+
+ gimp_message (gimp,
+ G_OBJECT (progress), GIMP_MESSAGE_WARNING,
+ _("There are no last settings for '%s', "
+ "showing the filter dialog instead."),
+ gimp_procedure_get_label (procedure));
+ }
+
+ if (! strcmp (procedure->original_name, "gimp:brightness-contrast"))
+ {
+ tool_name = "gimp-brightness-contrast-tool";
+ }
+ else if (! strcmp (procedure->original_name, "gimp:curves"))
+ {
+ tool_name = "gimp-curves-tool";
+ }
+ else if (! strcmp (procedure->original_name, "gimp:levels"))
+ {
+ tool_name = "gimp-levels-tool";
+ }
+ else if (! strcmp (procedure->original_name, "gimp:threshold"))
+ {
+ tool_name = "gimp-threshold-tool";
+ }
+ else if (! strcmp (procedure->original_name, "gimp:offset"))
+ {
+ tool_name = "gimp-offset-tool";
+ }
+ else
+ {
+ tool_name = "gimp-operation-tool";
+ }
+
+ active_tool = tool_manager_get_active (gimp);
+
+ /* do not use the passed context because we need to set the active
+ * tool on the global user context
+ */
+ context = gimp_get_user_context (gimp);
+
+ if (strcmp (gimp_object_get_name (active_tool->tool_info), tool_name))
+ {
+ GimpToolInfo *tool_info = gimp_get_tool_info (gimp, tool_name);
+
+ if (GIMP_IS_TOOL_INFO (tool_info))
+ gimp_context_set_tool (context, tool_info);
+ }
+ else
+ {
+ gimp_context_tool_changed (context);
+ }
+
+ active_tool = tool_manager_get_active (gimp);
+
+ if (! strcmp (gimp_object_get_name (active_tool->tool_info), tool_name))
+ {
+ /* Remember the procedure that created this tool, because
+ * we can't just switch to an operation tool using
+ * gimp_context_set_tool(), we also have to go through the
+ * initialization code below, otherwise we end up with a
+ * dummy tool that does nothing. See bug #776370.
+ */
+ g_object_set_data_full (G_OBJECT (active_tool), "gimp-gegl-procedure",
+ g_object_ref (procedure),
+ (GDestroyNotify) g_object_unref);
+
+ if (! strcmp (tool_name, "gimp-operation-tool"))
+ {
+ gimp_operation_tool_set_operation (GIMP_OPERATION_TOOL (active_tool),
+ procedure->original_name,
+ gimp_procedure_get_label (procedure),
+ gimp_procedure_get_label (procedure),
+ gimp_procedure_get_label (procedure),
+ gimp_viewable_get_icon_name (GIMP_VIEWABLE (procedure)),
+ gimp_procedure_get_help_id (procedure));
+ }
+
+ tool_manager_initialize_active (gimp, GIMP_DISPLAY (display));
+
+ if (settings)
+ gimp_filter_tool_set_config (GIMP_FILTER_TOOL (active_tool),
+ GIMP_CONFIG (settings));
+ }
+}
+
+
+/* public functions */
+
+GimpProcedure *
+gimp_gegl_procedure_new (Gimp *gimp,
+ GimpRunMode default_run_mode,
+ GimpObject *default_settings,
+ const gchar *operation,
+ const gchar *name,
+ const gchar *menu_label,
+ const gchar *tooltip,
+ const gchar *icon_name,
+ const gchar *help_id)
+{
+ GimpProcedure *procedure;
+ GimpGeglProcedure *gegl_procedure;
+ GType config_type;
+
+ g_return_val_if_fail (GIMP_IS_GIMP (gimp), NULL);
+ g_return_val_if_fail (operation != NULL, NULL);
+ g_return_val_if_fail (name != NULL, NULL);
+ g_return_val_if_fail (menu_label != NULL, NULL);
+
+ config_type = gimp_operation_config_get_type (gimp, operation, icon_name,
+ GIMP_TYPE_OPERATION_SETTINGS);
+
+ procedure = g_object_new (GIMP_TYPE_GEGL_PROCEDURE, NULL);
+
+ gegl_procedure = GIMP_GEGL_PROCEDURE (procedure);
+
+ gegl_procedure->default_run_mode = default_run_mode;
+ gegl_procedure->menu_label = g_strdup (menu_label);
+ gegl_procedure->help_id = g_strdup (help_id);
+
+ if (default_settings)
+ gegl_procedure->default_settings = g_object_ref (default_settings);
+
+ gimp_object_set_name (GIMP_OBJECT (procedure), name);
+ gimp_viewable_set_icon_name (GIMP_VIEWABLE (procedure), icon_name);
+ gimp_procedure_set_strings (procedure,
+ operation,
+ tooltip,
+ tooltip,
+ "author", "copyright", "date",
+ NULL);
+
+ gimp_procedure_add_argument (procedure,
+ gimp_param_spec_int32 ("run-mode",
+ "Run mode",
+ "Run mode",
+ G_MININT32, G_MAXINT32, 0,
+ GIMP_PARAM_READWRITE));
+ gimp_procedure_add_argument (procedure,
+ gimp_param_spec_image_id ("image",
+ "Image",
+ "Input image",
+ gimp, FALSE,
+ GIMP_PARAM_READWRITE));
+ gimp_procedure_add_argument (procedure,
+ gimp_param_spec_drawable_id ("drawable",
+ "Drawable",
+ "Input drawable",
+ gimp, TRUE,
+ GIMP_PARAM_READWRITE));
+ gimp_procedure_add_argument (procedure,
+ g_param_spec_object ("settings",
+ "Settings",
+ "Settings",
+ config_type,
+ GIMP_PARAM_READWRITE));
+
+ return procedure;
+}
diff --git a/app/actions/gimpgeglprocedure.h b/app/actions/gimpgeglprocedure.h
new file mode 100644
index 0000000..07fc24c
--- /dev/null
+++ b/app/actions/gimpgeglprocedure.h
@@ -0,0 +1,70 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * gimpgeglprocedure.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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GIMP_GEGL_PROCEDURE_H__
+#define __GIMP_GEGL_PROCEDURE_H__
+
+
+#include "pdb/gimpprocedure.h"
+
+
+#define GIMP_TYPE_GEGL_PROCEDURE (gimp_gegl_procedure_get_type ())
+#define GIMP_GEGL_PROCEDURE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_GEGL_PROCEDURE, GimpGeglProcedure))
+#define GIMP_GEGL_PROCEDURE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_GEGL_PROCEDURE, GimpGeglProcedureClass))
+#define GIMP_IS_GEGL_PROCEDURE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_GEGL_PROCEDURE))
+#define GIMP_IS_GEGL_PROCEDURE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_GEGL_PROCEDURE))
+#define GIMP_GEGL_PROCEDURE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_GEGL_PROCEDURE, GimpGeglProcedureClass))
+
+
+typedef struct _GimpGeglProcedure GimpGeglProcedure;
+typedef struct _GimpGeglProcedureClass GimpGeglProcedureClass;
+
+struct _GimpGeglProcedure
+{
+ GimpProcedure parent_instance;
+
+ GimpRunMode default_run_mode;
+ GimpObject *default_settings;
+
+ gchar *menu_label;
+ gchar *label;
+ gchar *help_id;
+};
+
+struct _GimpGeglProcedureClass
+{
+ GimpProcedureClass parent_class;
+};
+
+
+GType gimp_gegl_procedure_get_type (void) G_GNUC_CONST;
+
+GimpProcedure * gimp_gegl_procedure_new (Gimp *gimp,
+ GimpRunMode default_run_mode,
+ GimpObject *default_settings,
+ const gchar *operation,
+ const gchar *name,
+ const gchar *menu_label,
+ const gchar *tooltip,
+ const gchar *icon_name,
+ const gchar *help_id);
+
+
+#endif /* __GIMP_GEGL_PROCEDURE_H__ */
diff --git a/app/actions/gradient-editor-actions.c b/app/actions/gradient-editor-actions.c
new file mode 100644
index 0000000..ca730e6
--- /dev/null
+++ b/app/actions/gradient-editor-actions.c
@@ -0,0 +1,906 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "actions-types.h"
+
+#include "core/gimp.h"
+#include "core/gimpcontext.h"
+#include "core/gimpdatafactory.h"
+#include "core/gimpgradient.h"
+
+#include "widgets/gimpactiongroup.h"
+#include "widgets/gimpgradienteditor.h"
+#include "widgets/gimphelp-ids.h"
+
+#include "data-editor-commands.h"
+#include "gradient-editor-actions.h"
+#include "gradient-editor-commands.h"
+
+#include "gimp-intl.h"
+
+
+static const GimpActionEntry gradient_editor_actions[] =
+{
+ { "gradient-editor-popup", GIMP_ICON_GRADIENT,
+ NC_("gradient-editor-action", "Gradient Editor Menu"), NULL, NULL, NULL,
+ GIMP_HELP_GRADIENT_EDITOR_DIALOG },
+
+ { "gradient-editor-left-color-type", NULL,
+ NC_("gradient-editor-action", "Left Color Type") },
+ { "gradient-editor-load-left-color", GIMP_ICON_DOCUMENT_REVERT,
+ NC_("gradient-editor-action", "_Load Left Color From") },
+ { "gradient-editor-save-left-color", GIMP_ICON_DOCUMENT_SAVE,
+ NC_("gradient-editor-action", "_Save Left Color To") },
+
+ { "gradient-editor-right-color-type", NULL,
+ NC_("gradient-editor-action", "Right Color Type") },
+ { "gradient-editor-load-right-color", GIMP_ICON_DOCUMENT_REVERT,
+ NC_("gradient-editor-action", "Load Right Color Fr_om") },
+ { "gradient-editor-save-right-color", GIMP_ICON_DOCUMENT_SAVE,
+ NC_("gradient-editor-action", "Sa_ve Right Color To") },
+
+ { "gradient-editor-blending-func", NULL, "blending-function" },
+ { "gradient-editor-coloring-type", NULL, "coloring-type" },
+
+ { "gradient-editor-left-color", NULL,
+ NC_("gradient-editor-action", "L_eft Endpoint's Color..."), NULL, NULL,
+ gradient_editor_left_color_cmd_callback,
+ GIMP_HELP_GRADIENT_EDITOR_LEFT_COLOR },
+
+ { "gradient-editor-right-color", NULL,
+ NC_("gradient-editor-action", "R_ight Endpoint's Color..."), NULL, NULL,
+ gradient_editor_right_color_cmd_callback,
+ GIMP_HELP_GRADIENT_EDITOR_RIGHT_COLOR },
+
+ { "gradient-editor-flip", GIMP_ICON_OBJECT_FLIP_HORIZONTAL,
+ "flip", NULL, NULL,
+ gradient_editor_flip_cmd_callback,
+ GIMP_HELP_GRADIENT_EDITOR_FLIP },
+
+ { "gradient-editor-replicate", GIMP_ICON_OBJECT_DUPLICATE,
+ "replicate", NULL, NULL,
+ gradient_editor_replicate_cmd_callback,
+ GIMP_HELP_GRADIENT_EDITOR_FLIP },
+
+ { "gradient-editor-split-midpoint", NULL,
+ "splitmidpoint", NULL, NULL,
+ gradient_editor_split_midpoint_cmd_callback,
+ GIMP_HELP_GRADIENT_EDITOR_SPLIT_MIDPOINT },
+
+ { "gradient-editor-split-uniform", NULL,
+ "splituniform", NULL, NULL,
+ gradient_editor_split_uniformly_cmd_callback,
+ GIMP_HELP_GRADIENT_EDITOR_SPLIT_UNIFORM },
+
+ { "gradient-editor-delete", GIMP_ICON_EDIT_DELETE,
+ "delete", "", NULL,
+ gradient_editor_delete_cmd_callback,
+ GIMP_HELP_GRADIENT_EDITOR_DELETE },
+
+ { "gradient-editor-recenter", NULL,
+ "recenter", NULL, NULL,
+ gradient_editor_recenter_cmd_callback,
+ GIMP_HELP_GRADIENT_EDITOR_RECENTER },
+
+ { "gradient-editor-redistribute", NULL,
+ "redistribute", NULL, NULL,
+ gradient_editor_redistribute_cmd_callback,
+ GIMP_HELP_GRADIENT_EDITOR_REDISTRIBUTE },
+
+ { "gradient-editor-blend-color", NULL,
+ NC_("gradient-editor-action", "Ble_nd Endpoints' Colors"), NULL, NULL,
+ gradient_editor_blend_color_cmd_callback,
+ GIMP_HELP_GRADIENT_EDITOR_BLEND_COLOR },
+
+ { "gradient-editor-blend-opacity", NULL,
+ NC_("gradient-editor-action", "Blend Endpoints' Opacit_y"), NULL, NULL,
+ gradient_editor_blend_opacity_cmd_callback,
+ GIMP_HELP_GRADIENT_EDITOR_BLEND_OPACITY }
+};
+
+static const GimpToggleActionEntry gradient_editor_toggle_actions[] =
+{
+ { "gradient-editor-edit-active", GIMP_ICON_LINKED,
+ NC_("gradient-editor-action", "Edit Active Gradient"), NULL, NULL,
+ data_editor_edit_active_cmd_callback,
+ FALSE,
+ GIMP_HELP_GRADIENT_EDITOR_EDIT_ACTIVE }
+};
+
+
+#define LOAD_LEFT_FROM(num,magic) \
+ { "gradient-editor-load-left-" num, NULL, \
+ num, NULL, NULL, \
+ (magic), FALSE, \
+ GIMP_HELP_GRADIENT_EDITOR_LEFT_LOAD }
+#define SAVE_LEFT_TO(num,magic) \
+ { "gradient-editor-save-left-" num, NULL, \
+ num, NULL, NULL, \
+ (magic), FALSE, \
+ GIMP_HELP_GRADIENT_EDITOR_LEFT_SAVE }
+#define LOAD_RIGHT_FROM(num,magic) \
+ { "gradient-editor-load-right-" num, NULL, \
+ num, NULL, NULL, \
+ (magic), FALSE, \
+ GIMP_HELP_GRADIENT_EDITOR_RIGHT_LOAD }
+#define SAVE_RIGHT_TO(num,magic) \
+ { "gradient-editor-save-right-" num, NULL, \
+ num, NULL, NULL, \
+ (magic), FALSE, \
+ GIMP_HELP_GRADIENT_EDITOR_RIGHT_SAVE }
+
+static const GimpEnumActionEntry gradient_editor_load_left_actions[] =
+{
+ { "gradient-editor-load-left-left-neighbor", NULL,
+ NC_("gradient-editor-action", "_Left Neighbor's Right Endpoint"), NULL, NULL,
+ GRADIENT_EDITOR_COLOR_NEIGHBOR_ENDPOINT, FALSE,
+ GIMP_HELP_GRADIENT_EDITOR_LEFT_LOAD },
+
+ { "gradient-editor-load-left-right-endpoint", NULL,
+ NC_("gradient-editor-action", "_Right Endpoint"), NULL, NULL,
+ GRADIENT_EDITOR_COLOR_OTHER_ENDPOINT, FALSE,
+ GIMP_HELP_GRADIENT_EDITOR_LEFT_LOAD },
+
+ { "gradient-editor-load-left-fg", NULL,
+ NC_("gradient-editor-action", "_Foreground Color"), NULL, NULL,
+ GRADIENT_EDITOR_COLOR_FOREGROUND, FALSE,
+ GIMP_HELP_GRADIENT_EDITOR_LEFT_LOAD },
+
+ { "gradient-editor-load-left-bg", NULL,
+ NC_("gradient-editor-action", "_Background Color"), NULL, NULL,
+ GRADIENT_EDITOR_COLOR_BACKGROUND, FALSE,
+ GIMP_HELP_GRADIENT_EDITOR_LEFT_LOAD },
+
+ LOAD_LEFT_FROM ("01", GRADIENT_EDITOR_COLOR_FIRST_CUSTOM + 0),
+ LOAD_LEFT_FROM ("02", GRADIENT_EDITOR_COLOR_FIRST_CUSTOM + 1),
+ LOAD_LEFT_FROM ("03", GRADIENT_EDITOR_COLOR_FIRST_CUSTOM + 2),
+ LOAD_LEFT_FROM ("04", GRADIENT_EDITOR_COLOR_FIRST_CUSTOM + 3),
+ LOAD_LEFT_FROM ("05", GRADIENT_EDITOR_COLOR_FIRST_CUSTOM + 4),
+ LOAD_LEFT_FROM ("06", GRADIENT_EDITOR_COLOR_FIRST_CUSTOM + 5),
+ LOAD_LEFT_FROM ("07", GRADIENT_EDITOR_COLOR_FIRST_CUSTOM + 6),
+ LOAD_LEFT_FROM ("08", GRADIENT_EDITOR_COLOR_FIRST_CUSTOM + 7),
+ LOAD_LEFT_FROM ("09", GRADIENT_EDITOR_COLOR_FIRST_CUSTOM + 8),
+ LOAD_LEFT_FROM ("10", GRADIENT_EDITOR_COLOR_FIRST_CUSTOM + 9)
+};
+
+static const GimpEnumActionEntry gradient_editor_save_left_actions[] =
+{
+ SAVE_LEFT_TO ("01", 0),
+ SAVE_LEFT_TO ("02", 1),
+ SAVE_LEFT_TO ("03", 2),
+ SAVE_LEFT_TO ("04", 3),
+ SAVE_LEFT_TO ("05", 4),
+ SAVE_LEFT_TO ("06", 5),
+ SAVE_LEFT_TO ("07", 6),
+ SAVE_LEFT_TO ("08", 7),
+ SAVE_LEFT_TO ("09", 8),
+ SAVE_LEFT_TO ("10", 9)
+};
+
+static const GimpEnumActionEntry gradient_editor_load_right_actions[] =
+{
+ { "gradient-editor-load-right-right-neighbor", NULL,
+ NC_("gradient-editor-action", "_Right Neighbor's Left Endpoint"), NULL, NULL,
+ GRADIENT_EDITOR_COLOR_NEIGHBOR_ENDPOINT, FALSE,
+ GIMP_HELP_GRADIENT_EDITOR_RIGHT_LOAD },
+
+ { "gradient-editor-load-right-left-endpoint", NULL,
+ NC_("gradient-editor-action", "_Left Endpoint"), NULL, NULL,
+ GRADIENT_EDITOR_COLOR_OTHER_ENDPOINT, FALSE,
+ GIMP_HELP_GRADIENT_EDITOR_RIGHT_LOAD },
+
+ { "gradient-editor-load-right-fg", NULL,
+ NC_("gradient-editor-action", "_Foreground Color"), NULL, NULL,
+ GRADIENT_EDITOR_COLOR_FOREGROUND, FALSE,
+ GIMP_HELP_GRADIENT_EDITOR_RIGHT_LOAD },
+
+ { "gradient-editor-load-right-bg", NULL,
+ NC_("gradient-editor-action", "_Background Color"), NULL, NULL,
+ GRADIENT_EDITOR_COLOR_BACKGROUND, FALSE,
+ GIMP_HELP_GRADIENT_EDITOR_RIGHT_LOAD },
+
+ LOAD_RIGHT_FROM ("01", GRADIENT_EDITOR_COLOR_FIRST_CUSTOM + 0),
+ LOAD_RIGHT_FROM ("02", GRADIENT_EDITOR_COLOR_FIRST_CUSTOM + 1),
+ LOAD_RIGHT_FROM ("03", GRADIENT_EDITOR_COLOR_FIRST_CUSTOM + 2),
+ LOAD_RIGHT_FROM ("04", GRADIENT_EDITOR_COLOR_FIRST_CUSTOM + 3),
+ LOAD_RIGHT_FROM ("05", GRADIENT_EDITOR_COLOR_FIRST_CUSTOM + 4),
+ LOAD_RIGHT_FROM ("06", GRADIENT_EDITOR_COLOR_FIRST_CUSTOM + 5),
+ LOAD_RIGHT_FROM ("07", GRADIENT_EDITOR_COLOR_FIRST_CUSTOM + 6),
+ LOAD_RIGHT_FROM ("08", GRADIENT_EDITOR_COLOR_FIRST_CUSTOM + 7),
+ LOAD_RIGHT_FROM ("09", GRADIENT_EDITOR_COLOR_FIRST_CUSTOM + 8),
+ LOAD_RIGHT_FROM ("10", GRADIENT_EDITOR_COLOR_FIRST_CUSTOM + 9)
+};
+
+static const GimpEnumActionEntry gradient_editor_save_right_actions[] =
+{
+ SAVE_RIGHT_TO ("01", 0),
+ SAVE_RIGHT_TO ("02", 1),
+ SAVE_RIGHT_TO ("03", 2),
+ SAVE_RIGHT_TO ("04", 3),
+ SAVE_RIGHT_TO ("05", 4),
+ SAVE_RIGHT_TO ("06", 5),
+ SAVE_RIGHT_TO ("07", 6),
+ SAVE_RIGHT_TO ("08", 7),
+ SAVE_RIGHT_TO ("09", 8),
+ SAVE_RIGHT_TO ("10", 9)
+};
+
+#undef LOAD_LEFT_FROM
+#undef SAVE_LEFT_TO
+#undef LOAD_RIGHT_FROM
+#undef SAVE_RIGHT_TO
+
+
+static const GimpRadioActionEntry gradient_editor_left_color_type_actions[] =
+{
+ { "gradient-editor-left-color-fixed", NULL,
+ NC_("gradient-editor-color-type", "_Fixed"), NULL, NULL,
+ GIMP_GRADIENT_COLOR_FIXED,
+ GIMP_HELP_GRADIENT_EDITOR_LEFT_COLOR },
+
+ { "gradient-editor-left-color-foreground", NULL,
+ NC_("gradient-editor-color-type", "F_oreground Color"), NULL, NULL,
+ GIMP_GRADIENT_COLOR_FOREGROUND,
+ GIMP_HELP_GRADIENT_EDITOR_LEFT_COLOR },
+
+ { "gradient-editor-left-color-foreground-transparent", NULL,
+ NC_("gradient-editor-color-type",
+ "Fo_reground Color (Transparent)"), NULL, NULL,
+ GIMP_GRADIENT_COLOR_FOREGROUND_TRANSPARENT,
+ GIMP_HELP_GRADIENT_EDITOR_LEFT_COLOR },
+
+ { "gradient-editor-left-color-background", NULL,
+ NC_("gradient-editor-color-type", "_Background Color"), NULL, NULL,
+ GIMP_GRADIENT_COLOR_BACKGROUND,
+ GIMP_HELP_GRADIENT_EDITOR_LEFT_COLOR },
+
+ { "gradient-editor-left-color-background-transparent", NULL,
+ NC_("gradient-editor-color-type",
+ "B_ackground Color (Transparent)"), NULL, NULL,
+ GIMP_GRADIENT_COLOR_BACKGROUND_TRANSPARENT,
+ GIMP_HELP_GRADIENT_EDITOR_LEFT_COLOR }
+};
+
+static const GimpRadioActionEntry gradient_editor_right_color_type_actions[] =
+{
+ { "gradient-editor-right-color-fixed", NULL,
+ NC_("gradient-editor-color-type", "_Fixed"), NULL, NULL,
+ GIMP_GRADIENT_COLOR_FIXED,
+ GIMP_HELP_GRADIENT_EDITOR_RIGHT_COLOR },
+
+ { "gradient-editor-right-color-foreground", NULL,
+ NC_("gradient-editor-color-type", "F_oreground Color"), NULL, NULL,
+ GIMP_GRADIENT_COLOR_FOREGROUND,
+ GIMP_HELP_GRADIENT_EDITOR_RIGHT_COLOR },
+
+ { "gradient-editor-right-color-foreground-transparent", NULL,
+ NC_("gradient-editor-color-type",
+ "Fo_reground Color (Transparent)"), NULL, NULL,
+ GIMP_GRADIENT_COLOR_FOREGROUND_TRANSPARENT,
+ GIMP_HELP_GRADIENT_EDITOR_RIGHT_COLOR },
+
+ { "gradient-editor-right-color-background", NULL,
+ NC_("gradient-editor-color-type", "_Background Color"), NULL, NULL,
+ GIMP_GRADIENT_COLOR_BACKGROUND,
+ GIMP_HELP_GRADIENT_EDITOR_RIGHT_COLOR },
+
+ { "gradient-editor-right-color-background-transparent", NULL,
+ NC_("gradient-editor-color-type",
+ "B_ackground Color (Transparent)"), NULL, NULL,
+ GIMP_GRADIENT_COLOR_BACKGROUND_TRANSPARENT,
+ GIMP_HELP_GRADIENT_EDITOR_RIGHT_COLOR }
+};
+
+static const GimpRadioActionEntry gradient_editor_blending_actions[] =
+{
+ { "gradient-editor-blending-linear", NULL,
+ NC_("gradient-editor-blending", "_Linear"), NULL, NULL,
+ GIMP_GRADIENT_SEGMENT_LINEAR,
+ GIMP_HELP_GRADIENT_EDITOR_BLENDING },
+
+ { "gradient-editor-blending-curved", NULL,
+ NC_("gradient-editor-blending", "_Curved"), NULL, NULL,
+ GIMP_GRADIENT_SEGMENT_CURVED,
+ GIMP_HELP_GRADIENT_EDITOR_BLENDING },
+
+ { "gradient-editor-blending-sine", NULL,
+ NC_("gradient-editor-blending", "_Sinusoidal"), NULL, NULL,
+ GIMP_GRADIENT_SEGMENT_SINE,
+ GIMP_HELP_GRADIENT_EDITOR_BLENDING },
+
+ { "gradient-editor-blending-sphere-increasing", NULL,
+ NC_("gradient-editor-blending", "Spherical (i_ncreasing)"), NULL, NULL,
+ GIMP_GRADIENT_SEGMENT_SPHERE_INCREASING,
+ GIMP_HELP_GRADIENT_EDITOR_BLENDING },
+
+ { "gradient-editor-blending-sphere-decreasing", NULL,
+ NC_("gradient-editor-blending", "Spherical (_decreasing)"), NULL, NULL,
+ GIMP_GRADIENT_SEGMENT_SPHERE_DECREASING,
+ GIMP_HELP_GRADIENT_EDITOR_BLENDING },
+
+ { "gradient-editor-blending-step", NULL,
+ NC_("gradient-editor-blending", "S_tep"), NULL, NULL,
+ GIMP_GRADIENT_SEGMENT_STEP,
+ GIMP_HELP_GRADIENT_EDITOR_BLENDING },
+
+ { "gradient-editor-blending-varies", NULL,
+ NC_("gradient-editor-blending", "(Varies)"), NULL, NULL,
+ -1,
+ GIMP_HELP_GRADIENT_EDITOR_BLENDING }
+};
+
+static const GimpRadioActionEntry gradient_editor_coloring_actions[] =
+{
+ { "gradient-editor-coloring-rgb", NULL,
+ NC_("gradient-editor-coloring", "_RGB"), NULL, NULL,
+ GIMP_GRADIENT_SEGMENT_RGB,
+ GIMP_HELP_GRADIENT_EDITOR_COLORING },
+
+ { "gradient-editor-coloring-hsv-ccw", NULL,
+ NC_("gradient-editor-coloring", "HSV (_counter-clockwise hue)"), NULL, NULL,
+ GIMP_GRADIENT_SEGMENT_HSV_CCW,
+ GIMP_HELP_GRADIENT_EDITOR_COLORING },
+
+ { "gradient-editor-coloring-hsv-cw", NULL,
+ NC_("gradient-editor-coloring", "HSV (clockwise _hue)"), NULL, NULL,
+ GIMP_GRADIENT_SEGMENT_HSV_CW,
+ GIMP_HELP_GRADIENT_EDITOR_COLORING },
+
+ { "gradient-editor-coloring-varies", NULL,
+ NC_("gradient-editor-coloring", "(Varies)"), NULL, NULL,
+ -1,
+ GIMP_HELP_GRADIENT_EDITOR_COLORING }
+};
+
+static const GimpEnumActionEntry gradient_editor_zoom_actions[] =
+{
+ { "gradient-editor-zoom-in", GIMP_ICON_ZOOM_IN,
+ N_("Zoom In"), NULL,
+ N_("Zoom in"),
+ GIMP_ZOOM_IN, FALSE,
+ GIMP_HELP_GRADIENT_EDITOR_ZOOM_IN },
+
+ { "gradient-editor-zoom-out", GIMP_ICON_ZOOM_OUT,
+ N_("Zoom Out"), NULL,
+ N_("Zoom out"),
+ GIMP_ZOOM_OUT, FALSE,
+ GIMP_HELP_GRADIENT_EDITOR_ZOOM_OUT },
+
+ { "gradient-editor-zoom-all", GIMP_ICON_ZOOM_FIT_BEST,
+ N_("Zoom All"), NULL,
+ N_("Zoom all"),
+ GIMP_ZOOM_OUT_MAX, FALSE,
+ GIMP_HELP_GRADIENT_EDITOR_ZOOM_ALL }
+};
+
+
+void
+gradient_editor_actions_setup (GimpActionGroup *group)
+{
+ gimp_action_group_add_actions (group, "gradient-editor-action",
+ gradient_editor_actions,
+ G_N_ELEMENTS (gradient_editor_actions));
+
+ gimp_action_group_add_toggle_actions (group, "gradient-editor-action",
+ gradient_editor_toggle_actions,
+ G_N_ELEMENTS (gradient_editor_toggle_actions));
+
+ gimp_action_group_add_enum_actions (group, "gradient-editor-action",
+ gradient_editor_load_left_actions,
+ G_N_ELEMENTS (gradient_editor_load_left_actions),
+ gradient_editor_load_left_cmd_callback);
+
+ gimp_action_group_add_enum_actions (group, "gradient-editor-action",
+ gradient_editor_save_left_actions,
+ G_N_ELEMENTS (gradient_editor_save_left_actions),
+ gradient_editor_save_left_cmd_callback);
+
+ gimp_action_group_add_enum_actions (group, "gradient-editor-action",
+ gradient_editor_load_right_actions,
+ G_N_ELEMENTS (gradient_editor_load_right_actions),
+ gradient_editor_load_right_cmd_callback);
+
+
+ gimp_action_group_add_enum_actions (group, "gradient-editor-action",
+ gradient_editor_save_right_actions,
+ G_N_ELEMENTS (gradient_editor_save_right_actions),
+ gradient_editor_save_right_cmd_callback);
+
+ gimp_action_group_add_radio_actions (group, "gradient-editor-color-type",
+ gradient_editor_left_color_type_actions,
+ G_N_ELEMENTS (gradient_editor_left_color_type_actions),
+ NULL,
+ 0,
+ gradient_editor_left_color_type_cmd_callback);
+
+ gimp_action_group_add_radio_actions (group, "gradient-editor-color-type",
+ gradient_editor_right_color_type_actions,
+ G_N_ELEMENTS (gradient_editor_right_color_type_actions),
+ NULL,
+ 0,
+ gradient_editor_right_color_type_cmd_callback);
+
+ gimp_action_group_add_radio_actions (group, "gradient-editor-blending",
+ gradient_editor_blending_actions,
+ G_N_ELEMENTS (gradient_editor_blending_actions),
+ NULL,
+ 0,
+ gradient_editor_blending_func_cmd_callback);
+
+ gimp_action_group_add_radio_actions (group, "gradient-editor-coloring",
+ gradient_editor_coloring_actions,
+ G_N_ELEMENTS (gradient_editor_coloring_actions),
+ NULL,
+ 0,
+ gradient_editor_coloring_type_cmd_callback);
+
+ gimp_action_group_add_enum_actions (group, NULL,
+ gradient_editor_zoom_actions,
+ G_N_ELEMENTS (gradient_editor_zoom_actions),
+ gradient_editor_zoom_cmd_callback);
+}
+
+void
+gradient_editor_actions_update (GimpActionGroup *group,
+ gpointer data)
+{
+ GimpGradientEditor *editor = GIMP_GRADIENT_EDITOR (data);
+ GimpDataEditor *data_editor = GIMP_DATA_EDITOR (data);
+ GimpGradient *gradient;
+ gboolean editable = FALSE;
+ GimpRGB left_color;
+ GimpRGB right_color;
+ GimpRGB left_seg_color;
+ GimpRGB right_seg_color;
+ GimpRGB fg;
+ GimpRGB bg;
+ gboolean blending_equal = TRUE;
+ gboolean coloring_equal = TRUE;
+ gboolean left_editable = TRUE;
+ gboolean right_editable = TRUE;
+ gboolean selection = FALSE;
+ gboolean delete = FALSE;
+ gboolean edit_active = FALSE;
+
+ gradient = GIMP_GRADIENT (data_editor->data);
+
+ if (gradient)
+ {
+ GimpGradientSegmentType type;
+ GimpGradientSegmentColor color;
+ GimpGradientSegment *left_seg;
+ GimpGradientSegment *right_seg;
+ GimpGradientSegment *seg, *aseg;
+
+ if (data_editor->data_editable)
+ editable = TRUE;
+
+ gimp_gradient_segment_get_left_flat_color (gradient,
+ data_editor->context,
+ editor->control_sel_l,
+ &left_color);
+
+ if (editor->control_sel_l->prev)
+ left_seg = editor->control_sel_l->prev;
+ else
+ left_seg = gimp_gradient_segment_get_last (editor->control_sel_l);
+
+ gimp_gradient_segment_get_right_flat_color (gradient,
+ data_editor->context,
+ left_seg,
+ &left_seg_color);
+
+ gimp_gradient_segment_get_right_flat_color (gradient,
+ data_editor->context,
+ editor->control_sel_r,
+ &right_color);
+
+ if (editor->control_sel_r->next)
+ right_seg = editor->control_sel_r->next;
+ else
+ right_seg = gimp_gradient_segment_get_first (editor->control_sel_r);
+
+ gimp_gradient_segment_get_left_flat_color (gradient,
+ data_editor->context,
+ right_seg,
+ &right_seg_color);
+
+ left_editable = (editor->control_sel_l->left_color_type ==
+ GIMP_GRADIENT_COLOR_FIXED);
+ right_editable = (editor->control_sel_r->right_color_type ==
+ GIMP_GRADIENT_COLOR_FIXED);
+
+ type = editor->control_sel_l->type;
+ color = editor->control_sel_l->color;
+
+ seg = editor->control_sel_l;
+
+ do
+ {
+ blending_equal = blending_equal && (seg->type == type);
+ coloring_equal = coloring_equal && (seg->color == color);
+
+ aseg = seg;
+ seg = seg->next;
+ }
+ while (aseg != editor->control_sel_r);
+
+ selection = (editor->control_sel_l != editor->control_sel_r);
+ delete = (editor->control_sel_l->prev || editor->control_sel_r->next);
+ }
+
+ if (data_editor->context)
+ {
+ gimp_context_get_foreground (data_editor->context, &fg);
+ gimp_context_get_background (data_editor->context, &bg);
+ }
+
+ /* pretend the gradient not being editable while the dialog is
+ * insensitive. prevents the gradient from being modified while a
+ * dialog is running. bug #161411 --mitch
+ */
+ if (! gtk_widget_is_sensitive (GTK_WIDGET (editor)))
+ editable = FALSE;
+
+ if (! editable)
+ {
+ left_editable = FALSE;
+ right_editable = FALSE;
+ }
+
+ edit_active = gimp_data_editor_get_edit_active (data_editor);
+
+#define SET_ACTIVE(action,condition) \
+ gimp_action_group_set_action_active (group, action, (condition) != 0)
+#define SET_COLOR(action,color,set_label) \
+ gimp_action_group_set_action_color (group, action, (color), (set_label))
+#define SET_LABEL(action,label) \
+ gimp_action_group_set_action_label (group, action, (label))
+#define SET_SENSITIVE(action,condition) \
+ gimp_action_group_set_action_sensitive (group, action, (condition) != 0)
+#define SET_VISIBLE(action,condition) \
+ gimp_action_group_set_action_visible (group, action, (condition) != 0)
+
+ SET_SENSITIVE ("gradient-editor-left-color-fixed", editable);
+ SET_SENSITIVE ("gradient-editor-left-color-foreground", editable);
+ SET_SENSITIVE ("gradient-editor-left-color-foreground-transparent", editable);
+ SET_SENSITIVE ("gradient-editor-left-color-background", editable);
+ SET_SENSITIVE ("gradient-editor-left-color-background-transparent", editable);
+
+ if (gradient)
+ {
+ switch (editor->control_sel_l->left_color_type)
+ {
+ case GIMP_GRADIENT_COLOR_FIXED:
+ SET_ACTIVE ("gradient-editor-left-color-fixed", TRUE);
+ break;
+ case GIMP_GRADIENT_COLOR_FOREGROUND:
+ SET_ACTIVE ("gradient-editor-left-color-foreground", TRUE);
+ break;
+ case GIMP_GRADIENT_COLOR_FOREGROUND_TRANSPARENT:
+ SET_ACTIVE ("gradient-editor-left-color-foreground-transparent", TRUE);
+ break;
+ case GIMP_GRADIENT_COLOR_BACKGROUND:
+ SET_ACTIVE ("gradient-editor-left-color-background", TRUE);
+ break;
+ case GIMP_GRADIENT_COLOR_BACKGROUND_TRANSPARENT:
+ SET_ACTIVE ("gradient-editor-left-color-background-transparent", TRUE);
+ break;
+ }
+ }
+
+ SET_SENSITIVE ("gradient-editor-left-color", left_editable);
+ SET_SENSITIVE ("gradient-editor-load-left-left-neighbor", editable);
+ SET_SENSITIVE ("gradient-editor-load-left-right-endpoint", editable);
+
+ if (gradient)
+ {
+ SET_COLOR ("gradient-editor-left-color",
+ &left_color, FALSE);
+ SET_COLOR ("gradient-editor-load-left-left-neighbor",
+ &left_seg_color, FALSE);
+ SET_COLOR ("gradient-editor-load-left-right-endpoint",
+ &right_color, FALSE);
+ }
+
+ SET_SENSITIVE ("gradient-editor-load-left-fg", left_editable);
+ SET_SENSITIVE ("gradient-editor-load-left-bg", left_editable);
+
+ SET_COLOR ("gradient-editor-load-left-fg",
+ data_editor->context ? &fg : NULL, FALSE);
+ SET_COLOR ("gradient-editor-load-left-bg",
+ data_editor->context ? &bg : NULL, FALSE);
+
+ SET_SENSITIVE ("gradient-editor-load-left-01", left_editable);
+ SET_SENSITIVE ("gradient-editor-load-left-02", left_editable);
+ SET_SENSITIVE ("gradient-editor-load-left-03", left_editable);
+ SET_SENSITIVE ("gradient-editor-load-left-04", left_editable);
+ SET_SENSITIVE ("gradient-editor-load-left-05", left_editable);
+ SET_SENSITIVE ("gradient-editor-load-left-06", left_editable);
+ SET_SENSITIVE ("gradient-editor-load-left-07", left_editable);
+ SET_SENSITIVE ("gradient-editor-load-left-08", left_editable);
+ SET_SENSITIVE ("gradient-editor-load-left-09", left_editable);
+ SET_SENSITIVE ("gradient-editor-load-left-10", left_editable);
+
+ SET_COLOR ("gradient-editor-load-left-01", &editor->saved_colors[0], TRUE);
+ SET_COLOR ("gradient-editor-load-left-02", &editor->saved_colors[1], TRUE);
+ SET_COLOR ("gradient-editor-load-left-03", &editor->saved_colors[2], TRUE);
+ SET_COLOR ("gradient-editor-load-left-04", &editor->saved_colors[3], TRUE);
+ SET_COLOR ("gradient-editor-load-left-05", &editor->saved_colors[4], TRUE);
+ SET_COLOR ("gradient-editor-load-left-06", &editor->saved_colors[5], TRUE);
+ SET_COLOR ("gradient-editor-load-left-07", &editor->saved_colors[6], TRUE);
+ SET_COLOR ("gradient-editor-load-left-08", &editor->saved_colors[7], TRUE);
+ SET_COLOR ("gradient-editor-load-left-09", &editor->saved_colors[8], TRUE);
+ SET_COLOR ("gradient-editor-load-left-10", &editor->saved_colors[9], TRUE);
+
+ SET_SENSITIVE ("gradient-editor-save-left-01", gradient);
+ SET_SENSITIVE ("gradient-editor-save-left-02", gradient);
+ SET_SENSITIVE ("gradient-editor-save-left-03", gradient);
+ SET_SENSITIVE ("gradient-editor-save-left-04", gradient);
+ SET_SENSITIVE ("gradient-editor-save-left-05", gradient);
+ SET_SENSITIVE ("gradient-editor-save-left-06", gradient);
+ SET_SENSITIVE ("gradient-editor-save-left-07", gradient);
+ SET_SENSITIVE ("gradient-editor-save-left-08", gradient);
+ SET_SENSITIVE ("gradient-editor-save-left-09", gradient);
+ SET_SENSITIVE ("gradient-editor-save-left-10", gradient);
+
+ SET_COLOR ("gradient-editor-save-left-01", &editor->saved_colors[0], TRUE);
+ SET_COLOR ("gradient-editor-save-left-02", &editor->saved_colors[1], TRUE);
+ SET_COLOR ("gradient-editor-save-left-03", &editor->saved_colors[2], TRUE);
+ SET_COLOR ("gradient-editor-save-left-04", &editor->saved_colors[3], TRUE);
+ SET_COLOR ("gradient-editor-save-left-05", &editor->saved_colors[4], TRUE);
+ SET_COLOR ("gradient-editor-save-left-06", &editor->saved_colors[5], TRUE);
+ SET_COLOR ("gradient-editor-save-left-07", &editor->saved_colors[6], TRUE);
+ SET_COLOR ("gradient-editor-save-left-08", &editor->saved_colors[7], TRUE);
+ SET_COLOR ("gradient-editor-save-left-09", &editor->saved_colors[8], TRUE);
+ SET_COLOR ("gradient-editor-save-left-10", &editor->saved_colors[9], TRUE);
+
+ SET_SENSITIVE ("gradient-editor-right-color-fixed", editable);
+ SET_SENSITIVE ("gradient-editor-right-color-foreground", editable);
+ SET_SENSITIVE ("gradient-editor-right-color-foreground-transparent", editable);
+ SET_SENSITIVE ("gradient-editor-right-color-background", editable);
+ SET_SENSITIVE ("gradient-editor-right-color-background-transparent", editable);
+
+ if (gradient)
+ {
+ switch (editor->control_sel_r->right_color_type)
+ {
+ case GIMP_GRADIENT_COLOR_FIXED:
+ SET_ACTIVE ("gradient-editor-right-color-fixed", TRUE);
+ break;
+ case GIMP_GRADIENT_COLOR_FOREGROUND:
+ SET_ACTIVE ("gradient-editor-right-color-foreground", TRUE);
+ break;
+ case GIMP_GRADIENT_COLOR_FOREGROUND_TRANSPARENT:
+ SET_ACTIVE ("gradient-editor-right-color-foreground-transparent", TRUE);
+ break;
+ case GIMP_GRADIENT_COLOR_BACKGROUND:
+ SET_ACTIVE ("gradient-editor-right-color-background", TRUE);
+ break;
+ case GIMP_GRADIENT_COLOR_BACKGROUND_TRANSPARENT:
+ SET_ACTIVE ("gradient-editor-right-color-background-transparent", TRUE);
+ break;
+ }
+ }
+
+ SET_SENSITIVE ("gradient-editor-right-color", right_editable);
+ SET_SENSITIVE ("gradient-editor-load-right-right-neighbor", editable);
+ SET_SENSITIVE ("gradient-editor-load-right-left-endpoint", editable);
+
+ if (gradient)
+ {
+ SET_COLOR ("gradient-editor-right-color",
+ &right_color, FALSE);
+ SET_COLOR ("gradient-editor-load-right-right-neighbor",
+ &right_seg_color, FALSE);
+ SET_COLOR ("gradient-editor-load-right-left-endpoint",
+ &left_color, FALSE);
+ }
+
+ SET_SENSITIVE ("gradient-editor-load-right-fg", right_editable);
+ SET_SENSITIVE ("gradient-editor-load-right-bg", right_editable);
+
+ SET_COLOR ("gradient-editor-load-right-fg",
+ data_editor->context ? &fg : NULL, FALSE);
+ SET_COLOR ("gradient-editor-load-right-bg",
+ data_editor->context ? &bg : NULL, FALSE);
+
+ SET_SENSITIVE ("gradient-editor-load-right-01", right_editable);
+ SET_SENSITIVE ("gradient-editor-load-right-02", right_editable);
+ SET_SENSITIVE ("gradient-editor-load-right-03", right_editable);
+ SET_SENSITIVE ("gradient-editor-load-right-04", right_editable);
+ SET_SENSITIVE ("gradient-editor-load-right-05", right_editable);
+ SET_SENSITIVE ("gradient-editor-load-right-06", right_editable);
+ SET_SENSITIVE ("gradient-editor-load-right-07", right_editable);
+ SET_SENSITIVE ("gradient-editor-load-right-08", right_editable);
+ SET_SENSITIVE ("gradient-editor-load-right-09", right_editable);
+ SET_SENSITIVE ("gradient-editor-load-right-10", right_editable);
+
+ SET_COLOR ("gradient-editor-load-right-01", &editor->saved_colors[0], TRUE);
+ SET_COLOR ("gradient-editor-load-right-02", &editor->saved_colors[1], TRUE);
+ SET_COLOR ("gradient-editor-load-right-03", &editor->saved_colors[2], TRUE);
+ SET_COLOR ("gradient-editor-load-right-04", &editor->saved_colors[3], TRUE);
+ SET_COLOR ("gradient-editor-load-right-05", &editor->saved_colors[4], TRUE);
+ SET_COLOR ("gradient-editor-load-right-06", &editor->saved_colors[5], TRUE);
+ SET_COLOR ("gradient-editor-load-right-07", &editor->saved_colors[6], TRUE);
+ SET_COLOR ("gradient-editor-load-right-08", &editor->saved_colors[7], TRUE);
+ SET_COLOR ("gradient-editor-load-right-09", &editor->saved_colors[8], TRUE);
+ SET_COLOR ("gradient-editor-load-right-10", &editor->saved_colors[9], TRUE);
+
+ SET_SENSITIVE ("gradient-editor-save-right-01", gradient);
+ SET_SENSITIVE ("gradient-editor-save-right-02", gradient);
+ SET_SENSITIVE ("gradient-editor-save-right-03", gradient);
+ SET_SENSITIVE ("gradient-editor-save-right-04", gradient);
+ SET_SENSITIVE ("gradient-editor-save-right-05", gradient);
+ SET_SENSITIVE ("gradient-editor-save-right-06", gradient);
+ SET_SENSITIVE ("gradient-editor-save-right-07", gradient);
+ SET_SENSITIVE ("gradient-editor-save-right-08", gradient);
+ SET_SENSITIVE ("gradient-editor-save-right-09", gradient);
+ SET_SENSITIVE ("gradient-editor-save-right-10", gradient);
+
+ SET_COLOR ("gradient-editor-save-right-01", &editor->saved_colors[0], TRUE);
+ SET_COLOR ("gradient-editor-save-right-02", &editor->saved_colors[1], TRUE);
+ SET_COLOR ("gradient-editor-save-right-03", &editor->saved_colors[2], TRUE);
+ SET_COLOR ("gradient-editor-save-right-04", &editor->saved_colors[3], TRUE);
+ SET_COLOR ("gradient-editor-save-right-05", &editor->saved_colors[4], TRUE);
+ SET_COLOR ("gradient-editor-save-right-06", &editor->saved_colors[5], TRUE);
+ SET_COLOR ("gradient-editor-save-right-07", &editor->saved_colors[6], TRUE);
+ SET_COLOR ("gradient-editor-save-right-08", &editor->saved_colors[7], TRUE);
+ SET_COLOR ("gradient-editor-save-right-09", &editor->saved_colors[8], TRUE);
+ SET_COLOR ("gradient-editor-save-right-10", &editor->saved_colors[9], TRUE);
+
+ SET_SENSITIVE ("gradient-editor-flip", editable);
+ SET_SENSITIVE ("gradient-editor-replicate", editable);
+ SET_SENSITIVE ("gradient-editor-split-midpoint", editable);
+ SET_SENSITIVE ("gradient-editor-split-uniform", editable);
+ SET_SENSITIVE ("gradient-editor-delete", editable && delete);
+ SET_SENSITIVE ("gradient-editor-recenter", editable);
+ SET_SENSITIVE ("gradient-editor-redistribute", editable);
+
+ if (! selection)
+ {
+ SET_LABEL ("gradient-editor-blending-func",
+ _("_Blending Function for Segment"));
+ SET_LABEL ("gradient-editor-coloring-type",
+ _("Coloring _Type for Segment"));
+
+ SET_LABEL ("gradient-editor-flip",
+ _("_Flip Segment"));
+ SET_LABEL ("gradient-editor-replicate",
+ _("_Replicate Segment..."));
+ SET_LABEL ("gradient-editor-split-midpoint",
+ _("Split Segment at _Midpoint"));
+ SET_LABEL ("gradient-editor-split-uniform",
+ _("Split Segment _Uniformly..."));
+ SET_LABEL ("gradient-editor-delete",
+ _("_Delete Segment"));
+ SET_LABEL ("gradient-editor-recenter",
+ _("Re-_center Segment's Midpoint"));
+ SET_LABEL ("gradient-editor-redistribute",
+ _("Re-distribute _Handles in Segment"));
+ }
+ else
+ {
+ SET_LABEL ("gradient-editor-blending-func",
+ _("_Blending Function for Selection"));
+ SET_LABEL ("gradient-editor-coloring-type",
+ _("Coloring _Type for Selection"));
+
+ SET_LABEL ("gradient-editor-flip",
+ _("_Flip Selection"));
+ SET_LABEL ("gradient-editor-replicate",
+ _("_Replicate Selection..."));
+ SET_LABEL ("gradient-editor-split-midpoint",
+ _("Split Segments at _Midpoints"));
+ SET_LABEL ("gradient-editor-split-uniform",
+ _("Split Segments _Uniformly..."));
+ SET_LABEL ("gradient-editor-delete",
+ _("_Delete Selection"));
+ SET_LABEL ("gradient-editor-recenter",
+ _("Re-_center Midpoints in Selection"));
+ SET_LABEL ("gradient-editor-redistribute",
+ _("Re-distribute _Handles in Selection"));
+ }
+
+ SET_SENSITIVE ("gradient-editor-blending-varies", FALSE);
+ SET_VISIBLE ("gradient-editor-blending-varies", ! blending_equal);
+
+ SET_SENSITIVE ("gradient-editor-blending-linear", editable);
+ SET_SENSITIVE ("gradient-editor-blending-curved", editable);
+ SET_SENSITIVE ("gradient-editor-blending-sine", editable);
+ SET_SENSITIVE ("gradient-editor-blending-sphere-increasing", editable);
+ SET_SENSITIVE ("gradient-editor-blending-sphere-decreasing", editable);
+ SET_SENSITIVE ("gradient-editor-blending-step", editable);
+
+ if (blending_equal && gradient)
+ {
+ switch (editor->control_sel_l->type)
+ {
+ case GIMP_GRADIENT_SEGMENT_LINEAR:
+ SET_ACTIVE ("gradient-editor-blending-linear", TRUE);
+ break;
+ case GIMP_GRADIENT_SEGMENT_CURVED:
+ SET_ACTIVE ("gradient-editor-blending-curved", TRUE);
+ break;
+ case GIMP_GRADIENT_SEGMENT_SINE:
+ SET_ACTIVE ("gradient-editor-blending-sine", TRUE);
+ break;
+ case GIMP_GRADIENT_SEGMENT_SPHERE_INCREASING:
+ SET_ACTIVE ("gradient-editor-blending-sphere-increasing", TRUE);
+ break;
+ case GIMP_GRADIENT_SEGMENT_SPHERE_DECREASING:
+ SET_ACTIVE ("gradient-editor-blending-sphere-decreasing", TRUE);
+ break;
+ case GIMP_GRADIENT_SEGMENT_STEP:
+ SET_ACTIVE ("gradient-editor-blending-step", TRUE);
+ break;
+ }
+ }
+ else
+ {
+ SET_ACTIVE ("gradient-editor-blending-varies", TRUE);
+ }
+
+ SET_SENSITIVE ("gradient-editor-coloring-varies", FALSE);
+ SET_VISIBLE ("gradient-editor-coloring-varies", ! coloring_equal);
+
+ SET_SENSITIVE ("gradient-editor-coloring-rgb", editable);
+ SET_SENSITIVE ("gradient-editor-coloring-hsv-ccw", editable);
+ SET_SENSITIVE ("gradient-editor-coloring-hsv-cw", editable);
+
+ if (coloring_equal && gradient)
+ {
+ switch (editor->control_sel_l->color)
+ {
+ case GIMP_GRADIENT_SEGMENT_RGB:
+ SET_ACTIVE ("gradient-editor-coloring-rgb", TRUE);
+ break;
+ case GIMP_GRADIENT_SEGMENT_HSV_CCW:
+ SET_ACTIVE ("gradient-editor-coloring-hsv-ccw", TRUE);
+ break;
+ case GIMP_GRADIENT_SEGMENT_HSV_CW:
+ SET_ACTIVE ("gradient-editor-coloring-hsv-cw", TRUE);
+ break;
+ }
+ }
+ else
+ {
+ SET_ACTIVE ("gradient-editor-coloring-varies", TRUE);
+ }
+
+ SET_SENSITIVE ("gradient-editor-blend-color", editable && selection);
+ SET_SENSITIVE ("gradient-editor-blend-opacity", editable && selection);
+
+ SET_SENSITIVE ("gradient-editor-zoom-out", gradient);
+ SET_SENSITIVE ("gradient-editor-zoom-in", gradient);
+ SET_SENSITIVE ("gradient-editor-zoom-all", gradient);
+
+ SET_ACTIVE ("gradient-editor-edit-active", edit_active);
+
+#undef SET_ACTIVE
+#undef SET_COLOR
+#undef SET_LABEL
+#undef SET_SENSITIVE
+#undef SET_VISIBLE
+}
diff --git a/app/actions/gradient-editor-actions.h b/app/actions/gradient-editor-actions.h
new file mode 100644
index 0000000..5c2f999
--- /dev/null
+++ b/app/actions/gradient-editor-actions.h
@@ -0,0 +1,27 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GRADIENT_EDITOR_ACTIONS_H__
+#define __GRADIENT_EDITOR_ACTIONS_H__
+
+
+void gradient_editor_actions_setup (GimpActionGroup *group);
+void gradient_editor_actions_update (GimpActionGroup *group,
+ gpointer data);
+
+
+#endif /* __GRADIENT_EDITOR_ACTIONS_H__ */
diff --git a/app/actions/gradient-editor-commands.c b/app/actions/gradient-editor-commands.c
new file mode 100644
index 0000000..fa3709f
--- /dev/null
+++ b/app/actions/gradient-editor-commands.c
@@ -0,0 +1,738 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpmath/gimpmath.h"
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "actions-types.h"
+
+#include "core/gimp.h"
+#include "core/gimpcontext.h"
+#include "core/gimpgradient.h"
+
+#include "widgets/gimpgradienteditor.h"
+#include "widgets/gimphelp-ids.h"
+#include "widgets/gimpuimanager.h"
+#include "widgets/gimpviewabledialog.h"
+
+#include "gradient-editor-commands.h"
+
+#include "gimp-intl.h"
+
+
+/* local function prototypes */
+
+static void gradient_editor_split_uniform_response (GtkWidget *widget,
+ gint response_id,
+ GimpGradientEditor *editor);
+static void gradient_editor_replicate_response (GtkWidget *widget,
+ gint response_id,
+ GimpGradientEditor *editor);
+
+
+/* public functions */
+
+void
+gradient_editor_left_color_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpGradientEditor *editor = GIMP_GRADIENT_EDITOR (data);
+
+ gimp_gradient_editor_edit_left_color (editor);
+}
+
+void
+gradient_editor_left_color_type_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpGradientEditor *editor = GIMP_GRADIENT_EDITOR (data);
+ GimpGradient *gradient;
+ GimpGradientSegment *left;
+ GimpGradientColor color_type;
+
+ color_type = (GimpGradientColor) g_variant_get_int32 (value);
+
+ gimp_gradient_editor_get_selection (editor, &gradient, &left, NULL);
+
+ if (gradient &&
+ color_type >= 0 &&
+ color_type !=
+ gimp_gradient_segment_get_left_color_type (gradient, left))
+ {
+ GimpRGB color;
+
+ gimp_gradient_segment_get_left_flat_color (gradient,
+ GIMP_DATA_EDITOR (editor)->context,
+ left, &color);
+
+ gimp_data_freeze (GIMP_DATA (gradient));
+
+ gimp_gradient_segment_set_left_color_type (gradient, left, color_type);
+
+ if (color_type == GIMP_GRADIENT_COLOR_FIXED)
+ gimp_gradient_segment_set_left_color (gradient, left, &color);
+
+ gimp_data_thaw (GIMP_DATA (gradient));
+ }
+}
+
+void
+gradient_editor_load_left_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpGradientEditor *editor = GIMP_GRADIENT_EDITOR (data);
+ GimpDataEditor *data_editor = GIMP_DATA_EDITOR (data);
+ GimpGradient *gradient;
+ GimpGradientSegment *left;
+ GimpGradientSegment *right;
+ GimpGradientSegment *seg;
+ GimpRGB color;
+ GimpGradientColor color_type = GIMP_GRADIENT_COLOR_FIXED;
+ gint index = g_variant_get_int32 (value);
+
+ gimp_gradient_editor_get_selection (editor, &gradient, &left, &right);
+
+ switch (index)
+ {
+ case GRADIENT_EDITOR_COLOR_NEIGHBOR_ENDPOINT:
+ if (left->prev != NULL)
+ seg = left->prev;
+ else
+ seg = gimp_gradient_segment_get_last (left);
+
+ color = seg->right_color;
+ color_type = seg->right_color_type;
+ break;
+
+ case GRADIENT_EDITOR_COLOR_OTHER_ENDPOINT:
+ color = right->right_color;
+ color_type = right->right_color_type;
+ break;
+
+ case GRADIENT_EDITOR_COLOR_FOREGROUND:
+ gimp_context_get_foreground (data_editor->context, &color);
+ break;
+
+ case GRADIENT_EDITOR_COLOR_BACKGROUND:
+ gimp_context_get_background (data_editor->context, &color);
+ break;
+
+ default: /* Load a color */
+ color = editor->saved_colors[index - GRADIENT_EDITOR_COLOR_FIRST_CUSTOM];
+ break;
+ }
+
+ gimp_data_freeze (GIMP_DATA (gradient));
+
+ gimp_gradient_segment_range_blend (gradient, left, right,
+ &color,
+ &right->right_color,
+ TRUE, TRUE);
+ gimp_gradient_segment_set_left_color_type (gradient, left, color_type);
+
+ gimp_data_thaw (GIMP_DATA (gradient));
+}
+
+void
+gradient_editor_save_left_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpGradientEditor *editor = GIMP_GRADIENT_EDITOR (data);
+ GimpGradient *gradient;
+ GimpGradientSegment *left;
+ gint index = g_variant_get_int32 (value);
+
+ gimp_gradient_editor_get_selection (editor, &gradient, &left, NULL);
+
+ gimp_gradient_segment_get_left_color (gradient, left,
+ &editor->saved_colors[index]);
+}
+
+void
+gradient_editor_right_color_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpGradientEditor *editor = GIMP_GRADIENT_EDITOR (data);
+
+ gimp_gradient_editor_edit_right_color (editor);
+}
+
+void
+gradient_editor_right_color_type_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpGradientEditor *editor = GIMP_GRADIENT_EDITOR (data);
+ GimpGradient *gradient;
+ GimpGradientSegment *right;
+ GimpGradientColor color_type;
+
+ color_type = (GimpGradientColor) g_variant_get_int32 (value);
+
+ gimp_gradient_editor_get_selection (editor, &gradient, NULL, &right);
+
+ if (gradient &&
+ color_type >= 0 &&
+ color_type !=
+ gimp_gradient_segment_get_right_color_type (gradient, right))
+ {
+ GimpRGB color;
+
+ gimp_gradient_segment_get_right_flat_color (gradient,
+ GIMP_DATA_EDITOR (editor)->context,
+ right, &color);
+
+ gimp_data_freeze (GIMP_DATA (gradient));
+
+ gimp_gradient_segment_set_right_color_type (gradient, right, color_type);
+
+ if (color_type == GIMP_GRADIENT_COLOR_FIXED)
+ gimp_gradient_segment_set_right_color (gradient, right, &color);
+
+ gimp_data_thaw (GIMP_DATA (gradient));
+ }
+}
+
+void
+gradient_editor_load_right_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpGradientEditor *editor = GIMP_GRADIENT_EDITOR (data);
+ GimpDataEditor *data_editor = GIMP_DATA_EDITOR (data);
+ GimpGradient *gradient;
+ GimpGradientSegment *left;
+ GimpGradientSegment *right;
+ GimpGradientSegment *seg;
+ GimpRGB color;
+ GimpGradientColor color_type = GIMP_GRADIENT_COLOR_FIXED;
+ gint index = g_variant_get_int32 (value);
+
+ gimp_gradient_editor_get_selection (editor, &gradient, &left, &right);
+
+ switch (index)
+ {
+ case GRADIENT_EDITOR_COLOR_NEIGHBOR_ENDPOINT:
+ if (right->next != NULL)
+ seg = right->next;
+ else
+ seg = gimp_gradient_segment_get_first (right);
+
+ color = seg->left_color;
+ color_type = seg->left_color_type;
+ break;
+
+ case GRADIENT_EDITOR_COLOR_OTHER_ENDPOINT:
+ color = left->left_color;
+ color_type = left->left_color_type;
+ break;
+
+ case GRADIENT_EDITOR_COLOR_FOREGROUND:
+ gimp_context_get_foreground (data_editor->context, &color);
+ break;
+
+ case GRADIENT_EDITOR_COLOR_BACKGROUND:
+ gimp_context_get_background (data_editor->context, &color);
+ break;
+
+ default: /* Load a color */
+ color = editor->saved_colors[index - GRADIENT_EDITOR_COLOR_FIRST_CUSTOM];
+ break;
+ }
+
+ gimp_data_freeze (GIMP_DATA (gradient));
+
+ gimp_gradient_segment_range_blend (gradient, left, right,
+ &left->left_color,
+ &color,
+ TRUE, TRUE);
+ gimp_gradient_segment_set_right_color_type (gradient, left, color_type);
+
+ gimp_data_thaw (GIMP_DATA (gradient));
+}
+
+void
+gradient_editor_save_right_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpGradientEditor *editor = GIMP_GRADIENT_EDITOR (data);
+ GimpGradient *gradient;
+ GimpGradientSegment *right;
+ gint index = g_variant_get_int32 (value);
+
+ gimp_gradient_editor_get_selection (editor, &gradient, NULL, &right);
+
+ gimp_gradient_segment_get_right_color (gradient, right,
+ &editor->saved_colors[index]);
+}
+
+void
+gradient_editor_blending_func_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpGradientEditor *editor = GIMP_GRADIENT_EDITOR (data);
+ GimpGradient *gradient;
+ GimpGradientSegment *left;
+ GimpGradientSegment *right;
+ GEnumClass *enum_class = NULL;
+ GimpGradientSegmentType type;
+
+ type = (GimpGradientSegmentType) g_variant_get_int32 (value);
+
+ gimp_gradient_editor_get_selection (editor, &gradient, &left, &right);
+
+ enum_class = g_type_class_ref (GIMP_TYPE_GRADIENT_SEGMENT_TYPE);
+
+ if (gradient && g_enum_get_value (enum_class, type))
+ {
+ gimp_gradient_segment_range_set_blending_function (gradient,
+ left, right,
+ type);
+ }
+
+ g_type_class_unref (enum_class);
+}
+
+void
+gradient_editor_coloring_type_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpGradientEditor *editor = GIMP_GRADIENT_EDITOR (data);
+ GimpGradient *gradient;
+ GimpGradientSegment *left;
+ GimpGradientSegment *right;
+ GEnumClass *enum_class = NULL;
+ GimpGradientSegmentColor color;
+
+ color = (GimpGradientSegmentColor) g_variant_get_int32 (value);
+
+ gimp_gradient_editor_get_selection (editor, &gradient, &left, &right);
+
+ enum_class = g_type_class_ref (GIMP_TYPE_GRADIENT_SEGMENT_COLOR);
+
+ if (gradient && g_enum_get_value (enum_class, color))
+ {
+ gimp_gradient_segment_range_set_coloring_type (gradient,
+ left, right,
+ color);
+ }
+
+ g_type_class_unref (enum_class);
+}
+
+void
+gradient_editor_flip_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpGradientEditor *editor = GIMP_GRADIENT_EDITOR (data);
+ GimpGradient *gradient;
+ GimpGradientSegment *left;
+ GimpGradientSegment *right;
+
+ gimp_gradient_editor_get_selection (editor, &gradient, &left, &right);
+
+ gimp_gradient_segment_range_flip (gradient,
+ left, right,
+ &left, &right);
+
+ gimp_gradient_editor_set_selection (editor, left, right);
+}
+
+void
+gradient_editor_replicate_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpGradientEditor *editor = GIMP_GRADIENT_EDITOR (data);
+ GimpDataEditor *data_editor = GIMP_DATA_EDITOR (data);
+ GimpGradient *gradient;
+ GimpGradientSegment *left;
+ GimpGradientSegment *right;
+ GtkWidget *dialog;
+ GtkWidget *vbox;
+ GtkWidget *label;
+ GtkWidget *scale;
+ GtkAdjustment *scale_data;
+ const gchar *title;
+ const gchar *desc;
+
+ gimp_gradient_editor_get_selection (editor, &gradient, &left, &right);
+
+ if (left == right)
+ {
+ title = _("Replicate Segment");
+ desc = _("Replicate Gradient Segment");
+ }
+ else
+ {
+ title = _("Replicate Selection");
+ desc = _("Replicate Gradient Selection");
+ }
+
+ dialog = gimp_viewable_dialog_new (GIMP_VIEWABLE (gradient),
+ data_editor->context,
+ title,
+ "gimp-gradient-segment-replicate",
+ GIMP_ICON_GRADIENT, desc,
+ GTK_WIDGET (editor),
+ gimp_standard_help_func,
+ GIMP_HELP_GRADIENT_EDITOR_REPLICATE,
+
+ _("_Cancel"), GTK_RESPONSE_CANCEL,
+ _("_Replicate"), GTK_RESPONSE_OK,
+
+ NULL);
+
+ gtk_dialog_set_alternative_button_order (GTK_DIALOG (dialog),
+ GTK_RESPONSE_OK,
+ GTK_RESPONSE_CANCEL,
+ -1);
+
+ g_signal_connect (dialog, "response",
+ G_CALLBACK (gradient_editor_replicate_response),
+ editor);
+
+ vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
+ gtk_container_set_border_width (GTK_CONTAINER (vbox), 12);
+ gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))),
+ vbox, TRUE, TRUE, 0);
+ gtk_widget_show (vbox);
+
+ /* Instructions */
+ if (left == right)
+ label = gtk_label_new (_("Select the number of times\n"
+ "to replicate the selected segment."));
+ else
+ label = gtk_label_new (_("Select the number of times\n"
+ "to replicate the selection."));
+
+ gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
+ gtk_widget_show (label);
+
+ /* Scale */
+ scale_data = GTK_ADJUSTMENT (gtk_adjustment_new (2.0, 2.0, 21.0, 1.0, 1.0, 1.0));
+
+ scale = gtk_scale_new (GTK_ORIENTATION_HORIZONTAL, scale_data);
+ gtk_scale_set_digits (GTK_SCALE (scale), 0);
+ gtk_scale_set_value_pos (GTK_SCALE (scale), GTK_POS_TOP);
+ gtk_box_pack_start (GTK_BOX (vbox), scale, FALSE, TRUE, 4);
+ gtk_widget_show (scale);
+
+ g_object_set_data (G_OBJECT (dialog), "adjustment", scale_data);
+
+ gtk_widget_set_sensitive (GTK_WIDGET (editor), FALSE);
+ gimp_ui_manager_update (gimp_editor_get_ui_manager (GIMP_EDITOR (editor)),
+ gimp_editor_get_popup_data (GIMP_EDITOR (editor)));
+
+ gtk_widget_show (dialog);
+}
+
+void
+gradient_editor_split_midpoint_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpGradientEditor *editor = GIMP_GRADIENT_EDITOR (data);
+ GimpDataEditor *data_editor = GIMP_DATA_EDITOR (data);
+ GimpGradient *gradient;
+ GimpGradientSegment *left;
+ GimpGradientSegment *right;
+
+ gimp_gradient_editor_get_selection (editor, &gradient, &left, &right);
+
+ gimp_gradient_segment_range_split_midpoint (gradient,
+ data_editor->context,
+ left, right,
+ editor->blend_color_space,
+ &left, &right);
+
+ gimp_gradient_editor_set_selection (editor, left, right);
+}
+
+void
+gradient_editor_split_uniformly_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpGradientEditor *editor = GIMP_GRADIENT_EDITOR (data);
+ GimpDataEditor *data_editor = GIMP_DATA_EDITOR (data);
+ GimpGradient *gradient;
+ GimpGradientSegment *left;
+ GimpGradientSegment *right;
+ GtkWidget *dialog;
+ GtkWidget *vbox;
+ GtkWidget *label;
+ GtkWidget *scale;
+ GtkAdjustment *scale_data;
+ const gchar *title;
+ const gchar *desc;
+
+ gimp_gradient_editor_get_selection (editor, &gradient, &left, &right);
+
+ if (left == right)
+ {
+ title = _("Split Segment Uniformly");
+ desc = _("Split Gradient Segment Uniformly");
+ }
+ else
+ {
+ title = _("Split Segments Uniformly");
+ desc = _("Split Gradient Segments Uniformly");
+ }
+
+ dialog = gimp_viewable_dialog_new (GIMP_VIEWABLE (gradient),
+ data_editor->context,
+ title,
+ "gimp-gradient-segment-split-uniformly",
+ GIMP_ICON_GRADIENT, desc,
+ GTK_WIDGET (editor),
+ gimp_standard_help_func,
+ GIMP_HELP_GRADIENT_EDITOR_SPLIT_UNIFORM,
+
+ _("_Cancel"), GTK_RESPONSE_CANCEL,
+ _("_Split"), GTK_RESPONSE_OK,
+
+ NULL);
+
+ gtk_dialog_set_alternative_button_order (GTK_DIALOG (dialog),
+ GTK_RESPONSE_OK,
+ GTK_RESPONSE_CANCEL,
+ -1);
+
+ g_signal_connect (dialog, "response",
+ G_CALLBACK (gradient_editor_split_uniform_response),
+ editor);
+
+ /* The main vbox */
+ vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
+ gtk_container_set_border_width (GTK_CONTAINER (vbox), 12);
+ gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))),
+ vbox, TRUE, TRUE, 0);
+ gtk_widget_show (vbox);
+
+ /* Instructions */
+ if (left == right)
+ label = gtk_label_new (_("Select the number of uniform parts\n"
+ "in which to split the selected segment."));
+ else
+ label = gtk_label_new (_("Select the number of uniform parts\n"
+ "in which to split the segments in the selection."));
+
+ gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
+ gtk_widget_show (label);
+
+ /* Scale */
+ scale_data = GTK_ADJUSTMENT (gtk_adjustment_new (2.0, 2.0, 21.0, 1.0, 1.0, 1.0));
+
+ scale = gtk_scale_new (GTK_ORIENTATION_HORIZONTAL, scale_data);
+ gtk_scale_set_digits (GTK_SCALE (scale), 0);
+ gtk_scale_set_value_pos (GTK_SCALE (scale), GTK_POS_TOP);
+ gtk_box_pack_start (GTK_BOX (vbox), scale, FALSE, FALSE, 4);
+ gtk_widget_show (scale);
+
+ g_object_set_data (G_OBJECT (dialog), "adjustment", scale_data);
+
+ gtk_widget_set_sensitive (GTK_WIDGET (editor), FALSE);
+ gimp_ui_manager_update (gimp_editor_get_ui_manager (GIMP_EDITOR (editor)),
+ gimp_editor_get_popup_data (GIMP_EDITOR (editor)));
+
+ gtk_widget_show (dialog);
+}
+
+void
+gradient_editor_delete_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpGradientEditor *editor = GIMP_GRADIENT_EDITOR (data);
+ GimpGradient *gradient;
+ GimpGradientSegment *left;
+ GimpGradientSegment *right;
+
+ gimp_gradient_editor_get_selection (editor, &gradient, &left, &right);
+
+ gimp_gradient_segment_range_delete (gradient,
+ left, right,
+ &left, &right);
+
+ gimp_gradient_editor_set_selection (editor, left, right);
+}
+
+void
+gradient_editor_recenter_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpGradientEditor *editor = GIMP_GRADIENT_EDITOR (data);
+ GimpGradient *gradient;
+ GimpGradientSegment *left;
+ GimpGradientSegment *right;
+
+ gimp_gradient_editor_get_selection (editor, &gradient, &left, &right);
+
+ gimp_gradient_segment_range_recenter_handles (gradient, left, right);
+}
+
+void
+gradient_editor_redistribute_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpGradientEditor *editor = GIMP_GRADIENT_EDITOR (data);
+ GimpGradient *gradient;
+ GimpGradientSegment *left;
+ GimpGradientSegment *right;
+
+ gimp_gradient_editor_get_selection (editor, &gradient, &left, &right);
+
+ gimp_gradient_segment_range_redistribute_handles (gradient, left, right);
+}
+
+void
+gradient_editor_blend_color_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpGradientEditor *editor = GIMP_GRADIENT_EDITOR (data);
+ GimpGradient *gradient;
+ GimpGradientSegment *left;
+ GimpGradientSegment *right;
+
+ gimp_gradient_editor_get_selection (editor, &gradient, &left, &right);
+
+ gimp_gradient_segment_range_blend (gradient, left, right,
+ &left->left_color,
+ &right->right_color,
+ TRUE, FALSE);
+}
+
+void
+gradient_editor_blend_opacity_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpGradientEditor *editor = GIMP_GRADIENT_EDITOR (data);
+ GimpGradient *gradient;
+ GimpGradientSegment *left;
+ GimpGradientSegment *right;
+
+ gimp_gradient_editor_get_selection (editor, &gradient, &left, &right);
+
+ gimp_gradient_segment_range_blend (gradient, left, right,
+ &left->left_color,
+ &right->right_color,
+ FALSE, TRUE);
+}
+
+void
+gradient_editor_zoom_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpGradientEditor *editor = GIMP_GRADIENT_EDITOR (data);
+ GimpZoomType zoom_type = (GimpZoomType) g_variant_get_int32 (value);
+
+ gimp_gradient_editor_zoom (editor, zoom_type);
+}
+
+
+/* private functions */
+
+static void
+gradient_editor_split_uniform_response (GtkWidget *widget,
+ gint response_id,
+ GimpGradientEditor *editor)
+{
+ GtkAdjustment *adjustment;
+ gint split_parts;
+
+ adjustment = g_object_get_data (G_OBJECT (widget), "adjustment");
+
+ split_parts = RINT (gtk_adjustment_get_value (adjustment));
+
+ gtk_widget_destroy (widget);
+ gtk_widget_set_sensitive (GTK_WIDGET (editor), TRUE);
+ gimp_ui_manager_update (gimp_editor_get_ui_manager (GIMP_EDITOR (editor)),
+ gimp_editor_get_popup_data (GIMP_EDITOR (editor)));
+
+ if (response_id == GTK_RESPONSE_OK)
+ {
+ GimpDataEditor *data_editor = GIMP_DATA_EDITOR (editor);
+ GimpGradient *gradient;
+ GimpGradientSegment *left;
+ GimpGradientSegment *right;
+
+ gimp_gradient_editor_get_selection (editor, &gradient, &left, &right);
+
+ gimp_gradient_segment_range_split_uniform (gradient,
+ data_editor->context,
+ left, right,
+ split_parts,
+ editor->blend_color_space,
+ &left, &right);
+
+ gimp_gradient_editor_set_selection (editor, left, right);
+ }
+}
+
+static void
+gradient_editor_replicate_response (GtkWidget *widget,
+ gint response_id,
+ GimpGradientEditor *editor)
+{
+ GtkAdjustment *adjustment;
+ gint replicate_times;
+
+ adjustment = g_object_get_data (G_OBJECT (widget), "adjustment");
+
+ replicate_times = RINT (gtk_adjustment_get_value (adjustment));
+
+ gtk_widget_destroy (widget);
+ gtk_widget_set_sensitive (GTK_WIDGET (editor), TRUE);
+ gimp_ui_manager_update (gimp_editor_get_ui_manager (GIMP_EDITOR (editor)),
+ gimp_editor_get_popup_data (GIMP_EDITOR (editor)));
+
+ if (response_id == GTK_RESPONSE_OK)
+ {
+ GimpGradient *gradient;
+ GimpGradientSegment *left;
+ GimpGradientSegment *right;
+
+ gimp_gradient_editor_get_selection (editor, &gradient, &left, &right);
+
+ gimp_gradient_segment_range_replicate (gradient,
+ left, right,
+ replicate_times,
+ &left, &right);
+
+ gimp_gradient_editor_set_selection (editor, left, right);
+ }
+}
diff --git a/app/actions/gradient-editor-commands.h b/app/actions/gradient-editor-commands.h
new file mode 100644
index 0000000..4f930ea
--- /dev/null
+++ b/app/actions/gradient-editor-commands.h
@@ -0,0 +1,99 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GRADIENT_EDITOR_COMMANDS_H__
+#define __GRADIENT_EDITOR_COMMANDS_H__
+
+
+enum
+{
+ GRADIENT_EDITOR_COLOR_NEIGHBOR_ENDPOINT,
+ GRADIENT_EDITOR_COLOR_OTHER_ENDPOINT,
+ GRADIENT_EDITOR_COLOR_FOREGROUND,
+ GRADIENT_EDITOR_COLOR_BACKGROUND,
+ GRADIENT_EDITOR_COLOR_FIRST_CUSTOM
+};
+
+
+void gradient_editor_left_color_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void gradient_editor_left_color_type_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void gradient_editor_load_left_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void gradient_editor_save_left_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+void gradient_editor_right_color_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void gradient_editor_right_color_type_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void gradient_editor_load_right_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void gradient_editor_save_right_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+void gradient_editor_blending_func_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void gradient_editor_coloring_type_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+void gradient_editor_flip_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void gradient_editor_replicate_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void gradient_editor_split_midpoint_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void gradient_editor_split_uniformly_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void gradient_editor_delete_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void gradient_editor_recenter_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void gradient_editor_redistribute_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+void gradient_editor_blend_color_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void gradient_editor_blend_opacity_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+void gradient_editor_zoom_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+
+#endif /* __GRADIENT_EDITOR_COMMANDS_H__ */
diff --git a/app/actions/gradients-actions.c b/app/actions/gradients-actions.c
new file mode 100644
index 0000000..f4b22ef
--- /dev/null
+++ b/app/actions/gradients-actions.c
@@ -0,0 +1,150 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "actions-types.h"
+
+#include "core/gimpcontext.h"
+#include "core/gimpdata.h"
+
+#include "widgets/gimpactiongroup.h"
+#include "widgets/gimphelp-ids.h"
+
+#include "actions.h"
+#include "data-commands.h"
+#include "gradients-actions.h"
+#include "gradients-commands.h"
+
+#include "gimp-intl.h"
+
+
+static const GimpActionEntry gradients_actions[] =
+{
+ { "gradients-popup", GIMP_ICON_GRADIENT,
+ NC_("gradients-action", "Gradients Menu"), NULL, NULL, NULL,
+ GIMP_HELP_GRADIENT_DIALOG },
+
+ { "gradients-new", GIMP_ICON_DOCUMENT_NEW,
+ NC_("gradients-action", "_New Gradient"), NULL,
+ NC_("gradients-action", "Create a new gradient"),
+ data_new_cmd_callback,
+ GIMP_HELP_GRADIENT_NEW },
+
+ { "gradients-duplicate", GIMP_ICON_OBJECT_DUPLICATE,
+ NC_("gradients-action", "D_uplicate Gradient"), NULL,
+ NC_("gradients-action", "Duplicate this gradient"),
+ data_duplicate_cmd_callback,
+ GIMP_HELP_GRADIENT_DUPLICATE },
+
+ { "gradients-copy-location", GIMP_ICON_EDIT_COPY,
+ NC_("gradients-action", "Copy Gradient _Location"), NULL,
+ NC_("gradients-action", "Copy gradient file location to clipboard"),
+ data_copy_location_cmd_callback,
+ GIMP_HELP_GRADIENT_COPY_LOCATION },
+
+ { "gradients-show-in-file-manager", GIMP_ICON_FILE_MANAGER,
+ NC_("gradients-action", "Show in _File Manager"), NULL,
+ NC_("gradients-action", "Show gradient file location in the file manager"),
+ data_show_in_file_manager_cmd_callback,
+ GIMP_HELP_GRADIENT_SHOW_IN_FILE_MANAGER },
+
+ { "gradients-save-as-pov", GIMP_ICON_DOCUMENT_SAVE_AS,
+ NC_("gradients-action", "Save as _POV-Ray..."), NULL,
+ NC_("gradients-action", "Save gradient as POV-Ray"),
+ gradients_save_as_pov_ray_cmd_callback,
+ GIMP_HELP_GRADIENT_SAVE_AS_POV },
+
+ { "gradients-delete", GIMP_ICON_EDIT_DELETE,
+ NC_("gradients-action", "_Delete Gradient"), NULL,
+ NC_("gradients-action", "Delete this gradient"),
+ data_delete_cmd_callback,
+ GIMP_HELP_GRADIENT_DELETE },
+
+ { "gradients-refresh", GIMP_ICON_VIEW_REFRESH,
+ NC_("gradients-action", "_Refresh Gradients"), NULL,
+ NC_("gradients-action", "Refresh gradients"),
+ data_refresh_cmd_callback,
+ GIMP_HELP_GRADIENT_REFRESH }
+};
+
+static const GimpStringActionEntry gradients_edit_actions[] =
+{
+ { "gradients-edit", GIMP_ICON_EDIT,
+ NC_("gradients-action", "_Edit Gradient..."), NULL,
+ NC_("gradients-action", "Edit this gradient"),
+ "gimp-gradient-editor",
+ GIMP_HELP_GRADIENT_EDIT }
+};
+
+
+void
+gradients_actions_setup (GimpActionGroup *group)
+{
+ gimp_action_group_add_actions (group, "gradients-action",
+ gradients_actions,
+ G_N_ELEMENTS (gradients_actions));
+
+ gimp_action_group_add_string_actions (group, "gradients-action",
+ gradients_edit_actions,
+ G_N_ELEMENTS (gradients_edit_actions),
+ data_edit_cmd_callback);
+}
+
+void
+gradients_actions_update (GimpActionGroup *group,
+ gpointer user_data)
+{
+ GimpContext *context = action_data_get_context (user_data);
+ GimpGradient *gradient = NULL;
+ GimpData *data = NULL;
+ GFile *file = NULL;
+
+ if (context)
+ {
+ gradient = gimp_context_get_gradient (context);
+
+ if (action_data_sel_count (user_data) > 1)
+ {
+ gradient = NULL;
+ }
+
+ if (gradient)
+ {
+ data = GIMP_DATA (gradient);
+
+ file = gimp_data_get_file (data);
+ }
+ }
+
+#define SET_SENSITIVE(action,condition) \
+ gimp_action_group_set_action_sensitive (group, action, (condition) != 0)
+
+ SET_SENSITIVE ("gradients-edit", gradient);
+ SET_SENSITIVE ("gradients-duplicate", gradient);
+ SET_SENSITIVE ("gradients-save-as-pov", gradient);
+ SET_SENSITIVE ("gradients-copy-location", file);
+ SET_SENSITIVE ("gradients-show-in-file-manager", file);
+ SET_SENSITIVE ("gradients-delete", gradient && gimp_data_is_deletable (data));
+
+#undef SET_SENSITIVE
+}
diff --git a/app/actions/gradients-actions.h b/app/actions/gradients-actions.h
new file mode 100644
index 0000000..c8ee1ce
--- /dev/null
+++ b/app/actions/gradients-actions.h
@@ -0,0 +1,27 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GRADIENTS_ACTIONS_H__
+#define __GRADIENTS_ACTIONS_H__
+
+
+void gradients_actions_setup (GimpActionGroup *group);
+void gradients_actions_update (GimpActionGroup *group,
+ gpointer user_data);
+
+
+#endif /* __GRADIENT_ACTIONS_H__ */
diff --git a/app/actions/gradients-commands.c b/app/actions/gradients-commands.c
new file mode 100644
index 0000000..40b71fd
--- /dev/null
+++ b/app/actions/gradients-commands.c
@@ -0,0 +1,151 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "actions-types.h"
+
+#include "core/gimp.h"
+#include "core/gimpgradient-save.h"
+#include "core/gimpcontext.h"
+
+#include "widgets/gimpcontainereditor.h"
+#include "widgets/gimpcontainerview.h"
+#include "widgets/gimphelp-ids.h"
+
+#include "dialogs/dialogs.h"
+
+#include "gradients-commands.h"
+
+#include "gimp-intl.h"
+
+
+/* local function prototypes */
+
+static void gradients_save_as_pov_ray_response (GtkWidget *dialog,
+ gint response_id,
+ GimpGradient *gradient);
+
+
+/* public functions */
+
+void
+gradients_save_as_pov_ray_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpContainerEditor *editor = GIMP_CONTAINER_EDITOR (data);
+ GimpContext *context;
+ GimpGradient *gradient;
+ GtkWidget *dialog;
+
+ context = gimp_container_view_get_context (editor->view);
+ gradient = gimp_context_get_gradient (context);
+
+ if (! gradient)
+ return;
+
+#define SAVE_AS_POV_DIALOG_KEY "gimp-save-as-pov-ray-dialog"
+
+ dialog = dialogs_get_dialog (G_OBJECT (gradient), SAVE_AS_POV_DIALOG_KEY);
+
+ if (! dialog)
+ {
+ gchar *title = g_strdup_printf (_("Save '%s' as POV-Ray"),
+ gimp_object_get_name (gradient));
+
+ dialog = gtk_file_chooser_dialog_new (title, NULL,
+ GTK_FILE_CHOOSER_ACTION_SAVE,
+
+ _("_Cancel"), GTK_RESPONSE_CANCEL,
+ _("_Save"), GTK_RESPONSE_OK,
+
+ NULL);
+
+ g_free (title);
+
+ gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
+ gtk_dialog_set_alternative_button_order (GTK_DIALOG (dialog),
+ GTK_RESPONSE_OK,
+ GTK_RESPONSE_CANCEL,
+ -1);
+
+ g_object_set_data (G_OBJECT (dialog), "gimp", context->gimp);
+
+ gtk_window_set_screen (GTK_WINDOW (dialog),
+ gtk_widget_get_screen (GTK_WIDGET (editor)));
+ gtk_window_set_role (GTK_WINDOW (dialog), "gimp-gradient-save-pov");
+ gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE);
+
+ gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog),
+ TRUE);
+
+ g_signal_connect (dialog, "response",
+ G_CALLBACK (gradients_save_as_pov_ray_response),
+ gradient);
+ g_signal_connect (dialog, "delete-event",
+ G_CALLBACK (gtk_true),
+ NULL);
+
+ g_signal_connect_object (dialog, "destroy",
+ G_CALLBACK (g_object_unref),
+ g_object_ref (gradient),
+ G_CONNECT_SWAPPED);
+
+ gimp_help_connect (dialog, gimp_standard_help_func,
+ GIMP_HELP_GRADIENT_SAVE_AS_POV, NULL);
+
+ dialogs_attach_dialog (G_OBJECT (gradient),
+ SAVE_AS_POV_DIALOG_KEY, dialog);
+ }
+
+ gtk_window_present (GTK_WINDOW (dialog));
+}
+
+
+/* private functions */
+
+static void
+gradients_save_as_pov_ray_response (GtkWidget *dialog,
+ gint response_id,
+ GimpGradient *gradient)
+{
+ if (response_id == GTK_RESPONSE_OK)
+ {
+ GFile *file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog));
+ GError *error = NULL;
+
+ if (! gimp_gradient_save_pov (gradient, file, &error))
+ {
+ gimp_message_literal (g_object_get_data (G_OBJECT (dialog), "gimp"),
+ G_OBJECT (dialog), GIMP_MESSAGE_ERROR,
+ error->message);
+ g_clear_error (&error);
+ g_object_unref (file);
+ return;
+ }
+
+ g_object_unref (file);
+ }
+
+ gtk_widget_destroy (dialog);
+}
diff --git a/app/actions/gradients-commands.h b/app/actions/gradients-commands.h
new file mode 100644
index 0000000..938f3ff
--- /dev/null
+++ b/app/actions/gradients-commands.h
@@ -0,0 +1,27 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GRADIENTS_COMMANDS_H__
+#define __GRADIENTS_COMMANDS_H__
+
+
+void gradients_save_as_pov_ray_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+
+#endif /* __GRADIENTS_COMMANDS_H__ */
diff --git a/app/actions/help-actions.c b/app/actions/help-actions.c
new file mode 100644
index 0000000..6b1502a
--- /dev/null
+++ b/app/actions/help-actions.c
@@ -0,0 +1,66 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "actions-types.h"
+
+#include "widgets/gimpactiongroup.h"
+#include "widgets/gimphelp-ids.h"
+
+#include "help-actions.h"
+#include "help-commands.h"
+
+#include "gimp-intl.h"
+
+
+static const GimpActionEntry help_actions[] =
+{
+ { "help-menu", NULL, NC_("help-action", "_Help") },
+
+ { "help-help", "gimp-prefs-help-system",
+ NC_("help-action", "_Help"), "F1",
+ NC_("help-action", "Open the GIMP user manual"),
+ help_help_cmd_callback,
+ GIMP_HELP_HELP },
+
+ { "help-context-help", "gimp-prefs-help-system",
+ NC_("help-action", "_Context Help"), "<shift>F1",
+ NC_("help-action", "Show the help for a specific user interface item"),
+ help_context_help_cmd_callback,
+ GIMP_HELP_HELP_CONTEXT }
+};
+
+
+void
+help_actions_setup (GimpActionGroup *group)
+{
+ gimp_action_group_add_actions (group, "help-action",
+ help_actions,
+ G_N_ELEMENTS (help_actions));
+}
+
+void
+help_actions_update (GimpActionGroup *group,
+ gpointer data)
+{
+}
diff --git a/app/actions/help-actions.h b/app/actions/help-actions.h
new file mode 100644
index 0000000..970dc97
--- /dev/null
+++ b/app/actions/help-actions.h
@@ -0,0 +1,27 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __HELP_ACTIONS_H__
+#define __HELP_ACTIONS_H__
+
+
+void help_actions_setup (GimpActionGroup *group);
+void help_actions_update (GimpActionGroup *group,
+ gpointer data);
+
+
+#endif /* __HELP_ACTIONS_H__ */
diff --git a/app/actions/help-commands.c b/app/actions/help-commands.c
new file mode 100644
index 0000000..9e9693a
--- /dev/null
+++ b/app/actions/help-commands.c
@@ -0,0 +1,57 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "actions-types.h"
+
+#include "core/gimpprogress.h"
+
+#include "widgets/gimphelp.h"
+
+#include "actions.h"
+#include "help-commands.h"
+
+
+void
+help_help_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ Gimp *gimp;
+ GimpDisplay *display;
+ return_if_no_gimp (gimp, data);
+ return_if_no_display (display, data);
+
+ gimp_help_show (gimp, GIMP_PROGRESS (display), NULL, NULL);
+}
+
+void
+help_context_help_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GtkWidget *widget;
+ return_if_no_widget (widget, data);
+
+ gimp_context_help (widget);
+}
diff --git a/app/actions/help-commands.h b/app/actions/help-commands.h
new file mode 100644
index 0000000..61ce201
--- /dev/null
+++ b/app/actions/help-commands.h
@@ -0,0 +1,30 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __HELP_COMMANDS_H__
+#define __HELP_COMMANDS_H__
+
+
+void help_help_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void help_context_help_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+
+#endif /* __HELP_COMMANDS_H__ */
diff --git a/app/actions/image-actions.c b/app/actions/image-actions.c
new file mode 100644
index 0000000..213933f
--- /dev/null
+++ b/app/actions/image-actions.c
@@ -0,0 +1,497 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "actions-types.h"
+
+#include "config/gimpguiconfig.h"
+
+#include "gegl/gimp-babl.h"
+
+#include "core/gimp.h"
+#include "core/gimpchannel.h"
+#include "core/gimpcontext.h"
+#include "core/gimpimage.h"
+#include "core/gimpimage-color-profile.h"
+#include "core/gimpitemstack.h"
+
+#include "widgets/gimpactiongroup.h"
+#include "widgets/gimphelp-ids.h"
+
+#include "actions.h"
+#include "image-actions.h"
+#include "image-commands.h"
+
+#include "gimp-intl.h"
+
+
+static const GimpActionEntry image_actions[] =
+{
+ { "image-menubar", NULL,
+ NC_("image-action", "Image Menu"), NULL, NULL, NULL,
+ GIMP_HELP_IMAGE_WINDOW },
+
+ { "image-popup", NULL,
+ NC_("image-action", "Image Menu"), NULL, NULL, NULL,
+ GIMP_HELP_IMAGE_WINDOW },
+
+ { "image-menu", NULL, NC_("image-action", "_Image") },
+ { "image-mode-menu", NULL, NC_("image-action", "_Mode") },
+ { "image-precision-menu", NULL, NC_("image-action", "Pr_ecision") },
+#if PENDING_TRANSLATION
+ { "image-precision-menu", NULL, NC_("image-action", "_Encoding") },
+#endif
+ { "image-color-management-menu", NULL, NC_("image-action",
+ "Color Ma_nagement") },
+ { "image-transform-menu", NULL, NC_("image-action", "_Transform") },
+ { "image-guides-menu", NULL, NC_("image-action", "_Guides") },
+ { "image-metadata-menu", NULL, NC_("image-action", "Meta_data") },
+
+ { "colors-menu", NULL, NC_("image-action", "_Colors") },
+ { "colors-info-menu", NULL, NC_("image-action", "I_nfo") },
+ { "colors-auto-menu", NULL, NC_("image-action", "_Auto") },
+ { "colors-map-menu", NULL, NC_("image-action", "_Map") },
+ { "colors-tone-mapping-menu", NULL, NC_("image-action", "_Tone Mapping") },
+ { "colors-components-menu", NULL, NC_("image-action", "C_omponents") },
+ { "colors-desaturate-menu", NULL, NC_("image-action", "D_esaturate") },
+
+ { "image-new", GIMP_ICON_DOCUMENT_NEW,
+ NC_("image-action", "_New..."), "<primary>N",
+ NC_("image-action", "Create a new image"),
+ image_new_cmd_callback,
+ GIMP_HELP_FILE_NEW },
+
+ { "image-duplicate", GIMP_ICON_OBJECT_DUPLICATE,
+ NC_("image-action", "_Duplicate"), "<primary>D",
+ NC_("image-action", "Create a duplicate of this image"),
+ image_duplicate_cmd_callback,
+ GIMP_HELP_IMAGE_DUPLICATE },
+
+ { "image-color-profile-assign", NULL,
+ NC_("image-action", "_Assign Color Profile..."), NULL,
+ NC_("image-action", "Set a color profile on the image"),
+ image_color_profile_assign_cmd_callback,
+ GIMP_HELP_IMAGE_COLOR_PROFILE_ASSIGN },
+
+ { "image-color-profile-convert", NULL,
+ NC_("image-action", "_Convert to Color Profile..."), NULL,
+ NC_("image-action", "Apply a color profile to the image"),
+ image_color_profile_convert_cmd_callback,
+ GIMP_HELP_IMAGE_COLOR_PROFILE_CONVERT },
+
+ { "image-color-profile-discard", NULL,
+ NC_("image-action", "_Discard Color Profile"), NULL,
+ NC_("image-action", "Remove the image's color profile"),
+ image_color_profile_discard_cmd_callback,
+ GIMP_HELP_IMAGE_COLOR_PROFILE_DISCARD },
+
+ { "image-color-profile-save", NULL,
+ NC_("image-action", "_Save Color Profile to File..."), NULL,
+ NC_("image-action", "Save the image's color profile to an ICC file"),
+ image_color_profile_save_cmd_callback,
+ GIMP_HELP_IMAGE_COLOR_PROFILE_SAVE },
+
+ { "image-resize", GIMP_ICON_OBJECT_RESIZE,
+ NC_("image-action", "Can_vas Size..."), NULL,
+ NC_("image-action", "Adjust the image dimensions"),
+ image_resize_cmd_callback,
+ GIMP_HELP_IMAGE_RESIZE },
+
+ { "image-resize-to-layers", NULL,
+ NC_("image-action", "Fit Canvas to L_ayers"), NULL,
+ NC_("image-action", "Resize the image to enclose all layers"),
+ image_resize_to_layers_cmd_callback,
+ GIMP_HELP_IMAGE_RESIZE_TO_LAYERS },
+
+ { "image-resize-to-selection", NULL,
+ NC_("image-action", "F_it Canvas to Selection"), NULL,
+ NC_("image-action", "Resize the image to the extents of the selection"),
+ image_resize_to_selection_cmd_callback,
+ GIMP_HELP_IMAGE_RESIZE_TO_SELECTION },
+
+ { "image-print-size", GIMP_ICON_DOCUMENT_PRINT_RESOLUTION,
+ NC_("image-action", "_Print Size..."), NULL,
+ NC_("image-action", "Adjust the print resolution"),
+ image_print_size_cmd_callback,
+ GIMP_HELP_IMAGE_PRINT_SIZE },
+
+ { "image-scale", GIMP_ICON_OBJECT_SCALE,
+ NC_("image-action", "_Scale Image..."), NULL,
+ NC_("image-action", "Change the size of the image content"),
+ image_scale_cmd_callback,
+ GIMP_HELP_IMAGE_SCALE },
+
+ { "image-crop-to-selection", GIMP_ICON_TOOL_CROP,
+ NC_("image-action", "_Crop to Selection"), NULL,
+ NC_("image-action", "Crop the image to the extents of the selection"),
+ image_crop_to_selection_cmd_callback,
+ GIMP_HELP_IMAGE_CROP },
+
+ { "image-crop-to-content", GIMP_ICON_TOOL_CROP,
+ NC_("image-action", "Crop to C_ontent"), NULL,
+ NC_("image-action", "Crop the image to the extents of its content (remove empty borders from the image)"),
+ image_crop_to_content_cmd_callback,
+ GIMP_HELP_IMAGE_CROP },
+
+ { "image-merge-layers", NULL,
+ NC_("image-action", "Merge Visible _Layers..."), "<primary>M",
+ NC_("image-action", "Merge all visible layers into one layer"),
+ image_merge_layers_cmd_callback,
+ GIMP_HELP_IMAGE_MERGE_LAYERS },
+
+ { "image-flatten", NULL,
+ NC_("image-action", "_Flatten Image"), NULL,
+ NC_("image-action", "Merge all layers into one and remove transparency"),
+ image_flatten_image_cmd_callback,
+ GIMP_HELP_IMAGE_FLATTEN },
+
+ { "image-configure-grid", GIMP_ICON_GRID,
+ NC_("image-action", "Configure G_rid..."), NULL,
+ NC_("image-action", "Configure the grid for this image"),
+ image_configure_grid_cmd_callback,
+ GIMP_HELP_IMAGE_GRID },
+
+ { "image-properties", "dialog-information",
+ NC_("image-action", "Image Pr_operties"), "<alt>Return",
+ NC_("image-action", "Display information about this image"),
+ image_properties_cmd_callback,
+ GIMP_HELP_IMAGE_PROPERTIES }
+};
+
+static const GimpToggleActionEntry image_toggle_actions[] =
+{
+ { "image-color-management-enabled", NULL,
+ NC_("image-action", "_Enable Color Management"), NULL,
+ NC_("image-action", "Whether the image is color managed. Disabling "
+ "color management is equivalent to assigning a built-in sRGB "
+ "color profile. Better leave color management enabled."),
+ image_color_management_enabled_cmd_callback,
+ TRUE,
+ GIMP_HELP_IMAGE_COLOR_MANAGEMENT_ENABLED }
+};
+
+static const GimpRadioActionEntry image_convert_base_type_actions[] =
+{
+ { "image-convert-rgb", GIMP_ICON_CONVERT_RGB,
+ NC_("image-convert-action", "_RGB"), NULL,
+ NC_("image-convert-action", "Convert the image to the RGB colorspace"),
+ GIMP_RGB, GIMP_HELP_IMAGE_CONVERT_RGB },
+
+ { "image-convert-grayscale", GIMP_ICON_CONVERT_GRAYSCALE,
+ NC_("image-convert-action", "_Grayscale"), NULL,
+ NC_("image-convert-action", "Convert the image to grayscale"),
+ GIMP_GRAY, GIMP_HELP_IMAGE_CONVERT_GRAYSCALE },
+
+ { "image-convert-indexed", GIMP_ICON_CONVERT_INDEXED,
+ NC_("image-convert-action", "_Indexed..."), NULL,
+ NC_("image-convert-action", "Convert the image to indexed colors"),
+ GIMP_INDEXED, GIMP_HELP_IMAGE_CONVERT_INDEXED }
+};
+
+static const GimpRadioActionEntry image_convert_precision_actions[] =
+{
+ { "image-convert-u8", NULL,
+ NC_("image-convert-action", "8 bit integer"), NULL,
+ NC_("image-convert-action",
+ "Convert the image to 8 bit integer"),
+ GIMP_COMPONENT_TYPE_U8, GIMP_HELP_IMAGE_CONVERT_U8 },
+
+ { "image-convert-u16", NULL,
+ NC_("image-convert-action", "16 bit integer"), NULL,
+ NC_("image-convert-action",
+ "Convert the image to 16 bit integer"),
+ GIMP_COMPONENT_TYPE_U16, GIMP_HELP_IMAGE_CONVERT_U16 },
+
+ { "image-convert-u32", NULL,
+ NC_("image-convert-action", "32 bit integer"), NULL,
+ NC_("image-convert-action",
+ "Convert the image to 32 bit integer"),
+ GIMP_COMPONENT_TYPE_U32, GIMP_HELP_IMAGE_CONVERT_U32 },
+
+ { "image-convert-half", NULL,
+ NC_("image-convert-action", "16 bit floating point"), NULL,
+ NC_("image-convert-action",
+ "Convert the image to 16 bit floating point"),
+ GIMP_COMPONENT_TYPE_HALF, GIMP_HELP_IMAGE_CONVERT_HALF },
+
+ { "image-convert-float", NULL,
+ NC_("image-convert-action", "32 bit floating point"), NULL,
+ NC_("image-convert-action",
+ "Convert the image to 32 bit floating point"),
+ GIMP_COMPONENT_TYPE_FLOAT, GIMP_HELP_IMAGE_CONVERT_FLOAT },
+
+ { "image-convert-double", NULL,
+ NC_("image-convert-action", "64 bit floating point"), NULL,
+ NC_("image-convert-action",
+ "Convert the image to 64 bit floating point"),
+ GIMP_COMPONENT_TYPE_DOUBLE, GIMP_HELP_IMAGE_CONVERT_DOUBLE }
+};
+
+static const GimpRadioActionEntry image_convert_gamma_actions[] =
+{
+ { "image-convert-gamma", NULL,
+ NC_("image-convert-action", "Perceptual gamma (sRGB)"), NULL,
+ NC_("image-convert-action",
+ "Convert the image to perceptual (sRGB) gamma"),
+ FALSE, GIMP_HELP_IMAGE_CONVERT_GAMMA },
+
+ { "image-convert-linear", NULL,
+ NC_("image-convert-action", "Linear light"), NULL,
+ NC_("image-convert-action",
+ "Convert the image to linear light"),
+ TRUE, GIMP_HELP_IMAGE_CONVERT_GAMMA }
+};
+
+static const GimpEnumActionEntry image_flip_actions[] =
+{
+ { "image-flip-horizontal", GIMP_ICON_OBJECT_FLIP_HORIZONTAL,
+ NC_("image-action", "Flip _Horizontally"), NULL,
+ NC_("image-action", "Flip image horizontally"),
+ GIMP_ORIENTATION_HORIZONTAL, FALSE,
+ GIMP_HELP_IMAGE_FLIP_HORIZONTAL },
+
+ { "image-flip-vertical", GIMP_ICON_OBJECT_FLIP_VERTICAL,
+ NC_("image-action", "Flip _Vertically"), NULL,
+ NC_("image-action", "Flip image vertically"),
+ GIMP_ORIENTATION_VERTICAL, FALSE,
+ GIMP_HELP_IMAGE_FLIP_VERTICAL }
+};
+
+static const GimpEnumActionEntry image_rotate_actions[] =
+{
+ { "image-rotate-90", GIMP_ICON_OBJECT_ROTATE_90,
+ NC_("image-action", "Rotate 90° _clockwise"), NULL,
+ NC_("image-action", "Rotate the image 90 degrees to the right"),
+ GIMP_ROTATE_90, FALSE,
+ GIMP_HELP_IMAGE_ROTATE_90 },
+
+ { "image-rotate-180", GIMP_ICON_OBJECT_ROTATE_180,
+ NC_("image-action", "Rotate _180°"), NULL,
+ NC_("image-action", "Turn the image upside-down"),
+ GIMP_ROTATE_180, FALSE,
+ GIMP_HELP_IMAGE_ROTATE_180 },
+
+ { "image-rotate-270", GIMP_ICON_OBJECT_ROTATE_270,
+ NC_("image-action", "Rotate 90° counter-clock_wise"), NULL,
+ NC_("image-action", "Rotate the image 90 degrees to the left"),
+ GIMP_ROTATE_270, FALSE,
+ GIMP_HELP_IMAGE_ROTATE_270 }
+};
+
+
+void
+image_actions_setup (GimpActionGroup *group)
+{
+ gimp_action_group_add_actions (group, "image-action",
+ image_actions,
+ G_N_ELEMENTS (image_actions));
+
+ gimp_action_group_add_toggle_actions (group, "image-action",
+ image_toggle_actions,
+ G_N_ELEMENTS (image_toggle_actions));
+
+ gimp_action_group_add_radio_actions (group, "image-convert-action",
+ image_convert_base_type_actions,
+ G_N_ELEMENTS (image_convert_base_type_actions),
+ NULL, 0,
+ image_convert_base_type_cmd_callback);
+
+ gimp_action_group_add_radio_actions (group, "image-convert-action",
+ image_convert_precision_actions,
+ G_N_ELEMENTS (image_convert_precision_actions),
+ NULL, 0,
+ image_convert_precision_cmd_callback);
+
+ gimp_action_group_add_radio_actions (group, "image-convert-action",
+ image_convert_gamma_actions,
+ G_N_ELEMENTS (image_convert_gamma_actions),
+ NULL, 0,
+ image_convert_gamma_cmd_callback);
+
+ gimp_action_group_add_enum_actions (group, "image-action",
+ image_flip_actions,
+ G_N_ELEMENTS (image_flip_actions),
+ image_flip_cmd_callback);
+
+ gimp_action_group_add_enum_actions (group, "image-action",
+ image_rotate_actions,
+ G_N_ELEMENTS (image_rotate_actions),
+ image_rotate_cmd_callback);
+
+#define SET_ALWAYS_SHOW_IMAGE(action,show) \
+ gimp_action_group_set_action_always_show_image (group, action, show)
+
+ SET_ALWAYS_SHOW_IMAGE ("image-rotate-90", TRUE);
+ SET_ALWAYS_SHOW_IMAGE ("image-rotate-180", TRUE);
+ SET_ALWAYS_SHOW_IMAGE ("image-rotate-270", TRUE);
+
+#undef SET_ALWAYS_SHOW_IMAGE
+}
+
+void
+image_actions_update (GimpActionGroup *group,
+ gpointer data)
+{
+ GimpImage *image = action_data_get_image (data);
+ gboolean is_indexed = FALSE;
+ gboolean is_u8_gamma = FALSE;
+ gboolean is_double = FALSE;
+ gboolean aux = FALSE;
+ gboolean lp = FALSE;
+ gboolean sel = FALSE;
+ gboolean groups = FALSE;
+ gboolean color_managed = FALSE;
+ gboolean profile = FALSE;
+
+ if (image)
+ {
+ GimpContainer *layers;
+ const gchar *action = NULL;
+ GimpImageBaseType base_type;
+ GimpPrecision precision;
+ GimpComponentType component_type;
+
+ base_type = gimp_image_get_base_type (image);
+ precision = gimp_image_get_precision (image);
+ component_type = gimp_image_get_component_type (image);
+
+ switch (base_type)
+ {
+ case GIMP_RGB: action = "image-convert-rgb"; break;
+ case GIMP_GRAY: action = "image-convert-grayscale"; break;
+ case GIMP_INDEXED: action = "image-convert-indexed"; break;
+ }
+
+ gimp_action_group_set_action_active (group, action, TRUE);
+
+ switch (component_type)
+ {
+ case GIMP_COMPONENT_TYPE_U8: action = "image-convert-u8"; break;
+ case GIMP_COMPONENT_TYPE_U16: action = "image-convert-u16"; break;
+ case GIMP_COMPONENT_TYPE_U32: action = "image-convert-u32"; break;
+ case GIMP_COMPONENT_TYPE_HALF: action = "image-convert-half"; break;
+ case GIMP_COMPONENT_TYPE_FLOAT: action = "image-convert-float"; break;
+ case GIMP_COMPONENT_TYPE_DOUBLE: action = "image-convert-double"; break;
+ }
+
+ gimp_action_group_set_action_active (group, action, TRUE);
+
+ if (gimp_babl_format_get_linear (gimp_image_get_layer_format (image,
+ FALSE)))
+ {
+ gimp_action_group_set_action_active (group, "image-convert-linear",
+ TRUE);
+ }
+ else
+ {
+ gimp_action_group_set_action_active (group, "image-convert-gamma",
+ TRUE);
+ }
+
+ is_indexed = (base_type == GIMP_INDEXED);
+ is_u8_gamma = (precision == GIMP_PRECISION_U8_GAMMA);
+ is_double = (component_type == GIMP_COMPONENT_TYPE_DOUBLE);
+ aux = (gimp_image_get_active_channel (image) != NULL);
+ lp = ! gimp_image_is_empty (image);
+ sel = ! gimp_channel_is_empty (gimp_image_get_mask (image));
+
+ layers = gimp_image_get_layers (image);
+
+ groups = ! gimp_item_stack_is_flat (GIMP_ITEM_STACK (layers));
+
+ color_managed = gimp_image_get_is_color_managed (image);
+ profile = (gimp_image_get_color_profile (image) != NULL);
+ }
+
+#define SET_LABEL(action,label) \
+ gimp_action_group_set_action_label (group, action, (label))
+#define SET_SENSITIVE(action,condition) \
+ gimp_action_group_set_action_sensitive (group, action, (condition) != 0)
+#define SET_ACTIVE(action,condition) \
+ gimp_action_group_set_action_active (group, action, (condition) != 0)
+#define SET_VISIBLE(action,condition) \
+ gimp_action_group_set_action_visible (group, action, (condition) != 0)
+
+ SET_SENSITIVE ("image-duplicate", image);
+
+ if (profile)
+ {
+ SET_LABEL ("image-convert-rgb",
+ C_("image-convert-action", "_RGB..."));
+ SET_LABEL ("image-convert-grayscale",
+ C_("image-convert-action", "_Grayscale..."));
+ }
+ else
+ {
+ SET_LABEL ("image-convert-rgb",
+ C_("image-convert-action", "_RGB"));
+ SET_LABEL ("image-convert-grayscale",
+ C_("image-convert-action", "_Grayscale"));
+ }
+
+ SET_SENSITIVE ("image-convert-rgb", image);
+ SET_SENSITIVE ("image-convert-grayscale", image);
+ SET_SENSITIVE ("image-convert-indexed", image && !groups && is_u8_gamma);
+
+ SET_SENSITIVE ("image-convert-u8", image);
+ SET_SENSITIVE ("image-convert-u16", image && !is_indexed);
+ SET_SENSITIVE ("image-convert-u32", image && !is_indexed);
+ SET_SENSITIVE ("image-convert-half", image && !is_indexed);
+ SET_SENSITIVE ("image-convert-float", image && !is_indexed);
+ SET_SENSITIVE ("image-convert-double", image && !is_indexed);
+ SET_VISIBLE ("image-convert-double", is_double);
+
+ SET_SENSITIVE ("image-convert-gamma", image);
+ SET_SENSITIVE ("image-convert-linear", image && !is_indexed);
+
+ SET_SENSITIVE ("image-color-management-enabled", image);
+ SET_ACTIVE ("image-color-management-enabled", image && color_managed);
+
+ SET_SENSITIVE ("image-color-profile-assign", image);
+ SET_SENSITIVE ("image-color-profile-convert", image);
+ SET_SENSITIVE ("image-color-profile-discard", image && profile);
+ SET_SENSITIVE ("image-color-profile-save", image);
+
+ SET_SENSITIVE ("image-flip-horizontal", image);
+ SET_SENSITIVE ("image-flip-vertical", image);
+ SET_SENSITIVE ("image-rotate-90", image);
+ SET_SENSITIVE ("image-rotate-180", image);
+ SET_SENSITIVE ("image-rotate-270", image);
+
+ SET_SENSITIVE ("image-resize", image);
+ SET_SENSITIVE ("image-resize-to-layers", image);
+ SET_SENSITIVE ("image-resize-to-selection", image && sel);
+ SET_SENSITIVE ("image-print-size", image);
+ SET_SENSITIVE ("image-scale", image);
+ SET_SENSITIVE ("image-crop-to-selection", image && sel);
+ SET_SENSITIVE ("image-crop-to-content", image);
+ SET_SENSITIVE ("image-merge-layers", image && !aux && lp);
+ SET_SENSITIVE ("image-flatten", image && !aux && lp);
+ SET_SENSITIVE ("image-configure-grid", image);
+ SET_SENSITIVE ("image-properties", image);
+
+#undef SET_LABEL
+#undef SET_SENSITIVE
+#undef SET_ACTIVE
+#undef SET_VISIBLE
+}
diff --git a/app/actions/image-actions.h b/app/actions/image-actions.h
new file mode 100644
index 0000000..802f7af
--- /dev/null
+++ b/app/actions/image-actions.h
@@ -0,0 +1,27 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __IMAGE_ACTIONS_H__
+#define __IMAGE_ACTIONS_H__
+
+
+void image_actions_setup (GimpActionGroup *group);
+void image_actions_update (GimpActionGroup *group,
+ gpointer data);
+
+
+#endif /* __IMAGE_ACTIONS_H__ */
diff --git a/app/actions/image-commands.c b/app/actions/image-commands.c
new file mode 100644
index 0000000..536ee6f
--- /dev/null
+++ b/app/actions/image-commands.c
@@ -0,0 +1,1581 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpbase/gimpbase.h"
+#include "libgimpcolor/gimpcolor.h"
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "actions-types.h"
+
+#include "config/gimpdialogconfig.h"
+
+#include "gegl/gimp-babl.h"
+
+#include "core/core-enums.h"
+#include "core/gimp.h"
+#include "core/gimpcontext.h"
+#include "core/gimpimage.h"
+#include "core/gimpimage-color-profile.h"
+#include "core/gimpimage-convert-indexed.h"
+#include "core/gimpimage-convert-precision.h"
+#include "core/gimpimage-convert-type.h"
+#include "core/gimpimage-crop.h"
+#include "core/gimpimage-duplicate.h"
+#include "core/gimpimage-flip.h"
+#include "core/gimpimage-merge.h"
+#include "core/gimpimage-resize.h"
+#include "core/gimpimage-rotate.h"
+#include "core/gimpimage-scale.h"
+#include "core/gimpimage-undo.h"
+#include "core/gimpitem.h"
+#include "core/gimppickable.h"
+#include "core/gimppickable-auto-shrink.h"
+#include "core/gimpprogress.h"
+
+#include "widgets/gimpdialogfactory.h"
+#include "widgets/gimpdock.h"
+#include "widgets/gimphelp-ids.h"
+#include "widgets/gimpwidgets-utils.h"
+
+#include "display/gimpdisplay.h"
+#include "display/gimpdisplayshell.h"
+
+#include "dialogs/dialogs.h"
+#include "dialogs/color-profile-dialog.h"
+#include "dialogs/convert-indexed-dialog.h"
+#include "dialogs/convert-precision-dialog.h"
+#include "dialogs/grid-dialog.h"
+#include "dialogs/image-merge-layers-dialog.h"
+#include "dialogs/image-new-dialog.h"
+#include "dialogs/image-properties-dialog.h"
+#include "dialogs/image-scale-dialog.h"
+#include "dialogs/print-size-dialog.h"
+#include "dialogs/resize-dialog.h"
+
+#include "actions.h"
+#include "image-commands.h"
+
+#include "gimp-intl.h"
+
+
+/* local function prototypes */
+
+static void image_convert_rgb_callback (GtkWidget *dialog,
+ GimpImage *image,
+ GimpColorProfile *new_profile,
+ GFile *new_file,
+ GimpColorRenderingIntent intent,
+ gboolean bpc,
+ gpointer user_data);
+
+static void image_convert_gray_callback (GtkWidget *dialog,
+ GimpImage *image,
+ GimpColorProfile *new_profile,
+ GFile *new_file,
+ GimpColorRenderingIntent intent,
+ gboolean bpc,
+ gpointer user_data);
+
+static void image_convert_indexed_callback (GtkWidget *dialog,
+ GimpImage *image,
+ GimpConvertPaletteType palette_type,
+ gint max_colors,
+ gboolean remove_duplicates,
+ GimpConvertDitherType dither_type,
+ gboolean dither_alpha,
+ gboolean dither_text_layers,
+ GimpPalette *custom_palette,
+ gpointer user_data);
+
+static void image_convert_precision_callback (GtkWidget *dialog,
+ GimpImage *image,
+ GimpPrecision precision,
+ GeglDitherMethod layer_dither_method,
+ GeglDitherMethod text_layer_dither_method,
+ GeglDitherMethod mask_dither_method,
+ gpointer user_data);
+
+static void image_profile_assign_callback (GtkWidget *dialog,
+ GimpImage *image,
+ GimpColorProfile *new_profile,
+ GFile *new_file,
+ GimpColorRenderingIntent intent,
+ gboolean bpc,
+ gpointer user_data);
+
+static void image_profile_convert_callback (GtkWidget *dialog,
+ GimpImage *image,
+ GimpColorProfile *new_profile,
+ GFile *new_file,
+ GimpColorRenderingIntent intent,
+ gboolean bpc,
+ gpointer user_data);
+
+static void image_resize_callback (GtkWidget *dialog,
+ GimpViewable *viewable,
+ GimpContext *context,
+ gint width,
+ gint height,
+ 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,
+ gpointer user_data);
+
+static void image_print_size_callback (GtkWidget *dialog,
+ GimpImage *image,
+ gdouble xresolution,
+ gdouble yresolution,
+ GimpUnit resolution_unit,
+ gpointer user_data);
+
+static void image_scale_callback (GtkWidget *dialog,
+ GimpViewable *viewable,
+ gint width,
+ gint height,
+ GimpUnit unit,
+ GimpInterpolationType interpolation,
+ gdouble xresolution,
+ gdouble yresolution,
+ GimpUnit resolution_unit,
+ gpointer user_data);
+
+static void image_merge_layers_callback (GtkWidget *dialog,
+ GimpImage *image,
+ GimpContext *context,
+ GimpMergeType merge_type,
+ gboolean merge_active_group,
+ gboolean discard_invisible,
+ gpointer user_data);
+
+
+/* private variables */
+
+static GimpUnit image_resize_unit = GIMP_UNIT_PIXEL;
+static GimpUnit image_scale_unit = GIMP_UNIT_PIXEL;
+static GimpInterpolationType image_scale_interp = -1;
+static GimpPalette *image_convert_indexed_custom_palette = NULL;
+
+
+/* public functions */
+
+void
+image_new_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GtkWidget *widget;
+ GtkWidget *dialog;
+ return_if_no_widget (widget, data);
+
+ dialog = gimp_dialog_factory_dialog_new (gimp_dialog_factory_get_singleton (),
+ gtk_widget_get_screen (widget),
+ gimp_widget_get_monitor (widget),
+ NULL /*ui_manager*/,
+ "gimp-image-new-dialog", -1, FALSE);
+
+ if (dialog)
+ {
+ GimpImage *image = action_data_get_image (data);
+
+ image_new_dialog_set (dialog, image, NULL);
+
+ gtk_window_present (GTK_WINDOW (dialog));
+ }
+}
+
+void
+image_duplicate_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpDisplay *display;
+ GimpImage *image;
+ GimpDisplayShell *shell;
+ GimpImage *new_image;
+ return_if_no_display (display, data);
+
+ image = gimp_display_get_image (display);
+ shell = gimp_display_get_shell (display);
+
+ new_image = gimp_image_duplicate (image);
+
+ gimp_create_display (new_image->gimp, new_image, shell->unit,
+ gimp_zoom_model_get_factor (shell->zoom),
+ G_OBJECT (gtk_widget_get_screen (GTK_WIDGET (shell))),
+ gimp_widget_get_monitor (GTK_WIDGET (shell)));
+
+ g_object_unref (new_image);
+}
+
+void
+image_convert_base_type_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpDisplay *display;
+ GtkWidget *widget;
+ GimpDialogConfig *config;
+ GtkWidget *dialog;
+ GimpImageBaseType base_type;
+ GError *error = NULL;
+ return_if_no_image (image, data);
+ return_if_no_display (display, data);
+ return_if_no_widget (widget, data);
+
+ base_type = (GimpImageBaseType) g_variant_get_int32 (value);
+
+ if (base_type == gimp_image_get_base_type (image))
+ return;
+
+#define CONVERT_TYPE_DIALOG_KEY "gimp-convert-type-dialog"
+
+ dialog = dialogs_get_dialog (G_OBJECT (image), CONVERT_TYPE_DIALOG_KEY);
+
+ if (dialog)
+ {
+ gtk_widget_destroy (dialog);
+ dialog = NULL;
+ }
+
+ config = GIMP_DIALOG_CONFIG (image->gimp->config);
+
+ switch (base_type)
+ {
+ case GIMP_RGB:
+ case GIMP_GRAY:
+ if (gimp_image_get_color_profile (image))
+ {
+ ColorProfileDialogType dialog_type;
+ GimpColorProfileCallback callback;
+ GimpColorProfile *current_profile;
+ GimpColorProfile *default_profile;
+ const Babl *format;
+
+ current_profile =
+ gimp_color_managed_get_color_profile (GIMP_COLOR_MANAGED (image));
+
+ if (base_type == GIMP_RGB)
+ {
+ dialog_type = COLOR_PROFILE_DIALOG_CONVERT_TO_RGB;
+ callback = image_convert_rgb_callback;
+
+ format = gimp_babl_format (GIMP_RGB,
+ gimp_image_get_precision (image),
+ TRUE);
+ default_profile = gimp_babl_format_get_color_profile (format);
+ }
+ else
+ {
+ dialog_type = COLOR_PROFILE_DIALOG_CONVERT_TO_GRAY;
+ callback = image_convert_gray_callback;
+
+ format = gimp_babl_format (GIMP_GRAY,
+ gimp_image_get_precision (image),
+ TRUE);
+ default_profile = gimp_babl_format_get_color_profile (format);
+ }
+
+ dialog = color_profile_dialog_new (dialog_type,
+ image,
+ action_data_get_context (data),
+ widget,
+ current_profile,
+ default_profile,
+ 0, 0,
+ callback,
+ display);
+ }
+ else if (! gimp_image_convert_type (image, base_type, NULL, NULL, &error))
+ {
+ gimp_message_literal (image->gimp,
+ G_OBJECT (widget), GIMP_MESSAGE_WARNING,
+ error->message);
+ g_clear_error (&error);
+ }
+ break;
+
+ case GIMP_INDEXED:
+ dialog = convert_indexed_dialog_new (image,
+ action_data_get_context (data),
+ widget,
+ config->image_convert_indexed_palette_type,
+ config->image_convert_indexed_max_colors,
+ config->image_convert_indexed_remove_duplicates,
+ config->image_convert_indexed_dither_type,
+ config->image_convert_indexed_dither_alpha,
+ config->image_convert_indexed_dither_text_layers,
+ image_convert_indexed_custom_palette,
+ image_convert_indexed_callback,
+ display);
+ break;
+ }
+
+ if (dialog)
+ {
+ dialogs_attach_dialog (G_OBJECT (image),
+ CONVERT_TYPE_DIALOG_KEY, dialog);
+ gtk_window_present (GTK_WINDOW (dialog));
+ }
+
+ /* always flush, also when only the indexed dialog was shown, so
+ * the menu items get updated back to the current image type
+ */
+ gimp_image_flush (image);
+}
+
+void
+image_convert_precision_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpDisplay *display;
+ GtkWidget *widget;
+ GimpDialogConfig *config;
+ GtkWidget *dialog;
+ GimpComponentType component_type;
+ return_if_no_image (image, data);
+ return_if_no_display (display, data);
+ return_if_no_widget (widget, data);
+
+ component_type = (GimpComponentType) g_variant_get_int32 (value);
+
+ if (component_type == gimp_image_get_component_type (image))
+ return;
+
+#define CONVERT_PRECISION_DIALOG_KEY "gimp-convert-precision-dialog"
+
+ dialog = dialogs_get_dialog (G_OBJECT (image), CONVERT_PRECISION_DIALOG_KEY);
+
+ if (dialog)
+ {
+ gtk_widget_destroy (dialog);
+ dialog = NULL;
+ }
+
+ config = GIMP_DIALOG_CONFIG (image->gimp->config);
+
+ dialog = convert_precision_dialog_new (image,
+ action_data_get_context (data),
+ widget,
+ component_type,
+ config->image_convert_precision_layer_dither_method,
+ config->image_convert_precision_text_layer_dither_method,
+ config->image_convert_precision_channel_dither_method,
+ image_convert_precision_callback,
+ display);
+
+ dialogs_attach_dialog (G_OBJECT (image),
+ CONVERT_PRECISION_DIALOG_KEY, dialog);
+
+ gtk_window_present (GTK_WINDOW (dialog));
+
+ /* see comment above */
+ gimp_image_flush (image);
+}
+
+void
+image_convert_gamma_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpDisplay *display;
+ gboolean linear;
+ GimpPrecision precision;
+ return_if_no_image (image, data);
+ return_if_no_display (display, data);
+
+ linear = (gboolean) g_variant_get_int32 (value);
+
+ if (linear == gimp_babl_format_get_linear (gimp_image_get_layer_format (image,
+ FALSE)))
+ return;
+
+ precision = gimp_babl_precision (gimp_image_get_component_type (image),
+ linear);
+
+ gimp_image_convert_precision (image, precision,
+ GEGL_DITHER_NONE,
+ GEGL_DITHER_NONE,
+ GEGL_DITHER_NONE,
+ GIMP_PROGRESS (display));
+ gimp_image_flush (image);
+}
+
+void
+image_color_management_enabled_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ gboolean enabled;
+ return_if_no_image (image, data);
+
+ enabled = g_variant_get_boolean (value);
+
+ if (enabled != gimp_image_get_is_color_managed (image))
+ {
+ gimp_image_set_is_color_managed (image, enabled, TRUE);
+ gimp_image_flush (image);
+ }
+}
+
+void
+image_color_profile_assign_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpDisplay *display;
+ GtkWidget *widget;
+ GtkWidget *dialog;
+ return_if_no_image (image, data);
+ return_if_no_display (display, data);
+ return_if_no_widget (widget, data);
+
+#define PROFILE_ASSIGN_DIALOG_KEY "gimp-profile-assign-dialog"
+
+ dialog = dialogs_get_dialog (G_OBJECT (image), PROFILE_ASSIGN_DIALOG_KEY);
+
+ if (! dialog)
+ {
+ GimpColorProfile *current_profile;
+ GimpColorProfile *default_profile;
+
+ current_profile = gimp_color_managed_get_color_profile (GIMP_COLOR_MANAGED (image));
+ default_profile = gimp_image_get_builtin_color_profile (image);
+
+ dialog = color_profile_dialog_new (COLOR_PROFILE_DIALOG_ASSIGN_PROFILE,
+ image,
+ action_data_get_context (data),
+ widget,
+ current_profile,
+ default_profile,
+ 0, 0,
+ image_profile_assign_callback,
+ display);
+
+ dialogs_attach_dialog (G_OBJECT (image),
+ PROFILE_ASSIGN_DIALOG_KEY, dialog);
+ }
+
+ gtk_window_present (GTK_WINDOW (dialog));
+}
+
+void
+image_color_profile_convert_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpDisplay *display;
+ GtkWidget *widget;
+ GtkWidget *dialog;
+ return_if_no_image (image, data);
+ return_if_no_display (display, data);
+ return_if_no_widget (widget, data);
+
+#define PROFILE_CONVERT_DIALOG_KEY "gimp-profile-convert-dialog"
+
+ dialog = dialogs_get_dialog (G_OBJECT (image), PROFILE_CONVERT_DIALOG_KEY);
+
+ if (! dialog)
+ {
+ GimpDialogConfig *config = GIMP_DIALOG_CONFIG (image->gimp->config);
+ GimpColorProfile *current_profile;
+ GimpColorProfile *default_profile;
+
+ current_profile = gimp_color_managed_get_color_profile (GIMP_COLOR_MANAGED (image));
+ default_profile = gimp_image_get_builtin_color_profile (image);
+
+ dialog = color_profile_dialog_new (COLOR_PROFILE_DIALOG_CONVERT_TO_PROFILE,
+ image,
+ action_data_get_context (data),
+ widget,
+ current_profile,
+ default_profile,
+ config->image_convert_profile_intent,
+ config->image_convert_profile_bpc,
+ image_profile_convert_callback,
+ display);
+
+ dialogs_attach_dialog (G_OBJECT (image),
+ PROFILE_CONVERT_DIALOG_KEY, dialog);
+ }
+
+ gtk_window_present (GTK_WINDOW (dialog));
+}
+
+void
+image_color_profile_discard_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ return_if_no_image (image, data);
+
+ gimp_image_set_color_profile (image, NULL, NULL);
+ gimp_image_flush (image);
+}
+
+static void
+image_profile_save_dialog_response (GtkWidget *dialog,
+ gint response_id,
+ GimpImage *image)
+{
+ if (response_id == GTK_RESPONSE_ACCEPT)
+ {
+ GimpColorProfile *profile;
+ GFile *file;
+ GError *error = NULL;
+
+ profile = gimp_color_managed_get_color_profile (GIMP_COLOR_MANAGED (image));
+ file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog));
+
+ if (! file)
+ return;
+
+ if (! gimp_color_profile_save_to_file (profile, file, &error))
+ {
+ gimp_message (image->gimp, NULL,
+ GIMP_MESSAGE_WARNING,
+ _("Saving color profile failed: %s"),
+ error->message);
+ g_clear_error (&error);
+ g_object_unref (file);
+ return;
+ }
+
+ g_object_unref (file);
+ }
+
+ gtk_widget_destroy (dialog);
+}
+
+void
+image_color_profile_save_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpDisplay *display;
+ GtkWidget *widget;
+ GtkWidget *dialog;
+ return_if_no_image (image, data);
+ return_if_no_display (display, data);
+ return_if_no_widget (widget, data);
+
+#define PROFILE_SAVE_DIALOG_KEY "gimp-profile-save-dialog"
+
+ dialog = dialogs_get_dialog (G_OBJECT (image), PROFILE_SAVE_DIALOG_KEY);
+
+ if (! dialog)
+ {
+ GtkWindow *toplevel;
+ GimpColorProfile *profile;
+ gchar *basename;
+
+ toplevel = GTK_WINDOW (gtk_widget_get_toplevel (widget));
+ profile = gimp_color_managed_get_color_profile (GIMP_COLOR_MANAGED (image));
+
+ dialog =
+ gimp_color_profile_chooser_dialog_new (_("Save Color Profile"),
+ toplevel,
+ GTK_FILE_CHOOSER_ACTION_SAVE);
+
+ gimp_color_profile_chooser_dialog_connect_path (dialog,
+ G_OBJECT (image->gimp->config),
+ "color-profile-path");
+
+ basename = g_strconcat (gimp_color_profile_get_label (profile),
+ ".icc", NULL);
+ gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), basename);
+ g_free (basename);
+
+ g_signal_connect (dialog, "response",
+ G_CALLBACK (image_profile_save_dialog_response),
+ image);
+
+ dialogs_attach_dialog (G_OBJECT (image), PROFILE_SAVE_DIALOG_KEY, dialog);
+ }
+
+ gtk_window_present (GTK_WINDOW (dialog));
+}
+
+void
+image_resize_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GtkWidget *widget;
+ GimpDisplay *display;
+ GtkWidget *dialog;
+ return_if_no_image (image, data);
+ return_if_no_widget (widget, data);
+ return_if_no_display (display, data);
+
+#define RESIZE_DIALOG_KEY "gimp-resize-dialog"
+
+ dialog = dialogs_get_dialog (G_OBJECT (image), RESIZE_DIALOG_KEY);
+
+ if (! dialog)
+ {
+ GimpDialogConfig *config = GIMP_DIALOG_CONFIG (image->gimp->config);
+
+ if (image_resize_unit != GIMP_UNIT_PERCENT)
+ image_resize_unit = gimp_display_get_shell (display)->unit;
+
+ dialog = resize_dialog_new (GIMP_VIEWABLE (image),
+ action_data_get_context (data),
+ _("Set Image Canvas Size"),
+ "gimp-image-resize",
+ widget,
+ gimp_standard_help_func,
+ GIMP_HELP_IMAGE_RESIZE,
+ image_resize_unit,
+ config->image_resize_fill_type,
+ config->image_resize_layer_set,
+ config->image_resize_resize_text_layers,
+ image_resize_callback,
+ display);
+
+ dialogs_attach_dialog (G_OBJECT (image), RESIZE_DIALOG_KEY, dialog);
+ }
+
+ gtk_window_present (GTK_WINDOW (dialog));
+}
+
+void
+image_resize_to_layers_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpDisplay *display;
+ GimpImage *image;
+ GimpProgress *progress;
+ return_if_no_display (display, data);
+
+ image = gimp_display_get_image (display);
+
+ progress = gimp_progress_start (GIMP_PROGRESS (display), FALSE,
+ _("Resizing"));
+
+ gimp_image_resize_to_layers (image,
+ action_data_get_context (data),
+ NULL, NULL, NULL, NULL, progress);
+
+ if (progress)
+ gimp_progress_end (progress);
+
+ gimp_image_flush (image);
+}
+
+void
+image_resize_to_selection_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpDisplay *display;
+ GimpImage *image;
+ GimpProgress *progress;
+ return_if_no_display (display, data);
+
+ image = gimp_display_get_image (display);
+
+ progress = gimp_progress_start (GIMP_PROGRESS (display), FALSE,
+ _("Resizing"));
+
+ gimp_image_resize_to_selection (image,
+ action_data_get_context (data),
+ progress);
+
+ if (progress)
+ gimp_progress_end (progress);
+
+ gimp_image_flush (image);
+}
+
+void
+image_print_size_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpDisplay *display;
+ GimpImage *image;
+ GtkWidget *widget;
+ GtkWidget *dialog;
+ return_if_no_display (display, data);
+ return_if_no_widget (widget, data);
+
+ image = gimp_display_get_image (display);
+
+#define PRINT_SIZE_DIALOG_KEY "gimp-print-size-dialog"
+
+ dialog = dialogs_get_dialog (G_OBJECT (image), PRINT_SIZE_DIALOG_KEY);
+
+ if (! dialog)
+ {
+ dialog = print_size_dialog_new (image,
+ action_data_get_context (data),
+ _("Set Image Print Resolution"),
+ "gimp-image-print-size",
+ widget,
+ gimp_standard_help_func,
+ GIMP_HELP_IMAGE_PRINT_SIZE,
+ image_print_size_callback,
+ NULL);
+
+ dialogs_attach_dialog (G_OBJECT (image), PRINT_SIZE_DIALOG_KEY, dialog);
+ }
+
+ gtk_window_present (GTK_WINDOW (dialog));
+}
+
+void
+image_scale_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpDisplay *display;
+ GimpImage *image;
+ GtkWidget *widget;
+ GtkWidget *dialog;
+ return_if_no_display (display, data);
+ return_if_no_widget (widget, data);
+
+ image = gimp_display_get_image (display);
+
+#define SCALE_DIALOG_KEY "gimp-scale-dialog"
+
+ dialog = dialogs_get_dialog (G_OBJECT (image), SCALE_DIALOG_KEY);
+
+ if (! dialog)
+ {
+ if (image_scale_unit != GIMP_UNIT_PERCENT)
+ image_scale_unit = gimp_display_get_shell (display)->unit;
+
+ if (image_scale_interp == -1)
+ image_scale_interp = display->gimp->config->interpolation_type;
+
+ dialog = image_scale_dialog_new (image,
+ action_data_get_context (data),
+ widget,
+ image_scale_unit,
+ image_scale_interp,
+ image_scale_callback,
+ display);
+
+ dialogs_attach_dialog (G_OBJECT (image), SCALE_DIALOG_KEY, dialog);
+ }
+
+ gtk_window_present (GTK_WINDOW (dialog));
+}
+
+void
+image_flip_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpDisplay *display;
+ GimpImage *image;
+ GimpProgress *progress;
+ GimpOrientationType orientation;
+ return_if_no_display (display, data);
+
+ orientation = (GimpOrientationType) g_variant_get_int32 (value);
+
+ image = gimp_display_get_image (display);
+
+ progress = gimp_progress_start (GIMP_PROGRESS (display), FALSE,
+ _("Flipping"));
+
+ gimp_image_flip (image, action_data_get_context (data),
+ orientation, progress);
+
+ if (progress)
+ gimp_progress_end (progress);
+
+ gimp_image_flush (image);
+}
+
+void
+image_rotate_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpDisplay *display;
+ GimpImage *image;
+ GimpProgress *progress;
+ GimpRotationType rotation;
+ return_if_no_display (display, data);
+
+ rotation = (GimpRotationType) g_variant_get_int32 (value);
+
+ image = gimp_display_get_image (display);
+
+ progress = gimp_progress_start (GIMP_PROGRESS (display), FALSE,
+ _("Rotating"));
+
+ gimp_image_rotate (image, action_data_get_context (data),
+ rotation, progress);
+
+ if (progress)
+ gimp_progress_end (progress);
+
+ gimp_image_flush (image);
+}
+
+void
+image_crop_to_selection_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GtkWidget *widget;
+ gint x, y;
+ gint width, height;
+ return_if_no_image (image, data);
+ return_if_no_widget (widget, data);
+
+ if (! gimp_item_bounds (GIMP_ITEM (gimp_image_get_mask (image)),
+ &x, &y, &width, &height))
+ {
+ gimp_message_literal (image->gimp,
+ G_OBJECT (widget), GIMP_MESSAGE_WARNING,
+ _("Cannot crop because the current selection "
+ "is empty."));
+ return;
+ }
+
+ gimp_image_crop (image,
+ action_data_get_context (data), GIMP_FILL_TRANSPARENT,
+ x, y, width, height, TRUE);
+ gimp_image_flush (image);
+}
+
+void
+image_crop_to_content_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GtkWidget *widget;
+ gint x, y;
+ gint width, height;
+ return_if_no_image (image, data);
+ return_if_no_widget (widget, data);
+
+ switch (gimp_pickable_auto_shrink (GIMP_PICKABLE (image),
+ 0, 0,
+ gimp_image_get_width (image),
+ gimp_image_get_height (image),
+ &x, &y, &width, &height))
+ {
+ case GIMP_AUTO_SHRINK_SHRINK:
+ gimp_image_crop (image,
+ action_data_get_context (data), GIMP_FILL_TRANSPARENT,
+ x, y, width, height, TRUE);
+ gimp_image_flush (image);
+ break;
+
+ case GIMP_AUTO_SHRINK_EMPTY:
+ gimp_message_literal (image->gimp,
+ G_OBJECT (widget), GIMP_MESSAGE_INFO,
+ _("Cannot crop because the image has no content."));
+ break;
+
+ case GIMP_AUTO_SHRINK_UNSHRINKABLE:
+ gimp_message_literal (image->gimp,
+ G_OBJECT (widget), GIMP_MESSAGE_INFO,
+ _("Cannot crop because the image is already "
+ "cropped to its content."));
+ break;
+ }
+}
+
+void
+image_merge_layers_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GtkWidget *dialog;
+ GimpImage *image;
+ GimpDisplay *display;
+ GtkWidget *widget;
+ return_if_no_image (image, data);
+ return_if_no_display (display, data);
+ return_if_no_widget (widget, data);
+
+#define MERGE_LAYERS_DIALOG_KEY "gimp-merge-layers-dialog"
+
+ dialog = dialogs_get_dialog (G_OBJECT (image), MERGE_LAYERS_DIALOG_KEY);
+
+ if (! dialog)
+ {
+ GimpDialogConfig *config = GIMP_DIALOG_CONFIG (image->gimp->config);
+
+ dialog = image_merge_layers_dialog_new (image,
+ action_data_get_context (data),
+ widget,
+ config->layer_merge_type,
+ config->layer_merge_active_group_only,
+ config->layer_merge_discard_invisible,
+ image_merge_layers_callback,
+ display);
+
+ dialogs_attach_dialog (G_OBJECT (image), MERGE_LAYERS_DIALOG_KEY, dialog);
+ }
+
+ gtk_window_present (GTK_WINDOW (dialog));
+}
+
+void
+image_merge_layers_last_vals_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpDisplay *display;
+ GimpDialogConfig *config;
+ return_if_no_image (image, data);
+ return_if_no_display (display, data);
+
+ config = GIMP_DIALOG_CONFIG (image->gimp->config);
+
+ image_merge_layers_callback (NULL,
+ image,
+ action_data_get_context (data),
+ config->layer_merge_type,
+ config->layer_merge_active_group_only,
+ config->layer_merge_discard_invisible,
+ display);
+}
+
+void
+image_flatten_image_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpDisplay *display;
+ GtkWidget *widget;
+ GError *error = NULL;
+ return_if_no_image (image, data);
+ return_if_no_display (display, data);
+ return_if_no_widget (widget, data);
+
+ if (! gimp_image_flatten (image, action_data_get_context (data),
+ GIMP_PROGRESS (display), &error))
+ {
+ gimp_message_literal (image->gimp,
+ G_OBJECT (widget), GIMP_MESSAGE_WARNING,
+ error->message);
+ g_clear_error (&error);
+ return;
+ }
+
+ gimp_image_flush (image);
+}
+
+void
+image_configure_grid_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpDisplay *display;
+ GimpImage *image;
+ GtkWidget *dialog;
+ return_if_no_display (display, data);
+
+ image = gimp_display_get_image (display);
+
+#define GRID_DIALOG_KEY "gimp-grid-dialog"
+
+ dialog = dialogs_get_dialog (G_OBJECT (image), GRID_DIALOG_KEY);
+
+ if (! dialog)
+ {
+ GimpDisplayShell *shell = gimp_display_get_shell (display);
+
+ dialog = grid_dialog_new (image,
+ action_data_get_context (data),
+ gtk_widget_get_toplevel (GTK_WIDGET (shell)));
+
+ dialogs_attach_dialog (G_OBJECT (image), GRID_DIALOG_KEY, dialog);
+ }
+
+ gtk_window_present (GTK_WINDOW (dialog));
+}
+
+void
+image_properties_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpDisplay *display;
+ GimpImage *image;
+ GtkWidget *dialog;
+ return_if_no_display (display, data);
+
+ image = gimp_display_get_image (display);
+
+#define PROPERTIES_DIALOG_KEY "gimp-image-properties-dialog"
+
+ dialog = dialogs_get_dialog (G_OBJECT (image), PROPERTIES_DIALOG_KEY);
+
+ if (! dialog)
+ {
+ GimpDisplayShell *shell = gimp_display_get_shell (display);
+
+ dialog = image_properties_dialog_new (image,
+ action_data_get_context (data),
+ gtk_widget_get_toplevel (GTK_WIDGET (shell)));
+
+ dialogs_attach_dialog (G_OBJECT (image), PROPERTIES_DIALOG_KEY, dialog);
+ }
+
+ gtk_window_present (GTK_WINDOW (dialog));
+}
+
+
+/* private functions */
+
+static void
+image_convert_rgb_callback (GtkWidget *dialog,
+ GimpImage *image,
+ GimpColorProfile *new_profile,
+ GFile *new_file,
+ GimpColorRenderingIntent intent,
+ gboolean bpc,
+ gpointer user_data)
+{
+ GimpProgress *progress = user_data;
+ GError *error = NULL;
+
+ progress = gimp_progress_start (progress, FALSE,
+ _("Converting to RGB (%s)"),
+ gimp_color_profile_get_label (new_profile));
+
+ if (! gimp_image_convert_type (image, GIMP_RGB, new_profile,
+ progress, &error))
+ {
+ gimp_message (image->gimp, G_OBJECT (dialog),
+ GIMP_MESSAGE_ERROR,
+ "%s", error->message);
+ g_clear_error (&error);
+
+ if (progress)
+ gimp_progress_end (progress);
+
+ return;
+ }
+
+ if (progress)
+ gimp_progress_end (progress);
+
+ gimp_image_flush (image);
+
+ gtk_widget_destroy (dialog);
+}
+
+static void
+image_convert_gray_callback (GtkWidget *dialog,
+ GimpImage *image,
+ GimpColorProfile *new_profile,
+ GFile *new_file,
+ GimpColorRenderingIntent intent,
+ gboolean bpc,
+ gpointer user_data)
+{
+ GimpProgress *progress = user_data;
+ GError *error = NULL;
+
+ progress = gimp_progress_start (progress, FALSE,
+ _("Converting to grayscale (%s)"),
+ gimp_color_profile_get_label (new_profile));
+
+ if (! gimp_image_convert_type (image, GIMP_GRAY, new_profile,
+ progress, &error))
+ {
+ gimp_message (image->gimp, G_OBJECT (dialog),
+ GIMP_MESSAGE_ERROR,
+ "%s", error->message);
+ g_clear_error (&error);
+
+ if (progress)
+ gimp_progress_end (progress);
+
+ return;
+ }
+
+ if (progress)
+ gimp_progress_end (progress);
+
+ gimp_image_flush (image);
+
+ gtk_widget_destroy (dialog);
+}
+
+static void
+image_convert_indexed_callback (GtkWidget *dialog,
+ GimpImage *image,
+ GimpConvertPaletteType palette_type,
+ gint max_colors,
+ gboolean remove_duplicates,
+ GimpConvertDitherType dither_type,
+ gboolean dither_alpha,
+ gboolean dither_text_layers,
+ GimpPalette *custom_palette,
+ gpointer user_data)
+{
+ GimpDialogConfig *config = GIMP_DIALOG_CONFIG (image->gimp->config);
+ GimpDisplay *display = user_data;
+ GimpProgress *progress;
+ GError *error = NULL;
+
+ g_object_set (config,
+ "image-convert-indexed-palette-type", palette_type,
+ "image-convert-indexed-max-colors", max_colors,
+ "image-convert-indexed-remove-duplicates", remove_duplicates,
+ "image-convert-indexed-dither-type", dither_type,
+ "image-convert-indexed-dither-alpha", dither_alpha,
+ "image-convert-indexed-dither-text-layers", dither_text_layers,
+ NULL);
+
+ if (image_convert_indexed_custom_palette)
+ g_object_remove_weak_pointer (G_OBJECT (image_convert_indexed_custom_palette),
+ (gpointer) &image_convert_indexed_custom_palette);
+
+ image_convert_indexed_custom_palette = custom_palette;
+
+ if (image_convert_indexed_custom_palette)
+ g_object_add_weak_pointer (G_OBJECT (image_convert_indexed_custom_palette),
+ (gpointer) &image_convert_indexed_custom_palette);
+
+ progress = gimp_progress_start (GIMP_PROGRESS (display), FALSE,
+ _("Converting to indexed colors"));
+
+ if (! gimp_image_convert_indexed (image,
+ config->image_convert_indexed_palette_type,
+ config->image_convert_indexed_max_colors,
+ config->image_convert_indexed_remove_duplicates,
+ config->image_convert_indexed_dither_type,
+ config->image_convert_indexed_dither_alpha,
+ config->image_convert_indexed_dither_text_layers,
+ image_convert_indexed_custom_palette,
+ progress,
+ &error))
+ {
+ gimp_message_literal (image->gimp, G_OBJECT (display),
+ GIMP_MESSAGE_WARNING, error->message);
+ g_clear_error (&error);
+
+ if (progress)
+ gimp_progress_end (progress);
+
+ return;
+ }
+
+ if (progress)
+ gimp_progress_end (progress);
+
+ gimp_image_flush (image);
+
+ gtk_widget_destroy (dialog);
+}
+
+static void
+image_convert_precision_callback (GtkWidget *dialog,
+ GimpImage *image,
+ GimpPrecision precision,
+ GeglDitherMethod layer_dither_method,
+ GeglDitherMethod text_layer_dither_method,
+ GeglDitherMethod channel_dither_method,
+ gpointer user_data)
+{
+ GimpDialogConfig *config = GIMP_DIALOG_CONFIG (image->gimp->config);
+ GimpProgress *progress = user_data;
+ const gchar *enum_desc;
+ const Babl *old_format;
+ const Babl *new_format;
+ gint old_bits;
+ gint new_bits;
+
+ g_object_set (config,
+ "image-convert-precision-layer-dither-method",
+ layer_dither_method,
+ "image-convert-precision-text-layer-dither-method",
+ text_layer_dither_method,
+ "image-convert-precision-channel-dither-method",
+ channel_dither_method,
+ NULL);
+
+ /* we do the same dither method checks here *and* in the dialog,
+ * because the dialog leaves the passed dither methods untouched if
+ * dithering is disabled and passes the original values to the
+ * callback, in order not to change the values saved in
+ * GimpDialogConfig.
+ */
+
+ /* random formats with the right precision */
+ old_format = gimp_image_get_layer_format (image, FALSE);
+ new_format = gimp_babl_format (GIMP_RGB, precision, FALSE);
+
+ old_bits = (babl_format_get_bytes_per_pixel (old_format) * 8 /
+ babl_format_get_n_components (old_format));
+ new_bits = (babl_format_get_bytes_per_pixel (new_format) * 8 /
+ babl_format_get_n_components (new_format));
+
+ if (new_bits >= old_bits ||
+ new_bits > CONVERT_PRECISION_DIALOG_MAX_DITHER_BITS)
+ {
+ /* don't dither if we are converting to a higher bit depth,
+ * or to more than MAX_DITHER_BITS.
+ */
+ layer_dither_method = GEGL_DITHER_NONE;
+ text_layer_dither_method = GEGL_DITHER_NONE;
+ channel_dither_method = GEGL_DITHER_NONE;
+ }
+
+ gimp_enum_get_value (GIMP_TYPE_PRECISION, precision,
+ NULL, NULL, &enum_desc, NULL);
+
+ progress = gimp_progress_start (progress, FALSE,
+ _("Converting image to %s"),
+ enum_desc);
+
+ gimp_image_convert_precision (image,
+ precision,
+ layer_dither_method,
+ text_layer_dither_method,
+ channel_dither_method,
+ progress);
+
+ if (progress)
+ gimp_progress_end (progress);
+
+ gimp_image_flush (image);
+
+ gtk_widget_destroy (dialog);
+}
+
+static void
+image_profile_assign_callback (GtkWidget *dialog,
+ GimpImage *image,
+ GimpColorProfile *new_profile,
+ GFile *new_file,
+ GimpColorRenderingIntent intent,
+ gboolean bpc,
+ gpointer user_data)
+{
+ GError *error = NULL;
+
+ gimp_image_undo_group_start (image,
+ GIMP_UNDO_GROUP_PARASITE_ATTACH,
+ _("Assign color profile"));
+
+ if (! gimp_image_set_color_profile (image, new_profile, &error))
+ {
+ gimp_message (image->gimp, G_OBJECT (dialog),
+ GIMP_MESSAGE_ERROR,
+ "%s", error->message);
+ g_clear_error (&error);
+
+ gimp_image_undo_group_end (image);
+ gimp_image_undo (image);
+
+ return;
+ }
+
+ gimp_image_set_is_color_managed (image, TRUE, TRUE);
+
+ /* omg... */
+ gimp_image_parasite_detach (image, "icc-profile-name", TRUE);
+
+ gimp_image_undo_group_end (image);
+
+ gimp_image_flush (image);
+
+ gtk_widget_destroy (dialog);
+}
+
+static void
+image_profile_convert_callback (GtkWidget *dialog,
+ GimpImage *image,
+ GimpColorProfile *new_profile,
+ GFile *new_file,
+ GimpColorRenderingIntent intent,
+ gboolean bpc,
+ gpointer user_data)
+{
+ GimpDialogConfig *config = GIMP_DIALOG_CONFIG (image->gimp->config);
+ GimpProgress *progress = user_data;
+ GError *error = NULL;
+
+ g_object_set (config,
+ "image-convert-profile-intent", intent,
+ "image-convert-profile-black-point-compensation", bpc,
+ NULL);
+
+ progress = gimp_progress_start (progress, FALSE,
+ _("Converting to '%s'"),
+ gimp_color_profile_get_label (new_profile));
+
+ if (! gimp_image_convert_color_profile (image, new_profile,
+ config->image_convert_profile_intent,
+ config->image_convert_profile_bpc,
+ progress, &error))
+ {
+ gimp_message (image->gimp, G_OBJECT (dialog),
+ GIMP_MESSAGE_ERROR,
+ "%s", error->message);
+ g_clear_error (&error);
+
+ if (progress)
+ gimp_progress_end (progress);
+
+ return;
+ }
+
+ if (progress)
+ gimp_progress_end (progress);
+
+ gimp_image_flush (image);
+
+ gtk_widget_destroy (dialog);
+}
+
+static void
+image_resize_callback (GtkWidget *dialog,
+ GimpViewable *viewable,
+ GimpContext *context,
+ gint width,
+ gint height,
+ 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,
+ gpointer user_data)
+{
+ GimpDisplay *display = user_data;
+
+ image_resize_unit = unit;
+
+ if (width > 0 && height > 0)
+ {
+ 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,
+ "image-resize-layer-set", layer_set,
+ "image-resize-resize-text-layers", resize_text_layers,
+ NULL);
+
+ gtk_widget_destroy (dialog);
+
+ if (width == gimp_image_get_width (image) &&
+ height == gimp_image_get_height (image))
+ return;
+
+ 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,
+ layer_set,
+ resize_text_layers,
+ progress);
+
+ if (progress)
+ gimp_progress_end (progress);
+
+ if (update_resolution)
+ gimp_image_undo_group_end (image);
+
+ gimp_image_flush (image);
+ }
+ else
+ {
+ g_warning ("Resize Error: "
+ "Both width and height must be greater than zero.");
+ }
+}
+
+static void
+image_print_size_callback (GtkWidget *dialog,
+ GimpImage *image,
+ gdouble xresolution,
+ gdouble yresolution,
+ GimpUnit resolution_unit,
+ gpointer data)
+{
+ gdouble xres;
+ gdouble yres;
+
+ gtk_widget_destroy (dialog);
+
+ gimp_image_get_resolution (image, &xres, &yres);
+
+ if (xresolution == xres &&
+ yresolution == yres &&
+ resolution_unit == gimp_image_get_unit (image))
+ return;
+
+ gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_IMAGE_SCALE,
+ _("Change Print Size"));
+
+ gimp_image_set_resolution (image, xresolution, yresolution);
+ gimp_image_set_unit (image, resolution_unit);
+
+ gimp_image_undo_group_end (image);
+
+ gimp_image_flush (image);
+}
+
+static void
+image_scale_callback (GtkWidget *dialog,
+ GimpViewable *viewable,
+ gint width,
+ gint height,
+ GimpUnit unit,
+ GimpInterpolationType interpolation,
+ gdouble xresolution,
+ gdouble yresolution,
+ GimpUnit resolution_unit,
+ gpointer user_data)
+{
+ GimpProgress *progress = user_data;
+ GimpImage *image = GIMP_IMAGE (viewable);
+ gdouble xres;
+ gdouble yres;
+
+ image_scale_unit = unit;
+ image_scale_interp = interpolation;
+
+ gimp_image_get_resolution (image, &xres, &yres);
+
+ if (width > 0 && height > 0)
+ {
+ gtk_widget_destroy (dialog);
+
+ if (width == gimp_image_get_width (image) &&
+ height == gimp_image_get_height (image) &&
+ xresolution == xres &&
+ yresolution == yres &&
+ resolution_unit == gimp_image_get_unit (image))
+ return;
+
+ gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_IMAGE_SCALE,
+ _("Scale Image"));
+
+ gimp_image_set_resolution (image, xresolution, yresolution);
+ gimp_image_set_unit (image, resolution_unit);
+
+ if (width != gimp_image_get_width (image) ||
+ height != gimp_image_get_height (image))
+ {
+ progress = gimp_progress_start (progress, FALSE,
+ _("Scaling"));
+
+ gimp_image_scale (image, width, height, interpolation, progress);
+
+ if (progress)
+ gimp_progress_end (progress);
+ }
+
+ gimp_image_undo_group_end (image);
+
+ gimp_image_flush (image);
+ }
+ else
+ {
+ g_warning ("Scale Error: "
+ "Both width and height must be greater than zero.");
+ }
+}
+
+static void
+image_merge_layers_callback (GtkWidget *dialog,
+ GimpImage *image,
+ GimpContext *context,
+ GimpMergeType merge_type,
+ gboolean merge_active_group,
+ gboolean discard_invisible,
+ gpointer user_data)
+{
+ GimpDialogConfig *config = GIMP_DIALOG_CONFIG (image->gimp->config);
+ GimpDisplay *display = user_data;
+
+ g_object_set (config,
+ "layer-merge-type", merge_type,
+ "layer-merge-active-group-only", merge_active_group,
+ "layer-merge-discard-invisible", discard_invisible,
+ NULL);
+
+ gimp_image_merge_visible_layers (image,
+ context,
+ config->layer_merge_type,
+ config->layer_merge_active_group_only,
+ config->layer_merge_discard_invisible,
+ GIMP_PROGRESS (display));
+
+ gimp_image_flush (image);
+
+ gtk_widget_destroy (dialog);
+}
diff --git a/app/actions/image-commands.h b/app/actions/image-commands.h
new file mode 100644
index 0000000..018dec7
--- /dev/null
+++ b/app/actions/image-commands.h
@@ -0,0 +1,101 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __IMAGE_COMMANDS_H__
+#define __IMAGE_COMMANDS_H__
+
+
+void image_new_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void image_duplicate_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+void image_convert_base_type_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void image_convert_precision_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void image_convert_gamma_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+void image_color_management_enabled_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void image_color_profile_assign_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void image_color_profile_convert_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void image_color_profile_discard_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void image_color_profile_save_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+void image_resize_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void image_resize_to_layers_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void image_resize_to_selection_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void image_print_size_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void image_scale_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void image_flip_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void image_rotate_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void image_crop_to_selection_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void image_crop_to_content_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+void image_merge_layers_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void image_merge_layers_last_vals_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void image_flatten_image_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+void image_configure_grid_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void image_properties_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+
+#endif /* __IMAGE_COMMANDS_H__ */
diff --git a/app/actions/images-actions.c b/app/actions/images-actions.c
new file mode 100644
index 0000000..74745c1
--- /dev/null
+++ b/app/actions/images-actions.c
@@ -0,0 +1,98 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "actions-types.h"
+
+#include "core/gimpcontext.h"
+#include "core/gimpimage.h"
+
+#include "widgets/gimpactiongroup.h"
+#include "widgets/gimphelp-ids.h"
+
+#include "actions.h"
+#include "images-actions.h"
+#include "images-commands.h"
+
+#include "gimp-intl.h"
+
+
+static const GimpActionEntry images_actions[] =
+{
+ { "images-popup", GIMP_ICON_DIALOG_IMAGES,
+ NC_("images-action", "Images Menu"), NULL, NULL, NULL,
+ GIMP_HELP_IMAGE_DIALOG },
+
+ { "images-raise-views", GIMP_ICON_GO_TOP,
+ NC_("images-action", "_Raise Views"), NULL,
+ NC_("images-action", "Raise this image's displays"),
+ images_raise_views_cmd_callback,
+ NULL },
+
+ { "images-new-view", GIMP_ICON_DOCUMENT_NEW,
+ NC_("images-action", "_New View"), NULL,
+ NC_("images-action", "Create a new display for this image"),
+ images_new_view_cmd_callback,
+ NULL },
+
+ { "images-delete", GIMP_ICON_EDIT_DELETE,
+ NC_("images-action", "_Delete Image"), NULL,
+ NC_("images-action", "Delete this image"),
+ images_delete_image_cmd_callback,
+ NULL }
+};
+
+
+void
+images_actions_setup (GimpActionGroup *group)
+{
+ gimp_action_group_add_actions (group, "images-action",
+ images_actions,
+ G_N_ELEMENTS (images_actions));
+}
+
+void
+images_actions_update (GimpActionGroup *group,
+ gpointer data)
+{
+ GimpContext *context = action_data_get_context (data);
+ GimpImage *image = NULL;
+ gint disp_count = 0;
+
+ if (context)
+ {
+ image = gimp_context_get_image (context);
+
+ if (image)
+ disp_count = gimp_image_get_display_count (image);
+ }
+
+#define SET_SENSITIVE(action,condition) \
+ gimp_action_group_set_action_sensitive (group, action, (condition) != 0)
+
+ SET_SENSITIVE ("images-raise-views", image);
+ SET_SENSITIVE ("images-new-view", image);
+ SET_SENSITIVE ("images-delete", image && disp_count == 0);
+
+#undef SET_SENSITIVE
+}
diff --git a/app/actions/images-actions.h b/app/actions/images-actions.h
new file mode 100644
index 0000000..4a304f7
--- /dev/null
+++ b/app/actions/images-actions.h
@@ -0,0 +1,27 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __IMAGES_ACTIONS_H__
+#define __IMAGES_ACTIONS_H__
+
+
+void images_actions_setup (GimpActionGroup *group);
+void images_actions_update (GimpActionGroup *group,
+ gpointer data);
+
+
+#endif /* __IMAGES_ACTIONS_H__ */
diff --git a/app/actions/images-commands.c b/app/actions/images-commands.c
new file mode 100644
index 0000000..22ea8a8
--- /dev/null
+++ b/app/actions/images-commands.c
@@ -0,0 +1,117 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "actions-types.h"
+
+#include "core/gimp.h"
+#include "core/gimpcontainer.h"
+#include "core/gimpcontext.h"
+#include "core/gimpimage.h"
+
+#include "widgets/gimpcontainerview.h"
+#include "widgets/gimpimageview.h"
+
+#include "display/gimpdisplay.h"
+#include "display/gimpdisplayshell.h"
+
+#include "images-commands.h"
+
+
+/* public functions */
+
+void
+images_raise_views_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpContainerEditor *editor = GIMP_CONTAINER_EDITOR (data);
+ GimpContainer *container;
+ GimpContext *context;
+ GimpImage *image;
+
+ container = gimp_container_view_get_container (editor->view);
+ context = gimp_container_view_get_context (editor->view);
+
+ image = gimp_context_get_image (context);
+
+ if (image && gimp_container_have (container, GIMP_OBJECT (image)))
+ {
+ GList *list;
+
+ for (list = gimp_get_display_iter (image->gimp);
+ list;
+ list = g_list_next (list))
+ {
+ GimpDisplay *display = list->data;
+
+ if (gimp_display_get_image (display) == image)
+ gimp_display_shell_present (gimp_display_get_shell (display));
+ }
+ }
+}
+
+void
+images_new_view_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpContainerEditor *editor = GIMP_CONTAINER_EDITOR (data);
+ GimpContainer *container;
+ GimpContext *context;
+ GimpImage *image;
+
+ container = gimp_container_view_get_container (editor->view);
+ context = gimp_container_view_get_context (editor->view);
+
+ image = gimp_context_get_image (context);
+
+ if (image && gimp_container_have (container, GIMP_OBJECT (image)))
+ {
+ gimp_create_display (image->gimp, image, GIMP_UNIT_PIXEL, 1.0,
+ G_OBJECT (gtk_widget_get_screen (GTK_WIDGET (editor))),
+ gimp_widget_get_monitor (GTK_WIDGET (editor)));
+ }
+}
+
+void
+images_delete_image_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpContainerEditor *editor = GIMP_CONTAINER_EDITOR (data);
+ GimpContainer *container;
+ GimpContext *context;
+ GimpImage *image;
+
+ container = gimp_container_view_get_container (editor->view);
+ context = gimp_container_view_get_context (editor->view);
+
+ image = gimp_context_get_image (context);
+
+ if (image && gimp_container_have (container, GIMP_OBJECT (image)))
+ {
+ if (gimp_image_get_display_count (image) == 0)
+ g_object_unref (image);
+ }
+}
diff --git a/app/actions/images-commands.h b/app/actions/images-commands.h
new file mode 100644
index 0000000..f836fc4
--- /dev/null
+++ b/app/actions/images-commands.h
@@ -0,0 +1,33 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __IMAGES_COMMANDS_H__
+#define __IMAGES_COMMANDS_H__
+
+
+void images_raise_views_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void images_new_view_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void images_delete_image_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+
+#endif /* __IMAGES_COMMANDS_H__ */
diff --git a/app/actions/items-actions.c b/app/actions/items-actions.c
new file mode 100644
index 0000000..5f18e1f
--- /dev/null
+++ b/app/actions/items-actions.c
@@ -0,0 +1,142 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "actions-types.h"
+
+#include "core/gimp.h"
+#include "core/gimpitem.h"
+
+#include "widgets/gimpactiongroup.h"
+#include "widgets/gimpwidgets-utils.h"
+
+#include "items-actions.h"
+
+
+void
+items_actions_setup (GimpActionGroup *group,
+ const gchar *prefix)
+{
+ GEnumClass *enum_class;
+ GEnumValue *value;
+
+ enum_class = g_type_class_ref (GIMP_TYPE_COLOR_TAG);
+
+ for (value = enum_class->values; value->value_name; value++)
+ {
+ gchar action[32];
+
+ g_snprintf (action, sizeof (action),
+ "%s-color-tag-%s", prefix, value->value_nick);
+
+ if (value->value == GIMP_COLOR_TAG_NONE)
+ {
+ gimp_action_group_set_action_always_show_image (group, action, TRUE);
+ }
+ else
+ {
+ GimpRGB color;
+
+ gimp_action_group_set_action_context (group, action,
+ gimp_get_user_context (group->gimp));
+
+ gimp_get_color_tag_color (value->value, &color, FALSE);
+ gimp_action_group_set_action_color (group, action, &color, FALSE);
+ }
+ }
+
+ g_type_class_unref (enum_class);
+}
+
+void
+items_actions_update (GimpActionGroup *group,
+ const gchar *prefix,
+ GimpItem *item)
+{
+ GEnumClass *enum_class;
+ GEnumValue *value;
+ gchar action[32];
+ gboolean visible = FALSE;
+ gboolean linked = FALSE;
+ gboolean has_color_tag = FALSE;
+ gboolean locked = FALSE;
+ gboolean can_lock = FALSE;
+ gboolean locked_pos = FALSE;
+ gboolean can_lock_pos = FALSE;
+ GimpRGB tag_color;
+
+ if (item)
+ {
+ visible = gimp_item_get_visible (item);
+ linked = gimp_item_get_linked (item);
+ locked = gimp_item_get_lock_content (item);
+ can_lock = gimp_item_can_lock_content (item);
+ locked_pos = gimp_item_get_lock_position (item);
+ can_lock_pos = gimp_item_can_lock_position (item);
+
+ has_color_tag = gimp_get_color_tag_color (gimp_item_get_color_tag (item),
+ &tag_color, FALSE);
+ }
+
+#define SET_SENSITIVE(action,condition) \
+ gimp_action_group_set_action_sensitive (group, action, (condition) != 0)
+#define SET_ACTIVE(action,condition) \
+ gimp_action_group_set_action_active (group, action, (condition) != 0)
+#define SET_COLOR(action,color) \
+ gimp_action_group_set_action_color (group, action, color, FALSE)
+
+ g_snprintf (action, sizeof (action), "%s-visible", prefix);
+ SET_SENSITIVE (action, item);
+ SET_ACTIVE (action, visible);
+
+ g_snprintf (action, sizeof (action), "%s-linked", prefix);
+ SET_SENSITIVE (action, item);
+ SET_ACTIVE (action, linked);
+
+ g_snprintf (action, sizeof (action), "%s-lock-content", prefix);
+ SET_SENSITIVE (action, can_lock);
+ SET_ACTIVE (action, locked);
+
+ g_snprintf (action, sizeof (action), "%s-lock-position", prefix);
+ SET_SENSITIVE (action, can_lock_pos);
+ SET_ACTIVE (action, locked_pos);
+
+ g_snprintf (action, sizeof (action), "%s-color-tag-menu", prefix);
+ SET_COLOR (action, has_color_tag ? &tag_color : NULL);
+
+ enum_class = g_type_class_ref (GIMP_TYPE_COLOR_TAG);
+
+ for (value = enum_class->values; value->value_name; value++)
+ {
+ g_snprintf (action, sizeof (action),
+ "%s-color-tag-%s", prefix, value->value_nick);
+
+ SET_SENSITIVE (action, item);
+ }
+
+ g_type_class_unref (enum_class);
+
+#undef SET_SENSITIVE
+#undef SET_ACTIVE
+#undef SET_COLOR
+}
diff --git a/app/actions/items-actions.h b/app/actions/items-actions.h
new file mode 100644
index 0000000..90efc08
--- /dev/null
+++ b/app/actions/items-actions.h
@@ -0,0 +1,29 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __ITEMS_ACTIONS_H__
+#define __ITEMS_ACTIONS_H__
+
+
+void items_actions_setup (GimpActionGroup *group,
+ const gchar *prefix);
+void items_actions_update (GimpActionGroup *group,
+ const gchar *prefix,
+ GimpItem *item);
+
+
+#endif /* __ITEMS_ACTIONS_H__ */
diff --git a/app/actions/items-commands.c b/app/actions/items-commands.c
new file mode 100644
index 0000000..43e17d9
--- /dev/null
+++ b/app/actions/items-commands.c
@@ -0,0 +1,419 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpconfig/gimpconfig.h"
+
+#include "actions-types.h"
+
+#include "config/gimpdialogconfig.h"
+
+#include "core/gimp.h"
+#include "core/gimpcontext.h"
+#include "core/gimpimage.h"
+#include "core/gimpimage-undo.h"
+#include "core/gimpitem.h"
+#include "core/gimpitemundo.h"
+
+#include "dialogs/dialogs.h"
+#include "dialogs/fill-dialog.h"
+#include "dialogs/stroke-dialog.h"
+
+#include "actions.h"
+#include "items-commands.h"
+
+#include "gimp-intl.h"
+
+
+/* local function prototypes */
+
+static void items_fill_callback (GtkWidget *dialog,
+ GimpItem *item,
+ GimpDrawable *drawable,
+ GimpContext *context,
+ GimpFillOptions *options,
+ gpointer user_data);
+static void items_stroke_callback (GtkWidget *dialog,
+ GimpItem *item,
+ GimpDrawable *drawable,
+ GimpContext *context,
+ GimpStrokeOptions *options,
+ gpointer user_data);
+
+
+/* public functions */
+
+void
+items_visible_cmd_callback (GimpAction *action,
+ GVariant *value,
+ GimpImage *image,
+ GimpItem *item)
+{
+ gboolean visible = g_variant_get_boolean (value);
+
+ if (visible != gimp_item_get_visible (item))
+ {
+ GimpUndo *undo;
+ gboolean push_undo = TRUE;
+
+ undo = gimp_image_undo_can_compress (image, GIMP_TYPE_ITEM_UNDO,
+ GIMP_UNDO_ITEM_VISIBILITY);
+
+ if (undo && GIMP_ITEM_UNDO (undo)->item == item)
+ push_undo = FALSE;
+
+ gimp_item_set_visible (item, visible, push_undo);
+ gimp_image_flush (image);
+ }
+}
+
+void
+items_linked_cmd_callback (GimpAction *action,
+ GVariant *value,
+ GimpImage *image,
+ GimpItem *item)
+{
+ gboolean linked = g_variant_get_boolean (value);
+
+ if (linked != gimp_item_get_linked (item))
+ {
+ GimpUndo *undo;
+ gboolean push_undo = TRUE;
+
+ undo = gimp_image_undo_can_compress (image, GIMP_TYPE_ITEM_UNDO,
+ GIMP_UNDO_ITEM_LINKED);
+
+ if (undo && GIMP_ITEM_UNDO (undo)->item == item)
+ push_undo = FALSE;
+
+ gimp_item_set_linked (item, linked, push_undo);
+ gimp_image_flush (image);
+ }
+}
+
+void
+items_lock_content_cmd_callback (GimpAction *action,
+ GVariant *value,
+ GimpImage *image,
+ GimpItem *item)
+{
+ gboolean locked = g_variant_get_boolean (value);
+
+ if (locked != gimp_item_get_lock_content (item))
+ {
+ GimpUndo *undo;
+ gboolean push_undo = TRUE;
+
+ undo = gimp_image_undo_can_compress (image, GIMP_TYPE_ITEM_UNDO,
+ GIMP_UNDO_ITEM_LINKED);
+
+ if (undo && GIMP_ITEM_UNDO (undo)->item == item)
+ push_undo = FALSE;
+
+ gimp_item_set_lock_content (item, locked, push_undo);
+ gimp_image_flush (image);
+ }
+}
+
+void
+items_lock_position_cmd_callback (GimpAction *action,
+ GVariant *value,
+ GimpImage *image,
+ GimpItem *item)
+{
+ gboolean locked = g_variant_get_boolean (value);
+
+ if (locked != gimp_item_get_lock_position (item))
+ {
+ GimpUndo *undo;
+ gboolean push_undo = TRUE;
+
+ undo = gimp_image_undo_can_compress (image, GIMP_TYPE_ITEM_UNDO,
+ GIMP_UNDO_ITEM_LOCK_POSITION);
+
+ if (undo && GIMP_ITEM_UNDO (undo)->item == item)
+ push_undo = FALSE;
+
+
+ gimp_item_set_lock_position (item, locked, push_undo);
+ gimp_image_flush (image);
+ }
+}
+
+void
+items_color_tag_cmd_callback (GimpAction *action,
+ GimpImage *image,
+ GimpItem *item,
+ GimpColorTag color_tag)
+{
+ if (color_tag != gimp_item_get_color_tag (item))
+ {
+ GimpUndo *undo;
+ gboolean push_undo = TRUE;
+
+ undo = gimp_image_undo_can_compress (image, GIMP_TYPE_ITEM_UNDO,
+ GIMP_UNDO_ITEM_COLOR_TAG);
+
+ if (undo && GIMP_ITEM_UNDO (undo)->item == item)
+ push_undo = FALSE;
+
+ gimp_item_set_color_tag (item, color_tag, push_undo);
+ gimp_image_flush (image);
+ }
+}
+
+void
+items_fill_cmd_callback (GimpAction *action,
+ GimpImage *image,
+ GimpItem *item,
+ const gchar *dialog_key,
+ const gchar *dialog_title,
+ const gchar *dialog_icon_name,
+ const gchar *dialog_help_id,
+ gpointer data)
+{
+ GimpDrawable *drawable;
+ GtkWidget *dialog;
+ GtkWidget *widget;
+ 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 = dialogs_get_dialog (G_OBJECT (item), dialog_key);
+
+ if (! dialog)
+ {
+ GimpDialogConfig *config = GIMP_DIALOG_CONFIG (image->gimp->config);
+
+ dialog = fill_dialog_new (item,
+ drawable,
+ action_data_get_context (data),
+ dialog_title,
+ dialog_icon_name,
+ dialog_help_id,
+ widget,
+ config->fill_options,
+ items_fill_callback,
+ NULL);
+
+ dialogs_attach_dialog (G_OBJECT (item), dialog_key, dialog);
+ }
+
+ gtk_window_present (GTK_WINDOW (dialog));
+}
+
+void
+items_fill_last_vals_cmd_callback (GimpAction *action,
+ GimpImage *image,
+ GimpItem *item,
+ gpointer data)
+{
+ GimpDrawable *drawable;
+ GimpDialogConfig *config;
+ GtkWidget *widget;
+ GError *error = NULL;
+ 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;
+ }
+
+ config = GIMP_DIALOG_CONFIG (image->gimp->config);
+
+ if (! gimp_item_fill (item, drawable,
+ config->fill_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);
+ }
+}
+
+void
+items_stroke_cmd_callback (GimpAction *action,
+ GimpImage *image,
+ GimpItem *item,
+ const gchar *dialog_key,
+ const gchar *dialog_title,
+ const gchar *dialog_icon_name,
+ const gchar *dialog_help_id,
+ gpointer data)
+{
+ GimpDrawable *drawable;
+ GtkWidget *dialog;
+ GtkWidget *widget;
+ 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 stroke to."));
+ return;
+ }
+
+ dialog = dialogs_get_dialog (G_OBJECT (item), dialog_key);
+
+ if (! dialog)
+ {
+ GimpDialogConfig *config = GIMP_DIALOG_CONFIG (image->gimp->config);
+
+ dialog = stroke_dialog_new (item,
+ drawable,
+ action_data_get_context (data),
+ dialog_title,
+ dialog_icon_name,
+ dialog_help_id,
+ widget,
+ config->stroke_options,
+ items_stroke_callback,
+ NULL);
+
+ dialogs_attach_dialog (G_OBJECT (item), dialog_key, dialog);
+ }
+
+ gtk_window_present (GTK_WINDOW (dialog));
+}
+
+void
+items_stroke_last_vals_cmd_callback (GimpAction *action,
+ GimpImage *image,
+ GimpItem *item,
+ gpointer data)
+{
+ GimpDrawable *drawable;
+ GimpDialogConfig *config;
+ GtkWidget *widget;
+ GError *error = NULL;
+ 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 stroke to."));
+ return;
+ }
+
+ config = GIMP_DIALOG_CONFIG (image->gimp->config);
+
+ if (! gimp_item_stroke (item, drawable,
+ action_data_get_context (data),
+ config->stroke_options, NULL,
+ 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);
+ }
+}
+
+
+/* private functions */
+
+static void
+items_fill_callback (GtkWidget *dialog,
+ GimpItem *item,
+ GimpDrawable *drawable,
+ GimpContext *context,
+ GimpFillOptions *options,
+ gpointer user_data)
+{
+ GimpDialogConfig *config = GIMP_DIALOG_CONFIG (context->gimp->config);
+ GimpImage *image = gimp_item_get_image (item);
+ GError *error = NULL;
+
+ gimp_config_sync (G_OBJECT (options),
+ G_OBJECT (config->fill_options), 0);
+
+ if (! gimp_item_fill (item, drawable, options, TRUE, NULL, &error))
+ {
+ gimp_message_literal (context->gimp,
+ G_OBJECT (dialog),
+ GIMP_MESSAGE_WARNING,
+ error ? error->message : "NULL");
+
+ g_clear_error (&error);
+ return;
+ }
+
+ gimp_image_flush (image);
+
+ gtk_widget_destroy (dialog);
+}
+
+static void
+items_stroke_callback (GtkWidget *dialog,
+ GimpItem *item,
+ GimpDrawable *drawable,
+ GimpContext *context,
+ GimpStrokeOptions *options,
+ gpointer data)
+{
+ GimpDialogConfig *config = GIMP_DIALOG_CONFIG (context->gimp->config);
+ GimpImage *image = gimp_item_get_image (item);
+ GError *error = NULL;
+
+ gimp_config_sync (G_OBJECT (options),
+ G_OBJECT (config->stroke_options), 0);
+
+ if (! gimp_item_stroke (item, drawable, context, options, NULL,
+ TRUE, NULL, &error))
+ {
+ gimp_message_literal (context->gimp,
+ G_OBJECT (dialog),
+ GIMP_MESSAGE_WARNING,
+ error ? error->message : "NULL");
+
+ g_clear_error (&error);
+ return;
+ }
+
+ gimp_image_flush (image);
+
+ gtk_widget_destroy (dialog);
+}
diff --git a/app/actions/items-commands.h b/app/actions/items-commands.h
new file mode 100644
index 0000000..f7c87b5
--- /dev/null
+++ b/app/actions/items-commands.h
@@ -0,0 +1,72 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __ITEMS_COMMANDS_H__
+#define __ITEMS_COMMANDS_H__
+
+
+void items_visible_cmd_callback (GimpAction *action,
+ GVariant *value,
+ GimpImage *image,
+ GimpItem *item);
+void items_linked_cmd_callback (GimpAction *action,
+ GVariant *value,
+ GimpImage *image,
+ GimpItem *item);
+void items_lock_content_cmd_callback (GimpAction *action,
+ GVariant *value,
+ GimpImage *image,
+ GimpItem *item);
+void items_lock_position_cmd_callback (GimpAction *action,
+ GVariant *value,
+ GimpImage *image,
+ GimpItem *item);
+
+void items_color_tag_cmd_callback (GimpAction *action,
+ GimpImage *image,
+ GimpItem *item,
+ GimpColorTag color_tag);
+
+void items_fill_cmd_callback (GimpAction *action,
+ GimpImage *image,
+ GimpItem *item,
+ const gchar *dialog_key,
+ const gchar *dialog_title,
+ const gchar *dialog_icon_name,
+ const gchar *dialog_help_id,
+ gpointer data);
+void items_fill_last_vals_cmd_callback (GimpAction *action,
+ GimpImage *image,
+ GimpItem *item,
+ gpointer data);
+
+void items_stroke_cmd_callback (GimpAction *action,
+ GimpImage *image,
+ GimpItem *item,
+ const gchar *dialog_key,
+ const gchar *dialog_title,
+ const gchar *dialog_icon_name,
+ const gchar *dialog_help_id,
+ gpointer data);
+void items_stroke_last_vals_cmd_callback (GimpAction *action,
+ GimpImage *image,
+ GimpItem *item,
+ gpointer data);
+
+
+
+#endif /* __ITEMS_COMMANDS_H__ */
diff --git a/app/actions/layers-actions.c b/app/actions/layers-actions.c
new file mode 100644
index 0000000..2100696
--- /dev/null
+++ b/app/actions/layers-actions.c
@@ -0,0 +1,1027 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "actions-types.h"
+
+#include "operations/layer-modes/gimp-layer-modes.h"
+
+#include "core/gimpchannel.h"
+#include "core/gimpimage.h"
+#include "core/gimplayer.h"
+#include "core/gimplayer-floating-selection.h"
+
+#include "text/gimptextlayer.h"
+
+#include "widgets/gimphelp-ids.h"
+#include "widgets/gimpactiongroup.h"
+#include "widgets/gimpwidgets-utils.h"
+
+#include "actions.h"
+#include "image-commands.h"
+#include "items-actions.h"
+#include "layers-actions.h"
+#include "layers-commands.h"
+
+#include "gimp-intl.h"
+
+
+static const GimpActionEntry layers_actions[] =
+{
+ { "layers-popup", GIMP_ICON_DIALOG_LAYERS,
+ NC_("layers-action", "Layers Menu"), NULL, NULL, NULL,
+ GIMP_HELP_LAYER_DIALOG },
+
+ { "layers-blend-space-menu", NULL,
+ NC_("layers-action", "Blend Space"), NULL, NULL, NULL,
+ NULL },
+
+ { "layers-composite-space-menu", NULL,
+ NC_("layers-action", "Composite Space"), NULL, NULL, NULL,
+ NULL },
+
+ { "layers-composite-mode-menu", NULL,
+ NC_("layers-action", "Composite Mode"), NULL, NULL, NULL,
+ NULL },
+
+ { "layers-color-tag-menu", NULL,
+ NC_("layers-action", "Color Tag"), NULL, NULL, NULL,
+ GIMP_HELP_LAYER_COLOR_TAG },
+
+ { "layers-menu", NULL,
+ NC_("layers-action", "_Layer") },
+ { "layers-stack-menu", NULL,
+ NC_("layers-action", "Stac_k") },
+ { "layers-mask-menu", NULL,
+ NC_("layers-action", "_Mask") },
+ { "layers-transparency-menu", NULL,
+ NC_("layers-action", "Tr_ansparency") },
+ { "layers-transform-menu", NULL,
+ NC_("layers-action", "_Transform") },
+ { "layers-properties-menu", GIMP_ICON_DOCUMENT_PROPERTIES,
+ NC_("layers-action", "_Properties") },
+ { "layers-opacity-menu", GIMP_ICON_TRANSPARENCY,
+ NC_("layers-action", "_Opacity") },
+ { "layers-mode-menu", GIMP_ICON_TOOL_PENCIL,
+ NC_("layers-action", "Layer _Mode") },
+
+ { "layers-edit", GIMP_ICON_EDIT,
+ NC_("layers-action", "Default Edit Action"), NULL,
+ NC_("layers-action", "Activate the default edit action for this type of layer"),
+ layers_edit_cmd_callback,
+ GIMP_HELP_LAYER_EDIT },
+
+ { "layers-edit-text", GIMP_ICON_EDIT,
+ NC_("layers-action", "Edit Te_xt on canvas"), NULL,
+ NC_("layers-action", "Edit this text layer content on canvas"),
+ layers_edit_text_cmd_callback,
+ GIMP_HELP_LAYER_EDIT },
+
+ { "layers-edit-attributes", GIMP_ICON_EDIT,
+ NC_("layers-action", "_Edit Layer Attributes..."), NULL,
+ NC_("layers-action", "Edit the layer's name"),
+ layers_edit_attributes_cmd_callback,
+ GIMP_HELP_LAYER_EDIT },
+
+ { "layers-new", GIMP_ICON_DOCUMENT_NEW,
+ NC_("layers-action", "_New Layer..."), "<primary><shift>N",
+ NC_("layers-action", "Create a new layer and add it to the image"),
+ layers_new_cmd_callback,
+ GIMP_HELP_LAYER_NEW },
+
+ { "layers-new-last-values", GIMP_ICON_DOCUMENT_NEW,
+ NC_("layers-action", "_New Layer"), NULL,
+ NC_("layers-action", "Create a new layer with last used values"),
+ layers_new_last_vals_cmd_callback,
+ GIMP_HELP_LAYER_NEW },
+
+ { "layers-new-from-visible", NULL,
+ NC_("layers-action", "New from _Visible"), NULL,
+ NC_("layers-action",
+ "Create a new layer from what is visible in this image"),
+ layers_new_from_visible_cmd_callback,
+ GIMP_HELP_LAYER_NEW_FROM_VISIBLE },
+
+ { "layers-new-group", GIMP_ICON_FOLDER_NEW,
+ NC_("layers-action", "New Layer _Group"), NULL,
+ NC_("layers-action", "Create a new layer group and add it to the image"),
+ layers_new_group_cmd_callback,
+ GIMP_HELP_LAYER_NEW },
+
+ { "layers-duplicate", GIMP_ICON_OBJECT_DUPLICATE,
+ NC_("layers-action", "D_uplicate Layer"), "<primary><shift>D",
+ NC_("layers-action",
+ "Create a duplicate of the layer and add it to the image"),
+ layers_duplicate_cmd_callback,
+ GIMP_HELP_LAYER_DUPLICATE },
+
+ { "layers-delete", GIMP_ICON_EDIT_DELETE,
+ NC_("layers-action", "_Delete Layer"), NULL,
+ NC_("layers-action", "Delete this layer"),
+ layers_delete_cmd_callback,
+ GIMP_HELP_LAYER_DELETE },
+
+ { "layers-raise", GIMP_ICON_GO_UP,
+ NC_("layers-action", "_Raise Layer"), NULL,
+ NC_("layers-action", "Raise this layer one step in the layer stack"),
+ layers_raise_cmd_callback,
+ GIMP_HELP_LAYER_RAISE },
+
+ { "layers-raise-to-top", GIMP_ICON_GO_TOP,
+ NC_("layers-action", "Layer to _Top"), NULL,
+ NC_("layers-action", "Move this layer to the top of the layer stack"),
+ layers_raise_to_top_cmd_callback,
+ GIMP_HELP_LAYER_RAISE_TO_TOP },
+
+ { "layers-lower", GIMP_ICON_GO_DOWN,
+ NC_("layers-action", "_Lower Layer"), NULL,
+ NC_("layers-action", "Lower this layer one step in the layer stack"),
+ layers_lower_cmd_callback,
+ GIMP_HELP_LAYER_LOWER },
+
+ { "layers-lower-to-bottom", GIMP_ICON_GO_BOTTOM,
+ NC_("layers-action", "Layer to _Bottom"), NULL,
+ NC_("layers-action", "Move this layer to the bottom of the layer stack"),
+ layers_lower_to_bottom_cmd_callback,
+ GIMP_HELP_LAYER_LOWER_TO_BOTTOM },
+
+ { "layers-anchor", GIMP_ICON_LAYER_ANCHOR,
+ NC_("layers-action", "_Anchor Layer"), "<primary>H",
+ NC_("layers-action", "Anchor the floating layer"),
+ layers_anchor_cmd_callback,
+ GIMP_HELP_LAYER_ANCHOR },
+
+ { "layers-merge-down", GIMP_ICON_LAYER_MERGE_DOWN,
+ NC_("layers-action", "Merge Do_wn"), NULL,
+ NC_("layers-action", "Merge this layer with the first visible layer below it"),
+ layers_merge_down_cmd_callback,
+ GIMP_HELP_LAYER_MERGE_DOWN },
+
+ /* this is the same as layers-merge-down, except it's sensitive even if
+ * the layer can't be merged down
+ */
+ { "layers-merge-down-button", GIMP_ICON_LAYER_MERGE_DOWN,
+ NC_("layers-action", "Merge Do_wn"), NULL,
+ NC_("layers-action", "Merge this layer with the first visible layer below it"),
+ layers_merge_down_cmd_callback,
+ GIMP_HELP_LAYER_MERGE_DOWN },
+
+ { "layers-merge-group", NULL,
+ NC_("layers-action", "Merge Layer Group"), NULL,
+ NC_("layers-action", "Merge the layer group's layers into one normal layer"),
+ layers_merge_group_cmd_callback,
+ GIMP_HELP_LAYER_MERGE_GROUP },
+
+ { "layers-merge-layers", NULL,
+ NC_("layers-action", "Merge _Visible Layers..."), NULL,
+ NC_("layers-action", "Merge all visible layers into one layer"),
+ image_merge_layers_cmd_callback,
+ GIMP_HELP_IMAGE_MERGE_LAYERS },
+
+ { "layers-merge-layers-last-values", NULL,
+ NC_("layers-action", "Merge _Visible Layers"), NULL,
+ NC_("layers-action", "Merge all visible layers with last used values"),
+ image_merge_layers_last_vals_cmd_callback,
+ GIMP_HELP_IMAGE_MERGE_LAYERS },
+
+ { "layers-flatten-image", NULL,
+ NC_("layers-action", "_Flatten Image"), NULL,
+ NC_("layers-action", "Merge all layers into one and remove transparency"),
+ image_flatten_image_cmd_callback,
+ GIMP_HELP_IMAGE_FLATTEN },
+
+ { "layers-text-discard", GIMP_ICON_TOOL_TEXT,
+ NC_("layers-action", "_Discard Text Information"), NULL,
+ NC_("layers-action", "Turn this text layer into a normal layer"),
+ layers_text_discard_cmd_callback,
+ GIMP_HELP_LAYER_TEXT_DISCARD },
+
+ { "layers-text-to-vectors", GIMP_ICON_TOOL_TEXT,
+ NC_("layers-action", "Text to _Path"), NULL,
+ NC_("layers-action", "Create a path from this text layer"),
+ layers_text_to_vectors_cmd_callback,
+ GIMP_HELP_LAYER_TEXT_TO_PATH },
+
+ { "layers-text-along-vectors", GIMP_ICON_TOOL_TEXT,
+ NC_("layers-action", "Text alon_g Path"), NULL,
+ NC_("layers-action", "Warp this layer's text along the current path"),
+ layers_text_along_vectors_cmd_callback,
+ GIMP_HELP_LAYER_TEXT_ALONG_PATH },
+
+ { "layers-resize", GIMP_ICON_OBJECT_RESIZE,
+ NC_("layers-action", "Layer B_oundary Size..."), NULL,
+ NC_("layers-action", "Adjust the layer dimensions"),
+ layers_resize_cmd_callback,
+ GIMP_HELP_LAYER_RESIZE },
+
+ { "layers-resize-to-image", GIMP_ICON_LAYER_TO_IMAGESIZE,
+ NC_("layers-action", "Layer to _Image Size"), NULL,
+ NC_("layers-action", "Resize the layer to the size of the image"),
+ layers_resize_to_image_cmd_callback,
+ GIMP_HELP_LAYER_RESIZE_TO_IMAGE },
+
+ { "layers-scale", GIMP_ICON_OBJECT_SCALE,
+ NC_("layers-action", "_Scale Layer..."), NULL,
+ NC_("layers-action", "Change the size of the layer content"),
+ layers_scale_cmd_callback,
+ GIMP_HELP_LAYER_SCALE },
+
+ { "layers-crop-to-selection", GIMP_ICON_TOOL_CROP,
+ NC_("layers-action", "_Crop to Selection"), NULL,
+ NC_("layers-action", "Crop the layer to the extents of the selection"),
+ layers_crop_to_selection_cmd_callback,
+ GIMP_HELP_LAYER_CROP },
+
+ { "layers-crop-to-content", GIMP_ICON_TOOL_CROP,
+ NC_("layers-action", "Crop to C_ontent"), NULL,
+ NC_("layers-action", "Crop the layer to the extents of its content (remove empty borders from the layer)"),
+ layers_crop_to_content_cmd_callback,
+ GIMP_HELP_LAYER_CROP },
+
+ { "layers-mask-add", GIMP_ICON_LAYER_MASK,
+ NC_("layers-action", "Add La_yer Mask..."), NULL,
+ NC_("layers-action",
+ "Add a mask that allows non-destructive editing of transparency"),
+ layers_mask_add_cmd_callback,
+ GIMP_HELP_LAYER_MASK_ADD },
+
+ /* this is the same as layers-mask-add, except it's sensitive even if
+ * there is a mask on the layer
+ */
+ { "layers-mask-add-button", GIMP_ICON_LAYER_MASK,
+ NC_("layers-action", "Add La_yer Mask..."), NULL,
+ NC_("layers-action",
+ "Add a mask that allows non-destructive editing of transparency"),
+ layers_mask_add_cmd_callback,
+ GIMP_HELP_LAYER_MASK_ADD },
+
+ { "layers-mask-add-last-values", GIMP_ICON_LAYER_MASK,
+ NC_("layers-action", "Add La_yer Mask"), NULL,
+ NC_("layers-action",
+ "Add a mask with last used values"),
+ layers_mask_add_last_vals_cmd_callback,
+ GIMP_HELP_LAYER_MASK_ADD },
+
+ { "layers-alpha-add", GIMP_ICON_TRANSPARENCY,
+ NC_("layers-action", "Add Alpha C_hannel"), NULL,
+ NC_("layers-action", "Add transparency information to the layer"),
+ layers_alpha_add_cmd_callback,
+ GIMP_HELP_LAYER_ALPHA_ADD },
+
+ { "layers-alpha-remove", NULL,
+ NC_("layers-action", "_Remove Alpha Channel"), NULL,
+ NC_("layers-action", "Remove transparency information from the layer"),
+ layers_alpha_remove_cmd_callback,
+ GIMP_HELP_LAYER_ALPHA_REMOVE }
+};
+
+static const GimpToggleActionEntry layers_toggle_actions[] =
+{
+ { "layers-mask-edit", GIMP_ICON_EDIT,
+ NC_("layers-action", "_Edit Layer Mask"), NULL,
+ NC_("layers-action", "Work on the layer mask"),
+ layers_mask_edit_cmd_callback,
+ FALSE,
+ GIMP_HELP_LAYER_MASK_EDIT },
+
+ { "layers-mask-show", GIMP_ICON_VISIBLE,
+ NC_("layers-action", "S_how Layer Mask"), NULL, NULL,
+ layers_mask_show_cmd_callback,
+ FALSE,
+ GIMP_HELP_LAYER_MASK_SHOW },
+
+ { "layers-mask-disable", NULL,
+ NC_("layers-action", "_Disable Layer Mask"), NULL,
+ NC_("layers-action", "Dismiss the effect of the layer mask"),
+ layers_mask_disable_cmd_callback,
+ FALSE,
+ GIMP_HELP_LAYER_MASK_DISABLE },
+
+ { "layers-visible", GIMP_ICON_VISIBLE,
+ NC_("layers-action", "Toggle Layer _Visibility"), NULL, NULL,
+ layers_visible_cmd_callback,
+ FALSE,
+ GIMP_HELP_LAYER_VISIBLE },
+
+ { "layers-linked", GIMP_ICON_LINKED,
+ NC_("layers-action", "Toggle Layer _Linked State"), NULL, NULL,
+ layers_linked_cmd_callback,
+ FALSE,
+ GIMP_HELP_LAYER_LINKED },
+
+ { "layers-lock-content", NULL /* GIMP_ICON_LOCK */,
+ NC_("layers-action", "L_ock Pixels of Layer"), NULL, NULL,
+ layers_lock_content_cmd_callback,
+ FALSE,
+ GIMP_HELP_LAYER_LOCK_PIXELS },
+
+ { "layers-lock-position", GIMP_ICON_TOOL_MOVE,
+ NC_("layers-action", "L_ock Position of Layer"), NULL, NULL,
+ layers_lock_position_cmd_callback,
+ FALSE,
+ GIMP_HELP_LAYER_LOCK_POSITION },
+
+ { "layers-lock-alpha", GIMP_ICON_TRANSPARENCY,
+ NC_("layers-action", "Lock Alph_a Channel"), NULL,
+ NC_("layers-action",
+ "Keep transparency information on this layer from being modified"),
+ layers_lock_alpha_cmd_callback,
+ FALSE,
+ GIMP_HELP_LAYER_LOCK_ALPHA },
+};
+
+static const GimpRadioActionEntry layers_blend_space_actions[] =
+{
+ { "layers-blend-space-auto", NULL,
+ NC_("layers-action", "Auto"), NULL,
+ NC_("layers-action", "Layer Blend Space: Auto"),
+ GIMP_LAYER_COLOR_SPACE_AUTO,
+ NULL },
+
+ { "layers-blend-space-rgb-linear", NULL,
+ NC_("layers-action", "RGB (linear)"), NULL,
+ NC_("layers-action", "Layer Blend Space: RGB (linear)"),
+ GIMP_LAYER_COLOR_SPACE_RGB_LINEAR,
+ NULL },
+
+ { "layers-blend-space-rgb-perceptual", NULL,
+ NC_("layers-action", "RGB (perceptual)"), NULL,
+ NC_("layers-action", "Layer Blend Space: RGB (perceptual)"),
+ GIMP_LAYER_COLOR_SPACE_RGB_PERCEPTUAL,
+ NULL }
+};
+
+static const GimpRadioActionEntry layers_composite_space_actions[] =
+{
+ { "layers-composite-space-auto", NULL,
+ NC_("layers-action", "Auto"), NULL,
+ NC_("layers-action", "Layer Composite Space: Auto"),
+ GIMP_LAYER_COLOR_SPACE_AUTO,
+ NULL },
+
+ { "layers-composite-space-rgb-linear", NULL,
+ NC_("layers-action", "RGB (linear)"), NULL,
+ NC_("layers-action", "Layer Composite Space: RGB (linear)"),
+ GIMP_LAYER_COLOR_SPACE_RGB_LINEAR,
+ NULL },
+
+ { "layers-composite-space-rgb-perceptual", NULL,
+ NC_("layers-action", "RGB (perceptual)"), NULL,
+ NC_("layers-action", "Layer Composite Space: RGB (perceptual)"),
+ GIMP_LAYER_COLOR_SPACE_RGB_PERCEPTUAL,
+ NULL }
+};
+
+static const GimpRadioActionEntry layers_composite_mode_actions[] =
+{
+ { "layers-composite-mode-auto", NULL,
+ NC_("layers-action", "Auto"), NULL,
+ NC_("layers-action", "Layer Composite Mode: Auto"),
+ GIMP_LAYER_COMPOSITE_AUTO,
+ NULL },
+
+ { "layers-composite-mode-union", NULL,
+ NC_("layers-action", "Union"), NULL,
+ NC_("layers-action", "Layer Composite Mode: Union"),
+ GIMP_LAYER_COMPOSITE_UNION,
+ NULL },
+
+ { "layers-composite-mode-clip-to-backdrop", NULL,
+ NC_("layers-action", "Clip to Backdrop"), NULL,
+ NC_("layers-action", "Layer Composite Mode: Clip to Backdrop"),
+ GIMP_LAYER_COMPOSITE_CLIP_TO_BACKDROP,
+ NULL },
+
+ { "layers-composite-mode-clip-to-layer", NULL,
+ NC_("layers-action", "Clip to Layer"), NULL,
+ NC_("layers-action", "Layer Composite Mode: Clip to Layer"),
+ GIMP_LAYER_COMPOSITE_CLIP_TO_LAYER,
+ NULL },
+
+ { "layers-composite-mode-intersection", NULL,
+ NC_("layers-action", "Intersection"), NULL,
+ NC_("layers-action", "Layer Composite Mode: Intersection"),
+ GIMP_LAYER_COMPOSITE_INTERSECTION,
+ NULL }
+};
+
+static const GimpEnumActionEntry layers_color_tag_actions[] =
+{
+ { "layers-color-tag-none", GIMP_ICON_EDIT_CLEAR,
+ NC_("layers-action", "None"), NULL,
+ NC_("layers-action", "Layer Color Tag: Clear"),
+ GIMP_COLOR_TAG_NONE, FALSE,
+ GIMP_HELP_LAYER_COLOR_TAG },
+
+ { "layers-color-tag-blue", NULL,
+ NC_("layers-action", "Blue"), NULL,
+ NC_("layers-action", "Layer Color Tag: Set to Blue"),
+ GIMP_COLOR_TAG_BLUE, FALSE,
+ GIMP_HELP_LAYER_COLOR_TAG },
+
+ { "layers-color-tag-green", NULL,
+ NC_("layers-action", "Green"), NULL,
+ NC_("layers-action", "Layer Color Tag: Set to Green"),
+ GIMP_COLOR_TAG_GREEN, FALSE,
+ GIMP_HELP_LAYER_COLOR_TAG },
+
+ { "layers-color-tag-yellow", NULL,
+ NC_("layers-action", "Yellow"), NULL,
+ NC_("layers-action", "Layer Color Tag: Set to Yellow"),
+ GIMP_COLOR_TAG_YELLOW, FALSE,
+ GIMP_HELP_LAYER_COLOR_TAG },
+
+ { "layers-color-tag-orange", NULL,
+ NC_("layers-action", "Orange"), NULL,
+ NC_("layers-action", "Layer Color Tag: Set to Orange"),
+ GIMP_COLOR_TAG_ORANGE, FALSE,
+ GIMP_HELP_LAYER_COLOR_TAG },
+
+ { "layers-color-tag-brown", NULL,
+ NC_("layers-action", "Brown"), NULL,
+ NC_("layers-action", "Layer Color Tag: Set to Brown"),
+ GIMP_COLOR_TAG_BROWN, FALSE,
+ GIMP_HELP_LAYER_COLOR_TAG },
+
+ { "layers-color-tag-red", NULL,
+ NC_("layers-action", "Red"), NULL,
+ NC_("layers-action", "Layer Color Tag: Set to Red"),
+ GIMP_COLOR_TAG_RED, FALSE,
+ GIMP_HELP_LAYER_COLOR_TAG },
+
+ { "layers-color-tag-violet", NULL,
+ NC_("layers-action", "Violet"), NULL,
+ NC_("layers-action", "Layer Color Tag: Set to Violet"),
+ GIMP_COLOR_TAG_VIOLET, FALSE,
+ GIMP_HELP_LAYER_COLOR_TAG },
+
+ { "layers-color-tag-gray", NULL,
+ NC_("layers-action", "Gray"), NULL,
+ NC_("layers-action", "Layer Color Tag: Set to Gray"),
+ GIMP_COLOR_TAG_GRAY, FALSE,
+ GIMP_HELP_LAYER_COLOR_TAG }
+};
+
+static const GimpEnumActionEntry layers_mask_apply_actions[] =
+{
+ { "layers-mask-apply", NULL,
+ NC_("layers-action", "Apply Layer _Mask"), NULL,
+ NC_("layers-action", "Apply the effect of the layer mask and remove it"),
+ GIMP_MASK_APPLY, FALSE,
+ GIMP_HELP_LAYER_MASK_APPLY },
+
+ { "layers-mask-delete", GIMP_ICON_EDIT_DELETE,
+ NC_("layers-action", "Delete Layer Mas_k"), NULL,
+ NC_("layers-action", "Remove the layer mask and its effect"),
+ GIMP_MASK_DISCARD, FALSE,
+ GIMP_HELP_LAYER_MASK_DELETE }
+};
+
+static const GimpEnumActionEntry layers_mask_to_selection_actions[] =
+{
+ { "layers-mask-selection-replace", GIMP_ICON_SELECTION_REPLACE,
+ NC_("layers-action", "_Mask to Selection"), NULL,
+ NC_("layers-action", "Replace the selection with the layer mask"),
+ GIMP_CHANNEL_OP_REPLACE, FALSE,
+ GIMP_HELP_LAYER_MASK_SELECTION_REPLACE },
+
+ { "layers-mask-selection-add", GIMP_ICON_SELECTION_ADD,
+ NC_("layers-action", "_Add to Selection"), NULL,
+ NC_("layers-action", "Add the layer mask to the current selection"),
+ GIMP_CHANNEL_OP_ADD, FALSE,
+ GIMP_HELP_LAYER_MASK_SELECTION_ADD },
+
+ { "layers-mask-selection-subtract", GIMP_ICON_SELECTION_SUBTRACT,
+ NC_("layers-action", "_Subtract from Selection"), NULL,
+ NC_("layers-action", "Subtract the layer mask from the current selection"),
+ GIMP_CHANNEL_OP_SUBTRACT, FALSE,
+ GIMP_HELP_LAYER_MASK_SELECTION_SUBTRACT },
+
+ { "layers-mask-selection-intersect", GIMP_ICON_SELECTION_INTERSECT,
+ NC_("layers-action", "_Intersect with Selection"), NULL,
+ NC_("layers-action", "Intersect the layer mask with the current selection"),
+ GIMP_CHANNEL_OP_INTERSECT, FALSE,
+ GIMP_HELP_LAYER_MASK_SELECTION_INTERSECT }
+};
+
+static const GimpEnumActionEntry layers_alpha_to_selection_actions[] =
+{
+ { "layers-alpha-selection-replace", GIMP_ICON_SELECTION_REPLACE,
+ NC_("layers-action", "Al_pha to Selection"), NULL,
+ NC_("layers-action",
+ "Replace the selection with the layer's alpha channel"),
+ GIMP_CHANNEL_OP_REPLACE, FALSE,
+ GIMP_HELP_LAYER_ALPHA_SELECTION_REPLACE },
+
+ { "layers-alpha-selection-add", GIMP_ICON_SELECTION_ADD,
+ NC_("layers-action", "A_dd to Selection"), NULL,
+ NC_("layers-action",
+ "Add the layer's alpha channel to the current selection"),
+ GIMP_CHANNEL_OP_ADD, FALSE,
+ GIMP_HELP_LAYER_ALPHA_SELECTION_ADD },
+
+ { "layers-alpha-selection-subtract", GIMP_ICON_SELECTION_SUBTRACT,
+ NC_("layers-action", "_Subtract from Selection"), NULL,
+ NC_("layers-action",
+ "Subtract the layer's alpha channel from the current selection"),
+ GIMP_CHANNEL_OP_SUBTRACT, FALSE,
+ GIMP_HELP_LAYER_ALPHA_SELECTION_SUBTRACT },
+
+ { "layers-alpha-selection-intersect", GIMP_ICON_SELECTION_INTERSECT,
+ NC_("layers-action", "_Intersect with Selection"), NULL,
+ NC_("layers-action",
+ "Intersect the layer's alpha channel with the current selection"),
+ GIMP_CHANNEL_OP_INTERSECT, FALSE,
+ GIMP_HELP_LAYER_ALPHA_SELECTION_INTERSECT }
+};
+
+static const GimpEnumActionEntry layers_select_actions[] =
+{
+ { "layers-select-top", NULL,
+ NC_("layers-action", "Select _Top Layer"), "Home",
+ NC_("layers-action", "Select the topmost layer"),
+ GIMP_ACTION_SELECT_FIRST, FALSE,
+ GIMP_HELP_LAYER_TOP },
+
+ { "layers-select-bottom", NULL,
+ NC_("layers-action", "Select _Bottom Layer"), "End",
+ NC_("layers-action", "Select the bottommost layer"),
+ GIMP_ACTION_SELECT_LAST, FALSE,
+ GIMP_HELP_LAYER_BOTTOM },
+
+ { "layers-select-previous", NULL,
+ NC_("layers-action", "Select _Previous Layer"), "Prior",
+ NC_("layers-action", "Select the layer above the current layer"),
+ GIMP_ACTION_SELECT_PREVIOUS, FALSE,
+ GIMP_HELP_LAYER_PREVIOUS },
+
+ { "layers-select-next", NULL,
+ NC_("layers-action", "Select _Next Layer"), "Next",
+ NC_("layers-action", "Select the layer below the current layer"),
+ GIMP_ACTION_SELECT_NEXT, FALSE,
+ GIMP_HELP_LAYER_NEXT }
+};
+
+static const GimpEnumActionEntry layers_opacity_actions[] =
+{
+ { "layers-opacity-set", GIMP_ICON_TRANSPARENCY,
+ NC_("layers-action", "Layer Opacity: Set"), NULL, NULL,
+ GIMP_ACTION_SELECT_SET, TRUE,
+ GIMP_HELP_LAYER_OPACITY },
+ { "layers-opacity-transparent", GIMP_ICON_TRANSPARENCY,
+ NC_("layers-action", "Layer Opacity: Make Completely Transparent"), NULL, NULL,
+ GIMP_ACTION_SELECT_FIRST, FALSE,
+ GIMP_HELP_LAYER_OPACITY },
+ { "layers-opacity-opaque", GIMP_ICON_TRANSPARENCY,
+ NC_("layers-action", "Layer Opacity: Make Completely Opaque"), NULL, NULL,
+ GIMP_ACTION_SELECT_LAST, FALSE,
+ GIMP_HELP_LAYER_OPACITY },
+ { "layers-opacity-decrease", GIMP_ICON_TRANSPARENCY,
+ NC_("layers-action", "Layer Opacity: Make More Transparent"), NULL, NULL,
+ GIMP_ACTION_SELECT_PREVIOUS, FALSE,
+ GIMP_HELP_LAYER_OPACITY },
+ { "layers-opacity-increase", GIMP_ICON_TRANSPARENCY,
+ NC_("layers-action", "Layer Opacity: Make More Opaque"), NULL, NULL,
+ GIMP_ACTION_SELECT_NEXT, FALSE,
+ GIMP_HELP_LAYER_OPACITY },
+ { "layers-opacity-decrease-skip", GIMP_ICON_TRANSPARENCY,
+ NC_("layers-action", "Layer Opacity: Make 10% More Transparent"), NULL, NULL,
+ GIMP_ACTION_SELECT_SKIP_PREVIOUS, FALSE,
+ GIMP_HELP_LAYER_OPACITY },
+ { "layers-opacity-increase-skip", GIMP_ICON_TRANSPARENCY,
+ NC_("layers-action", "Layer Opacity: Make 10% More Opaque"), NULL, NULL,
+ GIMP_ACTION_SELECT_SKIP_NEXT, FALSE,
+ GIMP_HELP_LAYER_OPACITY }
+};
+
+static const GimpEnumActionEntry layers_mode_actions[] =
+{
+ { "layers-mode-first", GIMP_ICON_TOOL_PENCIL,
+ NC_("layers-action", "Layer Mode: Select First"), NULL, NULL,
+ GIMP_ACTION_SELECT_FIRST, FALSE,
+ GIMP_HELP_LAYER_MODE },
+ { "layers-mode-last", GIMP_ICON_TOOL_PENCIL,
+ NC_("layers-action", "Layer Mode: Select Last"), NULL, NULL,
+ GIMP_ACTION_SELECT_LAST, FALSE,
+ GIMP_HELP_LAYER_MODE },
+ { "layers-mode-previous", GIMP_ICON_TOOL_PENCIL,
+ NC_("layers-action", "Layer Mode: Select Previous"), NULL, NULL,
+ GIMP_ACTION_SELECT_PREVIOUS, FALSE,
+ GIMP_HELP_LAYER_MODE },
+ { "layers-mode-next", GIMP_ICON_TOOL_PENCIL,
+ NC_("layers-action", "Layer Mode: Select Next"), NULL, NULL,
+ GIMP_ACTION_SELECT_NEXT, FALSE,
+ GIMP_HELP_LAYER_MODE }
+};
+
+/**
+ * layers_actions_fix_tooltip:
+ * @group:
+ * @action:
+ * @modifiers:
+ *
+ * Make layer alpha to selection click-shortcuts discoverable, at
+ * least in theory.
+ **/
+static void
+layers_actions_fix_tooltip (GimpActionGroup *group,
+ const gchar *action,
+ GdkModifierType modifiers)
+{
+ const gchar *old_hint;
+ gchar *new_hint;
+
+ old_hint = gimp_action_group_get_action_tooltip (group,
+ action);
+ new_hint = g_strconcat (old_hint,
+ "\n",
+ /* Will be followed with e.g. "Shift-Click
+ on thumbnail"
+ */
+ _("Shortcut: "),
+ gimp_get_mod_string (modifiers),
+ /* Will be prepended with a modifier key
+ string, e.g. "Shift"
+ */
+ _("-Click on thumbnail in Layers dockable"),
+ NULL);
+
+ gimp_action_group_set_action_tooltip (group, action, new_hint);
+ g_free (new_hint);
+}
+
+void
+layers_actions_setup (GimpActionGroup *group)
+{
+ GdkDisplay *display = gdk_display_get_default ();
+ GdkModifierType extend_mask;
+ GdkModifierType modify_mask;
+
+ extend_mask =
+ gdk_keymap_get_modifier_mask (gdk_keymap_get_for_display (display),
+ GDK_MODIFIER_INTENT_EXTEND_SELECTION);
+ modify_mask =
+ gdk_keymap_get_modifier_mask (gdk_keymap_get_for_display (display),
+ GDK_MODIFIER_INTENT_MODIFY_SELECTION);
+
+ gimp_action_group_add_actions (group, "layers-action",
+ layers_actions,
+ G_N_ELEMENTS (layers_actions));
+
+ gimp_action_group_add_toggle_actions (group, "layers-action",
+ layers_toggle_actions,
+ G_N_ELEMENTS (layers_toggle_actions));
+
+ gimp_action_group_add_radio_actions (group, "layers-action",
+ layers_blend_space_actions,
+ G_N_ELEMENTS (layers_blend_space_actions),
+ NULL, 0,
+ layers_blend_space_cmd_callback);
+
+ gimp_action_group_add_radio_actions (group, "layers-action",
+ layers_composite_space_actions,
+ G_N_ELEMENTS (layers_composite_space_actions),
+ NULL, 0,
+ layers_composite_space_cmd_callback);
+
+ gimp_action_group_add_radio_actions (group, "layers-action",
+ layers_composite_mode_actions,
+ G_N_ELEMENTS (layers_composite_mode_actions),
+ NULL, 0,
+ layers_composite_mode_cmd_callback);
+
+ gimp_action_group_add_enum_actions (group, "layers-action",
+ layers_color_tag_actions,
+ G_N_ELEMENTS (layers_color_tag_actions),
+ layers_color_tag_cmd_callback);
+
+ gimp_action_group_add_enum_actions (group, "layers-action",
+ layers_mask_apply_actions,
+ G_N_ELEMENTS (layers_mask_apply_actions),
+ layers_mask_apply_cmd_callback);
+
+ gimp_action_group_add_enum_actions (group, "layers-action",
+ layers_mask_to_selection_actions,
+ G_N_ELEMENTS (layers_mask_to_selection_actions),
+ layers_mask_to_selection_cmd_callback);
+
+ gimp_action_group_add_enum_actions (group, "layers-action",
+ layers_alpha_to_selection_actions,
+ G_N_ELEMENTS (layers_alpha_to_selection_actions),
+ layers_alpha_to_selection_cmd_callback);
+
+ layers_actions_fix_tooltip (group, "layers-alpha-selection-replace",
+ GDK_MOD1_MASK);
+ layers_actions_fix_tooltip (group, "layers-alpha-selection-add",
+ extend_mask | GDK_MOD1_MASK);
+ layers_actions_fix_tooltip (group, "layers-alpha-selection-subtract",
+ modify_mask | GDK_MOD1_MASK);
+ layers_actions_fix_tooltip (group, "layers-alpha-selection-intersect",
+ extend_mask | modify_mask | GDK_MOD1_MASK);
+
+ gimp_action_group_add_enum_actions (group, "layers-action",
+ layers_select_actions,
+ G_N_ELEMENTS (layers_select_actions),
+ layers_select_cmd_callback);
+
+ gimp_action_group_add_enum_actions (group, "layers-action",
+ layers_opacity_actions,
+ G_N_ELEMENTS (layers_opacity_actions),
+ layers_opacity_cmd_callback);
+
+ gimp_action_group_add_enum_actions (group, "layers-action",
+ layers_mode_actions,
+ G_N_ELEMENTS (layers_mode_actions),
+ layers_mode_cmd_callback);
+
+ items_actions_setup (group, "layers");
+}
+
+void
+layers_actions_update (GimpActionGroup *group,
+ gpointer data)
+{
+ GimpImage *image = action_data_get_image (data);
+ GimpLayer *layer = NULL;
+ GimpLayerMask *mask = NULL; /* layer mask */
+ gboolean fs = FALSE; /* floating sel */
+ gboolean ac = FALSE; /* active channel */
+ gboolean sel = FALSE;
+ gboolean alpha = FALSE; /* alpha channel present */
+ gboolean indexed = FALSE; /* is indexed */
+ gboolean lock_alpha = FALSE;
+ gboolean can_lock_alpha = FALSE;
+ gboolean text_layer = FALSE;
+ gboolean visible = FALSE;
+ gboolean writable = FALSE;
+ gboolean movable = FALSE;
+ gboolean children = FALSE;
+ gboolean bs_mutable = FALSE;
+ gboolean cs_mutable = FALSE;
+ gboolean cm_mutable = FALSE;
+ GList *next = NULL;
+ GList *next_visible = NULL;
+ GList *prev = NULL;
+ gboolean next_mode = FALSE;
+ gboolean prev_mode = FALSE;
+
+ if (image)
+ {
+ fs = (gimp_image_get_floating_selection (image) != NULL);
+ ac = (gimp_image_get_active_channel (image) != NULL);
+ sel = ! gimp_channel_is_empty (gimp_image_get_mask (image));
+ indexed = (gimp_image_get_base_type (image) == GIMP_INDEXED);
+
+ layer = gimp_image_get_active_layer (image);
+
+ if (layer)
+ {
+ GimpLayerMode *modes;
+ GimpLayerMode mode = gimp_layer_get_mode (layer);
+ const gchar *action = NULL;
+ GList *layer_list;
+ GList *list;
+ gint n_modes;
+ gint i = 0;
+
+ switch (gimp_layer_get_blend_space (layer))
+ {
+ case GIMP_LAYER_COLOR_SPACE_AUTO:
+ action = "layers-blend-space-auto"; break;
+ case GIMP_LAYER_COLOR_SPACE_RGB_LINEAR:
+ action = "layers-blend-space-rgb-linear"; break;
+ case GIMP_LAYER_COLOR_SPACE_RGB_PERCEPTUAL:
+ action = "layers-blend-space-rgb-perceptual"; break;
+ default:
+ action = NULL; break; /* can't happen */
+ }
+
+ if (action)
+ gimp_action_group_set_action_active (group, action, TRUE);
+
+ switch (gimp_layer_get_composite_space (layer))
+ {
+ case GIMP_LAYER_COLOR_SPACE_AUTO:
+ action = "layers-composite-space-auto"; break;
+ case GIMP_LAYER_COLOR_SPACE_RGB_LINEAR:
+ action = "layers-composite-space-rgb-linear"; break;
+ case GIMP_LAYER_COLOR_SPACE_RGB_PERCEPTUAL:
+ action = "layers-composite-space-rgb-perceptual"; break;
+ default:
+ action = NULL; break; /* can't happen */
+ }
+
+ if (action)
+ gimp_action_group_set_action_active (group, action, TRUE);
+
+ switch (gimp_layer_get_composite_mode (layer))
+ {
+ case GIMP_LAYER_COMPOSITE_AUTO:
+ action = "layers-composite-mode-auto"; break;
+ case GIMP_LAYER_COMPOSITE_UNION:
+ action = "layers-composite-mode-union"; break;
+ case GIMP_LAYER_COMPOSITE_CLIP_TO_BACKDROP:
+ action = "layers-composite-mode-clip-to-backdrop"; break;
+ case GIMP_LAYER_COMPOSITE_CLIP_TO_LAYER:
+ action = "layers-composite-mode-clip-to-layer"; break;
+ case GIMP_LAYER_COMPOSITE_INTERSECTION:
+ action = "layers-composite-mode-intersection"; break;
+ }
+
+ gimp_action_group_set_action_active (group, action, TRUE);
+
+ bs_mutable = gimp_layer_mode_is_blend_space_mutable (mode);
+ cs_mutable = gimp_layer_mode_is_composite_space_mutable (mode);
+ cm_mutable = gimp_layer_mode_is_composite_mode_mutable (mode);
+
+ mask = gimp_layer_get_mask (layer);
+ lock_alpha = gimp_layer_get_lock_alpha (layer);
+ can_lock_alpha = gimp_layer_can_lock_alpha (layer);
+ alpha = gimp_drawable_has_alpha (GIMP_DRAWABLE (layer));
+ visible = gimp_item_get_visible (GIMP_ITEM (layer));
+ writable = ! gimp_item_is_content_locked (GIMP_ITEM (layer));
+ movable = ! gimp_item_is_position_locked (GIMP_ITEM (layer));
+
+ if (gimp_viewable_get_children (GIMP_VIEWABLE (layer)))
+ children = TRUE;
+
+ layer_list = gimp_item_get_container_iter (GIMP_ITEM (layer));
+
+ list = g_list_find (layer_list, layer);
+
+ if (list)
+ {
+ prev = g_list_previous (list);
+ next = g_list_next (list);
+
+ for (next_visible = next;
+ next_visible;
+ next_visible = g_list_next (next_visible))
+ {
+ if (gimp_item_get_visible (next_visible->data))
+ {
+ /* "next_visible" is actually "next_visible" and
+ * "writable" and "not group"
+ */
+ if (gimp_item_is_content_locked (next_visible->data) ||
+ gimp_viewable_get_children (next_visible->data))
+ next_visible = NULL;
+
+ break;
+ }
+ }
+ }
+
+ modes = gimp_layer_mode_get_context_array (mode,
+ GIMP_LAYER_MODE_CONTEXT_LAYER,
+ &n_modes);
+ while (i < (n_modes - 1) && modes[i] != mode)
+ i++;
+ g_free (modes);
+ next_mode = (i < n_modes - 1);
+ prev_mode = (i > 0);
+
+ text_layer = gimp_item_is_text_layer (GIMP_ITEM (layer));
+ }
+ }
+
+#define SET_VISIBLE(action,condition) \
+ gimp_action_group_set_action_visible (group, action, (condition) != 0)
+#define SET_SENSITIVE(action,condition) \
+ gimp_action_group_set_action_sensitive (group, action, (condition) != 0)
+#define SET_ACTIVE(action,condition) \
+ gimp_action_group_set_action_active (group, action, (condition) != 0)
+#define SET_LABEL(action,label) \
+ gimp_action_group_set_action_label (group, action, label)
+
+ SET_SENSITIVE ("layers-edit", !ac && ((layer && !fs) || text_layer));
+ SET_VISIBLE ("layers-edit-text", text_layer && !ac);
+ SET_SENSITIVE ("layers-edit-text", text_layer && !ac);
+ SET_SENSITIVE ("layers-edit-attributes", layer && !fs && !ac);
+
+ if (layer && gimp_layer_is_floating_sel (layer))
+ {
+ SET_LABEL ("layers-new", C_("layers-action", "To _New Layer"));
+ SET_LABEL ("layers-new-last-values", C_("layers-action", "To _New Layer"));
+ }
+ else
+ {
+ SET_LABEL ("layers-new", C_("layers-action", "_New Layer..."));
+ SET_LABEL ("layers-new-last-values", C_("layers-action", "_New Layer"));
+ }
+
+ SET_SENSITIVE ("layers-new", image);
+ SET_SENSITIVE ("layers-new-last-values", image);
+ SET_SENSITIVE ("layers-new-from-visible", image);
+ SET_SENSITIVE ("layers-new-group", image && !indexed);
+ SET_SENSITIVE ("layers-duplicate", layer && !fs && !ac);
+ SET_SENSITIVE ("layers-delete", layer && !ac);
+
+ SET_SENSITIVE ("layers-mode-first", layer && !ac && prev_mode);
+ SET_SENSITIVE ("layers-mode-last", layer && !ac && next_mode);
+ SET_SENSITIVE ("layers-mode-previous", layer && !ac && prev_mode);
+ SET_SENSITIVE ("layers-mode-next", layer && !ac && next_mode);
+
+ SET_SENSITIVE ("layers-select-top", layer && !fs && !ac && prev);
+ SET_SENSITIVE ("layers-select-bottom", layer && !fs && !ac && next);
+ SET_SENSITIVE ("layers-select-previous", layer && !fs && !ac && prev);
+ SET_SENSITIVE ("layers-select-next", layer && !fs && !ac && next);
+
+ SET_SENSITIVE ("layers-raise", layer && !fs && !ac && prev);
+ SET_SENSITIVE ("layers-raise-to-top", layer && !fs && !ac && prev);
+ SET_SENSITIVE ("layers-lower", layer && !fs && !ac && next);
+ SET_SENSITIVE ("layers-lower-to-bottom", layer && !fs && !ac && next);
+
+ SET_VISIBLE ("layers-anchor", layer && fs && !ac);
+ SET_VISIBLE ("layers-merge-down", !fs);
+ SET_SENSITIVE ("layers-merge-down", layer && !fs && !ac && visible && next_visible);
+ SET_VISIBLE ("layers-merge-down-button", !fs);
+ SET_SENSITIVE ("layers-merge-down-button", layer && !fs && !ac);
+ SET_VISIBLE ("layers-merge-group", children);
+ SET_SENSITIVE ("layers-merge-group", layer && !fs && !ac && children);
+ SET_SENSITIVE ("layers-merge-layers", layer && !fs && !ac);
+ SET_SENSITIVE ("layers-flatten-image", layer && !fs && !ac);
+
+ SET_VISIBLE ("layers-text-discard", text_layer && !ac);
+ SET_VISIBLE ("layers-text-to-vectors", text_layer && !ac);
+ SET_VISIBLE ("layers-text-along-vectors", text_layer && !ac);
+
+ SET_SENSITIVE ("layers-resize", writable && movable && !ac);
+ SET_SENSITIVE ("layers-resize-to-image", writable && movable && !ac);
+ SET_SENSITIVE ("layers-scale", writable && movable && !ac);
+
+ SET_SENSITIVE ("layers-crop-to-selection", writable && movable && sel);
+ SET_SENSITIVE ("layers-crop-to-content", writable && movable);
+
+ SET_SENSITIVE ("layers-alpha-add", writable && !children && !fs && !alpha);
+ SET_SENSITIVE ("layers-alpha-remove", writable && !children && !fs && alpha);
+
+ SET_SENSITIVE ("layers-lock-alpha", can_lock_alpha);
+ SET_ACTIVE ("layers-lock-alpha", lock_alpha);
+
+ SET_SENSITIVE ("layers-blend-space-auto", layer && bs_mutable);
+ SET_SENSITIVE ("layers-blend-space-rgb-linear", layer && bs_mutable);
+ SET_SENSITIVE ("layers-blend-space-rgb-perceptual", layer && bs_mutable);
+
+ SET_SENSITIVE ("layers-composite-space-auto", layer && cs_mutable);
+ SET_SENSITIVE ("layers-composite-space-rgb-linear", layer && cs_mutable);
+ SET_SENSITIVE ("layers-composite-space-rgb-perceptual", layer && cs_mutable);
+
+ SET_SENSITIVE ("layers-composite-mode-auto", layer && cm_mutable);
+ SET_SENSITIVE ("layers-composite-mode-union", layer && cm_mutable);
+ SET_SENSITIVE ("layers-composite-mode-clip-to-backdrop", layer && cm_mutable);
+ SET_SENSITIVE ("layers-composite-mode-clip-to-layer", layer && cm_mutable);
+ SET_SENSITIVE ("layers-composite-mode-intersection", layer && cm_mutable);
+
+ SET_SENSITIVE ("layers-mask-add", layer && !fs && !ac && !mask);
+ SET_SENSITIVE ("layers-mask-add-button", layer && !fs && !ac);
+ SET_SENSITIVE ("layers-mask-add-last-values", layer && !fs && !ac && !mask);
+
+ SET_SENSITIVE ("layers-mask-apply", writable && !fs && !ac && mask && !children);
+ SET_SENSITIVE ("layers-mask-delete", layer && !fs && !ac && mask);
+
+ SET_SENSITIVE ("layers-mask-edit", layer && !fs && !ac && mask);
+ SET_SENSITIVE ("layers-mask-show", layer && !fs && !ac && mask);
+ SET_SENSITIVE ("layers-mask-disable", layer && !fs && !ac && mask);
+
+ SET_ACTIVE ("layers-mask-edit", mask && gimp_layer_get_edit_mask (layer));
+ SET_ACTIVE ("layers-mask-show", mask && gimp_layer_get_show_mask (layer));
+ SET_ACTIVE ("layers-mask-disable", mask && !gimp_layer_get_apply_mask (layer));
+
+ SET_SENSITIVE ("layers-mask-selection-replace", layer && !fs && !ac && mask);
+ SET_SENSITIVE ("layers-mask-selection-add", layer && !fs && !ac && mask);
+ SET_SENSITIVE ("layers-mask-selection-subtract", layer && !fs && !ac && mask);
+ SET_SENSITIVE ("layers-mask-selection-intersect", layer && !fs && !ac && mask);
+
+ SET_SENSITIVE ("layers-alpha-selection-replace", layer && !fs && !ac);
+ SET_SENSITIVE ("layers-alpha-selection-add", layer && !fs && !ac);
+ SET_SENSITIVE ("layers-alpha-selection-subtract", layer && !fs && !ac);
+ SET_SENSITIVE ("layers-alpha-selection-intersect", layer && !fs && !ac);
+
+#undef SET_VISIBLE
+#undef SET_SENSITIVE
+#undef SET_ACTIVE
+#undef SET_LABEL
+
+ items_actions_update (group, "layers", GIMP_ITEM (layer));
+}
diff --git a/app/actions/layers-actions.h b/app/actions/layers-actions.h
new file mode 100644
index 0000000..0f257bf
--- /dev/null
+++ b/app/actions/layers-actions.h
@@ -0,0 +1,27 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __LAYERS_ACTIONS_H__
+#define __LAYERS_ACTIONS_H__
+
+
+void layers_actions_setup (GimpActionGroup *group);
+void layers_actions_update (GimpActionGroup *group,
+ gpointer data);
+
+
+#endif /* __LAYERS_ACTIONS_H__ */
diff --git a/app/actions/layers-commands.c b/app/actions/layers-commands.c
new file mode 100644
index 0000000..528eb4c
--- /dev/null
+++ b/app/actions/layers-commands.c
@@ -0,0 +1,1749 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <string.h>
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpmath/gimpmath.h"
+#include "libgimpbase/gimpbase.h"
+#include "libgimpcolor/gimpcolor.h"
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "actions-types.h"
+
+#include "config/gimpdialogconfig.h"
+
+#include "operations/layer-modes/gimp-layer-modes.h"
+
+#include "core/gimp.h"
+#include "core/gimpchannel.h"
+#include "core/gimpcontainer.h"
+#include "core/gimpcontext.h"
+#include "core/gimpdrawable-fill.h"
+#include "core/gimpgrouplayer.h"
+#include "core/gimpimage.h"
+#include "core/gimpimage-merge.h"
+#include "core/gimpimage-undo.h"
+#include "core/gimpimage-undo-push.h"
+#include "core/gimpitemundo.h"
+#include "core/gimplayerpropundo.h"
+#include "core/gimplayer-floating-selection.h"
+#include "core/gimplayer-new.h"
+#include "core/gimppickable.h"
+#include "core/gimppickable-auto-shrink.h"
+#include "core/gimptoolinfo.h"
+#include "core/gimpundostack.h"
+#include "core/gimpprogress.h"
+
+#include "text/gimptext.h"
+#include "text/gimptext-vectors.h"
+#include "text/gimptextlayer.h"
+
+#include "vectors/gimpstroke.h"
+#include "vectors/gimpvectors.h"
+#include "vectors/gimpvectors-warp.h"
+
+#include "widgets/gimpaction.h"
+#include "widgets/gimpdock.h"
+#include "widgets/gimphelp-ids.h"
+#include "widgets/gimpprogressdialog.h"
+
+#include "display/gimpdisplay.h"
+#include "display/gimpdisplayshell.h"
+#include "display/gimpimagewindow.h"
+
+#include "tools/gimptexttool.h"
+#include "tools/tool_manager.h"
+
+#include "dialogs/dialogs.h"
+#include "dialogs/layer-add-mask-dialog.h"
+#include "dialogs/layer-options-dialog.h"
+#include "dialogs/resize-dialog.h"
+#include "dialogs/scale-dialog.h"
+
+#include "actions.h"
+#include "items-commands.h"
+#include "layers-commands.h"
+
+#include "gimp-intl.h"
+
+
+/* local function prototypes */
+
+static void layers_new_callback (GtkWidget *dialog,
+ GimpImage *image,
+ GimpLayer *layer,
+ GimpContext *context,
+ const gchar *layer_name,
+ GimpLayerMode layer_mode,
+ GimpLayerColorSpace layer_blend_space,
+ GimpLayerColorSpace layer_composite_space,
+ GimpLayerCompositeMode layer_composite_mode,
+ gdouble layer_opacity,
+ GimpFillType layer_fill_type,
+ gint layer_width,
+ gint layer_height,
+ gint layer_offset_x,
+ gint layer_offset_y,
+ gboolean layer_visible,
+ gboolean layer_linked,
+ GimpColorTag layer_color_tag,
+ gboolean layer_lock_pixels,
+ gboolean layer_lock_position,
+ gboolean layer_lock_alpha,
+ gboolean rename_text_layer,
+ gpointer user_data);
+static void layers_edit_attributes_callback (GtkWidget *dialog,
+ GimpImage *image,
+ GimpLayer *layer,
+ GimpContext *context,
+ const gchar *layer_name,
+ GimpLayerMode layer_mode,
+ GimpLayerColorSpace layer_blend_space,
+ GimpLayerColorSpace layer_composite_space,
+ GimpLayerCompositeMode layer_composite_mode,
+ gdouble layer_opacity,
+ GimpFillType layer_fill_type,
+ gint layer_width,
+ gint layer_height,
+ gint layer_offset_x,
+ gint layer_offset_y,
+ gboolean layer_visible,
+ gboolean layer_linked,
+ GimpColorTag layer_color_tag,
+ gboolean layer_lock_pixels,
+ gboolean layer_lock_position,
+ gboolean layer_lock_alpha,
+ gboolean rename_text_layer,
+ gpointer user_data);
+static void layers_add_mask_callback (GtkWidget *dialog,
+ GimpLayer *layer,
+ GimpAddMaskType add_mask_type,
+ GimpChannel *channel,
+ gboolean invert,
+ gpointer user_data);
+static void layers_scale_callback (GtkWidget *dialog,
+ GimpViewable *viewable,
+ gint width,
+ gint height,
+ GimpUnit unit,
+ GimpInterpolationType interpolation,
+ gdouble xresolution,
+ gdouble yresolution,
+ GimpUnit resolution_unit,
+ gpointer user_data);
+static void layers_resize_callback (GtkWidget *dialog,
+ GimpViewable *viewable,
+ GimpContext *context,
+ gint width,
+ gint height,
+ GimpUnit unit,
+ gint offset_x,
+ gint offset_y,
+ gdouble unused0,
+ gdouble unused1,
+ GimpUnit unused2,
+ GimpFillType fill_type,
+ GimpItemSet unused3,
+ gboolean unused4,
+ gpointer data);
+
+static gint layers_mode_index (GimpLayerMode layer_mode,
+ const GimpLayerMode *modes,
+ gint n_modes);
+
+
+/* private variables */
+
+static GimpUnit layer_resize_unit = GIMP_UNIT_PIXEL;
+static GimpUnit layer_scale_unit = GIMP_UNIT_PIXEL;
+static GimpInterpolationType layer_scale_interp = -1;
+
+
+/* public functions */
+
+void
+layers_edit_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpLayer *layer;
+ GtkWidget *widget;
+ return_if_no_layer (image, layer, data);
+ return_if_no_widget (widget, data);
+
+ if (gimp_item_is_text_layer (GIMP_ITEM (layer)))
+ {
+ layers_edit_text_cmd_callback (action, value, data);
+ }
+ else
+ {
+ layers_edit_attributes_cmd_callback (action, value, data);
+ }
+}
+
+void
+layers_edit_text_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpLayer *layer;
+ GtkWidget *widget;
+ GimpTool *active_tool;
+ return_if_no_layer (image, layer, data);
+ return_if_no_widget (widget, data);
+
+ g_return_if_fail (gimp_item_is_text_layer (GIMP_ITEM (layer)));
+
+ active_tool = tool_manager_get_active (image->gimp);
+
+ if (! GIMP_IS_TEXT_TOOL (active_tool))
+ {
+ GimpToolInfo *tool_info = gimp_get_tool_info (image->gimp,
+ "gimp-text-tool");
+
+ if (GIMP_IS_TOOL_INFO (tool_info))
+ {
+ gimp_context_set_tool (action_data_get_context (data), tool_info);
+ active_tool = tool_manager_get_active (image->gimp);
+ }
+ }
+
+ if (GIMP_IS_TEXT_TOOL (active_tool))
+ {
+ if (gimp_text_tool_set_layer (GIMP_TEXT_TOOL (active_tool), layer))
+ {
+ GimpDisplayShell *shell;
+
+ shell = gimp_display_get_shell (active_tool->display);
+ gtk_widget_grab_focus (shell->canvas);
+ }
+ }
+}
+
+void
+layers_edit_attributes_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpLayer *layer;
+ GtkWidget *widget;
+ GtkWidget *dialog;
+ return_if_no_layer (image, layer, data);
+ return_if_no_widget (widget, data);
+
+#define EDIT_DIALOG_KEY "gimp-layer-edit-attributes-dialog"
+
+ dialog = dialogs_get_dialog (G_OBJECT (layer), EDIT_DIALOG_KEY);
+
+ if (! dialog)
+ {
+ GimpItem *item = GIMP_ITEM (layer);
+
+ dialog = layer_options_dialog_new (gimp_item_get_image (GIMP_ITEM (layer)),
+ layer,
+ action_data_get_context (data),
+ widget,
+ _("Layer Attributes"),
+ "gimp-layer-edit",
+ GIMP_ICON_EDIT,
+ _("Edit Layer Attributes"),
+ GIMP_HELP_LAYER_EDIT,
+ gimp_object_get_name (layer),
+ gimp_layer_get_mode (layer),
+ gimp_layer_get_blend_space (layer),
+ gimp_layer_get_composite_space (layer),
+ gimp_layer_get_composite_mode (layer),
+ gimp_layer_get_opacity (layer),
+ 0 /* unused */,
+ gimp_item_get_visible (item),
+ gimp_item_get_linked (item),
+ gimp_item_get_color_tag (item),
+ gimp_item_get_lock_content (item),
+ gimp_item_get_lock_position (item),
+ gimp_layer_get_lock_alpha (layer),
+ layers_edit_attributes_callback,
+ NULL);
+
+ dialogs_attach_dialog (G_OBJECT (layer), EDIT_DIALOG_KEY, dialog);
+ }
+
+ gtk_window_present (GTK_WINDOW (dialog));
+}
+
+void
+layers_new_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GtkWidget *widget;
+ GimpLayer *floating_sel;
+ GtkWidget *dialog;
+ return_if_no_image (image, data);
+ return_if_no_widget (widget, data);
+
+ /* If there is a floating selection, the new command transforms
+ * the current fs into a new layer
+ */
+ if ((floating_sel = gimp_image_get_floating_selection (image)))
+ {
+ GError *error = NULL;
+
+ if (! floating_sel_to_layer (floating_sel, &error))
+ {
+ gimp_message_literal (image->gimp,
+ G_OBJECT (widget), GIMP_MESSAGE_WARNING,
+ error->message);
+ g_clear_error (&error);
+ return;
+ }
+
+ gimp_image_flush (image);
+ return;
+ }
+
+#define NEW_DIALOG_KEY "gimp-layer-new-dialog"
+
+ dialog = dialogs_get_dialog (G_OBJECT (image), NEW_DIALOG_KEY);
+
+ if (! dialog)
+ {
+ GimpDialogConfig *config = GIMP_DIALOG_CONFIG (image->gimp->config);
+ GimpLayerMode layer_mode = config->layer_new_mode;
+
+ if (layer_mode == GIMP_LAYER_MODE_NORMAL ||
+ layer_mode == GIMP_LAYER_MODE_NORMAL_LEGACY)
+ {
+ layer_mode = gimp_image_get_default_new_layer_mode (image);
+ }
+
+ dialog = layer_options_dialog_new (image, NULL,
+ action_data_get_context (data),
+ widget,
+ _("New Layer"),
+ "gimp-layer-new",
+ GIMP_ICON_LAYER,
+ _("Create a New Layer"),
+ GIMP_HELP_LAYER_NEW,
+ config->layer_new_name,
+ layer_mode,
+ config->layer_new_blend_space,
+ config->layer_new_composite_space,
+ config->layer_new_composite_mode,
+ config->layer_new_opacity,
+ config->layer_new_fill_type,
+ TRUE,
+ FALSE,
+ GIMP_COLOR_TAG_NONE,
+ FALSE,
+ FALSE,
+ FALSE,
+ layers_new_callback,
+ NULL);
+
+ dialogs_attach_dialog (G_OBJECT (image), NEW_DIALOG_KEY, dialog);
+ }
+
+ gtk_window_present (GTK_WINDOW (dialog));
+}
+
+void
+layers_new_last_vals_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GtkWidget *widget;
+ GimpLayer *layer;
+ GimpDialogConfig *config;
+ GimpLayerMode layer_mode;
+
+ return_if_no_image (image, data);
+ return_if_no_widget (widget, data);
+
+ config = GIMP_DIALOG_CONFIG (image->gimp->config);
+
+ /* If there is a floating selection, the new command transforms
+ * the current fs into a new layer
+ */
+ if (gimp_image_get_floating_selection (image))
+ {
+ layers_new_cmd_callback (action, value, data);
+ return;
+ }
+
+ layer_mode = config->layer_new_mode;
+
+ if (layer_mode == GIMP_LAYER_MODE_NORMAL ||
+ layer_mode == GIMP_LAYER_MODE_NORMAL_LEGACY)
+ {
+ layer_mode = gimp_image_get_default_new_layer_mode (image);
+ }
+
+ layer = gimp_layer_new (image,
+ gimp_image_get_width (image),
+ gimp_image_get_height (image),
+ gimp_image_get_layer_format (image, TRUE),
+ config->layer_new_name,
+ config->layer_new_opacity,
+ layer_mode);
+
+ gimp_drawable_fill (GIMP_DRAWABLE (layer),
+ action_data_get_context (data),
+ config->layer_new_fill_type);
+ gimp_layer_set_blend_space (layer,
+ config->layer_new_blend_space, FALSE);
+ gimp_layer_set_composite_space (layer,
+ config->layer_new_composite_space, FALSE);
+ gimp_layer_set_composite_mode (layer,
+ config->layer_new_composite_mode, FALSE);
+
+ gimp_image_add_layer (image, layer, GIMP_IMAGE_ACTIVE_PARENT, -1, TRUE);
+ gimp_image_flush (image);
+}
+
+void
+layers_new_from_visible_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpDisplayShell *shell;
+ GimpLayer *layer;
+ GimpPickable *pickable;
+ GimpColorProfile *profile;
+ return_if_no_image (image, data);
+ return_if_no_shell (shell, data);
+
+ pickable = gimp_display_shell_get_canvas_pickable (shell);
+
+ gimp_pickable_flush (pickable);
+
+ profile = gimp_color_managed_get_color_profile (GIMP_COLOR_MANAGED (image));
+
+ layer = gimp_layer_new_from_gegl_buffer (gimp_pickable_get_buffer (pickable),
+ image,
+ gimp_image_get_layer_format (image,
+ TRUE),
+ _("Visible"),
+ GIMP_OPACITY_OPAQUE,
+ gimp_image_get_default_new_layer_mode (image),
+ profile);
+
+ gimp_image_add_layer (image, layer, GIMP_IMAGE_ACTIVE_PARENT, -1, TRUE);
+ gimp_image_flush (image);
+}
+
+void
+layers_new_group_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpLayer *layer;
+ return_if_no_image (image, data);
+
+ layer = gimp_group_layer_new (image);
+
+ gimp_image_add_layer (image, layer, GIMP_IMAGE_ACTIVE_PARENT, -1, TRUE);
+ gimp_image_flush (image);
+}
+
+void
+layers_select_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpLayer *layer;
+ GimpContainer *container;
+ GimpLayer *new_layer;
+ GimpActionSelectType select_type;
+ return_if_no_image (image, data);
+
+ select_type = (GimpActionSelectType) g_variant_get_int32 (value);
+
+ layer = gimp_image_get_active_layer (image);
+
+ if (layer)
+ container = gimp_item_get_container (GIMP_ITEM (layer));
+ else
+ container = gimp_image_get_layers (image);
+
+ new_layer = (GimpLayer *) action_select_object (select_type,
+ container,
+ (GimpObject *) layer);
+
+ if (new_layer && new_layer != layer)
+ {
+ gimp_image_set_active_layer (image, new_layer);
+ gimp_image_flush (image);
+ }
+}
+
+void
+layers_raise_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpLayer *layer;
+ return_if_no_layer (image, layer, data);
+
+ gimp_image_raise_item (image, GIMP_ITEM (layer), NULL);
+ gimp_image_flush (image);
+}
+
+void
+layers_raise_to_top_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpLayer *layer;
+ return_if_no_layer (image, layer, data);
+
+ gimp_image_raise_item_to_top (image, GIMP_ITEM (layer));
+ gimp_image_flush (image);
+}
+
+void
+layers_lower_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpLayer *layer;
+ return_if_no_layer (image, layer, data);
+
+ gimp_image_lower_item (image, GIMP_ITEM (layer), NULL);
+ gimp_image_flush (image);
+}
+
+void
+layers_lower_to_bottom_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpLayer *layer;
+ return_if_no_layer (image, layer, data);
+
+ gimp_image_lower_item_to_bottom (image, GIMP_ITEM (layer));
+ gimp_image_flush (image);
+}
+
+void
+layers_duplicate_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpLayer *layer;
+ GimpLayer *new_layer;
+ return_if_no_layer (image, layer, data);
+
+ new_layer = GIMP_LAYER (gimp_item_duplicate (GIMP_ITEM (layer),
+ G_TYPE_FROM_INSTANCE (layer)));
+
+ /* use the actual parent here, not GIMP_IMAGE_ACTIVE_PARENT because
+ * the latter would add a duplicated group inside itself instead of
+ * above it
+ */
+ gimp_image_add_layer (image, new_layer,
+ gimp_layer_get_parent (layer), -1,
+ TRUE);
+ gimp_image_flush (image);
+}
+
+void
+layers_anchor_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpLayer *layer;
+ return_if_no_layer (image, layer, data);
+
+ if (gimp_layer_is_floating_sel (layer))
+ {
+ floating_sel_anchor (layer);
+ gimp_image_flush (image);
+ }
+}
+
+void
+layers_merge_down_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpLayer *layer;
+ GimpDisplay *display;
+ return_if_no_layer (image, layer, data);
+ return_if_no_display (display, data);
+
+ gimp_image_merge_down (image, layer, action_data_get_context (data),
+ GIMP_EXPAND_AS_NECESSARY,
+ GIMP_PROGRESS (display), NULL);
+ gimp_image_flush (image);
+}
+
+void
+layers_merge_group_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpLayer *layer;
+ return_if_no_layer (image, layer, data);
+
+ gimp_image_merge_group_layer (image, GIMP_GROUP_LAYER (layer));
+ gimp_image_flush (image);
+}
+
+void
+layers_delete_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpLayer *layer;
+ return_if_no_layer (image, layer, data);
+
+ gimp_image_remove_layer (image, layer, TRUE, NULL);
+ gimp_image_flush (image);
+}
+
+void
+layers_text_discard_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpLayer *layer;
+ return_if_no_layer (image, layer, data);
+
+ if (GIMP_IS_TEXT_LAYER (layer))
+ gimp_text_layer_discard (GIMP_TEXT_LAYER (layer));
+}
+
+void
+layers_text_to_vectors_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpLayer *layer;
+ return_if_no_layer (image, layer, data);
+
+ if (GIMP_IS_TEXT_LAYER (layer))
+ {
+ GimpVectors *vectors;
+ gint x, y;
+
+ vectors = gimp_text_vectors_new (image, GIMP_TEXT_LAYER (layer)->text);
+
+ gimp_item_get_offset (GIMP_ITEM (layer), &x, &y);
+ gimp_item_translate (GIMP_ITEM (vectors), x, y, FALSE);
+
+ gimp_image_add_vectors (image, vectors,
+ GIMP_IMAGE_ACTIVE_PARENT, -1, TRUE);
+ gimp_image_flush (image);
+ }
+}
+
+void
+layers_text_along_vectors_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpLayer *layer;
+ GimpVectors *vectors;
+ return_if_no_layer (image, layer, data);
+ return_if_no_vectors (image, vectors, data);
+
+ if (GIMP_IS_TEXT_LAYER (layer))
+ {
+ gdouble box_width;
+ gdouble box_height;
+ GimpVectors *new_vectors;
+ gdouble offset;
+
+ box_width = gimp_item_get_width (GIMP_ITEM (layer));
+ box_height = gimp_item_get_height (GIMP_ITEM (layer));
+
+ new_vectors = gimp_text_vectors_new (image, GIMP_TEXT_LAYER (layer)->text);
+
+ offset = 0;
+ switch (GIMP_TEXT_LAYER (layer)->text->base_dir)
+ {
+ case GIMP_TEXT_DIRECTION_LTR:
+ case GIMP_TEXT_DIRECTION_RTL:
+ offset = 0.5 * box_height;
+ break;
+ case GIMP_TEXT_DIRECTION_TTB_RTL:
+ case GIMP_TEXT_DIRECTION_TTB_RTL_UPRIGHT:
+ case GIMP_TEXT_DIRECTION_TTB_LTR:
+ case GIMP_TEXT_DIRECTION_TTB_LTR_UPRIGHT:
+ {
+ GimpStroke *stroke = NULL;
+
+ while ((stroke = gimp_vectors_stroke_get_next (new_vectors, stroke)))
+ {
+ gimp_stroke_rotate (stroke, 0, 0, 270);
+ gimp_stroke_translate (stroke, 0, box_width);
+ }
+ }
+ offset = 0.5 * box_width;
+ break;
+ }
+
+
+ gimp_vectors_warp_vectors (vectors, new_vectors, offset);
+
+ gimp_item_set_visible (GIMP_ITEM (new_vectors), TRUE, FALSE);
+
+ gimp_image_add_vectors (image, new_vectors,
+ GIMP_IMAGE_ACTIVE_PARENT, -1, TRUE);
+ gimp_image_flush (image);
+ }
+}
+
+void
+layers_resize_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpLayer *layer;
+ GtkWidget *widget;
+ GtkWidget *dialog;
+ return_if_no_layer (image, layer, data);
+ return_if_no_widget (widget, data);
+
+#define RESIZE_DIALOG_KEY "gimp-resize-dialog"
+
+ dialog = dialogs_get_dialog (G_OBJECT (layer), RESIZE_DIALOG_KEY);
+
+ if (! dialog)
+ {
+ GimpDialogConfig *config = GIMP_DIALOG_CONFIG (image->gimp->config);
+ GimpDisplay *display = NULL;
+
+ if (GIMP_IS_IMAGE_WINDOW (data))
+ display = action_data_get_display (data);
+
+ if (layer_resize_unit != GIMP_UNIT_PERCENT && display)
+ layer_resize_unit = gimp_display_get_shell (display)->unit;
+
+ dialog = resize_dialog_new (GIMP_VIEWABLE (layer),
+ action_data_get_context (data),
+ _("Set Layer Boundary Size"),
+ "gimp-layer-resize",
+ widget,
+ gimp_standard_help_func,
+ GIMP_HELP_LAYER_RESIZE,
+ layer_resize_unit,
+ config->layer_resize_fill_type,
+ GIMP_ITEM_SET_NONE,
+ FALSE,
+ layers_resize_callback,
+ NULL);
+
+ dialogs_attach_dialog (G_OBJECT (layer), RESIZE_DIALOG_KEY, dialog);
+ }
+
+ gtk_window_present (GTK_WINDOW (dialog));
+}
+
+void
+layers_resize_to_image_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpLayer *layer;
+ return_if_no_layer (image, layer, data);
+
+ gimp_layer_resize_to_image (layer,
+ action_data_get_context (data),
+ GIMP_FILL_TRANSPARENT);
+ gimp_image_flush (image);
+}
+
+void
+layers_scale_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpLayer *layer;
+ GtkWidget *widget;
+ GtkWidget *dialog;
+ return_if_no_layer (image, layer, data);
+ return_if_no_widget (widget, data);
+
+#define SCALE_DIALOG_KEY "gimp-scale-dialog"
+
+ dialog = dialogs_get_dialog (G_OBJECT (layer), SCALE_DIALOG_KEY);
+
+ if (! dialog)
+ {
+ GimpDisplay *display = NULL;
+
+ if (GIMP_IS_IMAGE_WINDOW (data))
+ display = action_data_get_display (data);
+
+ if (layer_scale_unit != GIMP_UNIT_PERCENT && display)
+ layer_scale_unit = gimp_display_get_shell (display)->unit;
+
+ if (layer_scale_interp == -1)
+ layer_scale_interp = image->gimp->config->interpolation_type;
+
+ dialog = scale_dialog_new (GIMP_VIEWABLE (layer),
+ action_data_get_context (data),
+ _("Scale Layer"), "gimp-layer-scale",
+ widget,
+ gimp_standard_help_func, GIMP_HELP_LAYER_SCALE,
+ layer_scale_unit,
+ layer_scale_interp,
+ layers_scale_callback,
+ display);
+
+ dialogs_attach_dialog (G_OBJECT (layer), SCALE_DIALOG_KEY, dialog);
+ }
+
+ gtk_window_present (GTK_WINDOW (dialog));
+}
+
+void
+layers_crop_to_selection_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpLayer *layer;
+ GtkWidget *widget;
+ gint x, y;
+ gint width, height;
+ gint off_x, off_y;
+ return_if_no_layer (image, layer, data);
+ return_if_no_widget (widget, data);
+
+ if (! gimp_item_bounds (GIMP_ITEM (gimp_image_get_mask (image)),
+ &x, &y, &width, &height))
+ {
+ gimp_message_literal (image->gimp,
+ G_OBJECT (widget), GIMP_MESSAGE_WARNING,
+ _("Cannot crop because the current selection "
+ "is empty."));
+ return;
+ }
+
+ gimp_item_get_offset (GIMP_ITEM (layer), &off_x, &off_y);
+ off_x -= x;
+ off_y -= y;
+
+ gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_ITEM_RESIZE,
+ _("Crop Layer to Selection"));
+
+ gimp_item_resize (GIMP_ITEM (layer),
+ action_data_get_context (data), GIMP_FILL_TRANSPARENT,
+ width, height, off_x, off_y);
+
+ gimp_image_undo_group_end (image);
+ gimp_image_flush (image);
+}
+
+void
+layers_crop_to_content_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpLayer *layer;
+ GtkWidget *widget;
+ gint x, y;
+ gint width, height;
+ return_if_no_layer (image, layer, data);
+ return_if_no_widget (widget, data);
+
+ switch (gimp_pickable_auto_shrink (GIMP_PICKABLE (layer),
+ 0, 0,
+ gimp_item_get_width (GIMP_ITEM (layer)),
+ gimp_item_get_height (GIMP_ITEM (layer)),
+ &x, &y, &width, &height))
+ {
+ case GIMP_AUTO_SHRINK_SHRINK:
+ gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_ITEM_RESIZE,
+ _("Crop Layer to Content"));
+
+ gimp_item_resize (GIMP_ITEM (layer),
+ action_data_get_context (data), GIMP_FILL_TRANSPARENT,
+ width, height, -x, -y);
+
+ gimp_image_undo_group_end (image);
+ gimp_image_flush (image);
+ break;
+
+ case GIMP_AUTO_SHRINK_EMPTY:
+ gimp_message_literal (image->gimp,
+ G_OBJECT (widget), GIMP_MESSAGE_INFO,
+ _("Cannot crop because the active layer "
+ "has no content."));
+ break;
+
+ case GIMP_AUTO_SHRINK_UNSHRINKABLE:
+ gimp_message_literal (image->gimp,
+ G_OBJECT (widget), GIMP_MESSAGE_INFO,
+ _("Cannot crop because the active layer "
+ "is already cropped to its content."));
+ break;
+ }
+}
+
+void
+layers_mask_add_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpLayer *layer;
+ GtkWidget *widget;
+ GtkWidget *dialog;
+ return_if_no_layer (image, layer, data);
+ return_if_no_widget (widget, data);
+
+ if (gimp_layer_get_mask (layer))
+ return;
+
+#define ADD_MASK_DIALOG_KEY "gimp-add-mask-dialog"
+
+ dialog = dialogs_get_dialog (G_OBJECT (layer), ADD_MASK_DIALOG_KEY);
+
+ if (! dialog)
+ {
+ GimpDialogConfig *config = GIMP_DIALOG_CONFIG (image->gimp->config);
+
+ dialog = layer_add_mask_dialog_new (layer, action_data_get_context (data),
+ widget,
+ config->layer_add_mask_type,
+ config->layer_add_mask_invert,
+ layers_add_mask_callback,
+ NULL);
+
+ dialogs_attach_dialog (G_OBJECT (layer), ADD_MASK_DIALOG_KEY, dialog);
+ }
+
+ gtk_window_present (GTK_WINDOW (dialog));
+}
+
+void
+layers_mask_add_last_vals_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpLayer *layer;
+ GtkWidget *widget;
+ GimpDialogConfig *config;
+ GimpChannel *channel = NULL;
+ GimpLayerMask *mask;
+ return_if_no_layer (image, layer, data);
+ return_if_no_widget (widget, data);
+
+ if (gimp_layer_get_mask (layer))
+ return;
+
+ config = GIMP_DIALOG_CONFIG (image->gimp->config);
+
+ if (config->layer_add_mask_type == GIMP_ADD_MASK_CHANNEL)
+ {
+ channel = gimp_image_get_active_channel (image);
+
+ if (! channel)
+ {
+ GimpContainer *channels = gimp_image_get_channels (image);
+
+ channel = GIMP_CHANNEL (gimp_container_get_first_child (channels));
+ }
+
+ if (! channel)
+ {
+ layers_mask_add_cmd_callback (action, value, data);
+ return;
+ }
+ }
+
+ mask = gimp_layer_create_mask (layer,
+ config->layer_add_mask_type,
+ channel);
+
+ if (config->layer_add_mask_invert)
+ gimp_channel_invert (GIMP_CHANNEL (mask), FALSE);
+
+ gimp_layer_add_mask (layer, mask, TRUE, NULL);
+ gimp_image_flush (image);
+}
+
+void
+layers_mask_apply_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpLayer *layer;
+ return_if_no_layer (image, layer, data);
+
+ if (gimp_layer_get_mask (layer))
+ {
+ GimpMaskApplyMode mode = (GimpMaskApplyMode) g_variant_get_int32 (value);
+
+ gimp_layer_apply_mask (layer, mode, TRUE);
+ gimp_image_flush (image);
+ }
+}
+
+void
+layers_mask_edit_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpLayer *layer;
+ return_if_no_layer (image, layer, data);
+
+ if (gimp_layer_get_mask (layer))
+ {
+ gboolean active = g_variant_get_boolean (value);
+
+ gimp_layer_set_edit_mask (layer, active);
+ gimp_image_flush (image);
+ }
+}
+
+void
+layers_mask_show_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpLayer *layer;
+ return_if_no_layer (image, layer, data);
+
+ if (gimp_layer_get_mask (layer))
+ {
+ gboolean active = g_variant_get_boolean (value);
+
+ gimp_layer_set_show_mask (layer, active, TRUE);
+ gimp_image_flush (image);
+ }
+}
+
+void
+layers_mask_disable_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpLayer *layer;
+ return_if_no_layer (image, layer, data);
+
+ if (gimp_layer_get_mask (layer))
+ {
+ gboolean active = g_variant_get_boolean (value);
+
+ gimp_layer_set_apply_mask (layer, ! active, TRUE);
+ gimp_image_flush (image);
+ }
+}
+
+void
+layers_mask_to_selection_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpLayer *layer;
+ GimpLayerMask *mask;
+ return_if_no_layer (image, layer, data);
+
+ mask = gimp_layer_get_mask (layer);
+
+ if (mask)
+ {
+ GimpChannelOps operation = (GimpChannelOps) g_variant_get_int32 (value);
+
+ gimp_item_to_selection (GIMP_ITEM (mask), operation,
+ TRUE, FALSE, 0.0, 0.0);
+ gimp_image_flush (image);
+ }
+}
+
+void
+layers_alpha_add_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpLayer *layer;
+ return_if_no_layer (image, layer, data);
+
+ if (! gimp_drawable_has_alpha (GIMP_DRAWABLE (layer)))
+ {
+ gimp_layer_add_alpha (layer);
+ gimp_image_flush (image);
+ }
+}
+
+void
+layers_alpha_remove_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpLayer *layer;
+ return_if_no_layer (image, layer, data);
+
+ if (gimp_drawable_has_alpha (GIMP_DRAWABLE (layer)))
+ {
+ gimp_layer_remove_alpha (layer, action_data_get_context (data));
+ gimp_image_flush (image);
+ }
+}
+
+void
+layers_alpha_to_selection_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpLayer *layer;
+ GimpChannelOps operation;
+ return_if_no_layer (image, layer, data);
+
+ operation = (GimpChannelOps) g_variant_get_int32 (value);
+
+ gimp_item_to_selection (GIMP_ITEM (layer), operation,
+ TRUE, FALSE, 0.0, 0.0);
+ gimp_image_flush (image);
+}
+
+void
+layers_opacity_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpLayer *layer;
+ gdouble opacity;
+ GimpUndo *undo;
+ GimpActionSelectType select_type;
+ gboolean push_undo = TRUE;
+ return_if_no_layer (image, layer, data);
+
+ select_type = (GimpActionSelectType) g_variant_get_int32 (value);
+
+ undo = gimp_image_undo_can_compress (image, GIMP_TYPE_ITEM_UNDO,
+ GIMP_UNDO_LAYER_OPACITY);
+
+ if (undo && GIMP_ITEM_UNDO (undo)->item == GIMP_ITEM (layer))
+ push_undo = FALSE;
+
+ opacity = action_select_value (select_type,
+ gimp_layer_get_opacity (layer),
+ 0.0, 1.0, 1.0,
+ 1.0 / 255.0, 0.01, 0.1, 0.0, FALSE);
+ gimp_layer_set_opacity (layer, opacity, push_undo);
+ gimp_image_flush (image);
+}
+
+void
+layers_mode_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpLayer *layer;
+ GimpLayerMode *modes;
+ gint n_modes;
+ GimpLayerMode layer_mode;
+ gint index;
+ GimpUndo *undo;
+ GimpActionSelectType select_type;
+ gboolean push_undo = TRUE;
+ return_if_no_layer (image, layer, data);
+
+ select_type = (GimpActionSelectType) g_variant_get_int32 (value);
+
+ undo = gimp_image_undo_can_compress (image, GIMP_TYPE_ITEM_UNDO,
+ GIMP_UNDO_LAYER_MODE);
+
+ if (undo && GIMP_ITEM_UNDO (undo)->item == GIMP_ITEM (layer))
+ push_undo = FALSE;
+
+ layer_mode = gimp_layer_get_mode (layer);
+
+ modes = gimp_layer_mode_get_context_array (layer_mode,
+ GIMP_LAYER_MODE_CONTEXT_LAYER,
+ &n_modes);
+ index = layers_mode_index (layer_mode, modes, n_modes);
+ index = action_select_value (select_type,
+ index, 0, n_modes - 1, 0,
+ 0.0, 1.0, 1.0, 0.0, FALSE);
+ layer_mode = modes[index];
+ g_free (modes);
+
+ gimp_layer_set_mode (layer, layer_mode, push_undo);
+ gimp_image_flush (image);
+}
+
+void
+layers_blend_space_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpLayer *layer;
+ GimpLayerColorSpace blend_space;
+ return_if_no_layer (image, layer, data);
+
+ blend_space = (GimpLayerColorSpace) g_variant_get_int32 (value);
+
+ if (blend_space != gimp_layer_get_blend_space (layer))
+ {
+ GimpUndo *undo;
+ gboolean push_undo = TRUE;
+
+ undo = gimp_image_undo_can_compress (image, GIMP_TYPE_LAYER_PROP_UNDO,
+ GIMP_UNDO_LAYER_MODE);
+
+ if (undo && GIMP_ITEM_UNDO (undo)->item == GIMP_ITEM (layer))
+ push_undo = FALSE;
+
+ gimp_layer_set_blend_space (layer, blend_space, push_undo);
+ gimp_image_flush (image);
+ }
+}
+
+void
+layers_composite_space_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpLayer *layer;
+ GimpLayerColorSpace composite_space;
+ return_if_no_layer (image, layer, data);
+
+ composite_space = (GimpLayerColorSpace) g_variant_get_int32 (value);
+
+ if (composite_space != gimp_layer_get_composite_space (layer))
+ {
+ GimpUndo *undo;
+ gboolean push_undo = TRUE;
+
+ undo = gimp_image_undo_can_compress (image, GIMP_TYPE_LAYER_PROP_UNDO,
+ GIMP_UNDO_LAYER_MODE);
+
+ if (undo && GIMP_ITEM_UNDO (undo)->item == GIMP_ITEM (layer))
+ push_undo = FALSE;
+
+ gimp_layer_set_composite_space (layer, composite_space, push_undo);
+ gimp_image_flush (image);
+ }
+}
+
+void
+layers_composite_mode_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpLayer *layer;
+ GimpLayerCompositeMode composite_mode;
+ return_if_no_layer (image, layer, data);
+
+ composite_mode = (GimpLayerCompositeMode) g_variant_get_int32 (value);
+
+ if (composite_mode != gimp_layer_get_composite_mode (layer))
+ {
+ GimpUndo *undo;
+ gboolean push_undo = TRUE;
+
+ undo = gimp_image_undo_can_compress (image, GIMP_TYPE_LAYER_PROP_UNDO,
+ GIMP_UNDO_LAYER_MODE);
+
+ if (undo && GIMP_ITEM_UNDO (undo)->item == GIMP_ITEM (layer))
+ push_undo = FALSE;
+
+ gimp_layer_set_composite_mode (layer, composite_mode, push_undo);
+ gimp_image_flush (image);
+ }
+}
+
+void
+layers_visible_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpLayer *layer;
+ return_if_no_layer (image, layer, data);
+
+ items_visible_cmd_callback (action, value, image, GIMP_ITEM (layer));
+}
+
+void
+layers_linked_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpLayer *layer;
+ return_if_no_layer (image, layer, data);
+
+ items_linked_cmd_callback (action, value, image, GIMP_ITEM (layer));
+}
+
+void
+layers_lock_content_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpLayer *layer;
+ return_if_no_layer (image, layer, data);
+
+ items_lock_content_cmd_callback (action, value, image, GIMP_ITEM (layer));
+}
+
+void
+layers_lock_position_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpLayer *layer;
+ return_if_no_layer (image, layer, data);
+
+ items_lock_position_cmd_callback (action, value, image, GIMP_ITEM (layer));
+}
+
+void
+layers_lock_alpha_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpLayer *layer;
+ gboolean lock_alpha;
+ return_if_no_layer (image, layer, data);
+
+ lock_alpha = g_variant_get_boolean (value);
+
+ if (lock_alpha != gimp_layer_get_lock_alpha (layer))
+ {
+ GimpUndo *undo;
+ gboolean push_undo = TRUE;
+
+ undo = gimp_image_undo_can_compress (image, GIMP_TYPE_ITEM_UNDO,
+ GIMP_UNDO_LAYER_LOCK_ALPHA);
+
+ if (undo && GIMP_ITEM_UNDO (undo)->item == GIMP_ITEM (layer))
+ push_undo = FALSE;
+
+ gimp_layer_set_lock_alpha (layer, lock_alpha, push_undo);
+ gimp_image_flush (image);
+ }
+}
+
+void
+layers_color_tag_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpLayer *layer;
+ GimpColorTag color_tag;
+ return_if_no_layer (image, layer, data);
+
+ color_tag = (GimpColorTag) g_variant_get_int32 (value);
+
+ items_color_tag_cmd_callback (action, image, GIMP_ITEM (layer),
+ color_tag);
+}
+
+
+/* private functions */
+
+static void
+layers_new_callback (GtkWidget *dialog,
+ GimpImage *image,
+ GimpLayer *layer,
+ GimpContext *context,
+ const gchar *layer_name,
+ GimpLayerMode layer_mode,
+ GimpLayerColorSpace layer_blend_space,
+ GimpLayerColorSpace layer_composite_space,
+ GimpLayerCompositeMode layer_composite_mode,
+ gdouble layer_opacity,
+ GimpFillType layer_fill_type,
+ gint layer_width,
+ gint layer_height,
+ gint layer_offset_x,
+ gint layer_offset_y,
+ gboolean layer_visible,
+ gboolean layer_linked,
+ GimpColorTag layer_color_tag,
+ gboolean layer_lock_pixels,
+ gboolean layer_lock_position,
+ gboolean layer_lock_alpha,
+ gboolean rename_text_layer, /* unused */
+ gpointer user_data)
+{
+ GimpDialogConfig *config = GIMP_DIALOG_CONFIG (image->gimp->config);
+
+ g_object_set (config,
+ "layer-new-name", layer_name,
+ "layer-new-mode", layer_mode,
+ "layer-new-blend-space", layer_blend_space,
+ "layer-new-composite-space", layer_composite_space,
+ "layer-new-composite-mode", layer_composite_mode,
+ "layer-new-opacity", layer_opacity,
+ "layer-new-fill-type", layer_fill_type,
+ NULL);
+
+ layer = gimp_layer_new (image, layer_width, layer_height,
+ gimp_image_get_layer_format (image, TRUE),
+ config->layer_new_name,
+ config->layer_new_opacity,
+ config->layer_new_mode);
+
+ if (layer)
+ {
+ gimp_item_set_offset (GIMP_ITEM (layer), layer_offset_x, layer_offset_y);
+ gimp_drawable_fill (GIMP_DRAWABLE (layer), context,
+ config->layer_new_fill_type);
+ gimp_item_set_visible (GIMP_ITEM (layer), layer_visible, FALSE);
+ gimp_item_set_linked (GIMP_ITEM (layer), layer_linked, FALSE);
+ gimp_item_set_color_tag (GIMP_ITEM (layer), layer_color_tag, FALSE);
+ gimp_item_set_lock_content (GIMP_ITEM (layer), layer_lock_pixels,
+ FALSE);
+ gimp_item_set_lock_position (GIMP_ITEM (layer), layer_lock_position,
+ FALSE);
+ gimp_layer_set_lock_alpha (layer, layer_lock_alpha, FALSE);
+ gimp_layer_set_blend_space (layer, layer_blend_space, FALSE);
+ gimp_layer_set_composite_space (layer, layer_composite_space, FALSE);
+ gimp_layer_set_composite_mode (layer, layer_composite_mode, FALSE);
+
+ gimp_image_add_layer (image, layer,
+ GIMP_IMAGE_ACTIVE_PARENT, -1, TRUE);
+ gimp_image_flush (image);
+ }
+ else
+ {
+ g_warning ("%s: could not allocate new layer", G_STRFUNC);
+ }
+
+ gtk_widget_destroy (dialog);
+}
+
+static void
+layers_edit_attributes_callback (GtkWidget *dialog,
+ GimpImage *image,
+ GimpLayer *layer,
+ GimpContext *context,
+ const gchar *layer_name,
+ GimpLayerMode layer_mode,
+ GimpLayerColorSpace layer_blend_space,
+ GimpLayerColorSpace layer_composite_space,
+ GimpLayerCompositeMode layer_composite_mode,
+ gdouble layer_opacity,
+ GimpFillType unused1,
+ gint unused2,
+ gint unused3,
+ gint layer_offset_x,
+ gint layer_offset_y,
+ gboolean layer_visible,
+ gboolean layer_linked,
+ GimpColorTag layer_color_tag,
+ gboolean layer_lock_pixels,
+ gboolean layer_lock_position,
+ gboolean layer_lock_alpha,
+ gboolean rename_text_layer,
+ gpointer user_data)
+{
+ GimpItem *item = GIMP_ITEM (layer);
+
+ if (strcmp (layer_name, gimp_object_get_name (layer)) ||
+ layer_mode != gimp_layer_get_mode (layer) ||
+ layer_blend_space != gimp_layer_get_blend_space (layer) ||
+ layer_composite_space != gimp_layer_get_composite_space (layer) ||
+ layer_composite_mode != gimp_layer_get_composite_mode (layer) ||
+ layer_opacity != gimp_layer_get_opacity (layer) ||
+ layer_offset_x != gimp_item_get_offset_x (item) ||
+ layer_offset_y != gimp_item_get_offset_y (item) ||
+ layer_visible != gimp_item_get_visible (item) ||
+ layer_linked != gimp_item_get_linked (item) ||
+ layer_color_tag != gimp_item_get_color_tag (item) ||
+ layer_lock_pixels != gimp_item_get_lock_content (item) ||
+ layer_lock_position != gimp_item_get_lock_position (item) ||
+ layer_lock_alpha != gimp_layer_get_lock_alpha (layer))
+ {
+ gimp_image_undo_group_start (image,
+ GIMP_UNDO_GROUP_ITEM_PROPERTIES,
+ _("Layer Attributes"));
+
+ if (strcmp (layer_name, gimp_object_get_name (layer)))
+ {
+ GError *error = NULL;
+
+ if (! gimp_item_rename (GIMP_ITEM (layer), layer_name, &error))
+ {
+ gimp_message_literal (image->gimp,
+ G_OBJECT (dialog), GIMP_MESSAGE_WARNING,
+ error->message);
+ g_clear_error (&error);
+ }
+ }
+
+ if (layer_mode != gimp_layer_get_mode (layer))
+ gimp_layer_set_mode (layer, layer_mode, TRUE);
+
+ if (layer_blend_space != gimp_layer_get_blend_space (layer))
+ gimp_layer_set_blend_space (layer, layer_blend_space, TRUE);
+
+ if (layer_composite_space != gimp_layer_get_composite_space (layer))
+ gimp_layer_set_composite_space (layer, layer_composite_space, TRUE);
+
+ if (layer_composite_mode != gimp_layer_get_composite_mode (layer))
+ gimp_layer_set_composite_mode (layer, layer_composite_mode, TRUE);
+
+ if (layer_opacity != gimp_layer_get_opacity (layer))
+ gimp_layer_set_opacity (layer, layer_opacity, TRUE);
+
+ if (layer_offset_x != gimp_item_get_offset_x (item) ||
+ layer_offset_y != gimp_item_get_offset_y (item))
+ {
+ gimp_item_translate (item,
+ layer_offset_x - gimp_item_get_offset_x (item),
+ layer_offset_y - gimp_item_get_offset_y (item),
+ TRUE);
+ }
+
+ if (layer_visible != gimp_item_get_visible (item))
+ gimp_item_set_visible (item, layer_visible, TRUE);
+
+ if (layer_linked != gimp_item_get_linked (item))
+ gimp_item_set_linked (item, layer_linked, TRUE);
+
+ if (layer_color_tag != gimp_item_get_color_tag (item))
+ gimp_item_set_color_tag (item, layer_color_tag, TRUE);
+
+ if (layer_lock_pixels != gimp_item_get_lock_content (item))
+ gimp_item_set_lock_content (item, layer_lock_pixels, TRUE);
+
+ if (layer_lock_position != gimp_item_get_lock_position (item))
+ gimp_item_set_lock_position (item, layer_lock_position, TRUE);
+
+ if (layer_lock_alpha != gimp_layer_get_lock_alpha (layer))
+ gimp_layer_set_lock_alpha (layer, layer_lock_alpha, TRUE);
+
+ gimp_image_undo_group_end (image);
+
+ gimp_image_flush (image);
+ }
+
+ if (gimp_item_is_text_layer (GIMP_ITEM (layer)))
+ {
+ g_object_set (layer,
+ "auto-rename", rename_text_layer,
+ NULL);
+ }
+
+ gtk_widget_destroy (dialog);
+}
+
+static void
+layers_add_mask_callback (GtkWidget *dialog,
+ GimpLayer *layer,
+ GimpAddMaskType add_mask_type,
+ GimpChannel *channel,
+ gboolean invert,
+ gpointer user_data)
+{
+ GimpImage *image = gimp_item_get_image (GIMP_ITEM (layer));
+ GimpDialogConfig *config = GIMP_DIALOG_CONFIG (image->gimp->config);
+ GimpLayerMask *mask;
+ GError *error = NULL;
+
+ g_object_set (config,
+ "layer-add-mask-type", add_mask_type,
+ "layer-add-mask-invert", invert,
+ NULL);
+
+ mask = gimp_layer_create_mask (layer,
+ config->layer_add_mask_type,
+ channel);
+
+ if (config->layer_add_mask_invert)
+ gimp_channel_invert (GIMP_CHANNEL (mask), FALSE);
+
+ if (! gimp_layer_add_mask (layer, mask, TRUE, &error))
+ {
+ gimp_message_literal (image->gimp,
+ G_OBJECT (dialog), GIMP_MESSAGE_WARNING,
+ error->message);
+ g_object_unref (mask);
+ g_clear_error (&error);
+ return;
+ }
+
+ gimp_image_flush (image);
+
+ gtk_widget_destroy (dialog);
+}
+
+static void
+layers_scale_callback (GtkWidget *dialog,
+ GimpViewable *viewable,
+ gint width,
+ gint height,
+ GimpUnit unit,
+ GimpInterpolationType interpolation,
+ gdouble xresolution, /* unused */
+ gdouble yresolution, /* unused */
+ GimpUnit resolution_unit,/* unused */
+ gpointer user_data)
+{
+ GimpDisplay *display = GIMP_DISPLAY (user_data);
+
+ layer_scale_unit = unit;
+ layer_scale_interp = interpolation;
+
+ if (width > 0 && height > 0)
+ {
+ GimpItem *item = GIMP_ITEM (viewable);
+ GimpProgress *progress;
+ GtkWidget *progress_dialog = NULL;
+
+ gtk_widget_destroy (dialog);
+
+ if (width == gimp_item_get_width (item) &&
+ height == gimp_item_get_height (item))
+ return;
+
+ if (display)
+ {
+ progress = GIMP_PROGRESS (display);
+ }
+ else
+ {
+ progress_dialog = gimp_progress_dialog_new ();
+ progress = GIMP_PROGRESS (progress_dialog);
+ }
+
+ progress = gimp_progress_start (progress, FALSE, _("Scaling"));
+
+ gimp_item_scale_by_origin (item,
+ width, height, interpolation,
+ progress, TRUE);
+
+ if (progress)
+ gimp_progress_end (progress);
+
+ if (progress_dialog)
+ gtk_widget_destroy (progress_dialog);
+
+ gimp_image_flush (gimp_item_get_image (item));
+ }
+ else
+ {
+ g_warning ("Scale Error: "
+ "Both width and height must be greater than zero.");
+ }
+}
+
+static void
+layers_resize_callback (GtkWidget *dialog,
+ GimpViewable *viewable,
+ GimpContext *context,
+ gint width,
+ gint height,
+ GimpUnit unit,
+ gint offset_x,
+ gint offset_y,
+ gdouble unused0,
+ gdouble unused1,
+ GimpUnit unused2,
+ GimpFillType fill_type,
+ GimpItemSet unused3,
+ gboolean unused4,
+ gpointer user_data)
+{
+ layer_resize_unit = unit;
+
+ if (width > 0 && height > 0)
+ {
+ GimpItem *item = GIMP_ITEM (viewable);
+ GimpImage *image = gimp_item_get_image (item);
+ GimpDialogConfig *config = GIMP_DIALOG_CONFIG (image->gimp->config);
+
+ g_object_set (config,
+ "layer-resize-fill-type", fill_type,
+ NULL);
+
+ gtk_widget_destroy (dialog);
+
+ if (width == gimp_item_get_width (item) &&
+ height == gimp_item_get_height (item))
+ return;
+
+ gimp_item_resize (item, context, fill_type,
+ width, height, offset_x, offset_y);
+ gimp_image_flush (gimp_item_get_image (item));
+ }
+ else
+ {
+ g_warning ("Resize Error: "
+ "Both width and height must be greater than zero.");
+ }
+}
+
+static gint
+layers_mode_index (GimpLayerMode layer_mode,
+ const GimpLayerMode *modes,
+ gint n_modes)
+{
+ gint i = 0;
+
+ while (i < (n_modes - 1) && modes[i] != layer_mode)
+ i++;
+
+ return i;
+}
diff --git a/app/actions/layers-commands.h b/app/actions/layers-commands.h
new file mode 100644
index 0000000..7a8b181
--- /dev/null
+++ b/app/actions/layers-commands.h
@@ -0,0 +1,173 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __LAYERS_COMMANDS_H__
+#define __LAYERS_COMMANDS_H__
+
+
+void layers_edit_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void layers_edit_text_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void layers_edit_attributes_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+void layers_new_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void layers_new_last_vals_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void layers_new_from_visible_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+void layers_new_group_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+void layers_select_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+void layers_raise_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void layers_raise_to_top_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void layers_lower_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void layers_lower_to_bottom_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+void layers_duplicate_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void layers_anchor_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void layers_merge_down_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void layers_merge_group_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void layers_delete_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void layers_text_discard_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void layers_text_to_vectors_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void layers_text_along_vectors_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+void layers_resize_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void layers_resize_to_image_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void layers_scale_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void layers_crop_to_selection_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void layers_crop_to_content_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+void layers_mask_add_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void layers_mask_add_last_vals_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void layers_mask_apply_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void layers_mask_edit_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void layers_mask_show_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void layers_mask_disable_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void layers_mask_to_selection_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+void layers_alpha_add_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void layers_alpha_remove_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void layers_alpha_to_selection_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+void layers_opacity_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void layers_mode_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void layers_blend_space_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void layers_composite_space_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void layers_composite_mode_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+void layers_visible_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void layers_linked_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void layers_lock_content_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void layers_lock_position_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void layers_lock_alpha_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+void layers_color_tag_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+
+#endif /* __LAYERS_COMMANDS_H__ */
diff --git a/app/actions/mypaint-brushes-actions.c b/app/actions/mypaint-brushes-actions.c
new file mode 100644
index 0000000..0f39df3
--- /dev/null
+++ b/app/actions/mypaint-brushes-actions.c
@@ -0,0 +1,142 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "actions-types.h"
+
+#include "core/gimpcontext.h"
+#include "core/gimpmybrush.h"
+
+#include "widgets/gimpactiongroup.h"
+#include "widgets/gimphelp-ids.h"
+
+#include "actions.h"
+#include "data-commands.h"
+#include "mypaint-brushes-actions.h"
+
+#include "gimp-intl.h"
+
+
+static const GimpActionEntry mypaint_brushes_actions[] =
+{
+ { "mypaint-brushes-popup", GIMP_ICON_MYPAINT_BRUSH,
+ NC_("mypaint-brushes-action", "MyPaint Brushes Menu"), NULL, NULL, NULL,
+ GIMP_HELP_MYPAINT_BRUSH_DIALOG },
+
+ { "mypaint-brushes-new", GIMP_ICON_DOCUMENT_NEW,
+ NC_("mypaint-brushes-action", "_New MyPaint Brush"), NULL,
+ NC_("mypaint-brushes-action", "Create a new MyPaint brush"),
+ data_new_cmd_callback,
+ GIMP_HELP_MYPAINT_BRUSH_NEW },
+
+ { "mypaint-brushes-duplicate", GIMP_ICON_OBJECT_DUPLICATE,
+ NC_("mypaint-brushes-action", "D_uplicate MyPaint Brush"), NULL,
+ NC_("mypaint-brushes-action", "Duplicate this MyPaint brush"),
+ data_duplicate_cmd_callback,
+ GIMP_HELP_MYPAINT_BRUSH_DUPLICATE },
+
+ { "mypaint-brushes-copy-location", GIMP_ICON_EDIT_COPY,
+ NC_("mypaint-brushes-action", "Copy MyPaint Brush _Location"), NULL,
+ NC_("mypaint-brushes-action", "Copy MyPaint brush file location to clipboard"),
+ data_copy_location_cmd_callback,
+ GIMP_HELP_MYPAINT_BRUSH_COPY_LOCATION },
+
+ { "mypaint-brushes-show-in-file-manager", GIMP_ICON_FILE_MANAGER,
+ NC_("mypaint-brushes-action", "Show in _File Manager"), NULL,
+ NC_("mypaint-brushes-action", "Show MyPaint brush file location in the file manager"),
+ data_show_in_file_manager_cmd_callback,
+ GIMP_HELP_MYPAINT_BRUSH_SHOW_IN_FILE_MANAGER },
+
+ { "mypaint-brushes-delete", GIMP_ICON_EDIT_DELETE,
+ NC_("mypaint-brushes-action", "_Delete MyPaint Brush"), NULL,
+ NC_("mypaint-brushes-action", "Delete this MyPaint brush"),
+ data_delete_cmd_callback,
+ GIMP_HELP_MYPAINT_BRUSH_DELETE },
+
+ { "mypaint-brushes-refresh", GIMP_ICON_VIEW_REFRESH,
+ NC_("mypaint-brushes-action", "_Refresh MyPaint Brushes"), NULL,
+ NC_("mypaint-brushes-action", "Refresh MyPaint brushes"),
+ data_refresh_cmd_callback,
+ GIMP_HELP_MYPAINT_BRUSH_REFRESH }
+};
+
+static const GimpStringActionEntry mypaint_brushes_edit_actions[] =
+{
+ { "mypaint-brushes-edit", GIMP_ICON_EDIT,
+ NC_("mypaint-brushes-action", "_Edit MyPaint Brush..."), NULL,
+ NC_("mypaint-brushes-action", "Edit MyPaint brush"),
+ "gimp-mybrush-editor",
+ GIMP_HELP_MYPAINT_BRUSH_EDIT }
+};
+
+
+void
+mypaint_brushes_actions_setup (GimpActionGroup *group)
+{
+ gimp_action_group_add_actions (group, "mypaint-brushes-action",
+ mypaint_brushes_actions,
+ G_N_ELEMENTS (mypaint_brushes_actions));
+
+ gimp_action_group_add_string_actions (group, "mypaint-brushes-action",
+ mypaint_brushes_edit_actions,
+ G_N_ELEMENTS (mypaint_brushes_edit_actions),
+ data_edit_cmd_callback);
+}
+
+void
+mypaint_brushes_actions_update (GimpActionGroup *group,
+ gpointer user_data)
+{
+ GimpContext *context = action_data_get_context (user_data);
+ GimpMybrush *brush = NULL;
+ GimpData *data = NULL;
+ GFile *file = NULL;
+
+ if (context)
+ {
+ brush = gimp_context_get_mybrush (context);
+
+ if (action_data_sel_count (user_data) > 1)
+ {
+ brush = NULL;
+ }
+
+ if (brush)
+ {
+ data = GIMP_DATA (brush);
+
+ file = gimp_data_get_file (data);
+ }
+ }
+
+#define SET_SENSITIVE(action,condition) \
+ gimp_action_group_set_action_sensitive (group, action, (condition) != 0)
+
+ SET_SENSITIVE ("mypaint-brushes-edit", brush && FALSE);
+ SET_SENSITIVE ("mypaint-brushes-duplicate", brush && gimp_data_is_duplicatable (data));
+ SET_SENSITIVE ("mypaint-brushes-copy-location", file);
+ SET_SENSITIVE ("mypaint-brushes-show-in-file-manager", file);
+ SET_SENSITIVE ("mypaint-brushes-delete", brush && gimp_data_is_deletable (data));
+
+#undef SET_SENSITIVE
+}
diff --git a/app/actions/mypaint-brushes-actions.h b/app/actions/mypaint-brushes-actions.h
new file mode 100644
index 0000000..63c93c6
--- /dev/null
+++ b/app/actions/mypaint-brushes-actions.h
@@ -0,0 +1,27 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __MYPAINT_BRUSHES_ACTIONS_H__
+#define __MYPAINT_BRUSHES_ACTIONS_H__
+
+
+void mypaint_brushes_actions_setup (GimpActionGroup *group);
+void mypaint_brushes_actions_update (GimpActionGroup *group,
+ gpointer data);
+
+
+#endif /* __MYPAINT_BRUSHES_ACTIONS_H__ */
diff --git a/app/actions/palette-editor-actions.c b/app/actions/palette-editor-actions.c
new file mode 100644
index 0000000..1540126
--- /dev/null
+++ b/app/actions/palette-editor-actions.c
@@ -0,0 +1,183 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "actions-types.h"
+
+#include "core/gimp.h"
+#include "core/gimpcontext.h"
+
+#include "widgets/gimpactiongroup.h"
+#include "widgets/gimphelp-ids.h"
+#include "widgets/gimppaletteeditor.h"
+
+#include "data-editor-commands.h"
+#include "palette-editor-actions.h"
+#include "palette-editor-commands.h"
+
+#include "gimp-intl.h"
+
+
+static const GimpActionEntry palette_editor_actions[] =
+{
+ { "palette-editor-popup", GIMP_ICON_PALETTE,
+ NC_("palette-editor-action", "Palette Editor Menu"), NULL, NULL, NULL,
+ GIMP_HELP_PALETTE_EDITOR_DIALOG },
+
+ { "palette-editor-edit-color", GIMP_ICON_EDIT,
+ NC_("palette-editor-action", "_Edit Color..."), NULL,
+ NC_("palette-editor-action", "Edit this entry"),
+ palette_editor_edit_color_cmd_callback,
+ GIMP_HELP_PALETTE_EDITOR_EDIT },
+
+ { "palette-editor-delete-color", GIMP_ICON_EDIT_DELETE,
+ NC_("palette-editor-action", "_Delete Color"), NULL,
+ NC_("palette-editor-action", "Delete this entry"),
+ palette_editor_delete_color_cmd_callback,
+ GIMP_HELP_PALETTE_EDITOR_DELETE }
+};
+
+static const GimpToggleActionEntry palette_editor_toggle_actions[] =
+{
+ { "palette-editor-edit-active", GIMP_ICON_LINKED,
+ NC_("palette-editor-action", "Edit Active Palette"), NULL, NULL,
+ data_editor_edit_active_cmd_callback,
+ FALSE,
+ GIMP_HELP_PALETTE_EDITOR_EDIT_ACTIVE }
+};
+
+static const GimpEnumActionEntry palette_editor_new_actions[] =
+{
+ { "palette-editor-new-color-fg", GIMP_ICON_DOCUMENT_NEW,
+ NC_("palette-editor-action", "New Color from _FG"), NULL,
+ NC_("palette-editor-action",
+ "Create a new entry from the foreground color"),
+ FALSE, FALSE,
+ GIMP_HELP_PALETTE_EDITOR_NEW },
+
+ { "palette-editor-new-color-bg", GIMP_ICON_DOCUMENT_NEW,
+ NC_("palette-editor-action", "New Color from _BG"), NULL,
+ NC_("palette-editor-action",
+ "Create a new entry from the background color"),
+ TRUE, FALSE,
+ GIMP_HELP_PALETTE_EDITOR_NEW }
+};
+
+static const GimpEnumActionEntry palette_editor_zoom_actions[] =
+{
+ { "palette-editor-zoom-in", GIMP_ICON_ZOOM_IN,
+ N_("Zoom _In"), NULL,
+ N_("Zoom in"),
+ GIMP_ZOOM_IN, FALSE,
+ GIMP_HELP_PALETTE_EDITOR_ZOOM_IN },
+
+ { "palette-editor-zoom-out", GIMP_ICON_ZOOM_OUT,
+ N_("Zoom _Out"), NULL,
+ N_("Zoom out"),
+ GIMP_ZOOM_OUT, FALSE,
+ GIMP_HELP_PALETTE_EDITOR_ZOOM_OUT },
+
+ { "palette-editor-zoom-all", GIMP_ICON_ZOOM_FIT_BEST,
+ N_("Zoom _All"), NULL,
+ N_("Zoom all"),
+ GIMP_ZOOM_OUT_MAX, FALSE,
+ GIMP_HELP_PALETTE_EDITOR_ZOOM_ALL }
+};
+
+
+void
+palette_editor_actions_setup (GimpActionGroup *group)
+{
+ gimp_action_group_add_actions (group, "palette-editor-action",
+ palette_editor_actions,
+ G_N_ELEMENTS (palette_editor_actions));
+
+ gimp_action_group_add_toggle_actions (group, "palette-editor-action",
+ palette_editor_toggle_actions,
+ G_N_ELEMENTS (palette_editor_toggle_actions));
+
+ gimp_action_group_add_enum_actions (group, "palette-editor-action",
+ palette_editor_new_actions,
+ G_N_ELEMENTS (palette_editor_new_actions),
+ palette_editor_new_color_cmd_callback);
+
+ gimp_action_group_add_enum_actions (group, NULL,
+ palette_editor_zoom_actions,
+ G_N_ELEMENTS (palette_editor_zoom_actions),
+ palette_editor_zoom_cmd_callback);
+}
+
+void
+palette_editor_actions_update (GimpActionGroup *group,
+ gpointer user_data)
+{
+ GimpPaletteEditor *editor = GIMP_PALETTE_EDITOR (user_data);
+ GimpDataEditor *data_editor = GIMP_DATA_EDITOR (user_data);
+ GimpData *data;
+ gboolean editable = FALSE;
+ GimpRGB fg;
+ GimpRGB bg;
+ gboolean edit_active = FALSE;
+
+ data = data_editor->data;
+
+ if (data)
+ {
+ if (data_editor->data_editable)
+ editable = TRUE;
+ }
+
+ if (data_editor->context)
+ {
+ gimp_context_get_foreground (data_editor->context, &fg);
+ gimp_context_get_background (data_editor->context, &bg);
+ }
+
+ edit_active = gimp_data_editor_get_edit_active (data_editor);
+
+#define SET_SENSITIVE(action,condition) \
+ gimp_action_group_set_action_sensitive (group, action, (condition) != 0)
+#define SET_ACTIVE(action,condition) \
+ gimp_action_group_set_action_active (group, action, (condition) != 0)
+#define SET_COLOR(action,color) \
+ gimp_action_group_set_action_color (group, action, color, FALSE);
+
+ SET_SENSITIVE ("palette-editor-edit-color", editable && editor->color);
+ SET_SENSITIVE ("palette-editor-delete-color", editable && editor->color);
+
+ SET_SENSITIVE ("palette-editor-new-color-fg", editable);
+ SET_SENSITIVE ("palette-editor-new-color-bg", editable);
+
+ SET_COLOR ("palette-editor-new-color-fg", data_editor->context ? &fg : NULL);
+ SET_COLOR ("palette-editor-new-color-bg", data_editor->context ? &bg : NULL);
+
+ SET_SENSITIVE ("palette-editor-zoom-out", data);
+ SET_SENSITIVE ("palette-editor-zoom-in", data);
+ SET_SENSITIVE ("palette-editor-zoom-all", data);
+
+ SET_ACTIVE ("palette-editor-edit-active", edit_active);
+
+#undef SET_SENSITIVE
+#undef SET_ACTIVE
+#undef SET_COLOR
+}
diff --git a/app/actions/palette-editor-actions.h b/app/actions/palette-editor-actions.h
new file mode 100644
index 0000000..287df8a
--- /dev/null
+++ b/app/actions/palette-editor-actions.h
@@ -0,0 +1,27 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __PALETTE_EDITOR_ACTIONS_H__
+#define __PALETTE_EDITOR_ACTIONS_H__
+
+
+void palette_editor_actions_setup (GimpActionGroup *group);
+void palette_editor_actions_update (GimpActionGroup *group,
+ gpointer data);
+
+
+#endif /* __PALETTE_EDITOR_ACTIONS_H__ */
diff --git a/app/actions/palette-editor-commands.c b/app/actions/palette-editor-commands.c
new file mode 100644
index 0000000..55a8c0e
--- /dev/null
+++ b/app/actions/palette-editor-commands.c
@@ -0,0 +1,96 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "actions-types.h"
+
+#include "core/gimpcontext.h"
+#include "core/gimppalette.h"
+
+#include "widgets/gimppaletteeditor.h"
+#include "widgets/gimppaletteview.h"
+
+#include "palette-editor-commands.h"
+
+
+/* public functions */
+
+void
+palette_editor_edit_color_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpPaletteEditor *editor = GIMP_PALETTE_EDITOR (data);
+
+ gimp_palette_editor_edit_color (editor);
+}
+
+void
+palette_editor_new_color_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpPaletteEditor *editor = GIMP_PALETTE_EDITOR (data);
+ GimpDataEditor *data_editor = GIMP_DATA_EDITOR (data);
+ gboolean background = (gboolean) g_variant_get_int32 (value);
+
+ if (data_editor->data_editable)
+ {
+ GimpPalette *palette = GIMP_PALETTE (data_editor->data);
+ GimpPaletteEntry *entry;
+ GimpRGB color;
+
+ if (background)
+ gimp_context_get_background (data_editor->context, &color);
+ else
+ gimp_context_get_foreground (data_editor->context, &color);
+
+ entry = gimp_palette_add_entry (palette, -1, NULL, &color);
+ gimp_palette_view_select_entry (GIMP_PALETTE_VIEW (editor->view), entry);
+ }
+}
+
+void
+palette_editor_delete_color_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpPaletteEditor *editor = GIMP_PALETTE_EDITOR (data);
+ GimpDataEditor *data_editor = GIMP_DATA_EDITOR (data);
+
+ if (data_editor->data_editable && editor->color)
+ {
+ GimpPalette *palette = GIMP_PALETTE (data_editor->data);
+
+ gimp_palette_delete_entry (palette, editor->color);
+ }
+}
+
+void
+palette_editor_zoom_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpPaletteEditor *editor = GIMP_PALETTE_EDITOR (data);
+ GimpZoomType zoom_type = (GimpZoomType) g_variant_get_int32 (value);
+
+ gimp_palette_editor_zoom (editor, zoom_type);
+}
diff --git a/app/actions/palette-editor-commands.h b/app/actions/palette-editor-commands.h
new file mode 100644
index 0000000..29cd43c
--- /dev/null
+++ b/app/actions/palette-editor-commands.h
@@ -0,0 +1,37 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __PALETTE_EDITOR_COMMANDS_H__
+#define __PALETTE_EDITOR_COMMANDS_H__
+
+
+void palette_editor_edit_color_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void palette_editor_new_color_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void palette_editor_delete_color_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+void palette_editor_zoom_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+
+#endif /* __PALETTE_EDITOR_COMMANDS_H__ */
diff --git a/app/actions/palettes-actions.c b/app/actions/palettes-actions.c
new file mode 100644
index 0000000..80dab41
--- /dev/null
+++ b/app/actions/palettes-actions.c
@@ -0,0 +1,159 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "actions-types.h"
+
+#include "core/gimpcontext.h"
+#include "core/gimpdata.h"
+
+#include "widgets/gimpactiongroup.h"
+#include "widgets/gimphelp-ids.h"
+
+#include "actions.h"
+#include "data-commands.h"
+#include "palettes-actions.h"
+#include "palettes-commands.h"
+
+#include "gimp-intl.h"
+
+
+static const GimpActionEntry palettes_actions[] =
+{
+ { "palettes-popup", GIMP_ICON_PALETTE,
+ NC_("palettes-action", "Palettes Menu"), NULL, NULL, NULL,
+ GIMP_HELP_PALETTE_DIALOG },
+
+ { "palettes-new", GIMP_ICON_DOCUMENT_NEW,
+ NC_("palettes-action", "_New Palette"), NULL,
+ NC_("palettes-action", "Create a new palette"),
+ data_new_cmd_callback,
+ GIMP_HELP_PALETTE_NEW },
+
+ { "palettes-import", "gtk-convert",
+ NC_("palettes-action", "_Import Palette..."), NULL,
+ NC_("palettes-action", "Import palette"),
+ palettes_import_cmd_callback,
+ GIMP_HELP_PALETTE_IMPORT },
+
+ { "palettes-duplicate", GIMP_ICON_OBJECT_DUPLICATE,
+ NC_("palettes-action", "D_uplicate Palette"), NULL,
+ NC_("palettes-action", "Duplicate this palette"),
+ data_duplicate_cmd_callback,
+ GIMP_HELP_PALETTE_DUPLICATE },
+
+ { "palettes-merge", NULL,
+ NC_("palettes-action", "_Merge Palettes..."), NULL,
+ NC_("palettes-action", "Merge palettes"),
+ palettes_merge_cmd_callback,
+ GIMP_HELP_PALETTE_MERGE },
+
+ { "palettes-copy-location", GIMP_ICON_EDIT_COPY,
+ NC_("palettes-action", "Copy Palette _Location"), NULL,
+ NC_("palettes-action", "Copy palette file location to clipboard"),
+ data_copy_location_cmd_callback,
+ GIMP_HELP_PALETTE_COPY_LOCATION },
+
+ { "palettes-show-in-file-manager", GIMP_ICON_FILE_MANAGER,
+ NC_("palettes-action", "Show in _File Manager"), NULL,
+ NC_("palettes-action", "Show palette file location in the file manager"),
+ data_show_in_file_manager_cmd_callback,
+ GIMP_HELP_PALETTE_SHOW_IN_FILE_MANAGER },
+
+ { "palettes-delete", GIMP_ICON_EDIT_DELETE,
+ NC_("palettes-action", "_Delete Palette"), NULL,
+ NC_("palettes-action", "Delete this palette"),
+ data_delete_cmd_callback,
+ GIMP_HELP_PALETTE_DELETE },
+
+ { "palettes-refresh", GIMP_ICON_VIEW_REFRESH,
+ NC_("palettes-action", "_Refresh Palettes"), NULL,
+ NC_("palettes-action", "Refresh palettes"),
+ data_refresh_cmd_callback,
+ GIMP_HELP_PALETTE_REFRESH }
+};
+
+static const GimpStringActionEntry palettes_edit_actions[] =
+{
+ { "palettes-edit", GIMP_ICON_EDIT,
+ NC_("palettes-action", "_Edit Palette..."), NULL,
+ NC_("palettes-action", "Edit this palette"),
+ "gimp-palette-editor",
+ GIMP_HELP_PALETTE_EDIT }
+};
+
+
+void
+palettes_actions_setup (GimpActionGroup *group)
+{
+ gimp_action_group_add_actions (group, "palettes-action",
+ palettes_actions,
+ G_N_ELEMENTS (palettes_actions));
+
+ gimp_action_group_add_string_actions (group, "palettes-action",
+ palettes_edit_actions,
+ G_N_ELEMENTS (palettes_edit_actions),
+ data_edit_cmd_callback);
+}
+
+void
+palettes_actions_update (GimpActionGroup *group,
+ gpointer user_data)
+{
+ GimpContext *context = action_data_get_context (user_data);
+ GimpPalette *palette = NULL;
+ GimpData *data = NULL;
+ GFile *file = NULL;
+ gint sel_count = 0;
+
+ if (context)
+ {
+ palette = gimp_context_get_palette (context);
+
+ sel_count = action_data_sel_count (user_data);
+
+ if (sel_count > 1)
+ {
+ palette = NULL;
+ }
+
+ if (palette)
+ {
+ data = GIMP_DATA (palette);
+
+ file = gimp_data_get_file (data);
+ }
+ }
+
+#define SET_SENSITIVE(action,condition) \
+ gimp_action_group_set_action_sensitive (group, action, (condition) != 0)
+
+ SET_SENSITIVE ("palettes-edit", palette);
+ SET_SENSITIVE ("palettes-duplicate", palette && gimp_data_is_duplicatable (data));
+ SET_SENSITIVE ("palettes-merge", sel_count > 1);
+ SET_SENSITIVE ("palettes-copy-location", file);
+ SET_SENSITIVE ("palettes-show-in-file-manager", file);
+ SET_SENSITIVE ("palettes-delete", palette && gimp_data_is_deletable (data));
+
+#undef SET_SENSITIVE
+}
diff --git a/app/actions/palettes-actions.h b/app/actions/palettes-actions.h
new file mode 100644
index 0000000..4029532
--- /dev/null
+++ b/app/actions/palettes-actions.h
@@ -0,0 +1,27 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __PALETTES_ACTIONS_H__
+#define __PALETTES_ACTIONS_H__
+
+
+void palettes_actions_setup (GimpActionGroup *group);
+void palettes_actions_update (GimpActionGroup *group,
+ gpointer user_data);
+
+
+#endif /* __PALETTES_ACTIONS_H__ */
diff --git a/app/actions/palettes-commands.c b/app/actions/palettes-commands.c
new file mode 100644
index 0000000..5240e77
--- /dev/null
+++ b/app/actions/palettes-commands.c
@@ -0,0 +1,152 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "actions-types.h"
+
+#include "core/gimp.h"
+#include "core/gimpcontext.h"
+#include "core/gimpdatafactory.h"
+#include "core/gimppalette.h"
+
+#include "widgets/gimpcontainerview.h"
+#include "widgets/gimpdatafactoryview.h"
+#include "widgets/gimpdialogfactory.h"
+#include "widgets/gimphelp-ids.h"
+#include "widgets/gimpview.h"
+#include "widgets/gimpwidgets-utils.h"
+
+#include "dialogs/dialogs.h"
+
+#include "actions.h"
+#include "palettes-commands.h"
+
+#include "gimp-intl.h"
+
+
+/* local function prototypes */
+
+static void palettes_merge_callback (GtkWidget *widget,
+ const gchar *palette_name,
+ gpointer data);
+
+
+/* public functions */
+
+void
+palettes_import_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GtkWidget *widget;
+ return_if_no_widget (widget, data);
+
+ gimp_dialog_factory_dialog_new (gimp_dialog_factory_get_singleton (),
+ gtk_widget_get_screen (widget),
+ gimp_widget_get_monitor (widget),
+ NULL /*ui_manager*/,
+ "gimp-palette-import-dialog", -1, TRUE);
+}
+
+void
+palettes_merge_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpContainerEditor *editor = GIMP_CONTAINER_EDITOR (data);
+ GtkWidget *dialog;
+
+#define MERGE_DIALOG_KEY "gimp-palettes-merge-dialog"
+
+ dialog = dialogs_get_dialog (G_OBJECT (editor), MERGE_DIALOG_KEY);
+
+ if (! dialog)
+ {
+ dialog = gimp_query_string_box (_("Merge Palettes"),
+ GTK_WIDGET (editor),
+ gimp_standard_help_func,
+ GIMP_HELP_PALETTE_MERGE,
+ _("Enter a name for the merged palette"),
+ NULL,
+ G_OBJECT (editor), "destroy",
+ palettes_merge_callback, editor);
+
+ dialogs_attach_dialog (G_OBJECT (editor), MERGE_DIALOG_KEY, dialog);
+ }
+
+ gtk_window_present (GTK_WINDOW (dialog));
+}
+
+
+/* private functions */
+
+static void
+palettes_merge_callback (GtkWidget *widget,
+ const gchar *palette_name,
+ gpointer data)
+{
+ GimpContainerEditor *editor = data;
+ GimpDataFactoryView *view = data;
+ GimpDataFactory *factory;
+ GimpContext *context;
+ GimpPalette *new_palette;
+ GList *selected = NULL;
+ GList *list;
+
+ context = gimp_container_view_get_context (editor->view);
+ factory = gimp_data_factory_view_get_data_factory (view);
+
+ gimp_container_view_get_selected (editor->view, &selected);
+
+ if (g_list_length (selected) < 2)
+ {
+ gimp_message_literal (context->gimp,
+ G_OBJECT (editor), GIMP_MESSAGE_WARNING,
+ _("There must be at least two palettes selected "
+ "to merge."));
+ g_list_free (selected);
+ return;
+ }
+
+ new_palette = GIMP_PALETTE (gimp_data_factory_data_new (factory, context,
+ palette_name));
+
+ for (list = selected; list; list = g_list_next (list))
+ {
+ GimpPalette *palette = list->data;
+ GList *cols;
+
+ for (cols = gimp_palette_get_colors (palette);
+ cols;
+ cols = g_list_next (cols))
+ {
+ GimpPaletteEntry *entry = cols->data;
+
+ gimp_palette_add_entry (new_palette, -1,
+ entry->name,
+ &entry->color);
+ }
+ }
+
+ g_list_free (selected);
+}
diff --git a/app/actions/palettes-commands.h b/app/actions/palettes-commands.h
new file mode 100644
index 0000000..ab7fb24
--- /dev/null
+++ b/app/actions/palettes-commands.h
@@ -0,0 +1,30 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __PALETTES_COMMANDS_H__
+#define __PALETTES_COMMANDS_H__
+
+
+void palettes_import_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void palettes_merge_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+
+#endif /* __PALETTES_COMMANDS_H__ */
diff --git a/app/actions/patterns-actions.c b/app/actions/patterns-actions.c
new file mode 100644
index 0000000..f563ef6
--- /dev/null
+++ b/app/actions/patterns-actions.c
@@ -0,0 +1,149 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "actions-types.h"
+
+#include "core/gimpcontext.h"
+#include "core/gimpdata.h"
+
+#include "widgets/gimpactiongroup.h"
+#include "widgets/gimphelp-ids.h"
+
+#include "actions.h"
+#include "data-commands.h"
+#include "patterns-actions.h"
+
+#include "gimp-intl.h"
+
+
+static const GimpActionEntry patterns_actions[] =
+{
+ { "patterns-popup", GIMP_ICON_PATTERN,
+ NC_("patterns-action", "Patterns Menu"), NULL, NULL, NULL,
+ GIMP_HELP_PATTERN_DIALOG },
+
+ { "patterns-open-as-image", GIMP_ICON_DOCUMENT_OPEN,
+ NC_("patterns-action", "_Open Pattern as Image"), NULL,
+ NC_("patterns-action", "Open this pattern as an image"),
+ data_open_as_image_cmd_callback,
+ GIMP_HELP_PATTERN_OPEN_AS_IMAGE },
+
+ { "patterns-new", GIMP_ICON_DOCUMENT_NEW,
+ NC_("patterns-action", "_New Pattern"), NULL,
+ NC_("patterns-action", "Create a new pattern"),
+ data_new_cmd_callback,
+ GIMP_HELP_PATTERN_NEW },
+
+ { "patterns-duplicate", GIMP_ICON_OBJECT_DUPLICATE,
+ NC_("patterns-action", "D_uplicate Pattern"), NULL,
+ NC_("patterns-action", "Duplicate this pattern"),
+ data_duplicate_cmd_callback,
+ GIMP_HELP_PATTERN_DUPLICATE },
+
+ { "patterns-copy-location", GIMP_ICON_EDIT_COPY,
+ NC_("patterns-action", "Copy Pattern _Location"), NULL,
+ NC_("patterns-action", "Copy pattern file location to clipboard"),
+ data_copy_location_cmd_callback,
+ GIMP_HELP_PATTERN_COPY_LOCATION },
+
+ { "patterns-show-in-file-manager", GIMP_ICON_FILE_MANAGER,
+ NC_("patterns-action", "Show in _File Manager"), NULL,
+ NC_("patterns-action", "Show pattern file location in the file manager"),
+ data_show_in_file_manager_cmd_callback,
+ GIMP_HELP_PATTERN_SHOW_IN_FILE_MANAGER },
+
+ { "patterns-delete", GIMP_ICON_EDIT_DELETE,
+ NC_("patterns-action", "_Delete Pattern"), NULL,
+ NC_("patterns-action", "Delete this pattern"),
+ data_delete_cmd_callback,
+ GIMP_HELP_PATTERN_DELETE },
+
+ { "patterns-refresh", GIMP_ICON_VIEW_REFRESH,
+ NC_("patterns-action", "_Refresh Patterns"), NULL,
+ NC_("patterns-action", "Refresh patterns"),
+ data_refresh_cmd_callback,
+ GIMP_HELP_PATTERN_REFRESH }
+};
+
+static const GimpStringActionEntry patterns_edit_actions[] =
+{
+ { "patterns-edit", GIMP_ICON_EDIT,
+ NC_("patterns-action", "_Edit Pattern..."), NULL,
+ NC_("patterns-action", "Edit pattern"),
+ "gimp-pattern-editor",
+ GIMP_HELP_PATTERN_EDIT }
+};
+
+
+void
+patterns_actions_setup (GimpActionGroup *group)
+{
+ gimp_action_group_add_actions (group, "patterns-action",
+ patterns_actions,
+ G_N_ELEMENTS (patterns_actions));
+
+ gimp_action_group_add_string_actions (group, "patterns-action",
+ patterns_edit_actions,
+ G_N_ELEMENTS (patterns_edit_actions),
+ data_edit_cmd_callback);
+}
+
+void
+patterns_actions_update (GimpActionGroup *group,
+ gpointer user_data)
+{
+ GimpContext *context = action_data_get_context (user_data);
+ GimpPattern *pattern = NULL;
+ GimpData *data = NULL;
+ GFile *file = NULL;
+
+ if (context)
+ {
+ pattern = gimp_context_get_pattern (context);
+
+ if (action_data_sel_count (user_data) > 1)
+ {
+ pattern = NULL;
+ }
+
+ if (pattern)
+ {
+ data = GIMP_DATA (pattern);
+
+ file = gimp_data_get_file (data);
+ }
+ }
+
+#define SET_SENSITIVE(action,condition) \
+ gimp_action_group_set_action_sensitive (group, action, (condition) != 0)
+
+ SET_SENSITIVE ("patterns-edit", pattern && FALSE);
+ SET_SENSITIVE ("patterns-open-as-image", file);
+ SET_SENSITIVE ("patterns-duplicate", pattern && gimp_data_is_duplicatable (data));
+ SET_SENSITIVE ("patterns-copy-location", file);
+ SET_SENSITIVE ("patterns-show-in-file-manager", file);
+ SET_SENSITIVE ("patterns-delete", pattern && gimp_data_is_deletable (data));
+
+#undef SET_SENSITIVE
+}
diff --git a/app/actions/patterns-actions.h b/app/actions/patterns-actions.h
new file mode 100644
index 0000000..a736b9d
--- /dev/null
+++ b/app/actions/patterns-actions.h
@@ -0,0 +1,27 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __PATTERNS_ACTIONS_H__
+#define __PATTERNS_ACTIONS_H__
+
+
+void patterns_actions_setup (GimpActionGroup *group);
+void patterns_actions_update (GimpActionGroup *group,
+ gpointer user_data);
+
+
+#endif /* __PATTERNS_ACTIONS_H__ */
diff --git a/app/actions/plug-in-actions.c b/app/actions/plug-in-actions.c
new file mode 100644
index 0000000..5a78324
--- /dev/null
+++ b/app/actions/plug-in-actions.c
@@ -0,0 +1,517 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <string.h>
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpbase/gimpbase.h"
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "actions-types.h"
+
+#include "core/gimp.h"
+#include "core/gimpcontext.h"
+#include "core/gimpdrawable.h"
+#include "core/gimpimage.h"
+
+#include "plug-in/gimppluginmanager.h"
+#include "plug-in/gimppluginmanager-help-domain.h"
+#include "plug-in/gimppluginmanager-locale-domain.h"
+#include "plug-in/gimppluginmanager-menu-branch.h"
+#include "plug-in/gimppluginprocedure.h"
+
+#include "widgets/gimpaction.h"
+#include "widgets/gimpactiongroup.h"
+#include "widgets/gimpactionimpl.h"
+#include "widgets/gimphelp-ids.h"
+
+#include "actions.h"
+#include "plug-in-actions.h"
+#include "plug-in-commands.h"
+
+#include "gimp-intl.h"
+
+
+/* local function prototypes */
+
+static void plug_in_actions_menu_branch_added (GimpPlugInManager *manager,
+ GFile *file,
+ const gchar *menu_path,
+ const gchar *menu_label,
+ GimpActionGroup *group);
+static void plug_in_actions_register_procedure (GimpPDB *pdb,
+ GimpProcedure *procedure,
+ GimpActionGroup *group);
+static void plug_in_actions_unregister_procedure (GimpPDB *pdb,
+ GimpProcedure *procedure,
+ GimpActionGroup *group);
+static void plug_in_actions_menu_path_added (GimpPlugInProcedure *proc,
+ const gchar *menu_path,
+ GimpActionGroup *group);
+static void plug_in_actions_add_proc (GimpActionGroup *group,
+ GimpPlugInProcedure *proc);
+
+static gboolean plug_in_actions_check_translation (const gchar *original,
+ const gchar *translated);
+static void plug_in_actions_build_path (GimpActionGroup *group,
+ const gchar *original,
+ const gchar *translated);
+
+
+/* private variables */
+
+static const GimpActionEntry plug_in_actions[] =
+{
+ { "plug-in-reset-all", GIMP_ICON_RESET,
+ NC_("plug-in-action", "Reset all _Filters"), NULL,
+ NC_("plug-in-action", "Reset all plug-ins to their default settings"),
+ plug_in_reset_all_cmd_callback,
+ GIMP_HELP_FILTER_RESET_ALL }
+};
+
+
+/* public functions */
+
+void
+plug_in_actions_setup (GimpActionGroup *group)
+{
+ GimpPlugInManager *manager = group->gimp->plug_in_manager;
+ GSList *list;
+
+ gimp_action_group_add_actions (group, "plug-in-action",
+ plug_in_actions,
+ G_N_ELEMENTS (plug_in_actions));
+
+ for (list = gimp_plug_in_manager_get_menu_branches (manager);
+ list;
+ list = g_slist_next (list))
+ {
+ GimpPlugInMenuBranch *branch = list->data;
+
+ plug_in_actions_menu_branch_added (manager,
+ branch->file,
+ branch->menu_path,
+ branch->menu_label,
+ group);
+ }
+
+ g_signal_connect_object (manager,
+ "menu-branch-added",
+ G_CALLBACK (plug_in_actions_menu_branch_added),
+ group, 0);
+
+ for (list = manager->plug_in_procedures;
+ list;
+ list = g_slist_next (list))
+ {
+ GimpPlugInProcedure *plug_in_proc = list->data;
+
+ if (plug_in_proc->file)
+ plug_in_actions_register_procedure (group->gimp->pdb,
+ GIMP_PROCEDURE (plug_in_proc),
+ group);
+ }
+
+ g_signal_connect_object (group->gimp->pdb, "register-procedure",
+ G_CALLBACK (plug_in_actions_register_procedure),
+ group, 0);
+ g_signal_connect_object (group->gimp->pdb, "unregister-procedure",
+ G_CALLBACK (plug_in_actions_unregister_procedure),
+ group, 0);
+}
+
+void
+plug_in_actions_update (GimpActionGroup *group,
+ gpointer data)
+{
+ GimpImage *image = action_data_get_image (data);
+ GimpPlugInManager *manager = group->gimp->plug_in_manager;
+ GimpDrawable *drawable = NULL;
+ GSList *list;
+
+ if (image)
+ drawable = gimp_image_get_active_drawable (image);
+
+ for (list = manager->plug_in_procedures; list; list = g_slist_next (list))
+ {
+ GimpPlugInProcedure *proc = list->data;
+
+ if ((proc->menu_label || proc->menu_paths) &&
+ ! proc->file_proc &&
+ proc->image_types_val)
+ {
+ GimpProcedure *procedure = GIMP_PROCEDURE (proc);
+ gboolean sensitive;
+ const gchar *tooltip;
+
+ sensitive = gimp_procedure_get_sensitive (procedure,
+ GIMP_OBJECT (drawable),
+ &tooltip);
+
+ gimp_action_group_set_action_sensitive (group,
+ gimp_object_get_name (proc),
+ sensitive);
+
+ if (sensitive || ! drawable || ! tooltip)
+ tooltip = gimp_procedure_get_blurb (procedure);
+
+ gimp_action_group_set_action_tooltip (group,
+ gimp_object_get_name (proc),
+ tooltip);
+ }
+ }
+}
+
+
+/* private functions */
+
+static void
+plug_in_actions_menu_branch_added (GimpPlugInManager *manager,
+ GFile *file,
+ const gchar *menu_path,
+ const gchar *menu_label,
+ GimpActionGroup *group)
+{
+ const gchar *locale_domain;
+ const gchar *path_translated;
+ const gchar *label_translated;
+ gchar *full;
+ gchar *full_translated;
+
+ locale_domain = gimp_plug_in_manager_get_locale_domain (manager, file, NULL);
+
+ path_translated = dgettext (locale_domain, menu_path);
+ label_translated = dgettext (locale_domain, menu_label);
+
+ full = g_strconcat (menu_path, "/", menu_label, NULL);
+ full_translated = g_strconcat (path_translated, "/", label_translated, NULL);
+
+ if (plug_in_actions_check_translation (full, full_translated))
+ plug_in_actions_build_path (group, full, full_translated);
+ else
+ plug_in_actions_build_path (group, full, full);
+
+ g_free (full_translated);
+ g_free (full);
+}
+
+static void
+plug_in_actions_register_procedure (GimpPDB *pdb,
+ GimpProcedure *procedure,
+ GimpActionGroup *group)
+{
+ if (GIMP_IS_PLUG_IN_PROCEDURE (procedure))
+ {
+ GimpPlugInProcedure *plug_in_proc = GIMP_PLUG_IN_PROCEDURE (procedure);
+
+ g_signal_connect_object (plug_in_proc, "menu-path-added",
+ G_CALLBACK (plug_in_actions_menu_path_added),
+ group, 0);
+
+ if ((plug_in_proc->menu_label || plug_in_proc->menu_paths) &&
+ ! plug_in_proc->file_proc)
+ {
+#if 0
+ g_print ("%s: %s\n", G_STRFUNC,
+ gimp_object_get_name (procedure));
+#endif
+
+ plug_in_actions_add_proc (group, plug_in_proc);
+ }
+ }
+}
+
+static void
+plug_in_actions_unregister_procedure (GimpPDB *pdb,
+ GimpProcedure *procedure,
+ GimpActionGroup *group)
+{
+ if (GIMP_IS_PLUG_IN_PROCEDURE (procedure))
+ {
+ GimpPlugInProcedure *plug_in_proc = GIMP_PLUG_IN_PROCEDURE (procedure);
+
+ g_signal_handlers_disconnect_by_func (plug_in_proc,
+ plug_in_actions_menu_path_added,
+ group);
+
+ if ((plug_in_proc->menu_label || plug_in_proc->menu_paths) &&
+ ! plug_in_proc->file_proc)
+ {
+ GimpAction *action;
+
+#if 0
+ g_print ("%s: %s\n", G_STRFUNC,
+ gimp_object_get_name (procedure));
+#endif
+
+ action = gimp_action_group_get_action (group,
+ gimp_object_get_name (procedure));
+
+ if (action)
+ gimp_action_group_remove_action (group, action);
+ }
+ }
+}
+
+static void
+plug_in_actions_menu_path_added (GimpPlugInProcedure *plug_in_proc,
+ const gchar *menu_path,
+ GimpActionGroup *group)
+{
+ const gchar *locale_domain;
+ const gchar *path_translated;
+
+#if 0
+ g_print ("%s: %s (%s)\n", G_STRFUNC,
+ gimp_object_get_name (plug_in_proc), menu_path);
+#endif
+
+ locale_domain = gimp_plug_in_procedure_get_locale_domain (plug_in_proc);
+
+ path_translated = dgettext (locale_domain, menu_path);
+
+ if (plug_in_actions_check_translation (menu_path, path_translated))
+ plug_in_actions_build_path (group, menu_path, path_translated);
+ else
+ plug_in_actions_build_path (group, menu_path, menu_path);
+}
+
+static void
+plug_in_actions_add_proc (GimpActionGroup *group,
+ GimpPlugInProcedure *proc)
+{
+ GimpProcedureActionEntry entry;
+ const gchar *locale_domain;
+ gchar *path_original = NULL;
+ gchar *path_translated = NULL;
+
+ locale_domain = gimp_plug_in_procedure_get_locale_domain (proc);
+
+ if (! proc->menu_label)
+ {
+ gchar *p1, *p2;
+
+ path_original = proc->menu_paths->data;
+ path_translated = dgettext (locale_domain, path_original);
+
+ path_original = g_strdup (path_original);
+
+ if (plug_in_actions_check_translation (path_original, path_translated))
+ path_translated = g_strdup (path_translated);
+ else
+ path_translated = g_strdup (path_original);
+
+ p1 = strrchr (path_original, '/');
+ p2 = strrchr (path_translated, '/');
+
+ if (p1 && p2)
+ {
+ *p1 = '\0';
+ *p2 = '\0';
+ }
+ else
+ {
+ g_warning ("bad menu path for procedure \"%s\": \"%s\"",
+ gimp_object_get_name (proc), path_original);
+
+ g_free (path_original);
+ g_free (path_translated);
+
+ return;
+ }
+ }
+
+ entry.name = gimp_object_get_name (proc);
+ entry.icon_name = gimp_viewable_get_icon_name (GIMP_VIEWABLE (proc));
+ entry.label = gimp_procedure_get_menu_label (GIMP_PROCEDURE (proc));
+ entry.accelerator = NULL;
+ entry.tooltip = gimp_procedure_get_blurb (GIMP_PROCEDURE (proc));
+ entry.procedure = GIMP_PROCEDURE (proc);
+ entry.help_id = gimp_procedure_get_help_id (GIMP_PROCEDURE (proc));
+
+ gimp_action_group_add_procedure_actions (group, &entry, 1,
+ plug_in_run_cmd_callback);
+
+ if (proc->menu_label)
+ {
+ GList *list;
+
+ for (list = proc->menu_paths; list; list = g_list_next (list))
+ {
+ const gchar *original = list->data;
+ const gchar *translated = dgettext (locale_domain, original);
+
+ if (plug_in_actions_check_translation (original, translated))
+ plug_in_actions_build_path (group, original, translated);
+ else
+ plug_in_actions_build_path (group, original, original);
+ }
+ }
+ else
+ {
+ plug_in_actions_build_path (group, path_original, path_translated);
+
+ g_free (path_original);
+ g_free (path_translated);
+ }
+
+ if ((proc->menu_label || proc->menu_paths) &&
+ ! proc->file_proc &&
+ proc->image_types_val)
+ {
+ GimpContext *context = gimp_get_user_context (group->gimp);
+ GimpImage *image = gimp_context_get_image (context);
+ GimpDrawable *drawable = NULL;
+ gboolean sensitive;
+ const gchar *tooltip;
+
+ if (image)
+ drawable = gimp_image_get_active_drawable (image);
+
+ sensitive = gimp_procedure_get_sensitive (GIMP_PROCEDURE (proc),
+ GIMP_OBJECT (drawable),
+ &tooltip);
+
+ gimp_action_group_set_action_sensitive (group,
+ gimp_object_get_name (proc),
+ sensitive);
+
+ if (! sensitive && drawable && tooltip)
+ gimp_action_group_set_action_tooltip (group,
+ gimp_object_get_name (proc),
+ tooltip);
+ }
+}
+
+static gboolean
+plug_in_actions_check_translation (const gchar *original,
+ const gchar *translated)
+{
+ const gchar *p1;
+ const gchar *p2;
+
+ /* first check if <Prefix> is present and identical in both strings */
+ p1 = strchr (original, '>');
+ p2 = strchr (translated, '>');
+
+ if (!p1 || !p2 ||
+ (p1 - original) != (p2 - translated) ||
+ strncmp (original, translated, p1 - original))
+ {
+ g_printerr ("bad translation \"%s\"\n"
+ "for menu path \"%s\"\n"
+ "(<Prefix> must not be translated)\n\n",
+ translated, original);
+ return FALSE;
+ }
+
+ p1++;
+ p2++;
+
+ /* then check if either a '/' or nothing follows in *both* strings */
+ if (! ((*p1 == '/' && *p2 == '/') ||
+ (*p1 == '\0' && *p2 == '\0')))
+ {
+ g_printerr ("bad translation \"%s\"\n"
+ "for menu path \"%s\"\n"
+ "(<Prefix> must be followed by either nothing or '/')\n\n",
+ translated, original);
+ return FALSE;
+ }
+
+ /* then check the number of slashes in the remaining string */
+ while (p1 && p2)
+ {
+ p1 = strchr (p1, '/');
+ p2 = strchr (p2, '/');
+
+ if (p1) p1++;
+ if (p2) p2++;
+ }
+
+ if (p1 || p2)
+ {
+ g_printerr ("bad translation \"%s\"\n"
+ "for menu path \"%s\"\n"
+ "(number of '/' must be the same)\n\n",
+ translated, original);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static void
+plug_in_actions_build_path (GimpActionGroup *group,
+ const gchar *path_original,
+ const gchar *path_translated)
+{
+ GHashTable *path_table;
+ gchar *copy_original;
+ gchar *copy_translated;
+ gchar *p1, *p2;
+
+ path_table = g_object_get_data (G_OBJECT (group), "plug-in-path-table");
+
+ if (! path_table)
+ {
+ path_table = g_hash_table_new_full (g_str_hash, g_str_equal,
+ g_free, NULL);
+
+ g_object_set_data_full (G_OBJECT (group), "plug-in-path-table",
+ path_table,
+ (GDestroyNotify) g_hash_table_destroy);
+ }
+
+ copy_original = gimp_strip_uline (path_original);
+ copy_translated = g_strdup (path_translated);
+
+ p1 = strrchr (copy_original, '/');
+ p2 = strrchr (copy_translated, '/');
+
+ if (p1 && p2 && ! g_hash_table_lookup (path_table, copy_original))
+ {
+ GimpAction *action;
+ gchar *label;
+
+ label = p2 + 1;
+
+#if 0
+ g_print ("adding plug-in submenu '%s' (%s)\n",
+ copy_original, label);
+#endif
+
+ action = gimp_action_impl_new (copy_original, label, NULL, NULL, NULL);
+ gimp_action_group_add_action (group, action);
+ g_object_unref (action);
+
+ g_hash_table_insert (path_table, g_strdup (copy_original), action);
+
+ *p1 = '\0';
+ *p2 = '\0';
+
+ /* recursively call ourselves with the last part of the path removed */
+ plug_in_actions_build_path (group, copy_original, copy_translated);
+ }
+
+ g_free (copy_original);
+ g_free (copy_translated);
+}
diff --git a/app/actions/plug-in-actions.h b/app/actions/plug-in-actions.h
new file mode 100644
index 0000000..a586acd
--- /dev/null
+++ b/app/actions/plug-in-actions.h
@@ -0,0 +1,27 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __PLUG_IN_ACTIONS_H__
+#define __PLUG_IN_ACTIONS_H__
+
+
+void plug_in_actions_setup (GimpActionGroup *group);
+void plug_in_actions_update (GimpActionGroup *group,
+ gpointer data);
+
+
+#endif /* __PLUG_IN_ACTIONS_H__ */
diff --git a/app/actions/plug-in-commands.c b/app/actions/plug-in-commands.c
new file mode 100644
index 0000000..ed7428d
--- /dev/null
+++ b/app/actions/plug-in-commands.c
@@ -0,0 +1,221 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpbase/gimpbase.h"
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "actions-types.h"
+
+#include "core/gimp.h"
+#include "core/gimp-filter-history.h"
+#include "core/gimpcontainer.h"
+#include "core/gimpcontext.h"
+#include "core/gimpimage.h"
+#include "core/gimpitem.h"
+#include "core/gimpparamspecs.h"
+#include "core/gimpprogress.h"
+
+#include "pdb/gimpprocedure.h"
+
+#include "plug-in/gimppluginmanager.h"
+#include "plug-in/gimppluginmanager-data.h"
+
+#include "widgets/gimpbufferview.h"
+#include "widgets/gimpcontainerview.h"
+#include "widgets/gimpdatafactoryview.h"
+#include "widgets/gimphelp-ids.h"
+#include "widgets/gimpimageeditor.h"
+#include "widgets/gimpitemtreeview.h"
+#include "widgets/gimpmessagebox.h"
+#include "widgets/gimpmessagedialog.h"
+
+#include "dialogs/dialogs.h"
+
+#include "actions.h"
+#include "plug-in-commands.h"
+#include "procedure-commands.h"
+
+#include "gimp-intl.h"
+
+
+/* local function prototypes */
+
+static void plug_in_reset_all_response (GtkWidget *dialog,
+ gint response_id,
+ Gimp *gimp);
+
+
+/* public functions */
+
+void
+plug_in_run_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ Gimp *gimp;
+ GimpValueArray *args = NULL;
+ GimpDisplay *display = NULL;
+ GimpProcedure *procedure;
+ gsize hack;
+ return_if_no_gimp (gimp, data);
+
+ hack = g_variant_get_uint64 (value);
+
+ procedure = GSIZE_TO_POINTER (hack);
+
+ switch (procedure->proc_type)
+ {
+ case GIMP_EXTENSION:
+ args = procedure_commands_get_run_mode_arg (procedure);
+ break;
+
+ case GIMP_PLUGIN:
+ case GIMP_TEMPORARY:
+ if (GIMP_IS_DATA_FACTORY_VIEW (data) ||
+ GIMP_IS_BUFFER_VIEW (data))
+ {
+ GimpContainerEditor *editor = GIMP_CONTAINER_EDITOR (data);
+ GimpContainer *container;
+ GimpContext *context;
+ GimpObject *object;
+
+ container = gimp_container_view_get_container (editor->view);
+ context = gimp_container_view_get_context (editor->view);
+
+ object = gimp_context_get_by_type (context,
+ gimp_container_get_children_type (container));
+
+ args = procedure_commands_get_data_args (procedure, object);
+ }
+ else if (GIMP_IS_IMAGE_EDITOR (data))
+ {
+ GimpImageEditor *editor = GIMP_IMAGE_EDITOR (data);
+ GimpImage *image;
+
+ image = gimp_image_editor_get_image (editor);
+
+ args = procedure_commands_get_image_args (procedure, image);
+ }
+ else if (GIMP_IS_ITEM_TREE_VIEW (data))
+ {
+ GimpItemTreeView *view = GIMP_ITEM_TREE_VIEW (data);
+ GimpImage *image;
+ GimpItem *item;
+
+ image = gimp_item_tree_view_get_image (view);
+
+ if (image)
+ item = GIMP_ITEM_TREE_VIEW_GET_CLASS (view)->get_active_item (image);
+ else
+ item = NULL;
+
+ args = procedure_commands_get_item_args (procedure, image, item);
+ }
+ else
+ {
+ display = action_data_get_display (data);
+
+ args = procedure_commands_get_display_args (procedure, display, NULL);
+ }
+ break;
+
+ case GIMP_INTERNAL:
+ g_warning ("Unhandled procedure type.");
+ break;
+ }
+
+ if (args)
+ {
+ if (procedure_commands_run_procedure_async (procedure, gimp,
+ GIMP_PROGRESS (display),
+ GIMP_RUN_INTERACTIVE, args,
+ display))
+ {
+ /* remember only image plug-ins */
+ if (procedure->num_args >= 2 &&
+ GIMP_IS_PARAM_SPEC_IMAGE_ID (procedure->args[1]))
+ {
+ gimp_filter_history_add (gimp, procedure);
+ }
+ }
+
+ gimp_value_array_unref (args);
+ }
+}
+
+void
+plug_in_reset_all_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ Gimp *gimp;
+ GtkWidget *dialog;
+ return_if_no_gimp (gimp, data);
+
+#define RESET_FILTERS_DIALOG_KEY "gimp-reset-all-filters-dialog"
+
+ dialog = dialogs_get_dialog (G_OBJECT (gimp), RESET_FILTERS_DIALOG_KEY);
+
+ if (! dialog)
+ {
+ dialog = gimp_message_dialog_new (_("Reset all Filters"),
+ GIMP_ICON_DIALOG_QUESTION,
+ NULL, 0,
+ gimp_standard_help_func, NULL,
+
+ _("_Cancel"), GTK_RESPONSE_CANCEL,
+ _("_Reset"), GTK_RESPONSE_OK,
+
+ NULL);
+
+ gtk_dialog_set_alternative_button_order (GTK_DIALOG (dialog),
+ GTK_RESPONSE_OK,
+ GTK_RESPONSE_CANCEL,
+ -1);
+
+ g_signal_connect (dialog, "response",
+ G_CALLBACK (plug_in_reset_all_response),
+ gimp);
+
+ gimp_message_box_set_primary_text (GIMP_MESSAGE_DIALOG (dialog)->box,
+ _("Do you really want to reset all "
+ "filters to default values?"));
+
+ dialogs_attach_dialog (G_OBJECT (gimp), RESET_FILTERS_DIALOG_KEY, dialog);
+ }
+
+ gtk_window_present (GTK_WINDOW (dialog));
+}
+
+
+/* private functions */
+
+static void
+plug_in_reset_all_response (GtkWidget *dialog,
+ gint response_id,
+ Gimp *gimp)
+{
+ gtk_widget_destroy (dialog);
+
+ if (response_id == GTK_RESPONSE_OK)
+ gimp_plug_in_manager_data_free (gimp->plug_in_manager);
+}
diff --git a/app/actions/plug-in-commands.h b/app/actions/plug-in-commands.h
new file mode 100644
index 0000000..b648482
--- /dev/null
+++ b/app/actions/plug-in-commands.h
@@ -0,0 +1,31 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __PLUG_IN_COMMANDS_H__
+#define __PLUG_IN_COMMANDS_H__
+
+
+void plug_in_run_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+void plug_in_reset_all_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+
+#endif /* __PLUG_IN_COMMANDS_H__ */
diff --git a/app/actions/procedure-commands.c b/app/actions/procedure-commands.c
new file mode 100644
index 0000000..93ec29d
--- /dev/null
+++ b/app/actions/procedure-commands.c
@@ -0,0 +1,326 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpbase/gimpbase.h"
+
+#include "actions-types.h"
+
+#include "core/gimp.h"
+#include "core/gimpimage.h"
+#include "core/gimpparamspecs.h"
+#include "core/gimpprogress.h"
+
+#include "pdb/gimpprocedure.h"
+
+#include "display/gimpdisplay.h"
+
+#include "procedure-commands.h"
+
+
+GimpValueArray *
+procedure_commands_get_run_mode_arg (GimpProcedure *procedure)
+{
+ GimpValueArray *args;
+ gint n_args = 0;
+
+ args = gimp_procedure_get_arguments (procedure);
+
+ /* initialize the first argument */
+ if (gimp_value_array_length (args) > n_args &&
+ GIMP_IS_PARAM_SPEC_INT32 (procedure->args[n_args]))
+ {
+ g_value_set_int (gimp_value_array_index (args, n_args),
+ GIMP_RUN_INTERACTIVE);
+ n_args++;
+ }
+
+ gimp_value_array_truncate (args, n_args);
+
+ return args;
+}
+
+GimpValueArray *
+procedure_commands_get_data_args (GimpProcedure *procedure,
+ GimpObject *object)
+{
+ GimpValueArray *args;
+ gint n_args = 0;
+
+ args = gimp_procedure_get_arguments (procedure);
+
+ /* initialize the first argument */
+ g_value_set_int (gimp_value_array_index (args, n_args),
+ GIMP_RUN_INTERACTIVE);
+ n_args++;
+
+ if (gimp_value_array_length (args) > n_args &&
+ GIMP_IS_PARAM_SPEC_STRING (procedure->args[n_args]))
+ {
+ if (object)
+ {
+ g_value_set_string (gimp_value_array_index (args, n_args),
+ gimp_object_get_name (object));
+ n_args++;
+ }
+ else
+ {
+ g_warning ("Uh-oh, no active data object for the plug-in!");
+ gimp_value_array_unref (args);
+ return NULL;
+ }
+ }
+
+ gimp_value_array_truncate (args, n_args);
+
+ return args;
+}
+
+GimpValueArray *
+procedure_commands_get_image_args (GimpProcedure *procedure,
+ GimpImage *image)
+{
+ GimpValueArray *args;
+ gint n_args = 0;
+
+ args = gimp_procedure_get_arguments (procedure);
+
+ /* initialize the first argument */
+ g_value_set_int (gimp_value_array_index (args, n_args),
+ GIMP_RUN_INTERACTIVE);
+ n_args++;
+
+ if (gimp_value_array_length (args) > n_args &&
+ GIMP_IS_PARAM_SPEC_IMAGE_ID (procedure->args[n_args]))
+ {
+ if (image)
+ {
+ gimp_value_set_image (gimp_value_array_index (args, n_args), image);
+ n_args++;
+ }
+ else
+ {
+ g_warning ("Uh-oh, no active image for the plug-in!");
+ gimp_value_array_unref (args);
+ return NULL;
+ }
+ }
+
+ gimp_value_array_truncate (args, n_args);
+
+ return args;
+}
+
+GimpValueArray *
+procedure_commands_get_item_args (GimpProcedure *procedure,
+ GimpImage *image,
+ GimpItem *item)
+{
+ GimpValueArray *args;
+ gint n_args = 0;
+
+ args = gimp_procedure_get_arguments (procedure);
+
+ /* initialize the first argument */
+ g_value_set_int (gimp_value_array_index (args, n_args),
+ GIMP_RUN_INTERACTIVE);
+ n_args++;
+
+ if (gimp_value_array_length (args) > n_args &&
+ GIMP_IS_PARAM_SPEC_IMAGE_ID (procedure->args[n_args]))
+ {
+ if (image)
+ {
+ gimp_value_set_image (gimp_value_array_index (args, n_args), image);
+ n_args++;
+
+ if (gimp_value_array_length (args) > n_args &&
+ GIMP_IS_PARAM_SPEC_ITEM_ID (procedure->args[n_args]))
+ {
+ if (item &&
+ g_type_is_a (G_TYPE_FROM_INSTANCE (item),
+ GIMP_PARAM_SPEC_ITEM_ID (procedure->args[n_args])->item_type))
+ {
+ gimp_value_set_item (gimp_value_array_index (args, n_args),
+ item);
+ n_args++;
+ }
+ else
+ {
+ g_warning ("Uh-oh, no active item for the plug-in!");
+ gimp_value_array_unref (args);
+ return NULL;
+ }
+ }
+ }
+ }
+
+ gimp_value_array_truncate (args, n_args);
+
+ return args;
+}
+
+GimpValueArray *
+procedure_commands_get_display_args (GimpProcedure *procedure,
+ GimpDisplay *display,
+ GimpObject *settings)
+{
+ GimpValueArray *args;
+ gint n_args = 0;
+
+ args = gimp_procedure_get_arguments (procedure);
+
+ /* initialize the first argument */
+ g_value_set_int (gimp_value_array_index (args, n_args),
+ GIMP_RUN_INTERACTIVE);
+ n_args++;
+
+ if (gimp_value_array_length (args) > n_args &&
+ GIMP_IS_PARAM_SPEC_DISPLAY_ID (procedure->args[n_args]))
+ {
+ if (display)
+ {
+ gimp_value_set_display (gimp_value_array_index (args, n_args),
+ GIMP_OBJECT (display));
+ n_args++;
+ }
+ else
+ {
+ g_warning ("Uh-oh, no active display for the plug-in!");
+ gimp_value_array_unref (args);
+ return NULL;
+ }
+ }
+
+ if (gimp_value_array_length (args) > n_args &&
+ GIMP_IS_PARAM_SPEC_IMAGE_ID (procedure->args[n_args]))
+ {
+ GimpImage *image = display ? gimp_display_get_image (display) : NULL;
+
+ if (image)
+ {
+ gimp_value_set_image (gimp_value_array_index (args, n_args), image);
+ n_args++;
+
+ if (gimp_value_array_length (args) > n_args &&
+ GIMP_IS_PARAM_SPEC_DRAWABLE_ID (procedure->args[n_args]))
+ {
+ GimpDrawable *drawable = gimp_image_get_active_drawable (image);
+
+ if (drawable)
+ {
+ gimp_value_set_drawable (gimp_value_array_index (args, n_args),
+ drawable);
+ n_args++;
+ }
+ else
+ {
+ g_warning ("Uh-oh, no active drawable for the plug-in!");
+ gimp_value_array_unref (args);
+ return NULL;
+ }
+ }
+ }
+ }
+
+ if (gimp_value_array_length (args) > n_args &&
+ g_type_is_a (G_PARAM_SPEC_VALUE_TYPE (procedure->args[n_args]),
+ GIMP_TYPE_OBJECT))
+ {
+ g_value_set_object (gimp_value_array_index (args, n_args), settings);
+ n_args++;
+ }
+
+ gimp_value_array_truncate (args, n_args);
+
+ return args;
+}
+
+gboolean
+procedure_commands_run_procedure (GimpProcedure *procedure,
+ Gimp *gimp,
+ GimpProgress *progress,
+ GimpValueArray *args)
+{
+ GimpValueArray *return_vals;
+ GError *error = NULL;
+
+ g_return_val_if_fail (GIMP_IS_PROCEDURE (procedure), FALSE);
+ g_return_val_if_fail (GIMP_IS_GIMP (gimp), FALSE);
+ g_return_val_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress), FALSE);
+ g_return_val_if_fail (args != NULL, FALSE);
+
+ g_value_set_int (gimp_value_array_index (args, 0), GIMP_RUN_NONINTERACTIVE);
+
+ return_vals = gimp_procedure_execute (procedure, gimp,
+ gimp_get_user_context (gimp),
+ progress, args,
+ &error);
+ gimp_value_array_unref (return_vals);
+
+ if (error)
+ {
+ gimp_message_literal (gimp,
+ G_OBJECT (progress), GIMP_MESSAGE_ERROR,
+ error->message);
+ g_clear_error (&error);
+
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+gboolean
+procedure_commands_run_procedure_async (GimpProcedure *procedure,
+ Gimp *gimp,
+ GimpProgress *progress,
+ GimpRunMode run_mode,
+ GimpValueArray *args,
+ GimpDisplay *display)
+{
+ GError *error = NULL;
+
+ g_return_val_if_fail (GIMP_IS_PROCEDURE (procedure), FALSE);
+ g_return_val_if_fail (GIMP_IS_GIMP (gimp), FALSE);
+ g_return_val_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress), FALSE);
+ g_return_val_if_fail (display == NULL || GIMP_IS_DISPLAY (display), FALSE);
+ g_return_val_if_fail (args != NULL, FALSE);
+
+ g_value_set_int (gimp_value_array_index (args, 0), run_mode);
+
+ gimp_procedure_execute_async (procedure, gimp,
+ gimp_get_user_context (gimp),
+ progress, args,
+ GIMP_OBJECT (display), &error);
+
+ if (error)
+ {
+ gimp_message_literal (gimp,
+ G_OBJECT (progress), GIMP_MESSAGE_ERROR,
+ error->message);
+ g_clear_error (&error);
+
+ return FALSE;
+ }
+
+ return TRUE;
+}
diff --git a/app/actions/procedure-commands.h b/app/actions/procedure-commands.h
new file mode 100644
index 0000000..13c1109
--- /dev/null
+++ b/app/actions/procedure-commands.h
@@ -0,0 +1,46 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __PROCEDURE_COMMANDS_H__
+#define __PROCEDURE_COMMANDS_H__
+
+
+GimpValueArray * procedure_commands_get_run_mode_arg (GimpProcedure *procedure);
+GimpValueArray * procedure_commands_get_data_args (GimpProcedure *procedure,
+ GimpObject *object);
+GimpValueArray * procedure_commands_get_image_args (GimpProcedure *procedure,
+ GimpImage *image);
+GimpValueArray * procedure_commands_get_item_args (GimpProcedure *procedure,
+ GimpImage *image,
+ GimpItem *item);
+GimpValueArray * procedure_commands_get_display_args (GimpProcedure *procedure,
+ GimpDisplay *display,
+ GimpObject *settings);
+
+gboolean procedure_commands_run_procedure (GimpProcedure *procedure,
+ Gimp *gimp,
+ GimpProgress *progress,
+ GimpValueArray *args);
+gboolean procedure_commands_run_procedure_async (GimpProcedure *procedure,
+ Gimp *gimp,
+ GimpProgress *progress,
+ GimpRunMode run_mode,
+ GimpValueArray *args,
+ GimpDisplay *display);
+
+
+#endif /* __PROCEDURE_COMMANDS_H__ */
diff --git a/app/actions/quick-mask-actions.c b/app/actions/quick-mask-actions.c
new file mode 100644
index 0000000..542d0f4
--- /dev/null
+++ b/app/actions/quick-mask-actions.c
@@ -0,0 +1,138 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "actions-types.h"
+
+#include "core/gimpimage.h"
+#include "core/gimpimage-quick-mask.h"
+
+#include "widgets/gimpactiongroup.h"
+#include "widgets/gimphelp-ids.h"
+
+#include "actions.h"
+#include "quick-mask-actions.h"
+#include "quick-mask-commands.h"
+
+#include "gimp-intl.h"
+
+
+static const GimpActionEntry quick_mask_actions[] =
+{
+ { "quick-mask-popup", NULL,
+ NC_("quick-mask-action", "Quick Mask Menu"), NULL, NULL, NULL,
+ GIMP_HELP_QUICK_MASK },
+
+ { "quick-mask-configure", NULL,
+ NC_("quick-mask-action", "_Configure Color and Opacity..."), NULL, NULL,
+ quick_mask_configure_cmd_callback,
+ GIMP_HELP_QUICK_MASK_EDIT }
+};
+
+static const GimpToggleActionEntry quick_mask_toggle_actions[] =
+{
+ { "quick-mask-toggle", GIMP_ICON_QUICK_MASK_ON,
+ NC_("quick-mask-action", "Toggle _Quick Mask"), "<shift>Q",
+ NC_("quick-mask-action", "Toggle Quick Mask on/off"),
+ quick_mask_toggle_cmd_callback,
+ FALSE,
+ GIMP_HELP_QUICK_MASK_TOGGLE }
+};
+
+static const GimpRadioActionEntry quick_mask_invert_actions[] =
+{
+ { "quick-mask-invert-on", NULL,
+ NC_("quick-mask-action", "Mask _Selected Areas"), NULL, NULL,
+ TRUE,
+ GIMP_HELP_QUICK_MASK_INVERT },
+
+ { "quick-mask-invert-off", NULL,
+ NC_("quick-mask-action", "Mask _Unselected Areas"), NULL, NULL,
+ FALSE,
+ GIMP_HELP_QUICK_MASK_INVERT }
+};
+
+
+void
+quick_mask_actions_setup (GimpActionGroup *group)
+{
+ gimp_action_group_add_actions (group, "quick-mask-action",
+ quick_mask_actions,
+ G_N_ELEMENTS (quick_mask_actions));
+
+ gimp_action_group_add_toggle_actions (group, "quick-mask-action",
+ quick_mask_toggle_actions,
+ G_N_ELEMENTS (quick_mask_toggle_actions));
+
+ gimp_action_group_add_radio_actions (group, "quick-mask-action",
+ quick_mask_invert_actions,
+ G_N_ELEMENTS (quick_mask_invert_actions),
+ NULL,
+ FALSE,
+ quick_mask_invert_cmd_callback);
+}
+
+void
+quick_mask_actions_update (GimpActionGroup *group,
+ gpointer data)
+{
+ GimpImage *image = action_data_get_image (data);
+ gboolean quick_mask_state = FALSE;
+ gboolean quick_mask_inverted = FALSE;
+ GimpRGB quick_mask_color;
+
+ if (image)
+ {
+ quick_mask_state = gimp_image_get_quick_mask_state (image);
+ quick_mask_inverted = gimp_image_get_quick_mask_inverted (image);
+
+ gimp_image_get_quick_mask_color (image, &quick_mask_color);
+ }
+
+#define SET_SENSITIVE(action,sensitive) \
+ gimp_action_group_set_action_sensitive (group, action, (sensitive) != 0)
+#define SET_ACTIVE(action,active) \
+ gimp_action_group_set_action_active (group, action, (active) != 0)
+#define SET_COLOR(action,color) \
+ gimp_action_group_set_action_color (group, action, (color), FALSE)
+
+ SET_SENSITIVE ("quick-mask-toggle", image);
+ SET_ACTIVE ("quick-mask-toggle", quick_mask_state);
+
+ SET_SENSITIVE ("quick-mask-invert-on", image);
+ SET_SENSITIVE ("quick-mask-invert-off", image);
+
+ if (quick_mask_inverted)
+ SET_ACTIVE ("quick-mask-invert-on", TRUE);
+ else
+ SET_ACTIVE ("quick-mask-invert-off", TRUE);
+
+ SET_SENSITIVE ("quick-mask-configure", image);
+
+ if (image)
+ SET_COLOR ("quick-mask-configure", &quick_mask_color);
+
+#undef SET_SENSITIVE
+#undef SET_ACTIVE
+#undef SET_COLOR
+}
diff --git a/app/actions/quick-mask-actions.h b/app/actions/quick-mask-actions.h
new file mode 100644
index 0000000..78ea13e
--- /dev/null
+++ b/app/actions/quick-mask-actions.h
@@ -0,0 +1,27 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __QUICK_MASK_ACTIONS_H__
+#define __QUICK_MASK_ACTIONS_H__
+
+
+void quick_mask_actions_setup (GimpActionGroup *group);
+void quick_mask_actions_update (GimpActionGroup *group,
+ gpointer data);
+
+
+#endif /* __QUICK_MASK_ACTIONS_H__ */
diff --git a/app/actions/quick-mask-commands.c b/app/actions/quick-mask-commands.c
new file mode 100644
index 0000000..3ea9d01
--- /dev/null
+++ b/app/actions/quick-mask-commands.c
@@ -0,0 +1,182 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpcolor/gimpcolor.h"
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "actions-types.h"
+
+#include "core/gimp.h"
+#include "core/gimpchannel.h"
+#include "core/gimpimage.h"
+#include "core/gimpimage-quick-mask.h"
+
+#include "widgets/gimphelp-ids.h"
+
+#include "dialogs/dialogs.h"
+#include "dialogs/channel-options-dialog.h"
+#include "dialogs/item-options-dialog.h"
+
+#include "actions.h"
+#include "quick-mask-commands.h"
+
+#include "gimp-intl.h"
+
+
+#define RGBA_EPSILON 1e-6
+
+
+/* local function prototypes */
+
+static void quick_mask_configure_callback (GtkWidget *dialog,
+ GimpImage *image,
+ GimpChannel *channel,
+ GimpContext *context,
+ const gchar *channel_name,
+ const GimpRGB *channel_color,
+ gboolean save_selection,
+ gboolean channel_visible,
+ gboolean channel_linked,
+ GimpColorTag channel_color_tag,
+ gboolean channel_lock_content,
+ gboolean channel_lock_position,
+ gpointer user_data);
+
+
+/* public functions */
+
+void
+quick_mask_toggle_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ gboolean active;
+ return_if_no_image (image, data);
+
+ active = g_variant_get_boolean (value);
+
+ if (active != gimp_image_get_quick_mask_state (image))
+ {
+ gimp_image_set_quick_mask_state (image, active);
+ gimp_image_flush (image);
+ }
+}
+
+void
+quick_mask_invert_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ gboolean inverted;
+ return_if_no_image (image, data);
+
+ inverted = (gboolean) g_variant_get_int32 (value);
+
+ if (inverted != gimp_image_get_quick_mask_inverted (image))
+ {
+ gimp_image_quick_mask_invert (image);
+ gimp_image_flush (image);
+ }
+}
+
+void
+quick_mask_configure_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GtkWidget *widget;
+ GtkWidget *dialog;
+ return_if_no_image (image, data);
+ return_if_no_widget (widget, data);
+
+#define CONFIGURE_DIALOG_KEY "gimp-image-quick-mask-configure-dialog"
+
+ dialog = dialogs_get_dialog (G_OBJECT (image), CONFIGURE_DIALOG_KEY);
+
+ if (! dialog)
+ {
+ GimpRGB color;
+
+ gimp_image_get_quick_mask_color (image, &color);
+
+ dialog = channel_options_dialog_new (image, NULL,
+ action_data_get_context (data),
+ widget,
+ _("Quick Mask Attributes"),
+ "gimp-quick-mask-edit",
+ GIMP_ICON_QUICK_MASK_ON,
+ _("Edit Quick Mask Attributes"),
+ GIMP_HELP_QUICK_MASK_EDIT,
+ _("Edit Quick Mask Color"),
+ _("_Mask opacity:"),
+ FALSE,
+ NULL,
+ &color,
+ FALSE,
+ FALSE,
+ GIMP_COLOR_TAG_NONE,
+ FALSE,
+ FALSE,
+ quick_mask_configure_callback,
+ NULL);
+
+ item_options_dialog_set_switches_visible (dialog, FALSE);
+
+ dialogs_attach_dialog (G_OBJECT (image), CONFIGURE_DIALOG_KEY, dialog);
+ }
+
+ gtk_window_present (GTK_WINDOW (dialog));
+}
+
+
+/* private functions */
+
+static void
+quick_mask_configure_callback (GtkWidget *dialog,
+ GimpImage *image,
+ GimpChannel *channel,
+ GimpContext *context,
+ const gchar *channel_name,
+ const GimpRGB *channel_color,
+ gboolean save_selection,
+ gboolean channel_visible,
+ gboolean channel_linked,
+ GimpColorTag channel_color_tag,
+ gboolean channel_lock_content,
+ gboolean channel_lock_position,
+ gpointer user_data)
+{
+ GimpRGB old_color;
+
+ gimp_image_get_quick_mask_color (image, &old_color);
+
+ if (gimp_rgba_distance (&old_color, channel_color) > RGBA_EPSILON)
+ {
+ gimp_image_set_quick_mask_color (image, channel_color);
+ gimp_image_flush (image);
+ }
+
+ gtk_widget_destroy (dialog);
+}
diff --git a/app/actions/quick-mask-commands.h b/app/actions/quick-mask-commands.h
new file mode 100644
index 0000000..1e8628c
--- /dev/null
+++ b/app/actions/quick-mask-commands.h
@@ -0,0 +1,33 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __QUICK_MASK_COMMANDS_H__
+#define __QUICK_MASK_COMMANDS_H__
+
+
+void quick_mask_toggle_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void quick_mask_invert_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void quick_mask_configure_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+
+#endif /* __QUICK_MASK_COMMANDS_H__ */
diff --git a/app/actions/sample-points-actions.c b/app/actions/sample-points-actions.c
new file mode 100644
index 0000000..60111c4
--- /dev/null
+++ b/app/actions/sample-points-actions.c
@@ -0,0 +1,81 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "actions-types.h"
+
+#include "widgets/gimpactiongroup.h"
+#include "widgets/gimphelp-ids.h"
+#include "widgets/gimpsamplepointeditor.h"
+
+#include "sample-points-actions.h"
+#include "sample-points-commands.h"
+
+#include "gimp-intl.h"
+
+
+static const GimpActionEntry sample_points_actions[] =
+{
+ { "sample-points-popup", GIMP_ICON_SAMPLE_POINT,
+ NC_("sample-points-action", "Sample Point Menu"), NULL, NULL, NULL,
+ GIMP_HELP_SAMPLE_POINT_DIALOG }
+};
+
+static const GimpToggleActionEntry sample_points_toggle_actions[] =
+{
+ { "sample-points-sample-merged", NULL,
+ NC_("sample-points-action", "_Sample Merged"), "",
+ NC_("sample-points-action",
+ "Use the composite color of all visible layers"),
+ sample_points_sample_merged_cmd_callback,
+ TRUE,
+ GIMP_HELP_SAMPLE_POINT_SAMPLE_MERGED }
+};
+
+
+void
+sample_points_actions_setup (GimpActionGroup *group)
+{
+ gimp_action_group_add_actions (group, "sample-points-action",
+ sample_points_actions,
+ G_N_ELEMENTS (sample_points_actions));
+
+ gimp_action_group_add_toggle_actions (group, "sample-points-action",
+ sample_points_toggle_actions,
+ G_N_ELEMENTS (sample_points_toggle_actions));
+}
+
+void
+sample_points_actions_update (GimpActionGroup *group,
+ gpointer data)
+{
+ GimpSamplePointEditor *editor = GIMP_SAMPLE_POINT_EDITOR (data);
+
+#define SET_ACTIVE(action,condition) \
+ gimp_action_group_set_action_active (group, action, (condition) != 0)
+
+ SET_ACTIVE ("sample-points-sample-merged",
+ gimp_sample_point_editor_get_sample_merged (editor));
+
+#undef SET_ACTIVE
+}
diff --git a/app/actions/sample-points-actions.h b/app/actions/sample-points-actions.h
new file mode 100644
index 0000000..47b40fb
--- /dev/null
+++ b/app/actions/sample-points-actions.h
@@ -0,0 +1,27 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __SAMPLE_POINTS_ACIONS_H__
+#define __SAMPLE_POINTS_ACIONS_H__
+
+
+void sample_points_actions_setup (GimpActionGroup *group);
+void sample_points_actions_update (GimpActionGroup *group,
+ gpointer data);
+
+
+#endif /* __SAMPLE_POINTS_ACTIONS_H__ */
diff --git a/app/actions/sample-points-commands.c b/app/actions/sample-points-commands.c
new file mode 100644
index 0000000..c943c6d
--- /dev/null
+++ b/app/actions/sample-points-commands.c
@@ -0,0 +1,41 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "actions-types.h"
+
+#include "widgets/gimpsamplepointeditor.h"
+
+#include "sample-points-commands.h"
+
+
+/* public functions */
+
+void
+sample_points_sample_merged_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpSamplePointEditor *editor = GIMP_SAMPLE_POINT_EDITOR (data);
+ gboolean active = g_variant_get_boolean (value);
+
+ gimp_sample_point_editor_set_sample_merged (editor, active);
+}
diff --git a/app/actions/sample-points-commands.h b/app/actions/sample-points-commands.h
new file mode 100644
index 0000000..bfdd4ef
--- /dev/null
+++ b/app/actions/sample-points-commands.h
@@ -0,0 +1,27 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __SAMPLE_POINTS_COMMANDS_H__
+#define __SAMPLE_POINTS_COMMANDS_H__
+
+
+void sample_points_sample_merged_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+
+#endif /* __SAMPLE_POINTS_COMMANDS_H__ */
diff --git a/app/actions/select-actions.c b/app/actions/select-actions.c
new file mode 100644
index 0000000..294b077
--- /dev/null
+++ b/app/actions/select-actions.c
@@ -0,0 +1,199 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "actions-types.h"
+
+#include "core/gimp.h"
+#include "core/gimpchannel.h"
+#include "core/gimpimage.h"
+
+#include "widgets/gimpactiongroup.h"
+#include "widgets/gimphelp-ids.h"
+
+#include "actions.h"
+#include "select-actions.h"
+#include "select-commands.h"
+
+#include "gimp-intl.h"
+
+
+static const GimpActionEntry select_actions[] =
+{
+ { "selection-popup", GIMP_ICON_SELECTION,
+ NC_("select-action", "Selection Editor Menu"), NULL, NULL, NULL,
+ GIMP_HELP_SELECTION_DIALOG },
+
+ { "select-menu", NULL, NC_("select-action", "_Select") },
+
+ { "select-all", GIMP_ICON_SELECTION_ALL,
+ NC_("select-action", "_All"), "<primary>A",
+ NC_("select-action", "Select everything"),
+ select_all_cmd_callback,
+ GIMP_HELP_SELECTION_ALL },
+
+ { "select-none", GIMP_ICON_SELECTION_NONE,
+ NC_("select-action", "_None"), "<primary><shift>A",
+ NC_("select-action", "Dismiss the selection"),
+ select_none_cmd_callback,
+ GIMP_HELP_SELECTION_NONE },
+
+ { "select-invert", GIMP_ICON_INVERT,
+ NC_("select-action", "_Invert"), "<primary>I",
+ NC_("select-action", "Invert the selection"),
+ select_invert_cmd_callback,
+ GIMP_HELP_SELECTION_INVERT },
+
+ { "select-float", GIMP_ICON_LAYER_FLOATING_SELECTION,
+ NC_("select-action", "_Float"), "<primary><shift>L",
+ NC_("select-action", "Create a floating selection"),
+ select_float_cmd_callback,
+ GIMP_HELP_SELECTION_FLOAT },
+
+ { "select-feather", NULL,
+ NC_("select-action", "Fea_ther..."), NULL,
+ NC_("select-action",
+ "Blur the selection border so that it fades out smoothly"),
+ select_feather_cmd_callback,
+ GIMP_HELP_SELECTION_FEATHER },
+
+ { "select-sharpen", NULL,
+ NC_("select-action", "_Sharpen"), NULL,
+ NC_("select-action", "Remove fuzziness from the selection"),
+ select_sharpen_cmd_callback,
+ GIMP_HELP_SELECTION_SHARPEN },
+
+ { "select-shrink", GIMP_ICON_SELECTION_SHRINK,
+ NC_("select-action", "S_hrink..."), NULL,
+ NC_("select-action", "Contract the selection"),
+ select_shrink_cmd_callback,
+ GIMP_HELP_SELECTION_SHRINK },
+
+ { "select-grow", GIMP_ICON_SELECTION_GROW,
+ NC_("select-action", "_Grow..."), NULL,
+ NC_("select-action", "Enlarge the selection"),
+ select_grow_cmd_callback,
+ GIMP_HELP_SELECTION_GROW },
+
+ { "select-border", GIMP_ICON_SELECTION_BORDER,
+ NC_("select-action", "Bo_rder..."), NULL,
+ NC_("select-action", "Replace the selection by its border"),
+ select_border_cmd_callback,
+ GIMP_HELP_SELECTION_BORDER },
+
+ { "select-flood", NULL,
+ NC_("select-action", "Re_move Holes"), NULL,
+ NC_("select-action", "Remove holes from the selection"),
+ select_flood_cmd_callback,
+ GIMP_HELP_SELECTION_FLOOD },
+
+ { "select-save", GIMP_ICON_SELECTION_TO_CHANNEL,
+ NC_("select-action", "Save to _Channel"), NULL,
+ NC_("select-action", "Save the selection to a channel"),
+ select_save_cmd_callback,
+ GIMP_HELP_SELECTION_TO_CHANNEL },
+
+ { "select-fill", GIMP_ICON_TOOL_BUCKET_FILL,
+ NC_("select-action", "_Fill Selection Outline..."), NULL,
+ NC_("select-action", "Fill the selection outline"),
+ select_fill_cmd_callback,
+ GIMP_HELP_SELECTION_FILL },
+
+ { "select-fill-last-values", GIMP_ICON_TOOL_BUCKET_FILL,
+ NC_("select-action", "_Fill Selection Outline"), NULL,
+ NC_("select-action", "Fill the selection outline with last used values"),
+ select_fill_last_vals_cmd_callback,
+ GIMP_HELP_SELECTION_FILL },
+
+ { "select-stroke", GIMP_ICON_SELECTION_STROKE,
+ NC_("select-action", "_Stroke Selection..."), NULL,
+ NC_("select-action", "Paint along the selection outline"),
+ select_stroke_cmd_callback,
+ GIMP_HELP_SELECTION_STROKE },
+
+ { "select-stroke-last-values", GIMP_ICON_SELECTION_STROKE,
+ NC_("select-action", "_Stroke Selection"), NULL,
+ NC_("select-action", "Stroke the selection with last used values"),
+ select_stroke_last_vals_cmd_callback,
+ GIMP_HELP_SELECTION_STROKE }
+};
+
+
+void
+select_actions_setup (GimpActionGroup *group)
+{
+ gimp_action_group_add_actions (group, "select-action",
+ select_actions,
+ G_N_ELEMENTS (select_actions));
+}
+
+void
+select_actions_update (GimpActionGroup *group,
+ gpointer data)
+{
+ GimpImage *image = action_data_get_image (data);
+ GimpDrawable *drawable = NULL;
+ gboolean fs = FALSE;
+ gboolean sel = FALSE;
+ gboolean writable = FALSE;
+ gboolean children = FALSE;
+
+ if (image)
+ {
+ drawable = gimp_image_get_active_drawable (image);
+
+ if (drawable)
+ {
+ writable = ! gimp_item_is_content_locked (GIMP_ITEM (drawable));
+
+ if (gimp_viewable_get_children (GIMP_VIEWABLE (drawable)))
+ children = TRUE;
+ }
+
+ fs = (gimp_image_get_floating_selection (image) != NULL);
+ sel = ! gimp_channel_is_empty (gimp_image_get_mask (image));
+ }
+
+#define SET_SENSITIVE(action,condition) \
+ gimp_action_group_set_action_sensitive (group, action, (condition) != 0)
+
+ SET_SENSITIVE ("select-all", drawable);
+ SET_SENSITIVE ("select-none", drawable && sel);
+ SET_SENSITIVE ("select-invert", drawable);
+ SET_SENSITIVE ("select-float", writable && !children && sel);
+
+ SET_SENSITIVE ("select-feather", drawable && sel);
+ SET_SENSITIVE ("select-sharpen", drawable && sel);
+ SET_SENSITIVE ("select-shrink", drawable && sel);
+ SET_SENSITIVE ("select-grow", drawable && sel);
+ SET_SENSITIVE ("select-border", drawable && sel);
+ 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);
+
+#undef SET_SENSITIVE
+}
diff --git a/app/actions/select-actions.h b/app/actions/select-actions.h
new file mode 100644
index 0000000..250d2e1
--- /dev/null
+++ b/app/actions/select-actions.h
@@ -0,0 +1,27 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __SELECT_ACTIONS_H__
+#define __SELECT_ACTIONS_H__
+
+
+void select_actions_setup (GimpActionGroup *group);
+void select_actions_update (GimpActionGroup *group,
+ gpointer data);
+
+
+#endif /* __SELECT_ACTIONS_H__ */
diff --git a/app/actions/select-commands.c b/app/actions/select-commands.c
new file mode 100644
index 0000000..687872b
--- /dev/null
+++ b/app/actions/select-commands.c
@@ -0,0 +1,685 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpmath/gimpmath.h"
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "actions-types.h"
+
+#include "config/gimpdialogconfig.h"
+
+#include "core/gimp.h"
+#include "core/gimpchannel.h"
+#include "core/gimpimage.h"
+#include "core/gimpselection.h"
+
+#include "widgets/gimphelp-ids.h"
+#include "widgets/gimpdialogfactory.h"
+#include "widgets/gimpwidgets-utils.h"
+#include "widgets/gimpwindowstrategy.h"
+
+#include "display/gimpdisplay.h"
+#include "display/gimpdisplayshell.h"
+
+#include "dialogs/dialogs.h"
+
+#include "actions.h"
+#include "items-commands.h"
+#include "select-commands.h"
+
+#include "gimp-intl.h"
+
+
+/* local function prototypes */
+
+static void select_feather_callback (GtkWidget *widget,
+ gdouble size,
+ GimpUnit unit,
+ gpointer data);
+static void select_border_callback (GtkWidget *widget,
+ gdouble size,
+ GimpUnit unit,
+ gpointer data);
+static void select_grow_callback (GtkWidget *widget,
+ gdouble size,
+ GimpUnit unit,
+ gpointer data);
+static void select_shrink_callback (GtkWidget *widget,
+ gdouble size,
+ GimpUnit unit,
+ gpointer data);
+
+
+/* public functions */
+
+void
+select_all_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ return_if_no_image (image, data);
+
+ gimp_channel_all (gimp_image_get_mask (image), TRUE);
+ gimp_image_flush (image);
+}
+
+void
+select_none_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ return_if_no_image (image, data);
+
+ gimp_channel_clear (gimp_image_get_mask (image), NULL, TRUE);
+ gimp_image_flush (image);
+}
+
+void
+select_invert_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ return_if_no_image (image, data);
+
+ gimp_channel_invert (gimp_image_get_mask (image), TRUE);
+ gimp_image_flush (image);
+}
+
+void
+select_float_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GtkWidget *widget;
+ GError *error = NULL;
+ return_if_no_image (image, data);
+ return_if_no_widget (widget, data);
+
+ if (gimp_selection_float (GIMP_SELECTION (gimp_image_get_mask (image)),
+ gimp_image_get_active_drawable (image),
+ action_data_get_context (data),
+ TRUE, 0, 0, &error))
+ {
+ gimp_image_flush (image);
+ }
+ else
+ {
+ gimp_message_literal (image->gimp,
+ G_OBJECT (widget), GIMP_MESSAGE_WARNING,
+ error->message);
+ g_clear_error (&error);
+ }
+}
+
+void
+select_feather_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpDisplay *display;
+ GimpImage *image;
+ GtkWidget *dialog;
+ return_if_no_display (display, data);
+
+ image = gimp_display_get_image (display);
+
+#define FEATHER_DIALOG_KEY "gimp-selection-feather-dialog"
+
+ dialog = dialogs_get_dialog (G_OBJECT (image), FEATHER_DIALOG_KEY);
+
+ if (! dialog)
+ {
+ GimpDialogConfig *config = GIMP_DIALOG_CONFIG (image->gimp->config);
+ GtkWidget *button;
+ gdouble xres;
+ gdouble yres;
+
+ gimp_image_get_resolution (image, &xres, &yres);
+
+ dialog = gimp_query_size_box (_("Feather Selection"),
+ GTK_WIDGET (gimp_display_get_shell (display)),
+ gimp_standard_help_func,
+ GIMP_HELP_SELECTION_FEATHER,
+ _("Feather selection by"),
+ config->selection_feather_radius, 0, 32767, 3,
+ gimp_display_get_shell (display)->unit,
+ MIN (xres, yres),
+ FALSE,
+ G_OBJECT (image), "disconnect",
+ select_feather_callback, image);
+
+ /* Edge lock button */
+ button = gtk_check_button_new_with_mnemonic (_("_Selected areas continue outside the image"));
+ g_object_set_data (G_OBJECT (dialog), "edge-lock-toggle", button);
+ gimp_help_set_help_data (button,
+ _("When feathering, act as if selected areas "
+ "continued outside the image."),
+ NULL);
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button),
+ config->selection_feather_edge_lock);
+ gtk_box_pack_start (GTK_BOX (GIMP_QUERY_BOX_VBOX (dialog)), button,
+ FALSE, FALSE, 0);
+ gtk_widget_show (button);
+
+ dialogs_attach_dialog (G_OBJECT (image), FEATHER_DIALOG_KEY, dialog);
+ }
+
+ gtk_window_present (GTK_WINDOW (dialog));
+}
+
+void
+select_sharpen_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ return_if_no_image (image, data);
+
+ gimp_channel_sharpen (gimp_image_get_mask (image), TRUE);
+ gimp_image_flush (image);
+}
+
+void
+select_shrink_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpDisplay *display;
+ GimpImage *image;
+ GtkWidget *dialog;
+ return_if_no_display (display, data);
+
+ image = gimp_display_get_image (display);
+
+#define SHRINK_DIALOG_KEY "gimp-selection-shrink-dialog"
+
+ dialog = dialogs_get_dialog (G_OBJECT (image), SHRINK_DIALOG_KEY);
+
+ if (! dialog)
+ {
+ GimpDialogConfig *config = GIMP_DIALOG_CONFIG (image->gimp->config);
+ GtkWidget *button;
+ gint width;
+ gint height;
+ gint max_value;
+ gdouble xres;
+ gdouble yres;
+
+ gimp_item_bounds (GIMP_ITEM (gimp_image_get_mask (image)),
+ NULL, NULL, &width, &height);
+ max_value = MIN (width, height) / 2;
+
+ gimp_image_get_resolution (image, &xres, &yres);
+
+ dialog = gimp_query_size_box (_("Shrink Selection"),
+ GTK_WIDGET (gimp_display_get_shell (display)),
+ gimp_standard_help_func,
+ GIMP_HELP_SELECTION_SHRINK,
+ _("Shrink selection by"),
+ config->selection_shrink_radius,
+ 1, max_value, 0,
+ gimp_display_get_shell (display)->unit,
+ MIN (xres, yres),
+ FALSE,
+ G_OBJECT (image), "disconnect",
+ select_shrink_callback, image);
+
+ /* Edge lock button */
+ button = gtk_check_button_new_with_mnemonic (_("_Selected areas continue outside the image"));
+ g_object_set_data (G_OBJECT (dialog), "edge-lock-toggle", button);
+ gimp_help_set_help_data (button,
+ _("When shrinking, act as if selected areas "
+ "continued outside the image."),
+ NULL);
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button),
+ config->selection_shrink_edge_lock);
+ gtk_box_pack_start (GTK_BOX (GIMP_QUERY_BOX_VBOX (dialog)), button,
+ FALSE, FALSE, 0);
+ gtk_widget_show (button);
+
+ dialogs_attach_dialog (G_OBJECT (image), SHRINK_DIALOG_KEY, dialog);
+ }
+
+ gtk_window_present (GTK_WINDOW (dialog));
+}
+
+void
+select_grow_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpDisplay *display;
+ GimpImage *image;
+ GtkWidget *dialog;
+ return_if_no_display (display, data);
+
+ image = gimp_display_get_image (display);
+
+#define GROW_DIALOG_KEY "gimp-selection-grow-dialog"
+
+ dialog = dialogs_get_dialog (G_OBJECT (image), GROW_DIALOG_KEY);
+
+ if (! dialog)
+ {
+ GimpDialogConfig *config = GIMP_DIALOG_CONFIG (image->gimp->config);
+ gint width;
+ gint height;
+ gint max_value;
+ gdouble xres;
+ gdouble yres;
+
+ width = gimp_image_get_width (image);
+ height = gimp_image_get_height (image);
+ max_value = MAX (width, height);
+
+ gimp_image_get_resolution (image, &xres, &yres);
+
+ dialog = gimp_query_size_box (_("Grow Selection"),
+ GTK_WIDGET (gimp_display_get_shell (display)),
+ gimp_standard_help_func,
+ GIMP_HELP_SELECTION_GROW,
+ _("Grow selection by"),
+ config->selection_grow_radius,
+ 1, max_value, 0,
+ gimp_display_get_shell (display)->unit,
+ MIN (xres, yres),
+ FALSE,
+ G_OBJECT (image), "disconnect",
+ select_grow_callback, image);
+
+ dialogs_attach_dialog (G_OBJECT (image), GROW_DIALOG_KEY, dialog);
+ }
+
+ gtk_window_present (GTK_WINDOW (dialog));
+}
+
+void
+select_border_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpDisplay *display;
+ GimpImage *image;
+ GtkWidget *dialog;
+ return_if_no_display (display, data);
+
+ image = gimp_display_get_image (display);
+
+#define BORDER_DIALOG_KEY "gimp-selection-border-dialog"
+
+ dialog = dialogs_get_dialog (G_OBJECT (image), BORDER_DIALOG_KEY);
+
+ if (! dialog)
+ {
+ GimpDialogConfig *config = GIMP_DIALOG_CONFIG (image->gimp->config);
+ GtkWidget *combo;
+ GtkWidget *button;
+ gint width;
+ gint height;
+ gint max_value;
+ gdouble xres;
+ gdouble yres;
+
+ gimp_item_bounds (GIMP_ITEM (gimp_image_get_mask (image)),
+ NULL, NULL, &width, &height);
+ max_value = MIN (width, height) / 2;
+
+ gimp_image_get_resolution (image, &xres, &yres);
+
+ dialog = gimp_query_size_box (_("Border Selection"),
+ GTK_WIDGET (gimp_display_get_shell (display)),
+ gimp_standard_help_func,
+ GIMP_HELP_SELECTION_BORDER,
+ _("Border selection by"),
+ config->selection_border_radius,
+ 1, max_value, 0,
+ gimp_display_get_shell (display)->unit,
+ MIN (xres, yres),
+ FALSE,
+ G_OBJECT (image), "disconnect",
+ select_border_callback, image);
+
+ /* Border style combo */
+ combo = gimp_enum_combo_box_new (GIMP_TYPE_CHANNEL_BORDER_STYLE);
+ gimp_int_combo_box_set_label (GIMP_INT_COMBO_BOX (combo),
+ _("Border style"));
+
+ gtk_box_pack_start (GTK_BOX (GIMP_QUERY_BOX_VBOX (dialog)), combo,
+ FALSE, FALSE, 0);
+
+ g_object_set_data (G_OBJECT (dialog), "border-style-combo", combo);
+ gimp_int_combo_box_set_active (GIMP_INT_COMBO_BOX (combo),
+ config->selection_border_style);
+ gtk_widget_show (combo);
+
+ /* Edge lock button */
+ button = gtk_check_button_new_with_mnemonic (_("_Selected areas continue outside the image"));
+ g_object_set_data (G_OBJECT (dialog), "edge-lock-toggle", button);
+ gimp_help_set_help_data (button,
+ _("When bordering, act as if selected areas "
+ "continued outside the image."),
+ NULL);
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button),
+ config->selection_border_edge_lock);
+ gtk_box_pack_start (GTK_BOX (GIMP_QUERY_BOX_VBOX (dialog)), button,
+ FALSE, FALSE, 0);
+ gtk_widget_show (button);
+
+ dialogs_attach_dialog (G_OBJECT (image), BORDER_DIALOG_KEY, dialog);
+ }
+
+ gtk_window_present (GTK_WINDOW (dialog));
+}
+
+void
+select_flood_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ return_if_no_image (image, data);
+
+ gimp_channel_flood (gimp_image_get_mask (image), TRUE);
+ gimp_image_flush (image);
+}
+
+void
+select_save_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpChannel *channel;
+ GtkWidget *widget;
+ return_if_no_image (image, data);
+ return_if_no_widget (widget, data);
+
+ channel = GIMP_CHANNEL (gimp_item_duplicate (GIMP_ITEM (gimp_image_get_mask (image)),
+ GIMP_TYPE_CHANNEL));
+
+ /* saved selections are not visible by default */
+ gimp_item_set_visible (GIMP_ITEM (channel), FALSE, FALSE);
+
+ gimp_image_add_channel (image, channel,
+ GIMP_IMAGE_ACTIVE_PARENT, -1, TRUE);
+ gimp_image_flush (image);
+
+ gimp_window_strategy_show_dockable_dialog (GIMP_WINDOW_STRATEGY (gimp_get_window_strategy (image->gimp)),
+ image->gimp,
+ gimp_dialog_factory_get_singleton (),
+ gtk_widget_get_screen (widget),
+ gimp_widget_get_monitor (widget),
+ "gimp-channel-list");
+}
+
+void
+select_fill_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ return_if_no_image (image, data);
+
+ items_fill_cmd_callback (action,
+ image, GIMP_ITEM (gimp_image_get_mask (image)),
+ "gimp-selection-fill-dialog",
+ _("Fill Selection Outline"),
+ GIMP_ICON_TOOL_BUCKET_FILL,
+ GIMP_HELP_SELECTION_FILL,
+ data);
+}
+
+void
+select_fill_last_vals_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ return_if_no_image (image, data);
+
+ items_fill_last_vals_cmd_callback (action,
+ image,
+ GIMP_ITEM (gimp_image_get_mask (image)),
+ data);
+}
+
+void
+select_stroke_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ return_if_no_image (image, data);
+
+ items_stroke_cmd_callback (action,
+ image, GIMP_ITEM (gimp_image_get_mask (image)),
+ "gimp-selection-stroke-dialog",
+ _("Stroke Selection"),
+ GIMP_ICON_SELECTION_STROKE,
+ GIMP_HELP_SELECTION_STROKE,
+ data);
+}
+
+void
+select_stroke_last_vals_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ return_if_no_image (image, data);
+
+ items_stroke_last_vals_cmd_callback (action,
+ image,
+ GIMP_ITEM (gimp_image_get_mask (image)),
+ data);
+}
+
+
+/* private functions */
+
+static void
+select_feather_callback (GtkWidget *widget,
+ gdouble size,
+ GimpUnit unit,
+ gpointer data)
+{
+ GimpImage *image = GIMP_IMAGE (data);
+ GimpDialogConfig *config = GIMP_DIALOG_CONFIG (image->gimp->config);
+ GtkWidget *button;
+ gdouble radius_x;
+ gdouble radius_y;
+
+ button = g_object_get_data (G_OBJECT (widget), "edge-lock-toggle");
+
+ g_object_set (config,
+ "selection-feather-radius", size,
+ "selection-feather-edge-lock",
+ gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)),
+ NULL);
+
+ radius_x = config->selection_feather_radius;
+ radius_y = config->selection_feather_radius;
+
+ if (unit != GIMP_UNIT_PIXEL)
+ {
+ gdouble xres;
+ gdouble yres;
+ gdouble factor;
+
+ gimp_image_get_resolution (image, &xres, &yres);
+
+ factor = (MAX (xres, yres) /
+ MIN (xres, yres));
+
+ if (xres == MIN (xres, yres))
+ radius_y *= factor;
+ else
+ radius_x *= factor;
+ }
+
+ gimp_channel_feather (gimp_image_get_mask (image), radius_x, radius_y,
+ config->selection_feather_edge_lock,
+ TRUE);
+ gimp_image_flush (image);
+}
+
+static void
+select_border_callback (GtkWidget *widget,
+ gdouble size,
+ GimpUnit unit,
+ gpointer data)
+{
+ GimpImage *image = GIMP_IMAGE (data);
+ GimpDialogConfig *config = GIMP_DIALOG_CONFIG (image->gimp->config);
+ GtkWidget *combo;
+ GtkWidget *button;
+ gdouble radius_x;
+ gdouble radius_y;
+ gint border_style;
+
+ combo = g_object_get_data (G_OBJECT (widget), "border-style-combo");
+ button = g_object_get_data (G_OBJECT (widget), "edge-lock-toggle");
+
+ gimp_int_combo_box_get_active (GIMP_INT_COMBO_BOX (combo), &border_style);
+
+ g_object_set (config,
+ "selection-border-radius", size,
+ "selection-border-style", border_style,
+ "selection-border-edge-lock",
+ gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)),
+ NULL);
+
+ radius_x = ROUND (config->selection_border_radius);
+ radius_y = ROUND (config->selection_border_radius);
+
+ if (unit != GIMP_UNIT_PIXEL)
+ {
+ gdouble xres;
+ gdouble yres;
+ gdouble factor;
+
+ gimp_image_get_resolution (image, &xres, &yres);
+
+ factor = (MAX (xres, yres) /
+ MIN (xres, yres));
+
+ if (xres == MIN (xres, yres))
+ radius_y *= factor;
+ else
+ radius_x *= factor;
+ }
+
+ gimp_channel_border (gimp_image_get_mask (image), radius_x, radius_y,
+ config->selection_border_style,
+ config->selection_border_edge_lock,
+ TRUE);
+ gimp_image_flush (image);
+}
+
+static void
+select_grow_callback (GtkWidget *widget,
+ gdouble size,
+ GimpUnit unit,
+ gpointer data)
+{
+ GimpImage *image = GIMP_IMAGE (data);
+ GimpDialogConfig *config = GIMP_DIALOG_CONFIG (image->gimp->config);
+ gdouble radius_x;
+ gdouble radius_y;
+
+ g_object_set (config,
+ "selection-grow-radius", size,
+ NULL);
+
+ radius_x = ROUND (config->selection_grow_radius);
+ radius_y = ROUND (config->selection_grow_radius);
+
+ if (unit != GIMP_UNIT_PIXEL)
+ {
+ gdouble xres;
+ gdouble yres;
+ gdouble factor;
+
+ gimp_image_get_resolution (image, &xres, &yres);
+
+ factor = (MAX (xres, yres) /
+ MIN (xres, yres));
+
+ if (xres == MIN (xres, yres))
+ radius_y *= factor;
+ else
+ radius_x *= factor;
+ }
+
+ gimp_channel_grow (gimp_image_get_mask (image), radius_x, radius_y, TRUE);
+ gimp_image_flush (image);
+}
+
+static void
+select_shrink_callback (GtkWidget *widget,
+ gdouble size,
+ GimpUnit unit,
+ gpointer data)
+{
+ GimpImage *image = GIMP_IMAGE (data);
+ GimpDialogConfig *config = GIMP_DIALOG_CONFIG (image->gimp->config);
+ GtkWidget *button;
+ gint radius_x;
+ gint radius_y;
+
+ button = g_object_get_data (G_OBJECT (widget), "edge-lock-toggle");
+
+ g_object_set (config,
+ "selection-shrink-radius", size,
+ "selection-shrink-edge-lock",
+ gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)),
+ NULL);
+
+ radius_x = ROUND (config->selection_shrink_radius);
+ radius_y = ROUND (config->selection_shrink_radius);
+
+ if (unit != GIMP_UNIT_PIXEL)
+ {
+ gdouble xres;
+ gdouble yres;
+ gdouble factor;
+
+ gimp_image_get_resolution (image, &xres, &yres);
+
+ factor = (MAX (xres, yres) /
+ MIN (xres, yres));
+
+ if (xres == MIN (xres, yres))
+ radius_y *= factor;
+ else
+ radius_x *= factor;
+ }
+
+ gimp_channel_shrink (gimp_image_get_mask (image), radius_x, radius_y,
+ config->selection_shrink_edge_lock,
+ TRUE);
+ gimp_image_flush (image);
+}
diff --git a/app/actions/select-commands.h b/app/actions/select-commands.h
new file mode 100644
index 0000000..e6d2a30
--- /dev/null
+++ b/app/actions/select-commands.h
@@ -0,0 +1,70 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __SELECT_COMMANDS_H__
+#define __SELECT_COMMANDS_H__
+
+
+void select_all_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void select_none_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void select_invert_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void select_float_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void select_feather_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void select_sharpen_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void select_shrink_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void select_grow_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void select_border_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void select_flood_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void select_save_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+void select_fill_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void select_fill_last_vals_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void select_stroke_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void select_stroke_last_vals_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+
+#endif /* __SELECT_COMMANDS_H__ */
diff --git a/app/actions/templates-actions.c b/app/actions/templates-actions.c
new file mode 100644
index 0000000..e3a59ad
--- /dev/null
+++ b/app/actions/templates-actions.c
@@ -0,0 +1,105 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "actions-types.h"
+
+#include "core/gimpcontext.h"
+
+#include "widgets/gimpactiongroup.h"
+#include "widgets/gimphelp-ids.h"
+
+#include "actions.h"
+#include "templates-actions.h"
+#include "templates-commands.h"
+
+#include "gimp-intl.h"
+
+
+static const GimpActionEntry templates_actions[] =
+{
+ { "templates-popup", GIMP_ICON_TEMPLATE,
+ NC_("templates-action", "Templates Menu"), NULL, NULL, NULL,
+ GIMP_HELP_TEMPLATE_DIALOG },
+
+ { "templates-create-image", GIMP_ICON_IMAGE,
+ NC_("templates-action", "_Create Image from Template"), "",
+ NC_("templates-action", "Create a new image from the selected template"),
+ templates_create_image_cmd_callback,
+ GIMP_HELP_TEMPLATE_IMAGE_NEW },
+
+ { "templates-new", GIMP_ICON_DOCUMENT_NEW,
+ NC_("templates-action", "_New Template..."), NULL,
+ NC_("templates-action", "Create a new template"),
+ templates_new_cmd_callback,
+ GIMP_HELP_TEMPLATE_NEW },
+
+ { "templates-duplicate", GIMP_ICON_OBJECT_DUPLICATE,
+ NC_("templates-action", "D_uplicate Template..."), "",
+ NC_("templates-action", "Duplicate this template"),
+ templates_duplicate_cmd_callback,
+ GIMP_HELP_TEMPLATE_DUPLICATE },
+
+ { "templates-edit", GIMP_ICON_EDIT,
+ NC_("templates-action", "_Edit Template..."), NULL,
+ NC_("templates-action", "Edit this template"),
+ templates_edit_cmd_callback,
+ GIMP_HELP_TEMPLATE_EDIT },
+
+ { "templates-delete", GIMP_ICON_EDIT_DELETE,
+ NC_("templates-action", "_Delete Template"), NULL,
+ NC_("templates-action", "Delete this template"),
+ templates_delete_cmd_callback,
+ GIMP_HELP_TEMPLATE_DELETE }
+};
+
+
+void
+templates_actions_setup (GimpActionGroup *group)
+{
+ gimp_action_group_add_actions (group, "templates-action",
+ templates_actions,
+ G_N_ELEMENTS (templates_actions));
+}
+
+void
+templates_actions_update (GimpActionGroup *group,
+ gpointer data)
+{
+ GimpContext *context = action_data_get_context (data);
+ GimpTemplate *template = NULL;
+
+ if (context)
+ template = gimp_context_get_template (context);
+
+#define SET_SENSITIVE(action,condition) \
+ gimp_action_group_set_action_sensitive (group, action, (condition) != 0)
+
+ SET_SENSITIVE ("templates-create-image", template);
+ SET_SENSITIVE ("templates-new", context);
+ SET_SENSITIVE ("templates-duplicate", template);
+ SET_SENSITIVE ("templates-edit", template);
+ SET_SENSITIVE ("templates-delete", template);
+
+#undef SET_SENSITIVE
+}
diff --git a/app/actions/templates-actions.h b/app/actions/templates-actions.h
new file mode 100644
index 0000000..904a40d
--- /dev/null
+++ b/app/actions/templates-actions.h
@@ -0,0 +1,27 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __TEMPLATES_ACTIONS_H__
+#define __TEMPLATES_ACTIONS_H__
+
+
+void templates_actions_setup (GimpActionGroup *group);
+void templates_actions_update (GimpActionGroup *group,
+ gpointer data);
+
+
+#endif /* __TEMPLATES_COMMANDS_H__ */
diff --git a/app/actions/templates-commands.c b/app/actions/templates-commands.c
new file mode 100644
index 0000000..6039de0
--- /dev/null
+++ b/app/actions/templates-commands.c
@@ -0,0 +1,345 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpconfig/gimpconfig.h"
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "actions-types.h"
+
+#include "config/gimpcoreconfig.h"
+
+#include "core/gimp.h"
+#include "core/gimpcontainer.h"
+#include "core/gimpcontext.h"
+#include "core/gimpimage-new.h"
+#include "core/gimptemplate.h"
+
+#include "widgets/gimpcontainerview.h"
+#include "widgets/gimpdialogfactory.h"
+#include "widgets/gimphelp-ids.h"
+#include "widgets/gimpmessagebox.h"
+#include "widgets/gimpmessagedialog.h"
+#include "widgets/gimptemplateeditor.h"
+#include "widgets/gimptemplateview.h"
+#include "widgets/gimpwidgets-utils.h"
+
+#include "dialogs/dialogs.h"
+#include "dialogs/template-options-dialog.h"
+
+#include "actions.h"
+#include "templates-commands.h"
+
+#include "gimp-intl.h"
+
+
+typedef struct
+{
+ GimpContext *context;
+ GimpContainer *container;
+ GimpTemplate *template;
+} TemplateDeleteData;
+
+
+/* local function prototypes */
+
+static void templates_new_callback (GtkWidget *dialog,
+ GimpTemplate *template,
+ GimpTemplate *edit_template,
+ GimpContext *context,
+ gpointer user_data);
+static void templates_edit_callback (GtkWidget *dialog,
+ GimpTemplate *template,
+ GimpTemplate *edit_template,
+ GimpContext *context,
+ gpointer user_data);
+static void templates_delete_response (GtkWidget *dialog,
+ gint response_id,
+ TemplateDeleteData *delete_data);
+static void templates_delete_data_free (TemplateDeleteData *delete_data);
+
+
+/* public functions */
+
+void
+templates_create_image_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ Gimp *gimp;
+ GimpContainerEditor *editor = GIMP_CONTAINER_EDITOR (data);
+ GimpContainer *container;
+ GimpContext *context;
+ GimpTemplate *template;
+ return_if_no_gimp (gimp, data);
+
+ container = gimp_container_view_get_container (editor->view);
+ context = gimp_container_view_get_context (editor->view);
+
+ template = gimp_context_get_template (context);
+
+ if (template && gimp_container_have (container, GIMP_OBJECT (template)))
+ {
+ GtkWidget *widget = GTK_WIDGET (editor);
+ GimpImage *image;
+
+ image = gimp_image_new_from_template (gimp, template, context);
+ gimp_create_display (gimp, image, gimp_template_get_unit (template), 1.0,
+ G_OBJECT (gtk_widget_get_screen (widget)),
+ gimp_widget_get_monitor (widget));
+ g_object_unref (image);
+
+ gimp_image_new_set_last_template (gimp, template);
+ }
+}
+
+void
+templates_new_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpContainerEditor *editor = GIMP_CONTAINER_EDITOR (data);
+ GimpContext *context;
+ GtkWidget *dialog;
+
+ context = gimp_container_view_get_context (editor->view);
+
+#define NEW_DIALOG_KEY "gimp-template-new-dialog"
+
+ dialog = dialogs_get_dialog (G_OBJECT (context->gimp), NEW_DIALOG_KEY);
+
+ if (! dialog)
+ {
+ dialog = template_options_dialog_new (NULL, context,
+ GTK_WIDGET (editor),
+ _("New Template"),
+ "gimp-template-new",
+ GIMP_ICON_TEMPLATE,
+ _("Create a New Template"),
+ GIMP_HELP_TEMPLATE_NEW,
+ templates_new_callback,
+ NULL);
+
+ dialogs_attach_dialog (G_OBJECT (context->gimp), NEW_DIALOG_KEY, dialog);
+ }
+
+ gtk_window_present (GTK_WINDOW (dialog));
+}
+
+void
+templates_duplicate_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpContainerEditor *editor = GIMP_CONTAINER_EDITOR (data);
+ GimpContainer *container;
+ GimpContext *context;
+ GimpTemplate *template;
+
+ container = gimp_container_view_get_container (editor->view);
+ context = gimp_container_view_get_context (editor->view);
+
+ template = gimp_context_get_template (context);
+
+ if (template && gimp_container_have (container, GIMP_OBJECT (template)))
+ {
+ GimpTemplate *new_template;
+
+ new_template = gimp_config_duplicate (GIMP_CONFIG (template));
+
+ gimp_container_add (container, GIMP_OBJECT (new_template));
+ gimp_context_set_by_type (context,
+ gimp_container_get_children_type (container),
+ GIMP_OBJECT (new_template));
+ g_object_unref (new_template);
+
+ templates_edit_cmd_callback (action, value, data);
+ }
+}
+
+void
+templates_edit_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpContainerEditor *editor = GIMP_CONTAINER_EDITOR (data);
+ GimpContainer *container;
+ GimpContext *context;
+ GimpTemplate *template;
+
+ container = gimp_container_view_get_container (editor->view);
+ context = gimp_container_view_get_context (editor->view);
+
+ template = gimp_context_get_template (context);
+
+ if (template && gimp_container_have (container, GIMP_OBJECT (template)))
+ {
+ GtkWidget *dialog;
+
+#define EDIT_DIALOG_KEY "gimp-template-edit-dialog"
+
+ dialog = dialogs_get_dialog (G_OBJECT (template), EDIT_DIALOG_KEY);
+
+ if (! dialog)
+ {
+ dialog = template_options_dialog_new (template, context,
+ GTK_WIDGET (editor),
+ _("Edit Template"),
+ "gimp-template-edit",
+ GIMP_ICON_EDIT,
+ _("Edit Template"),
+ GIMP_HELP_TEMPLATE_EDIT,
+ templates_edit_callback,
+ NULL);
+
+ dialogs_attach_dialog (G_OBJECT (template), EDIT_DIALOG_KEY, dialog);
+ }
+
+ gtk_window_present (GTK_WINDOW (dialog));
+ }
+}
+
+void
+templates_delete_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpContainerEditor *editor = GIMP_CONTAINER_EDITOR (data);
+ GimpContainer *container;
+ GimpContext *context;
+ GimpTemplate *template;
+
+ container = gimp_container_view_get_container (editor->view);
+ context = gimp_container_view_get_context (editor->view);
+
+ template = gimp_context_get_template (context);
+
+ if (template && gimp_container_have (container, GIMP_OBJECT (template)))
+ {
+ TemplateDeleteData *delete_data = g_slice_new (TemplateDeleteData);
+ GtkWidget *dialog;
+
+ delete_data->context = context;
+ delete_data->container = container;
+ delete_data->template = template;
+
+ dialog =
+ gimp_message_dialog_new (_("Delete Template"), "edit-delete",
+ GTK_WIDGET (editor), 0,
+ gimp_standard_help_func, NULL,
+
+ _("_Cancel"), GTK_RESPONSE_CANCEL,
+ _("_Delete"), GTK_RESPONSE_OK,
+
+ NULL);
+
+ gtk_dialog_set_alternative_button_order (GTK_DIALOG (dialog),
+ GTK_RESPONSE_OK,
+ GTK_RESPONSE_CANCEL,
+ -1);
+
+ g_object_weak_ref (G_OBJECT (dialog),
+ (GWeakNotify) templates_delete_data_free, delete_data);
+
+ g_signal_connect_object (template, "disconnect",
+ G_CALLBACK (gtk_widget_destroy),
+ dialog, G_CONNECT_SWAPPED);
+
+ g_signal_connect (dialog, "response",
+ G_CALLBACK (templates_delete_response),
+ delete_data);
+
+ gimp_message_box_set_primary_text (GIMP_MESSAGE_DIALOG (dialog)->box,
+ _("Are you sure you want to delete "
+ "template '%s' from the list and "
+ "from disk?"),
+ gimp_object_get_name (template));
+ gtk_widget_show (dialog);
+ }
+}
+
+
+/* private functions */
+
+static void
+templates_new_callback (GtkWidget *dialog,
+ GimpTemplate *template,
+ GimpTemplate *edit_template,
+ GimpContext *context,
+ gpointer user_data)
+{
+ gimp_container_add (context->gimp->templates, GIMP_OBJECT (edit_template));
+ gimp_context_set_template (gimp_get_user_context (context->gimp),
+ edit_template);
+
+ gtk_widget_destroy (dialog);
+}
+
+static void
+templates_edit_callback (GtkWidget *dialog,
+ GimpTemplate *template,
+ GimpTemplate *edit_template,
+ GimpContext *context,
+ gpointer user_data)
+{
+ gimp_config_sync (G_OBJECT (edit_template),
+ G_OBJECT (template), 0);
+
+ gtk_widget_destroy (dialog);
+}
+
+static void
+templates_delete_response (GtkWidget *dialog,
+ gint response_id,
+ TemplateDeleteData *delete_data)
+{
+ if (response_id == GTK_RESPONSE_OK)
+ {
+ GimpObject *new_active = NULL;
+
+ if (delete_data->template ==
+ gimp_context_get_template (delete_data->context))
+ {
+ new_active = gimp_container_get_neighbor_of (delete_data->container,
+ GIMP_OBJECT (delete_data->template));
+ }
+
+ if (gimp_container_have (delete_data->container,
+ GIMP_OBJECT (delete_data->template)))
+ {
+ if (new_active)
+ gimp_context_set_by_type (delete_data->context,
+ gimp_container_get_children_type (delete_data->container),
+ new_active);
+
+ gimp_container_remove (delete_data->container,
+ GIMP_OBJECT (delete_data->template));
+ }
+ }
+
+ gtk_widget_destroy (dialog);
+}
+
+static void
+templates_delete_data_free (TemplateDeleteData *delete_data)
+{
+ g_slice_free (TemplateDeleteData, delete_data);
+}
diff --git a/app/actions/templates-commands.h b/app/actions/templates-commands.h
new file mode 100644
index 0000000..91356f2
--- /dev/null
+++ b/app/actions/templates-commands.h
@@ -0,0 +1,39 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __TEMPLATES_COMMANDS_H__
+#define __TEMPLATES_COMMANDS_H__
+
+
+void templates_create_image_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void templates_new_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void templates_duplicate_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void templates_edit_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void templates_delete_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+
+#endif /* __TEMPLATES_COMMANDS_H__ */
diff --git a/app/actions/text-editor-actions.c b/app/actions/text-editor-actions.c
new file mode 100644
index 0000000..5a31220
--- /dev/null
+++ b/app/actions/text-editor-actions.c
@@ -0,0 +1,148 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "actions-types.h"
+
+#include "widgets/gimpactiongroup.h"
+#include "widgets/gimptexteditor.h"
+#include "widgets/gimphelp-ids.h"
+
+#include "text-editor-actions.h"
+#include "text-editor-commands.h"
+
+#include "gimp-intl.h"
+
+
+static const GimpActionEntry text_editor_actions[] =
+{
+ { "text-editor-toolbar", GIMP_ICON_EDIT,
+ "Text Editor Toolbar", NULL, NULL, NULL,
+ GIMP_HELP_TEXT_EDITOR_DIALOG },
+
+ { "text-editor-load", GIMP_ICON_DOCUMENT_OPEN,
+ NC_("text-editor-action", "Open"), NULL,
+ NC_("text-editor-action", "Load text from file"),
+ text_editor_load_cmd_callback,
+ NULL },
+
+ { "text-editor-clear", GIMP_ICON_EDIT_CLEAR,
+ NC_("text-editor-action", "Clear"), NULL,
+ NC_("text-editor-action", "Clear all text"),
+ text_editor_clear_cmd_callback,
+ NULL }
+};
+
+static const GimpRadioActionEntry text_editor_direction_actions[] =
+{
+ { "text-editor-direction-ltr", GIMP_ICON_FORMAT_TEXT_DIRECTION_LTR,
+ NC_("text-editor-action", "LTR"), NULL,
+ NC_("text-editor-action", "From left to right"),
+ GIMP_TEXT_DIRECTION_LTR,
+ NULL },
+
+ { "text-editor-direction-rtl", GIMP_ICON_FORMAT_TEXT_DIRECTION_RTL,
+ NC_("text-editor-action", "RTL"), NULL,
+ NC_("text-editor-action", "From right to left"),
+ GIMP_TEXT_DIRECTION_RTL,
+ NULL },
+
+ { "text-editor-direction-ttb-rtl", GIMP_ICON_FORMAT_TEXT_DIRECTION_TTB_RTL,
+ NC_("text-editor-action", "TTB-RTL"), NULL,
+ NC_("text-editor-action", "Vertical, right to left (mixed orientation)"),
+ GIMP_TEXT_DIRECTION_TTB_RTL,
+ NULL },
+
+ { "text-editor-direction-ttb-rtl-upright", GIMP_ICON_FORMAT_TEXT_DIRECTION_TTB_RTL_UPRIGHT,
+ NC_("text-editor-action", "TTB-RTL-UPRIGHT"), NULL,
+ NC_("text-editor-action", "Vertical, right to left (upright orientation)"),
+ GIMP_TEXT_DIRECTION_TTB_RTL_UPRIGHT,
+ NULL },
+
+ { "text-editor-direction-ttb-ltr", GIMP_ICON_FORMAT_TEXT_DIRECTION_TTB_LTR,
+ NC_("text-editor-action", "TTB-LTR"), NULL,
+ NC_("text-editor-action", "Vertical, left to right (mixed orientation)"),
+ GIMP_TEXT_DIRECTION_TTB_LTR,
+ NULL },
+
+ { "text-editor-direction-ttb-ltr-upright", GIMP_ICON_FORMAT_TEXT_DIRECTION_TTB_LTR_UPRIGHT,
+ NC_("text-editor-action", "TTB-LTR-UPRIGHT"), NULL,
+ NC_("text-editor-action", "Vertical, left to right (upright orientation)"),
+ GIMP_TEXT_DIRECTION_TTB_LTR_UPRIGHT,
+ NULL },
+};
+
+
+void
+text_editor_actions_setup (GimpActionGroup *group)
+{
+ gimp_action_group_add_actions (group, "text-editor-action",
+ text_editor_actions,
+ G_N_ELEMENTS (text_editor_actions));
+
+ gimp_action_group_add_radio_actions (group, "text-editor-action",
+ text_editor_direction_actions,
+ G_N_ELEMENTS (text_editor_direction_actions),
+ NULL,
+ GIMP_TEXT_DIRECTION_LTR,
+ text_editor_direction_cmd_callback);
+}
+
+void
+text_editor_actions_update (GimpActionGroup *group,
+ gpointer data)
+{
+ GimpTextEditor *editor = GIMP_TEXT_EDITOR (data);
+
+#define SET_ACTIVE(action,condition) \
+ gimp_action_group_set_action_active (group, action, (condition) != 0)
+
+ switch (editor->base_dir)
+ {
+ case GIMP_TEXT_DIRECTION_LTR:
+ SET_ACTIVE ("text-editor-direction-ltr", TRUE);
+ break;
+
+ case GIMP_TEXT_DIRECTION_RTL:
+ SET_ACTIVE ("text-editor-direction-rtl", TRUE);
+ break;
+
+ case GIMP_TEXT_DIRECTION_TTB_RTL:
+ SET_ACTIVE ("text-editor-direction-ttb-rtl", TRUE);
+ break;
+
+ case GIMP_TEXT_DIRECTION_TTB_RTL_UPRIGHT:
+ SET_ACTIVE ("text-editor-direction-ttb-rtl-upright", TRUE);
+ break;
+
+ case GIMP_TEXT_DIRECTION_TTB_LTR:
+ SET_ACTIVE ("text-editor-direction-ttb-ltr", TRUE);
+ break;
+
+ case GIMP_TEXT_DIRECTION_TTB_LTR_UPRIGHT:
+ SET_ACTIVE ("text-editor-direction-ttb-ltr-upright", TRUE);
+ break;
+ }
+
+#undef SET_ACTIVE
+}
diff --git a/app/actions/text-editor-actions.h b/app/actions/text-editor-actions.h
new file mode 100644
index 0000000..a2940b7
--- /dev/null
+++ b/app/actions/text-editor-actions.h
@@ -0,0 +1,27 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __TEXT_EDITOR_ACIONS_H__
+#define __TEXT_EDITOR_ACIONS_H__
+
+
+void text_editor_actions_setup (GimpActionGroup *group);
+void text_editor_actions_update (GimpActionGroup *group,
+ gpointer data);
+
+
+#endif /* __TEXT_EDITOR_ACTIONS_H__ */
diff --git a/app/actions/text-editor-commands.c b/app/actions/text-editor-commands.c
new file mode 100644
index 0000000..3a7764d
--- /dev/null
+++ b/app/actions/text-editor-commands.c
@@ -0,0 +1,153 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpbase/gimpbase.h"
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "actions-types.h"
+
+#include "core/gimp.h"
+
+#include "widgets/gimphelp-ids.h"
+#include "widgets/gimptextbuffer.h"
+#include "widgets/gimptexteditor.h"
+#include "widgets/gimpuimanager.h"
+
+#include "text-editor-commands.h"
+
+#include "gimp-intl.h"
+
+
+/* local function prototypes */
+
+static void text_editor_load_response (GtkWidget *dialog,
+ gint response_id,
+ GimpTextEditor *editor);
+
+
+/* public functions */
+
+void
+text_editor_load_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpTextEditor *editor = GIMP_TEXT_EDITOR (data);
+
+ if (! editor->file_dialog)
+ {
+ GtkWidget *dialog;
+
+ dialog = editor->file_dialog =
+ gtk_file_chooser_dialog_new (_("Open Text File (UTF-8)"),
+ GTK_WINDOW (editor),
+ GTK_FILE_CHOOSER_ACTION_OPEN,
+
+ _("_Cancel"), GTK_RESPONSE_CANCEL,
+ _("_Open"), GTK_RESPONSE_OK,
+
+ NULL);
+
+ gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
+ gtk_dialog_set_alternative_button_order (GTK_DIALOG (dialog),
+ GTK_RESPONSE_OK,
+ GTK_RESPONSE_CANCEL,
+ -1);
+
+ gtk_window_set_role (GTK_WINDOW (dialog), "gimp-text-load-file");
+ gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE);
+ gtk_window_set_destroy_with_parent (GTK_WINDOW (dialog), TRUE);
+
+ g_object_add_weak_pointer (G_OBJECT (dialog),
+ (gpointer) &editor->file_dialog);
+
+ g_signal_connect (dialog, "response",
+ G_CALLBACK (text_editor_load_response),
+ editor);
+ g_signal_connect (dialog, "delete-event",
+ G_CALLBACK (gtk_true),
+ NULL);
+ }
+
+ gtk_window_present (GTK_WINDOW (editor->file_dialog));
+}
+
+void
+text_editor_clear_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpTextEditor *editor = GIMP_TEXT_EDITOR (data);
+ GtkTextBuffer *buffer;
+
+ buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (editor->view));
+
+ gtk_text_buffer_set_text (buffer, "", 0);
+}
+
+void
+text_editor_direction_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpTextEditor *editor = GIMP_TEXT_EDITOR (data);
+ GimpTextDirection direction;
+
+ direction = (GimpTextDirection) g_variant_get_int32 (value);
+
+ gimp_text_editor_set_direction (editor, direction);
+}
+
+
+/* private functions */
+
+static void
+text_editor_load_response (GtkWidget *dialog,
+ gint response_id,
+ GimpTextEditor *editor)
+{
+ if (response_id == GTK_RESPONSE_OK)
+ {
+ GtkTextBuffer *buffer;
+ GFile *file;
+ GError *error = NULL;
+
+ buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (editor->view));
+ file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog));
+
+ if (! gimp_text_buffer_load (GIMP_TEXT_BUFFER (buffer), file, &error))
+ {
+ gimp_message (editor->ui_manager->gimp, G_OBJECT (dialog),
+ GIMP_MESSAGE_ERROR,
+ _("Could not open '%s' for reading: %s"),
+ gimp_file_get_utf8_name (file),
+ error->message);
+ g_clear_error (&error);
+ g_object_unref (file);
+ return;
+ }
+
+ g_object_unref (file);
+ }
+
+ gtk_widget_hide (dialog);
+}
diff --git a/app/actions/text-editor-commands.h b/app/actions/text-editor-commands.h
new file mode 100644
index 0000000..1ea89d0
--- /dev/null
+++ b/app/actions/text-editor-commands.h
@@ -0,0 +1,33 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __TEXT_EDITOR_COMMANDS_H__
+#define __TEXT_EDITOR_COMMANDS_H__
+
+
+void text_editor_load_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void text_editor_clear_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void text_editor_direction_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+
+#endif /* __TEXT_EDITOR_COMMANDS_H__ */
diff --git a/app/actions/text-tool-actions.c b/app/actions/text-tool-actions.c
new file mode 100644
index 0000000..1692253
--- /dev/null
+++ b/app/actions/text-tool-actions.c
@@ -0,0 +1,229 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "actions-types.h"
+
+#include "core/gimpimage.h"
+
+#include "text/gimptextlayer.h"
+
+#include "widgets/gimpactiongroup.h"
+#include "widgets/gimptexteditor.h"
+#include "widgets/gimphelp-ids.h"
+
+#include "display/gimpdisplay.h"
+#include "display/gimpdisplayshell.h"
+
+#include "tools/gimptool.h"
+#include "tools/gimptexttool.h"
+
+#include "text-tool-actions.h"
+#include "text-tool-commands.h"
+
+#include "gimp-intl.h"
+
+
+static const GimpActionEntry text_tool_actions[] =
+{
+ { "text-tool-popup", NULL,
+ NC_("text-tool-action", "Text Tool Menu"), NULL, NULL, NULL,
+ NULL },
+
+ { "text-tool-input-methods-menu", NULL,
+ NC_("text-tool-action", "Input _Methods"), NULL, NULL, NULL,
+ NULL },
+
+ { "text-tool-cut", GIMP_ICON_EDIT_CUT,
+ NC_("text-tool-action", "Cu_t"), NULL, "<primary>X",
+ text_tool_cut_cmd_callback,
+ NULL },
+
+ { "text-tool-copy", GIMP_ICON_EDIT_COPY,
+ NC_("text-tool-action", "_Copy"), NULL, "<primary>C",
+ text_tool_copy_cmd_callback,
+ NULL },
+
+ { "text-tool-paste", GIMP_ICON_EDIT_PASTE,
+ NC_("text-tool-action", "_Paste"), NULL, "<primary>V",
+ text_tool_paste_cmd_callback,
+ NULL },
+
+ { "text-tool-delete", GIMP_ICON_EDIT_DELETE,
+ NC_("text-tool-action", "_Delete"), NULL, NULL,
+ text_tool_delete_cmd_callback,
+ NULL },
+
+ { "text-tool-load", GIMP_ICON_DOCUMENT_OPEN,
+ NC_("text-tool-action", "_Open text file..."), NULL, NULL,
+ text_tool_load_cmd_callback,
+ NULL },
+
+ { "text-tool-clear", GIMP_ICON_EDIT_CLEAR,
+ NC_("text-tool-action", "Cl_ear"), NULL,
+ NC_("text-tool-action", "Clear all text"),
+ text_tool_clear_cmd_callback,
+ NULL },
+
+ { "text-tool-text-to-path", GIMP_ICON_PATH,
+ NC_("text-tool-action", "_Path from Text"), "",
+ NC_("text-tool-action",
+ "Create a path from the outlines of the current text"),
+ text_tool_text_to_path_cmd_callback,
+ NULL },
+
+ { "text-tool-text-along-path", GIMP_ICON_PATH,
+ NC_("text-tool-action", "Text _along Path"), "",
+ NC_("text-tool-action",
+ "Bend the text along the currently active path"),
+ text_tool_text_along_path_cmd_callback,
+ NULL }
+};
+
+static const GimpRadioActionEntry text_tool_direction_actions[] =
+{
+ { "text-tool-direction-ltr", GIMP_ICON_FORMAT_TEXT_DIRECTION_LTR,
+ NC_("text-tool-action", "From left to right"), NULL, NULL,
+ GIMP_TEXT_DIRECTION_LTR,
+ NULL },
+
+ { "text-tool-direction-rtl", GIMP_ICON_FORMAT_TEXT_DIRECTION_RTL,
+ NC_("text-tool-action", "From right to left"), NULL, NULL,
+ GIMP_TEXT_DIRECTION_RTL,
+ NULL },
+
+ { "text-tool-direction-ttb-rtl", GIMP_ICON_FORMAT_TEXT_DIRECTION_TTB_RTL,
+ NC_("text-tool-action", "Vertical, right to left (mixed orientation)"), NULL, NULL,
+ GIMP_TEXT_DIRECTION_TTB_RTL,
+ NULL },
+
+ { "text-tool-direction-ttb-rtl-upright", GIMP_ICON_FORMAT_TEXT_DIRECTION_TTB_RTL_UPRIGHT,
+ NC_("text-tool-action", "Vertical, right to left (upright orientation)"), NULL, NULL,
+ GIMP_TEXT_DIRECTION_TTB_RTL_UPRIGHT,
+ NULL },
+
+ { "text-tool-direction-ttb-ltr", GIMP_ICON_FORMAT_TEXT_DIRECTION_TTB_LTR,
+ NC_("text-tool-action", "Vertical, left to right (mixed orientation)"), NULL, NULL,
+ GIMP_TEXT_DIRECTION_TTB_LTR,
+ NULL },
+
+ { "text-tool-direction-ttb-ltr-upright", GIMP_ICON_FORMAT_TEXT_DIRECTION_TTB_LTR_UPRIGHT,
+ NC_("text-tool-action", "Vertical, left to right (upright orientation)"), NULL, NULL,
+ GIMP_TEXT_DIRECTION_TTB_LTR_UPRIGHT,
+ NULL }
+};
+
+
+#define SET_HIDE_EMPTY(action,condition) \
+ gimp_action_group_set_action_hide_empty (group, action, (condition) != 0)
+
+void
+text_tool_actions_setup (GimpActionGroup *group)
+{
+ gimp_action_group_add_actions (group, "text-tool-action",
+ text_tool_actions,
+ G_N_ELEMENTS (text_tool_actions));
+
+ gimp_action_group_add_radio_actions (group, "text-tool-action",
+ text_tool_direction_actions,
+ G_N_ELEMENTS (text_tool_direction_actions),
+ NULL,
+ GIMP_TEXT_DIRECTION_LTR,
+ text_tool_direction_cmd_callback);
+
+ SET_HIDE_EMPTY ("text-tool-input-methods-menu", FALSE);
+}
+
+/* The following code is written on the assumption that this is for a
+ * context menu, activated by right-clicking in a text layer.
+ * Therefore, the tool must have a display. If for any reason the
+ * code is adapted to a different situation, some existence testing
+ * will need to be added.
+ */
+void
+text_tool_actions_update (GimpActionGroup *group,
+ gpointer data)
+{
+ GimpTextTool *text_tool = GIMP_TEXT_TOOL (data);
+ GimpDisplay *display = GIMP_TOOL (text_tool)->display;
+ GimpImage *image = gimp_display_get_image (display);
+ GimpLayer *layer;
+ GimpVectors *vectors;
+ GimpDisplayShell *shell;
+ GtkClipboard *clipboard;
+ gboolean text_layer = FALSE;
+ gboolean text_sel = FALSE; /* some text is selected */
+ gboolean clip = FALSE; /* clipboard has text available */
+ gboolean input_method_menu;
+ gboolean unicode_menu;
+ GimpTextDirection direction;
+ gint i;
+
+ layer = gimp_image_get_active_layer (image);
+
+ if (layer)
+ text_layer = gimp_item_is_text_layer (GIMP_ITEM (layer));
+
+ vectors = gimp_image_get_active_vectors (image);
+
+ text_sel = gimp_text_tool_get_has_text_selection (text_tool);
+
+ /* see whether there is text available for pasting */
+ shell = gimp_display_get_shell (display);
+ clipboard = gtk_widget_get_clipboard (shell->canvas,
+ GDK_SELECTION_CLIPBOARD);
+ clip = gtk_clipboard_wait_is_text_available (clipboard);
+
+ g_object_get (gtk_widget_get_settings (shell->canvas),
+ "gtk-show-input-method-menu", &input_method_menu,
+ "gtk-show-unicode-menu", &unicode_menu,
+ NULL);
+
+#define SET_VISIBLE(action,condition) \
+ gimp_action_group_set_action_visible (group, action, (condition) != 0)
+#define SET_SENSITIVE(action,condition) \
+ gimp_action_group_set_action_sensitive (group, action, (condition) != 0)
+#define SET_ACTIVE(action,condition) \
+ gimp_action_group_set_action_active (group, action, (condition) != 0)
+
+ SET_SENSITIVE ("text-tool-cut", text_sel);
+ SET_SENSITIVE ("text-tool-copy", text_sel);
+ SET_SENSITIVE ("text-tool-paste", clip);
+ SET_SENSITIVE ("text-tool-delete", text_sel);
+ SET_SENSITIVE ("text-tool-clear", text_layer);
+ SET_SENSITIVE ("text-tool-load", image);
+ SET_SENSITIVE ("text-tool-text-to-path", text_layer);
+ SET_SENSITIVE ("text-tool-text-along-path", text_layer && vectors);
+
+ direction = gimp_text_tool_get_direction (text_tool);
+ for (i = 0; i < G_N_ELEMENTS (text_tool_direction_actions); i++)
+ {
+ if (direction == text_tool_direction_actions[i].value)
+ {
+ SET_ACTIVE (text_tool_direction_actions[i].name, TRUE);
+ break;
+ }
+ }
+
+ SET_VISIBLE ("text-tool-input-methods-menu", input_method_menu);
+}
diff --git a/app/actions/text-tool-actions.h b/app/actions/text-tool-actions.h
new file mode 100644
index 0000000..5efca91
--- /dev/null
+++ b/app/actions/text-tool-actions.h
@@ -0,0 +1,27 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __TEXT_TOOL_ACTIONS_H__
+#define __TEXT_TOOL_ACTIONS_H__
+
+
+void text_tool_actions_setup (GimpActionGroup *group);
+void text_tool_actions_update (GimpActionGroup *group,
+ gpointer data);
+
+
+#endif /* __TEXT_TOOL_ACTIONS_H__ */
diff --git a/app/actions/text-tool-commands.c b/app/actions/text-tool-commands.c
new file mode 100644
index 0000000..296bbf3
--- /dev/null
+++ b/app/actions/text-tool-commands.c
@@ -0,0 +1,229 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpbase/gimpbase.h"
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "actions-types.h"
+
+#include "core/gimp.h"
+#include "core/gimptoolinfo.h"
+
+#include "widgets/gimphelp-ids.h"
+#include "widgets/gimptextbuffer.h"
+#include "widgets/gimpuimanager.h"
+#include "widgets/gimpwidgets-utils.h"
+
+#include "display/gimpdisplay.h"
+
+#include "tools/gimptexttool.h"
+
+#include "dialogs/dialogs.h"
+
+#include "text-tool-commands.h"
+
+#include "gimp-intl.h"
+
+
+/* local function prototypes */
+
+static void text_tool_load_dialog_response (GtkWidget *dialog,
+ gint response_id,
+ GimpTextTool *tool);
+
+
+/* public functions */
+
+void
+text_tool_cut_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpTextTool *text_tool = GIMP_TEXT_TOOL (data);
+
+ gimp_text_tool_cut_clipboard (text_tool);
+}
+
+void
+text_tool_copy_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpTextTool *text_tool = GIMP_TEXT_TOOL (data);
+
+ gimp_text_tool_copy_clipboard (text_tool);
+}
+
+void
+text_tool_paste_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpTextTool *text_tool = GIMP_TEXT_TOOL (data);
+
+ gimp_text_tool_paste_clipboard (text_tool);
+}
+
+void
+text_tool_delete_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpTextTool *text_tool = GIMP_TEXT_TOOL (data);
+
+ gimp_text_tool_delete_selection (text_tool);
+}
+
+void
+text_tool_load_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpTextTool *text_tool = GIMP_TEXT_TOOL (data);
+ GtkWidget *dialog;
+
+ dialog = dialogs_get_dialog (G_OBJECT (text_tool), "gimp-text-file-dialog");
+
+ if (! dialog)
+ {
+ GtkWidget *parent = NULL;
+
+ if (GIMP_TOOL (text_tool)->display)
+ {
+ GimpDisplayShell *shell;
+
+ shell = gimp_display_get_shell (GIMP_TOOL (text_tool)->display);
+
+ parent = gtk_widget_get_toplevel (GTK_WIDGET (shell));
+ }
+
+ dialog = gtk_file_chooser_dialog_new (_("Open Text File (UTF-8)"),
+ parent ? GTK_WINDOW (parent) : NULL,
+ GTK_FILE_CHOOSER_ACTION_OPEN,
+
+ _("_Cancel"), GTK_RESPONSE_CANCEL,
+ _("_Open"), GTK_RESPONSE_OK,
+
+ NULL);
+
+ gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
+ gtk_dialog_set_alternative_button_order (GTK_DIALOG (dialog),
+ GTK_RESPONSE_OK,
+ GTK_RESPONSE_CANCEL,
+ -1);
+
+ gtk_window_set_role (GTK_WINDOW (dialog), "gimp-text-load-file");
+ gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE);
+
+ g_signal_connect (dialog, "response",
+ G_CALLBACK (text_tool_load_dialog_response),
+ text_tool);
+ g_signal_connect (dialog, "delete-event",
+ G_CALLBACK (gtk_true),
+ NULL);
+
+ dialogs_attach_dialog (G_OBJECT (text_tool),
+ "gimp-text-file-dialog", dialog);
+ }
+
+ gtk_window_present (GTK_WINDOW (dialog));
+}
+
+void
+text_tool_clear_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpTextTool *text_tool = GIMP_TEXT_TOOL (data);
+ GtkTextBuffer *buffer = GTK_TEXT_BUFFER (text_tool->buffer);
+ GtkTextIter start, end;
+
+ gtk_text_buffer_get_bounds (buffer, &start, &end);
+ gtk_text_buffer_select_range (buffer, &start, &end);
+ gimp_text_tool_delete_selection (text_tool);
+}
+
+void
+text_tool_text_to_path_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpTextTool *text_tool = GIMP_TEXT_TOOL (data);
+
+ gimp_text_tool_create_vectors (text_tool);
+}
+
+void
+text_tool_text_along_path_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpTextTool *text_tool = GIMP_TEXT_TOOL (data);
+
+ gimp_text_tool_create_vectors_warped (text_tool);
+}
+
+void
+text_tool_direction_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpTextTool *text_tool = GIMP_TEXT_TOOL (data);
+ GimpTextDirection direction;
+
+ direction = (GimpTextDirection) g_variant_get_int32 (value);
+
+ g_object_set (text_tool->proxy,
+ "base-direction", direction,
+ NULL);
+}
+
+
+/* private functions */
+
+static void
+text_tool_load_dialog_response (GtkWidget *dialog,
+ gint response_id,
+ GimpTextTool *tool)
+{
+ if (response_id == GTK_RESPONSE_OK)
+ {
+ GFile *file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog));
+ GError *error = NULL;
+
+ if (! gimp_text_buffer_load (tool->buffer, file, &error))
+ {
+ gimp_message (GIMP_TOOL (tool)->tool_info->gimp, G_OBJECT (dialog),
+ GIMP_MESSAGE_ERROR,
+ _("Could not open '%s' for reading: %s"),
+ gimp_file_get_utf8_name (file),
+ error->message);
+ g_clear_error (&error);
+ g_object_unref (file);
+ return;
+ }
+
+ g_object_unref (file);
+ }
+
+ gtk_widget_hide (dialog);
+}
diff --git a/app/actions/text-tool-commands.h b/app/actions/text-tool-commands.h
new file mode 100644
index 0000000..d7bef1c
--- /dev/null
+++ b/app/actions/text-tool-commands.h
@@ -0,0 +1,51 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __TEXT_TOOL_COMMANDS_H__
+#define __TEXT_TOOL_COMMANDS_H__
+
+
+void text_tool_cut_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void text_tool_copy_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void text_tool_paste_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void text_tool_delete_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void text_tool_load_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void text_tool_clear_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void text_tool_text_to_path_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void text_tool_text_along_path_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void text_tool_direction_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+
+#endif /* __TEXT_TOOL_COMMANDS_H__ */
diff --git a/app/actions/tool-options-actions.c b/app/actions/tool-options-actions.c
new file mode 100644
index 0000000..10c59eb
--- /dev/null
+++ b/app/actions/tool-options-actions.c
@@ -0,0 +1,238 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "actions-types.h"
+
+#include "core/gimp.h"
+#include "core/gimpcontext.h"
+#include "core/gimplist.h"
+#include "core/gimptoolinfo.h"
+#include "core/gimptoolpreset.h"
+
+#include "widgets/gimpactiongroup.h"
+#include "widgets/gimphelp-ids.h"
+
+#include "tool-options-actions.h"
+#include "tool-options-commands.h"
+
+#include "gimp-intl.h"
+
+
+/* local function prototypes */
+
+static void tool_options_actions_update_presets (GimpActionGroup *group,
+ const gchar *action_prefix,
+ GimpActionCallback callback,
+ const gchar *help_id,
+ GimpContainer *presets,
+ gboolean need_writable,
+ gboolean need_deletable);
+
+
+/* global variables */
+
+static const GimpActionEntry tool_options_actions[] =
+{
+ { "tool-options-popup", GIMP_ICON_DIALOG_TOOL_OPTIONS,
+ NC_("tool-options-action", "Tool Options Menu"), NULL, NULL, NULL,
+ GIMP_HELP_TOOL_OPTIONS_DIALOG },
+
+ { "tool-options-save-preset-menu", GIMP_ICON_DOCUMENT_SAVE,
+ NC_("tool-options-action", "_Save Tool Preset"), "", NULL, NULL,
+ GIMP_HELP_TOOL_OPTIONS_SAVE },
+
+ { "tool-options-restore-preset-menu", GIMP_ICON_DOCUMENT_REVERT,
+ NC_("tool-options-action", "_Restore Tool Preset"), "", NULL, NULL,
+ GIMP_HELP_TOOL_OPTIONS_RESTORE },
+
+ { "tool-options-edit-preset-menu", GIMP_ICON_EDIT,
+ NC_("tool-options-action", "E_dit Tool Preset"), NULL, NULL, NULL,
+ GIMP_HELP_TOOL_OPTIONS_EDIT },
+
+ { "tool-options-delete-preset-menu", GIMP_ICON_EDIT_DELETE,
+ NC_("tool-options-action", "_Delete Tool Preset"), "", NULL, NULL,
+ GIMP_HELP_TOOL_OPTIONS_DELETE },
+
+ { "tool-options-save-new-preset", GIMP_ICON_DOCUMENT_NEW,
+ NC_("tool-options-action", "_New Tool Preset..."), "", NULL,
+ tool_options_save_new_preset_cmd_callback,
+ GIMP_HELP_TOOL_OPTIONS_SAVE },
+
+ { "tool-options-reset", GIMP_ICON_RESET,
+ NC_("tool-options-action", "R_eset Tool Options"), NULL,
+ NC_("tool-options-action", "Reset to default values"),
+ tool_options_reset_cmd_callback,
+ GIMP_HELP_TOOL_OPTIONS_RESET },
+
+ { "tool-options-reset-all", GIMP_ICON_RESET,
+ NC_("tool-options-action", "Reset _all Tool Options"), NULL,
+ NC_("tool-options-action", "Reset all tool options"),
+ tool_options_reset_all_cmd_callback,
+ GIMP_HELP_TOOL_OPTIONS_RESET }
+};
+
+
+/* public functions */
+
+#define SET_VISIBLE(action,condition) \
+ gimp_action_group_set_action_visible (group, action, (condition) != 0)
+#define SET_SENSITIVE(action,condition) \
+ gimp_action_group_set_action_sensitive (group, action, (condition) != 0)
+#define SET_HIDE_EMPTY(action,condition) \
+ gimp_action_group_set_action_hide_empty (group, action, (condition) != 0)
+
+void
+tool_options_actions_setup (GimpActionGroup *group)
+{
+ gimp_action_group_add_actions (group, "tool-options-action",
+ tool_options_actions,
+ G_N_ELEMENTS (tool_options_actions));
+
+ SET_HIDE_EMPTY ("tool-options-restore-preset-menu", FALSE);
+ SET_HIDE_EMPTY ("tool-options-edit-preset-menu", FALSE);
+ SET_HIDE_EMPTY ("tool-options-delete-preset-menu", FALSE);
+}
+
+void
+tool_options_actions_update (GimpActionGroup *group,
+ gpointer data)
+{
+ GimpContext *context = gimp_get_user_context (group->gimp);
+ GimpToolInfo *tool_info = gimp_context_get_tool (context);
+
+ SET_VISIBLE ("tool-options-save-preset-menu", tool_info->presets);
+ SET_VISIBLE ("tool-options-restore-preset-menu", tool_info->presets);
+ SET_VISIBLE ("tool-options-edit-preset-menu", tool_info->presets);
+ SET_VISIBLE ("tool-options-delete-preset-menu", tool_info->presets);
+
+ tool_options_actions_update_presets (group, "tool-options-save-preset",
+ tool_options_save_preset_cmd_callback,
+ GIMP_HELP_TOOL_OPTIONS_SAVE,
+ tool_info->presets,
+ TRUE /* writable */,
+ FALSE /* deletable */);
+
+ tool_options_actions_update_presets (group, "tool-options-restore-preset",
+ tool_options_restore_preset_cmd_callback,
+ GIMP_HELP_TOOL_OPTIONS_RESTORE,
+ tool_info->presets,
+ FALSE /* writable */,
+ FALSE /* deletable */);
+
+ tool_options_actions_update_presets (group, "tool-options-edit-preset",
+ tool_options_edit_preset_cmd_callback,
+ GIMP_HELP_TOOL_OPTIONS_EDIT,
+ tool_info->presets,
+ FALSE /* writable */,
+ FALSE /* deletable */);
+
+ tool_options_actions_update_presets (group, "tool-options-delete-preset",
+ tool_options_delete_preset_cmd_callback,
+ GIMP_HELP_TOOL_OPTIONS_DELETE,
+ tool_info->presets,
+ FALSE /* writable */,
+ TRUE /* deletable */);
+}
+
+
+/* private function */
+
+static void
+tool_options_actions_update_presets (GimpActionGroup *group,
+ const gchar *action_prefix,
+ GimpActionCallback callback,
+ const gchar *help_id,
+ GimpContainer *presets,
+ gboolean need_writable,
+ gboolean need_deletable)
+{
+ GList *list;
+ gint n_children = 0;
+ gint i;
+
+ for (i = 0; ; i++)
+ {
+ gchar *action_name;
+ GimpAction *action;
+
+ action_name = g_strdup_printf ("%s-%03d", action_prefix, i);
+ action = gimp_action_group_get_action (group, action_name);
+ g_free (action_name);
+
+ if (! action)
+ break;
+
+ gimp_action_group_remove_action (group, action);
+ }
+
+ if (presets)
+ n_children = gimp_container_get_n_children (presets);
+
+ if (n_children > 0)
+ {
+ GimpEnumActionEntry entry;
+
+ entry.name = NULL;
+ entry.label = NULL;
+ entry.accelerator = "";
+ entry.tooltip = NULL;
+ entry.value = 0;
+ entry.value_variable = FALSE;
+ entry.help_id = help_id;
+
+ for (list = GIMP_LIST (presets)->queue->head, i = 0;
+ list;
+ list = g_list_next (list), i++)
+ {
+ GimpObject *preset = list->data;
+ GdkPixbuf *pixbuf = NULL;
+
+ entry.name = g_strdup_printf ("%s-%03d", action_prefix, i);
+ entry.label = gimp_object_get_name (preset);
+ entry.icon_name = gimp_viewable_get_icon_name (GIMP_VIEWABLE (preset));
+ entry.value = i;
+
+ g_object_get (preset, "icon-pixbuf", &pixbuf, NULL);
+
+ gimp_action_group_add_enum_actions (group, NULL, &entry, 1, callback);
+
+ if (need_writable)
+ SET_SENSITIVE (entry.name,
+ gimp_data_is_writable (GIMP_DATA (preset)));
+
+ if (need_deletable)
+ SET_SENSITIVE (entry.name,
+ gimp_data_is_deletable (GIMP_DATA (preset)));
+
+ if (pixbuf)
+ gimp_action_group_set_action_pixbuf (group, entry.name, pixbuf);
+
+ g_free ((gchar *) entry.name);
+ }
+ }
+}
+
+#undef SET_VISIBLE
+#undef SET_SENSITIVE
+#undef SET_HIDE_EMPTY
diff --git a/app/actions/tool-options-actions.h b/app/actions/tool-options-actions.h
new file mode 100644
index 0000000..2115fe1
--- /dev/null
+++ b/app/actions/tool-options-actions.h
@@ -0,0 +1,27 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __TOOL_OPTIONS_ACTIONS_H__
+#define __TOOL_OPTIONS_ACTIONS_H__
+
+
+void tool_options_actions_setup (GimpActionGroup *group);
+void tool_options_actions_update (GimpActionGroup *group,
+ gpointer data);
+
+
+#endif /* __TOOL_OPTIONS_ACTIONS_H__ */
diff --git a/app/actions/tool-options-commands.c b/app/actions/tool-options-commands.c
new file mode 100644
index 0000000..94fd3c6
--- /dev/null
+++ b/app/actions/tool-options-commands.c
@@ -0,0 +1,268 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <string.h>
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpconfig/gimpconfig.h"
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "actions-types.h"
+
+#include "core/gimp.h"
+#include "core/gimpcontainer.h"
+#include "core/gimpdatafactory.h"
+#include "core/gimptoolinfo.h"
+#include "core/gimptooloptions.h"
+#include "core/gimptoolpreset.h"
+
+#include "widgets/gimpdataeditor.h"
+#include "widgets/gimpdialogfactory.h"
+#include "widgets/gimpeditor.h"
+#include "widgets/gimphelp-ids.h"
+#include "widgets/gimpmessagebox.h"
+#include "widgets/gimpmessagedialog.h"
+#include "widgets/gimptooloptionseditor.h"
+#include "widgets/gimpuimanager.h"
+#include "widgets/gimpwidgets-utils.h"
+#include "widgets/gimpwindowstrategy.h"
+
+#include "dialogs/data-delete-dialog.h"
+
+#include "tool-options-commands.h"
+
+#include "gimp-intl.h"
+
+
+/* local function prototypes */
+
+static void tool_options_show_preset_editor (Gimp *gimp,
+ GimpEditor *editor,
+ GimpToolPreset *preset);
+
+
+/* public functions */
+
+void
+tool_options_save_new_preset_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer user_data)
+{
+ GimpEditor *editor = GIMP_EDITOR (user_data);
+ Gimp *gimp = gimp_editor_get_ui_manager (editor)->gimp;
+ GimpContext *context = gimp_get_user_context (gimp);
+ GimpData *data;
+
+ data = gimp_data_factory_data_new (context->gimp->tool_preset_factory,
+ context, _("Untitled"));
+
+ tool_options_show_preset_editor (gimp, editor, GIMP_TOOL_PRESET (data));
+}
+
+void
+tool_options_save_preset_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpEditor *editor = GIMP_EDITOR (data);
+ Gimp *gimp = gimp_editor_get_ui_manager (editor)->gimp;
+ GimpContext *context = gimp_get_user_context (gimp);
+ GimpToolInfo *tool_info = gimp_context_get_tool (context);
+ GimpToolPreset *preset;
+ gint index;
+
+ index = g_variant_get_int32 (value);
+
+ preset = (GimpToolPreset *)
+ gimp_container_get_child_by_index (tool_info->presets, index);
+
+ if (preset)
+ {
+ gimp_config_sync (G_OBJECT (tool_info->tool_options),
+ G_OBJECT (preset->tool_options), 0);
+
+ tool_options_show_preset_editor (gimp, editor, preset);
+ }
+}
+
+void
+tool_options_restore_preset_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpEditor *editor = GIMP_EDITOR (data);
+ Gimp *gimp = gimp_editor_get_ui_manager (editor)->gimp;
+ GimpContext *context = gimp_get_user_context (gimp);
+ GimpToolInfo *tool_info = gimp_context_get_tool (context);
+ GimpToolPreset *preset;
+ gint index;
+
+ index = g_variant_get_int32 (value);
+
+ preset = (GimpToolPreset *)
+ gimp_container_get_child_by_index (tool_info->presets, index);
+
+ if (preset)
+ {
+ if (gimp_context_get_tool_preset (context) != preset)
+ gimp_context_set_tool_preset (context, preset);
+ else
+ gimp_context_tool_preset_changed (context);
+ }
+}
+
+void
+tool_options_edit_preset_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpEditor *editor = GIMP_EDITOR (data);
+ Gimp *gimp = gimp_editor_get_ui_manager (editor)->gimp;
+ GimpContext *context = gimp_get_user_context (gimp);
+ GimpToolInfo *tool_info = gimp_context_get_tool (context);
+ GimpToolPreset *preset;
+ gint index;
+
+ index = g_variant_get_int32 (value);
+
+ preset = (GimpToolPreset *)
+ gimp_container_get_child_by_index (tool_info->presets, index);
+
+ if (preset)
+ {
+ tool_options_show_preset_editor (gimp, editor, preset);
+ }
+}
+
+void
+tool_options_delete_preset_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpEditor *editor = GIMP_EDITOR (data);
+ GimpContext *context = gimp_get_user_context (gimp_editor_get_ui_manager (editor)->gimp);
+ GimpToolInfo *tool_info = gimp_context_get_tool (context);
+ GimpToolPreset *preset;
+ gint index;
+
+ index = g_variant_get_int32 (value);
+
+ preset = (GimpToolPreset *)
+ gimp_container_get_child_by_index (tool_info->presets, index);
+
+ if (preset &&
+ gimp_data_is_deletable (GIMP_DATA (preset)))
+ {
+ GimpDataFactory *factory = context->gimp->tool_preset_factory;
+ GtkWidget *dialog;
+
+ dialog = data_delete_dialog_new (factory, GIMP_DATA (preset), NULL,
+ GTK_WIDGET (editor));
+ gtk_widget_show (dialog);
+ }
+}
+
+void
+tool_options_reset_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpEditor *editor = GIMP_EDITOR (data);
+ GimpContext *context = gimp_get_user_context (gimp_editor_get_ui_manager (editor)->gimp);
+ GimpToolInfo *tool_info = gimp_context_get_tool (context);
+
+ gimp_config_reset (GIMP_CONFIG (tool_info->tool_options));
+}
+
+void
+tool_options_reset_all_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpEditor *editor = GIMP_EDITOR (data);
+ GtkWidget *dialog;
+
+ dialog = gimp_message_dialog_new (_("Reset All Tool Options"),
+ GIMP_ICON_DIALOG_QUESTION,
+ GTK_WIDGET (editor),
+ GTK_DIALOG_MODAL |
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ gimp_standard_help_func, NULL,
+
+ _("_Cancel"), GTK_RESPONSE_CANCEL,
+ _("_Reset"), GTK_RESPONSE_OK,
+
+ NULL);
+
+ gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_CANCEL);
+ gtk_dialog_set_alternative_button_order (GTK_DIALOG (dialog),
+ GTK_RESPONSE_OK,
+ GTK_RESPONSE_CANCEL,
+ -1);
+
+ g_signal_connect_object (gtk_widget_get_toplevel (GTK_WIDGET (editor)),
+ "unmap",
+ G_CALLBACK (gtk_widget_destroy),
+ dialog, G_CONNECT_SWAPPED);
+
+ gimp_message_box_set_primary_text (GIMP_MESSAGE_DIALOG (dialog)->box,
+ _("Do you really want to reset all "
+ "tool options to default values?"));
+
+ if (gimp_dialog_run (GIMP_DIALOG (dialog)) == GTK_RESPONSE_OK)
+ {
+ Gimp *gimp = gimp_editor_get_ui_manager (editor)->gimp;
+ GList *list;
+
+ for (list = gimp_get_tool_info_iter (gimp);
+ list;
+ list = g_list_next (list))
+ {
+ GimpToolInfo *tool_info = list->data;
+
+ gimp_config_reset (GIMP_CONFIG (tool_info->tool_options));
+ }
+ }
+
+ gtk_widget_destroy (dialog);
+}
+
+
+/* private functions */
+
+static void
+tool_options_show_preset_editor (Gimp *gimp,
+ GimpEditor *editor,
+ GimpToolPreset *preset)
+{
+ GtkWidget *dockable;
+
+ dockable =
+ gimp_window_strategy_show_dockable_dialog (GIMP_WINDOW_STRATEGY (gimp_get_window_strategy (gimp)),
+ gimp,
+ gimp_dialog_factory_get_singleton (),
+ gtk_widget_get_screen (GTK_WIDGET (editor)),
+ gimp_widget_get_monitor (GTK_WIDGET (editor)),
+ "gimp-tool-preset-editor");
+
+ gimp_data_editor_set_data (GIMP_DATA_EDITOR (gtk_bin_get_child (GTK_BIN (dockable))),
+ GIMP_DATA (preset));
+}
diff --git a/app/actions/tool-options-commands.h b/app/actions/tool-options-commands.h
new file mode 100644
index 0000000..8594e44
--- /dev/null
+++ b/app/actions/tool-options-commands.h
@@ -0,0 +1,47 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __TOOL_OPTIONS_COMMANDS_H__
+#define __TOOL_OPTIONS_COMMANDS_H__
+
+
+void tool_options_save_new_preset_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+void tool_options_save_preset_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void tool_options_restore_preset_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void tool_options_edit_preset_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void tool_options_delete_preset_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+void tool_options_reset_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void tool_options_reset_all_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+
+#endif /* __TOOL_OPTIONS_COMMANDS_H__ */
diff --git a/app/actions/tool-preset-editor-actions.c b/app/actions/tool-preset-editor-actions.c
new file mode 100644
index 0000000..8b22e6f
--- /dev/null
+++ b/app/actions/tool-preset-editor-actions.c
@@ -0,0 +1,105 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "actions-types.h"
+
+#include "core/gimp.h"
+#include "core/gimpcontext.h"
+
+#include "widgets/gimpactiongroup.h"
+#include "widgets/gimpdataeditor.h"
+#include "widgets/gimphelp-ids.h"
+
+#include "data-editor-commands.h"
+#include "tool-preset-editor-actions.h"
+#include "tool-preset-editor-commands.h"
+
+#include "gimp-intl.h"
+
+
+static const GimpActionEntry tool_preset_editor_actions[] =
+{
+ { "tool-preset-editor-popup", GIMP_ICON_TOOL_PRESET,
+ NC_("tool-preset-editor-action", "Tool Preset Editor Menu"), NULL, NULL, NULL,
+ GIMP_HELP_TOOL_PRESET_EDITOR_DIALOG },
+
+ { "tool-preset-editor-save", GIMP_ICON_DOCUMENT_SAVE,
+ NC_("tool-preset-editor-action", "_Save Tool Options to Preset"), NULL,
+ NC_("tool-preset-editor-action", "Save the active tool options to this "
+ "tool preset"),
+ tool_preset_editor_save_cmd_callback,
+ GIMP_HELP_TOOL_PRESET_SAVE },
+
+ { "tool-preset-editor-restore", GIMP_ICON_DOCUMENT_REVERT,
+ NC_("tool-preset-editor-action", "_Restore Tool Preset"), NULL,
+ NC_("tool-preset-editor-action", "Restore this tool preset"),
+ tool_preset_editor_restore_cmd_callback,
+ GIMP_HELP_TOOL_PRESET_RESTORE }
+};
+
+
+static const GimpToggleActionEntry tool_preset_editor_toggle_actions[] =
+{
+ { "tool-preset-editor-edit-active", GIMP_ICON_LINKED,
+ NC_("tool-preset-editor-action", "Edit Active Tool Preset"), NULL, NULL,
+ data_editor_edit_active_cmd_callback,
+ FALSE,
+ GIMP_HELP_TOOL_PRESET_EDITOR_EDIT_ACTIVE }
+};
+
+
+void
+tool_preset_editor_actions_setup (GimpActionGroup *group)
+{
+ gimp_action_group_add_actions (group, "tool-preset-editor-action",
+ tool_preset_editor_actions,
+ G_N_ELEMENTS (tool_preset_editor_actions));
+
+ gimp_action_group_add_toggle_actions (group, "tool-preset-editor-action",
+ tool_preset_editor_toggle_actions,
+ G_N_ELEMENTS (tool_preset_editor_toggle_actions));
+
+}
+
+void
+tool_preset_editor_actions_update (GimpActionGroup *group,
+ gpointer user_data)
+{
+ GimpDataEditor *data_editor = GIMP_DATA_EDITOR (user_data);
+ gboolean edit_active = FALSE;
+
+ edit_active = gimp_data_editor_get_edit_active (data_editor);
+
+#define SET_SENSITIVE(action,condition) \
+ gimp_action_group_set_action_sensitive (group, action, (condition) != 0)
+#define SET_ACTIVE(action,condition) \
+ gimp_action_group_set_action_active (group, action, (condition) != 0)
+
+ SET_SENSITIVE ("tool-preset-editor-save", data_editor->data);
+ SET_SENSITIVE ("tool-preset-editor-restore", data_editor->data);
+ SET_ACTIVE ("tool-preset-editor-edit-active", edit_active);
+
+#undef SET_SENSITIVE
+#undef SET_ACTIVE
+}
diff --git a/app/actions/tool-preset-editor-actions.h b/app/actions/tool-preset-editor-actions.h
new file mode 100644
index 0000000..35275c5
--- /dev/null
+++ b/app/actions/tool-preset-editor-actions.h
@@ -0,0 +1,27 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __TOOL_PRESET_EDITOR_ACTIONS_H__
+#define __TOOL_PRESET_EDITOR_ACTIONS_H__
+
+
+void tool_preset_editor_actions_setup (GimpActionGroup *group);
+void tool_preset_editor_actions_update (GimpActionGroup *group,
+ gpointer data);
+
+
+#endif /* __TOOL_PRESET_EDITOR_ACTIONS_H__ */
diff --git a/app/actions/tool-preset-editor-commands.c b/app/actions/tool-preset-editor-commands.c
new file mode 100644
index 0000000..654ae16
--- /dev/null
+++ b/app/actions/tool-preset-editor-commands.c
@@ -0,0 +1,90 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpconfig/gimpconfig.h"
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "actions-types.h"
+
+#include "core/gimp.h"
+#include "core/gimpcontext.h"
+#include "core/gimptoolinfo.h"
+#include "core/gimptoolpreset.h"
+
+#include "widgets/gimpdataeditor.h"
+
+#include "tool-preset-editor-commands.h"
+
+#include "gimp-intl.h"
+
+
+/* public functions */
+
+void
+tool_preset_editor_save_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpDataEditor *editor = GIMP_DATA_EDITOR (data);
+ GimpContext *context = editor->context;
+ GimpToolPreset *preset;
+ GimpToolInfo *tool_info;
+
+ preset = GIMP_TOOL_PRESET (gimp_data_editor_get_data (editor));
+ tool_info = gimp_context_get_tool (gimp_get_user_context (context->gimp));
+
+ if (tool_info && preset)
+ {
+ GimpToolInfo *preset_tool;
+
+ preset_tool = gimp_context_get_tool (GIMP_CONTEXT (preset->tool_options));
+
+ if (tool_info != preset_tool)
+ {
+ gimp_message (context->gimp,
+ G_OBJECT (editor), GIMP_MESSAGE_WARNING,
+ _("Can't save '%s' tool options to an "
+ "existing '%s' tool preset."),
+ tool_info->label,
+ preset_tool->label);
+ return;
+ }
+
+ gimp_config_sync (G_OBJECT (tool_info->tool_options),
+ G_OBJECT (preset->tool_options), 0);
+ }
+}
+
+void
+tool_preset_editor_restore_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpDataEditor *editor = GIMP_DATA_EDITOR (data);
+ GimpContext *context = editor->context;
+ GimpToolPreset *preset;
+
+ preset = GIMP_TOOL_PRESET (gimp_data_editor_get_data (editor));
+
+ if (preset)
+ gimp_context_tool_preset_changed (gimp_get_user_context (context->gimp));
+}
diff --git a/app/actions/tool-preset-editor-commands.h b/app/actions/tool-preset-editor-commands.h
new file mode 100644
index 0000000..f90f636
--- /dev/null
+++ b/app/actions/tool-preset-editor-commands.h
@@ -0,0 +1,30 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __TOOL_PRESET_EDITOR_COMMANDS_H__
+#define __TOOL_PRESET_EDITOR_COMMANDS_H__
+
+
+void tool_preset_editor_save_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void tool_preset_editor_restore_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+
+#endif /* __TOOL_PRESET_EDITOR_COMMANDS_H__ */
diff --git a/app/actions/tool-presets-actions.c b/app/actions/tool-presets-actions.c
new file mode 100644
index 0000000..36baabd
--- /dev/null
+++ b/app/actions/tool-presets-actions.c
@@ -0,0 +1,155 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "actions-types.h"
+
+#include "core/gimpcontext.h"
+#include "core/gimpdata.h"
+#include "core/gimptoolpreset.h"
+#include "core/gimptooloptions.h"
+
+#include "widgets/gimpactiongroup.h"
+#include "widgets/gimphelp-ids.h"
+
+#include "actions.h"
+#include "data-commands.h"
+#include "tool-presets-actions.h"
+#include "tool-presets-commands.h"
+
+#include "gimp-intl.h"
+
+
+static const GimpActionEntry tool_presets_actions[] =
+{
+ { "tool-presets-popup", GIMP_ICON_TOOL_PRESET,
+ NC_("tool-presets-action", "Tool Presets Menu"), NULL, NULL, NULL,
+ GIMP_HELP_TOOL_PRESET_DIALOG },
+
+ { "tool-presets-new", GIMP_ICON_DOCUMENT_NEW,
+ NC_("tool-presets-action", "_New Tool Preset"), NULL,
+ NC_("tool-presets-action", "Create a new tool preset"),
+ data_new_cmd_callback,
+ GIMP_HELP_TOOL_PRESET_NEW },
+
+ { "tool-presets-duplicate", GIMP_ICON_OBJECT_DUPLICATE,
+ NC_("tool-presets-action", "D_uplicate Tool Preset"), NULL,
+ NC_("tool-presets-action", "Duplicate this tool preset"),
+ data_duplicate_cmd_callback,
+ GIMP_HELP_TOOL_PRESET_DUPLICATE },
+
+ { "tool-presets-copy-location", GIMP_ICON_EDIT_COPY,
+ NC_("tool-presets-action", "Copy Tool Preset _Location"), NULL,
+ NC_("tool-presets-action", "Copy tool preset file location to clipboard"),
+ data_copy_location_cmd_callback,
+ GIMP_HELP_TOOL_PRESET_COPY_LOCATION },
+
+ { "tool-presets-show-in-file-manager", GIMP_ICON_FILE_MANAGER,
+ NC_("tool-presets-action", "Show in _File Manager"), NULL,
+ NC_("tool-presets-action", "Show tool preset file location in the file manager"),
+ data_show_in_file_manager_cmd_callback,
+ GIMP_HELP_TOOL_PRESET_SHOW_IN_FILE_MANAGER },
+
+ { "tool-presets-save", GIMP_ICON_DOCUMENT_SAVE,
+ NC_("tool-presets-action", "_Save Tool Options to Preset"), NULL,
+ NC_("tool-presets-action", "Save the active tool options to this "
+ "tool preset"),
+ tool_presets_save_cmd_callback,
+ GIMP_HELP_TOOL_PRESET_SAVE },
+
+ { "tool-presets-restore", GIMP_ICON_DOCUMENT_REVERT,
+ NC_("tool-presets-action", "_Restore Tool Preset"), NULL,
+ NC_("tool-presets-action", "Restore this tool preset"),
+ tool_presets_restore_cmd_callback,
+ GIMP_HELP_TOOL_PRESET_RESTORE },
+
+ { "tool-presets-delete", GIMP_ICON_EDIT_DELETE,
+ NC_("tool-presets-action", "_Delete Tool Preset"), NULL,
+ NC_("tool-presets-action", "Delete this tool preset"),
+ data_delete_cmd_callback,
+ GIMP_HELP_TOOL_PRESET_DELETE },
+
+ { "tool-presets-refresh", GIMP_ICON_VIEW_REFRESH,
+ NC_("tool-presets-action", "_Refresh Tool Presets"), NULL,
+ NC_("tool-presets-action", "Refresh tool presets"),
+ data_refresh_cmd_callback,
+ GIMP_HELP_TOOL_PRESET_REFRESH }
+};
+
+static const GimpStringActionEntry tool_presets_edit_actions[] =
+{
+ { "tool-presets-edit", GIMP_ICON_EDIT,
+ NC_("tool-presets-action", "_Edit Tool Preset..."), NULL,
+ NC_("tool-presets-action", "Edit this tool preset"),
+ "gimp-tool-preset-editor",
+ GIMP_HELP_TOOL_PRESET_EDIT }
+};
+
+
+void
+tool_presets_actions_setup (GimpActionGroup *group)
+{
+ gimp_action_group_add_actions (group, "tool-presets-action",
+ tool_presets_actions,
+ G_N_ELEMENTS (tool_presets_actions));
+
+ gimp_action_group_add_string_actions (group, "tool-presets-action",
+ tool_presets_edit_actions,
+ G_N_ELEMENTS (tool_presets_edit_actions),
+ data_edit_cmd_callback);
+}
+
+void
+tool_presets_actions_update (GimpActionGroup *group,
+ gpointer user_data)
+{
+ GimpContext *context = action_data_get_context (user_data);
+ GimpToolPreset *tool_preset = NULL;
+ GimpData *data = NULL;
+ GFile *file = NULL;
+
+ if (context)
+ {
+ tool_preset = gimp_context_get_tool_preset (context);
+
+ if (tool_preset)
+ {
+ data = GIMP_DATA (tool_preset);
+
+ file = gimp_data_get_file (data);
+ }
+ }
+
+#define SET_SENSITIVE(action,condition) \
+ gimp_action_group_set_action_sensitive (group, action, (condition) != 0)
+
+ SET_SENSITIVE ("tool-presets-edit", tool_preset);
+ SET_SENSITIVE ("tool-presets-duplicate", tool_preset && gimp_data_is_duplicatable (data));
+ SET_SENSITIVE ("tool-presets-copy-location", file);
+ SET_SENSITIVE ("tool-presets-show-in-file-manager", file);
+ SET_SENSITIVE ("tool-presets-save", tool_preset);
+ SET_SENSITIVE ("tool-presets-restore", tool_preset);
+ SET_SENSITIVE ("tool-presets-delete", tool_preset && gimp_data_is_deletable (data));
+
+#undef SET_SENSITIVE
+}
diff --git a/app/actions/tool-presets-actions.h b/app/actions/tool-presets-actions.h
new file mode 100644
index 0000000..7cdf969
--- /dev/null
+++ b/app/actions/tool-presets-actions.h
@@ -0,0 +1,27 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __TOOL_PRESETS_ACTIONS_H__
+#define __TOOL_PRESETS_ACTIONS_H__
+
+
+void tool_presets_actions_setup (GimpActionGroup *group);
+void tool_presets_actions_update (GimpActionGroup *group,
+ gpointer user_data);
+
+
+#endif /* __TOOL_PRESET_ACTIONS_H__ */
diff --git a/app/actions/tool-presets-commands.c b/app/actions/tool-presets-commands.c
new file mode 100644
index 0000000..bc60557
--- /dev/null
+++ b/app/actions/tool-presets-commands.c
@@ -0,0 +1,95 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpconfig/gimpconfig.h"
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "actions-types.h"
+
+#include "core/gimp.h"
+#include "core/gimpcontext.h"
+#include "core/gimptoolinfo.h"
+#include "core/gimptoolpreset.h"
+
+#include "widgets/gimpcontainereditor.h"
+#include "widgets/gimpcontainerview.h"
+
+#include "tool-presets-commands.h"
+
+#include "gimp-intl.h"
+
+
+/* public functions */
+
+void
+tool_presets_save_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpContainerEditor *editor = GIMP_CONTAINER_EDITOR (data);
+ GimpContext *context;
+ GimpToolPreset *preset;
+ GimpToolInfo *tool_info;
+
+ context = gimp_container_view_get_context (editor->view);
+
+ preset = gimp_context_get_tool_preset (context);
+ tool_info = gimp_context_get_tool (gimp_get_user_context (context->gimp));
+
+ if (tool_info && preset)
+ {
+ GimpToolInfo *preset_tool;
+
+ preset_tool = gimp_context_get_tool (GIMP_CONTEXT (preset->tool_options));
+
+ if (tool_info != preset_tool)
+ {
+ gimp_message (context->gimp,
+ G_OBJECT (editor), GIMP_MESSAGE_WARNING,
+ _("Can't save '%s' tool options to an "
+ "existing '%s' tool preset."),
+ tool_info->label,
+ preset_tool->label);
+ return;
+ }
+
+ gimp_config_sync (G_OBJECT (tool_info->tool_options),
+ G_OBJECT (preset->tool_options), 0);
+ }
+}
+
+void
+tool_presets_restore_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpContainerEditor *editor = GIMP_CONTAINER_EDITOR (data);
+ GimpContext *context;
+ GimpToolPreset *preset;
+
+ context = gimp_container_view_get_context (editor->view);
+
+ preset = gimp_context_get_tool_preset (context);
+
+ if (preset)
+ gimp_context_tool_preset_changed (gimp_get_user_context (context->gimp));
+}
diff --git a/app/actions/tool-presets-commands.h b/app/actions/tool-presets-commands.h
new file mode 100644
index 0000000..ecf9c21
--- /dev/null
+++ b/app/actions/tool-presets-commands.h
@@ -0,0 +1,30 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __TOOL_PRESETS_COMMANDS_H__
+#define __TOOL_PRESETS_COMMANDS_H__
+
+
+void tool_presets_save_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void tool_presets_restore_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+
+#endif /* __TOOL_PRESETS_COMMANDS_H__ */
diff --git a/app/actions/tools-actions.c b/app/actions/tools-actions.c
new file mode 100644
index 0000000..dd9a827
--- /dev/null
+++ b/app/actions/tools-actions.c
@@ -0,0 +1,800 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <string.h>
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "actions-types.h"
+
+#include "core/gimp.h"
+#include "core/gimpcontainer.h"
+#include "core/gimpcontext.h"
+#include "core/gimptoolinfo.h"
+
+#include "widgets/gimpaction.h"
+#include "widgets/gimpactiongroup.h"
+#include "widgets/gimphelp-ids.h"
+
+#include "actions.h"
+#include "tools-actions.h"
+#include "tools-commands.h"
+
+#include "gimp-intl.h"
+
+
+static const GimpActionEntry tools_actions[] =
+{
+ { "tools-menu", NULL, NC_("tools-action", "_Tools") },
+ { "tools-select-menu", NULL, NC_("tools-action", "_Selection Tools") },
+ { "tools-paint-menu", NULL, NC_("tools-action", "_Paint Tools") },
+ { "tools-transform-menu", NULL, NC_("tools-action", "_Transform Tools") },
+ { "tools-color-menu", NULL, NC_("tools-action", "_Color Tools") },
+};
+
+static const GimpStringActionEntry tools_alternative_actions[] =
+{
+ { "tools-by-color-select-short", GIMP_ICON_TOOL_BY_COLOR_SELECT,
+ NC_("tools-action", "_By Color"), NULL,
+ NC_("tools-action", "Select regions with similar colors"),
+ "gimp-by-color-select-tool",
+ GIMP_HELP_TOOL_BY_COLOR_SELECT },
+
+ { "tools-rotate-arbitrary", GIMP_ICON_TOOL_ROTATE,
+ NC_("tools-action", "_Arbitrary Rotation..."), "",
+ NC_("tools-action", "Rotate drawable by an arbitrary angle"),
+ "gimp-rotate-layer",
+ GIMP_HELP_TOOL_ROTATE },
+
+ { "tools-rotate-image-arbitrary", GIMP_ICON_TOOL_ROTATE,
+ NC_("tools-action", "_Arbitrary Rotation..."), "",
+ NC_("tools-action", "Rotate image by an arbitrary angle"),
+ "gimp-rotate-image",
+ GIMP_HELP_TOOL_ROTATE }
+};
+
+static const GimpEnumActionEntry tools_color_average_radius_actions[] =
+{
+ { "tools-color-average-radius-set", GIMP_ICON_TOOL_COLOR_PICKER,
+ "Set Color Picker Radius", NULL, NULL,
+ GIMP_ACTION_SELECT_SET, TRUE,
+ NULL }
+};
+
+static const GimpEnumActionEntry tools_paintbrush_size_actions[] =
+{
+ { "tools-paintbrush-size-set", GIMP_ICON_TOOL_PAINTBRUSH,
+ "Set Brush Size", NULL, NULL,
+ GIMP_ACTION_SELECT_SET, TRUE,
+ NULL }
+};
+
+static const GimpEnumActionEntry tools_paintbrush_aspect_ratio_actions[] =
+{
+ { "tools-paintbrush-aspect-ratio-set", GIMP_ICON_TOOL_PAINTBRUSH,
+ "Set Brush Aspect Ratio", NULL, NULL,
+ GIMP_ACTION_SELECT_SET, TRUE,
+ NULL }
+};
+
+static const GimpEnumActionEntry tools_paintbrush_angle_actions[] =
+{
+ { "tools-paintbrush-angle-set", GIMP_ICON_TOOL_PAINTBRUSH,
+ "Set Brush Angle", NULL, NULL,
+ GIMP_ACTION_SELECT_SET, TRUE,
+ NULL }
+};
+
+static const GimpEnumActionEntry tools_paintbrush_spacing_actions[] =
+{
+ { "tools-paintbrush-spacing-set", GIMP_ICON_TOOL_PAINTBRUSH,
+ "Set Brush Spacing", NULL, NULL,
+ GIMP_ACTION_SELECT_SET, TRUE,
+ NULL }
+};
+
+static const GimpEnumActionEntry tools_paintbrush_hardness_actions[] =
+{
+ { "tools-paintbrush-hardness-set", GIMP_ICON_TOOL_PAINTBRUSH,
+ "Set Brush Hardness", NULL, NULL,
+ GIMP_ACTION_SELECT_SET, TRUE,
+ NULL }
+};
+
+static const GimpEnumActionEntry tools_paintbrush_force_actions[] =
+{
+ { "tools-paintbrush-force-set", GIMP_ICON_TOOL_PAINTBRUSH,
+ "Set Brush Force", NULL, NULL,
+ GIMP_ACTION_SELECT_SET, TRUE,
+ NULL }
+};
+
+static const GimpEnumActionEntry tools_ink_blob_size_actions[] =
+{
+ { "tools-ink-blob-size-set", GIMP_ICON_TOOL_INK,
+ "Set Ink Blob Size", NULL, NULL,
+ GIMP_ACTION_SELECT_SET, TRUE,
+ NULL }
+};
+
+static const GimpEnumActionEntry tools_ink_blob_aspect_actions[] =
+{
+ { "tools-ink-blob-aspect-set", GIMP_ICON_TOOL_INK,
+ "Set Ink Blob Aspect", NULL, NULL,
+ GIMP_ACTION_SELECT_SET, TRUE,
+ NULL }
+};
+
+static const GimpEnumActionEntry tools_ink_blob_angle_actions[] =
+{
+ { "tools-ink-blob-angle-set", GIMP_ICON_TOOL_INK,
+ "Set Ink Blob Angle", NULL, NULL,
+ GIMP_ACTION_SELECT_SET, TRUE,
+ NULL }
+};
+
+static const GimpEnumActionEntry tools_airbrush_rate_actions[] =
+{
+ { "tools-airbrush-rate-set", GIMP_ICON_TOOL_AIRBRUSH,
+ NC_("tools-action", "Airbrush Rate: Set"), NULL, NULL,
+ GIMP_ACTION_SELECT_SET, TRUE,
+ NULL },
+ { "tools-airbrush-rate-minimum", GIMP_ICON_TOOL_AIRBRUSH,
+ NC_("tools-action", "Airbrush Rate: Set to Minimum"), NULL, NULL,
+ GIMP_ACTION_SELECT_FIRST, FALSE,
+ NULL },
+ { "tools-airbrush-rate-maximum", GIMP_ICON_TOOL_AIRBRUSH,
+ NC_("tools-action", "Airbrush Rate: Set to Maximum"), NULL, NULL,
+ GIMP_ACTION_SELECT_LAST, FALSE,
+ NULL },
+ { "tools-airbrush-rate-decrease", GIMP_ICON_TOOL_AIRBRUSH,
+ NC_("tools-action", "Airbrush Rate: Decrease by 1"), NULL, NULL,
+ GIMP_ACTION_SELECT_PREVIOUS, FALSE,
+ NULL },
+ { "tools-airbrush-rate-increase", GIMP_ICON_TOOL_AIRBRUSH,
+ NC_("tools-action", "Airbrush Rate: Increase by 1"), NULL, NULL,
+ GIMP_ACTION_SELECT_NEXT, FALSE,
+ NULL },
+ { "tools-airbrush-rate-decrease-skip", GIMP_ICON_TOOL_AIRBRUSH,
+ NC_("tools-action", "Airbrush Rate: Decrease by 10"), NULL, NULL,
+ GIMP_ACTION_SELECT_SKIP_PREVIOUS, FALSE,
+ NULL },
+ { "tools-airbrush-rate-increase-skip", GIMP_ICON_TOOL_AIRBRUSH,
+ NC_("tools-action", "Airbrush Rate: Increase by 10"), NULL, NULL,
+ GIMP_ACTION_SELECT_SKIP_NEXT, FALSE,
+ NULL }
+};
+
+static const GimpEnumActionEntry tools_airbrush_flow_actions[] =
+{
+ { "tools-airbrush-flow-set", GIMP_ICON_TOOL_AIRBRUSH,
+ NC_("tools-action", "Airbrush Flow: Set"), NULL, NULL,
+ GIMP_ACTION_SELECT_SET, TRUE,
+ NULL },
+ { "tools-airbrush-flow-minimum", GIMP_ICON_TOOL_AIRBRUSH,
+ NC_("tools-action", "Airbrush Flow: Set to Minimum"), NULL, NULL,
+ GIMP_ACTION_SELECT_FIRST, FALSE,
+ NULL },
+ { "tools-airbrush-flow-maximum", GIMP_ICON_TOOL_AIRBRUSH,
+ NC_("tools-action", "Airbrush Flow: Set to Maximum"), NULL, NULL,
+ GIMP_ACTION_SELECT_LAST, FALSE,
+ NULL },
+ { "tools-airbrush-flow-decrease", GIMP_ICON_TOOL_AIRBRUSH,
+ NC_("tools-action", "Airbrush Flow: Decrease by 1"), NULL, NULL,
+ GIMP_ACTION_SELECT_PREVIOUS, FALSE,
+ NULL },
+ { "tools-airbrush-flow-increase", GIMP_ICON_TOOL_AIRBRUSH,
+ NC_("tools-action", "Airbrush Flow: Increase by 1"), NULL, NULL,
+ GIMP_ACTION_SELECT_NEXT, FALSE,
+ NULL },
+ { "tools-airbrush-flow-decrease-skip", GIMP_ICON_TOOL_AIRBRUSH,
+ NC_("tools-action", "Airbrush Flow: Decrease by 10"), NULL, NULL,
+ GIMP_ACTION_SELECT_SKIP_PREVIOUS, FALSE,
+ NULL },
+ { "tools-airbrush-flow-increase-skip", GIMP_ICON_TOOL_AIRBRUSH,
+ NC_("tools-action", "Airbrush Flow: Increase by 10"), NULL, NULL,
+ GIMP_ACTION_SELECT_SKIP_NEXT, FALSE,
+ NULL }
+};
+
+static const GimpEnumActionEntry tools_mybrush_radius_actions[] =
+{
+ { "tools-mypaint-brush-radius-set", GIMP_ICON_TOOL_MYPAINT_BRUSH,
+ "Set MyPaint Brush Radius", NULL, NULL,
+ GIMP_ACTION_SELECT_SET, TRUE,
+ NULL }
+};
+
+static const GimpEnumActionEntry tools_mybrush_hardness_actions[] =
+{
+ { "tools-mypaint-brush-hardness-set", GIMP_ICON_TOOL_MYPAINT_BRUSH,
+ "Set MyPaint Brush Hardness", NULL, NULL,
+ GIMP_ACTION_SELECT_SET, TRUE,
+ NULL }
+};
+
+static const GimpEnumActionEntry tools_foreground_select_brush_size_actions[] =
+{
+ { "tools-foreground-select-brush-size-set",
+ GIMP_ICON_TOOL_FOREGROUND_SELECT,
+ "Set Foreground Select Brush Size", NULL, NULL,
+ GIMP_ACTION_SELECT_SET, TRUE,
+ NULL }
+};
+
+static const GimpEnumActionEntry tools_transform_preview_opacity_actions[] =
+{
+ { "tools-transform-preview-opacity-set", GIMP_ICON_TOOL_PERSPECTIVE,
+ "Set Transform Tool Preview Opacity", NULL, NULL,
+ GIMP_ACTION_SELECT_SET, TRUE,
+ NULL }
+};
+
+static const GimpEnumActionEntry tools_warp_effect_size_actions[] =
+{
+ { "tools-warp-effect-size-set", GIMP_ICON_TOOL_WARP,
+ "Set Warp Effect Size", NULL, NULL,
+ GIMP_ACTION_SELECT_SET, TRUE,
+ NULL }
+};
+
+static const GimpEnumActionEntry tools_warp_effect_hardness_actions[] =
+{
+ { "tools-warp-effect-hardness-set", GIMP_ICON_TOOL_WARP,
+ "Set Warp Effect Hardness", NULL, NULL,
+ GIMP_ACTION_SELECT_SET, TRUE,
+ NULL }
+};
+
+static const GimpEnumActionEntry tools_opacity_actions[] =
+{
+ { "tools-opacity-set", GIMP_ICON_DIALOG_TOOL_OPTIONS,
+ NC_("tools-action", "Tool's Opacity: Set"), NULL, NULL,
+ GIMP_ACTION_SELECT_SET, TRUE,
+ NULL },
+ { "tools-opacity-set-to-default", GIMP_ICON_DIALOG_TOOL_OPTIONS,
+ NC_("tools-action", "Tool's Opacity: Set to Default Value"), NULL, NULL,
+ GIMP_ACTION_SELECT_SET_TO_DEFAULT, FALSE,
+ NULL },
+ { "tools-opacity-minimum", GIMP_ICON_DIALOG_TOOL_OPTIONS,
+ NC_("tools-action", "Tool's Opacity: Minimize"), NULL, NULL,
+ GIMP_ACTION_SELECT_FIRST, FALSE,
+ NULL },
+ { "tools-opacity-maximum", GIMP_ICON_DIALOG_TOOL_OPTIONS,
+ NC_("tools-action", "Tool's Opacity: Maximize"), NULL, NULL,
+ GIMP_ACTION_SELECT_LAST, FALSE,
+ NULL },
+ { "tools-opacity-decrease", GIMP_ICON_DIALOG_TOOL_OPTIONS,
+ NC_("tools-action", "Tool's Opacity: Decrease by 1"), "less", NULL,
+ GIMP_ACTION_SELECT_PREVIOUS, FALSE,
+ NULL },
+ { "tools-opacity-increase", GIMP_ICON_DIALOG_TOOL_OPTIONS,
+ NC_("tools-action", "Tool's Opacity: Increase by 1"), "greater", NULL,
+ GIMP_ACTION_SELECT_NEXT, FALSE,
+ NULL },
+ { "tools-opacity-decrease-skip", GIMP_ICON_DIALOG_TOOL_OPTIONS,
+ NC_("tools-action", "Tool's Opacity: Decrease by 10"), "<primary>less", NULL,
+ GIMP_ACTION_SELECT_SKIP_PREVIOUS, FALSE,
+ NULL },
+ { "tools-opacity-increase-skip", GIMP_ICON_DIALOG_TOOL_OPTIONS,
+ NC_("tools-action", "Tool's Opacity: Increase by 10"), "<primary>greater", NULL,
+ GIMP_ACTION_SELECT_SKIP_NEXT, FALSE,
+ NULL },
+ { "tools-opacity-decrease-percent", GIMP_ICON_DIALOG_TOOL_OPTIONS,
+ NC_("tools-action", "Tool's Opacity: Decrease Relative"), NULL, NULL,
+ GIMP_ACTION_SELECT_PERCENT_PREVIOUS, FALSE,
+ NULL },
+ { "tools-opacity-increase-percent", GIMP_ICON_DIALOG_TOOL_OPTIONS,
+ NC_("tools-action", "Tool's Opacity: Increase Relative"), NULL, NULL,
+ GIMP_ACTION_SELECT_PERCENT_NEXT, FALSE,
+ NULL },
+};
+
+static const GimpEnumActionEntry tools_size_actions[] =
+{
+ { "tools-size-set", GIMP_ICON_DIALOG_TOOL_OPTIONS,
+ NC_("tools-action", "Tool's Size: Set"), NULL, NULL,
+ GIMP_ACTION_SELECT_SET, TRUE,
+ NULL },
+ { "tools-size-set-to-default", GIMP_ICON_DIALOG_TOOL_OPTIONS,
+ NC_("tools-action", "Tool's Size: Set to Default Value"), "backslash", NULL,
+ GIMP_ACTION_SELECT_SET_TO_DEFAULT, FALSE,
+ NULL },
+ { "tools-size-minimum", GIMP_ICON_DIALOG_TOOL_OPTIONS,
+ NC_("tools-action", "Tool's Size: Minimize"), NULL, NULL,
+ GIMP_ACTION_SELECT_FIRST, FALSE,
+ NULL },
+ { "tools-size-maximum", GIMP_ICON_DIALOG_TOOL_OPTIONS,
+ NC_("tools-action", "Tool's Size: Maximize"), NULL, NULL,
+ GIMP_ACTION_SELECT_LAST, FALSE,
+ NULL },
+ { "tools-size-decrease", GIMP_ICON_DIALOG_TOOL_OPTIONS,
+ NC_("tools-action", "Tool's Size: Decrease by 1"), "bracketleft", NULL,
+ GIMP_ACTION_SELECT_PREVIOUS, FALSE,
+ NULL },
+ { "tools-size-increase", GIMP_ICON_DIALOG_TOOL_OPTIONS,
+ NC_("tools-action", "Tool's Size: Increase by 1"), "bracketright", NULL,
+ GIMP_ACTION_SELECT_NEXT, FALSE,
+ NULL },
+ { "tools-size-decrease-skip", GIMP_ICON_DIALOG_TOOL_OPTIONS,
+ NC_("tools-action", "Tool's Size: Decrease by 10"), "braceleft", NULL,
+ GIMP_ACTION_SELECT_SKIP_PREVIOUS, FALSE,
+ NULL },
+ { "tools-size-increase-skip", GIMP_ICON_DIALOG_TOOL_OPTIONS,
+ NC_("tools-action", "Tool's Size: Increase by 10"), "braceright", NULL,
+ GIMP_ACTION_SELECT_SKIP_NEXT, FALSE,
+ NULL },
+ { "tools-size-decrease-percent", GIMP_ICON_DIALOG_TOOL_OPTIONS,
+ NC_("tools-action", "Tool's Size: Decrease Relative"), NULL, NULL,
+ GIMP_ACTION_SELECT_PERCENT_PREVIOUS, FALSE,
+ NULL },
+ { "tools-size-increase-percent", GIMP_ICON_DIALOG_TOOL_OPTIONS,
+ NC_("tools-action", "Tool's Size: Increase Relative"), NULL, NULL,
+ GIMP_ACTION_SELECT_PERCENT_NEXT, FALSE,
+ NULL },
+};
+
+static const GimpEnumActionEntry tools_aspect_actions[] =
+{
+ { "tools-aspect-set", GIMP_ICON_DIALOG_TOOL_OPTIONS,
+ NC_("tools-action", "Tool's Aspect Ratio: Set"), NULL, NULL,
+ GIMP_ACTION_SELECT_SET, TRUE,
+ NULL },
+ { "tools-aspect-set-to-default", GIMP_ICON_DIALOG_TOOL_OPTIONS,
+ NC_("tools-action", "Tool's Aspect Ratio: Set To Default Value"), NULL, NULL,
+ GIMP_ACTION_SELECT_SET_TO_DEFAULT, FALSE,
+ NULL },
+ { "tools-aspect-minimum", GIMP_ICON_DIALOG_TOOL_OPTIONS,
+ NC_("tools-action", "Tool's Aspect Ratio: Minimize"), NULL, NULL,
+ GIMP_ACTION_SELECT_FIRST, FALSE,
+ NULL },
+ { "tools-aspect-maximum", GIMP_ICON_DIALOG_TOOL_OPTIONS,
+ NC_("tools-action", "Tool's Aspect Ratio: Maximize"), NULL, NULL,
+ GIMP_ACTION_SELECT_LAST, FALSE,
+ NULL },
+ { "tools-aspect-decrease", GIMP_ICON_DIALOG_TOOL_OPTIONS,
+ NC_("tools-action", "Tool's Aspect Ratio: Decrease by 0.1"), NULL, NULL,
+ GIMP_ACTION_SELECT_PREVIOUS, FALSE,
+ NULL },
+ { "tools-aspect-increase", GIMP_ICON_DIALOG_TOOL_OPTIONS,
+ NC_("tools-action", "Tool's Aspect Ratio: Increase by 0.1"), NULL, NULL,
+ GIMP_ACTION_SELECT_NEXT, FALSE,
+ NULL },
+ { "tools-aspect-decrease-skip", GIMP_ICON_DIALOG_TOOL_OPTIONS,
+ NC_("tools-action", "Tool's Aspect Ratio: Decrease by 1"), NULL, NULL,
+ GIMP_ACTION_SELECT_SKIP_PREVIOUS, FALSE,
+ NULL },
+ { "tools-aspect-increase-skip", GIMP_ICON_DIALOG_TOOL_OPTIONS,
+ NC_("tools-action", "Tool's Aspect Ratio: Increase by 1"), NULL, NULL,
+ GIMP_ACTION_SELECT_SKIP_NEXT, FALSE,
+ NULL },
+ { "tools-aspect-decrease-percent", GIMP_ICON_DIALOG_TOOL_OPTIONS,
+ NC_("tools-action", "Tool's Aspect Ratio: Decrease Relative"), NULL, NULL,
+ GIMP_ACTION_SELECT_PERCENT_PREVIOUS, FALSE,
+ NULL },
+ { "tools-aspect-increase-percent", GIMP_ICON_DIALOG_TOOL_OPTIONS,
+ NC_("tools-action", "Tool's Aspect Ratio: Increase Relative"), NULL, NULL,
+ GIMP_ACTION_SELECT_PERCENT_NEXT, FALSE,
+ NULL },
+};
+
+static const GimpEnumActionEntry tools_angle_actions[] =
+{
+ { "tools-angle-set", GIMP_ICON_DIALOG_TOOL_OPTIONS,
+ NC_("tools-action", "Tool's Angle: Set"), NULL, NULL,
+ GIMP_ACTION_SELECT_SET, TRUE,
+ NULL },
+ { "tools-angle-set-to-default", GIMP_ICON_DIALOG_TOOL_OPTIONS,
+ NC_("tools-action", "Tool's Angle: Set Angle To Default Value"), NULL, NULL,
+ GIMP_ACTION_SELECT_SET_TO_DEFAULT, FALSE,
+ NULL },
+ { "tools-angle-minimum", GIMP_ICON_DIALOG_TOOL_OPTIONS,
+ NC_("tools-action", "Tool's Angle: Minimize"), NULL, NULL,
+ GIMP_ACTION_SELECT_FIRST, FALSE,
+ NULL },
+ { "tools-angle-maximum", GIMP_ICON_DIALOG_TOOL_OPTIONS,
+ NC_("tools-action", "Tool's Angle: Maximize"), NULL, NULL,
+ GIMP_ACTION_SELECT_LAST, FALSE,
+ NULL },
+ { "tools-angle-decrease", GIMP_ICON_DIALOG_TOOL_OPTIONS,
+ NC_("tools-action", "Tool's Angle: Decrease by 1°"), NULL, NULL,
+ GIMP_ACTION_SELECT_PREVIOUS, FALSE,
+ NULL },
+ { "tools-angle-increase", GIMP_ICON_DIALOG_TOOL_OPTIONS,
+ NC_("tools-action", "Tool's Angle: Increase by 1°"), NULL, NULL,
+ GIMP_ACTION_SELECT_NEXT, FALSE,
+ NULL },
+ { "tools-angle-decrease-skip", GIMP_ICON_DIALOG_TOOL_OPTIONS,
+ NC_("tools-action", "Tool's Angle: Decrease by 15°"), NULL, NULL,
+ GIMP_ACTION_SELECT_SKIP_PREVIOUS, FALSE,
+ NULL },
+ { "tools-angle-increase-skip", GIMP_ICON_DIALOG_TOOL_OPTIONS,
+ NC_("tools-action", "Tool's Angle: Increase by 15°"), NULL, NULL,
+ GIMP_ACTION_SELECT_SKIP_NEXT, FALSE,
+ NULL },
+ { "tools-angle-decrease-percent", GIMP_ICON_DIALOG_TOOL_OPTIONS,
+ NC_("tools-action", "Tool's Angle: Decrease Relative"), NULL, NULL,
+ GIMP_ACTION_SELECT_PERCENT_PREVIOUS, FALSE,
+ NULL },
+ { "tools-angle-increase-percent", GIMP_ICON_DIALOG_TOOL_OPTIONS,
+ NC_("tools-action", "Tool's Angle: Increase Relative"), NULL, NULL,
+ GIMP_ACTION_SELECT_PERCENT_NEXT, FALSE,
+ NULL },
+};
+
+static const GimpEnumActionEntry tools_spacing_actions[] =
+{
+ { "tools-spacing-set", GIMP_ICON_DIALOG_TOOL_OPTIONS,
+ NC_("tools-action", "Tool's Spacing: Set"), NULL, NULL,
+ GIMP_ACTION_SELECT_SET, TRUE,
+ NULL },
+ { "tools-spacing-set-to-default", GIMP_ICON_DIALOG_TOOL_OPTIONS,
+ NC_("tools-action", "Tool's Spacing: Set To Default Value"), NULL, NULL,
+ GIMP_ACTION_SELECT_SET_TO_DEFAULT, FALSE,
+ NULL },
+ { "tools-spacing-minimum", GIMP_ICON_DIALOG_TOOL_OPTIONS,
+ NC_("tools-action", "Tool's Spacing: Minimize"), NULL, NULL,
+ GIMP_ACTION_SELECT_FIRST, FALSE,
+ NULL },
+ { "tools-spacing-maximum", GIMP_ICON_DIALOG_TOOL_OPTIONS,
+ NC_("tools-action", "Tool's Spacing: Maximize"), NULL, NULL,
+ GIMP_ACTION_SELECT_LAST, FALSE,
+ NULL },
+ { "tools-spacing-decrease", GIMP_ICON_DIALOG_TOOL_OPTIONS,
+ NC_("tools-action", "Tool's Spacing: Decrease by 1"), NULL, NULL,
+ GIMP_ACTION_SELECT_PREVIOUS, FALSE,
+ NULL },
+ { "tools-spacing-increase", GIMP_ICON_DIALOG_TOOL_OPTIONS,
+ NC_("tools-action", "Tool's Spacing: Increase by 1"), NULL, NULL,
+ GIMP_ACTION_SELECT_NEXT, FALSE,
+ NULL },
+ { "tools-spacing-decrease-skip", GIMP_ICON_DIALOG_TOOL_OPTIONS,
+ NC_("tools-action", "Tool's Spacing: Decrease by 10"), NULL, NULL,
+ GIMP_ACTION_SELECT_SKIP_PREVIOUS, FALSE,
+ NULL },
+ { "tools-spacing-increase-skip", GIMP_ICON_DIALOG_TOOL_OPTIONS,
+ NC_("tools-action", "Tool's Spacing: Increase by 10"), NULL, NULL,
+ GIMP_ACTION_SELECT_SKIP_NEXT, FALSE,
+ NULL },
+ { "tools-spacing-decrease-percent", GIMP_ICON_DIALOG_TOOL_OPTIONS,
+ NC_("tools-action", "Tool's Spacing: Decrease Relative"), NULL, NULL,
+ GIMP_ACTION_SELECT_PERCENT_PREVIOUS, FALSE,
+ NULL },
+ { "tools-spacing-increase-percent", GIMP_ICON_DIALOG_TOOL_OPTIONS,
+ NC_("tools-action", "Tool's Spacing: Increase Relative"), NULL, NULL,
+ GIMP_ACTION_SELECT_PERCENT_NEXT, FALSE,
+ NULL },
+};
+
+static const GimpEnumActionEntry tools_hardness_actions[] =
+{
+ { "tools-hardness-set", GIMP_ICON_DIALOG_TOOL_OPTIONS,
+ NC_("tools-action", "Tool's Hardness: Set"), NULL, NULL,
+ GIMP_ACTION_SELECT_SET, TRUE,
+ NULL },
+ { "tools-hardness-set-to-default", GIMP_ICON_DIALOG_TOOL_OPTIONS,
+ NC_("tools-action", "Tool's Hardness: Set to Default Value"), NULL, NULL,
+ GIMP_ACTION_SELECT_SET_TO_DEFAULT, FALSE,
+ NULL },
+ { "tools-hardness-minimum", GIMP_ICON_DIALOG_TOOL_OPTIONS,
+ NC_("tools-action", "Tool's Hardness: Minimize"), NULL, NULL,
+ GIMP_ACTION_SELECT_FIRST, FALSE,
+ NULL },
+ { "tools-hardness-maximum", GIMP_ICON_DIALOG_TOOL_OPTIONS,
+ NC_("tools-action", "Tool's Hardness: Maximize"), NULL, NULL,
+ GIMP_ACTION_SELECT_LAST, FALSE,
+ NULL },
+ { "tools-hardness-decrease", GIMP_ICON_DIALOG_TOOL_OPTIONS,
+ NC_("tools-action", "Tool's Hardness: Decrease by 1"), NULL, NULL,
+ GIMP_ACTION_SELECT_PREVIOUS, FALSE,
+ NULL },
+ { "tools-hardness-increase", GIMP_ICON_DIALOG_TOOL_OPTIONS,
+ NC_("tools-action", "Tool's Hardness: Increase by 1"), NULL, NULL,
+ GIMP_ACTION_SELECT_NEXT, FALSE,
+ NULL },
+ { "tools-hardness-decrease-skip", GIMP_ICON_DIALOG_TOOL_OPTIONS,
+ NC_("tools-action", "Tool's Hardness: Decrease by 10"), NULL, NULL,
+ GIMP_ACTION_SELECT_SKIP_PREVIOUS, FALSE,
+ NULL },
+ { "tools-hardness-increase-skip", GIMP_ICON_DIALOG_TOOL_OPTIONS,
+ NC_("tools-action", "Tool's Hardness: Increase by 10"), NULL, NULL,
+ GIMP_ACTION_SELECT_SKIP_NEXT, FALSE,
+ NULL },
+ { "tools-hardness-decrease-percent", GIMP_ICON_DIALOG_TOOL_OPTIONS,
+ NC_("tools-action", "Tool's Hardness: Decrease Relative"), NULL, NULL,
+ GIMP_ACTION_SELECT_PERCENT_PREVIOUS, FALSE,
+ NULL },
+ { "tools-hardness-increase-percent", GIMP_ICON_DIALOG_TOOL_OPTIONS,
+ NC_("tools-action", "Tool's Hardness: Increase Relative"), NULL, NULL,
+ GIMP_ACTION_SELECT_PERCENT_NEXT, FALSE,
+ NULL },
+};
+
+static const GimpEnumActionEntry tools_force_actions[] =
+{
+ { "tools-force-set", GIMP_ICON_DIALOG_TOOL_OPTIONS,
+ NC_("tools-action", "Tool's Force: Set"), NULL, NULL,
+ GIMP_ACTION_SELECT_SET, TRUE,
+ NULL },
+ { "tools-force-set-to-default", GIMP_ICON_DIALOG_TOOL_OPTIONS,
+ NC_("tools-action", "Tool's Force: Set to Default Value"), NULL, NULL,
+ GIMP_ACTION_SELECT_SET_TO_DEFAULT, FALSE,
+ NULL },
+ { "tools-force-minimum", GIMP_ICON_DIALOG_TOOL_OPTIONS,
+ NC_("tools-action", "Tool's Force: Minimize"), NULL, NULL,
+ GIMP_ACTION_SELECT_FIRST, FALSE,
+ NULL },
+ { "tools-force-maximum", GIMP_ICON_DIALOG_TOOL_OPTIONS,
+ NC_("tools-action", "Tool's Force: Maximize"), NULL, NULL,
+ GIMP_ACTION_SELECT_LAST, FALSE,
+ NULL },
+ { "tools-force-decrease", GIMP_ICON_DIALOG_TOOL_OPTIONS,
+ NC_("tools-action", "Tool's Force: Decrease by 1"), NULL, NULL,
+ GIMP_ACTION_SELECT_PREVIOUS, FALSE,
+ NULL },
+ { "tools-force-increase", GIMP_ICON_DIALOG_TOOL_OPTIONS,
+ NC_("tools-action", "Tool's Force: Increase by 1"), NULL, NULL,
+ GIMP_ACTION_SELECT_NEXT, FALSE,
+ NULL },
+ { "tools-force-decrease-skip", GIMP_ICON_DIALOG_TOOL_OPTIONS,
+ NC_("tools-action", "Tool's Force: Decrease by 10"), NULL, NULL,
+ GIMP_ACTION_SELECT_SKIP_PREVIOUS, FALSE,
+ NULL },
+ { "tools-force-increase-skip", GIMP_ICON_DIALOG_TOOL_OPTIONS,
+ NC_("tools-action", "Tool's Force: Increase by 10"), NULL, NULL,
+ GIMP_ACTION_SELECT_SKIP_NEXT, FALSE,
+ NULL },
+ { "tools-force-decrease-percent", GIMP_ICON_DIALOG_TOOL_OPTIONS,
+ NC_("tools-action", "Tool's Force: Decrease Relative"), NULL, NULL,
+ GIMP_ACTION_SELECT_PERCENT_PREVIOUS, FALSE,
+ NULL },
+ { "tools-force-increase-percent", GIMP_ICON_DIALOG_TOOL_OPTIONS,
+ NC_("tools-action", "Tool's Force: Increase Relative"), NULL, NULL,
+ GIMP_ACTION_SELECT_PERCENT_NEXT, FALSE,
+ NULL },
+};
+
+static const GimpEnumActionEntry tools_object_1_actions[] =
+{
+ { "tools-object-1-set", GIMP_ICON_DIALOG_TOOL_OPTIONS,
+ "Select Object 1 by Index", NULL, NULL,
+ GIMP_ACTION_SELECT_SET, TRUE,
+ NULL },
+ { "tools-object-1-first", GIMP_ICON_DIALOG_TOOL_OPTIONS,
+ "First Object 1", NULL, NULL,
+ GIMP_ACTION_SELECT_FIRST, FALSE,
+ NULL },
+ { "tools-object-1-last", GIMP_ICON_DIALOG_TOOL_OPTIONS,
+ "Last Object 1", NULL, NULL,
+ GIMP_ACTION_SELECT_LAST, FALSE,
+ NULL },
+ { "tools-object-1-previous", GIMP_ICON_DIALOG_TOOL_OPTIONS,
+ "Previous Object 1", NULL, NULL,
+ GIMP_ACTION_SELECT_PREVIOUS, FALSE,
+ NULL },
+ { "tools-object-1-next", GIMP_ICON_DIALOG_TOOL_OPTIONS,
+ "Next Object 1", NULL, NULL,
+ GIMP_ACTION_SELECT_NEXT, FALSE,
+ NULL }
+};
+
+static const GimpEnumActionEntry tools_object_2_actions[] =
+{
+ { "tools-object-2-set", GIMP_ICON_DIALOG_TOOL_OPTIONS,
+ "Select Object 2 by Index", NULL, NULL,
+ GIMP_ACTION_SELECT_SET, TRUE,
+ NULL },
+ { "tools-object-2-first", GIMP_ICON_DIALOG_TOOL_OPTIONS,
+ "First Object 2", NULL, NULL,
+ GIMP_ACTION_SELECT_FIRST, FALSE,
+ NULL },
+ { "tools-object-2-last", GIMP_ICON_DIALOG_TOOL_OPTIONS,
+ "Last Object 2", NULL, NULL,
+ GIMP_ACTION_SELECT_LAST, FALSE,
+ NULL },
+ { "tools-object-2-previous", GIMP_ICON_DIALOG_TOOL_OPTIONS,
+ "Previous Object 2", NULL, NULL,
+ GIMP_ACTION_SELECT_PREVIOUS, FALSE,
+ NULL },
+ { "tools-object-2-next", GIMP_ICON_DIALOG_TOOL_OPTIONS,
+ "Next Object 2", NULL, NULL,
+ GIMP_ACTION_SELECT_NEXT, FALSE,
+ NULL }
+};
+
+
+void
+tools_actions_setup (GimpActionGroup *group)
+{
+ GimpAction *action;
+ GList *list;
+
+ gimp_action_group_add_actions (group, "tools-action",
+ tools_actions,
+ G_N_ELEMENTS (tools_actions));
+
+ gimp_action_group_add_string_actions (group, "tools-action",
+ tools_alternative_actions,
+ G_N_ELEMENTS (tools_alternative_actions),
+ tools_select_cmd_callback);
+
+ action = gimp_action_group_get_action (group,
+ "tools-by-color-select-short");
+ gimp_action_set_accel_path (action, "<Actions>/tools/tools-by-color-select");
+
+ gimp_action_group_add_enum_actions (group, NULL,
+ tools_color_average_radius_actions,
+ G_N_ELEMENTS (tools_color_average_radius_actions),
+ tools_color_average_radius_cmd_callback);
+
+ gimp_action_group_add_enum_actions (group, NULL,
+ tools_paintbrush_size_actions,
+ G_N_ELEMENTS (tools_paintbrush_size_actions),
+ tools_paintbrush_size_cmd_callback);
+ gimp_action_group_add_enum_actions (group, NULL,
+ tools_paintbrush_aspect_ratio_actions,
+ G_N_ELEMENTS (tools_paintbrush_aspect_ratio_actions),
+ tools_paintbrush_aspect_ratio_cmd_callback);
+ gimp_action_group_add_enum_actions (group, NULL,
+ tools_paintbrush_angle_actions,
+ G_N_ELEMENTS (tools_paintbrush_angle_actions),
+ tools_paintbrush_angle_cmd_callback);
+ gimp_action_group_add_enum_actions (group, NULL,
+ tools_paintbrush_spacing_actions,
+ G_N_ELEMENTS (tools_paintbrush_spacing_actions),
+ tools_paintbrush_spacing_cmd_callback);
+ gimp_action_group_add_enum_actions (group, NULL,
+ tools_paintbrush_hardness_actions,
+ G_N_ELEMENTS (tools_paintbrush_hardness_actions),
+ tools_paintbrush_hardness_cmd_callback);
+ gimp_action_group_add_enum_actions (group, NULL,
+ tools_paintbrush_force_actions,
+ G_N_ELEMENTS (tools_paintbrush_force_actions),
+ tools_paintbrush_force_cmd_callback);
+
+ gimp_action_group_add_enum_actions (group, NULL,
+ tools_ink_blob_size_actions,
+ G_N_ELEMENTS (tools_ink_blob_size_actions),
+ tools_ink_blob_size_cmd_callback);
+ gimp_action_group_add_enum_actions (group, NULL,
+ tools_ink_blob_aspect_actions,
+ G_N_ELEMENTS (tools_ink_blob_aspect_actions),
+ tools_ink_blob_aspect_cmd_callback);
+ gimp_action_group_add_enum_actions (group, NULL,
+ tools_ink_blob_angle_actions,
+ G_N_ELEMENTS (tools_ink_blob_angle_actions),
+ tools_ink_blob_angle_cmd_callback);
+
+ gimp_action_group_add_enum_actions (group, "tools-action",
+ tools_airbrush_rate_actions,
+ G_N_ELEMENTS (tools_airbrush_rate_actions),
+ tools_airbrush_rate_cmd_callback);
+ gimp_action_group_add_enum_actions (group, "tools-action",
+ tools_airbrush_flow_actions,
+ G_N_ELEMENTS (tools_airbrush_flow_actions),
+ tools_airbrush_flow_cmd_callback);
+
+ gimp_action_group_add_enum_actions (group, NULL,
+ tools_mybrush_radius_actions,
+ G_N_ELEMENTS (tools_mybrush_radius_actions),
+ tools_mybrush_radius_cmd_callback);
+ gimp_action_group_add_enum_actions (group, NULL,
+ tools_mybrush_hardness_actions,
+ G_N_ELEMENTS (tools_mybrush_hardness_actions),
+ tools_mybrush_hardness_cmd_callback);
+
+ gimp_action_group_add_enum_actions (group, NULL,
+ tools_foreground_select_brush_size_actions,
+ G_N_ELEMENTS (tools_foreground_select_brush_size_actions),
+ tools_fg_select_brush_size_cmd_callback);
+
+ gimp_action_group_add_enum_actions (group, NULL,
+ tools_transform_preview_opacity_actions,
+ G_N_ELEMENTS (tools_transform_preview_opacity_actions),
+ tools_transform_preview_opacity_cmd_callback);
+
+ gimp_action_group_add_enum_actions (group, NULL,
+ tools_warp_effect_size_actions,
+ G_N_ELEMENTS (tools_warp_effect_size_actions),
+ tools_warp_effect_size_cmd_callback);
+ gimp_action_group_add_enum_actions (group, NULL,
+ tools_warp_effect_hardness_actions,
+ G_N_ELEMENTS (tools_warp_effect_hardness_actions),
+ tools_warp_effect_hardness_cmd_callback);
+
+ gimp_action_group_add_enum_actions (group, "tools-action",
+ tools_opacity_actions,
+ G_N_ELEMENTS (tools_opacity_actions),
+ tools_opacity_cmd_callback);
+ gimp_action_group_add_enum_actions (group, "tools-action",
+ tools_size_actions,
+ G_N_ELEMENTS (tools_size_actions),
+ tools_size_cmd_callback);
+ gimp_action_group_add_enum_actions (group, "tools-action",
+ tools_aspect_actions,
+ G_N_ELEMENTS (tools_aspect_actions),
+ tools_aspect_cmd_callback);
+ gimp_action_group_add_enum_actions (group, "tools-action",
+ tools_angle_actions,
+ G_N_ELEMENTS (tools_angle_actions),
+ tools_angle_cmd_callback);
+ gimp_action_group_add_enum_actions (group, "tools-action",
+ tools_spacing_actions,
+ G_N_ELEMENTS (tools_spacing_actions),
+ tools_spacing_cmd_callback);
+ gimp_action_group_add_enum_actions (group, "tools-action",
+ tools_hardness_actions,
+ G_N_ELEMENTS (tools_hardness_actions),
+ tools_hardness_cmd_callback);
+ gimp_action_group_add_enum_actions (group, "tools-action",
+ tools_force_actions,
+ G_N_ELEMENTS (tools_force_actions),
+ tools_force_cmd_callback);
+
+ gimp_action_group_add_enum_actions (group, NULL,
+ tools_object_1_actions,
+ G_N_ELEMENTS (tools_object_1_actions),
+ tools_object_1_cmd_callback);
+ gimp_action_group_add_enum_actions (group, NULL,
+ tools_object_2_actions,
+ G_N_ELEMENTS (tools_object_2_actions),
+ tools_object_2_cmd_callback);
+
+ for (list = gimp_get_tool_info_iter (group->gimp);
+ list;
+ list = g_list_next (list))
+ {
+ GimpToolInfo *tool_info = list->data;
+
+ if (tool_info->menu_label)
+ {
+ GimpStringActionEntry entry;
+ gchar *name;
+ const gchar *icon_name;
+ const gchar *identifier;
+
+ name = gimp_tool_info_get_action_name (tool_info);
+ icon_name = gimp_viewable_get_icon_name (GIMP_VIEWABLE (tool_info));
+ identifier = gimp_object_get_name (tool_info);
+
+ entry.name = name;
+ entry.icon_name = icon_name;
+ entry.label = tool_info->menu_label;
+ entry.accelerator = tool_info->menu_accel;
+ entry.tooltip = tool_info->tooltip;
+ entry.help_id = tool_info->help_id;
+ entry.value = identifier;
+
+ gimp_action_group_add_string_actions (group, NULL,
+ &entry, 1,
+ tools_select_cmd_callback);
+
+ g_free (name);
+ }
+ }
+}
+
+void
+tools_actions_update (GimpActionGroup *group,
+ gpointer data)
+{
+}
diff --git a/app/actions/tools-actions.h b/app/actions/tools-actions.h
new file mode 100644
index 0000000..9bec68b
--- /dev/null
+++ b/app/actions/tools-actions.h
@@ -0,0 +1,27 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __TOOLS_ACTIONS_H__
+#define __TOOLS_ACTIONS_H__
+
+
+void tools_actions_setup (GimpActionGroup *group);
+void tools_actions_update (GimpActionGroup *group,
+ gpointer data);
+
+
+#endif /* __TOOLS_ACTIONS_H__ */
diff --git a/app/actions/tools-commands.c b/app/actions/tools-commands.c
new file mode 100644
index 0000000..7e84c53
--- /dev/null
+++ b/app/actions/tools-commands.c
@@ -0,0 +1,820 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <string.h>
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpmath/gimpmath.h"
+
+#include "actions-types.h"
+
+#include "core/gimp.h"
+#include "core/gimpcontainer.h"
+#include "core/gimpcontext.h"
+#include "core/gimptoolinfo.h"
+
+#include "paint/gimpinkoptions.h"
+#include "paint/gimpairbrushoptions.h"
+#include "paint/gimpmybrushoptions.h"
+
+#include "widgets/gimpaction.h"
+#include "widgets/gimpenumaction.h"
+#include "widgets/gimpuimanager.h"
+
+#include "display/gimpdisplay.h"
+
+#include "tools/gimp-tools.h"
+#include "tools/gimpcoloroptions.h"
+#include "tools/gimpforegroundselectoptions.h"
+#include "tools/gimprectangleoptions.h"
+#include "tools/gimptool.h"
+#include "tools/gimptoolcontrol.h"
+#include "tools/gimptransformoptions.h"
+#include "tools/gimptransformtool.h"
+#include "tools/gimpwarpoptions.h"
+#include "tools/tool_manager.h"
+
+#include "actions.h"
+#include "tools-commands.h"
+
+
+/* local function prototypes */
+
+static void tools_activate_enum_action (const gchar *action_desc,
+ GVariant *value);
+
+
+/* local variables */
+
+/* this is a hack to allow GimpToolButton to activate a tool-selection action
+ * without initializing the tool
+ */
+static gint tools_select_cmd_initialize_blocked = 0;
+
+
+/* public functions */
+
+void
+tools_select_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ Gimp *gimp;
+ GimpToolInfo *tool_info;
+ GimpContext *context;
+ GimpDisplay *display;
+ const gchar *tool_name;
+ gboolean set_transform_type = FALSE;
+ GimpTransformType transform_type;
+ return_if_no_gimp (gimp, data);
+
+ tool_name = g_variant_get_string (value, NULL);
+
+ /* special case gimp-rotate-tool being called from the Image or Layer
+ * menus
+ */
+ if (strcmp (tool_name, "gimp-rotate-layer") == 0)
+ {
+ tool_name = "gimp-rotate-tool";
+ set_transform_type = TRUE;
+ transform_type = GIMP_TRANSFORM_TYPE_LAYER;
+ }
+ else if (strcmp (tool_name, "gimp-rotate-image") == 0)
+ {
+ tool_name = "gimp-rotate-tool";
+ set_transform_type = TRUE;
+ transform_type = GIMP_TRANSFORM_TYPE_IMAGE;
+ }
+
+ tool_info = gimp_get_tool_info (gimp, tool_name);
+
+ context = gimp_get_user_context (gimp);
+
+ /* always allocate a new tool when selected from the image menu
+ */
+ if (gimp_context_get_tool (context) != tool_info ||
+ tools_select_cmd_initialize_blocked)
+ {
+ gimp_context_set_tool (context, tool_info);
+ }
+ else
+ {
+ gimp_context_tool_changed (context);
+ }
+
+ if (set_transform_type)
+ {
+ GimpTool *tool = tool_manager_get_active (gimp);
+
+ gimp_transform_tool_set_type (GIMP_TRANSFORM_TOOL (tool),
+ transform_type);
+ }
+
+ if (! tools_select_cmd_initialize_blocked)
+ {
+ display = gimp_context_get_display (context);
+
+ if (display && gimp_display_get_image (display))
+ tool_manager_initialize_active (gimp, display);
+ }
+}
+
+void
+tools_select_cmd_block_initialize (void)
+{
+ tools_select_cmd_initialize_blocked++;
+}
+
+void
+tools_select_cmd_unblock_initialize (void)
+{
+ g_return_if_fail (tools_select_cmd_initialize_blocked > 0);
+
+ tools_select_cmd_initialize_blocked--;
+}
+
+void
+tools_color_average_radius_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpContext *context;
+ GimpToolInfo *tool_info;
+ GimpActionSelectType select_type;
+ return_if_no_context (context, data);
+
+ select_type = (GimpActionSelectType) g_variant_get_int32 (value);
+
+ tool_info = gimp_context_get_tool (context);
+
+ if (tool_info && GIMP_IS_COLOR_OPTIONS (tool_info->tool_options))
+ {
+ action_select_property (select_type,
+ action_data_get_display (data),
+ G_OBJECT (tool_info->tool_options),
+ "average-radius",
+ 1.0, 1.0, 10.0, 0.1, FALSE);
+ }
+}
+
+void
+tools_paintbrush_size_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpContext *context;
+ GimpToolInfo *tool_info;
+ GimpActionSelectType select_type;
+ return_if_no_context (context, data);
+
+ select_type = (GimpActionSelectType) g_variant_get_int32 (value);
+
+ tool_info = gimp_context_get_tool (context);
+
+ if (tool_info && GIMP_IS_PAINT_OPTIONS (tool_info->tool_options))
+ {
+ action_select_property (select_type,
+ action_data_get_display (data),
+ G_OBJECT (tool_info->tool_options),
+ "brush-size",
+ 0.1, 1.0, 10.0, 1.0, FALSE);
+ }
+}
+
+void
+tools_paintbrush_angle_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpContext *context;
+ GimpToolInfo *tool_info;
+ GimpActionSelectType select_type;
+ return_if_no_context (context, data);
+
+ select_type = (GimpActionSelectType) g_variant_get_int32 (value);
+
+ tool_info = gimp_context_get_tool (context);
+
+ if (tool_info && GIMP_IS_PAINT_OPTIONS (tool_info->tool_options))
+ {
+ action_select_property (select_type,
+ action_data_get_display (data),
+ G_OBJECT (tool_info->tool_options),
+ "brush-angle",
+ 0.1, 1.0, 15.0, 0.1, TRUE);
+ }
+}
+
+void
+tools_paintbrush_aspect_ratio_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpContext *context;
+ GimpToolInfo *tool_info;
+ GimpActionSelectType select_type;
+ return_if_no_context (context, data);
+
+ select_type = (GimpActionSelectType) g_variant_get_int32 (value);
+
+ tool_info = gimp_context_get_tool (context);
+
+ if (tool_info && GIMP_IS_PAINT_OPTIONS (tool_info->tool_options))
+ {
+ action_select_property (select_type,
+ action_data_get_display (data),
+ G_OBJECT (tool_info->tool_options),
+ "brush-aspect-ratio",
+ 0.01, 0.1, 1.0, 0.1, TRUE);
+ }
+}
+
+void
+tools_paintbrush_spacing_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpContext *context;
+ GimpToolInfo *tool_info;
+ GimpActionSelectType select_type;
+ return_if_no_context (context, data);
+
+ select_type = (GimpActionSelectType) g_variant_get_int32 (value);
+
+ tool_info = gimp_context_get_tool (context);
+
+ if (tool_info && GIMP_IS_PAINT_OPTIONS (tool_info->tool_options))
+ {
+ action_select_property (select_type,
+ action_data_get_display (data),
+ G_OBJECT (tool_info->tool_options),
+ "brush-spacing",
+ 0.001, 0.01, 0.1, 0.1, FALSE);
+ }
+}
+
+void
+tools_paintbrush_hardness_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpContext *context;
+ GimpToolInfo *tool_info;
+ GimpActionSelectType select_type;
+ return_if_no_context (context, data);
+
+ select_type = (GimpActionSelectType) g_variant_get_int32 (value);
+
+ tool_info = gimp_context_get_tool (context);
+
+ if (tool_info && GIMP_IS_PAINT_OPTIONS (tool_info->tool_options))
+ {
+ action_select_property (select_type,
+ action_data_get_display (data),
+ G_OBJECT (tool_info->tool_options),
+ "brush-hardness",
+ 0.001, 0.01, 0.1, 0.1, FALSE);
+ }
+}
+
+void
+tools_paintbrush_force_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpContext *context;
+ GimpToolInfo *tool_info;
+ GimpActionSelectType select_type;
+ return_if_no_context (context, data);
+
+ select_type = (GimpActionSelectType) g_variant_get_int32 (value);
+
+ tool_info = gimp_context_get_tool (context);
+
+ if (tool_info && GIMP_IS_PAINT_OPTIONS (tool_info->tool_options))
+ {
+ action_select_property (select_type,
+ action_data_get_display (data),
+ G_OBJECT (tool_info->tool_options),
+ "brush-force",
+ 0.001, 0.01, 0.1, 0.1, FALSE);
+ }
+}
+
+void
+tools_ink_blob_size_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpContext *context;
+ GimpToolInfo *tool_info;
+ GimpActionSelectType select_type;
+ return_if_no_context (context, data);
+
+ select_type = (GimpActionSelectType) g_variant_get_int32 (value);
+
+ tool_info = gimp_context_get_tool (context);
+
+ if (tool_info && GIMP_IS_INK_OPTIONS (tool_info->tool_options))
+ {
+ action_select_property (select_type,
+ action_data_get_display (data),
+ G_OBJECT (tool_info->tool_options),
+ "size",
+ 0.1, 1.0, 10.0, 0.1, FALSE);
+ }
+}
+
+void
+tools_ink_blob_aspect_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpContext *context;
+ GimpToolInfo *tool_info;
+ GimpActionSelectType select_type;
+ return_if_no_context (context, data);
+
+ select_type = (GimpActionSelectType) g_variant_get_int32 (value);
+
+ tool_info = gimp_context_get_tool (context);
+
+ if (tool_info && GIMP_IS_INK_OPTIONS (tool_info->tool_options))
+ {
+ action_select_property (select_type,
+ action_data_get_display (data),
+ G_OBJECT (tool_info->tool_options),
+ "blob-aspect",
+ 1.0, 0.1, 1.0, 0.1, FALSE);
+ }
+}
+
+void
+tools_ink_blob_angle_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpContext *context;
+ GimpToolInfo *tool_info;
+ GimpActionSelectType select_type;
+ return_if_no_context (context, data);
+
+ select_type = (GimpActionSelectType) g_variant_get_int32 (value);
+
+ tool_info = gimp_context_get_tool (context);
+
+ if (tool_info && GIMP_IS_INK_OPTIONS (tool_info->tool_options))
+ {
+ action_select_property (select_type,
+ action_data_get_display (data),
+ G_OBJECT (tool_info->tool_options),
+ "blob-angle",
+ gimp_deg_to_rad (0.1),
+ gimp_deg_to_rad (1.0),
+ gimp_deg_to_rad (15.0),
+ 0.1, TRUE);
+ }
+}
+
+void
+tools_airbrush_rate_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpContext *context;
+ GimpToolInfo *tool_info;
+ GimpActionSelectType select_type;
+ return_if_no_context (context, data);
+
+ select_type = (GimpActionSelectType) g_variant_get_int32 (value);
+
+ tool_info = gimp_context_get_tool (context);
+
+ if (tool_info && GIMP_IS_AIRBRUSH_OPTIONS (tool_info->tool_options))
+ {
+ action_select_property (select_type,
+ action_data_get_display (data),
+ G_OBJECT (tool_info->tool_options),
+ "rate",
+ 0.1, 1.0, 10.0, 0.1, FALSE);
+ }
+}
+
+void
+tools_airbrush_flow_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpContext *context;
+ GimpToolInfo *tool_info;
+ GimpActionSelectType select_type;
+ return_if_no_context (context, data);
+
+ select_type = (GimpActionSelectType) g_variant_get_int32 (value);
+
+ tool_info = gimp_context_get_tool (context);
+
+ if (tool_info && GIMP_IS_AIRBRUSH_OPTIONS (tool_info->tool_options))
+ {
+ action_select_property (select_type,
+ action_data_get_display (data),
+ G_OBJECT (tool_info->tool_options),
+ "flow",
+ 0.1, 1.0, 10.0, 0.1, FALSE);
+ }
+}
+
+void
+tools_mybrush_radius_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpContext *context;
+ GimpToolInfo *tool_info;
+ GimpActionSelectType select_type;
+ return_if_no_context (context, data);
+
+ select_type = (GimpActionSelectType) g_variant_get_int32 (value);
+
+ tool_info = gimp_context_get_tool (context);
+
+ if (tool_info && GIMP_IS_MYBRUSH_OPTIONS (tool_info->tool_options))
+ {
+ action_select_property (select_type,
+ action_data_get_display (data),
+ G_OBJECT (tool_info->tool_options),
+ "radius",
+ 0.1, 0.1, 0.5, 1.0, FALSE);
+ }
+}
+
+void
+tools_mybrush_hardness_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpContext *context;
+ GimpToolInfo *tool_info;
+ GimpActionSelectType select_type;
+ return_if_no_context (context, data);
+
+ select_type = (GimpActionSelectType) g_variant_get_int32 (value);
+
+ tool_info = gimp_context_get_tool (context);
+
+ if (tool_info && GIMP_IS_MYBRUSH_OPTIONS (tool_info->tool_options))
+ {
+ action_select_property (select_type,
+ action_data_get_display (data),
+ G_OBJECT (tool_info->tool_options),
+ "hardness",
+ 0.001, 0.01, 0.1, 1.0, FALSE);
+ }
+}
+
+void
+tools_fg_select_brush_size_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpContext *context;
+ GimpToolInfo *tool_info;
+ GimpActionSelectType select_type;
+ return_if_no_context (context, data);
+
+ select_type = (GimpActionSelectType) g_variant_get_int32 (value);
+
+ tool_info = gimp_context_get_tool (context);
+
+ if (tool_info && GIMP_IS_FOREGROUND_SELECT_OPTIONS (tool_info->tool_options))
+ {
+ action_select_property (select_type,
+ action_data_get_display (data),
+ G_OBJECT (tool_info->tool_options),
+ "stroke-width",
+ 1.0, 4.0, 16.0, 0.1, FALSE);
+ }
+}
+
+void
+tools_transform_preview_opacity_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpContext *context;
+ GimpToolInfo *tool_info;
+ GimpActionSelectType select_type;
+ return_if_no_context (context, data);
+
+ select_type = (GimpActionSelectType) g_variant_get_int32 (value);
+
+ tool_info = gimp_context_get_tool (context);
+
+ if (tool_info && GIMP_IS_TRANSFORM_OPTIONS (tool_info->tool_options))
+ {
+ action_select_property (select_type,
+ action_data_get_display (data),
+ G_OBJECT (tool_info->tool_options),
+ "preview-opacity",
+ 0.01, 0.1, 0.5, 0.1, FALSE);
+ }
+}
+
+void
+tools_warp_effect_size_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpContext *context;
+ GimpToolInfo *tool_info;
+ GimpActionSelectType select_type;
+ return_if_no_context (context, data);
+
+ select_type = (GimpActionSelectType) g_variant_get_int32 (value);
+
+ tool_info = gimp_context_get_tool (context);
+
+ if (tool_info && GIMP_IS_WARP_OPTIONS (tool_info->tool_options))
+ {
+ action_select_property (select_type,
+ action_data_get_display (data),
+ G_OBJECT (tool_info->tool_options),
+ "effect-size",
+ 1.0, 4.0, 16.0, 0.1, FALSE);
+ }
+}
+
+void
+tools_warp_effect_hardness_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpContext *context;
+ GimpToolInfo *tool_info;
+ GimpActionSelectType select_type;
+ return_if_no_context (context, data);
+
+ select_type = (GimpActionSelectType) g_variant_get_int32 (value);
+
+ tool_info = gimp_context_get_tool (context);
+
+ if (tool_info && GIMP_IS_WARP_OPTIONS (tool_info->tool_options))
+ {
+ action_select_property (select_type,
+ action_data_get_display (data),
+ G_OBJECT (tool_info->tool_options),
+ "effect-hardness",
+ 0.001, 0.01, 0.1, 0.1, FALSE);
+ }
+}
+
+void
+tools_opacity_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpContext *context;
+ GimpTool *tool;
+ return_if_no_context (context, data);
+
+ tool = tool_manager_get_active (context->gimp);
+
+ if (tool)
+ {
+ const gchar *action_desc;
+
+ action_desc = gimp_tool_control_get_action_opacity (tool->control);
+
+ if (action_desc)
+ tools_activate_enum_action (action_desc, value);
+ }
+}
+
+void
+tools_size_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpContext *context;
+ GimpTool *tool;
+ return_if_no_context (context, data);
+
+ tool = tool_manager_get_active (context->gimp);
+
+ if (tool)
+ {
+ const gchar *action_desc;
+
+ action_desc = gimp_tool_control_get_action_size (tool->control);
+
+ if (action_desc)
+ tools_activate_enum_action (action_desc, value);
+ }
+}
+
+void
+tools_aspect_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpContext *context;
+ GimpTool *tool;
+ return_if_no_context (context, data);
+
+ tool = tool_manager_get_active (context->gimp);
+
+ if (tool)
+ {
+ const gchar *action_desc;
+
+ action_desc = gimp_tool_control_get_action_aspect (tool->control);
+
+ if (action_desc)
+ tools_activate_enum_action (action_desc, value);
+ }
+}
+
+void
+tools_angle_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpContext *context;
+ GimpTool *tool;
+ return_if_no_context (context, data);
+
+ tool = tool_manager_get_active (context->gimp);
+
+ if (tool)
+ {
+ const gchar *action_desc;
+
+ action_desc = gimp_tool_control_get_action_angle (tool->control);
+
+ if (action_desc)
+ tools_activate_enum_action (action_desc, value);
+ }
+}
+
+void
+tools_spacing_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpContext *context;
+ GimpTool *tool;
+ return_if_no_context (context, data);
+
+ tool = tool_manager_get_active (context->gimp);
+
+ if (tool)
+ {
+ const gchar *action_desc;
+
+ action_desc = gimp_tool_control_get_action_spacing (tool->control);
+
+ if (action_desc)
+ tools_activate_enum_action (action_desc, value);
+ }
+}
+
+void
+tools_hardness_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpContext *context;
+ GimpTool *tool;
+ return_if_no_context (context, data);
+
+ tool = tool_manager_get_active (context->gimp);
+
+ if (tool)
+ {
+ const gchar *action_desc;
+
+ action_desc = gimp_tool_control_get_action_hardness (tool->control);
+
+ if (action_desc)
+ tools_activate_enum_action (action_desc, value);
+ }
+}
+
+void
+tools_force_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpContext *context;
+ GimpTool *tool;
+ return_if_no_context (context, data);
+
+ tool = tool_manager_get_active (context->gimp);
+
+ if (tool)
+ {
+ const gchar *action_desc;
+
+ action_desc = gimp_tool_control_get_action_force (tool->control);
+
+ if (action_desc)
+ tools_activate_enum_action (action_desc, value);
+ }
+}
+
+void
+tools_object_1_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpContext *context;
+ GimpTool *tool;
+ return_if_no_context (context, data);
+
+ tool = tool_manager_get_active (context->gimp);
+
+ if (tool)
+ {
+ const gchar *action_desc;
+
+ action_desc = gimp_tool_control_get_action_object_1 (tool->control);
+
+ if (action_desc)
+ tools_activate_enum_action (action_desc, value);
+ }
+}
+
+void
+tools_object_2_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpContext *context;
+ GimpTool *tool;
+ return_if_no_context (context, data);
+
+ tool = tool_manager_get_active (context->gimp);
+
+ if (tool)
+ {
+ const gchar *action_desc;
+
+ action_desc = gimp_tool_control_get_action_object_2 (tool->control);
+
+ if (action_desc)
+ tools_activate_enum_action (action_desc, value);
+ }
+}
+
+
+/* private functions */
+
+static void
+tools_activate_enum_action (const gchar *action_desc,
+ GVariant *value)
+{
+ gchar *group_name;
+ gchar *action_name;
+
+ group_name = g_strdup (action_desc);
+ action_name = strchr (group_name, '/');
+
+ if (action_name)
+ {
+ GList *managers;
+ GimpAction *action;
+
+ *action_name++ = '\0';
+
+ managers = gimp_ui_managers_from_name ("<Image>");
+
+ action = gimp_ui_manager_find_action (managers->data,
+ group_name, action_name);
+
+ if (GIMP_IS_ENUM_ACTION (action) &&
+ GIMP_ENUM_ACTION (action)->value_variable)
+ {
+ gimp_action_emit_activate (GIMP_ACTION (action), value);
+ }
+ }
+
+ g_free (group_name);
+}
diff --git a/app/actions/tools-commands.h b/app/actions/tools-commands.h
new file mode 100644
index 0000000..38ab455
--- /dev/null
+++ b/app/actions/tools-commands.h
@@ -0,0 +1,120 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __TOOLS_COMMANDS_H__
+#define __TOOLS_COMMANDS_H__
+
+
+void tools_select_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void tools_select_cmd_block_initialize (void);
+void tools_select_cmd_unblock_initialize (void);
+
+void tools_color_average_radius_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+void tools_paintbrush_size_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void tools_paintbrush_angle_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void tools_paintbrush_aspect_ratio_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void tools_paintbrush_spacing_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void tools_paintbrush_hardness_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void tools_paintbrush_force_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+void tools_ink_blob_size_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void tools_ink_blob_aspect_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void tools_ink_blob_angle_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+void tools_airbrush_rate_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void tools_airbrush_flow_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+void tools_mybrush_radius_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void tools_mybrush_hardness_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+void tools_fg_select_brush_size_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+void tools_transform_preview_opacity_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+void tools_warp_effect_size_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void tools_warp_effect_hardness_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+void tools_opacity_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void tools_size_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void tools_aspect_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void tools_angle_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void tools_spacing_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void tools_hardness_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void tools_force_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+void tools_object_1_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void tools_object_2_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+
+#endif /* __TOOLS_COMMANDS_H__ */
diff --git a/app/actions/vectors-actions.c b/app/actions/vectors-actions.c
new file mode 100644
index 0000000..300203b
--- /dev/null
+++ b/app/actions/vectors-actions.c
@@ -0,0 +1,465 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "actions-types.h"
+
+#include "core/gimpchannel.h"
+#include "core/gimpcontainer.h"
+#include "core/gimpimage.h"
+
+#include "widgets/gimpactiongroup.h"
+#include "widgets/gimphelp-ids.h"
+#include "widgets/gimpwidgets-utils.h"
+
+#include "actions.h"
+#include "items-actions.h"
+#include "vectors-actions.h"
+#include "vectors-commands.h"
+
+#include "gimp-intl.h"
+
+
+static const GimpActionEntry vectors_actions[] =
+{
+ { "vectors-popup", GIMP_ICON_DIALOG_PATHS,
+ NC_("vectors-action", "Paths Menu"), NULL, NULL, NULL,
+ GIMP_HELP_PATH_DIALOG },
+
+ { "vectors-color-tag-menu", NULL,
+ NC_("vectors-action", "Color Tag"), NULL, NULL, NULL,
+ GIMP_HELP_PATH_COLOR_TAG },
+
+ { "vectors-edit", GIMP_ICON_TOOL_PATH,
+ NC_("vectors-action", "Edit Pa_th"), NULL,
+ NC_("vectors-action", "Edit the active path"),
+ vectors_edit_cmd_callback,
+ GIMP_HELP_TOOL_VECTORS },
+
+ { "vectors-edit-attributes", GIMP_ICON_EDIT,
+ NC_("vectors-action", "_Edit Path Attributes..."), NULL,
+ NC_("vectors-action", "Edit path attributes"),
+ vectors_edit_attributes_cmd_callback,
+ GIMP_HELP_PATH_EDIT },
+
+ { "vectors-new", GIMP_ICON_DOCUMENT_NEW,
+ NC_("vectors-action", "_New Path..."), NULL,
+ NC_("vectors-action", "Create a new path..."),
+ vectors_new_cmd_callback,
+ GIMP_HELP_PATH_NEW },
+
+ { "vectors-new-last-values", GIMP_ICON_DOCUMENT_NEW,
+ NC_("vectors-action", "_New Path with last values"), NULL,
+ NC_("vectors-action", "Create a new path with last used values"),
+ vectors_new_last_vals_cmd_callback,
+ GIMP_HELP_PATH_NEW },
+
+ { "vectors-duplicate", GIMP_ICON_OBJECT_DUPLICATE,
+ NC_("vectors-action", "D_uplicate Path"), NULL,
+ NC_("vectors-action", "Duplicate this path"),
+ vectors_duplicate_cmd_callback,
+ GIMP_HELP_PATH_DUPLICATE },
+
+ { "vectors-delete", GIMP_ICON_EDIT_DELETE,
+ NC_("vectors-action", "_Delete Path"), NULL,
+ NC_("vectors-action", "Delete this path"),
+ vectors_delete_cmd_callback,
+ GIMP_HELP_PATH_DELETE },
+
+ { "vectors-merge-visible", NULL,
+ NC_("vectors-action", "Merge _Visible Paths"), NULL, NULL,
+ vectors_merge_visible_cmd_callback,
+ GIMP_HELP_PATH_MERGE_VISIBLE },
+
+ { "vectors-raise", GIMP_ICON_GO_UP,
+ NC_("vectors-action", "_Raise Path"), NULL,
+ NC_("vectors-action", "Raise this path"),
+ vectors_raise_cmd_callback,
+ GIMP_HELP_PATH_RAISE },
+
+ { "vectors-raise-to-top", GIMP_ICON_GO_TOP,
+ NC_("vectors-action", "Raise Path to _Top"), NULL,
+ NC_("vectors-action", "Raise this path to the top"),
+ vectors_raise_to_top_cmd_callback,
+ GIMP_HELP_PATH_RAISE_TO_TOP },
+
+ { "vectors-lower", GIMP_ICON_GO_DOWN,
+ NC_("vectors-action", "_Lower Path"), NULL,
+ NC_("vectors-action", "Lower this path"),
+ vectors_lower_cmd_callback,
+ GIMP_HELP_PATH_LOWER },
+
+ { "vectors-lower-to-bottom", GIMP_ICON_GO_BOTTOM,
+ NC_("vectors-action", "Lower Path to _Bottom"), NULL,
+ NC_("vectors-action", "Lower this path to the bottom"),
+ vectors_lower_to_bottom_cmd_callback,
+ GIMP_HELP_PATH_LOWER_TO_BOTTOM },
+
+ { "vectors-fill", GIMP_ICON_TOOL_BUCKET_FILL,
+ NC_("vectors-action", "Fill Pat_h..."), NULL,
+ NC_("vectors-action", "Fill the path"),
+ vectors_fill_cmd_callback,
+ GIMP_HELP_PATH_FILL },
+
+ { "vectors-fill-last-values", GIMP_ICON_TOOL_BUCKET_FILL,
+ NC_("vectors-action", "Fill Path"), NULL,
+ NC_("vectors-action", "Fill the path with last values"),
+ vectors_fill_last_vals_cmd_callback,
+ GIMP_HELP_PATH_FILL },
+
+ { "vectors-stroke", GIMP_ICON_PATH_STROKE,
+ NC_("vectors-action", "Stro_ke Path..."), NULL,
+ NC_("vectors-action", "Paint along the path"),
+ vectors_stroke_cmd_callback,
+ GIMP_HELP_PATH_STROKE },
+
+ { "vectors-stroke-last-values", GIMP_ICON_PATH_STROKE,
+ NC_("vectors-action", "Stro_ke Path"), NULL,
+ NC_("vectors-action", "Paint along the path with last values"),
+ vectors_stroke_last_vals_cmd_callback,
+ GIMP_HELP_PATH_STROKE },
+
+ { "vectors-copy", GIMP_ICON_EDIT_COPY,
+ NC_("vectors-action", "Co_py Path"), "", NULL,
+ vectors_copy_cmd_callback,
+ GIMP_HELP_PATH_COPY },
+
+ { "vectors-paste", GIMP_ICON_EDIT_PASTE,
+ NC_("vectors-action", "Paste Pat_h"), "", NULL,
+ vectors_paste_cmd_callback,
+ GIMP_HELP_PATH_PASTE },
+
+ { "vectors-export", GIMP_ICON_DOCUMENT_SAVE,
+ NC_("vectors-action", "E_xport Path..."), "", NULL,
+ vectors_export_cmd_callback,
+ GIMP_HELP_PATH_EXPORT },
+
+ { "vectors-import", GIMP_ICON_DOCUMENT_OPEN,
+ NC_("vectors-action", "I_mport Path..."), "", NULL,
+ vectors_import_cmd_callback,
+ GIMP_HELP_PATH_IMPORT }
+};
+
+static const GimpToggleActionEntry vectors_toggle_actions[] =
+{
+ { "vectors-visible", GIMP_ICON_VISIBLE,
+ NC_("vectors-action", "Toggle Path _Visibility"), NULL, NULL,
+ vectors_visible_cmd_callback,
+ FALSE,
+ GIMP_HELP_PATH_VISIBLE },
+
+ { "vectors-linked", GIMP_ICON_LINKED,
+ NC_("vectors-action", "Toggle Path _Linked State"), NULL, NULL,
+ vectors_linked_cmd_callback,
+ FALSE,
+ GIMP_HELP_PATH_LINKED },
+
+ { "vectors-lock-content", NULL /* GIMP_ICON_LOCK */,
+ NC_("vectors-action", "L_ock Strokes of Path"), NULL, NULL,
+ vectors_lock_content_cmd_callback,
+ FALSE,
+ GIMP_HELP_PATH_LOCK_STROKES },
+
+ { "vectors-lock-position", GIMP_ICON_TOOL_MOVE,
+ NC_("vectors-action", "L_ock Position of Path"), NULL, NULL,
+ vectors_lock_position_cmd_callback,
+ FALSE,
+ GIMP_HELP_PATH_LOCK_POSITION }
+};
+
+static const GimpEnumActionEntry vectors_color_tag_actions[] =
+{
+ { "vectors-color-tag-none", GIMP_ICON_EDIT_CLEAR,
+ NC_("vectors-action", "None"), NULL,
+ NC_("vectors-action", "Path Color Tag: Clear"),
+ GIMP_COLOR_TAG_NONE, FALSE,
+ GIMP_HELP_PATH_COLOR_TAG },
+
+ { "vectors-color-tag-blue", NULL,
+ NC_("vectors-action", "Blue"), NULL,
+ NC_("vectors-action", "Path Color Tag: Set to Blue"),
+ GIMP_COLOR_TAG_BLUE, FALSE,
+ GIMP_HELP_PATH_COLOR_TAG },
+
+ { "vectors-color-tag-green", NULL,
+ NC_("vectors-action", "Green"), NULL,
+ NC_("vectors-action", "Path Color Tag: Set to Green"),
+ GIMP_COLOR_TAG_GREEN, FALSE,
+ GIMP_HELP_PATH_COLOR_TAG },
+
+ { "vectors-color-tag-yellow", NULL,
+ NC_("vectors-action", "Yellow"), NULL,
+ NC_("vectors-action", "Path Color Tag: Set to Yellow"),
+ GIMP_COLOR_TAG_YELLOW, FALSE,
+ GIMP_HELP_PATH_COLOR_TAG },
+
+ { "vectors-color-tag-orange", NULL,
+ NC_("vectors-action", "Orange"), NULL,
+ NC_("vectors-action", "Path Color Tag: Set to Orange"),
+ GIMP_COLOR_TAG_ORANGE, FALSE,
+ GIMP_HELP_PATH_COLOR_TAG },
+
+ { "vectors-color-tag-brown", NULL,
+ NC_("vectors-action", "Brown"), NULL,
+ NC_("vectors-action", "Path Color Tag: Set to Brown"),
+ GIMP_COLOR_TAG_BROWN, FALSE,
+ GIMP_HELP_PATH_COLOR_TAG },
+
+ { "vectors-color-tag-red", NULL,
+ NC_("vectors-action", "Red"), NULL,
+ NC_("vectors-action", "Path Color Tag: Set to Red"),
+ GIMP_COLOR_TAG_RED, FALSE,
+ GIMP_HELP_PATH_COLOR_TAG },
+
+ { "vectors-color-tag-violet", NULL,
+ NC_("vectors-action", "Violet"), NULL,
+ NC_("vectors-action", "Path Color Tag: Set to Violet"),
+ GIMP_COLOR_TAG_VIOLET, FALSE,
+ GIMP_HELP_PATH_COLOR_TAG },
+
+ { "vectors-color-tag-gray", NULL,
+ NC_("vectors-action", "Gray"), NULL,
+ NC_("vectors-action", "Path Color Tag: Set to Gray"),
+ GIMP_COLOR_TAG_GRAY, FALSE,
+ GIMP_HELP_PATH_COLOR_TAG }
+};
+
+static const GimpEnumActionEntry vectors_to_selection_actions[] =
+{
+ { "vectors-selection-replace", GIMP_ICON_SELECTION_REPLACE,
+ NC_("vectors-action", "Path to Sele_ction"), NULL,
+ NC_("vectors-action", "Path to selection"),
+ GIMP_CHANNEL_OP_REPLACE, FALSE,
+ GIMP_HELP_PATH_SELECTION_REPLACE },
+
+ { "vectors-selection-from-vectors", GIMP_ICON_SELECTION_REPLACE,
+ NC_("vectors-action", "Fr_om Path"), "<shift>V",
+ NC_("vectors-action", "Replace selection with path"),
+ GIMP_CHANNEL_OP_REPLACE, FALSE,
+ GIMP_HELP_PATH_SELECTION_REPLACE },
+
+ { "vectors-selection-add", GIMP_ICON_SELECTION_ADD,
+ NC_("vectors-action", "_Add to Selection"), NULL,
+ NC_("vectors-action", "Add path to selection"),
+ GIMP_CHANNEL_OP_ADD, FALSE,
+ GIMP_HELP_PATH_SELECTION_ADD },
+
+ { "vectors-selection-subtract", GIMP_ICON_SELECTION_SUBTRACT,
+ NC_("vectors-action", "_Subtract from Selection"), NULL,
+ NC_("vectors-action", "Subtract path from selection"),
+ GIMP_CHANNEL_OP_SUBTRACT, FALSE,
+ GIMP_HELP_PATH_SELECTION_SUBTRACT },
+
+ { "vectors-selection-intersect", GIMP_ICON_SELECTION_INTERSECT,
+ NC_("vectors-action", "_Intersect with Selection"), NULL,
+ NC_("vectors-action", "Intersect path with selection"),
+ GIMP_CHANNEL_OP_INTERSECT, FALSE,
+ GIMP_HELP_PATH_SELECTION_INTERSECT }
+};
+
+static const GimpEnumActionEntry vectors_selection_to_vectors_actions[] =
+{
+ { "vectors-selection-to-vectors", GIMP_ICON_SELECTION_TO_PATH,
+ NC_("vectors-action", "Selecti_on to Path"), NULL,
+ NC_("vectors-action", "Selection to path"),
+ FALSE, FALSE,
+ GIMP_HELP_SELECTION_TO_PATH },
+
+ { "vectors-selection-to-vectors-short", GIMP_ICON_SELECTION_TO_PATH,
+ NC_("vectors-action", "To _Path"), NULL,
+ NC_("vectors-action", "Selection to path"),
+ FALSE, FALSE,
+ GIMP_HELP_SELECTION_TO_PATH },
+
+ { "vectors-selection-to-vectors-advanced", GIMP_ICON_SELECTION_TO_PATH,
+ NC_("vectors-action", "Selection to Path (_Advanced)"), NULL,
+ NC_("vectors-action", "Advanced options"),
+ TRUE, FALSE,
+ GIMP_HELP_SELECTION_TO_PATH }
+};
+
+static const GimpEnumActionEntry vectors_select_actions[] =
+{
+ { "vectors-select-top", NULL,
+ NC_("vectors-action", "Select _Top Path"), NULL,
+ NC_("vectors-action", "Select the topmost path"),
+ GIMP_ACTION_SELECT_FIRST, FALSE,
+ GIMP_HELP_PATH_TOP },
+
+ { "vectors-select-bottom", NULL,
+ NC_("vectors-action", "Select _Bottom Path"), NULL,
+ NC_("vectors-action", "Select the bottommost path"),
+ GIMP_ACTION_SELECT_LAST, FALSE,
+ GIMP_HELP_PATH_BOTTOM },
+
+ { "vectors-select-previous", NULL,
+ NC_("vectors-action", "Select _Previous Path"), NULL,
+ NC_("vectors-action", "Select the path above the current path"),
+ GIMP_ACTION_SELECT_PREVIOUS, FALSE,
+ GIMP_HELP_PATH_PREVIOUS },
+
+ { "vectors-select-next", NULL,
+ NC_("vectors-action", "Select _Next Path"), NULL,
+ NC_("vectors-action", "Select the vector below the current path"),
+ GIMP_ACTION_SELECT_NEXT, FALSE,
+ GIMP_HELP_PATH_NEXT }
+};
+
+void
+vectors_actions_setup (GimpActionGroup *group)
+{
+ gimp_action_group_add_actions (group, "vectors-action",
+ vectors_actions,
+ G_N_ELEMENTS (vectors_actions));
+
+ gimp_action_group_add_toggle_actions (group, "vectors-action",
+ vectors_toggle_actions,
+ G_N_ELEMENTS (vectors_toggle_actions));
+
+ gimp_action_group_add_enum_actions (group, "vectors-action",
+ vectors_color_tag_actions,
+ G_N_ELEMENTS (vectors_color_tag_actions),
+ vectors_color_tag_cmd_callback);
+
+ gimp_action_group_add_enum_actions (group, "vectors-action",
+ vectors_to_selection_actions,
+ G_N_ELEMENTS (vectors_to_selection_actions),
+ vectors_to_selection_cmd_callback);
+
+ gimp_action_group_add_enum_actions (group, "vectors-action",
+ vectors_selection_to_vectors_actions,
+ G_N_ELEMENTS (vectors_selection_to_vectors_actions),
+ vectors_selection_to_vectors_cmd_callback);
+
+ gimp_action_group_add_enum_actions (group, "vectors-action",
+ vectors_select_actions,
+ G_N_ELEMENTS (vectors_select_actions),
+ vectors_select_cmd_callback);
+
+ items_actions_setup (group, "vectors");
+}
+
+void
+vectors_actions_update (GimpActionGroup *group,
+ gpointer data)
+{
+ GimpImage *image = action_data_get_image (data);
+ GimpVectors *vectors = NULL;
+ GimpDrawable *drawable = NULL;
+ gint n_vectors = 0;
+ gboolean mask_empty = TRUE;
+ gboolean dr_writable = FALSE;
+ gboolean dr_children = FALSE;
+ GList *next = NULL;
+ GList *prev = NULL;
+
+ if (image)
+ {
+ n_vectors = gimp_image_get_n_vectors (image);
+ mask_empty = gimp_channel_is_empty (gimp_image_get_mask (image));
+
+ vectors = gimp_image_get_active_vectors (image);
+
+ if (vectors)
+ {
+ GList *vectors_list;
+ GList *list;
+
+ vectors_list = gimp_item_get_container_iter (GIMP_ITEM (vectors));
+
+ list = g_list_find (vectors_list, vectors);
+
+ if (list)
+ {
+ prev = g_list_previous (list);
+ next = g_list_next (list);
+ }
+ }
+
+ drawable = gimp_image_get_active_drawable (image);
+
+ if (drawable)
+ {
+ dr_writable = ! gimp_item_is_content_locked (GIMP_ITEM (drawable));
+
+ if (gimp_viewable_get_children (GIMP_VIEWABLE (drawable)))
+ dr_children = TRUE;
+ }
+ }
+
+#define SET_SENSITIVE(action,condition) \
+ gimp_action_group_set_action_sensitive (group, action, (condition) != 0)
+#define SET_ACTIVE(action,condition) \
+ gimp_action_group_set_action_active (group, action, (condition) != 0)
+
+ SET_SENSITIVE ("vectors-edit", vectors);
+ SET_SENSITIVE ("vectors-edit-attributes", vectors);
+
+ SET_SENSITIVE ("vectors-new", image);
+ SET_SENSITIVE ("vectors-new-last-values", image);
+ SET_SENSITIVE ("vectors-duplicate", vectors);
+ SET_SENSITIVE ("vectors-delete", vectors);
+ SET_SENSITIVE ("vectors-merge-visible", n_vectors > 1);
+
+ SET_SENSITIVE ("vectors-raise", vectors && prev);
+ SET_SENSITIVE ("vectors-raise-to-top", vectors && prev);
+ SET_SENSITIVE ("vectors-lower", vectors && next);
+ SET_SENSITIVE ("vectors-lower-to-bottom", vectors && next);
+
+ SET_SENSITIVE ("vectors-copy", vectors);
+ SET_SENSITIVE ("vectors-paste", image);
+ SET_SENSITIVE ("vectors-export", vectors);
+ SET_SENSITIVE ("vectors-import", image);
+
+ 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);
+ SET_SENSITIVE ("vectors-stroke-last-values", vectors &&
+ dr_writable &&
+ !dr_children);
+
+ SET_SENSITIVE ("vectors-selection-replace", vectors);
+ SET_SENSITIVE ("vectors-selection-from-vectors", vectors);
+ SET_SENSITIVE ("vectors-selection-add", vectors);
+ SET_SENSITIVE ("vectors-selection-subtract", vectors);
+ SET_SENSITIVE ("vectors-selection-intersect", vectors);
+
+ SET_SENSITIVE ("vectors-select-top", vectors && prev);
+ SET_SENSITIVE ("vectors-select-bottom", vectors && next);
+ SET_SENSITIVE ("vectors-select-previous", vectors && prev);
+ SET_SENSITIVE ("vectors-select-next", vectors && next);
+
+#undef SET_SENSITIVE
+#undef SET_ACTIVE
+
+ items_actions_update (group, "vectors", GIMP_ITEM (vectors));
+}
diff --git a/app/actions/vectors-actions.h b/app/actions/vectors-actions.h
new file mode 100644
index 0000000..b5422b8
--- /dev/null
+++ b/app/actions/vectors-actions.h
@@ -0,0 +1,27 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __VECTORS_ACTIONS_H__
+#define __VECTORS_ACTIONS_H__
+
+
+void vectors_actions_setup (GimpActionGroup *group);
+void vectors_actions_update (GimpActionGroup *group,
+ gpointer data);
+
+
+#endif /* __VECTORS_ACTIONS_H__ */
diff --git a/app/actions/vectors-commands.c b/app/actions/vectors-commands.c
new file mode 100644
index 0000000..43b3044
--- /dev/null
+++ b/app/actions/vectors-commands.c
@@ -0,0 +1,892 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <string.h>
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpbase/gimpbase.h"
+#include "libgimpconfig/gimpconfig.h"
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "actions-types.h"
+
+#include "config/gimpdialogconfig.h"
+
+#include "core/gimp.h"
+#include "core/gimp-utils.h"
+#include "core/gimpchannel.h"
+#include "core/gimpcontext.h"
+#include "core/gimpimage.h"
+#include "core/gimpimage-merge.h"
+#include "core/gimpimage-undo.h"
+#include "core/gimpparamspecs.h"
+#include "core/gimpprogress.h"
+#include "core/gimptoolinfo.h"
+
+#include "pdb/gimppdb.h"
+#include "pdb/gimpprocedure.h"
+
+#include "vectors/gimpvectors.h"
+#include "vectors/gimpvectors-export.h"
+#include "vectors/gimpvectors-import.h"
+
+#include "widgets/gimpaction.h"
+#include "widgets/gimpclipboard.h"
+#include "widgets/gimphelp-ids.h"
+
+#include "display/gimpdisplay.h"
+
+#include "tools/gimpvectortool.h"
+#include "tools/tool_manager.h"
+
+#include "dialogs/dialogs.h"
+#include "dialogs/vectors-export-dialog.h"
+#include "dialogs/vectors-import-dialog.h"
+#include "dialogs/vectors-options-dialog.h"
+
+#include "actions.h"
+#include "items-commands.h"
+#include "vectors-commands.h"
+
+#include "gimp-intl.h"
+
+
+/* local function prototypes */
+
+static void vectors_new_callback (GtkWidget *dialog,
+ GimpImage *image,
+ GimpVectors *vectors,
+ GimpContext *context,
+ const gchar *vectors_name,
+ gboolean vectors_visible,
+ gboolean vectors_linked,
+ GimpColorTag vectors_color_tag,
+ gboolean vectors_lock_content,
+ gboolean vectors_lock_position,
+ gpointer user_data);
+static void vectors_edit_attributes_callback (GtkWidget *dialog,
+ GimpImage *image,
+ GimpVectors *vectors,
+ GimpContext *context,
+ const gchar *vectors_name,
+ gboolean vectors_visible,
+ gboolean vectors_linked,
+ GimpColorTag vectors_color_tag,
+ gboolean vectors_lock_content,
+ gboolean vectors_lock_position,
+ gpointer user_data);
+static void vectors_import_callback (GtkWidget *dialog,
+ GimpImage *image,
+ GFile *file,
+ GFile *import_folder,
+ gboolean merge_vectors,
+ gboolean scale_vectors,
+ gpointer user_data);
+static void vectors_export_callback (GtkWidget *dialog,
+ GimpImage *image,
+ GFile *file,
+ GFile *export_folder,
+ gboolean active_only,
+ gpointer user_data);
+
+
+/* public functions */
+
+void
+vectors_edit_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpVectors *vectors;
+ GimpTool *active_tool;
+ return_if_no_vectors (image, vectors, data);
+
+ active_tool = tool_manager_get_active (image->gimp);
+
+ if (! GIMP_IS_VECTOR_TOOL (active_tool))
+ {
+ GimpToolInfo *tool_info = gimp_get_tool_info (image->gimp,
+ "gimp-vector-tool");
+
+ if (GIMP_IS_TOOL_INFO (tool_info))
+ {
+ gimp_context_set_tool (action_data_get_context (data), tool_info);
+ active_tool = tool_manager_get_active (image->gimp);
+ }
+ }
+
+ if (GIMP_IS_VECTOR_TOOL (active_tool))
+ gimp_vector_tool_set_vectors (GIMP_VECTOR_TOOL (active_tool), vectors);
+}
+
+void
+vectors_edit_attributes_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpVectors *vectors;
+ GtkWidget *widget;
+ GtkWidget *dialog;
+ return_if_no_vectors (image, vectors, data);
+ return_if_no_widget (widget, data);
+
+#define EDIT_DIALOG_KEY "gimp-vectors-edit-attributes-dialog"
+
+ dialog = dialogs_get_dialog (G_OBJECT (vectors), EDIT_DIALOG_KEY);
+
+ if (! dialog)
+ {
+ GimpItem *item = GIMP_ITEM (vectors);
+
+ dialog = vectors_options_dialog_new (image, vectors,
+ action_data_get_context (data),
+ widget,
+ _("Path Attributes"),
+ "gimp-vectors-edit",
+ GIMP_ICON_EDIT,
+ _("Edit Path Attributes"),
+ GIMP_HELP_PATH_EDIT,
+ gimp_object_get_name (vectors),
+ gimp_item_get_visible (item),
+ gimp_item_get_linked (item),
+ gimp_item_get_color_tag (item),
+ gimp_item_get_lock_content (item),
+ gimp_item_get_lock_position (item),
+ vectors_edit_attributes_callback,
+ NULL);
+
+ dialogs_attach_dialog (G_OBJECT (vectors), EDIT_DIALOG_KEY, dialog);
+ }
+
+ gtk_window_present (GTK_WINDOW (dialog));
+}
+
+void
+vectors_new_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GtkWidget *widget;
+ GtkWidget *dialog;
+ return_if_no_image (image, data);
+ return_if_no_widget (widget, data);
+
+#define NEW_DIALOG_KEY "gimp-vectors-new-dialog"
+
+ dialog = dialogs_get_dialog (G_OBJECT (image), NEW_DIALOG_KEY);
+
+ if (! dialog)
+ {
+ GimpDialogConfig *config = GIMP_DIALOG_CONFIG (image->gimp->config);
+
+ dialog = vectors_options_dialog_new (image, NULL,
+ action_data_get_context (data),
+ widget,
+ _("New Path"),
+ "gimp-vectors-new",
+ GIMP_ICON_PATH,
+ _("Create a New Path"),
+ GIMP_HELP_PATH_NEW,
+ config->vectors_new_name,
+ FALSE,
+ FALSE,
+ GIMP_COLOR_TAG_NONE,
+ FALSE,
+ FALSE,
+ vectors_new_callback,
+ NULL);
+
+ dialogs_attach_dialog (G_OBJECT (image), NEW_DIALOG_KEY, dialog);
+ }
+
+ gtk_window_present (GTK_WINDOW (dialog));
+}
+
+void
+vectors_new_last_vals_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpVectors *vectors;
+ GimpDialogConfig *config;
+ return_if_no_image (image, data);
+
+ config = GIMP_DIALOG_CONFIG (image->gimp->config);
+
+ vectors = gimp_vectors_new (image, config->vectors_new_name);
+ gimp_image_add_vectors (image, vectors,
+ GIMP_IMAGE_ACTIVE_PARENT, -1, TRUE);
+ gimp_image_flush (image);
+}
+
+void
+vectors_raise_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpVectors *vectors;
+ return_if_no_vectors (image, vectors, data);
+
+ gimp_image_raise_item (image, GIMP_ITEM (vectors), NULL);
+ gimp_image_flush (image);
+}
+
+void
+vectors_raise_to_top_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpVectors *vectors;
+ return_if_no_vectors (image, vectors, data);
+
+ gimp_image_raise_item_to_top (image, GIMP_ITEM (vectors));
+ gimp_image_flush (image);
+}
+
+void
+vectors_lower_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpVectors *vectors;
+ return_if_no_vectors (image, vectors, data);
+
+ gimp_image_lower_item (image, GIMP_ITEM (vectors), NULL);
+ gimp_image_flush (image);
+}
+
+void
+vectors_lower_to_bottom_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpVectors *vectors;
+ return_if_no_vectors (image, vectors, data);
+
+ gimp_image_lower_item_to_bottom (image, GIMP_ITEM (vectors));
+ gimp_image_flush (image);
+}
+
+void
+vectors_duplicate_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpVectors *vectors;
+ GimpVectors *new_vectors;
+ return_if_no_vectors (image, vectors, data);
+
+ new_vectors = GIMP_VECTORS (gimp_item_duplicate (GIMP_ITEM (vectors),
+ G_TYPE_FROM_INSTANCE (vectors)));
+ /* use the actual parent here, not GIMP_IMAGE_ACTIVE_PARENT because
+ * the latter would add a duplicated group inside itself instead of
+ * above it
+ */
+ gimp_image_add_vectors (image, new_vectors,
+ gimp_vectors_get_parent (vectors), -1,
+ TRUE);
+ gimp_image_flush (image);
+}
+
+void
+vectors_delete_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpVectors *vectors;
+ return_if_no_vectors (image, vectors, data);
+
+ gimp_image_remove_vectors (image, vectors, TRUE, NULL);
+ gimp_image_flush (image);
+}
+
+void
+vectors_merge_visible_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpVectors *vectors;
+ GtkWidget *widget;
+ GError *error = NULL;
+ return_if_no_vectors (image, vectors, data);
+ return_if_no_widget (widget, data);
+
+ if (! gimp_image_merge_visible_vectors (image, &error))
+ {
+ gimp_message_literal (image->gimp,
+ G_OBJECT (widget), GIMP_MESSAGE_WARNING,
+ error->message);
+ g_clear_error (&error);
+ return;
+ }
+
+ gimp_image_flush (image);
+}
+
+void
+vectors_to_selection_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpVectors *vectors;
+ GimpChannelOps operation;
+ return_if_no_vectors (image, vectors, data);
+
+ operation = (GimpChannelOps) g_variant_get_int32 (value);
+
+ gimp_item_to_selection (GIMP_ITEM (vectors), operation,
+ TRUE, FALSE, 0, 0);
+ gimp_image_flush (image);
+}
+
+void
+vectors_selection_to_vectors_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GtkWidget *widget;
+ GimpProcedure *procedure;
+ GimpValueArray *args;
+ GimpDisplay *display;
+ gboolean advanced;
+ GError *error = NULL;
+ return_if_no_image (image, data);
+ return_if_no_widget (widget, data);
+
+ advanced = (gboolean) g_variant_get_int32 (value);
+
+ if (advanced)
+ procedure = gimp_pdb_lookup_procedure (image->gimp->pdb,
+ "plug-in-sel2path-advanced");
+ else
+ procedure = gimp_pdb_lookup_procedure (image->gimp->pdb,
+ "plug-in-sel2path");
+
+ if (! procedure)
+ {
+ gimp_message_literal (image->gimp,
+ G_OBJECT (widget), GIMP_MESSAGE_ERROR,
+ "Selection to path procedure lookup failed.");
+ return;
+ }
+
+ display = gimp_context_get_display (action_data_get_context (data));
+
+ args = gimp_procedure_get_arguments (procedure);
+ gimp_value_array_truncate (args, 2);
+
+ g_value_set_int (gimp_value_array_index (args, 0),
+ GIMP_RUN_INTERACTIVE);
+ gimp_value_set_image (gimp_value_array_index (args, 1),
+ image);
+
+ gimp_procedure_execute_async (procedure, image->gimp,
+ action_data_get_context (data),
+ GIMP_PROGRESS (display), args,
+ GIMP_OBJECT (display), &error);
+
+ gimp_value_array_unref (args);
+
+ if (error)
+ {
+ gimp_message_literal (image->gimp,
+ G_OBJECT (widget), GIMP_MESSAGE_ERROR,
+ error->message);
+ g_error_free (error);
+ }
+}
+
+void
+vectors_fill_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpVectors *vectors;
+ return_if_no_vectors (image, vectors, data);
+
+ items_fill_cmd_callback (action,
+ image, GIMP_ITEM (vectors),
+ "gimp-vectors-fill-dialog",
+ _("Fill Path"),
+ GIMP_ICON_TOOL_BUCKET_FILL,
+ GIMP_HELP_PATH_FILL,
+ data);
+}
+
+void
+vectors_fill_last_vals_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpVectors *vectors;
+ return_if_no_vectors (image, vectors, data);
+
+ items_fill_last_vals_cmd_callback (action,
+ image, GIMP_ITEM (vectors),
+ data);
+}
+
+void
+vectors_stroke_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpVectors *vectors;
+ return_if_no_vectors (image, vectors, data);
+
+ items_stroke_cmd_callback (action,
+ image, GIMP_ITEM (vectors),
+ "gimp-vectors-stroke-dialog",
+ _("Stroke Path"),
+ GIMP_ICON_PATH_STROKE,
+ GIMP_HELP_PATH_STROKE,
+ data);
+}
+
+void
+vectors_stroke_last_vals_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpVectors *vectors;
+ return_if_no_vectors (image, vectors, data);
+
+ items_stroke_last_vals_cmd_callback (action,
+ image, GIMP_ITEM (vectors),
+ data);
+}
+
+void
+vectors_copy_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpVectors *vectors;
+ gchar *svg;
+ return_if_no_vectors (image, vectors, data);
+
+ svg = gimp_vectors_export_string (image, vectors);
+
+ if (svg)
+ {
+ gimp_clipboard_set_svg (image->gimp, svg);
+ g_free (svg);
+ }
+}
+
+void
+vectors_paste_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GtkWidget *widget;
+ gchar *svg;
+ gsize svg_size;
+ return_if_no_image (image, data);
+ return_if_no_widget (widget, data);
+
+ svg = gimp_clipboard_get_svg (image->gimp, &svg_size);
+
+ if (svg)
+ {
+ GError *error = NULL;
+
+ if (! gimp_vectors_import_buffer (image, svg, svg_size,
+ TRUE, FALSE,
+ GIMP_IMAGE_ACTIVE_PARENT, -1,
+ NULL, &error))
+ {
+ gimp_message (image->gimp, G_OBJECT (widget), GIMP_MESSAGE_ERROR,
+ "%s", error->message);
+ g_clear_error (&error);
+ }
+ else
+ {
+ gimp_image_flush (image);
+ }
+
+ g_free (svg);
+ }
+}
+
+void
+vectors_export_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpVectors *vectors;
+ GtkWidget *widget;
+ GtkWidget *dialog;
+ return_if_no_vectors (image, vectors, data);
+ return_if_no_widget (widget, data);
+
+#define EXPORT_DIALOG_KEY "gimp-vectors-export-dialog"
+
+ dialog = dialogs_get_dialog (G_OBJECT (image), EXPORT_DIALOG_KEY);
+
+ if (! dialog)
+ {
+ GimpDialogConfig *config = GIMP_DIALOG_CONFIG (image->gimp->config);
+ GFile *folder = NULL;
+
+ if (config->vectors_export_path)
+ folder = gimp_file_new_for_config_path (config->vectors_export_path,
+ NULL);
+
+ dialog = vectors_export_dialog_new (image, widget,
+ folder,
+ config->vectors_export_active_only,
+ vectors_export_callback,
+ NULL);
+
+ if (folder)
+ g_object_unref (folder);
+
+ dialogs_attach_dialog (G_OBJECT (image), EXPORT_DIALOG_KEY, dialog);
+ }
+
+ gtk_window_present (GTK_WINDOW (dialog));
+}
+
+void
+vectors_import_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GtkWidget *widget;
+ GtkWidget *dialog;
+ return_if_no_image (image, data);
+ return_if_no_widget (widget, data);
+
+#define IMPORT_DIALOG_KEY "gimp-vectors-import-dialog"
+
+ dialog = dialogs_get_dialog (G_OBJECT (image), IMPORT_DIALOG_KEY);
+
+ if (! dialog)
+ {
+ GimpDialogConfig *config = GIMP_DIALOG_CONFIG (image->gimp->config);
+ GFile *folder = NULL;
+
+ if (config->vectors_import_path)
+ folder = gimp_file_new_for_config_path (config->vectors_import_path,
+ NULL);
+
+ dialog = vectors_import_dialog_new (image, widget,
+ folder,
+ config->vectors_import_merge,
+ config->vectors_import_scale,
+ vectors_import_callback,
+ NULL);
+
+ dialogs_attach_dialog (G_OBJECT (image), IMPORT_DIALOG_KEY, dialog);
+ }
+
+ gtk_window_present (GTK_WINDOW (dialog));
+}
+
+void
+vectors_visible_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpVectors *vectors;
+ return_if_no_vectors (image, vectors, data);
+
+ items_visible_cmd_callback (action, value, image, GIMP_ITEM (vectors));
+}
+
+void
+vectors_linked_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpVectors *vectors;
+ return_if_no_vectors (image, vectors, data);
+
+ items_linked_cmd_callback (action, value, image, GIMP_ITEM (vectors));
+}
+
+void
+vectors_lock_content_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpVectors *vectors;
+ return_if_no_vectors (image, vectors, data);
+
+ items_lock_content_cmd_callback (action, value, image, GIMP_ITEM (vectors));
+}
+
+void
+vectors_lock_position_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpVectors *vectors;
+ return_if_no_vectors (image, vectors, data);
+
+ items_lock_position_cmd_callback (action, value, image, GIMP_ITEM (vectors));
+}
+
+void
+vectors_color_tag_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpVectors *vectors;
+ GimpColorTag color_tag;
+ return_if_no_vectors (image, vectors, data);
+
+ color_tag = (GimpColorTag) g_variant_get_int32 (value);
+
+ items_color_tag_cmd_callback (action, image, GIMP_ITEM (vectors),
+ color_tag);
+}
+
+
+/* private functions */
+
+static void
+vectors_new_callback (GtkWidget *dialog,
+ GimpImage *image,
+ GimpVectors *vectors,
+ GimpContext *context,
+ const gchar *vectors_name,
+ gboolean vectors_visible,
+ gboolean vectors_linked,
+ GimpColorTag vectors_color_tag,
+ gboolean vectors_lock_content,
+ gboolean vectors_lock_position,
+ gpointer user_data)
+{
+ GimpDialogConfig *config = GIMP_DIALOG_CONFIG (image->gimp->config);
+
+ g_object_set (config,
+ "path-new-name", vectors_name,
+ NULL);
+
+ vectors = gimp_vectors_new (image, config->vectors_new_name);
+ gimp_item_set_visible (GIMP_ITEM (vectors), vectors_visible, FALSE);
+ gimp_item_set_linked (GIMP_ITEM (vectors), vectors_linked, FALSE);
+ gimp_item_set_color_tag (GIMP_ITEM (vectors), vectors_color_tag, FALSE);
+ gimp_item_set_lock_content (GIMP_ITEM (vectors), vectors_lock_content, FALSE);
+ gimp_item_set_lock_position (GIMP_ITEM (vectors), vectors_lock_position, FALSE);
+
+ gimp_image_add_vectors (image, vectors,
+ GIMP_IMAGE_ACTIVE_PARENT, -1, TRUE);
+ gimp_image_flush (image);
+
+ gtk_widget_destroy (dialog);
+}
+
+static void
+vectors_edit_attributes_callback (GtkWidget *dialog,
+ GimpImage *image,
+ GimpVectors *vectors,
+ GimpContext *context,
+ const gchar *vectors_name,
+ gboolean vectors_visible,
+ gboolean vectors_linked,
+ GimpColorTag vectors_color_tag,
+ gboolean vectors_lock_content,
+ gboolean vectors_lock_position,
+ gpointer user_data)
+{
+ GimpItem *item = GIMP_ITEM (vectors);
+
+ if (strcmp (vectors_name, gimp_object_get_name (vectors)) ||
+ vectors_visible != gimp_item_get_visible (item) ||
+ vectors_linked != gimp_item_get_linked (item) ||
+ vectors_color_tag != gimp_item_get_color_tag (item) ||
+ vectors_lock_content != gimp_item_get_lock_content (item) ||
+ vectors_lock_position != gimp_item_get_lock_position (item))
+ {
+ gimp_image_undo_group_start (image,
+ GIMP_UNDO_GROUP_ITEM_PROPERTIES,
+ _("Path Attributes"));
+
+ if (strcmp (vectors_name, gimp_object_get_name (vectors)))
+ gimp_item_rename (GIMP_ITEM (vectors), vectors_name, NULL);
+
+ if (vectors_visible != gimp_item_get_visible (item))
+ gimp_item_set_visible (item, vectors_visible, TRUE);
+
+ if (vectors_linked != gimp_item_get_linked (item))
+ gimp_item_set_linked (item, vectors_linked, TRUE);
+
+ if (vectors_color_tag != gimp_item_get_color_tag (item))
+ gimp_item_set_color_tag (item, vectors_color_tag, TRUE);
+
+ if (vectors_lock_content != gimp_item_get_lock_content (item))
+ gimp_item_set_lock_content (item, vectors_lock_content, TRUE);
+
+ if (vectors_lock_position != gimp_item_get_lock_position (item))
+ gimp_item_set_lock_position (item, vectors_lock_position, TRUE);
+
+ gimp_image_undo_group_end (image);
+
+ gimp_image_flush (image);
+ }
+
+ gtk_widget_destroy (dialog);
+}
+
+static void
+vectors_import_callback (GtkWidget *dialog,
+ GimpImage *image,
+ GFile *file,
+ GFile *import_folder,
+ gboolean merge_vectors,
+ gboolean scale_vectors,
+ gpointer user_data)
+{
+ GimpDialogConfig *config = GIMP_DIALOG_CONFIG (image->gimp->config);
+ gchar *path = NULL;
+ GError *error = NULL;
+
+ if (import_folder)
+ path = gimp_file_get_config_path (import_folder, NULL);
+
+ g_object_set (config,
+ "path-import-path", path,
+ "path-import-merge", merge_vectors,
+ "path-import-scale", scale_vectors,
+ NULL);
+
+ if (path)
+ g_free (path);
+
+ if (gimp_vectors_import_file (image, file,
+ config->vectors_import_merge,
+ config->vectors_import_scale,
+ GIMP_IMAGE_ACTIVE_PARENT, -1,
+ NULL, &error))
+ {
+ gimp_image_flush (image);
+ }
+ else
+ {
+ gimp_message (image->gimp, G_OBJECT (dialog),
+ GIMP_MESSAGE_ERROR,
+ "%s", error->message);
+ g_error_free (error);
+ return;
+ }
+
+ gtk_widget_destroy (dialog);
+}
+
+static void
+vectors_export_callback (GtkWidget *dialog,
+ GimpImage *image,
+ GFile *file,
+ GFile *export_folder,
+ gboolean active_only,
+ gpointer user_data)
+{
+ GimpDialogConfig *config = GIMP_DIALOG_CONFIG (image->gimp->config);
+ GimpVectors *vectors = NULL;
+ gchar *path = NULL;
+ GError *error = NULL;
+
+ if (export_folder)
+ path = gimp_file_get_config_path (export_folder, NULL);
+
+ g_object_set (config,
+ "path-export-path", path,
+ "path-export-active-only", active_only,
+ NULL);
+
+ if (path)
+ g_free (path);
+
+ if (config->vectors_export_active_only)
+ vectors = gimp_image_get_active_vectors (image);
+
+ if (! gimp_vectors_export_file (image, vectors, file, &error))
+ {
+ gimp_message (image->gimp, G_OBJECT (dialog),
+ GIMP_MESSAGE_ERROR,
+ "%s", error->message);
+ g_clear_error (&error);
+ return;
+ }
+
+ gtk_widget_destroy (dialog);
+}
+
+void
+vectors_select_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpVectors *vectors;
+ GimpContainer *container;
+ GimpVectors *new_vectors;
+ GimpActionSelectType select_type;
+ return_if_no_image (image, data);
+
+ select_type = (GimpActionSelectType) g_variant_get_int32 (value);
+
+ vectors = gimp_image_get_active_vectors (image);
+
+ if (vectors)
+ container = gimp_item_get_container (GIMP_ITEM (vectors));
+ else
+ container = gimp_image_get_vectors (image);
+
+ new_vectors = (GimpVectors *) action_select_object (select_type,
+ container,
+ (GimpObject *) vectors);
+
+ if (new_vectors && new_vectors != vectors)
+ {
+ gimp_image_set_active_vectors (image, new_vectors);
+ gimp_image_flush (image);
+ }
+}
diff --git a/app/actions/vectors-commands.h b/app/actions/vectors-commands.h
new file mode 100644
index 0000000..5ce88b9
--- /dev/null
+++ b/app/actions/vectors-commands.h
@@ -0,0 +1,112 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __VECTORS_COMMANDS_H__
+#define __VECTORS_COMMANDS_H__
+
+
+void vectors_edit_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void vectors_edit_attributes_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void vectors_new_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void vectors_new_last_vals_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+void vectors_raise_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void vectors_raise_to_top_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void vectors_lower_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void vectors_lower_to_bottom_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+void vectors_duplicate_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void vectors_delete_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void vectors_merge_visible_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void vectors_to_selection_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void vectors_selection_to_vectors_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+void vectors_fill_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void vectors_fill_last_vals_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void vectors_stroke_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void vectors_stroke_last_vals_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+void vectors_copy_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void vectors_paste_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void vectors_export_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void vectors_import_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+void vectors_visible_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void vectors_linked_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void vectors_lock_content_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void vectors_lock_position_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+void vectors_color_tag_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+void vectors_select_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+
+#endif /* __VECTORS_COMMANDS_H__ */
diff --git a/app/actions/view-actions.c b/app/actions/view-actions.c
new file mode 100644
index 0000000..bbf272c
--- /dev/null
+++ b/app/actions/view-actions.c
@@ -0,0 +1,1211 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpmath/gimpmath.h"
+#include "libgimpcolor/gimpcolor.h"
+#include "libgimpconfig/gimpconfig.h"
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "actions-types.h"
+
+#include "config/gimpdisplayoptions.h"
+#include "config/gimpguiconfig.h"
+
+#include "core/gimp.h"
+#include "core/gimpcontext.h"
+#include "core/gimpimage.h"
+
+#include "widgets/gimpactiongroup.h"
+#include "widgets/gimprender.h"
+#include "widgets/gimphelp-ids.h"
+#include "widgets/gimpwidgets-utils.h"
+
+#include "display/gimpdisplay.h"
+#include "display/gimpdisplayshell.h"
+#include "display/gimpdisplayshell-appearance.h"
+#include "display/gimpdisplayshell-scale.h"
+#include "display/gimpimagewindow.h"
+
+#include "actions.h"
+#include "view-actions.h"
+#include "view-commands.h"
+#include "window-actions.h"
+#include "window-commands.h"
+
+#include "gimp-intl.h"
+
+
+/* local function prototypes */
+
+static void view_actions_set_zoom (GimpActionGroup *group,
+ GimpDisplayShell *shell);
+static void view_actions_set_rotate (GimpActionGroup *group,
+ GimpDisplayShell *shell);
+static void view_actions_check_type_notify (GimpDisplayConfig *config,
+ GParamSpec *pspec,
+ GimpActionGroup *group);
+
+
+static const GimpActionEntry view_actions[] =
+{
+ { "view-menu", NULL, NC_("view-action", "_View") },
+ { "view-zoom-menu", NULL, NC_("view-action", "_Zoom") },
+ { "view-rotate-menu", NULL, NC_("view-action", "_Flip & Rotate") },
+ { "view-padding-color-menu", NULL, NC_("view-action", "_Padding Color") },
+
+ { "view-color-management-menu", NULL,
+ NC_("view-action", "_Color Management") },
+
+ { "view-display-intent-menu", NULL,
+ NC_("view-action", "Display _Rendering Intent") },
+
+ { "view-softproof-intent-menu", NULL,
+ NC_("view-action", "Soft-Proofing Re_ndering Intent") },
+
+ { "view-move-to-screen-menu", GIMP_ICON_WINDOW_MOVE_TO_SCREEN,
+ NC_("view-action", "Move to Screen"), NULL, NULL, NULL,
+ GIMP_HELP_VIEW_CHANGE_SCREEN },
+
+ { "view-new", GIMP_ICON_WINDOW_NEW,
+ NC_("view-action", "_New View"), NULL,
+ NC_("view-action", "Create another view on this image"),
+ view_new_cmd_callback,
+ GIMP_HELP_VIEW_NEW },
+
+ { "view-close", GIMP_ICON_WINDOW_CLOSE,
+ NC_("view-action", "_Close View"), "<primary>W",
+ NC_("view-action", "Close the active image view"),
+ view_close_cmd_callback,
+ GIMP_HELP_FILE_CLOSE },
+
+ { "view-scroll-center", GIMP_ICON_CENTER,
+ NC_("view-action", "C_enter Image in Window"), "<shift>J",
+ NC_("view-action", "Scroll the image so that it is centered in the window"),
+ view_scroll_center_cmd_callback,
+ GIMP_HELP_VIEW_SCROLL_CENTER },
+
+ { "view-zoom-fit-in", GIMP_ICON_ZOOM_FIT_BEST,
+ NC_("view-action", "_Fit Image in Window"), "<primary><shift>J",
+ NC_("view-action", "Adjust the zoom ratio so that the image becomes fully visible"),
+ view_zoom_fit_in_cmd_callback,
+ GIMP_HELP_VIEW_ZOOM_FIT_IN },
+
+ { "view-zoom-fill", GIMP_ICON_ZOOM_FIT_BEST,
+ NC_("view-action", "Fi_ll Window"), NULL,
+ NC_("view-action", "Adjust the zoom ratio so that the entire window is used"),
+ view_zoom_fill_cmd_callback,
+ GIMP_HELP_VIEW_ZOOM_FILL },
+
+ { "view-zoom-selection", GIMP_ICON_SELECTION,
+ NC_("view-action", "Zoom to _Selection"), NULL,
+ NC_("view-action", "Adjust the zoom ratio so that the selection fills the window"),
+ view_zoom_selection_cmd_callback,
+ GIMP_HELP_VIEW_ZOOM_SELECTION },
+
+ { "view-zoom-revert", NULL,
+ NC_("view-action", "Re_vert Zoom"), "grave",
+ NC_("view-action", "Restore the previous zoom level"),
+ view_zoom_revert_cmd_callback,
+ GIMP_HELP_VIEW_ZOOM_REVERT },
+
+ { "view-rotate-other", NULL,
+ NC_("view-action", "Othe_r rotation angle..."), NULL,
+ NC_("view-action", "Set a custom rotation angle"),
+ view_rotate_other_cmd_callback,
+ GIMP_HELP_VIEW_ROTATE_OTHER },
+
+ { "view-navigation-window", GIMP_ICON_DIALOG_NAVIGATION,
+ NC_("view-action", "Na_vigation Window"), NULL,
+ NC_("view-action", "Show an overview window for this image"),
+ view_navigation_window_cmd_callback,
+ GIMP_HELP_NAVIGATION_DIALOG },
+
+ { "view-display-filters", GIMP_ICON_DISPLAY_FILTER,
+ NC_("view-action", "Display _Filters..."), NULL,
+ NC_("view-action", "Configure filters applied to this view"),
+ view_display_filters_cmd_callback,
+ GIMP_HELP_DISPLAY_FILTER_DIALOG },
+
+ { "view-color-management-reset", GIMP_ICON_RESET,
+ NC_("view-action", "As in _Preferences"), NULL,
+ NC_("view-action",
+ "Reset color management to what's configured in preferences"),
+ view_color_management_reset_cmd_callback,
+ GIMP_HELP_VIEW_COLOR_MANAGEMENT },
+
+ { "view-softproof-profile", NULL,
+ NC_("view-action", "Soft-_Proofing Profile..."), NULL,
+ NC_("view-action", "Set the soft-proofing profile"),
+ view_softproof_profile_cmd_callback,
+ GIMP_HELP_VIEW_COLOR_MANAGEMENT },
+
+ { "view-shrink-wrap", GIMP_ICON_ZOOM_FIT_BEST,
+ NC_("view-action", "Shrink _Wrap"), "<primary>J",
+ NC_("view-action", "Reduce the image window to the size of the image display"),
+ view_shrink_wrap_cmd_callback,
+ GIMP_HELP_VIEW_SHRINK_WRAP },
+
+ { "view-open-display", NULL,
+ NC_("view-action", "_Open Display..."), NULL,
+ NC_("view-action", "Connect to another display"),
+ window_open_display_cmd_callback,
+ NULL }
+};
+
+static const GimpToggleActionEntry view_toggle_actions[] =
+{
+
+ { "view-show-all", NULL,
+ NC_("view-action", "Show _All"), NULL,
+ NC_("view-action", "Show full image content"),
+ view_show_all_cmd_callback,
+ FALSE,
+ GIMP_HELP_VIEW_SHOW_ALL },
+
+ { "view-dot-for-dot", NULL,
+ NC_("view-action", "_Dot for Dot"), NULL,
+ NC_("view-action", "A pixel on the screen represents an image pixel"),
+ view_dot_for_dot_cmd_callback,
+ TRUE,
+ GIMP_HELP_VIEW_DOT_FOR_DOT },
+
+ { "view-color-management-enable", NULL,
+ NC_("view-action", "_Color-Manage this View"), NULL,
+ NC_("view-action", "Use color management for this view"),
+ view_color_management_enable_cmd_callback,
+ TRUE,
+ GIMP_HELP_VIEW_COLOR_MANAGEMENT },
+
+ { "view-color-management-softproof", NULL,
+ NC_("view-action", "_Proof Colors"), NULL,
+ NC_("view-action", "Use this view for soft-proofing"),
+ view_color_management_softproof_cmd_callback,
+ FALSE,
+ GIMP_HELP_VIEW_COLOR_MANAGEMENT },
+
+ { "view-display-black-point-compensation", NULL,
+ NC_("view-action", "_Black Point Compensation"), NULL,
+ NC_("view-action", "Use black point compensation for image display"),
+ view_display_bpc_cmd_callback,
+ TRUE,
+ GIMP_HELP_VIEW_COLOR_MANAGEMENT },
+
+ { "view-softproof-black-point-compensation", NULL,
+ NC_("view-action", "_Black Point Compensation"), NULL,
+ NC_("view-action", "Use black point compensation for soft-proofing"),
+ view_softproof_bpc_cmd_callback,
+ TRUE,
+ GIMP_HELP_VIEW_COLOR_MANAGEMENT },
+
+ { "view-softproof-gamut-check", NULL,
+ NC_("view-action", "_Mark Out Of Gamut Colors"), NULL,
+ NC_("view-action", "When soft-proofing, mark colors which cannot "
+ "be represented in the target color space"),
+ view_softproof_gamut_check_cmd_callback,
+ FALSE,
+ GIMP_HELP_VIEW_COLOR_MANAGEMENT },
+
+ { "view-show-selection", NULL,
+ NC_("view-action", "Show _Selection"), "<primary>T",
+ NC_("view-action", "Display the selection outline"),
+ view_toggle_selection_cmd_callback,
+ TRUE,
+ GIMP_HELP_VIEW_SHOW_SELECTION },
+
+ { "view-show-layer-boundary", NULL,
+ NC_("view-action", "Show _Layer Boundary"), NULL,
+ NC_("view-action", "Draw a border around the active layer"),
+ view_toggle_layer_boundary_cmd_callback,
+ TRUE,
+ GIMP_HELP_VIEW_SHOW_LAYER_BOUNDARY },
+
+ { "view-show-canvas-boundary", NULL,
+ NC_("view-action", "Show Canvas Bounda_ry"), NULL,
+ NC_("view-action", "Draw a border around the canvas"),
+ view_toggle_canvas_boundary_cmd_callback,
+ TRUE,
+ GIMP_HELP_VIEW_SHOW_CANVAS_BOUNDARY },
+
+ { "view-show-guides", NULL,
+ NC_("view-action", "Show _Guides"), "<primary><shift>T",
+ NC_("view-action", "Display the image's guides"),
+ view_toggle_guides_cmd_callback,
+ TRUE,
+ GIMP_HELP_VIEW_SHOW_GUIDES },
+
+ { "view-show-grid", NULL,
+ NC_("view-action", "S_how Grid"), NULL,
+ NC_("view-action", "Display the image's grid"),
+ view_toggle_grid_cmd_callback,
+ FALSE,
+ GIMP_HELP_VIEW_SHOW_GRID },
+
+ { "view-show-sample-points", NULL,
+ NC_("view-action", "Sh_ow Sample Points"), NULL,
+ NC_("view-action", "Display the image's color sample points"),
+ view_toggle_sample_points_cmd_callback,
+ TRUE,
+ GIMP_HELP_VIEW_SHOW_SAMPLE_POINTS },
+
+ { "view-snap-to-guides", NULL,
+ NC_("view-action", "Snap to Gu_ides"), NULL,
+ NC_("view-action", "Tool operations snap to guides"),
+ view_snap_to_guides_cmd_callback,
+ TRUE,
+ GIMP_HELP_VIEW_SNAP_TO_GUIDES },
+
+ { "view-snap-to-grid", NULL,
+ NC_("view-action", "Sna_p to Grid"), NULL,
+ NC_("view-action", "Tool operations snap to the grid"),
+ view_snap_to_grid_cmd_callback,
+ FALSE,
+ GIMP_HELP_VIEW_SNAP_TO_GRID },
+
+ { "view-snap-to-canvas", NULL,
+ NC_("view-action", "Snap to _Canvas Edges"), NULL,
+ NC_("view-action", "Tool operations snap to the canvas edges"),
+ view_snap_to_canvas_cmd_callback,
+ FALSE,
+ GIMP_HELP_VIEW_SNAP_TO_CANVAS },
+
+ { "view-snap-to-vectors", NULL,
+ NC_("view-action", "Snap t_o Active Path"), NULL,
+ NC_("view-action", "Tool operations snap to the active path"),
+ view_snap_to_vectors_cmd_callback,
+ FALSE,
+ GIMP_HELP_VIEW_SNAP_TO_VECTORS },
+
+ { "view-show-menubar", NULL,
+ NC_("view-action", "Show _Menubar"), NULL,
+ NC_("view-action", "Show this window's menubar"),
+ view_toggle_menubar_cmd_callback,
+ TRUE,
+ GIMP_HELP_VIEW_SHOW_MENUBAR },
+
+ { "view-show-rulers", NULL,
+ NC_("view-action", "Show R_ulers"), "<primary><shift>R",
+ NC_("view-action", "Show this window's rulers"),
+ view_toggle_rulers_cmd_callback,
+ TRUE,
+ GIMP_HELP_VIEW_SHOW_RULERS },
+
+ { "view-show-scrollbars", NULL,
+ NC_("view-action", "Show Scroll_bars"), NULL,
+ NC_("view-action", "Show this window's scrollbars"),
+ view_toggle_scrollbars_cmd_callback,
+ TRUE,
+ GIMP_HELP_VIEW_SHOW_SCROLLBARS },
+
+ { "view-show-statusbar", NULL,
+ NC_("view-action", "Show S_tatusbar"), NULL,
+ NC_("view-action", "Show this window's statusbar"),
+ view_toggle_statusbar_cmd_callback,
+ TRUE,
+ GIMP_HELP_VIEW_SHOW_STATUSBAR },
+
+ { "view-fullscreen", GIMP_ICON_VIEW_FULLSCREEN,
+ NC_("view-action", "Fullscr_een"), "F11",
+ NC_("view-action", "Toggle fullscreen view"),
+ view_fullscreen_cmd_callback,
+ FALSE,
+ GIMP_HELP_VIEW_FULLSCREEN }
+};
+
+static const GimpEnumActionEntry view_zoom_actions[] =
+{
+ { "view-zoom", NULL,
+ NC_("view-zoom-action", "Set zoom factor"), NULL, NULL,
+ GIMP_ACTION_SELECT_SET, TRUE,
+ NULL },
+
+ { "view-zoom-minimum", GIMP_ICON_ZOOM_OUT,
+ NC_("view-zoom-action", "Zoom out as far as possible"), NULL, NULL,
+ GIMP_ACTION_SELECT_FIRST, FALSE,
+ GIMP_HELP_VIEW_ZOOM_OUT },
+
+ { "view-zoom-maximum", GIMP_ICON_ZOOM_IN,
+ NC_("view-zoom-action", "Zoom in as far as possible"), NULL, NULL,
+ GIMP_ACTION_SELECT_LAST, FALSE,
+ GIMP_HELP_VIEW_ZOOM_IN },
+
+ { "view-zoom-out", GIMP_ICON_ZOOM_OUT,
+ NC_("view-zoom-action", "Zoom _Out"), "minus",
+ NC_("view-zoom-action", "Zoom out"),
+ GIMP_ACTION_SELECT_PREVIOUS, FALSE,
+ GIMP_HELP_VIEW_ZOOM_OUT },
+
+ { "view-zoom-in", GIMP_ICON_ZOOM_IN,
+ NC_("view-zoom-action", "Zoom _In"), "plus",
+ NC_("view-zoom-action", "Zoom in"),
+ GIMP_ACTION_SELECT_NEXT, FALSE,
+ GIMP_HELP_VIEW_ZOOM_IN },
+
+ { "view-zoom-out-accel", GIMP_ICON_CHAR_PICKER,
+ NC_("view-zoom-action", "Zoom Out"), "KP_Subtract",
+ NC_("view-zoom-action", "Zoom out"),
+ GIMP_ACTION_SELECT_PREVIOUS, FALSE,
+ GIMP_HELP_VIEW_ZOOM_OUT },
+
+ { "view-zoom-in-accel", GIMP_ICON_CHAR_PICKER,
+ NC_("view-zoom-action", "Zoom In"), "KP_Add",
+ NC_("view-zoom-action", "Zoom in"),
+ GIMP_ACTION_SELECT_NEXT, FALSE,
+ GIMP_HELP_VIEW_ZOOM_IN },
+
+ { "view-zoom-out-skip", GIMP_ICON_ZOOM_OUT,
+ NC_("view-zoom-action", "Zoom out a lot"), NULL, NULL,
+ GIMP_ACTION_SELECT_SKIP_PREVIOUS, FALSE,
+ GIMP_HELP_VIEW_ZOOM_OUT },
+
+ { "view-zoom-in-skip", GIMP_ICON_ZOOM_IN,
+ NC_("view-zoom-action", "Zoom in a lot"), NULL, NULL,
+ GIMP_ACTION_SELECT_SKIP_NEXT, FALSE,
+ GIMP_HELP_VIEW_ZOOM_IN }
+};
+
+static const GimpRadioActionEntry view_zoom_explicit_actions[] =
+{
+ { "view-zoom-16-1", NULL,
+ NC_("view-zoom-action", "1_6:1 (1600%)"), "5",
+ NC_("view-zoom-action", "Zoom 16:1"),
+ 160000,
+ GIMP_HELP_VIEW_ZOOM_IN },
+
+ { "view-zoom-16-1-accel", NULL,
+ NC_("view-zoom-action", "1_6:1 (1600%)"), "KP_5",
+ NC_("view-zoom-action", "Zoom 16:1"),
+ 160000,
+ GIMP_HELP_VIEW_ZOOM_IN },
+
+ { "view-zoom-8-1", NULL,
+ NC_("view-zoom-action", "_8:1 (800%)"), "4",
+ NC_("view-zoom-action", "Zoom 8:1"),
+ 80000,
+ GIMP_HELP_VIEW_ZOOM_IN },
+
+ { "view-zoom-8-1-accel", NULL,
+ NC_("view-zoom-action", "_8:1 (800%)"), "KP_4",
+ NC_("view-zoom-action", "Zoom 8:1"),
+ 80000,
+ GIMP_HELP_VIEW_ZOOM_IN },
+
+ { "view-zoom-4-1", NULL,
+ NC_("view-zoom-action", "_4:1 (400%)"), "3",
+ NC_("view-zoom-action", "Zoom 4:1"),
+ 40000,
+ GIMP_HELP_VIEW_ZOOM_IN },
+
+ { "view-zoom-4-1-accel", NULL,
+ NC_("view-zoom-action", "_4:1 (400%)"), "KP_3",
+ NC_("view-zoom-action", "Zoom 4:1"),
+ 40000,
+ GIMP_HELP_VIEW_ZOOM_IN },
+
+ { "view-zoom-2-1", NULL,
+ NC_("view-zoom-action", "_2:1 (200%)"), "2",
+ NC_("view-zoom-action", "Zoom 2:1"),
+ 20000,
+ GIMP_HELP_VIEW_ZOOM_IN },
+
+ { "view-zoom-2-1-accel", NULL,
+ NC_("view-zoom-action", "_2:1 (200%)"), "KP_2",
+ NC_("view-zoom-action", "Zoom 2:1"),
+ 20000,
+ GIMP_HELP_VIEW_ZOOM_IN },
+
+ { "view-zoom-1-1", GIMP_ICON_ZOOM_ORIGINAL,
+ NC_("view-zoom-action", "_1:1 (100%)"), "1",
+ NC_("view-zoom-action", "Zoom 1:1"),
+ 10000,
+ GIMP_HELP_VIEW_ZOOM_100 },
+
+ { "view-zoom-1-1-accel", GIMP_ICON_ZOOM_ORIGINAL,
+ NC_("view-zoom-action", "_1:1 (100%)"), "KP_1",
+ NC_("view-zoom-action", "Zoom 1:1"),
+ 10000,
+ GIMP_HELP_VIEW_ZOOM_100 },
+
+ { "view-zoom-1-2", NULL,
+ NC_("view-zoom-action", "1:_2 (50%)"), "<shift>2",
+ NC_("view-zoom-action", "Zoom 1:2"),
+ 5000,
+ GIMP_HELP_VIEW_ZOOM_OUT },
+
+ { "view-zoom-1-4", NULL,
+ NC_("view-zoom-action", "1:_4 (25%)"), "<shift>3",
+ NC_("view-zoom-action", "Zoom 1:4"),
+ 2500,
+ GIMP_HELP_VIEW_ZOOM_OUT },
+
+ { "view-zoom-1-8", NULL,
+ NC_("view-zoom-action", "1:_8 (12.5%)"), "<shift>4",
+ NC_("view-zoom-action", "Zoom 1:8"),
+ 1250,
+ GIMP_HELP_VIEW_ZOOM_OUT },
+
+ { "view-zoom-1-16", NULL,
+ NC_("view-zoom-action", "1:1_6 (6.25%)"), "<shift>5",
+ NC_("view-zoom-action", "Zoom 1:16"),
+ 625,
+ GIMP_HELP_VIEW_ZOOM_OUT },
+
+ { "view-zoom-other", NULL,
+ NC_("view-zoom-action", "Othe_r zoom factor..."), NULL,
+ NC_("view-zoom-action", "Set a custom zoom factor"),
+ 0,
+ GIMP_HELP_VIEW_ZOOM_OTHER }
+};
+
+static const GimpToggleActionEntry view_flip_actions[] =
+{
+ { "view-flip-horizontally", GIMP_ICON_OBJECT_FLIP_HORIZONTAL,
+ NC_("view-action", "Flip _Horizontally"), NULL,
+ NC_("view-action", "Flip the view horizontally"),
+ view_flip_horizontally_cmd_callback,
+ FALSE,
+ GIMP_HELP_VIEW_FLIP },
+
+ { "view-flip-vertically", GIMP_ICON_OBJECT_FLIP_VERTICAL,
+ NC_("view-action", "Flip _Vertically"), NULL,
+ NC_("view-action", "Flip the view vertically"),
+ view_flip_vertically_cmd_callback,
+ FALSE,
+ GIMP_HELP_VIEW_FLIP }
+};
+
+static const GimpEnumActionEntry view_rotate_absolute_actions[] =
+{
+ { "view-rotate-set-absolute", NULL,
+ "Display Rotation Absolute Angle Set", NULL, NULL,
+ GIMP_ACTION_SELECT_SET, TRUE,
+ NULL },
+
+ { "view-rotate-reset", GIMP_ICON_RESET,
+ NC_("view-action", "_Reset Flip & Rotate"), "exclam",
+ NC_("view-action",
+ "Reset flipping to unflipped and the angle of rotation to 0°"),
+ GIMP_ACTION_SELECT_SET_TO_DEFAULT, FALSE,
+ GIMP_HELP_VIEW_ROTATE_RESET },
+};
+
+static const GimpEnumActionEntry view_rotate_relative_actions[] =
+{
+ { "view-rotate-15", GIMP_ICON_OBJECT_ROTATE_90,
+ NC_("view-action", "Rotate 15° _clockwise"), NULL,
+ NC_("view-action", "Rotate the view 15 degrees to the right"),
+ GIMP_ACTION_SELECT_NEXT, FALSE,
+ GIMP_HELP_VIEW_ROTATE_15 },
+
+ { "view-rotate-90", GIMP_ICON_OBJECT_ROTATE_90,
+ NC_("view-action", "Rotate 90° _clockwise"), NULL,
+ NC_("view-action", "Rotate the view 90 degrees to the right"),
+ GIMP_ACTION_SELECT_SKIP_NEXT, FALSE,
+ GIMP_HELP_VIEW_ROTATE_90 },
+
+ { "view-rotate-180", GIMP_ICON_OBJECT_ROTATE_180,
+ NC_("view-action", "Rotate _180°"), NULL,
+ NC_("view-action", "Turn the view upside-down"),
+ GIMP_ACTION_SELECT_LAST, FALSE,
+ GIMP_HELP_VIEW_ROTATE_180 },
+
+ { "view-rotate-270", GIMP_ICON_OBJECT_ROTATE_270,
+ NC_("view-action", "Rotate 90° counter-clock_wise"), NULL,
+ NC_("view-action", "Rotate the view 90 degrees to the left"),
+ GIMP_ACTION_SELECT_SKIP_PREVIOUS, FALSE,
+ GIMP_HELP_VIEW_ROTATE_270 },
+
+ { "view-rotate-345", GIMP_ICON_OBJECT_ROTATE_270,
+ NC_("view-action", "Rotate 15° counter-clock_wise"), NULL,
+ NC_("view-action", "Rotate the view 15 degrees to the left"),
+ GIMP_ACTION_SELECT_PREVIOUS, FALSE,
+ GIMP_HELP_VIEW_ROTATE_345 }
+};
+
+static const GimpRadioActionEntry view_display_intent_actions[] =
+{
+ { "view-display-intent-perceptual", NULL,
+ NC_("view-action", "_Perceptual"), NULL,
+ NC_("view-action", "Display rendering intent is perceptual"),
+ GIMP_COLOR_RENDERING_INTENT_PERCEPTUAL,
+ GIMP_HELP_VIEW_COLOR_MANAGEMENT },
+
+ { "view-display-intent-relative-colorimetric", NULL,
+ NC_("view-action", "_Relative Colorimetric"), NULL,
+ NC_("view-action", "Display rendering intent is relative colorimetric"),
+ GIMP_COLOR_RENDERING_INTENT_RELATIVE_COLORIMETRIC,
+ GIMP_HELP_VIEW_COLOR_MANAGEMENT },
+
+ { "view-display-intent-saturation", NULL,
+ NC_("view-action", "_Saturation"), NULL,
+ NC_("view-action", "Display rendering intent is saturation"),
+ GIMP_COLOR_RENDERING_INTENT_SATURATION,
+ GIMP_HELP_VIEW_COLOR_MANAGEMENT },
+
+ { "view-display-intent-absolute-colorimetric", NULL,
+ NC_("view-action", "_Absolute Colorimetric"), NULL,
+ NC_("view-action", "Display rendering intent is absolute colorimetric"),
+ GIMP_COLOR_RENDERING_INTENT_ABSOLUTE_COLORIMETRIC,
+ GIMP_HELP_VIEW_COLOR_MANAGEMENT }
+};
+
+static const GimpRadioActionEntry view_softproof_intent_actions[] =
+{
+ { "view-softproof-intent-perceptual", NULL,
+ NC_("view-action", "_Perceptual"), NULL,
+ NC_("view-action", "Soft-proofing rendering intent is perceptual"),
+ GIMP_COLOR_RENDERING_INTENT_PERCEPTUAL,
+ GIMP_HELP_VIEW_COLOR_MANAGEMENT },
+
+ { "view-softproof-intent-relative-colorimetric", NULL,
+ NC_("view-action", "_Relative Colorimetric"), NULL,
+ NC_("view-action", "Soft-proofing rendering intent is relative colorimetric"),
+ GIMP_COLOR_RENDERING_INTENT_RELATIVE_COLORIMETRIC,
+ GIMP_HELP_VIEW_COLOR_MANAGEMENT },
+
+ { "view-softproof-intent-saturation", NULL,
+ NC_("view-action", "_Saturation"), NULL,
+ NC_("view-action", "Soft-proofing rendering intent is saturation"),
+ GIMP_COLOR_RENDERING_INTENT_SATURATION,
+ GIMP_HELP_VIEW_COLOR_MANAGEMENT },
+
+ { "view-softproof-intent-absolute-colorimetric", NULL,
+ NC_("view-action", "_Absolute Colorimetric"), NULL,
+ NC_("view-action", "Soft-proofing rendering intent is absolute colorimetric"),
+ GIMP_COLOR_RENDERING_INTENT_ABSOLUTE_COLORIMETRIC,
+ GIMP_HELP_VIEW_COLOR_MANAGEMENT }
+};
+
+static const GimpEnumActionEntry view_padding_color_actions[] =
+{
+ { "view-padding-color-theme", NULL,
+ NC_("view-padding-color", "From _Theme"), NULL,
+ NC_("view-padding-color", "Use the current theme's background color"),
+ GIMP_CANVAS_PADDING_MODE_DEFAULT, FALSE,
+ GIMP_HELP_VIEW_PADDING_COLOR },
+
+ { "view-padding-color-light-check", NULL,
+ NC_("view-padding-color", "_Light Check Color"), NULL,
+ NC_("view-padding-color", "Use the light check color"),
+ GIMP_CANVAS_PADDING_MODE_LIGHT_CHECK, FALSE,
+ GIMP_HELP_VIEW_PADDING_COLOR },
+
+ { "view-padding-color-dark-check", NULL,
+ NC_("view-padding-color", "_Dark Check Color"), NULL,
+ NC_("view-padding-color", "Use the dark check color"),
+ GIMP_CANVAS_PADDING_MODE_DARK_CHECK, FALSE,
+ GIMP_HELP_VIEW_PADDING_COLOR },
+
+ { "view-padding-color-custom", GIMP_ICON_PALETTE,
+ NC_("view-padding-color", "_Custom Color..."), NULL,
+ NC_("view-padding-color", "Use an arbitrary color"),
+ GIMP_CANVAS_PADDING_MODE_CUSTOM, FALSE,
+ GIMP_HELP_VIEW_PADDING_COLOR },
+
+ { "view-padding-color-prefs", GIMP_ICON_RESET,
+ NC_("view-padding-color", "As in _Preferences"), NULL,
+ NC_("view-padding-color",
+ "Reset padding color to what's configured in preferences"),
+ GIMP_CANVAS_PADDING_MODE_RESET, FALSE,
+ GIMP_HELP_VIEW_PADDING_COLOR }
+};
+
+static const GimpToggleActionEntry view_padding_color_toggle_actions[] =
+{
+ { "view-padding-color-in-show-all", NULL,
+ NC_("view-padding-color", "Keep Padding in \"Show _All\" Mode"), NULL,
+ NC_("view-padding-color",
+ "Keep canvas padding when \"View -> Show All\" is enabled"),
+ view_padding_color_in_show_all_cmd_callback,
+ FALSE,
+ GIMP_HELP_VIEW_PADDING_COLOR }
+};
+
+static const GimpEnumActionEntry view_scroll_horizontal_actions[] =
+{
+ { "view-scroll-horizontal", NULL,
+ NC_("view-action", "Set horizontal scroll offset"), NULL, NULL,
+ GIMP_ACTION_SELECT_SET, TRUE,
+ NULL },
+
+ { "view-scroll-left-border", NULL,
+ NC_("view-action", "Scroll to left border"), NULL, NULL,
+ GIMP_ACTION_SELECT_FIRST, FALSE,
+ NULL },
+
+ { "view-scroll-right-border", NULL,
+ NC_("view-action", "Scroll to right border"), NULL, NULL,
+ GIMP_ACTION_SELECT_LAST, FALSE,
+ NULL },
+
+ { "view-scroll-left", NULL,
+ NC_("view-action", "Scroll left"), NULL, NULL,
+ GIMP_ACTION_SELECT_PREVIOUS, FALSE,
+ NULL },
+
+ { "view-scroll-right", NULL,
+ NC_("view-action", "Scroll right"), NULL, NULL,
+ GIMP_ACTION_SELECT_NEXT, FALSE,
+ NULL },
+
+ { "view-scroll-page-left", NULL,
+ NC_("view-action", "Scroll page left"), NULL, NULL,
+ GIMP_ACTION_SELECT_SKIP_PREVIOUS, FALSE,
+ NULL },
+
+ { "view-scroll-page-right", NULL,
+ NC_("view-action", "Scroll page right"), NULL, NULL,
+ GIMP_ACTION_SELECT_SKIP_NEXT, FALSE,
+ NULL }
+};
+
+static const GimpEnumActionEntry view_scroll_vertical_actions[] =
+{
+ { "view-scroll-vertical", NULL,
+ NC_("view-action", "Set vertical scroll offset"), NULL, NULL,
+ GIMP_ACTION_SELECT_SET, TRUE,
+ NULL },
+
+ { "view-scroll-top-border", NULL,
+ NC_("view-action", "Scroll to top border"), NULL, NULL,
+ GIMP_ACTION_SELECT_FIRST, FALSE,
+ NULL },
+
+ { "view-scroll-bottom-border", NULL,
+ NC_("view-action", "Scroll to bottom border"), NULL, NULL,
+ GIMP_ACTION_SELECT_LAST, FALSE,
+ NULL },
+
+ { "view-scroll-up", NULL,
+ NC_("view-action", "Scroll up"), NULL, NULL,
+ GIMP_ACTION_SELECT_PREVIOUS, FALSE,
+ NULL },
+
+ { "view-scroll-down", NULL,
+ NC_("view-action", "Scroll down"), NULL, NULL,
+ GIMP_ACTION_SELECT_NEXT, FALSE,
+ NULL },
+
+ { "view-scroll-page-up", NULL,
+ NC_("view-action", "Scroll page up"), NULL, NULL,
+ GIMP_ACTION_SELECT_SKIP_PREVIOUS, FALSE,
+ NULL },
+
+ { "view-scroll-page-down", NULL,
+ NC_("view-action", "Scroll page down"), NULL, NULL,
+ GIMP_ACTION_SELECT_SKIP_NEXT, FALSE,
+ NULL }
+};
+
+
+void
+view_actions_setup (GimpActionGroup *group)
+{
+ GimpAction *action;
+
+ gimp_action_group_add_actions (group, "view-action",
+ view_actions,
+ G_N_ELEMENTS (view_actions));
+
+ gimp_action_group_add_toggle_actions (group, "view-action",
+ view_toggle_actions,
+ G_N_ELEMENTS (view_toggle_actions));
+
+ gimp_action_group_add_enum_actions (group, "view-zoom-action",
+ view_zoom_actions,
+ G_N_ELEMENTS (view_zoom_actions),
+ view_zoom_cmd_callback);
+
+ gimp_action_group_add_radio_actions (group, "view-zoom-action",
+ view_zoom_explicit_actions,
+ G_N_ELEMENTS (view_zoom_explicit_actions),
+ NULL,
+ 10000,
+ view_zoom_explicit_cmd_callback);
+
+ gimp_action_group_add_toggle_actions (group, "view-action",
+ view_flip_actions,
+ G_N_ELEMENTS (view_flip_actions));
+
+ gimp_action_group_add_enum_actions (group, "view-action",
+ view_rotate_absolute_actions,
+ G_N_ELEMENTS (view_rotate_absolute_actions),
+ view_rotate_absolute_cmd_callback);
+
+ gimp_action_group_add_enum_actions (group, "view-action",
+ view_rotate_relative_actions,
+ G_N_ELEMENTS (view_rotate_relative_actions),
+ view_rotate_relative_cmd_callback);
+
+ gimp_action_group_add_radio_actions (group, "view-action",
+ view_display_intent_actions,
+ G_N_ELEMENTS (view_display_intent_actions),
+ NULL,
+ GIMP_COLOR_MANAGEMENT_DISPLAY,
+ view_display_intent_cmd_callback);
+
+ gimp_action_group_add_radio_actions (group, "view-action",
+ view_softproof_intent_actions,
+ G_N_ELEMENTS (view_softproof_intent_actions),
+ NULL,
+ GIMP_COLOR_MANAGEMENT_DISPLAY,
+ view_softproof_intent_cmd_callback);
+
+ gimp_action_group_add_enum_actions (group, "view-padding-color",
+ view_padding_color_actions,
+ G_N_ELEMENTS (view_padding_color_actions),
+ view_padding_color_cmd_callback);
+
+ gimp_action_group_add_toggle_actions (group, "view-padding-color",
+ view_padding_color_toggle_actions,
+ G_N_ELEMENTS (view_padding_color_toggle_actions));
+
+ gimp_action_group_add_enum_actions (group, "view-action",
+ view_scroll_horizontal_actions,
+ G_N_ELEMENTS (view_scroll_horizontal_actions),
+ view_scroll_horizontal_cmd_callback);
+
+ gimp_action_group_add_enum_actions (group, "view-action",
+ view_scroll_vertical_actions,
+ G_N_ELEMENTS (view_scroll_vertical_actions),
+ view_scroll_vertical_cmd_callback);
+
+ /* connect "activate" of view-zoom-other manually so it can be
+ * selected even if it's the active item of the radio group
+ */
+ action = gimp_action_group_get_action (group, "view-zoom-other");
+
+ g_signal_connect (action, "activate",
+ G_CALLBACK (view_zoom_other_cmd_callback),
+ group->user_data);
+
+ g_signal_connect_object (group->gimp->config, "notify::check-type",
+ G_CALLBACK (view_actions_check_type_notify),
+ group, 0);
+ view_actions_check_type_notify (GIMP_DISPLAY_CONFIG (group->gimp->config),
+ NULL, group);
+
+ if (GIMP_IS_IMAGE_WINDOW (group->user_data) ||
+ GIMP_IS_GIMP (group->user_data))
+ {
+ /* add window actions only if the context of the group is
+ * the display itself or the global popup (not if the context
+ * is a dock)
+ * (see dock-actions.c)
+ */
+ window_actions_setup (group, GIMP_HELP_VIEW_CHANGE_SCREEN);
+ }
+}
+
+void
+view_actions_update (GimpActionGroup *group,
+ gpointer data)
+{
+ GimpDisplay *display = action_data_get_display (data);
+ GimpImage *image = NULL;
+ GimpDisplayShell *shell = NULL;
+ GimpDisplayOptions *options = NULL;
+ GimpColorConfig *color_config = NULL;
+ gchar *label = NULL;
+ gboolean fullscreen = FALSE;
+ gboolean revert_enabled = FALSE; /* able to revert zoom? */
+ gboolean flip_horizontally = FALSE;
+ gboolean flip_vertically = FALSE;
+ gboolean cm = FALSE;
+ gboolean sp = FALSE;
+ gboolean d_bpc = FALSE;
+ gboolean s_bpc = FALSE;
+ gboolean gammut = FALSE;
+
+ if (display)
+ {
+ GimpImageWindow *window;
+ const gchar *action = NULL;
+
+ image = gimp_display_get_image (display);
+ shell = gimp_display_get_shell (display);
+ window = gimp_display_shell_get_window (shell);
+
+ if (window)
+ fullscreen = gimp_image_window_get_fullscreen (window);
+
+ options = (image ?
+ (fullscreen ? shell->fullscreen_options : shell->options) :
+ shell->no_image_options);
+
+ revert_enabled = gimp_display_shell_scale_can_revert (shell);
+
+ flip_horizontally = shell->flip_horizontally;
+ flip_vertically = shell->flip_vertically;
+
+ color_config = gimp_display_shell_get_color_config (shell);
+
+ switch (gimp_color_config_get_mode (color_config))
+ {
+ case GIMP_COLOR_MANAGEMENT_OFF:
+ break;
+
+ case GIMP_COLOR_MANAGEMENT_DISPLAY:
+ cm = (image != NULL);
+ break;
+
+ case GIMP_COLOR_MANAGEMENT_SOFTPROOF:
+ cm = (image != NULL);
+ sp = (image != NULL);
+ break;
+ }
+
+ switch (gimp_color_config_get_display_intent (color_config))
+ {
+ case GIMP_COLOR_RENDERING_INTENT_PERCEPTUAL:
+ action = "view-display-intent-perceptual";
+ break;
+
+ case GIMP_COLOR_RENDERING_INTENT_RELATIVE_COLORIMETRIC:
+ action = "view-display-intent-relative-colorimetric";
+ break;
+
+ case GIMP_COLOR_RENDERING_INTENT_SATURATION:
+ action = "view-display-intent-saturation";
+ break;
+
+ case GIMP_COLOR_RENDERING_INTENT_ABSOLUTE_COLORIMETRIC:
+ action = "view-display-intent-absolute-colorimetric";
+ break;
+ }
+
+ gimp_action_group_set_action_active (group, action, TRUE);
+
+ switch (gimp_color_config_get_simulation_intent (color_config))
+ {
+ case GIMP_COLOR_RENDERING_INTENT_PERCEPTUAL:
+ action = "view-softproof-intent-perceptual";
+ break;
+
+ case GIMP_COLOR_RENDERING_INTENT_RELATIVE_COLORIMETRIC:
+ action = "view-softproof-intent-relative-colorimetric";
+ break;
+
+ case GIMP_COLOR_RENDERING_INTENT_SATURATION:
+ action = "view-softproof-intent-saturation";
+ break;
+
+ case GIMP_COLOR_RENDERING_INTENT_ABSOLUTE_COLORIMETRIC:
+ action = "view-softproof-intent-absolute-colorimetric";
+ break;
+ }
+
+ gimp_action_group_set_action_active (group, action, TRUE);
+
+ d_bpc = gimp_color_config_get_display_bpc (color_config);
+ s_bpc = gimp_color_config_get_simulation_bpc (color_config);
+ gammut = gimp_color_config_get_simulation_gamut_check (color_config);
+ }
+
+#define SET_ACTIVE(action,condition) \
+ gimp_action_group_set_action_active (group, action, (condition) != 0)
+#define SET_SENSITIVE(action,condition) \
+ gimp_action_group_set_action_sensitive (group, action, (condition) != 0)
+#define SET_COLOR(action,color) \
+ gimp_action_group_set_action_color (group, action, color, FALSE)
+
+ SET_SENSITIVE ("view-new", image);
+ SET_SENSITIVE ("view-close", image);
+
+ SET_SENSITIVE ("view-show-all", image);
+ SET_ACTIVE ("view-show-all", display && shell->show_all);
+
+ SET_SENSITIVE ("view-dot-for-dot", image);
+ SET_ACTIVE ("view-dot-for-dot", display && shell->dot_for_dot);
+
+ SET_SENSITIVE ("view-scroll-center", image);
+
+ SET_SENSITIVE ("view-zoom-revert", revert_enabled);
+ if (revert_enabled)
+ {
+ label = g_strdup_printf (_("Re_vert Zoom (%d%%)"),
+ ROUND (shell->last_scale * 100));
+ gimp_action_group_set_action_label (group, "view-zoom-revert", label);
+ g_free (label);
+ }
+ else
+ {
+ gimp_action_group_set_action_label (group, "view-zoom-revert",
+ _("Re_vert Zoom"));
+ }
+
+ SET_SENSITIVE ("view-zoom", image);
+ SET_SENSITIVE ("view-zoom-minimum", image);
+ SET_SENSITIVE ("view-zoom-maximum", image);
+ SET_SENSITIVE ("view-zoom-in", image);
+ SET_SENSITIVE ("view-zoom-in-accel", image);
+ SET_SENSITIVE ("view-zoom-in-skip", image);
+ SET_SENSITIVE ("view-zoom-out", image);
+ SET_SENSITIVE ("view-zoom-out-accel", image);
+ SET_SENSITIVE ("view-zoom-out-skip", image);
+
+ SET_SENSITIVE ("view-zoom-fit-in", image);
+ SET_SENSITIVE ("view-zoom-fill", image);
+ SET_SENSITIVE ("view-zoom-selection", image);
+ SET_SENSITIVE ("view-zoom-revert", image);
+
+ SET_SENSITIVE ("view-zoom-16-1", image);
+ SET_SENSITIVE ("view-zoom-16-1-accel", image);
+ SET_SENSITIVE ("view-zoom-8-1", image);
+ SET_SENSITIVE ("view-zoom-8-1-accel", image);
+ SET_SENSITIVE ("view-zoom-4-1", image);
+ SET_SENSITIVE ("view-zoom-4-1-accel", image);
+ SET_SENSITIVE ("view-zoom-2-1", image);
+ SET_SENSITIVE ("view-zoom-2-1-accel", image);
+ SET_SENSITIVE ("view-zoom-1-1", image);
+ SET_SENSITIVE ("view-zoom-1-1-accel", image);
+ SET_SENSITIVE ("view-zoom-1-2", image);
+ SET_SENSITIVE ("view-zoom-1-4", image);
+ SET_SENSITIVE ("view-zoom-1-8", image);
+ SET_SENSITIVE ("view-zoom-1-16", image);
+ SET_SENSITIVE ("view-zoom-other", image);
+
+ SET_SENSITIVE ("view-flip-horizontally", image);
+ SET_ACTIVE ("view-flip-horizontally", flip_horizontally);
+
+ SET_SENSITIVE ("view-flip-vertically", image);
+ SET_ACTIVE ("view-flip-vertically", flip_vertically);
+
+ SET_SENSITIVE ("view-rotate-reset", image);
+ SET_SENSITIVE ("view-rotate-15", image);
+ SET_SENSITIVE ("view-rotate-345", image);
+ SET_SENSITIVE ("view-rotate-90", image);
+ SET_SENSITIVE ("view-rotate-180", image);
+ SET_SENSITIVE ("view-rotate-270", image);
+ SET_SENSITIVE ("view-rotate-other", image);
+
+ if (image)
+ {
+ view_actions_set_zoom (group, shell);
+ view_actions_set_rotate (group, shell);
+ }
+
+ SET_SENSITIVE ("view-navigation-window", image);
+ SET_SENSITIVE ("view-display-filters", image);
+
+ SET_SENSITIVE ("view-color-management-enable", image);
+ SET_ACTIVE ("view-color-management-enable", cm);
+ SET_SENSITIVE ("view-color-management-softproof", image);
+ SET_ACTIVE ("view-color-management-softproof", sp);
+ SET_SENSITIVE ("view-display-intent-perceptual", cm);
+ SET_SENSITIVE ("view-display-intent-relative-colorimetric", cm);
+ SET_SENSITIVE ("view-display-intent-saturation", cm);
+ SET_SENSITIVE ("view-display-intent-absolute-colorimetric", cm);
+ SET_SENSITIVE ("view-display-black-point-compensation", cm);
+ SET_ACTIVE ("view-display-black-point-compensation", d_bpc);
+ SET_SENSITIVE ("view-softproof-profile", sp);
+ SET_SENSITIVE ("view-softproof-intent-perceptual", sp);
+ SET_SENSITIVE ("view-softproof-intent-relative-colorimetric", sp);
+ SET_SENSITIVE ("view-softproof-intent-saturation", sp);
+ SET_SENSITIVE ("view-softproof-intent-absolute-colorimetric", sp);
+ SET_SENSITIVE ("view-softproof-black-point-compensation", sp);
+ SET_ACTIVE ("view-softproof-black-point-compensation", s_bpc);
+ SET_SENSITIVE ("view-softproof-gamut-check", sp);
+ SET_ACTIVE ("view-softproof-gamut-check", gammut);
+ SET_SENSITIVE ("view-color-management-reset", image);
+
+ SET_SENSITIVE ("view-show-selection", image);
+ SET_ACTIVE ("view-show-selection", display && options->show_selection);
+ SET_SENSITIVE ("view-show-layer-boundary", image);
+ SET_ACTIVE ("view-show-layer-boundary", display && options->show_layer_boundary);
+ SET_SENSITIVE ("view-show-canvas-boundary", image && shell->show_all);
+ SET_ACTIVE ("view-show-canvas-boundary", display && options->show_canvas_boundary);
+ SET_SENSITIVE ("view-show-guides", image);
+ SET_ACTIVE ("view-show-guides", display && options->show_guides);
+ SET_SENSITIVE ("view-show-grid", image);
+ SET_ACTIVE ("view-show-grid", display && options->show_grid);
+ SET_SENSITIVE ("view-show-sample-points", image);
+ SET_ACTIVE ("view-show-sample-points", display && options->show_sample_points);
+
+ SET_SENSITIVE ("view-snap-to-guides", image);
+ SET_ACTIVE ("view-snap-to-guides", display && options->snap_to_guides);
+ SET_SENSITIVE ("view-snap-to-grid", image);
+ SET_ACTIVE ("view-snap-to-grid", display && options->snap_to_grid);
+ SET_SENSITIVE ("view-snap-to-canvas", image);
+ SET_ACTIVE ("view-snap-to-canvas", display && options->snap_to_canvas);
+ SET_SENSITIVE ("view-snap-to-vectors", image);
+ SET_ACTIVE ("view-snap-to-vectors", display && options->snap_to_path);
+
+ SET_SENSITIVE ("view-padding-color-theme", image);
+ SET_SENSITIVE ("view-padding-color-light-check", image);
+ SET_SENSITIVE ("view-padding-color-dark-check", image);
+ SET_SENSITIVE ("view-padding-color-custom", image);
+ SET_SENSITIVE ("view-padding-color-prefs", image);
+
+ if (display)
+ {
+ SET_COLOR ("view-padding-color-menu", &options->padding_color);
+
+ if (shell->canvas)
+ {
+ GtkStyle *style = gtk_widget_get_style (shell->canvas);
+ GimpRGB color;
+
+ gtk_widget_ensure_style (shell->canvas);
+ gimp_rgb_set_gdk_color (&color, style->bg + GTK_STATE_NORMAL);
+ gimp_rgb_set_alpha (&color, GIMP_OPACITY_OPAQUE);
+
+ SET_COLOR ("view-padding-color-theme", &color);
+ }
+ }
+
+ SET_SENSITIVE ("view-padding-color-in-show-all", image);
+ SET_ACTIVE ("view-padding-color-in-show-all", display && options->padding_in_show_all);
+
+ SET_SENSITIVE ("view-show-menubar", image);
+ SET_ACTIVE ("view-show-menubar", display && options->show_menubar);
+ SET_SENSITIVE ("view-show-rulers", image);
+ SET_ACTIVE ("view-show-rulers", display && options->show_rulers);
+ SET_SENSITIVE ("view-show-scrollbars", image);
+ SET_ACTIVE ("view-show-scrollbars", display && options->show_scrollbars);
+ SET_SENSITIVE ("view-show-statusbar", image);
+ SET_ACTIVE ("view-show-statusbar", display && options->show_statusbar);
+
+ SET_SENSITIVE ("view-shrink-wrap", image);
+ SET_ACTIVE ("view-fullscreen", display && fullscreen);
+
+ if (GIMP_IS_IMAGE_WINDOW (group->user_data) ||
+ GIMP_IS_GIMP (group->user_data))
+ {
+ GtkWidget *window = NULL;
+
+ if (shell)
+ window = gtk_widget_get_toplevel (GTK_WIDGET (shell));
+
+ /* see view_actions_setup() */
+ if (GTK_IS_WINDOW (window))
+ window_actions_update (group, window);
+ }
+
+#undef SET_ACTIVE
+#undef SET_SENSITIVE
+#undef SET_COLOR
+}
+
+
+/* private functions */
+
+static void
+view_actions_set_zoom (GimpActionGroup *group,
+ GimpDisplayShell *shell)
+{
+ const gchar *action = NULL;
+ gchar *str;
+ gchar *label;
+ guint scale;
+
+ g_object_get (shell->zoom,
+ "percentage", &str,
+ NULL);
+
+ scale = ROUND (gimp_zoom_model_get_factor (shell->zoom) * 1000);
+
+ switch (scale)
+ {
+ case 16000: action = "view-zoom-16-1"; break;
+ case 8000: action = "view-zoom-8-1"; break;
+ case 4000: action = "view-zoom-4-1"; break;
+ case 2000: action = "view-zoom-2-1"; break;
+ case 1000: action = "view-zoom-1-1"; break;
+ case 500: action = "view-zoom-1-2"; break;
+ case 250: action = "view-zoom-1-4"; break;
+ case 125: action = "view-zoom-1-8"; break;
+ case 63:
+ case 62: action = "view-zoom-1-16"; break;
+ }
+
+ if (! action)
+ {
+ action = "view-zoom-other";
+
+ label = g_strdup_printf (_("Othe_r (%s)..."), str);
+ gimp_action_group_set_action_label (group, action, label);
+ g_free (label);
+
+ shell->other_scale = gimp_zoom_model_get_factor (shell->zoom);
+ }
+
+ gimp_action_group_set_action_active (group, action, TRUE);
+
+ label = g_strdup_printf (_("_Zoom (%s)"), str);
+ gimp_action_group_set_action_label (group, "view-zoom-menu", label);
+ g_free (label);
+
+ /* flag as dirty */
+ shell->other_scale = - fabs (shell->other_scale);
+
+ g_free (str);
+}
+
+static void
+view_actions_set_rotate (GimpActionGroup *group,
+ GimpDisplayShell *shell)
+{
+ const gchar *flip;
+ gchar *label;
+
+ if (shell->flip_horizontally &&
+ shell->flip_vertically)
+ {
+ /* please preserve the trailing space */
+ /* H: Horizontal, V: Vertical */
+ flip = _("(H+V) ");
+ }
+ else if (shell->flip_horizontally)
+ {
+ /* please preserve the trailing space */
+ /* H: Horizontal */
+ flip = _("(H) ");
+ }
+ else if (shell->flip_vertically)
+ {
+ /* please preserve the trailing space */
+ /* V: Vertical */
+ flip = _("(V) ");
+ }
+ else
+ {
+ flip = "";
+ }
+
+ label = g_strdup_printf (_("_Flip %s& Rotate (%d°)"),
+ flip, (gint) shell->rotate_angle);
+ gimp_action_group_set_action_label (group, "view-rotate-menu", label);
+ g_free (label);
+}
+
+static void
+view_actions_check_type_notify (GimpDisplayConfig *config,
+ GParamSpec *pspec,
+ GimpActionGroup *group)
+{
+ gimp_action_group_set_action_color (group, "view-padding-color-light-check",
+ gimp_render_light_check_color (),
+ FALSE);
+ gimp_action_group_set_action_color (group, "view-padding-color-dark-check",
+ gimp_render_dark_check_color (),
+ FALSE);
+}
diff --git a/app/actions/view-actions.h b/app/actions/view-actions.h
new file mode 100644
index 0000000..97aad0a
--- /dev/null
+++ b/app/actions/view-actions.h
@@ -0,0 +1,27 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __VIEW_ACTIONS_H__
+#define __VIEW_ACTIONS_H__
+
+
+void view_actions_setup (GimpActionGroup *group);
+void view_actions_update (GimpActionGroup *group,
+ gpointer data);
+
+
+#endif /* __VIEW_ACTIONS_H__ */
diff --git a/app/actions/view-commands.c b/app/actions/view-commands.c
new file mode 100644
index 0000000..2c2629c
--- /dev/null
+++ b/app/actions/view-commands.c
@@ -0,0 +1,1281 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpmath/gimpmath.h"
+#include "libgimpconfig/gimpconfig.h"
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "actions-types.h"
+
+#include "config/gimpdisplayoptions.h"
+#include "config/gimpguiconfig.h"
+
+#include "core/gimp.h"
+#include "core/gimpcontext.h"
+#include "core/gimpimage.h"
+#include "core/gimpgrouplayer.h"
+
+#include "widgets/gimpactiongroup.h"
+#include "widgets/gimpcolordialog.h"
+#include "widgets/gimpdock.h"
+#include "widgets/gimpdialogfactory.h"
+#include "widgets/gimpuimanager.h"
+#include "widgets/gimpwidgets-utils.h"
+#include "widgets/gimpwindowstrategy.h"
+
+#include "display/gimpdisplay.h"
+#include "display/gimpdisplay-foreach.h"
+#include "display/gimpdisplayshell.h"
+#include "display/gimpdisplayshell-appearance.h"
+#include "display/gimpdisplayshell-filter-dialog.h"
+#include "display/gimpdisplayshell-rotate.h"
+#include "display/gimpdisplayshell-rotate-dialog.h"
+#include "display/gimpdisplayshell-scale.h"
+#include "display/gimpdisplayshell-scale-dialog.h"
+#include "display/gimpdisplayshell-scroll.h"
+#include "display/gimpdisplayshell-close.h"
+#include "display/gimpimagewindow.h"
+
+#include "dialogs/color-profile-dialog.h"
+#include "dialogs/dialogs.h"
+
+#include "actions.h"
+#include "view-commands.h"
+
+#include "gimp-intl.h"
+
+
+#define SET_ACTIVE(manager,action_name,active) \
+ { GimpActionGroup *group = \
+ gimp_ui_manager_get_action_group (manager, "view"); \
+ gimp_action_group_set_action_active (group, action_name, active); }
+
+#define IS_ACTIVE_DISPLAY(display) \
+ ((display) == \
+ gimp_context_get_display (gimp_get_user_context ((display)->gimp)))
+
+
+/* local function prototypes */
+
+static void view_softproof_profile_callback (GtkWidget *dialog,
+ GimpImage *image,
+ GimpColorProfile *new_profile,
+ GFile *new_file,
+ GimpColorRenderingIntent intent,
+ gboolean bpc,
+ gpointer user_data);
+static void view_padding_color_dialog_update (GimpColorDialog *dialog,
+ const GimpRGB *color,
+ GimpColorDialogState state,
+ GimpDisplayShell *shell);
+
+
+/* public functions */
+
+void
+view_new_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpDisplay *display;
+ GimpDisplayShell *shell;
+ return_if_no_display (display, data);
+
+ shell = gimp_display_get_shell (display);
+
+ gimp_create_display (display->gimp,
+ gimp_display_get_image (display),
+ shell->unit, gimp_zoom_model_get_factor (shell->zoom),
+ G_OBJECT (gtk_widget_get_screen (GTK_WIDGET (shell))),
+ gimp_widget_get_monitor (GTK_WIDGET (shell)));
+}
+
+void
+view_close_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpDisplay *display;
+ GimpDisplayShell *shell;
+ GimpImage *image;
+ return_if_no_display (display, data);
+
+ shell = gimp_display_get_shell (display);
+ image = gimp_display_get_image (display);
+
+ /* Check for the image so we don't close the last display. */
+ if (image)
+ gimp_display_shell_close (shell, FALSE);
+}
+
+void
+view_scroll_center_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpDisplay *display;
+ return_if_no_display (display, data);
+
+ gimp_display_shell_scroll_center_image (gimp_display_get_shell (display),
+ TRUE, TRUE);
+}
+
+void
+view_zoom_fit_in_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpDisplay *display;
+ return_if_no_display (display, data);
+
+ gimp_display_shell_scale_fit_in (gimp_display_get_shell (display));
+}
+
+void
+view_zoom_fill_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpDisplay *display;
+ return_if_no_display (display, data);
+
+ gimp_display_shell_scale_fill (gimp_display_get_shell (display));
+}
+
+void
+view_zoom_selection_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpDisplay *display;
+ GimpImage *image;
+ gint x, y, width, height;
+ return_if_no_display (display, data);
+ return_if_no_image (image, data);
+
+ gimp_item_bounds (GIMP_ITEM (gimp_image_get_mask (image)),
+ &x, &y, &width, &height);
+
+ gimp_display_shell_scale_to_rectangle (gimp_display_get_shell (display),
+ GIMP_ZOOM_IN,
+ x, y, width, height,
+ FALSE);
+}
+
+void
+view_zoom_revert_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpDisplay *display;
+ return_if_no_display (display, data);
+
+ gimp_display_shell_scale_revert (gimp_display_get_shell (display));
+}
+
+void
+view_zoom_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpDisplayShell *shell;
+ GimpActionSelectType select_type;
+ return_if_no_shell (shell, data);
+
+ select_type = (GimpActionSelectType) g_variant_get_int32 (value);
+
+ switch (select_type)
+ {
+ case GIMP_ACTION_SELECT_FIRST:
+ gimp_display_shell_scale (shell,
+ GIMP_ZOOM_OUT_MAX,
+ 0.0,
+ GIMP_ZOOM_FOCUS_BEST_GUESS);
+ break;
+
+ case GIMP_ACTION_SELECT_LAST:
+ gimp_display_shell_scale (shell,
+ GIMP_ZOOM_IN_MAX,
+ 0.0,
+ GIMP_ZOOM_FOCUS_BEST_GUESS);
+ break;
+
+ case GIMP_ACTION_SELECT_PREVIOUS:
+ gimp_display_shell_scale (shell,
+ GIMP_ZOOM_OUT,
+ 0.0,
+ GIMP_ZOOM_FOCUS_BEST_GUESS);
+ break;
+
+ case GIMP_ACTION_SELECT_NEXT:
+ gimp_display_shell_scale (shell,
+ GIMP_ZOOM_IN,
+ 0.0,
+ GIMP_ZOOM_FOCUS_BEST_GUESS);
+ break;
+
+ case GIMP_ACTION_SELECT_SKIP_PREVIOUS:
+ gimp_display_shell_scale (shell,
+ GIMP_ZOOM_OUT_MORE,
+ 0.0,
+ GIMP_ZOOM_FOCUS_BEST_GUESS);
+ break;
+
+ case GIMP_ACTION_SELECT_SKIP_NEXT:
+ gimp_display_shell_scale (shell,
+ GIMP_ZOOM_IN_MORE,
+ 0.0,
+ GIMP_ZOOM_FOCUS_BEST_GUESS);
+ break;
+
+ default:
+ {
+ gdouble scale = gimp_zoom_model_get_factor (shell->zoom);
+
+ scale = action_select_value (select_type,
+ scale,
+ 0.0, 512.0, 1.0,
+ 1.0 / 8.0, 1.0, 16.0, 0.0,
+ FALSE);
+
+ /* min = 1.0 / 256, max = 256.0 */
+ /* scale = min * (max / min)**(i/n), i = 0..n */
+ scale = pow (65536.0, scale / 512.0) / 256.0;
+
+ gimp_display_shell_scale (shell,
+ GIMP_ZOOM_TO,
+ scale,
+ GIMP_ZOOM_FOCUS_BEST_GUESS);
+ break;
+ }
+ }
+}
+
+void
+view_zoom_explicit_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpDisplayShell *shell;
+ gint factor;
+ return_if_no_shell (shell, data);
+
+ factor = g_variant_get_int32 (value);
+
+ if (factor != 0 /* not Other... */)
+ {
+ if (fabs (factor - gimp_zoom_model_get_factor (shell->zoom)) > 0.0001)
+ gimp_display_shell_scale (shell,
+ GIMP_ZOOM_TO,
+ (gdouble) factor / 10000,
+ GIMP_ZOOM_FOCUS_RETAIN_CENTERING_ELSE_BEST_GUESS);
+ }
+}
+
+/* not a GimpActionCallback */
+void
+view_zoom_other_cmd_callback (GimpAction *action,
+ gpointer data)
+{
+ GimpDisplayShell *shell;
+ return_if_no_shell (shell, data);
+
+ /* check if we are activated by the user or from
+ * view_actions_set_zoom(), also this is really a GtkToggleAction
+ * NOT a GimpToggleAction
+ */
+ if (gtk_toggle_action_get_active ((GtkToggleAction *) action) &&
+ shell->other_scale != gimp_zoom_model_get_factor (shell->zoom))
+ {
+ gimp_display_shell_scale_dialog (shell);
+ }
+}
+
+void
+view_show_all_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpDisplay *display;
+ GimpDisplayShell *shell;
+ gboolean active;
+ return_if_no_display (display, data);
+
+ shell = gimp_display_get_shell (display);
+
+ active = g_variant_get_boolean (value);
+
+ if (active != shell->show_all)
+ {
+ GimpImageWindow *window = gimp_display_shell_get_window (shell);
+
+ gimp_display_shell_set_show_all (shell, active);
+
+ if (window)
+ SET_ACTIVE (gimp_image_window_get_ui_manager (window),
+ "view-show-all", shell->show_all);
+
+ if (IS_ACTIVE_DISPLAY (display))
+ SET_ACTIVE (shell->popup_manager, "view-show-all",
+ shell->show_all);
+ }
+}
+
+void
+view_dot_for_dot_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpDisplay *display;
+ GimpDisplayShell *shell;
+ gboolean active;
+ return_if_no_display (display, data);
+
+ shell = gimp_display_get_shell (display);
+
+ active = g_variant_get_boolean (value);
+
+ if (active != shell->dot_for_dot)
+ {
+ GimpImageWindow *window = gimp_display_shell_get_window (shell);
+
+ gimp_display_shell_scale_set_dot_for_dot (shell, active);
+
+ if (window)
+ SET_ACTIVE (gimp_image_window_get_ui_manager (window),
+ "view-dot-for-dot", shell->dot_for_dot);
+
+ if (IS_ACTIVE_DISPLAY (display))
+ SET_ACTIVE (shell->popup_manager, "view-dot-for-dot",
+ shell->dot_for_dot);
+ }
+}
+
+void
+view_flip_horizontally_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpDisplay *display;
+ GimpDisplayShell *shell;
+ gboolean active;
+ return_if_no_display (display, data);
+
+ shell = gimp_display_get_shell (display);
+
+ active = g_variant_get_boolean (value);
+
+ if (active != shell->flip_horizontally)
+ {
+ gimp_display_shell_flip (shell, active, shell->flip_vertically);
+ }
+}
+
+void
+view_flip_vertically_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpDisplay *display;
+ GimpDisplayShell *shell;
+ gboolean active;
+ return_if_no_display (display, data);
+
+ shell = gimp_display_get_shell (display);
+
+ active = g_variant_get_boolean (value);
+
+ if (active != shell->flip_vertically)
+ {
+ gimp_display_shell_flip (shell, shell->flip_horizontally, active);
+ }
+}
+
+void
+view_rotate_absolute_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpDisplay *display;
+ GimpDisplayShell *shell;
+ GimpActionSelectType select_type;
+ gdouble angle = 0.0;
+ return_if_no_display (display, data);
+
+ select_type = (GimpActionSelectType) g_variant_get_int32 (value);
+
+ shell = gimp_display_get_shell (display);
+
+ angle = action_select_value (select_type,
+ 0.0,
+ -180.0, 180.0, 0.0,
+ 1.0, 15.0, 90.0, 0.0,
+ TRUE);
+
+ gimp_display_shell_rotate_to (shell, angle);
+
+ if (select_type == GIMP_ACTION_SELECT_SET_TO_DEFAULT)
+ gimp_display_shell_flip (shell, FALSE, FALSE);
+}
+
+void
+view_rotate_relative_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpDisplay *display;
+ GimpDisplayShell *shell;
+ GimpActionSelectType select_type;
+ gdouble delta = 0.0;
+ return_if_no_display (display, data);
+
+ select_type = (GimpActionSelectType) g_variant_get_int32 (value);
+
+ shell = gimp_display_get_shell (display);
+
+ delta = action_select_value (select_type,
+ 0.0,
+ -180.0, 180.0, 0.0,
+ 1.0, 15.0, 90.0, 0.0,
+ TRUE);
+
+ gimp_display_shell_rotate (shell, delta);
+}
+
+void
+view_rotate_other_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpDisplay *display;
+ GimpDisplayShell *shell;
+ return_if_no_display (display, data);
+
+ shell = gimp_display_get_shell (display);
+
+ gimp_display_shell_rotate_dialog (shell);
+}
+
+void
+view_scroll_horizontal_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpDisplayShell *shell;
+ GtkAdjustment *adj;
+ GimpActionSelectType select_type;
+ gdouble offset;
+ return_if_no_shell (shell, data);
+
+ select_type = (GimpActionSelectType) g_variant_get_int32 (value);
+
+ adj = shell->hsbdata;
+
+ offset = action_select_value (select_type,
+ gtk_adjustment_get_value (adj),
+ gtk_adjustment_get_lower (adj),
+ gtk_adjustment_get_upper (adj) -
+ gtk_adjustment_get_page_size (adj),
+ gtk_adjustment_get_lower (adj),
+ 1,
+ gtk_adjustment_get_step_increment (adj),
+ gtk_adjustment_get_page_increment (adj),
+ 0,
+ FALSE);
+
+ gtk_adjustment_set_value (shell->hsbdata, offset);
+}
+
+void
+view_scroll_vertical_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpDisplayShell *shell;
+ GtkAdjustment *adj;
+ GimpActionSelectType select_type;
+ gdouble offset;
+ return_if_no_shell (shell, data);
+
+ select_type = (GimpActionSelectType) g_variant_get_int32 (value);
+
+ adj = shell->vsbdata;
+
+ offset = action_select_value (select_type,
+ gtk_adjustment_get_value (adj),
+ gtk_adjustment_get_lower (adj),
+ gtk_adjustment_get_upper (adj) -
+ gtk_adjustment_get_page_size (adj),
+ gtk_adjustment_get_lower (adj),
+ 1,
+ gtk_adjustment_get_step_increment (adj),
+ gtk_adjustment_get_page_increment (adj),
+ 0,
+ FALSE);
+
+ gtk_adjustment_set_value (shell->vsbdata, offset);
+}
+
+void
+view_navigation_window_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ Gimp *gimp;
+ GimpDisplayShell *shell;
+ return_if_no_gimp (gimp, data);
+ return_if_no_shell (shell, data);
+
+ gimp_window_strategy_show_dockable_dialog (GIMP_WINDOW_STRATEGY (gimp_get_window_strategy (gimp)),
+ gimp,
+ gimp_dialog_factory_get_singleton (),
+ gtk_widget_get_screen (GTK_WIDGET (shell)),
+ gimp_widget_get_monitor (GTK_WIDGET (shell)),
+ "gimp-navigation-view");
+}
+
+void
+view_display_filters_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpDisplayShell *shell;
+ GtkWidget *dialog;
+ return_if_no_shell (shell, data);
+
+#define FILTERS_DIALOG_KEY "gimp-display-filters-dialog"
+
+ dialog = dialogs_get_dialog (G_OBJECT (shell), FILTERS_DIALOG_KEY);
+
+ if (! dialog)
+ {
+ dialog = gimp_display_shell_filter_dialog_new (shell);
+
+ dialogs_attach_dialog (G_OBJECT (shell), FILTERS_DIALOG_KEY, dialog);
+ }
+
+ gtk_window_present (GTK_WINDOW (dialog));
+}
+
+void
+view_color_management_reset_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpDisplayShell *shell;
+ GimpColorConfig *global_config;
+ GimpColorConfig *shell_config;
+ return_if_no_shell (shell, data);
+
+ global_config = GIMP_CORE_CONFIG (shell->display->config)->color_management;
+ shell_config = gimp_display_shell_get_color_config (shell);
+
+ gimp_config_copy (GIMP_CONFIG (global_config),
+ GIMP_CONFIG (shell_config),
+ 0);
+ shell->color_config_set = FALSE;
+}
+
+void
+view_color_management_enable_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpDisplayShell *shell;
+ GimpColorConfig *color_config;
+ GimpColorManagementMode mode;
+ gboolean active;
+ return_if_no_shell (shell, data);
+
+ color_config = gimp_display_shell_get_color_config (shell);
+
+ active = g_variant_get_boolean (value);
+
+ mode = gimp_color_config_get_mode (color_config);
+
+ if (active)
+ {
+ if (mode != GIMP_COLOR_MANAGEMENT_SOFTPROOF)
+ mode = GIMP_COLOR_MANAGEMENT_DISPLAY;
+ }
+ else
+ {
+ mode = GIMP_COLOR_MANAGEMENT_OFF;
+ }
+
+ if (mode != gimp_color_config_get_mode (color_config))
+ {
+ g_object_set (color_config,
+ "mode", mode,
+ NULL);
+ shell->color_config_set = TRUE;
+ }
+}
+
+void
+view_color_management_softproof_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpDisplayShell *shell;
+ GimpColorConfig *color_config;
+ GimpColorManagementMode mode;
+ gboolean active;
+ return_if_no_shell (shell, data);
+
+ color_config = gimp_display_shell_get_color_config (shell);
+
+ active = g_variant_get_boolean (value);
+
+ mode = gimp_color_config_get_mode (color_config);
+
+ if (active)
+ {
+ mode = GIMP_COLOR_MANAGEMENT_SOFTPROOF;
+ }
+ else
+ {
+ if (mode != GIMP_COLOR_MANAGEMENT_OFF)
+ mode = GIMP_COLOR_MANAGEMENT_DISPLAY;
+ }
+
+ if (mode != gimp_color_config_get_mode (color_config))
+ {
+ g_object_set (color_config,
+ "mode", mode,
+ NULL);
+ shell->color_config_set = TRUE;
+ }
+}
+
+void
+view_display_intent_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpDisplayShell *shell;
+ GimpColorConfig *color_config;
+ GimpColorRenderingIntent intent;
+ return_if_no_shell (shell, data);
+
+ intent = (GimpColorRenderingIntent) g_variant_get_int32 (value);
+
+ color_config = gimp_display_shell_get_color_config (shell);
+
+ if (intent != gimp_color_config_get_display_intent (color_config))
+ {
+ g_object_set (color_config,
+ "display-rendering-intent", intent,
+ NULL);
+ shell->color_config_set = TRUE;
+ }
+}
+
+void
+view_display_bpc_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpDisplayShell *shell;
+ GimpColorConfig *color_config;
+ gboolean active;
+ return_if_no_shell (shell, data);
+
+ color_config = gimp_display_shell_get_color_config (shell);
+
+ active = g_variant_get_boolean (value);
+
+ if (active != gimp_color_config_get_display_bpc (color_config))
+ {
+ g_object_set (color_config,
+ "display-use-black-point-compensation", active,
+ NULL);
+ shell->color_config_set = TRUE;
+ }
+}
+
+void
+view_softproof_profile_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpDisplayShell *shell;
+ GimpColorConfig *color_config;
+ GtkWidget *dialog;
+ return_if_no_image (image, data);
+ return_if_no_shell (shell, data);
+
+ color_config = gimp_display_shell_get_color_config (shell);
+
+#define SOFTPROOF_PROFILE_DIALOG_KEY "gimp-softproof-profile-dialog"
+
+ dialog = dialogs_get_dialog (G_OBJECT (shell), SOFTPROOF_PROFILE_DIALOG_KEY);
+
+ if (! dialog)
+ {
+ GimpColorProfile *current_profile;
+
+ current_profile = gimp_color_config_get_simulation_color_profile (color_config,
+ NULL);
+
+ dialog = color_profile_dialog_new (COLOR_PROFILE_DIALOG_SELECT_SOFTPROOF_PROFILE,
+ image,
+ action_data_get_context (data),
+ GTK_WIDGET (shell),
+ current_profile,
+ NULL,
+ 0, 0,
+ view_softproof_profile_callback,
+ shell);
+
+ dialogs_attach_dialog (G_OBJECT (shell),
+ SOFTPROOF_PROFILE_DIALOG_KEY, dialog);
+ }
+
+ gtk_window_present (GTK_WINDOW (dialog));
+}
+
+void
+view_softproof_intent_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpDisplayShell *shell;
+ GimpColorConfig *color_config;
+ GimpColorRenderingIntent intent;
+ return_if_no_shell (shell, data);
+
+ intent = (GimpColorRenderingIntent) g_variant_get_int32 (value);
+
+ color_config = gimp_display_shell_get_color_config (shell);
+
+ if (intent != gimp_color_config_get_simulation_intent (color_config))
+ {
+ g_object_set (color_config,
+ "simulation-rendering-intent", intent,
+ NULL);
+ shell->color_config_set = TRUE;
+ }
+}
+
+void
+view_softproof_bpc_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpDisplayShell *shell;
+ GimpColorConfig *color_config;
+ gboolean active;
+ return_if_no_shell (shell, data);
+
+ color_config = gimp_display_shell_get_color_config (shell);
+
+ active = g_variant_get_boolean (value);
+
+ if (active != gimp_color_config_get_simulation_bpc (color_config))
+ {
+ g_object_set (color_config,
+ "simulation-use-black-point-compensation", active,
+ NULL);
+ shell->color_config_set = TRUE;
+ }
+}
+
+void
+view_softproof_gamut_check_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpDisplayShell *shell;
+ GimpColorConfig *color_config;
+ gboolean active;
+ return_if_no_shell (shell, data);
+
+ color_config = gimp_display_shell_get_color_config (shell);
+
+ active = g_variant_get_boolean (value);
+
+ if (active != gimp_color_config_get_simulation_gamut_check (color_config))
+ {
+ g_object_set (color_config,
+ "simulation-gamut-check", active,
+ NULL);
+ shell->color_config_set = TRUE;
+ }
+}
+
+void
+view_toggle_selection_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpDisplayShell *shell;
+ gboolean active;
+ return_if_no_shell (shell, data);
+
+ active = g_variant_get_boolean (value);
+
+ if (active != gimp_display_shell_get_show_selection (shell))
+ {
+ gimp_display_shell_set_show_selection (shell, active);
+ }
+}
+
+void
+view_toggle_layer_boundary_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpDisplayShell *shell;
+ gboolean active;
+ return_if_no_shell (shell, data);
+
+ active = g_variant_get_boolean (value);
+
+ if (active != gimp_display_shell_get_show_layer (shell))
+ {
+ gimp_display_shell_set_show_layer (shell, active);
+ }
+}
+
+void
+view_toggle_canvas_boundary_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpDisplayShell *shell;
+ gboolean active;
+ return_if_no_shell (shell, data);
+
+ active = g_variant_get_boolean (value);
+
+ if (active != gimp_display_shell_get_show_canvas (shell))
+ {
+ gimp_display_shell_set_show_canvas (shell, active);
+ }
+}
+
+void
+view_toggle_menubar_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpDisplayShell *shell;
+ gboolean active;
+ return_if_no_shell (shell, data);
+
+ active = g_variant_get_boolean (value);
+
+ if (active != gimp_display_shell_get_show_menubar (shell))
+ {
+ gimp_display_shell_set_show_menubar (shell, active);
+ }
+}
+
+void
+view_toggle_rulers_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpDisplayShell *shell;
+ gboolean active;
+ return_if_no_shell (shell, data);
+
+ active = g_variant_get_boolean (value);
+
+ if (active != gimp_display_shell_get_show_rulers (shell))
+ {
+ gimp_display_shell_set_show_rulers (shell, active);
+ }
+}
+
+void
+view_toggle_scrollbars_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpDisplayShell *shell;
+ gboolean active;
+ return_if_no_shell (shell, data);
+
+ active = g_variant_get_boolean (value);
+
+ if (active != gimp_display_shell_get_show_scrollbars (shell))
+ {
+ gimp_display_shell_set_show_scrollbars (shell, active);
+ }
+}
+
+void
+view_toggle_statusbar_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpDisplayShell *shell;
+ gboolean active;
+ return_if_no_shell (shell, data);
+
+ active = g_variant_get_boolean (value);
+
+ if (active != gimp_display_shell_get_show_statusbar (shell))
+ {
+ gimp_display_shell_set_show_statusbar (shell, active);
+ }
+}
+
+void
+view_toggle_guides_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpDisplayShell *shell;
+ gboolean active;
+ return_if_no_shell (shell, data);
+
+ active = g_variant_get_boolean (value);
+
+ if (active != gimp_display_shell_get_show_guides (shell))
+ {
+ gimp_display_shell_set_show_guides (shell, active);
+ }
+}
+
+void
+view_toggle_grid_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpDisplayShell *shell;
+ gboolean active;
+ return_if_no_shell (shell, data);
+
+ active = g_variant_get_boolean (value);
+
+ if (active != gimp_display_shell_get_show_grid (shell))
+ {
+ gimp_display_shell_set_show_grid (shell, active);
+ }
+}
+
+void
+view_toggle_sample_points_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpDisplayShell *shell;
+ gboolean active;
+ return_if_no_shell (shell, data);
+
+ active = g_variant_get_boolean (value);
+
+ if (active != gimp_display_shell_get_show_sample_points (shell))
+ {
+ gimp_display_shell_set_show_sample_points (shell, active);
+ }
+}
+
+void
+view_snap_to_guides_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpDisplayShell *shell;
+ gboolean active;
+ return_if_no_shell (shell, data);
+
+ active = g_variant_get_boolean (value);
+
+ if (active != gimp_display_shell_get_snap_to_guides (shell))
+ {
+ gimp_display_shell_set_snap_to_guides (shell, active);
+ }
+}
+
+void
+view_snap_to_grid_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpDisplayShell *shell;
+ gboolean active;
+ return_if_no_shell (shell, data);
+
+ active = g_variant_get_boolean (value);
+
+ if (active != gimp_display_shell_get_snap_to_grid (shell))
+ {
+ gimp_display_shell_set_snap_to_grid (shell, active);
+ }
+}
+
+void
+view_snap_to_canvas_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpDisplayShell *shell;
+ gboolean active;
+ return_if_no_shell (shell, data);
+
+ active = g_variant_get_boolean (value);
+
+ if (active != gimp_display_shell_get_snap_to_canvas (shell))
+ {
+ gimp_display_shell_set_snap_to_canvas (shell, active);
+ }
+}
+
+void
+view_snap_to_vectors_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpDisplayShell *shell;
+ gboolean active;
+ return_if_no_shell (shell, data);
+
+ active = g_variant_get_boolean (value);
+
+ if (active != gimp_display_shell_get_snap_to_vectors (shell))
+ {
+ gimp_display_shell_set_snap_to_vectors (shell, active);
+ }
+}
+
+void
+view_padding_color_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpDisplay *display;
+ GimpImageWindow *window;
+ GimpDisplayShell *shell;
+ GimpDisplayOptions *options;
+ GimpCanvasPaddingMode padding_mode;
+ gboolean fullscreen;
+ return_if_no_display (display, data);
+
+ padding_mode = (GimpCanvasPaddingMode) g_variant_get_int32 (value);
+
+ shell = gimp_display_get_shell (display);
+ window = gimp_display_shell_get_window (shell);
+
+ if (window)
+ fullscreen = gimp_image_window_get_fullscreen (window);
+ else
+ fullscreen = FALSE;
+
+ if (fullscreen)
+ options = shell->fullscreen_options;
+ else
+ options = shell->options;
+
+#define PADDING_COLOR_DIALOG_KEY "gimp-padding-color-dialog"
+
+ switch (padding_mode)
+ {
+ case GIMP_CANVAS_PADDING_MODE_DEFAULT:
+ case GIMP_CANVAS_PADDING_MODE_LIGHT_CHECK:
+ case GIMP_CANVAS_PADDING_MODE_DARK_CHECK:
+ dialogs_destroy_dialog (G_OBJECT (shell), PADDING_COLOR_DIALOG_KEY);
+
+ options->padding_mode_set = TRUE;
+
+ gimp_display_shell_set_padding (shell, padding_mode,
+ &options->padding_color);
+ break;
+
+ case GIMP_CANVAS_PADDING_MODE_CUSTOM:
+ {
+ GtkWidget *dialog;
+
+ dialog = dialogs_get_dialog (G_OBJECT (shell), PADDING_COLOR_DIALOG_KEY);
+
+ if (! dialog)
+ {
+ GimpImage *image = gimp_display_get_image (display);
+ GimpDisplayShell *shell = gimp_display_get_shell (display);
+
+ dialog =
+ gimp_color_dialog_new (GIMP_VIEWABLE (image),
+ action_data_get_context (data),
+ _("Set Canvas Padding Color"),
+ GIMP_ICON_FONT,
+ _("Set Custom Canvas Padding Color"),
+ GTK_WIDGET (shell),
+ NULL, NULL,
+ &options->padding_color,
+ FALSE, FALSE);
+
+ g_signal_connect (dialog, "update",
+ G_CALLBACK (view_padding_color_dialog_update),
+ shell);
+
+ dialogs_attach_dialog (G_OBJECT (shell),
+ PADDING_COLOR_DIALOG_KEY, dialog);
+ }
+
+ gtk_window_present (GTK_WINDOW (dialog));
+ }
+ break;
+
+ case GIMP_CANVAS_PADDING_MODE_RESET:
+ dialogs_destroy_dialog (G_OBJECT (shell), PADDING_COLOR_DIALOG_KEY);
+
+ {
+ GimpDisplayOptions *default_options;
+
+ options->padding_mode_set = FALSE;
+
+ if (fullscreen)
+ default_options = display->config->default_fullscreen_view;
+ else
+ default_options = display->config->default_view;
+
+ gimp_display_shell_set_padding (shell,
+ default_options->padding_mode,
+ &default_options->padding_color);
+ gimp_display_shell_set_padding_in_show_all (shell,
+ default_options->padding_in_show_all);
+ }
+ break;
+ }
+}
+
+void
+view_padding_color_in_show_all_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpDisplayShell *shell;
+ gboolean active;
+ return_if_no_shell (shell, data);
+
+ active = g_variant_get_boolean (value);
+
+ if (active != gimp_display_shell_get_padding_in_show_all (shell))
+ {
+ gimp_display_shell_set_padding_in_show_all (shell, active);
+ }
+}
+
+void
+view_shrink_wrap_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpDisplayShell *shell;
+ return_if_no_shell (shell, data);
+
+ gimp_display_shell_scale_shrink_wrap (shell, FALSE);
+}
+
+void
+view_fullscreen_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpDisplay *display;
+ GimpDisplayShell *shell;
+ GimpImageWindow *window;
+ return_if_no_display (display, data);
+
+ shell = gimp_display_get_shell (display);
+ window = gimp_display_shell_get_window (shell);
+
+ if (window)
+ {
+ gboolean active = g_variant_get_boolean (value);
+
+ gimp_image_window_set_fullscreen (window, active);
+ }
+}
+
+
+/* private functions */
+
+static void
+view_softproof_profile_callback (GtkWidget *dialog,
+ GimpImage *image,
+ GimpColorProfile *new_profile,
+ GFile *new_file,
+ GimpColorRenderingIntent intent,
+ gboolean bpc,
+ gpointer user_data)
+{
+ GimpDisplayShell *shell = user_data;
+ GimpColorConfig *color_config;
+ gchar *path = NULL;
+
+ color_config = gimp_display_shell_get_color_config (shell);
+
+ if (new_file)
+ path = g_file_get_path (new_file);
+
+ g_object_set (color_config,
+ "printer-profile", path,
+ NULL);
+ shell->color_config_set = TRUE;
+
+ gtk_widget_destroy (dialog);
+}
+
+static void
+view_padding_color_dialog_update (GimpColorDialog *dialog,
+ const GimpRGB *color,
+ GimpColorDialogState state,
+ GimpDisplayShell *shell)
+{
+ GimpImageWindow *window;
+ GimpDisplayOptions *options;
+ gboolean fullscreen;
+
+ window = gimp_display_shell_get_window (shell);
+
+ if (window)
+ fullscreen = gimp_image_window_get_fullscreen (window);
+ else
+ fullscreen = FALSE;
+
+ if (fullscreen)
+ options = shell->fullscreen_options;
+ else
+ options = shell->options;
+
+ switch (state)
+ {
+ case GIMP_COLOR_DIALOG_OK:
+ options->padding_mode_set = TRUE;
+
+ gimp_display_shell_set_padding (shell, GIMP_CANVAS_PADDING_MODE_CUSTOM,
+ color);
+ /* fallthru */
+
+ case GIMP_COLOR_DIALOG_CANCEL:
+ gtk_widget_destroy (GTK_WIDGET (dialog));
+ break;
+
+ default:
+ break;
+ }
+}
diff --git a/app/actions/view-commands.h b/app/actions/view-commands.h
new file mode 100644
index 0000000..17b15b2
--- /dev/null
+++ b/app/actions/view-commands.h
@@ -0,0 +1,181 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __VIEW_COMMANDS_H__
+#define __VIEW_COMMANDS_H__
+
+
+void view_new_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void view_close_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+void view_scroll_center_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+void view_zoom_fit_in_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void view_zoom_fill_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void view_zoom_selection_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void view_zoom_revert_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void view_zoom_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void view_zoom_explicit_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+/* not a GimpActionCallback */
+void view_zoom_other_cmd_callback (GimpAction *action,
+ gpointer data);
+
+void view_show_all_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+void view_dot_for_dot_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+void view_scroll_horizontal_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void view_scroll_vertical_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+void view_flip_horizontally_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void view_flip_vertically_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+void view_rotate_absolute_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void view_rotate_relative_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void view_rotate_other_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+void view_navigation_window_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void view_display_filters_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+void view_color_management_reset_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void view_color_management_enable_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void view_color_management_softproof_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void view_display_intent_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void view_display_bpc_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void view_softproof_profile_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void view_softproof_intent_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void view_softproof_bpc_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void view_softproof_gamut_check_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+void view_toggle_selection_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void view_toggle_layer_boundary_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void view_toggle_canvas_boundary_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void view_toggle_menubar_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void view_toggle_rulers_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void view_toggle_scrollbars_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void view_toggle_statusbar_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void view_toggle_guides_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void view_toggle_grid_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void view_toggle_sample_points_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+void view_snap_to_guides_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void view_snap_to_grid_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void view_snap_to_canvas_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void view_snap_to_vectors_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void view_padding_color_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void view_padding_color_in_show_all_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+void view_shrink_wrap_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void view_fullscreen_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+
+#endif /* __VIEW_COMMANDS_H__ */
diff --git a/app/actions/window-actions.c b/app/actions/window-actions.c
new file mode 100644
index 0000000..ec2e9be
--- /dev/null
+++ b/app/actions/window-actions.c
@@ -0,0 +1,297 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "actions-types.h"
+
+#include "widgets/gimpactiongroup.h"
+#include "widgets/gimphelp-ids.h"
+
+#include "actions.h"
+#include "window-actions.h"
+#include "window-commands.h"
+
+#include "gimp-intl.h"
+
+
+/* private functions */
+
+static void window_actions_display_opened (GdkDisplayManager *manager,
+ GdkDisplay *display,
+ GimpActionGroup *group);
+static void window_actions_display_closed (GdkDisplay *display,
+ gboolean is_error,
+ GimpActionGroup *group);
+
+
+/* public functions */
+
+void
+window_actions_setup (GimpActionGroup *group,
+ const gchar *move_to_screen_help_id)
+{
+ GdkDisplayManager *manager = gdk_display_manager_get ();
+ GSList *displays;
+ GSList *list;
+
+ g_object_set_data_full (G_OBJECT (group), "move-to-screen-help-id",
+ g_strdup (move_to_screen_help_id),
+ (GDestroyNotify) g_free);
+
+ g_object_set_data_full (G_OBJECT (group), "display-table",
+ g_hash_table_new_full (g_str_hash,
+ g_str_equal,
+ g_free, NULL),
+ (GDestroyNotify) g_hash_table_unref);
+
+ displays = gdk_display_manager_list_displays (manager);
+
+ /* present displays in the order in which they were opened */
+ displays = g_slist_reverse (displays);
+
+ for (list = displays; list; list = g_slist_next (list))
+ {
+ window_actions_display_opened (manager, list->data, group);
+ }
+
+ g_slist_free (displays);
+
+ g_signal_connect_object (manager, "display-opened",
+ G_CALLBACK (window_actions_display_opened),
+ G_OBJECT (group), 0);
+}
+
+void
+window_actions_update (GimpActionGroup *group,
+ GtkWidget *window)
+{
+ const gchar *group_name;
+ gint show_menu = FALSE;
+ gchar *name;
+
+ group_name = gimp_action_group_get_name (group);
+
+#define SET_ACTIVE(action,active) \
+ gimp_action_group_set_action_active (group, action, (active) != 0)
+#define SET_VISIBLE(action,active) \
+ gimp_action_group_set_action_visible (group, action, (active) != 0)
+
+ if (GTK_IS_WINDOW (window))
+ {
+ GdkScreen *screen;
+ gchar *screen_name;
+
+#ifndef GIMP_UNSTABLE
+ {
+ GdkDisplay *display;
+
+ display = gtk_widget_get_display (window);
+ show_menu = (gdk_display_get_n_screens (display) > 1);
+ }
+#else
+ show_menu = TRUE;
+#endif /* !GIMP_UNSTABLE */
+
+ if (! show_menu)
+ {
+ GdkDisplayManager *manager = gdk_display_manager_get ();
+ GSList *displays;
+
+ displays = gdk_display_manager_list_displays (manager);
+ show_menu = (displays->next != NULL);
+ g_slist_free (displays);
+ }
+
+ screen = gtk_widget_get_screen (window);
+
+ screen_name = gdk_screen_make_display_name (screen);
+ name = g_strdup_printf ("%s-move-to-screen-%s", group_name, screen_name);
+ g_free (screen_name);
+
+ SET_ACTIVE (name, TRUE);
+ g_free (name);
+ }
+
+ name = g_strdup_printf ("%s-move-to-screen-menu", group_name);
+ SET_VISIBLE (name, show_menu);
+ g_free (name);
+
+#undef SET_ACTIVE
+#undef SET_VISIBLE
+}
+
+
+/* private functions */
+
+static void
+window_actions_display_opened (GdkDisplayManager *manager,
+ GdkDisplay *display,
+ GimpActionGroup *group)
+{
+ GimpRadioActionEntry *entries;
+ GHashTable *displays;
+ const gchar *display_name;
+ const gchar *help_id;
+ const gchar *group_name;
+ GSList *radio_group;
+ gint count;
+ gint n_screens;
+ gint i;
+
+ displays = g_object_get_data (G_OBJECT (group), "display-table");
+
+ display_name = gdk_display_get_name (display);
+
+ count = GPOINTER_TO_INT (g_hash_table_lookup (displays,
+ display_name));
+
+ g_hash_table_insert (displays, g_strdup (display_name),
+ GINT_TO_POINTER (count + 1));
+
+ /* don't add the same display twice */
+ if (count > 0)
+ return;
+
+ help_id = g_object_get_data (G_OBJECT (group), "change-to-screen-help-id");
+
+ group_name = gimp_action_group_get_name (group);
+
+ n_screens = gdk_display_get_n_screens (display);
+
+ entries = g_new0 (GimpRadioActionEntry, n_screens);
+
+ for (i = 0; i < n_screens; i++)
+ {
+ GdkScreen *screen = gdk_display_get_screen (display, i);
+ gchar *screen_name;
+
+ screen_name = gdk_screen_make_display_name (screen);
+
+ entries[i].name = g_strdup_printf ("%s-move-to-screen-%s",
+ group_name, screen_name);
+ entries[i].icon_name = GIMP_ICON_WINDOW_MOVE_TO_SCREEN;
+ entries[i].label = g_strdup_printf (_("Screen %s"), screen_name);
+ entries[i].accelerator = NULL;
+ entries[i].tooltip = g_strdup_printf (_("Move this window to "
+ "screen %s"), screen_name);
+ entries[i].value = g_quark_from_string (screen_name);
+ entries[i].help_id = help_id;
+
+ g_free (screen_name);
+ }
+
+ radio_group = g_object_get_data (G_OBJECT (group),
+ "change-to-screen-radio-group");
+ radio_group = gimp_action_group_add_radio_actions (group, NULL,
+ entries, n_screens,
+ radio_group, 0,
+ window_move_to_screen_cmd_callback);
+ g_object_set_data (G_OBJECT (group), "change-to-screen-radio-group",
+ radio_group);
+
+ for (i = 0; i < n_screens; i++)
+ {
+ GdkScreen *screen = gdk_display_get_screen (display, i);
+ GimpAction *action;
+
+ action = gimp_action_group_get_action (group, entries[i].name);
+
+ if (action)
+ g_object_set_data (G_OBJECT (action), "screen", screen);
+
+ g_free ((gchar *) entries[i].name);
+ g_free ((gchar *) entries[i].tooltip);
+ g_free ((gchar *) entries[i].label);
+ }
+
+ g_free (entries);
+
+ g_signal_connect_object (display, "closed",
+ G_CALLBACK (window_actions_display_closed),
+ G_OBJECT (group), 0);
+}
+
+static void
+window_actions_display_closed (GdkDisplay *display,
+ gboolean is_error,
+ GimpActionGroup *group)
+{
+ GHashTable *displays;
+ const gchar *display_name;
+ const gchar *group_name;
+ gint count;
+ gint n_screens;
+ gint i;
+
+ displays = g_object_get_data (G_OBJECT (group), "display-table");
+
+ display_name = gdk_display_get_name (display);
+
+ count = GPOINTER_TO_INT (g_hash_table_lookup (displays,
+ display_name));
+
+ /* don't remove the same display twice */
+ if (count > 1)
+ {
+ g_hash_table_insert (displays, g_strdup (display_name),
+ GINT_TO_POINTER (count - 1));
+ return;
+ }
+
+ g_hash_table_remove (displays, display_name);
+
+ group_name = gimp_action_group_get_name (group);
+
+ n_screens = gdk_display_get_n_screens (display);
+
+ for (i = 0; i < n_screens; i++)
+ {
+ GdkScreen *screen = gdk_display_get_screen (display, i);
+ GimpAction *action;
+ gchar *screen_name;
+ gchar *action_name;
+
+ screen_name = gdk_screen_make_display_name (screen);
+ action_name = g_strdup_printf ("%s-move-to-screen-%s",
+ group_name, screen_name);
+ g_free (screen_name);
+
+ action = gimp_action_group_get_action (group, action_name);
+
+ if (action)
+ {
+ GSList *radio_group;
+
+ radio_group = gtk_radio_action_get_group (GTK_RADIO_ACTION (action));
+ if (radio_group->data == (gpointer) action)
+ radio_group = radio_group->next;
+
+ gimp_action_group_remove_action (group, action);
+
+ g_object_set_data (G_OBJECT (group), "change-to-screen-radio-group",
+ radio_group);
+ }
+
+ g_free (action_name);
+ }
+}
diff --git a/app/actions/window-actions.h b/app/actions/window-actions.h
new file mode 100644
index 0000000..2aae4e2
--- /dev/null
+++ b/app/actions/window-actions.h
@@ -0,0 +1,28 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __WINDOW_ACTIONS_H__
+#define __WINDOW_ACTIONS_H__
+
+
+void window_actions_setup (GimpActionGroup *group,
+ const gchar *move_to_screen_help_id);
+void window_actions_update (GimpActionGroup *group,
+ GtkWidget *window);
+
+
+#endif /* __WINDOW_ACTIONS_H__ */
diff --git a/app/actions/window-commands.c b/app/actions/window-commands.c
new file mode 100644
index 0000000..046f986
--- /dev/null
+++ b/app/actions/window-commands.c
@@ -0,0 +1,158 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <string.h>
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "actions-types.h"
+
+#include "widgets/gimpmessagebox.h"
+#include "widgets/gimpmessagedialog.h"
+
+#include "actions.h"
+#include "window-commands.h"
+
+#include "gimp-intl.h"
+
+
+/* public functions */
+
+void
+window_close_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GtkWidget *widget;
+ return_if_no_widget (widget, data);
+
+ if (! gtk_widget_is_toplevel (widget))
+ widget = gtk_widget_get_toplevel (widget);
+
+ if (widget && gtk_widget_get_window (widget))
+ {
+ GdkEvent *event = gdk_event_new (GDK_DELETE);
+
+ event->any.window = g_object_ref (gtk_widget_get_window (widget));
+ event->any.send_event = TRUE;
+
+ gtk_main_do_event (event);
+ gdk_event_free (event);
+ }
+}
+
+void
+window_open_display_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GtkWidget *widget;
+ GtkWidget *dialog;
+ GtkWidget *entry;
+ return_if_no_widget (widget, data);
+
+ dialog = gimp_message_dialog_new ("Open Display", GIMP_ICON_WILBER_EEK,
+ widget, GTK_DIALOG_MODAL,
+ NULL, NULL,
+
+ _("_Cancel"), GTK_RESPONSE_CANCEL,
+ _("_OK"), GTK_RESPONSE_OK,
+
+ NULL);
+
+ gtk_dialog_set_alternative_button_order (GTK_DIALOG (dialog),
+ GTK_RESPONSE_OK,
+ GTK_RESPONSE_CANCEL,
+ -1);
+
+ gimp_message_box_set_primary_text (GIMP_MESSAGE_DIALOG (dialog)->box,
+ "Experimental multi-display stuff!\n"
+ "Click OK and have fun crashing GIMP...");
+
+ gimp_message_box_set_text (GIMP_MESSAGE_DIALOG (dialog)->box,
+ "Please enter the name of the new display:");
+
+ entry = gtk_entry_new ();
+ gtk_entry_set_activates_default (GTK_ENTRY (entry), TRUE);
+ gtk_box_pack_start (GTK_BOX (GIMP_MESSAGE_DIALOG (dialog)->box), entry,
+ TRUE, TRUE, 0);
+
+ gtk_widget_grab_focus (entry);
+ gtk_widget_show_all (dialog);
+
+ while (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK)
+ {
+ gchar *screen_name;
+
+ screen_name = gtk_editable_get_chars (GTK_EDITABLE (entry), 0, -1);
+
+ if (strcmp (screen_name, ""))
+ {
+ GdkDisplay *display;
+
+ gtk_widget_set_sensitive (dialog, FALSE);
+
+ display = gdk_display_open (screen_name);
+
+ if (! display)
+ gimp_message_box_set_text (GIMP_MESSAGE_DIALOG (dialog)->box,
+ "Can't open display '%s'. "
+ "Please try another one:",
+ screen_name);
+
+ g_free (screen_name);
+
+ gtk_widget_set_sensitive (dialog, TRUE);
+
+ if (display)
+ break;
+ }
+
+ gtk_widget_grab_focus (entry);
+ }
+
+ gtk_widget_destroy (dialog);
+}
+
+void
+window_move_to_screen_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GtkWidget *widget;
+#if 0
+ GdkScreen *screen;
+#endif
+ return_if_no_widget (widget, data);
+
+#if 0
+ if (! gtk_widget_is_toplevel (widget))
+ widget = gtk_widget_get_toplevel (widget);
+
+ screen = g_object_get_data (G_OBJECT (current), "screen");
+
+ if (GDK_IS_SCREEN (screen) && screen != gtk_widget_get_screen (widget))
+ {
+ gtk_window_set_screen (GTK_WINDOW (widget), screen);
+ }
+#endif
+}
diff --git a/app/actions/window-commands.h b/app/actions/window-commands.h
new file mode 100644
index 0000000..41478d5
--- /dev/null
+++ b/app/actions/window-commands.h
@@ -0,0 +1,33 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __WINDOW_COMMANDS_H__
+#define __WINDOW_COMMANDS_H__
+
+
+void window_close_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void window_open_display_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void window_move_to_screen_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+
+#endif /* __WINDOW_COMMANDS_H__ */
diff --git a/app/actions/windows-actions.c b/app/actions/windows-actions.c
new file mode 100644
index 0000000..52b2a9c
--- /dev/null
+++ b/app/actions/windows-actions.c
@@ -0,0 +1,618 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+#include <gdk/gdkkeysyms.h>
+
+#include "libgimpbase/gimpbase.h"
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "actions-types.h"
+
+#include "config/gimpdisplayconfig.h"
+#include "config/gimpguiconfig.h"
+
+#include "core/gimp.h"
+#include "core/gimpimage.h"
+#include "core/gimplist.h"
+
+#include "widgets/gimpaction.h"
+#include "widgets/gimpactiongroup.h"
+#include "widgets/gimpdialogfactory.h"
+#include "widgets/gimpdock.h"
+#include "widgets/gimpdockwindow.h"
+#include "widgets/gimphelp-ids.h"
+
+#include "display/gimpdisplay.h"
+#include "display/gimpdisplayshell.h"
+
+#include "dialogs/dialogs.h"
+
+#include "windows-actions.h"
+#include "windows-commands.h"
+
+#include "gimp-intl.h"
+
+
+static void windows_actions_display_add (GimpContainer *container,
+ GimpDisplay *display,
+ GimpActionGroup *group);
+static void windows_actions_display_remove (GimpContainer *container,
+ GimpDisplay *display,
+ GimpActionGroup *group);
+static void windows_actions_display_reorder (GimpContainer *container,
+ GimpDisplay *display,
+ gint position,
+ GimpActionGroup *group);
+static void windows_actions_image_notify (GimpDisplay *display,
+ const GParamSpec *unused,
+ GimpActionGroup *group);
+static void windows_actions_title_notify (GimpDisplayShell *shell,
+ const GParamSpec *unused,
+ GimpActionGroup *group);
+static void windows_actions_update_display_accels (GimpActionGroup *group);
+
+static void windows_actions_dock_window_added (GimpDialogFactory *factory,
+ GimpDockWindow *dock_window,
+ GimpActionGroup *group);
+static void windows_actions_dock_window_removed (GimpDialogFactory *factory,
+ GimpDockWindow *dock_window,
+ GimpActionGroup *group);
+static void windows_actions_dock_window_notify (GimpDockWindow *dock,
+ const GParamSpec *pspec,
+ GimpActionGroup *group);
+static void windows_actions_recent_add (GimpContainer *container,
+ GimpSessionInfo *info,
+ GimpActionGroup *group);
+static void windows_actions_recent_remove (GimpContainer *container,
+ GimpSessionInfo *info,
+ GimpActionGroup *group);
+static void windows_actions_single_window_mode_notify (GimpDisplayConfig *config,
+ GParamSpec *pspec,
+ GimpActionGroup *group);
+
+
+/* The only reason we have "Tab" in the action entries below is to
+ * give away the hardcoded keyboard shortcut. If the user changes the
+ * shortcut to something else, both that shortcut and Tab will
+ * work. The reason we have the shortcut hardcoded is because
+ * gtk_accelerator_valid() returns FALSE for GDK_tab.
+ */
+
+static const GimpActionEntry windows_actions[] =
+{
+ { "windows-menu", NULL, NC_("windows-action",
+ "_Windows") },
+ { "windows-docks-menu", NULL, NC_("windows-action",
+ "_Recently Closed Docks") },
+ { "windows-dialogs-menu", NULL, NC_("windows-action",
+ "_Dockable Dialogs") },
+
+ { "windows-show-display-next", NULL,
+ NC_("windows-action", "Next Image"), "<alt>Tab",
+ NC_("windows-action", "Switch to the next image"),
+ windows_show_display_next_cmd_callback,
+ NULL },
+
+ { "windows-show-display-previous", NULL,
+ NC_("windows-action", "Previous Image"), "<alt><shift>Tab",
+ NC_("windows-action", "Switch to the previous image"),
+ windows_show_display_previous_cmd_callback,
+ NULL },
+
+ { "windows-tab-position", NULL, NC_("windows-action",
+ "_Tabs Position") },
+};
+
+static const GimpToggleActionEntry windows_toggle_actions[] =
+{
+ { "windows-hide-docks", NULL,
+ NC_("windows-action", "_Hide Docks"), "Tab",
+ NC_("windows-action", "When enabled, docks and other dialogs are hidden, leaving only image windows."),
+ windows_hide_docks_cmd_callback,
+ FALSE,
+ GIMP_HELP_WINDOWS_HIDE_DOCKS },
+
+ { "windows-show-tabs", NULL,
+ NC_("windows-action", "_Show Tabs"), NULL,
+ NC_("windows-action", "When enabled, the image tabs bar is shown."),
+ windows_show_tabs_cmd_callback,
+ FALSE,
+ GIMP_HELP_WINDOWS_SHOW_TABS },
+
+ { "windows-use-single-window-mode", NULL,
+ NC_("windows-action", "Single-Window _Mode"), NULL,
+ NC_("windows-action", "When enabled, GIMP is in a single-window mode."),
+ windows_use_single_window_mode_cmd_callback,
+ FALSE,
+ GIMP_HELP_WINDOWS_USE_SINGLE_WINDOW_MODE }
+};
+
+static const GimpRadioActionEntry windows_tabs_position_actions[] =
+{
+ { "windows-tabs-position-top", GIMP_ICON_GO_TOP,
+ NC_("windows-tabs-position-action", "_Top"), NULL,
+ NC_("windows-tabs-position-action", "Position the tabs on the top"),
+ GIMP_POSITION_TOP, GIMP_HELP_WINDOWS_TABS_POSITION },
+
+ { "windows-tabs-position-bottom", GIMP_ICON_GO_BOTTOM,
+ NC_("windows-tabs-position-action", "_Bottom"), NULL,
+ NC_("windows-tabs-position-action", "Position the tabs on the bottom"),
+ GIMP_POSITION_BOTTOM, GIMP_HELP_WINDOWS_TABS_POSITION },
+
+ { "windows-tabs-position-left", GIMP_ICON_GO_FIRST,
+ NC_("windows-tabs-position-action", "_Left"), NULL,
+ NC_("windows-tabs-position-action", "Position the tabs on the left"),
+ GIMP_POSITION_LEFT, GIMP_HELP_WINDOWS_TABS_POSITION },
+
+ { "windows-tabs-position-right", GIMP_ICON_GO_LAST,
+ NC_("windows-tabs-position-action", "_Right"), NULL,
+ NC_("windows-tabs-position-action", "Position the tabs on the right"),
+ GIMP_POSITION_RIGHT, GIMP_HELP_WINDOWS_TABS_POSITION },
+};
+
+void
+windows_actions_setup (GimpActionGroup *group)
+{
+ GList *list;
+
+ gimp_action_group_add_actions (group, "windows-action",
+ windows_actions,
+ G_N_ELEMENTS (windows_actions));
+
+ gimp_action_group_add_toggle_actions (group, "windows-action",
+ windows_toggle_actions,
+ G_N_ELEMENTS (windows_toggle_actions));
+
+ gimp_action_group_add_radio_actions (group, "windows-tabs-position-action",
+ windows_tabs_position_actions,
+ G_N_ELEMENTS (windows_tabs_position_actions),
+ NULL, 0,
+ windows_set_tabs_position_cmd_callback);
+
+ gimp_action_group_set_action_hide_empty (group, "windows-docks-menu", FALSE);
+
+ g_signal_connect_object (group->gimp->displays, "add",
+ G_CALLBACK (windows_actions_display_add),
+ group, 0);
+ g_signal_connect_object (group->gimp->displays, "remove",
+ G_CALLBACK (windows_actions_display_remove),
+ group, 0);
+ g_signal_connect_object (group->gimp->displays, "reorder",
+ G_CALLBACK (windows_actions_display_reorder),
+ group, 0);
+
+ for (list = gimp_get_display_iter (group->gimp);
+ list;
+ list = g_list_next (list))
+ {
+ GimpDisplay *display = list->data;
+
+ windows_actions_display_add (group->gimp->displays, display, group);
+ }
+
+ g_signal_connect_object (gimp_dialog_factory_get_singleton (), "dock-window-added",
+ G_CALLBACK (windows_actions_dock_window_added),
+ group, 0);
+ g_signal_connect_object (gimp_dialog_factory_get_singleton (), "dock-window-removed",
+ G_CALLBACK (windows_actions_dock_window_removed),
+ group, 0);
+
+ for (list = gimp_dialog_factory_get_open_dialogs (gimp_dialog_factory_get_singleton ());
+ list;
+ list = g_list_next (list))
+ {
+ GimpDockWindow *dock_window = list->data;
+
+ if (GIMP_IS_DOCK_WINDOW (dock_window))
+ windows_actions_dock_window_added (gimp_dialog_factory_get_singleton (),
+ dock_window,
+ group);
+ }
+
+ g_signal_connect_object (global_recent_docks, "add",
+ G_CALLBACK (windows_actions_recent_add),
+ group, 0);
+ g_signal_connect_object (global_recent_docks, "remove",
+ G_CALLBACK (windows_actions_recent_remove),
+ group, 0);
+
+ for (list = GIMP_LIST (global_recent_docks)->queue->head;
+ list;
+ list = g_list_next (list))
+ {
+ GimpSessionInfo *info = list->data;
+
+ windows_actions_recent_add (global_recent_docks, info, group);
+ }
+
+ g_signal_connect_object (group->gimp->config, "notify::single-window-mode",
+ G_CALLBACK (windows_actions_single_window_mode_notify),
+ group, 0);
+}
+
+void
+windows_actions_update (GimpActionGroup *group,
+ gpointer data)
+{
+ GimpGuiConfig *config = GIMP_GUI_CONFIG (group->gimp->config);
+ const gchar *action = NULL;
+
+#define SET_ACTIVE(action,condition) \
+ gimp_action_group_set_action_active (group, action, (condition) != 0)
+
+ SET_ACTIVE ("windows-use-single-window-mode", config->single_window_mode);
+ SET_ACTIVE ("windows-hide-docks", config->hide_docks);
+ SET_ACTIVE ("windows-show-tabs", config->show_tabs);
+
+ switch (config->tabs_position)
+ {
+ case GIMP_POSITION_TOP:
+ action = "windows-tabs-position-top";
+ break;
+ case GIMP_POSITION_BOTTOM:
+ action = "windows-tabs-position-bottom";
+ break;
+ case GIMP_POSITION_LEFT:
+ action = "windows-tabs-position-left";
+ break;
+ case GIMP_POSITION_RIGHT:
+ action = "windows-tabs-position-right";
+ break;
+ default:
+ action = "windows-tabs-position-top";
+ break;
+ }
+
+ gimp_action_group_set_action_active (group, action, TRUE);
+ gimp_action_group_set_action_sensitive (group, "windows-tab-position", config->single_window_mode);
+ gimp_action_group_set_action_sensitive (group, "windows-show-tabs", config->single_window_mode);
+
+#undef SET_ACTIVE
+}
+
+gchar *
+windows_actions_dock_window_to_action_name (GimpDockWindow *dock_window)
+{
+ return g_strdup_printf ("windows-dock-%04d",
+ gimp_dock_window_get_id (dock_window));
+}
+
+
+/* private functions */
+
+static void
+windows_actions_display_add (GimpContainer *container,
+ GimpDisplay *display,
+ GimpActionGroup *group)
+{
+ GimpDisplayShell *shell = gimp_display_get_shell (display);
+
+ g_signal_connect_object (display, "notify::image",
+ G_CALLBACK (windows_actions_image_notify),
+ group, 0);
+
+ g_signal_connect_object (shell, "notify::title",
+ G_CALLBACK (windows_actions_title_notify),
+ group, 0);
+
+ windows_actions_image_notify (display, NULL, group);
+}
+
+static void
+windows_actions_display_remove (GimpContainer *container,
+ GimpDisplay *display,
+ GimpActionGroup *group)
+{
+ GimpDisplayShell *shell = gimp_display_get_shell (display);
+ GimpAction *action;
+ gchar *action_name;
+
+ if (shell)
+ g_signal_handlers_disconnect_by_func (shell,
+ windows_actions_title_notify,
+ group);
+
+ action_name = gimp_display_get_action_name (display);
+ action = gimp_action_group_get_action (group, action_name);
+ g_free (action_name);
+
+ if (action)
+ gimp_action_group_remove_action_and_accel (group, action);
+
+ windows_actions_update_display_accels (group);
+}
+
+static void
+windows_actions_display_reorder (GimpContainer *container,
+ GimpDisplay *display,
+ gint new_index,
+ GimpActionGroup *group)
+{
+ windows_actions_update_display_accels (group);
+}
+
+static void
+windows_actions_image_notify (GimpDisplay *display,
+ const GParamSpec *unused,
+ GimpActionGroup *group)
+{
+ GimpImage *image = gimp_display_get_image (display);
+ GimpAction *action;
+ gchar *action_name;
+
+ action_name = gimp_display_get_action_name (display);
+
+ action = gimp_action_group_get_action (group, action_name);
+
+ if (! action)
+ {
+ GimpActionEntry entry;
+
+ entry.name = action_name;
+ entry.icon_name = GIMP_ICON_IMAGE;
+ entry.label = "";
+ entry.accelerator = NULL;
+ entry.tooltip = NULL;
+ entry.callback = windows_show_display_cmd_callback;
+ entry.help_id = NULL;
+
+ gimp_action_group_add_actions (group, NULL, &entry, 1);
+
+ gimp_action_group_set_action_always_show_image (group, action_name,
+ TRUE);
+ action = gimp_action_group_get_action (group, action_name);
+
+ g_object_set_data (G_OBJECT (action), "display", display);
+ }
+
+ g_free (action_name);
+
+ if (image)
+ {
+ const gchar *display_name;
+ gchar *escaped;
+ gchar *title;
+
+ display_name = gimp_image_get_display_name (image);
+ escaped = gimp_escape_uline (display_name);
+
+ title = g_strdup_printf ("%s-%d.%d", escaped,
+ gimp_image_get_ID (image),
+ gimp_display_get_instance (display));
+ g_free (escaped);
+
+ g_object_set (action,
+ "visible", TRUE,
+ "label", title,
+ "tooltip", gimp_image_get_display_path (image),
+ "viewable", image,
+ "context", gimp_get_user_context (group->gimp),
+ NULL);
+
+ g_free (title);
+
+ windows_actions_update_display_accels (group);
+ }
+ else
+ {
+ g_object_set (action,
+ "visible", FALSE,
+ "viewable", NULL,
+ NULL);
+ }
+}
+
+static void
+windows_actions_title_notify (GimpDisplayShell *shell,
+ const GParamSpec *unused,
+ GimpActionGroup *group)
+{
+ windows_actions_image_notify (shell->display, NULL, group);
+}
+
+static void
+windows_actions_update_display_accels (GimpActionGroup *group)
+{
+ GList *list;
+ gint i;
+
+ for (list = gimp_get_display_iter (group->gimp), i = 0;
+ list && i < 10;
+ list = g_list_next (list), i++)
+ {
+ GimpDisplay *display = list->data;
+ GimpAction *action;
+ gchar *action_name;
+
+ if (! gimp_display_get_image (display))
+ break;
+
+ action_name = gimp_display_get_action_name (display);
+
+ action = gimp_action_group_get_action (group, action_name);
+ g_free (action_name);
+
+ if (action)
+ {
+ const gchar *accel_path;
+ guint accel_key;
+
+ accel_path = gimp_action_get_accel_path (action);
+
+ if (i < 9)
+ accel_key = GDK_KEY_1 + i;
+ else
+ accel_key = GDK_KEY_0;
+
+ gtk_accel_map_change_entry (accel_path,
+ accel_key, GDK_MOD1_MASK,
+ TRUE);
+ }
+ }
+}
+
+static void
+windows_actions_dock_window_added (GimpDialogFactory *factory,
+ GimpDockWindow *dock_window,
+ GimpActionGroup *group)
+{
+ GimpAction *action;
+ GimpActionEntry entry;
+ gchar *action_name = windows_actions_dock_window_to_action_name (dock_window);
+
+ entry.name = action_name;
+ entry.icon_name = NULL;
+ entry.label = "";
+ entry.accelerator = NULL;
+ entry.tooltip = NULL;
+ entry.callback = windows_show_dock_cmd_callback;
+ entry.help_id = GIMP_HELP_WINDOWS_SHOW_DOCK;
+
+ gimp_action_group_add_actions (group, NULL, &entry, 1);
+
+ action = gimp_action_group_get_action (group, action_name);
+
+ g_object_set (action,
+ "ellipsize", PANGO_ELLIPSIZE_END,
+ NULL);
+
+ g_object_set_data (G_OBJECT (action), "dock-window", dock_window);
+
+ g_free (action_name);
+
+ g_signal_connect_object (dock_window, "notify::title",
+ G_CALLBACK (windows_actions_dock_window_notify),
+ group, 0);
+
+ if (gtk_window_get_title (GTK_WINDOW (dock_window)))
+ windows_actions_dock_window_notify (dock_window, NULL, group);
+}
+
+static void
+windows_actions_dock_window_removed (GimpDialogFactory *factory,
+ GimpDockWindow *dock_window,
+ GimpActionGroup *group)
+{
+ GimpAction *action;
+ gchar *action_name;
+
+ action_name = windows_actions_dock_window_to_action_name (dock_window);
+ action = gimp_action_group_get_action (group, action_name);
+ g_free (action_name);
+
+ if (action)
+ gimp_action_group_remove_action_and_accel (group, action);
+}
+
+static void
+windows_actions_dock_window_notify (GimpDockWindow *dock_window,
+ const GParamSpec *pspec,
+ GimpActionGroup *group)
+{
+ GimpAction *action;
+ gchar *action_name;
+
+ action_name = windows_actions_dock_window_to_action_name (dock_window);
+ action = gimp_action_group_get_action (group, action_name);
+ g_free (action_name);
+
+ if (action)
+ g_object_set (action,
+ "label", gtk_window_get_title (GTK_WINDOW (dock_window)),
+ "tooltip", gtk_window_get_title (GTK_WINDOW (dock_window)),
+ NULL);
+}
+
+static void
+windows_actions_recent_add (GimpContainer *container,
+ GimpSessionInfo *info,
+ GimpActionGroup *group)
+{
+ GimpAction *action;
+ GimpActionEntry entry;
+ gint info_id;
+ static gint info_id_counter = 1;
+ gchar *action_name;
+
+ info_id = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (info),
+ "recent-action-id"));
+
+ if (! info_id)
+ {
+ info_id = info_id_counter++;
+
+ g_object_set_data (G_OBJECT (info), "recent-action-id",
+ GINT_TO_POINTER (info_id));
+ }
+
+ action_name = g_strdup_printf ("windows-recent-%04d", info_id);
+
+ entry.name = action_name;
+ entry.icon_name = NULL;
+ entry.label = gimp_object_get_name (info);
+ entry.accelerator = NULL;
+ entry.tooltip = gimp_object_get_name (info);
+ entry.callback = windows_open_recent_cmd_callback;
+ entry.help_id = GIMP_HELP_WINDOWS_OPEN_RECENT_DOCK;
+
+ gimp_action_group_add_actions (group, NULL, &entry, 1);
+
+ action = gimp_action_group_get_action (group, action_name);
+
+ g_object_set (action,
+ "ellipsize", PANGO_ELLIPSIZE_END,
+ "max-width-chars", 30,
+ NULL);
+
+ g_object_set_data (G_OBJECT (action), "info", info);
+
+ g_free (action_name);
+}
+
+static void
+windows_actions_recent_remove (GimpContainer *container,
+ GimpSessionInfo *info,
+ GimpActionGroup *group)
+{
+ GimpAction *action;
+ gint info_id;
+ gchar *action_name;
+
+ info_id = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (info),
+ "recent-action-id"));
+
+ action_name = g_strdup_printf ("windows-recent-%04d", info_id);
+ action = gimp_action_group_get_action (group, action_name);
+ g_free (action_name);
+
+ if (action)
+ gimp_action_group_remove_action_and_accel (group, action);
+}
+
+static void
+windows_actions_single_window_mode_notify (GimpDisplayConfig *config,
+ GParamSpec *pspec,
+ GimpActionGroup *group)
+{
+ gimp_action_group_set_action_active (group,
+ "windows-use-single-window-mode",
+ GIMP_GUI_CONFIG (config)->single_window_mode);
+}
diff --git a/app/actions/windows-actions.h b/app/actions/windows-actions.h
new file mode 100644
index 0000000..6d73fed
--- /dev/null
+++ b/app/actions/windows-actions.h
@@ -0,0 +1,28 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __WINDOWS_ACTIONS_H__
+#define __WINDOWS_ACTIONS_H__
+
+
+void windows_actions_setup (GimpActionGroup *group);
+void windows_actions_update (GimpActionGroup *group,
+ gpointer data);
+gchar * windows_actions_dock_window_to_action_name (GimpDockWindow *dock_window);
+
+
+#endif /* __WINDOWS_ACTIONS_H__ */
diff --git a/app/actions/windows-commands.c b/app/actions/windows-commands.c
new file mode 100644
index 0000000..873b595
--- /dev/null
+++ b/app/actions/windows-commands.c
@@ -0,0 +1,225 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <string.h>
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "actions-types.h"
+
+#include "config/gimpdisplayconfig.h"
+#include "config/gimpguiconfig.h"
+
+#include "core/gimp.h"
+#include "core/gimpcontainer.h"
+
+#include "widgets/gimpactiongroup.h"
+#include "widgets/gimpdialogfactory.h"
+#include "widgets/gimpsessioninfo.h"
+#include "widgets/gimpwidgets-utils.h"
+
+#include "display/gimpdisplay.h"
+#include "display/gimpdisplayshell.h"
+
+#include "dialogs/dialogs.h"
+
+#include "actions.h"
+#include "dialogs-actions.h"
+#include "windows-commands.h"
+
+#include "gimp-intl.h"
+
+
+void
+windows_hide_docks_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ Gimp *gimp;
+ gboolean active;
+ return_if_no_gimp (gimp, data);
+
+ active = g_variant_get_boolean (value);
+
+ if (active != GIMP_GUI_CONFIG (gimp->config)->hide_docks)
+ g_object_set (gimp->config,
+ "hide-docks", active,
+ NULL);
+}
+
+void
+windows_use_single_window_mode_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ Gimp *gimp;
+ gboolean active;
+ return_if_no_gimp (gimp, data);
+
+ active = g_variant_get_boolean (value);
+
+ if (active != GIMP_GUI_CONFIG (gimp->config)->single_window_mode)
+ g_object_set (gimp->config,
+ "single-window-mode", active,
+ NULL);
+}
+
+void
+windows_show_tabs_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ Gimp *gimp;
+ gboolean active;
+ return_if_no_gimp (gimp, data);
+
+ active = g_variant_get_boolean (value);
+
+ if (active != GIMP_GUI_CONFIG (gimp->config)->show_tabs)
+ g_object_set (gimp->config,
+ "show-tabs", active,
+ NULL);
+}
+
+
+void
+windows_set_tabs_position_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ Gimp *gimp;
+ GimpPosition position;
+ return_if_no_gimp (gimp, data);
+
+ position = (GimpPosition) g_variant_get_int32 (value);
+
+ if (position != GIMP_GUI_CONFIG (gimp->config)->tabs_position)
+ g_object_set (gimp->config,
+ "tabs-position", position,
+ NULL);
+}
+
+void
+windows_show_display_next_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpDisplay *display;
+ Gimp *gimp;
+ gint index;
+ return_if_no_display (display, data);
+ return_if_no_gimp (gimp, data);
+
+ index = gimp_container_get_child_index (gimp->displays,
+ GIMP_OBJECT (display));
+ index++;
+
+ if (index >= gimp_container_get_n_children (gimp->displays))
+ index = 0;
+
+ display = GIMP_DISPLAY (gimp_container_get_child_by_index (gimp->displays,
+ index));
+ gimp_display_shell_present (gimp_display_get_shell (display));
+}
+
+void
+windows_show_display_previous_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpDisplay *display;
+ Gimp *gimp;
+ gint index;
+ return_if_no_display (display, data);
+ return_if_no_gimp (gimp, data);
+
+ index = gimp_container_get_child_index (gimp->displays,
+ GIMP_OBJECT (display));
+ index--;
+
+ if (index < 0)
+ index = gimp_container_get_n_children (gimp->displays) - 1;
+
+ display = GIMP_DISPLAY (gimp_container_get_child_by_index (gimp->displays,
+ index));
+ gimp_display_shell_present (gimp_display_get_shell (display));
+}
+
+void
+windows_show_display_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpDisplay *display = g_object_get_data (G_OBJECT (action), "display");
+
+ gimp_display_shell_present (gimp_display_get_shell (display));
+}
+
+void
+windows_show_dock_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GtkWindow *dock_window = g_object_get_data (G_OBJECT (action), "dock-window");
+
+ gtk_window_present (dock_window);
+}
+
+void
+windows_open_recent_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpSessionInfo *info;
+ GimpDialogFactoryEntry *entry;
+ Gimp *gimp;
+ GtkWidget *widget;
+ return_if_no_gimp (gimp, data);
+ return_if_no_widget (widget, data);
+
+ info = g_object_get_data (G_OBJECT (action), "info");
+ entry = gimp_session_info_get_factory_entry (info);
+
+ if (entry && strcmp ("gimp-toolbox-window", entry->identifier) == 0 &&
+ dialogs_actions_toolbox_exists (gimp))
+ {
+ gimp_message (gimp,
+ G_OBJECT (action_data_get_widget (data)),
+ GIMP_MESSAGE_WARNING,
+ _("The chosen recent dock contains a toolbox. Please "
+ "close the currently open toolbox and try again."));
+ return;
+ }
+
+ g_object_ref (info);
+
+ gimp_container_remove (global_recent_docks, GIMP_OBJECT (info));
+
+ gimp_dialog_factory_add_session_info (gimp_dialog_factory_get_singleton (),
+ info);
+
+ gimp_session_info_restore (info, gimp_dialog_factory_get_singleton (),
+ gtk_widget_get_screen (widget),
+ gimp_widget_get_monitor (widget));
+
+ g_object_unref (info);
+}
diff --git a/app/actions/windows-commands.h b/app/actions/windows-commands.h
new file mode 100644
index 0000000..712d3c1
--- /dev/null
+++ b/app/actions/windows-commands.h
@@ -0,0 +1,53 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __WINDOWS_COMMANDS_H__
+#define __WINDOWS_COMMANDS_H__
+
+
+void windows_hide_docks_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void windows_use_single_window_mode_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+void windows_show_tabs_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void windows_set_tabs_position_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+void windows_show_display_next_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void windows_show_display_previous_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void windows_show_display_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void windows_show_dock_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+void windows_open_recent_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
+
+#endif /* __WINDOWS_COMMANDS_H__ */