python: Port arguments code to use functions

This patch ports the first-party Python plug-ins
to use the new argument API.
This restores the ability to add dropdown menus from
enums and Gimp.Choice parameters, and also allows
defaults to be set for custom datatypes like Gegl.Color.
This commit is contained in:
Alx Sa 2024-06-07 03:09:43 +00:00
parent d1c4457fa3
commit 292cb01fc2
9 changed files with 280 additions and 515 deletions

View File

@ -265,30 +265,6 @@ def export_colorxhtml(procedure, run_mode, image, file, metadata, config, data):
class ColorXhtml(Gimp.PlugIn): class ColorXhtml(Gimp.PlugIn):
## Parameters ##
__gproperties__ = {
"source-file":(bool,
_("_Read characters from file, if true, or use text entry"),
_("_Read characters from file, if true, or use text entry"),
False,
GObject.ParamFlags.READWRITE),
"characters": (str,
_("_File to read or characters to use"),
_("_File to read or characters to use"),
"foo",
GObject.ParamFlags.READWRITE),
"font-size": (int,
_("Fo_nt size in pixels"),
_("Fo_nt size in pixels"),
5, 100, 10,
GObject.ParamFlags.READWRITE),
"separate": (bool,
_("_Write a separate CSS file"),
_("_Write a separate CSS file"),
False,
GObject.ParamFlags.READWRITE)
}
## GimpPlugIn virtual methods ## ## GimpPlugIn virtual methods ##
def do_set_i18n(self, procname): def do_set_i18n(self, procname):
return True, 'gimp30-python', None return True, 'gimp30-python', None
@ -314,10 +290,19 @@ class ColorXhtml(Gimp.PlugIn):
procedure.set_extensions ("html,xhtml"); procedure.set_extensions ("html,xhtml");
procedure.add_argument_from_property(self, "source-file") procedure.add_boolean_argument ("source-file",
procedure.add_argument_from_property(self, "characters") _("_Read characters from file, if true, or use text entry"),
procedure.add_argument_from_property(self, "font-size") _("Read characters from file, if true, or use text entry"),
procedure.add_argument_from_property(self, "separate") False, GObject.ParamFlags.READWRITE)
procedure.add_string_argument ("characters", _("_File to read or characters to use"),
_("File to read or characters to use"),
"foo", GObject.ParamFlags.READWRITE)
procedure.add_int_argument ("font-size", _("Fo_nt size in pixels"),
_("Font size in pixels"), 5, 100, 10,
GObject.ParamFlags.READWRITE)
procedure.add_boolean_argument ("separate", _("_Write a separate CSS file"),
_("Write a separate CSS file"),
False, GObject.ParamFlags.READWRITE)
return procedure return procedure

View File

@ -31,19 +31,6 @@ def N_(message): return message
def _(message): return GLib.dgettext(None, message) def _(message): return GLib.dgettext(None, message)
def foggify(procedure, run_mode, image, n_drawables, drawables, config, data): def foggify(procedure, run_mode, image, n_drawables, drawables, config, data):
Gegl.init(None)
_color = Gegl.Color.new("black")
_color.set_rgba(0.94, 0, 0, 1.0)
# Work around not being able to set default color by only setting it
# when color in our config is None. This won't help when resetting to
# factory default. This also fixes a critical when running without
# changing the color away from None.
color = config.get_property('color')
if color is None:
config.set_property('color', _color)
if run_mode == Gimp.RunMode.INTERACTIVE: if run_mode == Gimp.RunMode.INTERACTIVE:
GimpUi.init('python-fu-foggify') GimpUi.init('python-fu-foggify')
@ -105,32 +92,6 @@ def foggify(procedure, run_mode, image, n_drawables, drawables, config, data):
return procedure.new_return_values(Gimp.PDBStatusType.SUCCESS, GLib.Error()) return procedure.new_return_values(Gimp.PDBStatusType.SUCCESS, GLib.Error())
class Foggify (Gimp.PlugIn): class Foggify (Gimp.PlugIn):
## Parameters ##
__gproperties__ = {
"name": (str,
_("Layer _name"),
_("Layer name"),
_("Clouds"),
GObject.ParamFlags.READWRITE),
"turbulence": (float,
_("_Turbulence"),
_("Turbulence"),
0.0, 7.0, 1.0,
GObject.ParamFlags.READWRITE),
"opacity": (float,
_("O_pacity"),
_("Opacity"),
0.0, 100.0, 100.0,
GObject.ParamFlags.READWRITE),
}
# I use a different syntax for this property because I think it is
# supposed to allow setting a default, except it doesn't seem to
# work. I still leave it this way for now until we figure this out
# as it should be the better syntax.
color = GObject.Property(type =Gegl.Color, default=None,
nick =_("_Fog color"),
blurb=_("Fog color"))
## GimpPlugIn virtual methods ## ## GimpPlugIn virtual methods ##
def do_set_i18n(self, procname): def do_set_i18n(self, procname):
return True, 'gimp30-python', None return True, 'gimp30-python', None
@ -139,6 +100,11 @@ class Foggify (Gimp.PlugIn):
return [ 'python-fu-foggify' ] return [ 'python-fu-foggify' ]
def do_create_procedure(self, name): def do_create_procedure(self, name):
Gegl.init(None)
_color = Gegl.Color.new("black")
_color.set_rgba(0.94, 0.71, 0.27, 1.0)
procedure = Gimp.ImageProcedure.new(self, name, procedure = Gimp.ImageProcedure.new(self, name,
Gimp.PDBProcType.PLUGIN, Gimp.PDBProcType.PLUGIN,
foggify, None) foggify, None)
@ -154,10 +120,15 @@ class Foggify (Gimp.PlugIn):
"1999,2007") "1999,2007")
procedure.add_menu_path ("<Image>/Filters/Decor") procedure.add_menu_path ("<Image>/Filters/Decor")
procedure.add_argument_from_property(self, "name") procedure.add_string_argument ("name", _("Layer _name"), _("Layer name"),
procedure.add_argument_from_property(self, "color") _("Clouds"), GObject.ParamFlags.READWRITE)
procedure.add_argument_from_property(self, "turbulence") procedure.add_color_argument ("color", _("_Fog color"), _("_Fog color"),
procedure.add_argument_from_property(self, "opacity") True, _color, GObject.ParamFlags.READWRITE)
procedure.add_double_argument ("turbulence", _("_Turbulence"), _("Turbulence"),
0.0, 7.0, 1.0, GObject.ParamFlags.READWRITE)
procedure.add_double_argument ("opacity", _("O_pacity"), _("Opacity"),
0.0, 100.0, 100.0, GObject.ParamFlags.READWRITE)
return procedure return procedure
Gimp.main(Foggify.__gtype__, sys.argv) Gimp.main(Foggify.__gtype__, sys.argv)

View File

