Table of Contents
This chapter discusses the general use of states and the built in states dragstate and resizestate.
States are a convenient method of defining multiple complex behaviors in your application using declarative syntax, behaviors that might normally be contained in a script block.
States are written within the object to which the state is applied and can contain any number of children. 
               All code in a <state>
               
                is written as if it were directly inside the parent of the state when it is applied.  This concept sounds 
               a bit abstract, but in practice seems quite natural, as we hope the following discussion will make clear.
            
               Declarative programming is great for declaring the initial state of an application, but 
               subsequent transformations may make the originally declared structures barely recognizable. 
               Laszlo's <state>
               
                construct provides a way to make declarative constructs effectively procedural.
               
            
The alternative to using states is to declare the initial state of your program with tags, and then manipulate that state with procedural code, that is, with script. This poses a problem, because some of LZX's most powerful features are difficult to add programmatically.
This is particularly true of animators and constraints. Constraints are central to the whole Laszlo idea, but manipulating them with script can be very tricky. For instance, here's a small program where the blue box follows the mouse:
Example 32.1. Following mouse events without states
<canvas width="100%">
  <view bgcolor="blue" width="20" height="20">
    <attribute name="x" value="${parent.getMouse('x') - 10}"/>
    <attribute name="y" value="${parent.getMouse('y') - 10}"/>
  </view>
