Updated Item Renderer Contract

Closed: 1/26/09

Problem:

Currently, Gumbo exposes the designer/developer contract as a skinning contract between component and skin. Components can have component states, and define skin parts, the skin comes in later to provide these skin parts and additionally, can define their own skin states. However, there is another way to provide visuals for a component that is not covered by this very clear skinning contract. Another way to do this is through subclassing - a base class can define behavior, and derived classes can come in to provide new behavior as well as visuals. This is currently how item renderers work in Gumbo. ItemRenderer subclasses MXMLComponent to add in particular states needed by all item renderers. End users would subclass ItemRenderer to add in their own visuals, and any other behavior they desire. Currently, item renderers are the only example of this kind of "skinning" by way of subclassing in the SDK, however as users create custom components, this subclassing mechanism will become more prevalent. This subclassing mechanism is weird for the following reasons:

1. )This subclassing mechanism currently does not allow the clean definition of component states, visual states and skin parts the way the skinning contract does. For example, there's no metadata describing an item renderer's required states, whereas the skinning contract does.
2. ) The subclass feels a lot like a skin. To end users using Thermo, subclassing ItemRenderer vs. skinning a skinnable component is a negligible difference. To hand coders, this difference is not that negligible. They may expect the ability to define states (both for the component and for the visuals) even though they are subclassing.
3.) Certain cases arise where a component lives in the skinning and subclassing world. Imagine a user extending Panel, a skinnable component, to add in new component states and behavior that doesn't require a new skin. When the developer adds in new states or parts, how does the tool know whether this is a skin part/skin state as specified by the skinning contract, or a component state or part as defined by the subclassing mechanism?

How do we bridge this inconsistency between the sort of horizontal nature of skinning (a component exists and its associated with a skin, usually its peer) and the vertical nature of subclassing (a base class is extended and the derived class adds in visuals and custom behavior)?

Proposals:

There are several proposals:

Proposal 1: Eliminate areas where this can occur, like in the Panel example above.

Proposal 2: Extend the same metadata in use by the skinning contract (skinState, skinPart) to the subclassing case. If/when down the line we implement the multi-dimensional state solutions, this problem can be solved.

Proposal 3: Introduce different metadata for the subclassing state. Similar to skinState, skinPart, there can be derivedState, derivedPart and if an overlap of the two mechanisms occur, you can disambiguate by metadata. This makes tooling's life easier.

Proposal 4: Do nothing at this time. 

With either proposal 2 and 3, we need to introduce component lifecycle API's into the subclassing class hierarchy. Wow, there's finally a need for MXMLComponent, as MXMLComponent would be the ideal place to add these API's.

Open Questions:

Dynamic Parts: Do we want MXMLComponent to also allow creating dynamic visual parts? This would mean adding the createDynamicPartInstance(), removeDyanmicPartInstance(), numDynamicParts() and getDynamicPartAt() methods currently defined in SkinnableComponent. If we're going to let MXMLComponent play in the skinning contract world, we should theoretically allow for this functionality.

Omitted Required Parts: Right now if required skin parts are not found in a skinnable component's associated skin, helpful RTE's are thrown. We could do something similar in MXMLComponent for ease of use - say in the first commitProperties() pass we ensure required visual parts are non-null and if they are, throw an RTE.

Conclusion: 

So, the tiger team met. RAAR! We decided on proposal 4, to do nothing at this time. Though the skinning contract has several benefits, with skinning comes a definite overhead. Subclassing is a tried and true methodology of programming valid Flex applications - in fact, its been the "bread and butter" of Flex till this version. At this point in time, it seems too heavy-handed to request folks to abandon subclassing and always participate in skinning when they want a formalized contract between logic and visuals. Similarly, it seems too premature to formalize the subclassing mechanism since we're not sure how often this workflow will be used and whether end-users will even want a formalized contract for this mechanism.