Static initialisers two ways.

Static initialisers are good ways of running code for a class before any instances of it are created. Very useful for setting up things like loggers or defining default styles for custom components. Two different methods of achieving this are outlined below.

The first method looks something like this:


 private static var classConstructed:Boolean = classConstruct();
 
private static function classConstruct():Boolean
 { 
    //do some initialising...
    return true;
 }

When the static variable classContructed gets initialised, it calls the static method classConstruct executing whatever initialisation code is needed.

The second method looks like this:

 
[Mixin] 
public class SomeClass 
{ 
    public static function init (systemManager:ISystemManager) :void 
    { 
        //do some initialising... 
    }

This method uses slightly less code as it hooks into Flex's built in initialisation. All classes that use the [Mixin] metadata tag have thier static init method called during the SystemManager's mx_internal docFrameHandler method.

How to use custom bitwise flags in Actionscript

The Alert class in AS3 is a good example of using bitwise flags to specify a configuration without having to set lots of separate Boolean flags. Its also very easy to create bitflags for yourself, which save time, code and memory! Below is an example of custom bitflags as well as an explanation of how it all works. You can have various buttons enabled in the Flex Alert - “OK”, “NO”, “Cancel” etc. Any combination can be used, and the configuration is all set via one argument. Each value is separated with the bitwise OR operator (the pipe | – not to be confused with the logical OR operator || - two pipes).

The example below would contain OK, NO and CANCEL buttons.

 
Alert.show(“My Alert message”, “My Alert tittle”, Alert.OK | Alert.NO | Alert.CANCEL );
 

Below details how this works in terms of bitwise operations, but first here is an example of how to use this in your own program.

Example of using custom bitwise flags in actionscript Create a static class to hold the values and a method to test them.

 
package 
{ 
 
public class Colours 
 { 
 
    public static const ULTRA_RED:uint 		= 1; 
    public static const RED:uint 			= 2; 
    public static const ORANGE:uint 		= 4; 
    public static const YELLOW:uint 		= 8; 
    public static const GREEN:uint			= 16; 
    public static const BLUE:uint			= 32; 
    public static const INDIGO:uint 		= 64; 
    public static const VIOLETE:uint 		= 128; 
    public static const ULTRA_VIOLETE:uint 	= 256; 
 
    //convenience const to enable all flags 
    public static const ALL:uint = ULTRA_RED | RED | ORANGE | YELLOW | GREEN | BLUE | INDIGO | VIOLETE | ULTRA_VIOLETE; 
 
    public static function test(flags:uint, testFlag:uint):Boolean 
    { 
        return (flags & testFlag) == testFlag;
    } 
 } 
} 

Now, you can pass a combination of flags around as one single argument. The flags are combined using the bitwise OR operator.

 
var chosenColours:uint = Colours.RED | Colours.BLUE | Colours.VIOLETE; 

Then later test to see if the flag you want is in that single argument.

 
if ( Colours.test(chosenColours, Colours.RED) ) 
    trace(“We have RED”); 
else 
    trace(“We don’t have RED”); 

Note the Colours.ALL const, which is just a convenient way to enable all the flags in one go. 

And that's it. Makes life very simple, less method arguments, less var declaration, less database columns if you store a configuration, less memory used. Very simple to implement and very useful!

How it works - creating Each of the constants that define the flags Colours.RED, Colours.YELLOW etc are all integers. The separate flags must be multiples of 2 (which will become clearer later), so they would be 1,2,4,8,16,32 etc. The bitwise OR looks at the binary representation of each integer and analyses each bit of each integer in turn. Each bit is treated as a Boolean flag. If the bit is 1, its on, if its 0 its off. The bitwise OR will look at all the corresponding bits of each value in the list, starting with the first bit, then the second etc. If any of the bits are 1, the resulting bit for that position is 1, if ALL are 0 the resulting bit for that position is 0.
        0001  ( decimal 1 )         0010  ( decimal 2 )         1000  ( decimal 8 ) Bitwise OR =         1011  ( decimal 11 )
So, looking down each column of bits, the OR checks if any are 1, if so, the resulting bit is 1, else its 0. So the output of ( 1 | 2 | 8 ) is 1011,which is decimal 11. As the integers are multiples of 2 you don’t get multiple “1” bits in the binary representation of any number so only 1 column is ever marked as “on” by any flag – as in the example above. If you added 0110 ( binary 10 ) to the example above it would end up with 2 columns marked as "on" for one flag, which would break the system as you could not then calculate if the resulting bit flag contained a specific flag, as explained below.


How it works - testing Now you have one value that represents multiple flags. The next step is to check if it contains a particular flag. This is very similar, except you reverse the process and use the bitwise operator AND (the ampersand &, not to be confused with the logical AND &&) This looks at the columns of bits, and if ALL of them are 1, the result is 1, if not its 0. In the same way, as the columns are unique due to multiples of 2, we can check if the combined integer contains our value.
        1011 (decimal 11 - our combined flags)         0010 (decimal 2 - the flag to check for) Bitwise AND =         0010 (decimal 2)
As only the 2nd (from right) column contined both “On” bits, the result is 0010, which is our decimal 2, the value we wanted to check! So you can easily check to see if your value is in the combined flags by doing the following.



var hasValue:Boolean = ((flags & value) == value)

Very useful stuff!

AutoComplete component sizing.

The Flex Components AutoComplete ( Link ) offers a great auto suggestion text input component, which often makes for a better experience than a combo box or list. What it didn't do was resize quite how a wanted it to.

I was using the AutoComplete component as the auto-resizing part of a horizontal panel in an AIR application. When the window was resized by the user, the AutoComplete would enlarge or shrink to fit, down a minimum size set on the window.

The problem was that I couldn't seem to get the AutoComplete to fit without scrollbars appearing. After a bit of digging I found the minimum width gets set to the longest item in the data provider in the measure method of ComboBase. This was exacerbated by the long items in the data provider I was using, forcing scroll bars onto any reasonable size of window.

Extending AutoComplete and overriding measure with the following fixes the problem, and hasn't given me any issues so far.

 
override protected function measure():void 
{ 
    measuredWidth = mx.core.UIComponent.DEFAULT_MEASURED_WIDTH; 
    measuredHeight = UIComponent.DEFAULT_MEASURED_HEIGHT; 
    measuredMinWidth = UIComponent.DEFAULT_MEASURED_MIN_WIDTH;
    measuredMinHeight = UIComponent.DEFAULT_MEASURED_MIN_HEIGHT; 
} 

By not calling super and setting the four properties above then the component takes on the default minimum width of 40 and re-flows as expected. Obviously some of the items in the drop down may be cut off, but the text in the input field is draggable, so it's always possible to see all of it one way or another. A future improvement to this might be to include a tool-tip rollover to truncated drop down items.

I might improve this if I reuse the component in the future - maybe include some measurement logic similar to TextInput, or just some provision for borders and padding. In it's current application it works though, so I might just leave well alone!

SliderDataTip border skinning patch

In the previous post I discussed an issue with the SliderDataTip class' border skinning. http://www.as3offcuts.com/?p=57

Since then I've submitted a fix as a patch to the Adobe bugs system. This was the first time I'd submitted a patch, so had to jump through a few hoops to get there, but it was all pretty straightforward.

It basically involved:

