diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:30:19 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:30:19 +0000 |
commit | 5c1676dfe6d2f3c837a5e074117b45613fd29a72 (patch) | |
tree | cbffb45144febf451e54061db2b21395faf94bfe /app/actions | |
parent | Initial commit. (diff) | |
download | gimp-5c1676dfe6d2f3c837a5e074117b45613fd29a72.tar.xz gimp-5c1676dfe6d2f3c837a5e074117b45613fd29a72.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')
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__ */ |