In a previous blog posting I rambled on about how plugins need to be easier, both for users and developers. I haven’t had a lot of time lately to work on Paint.NET, but I have managed to get started on a new system for developing effect plugins that provide configuration UI for the user. These types of plugins are the most popular: you click on them in the Effects menu and it pops up a dialog with sliders and buttons and whatnot which lets you configure properties that determine how the effect is rendered.
The problem with developing these configuration dialogs is that they are extremely tiresome to write. You can write rendering code for a simple plugin very quickly using CodeLab, but you are limited to a “1, 2, or 3 amount sliders” configuration dialog. If you need 4 sliders, then you have to write a brand new dialog from scratch complete with layout and data binding. It’s easy to get the implementation wrong, or to at least skirt the line of what constitutes a “correct” implementation. My experience has been that if it’s possible to do things “the wrong way,” then your framework needs to be changed: it should only ever be possible to do things the right way, or at least make it extremely obvious when you’re breaking the rules. Right now that distinction isn’t really clear.
I have been working on a new system that will allow plugin developers to easily get intricate configuration dialogs from just a description of the properties that govern rendering. For example, adding this code in an Effect:
protected override PropertyCollection CreatePropertyCollection()
{
List<Property> props = new List<Property>();
props.Add(new Int32Property(PropertyNames.Factor, 1, 1, 10));
props.Add(new DoubleProperty(PropertyNames.Zoom, 10, 0, 100));
props.Add(new AngleProperty(PropertyNames.Angle));
props.Add(new DoubleVectorProperty(
PropertyNames.Offset,
Pair.MakePair(0.0, 0.0),
Pair.MakePair(-1.0, -1.0),
Pair.MakePair(1.0, 1.0)));
props.Add(new Int32Property(PropertyNames.Quality, 2, 1, 4));
props.Add(new BooleanProperty(PropertyNames.InvertColors));
return new PropertyCollection(props, new PropertyCollectionRule[0]);
}
… generates this type of dialog:
(click for full-size)
All of the layout and data binding is handled automatically, making the plugin author’s life much, much easier. The dialog is resizable, and if there are too many properties to fit on-screen it will automatically provide a scrollbar. The UI itself is still rough draft: the “offset” is still just two sliders right now, for instance, and needs something akin to what we have in the Rotate/Zoom dialog. This system and the UI generation should only improve with time. Eventually I want to have the Rotate/Zoom, Curves, and even Levels configuration dialogs written using this. So far I have an enhanced version of Frosted Glass using this, and have re-done the UI for Clouds up to feature parity with v3.10.
But the great thing about being able to easily get this UI is that it is also very easy to change it. What if you want to change the ordering? Add a property? Remove two properties? It’s easy. Just change the code in your CreatePropertyCollection() function.
Once this system is mostly finished for Effect development, I will also be extending it to the UI generation for file type plugins. This will allow me to provide rich configuration for things like HDPhoto, but without having to write a lot of the complicated logic that governs its data binding and property value dependencies (“property Z may only be configured if property M is enabled” … barf).
The other thing some of you may have picked up on is that the code above could easily be auto-generated from, for instance, an XML description of the same properties. This system is being designed to make code generation scenarios simple to implement, such as for CodeLab.
Lastly, once the system is well understood, I will rewrite the “Colors” floater window using the same UI generation and property system. That thing is about 5,000 lines of code and is very fragile. It has grown organically since 2004 and is in very sad shape. It works, but only because it has been thoroughly debugged. I much prefer code that works because it was meant to work (i.o.w. it works by design, not by accident).
Will the old API stay forever, or will it eventually be removed?
Pi, the intent is not to remove the old API, but to simply encourage people to use the new one. The new stuff builds on top of the old API and is essentially a large collection of helper classes. There isn’t really a compelling reason to remove the old API, as that would break compatibility with most plugins. Eventually there may be a brand new API for plugins at which point I will ensure that the old API still works, but is marked [Obsolete] so that no new plugins can be written using it.
Is there a possibility that you will eventually make the gradient feature able to support more than two colors like the gradient in Photoshop? And, is there any thought to adding a color scheming feature to it? Something enabling a person to work with swatches like the Kuler app allows? That would be very cool.
Thanks.
Heh, I’m sure there’s a billion features that could be added, B 🙂
I do have one request, though. When you change some of the toolbar options for a tool, then you exit PDN and start it up again, it’s “forgotten” what you set the setting to.
For example, I use the magic wand tool a *lot* but I’m always setting the “tolorence” down to about 10% or so. It’d be great if PDN was simply able to “remember” that and not reset it back to 50% whenever it starts back up!
Hey Dean, if you click on the Tool button in the toolbar (far left, 2nd row) and then click “Choose Defaults”, then you can tell Paint.NET what you want the startup defaults to be.
This was chosen as a way to do things in order to balance folks who want Paint.NET to remember settings, and folks who were accidentally clicking certain settings but who did not mean for Paint.NET to remember them. For instance, I got lots of people asking why the rendering was so bad, when in fact they had inadvertently disabled anti-aliasing and/or alpha blending.
Wow, I never noticed that, cool 🙂
Rick
My dream is that Paint.Net get a “PlugIns” dialog like the “Firefox Add-ons dialog”, when you can install, uninstall, configure, disable or update the add-ons.
This will increase the popularity of the plugins, because will easy perform the above operations directly on Paint.Net.
Click,
If you read back to an earlier blog post, he mentions something about this:
https://blog.getpaint.net/2007/06/01/what%e2%80%99s-next-for-paintnet/
in the section entitled ‘3.Next’
Excellent!