  • Signing Adobe's contributor license forms, emailing them in, and waiting for a reply.
  • Checking out the 3.x branch and testing my fix in it.
  • Building the altered branch and running Abode's check in tests on it.
  • Making a patch of the fix with tortoise or something similar.
  • Submitting the patch on Adobe's bug site.
  • A good run through of the process can be found here and here.

    The patch is essentially the same as the fix described in the previous post, with the addition of removing the border construction from createChildren and just having it exist in styleChanged. There was no need for the code in createChildren; the border was already being created before createChildren was called in the first call to styleChanged.

    Have a look at the patch file here: Patch (sdk-24282)

    SliderDataTip border skinning fix (work in progress).

    There's a small issue with the border of the data tip in the two Flex Slider classes (VSlider and HSlider) (which I raised yesterday. https://bugs.adobe.com/jira/browse/SDK-24282)

    I quickly knocked up a fix for it that could either be placed in ToolTip, SliderDataTip or in an extension to SliderDataTip.

    If the fix is going into the ToolTip class, then the styleChanged method becomes the following:

    
    override public function styleChanged(styleProp:String):void 
    { 
        // This will take care of doing invalidateSize() if styleProp 
        // is "styleName" or a registered layout style such as "borderStyle". 
        super.styleChanged(styleProp); 
        // However, if the borderStyle changes from "errorTipAbove" to 
        // "errorTipBelow" or vice versa, the measured size won't change. 
        // (The pointy part of the skin simply changes from the bottom 
        // to the top or vice versa.) This means that the LayoutManager 
        // won't call updateDisplayList() because the size hasn't changed. 
        // But the TextField has to be repositioned, so we need to 
        // invalidate the layout as well as the size. 
        if (styleProp == "borderStyle" ||         styleProp == "styleName" ||         styleProp == "borderSkin" ||         styleProp == null         ) 
        { 
            if( !(border is getStyle("borderSkin")) ) 
            {
                if(border) 
                    removeChild(DisplayObject(border)); 					                     var borderClass:Class = getStyle("borderSkin");
                border = new borderClass();
                if (border is ISimpleStyleClient)                 ISimpleStyleClient(border).styleName = this;
                addChildAt(DisplayObject(border), 0); 
            }
     
            invalidateDisplayList(); 
        } 
    }
    
    
    

