As we add behaviors to our components, like 'smoothScrolling' to ScrollBar/Scroller and 'resizeThumb' to ScrollBar, we need to know how/where to expose these behaviors so that developers can change the default or per-instance behavior. Should they be styles? Should they be properties? If properties, are they backed by some static property so that developers can easily change the default application behavior?
Complete this section when a decision has been made and approved
A good decision would be: - understandable, so that developers would generally know how to expose behaviors and didn't need to cast around for input when the issues arise - easily doable: we're not looking for core infrastructure changes here, but just a policy decision, and probably some scrubbing of current behaviors as appropriate
There is already precedent for this in Halo. For example, Slider exposed slideDuration and slideEasingFunction as styles:
<a href="Style%28name%3D%26quot%3BslideDuration%26quot%3B%2C%20type%3D%26quot%3BNumber%26quot%3B%2C%20format%3D%26quot%3BTime%26quot%3B%2C%20inherit%3D%26quot%3Bno%26quot%3B%29">Style(name="slideDuration", type="Number", format="Time", inherit="no")</a>
<a href="Style%28name%3D%26quot%3BslideEasingFunction%26quot%3B%2C%20type%3D%26quot%3BFunction%26quot%3B%2C%20inherit%3D%26quot%3Bno%26quot%3B%29">Style(name="slideEasingFunction", type="Function", inherit="no")</a>
This approach allows the developer to specify a global default that is picked up on the fly by existing objects. It also allows developers to target specific instances as necessary.
For example, we could add styles like the above, and smoothScrolling, and thumbSize to particular classes like Slider and ScrollBar. Then we could add default values to defaults.css. Then the classes depending on these behaviors could dynamically query the styles when necessary. Finally, developers wishing for different behavior could write CSS code that changed the value globally or per-instance .
Usage:
To globally change a style, a developer could write the following CSS:
global {
smoothScrolling: false;
}
or
ScrollBar {
smoothScrolling: false;
}
To change the style for scrollbars inside of all TextArea components, they could write this, using descendent selectors:
TextArea ScrollBar{
smoothScrolling: false;
}
It is straightforward to expose behaviors as properties instead of styles. For example, smoothScrolling is currently a Boolean property on ScrollBar. The class looks at this property's value whenever it needs to perform a scrolling operation and behaves accordingly.
It can be tricky for developers to get a handle to the specific ScrollBar instances they need. For example, developers create TextAreas, which then create Scrollers, which then, internally, use ScrollBars. For a developer to change a property on a ScrollBar instance, they need to burrow all the way down to get ahold of that property. It is probably more useful to expose some way of setting the property default, so we propose a static flag on some class (ScrollBar, in the case of smoothScrolling), which acts as the default value for the instance property when that instance is created.
A developer wishing for non-default behavior could simply set the static default value and then expect all instances to pick that value up. They could, alternatively, get ahold of the proper instances and set those values directly. They could also, in the manner of spark developers, create a custom skin that set the property. In some cases, it might make sense to expose the property through other components to make it more visible to the developer. For example, the smoothScrolling behavior is exposed on both ScrollBar and Scroller, so a skin developer could set the property directly on the Scroller to get that instance to have non-default behavior.
Currently, the only way to set static properties is through ActionScript code. Should we make it possible to do this through MXML?
We recommend approahc #1: Behaviors as Styles. This approach is pretty standardized in Halo components and provides the per-instance and global value-setting facilities we want. Going the property route would really be a new pattern (especially with the static-property approach) and might eventually require tooling work; why create a new approach when a perfectly adequate one exists?
Meeting 5/4/09
To answer a question in the original writeup, styles can be used to target specific instances, either through inline styles (styles exposed as attributes on a component) or through advanced CSS.
Styles support dynamic behavior changes more easily than the property approach - calling getStyle() will always return the latest value, as opposed to using a static property and caching the instance property. On the other hand, it is probably not a common use case to want to change the behavior on the fly for an instantiated object.
Behaviors in CSS in the HTML world: originally, behaviors in CSS were somewhat controversial. But they have been available in various forms from browser makers for some time and seem less controversial now.
Decision: let's go with styles, not properties.
Where do we expose the styles?
Where do we set the global defaults?
Avoid setting styles on class-specific selectors, because it makes it difficult for developers to figure out what the defaults are and what the behaviors will or should be. Putting everything in global makes it more obvious.
As background, there is a pattern for spark components now to put everything visual in the Global type selector.
Note on metadata: this is only needed in situations where developers might want to set the style as an inline attribute.
Decisions:
Note: this change is being made only for spark components; we are not changing the way we do things for Halo components.