# Enhanced States Syntax - Functional and Design Specification
----
## Glossary
----
**state** - A _state_ (or '_view-state_') is a collection of changes (called _overrides_) to a view. The changes within a state can comprise additions or removals of components as well as changes to their properties, styles, and behavior.
\\
\\
**overlay** - An _overlay_ is a special class of _state_ that can be applied concurrently with other states and/or overlays. Overlays are triggered via a user defined predicate or "condition", and are cleared when the associated condition no longer holds. _Note: This language feature will be detailed in a follow up specification_.
## Summary and Background
----
#### Goals
* Reduce the complexity of the Flex view-states feature by (1) providing a new syntax that allows state-specific object and/or property changes to be specified inline, as opposed to with somewhat more verbose, and out-of-context override tags, and (2) eliminating the concept of hierarchical states.
\\ \\
* Refine and evolve the view states model such that we support a means of sharing component instances between states without necessitating the use of state hierarchies as we have today.
\\ \\
* Promote the states functionality to an MXML language feature, expanding the set of runtime objects that are supported by the stateful document model.
## Usage Scenario
----
Flex 4 will target all of the legacy usage scenarios of classic Flex states functionality (stateful components, states as application "views" or "pages", effects and transitions between view states, etc.). This document outlines what is primarily a syntax change for the existing functionality.
## Detailed Description
----
### Inline States Syntax
States will be promoted to a full language feature of MXML during the Flex 4 time frame. A more terse and flexible inline syntax will be provided for expressing all state-specific changes to a component instance. The classic syntax will be deprecated as of MXML version 4.0.
First, a brief description of how the states model will change for version 4.0 components:
* A set of states within a component definition is still defined via the **states** array property of UIComponent, however individual overrides are no longer declared as children of the states tags themselves. The legacy _AddChild_, _RemoveChild_, _SetProperty_, _SetStyle_, and _SetEventHandler_ overrides have been replaced in favor of language keywords that can be used inline within the document.
\\
\\
_AddChild_, _RemoveChild_ are deprecated in favor of the the '**includeIn**' and '**excludeFrom**' compile-time attributes. These attributes can be used to annotate document nodes directly inline, in order to specify the set of states for which they are to be realized.
\\
\\
_SetProperty_, _SetStyle_, and _SetEventHandler_ overrides are replaced with a new syntax that allows for the attribute identifier of a property or style to denote which state(s) that value applies.
* During the scope of this feature iteration, as with Flex 3, only UIComponent instances support being stateful. We will support generic use of the new states syntax with arbitrary MXML component documents in a follow-up iteration (that will be spec'd out separately and implemented within the Flex 4 timeframe). See the [implementation details](%23A%20Phased%20Approach) for more.
* A convenient '_Reparent_' tag will allow for the ability to specify an alternate parent for a given document node, in the context of a specific state.
\\ \\
* Once a "stateful" component has been defined (one where the **states** language tag has one or more valid State children), the component must at any given time be in one of the defined states (it is no longer valid for a component to be in a 'base' or 'null' state). By default, the first declared state is the initial state (the initial value of **currentState**), unless **currentState** is explicitly set.
\\ \\ On a related note, unlike the classic states model, if there is a enter transition defined for the state serving as the initial state, the transition will _not_ apply until subsequent activations of that state. \\ \\
* State names are no longer arbitrary strings, specifically for a state name to be valid, the identifier must be consistent with a valid XML attribute _excluding_ the dot '.' and colon ':' characters. For tooling purposes one can utilize the new Flex 4 custom namespace functionality to annotate individual states with design time attributes (for example a "friendly" name), if a non-restrictive identifier is required.
\\ \\
* All state-aware Flex features (effects, transitions, etc.) continue to function as they have previously.
\\ \\
* For the first phase of the development of this feature, the stateful document model can be augmented or extended at runtime by accessing the states array and contained set of Overrides for each state as with Flex 3. In a later phase during the Flex 4 development path, we will revisit this API and provide something more consistent with the new model. (_See [B Features](%23B%20Features) section_).
\\ \\
* The presence of an 'MXML language namespace' determines the language version for an MXML document. Note that the legacy states syntax is only applicable for the documents in the old MXML language namespace _http://www.adobe.com/2006/mxml_. The new MXML language namespace _http://ns.adobe.com/mxml/2009_ will support the new syntax only. There are no scenarios where we allow mixing of the two. _Note: The details of the new language namespace are documented in the Flex 4 [MXML 2009 language specification](http://opensource.adobe.com/wiki/display/flexsdk/MXML%2B2009)._
## API Description
----
A detailed overview of the new inline syntax follows:
### State-Specific Component Instances
The _AddChild_ and _RemoveChild_ override mechanism will be replaced by a new **includeIn** language attribute that can be used to decorate inline MXML component instance tags with the set of states for which the specific instance is to be realized.
The new **includeIn** attribute accepts a comma delimited list of state names, all of which must have been previously declared within the document's _states_ array. Optionally, **excludeFrom** can be used to define an explicit "black-list" of states where the instance will _not_ apply.
The **excludeFrom** and **includeIn** attributes are mutually exclusive. If both are defined on a single tag, it is considered an error and an appropriate compiler error will be issued.
An example:
<m:states>
<m:state name="A">
<m:state name="B">
<m:state name="C">
</m:state></m:state></m:state></m:states>
<button label="Click Me" includein="A, B">
</button><button label="Button C" excludefrom="C">
The **includeIn** and **excludeFrom** attributes will be treated as reserved language keywords by the MXML compiler.
The **includeIn** and **excludeFrom** attributes can be legally specified on any MXML object within a document, with the exception of:
* The root node of an MXML document (e.g. Application).
* Property tags (special MXML tags that represent properties of their parent object, e.g. _mx:label_).
* Descendants of the XML, XMLList, or Model tags. (_See [B Features](%23B%20Features) section_).
* Any "language" tags declared within the new Flex 4 language namespace (including any descendants of language tags). The full set of language tags are detailed in the Flex 4 [MXML 2009 language specification](http://opensource.adobe.com/wiki/display/flexsdk/MXML%2B2009), but they include (for example), _Script_, _Binding_, _Metadata_, _Style_, etc.
In addition to referencing mutually exclusive states, both attributes also support composite states (currently known as _overlays_). A more detailed specification of how Overlays are supported in the new state model will be incorporated into the Overlays specification (not yet drafted).
**EXAMPLE (1): An AddChild Equivalent**
BEFORE - Classic states syntax (O'Reilly Programming Flex 2):
<mx:application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
<mx:states>
<mx:state name="newCheckbox">
<mx:addchild relativeto="{vbox}">
<mx:checkbox id="checkbox" label="Checkbox">
</mx:checkbox></mx:addchild>
</mx:state>
<mx:state name="newTextArea" basedon="newCheckBox">
<mx:addchild relativeto="{vbox}">
<mx:textarea id="textarea">
</mx:textarea></mx:addchild>
</mx:state>
</mx:states>
<mx:vbox id="vbox">
<mx:button label="Click" click="currentState='newCheckbox'">
<mx:button label="Click" click="currentState='newTextArea'">
</mx:button></mx:button></mx:vbox>
</mx:application>
AFTER - Inline states syntax:
<mx:application xmlns:mx="library:ns.adobe.com/flex/halo" xmlns:m="http://ns.adobe.com/mxml/2009" layout="absolute">
<m:states>
<m:state name="default">
<m:state name="newCheckbox">
<m:state name="newTextArea">
</m:state></m:state></m:state></m:states>
<mx:vbox>
<mx:button label="Click" click="currentState='newCheckbox'">
<mx:button label="Click" click="currentState='newTextArea'">
<mx:checkbox id="checkbox" label="Checkbox" includein="newCheckbox, newTextArea">
<mx:textarea id="textarea" includein="newTextArea">
</mx:textarea></mx:checkbox></mx:button></mx:button></mx:vbox>
</mx:application>
Transient component instances (instances that appear across one or more states), are declared inline with the rest of the document, essentially at their "natural" location in the DOM. The context of a state-specific instance is no longer explicitly defined by the **relativeTo**/*position* properties of _AddChild_. Location is instead inferred by the inline placement.
Note that for a state-specific node to be realized within a state, its ancestors must also be defined within the same state as well. For example, a child is not visible in StateA if its parent is excluded from StateA. If such a scenario is detected, a compiler warning will be issued.
**EXAMPLE (2): Child Insertion**
BEFORE - Classic states syntax (O'Reilly Programming Flex 2):
<mx:application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
<mx:states>
<mx:state name="newTextInput">
<mx:addchild relativeto="{checkbox1}" position="after">
<mx:textinput id="textinput">
</mx:textinput></mx:addchild>
</mx:state>
</mx:states>
<mx:vbox id="vbox">
<mx:checkbox id="checkbox1" label="One">
<mx:checkbox id="checkbox2" label="Two">
<mx:button id="button" label="Click" click="currentState='newTextInput'">
</mx:button></mx:checkbox></mx:checkbox></mx:vbox>
</mx:application>
AFTER - Inline states syntax:
<mx:application xmlns:mx="library:ns.adobe.com/flex/halo" xmlns:m="http://ns.adobe.com/mxml/2009" layout="absolute">
<m:states>
<m:state name="default">
<m:state name="newTextInput">
</m:state></m:state></m:states>
<mx:vbox>
<mx:checkbox label="One">
<mx:textinput includein="newTextInput">
<mx:checkbox label="Two">
<mx:button id="button" label="Click" click="currentState='newTextInput'">
</mx:button></mx:checkbox></mx:textinput></mx:checkbox></mx:vbox>
</mx:application>
And another example, demonstrating how the use of _RemoveChild_ in the legacy syntax, translates to the new:
**EXAMPLE (3): A RemoveChild Equivalent**
BEFORE - Classic states syntax (O'Reilly Programming Flex 2):
<mx:application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
<mx:states>
<mx:state name="noCheckboxes">
<mx:removechild target="{checkbox1}">
<mx:removechild target="{checkbox2}">
</mx:removechild></mx:removechild></mx:state>
</mx:states>
<mx:vbox id="vbox">
<mx:checkbox id="checkbox1" label="One">
<mx:checkbox id="checkbox2" label="Two">
<mx:button id="button" label="Click" click="currentState='noCheckboxes'">
</mx:button></mx:checkbox></mx:checkbox></mx:vbox>
</mx:application>
AFTER - Inline states syntax:
<mx:application xmlns:mx="library:ns.adobe.com/flex/halo" xmlns:m="http://ns.adobe.com/mxml/2009" layout="absolute">
<m:states>
<m:state name="default">
<m:state name="noCheckboxes">
</m:state></m:state></m:states>
<mx:vbox id="vbox">
<mx:checkbox label="One" excludefrom="noCheckboxes">
<mx:checkbox label="Two" includein="default">
<mx:button id="button" label="Click" click="currentState='noCheckboxes'">
</mx:button></mx:checkbox></mx:checkbox></mx:vbox>
</mx:application>
### Reparenting
Where one would generally have used a _RemoveChild_ followed by an _AddChild_ to reparent instances within a state (Flex 3), a new **Reparent** language tag will be provided that can be used as an inline insertion point for a given component instance.
The _Reparent_ tag itself provides a **target** attribute which specifies the component instance to reparent. The **includeIn** attribute used in combination with the Reparent tag specifies the context for which the reparenting is to take place. There is no formal runtime representation of the _Reparent_ tag itself. The compiler will convert the Reparent into explicit remove and insertion overrides for the given state(s).
Note that for a _Reparent_ tag to be valid, it must refer to a document node that is **not** already realized within the state that the reparenting is to take place. Additionally, two or more _Reparent_ tags must not target the same DOM node within the same state. The set of reparent operations in a given state must, when combined, result in a valid DOM (no circular references, etc.). If any of these error conditions are detected, a compiler error will be issued.
Additional restrictions on the _Reparent_ tag are as follows:
* A reparent operation can only reparent document nodes to a type-compatible destination. The compiler will issue an error if the reparent operation is invalid due to type incompatiblity.
* Being a 'language' tag, Reparent has no runtime representation per se, the compiler ultimate generates the code necessary to carry out the reparenting operation for the specified state.
See the [#Media Chat](%23Media%20Chat) example later for an example Reparent use case.
### State-Specific Property Values
The _SetProperty_, _SetStyle_, and _SetEventHandler_ overrides will be replaced by an inline attribute notation.
State-specific property values can be expressed by utilizing the 'dot' operator on any writable XML attribute to essentially provide a hint to the compiler that the attribute is to be 'scoped' to a specific state.
</button><button label="XXX" label.a="YYY" label.b="ZZZ">
The unqualified property/value pair (e.g property=value) is assumed to be the default base value and the value within _all_ states, unless specifically overridden.
</button><button label="YYY" label.a="XXX">
The "drill-down" (dot) syntax can be utilized with most component properties, styles, or event handlers. The state-specific attribute syntax _cannot_ however be used with built-in language attributes. The full set of language attributes are detailed in the Flex 4 [MXML 2009 language specification](http://opensource.adobe.com/wiki/display/flexsdk/MXML%2B2009), but they include (for example), _id_, _states_, _frameRate_, etc.
To facilitate the ability to "clear" a property value within a given state, a new directive '@Clear()" will be introduced. This essentially results in property being _unset_. e.g. For a style property, it would result in a clearStyle() being invoked (thus allowing the natural cascade to take effect). The @Clear() value directive can be used with properties, styles, and event handlers.
</button><button color="0xFF0000" color.a="@Clear()">
Some additional examples of state-specific property syntax:
**EXAMPLE (4): State-Specific Styles**
BEFORE - Classic states syntax (O'Reilly Programming Flex 2):
<mx:application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
<mx:states>
<mx:state name="landState">
<mx:setstyle target="{car}" name="color" value="0xFF0000">
<mx:setstyle target="{train}" name="color" value="0xFF0000">
<mx:setstyle target="{motorcycle}" name="color" value="0xFF0000">
</mx:setstyle></mx:setstyle></mx:setstyle></mx:state>
<mx:state name="airState">
<mx:setstyle target="{helicopter}" name="color" value="0xFF0000">
<mx:setstyle target="{airplane}" name="color" value="0xFF0000">
</mx:setstyle></mx:setstyle></mx:state>
<mx:state name="waterState">
<mx:setstyle target="{boat}" name="color" value="0xFF0000">
<mx:setstyle target="{submarine}" name="color" value="0xFF0000">
</mx:setstyle></mx:setstyle></mx:state>
</mx:states>
<mx:vbox id="vbox">
<mx:hbox>
<mx:button id="land" label="Land" click="currentState='landState'">
<mx:button id="air" label="Air" click="currentState='airState'">
<mx:button id="water" label="Water" click="currentState='waterState'">
</mx:button></mx:button></mx:button></mx:hbox>
<mx:checkbox id="helicopter" label="Helicopter">
<mx:checkbox id="motorcycle" label="Motorcycle">
<mx:checkbox id="car" label="Car">
<mx:checkbox id="airplane" label="Airplane">
<mx:checkbox id="train" label="Train">
<mx:checkbox id="boat" label="Boat">
<mx:checkbox id="submarine" label="Submarine">
</mx:checkbox></mx:checkbox></mx:checkbox></mx:checkbox></mx:checkbox></mx:checkbox></mx:checkbox></mx:vbox>
</mx:application>
AFTER - Inline states syntax:
<mx:application xmlns:mx="library:ns.adobe.com/flex/halo" xmlns:m="http://ns.adobe.com/mxml/2009" layout="absolute">
<m:states>
<m:state name="landState">
<m:state name="airState">
<m:state name="waterState">
</m:state></m:state></m:state></m:states>
<mx:vbox id="vbox">
<mx:hbox>
<mx:button id="land" label="Land" click="currentState='landState'">
<mx:button id="air" label="Air" click="currentState='airState'">
<mx:button id="water" label="Water" click="currentState='waterState'">
</mx:button></mx:button></mx:button></mx:hbox>
<mx:checkbox label="Helicopter" color.airstate="0xFF0000">
<mx:checkbox label="Motorcycle" color.landstate="0xFF0000">
<mx:checkbox label="Car" color.landstate="0xFF0000">
<mx:checkbox label="Airplane" color.airstate="0xFF0000">
<mx:checkbox label="Train" color.landstate="0xFF0000">
<mx:checkbox label="Boat" color.waterstate="0xFF0000">
<mx:checkbox label="Submarine" color.waterstate="0xFF0000">
</mx:checkbox></mx:checkbox></mx:checkbox></mx:checkbox></mx:checkbox></mx:checkbox></mx:checkbox></mx:vbox>
</mx:application>
**EXAMPLE (5): State-Specific Properties and Event Handlers**
BEFORE - Classic states syntax (O'Reilly Programming Flex 2):
<mx:application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
<mx:states>
<mx:state name="enabled">
<mx:setproperty target="{textinput}" name="enabled" value="{true}">
<mx:seteventhandler target="{button}" name="click" handler="currentState=''">
<mx:setproperty target="{button}" name="label" value="Disable">
</mx:setproperty></mx:seteventhandler></mx:setproperty></mx:state>
</mx:states>
<mx:hbox id="hbox">
<mx:button id="button" label="Enable" click="currentState='enabled'">
<mx:textinput id="textinput" enabled="false" text="example text">
</mx:textinput></mx:button></mx:hbox>
</mx:application>
AFTER - Inline states syntax:
<mx:application xmlns:mx="library:ns.adobe.com/flex/halo" xmlns:m="http://ns.adobe.com/mxml/2009" layout="absolute">
<m:states>
<m:state name="disabledState">
<m:state name="enabledState">
</m:state></m:state></m:states>
<mx:hbox>
<mx:button id="button" label="Enable" label.enabledstate="Disable" click="currentState='enabled'" click.enabledstate="currentState=''">
<mx:textinput enabled="false" enabled.enabledstate="true" text="example text">
</mx:textinput></mx:button></mx:hbox>
</mx:application>
The state-specific property value syntax can also be used with object based properties…
**EXAMPLE (6): Object-Based Properties**
BEFORE - Classic states syntax:
<mx:application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:states>
<mx:state name="glow">
<mx:setproperty target="{b}" name="filters">
<mx:value>
<mx:array>
<mx:glowfilter>
</mx:glowfilter></mx:array>
</mx:value>
</mx:setproperty>
</mx:state>
</mx:states>
<mx:button label="Button" id="b" click="currentState=currentState=='glow'?'':'glow'">
<mx:filters>
<mx:dropshadowfilter distance="9">
</mx:dropshadowfilter></mx:filters>
</mx:button>
</mx:application>
AFTER - Inline states syntax:
<mx:application xmlns:mx="library:ns.adobe.com/flex/halo" xmlns:m="http://ns.adobe.com/mxml/2009">
<m:states>
<m:state name="default">
<m:state name="glow">
</m:state></m:state></m:states>
<mx:button label="Button" click="currentState=currentState=='glow'?'':'glow'">
<mx:filters>
<mx:dropshadowfilter distance="9">
</mx:dropshadowfilter></mx:filters>
<mx:filters.glow>
<mx:glowfilter>
</mx:glowfilter></mx:filters.glow>
</mx:button>
</mx:application>
<mx:application xmlns:m="http://ns.adobe.com/mxml/2009" xmlns:mx="library:ns.adobe.com/flex/halo">
<m:states>
<m:state name="default">
<m:state name="glow">
</m:state></m:state></m:states>
<mx:button label="Button" click="currentState=currentState=='glow'?'':'glow'">
<mx:filters>
<mx:dropshadowfilter distance="9" includein="default">
<mx:glowfilter includein="glow">
</mx:glowfilter></mx:dropshadowfilter></mx:filters>
</mx:button>
</mx:application>
When state-specific attributes are used with composite states (Overlays), along with mutually exclusive states, the order of precedence is as follows:
* Overlay-specific values in order of declaration of the conditions take priority.
* State-specific values.
* Default value.
### State Groups
If several states within a stateful document are quite similar, and are commonly used together when setting state-specific properties, a "state group" can be created. State groups are essentially state macros that can be used directly within an _includeIn_ or _excludeFrom_, or a state-specific property's scope.
For example, given this case:
<m:states>
<m:state name="A">
<m:state name="B">
<m:state name="C">
<m:state name="D">
</m:state></m:state></m:state></m:state></m:states>
...
<mx:button label.a="SomeLabel" label.c="SomeLabel" label.d="SomeLabel">
<mx:button includein="A,C,D">
<mx:button label.a="SomeLabel" label.b="SomeLabel">
<mx:button includein="A,B">
If one discoveres a pattern of treating a set of states identically in some cases, a state group representing these states can be created and referred to as appropriate.
<m:states>
<m:state name="A" stategroups="G1,G2">
<m:state name="B" stategroups="G2">
<m:state name="C" stategroups="G1">
<m:state name="D" stategroups="G1">
</m:state></m:state></m:state></m:state></m:states>
...
<mx:button label.g1="SomeLabel">
<mx:button includein="G1">
<mx:button label.g2="SomeLabel">
<mx:button includein="G2">
The **stateGroups** attribute accepts a comma delimited list of valid state identifiers (whitespace ignored).
### Custom Creation and Destruction Policies
**itemCreationPolicy**
Historically if one wanted a custom creation policy (immediate vs. deferred instantiated) for a state-specific component instance they would utilize the **creationPolicy** attribute of the _AddChild_ override.
To provide for a similar level of control, a per-item based creation policy _language attribute_ (**itemCreationPolicy**) will be introduced.
Supported values for **itemCreationPolicy** are ItemCreationPolicy.DEFERRED, ItemCreationPolicy.IMMEDIATE. The **itemCreationPolicy** language attribute can be specified on any MXML object supporting the **includeIn** and **excludeFrom** attributes.
An item creation policy of ItemCreationPolicy.DEFERRED is the default, the instance is created when needed.
An item creation policy of ItemCreationPolicy.IMMEDIATE means that the object will be created as soon as the owning document context is initialized.
**EXAMPLE (7.1): Item Creation Policy**
BEFORE - Classic states syntax:
<mx:application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
<mx:states>
<mx:state name="newTextInput">
<mx:addchild relativeto="{checkbox1}" position="after" creationpolicy="all">
<mx:textinput id="textinput">
</mx:textinput></mx:addchild>
</mx:state>
</mx:states>
<mx:vbox id="vbox">
<mx:checkbox id="checkbox1" label="One">
<mx:checkbox id="checkbox2" label="Two">
<mx:button id="button" label="Click" click="currentState='newTextInput'">
</mx:button></mx:checkbox></mx:checkbox></mx:vbox>
</mx:application>
AFTER - Inline states syntax:
<mx:application xmlns:mx="library:ns.adobe.com/flex/halo" xmlns:m="http://ns.adobe.com/mxml/2009" layout="absolute">
<mx:states>
<mx:state name="default">
<mx:state name="newTextInput">
</mx:state></mx:state></mx:states>
<mx:vbox id="vbox">
<mx:checkbox label="One">
<mx:textinput includein="newTextInput" itemcreationpolicy="immediate">
<mx:checkbox label="Two">
<mx:button id="button" label="Click" click="currentState='newTextInput'">
</mx:button></mx:checkbox></mx:textinput></mx:checkbox></mx:vbox>
</mx:application>
**itemDestructionPolicy**
By default, after the framework initially creates a state-specific instance, the instance is cached indefinitely, even after switching to a state where the item is excluded.
An optional **itemDestructionPolicy** _language attribute_ is provided as a means of ensuring a state-specific instance is destroyed upon leaving a state in which it exists. Typically it is more efficient to allow items to be cached, however there are times, such as for rarely visited states, that you may wish not to take the memory hit for a cached instance.
Supported values for **itemDestructionPolicy** are _"never"_ and _"auto"_. The **itemDestructionPolicy** language attribute can be specified on any MXML object supporting the **includeIn** and **excludeFrom** attributes.
An item destruction policy of _"never"_ is the default, all state-specific instances are realized when appropriate and cached indefinitely.
An item destruction policy of _"auto"_ means that the object will be removed from the DOM and all document and framework references to the object cleared, upon leaving a state where the instance exists.
In the example below, the text input instance will be released upon switching to then from, the 'newTextInput' state:
**EXAMPLE (7.2): Item Destruction Policy**
<mx:application xmlns:mx="library:ns.adobe.com/flex/halo" xmlns:m="http://ns.adobe.com/mxml/2009" layout="absolute">
<mx:states>
<mx:state name="default">
<mx:state name="newTextInput">
</mx:state></mx:state></mx:states>
<mx:vbox id="vbox">
<mx:checkbox label="One">
<mx:textinput includein="newTextInput" itemdestructionpolicy="auto">
<mx:checkbox label="Two">
<mx:button id="button" label="Click" click="currentState='newTextInput'">
</mx:button></mx:checkbox></mx:textinput></mx:checkbox></mx:vbox>
</mx:application>
### Some Additional Examples
Here is an example that ties everything together. A real world use case (Flex Media Chat, www.flashcomguru.com)...
**EXAMPLE (8): Flex Media Chat Window**
BEFORE - Classic states syntax:
<mx:application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:states>
<mx:state name="chatState">
<mx:setproperty target="{mainPanel}" name="width" value="80%">
<mx:setproperty target="{mainPanel}" name="height" value="80%">
<mx:removechild target="{submit}">
<mx:removechild target="{female}">
<mx:removechild target="{hbox1}">
<mx:removechild target="{hbox2}">
<mx:removechild target="{username}">
<mx:addchild relativeto="{mainPanel}" position="lastChild">
<mx:vbox width="100%" height="100%" verticalgap="8" verticalalign="middle" horizontalalign="left" id="vbox2">
<mx:hdividedbox width="100%" height="100%" livedragging="true">
<chat:chattextarea id="hist" editable="false" width="75%" height="100%" paddingleft="3" focusalpha="0" htmltext="{chat.chatHistory}">
</chat:chattextarea>
<mx:list id="userlist" height="100%" width="25%" itemrenderer="usersRenderer" dataprovider="{chat.dpUsers}"></mx:list>
</mx:hdividedbox>
<mx:hbox width="100%" verticalalign="middle" horizontalalign="center" id="hbox6">
<mx:hbox width="75%" verticalalign="middle" horizontalalign="center" id="hbox5">
<mx:colorpicker id="picker" tooltip="Font color">
<mx:textinput width="100%" id="msg" paddingleft="3" focusalpha="0" keyup="checkSend(event)" color="{picker.selectedColor}">
<mx:button label="Send" id="send" click="sendMsg()">
</mx:button></mx:textinput></mx:colorpicker></mx:hbox>
<mx:hbox width="25%" verticalalign="middle" horizontalalign="center" id="hbox7">
</mx:hbox>
</mx:hbox>
</mx:vbox>
</mx:addchild>
<mx:setproperty target="{text1}" name="text" value="FlexMediaChat">
<mx:removechild target="{vbox1}">
<mx:setproperty target="{hbox4}" name="width" value="75%">
<mx:setstyle target="{mainPanel}" name="horizontalAlign" value="left">
<mx:setstyle target="{text1}" name="color">
<mx:removechild target="{image1}">
<mx:addchild relativeto="{hbox8}" position="lastChild" target="{image1}">
<mx:removechild target="{text1}">
<mx:addchild relativeto="{hbox8}" position="lastChild" target="{text1}">
<mx:removechild target="{hbox4}">
<mx:addchild relativeto="{hbox9}" position="lastChild" target="{hbox4}">
<mx:setproperty target="{hbox9}" name="width" value="100%">
<mx:addchild relativeto="{hbox4}" position="lastChild">
<mx:spacer width="80%" height="100%">
</mx:spacer></mx:addchild>
</mx:setproperty></mx:addchild></mx:removechild></mx:addchild></mx:removechild></mx:addchild></mx:removechild></mx:setstyle></mx:setstyle></mx:setproperty></mx:removechild></mx:setproperty></mx:removechild></mx:removechild></mx:removechild></mx:removechild></mx:removechild></mx:setproperty></mx:setproperty></mx:state>
</mx:states>
<mx:panel width="410" height="210" layout="vertical" id="mainPanel" horizontalalign="center" headerheight="10" verticalalign="middle" fontsize="12" paddingtop="10" paddingleft="10" paddingright="10" paddingbottom="10" verticalscrollpolicy="off" horizontalscrollpolicy="off">
<mx:hbox width="97%" id="hbox9">
<mx:hbox width="97%" id="hbox4" horizontalalign="left">
<mx:image source="assets/internet-group-chat.png" id="image1">
<mx:text text="User Login" fontweight="bold" fontsize="18" id="text1" selectable="false" color="#333333">
</mx:text></mx:image></mx:hbox>
<mx:hbox id="hbox8" horizontalalign="right">
</mx:hbox>
</mx:hbox>
<mx:vbox height="92%" width="95%" horizontalscrollpolicy="off" id="vbox1">
<mx:spacer width="100%" height="6">
<mx:hbox width="100%" id="hbox1">
<mx:text text="Username:">
<mx:textinput id="username" width="269" focusalpha="0" enter="connect(event)">
</mx:textinput></mx:text></mx:hbox>
<mx:hbox width="100%" id="hbox2">
<mx:radiobuttongroup id="gender">
<mx:text text="Gender:">
<mx:spacer width="16" height="100%">
<mx:image id="maleicon" source="assets/male_login.png">
<mx:radiobutton label="male" groupname="gender" selected="true" id="male">
<mx:image id="femaleicon" source="assets/female_login.png">
<mx:radiobutton label="female" groupname="gender" id="female" selected="false">
</mx:radiobutton></mx:image></mx:radiobutton></mx:image></mx:spacer></mx:text></mx:radiobuttongroup></mx:hbox>
<mx:spacer width="100%" height="7">
<mx:hbox width="100%" id="hbox3" horizontalalign="right">
<mx:image source="assets/dialog-warning.png" id="warning">
<mx:text color="#e60000" id="status" text="Text">
<mx:spacer width="100%">
<mx:button label="Connect" click="connect( event )" id="submit" width="110" height="34" icon="@Embed('assets/go-next.png')">
</mx:button></mx:spacer></mx:text></mx:image></mx:hbox>
</mx:spacer></mx:spacer></mx:vbox>
</mx:panel>
</mx:application>
AFTER - Inline states syntax:
<mx:application xmlns:mx="library:ns.adobe.com/flex/halo" xmlns:m="http://ns.adobe.com/mxml/2009" m:version="4">
<m:states>
<m:state name="defaultState">
<m:state name="chatState">
</m:state></m:state></m:states>
<mx:panel width="410" width.chatstate="80%" height="110" height.chatstate="80%" layout="vertical" id="mainPanel" horizontalalign="center" horizontalalign.chatstate="left" headerheight="10" verticalalign="middle" fontsize="12" paddingtop="10" paddingleft="10" paddingright="10" paddingbottom="10" verticalscrollpolicy="off" horizontalscrollpolicy="off">
<mx:hbox width="97%" width.chatstate="100%">
<mx:hbox width="97%" width.chatstate="80%" id="hbox4" horizontalalign="left">
<mx:image source="assets/internet-group-chat.png" id="image1">
<mx:text text="User Login" text.chatstate="FlexMediaChat" fontweight="bold" fontsize="18" id="text1" selectable="false" color="#333333" color.chatstate="">
<mx:spacer width="80%" height="100%" includein="chatState">
</mx:spacer></mx:text></mx:image></mx:hbox>
<mx:hbox horizontalalign="right">
<mx:reparent target="{image1}" includein="chatState">
<mx:reparent target="{text1}" includein="chatState">
</mx:reparent></mx:reparent></mx:hbox>
<mx:reparent target="{hbox4}" includein="chatState">
</mx:reparent></mx:hbox>
<mx:vbox height="92%" width="95%" horizontalscrollpolicy="off" includein="defaultState">
<mx:spacer width="100%" height="6">
<mx:hbox width="100%" includein="defaultState">
<mx:text text="Username:">
<mx:textinput id="username" width="269" focusalpha="0" enter="connect(event)" includein="defaultState">
</mx:textinput></mx:text></mx:hbox>
<mx:hbox width="100%" includein="defaultState">
<mx:radiobuttongroup>
<mx:text text="Gender:">
<mx:spacer width="16" height="100%">
<mx:image id="maleicon" source="assets/male_login.png">
<mx:radiobutton label="male" groupname="gender" selected="true" id="male">
<mx:image source="assets/female_login.png">
<mx:radiobutton label="female" groupname="gender" selected="false" includein="defaultState">
</mx:radiobutton></mx:image></mx:radiobutton></mx:image></mx:spacer></mx:text></mx:radiobuttongroup></mx:hbox>
<mx:spacer width="100%" height="7">
<mx:hbox width="100%" horizontalalign="right">
<mx:image source="assets/dialog-warning.png" id="warning">
<mx:text color="#e60000" id="status" text="Text">
<mx:spacer width="100%">
<mx:button label="Connect" click="connect( event )" id="submit" width="110" height="34" icon="@Embed('assets/go-next.png')" includein="defaultState">
</mx:button></mx:spacer></mx:text></mx:image></mx:hbox>
</mx:spacer></mx:spacer></mx:vbox>
<mx:vbox width="100%" height="100%" verticalgap="8" verticalalign="middle" horizontalalign="left" includein="chatState">
<mx:hdividedbox width="100%" height="100%" livedragging="true">
<chat:chattextarea editable="false" width="75%" height="100%" paddingleft="3" focusalpha="0" htmltext="{chat.chatHistory}">
</chat:chattextarea>
<mx:list height="100%" width="25%" itemrenderer="usersRenderer" dataprovider="{chat.dpUsers}"></mx:list>
</mx:hdividedbox>
<mx:hbox width="100%" verticalalign="middle" horizontalalign="center">
<mx:hbox width="75%" verticalalign="middle" horizontalalign="center">
<mx:colorpicker id="picker" tooltip="Font color">
<mx:textinput width="100%" id="msg" paddingleft="3" focusalpha="0" keyup="checkSend(event)" color="{picker.selectedColor}">
<mx:button label="Send" id="send" click="sendMsg()">
</mx:button></mx:textinput></mx:colorpicker></mx:hbox>
<mx:hbox width="25%" verticalalign="middle" horizontalalign="center">
</mx:hbox>
</mx:hbox>
</mx:vbox>
</mx:panel>
</mx:application>
And lastly, a Flex 4 button skin example, noting first the classic syntax, followed by the inline syntax.
**EXAMPLE (9): Flex 4 Button Skin**
BEFORE - Classic states syntax:
<skin xmlns:mx="http://www.adobe.com/2006/mxml">
<states>
<mx:state name="up">
<mx:state name="over">
<mx:setproperty target="{s}" name="color" value="0x6666BB">
<mx:setproperty target="{e2}" name="color" value="0xF0F0F0">
</mx:setproperty></mx:setproperty></mx:state>
<mx:state name="down" basedon="over">
<mx:setproperty target="{e1}" name="color" value="0xBBBBDD">
<mx:setproperty target="{e2}" name="color" value="0xBBBBDD">
</mx:setproperty></mx:setproperty></mx:state>
<mx:state name="disabled">
<mx:setproperty target="{s}" name="color" value="0xAAAAAA">
<mx:setproperty target="{e2}" name="color" value="0xF0F0F0">
</mx:setproperty></mx:setproperty></mx:state>
</mx:state></states>
<content>
<mx:graphic left="0" top="0" right="0" bottom="0" scalegridleft="6" scalegridtop="6" scalegridright="44" scalegridbottom="14">
<mx:rect width="50" height="20" radiusx="6" radiusy="6">
<mx:fill>
<mx:solidcolor id="s" color="0x666666">
</mx:solidcolor></mx:fill>
</mx:rect>
<mx:rect width="48" height="18" x="1" y="1" radiusx="5" radiusy="5">
<mx:fill>
<mx:lineargradient rotation="90">
<mx:gradiententry id="e2" color="0xFFFFFF" alpha="0.8">
<mx:gradiententry id="e1" color="0xDEDEDE" alpha="0.6">
</mx:gradiententry></mx:gradiententry></mx:lineargradient>
</mx:fill>
</mx:rect>
</mx:graphic>
<contentholder horizontalcenter="0" verticalcenter="1" left="10" right="10" content="{data.content}" layout="flex.layout.HorizontalLayout">
</contentholder></content>
</skin>
AFTER - Inline states syntax:
<skin xmlns:mx="library:ns.adobe.com/flex/halo" xmlns:m="http://ns.adobe.com/mxml/2009">
<m:states>
<m:state name="up">
<m:state name="over">
<m:state name="down">
<m:state name="disabled">
</m:state></m:state></m:state></m:state></m:states>
<content>
<mx:graphic left="0" top="0" right="0" bottom="0" scalegridleft="6" scalegridtop="6" scalegridright="44" scalegridbottom="14">
<mx:rect width="50" height="20" radiusx="6" radiusy="6">
<mx:fill>
<mx:solidcolor color="0x666666" color.over="0x6666BB" color.down="0x6666BB" color.disabled="0xAAAAAA">
</mx:solidcolor></mx:fill>
</mx:rect>
<mx:rect width="48" height="18" x="1" y="1" radiusx="5" radiusy="5">
<mx:fill>
<mx:lineargradient rotation="90">
<mx:gradiententry color="0xFFFFFF" color.down="0xBBBBDD" color.over="0xF0F0F0" color.disabled="0xF0F0F0" alpha="0.8">
<mx:gradiententry color="0xDEDEDE" color.down="0xBBBBDD" alpha="0.6">
</mx:gradiententry></mx:gradiententry></mx:lineargradient>
</mx:fill>
</mx:rect>
</mx:graphic>
<contentholder horizontalcenter="0" verticalcenter="1" left="10" right="10" content="{data.content}" layout="flex.layout.HorizontalLayout">
</contentholder></content>
</skin>
## B Features
----
**Stateful XML/E4X Nodes** - There is an ask to allow descendants of XML and XMLList tags to support the new states syntax. If the feature is green-lit at a later date, an associated mini-spec will be published.
**Stateful Model Nodes** - There is an ask to allow descendants of MXML datamodel (mx:Model) nodes to support the new states syntax. If the feature is green-lit at a later date, an associated mini-spec will be published.
**Enhanced Runtime API** - As a fit and finish task, it would be prudent to update the runtime states API to follow closer to the way the new syntax works. e.g. A helper would be provided that would allow a developer to setPropertyForState(object, property, state) for instance. Or specifically set the include or exclude list for a given component instance. Essentially an API divorced from the notion of the current runtime States and Overrides model. When the work is done on this feature, a mini-spec will be circulated.
## Additional Implementation Details
----
### Implementation Design and Implications
#### A Phased Approach
As mentioned previously, the states concept as first introduced in Flex 2.x and carried forward in Flex 3.0 will be promoted to a first-class MXML language feature for Flex 4.0. This means, for instance, that state-specific objects will no longer be limited to visual children (UIComponents).
In order to get to a point where our tooling products can begin utilizing the new language features, we will phase in the functionality in stages.
1. Introduce the new syntax, and retrofit the compiler to be 'state-aware'. Initially the compiler will lean on our existing States infrastructure and will automatically generate the states and overrides to represent the dynamic state-specific content. The current IOverride based classes will be modified and extended as needed during this phase to account for the new functionality.
\\ \\ During this phase it is expected that the current runtime API to manipulate states will remain intact (e.g. developers will still be able to selectively create and overrides and add/insert them into state override arrays.) The special attributes includeIn, excludeFrom, and state-specific attribute syntax are not valid at runtime. \\ \\
1. The second phase will be focused on allowing other custom components (non UIComponents) to leverage the states language features, (e.g. any component implementing an IStateClient2 interface for instance) such that state changes relative to that component can be interpreted in a custom manner. UIComponent will be migrated to utilize the more generic interface, and we will explore further runtime representations of state change (beyond the state and override runtime objects) to improve on runtime performance. Additionally we will enhance the runtime states APIs to be more consistent with the new syntax. An addendum to this specification (a mini-spec) will be distributed prior to development detailing the changes in the second phase of work.
#### Phase One Compiler and Framework Changes
##### Compiler Changes
The MXML sub-compiler will be enhanced with direct support for states as follows:
* During the interface compilation phase, the set of states will be noted and used for validation in successive compilation phases.
* During the implementation compilation phase, the compiler will collect and coallesce all scattered shared objects (including their parent context), and state-specific attribute values. IDs for shared object parents will automatically be generated via MxmlDocument.ensureId() and slots allocated for AddItems targets. Additionally, all Reparent tags will be parsed and noted. All special attributes (includeIn, excludeFrom, and state-specific node properties) are detected and handled primarily within the ComponentBuilder module. All state-specific objects and properties are registered with the root MxmlDocument and its underlying stateful model prior to code generation.
* Any data-bound state-specific values will be modified such that the binding target becomes the property or style override instance, rather than the object instance.
* The compiler will flag syntactic errors when/as detected:
* Any ambiguous or invalid object DOM issue (e.g. An instance is reparented to two locations at once) will be flagged during the builder phase.
* Any reference to a non-declared state will be considered invalid.
* All state-specific values will be type checked.
* During the code generation phase, state related code and initialization will be generated within the component's initialize() routine, consisting of the collection of states and overrides gathered in the earlier phase. State-specific object instances that are shared between states will be declared once and shared between AddItems instances.
* In order to determine what _currentState_ semantics to adhere to at runtime (e.g. whether or not the null state is valid for a given stateful component), the compiler will automatically ensure all Flex 4 stateful component instances support the IStateClient2 interface. The presence of this interface at runtime dictates Flex 4 runtime states semantics.
##### SDK/API Changes
* All overrides will be modified to allow for their 'destination' and/or 'target' properties to accept a string based id (vs. binding reference), this is consistent with the approach that AddItems uses, and allows for reduction of the number of binding instances per state.
* An **itemCreationPolicy** will be introduced to allow for per display object creation policy, since the equivalent _AddChild_ mechanism is no longer applicable.
* In order to allow for any element of an array based property to make use of state-specific instancing, we will make use of the new Flex 4 override _AddItems_.
* All overrides will be modified to allow for initialization from a properties descriptor, this will allow for a more compact form of state related code generation.
#### Nice To Have:
* The set of available overrides will be expanded to provide for batch property and style setting (e.g. _SetProperties_, _SetStyles_). This is primarily only a modest performance related change, to help minimize the number of overrides within a given state.
## Prototype Work
----
The bulk of the necessary compiler changes have been prototyped and passed along to the compiler team for review. An analysis of the changes with regards to performance was also done, using our stock performance automation tests, with good results.
## Compiler Work
----
Please refer to the preceding [#Implementation Design and Implications](%23Implementation%20Design%20and%20Implications) section.
## Web Tier Compiler Impact
----
_Not Applicable._
## Flex Feature Dependencies
----
This feature is dependent on any state-related features such as Overlays, Effects, Transitions.
## Backwards Compatibility
----
### Syntax changes
The legacy states syntax will be deprecated in favor of what is detailed here. A mechanism will be provided to utilize the classic states syntax if desired but only by opting out of the Flex 4 model altogether (e.g. via -compatibility-version or by removing any MXML 2009 (Flex 4) namespace declarations).
### Behavior
_Not applicable_
### Warnings/Deprecation
A deprecation related warning will be issued if the use of Override children of states are used within a Flex 4 document.
## Accessibility
----
_Not Applicable._
## Performance
----
The new syntax as interpreted by the compiler results in generated code comparable to the current Flex 3 runtime states model, so no performance regressions or injections should be introduced (e.g. the IOverride based classes are still utilized at runtime to accomplish state changes).
## Globalization
----
_Not Applicable._
## Localization
----
### Compiler Features
The following state syntax related error and warning messages have been added to compiler_en.properties and require translation:
**StateResolutionError** - Cannot resolve state '$(name)'.
**AmbiguousStateFilterError** - The includeIn and excludeFrom keywords may not be specified concurrently.
_...more will be added here as necessary_.
There are no help description or linker message additions at this time.
### Framework Features
_Not Applicable._
## Issues and Recommendations
----
* *What about validation, and other XML legalities, around the new syntax?* The 'dot' character is a valid in XML attributes so the documents will be well-formed. However, as with Flex 2 and Flex 3, MXML continues to not be compatible with validation due to the dynamic nature of the language. e.g. Custom component tags, custom styles, etc. We aren't necessarily making things worse. An additional note on the subject, XAML chose to utilize dot notation to scope attributes to parent containers with their "attached properties" feature, so there is a precedent.
* *When porting from the old syntax to new, specifically SetStyle instances, it appears that the new syntax encourages setting inline styles? Isn't this a bad thing?* If there is heavy use of styles in a stateful document, the developer is strongly encouraged to migrate their styles to a stylesheet, and apply state-specific class names to 'styleName' instead. Flex 4 will also most likely support pseudo-selectors that would be state aware which will allow for authoring state-aware style cascades.
## Documentation
----
The new states functionality represents a significant overhaul to the way stateful documents and components are authored with MXML. An equally as significant documentation revision around the view states feature is required, detailing not only the new language keywords, but also providing comprehensive examples.
## QA
----
Suggested focus areas and test cases to consider (not exhaustive):
* Components without 2009 language namespace (MXML 4) declared should support only legacy states syntax.
* Components with 2009 language namespace (MXML 4) declared should support only newer states syntax.
* includeIn property can only reference states previously declared within the mx:states array.
* excludeFrom property can only reference states previously declared within the mx:states array.
* Test that includeIn/excludeFrom work on any UIComponent instance that is an instance of the pseudo-array property 'children' (dom child or a parent container or another UIComponent).
* Test that includeIn/excludeFrom works on any array element node (ContentHolder child, filters, graphics tag segments, etc.).
* Test that includeIn/excludeFrom, when used on a scalar object property value, generates an error message.
* State names are limited to identifiers that can be _both_ valid XML attributes (per XML 1.0 specification), _and_ valid AS3 identifiers (e.g. limited to primarily alpha numeric characters with some exceptions (underscore, etc)).
* State-specific event-handlers.
* State-specific effect triggers.
* State-specific styles.
* State-specific styles should be able to 'reset' a style to null, such that cascade applies it's value (vs. default style). e.g. color="0xFF0000" color.stateA=""
* State-specific properties where value is a binding instance.
* State-specific attribute syntax cannot be used with 'special' built-in language attributes (frameRate, id, etc.).
* Test that state-specific attribute syntax works on object based properties and when child node attributes syntax is used (vs. inline xml attributes).
* Historically State property and style overrides utilizing binding, would not update after a binding changes (only when state changed). We should ensure this legacy 'bug' is addressed with the newer changes.
* State specific properties.
* The Reparent tag must not describe invalid DOM (circular references, invalid child/parent relationships).
* The Reparent tag can only reparent a target to another location that accepts the type of instance.
* A state-specific node cannot be reparented to multiple parents within the same state.
* Test that if currentState is null by default, the first defined state becomes the 'initial' value of currentState automatically.
----
[[ include ref='flexsdk_rightnav' ]]
[[ include ref='site:open_commentlogin' ]]
</mx:button></mx:button></mx:button></mx:button></mx:button></mx:button></mx:button></mx:button></button>