Implementing View States with ActionScript

At EUI we’re building an application that uses a Flash-like model of pulling symbols from a library and dropping them on a stage. While architecting the core components of this system, it became apparent that each symbol would need to have several different view states, e.g., selected, dragging, dragged-over, etc. Flex 2 has a introduced a rather elegant way of defining and applying view states, but I have only seen it implemented using MXML. As a long-time Flash developer, I’m still a bit unclear on how to best use MXML and Actionscript together in one component, although the RandomWalk component that was demonstrated at ACDS has a really good example (see IconItem.mxml in the source). Reviewing the example again, I think I could figure out how to make my symbol component an MXML component and still utilize the Flex invalidation mechanism, however when I first started, I couldn’t get my head around this. Anyway, it became a mission to figure out how to use view states in an Actionscript only component.

I knew MXML eventually became Actionscript, but an all-too-quick glance at the files in generated directory after compiling an application with a -keep switch, made it seemed like the conversion happened with a lot of smoke and mirrors. However, after attending ACDS, I began to realize just how directly related MXML and Actionscript really are. With that in mind, I set out to make my symbol component suport view states.

Before I get into the code, here’s a a quick blip about view states in Flex. A view state is simply a collection of instructions to apply to represent a component’s or a application’s, um, state. In it’s simplest form a view state is created by defining which properties and styles are applied when it is active. Additionally, you can also add and remove children and set event-handlers based on state. I don’t want to go into too much detail about what states do because the documentation covers it rather well, but the other cool thing about states is that you can base one state on another state and you can specify how to transition from one state to another.

All the code dealing with states lives in mx.states, and is surprisingly light-weight. When first examining the MXML implementation of view states, it threw me off that you defined a state by nesting a SetProperty node within a State node. It seemed as though you were using an MXML tag to call a function, however, SetProperty is a class. The MXML tag makes an instance of mx.states.SetProperty, just as you’d expect. Once I realized this, it became clear how I could define a view state in Actionscript. Enough rambling, here is the code:


//*****************
// Default State
//*****************

// create an instance of state
var s1:State = new State();

// give the state a name. The name properties
// accepts a string, and I've defined a SymbolStates
// class that defines several name as constants so I
// verify that I'm passing around valid state names
s1.name = SymbolStates.DEFAULT_STATE;

// heres the real magic of a State. overrides is an array that holds
// instances of the various "Set" classes from mx.states. When a
// currentState is set, each override is sequentially applied.
s1.overrides = [ new SetProperty(this,"img_bkg_color",0xFFFFFF),
new SetProperty(img_bkg,"alpha",0),
new SetProperty(this,"img_stroke_weight",null),
new SetProperty(this,"img_stroke_color",0x999999),
new SetProperty(this,"lbl_bkg_color",0xEFEFEF),
new SetStyle(lbl,"color",0x666666),
new SetProperty(this,"showShadow",false) ];

//*****************
// Selected State
//*****************

// rinse and repeat with the selected state
var s2:State = new State();
s2.name = SymbolStates.SELECTED_STATE;

// the selected state is based on the default state, so the overrides listed
// here will be applied after applying the overrides from the default state
s2.basedOn = SymbolStates.DEFAULT_STATE;
s2.overrides = [ new SetProperty(this,"img_bkg_color",0x000000),
new SetProperty(img_bkg,"alpha",.1),
new SetProperty(this,"lbl_bkg_color",0x0066CC),
new SetStyle(lbl,"color",0xFFFFFF) ];

// add these states to the states array (inherited from UIComponent)
states = [s1,s2];

// i also added this lin because i'm not sure what happens under the hood if you
// don't specify a default view state

if(!currentState) currentState = SymbolStates.DEFAULT_STATE;

After defining the states, all that is left to do is reflect these property changes in the updateDisplayList method.

Here are some final thoughts regarding view states in Flex, specifically implementing them with Actionscript.

  • Implementing view states in MXML seems much more intuitive and requires less typing. I think we may start writing our components as MXML for sake of facilitating things like this. There seems to be a certain pureness to having AS classes, but I don’t know if it always makes sense
  • It’s nice to keep the logic for defining states in one place. Previously, in AS2, we’d define a state, and then switch(state) in the draw method and render accordingly. This worked, but the Flex way has a bit of magic to it that is especially useful if your component’s state can be reflected by altering properties/states of it’s children. It was a bit tedious in my Symbol class to have to define a property for img_bkg_color and then use the drawing API to draw according to it’s value. If the symbol was entirely a composite component, with no drawing, it would have been much more straight forward
This entry was posted in Flex. Bookmark the permalink. Post a comment or leave a trackback: Trackback URL.

3 Comments

  1. Bill White
    Posted January 13, 2008 at 1:27 pm | Permalink

    I’ve been looking for a sample like this. Thanks for the helpful post!

  2. Lightpower
    Posted December 16, 2009 at 7:39 am | Permalink

    Thank you for your sample! It is very useful

  3. Posted November 14, 2010 at 2:55 am | Permalink

    Left from the MXML states, this is what i was looking for, Thanks Andy.

Post a Comment

Your email is never published nor shared. Required fields are marked *

*
*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>