One of the nice things about Flex is that you can default stylistic elements such as padding from a top level via CSS declarations on the Application level. However, if the property you have in mind isn’t a Flex Style, it isn’t so easy to default.
A common example is the horizontalScrollPolicy and verticalScrollPolicy values of the Container class. For various reasons, Adobe (understandably) chose to make these two values properties instead of styles. They’re defaulted to “auto” which means scrollbars are created when needed, but often it would be more convenient if they were defaulted to “off”.
Anyway, here’s one way to default those values:
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" preinitialize="init()">
<mx:HBox width="50" height="50">
<mx:Label text="hello"/>
<mx:Label text="hello"/>
<mx:Label text="hello"/>
<mx:Label text="hello"/>
</mx:HBox>
<mx:Script>
<![CDATA[
import mx.core.UIComponent;
import mx.core.Container;
import mx.core.mx_internal;
import mx.core.ScrollPolicy;
private function init():void {
UIComponent.mx_internal::dispatchEventHook = myHook;
}
private function myHook(e:Event,uic:UIComponent):void {
if (e.type == "preinitialize") {
if (uic is Container) {
Container(uic).horizontalScrollPolicy = ScrollPolicy.OFF;
}
}
}
]]>
</mx:Script>
</mx:Application>
The hook intercepts ALL events that get dispatched from UIComponents and does the processing you want it to. Of course there is a problem if someone else decides they want to use the hook. Also, being an element under the mx_internal namespace, there is no guarantee for compatibility in future versions.
So this code works just fine except if you decide later you want a particular container to have scrollbars, it won’t work. To remedy this, here’s yet another dirty hack:
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" preinitialize="init()">
<mx:HBox width="50" height="50" horizontalScrollPolicy="on">
<mx:Label text="hello"/>
<mx:Label text="hello"/>
<mx:Label text="hello"/>
<mx:Label text="hello"/>
</mx:HBox>
<mx:HBox width="50" height="50">
<mx:Label text="hello"/>
<mx:Label text="hello"/>
<mx:Label text="hello"/>
<mx:Label text="hello"/>
</mx:HBox>
<mx:Script>
<![CDATA[
import mx.core.UIComponent;
import mx.core.ScrollPolicy;
import mx.core.Container;
import mx.core.mx_internal;
private function init():void {
UIComponent.mx_internal::dispatchEventHook = myHook;
}
private function myHook(e:Event,uic:UIComponent):void {
if (e.type == "horizontalScrollPolicyChanged") {
if (uic is Container) {
uic.setStyle("foot",true);
}
}
if (e.type == "preinitialize") {
if (uic is Container) {
if (!uic.getStyle("foot"))
Container(uic).horizontalScrollPolicy = ScrollPolicy.OFF;
}
}
}
]]>
</mx:Script>
</mx:Application>
The idea here is that we need to know if the user has set the scrollbars. Incidently, an event gets dispatched when scrollbars are set so since we are listening to all events, we can intercept it. Now all we need is to flag the component somehow. Since Flex styles can be set programmatically and arbitrarily, we can use some unused name (in this case “foot”).
Anyway, these methods are the polar opposite of standard practice and shouldn’t be used unless you are either brave, stupid, crazy, all of the above, two of the above, or none of the above.
Tags: default, horizontalScrollPolicy, major hack, properties, scrollbars, verticalScrollPolicy