@ -177,21 +177,6 @@ def gradient_css_save(procedure, config, data):
GLib.Error('File saving failed: {}'.format(file.get_path()))) GLib.Error('File saving failed: {}'.format(file.get_path())))
class GradientsSaveAsCSS (Gimp.PlugIn): class GradientsSaveAsCSS (Gimp.PlugIn):
## Parameters ##
__gproperties__ = {
"run-mode": (Gimp.RunMode,
_("Run mode"),
_("The run mode"),
Gimp.RunMode.NONINTERACTIVE,
GObject.ParamFlags.READWRITE),
"gradient": (Gimp.Gradient,
_("_Gradient to use"), "",
GObject.ParamFlags.READWRITE),
"file": (Gio.File,
_("_File"), None,
GObject.ParamFlags.READWRITE),
}
## GimpPlugIn virtual methods ## ## GimpPlugIn virtual methods ##
def do_set_i18n(self, procname): def do_set_i18n(self, procname):
return True, 'gimp30-python', None return True, 'gimp30-python', None
@ -213,9 +198,14 @@ class GradientsSaveAsCSS (Gimp.PlugIn):
"2011") "2011")
procedure.add_menu_path('<Gradients>/Gradients Menu') procedure.add_menu_path('<Gradients>/Gradients Menu')
procedure.add_argument_from_property(self, "run-mode") procedure.add_enum_argument ("run-mode", _("Run mode"),
procedure.add_argument_from_property(self, "gradient") _("The run mode"), Gimp.RunMode,
procedure.add_argument_from_property(self, "file") Gimp.RunMode.NONINTERACTIVE,
GObject.ParamFlags.READWRITE)
procedure.add_gradient_argument ("gradient", _("_Gradient to use"),
"", GObject.ParamFlags.READWRITE)
procedure.add_file_argument ("file", _("_File"),
"", GObject.ParamFlags.READWRITE)
return procedure return procedure
Gimp.main(GradientsSaveAsCSS.__gtype__, sys.argv) Gimp.main(GradientsSaveAsCSS.__gtype__, sys.argv)

View File

@ -87,14 +87,6 @@ class StringEnum:
return key return key
raise AttributeError("No such key string " + key) raise AttributeError("No such key string " + key)
OUTPUT_FORMAT_LABELS = (_("Pixel count"), _("Normalized"), _("Percent"))
output_format_enum = StringEnum(
"pixel count", OUTPUT_FORMAT_LABELS[0],
"normalized", OUTPUT_FORMAT_LABELS[1],
"percent", OUTPUT_FORMAT_LABELS[2]
)
def histogram_export(procedure, img, layers, gio_file, def histogram_export(procedure, img, layers, gio_file,
bucket_size, sample_average, output_format): bucket_size, sample_average, output_format):
layers = img.list_selected_layers() layers = img.list_selected_layers()
@ -139,12 +131,12 @@ def histogram_export(procedure, img, layers, gio_file,
histo_config.set_property('channel', channel) histo_config.set_property('channel', channel)
result = histo_proc.run(histo_config) result = histo_proc.run(histo_config)
if output_format == output_format_enum.pixel_count: if output_format == "pixel-count":
count = int(result.index(5)) count = int(result.index(5))
else: else:
pixels = result.index(4) pixels = result.index(4)
count = (result.index(5) / pixels) if pixels else 0 count = (result.index(5) / pixels) if pixels else 0
if output_format == output_format_enum.percent: if output_format == "percent":
count = "%.2f%%" % (count * 100) count = "%.2f%%" % (count * 100)
row.append(str(count)) row.append(str(count))
writer.writerow(row) writer.writerow(row)
@ -177,30 +169,7 @@ def run(procedure, run_mode, image, n_layers, layers, config, data):
GimpUi.init("histogram-export.py") GimpUi.init("histogram-export.py")
dialog = GimpUi.ProcedureDialog.new(procedure, config, _("Histogram Export...")) dialog = GimpUi.ProcedureDialog.new(procedure, config, _("Histogram Export..."))
vbox = dialog.fill_box ("histogram-box", ["file", "bucket-size", "sample-average"]) dialog.fill()
#TODO: For now, we'll manually create a GimpStringComboBox
#for the GUI version of 'output-format'. Once we can
#use Gimp.Choice in Python, we can replace the str
#parameter without changing any third-party function calls
hbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=6)
vbox.pack_start(hbox, False, False, 0)
hbox.set_visible(True)
label = Gtk.Label.new_with_mnemonic(_("Output _format"))
hbox.pack_start(label, False, False, 0)
label.set_visible(True)
output_format_store = store = Gtk.ListStore(str, str)
output_format_store.append(["pixel count", OUTPUT_FORMAT_LABELS[0]])
output_format_store.append(["normalized", OUTPUT_FORMAT_LABELS[1]])
output_format_store.append(["percent", OUTPUT_FORMAT_LABELS[2]])
combo = GimpUi.prop_string_combo_box_new (config, "output-format", output_format_store, 0, 1)
hbox.pack_start(combo, False, False, 0)
combo.set_visible(True)
dialog.fill(["histogram-box"])
if not dialog.run(): if not dialog.run():
return procedure.new_return_values(Gimp.PDBStatusType.CANCEL, return procedure.new_return_values(Gimp.PDBStatusType.CANCEL,
@ -223,32 +192,6 @@ def run(procedure, run_mode, image, n_layers, layers, config, data):
class HistogramExport(Gimp.PlugIn): class HistogramExport(Gimp.PlugIn):
## Parameters ##
__gproperties__ = {
# TODO: GFile props still don't have labels + only load existing files
# (here we likely want to create a new file).
"file": (Gio.File,
_("Histogram File"),
"Histogram export file",
GObject.ParamFlags.READWRITE),
"bucket-size": (float,
_("_Bucket Size"),
"Bucket Size",
0.001, 1.0, 0.01,
GObject.ParamFlags.READWRITE),
"sample-average": (bool,
_("Sample _Average"),
"Sample Average",
False,
GObject.ParamFlags.READWRITE),
"output-format": (str,
_("Output _format"),
"Output format: 'pixel count', 'normalized', 'percent'",
"pixel count",
GObject.ParamFlags.READWRITE),
}
## GimpPlugIn virtual methods ## ## GimpPlugIn virtual methods ##
def do_set_i18n(self, procname): def do_set_i18n(self, procname):
return True, 'gimp30-python', None return True, 'gimp30-python', None
@ -274,10 +217,20 @@ class HistogramExport(Gimp.PlugIn):
"2014") "2014")
procedure.add_menu_path("<Image>/Colors/Info/") procedure.add_menu_path("<Image>/Colors/Info/")
procedure.add_argument_from_property(self, "file") # TODO: GFile props still don't have labels + only load existing files
procedure.add_argument_from_property(self, "bucket-size") # (here we likely want to create a new file).
procedure.add_argument_from_property(self, "sample-average") procedure.add_file_argument ("file", _("Histogram File"),
procedure.add_argument_from_property(self, "output-format") _("Histogram export file"), GObject.ParamFlags.READWRITE)
procedure.add_double_argument ("bucket-size", _("_Bucket Size"), _("Bucket Size"),
0.001, 1.0, 0.01, GObject.ParamFlags.READWRITE)
procedure.add_boolean_argument ("sample-average", _("Sample _Average"), _("Sample Average"),
False, GObject.ParamFlags.READWRITE)
choice = Gimp.Choice.new()
choice.add("pixel-count", 0, _("Pixel Count"), "")
choice.add("normalized", 1, _("Normalized"), "")
choice.add("percent", 2, _("Percent"), "")
procedure.add_choice_argument ("output-format", _("Output _format"), _("Output format"),
choice, "percent", GObject.ParamFlags.READWRITE)
return procedure return procedure