</canvas>
<!-- * X_LZ_COPYRIGHT_BEGIN ***************************************************
* Copyright 2007, 2008 Laszlo Systems, Inc.  All Rights Reserved.                   *
* Use is subject to license terms.                                            *
* X_LZ_COPYRIGHT_END ****************************************************** -->
                  While this is a nice way of expressing this kind of thing (made possible by Laszlo's constraint system), it's rarely useful in a program. Usually, objects only follow the mouse when they're being dragged. What's needed for that is a way to write declarative LZX nodes that could be applied and removed depending on whether the view is to be dragged or not.
               The <state> tag makes this possible. Here's a rewrite of the above program using states to make the blue 
               box drag only when the mouse is down:
               
            
Example 32.2. Using states to follow mouse
<canvas width="100%">
  <view bgcolor="blue" width="20" height="20" onmousedown="this.setAttribute('mouseIsDown', true )" onmouseup="this.setAttribute('mouseIsDown', false )">
    <attribute name="mouseIsDown" value="false"/>
    <handler name="onmouseIsDown">
        if(mouseIsDown == true){
            ds.setAttribute('applied', true);
        } else {
            ds.setAttribute('applied', false);
        }
    </handler>
    <state name="ds">
      <attribute name="x" value="${parent.getMouse('x') - 10}"/>
      <attribute name="y" value="${parent.getMouse('y') - 10}"/>
    </state>
  </view>
</canvas>
<!-- * X_LZ_COPYRIGHT_BEGIN ***************************************************
* Copyright 2008 Laszlo Systems, Inc.  All Rights Reserved.                   *
* Use is subject to license terms.                                            *
* X_LZ_COPYRIGHT_END ****************************************************** -->
                  
               Note that the syntax of the constraints hasn't changed; they're just inside a <state> tag. 
               This is useful, but it's also a little strange: the <state> tag is essentially an invisible node of 
               hierarchy. You can see this in the fact that the parent in the apply constraint for the state is
                not the same object as the parent in the drag constraints inside the state.
               
            
               This example highlights the metaphysical nature of states: they modify the meta-object protocol enough so that
                their contents can be stored and applied elsewhere. (This could conceivably be a feature of the system as a whole 
                as in, for example, an lz.node.setParent(otherNode), but it's not). 
               
            
Here's a question: what should happen when you write this?
Example 32.3. attributes of states
  <class name="myDragState" extends="state">
    <attribute name="dragMin" value="2"/>
    <attribute name="dragMax" value="20"/>
    <!-- ... -->
  </class>
                  Do the attributes dragMin and dragMax pertain to the state itself, 
                  or to the state's container? The former is more powerful: it would allow for developers to extend the special behavior of
                  states, 
                  say by over-riding the state's apply method. The latter, though, is more consistent with the LZX idiom, where, 
                  as a first-order approximation, a class behaves like a macro.
                  
               
The answer is, the behavior is the latter: attributes apply to the state's container. Here's a little test program that shows that.
Example 32.4. Attributes pertain to container, not to parent
<canvas width="100%">
  <class name="constrainedDragState" extends="state">
    <attribute name="dragMin" value="100"/>
    <attribute name="dragMax" value="300"/>
    <attribute name="mousePos" value="${parent.getMouse( 'x' ) - 10}"/>
    <attribute name="x" value="${Math.max(Math.min(this.dragMax, this.mousePos), this.dragMin )}"/>
  </class>
  
  <view bgcolor="blue" width="20" height="20" x="100" y="50" onmousedown="myDrag.apply()" onmouseup="myDrag.remove()">
    <attribute name="mouseIsDown" value="false"/>
    <constrainedDragState name="myDrag"/>
  </view>
</canvas>
<!-- * X_LZ_COPYRIGHT_BEGIN ***************************************************
* Copyright 2007, 2008 Laszlo Systems, Inc.  All Rights Reserved.                   *
* Use is subject to license terms.                                            *
* X_LZ_COPYRIGHT_END ****************************************************** -->
                     
                  Note that the references to dragMin, dragMax and such are all qualified by the keyword this.
                  
               
                  Any attribute for which the state has a setter belongs to the state itself, 
                  whereas any attribute that doesn't belongs to the state's apply target. This makes sense, 
                  because any setter for an attribute which is intended to be applied by the state 
                  (and not kept by the state) can be written in the apply target. 
                  This how it  works in LZX. Here's a little program that proves that:
               
Example 32.5. Using setters in <state> attributes
<canvas height="200" width="100%">
  <class name="testState" extends="state">
    <attribute name="countApplies" type="number" value="0" setter="this.countApplies = countApplies"/>
    <handler name="onapplied"><![CDATA[
      
        if(this.applied == true){
            this.setAttribute('countApplies', this['countApplies'] >= 0 ? ++this.countApplies : 1);
        }
        
    ]]></handler>
  </class>
  <button>Try it
    <handler name="onclick">
      ts.setAttribute('applied', true);
      message.addText("\napplies: " + ts.countApplies);
      ts.setAttribute('applied', false);
    </handler>
    <testState name="ts"/>
  </button>
  <text id="message" y="30" multiline="true"/>
</canvas>
<!-- * X_LZ_COPYRIGHT_BEGIN ***************************************************
* Copyright 2008 Laszlo Systems, Inc.  All Rights Reserved.                   *
* Use is subject to license terms.                                            *
* X_LZ_COPYRIGHT_END ****************************************************** -->
                     In states, the "this" keyword refers to the view or node that state is nested inside of. Methods nested inside of a state apply to the view. There is an exception to the above rule: when listening to the onapply or onremove events, the methods apply to the state, and the "this" keyword points to the state.
All states are instantiated. Therefore your application "pays the instantiation cost" of a regular node 
                  of hierarchy for a state, whether or not it is applied. This is because the state is itself an lz.node,
                   which must be processed by the lz.node constructor.
               
The advantage of limiting the ways in which a developer can modify a state itself is that then a given state can have a limited number of attributes, which are controlled by the runtime. Allowing developers to change the semantics of "state" by attaching attributes and methods to it would make it harder to make this optimization.
Example 32.6. Using states to animiate transitions
<canvas width="100%">
  <window title="state demo" width="400" height="300" oninit="this.max.setAttribute('applied', true)">
    <state name="max">
      <animatorgroup duration="1000" process="simultaneous">
        <animator attribute="width" to="400"/>
        <animator attribute="height" to="300"/>
        <animator attribute="x" to="100"/>
        <animator attribute="y" to="100"/>
      </animatorgroup>
      <text align="center" y="20%">M a x i m i z e d</text>
    </state>
    <state name="min">
      <animatorgroup duration="1000" process="simultaneous">
        <animator attribute="width" to="170"/>
        <animator attribute="height" to="100"/>
        <animator attribute="x" to="0"/>
        <animator attribute="y" to="0"/>
      </animatorgroup>
      <text align="center" valign="middle">Minimized</text>
    </state>
    <button placement="title_area" align="right" height="16"> Toggle
      <attribute name="isMax" value="true"/>
      <handler name="onclick">
        if (this.isMax) {parent.max.setAttribute('applied', false); parent.min.setAttribute('applied', true);}
        else {parent.max.setAttribute('applied', true); parent.min.setAttribute('applied', false);}
        this.isMax = !this.isMax;
      </handler>
    </button>
</window>
</canvas>
<!-- * X_LZ_COPYRIGHT_BEGIN ***************************************************
* Copyright 2008 Laszlo Systems, Inc.  All Rights Reserved.                   *
* Use is subject to license terms.                                            *
* X_LZ_COPYRIGHT_END ****************************************************** -->
                     
                     The state element is declared with the apply, onapply, and
                     onremove attributes, and the <view>
                  
                  .  apply, 
                  onapply,
                     and onremove control the behavior of the state itself.  Any other
                     attributes and children are applied to the state's parent, when
                     the state is applied.
                     
               
                  If the state is a child of an element that is not a view,
                     such as a <layout>
                  
                   or <animator>
                  
                  , then the view attributes may not
                     make sense.  It is possible to attach an attribute that applies
                     to one of these other elements to a state, by using
                     the <attribute>
                  
                   element.
                  
               
States can also contain views or classes that are only created when the state is applied.
<state name="showchildren">
  <view y="13" x="13" name="children">
    <simplelayout/>
    <treeitem grown="${parent.opened}">
      <datapath xpath="*" pooling="true"/>
    </treeitem>
   </view>
</state>
            
                  The <state> tag does not define classroot.  Therefore, its sublasses don't have it either.
                  If you subclass state you don't get classroot.
               
<class name="redState" extends="state" />
will not have classroot defined.
You can subclass <state> to suit whatever purpose is at hand. LZX contains two such subclasses of <state> 
                  to solve common problems.
               
This example shows how to subclass the <dragstate>
                  
                   class to create a state functionality that you can apply to
                   different views. 
               
Example 32.7. Dropshadow done using states
<canvas height="200" width="100%">
  <class extends="dragstate" name="fadeDragger" pooling="true">
    <handler name="onapply">
      parent.bringToFront();
      parent.setAttribute('opacity', .5)
    </handler>
    <handler name="onremove">
      parent.setAttribute('opacity', 1)
    </handler>
    <view name="hShadow" x="10" y="${parent.body.height}" width="${parent.body.width}" height="10" opacity=".2" bgcolor="black"/>
    <view name="vShadow" x="${parent.body.width}" y="10" width="10" height="${parent.body.height - 10}" opacity=".2" bgcolor="black"/>
  </class>
  
  <view onmousedown="myFadeDragger.apply()" onmouseup="myFadeDragger.remove()">
    <fadeDragger name="myFadeDragger"/>
    <view name="body" width="40" height="40" bgcolor="blue"/>
  </view>
  <view x="100" y="100" onmousedown="myFadeDragger.apply()" onmouseup="myFadeDragger.remove()">
    <fadeDragger name="myFadeDragger"/>
    <view name="body" width="60" height="60" bgcolor="red"/>
  </view>
</canvas>
<!-- * X_LZ_COPYRIGHT_BEGIN ***************************************************
* Copyright 2007, 2008 Laszlo Systems, Inc.  All Rights Reserved.                   *
* Use is subject to license terms.                                            *
* X_LZ_COPYRIGHT_END ****************************************************** -->
                     Copyright © 2002-2010 Laszlo Systems, Inc. All Rights Reserved. Unauthorized use, duplication or distribution is strictly prohibited. This is the proprietary information of Laszlo Systems, Inc. Use is subject to license terms.