Re: [Gimp-developer] PF_ENUM, SF_ENUM, dynamically defined enums for plugins

2022-08-15 Thread Jehan Pagès via gimp-developer-list
Hi all!

On Mon, Aug 15, 2022 at 12:25 AM Ofnuts via gimp-developer-list <
gimp-developer-list@gnome.org> wrote:

> I'm not convinced this needs to be an enum. The basic problem it to
> show  a list of strings, and return the index of the selected one.  The
> contents of the list can be quite dynamic. As far as I can tell, in 2.10
> they aren't cached in pluginrc. In 3.0, the query/init methods of the
> plugin suggest that things can be dynamic and a list of URLs/devices
> could be created during registration (this could also change if the user
> changes the UI language, and only the plugin would know how to retrieve
> the translations...).  How the returned integer is used is left to the
> imagination of the author.
>

I discussed the topic of enum-type arguments in the MR opened by Lloyd:
https://gitlab.gnome.org/GNOME/gimp/-/merge_requests/709

Feel free to read the discussion, though I'll also try to re-explain it
here.

As a first disclaimer, I will discuss this with C code because I am
personally not interested into script-fu-only specifics, neither into any
language-specifics. This includes C itself (i.e. I don't care about
solutions which work only on C either), but C is our base language, which
is why it's our generic language here.
We used to have many bindings in many languages, most of them (but
script-fu) are now dead (development-wise) because they focused on logic
specific to the language (which is great and for sure has a lot of
advantages, don't get me wrong, but also means a lot more continuous
maintenance).

>
> So, IMHO, this is more like a variant of regular integer, instead of
> showing a slider you display  a list of labels.
>

This is actually the current state of things currently in GIMP 2.99/3.0.

When we want a list of options (a.k.a. enum-like type) as argument, we
declare it as an int argument. And we list the values in the docs string:

  GIMP_PROC_ARG_INT (procedure, "preset",
 _("Source _type"),
 _("WebP encoder preset (Default=0, Picture=1,
Photo=2, Drawing=3, "
   "Icon=4, Text=5)"),
 0, 5, WEBP_PRESET_DEFAULT,
 G_PARAM_READWRITE);

On API/plug-in/script programmer side, it's ugly because it means that
people rely on meaningless integers and always have to refer to docs to
re-read existing code. Also it means if we forget to update the docs, the
possible values might be incomplete. Worse, for some procedure, the number
of options is so huge, we currently don't list them in the string docs.
This is the case of "pixel-format" in plug-ins/common/file-raw-data.c which
has 19 possible values. So I didn't even bother writing the docs, though
it's also because I was planning for better system to declare list of
options.

On GUI side though, we don't have such a problem because we have the API to
easily map int values to individual string items:

  /* Create the combobox containing the presets */
  store = gimp_int_store_new ("Default", WEBP_PRESET_DEFAULT,
  "Picture", WEBP_PRESET_PICTURE,
  "Photo",   WEBP_PRESET_PHOTO,
  "Drawing", WEBP_PRESET_DRAWING,
  "Icon",WEBP_PRESET_ICON,
  "Text",WEBP_PRESET_TEXT,
  NULL);
  gimp_procedure_dialog_get_int_combo (GIMP_PROCEDURE_DIALOG (dialog),
   "preset", GIMP_INT_STORE (store));

So my initial idea was to move this "store" list (but it will have to be
another type, not depending on GTK) into the declaration part of plug-ins.
This way, at least the problem of documenting the values and even managing
errors (non-supported values) is no more.
Then we would not have to maintain a huge docs for the arg (but smaller doc
strings for each values) and we can generate better docs for such
arguments. Though we would still have to deal with integer on caller side.
It would be better with semantic values.

An alternative could be to use string arguments (also associated to a
limited given list of allowed values on callee side), this would bring
semantic, using for instance "picture" as arg rather than whatever int
value is WEBP_PRESET_PICTURE.

In any case, the best would be to have real enum types declared and usable
on caller side too, hence using the same type on both side, and that brings
some semantic to the API. It seemed to me that it was not possible to
generate enum types dynamically, but Lloyd seems to think it is thanks to
GTypeModule. So let's see how it goes. :-)

Jehan