View File

@ -33,52 +33,6 @@ otherwise copies the given palette and returns it.
""" """
class PaletteOffset (Gimp.PlugIn): class PaletteOffset (Gimp.PlugIn):
## Parameter: run-mode ##
@GObject.Property(type=Gimp.RunMode,
default=Gimp.RunMode.NONINTERACTIVE,
nick="Run mode", blurb="The run mode")
def run_mode(self):
"""Read-write integer property."""
return self._run_mode
@run_mode.setter
def run_mode(self, run_mode):
self._run_mode = run_mode
## Parameter: palette ##
@GObject.Property(type=Gimp.Palette,
nick= _("Palette"),
blurb= _("Palette"))
def palette(self):
return self._palette
@palette.setter
def palette(self, palette):
self._palette = palette
## Parameter: amount ##
@GObject.Property(type=int,
default=1,
nick= _("Off_set"),
blurb= _("Offset"))
def amount(self):
return self._amount
@amount.setter
def amount(self, amount):
self._amount = amount
## Return: new-palette ##
@GObject.Property(type=Gimp.Palette,
nick=_("The edited palette"),
blurb=_("The newly created palette when read-only, otherwise the input palette"))
def new_palette(self):
return self.new_palette
@new_palette.setter
def new_palette(self, new_palette):
self.new_palette = new_palette
## GimpPlugIn virtual methods ## ## GimpPlugIn virtual methods ##
def do_set_i18n(self, procname): def do_set_i18n(self, procname):
return True, 'gimp30-python', None return True, 'gimp30-python', None
@ -98,10 +52,18 @@ class PaletteOffset (Gimp.PlugIn):
procedure.set_attribution("Joao S. O. Bueno Calligaris, Carol Spears", procedure.set_attribution("Joao S. O. Bueno Calligaris, Carol Spears",
"(c) Joao S. O. Bueno Calligaris", "(c) Joao S. O. Bueno Calligaris",
"2004, 2006") "2004, 2006")
procedure.add_argument_from_property(self, "run-mode") procedure.add_enum_argument ("run-mode", _("Run mode"),
procedure.add_argument_from_property(self, "palette") _("The run mode"), Gimp.RunMode,
procedure.add_argument_from_property(self, "amount") Gimp.RunMode.NONINTERACTIVE,
procedure.add_return_value_from_property(self, "new-palette") GObject.ParamFlags.READWRITE)
procedure.add_palette_argument ("palette", _("_Palette"),
_("Palette"),
GObject.ParamFlags.READWRITE)
procedure.add_int_argument ("amount", _("O_ffset"), _("Offset"),
1, GLib.MAXINT, 1, GObject.ParamFlags.READWRITE)
procedure.add_palette_return_value ("new-palette", _("The edited palette"),
_("The newly created palette when read-only, otherwise the input palette"),
GObject.ParamFlags.READWRITE)
procedure.add_menu_path ('<Palettes>/Palettes Menu') procedure.add_menu_path ('<Palettes>/Palettes Menu')
else: else:
procedure = None procedure = None
@ -128,34 +90,16 @@ class PaletteOffset (Gimp.PlugIn):
GimpUi.init ("palette-offset.py") GimpUi.init ("palette-offset.py")
use_header_bar = Gtk.Settings.get_default().get_property("gtk-dialogs-use-header") dialog = GimpUi.ProcedureDialog(procedure=procedure, config=config)
dialog = GimpUi.Dialog(use_header_bar=use_header_bar, dialog.fill(["palette", "amount"])
title=_("Offset Palette...")) if not dialog.run():
dialog.destroy()
return procedure.new_return_values(Gimp.PDBStatusType.CANCEL, GLib.Error())
else:
dialog.destroy()
dialog.add_button(_("_Cancel"), Gtk.ResponseType.CANCEL) amount = config.get_property("amount")
dialog.add_button(_("_OK"), Gtk.ResponseType.OK) palette = config.get_property("palette")
box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL,
homogeneous=False, spacing=12)
dialog.get_content_area().add(box)
box.show()
label = Gtk.Label.new(_("Offset"))
box.pack_start(label, False, False, 1)
label.show()
amount = self.set_property("amount", amount)
spin = GimpUi.prop_spin_button_new(self, "amount", 1.0, 5.0, 0)
spin.set_activates_default(True)
box.pack_end(spin, False, False, 1)
spin.show()
dialog.show()
if dialog.run() != Gtk.ResponseType.OK:
return procedure.new_return_values(Gimp.PDBStatusType.CANCEL,
GLib.Error("Canceled"))
amount = self.get_property("amount")
config.set_property("palette", None)
#If palette is read only, work on a copy: #If palette is read only, work on a copy:
editable = palette.is_editable() editable = palette.is_editable()

View File

