I like the design you suggest, although I'd like to contribute a couple of ideas and questions (yes, questions
are contributions):
* The external interface is relatively simple. It reduces to adding a unique String parameter to Script. A formal description for this parameter would be:
[...]
Note that the above description fits strictly within JavaScript syntax.
Good. As for the actual implementation, if I were you, I would choose JSON without a doubt. So we have a Script process with two read-only properties: .parameters (JSON, XML or whatever) and .codeText (UTF8 text), right?
[Internal interface]
- During execution, a script has access to several read-only properties of a special JavaScript object. As you probably figure out at this point, that properties are just the result of interpreting and executing Script::parameters as JavaScript code.
...by "eval"ing JSON
.
But, as I understand it, when the user runs the code, Script.parameters is still empty (the Script instance needs to be created
after the code ends execution, so that the user could have had a chance to configure it, via the usual configuration dialog), hence during execution of the script we don't know what the properties of the Parameters object are.
Thus, creating a Script instance directly from the editor window ("dragging the small blue triangle to the desktop area") wouldn't make much sense, since that would create a Settings process with an empty .parameters property (the script hasn't been run), and upon dragging that instance onto an image (i.e. execute it), the script's configuration dialog would configure that instance, but somehow that data should make its way to the Script icon that lies on the desktop. Is that an OO violation?
EXCEPT that users were expected to define a special function (e.g. "CONFIGURE") that did the usual configuration work (show a dialog or whatever) and returned a data structure. Then PJSR would gain a good share of freedom:
- when "dragging the triangle to the desktop", PJSR would be told to run that function (a dialog is shown), and we could have a full-blown Scripts object, already configured, ready to be applied to images (and to ImageContainers, yippie!). When applied, the Parameters object would have to be populated from Script.parameters (eval the JSON, or whatever).
- when running scripts from the editor, PJSR could set up the Parameters object from the data returned from CONFIGURE, and then would run the script as usual. The script would NOT need to call CONFIGURE.
(I have a little idea regarding the Settings object, but is offtopic in this discussion - feel free to ask though!).
// Send parameters and values to Core.
this.broadcast = function()
Since "broadcast" is a detail about how things work in PI Core, and users don't need to know anything about it, I would call this method "put" or something like that.
Object Parameters.get( String id )
Acquires the specified parameter id and returns its value, if it exists, or undefined otherwise.
I was going to suggest that the .has method isn't actually needed, since we could do (pseudocode):
foreach param ('radius', 'lineWidth', 'helloText') {
value = Parameters.get (param);
if (undef == value) { next; }
this[param] = value;
}
But this breaks when a parameter exists and is undefined, since this code would treat this case as if the parameter didn't exist at all. Your .get is broken in the same way, the code that calls your .get and gets an undef, would interpret it as if the parameter didn't exist. I thing .get should throw an exception when asked for an non-existing parameter. OTOH, making a .get die seems quite radical to me, but that's what .has is for. Maybe a big red warning in the documentation could suffice. Or maybe the whole notion of "parameter having an undefined value" makes no sense at all.
Summary:
function CONFIGURE
{
// obtain values from the usual configuration dialog, or whatever. Store them in this.
// give data back to PJSR, which would set up Parameters
return this;
}
function main()
{
// directly use parameters:
var diameter = Parameters.radius * 2 * PI;
// ...
}
No MyParameters.retrieve, since the configuration values are class properties, readily visible in Parameters (read-only). No .broadcast either, given that that work is already done.
I can try to implement this for the upcoming version 1.5.8, or postpone it for 1.6, depending on the difficulties that I find, but this definitely has to be done. What do you think?
You know,
release early, release often!
(although I must admit, to my embarrasment, that I don't follow that...). I guess, though, that my suggestions are quite big a change, and would need to wait 1.6 - they break compatibility. PJSR could search for a function "CONFIGURE" and, depending on its existence, could behave as it does now or enable the new functionality. Then, in PI 1.7 or 1.8, support for old scripts could be dropped.
I guess PI 2.0 will never see the light, it's one of those big projects that you can't give an overhaul big enough to warrant a major version bump. We'll have 1.10 instead
.