Fidgeting Widgets at the Emerald Sprint
Improving widgets for Dexterity
Take a look at David Glick's great sprint wrapup to get an idea of everything that happened at last weekend's Emerald Sprint. This is just a report on my little piece of it.
I wanted to work on widgets at the sprint for a couple of reasons:
- Enhancing the Dexterity widgets is a key part of achieving feature parity with Archetypes, which we need to bring over the next set of developers;
- My knowledge of z3c.form widgets was at a surface level, and I wanted to get better with them.
My entry point for this was to try and polish up the Choice and Multi-Choice field widgets. I've always liked the Archetypes feature that lets you choose whether you wish to use an HTML select box or checkboxes/radio buttons for choice fields. I also like the "auto" feature where Archetypes will automatically choose a select box if you've a large number of choices, but use checkboxes or radio buttons for smaller numbers.
Adapting the Widgets
Dexterity uses z3c.form for its form library and zope.schema to represent the fields. z3c.form fields are themselves schema-based. zope.schema fields are used to describe all the attributes of the field widgets.
Dexterity exposes only a small fraction of those attributes in the schema editor. You may get at the rest by editing the supermodel XML or via Python. But we really don't need — or want — to present the through-the-Plone user of Dexterity with options to set most of the widget attributes. So, the Dexterity schema editor offers editing for only the most useful attributes.
Up until recently, there wasn't a good way to add to the list of widget attributes or the set that Dexterity exposes. Fortunately, our super sprint master, David Glick, had anticipated this need and has created experimental branches of plone.schemaeditor and plone.autoform to support adding and exposing widget attributes via adapters.
I've added to the 4.3 coredev a configuration file that pulls in David's branches as well as the branch of plone.app.z3cform where I was working on the choice widgets. Eventually, this will all be merged into the master branches for the packages.
The basics aren't too conceptually hard. To add and or expose widget attributes, you:
- Build an interface class that subclasses the main version of the widget;
- Provide a field widget factory for the Plone layer that will use your interface;
- Provide an export/import handler that does the serialization of your widget attribute to and from supermodel.
The implementation is much harder, but David has provided classes that do all the work. You only need to subclass them and wire them in with ZCML. That's all done with a very small number of lines of code.
Difficulty in the Details
My first few tries at this went poorly. I was picking the wrong widget interface classes to subclass, and the schema editor wasn't finding my adapted widgets. Planting break points where the adaptation takes place allowed me to find out which interfaces were actually in use.
Much more difficulty came from some oddities of the z3c.form choice widgets. It turns out that there's a clever bit of code that is used to dispatch all the various kinds of selection fields you might be using (for example, using some query mechanism to provide values) to the widgets. This one drove me nuts and required at least an hour of David's time to track down. Most types of widgets should be much easier.
And … it's not done yet. That dispatcher also undermined my ability to subclass the choice widget. I'm pretty sure I've got a solution that I mean to deploy in the next couple of days.
Brought to you by …
See David's blog entry for a list of the sprint sponsors and participants. It was a great environment for sprinting. As is often the case, I think you'll see the real accomplishments of the sprint over the coming year, rather than in the immediate commits. We did a lot of brainstorming (thanks, Alice Tseng!) about the way the Dexterity's UI should evolve that will have its real payoff going forward.