@ -77,12 +77,6 @@ GRAIN_SCALE = (1.0, 1.0 , 1.0,
100., 256., 256., 100., 256., 256.,
256., 360.,) 256., 360.,)
SELECT_ALL = 0
SELECT_SLICE = 1
SELECT_AUTOSLICE = 2
SELECT_PARTITIONED = 3
SELECTIONS = (SELECT_ALL, SELECT_SLICE, SELECT_AUTOSLICE, SELECT_PARTITIONED)
try: try:
from colormath.color_objects import RGBColor, LabColor, LCHabColor from colormath.color_objects import RGBColor, LabColor, LCHabColor
@ -222,7 +216,7 @@ def palette_sort(palette, selection, slice_expr, channel1, ascending1,
num_colors = palette.get_color_count() num_colors = palette.get_color_count()
start, nrows, length = None, None, None start, nrows, length = None, None, None
if selection == SELECT_AUTOSLICE: if selection == "auto-slice":
def find_index(color, startindex=0): def find_index(color, startindex=0):
for i in range(startindex, num_colors): for i in range(startindex, num_colors):
c = palette.entry_get_color(i) c = palette.entry_get_color(i)
@ -262,9 +256,9 @@ def palette_sort(palette, selection, slice_expr, channel1, ascending1,
except ValueError: except ValueError:
# bad expression is okay here, just assume one row # bad expression is okay here, just assume one row
nrows = 1 nrows = 1
# remaining behavior is implemented by SELECT_SLICE 'inheritance'. # remaining behavior is implemented by "slice-array" 'inheritance'.
selection = SELECT_SLICE selection = "slice-array"
elif selection in (SELECT_SLICE, SELECT_PARTITIONED): elif selection in ("slice-array", "partitioned"):
start, nrows, length = parse_slice(slice_expr, num_colors) start, nrows, length = parse_slice(slice_expr, num_colors)
channels_getter_1 = channel_getters[channel1] channels_getter_1 = channel_getters[channel1]
@ -283,14 +277,15 @@ def palette_sort(palette, selection, slice_expr, channel1, ascending1,
result.append((index, entry)) result.append((index, entry))
return result return result
if selection == SELECT_ALL: print (selection)
if selection == "all":
entry_list = get_colors(0, num_colors) entry_list = get_colors(0, num_colors)
entry_list.sort(key=lambda v: v[0]) entry_list.sort(key=lambda v: v[0])
for i in range(num_colors): for i in range(num_colors):
palette.entry_set_name(i, entry_list[i][1][0]) palette.entry_set_name(i, entry_list[i][1][0])
palette.entry_set_color(i, entry_list[i][1][1]) palette.entry_set_color(i, entry_list[i][1][1])
elif selection == SELECT_PARTITIONED: elif selection == "partitioned":
if num_colors < (start + length * nrows) - 1: if num_colors < (start + length * nrows) - 1:
raise ValueError('Not enough entries in palette to ' raise ValueError('Not enough entries in palette to '
'sort complete rows! Got %d, expected >=%d' % 'sort complete rows! Got %d, expected >=%d' %
@ -313,13 +308,13 @@ def palette_sort(palette, selection, slice_expr, channel1, ascending1,
old_partition = this_partition old_partition = this_partition
base = rowstart base = rowstart
for size in partition_spans: for size in partition_spans:
palette_sort(palette, SELECT_SLICE, '%d:1,%d' % (base, size), palette_sort(palette, "slice-array", '%d:1,%d' % (base, size),
channel1, ascending1, channel1, ascending1,
channel2, ascending2, channel2, ascending2,
quantize, 0, 1.0) quantize, 0, 1.0)
base += size base += size
else: else:
# SELECT_SLICE and SELECT_AUTOSLICE # "slice-array" and "auto-slice"
stride = length stride = length
if num_colors < (start + stride * nrows) - 1: if num_colors < (start + stride * nrows) - 1:
raise ValueError('Not enough entries in palette to sort ' raise ValueError('Not enough entries in palette to sort '
@ -348,74 +343,7 @@ You can optionally install colormath (https://pypi.python.org/pypi/colormath/1.0
to GIMP's Python to get even more channels to choose from. to GIMP's Python to get even more channels to choose from.
""" """
selections_option = [ _("All"), _("Slice / Array"), _("Autoslice (fg->bg)"), _("Partitioned") ]
class PaletteSort (Gimp.PlugIn): class PaletteSort (Gimp.PlugIn):
## Parameters ##
__gproperties__ = {
"run-mode": (Gimp.RunMode,
_("Run mode"),
"The run mode",
Gimp.RunMode.INTERACTIVE,
GObject.ParamFlags.READWRITE),
"palette": (Gimp.Palette,
_("_Palette"),
_("Palette"),
GObject.ParamFlags.READWRITE),
"selections": (int,
_("Select_ions"),
str(selections_option),
0, 3, 0,
GObject.ParamFlags.READWRITE),
# TODO: It would be much simpler to replace the slice expression with three
# separate parameters: start-index, number-of-rows, row_length
"slice_expr": (str,
_("Slice _expression"),
slice_expr_doc,
"",
GObject.ParamFlags.READWRITE),
"channel1": (int,
_("Channel _to sort"),
"Channel to sort: " + str(AVAILABLE_CHANNELS),
0, len(AVAILABLE_CHANNELS), 3,
GObject.ParamFlags.READWRITE),
"ascending1": (bool,
_("_Ascending"),
_("Ascending"),
True,
GObject.ParamFlags.READWRITE),
"channel2": (int,
_("Secondary C_hannel to sort"),
"Secondary Channel to sort: " + str(AVAILABLE_CHANNELS),
0, len(AVAILABLE_CHANNELS), 5,
GObject.ParamFlags.READWRITE),
"ascending2": (bool,
_("Ascen_ding"),
_("Ascending"),
True,
GObject.ParamFlags.READWRITE),
"quantize": (float,
_("_Quantization"),
_("Quantization"),
0.0, 1.0, 0.0,
GObject.ParamFlags.READWRITE),
"pchannel": (int,
_("Partitionin_g channel"),
"Partitioning channel: " + str(AVAILABLE_CHANNELS),
0, len(AVAILABLE_CHANNELS), 3,
GObject.ParamFlags.READWRITE),
"pquantize": (float,
_("Partition q_uantization"),
_("Partition quantization"),
0.0, 1.0, 0.0,
GObject.ParamFlags.READWRITE),
# Returned value
"new_palette": (Gimp.Palette,
_("Palette"),
_("Palette"),
GObject.ParamFlags.READWRITE),
}
## GimpPlugIn virtual methods ## ## GimpPlugIn virtual methods ##
def do_set_i18n(self, procname): def do_set_i18n(self, procname):
return True, 'gimp30-python', None return True, 'gimp30-python', None
@ -440,18 +368,53 @@ class PaletteSort (Gimp.PlugIn):
"2006-2014") "2006-2014")
procedure.add_menu_path ('<Palettes>/Palettes Menu') procedure.add_menu_path ('<Palettes>/Palettes Menu')
procedure.add_argument_from_property(self, "run-mode") procedure.add_enum_argument ("run-mode", _("Run mode"),
procedure.add_argument_from_property(self, "palette") _("The run mode"), Gimp.RunMode,
procedure.add_argument_from_property(self, "selections") Gimp.RunMode.INTERACTIVE,
procedure.add_argument_from_property(self, "slice_expr") GObject.ParamFlags.READWRITE)
procedure.add_argument_from_property(self, "channel1") procedure.add_palette_argument ("palette", _("_Palette"),
procedure.add_argument_from_property(self, "ascending1") _("Palette"),
procedure.add_argument_from_property(self, "channel2") GObject.ParamFlags.READWRITE)
procedure.add_argument_from_property(self, "ascending2")
procedure.add_argument_from_property(self, "quantize") selection_choice = Gimp.Choice.new()
procedure.add_argument_from_property(self, "pchannel") selection_choice.add("all", 0, _("All"), "")
procedure.add_argument_from_property(self, "pquantize") selection_choice.add("slice-array", 1, _("Slice / Array"), "")
procedure.add_return_value_from_property(self, "new_palette") selection_choice.add("auto-slice", 2, _("Autoslice (fg->bg)"), "")
selection_choice.add("partitioned", 3, _("Partitioned"), "")
procedure.add_choice_argument ("selections", _("Select_ions"), _("Selections"),
selection_choice, "all", GObject.ParamFlags.READWRITE)
# TODO: It would be much simpler to replace the slice expression with three
# separate parameters: start-index, number-of-rows, row_length
procedure.add_string_argument ("slice-expr", _("Slice _expression"),
slice_expr_doc, "",
GObject.ParamFlags.READWRITE)
channel_choice = Gimp.Choice.new()
self.add_choices (channel_choice)
procedure.add_choice_argument ("channel1", _("Channel _to sort"), _("Channel to sort"),
channel_choice, "luma", GObject.ParamFlags.READWRITE)
procedure.add_boolean_argument ("ascending1", _("_Ascending"), _("Ascending"),
True, GObject.ParamFlags.READWRITE)
channel_choice2 = Gimp.Choice.new()
self.add_choices (channel_choice2)
procedure.add_choice_argument ("channel2", _("Secondary C_hannel to sort"),
_("Secondary Channel to sort"), channel_choice2,
"saturation", GObject.ParamFlags.READWRITE)
procedure.add_boolean_argument ("ascending2", _("Ascen_ding"), _("Ascending"),
True, GObject.ParamFlags.READWRITE)
procedure.add_double_argument ("quantize", _("_Quantization"),
_("Quantization"), 0.0, 1.0, 0.0,
GObject.ParamFlags.READWRITE)
pchannel_choice = Gimp.Choice.new()
self.add_choices (pchannel_choice)
procedure.add_choice_argument ("pchannel", _("Partitionin_g channel"),
_("Partitioning channel"), pchannel_choice,
"luma", GObject.ParamFlags.READWRITE)
procedure.add_double_argument ("pquantize", _("Partition q_uantization"),
_("Partition quantization"), 0.0, 1.0, 0.0,
GObject.ParamFlags.READWRITE)
procedure.add_palette_return_value ("new-palette", _("Palette"),
_("Palette"), GObject.ParamFlags.READWRITE)
return procedure return procedure
@ -478,13 +441,9 @@ class PaletteSort (Gimp.PlugIn):
dialog = GimpUi.ProcedureDialog(procedure=procedure, config=config) dialog = GimpUi.ProcedureDialog(procedure=procedure, config=config)
dialog.fill (["palette"]) dialog.fill (["palette"])
dialog.get_int_combo("selections", GimpUi.IntStore.new (selections_option))
dialog.fill (["selections","slice-expr"]) dialog.fill (["selections","slice-expr"])
dialog.get_int_combo("channel1", GimpUi.IntStore.new (AVAILABLE_CHANNELS))
dialog.fill (["channel1", "ascending1"]) dialog.fill (["channel1", "ascending1"])
dialog.get_int_combo("channel2", GimpUi.IntStore.new (AVAILABLE_CHANNELS))
dialog.fill (["channel2","ascending2", "quantize"]) dialog.fill (["channel2","ascending2", "quantize"])
dialog.get_int_combo("pchannel", GimpUi.IntStore.new (AVAILABLE_CHANNELS))
dialog.fill (["pchannel","pquantize"]) dialog.fill (["pchannel","pquantize"])
if not dialog.run(): if not dialog.run():
@ -495,13 +454,13 @@ class PaletteSort (Gimp.PlugIn):
palette = config.get_property("palette") palette = config.get_property("palette")
selection = config.get_property("selections") selection = config.get_property("selections")
slice_expr = config.get_property ("slice_expr") slice_expr = config.get_property("slice-expr")
channel1 = config.get_property("channel1") channel1 = config.get_choice_id("channel1")
ascending1 = config.get_property ("ascending1") ascending1 = config.get_property ("ascending1")
channel2 = config.get_property("channel2") channel2 = config.get_choice_id("channel2")
ascending2 = config.get_property ("ascending2") ascending2 = config.get_property ("ascending2")
quantize = config.get_property ("quantize") quantize = config.get_property ("quantize")
pchannel = config.get_property("pchannel") pchannel = config.get_choice_id("pchannel")
pquantize = config.get_property ("pquantize") pquantize = config.get_property ("pquantize")
try: try:
new_palette = palette_sort(palette, selection, slice_expr, channel1, ascending1, new_palette = palette_sort(palette, selection, slice_expr, channel1, ascending1,
@ -516,4 +475,18 @@ class PaletteSort (Gimp.PlugIn):
return_val.insert(1, value) return_val.insert(1, value)
return return_val return return_val
def add_choices (self, choice):
#TODO: Re-incorporate LAB and LCHab options with GeglColor
choice.add("red", 0, _("Red"), "")
choice.add("green", 1, _("Green"), "")
choice.add("blue", 2, _("Blue"), "")
choice.add("luma", 3, _("Luma (Y)"), "")
choice.add("hue", 4, _("Hue"), "")
choice.add("saturation", 5, _("Saturation"), "")
choice.add("value", 6, _("Value"), "")
choice.add("saturation-hsl", 7, _("Saturation (HSL)"), "")
choice.add("lightness-hsl", 8, _("Lightness (HSL)"), "")
choice.add("index", 9, _("Index"), "")
choice.add("random", 10, _("Random"), "")
Gimp.main(PaletteSort.__gtype__, sys.argv) Gimp.main(PaletteSort.__gtype__, sys.argv)

View File

@ -111,43 +111,6 @@ def run(procedure, config, data):
return retval return retval
class PaletteToGradient (Gimp.PlugIn): class PaletteToGradient (Gimp.PlugIn):
## Parameter: run mode ##
@GObject.Property(type=Gimp.RunMode,
default=Gimp.RunMode.NONINTERACTIVE,
nick="Run mode", blurb="The run mode")
def run_mode(self):
'''The run mode (unused)'''
return self.runmode
@run_mode.setter
def run_mode(self, runmode):
self.runmode = runmode
## Parameter: palette ##
@GObject.Property(type=Gimp.Palette,
default=None,
nick= _("_Palette"))
def palette(self):
'''Palette or None for the currently selected palette'''
return self.palette
@palette.setter
def palette(self, palette):
self.palette = palette
## Properties: return values ##
@GObject.Property(type=Gimp.Gradient,
default="",
nick=_("The newly created gradient"),
blurb=_("The newly created gradient"))
def new_gradient(self):
"""Read-write integer property."""
return self.new_gradient
@new_gradient.setter
def new_gradient(self, new_gradient):
self.new_gradient = new_gradient
## GimpPlugIn virtual methods ## ## GimpPlugIn virtual methods ##
def do_set_i18n(self, procname): def do_set_i18n(self, procname):
return True, 'gimp30-python', None return True, 'gimp30-python', None
@ -176,12 +139,17 @@ class PaletteToGradient (Gimp.PlugIn):
if procedure is not None: if procedure is not None:
procedure.set_attribution("Carol Spears, reproduced from previous work by Adrian Likins and Jeff Trefftz", procedure.set_attribution("Carol Spears, reproduced from previous work by Adrian Likins and Jeff Trefftz",
"Carol Spears", "2006") "Carol Spears", "2006")
# We don't build a GParamSpec ourselves because passing it
# around is apparently broken in Python. Hence this trick. procedure.add_enum_argument ("run-mode", _("Run mode"),
# See pygobject#227 _("The run mode"), Gimp.RunMode,
procedure.add_argument_from_property(self, "run-mode") Gimp.RunMode.NONINTERACTIVE,
procedure.add_argument_from_property(self, "palette") GObject.ParamFlags.READWRITE)
procedure.add_return_value_from_property(self, "new-gradient") procedure.add_palette_argument ("palette", _("_Palette"),
_("Palette"),
GObject.ParamFlags.READWRITE)
procedure.add_gradient_return_value ("new-gradient", _("The newly created gradient"),
_("The newly created gradient"),
GObject.ParamFlags.READWRITE)
procedure.add_menu_path ('<Palettes>/Palettes Menu') procedure.add_menu_path ('<Palettes>/Palettes Menu')

View File

@ -480,10 +480,15 @@ class SelectionShape(Shape):
return x + dist * cos(perpendicular), y + dist * sin(perpendicular) return x + dist * cos(perpendicular), y + dist * sin(perpendicular)
shapes = [ shapes = {
CircleShape(), RackShape(), FrameShape(), SelectionShape(), "circle": CircleShape(),
PolygonShape(), SineShape(), BumpShape() "rack": RackShape(),
] "frame": FrameShape(),
"selection": SelectionShape(),
"polygon-star": PolygonShape(),
"sine": SineShape(),
"bumps": BumpShape()
}
### Tools ### Tools
@ -651,16 +656,18 @@ class SaveToPathTool():
control_points, False) control_points, False)
tools = [ tools = {
PreviewTool(), "preview": PreviewTool(),
StrokePaintTool(_("PaintBrush"), "gimp-paintbrush"), "paintbrush": StrokePaintTool(_("PaintBrush"), "gimp-paintbrush"),
PencilTool(), AirBrushTool(), StrokeTool(), "penciltool": PencilTool(),
StrokePaintTool(_("Ink"), 'gimp-ink'), "airbrush": AirBrushTool(),
StrokePaintTool(_("MyPaintBrush"), 'gimp-mybrush') "stroke": StrokeTool(),
"ink": StrokePaintTool(_("Ink"), 'gimp-ink'),
"mypaintbrush": StrokePaintTool(_("MyPaintBrush"), 'gimp-mybrush')
# Clone does not work properly when an image is not set. When that happens, drawing fails, and # Clone does not work properly when an image is not set. When that happens, drawing fails, and
# I am unable to catch the error. This causes the plugin to crash, and subsequent problems with undo. # I am unable to catch the error. This causes the plugin to crash, and subsequent problems with undo.
# StrokePaintTool("Clone", 'gimp-clone', False) # StrokePaintTool("Clone", 'gimp-clone', False)
] }
class PatternParameters: class PatternParameters:
@ -671,7 +678,7 @@ class PatternParameters:
""" """
def __init__(self): def __init__(self):
if not hasattr(self, 'curve_type'): if not hasattr(self, 'curve_type'):
self.curve_type = 0 self.curve_type = "spyrograph"
# Pattern # Pattern
if not hasattr(self, 'pattern_notation'): if not hasattr(self, 'pattern_notation'):
@ -710,7 +717,7 @@ class PatternParameters:
# Shape # Shape
if not hasattr(self, 'shape_index'): if not hasattr(self, 'shape_index'):
self.shape_index = 0 # Index in the shapes array self.shape_index = "circle" # Index in the shapes array
if not hasattr(self, 'sides'): if not hasattr(self, 'sides'):
self.sides = 5 self.sides = 5
if not hasattr(self, 'morph'): if not hasattr(self, 'morph'):
@ -725,7 +732,7 @@ class PatternParameters:
# Drawing style # Drawing style
if not hasattr(self, 'tool_index'): if not hasattr(self, 'tool_index'):
self.tool_index = 0 # Index in the tools array. self.tool_index = "preview" # Index in the tools array.
if not hasattr(self, 'long_gradient'): if not hasattr(self, 'long_gradient'):
self.long_gradient = False self.long_gradient = False
@ -1029,7 +1036,12 @@ class LissaCurveType:
return False return False
curve_types = [SpyroCurveType(), EpitrochoidCurvetype(), SineCurveType(), LissaCurveType()] curve_types = {
"spyrograph": SpyroCurveType(),
"epitrochoid": EpitrochoidCurvetype(),
"sine": SineCurveType(),
"lissajous": LissaCurveType()
}
# Drawing engine. Also implements drawing incrementally. # Drawing engine. Also implements drawing incrementally.
# We don't draw the entire stroke, because it could take several seconds, # We don't draw the entire stroke, because it could take several seconds,
@ -1434,10 +1446,14 @@ class SpyroWindow():
myscale.spin.set_width_chars(6) myscale.spin.set_width_chars(6)
return adj, myscale return adj, myscale
def set_combo_in_table(txt_list, table, row, callback): def set_combo_in_table(txt_list, is_dictionary, table, row, callback):
combo = Gtk.ComboBoxText.new() combo = Gtk.ComboBoxText.new()
for txt in txt_list: if (is_dictionary == False):
combo.append_text(_(txt)) for txt in txt_list:
combo.append_text(_(txt))
else:
for key in txt_list:
combo.append (key, txt_list[key].name)
combo.set_halign(Gtk.Align.FILL) combo.set_halign(Gtk.Align.FILL)
table.attach(combo, 1, row, 1, 1) table.attach(combo, 1, row, 1, 1)
@ -1455,14 +1471,14 @@ class SpyroWindow():
row = 0 row = 0
label_in_table(_("Curve Type"), table, row, label_in_table(_("Curve Type"), table, row,
_("An Epitrochoid pattern is when the moving gear is on the outside of the fixed gear.")) _("An Epitrochoid pattern is when the moving gear is on the outside of the fixed gear."))
self.curve_type_combo = set_combo_in_table([ct.name for ct in curve_types], table, row, self.curve_type_combo = set_combo_in_table(curve_types, True, table, row,
self.curve_type_changed) self.curve_type_changed)
row += 1 row += 1
label_in_table(_("Tool"), table, row, label_in_table(_("Tool"), table, row,
_("The tool with which to draw the pattern. " _("The tool with which to draw the pattern. "
"The Preview tool just draws quickly.")) "The Preview tool just draws quickly."))
self.tool_combo = set_combo_in_table([tool.name for tool in tools], table, row, self.tool_combo = set_combo_in_table(tools, True, table, row,
self.tool_combo_changed) self.tool_combo_changed)
self.long_gradient_checkbox = Gtk.CheckButton(label=_("Long Gradient")) self.long_gradient_checkbox = Gtk.CheckButton(label=_("Long Gradient"))
@ -1545,12 +1561,12 @@ class SpyroWindow():
row = 0 row = 0
label_in_table(_("Fixed Gear Teeth"), kit_table, row, fixed_gear_tooltip) label_in_table(_("Fixed Gear Teeth"), kit_table, row, fixed_gear_tooltip)
self.kit_outer_teeth_combo = set_combo_in_table([str(t) for t in ring_teeth], kit_table, row, self.kit_outer_teeth_combo = set_combo_in_table([str(t) for t in ring_teeth], False, kit_table, row,
self.kit_outer_teeth_combo_changed) self.kit_outer_teeth_combo_changed)
row += 1 row += 1
label_in_table(_("Moving Gear Teeth"), kit_table, row, moving_gear_tooltip) label_in_table(_("Moving Gear Teeth"), kit_table, row, moving_gear_tooltip)
self.kit_inner_teeth_combo = set_combo_in_table([str(t) for t in wheel_teeth], kit_table, row, self.kit_inner_teeth_combo = set_combo_in_table([str(t) for t in wheel_teeth], False, kit_table, row,
self.kit_inner_teeth_combo_changed) self.kit_inner_teeth_combo_changed)
row += 1 row += 1
@ -1667,7 +1683,7 @@ class SpyroWindow():
"Frame hugs the boundaries of the rectangular selection, " "Frame hugs the boundaries of the rectangular selection, "
"use hole=100 in Gear notation to touch boundary. " "use hole=100 in Gear notation to touch boundary. "
"Selection will hug boundaries of current selection - try something non-rectangular.")) "Selection will hug boundaries of current selection - try something non-rectangular."))
self.shape_combo = set_combo_in_table([shape.name for shape in shapes], table, row, self.shape_combo = set_combo_in_table(shapes, True, table, row,
self.shape_combo_changed) self.shape_combo_changed)
row += 1 row += 1
@ -1733,7 +1749,7 @@ class SpyroWindow():
row = 0 row = 0
label_in_table(_("Save"), table, row, label_in_table(_("Save"), table, row,
_("Choose whether to save as new layer, redraw on last active layer, or save to path")) _("Choose whether to save as new layer, redraw on last active layer, or save to path"))
self.save_option_combo = set_combo_in_table(save_options, table, row, self.save_option_combo = set_combo_in_table(save_options, False, table, row,
self.save_option_changed) self.save_option_changed)
self.save_option_combo.show() self.save_option_combo.show()
@ -1918,7 +1934,7 @@ class SpyroWindow():
def update_view(self): def update_view(self):
""" Update the UI to reflect the values in the Pattern Parameters. """ """ Update the UI to reflect the values in the Pattern Parameters. """
self.curve_type_combo.set_active(self.p.curve_type) self.curve_type_combo.set_active_id(self.p.curve_type)
self.curve_type_side_effects() self.curve_type_side_effects()
self.pattern_notebook.set_current_page(pattern_notation_page[self.p.pattern_notation]) self.pattern_notebook.set_current_page(pattern_notation_page[self.p.pattern_notation])
@ -1941,7 +1957,7 @@ class SpyroWindow():
self.doughnut.set_width(self.p.doughnut_width) self.doughnut.set_width(self.p.doughnut_width)
self.petals_changed_side_effects() self.petals_changed_side_effects()
self.shape_combo.set_active(self.p.shape_index) self.shape_combo.set_active_id(self.p.shape_index)
self.shape_combo_side_effects() self.shape_combo_side_effects()
self.sides_adj.set_value(self.p.sides) self.sides_adj.set_value(self.p.sides)
self.morph_adj.set_value(self.p.morph) self.morph_adj.set_value(self.p.morph)
@ -1949,7 +1965,7 @@ class SpyroWindow():
self.shape_rotation_adj.set_value(self.p.shape_rotation) self.shape_rotation_adj.set_value(self.p.shape_rotation)
self.margin_adj.set_value(self.p.margin_pixels) self.margin_adj.set_value(self.p.margin_pixels)
self.tool_combo.set_active(self.p.tool_index) self.tool_combo.set_active_id(self.p.tool_index)
self.long_gradient_checkbox.set_active(self.p.long_gradient) self.long_gradient_checkbox.set_active(self.p.long_gradient)
self.save_option_combo.set_active(self.p.save_option) self.save_option_combo.set_active(self.p.save_option)
@ -1987,7 +2003,7 @@ class SpyroWindow():
self.doughnut_width_myscale.set_sensitive(False) self.doughnut_width_myscale.set_sensitive(False)
def curve_type_changed(self, val): def curve_type_changed(self, val):
self.p.curve_type = val.get_active() self.p.curve_type = val.get_active_id()
self.curve_type_side_effects() self.curve_type_side_effects()
self.redraw() self.redraw()
@ -2086,7 +2102,7 @@ class SpyroWindow():
self.equal_w_h_checkbox.set_sensitive(shapes[self.p.shape_index].can_equal_w_h()) self.equal_w_h_checkbox.set_sensitive(shapes[self.p.shape_index].can_equal_w_h())
def shape_combo_changed(self, val): def shape_combo_changed(self, val):
self.p.shape_index = val.get_active() self.p.shape_index = val.get_active_id()
self.shape_combo_side_effects() self.shape_combo_side_effects()
self.redraw() self.redraw()
@ -2116,7 +2132,7 @@ class SpyroWindow():
self.long_gradient_checkbox.set_sensitive(tools[self.p.tool_index].can_color) self.long_gradient_checkbox.set_sensitive(tools[self.p.tool_index].can_color)
def tool_combo_changed(self, val): def tool_combo_changed(self, val):
self.p.tool_index = val.get_active() self.p.tool_index = val.get_active_id()
self.tool_changed_side_effects() self.tool_changed_side_effects()
self.redraw() self.redraw()
@ -2204,80 +2220,6 @@ class SpyroWindow():
class SpyrogimpPlusPlugin(Gimp.PlugIn): class SpyrogimpPlusPlugin(Gimp.PlugIn):
## Parameters ##
__gproperties__ = {
"curve-type" : (int,
_("The curve type { Spyrograph (0), Epitrochoid (1), Sine (2), Lissajous(3) }"),
_("The curve type { Spyrograph (0), Epitrochoid (1), Sine (2), Lissajous(3) }"),
0, 3, 0,
GObject.ParamFlags.READWRITE),
"shape": (int,
_("Shape of fixed gear"),
_("Shape of fixed gear"),
0, GLib.MAXINT, 0,
GObject.ParamFlags.READWRITE),
"sides": (int,
_("Number of sides of fixed gear (3 or greater). Only used by some shapes."),
_("Number of sides of fixed gear (3 or greater). Only used by some shapes."),
3, GLib.MAXINT, 3,
GObject.ParamFlags.READWRITE),
"morph": (float,
_("Morph shape of fixed gear, between 0 and 1. Only used by some shapes."),
_("Morph shape of fixed gear, between 0 and 1. Only used by some shapes."),
0.0, 1.0, 0.0,
GObject.ParamFlags.READWRITE),
"fixed-teeth": (int,
_("Number of teeth for fixed gear"),
_("Number of teeth for fixed gear"),
0, GLib.MAXINT, 96,
GObject.ParamFlags.READWRITE),
"moving-teeth": (int,
_("Number of teeth for moving gear"),
_("Number of teeth for moving gear"),
0, GLib.MAXINT, 36,
GObject.ParamFlags.READWRITE),
"hole-percent": (float,
_("Location of hole in moving gear in percent, where 100 means that "
"the hole is at the edge of the gear, and 0 means the hole is at the center"),
_("Location of hole in moving gear in percent, where 100 means that "
"the hole is at the edge of the gear, and 0 means the hole is at the center"),
0.0, 100.0, 100.0,
GObject.ParamFlags.READWRITE),
"margin": (int,
_("Margin from selection, in pixels"),
_("Margin from selection, in pixels"),
0, GLib.MAXINT, 0,
GObject.ParamFlags.READWRITE),
"equal-w-h": (bool,
_("Make height and width equal"),
_("Make height and width equal"),
False,
GObject.ParamFlags.READWRITE),
"pattern-rotation": (float,
_("Pattern rotation, in degrees"),
_("Pattern rotation, in degrees"),
-360.0, 360.0, 0.0,
GObject.ParamFlags.READWRITE),
"shape-rotation": (float,
_("Shape rotation of fixed gear, in degrees"),
_("Shape rotation of fixed gear, in degrees"),
-360.0, 360.0, 0.0,
GObject.ParamFlags.READWRITE),
"tool": (int,
_("Tool to use for drawing the pattern."),
_("Tool to use for drawing the pattern."),
0, GLib.MAXINT, 1,
GObject.ParamFlags.READWRITE),
"long-gradient" : (bool,
_("Whether to apply a long gradient to match the length of the pattern. "
"Only applicable to some of the tools."),
_("Whether to apply a long gradient to match the length of the pattern. "
"Only applicable to some of the tools."),
False,
GObject.ParamFlags.READWRITE),
}
## GimpPlugIn virtual methods ## ## GimpPlugIn virtual methods ##
def do_set_i18n(self, procname): def do_set_i18n(self, procname):
return True, 'gimp30-python', None return True, 'gimp30-python', None
@ -2302,19 +2244,67 @@ class SpyrogimpPlusPlugin(Gimp.PlugIn):
"2018") "2018")
procedure.add_menu_path ("<Image>/Filters/Render/") procedure.add_menu_path ("<Image>/Filters/Render/")
procedure.add_argument_from_property(self, "curve-type") curve_choice = Gimp.Choice.new()
procedure.add_argument_from_property(self, "shape") curve_choice.add("spyrograph", 0, _("Spyrograph"), "")
procedure.add_argument_from_property(self, "sides") curve_choice.add("epitrochoid", 1, _("Epitrochoid"), "")
procedure.add_argument_from_property(self, "morph") curve_choice.add("sine", 2, _("Sine"), "")
procedure.add_argument_from_property(self, "fixed-teeth") curve_choice.add("lissajous", 3, _("Lissajous"), "")
procedure.add_argument_from_property(self, "moving-teeth") procedure.add_choice_argument ("curve-type", _("Curve Type"), _("Curve Type"),
procedure.add_argument_from_property(self, "hole_percent") curve_choice, "spyrograph", GObject.ParamFlags.READWRITE)
procedure.add_argument_from_property(self, "margin") shape_choice = Gimp.Choice.new()
procedure.add_argument_from_property(self, "equal-w-h") shape_choice.add("circle", 0, _("Circle"), "")
procedure.add_argument_from_property(self, "pattern-rotation") shape_choice.add("rack", 1, _("rack"), "")
procedure.add_argument_from_property(self, "shape-rotation") shape_choice.add("frame", 2, _("frame"), "")
procedure.add_argument_from_property(self, "tool") shape_choice.add("selection", 3, _("Selection"), "")
procedure.add_argument_from_property(self, "long-gradient") shape_choice.add("polygon-star", 4, _("Polygon-Star"), "")
shape_choice.add("sine", 5, _("Sine"), "")
shape_choice.add("bumps", 6, _("Bumps"), "")
procedure.add_choice_argument ("shape", _("Shape"), _("Shape"),
shape_choice, "circle", GObject.ParamFlags.READWRITE)
procedure.add_int_argument ("sides", _("Si_des"),
_("Number of sides of fixed gear (3 or greater). Only used by some shapes."),
3, GLib.MAXINT, 3, GObject.ParamFlags.READWRITE)
procedure.add_double_argument ("morph", _("_Morph"),
_("Morph shape of fixed gear, between 0 and 1. Only used by some shapes."),
0.0, 1.0, 0.0, GObject.ParamFlags.READWRITE)
procedure.add_int_argument ("fixed-teeth", _("Fi_xed Gear Teeth"),
_("Number of teeth for fixed gear."),
0, GLib.MAXINT, 96, GObject.ParamFlags.READWRITE)
procedure.add_int_argument ("moving-teeth", _("Mo_ving Gear Teeth"),
_("Number of teeth for fixed gear."),
0, GLib.MAXINT, 36, GObject.ParamFlags.READWRITE)
procedure.add_double_argument ("hole_percent", _("_Hole Radius (%)"),
_("Location of hole in moving gear in percent, where 100 means that "
"the hole is at the edge of the gear, and 0 means the hole is at the center"),
0.0, 100.0, 100.0, GObject.ParamFlags.READWRITE)
procedure.add_int_argument ("margin", _("Margin (_px)"),
_("Margin from selection, in pixels"),
0, GLib.MAXINT, 0, GObject.ParamFlags.READWRITE)
procedure.add_boolean_argument ("equal-w-h", _("Make width and height equal"),
_("Make width and height equal"),
False, GObject.ParamFlags.READWRITE)
procedure.add_double_argument ("pattern-rotation", _("_Rotation"),
_("Pattern rotation, in degrees"),
-360.0, 360.0, 0.0, GObject.ParamFlags.READWRITE)
procedure.add_double_argument ("shape-rotation", _("_Rotation"),
_("Shape rotation of fixed gear, in degrees"),
-360.0, 360.0, 0.0, GObject.ParamFlags.READWRITE)
tool_choice = Gimp.Choice.new()
tool_choice.add("preview", 0, _("Preview"), "")
tool_choice.add("paintbrush", 1, _("PaintBrush"), "")
tool_choice.add("pencil", 2, _("Pencil"), "")
tool_choice.add("airbrush", 3, _("AirBrush"), "")
tool_choice.add("stroke", 4, _("Stroke"), "")
tool_choice.add("ink", 5, _("Ink"), "")
tool_choice.add("mypaintbrush", 6, _("MyPaintBrush"), "")
#TODO: Add Clone option once it's fixed
procedure.add_choice_argument ("tool", _("Tool"), _("Tool"),
tool_choice, "preview", GObject.ParamFlags.READWRITE)
procedure.add_boolean_argument ("long-gradient",
_("Long _Gradient"),
_("Whether to apply a long gradient to match the length of the pattern. "
"Only applicable to some of the tools."),
False, GObject.ParamFlags.READWRITE)
return procedure return procedure