> On 08/08/2022 14:42, Lloyd Konneker via gimp-developer-list wrote:
> > This is a continuation of a thread on this list:
> >
> https://mail.gnome.org/archives/gimp-developer-list/2022-July/msg00016.html
> .
> > The thread diverged to a discussion about future PF_OPTION implementation
> > in GIMP 3.
> >
> > Here are my preliminary 

Re: [Gimp-developer] PF_ENUM, SF_ENUM, dynamically defined enums for plugins

2022-08-15 Thread Lloyd Konneker via gimp-developer-list
Yes, the proposal seems to have been shot down already.  I don't think it
will work.

See a discussion https://gitlab.gnome.org/GNOME/gimp/-/merge_requests/709

I paraphrase here and might not be accurately describing things

The primary goal is to let plugin authors refer to enums symbolically, like
FooEnum.BarValue.

The current implementation is what I call "mock enums."
A plugin registers/declares an argument of type int with a formatted string
in the blurb of the GParamSpecInt.
Something like this "BarValue=0, ZedValue=1".
Then GimpProcedureDialog should (doesn't yet) show it properly as an int
combo box.
The PDBBrowser shows the blurb, so a reader can understand.
The problem is, other plugins (calling this plugin) can't refer to the enum
values symbolically.
The declaring plugin might be able to, but not other plugins.
The other plugs usually just hard-code integer literals like "1."
And if the declaring plugin changes the enum, using plugins might break.
Not a huge problem, since many plugins are never called by other plugins.

See also gimp#8495.

Also see pygobject#541.  An issue  at Gitlab PyGobject project where I ask
whether this proposal might ever work.

BTW, this thread is misnamed.  I am really talking about PF_OPTION and
SF-OPTION.
___
gimp-developer-list mailing list
List address:gimp-developer-list@gnome.org
List membership: https://mail.gnome.org/mailman/listinfo/gimp-developer-list
List archives:   https://mail.gnome.org/archives/gimp-developer-list


Re: [Gimp-developer] PF_ENUM, SF_ENUM, dynamically defined enums for plugins

2022-08-15 Thread Ofnuts via gimp-developer-list

Not really. With the current interface, I manage it that way:

I have these two functions:

def createOpts(name,pairs):
    optsclass=namedtuple(name+'Type',[symbol for symbol,label in 
pairs]+['labels','labelTuples'])

    opts=optsclass(*(
    range(len(pairs))
    +[[label for symbol,label in pairs]]
    +[[(label,i) for i,(symbol,label) in enumerate(pairs)]]
    ))
    return opts

def createValuedOpts(name,triplets):
    optsclass=namedtuple(name+'Type',[symbol for symbol,_,_ in 
triplets]+['labels','labelTuples','values'])

    opts=optsclass(*(
    range(len(triplets))
    +[[label for _,label,_ in triplets]]
    +[[(label,i) for i,(_,label,_) in enumerate(triplets)]]
    +[[value for _,_,value in triplets]]
    ))
    return opts

"createOpts" lets one define a namedtuple where members have the proper 
values, so for instance, after


GuidesShow=createOpts('GuidesShow',[('NO','No'),('YES','Yes')])

I can use "GuidesShow.NO" in the code and I don't really care if it was 
defined as 1 or 0.


"createValuedOpts" adds a "values" array which is indexed by the other 
members. "values" elements can be anything: integer/float constants,  
strings, but also functions/lambdas  so for instance I can define a 
bunch of conversions:


Units=createValuedOpts('Units',[
    ('MM',"Millimetres",lambda x: x/25.4),
    ('CM',"Centimetres",lambda x: x/2.54),
    ('INCH',"Inches",lambda x: x),
    ])

So later in the code, assuming "units" is the value of the corresponding 
parameter, converting whatever values to inches is just


inches=Units.values[units](input)

The "labels" member is also generated to be used in the registration:

optionsUnits=(PF_OPTION,'unit','Units', Units.MM, Units.labels)

Here also, I never have to worry about some behind-the-scenes integer 
value.




On 15/08/2022 02:52, Nathan Summers wrote:


Sounds like a nightmare for scripting if I'm understanding correctly.

Rockwalrus


___
gimp-developer-list mailing list
List address:gimp-developer-list@gnome.org
List membership: https://mail.gnome.org/mailman/listinfo/gimp-developer-list
List archives:   https://mail.gnome.org/archives/gimp-developer-list