/*
 * The qx.util.fsm package.
 *
 * Example:
 *
 * <pre class="javascript">
 * var fsm;
 * var state;
 * var trans;
 *
 * // Create a new finite state machine called "Test Machine"
 * fsm = new qx.util.fsm.FiniteStateMachine("Test machine");
 *
 * // State S1
 * state = new qx.util.fsm.State(
 *   // State name
 *   "S1",
 *
 *   // Object with state information
 *   {
 *     // Function called on entry to this state
 *     "onentry" :
 *       function(fsm, event)
 *       {
 *         alert("Previous state: " + fsm.getPreviousState());
 *       };
 *
 *     // Function called on exit from this state
 *     "onexit" :
 *       function(fsm, event)
 *       {
 *         alert("Next state: " + fsm.getNextState());
 *       };
 *
 *     // Automatic actions to take place before a (possibly) new state's
 *     // onentry function is called.
 *     "autoActionsBeforeOnentry" :
 *     {
 *       // The name of a function.
 *       "setEnabled" :
 *       [
 *         {
 *           // The parameter value(s), thus "setEnabled(true);"
 *           "parameters"   : [ true ],
 *
 *           // The function would be called on each object:
 *           //  this.getObject("obj1").setEnabled(true);
 *           //  this.getObject("obj2").setEnabled(true);
 *           "objects" : [ "obj1", "obj2" ]
 *
 *           // And similarly for each object in each specified group.
 *           "groups"  : [ "group1", "group2" ],
 *         }
 *       ];
 *
 *       "setColor" :
 *       [
 *         {
 *           "parameters" : [ "blue" ]
 *           "groups"     : [ "group3", "group4" ],
 *           "objects"    : [ "obj3", "obj4" ]
 *         }
 *       ];
 *     };
 *
 *     // also available, in same format as actionsBeforeOnentry:
 *     //   "autoActionsAfterOnentry",
 *     //   "autoActionsBeforeOnexit"
 *     //   "autoActionsAfterOnexit"
 *
 *     // Events handled by this state, or queued for processing by a future
 *     // state
 *     "events" :
 *     {
 *       // The event type "compete" is handled by one of the transitions in
 *       // this state.  The transitions will be searched in order of their
 *       // addition to the state, until the predicate for a transition
 *       // returns true (or no predicate is specified for the transition,
 *       // which is an implicit "true") That transition will be used.
 *       "complete"  : qx.util.fsm.FiniteStateMachine.EventHandling.PREDICATE,
 *
 *       // The event type "interval" has two objects specified by their
 *       // "friendly name".  The action when an event of type "interval"
 *       // occurs depends on which object was the target of the event.
 *       "interval"  :
 *       {
 *         // If the target of the event was the object to which we have given
 *         // the friendly name "flash" then use a transition specified by
 *         // name
 *         "flash"   : "S1_S3_interval_flash",
 *
 *         // If the target of the event was the object to which we have given
 *         // the friendly name "timeout", then enqueue this event for
 *         // possible processing by a future state.
 *         "timeout" : qx.util.fsm.FiniteStateMachine.EventHandling.BLOCKED
 *       },
 *
 *         // The event type "execute", too, has two objects specified by
 *         // their "friendly name".
 *       "execute"   :
 *       {
 *         // If the target of the event was the object to which we have given
 *         // the friend name "ok", search the transitions in order looking
 *         // for one where the predicate is true
 *         "ok"      : qx.util.fsm.FiniteStateMachine.EventHandling.PREDICATE
 *
 *         // If the target of the event was the object to which we have given
 *         // the friendly name "restart", then enqueue this event for
 *         // possible processing by a future state.
 *         "restart" : qx.util.fsm.FiniteStateMachine.EventHandling.BLOCKED
 *       }
 *
 *       // all events other than those which are handled or blocked are
 *       // ignored.
 *     };
 *   });
 *
 * // Add State S1 to the finite state machine.
 * fsm.addState(state);
 *
 * // Transition from S1 to S2 due to event 1
 * trans = new qx.util.fsm.Transition(
 *   // Transition name
 *   "S1_S2_ev1",
 *
 *   // Object with transition information
 *   {
 *     // return TRUE to pass
 *     "predicate" :
 *       function(fsm, event)
 *       {
 *         var type = event.getType();
 *         if (type == "somethingWeCareAbout")
 *         {
 *           return true;
 *         }
 *         else if (type == "somethingToHandleInAnotherState")
 *         {
 *           // reattempt event delivery following state transition
 *           fsm.postponeEvent(event);
 *
 *           // do no further transition attempts for this event for now
 *           return null;
 *         }
 *         else
 *         {
 *           return false;
 *         }
 *       },
 *
 *     // if event matches and predicate passes, pop the state stack and go to
 *     // the state which was found at the top of the stack.  States are added
 *     // to the state stack by calling fsm.pushState() during a state's
 *     // onexit function or by a transition's action function.
 *     "nextState" : qx.util.fsm.FiniteStateMachine.StateChange.POP_STATE_STACK,
 *
 *     // action taken during transisition
 *     "action"    :
 *       function(fsm, event)
 *       {
 *         // save current state so a future transition can get back to
 *         // this saved state
 *         fsm.pushState();
 *       }
 *   });
 * state.addTransition(trans);
 *
 * // Default transition (any event): remain in current state
 * trans = new qx.util.fsm.Transition(
 *   "S1_S1_default",
 *   {
 *     // true or undefined : always pass
 *     "predicate" :
 *       function(fsm, event)
 *       {
 *         // This predicate does not pass, and we return null to tell the
 *         // finite state machine that no additional transitions in the
 *         // transition list should be tested.  (Note that the next
 *         // transition is the one explicitly called for by the "interval"
 *         // event on the object with friendly name "flash".  We do not want
 *         // a predicate search to find it.
 *         return null;
 *       },
 *
 *     // return to current state
 *     "nextState" : qx.util.fsm.FiniteStateMachine.StateChange.CURRENT_STATE,
 *   });
 * state.addTransition(trans);
 *
 * // Transition from S1 to S2 due to event 2.  Since the previous transition
 * // returned null in its predicate function, the only way to get to this
 * // transition is when it is called out explicitly in the state's event
 * // list.  This one was specified for the "interval" event on the object
 * // with friendly name "flash".
 * trans = new qx.util.finitestatememachine.Transition(
 *   "S1_S3_interval_flash",
 *   {
 *     // No predicate or a value of 'true' means that the predicate passes as
 *     // if a predicate function returned true.
 *     "predicate" : true,
 *
 *     // if event matches, go to this state
 *     "nextState" : "S2",
 *
 *     // action taken during transisition
 *     "action"    :
 *       function(fsm, event)
 *       {
 *         alert(this.getName() + "action function");
 *       }
 *   });
 * state.addTransition(trans);
 *
 * // We would, of course, need to add state S2 since it is specified in a
 * // nextState property.  That is left as an exercise for the reader.
 *
 *
 * // Initialize and start the machine running
 * fsm.start();
 * </pre>
 */
