AS 3 Static Initializer
June 18th, 2008
I have been working on a new CSS parser for my SUMO Framework. The idea is to have something that can load a CSS file, parse each CSS class into objects then use them as templates to create TextFields. There is a lot of logic needed to work out the conversion so I started looking into using “Reference” classes to help validate the CSS. Here is some stuff I came up with.
My first idea was to simply create a stand alone class with just constants in it. I use these all over the place in the Framework1 so I started creating one for TextFeilds and the other for TextFormats. The goal is to have 1 CSS class that was smart enough to parse out each property, decide if it belongs to in a TextFeild or a TextFormat, and return a TextField styled by the created TextFormat. I want the system that did not rely on HTML markup to be styled. You should be able to say “give me a label with ‘this’ style” and here is the text “Hello World”.
Like all of my research, I asked the Google Gods to show me the way. Here is a great post I came across from Daniel Rinehart. I really like his idea of putting values in a constant object then using a function to return true of false if it exists. Here is sample code from his class:
public class MIME {
public static const GIF_MIME_TYPE:String = “image/gif”;
public static const JPG_MIME_TYPE:String = “image/jpeg”;
public static const PNG_MIME_TYPE:String = “image/png”;
public static const SWF_MIME_TYPE:String = “application/x-shockwave-flash”;
private static const IMAGE_TYPES:Object = new Object()
// This block is run once when the class is first accessed
{
IMAGE_TYPES[GIF_MIME_TYPE] = true;
IMAGE_TYPES[JPG_MIME_TYPE] = true;
IMAGE_TYPES[PNG_MIME_TYPE] = true;
IMAGE_TYPES[SWF_MIME_TYPE] = true;
}
public static function isImage(mimeType:String):Boolean {
return (IMAGE_TYPES[mimeType] == true);
}
}
}
Its a really neat trick because all you have to do to validate that a constant exists is call “isImage” function (in his example) and it looks it up from the IMAGES_TYPES object. One of the commenters offered up this suggestion for looping through the constant by reflection:
for each (var constant:XML in describeType(MIME).constant) {
if (MIME[constant.@name] == mimeType) {
return true;
}
}
return false;
}
I really liked Refection and I use it throughout the Framework. Because I don’t want to have multiple loops running all over the place when I am doing parsing, this Static Initializer class will cut down on a large part of the cpu overhead. The tradeoff is that I have to hard code a lot of the CSS rules. Luckily all of the properties I will be looking for are defined clearly in ActionScript so chances are I will not be adding new one very often. Here is what I came up with:
This is the TextFieldReference Class
{
public class TextFieldReference
{
public static const ALWAYS_SHOW_SELECTION:String = “alwaysShowSelection”;
public static const ANTI_ALIAS_TYPE:String = “antiAliasType”;
public static const AUTO_SIZE:String = “autoSize”;
public static const BACKGROUND:String = “background”;
public static const BACKGROUND_COLOR:String = “backgroundColor”;
public static const BORDER:String = “border”;
public static const BORDER_COLOR:String = “borderColor”;
public static const CONDENSE_WHITE:String = “condenseWhite”;
public static const DISPLAY_AS_PASSWORD:String = “displayAsPassword”;
public static const EMBED_FONTS:String = “embedFonts”;
public static const GRID_FIT_TYPE:String = “gridFitType”;
public static const MAX_CHARS:String = “maxChars”;
public static const MOUSE_WHEEL_ENABLED:String = “mouseWheelEnabled”;
public static const MULTILINE:String = “multiline”;
public static const RESTRICT:String = “restrict”;
public static const SELECTABLE:String = “selectable”;
public static const SELECTION_BEGIN_INDEX:String = “selectionBeginIndex”;
public static const SELECTIOEND_INDEX:String = “selectioendIndex”;
public static const SHARPNESS:String = “sharpness”;
public static const TEXT_COLOR:String = “textColor”;
public static const TEXT_HEIGHT:String = “textHeight”;
public static const TEXT_WIDTH:String = “textWidth”;
public static const THICKNESS:String = “thickness”;
public static const WORD_WRAP:String = “wordWrap”;
public static const WIDTH:String = “width”;
public static const HEIGHT:String = “height”;
public static const ALPHA:String = “alpha”;
public static const x:String = “x”;
public static const y:String = “y”;
private static const PROPERTY_TYPES:Object = new Object();{
PROPERTY_TYPES[ALWAYS_SHOW_SELECTION] = true;
PROPERTY_TYPES[ANTI_ALIAS_TYPE] = true;
PROPERTY_TYPES[AUTO_SIZE] = true;
PROPERTY_TYPES[BACKGROUND] = true;
PROPERTY_TYPES[BACKGROUND_COLOR] = true;
PROPERTY_TYPES[BORDER] = true;
PROPERTY_TYPES[BORDER_COLOR] = true;
PROPERTY_TYPES[CONDENSE_WHITE] = true;
PROPERTY_TYPES[DISPLAY_AS_PASSWORD] = true;
PROPERTY_TYPES[EMBED_FONTS] = true;
PROPERTY_TYPES[GRID_FIT_TYPE] = true;
PROPERTY_TYPES[MAX_CHARS] = true;
PROPERTY_TYPES[MOUSE_WHEEL_ENABLED] = true;
PROPERTY_TYPES[MULTILINE] = true;
PROPERTY_TYPES[RESTRICT] = true;
PROPERTY_TYPES[SELECTABLE] = true;
PROPERTY_TYPES[SELECTION_BEGIN_INDEX] = true;
PROPERTY_TYPES[SELECTIOEND_INDEX] = true;
PROPERTY_TYPES[SHARPNESS] = true;
PROPERTY_TYPES[TEXT_COLOR] = true;
PROPERTY_TYPES[TEXT_HEIGHT] = true;
PROPERTY_TYPES[TEXT_WIDTH] = true;
PROPERTY_TYPES[THICKNESS] = true;
PROPERTY_TYPES[WORD_WRAP] = true;
PROPERTY_TYPES[WIDTH] = true;
PROPERTY_TYPES[HEIGHT] = true;
PROPERTY_TYPES[ALPHA] = true;
PROPERTY_TYPES[x] = true;
PROPERTY_TYPES[y] = true;
}
/**
*
*/
public static function isSupported(property:String):Boolean {
return (PROPERTY_TYPES[property] == true);
}
}
}
And this is the TextFormatReference Class
public class TextFormatReference {
public static const ALIGN:String = “align”;
public static const BLOCK_INDENT:String = “blockIndent”;
public static const BOLD:String = “bold”;
public static const BULLET:String = “bullet”;
public static const COLOR:String = “color”;
public static const FONT:String = “font”;
public static const INDENT:String = “indent”;
public static const ITALIC:String = “italic”;
public static const KERNING:String = “kerning”;
public static const LEADING:String = “leading”;
public static const LEFT_MARGIN:String = “leftMargin”;
public static const LETTER_SPACING:String = “letterSpacing”;
public static const RIGHT_MARGIN:String = “rightMargin”;
public static const SIZE:String = “size”;
public static const TAB_STOPS:String = “tabStops”;
public static const TARGET:String = “target”;
public static const UNDERLINE:String = “underline”;
private static const PROPERTY_TYPES:Object = new Object();{
PROPERTY_TYPES[ALIGN] = true;
PROPERTY_TYPES[BLOCK_INDENT] = true;
PROPERTY_TYPES[BOLD] = true;
PROPERTY_TYPES[BULLET] = true;
PROPERTY_TYPES[COLOR] = true;
PROPERTY_TYPES[FONT] = true;
PROPERTY_TYPES[INDENT] = true;
PROPERTY_TYPES[ITALIC] = true;
PROPERTY_TYPES[KERNING] = true;
PROPERTY_TYPES[LEADING] = true;
PROPERTY_TYPES[LEFT_MARGIN] = true;
PROPERTY_TYPES[LETTER_SPACING] = true;
PROPERTY_TYPES[RIGHT_MARGIN] = true;
PROPERTY_TYPES[SIZE] = true;
PROPERTY_TYPES[TAB_STOPS] = true;
PROPERTY_TYPES[TARGET] = true;
PROPERTY_TYPES[UNDERLINE] = true;
//PROPERTY_TYPES[URL] = true;
}
public static function isSupported(property:String):Boolean {
return (PROPERTY_TYPES[property]);
}
}
So for now this may be a lot to take in. You are probably wondering how the hell can you use this? Well here is a sample from my CSS parser:
* Goes through css object and determines if the css prop can be used in a TextField, a TextFormat,
* or should be ignored.
*/
internal function parseCSS(cssObject:Object):void{
var text_format:TextFormat = new TextFormat();
//
for (var prop:String in cssObject) {
if(TextFieldReference.isSupported(prop)){
data[prop] = TextFieldReference.cleanupProp(prop,cssObject[prop]);
}else if (TextFormatReference.isSupported(prop)){
text_format[prop] = TextFormatReference.cleanupProp(prop,cssObject[prop]);
}else{
trace(“Alert: This prop ‘”+prop+“‘ is not supported.”);
}
}
data.defaultTextFormat = text_format;
}
As you can see I am doing 1 loop through all the properties that come in from a css object (This is created from the css parser). For this example I have taken out the cleanupProp function from the two reference classes but will get into that specifically when I post about my super slick CSS parser. The thing I really wanted to show you was how clean these Static Initializer Class can make your code. I only have 1 loop, and the rest is all “static” so to speak.
- I call them Reference Classes [↩]













July 8th, 2008 at 9:02 am
[...] AS 3 Static Initializer Class [...]