    This basically adds a check to see if the borderSkin style has changed. If so it remakes the border in the same way it's originally made in createChildren.

    If it's going into SliderDataTip or a subclass of ToolTip or SliderDataTip then add the above as an override to the styleChanged method, but also remember to import the mx_internal namespace and add the use namespace mx_internal line so that you can access the border property.

    So far I've tested runtime changes to border styles in the style defined for dataTipSlideName in the relevant slider, and they appear to work fine. Changing the dataTipSlideName itself won't update the data tip while it's open, but will when it is next opened. Fixing this would require a seperate addition to the styleChanged method of the Slider class.

    I'll try and get round to testing this a bit more and submitting it as a patch.

    HTML Text in a Flex Alert box

    A quick and easy way to render HTML text with the body of a Flex Alert box. There is no API to set the htmlText property of the Alert text field, but you can access it using the mx_internal namespace.

     
    var title:String ="HTML Alert!"; 
    var htmlBody:String = "This is my HTML message with <b>Bold</b> text and <br/> HTML formatting <b/>"; 
     var alert:Alert = Alert.show(str,  htmlBody);  // now target the Alert text field (after we have opened it) and set the HTML text property	
     
    use namespace mx.core.mx_internal; 
    IUITextField(alert.alertForm.textField).htmlText = htmlBody; 
     

    Using namespaces for access control.

    Using your own namespaces can be a good way to add another level of access control to class libraries that sits somewhere between public and internal.

    If you want to expose methods to classes in different packages, but not make them readily available to the whole of the outside world then this is a good way to do it. The Flex framework itself makes quite heavy use of the mx_internal namespace for inter-package communication and undocumented APIs

    First is to make the namespace. This can be done in an actionscript file that contains the following:

     
    package com.as3offcuts.namespaces 
    { 
         public namespace offcuts_internal; 
    } 
    

    That's it. Now you can import this namespace in your classes and either declare methods using it instead of public/internal etc. or call methods from other classes using it. The following demonstrates using the new namespace on an instance method:

     
    package com.as3offcuts.somepackage 
    { 
    import com.as3offcuts.namespaces.offcuts_internal; 
    
    use namespace offcuts_internal; 
     
    public class SomeClass 
     { 
        offcuts_internal function doSomething():void 
        { 
            trace("something"); 
        } 
     } 
    }
    

    There are three elements in the above example. The first is to import the namespace, much as you would import a class. The second is the use namespace declaration, and the third is use it in place of public or internal or whatever.

    To then access this method from another class simply repeat the first two steps (import the namespace and the 'use namespace ... ' line.) and then call the method as you would call a public or internal one.

     
    package com.as3offcuts.otherpackage 
    { 
     import com.as3offcuts.namespaces.offcuts_internal; 
     
    use namespace offcuts_internal; 
     
    public class SomeOtherClass 
     { 
        public function SomeOtherClass() 
        { 
            var someClass:SomeClass = new SomeClass(); 
            someClass.doSomething(); 
         }
     }
    }

    In terms of access control, as mentioned above, this sits somewhere between public and internal. It would be nice if it was just library level, but in reality anyone can import your namespace and use all the methods. They would however need to know about the namespace in first place. On the flip side though, another use for this is undocumented APIs, in which case you may actually want other people to use it.

    As a foot note, importing and using the mx_internal namespace opens up undocumented functionality in the Flex framework. As the mx_internal.as file warns though, these methods are liable to change in future releases.

    Encoding image byte data as a String.

    I was recently working with ways to hide (or obscure) images in an application's source code. I'm not sure there's many uses for encoding image data in a string; It's certainly not an easy or efficient way of working with images.  

    Never the less though here's a few notes on converting images to strings of byte data and back. First step was to write a small application that could load up an image and parse its data into a String format that could be copied/pasted/saved.

    
    