View File

@ -26,6 +26,8 @@ from gi.repository import Gio
import time import time
import sys import sys
def N_(message): return message
def _(message): return GLib.dgettext(None, message)
''' '''
A Python plugin. A Python plugin.
@ -126,25 +128,6 @@ def test_dialog(procedure, run_mode, image, n_drawables, drawables, config, data
class TestDialogPlugin (Gimp.PlugIn): class TestDialogPlugin (Gimp.PlugIn):
## Parameters ##
# See comments about this in foggify.py, from which we borrowed
brush = GObject.Property(type = Gimp.Brush,
nick = "_Brush",
blurb = "Brush")
font = GObject.Property(type = Gimp.Font,
nick = "_Font",
blurb = "Font")
gradient = GObject.Property(type = Gimp.Gradient,
nick = "_Gradient",
blurb = "Gradient")
palette = GObject.Property(type = Gimp.Palette,
nick = "_Palette",
blurb = "Palette")
pattern = GObject.Property(type = Gimp.Pattern,
nick = "Pa_ttern",
blurb = "Pattern")
# FUTURE all other Gimp classes that have GimpParamSpecs # FUTURE all other Gimp classes that have GimpParamSpecs
## GimpPlugIn virtual methods ## ## GimpPlugIn virtual methods ##
@ -169,11 +152,19 @@ class TestDialogPlugin (Gimp.PlugIn):
# Top level menu "Test" # Top level menu "Test"
procedure.add_menu_path ("<Image>/Filters/Development/Demos") procedure.add_menu_path ("<Image>/Filters/Development/Demos")
procedure.add_argument_from_property(self, "brush") procedure.add_brush_argument ("brush", _("_Brush"), _("Brush"),
procedure.add_argument_from_property(self, "font") GObject.ParamFlags.READWRITE)
procedure.add_argument_from_property(self, "gradient") procedure.add_font_argument ("font", _("_Font"), _("Font"),
procedure.add_argument_from_property(self, "palette") GObject.ParamFlags.READWRITE)
procedure.add_argument_from_property(self, "pattern") procedure.add_gradient_argument ("gradient", _("_Gradient"),
_("Gradient"),
GObject.ParamFlags.READWRITE)
procedure.add_palette_argument ("palette", _("_Palette"),
_("Palette"),
GObject.ParamFlags.READWRITE)
procedure.add_pattern_argument ("pattern", _("Pa_ttern"),
_("Pattern"),
GObject.ParamFlags.READWRITE)
return procedure return procedure