    <mx:Application 	xmlns:mx="http://www.adobe.com/2006/mxml" 	xmlns:local="*" 	layout="vertical" 	xmlns:net="flash.net.*" xmlns:display="flash.display.*"> 
     <mx:Script> 
     <![CDATA[ 
     [Bindable] 			private var text:String = ""; 
     private var loader:Loader; 
     
    private function process( bytes:ByteArray ) :void 
     { 
        bytes.position = 0; 
        var str:String = ""; 
     
        for(var i:int=0; i < bytes.length; i++)
        { 
            var byte:String = bytes.readUnsignedByte().toString(16); 
     
            if(byte.length<2) 
                byte= "0" + byte;  					str += byte; 				}  				text = str; 
        } 
     
        private function load( ) :void 
        {
            if(!loader) 					loader = new Loader(); 
            loader.contentLoaderInfo.addEventListener( Event.COMPLETE, onLoadComplete );
            loader.load( new URLRequest(urlInput.text) ); 
        } 
     
        private function onLoadComplete( e:Event ) :void 
        { 
            process( (e.target as LoaderInfo).bytes ); 
        } 
     ]]> 	</mx:Script> 
     
    <mx:TextArea text="{text}" width="100%" height="100%" /> 	
    <mx:TextInput id="urlInput" width="100%" /> 	
    <mx:Button id="processBtn" label="Process" click="load( )" />  
    </mx:Application>
     

    The main part of this is the process method, which takes a ByteArray and converts it into a string. In this case the bytes are supplied from the loaded image via the LoaderInfo object. This application will then display the string in a big text area. (The string may well be very long!).

    Second step is a little class that extends the Flex Image component and adds one property, byteSource, which it exposes as a getter/setter.  Below is the code for the setter:

     
    public function set byteSource( val:String ) :void 
    { 
        var newBytes:ByteArray = new ByteArray(); 
        var dataArr1:Array = val.split(""); 
        var dataArr2:Array = []; 
     
        for( var j:int=0; j < dataArr1.length; j+=2 ) 
        { 
            dataArr2.push("0x"+dataArr1[j]+dataArr1[j+1]);
        } 
     
        for( var k:int=0; k < dataArr2.length; k++ ) 
        { 
            newBytes[k] = dataArr2[k]; 	}  	this.source = newBytes;
            _byteSource = val;
        }
    }
    

    This method takes a string like the one generated from the application above, converts it into a ByteArray, and assigns that to the components source property. This component can now be added to any project, and supplied a string from which it will display an image. E.g.

     
    <controls:ByteImage byteSource="{ImageObject.image}" /> 
    

    Where ImageObject.image is a static constant String of image data.  

    Extending DateFormatter to add 'st', 'nd', 'rd', 'th' Support.

    I recently found myself with the task of configuring a date format for a new client.  The format that was specced looked something like:

    Wednesday 14th October, 13:33

    It was at this point I realised there is no support for the 'th' (or 'st', 'nd', 'rd') part of a date in the Flex DateFormatter.

    Rather than mess around with the string after it had been formatted, I had a poke around the DateFormatter's source code and decided to write an extended date formatter which added support for date suffixes. To achieve this I needed to extend three parts of the original DateFormatter.

    1. The format method of DateFormatter. This doesn't need to change much, most of what it does is validate and process the date object or string that was passed to it, before creating a StringFormatter to do the rest of the work. Unfortunately it won't let you access the processed value before it sends it on to the StringFormatter, and what gets returned from that isn't always re-usable, so I've duplicated all the processing code in my overridden format method. I've then altered the parameters that get passed to the new StringFormatter with the following 2 points.

    2. The private static constant VALID_PATTERN_CHARS that gets passed to the previously mentioned StringFormatter needs changing to add a new pattern character. This can't be overridden, so I define a new static constant that includes all the normal ones, plus 'T' to represent a date suffix.

    3. The internal static method extractTokenDate of the DateBase class that gets passed to the previously mentioned StringFormatter needs to be able to handle our new 'T' character. To acheive this I created my own static method that first calls extractTokenDate in DateBase, and then handles any empty result that has a token of 'T' before returning that result. Using the new DateFormatter with a 'T' in the format string will default to adding the correct 'st', 'nd', 'rd', 'th' to a date. I added a little extra customisation into this with the static var CUSTOM_NUMBER_SUFFIXES.

    This can be set to a 31 element array of any custom suffix that will be appended to the date matching it's index in the array plus one.