////////////////////////////////////////////////////////////////////////////////
//
//  Licensed to the Apache Software Foundation (ASF) under one or more
//  contributor license agreements.  See the NOTICE file distributed with
//  this work for additional information regarding copyright ownership.
//  The ASF licenses this file to You under the Apache License, Version 2.0
//  (the "License"); you may not use this file except in compliance with
//  the License.  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
//
////////////////////////////////////////////////////////////////////////////////

package mx.charts.styles
{

import mx.core.mx_internal;
import mx.graphics.IFill;
import mx.graphics.IStroke;
import mx.graphics.SolidColor;
import mx.graphics.Stroke;
import mx.styles.CSSStyleDeclaration;
import mx.styles.IStyleManager2;

use namespace mx_internal;

/**
 *  Initializes the core default styles for the charts classes. Each chart and element is responsible for initializing their own
 *	style values, but they rely on the common values computed by the HaloDefaults class.
 *
 *  @langversion 3.0
 *  @playerversion Flash 9
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
public class HaloDefaults
{
    include "../../core/Version.as";

	//--------------------------------------------------------------------------
	//
	//  Class variables
	//
	//--------------------------------------------------------------------------

	/**
	 *  @private
	 */
	private static var inited:Boolean;

	[Inspectable(environment="none")]
	/**
	 *	The default selectors applied to the individual series in a chart.
	 *
	 *  @langversion 3.0
	 *  @playerversion Flash 9
	 *  @playerversion AIR 1.1
	 *  @productversion Flex 3
	 */
	mx_internal static var chartBaseChartSeriesStyles:Array;

	[Inspectable(environment="none")]
	/**
	 *	The default color values used by chart controls to color different series (or, in a PieSeries, different items).
	 *
	 *  @langversion 3.0
	 *  @playerversion Flash 9
	 *  @playerversion AIR 1.1
	 *  @productversion Flex 3
	 */
	mx_internal static var defaultColors:Array =
	[
		0xE48701
		,0xA5BC4E
		,0x1B95D9
		,0xCACA9E
		,0x6693B0
		,0xF05E27
		,0x86D1E4
		,0xE4F9A0
		,0xFFD512
		,0x75B000
		,0x0662B0
		,0xEDE8C6
		,0xCC3300
		,0xD1DFE7
		,0x52D4CA
		,0xC5E05D
		,0xE7C174
		,0xFFF797
		,0xC5F68F
		,0xBDF1E6
		,0x9E987D
		,0xEB988D
		,0x91C9E5
		,0x93DC4A
		,0xFFB900
		,0x9EBBCD
		,0x009797
		,0x0DB2C2
	];

	[Inspectable(environment="none")]
	/**
	 *	The default SolidColor objects used as fills by chart controls to color different series (or, in a PieSeries, different items).
	 *	These Fill objects correspond to the values in the defaultColors Array.
	 *
	 *  @langversion 3.0
	 *  @playerversion Flash 9
	 *  @playerversion AIR 1.1
	 *  @productversion Flex 3
	 */
	mx_internal static var defaultFills:Array = [];

	[Inspectable(environment="none")]
	mx_internal static var pointStroke:IStroke;

	[Inspectable(environment="none")]
	/**
	 *	A pre-defined invisible Stroke that is used by several chart styles.
	 *
	 *  @langversion 3.0
	 *  @playerversion Flash 9
	 *  @playerversion AIR 1.1
	 *  @productversion Flex 3
	 */
	mx_internal static var emptyStroke:IStroke;

	//--------------------------------------------------------------------------
	//
	//  Class methods
	//
	//--------------------------------------------------------------------------

	/**
	 *  Creates a CSSStyleDeclaration object or returns an existing one.
	 *
	 *  @param selectorName The name of the selector to return. If no existing CSSStyleDeclaration object matches
	 *  this name, this method creates a new one and returns it.
	 *
	 *  @param styleManager The styleManager instance to be used for getting and setting style declarations.
	 *
	 *  @return The CSSStyleDeclaration object that matches the provided selector name. If no CSSStyleDeclaration object matches
	 *  that name, this method creates a new one and returns it.
	 *
	 *  @langversion 3.0
	 *  @playerversion Flash 9
	 *  @playerversion AIR 1.1
	 *  @productversion Flex 3
	 */
	public static function createSelector(
								selectorName:String, styleManager:IStyleManager2):CSSStyleDeclaration
	{
		var selector:CSSStyleDeclaration =
			styleManager.getStyleDeclaration(selectorName);

		if (!selector)
		{
			selector = new CSSStyleDeclaration();
			styleManager.setStyleDeclaration(selectorName, selector, false);
		}

		return selector;
	}

	/**
	 *  Initializes the common values used by the default styles for the chart and element classes.
	 *
	 *  @param styleManager The styleManager instance to be used for getting and setting style declarations.
	 *
	 *  @langversion 3.0
	 *  @playerversion Flash 9
	 *  @playerversion AIR 1.1
	 *  @productversion Flex 3
	 */
	public static function init(styleManager:IStyleManager2):void
	{
		if (inited)
			return;

		var seriesStyleCount:int = defaultColors.length;

		for (var i:int = 0; i < seriesStyleCount; i++)
		{
			defaultFills[i] = new SolidColor(defaultColors[i]);
		}

		pointStroke = new Stroke(0, 0, 0.5);
		emptyStroke = new Stroke(0, 0, 0);
		chartBaseChartSeriesStyles = [];

		var f:Function;

		for (i = 0; i < seriesStyleCount; i++)
		{
			var styleName:String = "haloSeries" + i;
			chartBaseChartSeriesStyles[i] = styleName;

			var o:CSSStyleDeclaration =
				HaloDefaults.createSelector("." + styleName, styleManager);

			f = function (o:CSSStyleDeclaration, defaultFill:IFill,defaultStroke:IStroke):void
			{
				o.defaultFactory = function():void
				{
					this.fill =  defaultFill;
					this.areaFill = defaultFill;
					this.areaStroke =  emptyStroke;
					this.lineStroke =  defaultStroke;
				}
			}

			f(o, HaloDefaults.defaultFills[i],new Stroke(defaultColors[i], 3, 1));
		}

	}

	/**
	 *  Returns the CSSStyleDeclaration by chasing the chain of styleManagers
	 *  if necessary.
	 *
	 *  @param name The name of the CSSStyleDeclaration
	 *  @return The CSSStyleDeclaration or null if not found
	 */
	public static function findStyleDeclaration(styleManager:IStyleManager2, name:String):CSSStyleDeclaration
	{
		var decl:CSSStyleDeclaration = styleManager.getStyleDeclaration(name);
		if (!decl)
		{
			var sm:IStyleManager2 = styleManager;
			while (sm.parent)
			{
				decl = sm.getStyleDeclaration(name);
				if (decl)
					break;
				sm = sm.parent;
			}
		}
		return decl;
	}
}

}

////////////////////////////////////////////////////////////////////////////////
//
//  Licensed to the Apache Software Foundation (ASF) under one or more
//  contributor license agreements.  See the NOTICE file distributed with
//  this work for additional information regarding copyright ownership.
//  The ASF licenses this file to You under the Apache License, Version 2.0
//  (the "License"); you may not use this file except in compliance with
//  the License.  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
//
////////////////////////////////////////////////////////////////////////////////

package mx.charts.styles
{

import mx.core.mx_internal;
import mx.graphics.IFill;
import mx.graphics.IStroke;
import mx.graphics.SolidColor;
import mx.graphics.Stroke;
import mx.styles.CSSStyleDeclaration;
import mx.styles.IStyleManager2;

use namespace mx_internal;

/**
 *  Initializes the core default styles for the charts classes. Each chart and element is responsible for initializing their own
 *	style values, but they rely on the common values computed by the HaloDefaults class.
 *
 *  @langversion 3.0
 *  @playerversion Flash 9
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
public class HaloDefaults
{
    include "../../core/Version.as";

	//--------------------------------------------------------------------------
	//
	//  Class variables
	//
	//--------------------------------------------------------------------------

	/**
	 *  @private
	 */
	private static var inited:Boolean;

	[Inspectable(environment="none")]
	/**
	 *	The default selectors applied to the individual series in a chart.
	 *
	 *  @langversion 3.0
	 *  @playerversion Flash 9
	 *  @playerversion AIR 1.1
	 *  @productversion Flex 3
	 */
	mx_internal static var chartBaseChartSeriesStyles:Array;

	[Inspectable(environment="none")]
	/**
	 *	The default color values used by chart controls to color different series (or, in a PieSeries, different items).
	 *
	 *  @langversion 3.0
	 *  @playerversion Flash 9
	 *  @playerversion AIR 1.1
	 *  @productversion Flex 3
	 */
	mx_internal static var defaultColors:Array =
	[
		0xE48701
		,0xA5BC4E
		,0x1B95D9
		,0xCACA9E
		,0x6693B0
		,0xF05E27
		,0x86D1E4
		,0xE4F9A0
		,0xFFD512
		,0x75B000
		,0x0662B0
		,0xEDE8C6
		,0xCC3300
		,0xD1DFE7
		,0x52D4CA
		,0xC5E05D
		,0xE7C174
		,0xFFF797
		,0xC5F68F
		,0xBDF1E6
		,0x9E987D
		,0xEB988D
		,0x91C9E5
		,0x93DC4A
		,0xFFB900
		,0x9EBBCD
		,0x009797
		,0x0DB2C2
	];

	[Inspectable(environment="none")]
	/**
	 *	The default SolidColor objects used as fills by chart controls to color different series (or, in a PieSeries, different items).
	 *	These Fill objects correspond to the values in the defaultColors Array.
	 *
	 *  @langversion 3.0
	 *  @playerversion Flash 9
	 *  @playerversion AIR 1.1
	 *  @productversion Flex 3
	 */
	mx_internal static var defaultFills:Array = [];

	[Inspectable(environment="none")]
	mx_internal static var pointStroke:IStroke;

	[Inspectable(environment="none")]
	/**
	 *	A pre-defined invisible Stroke that is used by several chart styles.
	 *
	 *  @langversion 3.0
	 *  @playerversion Flash 9
	 *  @playerversion AIR 1.1
	 *  @productversion Flex 3
	 */
	mx_internal static var emptyStroke:IStroke;

	//--------------------------------------------------------------------------
	//
	//  Class methods
	//
	//--------------------------------------------------------------------------

	/**
	 *  Creates a CSSStyleDeclaration object or returns an existing one.
	 *
	 *  @param selectorName The name of the selector to return. If no existing CSSStyleDeclaration object matches
	 *  this name, this method creates a new one and returns it.
	 *
	 *  @param styleManager The styleManager instance to be used for getting and setting style declarations.
	 *
	 *  @return The CSSStyleDeclaration object that matches the provided selector name. If no CSSStyleDeclaration object matches
	 *  that name, this method creates a new one and returns it.
	 *
	 *  @langversion 3.0
	 *  @playerversion Flash 9
	 *  @playerversion AIR 1.1
	 *  @productversion Flex 3
	 */
	public static function createSelector(
								selectorName:String, styleManager:IStyleManager2):CSSStyleDeclaration
	{
		var selector:CSSStyleDeclaration =
			styleManager.getStyleDeclaration(selectorName);

		if (!selector)
		{
			selector = new CSSStyleDeclaration();
			styleManager.setStyleDeclaration(selectorName, selector, false);
		}

		return selector;
	}

	/**
	 *  Initializes the common values used by the default styles for the chart and element classes.
	 *
	 *  @param styleManager The styleManager instance to be used for getting and setting style declarations.
	 *
	 *  @langversion 3.0
	 *  @playerversion Flash 9
	 *  @playerversion AIR 1.1
	 *  @productversion Flex 3
	 */
	public static function init(styleManager:IStyleManager2):void
	{
		if (inited)
			return;

		var seriesStyleCount:int = defaultColors.length;

		for (var i:int = 0; i < seriesStyleCount; i++)
		{
			defaultFills[i] = new SolidColor(defaultColors[i]);
		}

		pointStroke = new Stroke(0, 0, 0.5);
		emptyStroke = new Stroke(0, 0, 0);
		chartBaseChartSeriesStyles = [];

		var f:Function;

		for (i = 0; i < seriesStyleCount; i++)
		{
			var styleName:String = "haloSeries" + i;
			chartBaseChartSeriesStyles[i] = styleName;

			var o:CSSStyleDeclaration =
				HaloDefaults.createSelector("." + styleName, styleManager);

			f = function (o:CSSStyleDeclaration, defaultFill:IFill,defaultStroke:IStroke):void
			{
				o.defaultFactory = function():void
				{
					this.fill =  defaultFill;
					this.areaFill = defaultFill;
					this.areaStroke =  emptyStroke;
					this.lineStroke =  defaultStroke;
				}
			}

			f(o, HaloDefaults.defaultFills[i],new Stroke(defaultColors[i], 3, 1));
		}

	}

	/**
	 *  Returns the CSSStyleDeclaration by chasing the chain of styleManagers
	 *  if necessary.
	 *
	 *  @param name The name of the CSSStyleDeclaration
	 *  @return The CSSStyleDeclaration or null if not found
	 */
	public static function findStyleDeclaration(styleManager:IStyleManager2, name:String):CSSStyleDeclaration
	{
		var decl:CSSStyleDeclaration = styleManager.getStyleDeclaration(name);
		if (!decl)
		{
			var sm:IStyleManager2 = styleManager.parent;
			while (sm)
			{
				decl = sm.getStyleDeclaration(name);
				if (decl)
					break;
				sm = sm.parent;
			}
		}
		return decl;
	}
}

}

fix for FLEX-34728

fix for FLEX-34728


/*
Copyright (c) 2007 FlexLib Contributors.  See:
    http://code.google.com/p/flexlib/wiki/ProjectContributors

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
/*
	Class that provides Reset and Undo/Redo functionality for a Form
*/
package flexlib.containers
{

import flash.events.*;
import flash.ui.KeyLocation;
import flash.ui.Keyboard;
import flash.utils.describeType;

import mx.containers.*;
import mx.controls.*;
import mx.core.Container;
import mx.core.UIComponent;
import mx.events.ValidationResultEvent;
import mx.messaging.errors.MessagingError;
import mx.validators.ValidationResult;
import mx.validators.Validator;

[IconFile("AdvancedForm.png")]

/**
 *  The Advanced Form component provides Reset, Undo and Redo functionality.
 *
 *
The Advanced Form component provides Reset, Undo and Redo functionality.
 * 	Undo and Redo are accessed by pressing "ctrl-Z" and "ctrl-Y" repsectively.

 *
 *  @mxml
 *
 *

 *  <flexlib:AdvancedForm
 * 	  Properties
 * 	  undoHistorySize="5"
 * 	  modelType="shared|memory"
 *
 *    >
 *    ...
 *      child tags
 *    ...
 *  </flexlib:AdvancedForm>
 *

 */
public class AdvancedForm extends Form
{

	//[Bindable]
	//public var debug:String = "";

	//--------------------------------------------------------------------------
	//
	//  Variables
	//
	//--------------------------------------------------------------------------

	/**
	 *  @private
	 */
	private var noSnapshotFlag:Boolean = false;

	/**
	 *  @private Key for reset snapshot
	 */
	private var resetSnapshotKey:String = "reset";

	/**
	 *  @private
	 */
	private var undoCounter:int = 0;

	/**
	 *  @private
	 */
	private var undoCurrentIndex:int = -1;

	/**
	 *  @private
	 */
	private var modelStack:Object;

	//--------------------------------------------------------------------------
	//
	//  Properties
	//
	//--------------------------------------------------------------------------

	//----------------------------------
	//  validators
	//----------------------------------

	/**
	 *  @private LookupTable of isValid flags
	 */
	private var validators:Object;

	//----------------------------------
	//  undoHistorySize
	//----------------------------------

	/**
	 *  @private
	 */
	private var _undoHistorySize:int = 5;

	/**
	 *  The undoHistorySize defaults the number of undos.
	 *
	 *  @default true
	 */
	public function set undoHistorySize( value:int ):void {
		_undoHistorySize = value;
	}
	public function get undoHistorySize():int {
		return _undoHistorySize;
	}

	//----------------------------------
	//  modelType
	//----------------------------------

	/**
	 *  @private
	 */
	private var _modelType:String = "shared";

	[Inspectable(category="General", enumeration="shared,memory", defaultValue="shared")]
	/**
	 *  The modelStack handles the data.
	 *
	 *  @default true
	 */
	public function set modelType( value:String ):void {
		if( value == "shared" ) {

		} else {

		}
	}
	public function get modelType():String {
		return _modelType;
	}

	//----------------------------------
	//  isValid
	//----------------------------------

	/**
	 *  Property that allows for one place to know if the From is valid
	 *
	 *  Default to true, if any Validators are present then it will be set to false
	 */
	[Bindable]
	public var isValid:Boolean = true;

	//--------------------------------------------------------------------------
	//
	//  Methods
	//
	//--------------------------------------------------------------------------

	/**
	 * Resets values of the form
	 */
	public function resetForm():void {
		var children:Array = this.getChildren();
		resetValues( children, resetSnapshotKey );
		undoCounter = 0;
		undoCurrentIndex = -1;
		modelStack = new Object();
		snapshotValues( this.getChildren(), resetSnapshotKey );
	}

	/**
	 * @private
	 */
	private function myKeyDownHandler( event:KeyboardEvent ):void {

		if( event.ctrlKey && event.keyCode == 90 && !( event.target is NumericStepper ) ) {
			event.stopPropagation();
			event.preventDefault()
			doUndo();

		} else if( event.ctrlKey && event.keyCode == 89 && !( event.target is NumericStepper ) ) {
			doRedo();
		} else {
			super.keyDownHandler( event );
		}
	}

	/**
	 * Creates snapshot of values for reseting
	 */
	override protected function childrenCreated():void {
		super.childrenCreated();
		// Find Validators and add EventListeners
		parent.addEventListener( "creationComplete", setValidatorListenerEvents );

		this.parent.addEventListener( KeyboardEvent.KEY_DOWN, myKeyDownHandler, false, 0, true );
	}

	/**
	 * 	Loop through all Validtors at the same level as the Form and set a Event listener for Valid and Invalid
	 */
	private function setValidatorListenerEvents( event:Event ):void
	{
		// Take First Snapshot After All Children have been created
		snapshotValues( this.getChildren(), resetSnapshotKey );

		var container:Object = document;

		// Check parent control to make sure its capable of having children
		if( !( container is Container ) )
			return;

		// Describe Parent
		var classInfo:XML = describeType( container );

		// Reset Defaults
		validators = new Array();
		isValid = true;

        // Loop over all parentDocument's properties looking for Validators
        for each (var a:XML in classInfo..accessor) {
        	try {
				if( container[ a.@name ] is Validator ) {
					//Logger.debug( "setValidatorListenerEvents:Property is Validator: " + a.@name );

					// If Validator is found default to false
					isValid = false;

					var obj:Object = new Object();
					obj.reference = container[ a.@name ];
					obj.isValid = false;
					validators.push( obj );

					// Set Valid and Invalid week reference listeners on the Validators
					Validator( container[ a.@name ] ).addEventListener( ValidationResultEvent.VALID, setValidFlag, false, 0, true );
					Validator( container[ a.@name ] ).addEventListener( ValidationResultEvent.INVALID, setValidFlag, false, 0, true );
				}
         	} catch( err:Error ) {
         		if( err.errorID != 1077 ) {
	         		//Logger.error( "AdvancedForm:setValidatorListenerEvents: " + err.message );
         		}
         	}
		}
	}

	/**
	 * 	Handles all valid and invalid events on the validators
	 */
	private function setValidFlag( event:ValidationResultEvent ):void
	{
		var tmpFlag:Boolean = true;
		for( var i:int = 0; i < validators.length; i++ ) {
			if( validators[ i ].reference == event.target ) {
				//Logger.debug( "setValidFlag:event.target: " + event.type );
				validators[ i ].isValid = ( event.type == ValidationResultEvent.VALID );
			}
			tmpFlag = ( tmpFlag && validators[ i ].isValid );
		}
		isValid = tmpFlag;
	}

	/**
	 *
	 */
	private function snapshotValues( obj:Object, snapshotKey:String ):void {
		try {
			if( modelStack == null )
				modelStack = new Object();

			if( modelStack[ snapshotKey ] == null )
				modelStack[ snapshotKey ] = new Object();

			var snapshotModel:Object = modelStack[ snapshotKey ];

			for( var a:String in obj ) {
				if( obj[ a ] is FormItem ) {
					snapshotValues( obj[ a ].getChildren(), snapshotKey );
				} else {
					var tmpObj:Object = obj[ a ];

					var tmpID:String = tmpObj.toString();
					if( snapshotModel[ tmpID ] == undefined )
						snapshotModel[ tmpID ] = new Object();
					var value:Object;
					if( tmpObj is TextInput || tmpObj is TextArea )
						value = tmpObj.text;
					if( tmpObj is RadioButton || tmpObj is CheckBox )
						value = tmpObj.selected;
					if( tmpObj is ComboBox )
						value = tmpObj.selectedIndex;
					if( tmpObj is NumericStepper )
						value = tmpObj.value;

					if( tmpObj is TextInput || tmpObj is TextArea )
						UIComponent( tmpObj ).addEventListener( FocusEvent.FOCUS_OUT, textInputChange );
					else
						UIComponent( tmpObj ).addEventListener( Event.CHANGE, controlChange );

					snapshotModel[ tmpID ] = value;
				}
			}
		} catch( err:Error ) {
			//Logger.error( "AdvancedForm:snapshotValues: " + err.message );
		}
	}

	/**
	 * 	@private
	 */
	private function textInputChange( event:FocusEvent ):void {
		var snapshotModel:Object = getLastestSnapshot();
		var tmpKey:String = event.target.parent.toString();
		if( snapshotModel[ tmpKey ] == undefined )
			;//throw new Error( "Snapshot not defined for key = " + tmpKey );
		if( snapshotModel[ tmpKey ] != event.target.parent.text ) {
			takeSnapshot();
		}
	}

	/**
	 * 	@private
	 */
	private function controlChange( event:Event ):void {
		if( event.target is RadioButton && !event.target.selected )
			takeSnapshot();
		if( !(event.target is RadioButton) )
			takeSnapshot();

	}

	/**
	 * 	@private
	 */
	private function doUndo():void {
		//debug += "\ndoUndo: undoCurrentIndex: " + undoCurrentIndex + " undoCounter: " + undoCounter;
		noSnapshotFlag = true;
		var index:int = undoCurrentIndex - 1;
		if( index >= ( undoCounter - 1 - undoHistorySize ) && index > -2 ) {
			undoCurrentIndex--;
			//debug += "\ndoUndo: resetValues: " + undoCurrentIndex;
			resetValues( this.getChildren(), getSnapshotKey( undoCurrentIndex ) );

		}
		noSnapshotFlag = false;
	}

	/**
	 * 	@private
	 */
	private function doRedo():void {
		//debug += "\ndoRedo: undoCurrentIndex: " + undoCurrentIndex + " undoCounter: " + undoCounter;
		noSnapshotFlag = true;
		var index:int = undoCurrentIndex + 1;
		if( index < undoCounter ) {
			undoCurrentIndex++;
			resetValues( this.getChildren(), getSnapshotKey( undoCurrentIndex ) );
		}
		noSnapshotFlag = false;
	}

	/**
	 * 	@private
	 */
	private function takeSnapshot():void {
		if( !noSnapshotFlag ) {
			if( undoCurrentIndex < undoCounter - 1 )
				undoCounter = undoCurrentIndex + 1;
			//debug += "\ntakeSnaphost: undoCurrentIndex: " + undoCurrentIndex + " undoCounter: " + undoCounter;
			snapshotValues( this.getChildren(), undoCounter+"" );
			undoCurrentIndex = undoCounter;
			undoCounter++;
		}
	}

	/**
	 * 	@private
	 */
	private function getLastestSnapshot():Object {
		if( undoCurrentIndex > -1 )
			return modelStack[ undoCurrentIndex+"" ];
		else
			return modelStack[ resetSnapshotKey ];
	}

	/**
	 * 	@private
	 */
	private function getSnapshotKey( coutner:int ):String {
		if( coutner >= 0 )
			return coutner+"";
		else
			return resetSnapshotKey;
	}

	/**
	 *
	 */
	private function resetValues( obj:Object, snapshotKey:String ):void {
		if( modelStack[ snapshotKey ] == undefined )
			throw new Error( "Invalid snapshot" );

		// Disable all Validators
		try {
			for( var i:int = 0; i < validators.length; i++ ) {
				isValid = false;
				Validator( validators[ i ].reference ).enabled = false;
				validators[ i ].isValid = false;
			}
		} catch( err:Error ) {
			//Logger.error( "AdvancedForm:resetValues:Disabling Validators: " + err.message );
		}

		var snapshotModel:Object = modelStack[ snapshotKey ];

		for( var a:String in obj ) {
			if( obj[ a ] is FormItem ) {
				resetValues( obj[ a ].getChildren(), snapshotKey );
			} else {
				var tmpObj:Object = obj[ a ];

				var tmpID:String = tmpObj.toString();
				if( snapshotModel[ tmpID ] == undefined
					&& ( tmpObj is Container
						|| ( !(tmpObj is TextInput)
							&& !(tmpObj is RadioButton)
							&& !(tmpObj is ComboBox)
							&& !(tmpObj is NumericStepper) )
						) )
					continue;
				if( snapshotModel[ tmpID ] == undefined )
					throw new Error( "Invalid obj in snapshot: " + tmpID );
				var value:Object;
				if( tmpObj is TextInput || tmpObj is TextArea )
					tmpObj.text = snapshotModel[ tmpID ];
				if( tmpObj is RadioButton || tmpObj is CheckBox )
					tmpObj.selected = snapshotModel[ tmpID ];
				if( tmpObj is ComboBox )
					tmpObj.selectedIndex = snapshotModel[ tmpID ];
				if( tmpObj is NumericStepper )
					tmpObj.value = snapshotModel[ tmpID ];
			}
		}

		// Enable all Validators
		try {
			for( i = 0; i < validators.length; i++ ) {
				Validator( validators[ i ].reference ).enabled = true;
			}
		} catch( err:Error ) {
			//Logger.error( "AdvancedForm:resetValues:Disabling Validators: " + err.message );
		}
	}

	/**
	 * 	Gather references and defaults of all the children
	 */
	private function strChildren( obj:Object ):String {
		var str:String = "";
		for( var a:String in obj ) {
			str += a + "=[" + obj[ a ] + "]\n";
		}
		return str;
	}

}
}

/*
Copyright (c) 2007 FlexLib Contributors.  See:
    http://code.google.com/p/flexlib/wiki/ProjectContributors

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
/*
	Class t hat provides Reset and Undo/Redo functionality for a Form
*/
package flexlib.containers
{

import flash.events.*;
import flash.ui.KeyLocation;
import flash.ui.Keyboard;
import flash.utils.describeType;

import mx.containers.*;
import mx.controls.*;
import mx.core.Container;
import mx.core.UIComponent;
import mx.events.ValidationResultEvent;
import mx.messaging.errors.MessagingError;
import mx.validators.ValidationResult;
import mx.validators.Validator;

[IconFile("AdvancedForm.png")]

/**
 *  The Advanced Form component provides Reset, Undo and Redo functionality.
 *
 *
The Advanced Form component provides Reset, Undo and Redo functionality.
 * 	Undo and Redo are accessed by pressing "ctrl-Z" and "ctrl-Y" repsectively.

 *
 *  @mxml
 *
 *

 *  <flexlib:AdvancedForm
 * 	  Properties
 * 	  undoHistorySize="5"
 * 	  modelType="shared|memory"
 *
 *    >
 *    ...
 *      child tags
 *    ...
 *  </flexlib:AdvancedForm>
 *

 */
public class AdvancedForm extends Form
{

	//[Bindable]
	//public var debug:String = "";

	//--------------------------------------------------------------------------
	//
	//  Variables
	//
	//--------------------------------------------------------------------------

	/**
	 *  @private
	 */
	private var noSnapshotFlag:Boolean = false;

	/**
	 *  @private Key for reset snapshot
	 */
	private var resetSnapshotKey:String = "reset";

	/**
	 *  @private
	 */
	private var undoCounter:int = 0;

	/**
	 *  @private
	 */
	private var undoCurrentIndex:int = -1;

	/**
	 *  @private
	 */
	private var modelStack:Object;

	//--------------------------------------------------------------------------
	//
	//  Properties
	//
	//--------------------------------------------------------------------------

	//----------------------------------
	//  validators
	//----------------------------------

	/**
	 *  @private LookupTable of isValid flags
	 */
	private var validators:Object;

	//----------------------------------
	//  undoHistorySize
	//----------------------------------

	/**
	 *  @private
	 */
	private var _undoHistorySize:int = 5;

	/**
	 *  The undoHistorySize defaults the number of undos.
	 *
	 *  @default true
	 */
	public function set undoHistorySize( value:int ):void {
		_undoHistorySize = value;
	}
	public function get undoHistorySize():int {
		return _undoHistorySize;
	}

	//----------------------------------
	//  modelType
	//----------------------------------

	/**
	 *  @private
	 */
	private var _modelType:String = "shared";

	[Inspectable(category="General", enumeration="shared,memory", defaultValue="shared")]
	/**
	 *  The modelStack handles the data.
	 *
	 *  @default true
	 */
	public function set modelType( value:String ):void {
		if( value == "shared" ) {

		} else {

		}
	}
	public function get modelType():String {
		return _modelType;
	}

	//----------------------------------
	//  isValid
	//----------------------------------

	/**
	 *  Property that allows for one place to know if the From is valid
	 *
	 *  Default to true, if any Validators are present then it will be set to false
	 */
	[Bindable]
	public var isValid:Boolean = true;

	//--------------------------------------------------------------------------
	//
	//  Methods
	//
	//--------------------------------------------------------------------------

	/**
	 * Resets values of the form
	 */
	public function resetForm():void {
		var children:Array = this.getChildren();
		resetValues( children, resetSnapshotKey );
		undoCounter = 0;
		undoCurrentIndex = -1;
		modelStack = new Object();
		snapshotValues( this.getChildren(), resetSnapshotKey );
	}

	/**
	 * @private
	 */
	private function myKeyDownHandler( event:KeyboardEvent ):void {

		if( event.ctrlKey && event.keyCode == 90 && !( event.target is NumericStepper ) ) {
			event.stopPropagation();
			event.preventDefault()
			doUndo();

		} else if( event.ctrlKey && event.keyCode == 89 && !( event.target is NumericStepper ) ) {
			doRedo();
		} else {
			super.keyDownHandler( event );
		}
	}

	/**
	 * Creates snapshot of values for reseting
	 */
	override protected function childrenCreated():void {
		super.childrenCreated();
		// Find Validators and add EventListeners
		parent.addEventListener( "creationComplete", setValidatorListenerEvents );

		this.parent.addEventListener( KeyboardEvent.KEY_DOWN, myKeyDownHandler, false, 0, true );
	}

	/**
	 * 	Loop through all Validtors at the same level as the Form and set a Event listener for Valid and Invalid
	 */
	private function setValidatorListenerEvents( event:Event ):void
	{
		// Take First Snapshot After All Children have been created
		snapshotValues( this.getChildren(), resetSnapshotKey );

		var container:Object = document;

		// Check parent control to make sure its capable of having children
		if( !( container is Container ) )
			return;

		// Describe Parent
		var classInfo:XML = describeType( container );

		// Reset Defaults
		validators = new Array();
		isValid = true;

        // Loop over all parentDocument's properties looking for Validators
        for each (var a:XML in classInfo..accessor) {
        	try {
				if( container[ a.@name ] is Validator ) {
					//Logger.debug( "setValidatorListenerEvents:Property is Validator: " + a.@name );

					// If Validator is found default to false
					isValid = false;

					var obj:Object = new Object();
					obj.reference = container[ a.@name ];
					obj.isValid = false;
					validators.push( obj );

					// Set Valid and Invalid week reference listeners on the Validators
					Validator( container[ a.@name ] ).addEventListener( ValidationResultEvent.VALID, setValidFlag, false, 0, true );
					Validator( container[ a.@name ] ).addEventListener( ValidationResultEvent.INVALID, setValidFlag, false, 0, true );
				}
         	} catch( err:Error ) {
         		if( err.errorID != 1077 ) {
	         		//Logger.error( "AdvancedForm:setValidatorListenerEvents: " + err.message );
         		}
         	}
		}
	}

	/**
	 * 	Handles all valid and invalid events on the validators
	 */
	private function setValidFlag( event:ValidationResultEvent ):void
	{
		var tmpFlag:Boolean = true;
		for( var i:int = 0; i < validators.length; i++ ) {
			if( validators[ i ].reference == event.target ) {
				//Logger.debug( "setValidFlag:event.target: " + event.type );
				validators[ i ].isValid = ( event.type == ValidationResultEvent.VALID );
			}
			tmpFlag = ( tmpFlag && validators[ i ].isValid );
		}
		isValid = tmpFlag;
	}

	/**
	 *
	 */
	private function snapshotValues( obj:Object, snapshotKey:String ):void {
		try {
			if( modelStack == null )
				modelStack = new Object();

			if( modelStack[ snapshotKey ] == null )
				modelStack[ snapshotKey ] = new Object();

			var snapshotModel:Object = modelStack[ snapshotKey ];

			for( var a:String in obj ) {
				if( obj[ a ] is FormItem ) {
					snapshotValues( obj[ a ].getChildren(), snapshotKey );
				} else {
					var tmpObj:Object = obj[ a ];

					var tmpID:String = tmpObj.toString();
					if( snapshotModel[ tmpID ] == undefined )
						snapshotModel[ tmpID ] = new Object();
					var value:Object;
					if( tmpObj is TextInput || tmpObj is TextArea )
						value = tmpObj.text;
					if( tmpObj is RadioButton || tmpObj is CheckBox )
						value = tmpObj.selected;
					if( tmpObj is ComboBox )
						value = tmpObj.selectedIndex;
					if( tmpObj is NumericStepper )
						value = tmpObj.value;

					if( tmpObj is TextInput || tmpObj is TextArea )
						UIComponent( tmpObj ).addEventListener( FocusEvent.FOCUS_OUT, textInputChange );
					else
						UIComponent( tmpObj ).addEventListener( Event.CHANGE, controlChange );

					snapshotModel[ tmpID ] = value;
				}
			}
		} catch( err:Error ) {
			//Logger.error( "AdvancedForm:snapshotValues: " + err.message );
		}
	}

	/**
	 * 	@private
	 */
	private function textInputChange( event:FocusEvent ):void {
		var snapshotModel:Object = getLastestSnapshot();
		var tmpKey:String = event.target.parent.toString();
		if( snapshotModel[ tmpKey ] == undefined )
			;//throw new Error( "Snapshot not defined for key = " + tmpKey );
		if( snapshotModel[ tmpKey ] != event.target.parent.text ) {
			takeSnapshot();
		}
	}

	/**
	 * 	@private
	 */
	private function controlChange( event:Event ):void {
		if( event.target is RadioButton && !event.target.selected )
			takeSnapshot();
		if( !(event.target is RadioButton) )
			takeSnapshot();

	}

	/**
	 * 	@private
	 */
	private function doUndo():void {
		//debug += "\ndoUndo: undoCurrentIndex: " + undoCurrentIndex + " undoCounter: " + undoCounter;
		noSnapshotFlag = true;
		var index:int = undoCurrentIndex - 1;
		if( index >= ( undoCounter - 1 - undoHistorySize ) && index > -2 ) {
			undoCurrentIndex--;
			//debug += "\ndoUndo: resetValues: " + undoCurrentIndex;
			resetValues( this.getChildren(), getSnapshotKey( undoCurrentIndex ) );

		}
		noSnapshotFlag = false;
	}

	/**
	 * 	@private
	 */
	private function doRedo():void {
		//debug += "\ndoRedo: undoCurrentIndex: " + undoCurrentIndex + " undoCounter: " + undoCounter;
		noSnapshotFlag = true;
		var index:int = undoCurrentIndex + 1;
		if( index < undoCounter ) {
			undoCurrentIndex++;
			resetValues( this.getChildren(), getSnapshotKey( undoCurrentIndex ) );
		}
		noSnapshotFlag = false;
	}

	/**
	 * 	@private
	 */
	private function takeSnapshot():void {
		if( !noSnapshotFlag ) {
			if( undoCurrentIndex < undoCounter - 1 )
				undoCounter = undoCurrentIndex + 1;
			//debug += "\ntakeSnaphost: undoCurrentIndex: " + undoCurrentIndex + " undoCounter: " + undoCounter;
			snapshotValues( this.getChildren(), undoCounter+"" );
			undoCurrentIndex = undoCounter;
			undoCounter++;
		}
	}

	/**
	 * 	@private
	 */
	private function getLastestSnapshot():Object {
		if( undoCurrentIndex > -1 )
			return modelStack[ undoCurrentIndex+"" ];
		else
			return modelStack[ resetSnapshotKey ];
	}

	/**
	 * 	@private
	 */
	private function getSnapshotKey( coutner:int ):String {
		if( coutner >= 0 )
			return coutner+"";
		else
			return resetSnapshotKey;
	}

	/**
	 *
	 */
	private function resetValues( obj:Object, snapshotKey:String ):void {
		if( modelStack[ snapshotKey ] == undefined )
			throw new Error( "Invalid snapshot" );

		// Disable all Validators
		try {
			for( var i:int = 0; i < validators.length; i++ ) {
				isValid = false;
				Validator( validators[ i ].reference ).enabled = false;
				validators[ i ].isValid = false;
			}
		} catch( err:Error ) {
			//Logger.error( "AdvancedForm:resetValues:Disabling Validators: " + err.message );
		}

		var snapshotModel:Object = modelStack[ snapshotKey ];

		for( var a:String in obj ) {
			if( obj[ a ] is FormItem ) {
				resetValues( obj[ a ].getChildren(), snapshotKey );
			} else {
				var tmpObj:Object = obj[ a ];

				var tmpID:String = tmpObj.toString();
				if( snapshotModel[ tmpID ] == undefined
					&& ( tmpObj is Container
						|| ( !(tmpObj is TextInput)
							&& !(tmpObj is RadioButton)
							&& !(tmpObj is ComboBox)
							&& !(tmpObj is NumericStepper) )
						) )
					continue;
				if( snapshotModel[ tmpID ] == undefined )
					throw new Error( "Invalid obj in snapshot: " + tmpID );
				var value:Object;
				if( tmpObj is TextInput || tmpObj is TextArea )
					tmpObj.text = snapshotModel[ tmpID ];
				if( tmpObj is RadioButton || tmpObj is CheckBox )
					tmpObj.selected = snapshotModel[ tmpID ];
				if( tmpObj is ComboBox )
					tmpObj.selectedIndex = snapshotModel[ tmpID ];
				if( tmpObj is NumericStepper )
					tmpObj.value = snapshotModel[ tmpID ];
			}
		}

		// Enable all Validators
		try {
			for( i = 0; i < validators.length; i++ ) {
				Validator( validators[ i ].reference ).enabled = true;
			}
		} catch( err:Error ) {
			//Logger.error( "AdvancedForm:resetValues:Disabling Validators: " + err.message );
		}
	}

	/**
	 * 	Gather references and defaults of all the children
	 */
	private function strChildren( obj:Object ):String {
		var str:String = "";
		for( var a:String in obj ) {
			str += a + "=[" + obj[ a ] + "]\n";
		}
		return str;
	}

}
}

Test commit rights, added a space in a comment.


package
{
    import flash.display.Sprite;
    import flash.text.TextField;
    import flash.net.Socket;
    import flash.events.Event;
    import flash.events.IOErrorEvent;
    import flash.events.ProgressEvent;
    import flash.events.SecurityErrorEvent;
    import flash.utils.ByteArray;

    public class swfcat extends Sprite
    {
        private const TOR_ADDRESS:String = "173.255.221.44";
        private const TOR_PORT:int = 9001;

        private var output_text:TextField;

        // Socket to Tor relay.
        private var s_t:Socket;
        // Socket to facilitator.
        private var s_f:Socket;
        // Socket to client.
        private var s_c:Socket;

        private var fac_addr:Object;

        private function puts(s:String):void
        {
            output_text.appendText(s + "\n");
            output_text.scrollV = output_text.maxScrollV;
        }

        public function swfcat()
        {
            output_text = new TextField();
            output_text.width = 400;
            output_text.height = 300;
            output_text.background = true;
            output_text.backgroundColor = 0x001f0f;
            output_text.textColor = 0x44CC44;
            addChild(output_text);

            puts("Starting.");
            // Wait until the query string parameters are loaded.
            this.loaderInfo.addEventListener(Event.COMPLETE, loaderinfo_complete);
        }

        private function loaderinfo_complete(e:Event):void
        {
            var fac_spec:String;

            puts("Parameters loaded.");
            fac_spec = this.loaderInfo.parameters["facilitator"];
            if (!fac_spec) {
                puts("Error: no \"facilitator\" specification provided.");
                return;
            }
            puts("Facilitator spec: \"" + fac_spec + "\"");
            fac_addr = parse_addr_spec(fac_spec);
            if (!fac_addr) {
                puts("Error: Facilitator spec must be in the form \"host:port\".");
                return;
            }

            go(TOR_ADDRESS, TOR_PORT);
        }

        /* We connect first to the Tor relay; once that happens we connect to
           the facilitator to get a client address; once we have the address
           of a waiting client then we connect to the client and BAM! we're in business. */
        private function go(tor_address:String, tor_port:int):void
        {
            s_t = new Socket();

            s_t.addEventListener(Event.CONNECT, tor_connected);
            s_t.addEventListener(Event.CLOSE, function (e:Event):void {
                puts("Tor: closed.");
                if (s_c.connected)
                    s_c.close();
            });
            s_t.addEventListener(IOErrorEvent.IO_ERROR, function (e:IOErrorEvent):void {
                puts("Tor: I/O error: " + e.text + ".");
                if (s_c.connected)
                    s_c.close();
            });
            s_t.addEventListener(SecurityErrorEvent.SECURITY_ERROR, function (e:SecurityErrorEvent):void {
                puts("Tor: security error: " + e.text + ".");
                if (s_c.connected)
                    s_c.close();
            });

            puts("Tor: connecting to " + tor_address + ":" + tor_port + ".");
            s_t.connect(tor_address, tor_port);
        }

        private function tor_connected(e:Event):void
        {
            /* Got a connection to tor, now let's get served a client from the facilitator */
            s_f = new Socket();

            puts("Tor: connected.");
            s_f.addEventListener(Event.CONNECT, fac_connected);
            s_f.addEventListener(Event.CLOSE, function (e:Event):void {
                puts("Facilitator: closed connection.");
            });
            s_f.addEventListener(IOErrorEvent.IO_ERROR, function (e:IOErrorEvent):void {
                puts("Facilitator: I/O error: " + e.text + ".");
                if (s_t.connected)
                    s_t.close();
            });
            s_f.addEventListener(SecurityErrorEvent.SECURITY_ERROR, function (e:SecurityErrorEvent):void {
                puts("Facilitator: security error: " + e.text + ".");
                if (s_t.connected)
                    s_t.close();
            });

            puts("Facilitator: connecting to " + fac_addr.host + ":" + fac_addr.port + ".");
            s_f.connect(fac_addr.host, fac_addr.port);
        }

        private function fac_connected(e:Event):void
        {
            puts("Facilitator: connected.");

            s_f.addEventListener(ProgressEvent.SOCKET_DATA, function (e:ProgressEvent):void {
                var client_spec:String;
                var client_addr:Object;

                client_spec = s_f.readMultiByte(e.bytesLoaded, "utf-8");
                puts("Facilitator: got \"" + client_spec + "\"");

                client_addr = parse_addr_spec(client_spec);
                if (!client_addr) {
                    puts("Error: Client spec must be in the form \"host:port\".");
                    return;
                }
                if (client_addr.host == "0.0.0.0" && client_addr.port == 0) {
                    puts("Error: Facilitator has no clients.");
                    return;
                }

                puts("Client: connecting to " + client_addr.host + ":" + client_addr.port + ".");
                s_c.connect(client_addr.host, client_addr.port);

            });

            s_f.writeUTFBytes("GET / HTTP/1.0\r\n\r\n");
        }

        private function client_connected(e:Event):void
        {
            puts("Client: connected.");

            s_t.addEventListener(ProgressEvent.SOCKET_DATA, function (e:ProgressEvent):void {
                var bytes:ByteArray = new ByteArray();
                s_t.readBytes(bytes, 0, e.bytesLoaded);
                puts("Tor: read " + bytes.length + ".");
                s_c.writeBytes(bytes);
            });
            s_c.addEventListener(ProgressEvent.SOCKET_DATA, function (e:ProgressEvent):void {
                var bytes:ByteArray = new ByteArray();
                s_c.readBytes(bytes, 0, e.bytesLoaded);
                puts("Client: read " + bytes.length + ".");
                s_t.writeBytes(bytes);
            });
        }

        private static function parse_addr_spec(spec:String):Object
        {
            var parts:Array;
            var addr:Object;

            parts = spec.split(":", 2);
            if (parts.length != 2 || !parseInt(parts[1]))
                return null;
            addr = {}
            addr.host = parts[0];
            addr.port = parseInt(parts[1]);

            return addr;
        }
    }
}

package
{
    import flash.display.Sprite;
    import flash.text.TextField;
    import flash.net.Socket;
    import flash.events.Event;
    import flash.events.IOErrorEvent;
    import flash.events.ProgressEvent;
    import flash.events.SecurityErrorEvent;
    import flash.utils.ByteArray;

    public class swfcat extends Sprite
    {
        /* David's relay (nickname 3VXRyxz67OeRoqHn) that also serves a
           crossdomain policy. */
        private const DEFAULT_TOR_ADDR:Object = {
            host: "173.255.221.44",
            port: 9001
        };

        private var output_text:TextField;

        // Socket to Tor relay.
        private var s_t:Socket;
        // Socket to facilitator.
        private var s_f:Socket;
        // Socket to client.
        private var s_c:Socket;

        private var fac_addr:Object;
        private var tor_addr:Object;

        private function puts(s:String):void
        {
            output_text.appendText(s + "\n");
            output_text.scrollV = output_text.maxScrollV;
        }

        public function swfcat()
        {
            output_text = new TextField();
            output_text.width = 400;
            output_text.height = 300;
            output_text.background = true;
            output_text.backgroundColor = 0x001f0f;
            output_text.textColor = 0x44CC44;
            addChild(output_text);

            puts("Starting.");
            // Wait until the query string parameters are loaded.
            this.loaderInfo.addEventListener(Event.COMPLETE, loaderinfo_complete);
        }

        private function loaderinfo_complete(e:Event):void
        {
            var fac_spec:String;
            var tor_spec:String;

            puts("Parameters loaded.");
            fac_spec = this.loaderInfo.parameters["facilitator"];
            if (!fac_spec) {
                puts("Error: no \"facilitator\" specification provided.");
                return;
            }
            puts("Facilitator spec: \"" + fac_spec + "\"");
            fac_addr = parse_addr_spec(fac_spec);
            if (!fac_addr) {
                puts("Error: Facilitator spec must be in the form \"host:port\".");
                return;
            }

            tor_addr = DEFAULT_TOR_ADDR;

            go();
        }

        /* We connect first to the Tor relay; once that happens we connect to
           the facilitator to get a client address; once we have the address
           of a waiting client then we connect to the client and BAM! we're in business. */
        private function go():void
        {
            s_t = new Socket();

            s_t.addEventListener(Event.CONNECT, tor_connected);
            s_t.addEventListener(Event.CLOSE, function (e:Event):void {
                puts("Tor: closed.");
                if (s_c.connected)
                    s_c.close();
            });
            s_t.addEventListener(IOErrorEvent.IO_ERROR, function (e:IOErrorEvent):void {
                puts("Tor: I/O error: " + e.text + ".");
                if (s_c.connected)
                    s_c.close();
            });
            s_t.addEventListener(SecurityErrorEvent.SECURITY_ERROR, function (e:SecurityErrorEvent):void {
                puts("Tor: security error: " + e.text + ".");
                if (s_c.connected)
                    s_c.close();
            });

            puts("Tor: connecting to " + tor_addr.host + ":" + tor_addr.port + ".");
            s_t.connect(tor_addr.host, tor_addr.port);
        }

        private function tor_connected(e:Event):void
        {
            /* Got a connection to tor, now let's get served a client from the facilitator */
            s_f = new Socket();

            puts("Tor: connected.");
            s_f.addEventListener(Event.CONNECT, fac_connected);
            s_f.addEventListener(Event.CLOSE, function (e:Event):void {
                puts("Facilitator: closed connection.");
            });
            s_f.addEventListener(IOErrorEvent.IO_ERROR, function (e:IOErrorEvent):void {
                puts("Facilitator: I/O error: " + e.text + ".");
                if (s_t.connected)
                    s_t.close();
            });
            s_f.addEventListener(SecurityErrorEvent.SECURITY_ERROR, function (e:SecurityErrorEvent):void {
                puts("Facilitator: security error: " + e.text + ".");
                if (s_t.connected)
                    s_t.close();
            });

            puts("Facilitator: connecting to " + fac_addr.host + ":" + fac_addr.port + ".");
            s_f.connect(fac_addr.host, fac_addr.port);
        }

        private function fac_connected(e:Event):void
        {
            puts("Facilitator: connected.");

            s_f.addEventListener(ProgressEvent.SOCKET_DATA, function (e:ProgressEvent):void {
                var client_spec:String;
                var client_addr:Object;

                client_spec = s_f.readMultiByte(e.bytesLoaded, "utf-8");
                puts("Facilitator: got \"" + client_spec + "\"");

                client_addr = parse_addr_spec(client_spec);
                if (!client_addr) {
                    puts("Error: Client spec must be in the form \"host:port\".");
                    return;
                }
                if (client_addr.host == "0.0.0.0" && client_addr.port == 0) {
                    puts("Error: Facilitator has no clients.");
                    return;
                }

                puts("Client: connecting to " + client_addr.host + ":" + client_addr.port + ".");
                s_c.connect(client_addr.host, client_addr.port);

            });

            s_f.writeUTFBytes("GET / HTTP/1.0\r\n\r\n");
        }

        private function client_connected(e:Event):void
        {
            puts("Client: connected.");

            s_t.addEventListener(ProgressEvent.SOCKET_DATA, function (e:ProgressEvent):void {
                var bytes:ByteArray = new ByteArray();
                s_t.readBytes(bytes, 0, e.bytesLoaded);
                puts("Tor: read " + bytes.length + ".");
                s_c.writeBytes(bytes);
            });
            s_c.addEventListener(ProgressEvent.SOCKET_DATA, function (e:ProgressEvent):void {
                var bytes:ByteArray = new ByteArray();
                s_c.readBytes(bytes, 0, e.bytesLoaded);
                puts("Client: read " + bytes.length + ".");
                s_t.writeBytes(bytes);
            });
        }

        private static function parse_addr_spec(spec:String):Object
        {
            var parts:Array;
            var addr:Object;

            parts = spec.split(":", 2);
            if (parts.length != 2 || !parseInt(parts[1]))
                return null;
            addr = {}
            addr.host = parts[0];
            addr.port = parseInt(parts[1]);

            return addr;
        }
    }
}

Handle the Tor relay address as an instance variable.

Comment the hardcoded relay address.


package aerys.minko.render.shader.compiler
{
	import aerys.minko.render.shader.compiler.allocator.Allocation;
	import aerys.minko.render.shader.compiler.allocator.ParameterAllocation;
	import aerys.minko.render.shader.compiler.visitor.writer.WriteAgal;
	import aerys.minko.render.shader.compiler.visitor.writer.WriteDot;
	import aerys.minko.render.shader.node.INode;
	import aerys.minko.render.shader.node.leaf.AbstractParameter;
	import aerys.minko.render.shader.node.leaf.StyleParameter;
	import aerys.minko.render.shader.node.leaf.TransformParameter;
	import aerys.minko.render.shader.node.leaf.WorldParameter;
	import aerys.minko.render.shader.node.operation.AbstractOperation;

	import flash.display.BitmapData;
	import flash.geom.Matrix;
	import flash.geom.Rectangle;
	import flash.text.TextField;

	public class DebugCompiler extends Compiler
	{
		internal static const FIELD_WIDTH	: uint = 20;
		internal static const FIELD_HEIGHT	: uint = 25;

		public function DebugCompiler()
		{
			super();
		}

		public function compileAgalVertexShader() : String
		{
			return new WriteAgal(
				_attrAllocator, _fsTmpAllocator, _varyingAllocator,
				_fsConstAllocator, _vsTmpAllocator, _vsConstAllocator
			).processVertexShader(_vertexOps);
		}

		public function compileAgalFragmentShader() : String
		{
			return new WriteAgal(
				_attrAllocator, _fsTmpAllocator, _varyingAllocator,
				_fsConstAllocator, _vsTmpAllocator, _vsConstAllocator
			).processFragmentShader(_colorNode);
		}

		public function writeDotGraph() : String
		{
			return new WriteDot().processShader(_clipspacePosNode, _colorNode);
		}

		public function writeConstantAllocationSummary(vertexShader : Boolean	= true) : String
		{
			var offsetToLetter		: Vector.<String> = Vector.<String>(['x', 'y', 'z', 'w']);
			var summary				: String = '';

			var allocationTable 	: Vector.<ParameterAllocation>	= vertexShader ? _vsParams : _fsParams;
			var constantTable		: Vector.<Number>				= vertexShader ? _vsConstData : _fsConstData;

			var occupiedRegisters	: uint = constantTable.length / 4;
			for (var registerId : uint = 0; registerId < occupiedRegisters; ++registerId)
				for (var offsetId : uint = 0; offsetId < 4; ++offsetId)
				{
					var foundInParameterTable : Boolean = false;

					for each (var allocation : ParameterAllocation in allocationTable)
					{
						if (allocation.offset == 4 * registerId + offsetId)
						{
							foundInParameterTable = true;

							summary += (vertexShader ? "vc" : "fc");
							if (allocation.size < 4)
							{
								summary += registerId + '.';
								for (var i : uint = allocation.offset % 4; i < allocation.offset % 4 + allocation.size && i < 4; ++i)
									summary += offsetToLetter[i];
							}
							else if (allocation.size == 16)
							{
								summary += '[' + registerId + '-' + (registerId + 3) + ']';
							}

							var parameter : AbstractParameter = allocation.parameter;
							if (parameter is StyleParameter)
							{
								var styleParam : StyleParameter = parameter as StyleParameter;
								summary += "\t\tStyleParameter['" + styleParam.key + "']\n";
							}
							else if (parameter is WorldParameter)
							{
								var worldParam : WorldParameter = parameter as WorldParameter;
								summary += "\t\tWorldParameter[class='"
									+ worldParam.className + "', index='"
									+ worldParam.index + "', field='"
									+ worldParam.field + "']\n";
							}
							else if (parameter is TransformParameter)
							{
								var transformParam : TransformParameter = parameter as TransformParameter;
								summary += "\t\tTransformParameter[key='"
									+ transformParam.key + "']\n";
							}

							break;
						}
						else if (allocation.offset < 4 * registerId + offsetId
							&& allocation.offset + allocation.size > 4 * registerId + offsetId)
						{
							foundInParameterTable = true;
							break;
						}
					}

					if (!foundInParameterTable)
					{
						summary += (vertexShader ? "vc" : "fc") + registerId.toString()
							+ '.' + offsetToLetter[offsetId]
							+ "\t\tConstant[value='" + constantTable[4 * registerId + offsetId] + "']\n";
					}
				}

			return summary;
		}

		public function writeTemporaryAllocationSummary(vertexShader : Boolean = true) : BitmapData
		{
			var allocations : Vector.<Allocation>	= vertexShader ? _vsTmpAllocator.allocations : _fsTmpAllocator.allocations;
			var allocation	: Allocation;

			var maxOpId 	: uint = 0;
			var maxOffset	: uint = 0;
			for each (allocation in allocations)
			{
				if (allocation.endId > maxOpId)
					maxOpId = allocation.endId;
				if (allocation.offset + allocation.size > maxOffset)
					maxOffset = allocation.offset + allocation.size
			}
			var bitmapData	: BitmapData	= new BitmapData(FIELD_HEIGHT * maxOffset, FIELD_WIDTH * maxOpId, false, 0xFFFFFF);

			var textField	: TextField		= new TextField();
			for each (allocation in allocations)
			{
				var rect : Rectangle = new Rectangle(
					allocation.offset						* FIELD_HEIGHT,
					(allocation.beginId - 1)				* FIELD_WIDTH,
					allocation.size							* FIELD_HEIGHT,
					(allocation.endId - allocation.beginId)	* FIELD_WIDTH
				);

				bitmapData.fillRect(rect, Math.random() * 0x505050 + 0x909090);

				textField.text = AbstractOperation(allocation.node).instructionName;
				bitmapData.draw(textField, new Matrix(1, 0, 0, 1, rect.x, rect.y));
			}

			var offsetId : uint;
			for (offsetId = 1; offsetId < maxOffset; offsetId += 1)
				bitmapData.fillRect(new Rectangle(
					offsetId * FIELD_HEIGHT,
					0,
					1,
					FIELD_WIDTH * maxOpId
				), 0xBBBBBB);

			for (var operationId : uint = 1; operationId < maxOpId; ++operationId)
				bitmapData.fillRect(new Rectangle(
					0,
					operationId * FIELD_WIDTH,
					maxOffset * FIELD_HEIGHT,
					1
				), 0xBBBBBB);

			for (offsetId = 4; offsetId < maxOffset; offsetId += 4)
				bitmapData.fillRect(new Rectangle(
					offsetId * FIELD_HEIGHT,
					0,
					1,
					FIELD_WIDTH * maxOpId
				), 0);

			return bitmapData;
		}

	}
}

package aerys.minko.render.shader.compiler
{
	import aerys.minko.render.shader.compiler.allocator.Allocation;
	import aerys.minko.render.shader.compiler.allocator.ParameterAllocation;
	import aerys.minko.render.shader.compiler.visitor.writer.WriteAgal;
	import aerys.minko.render.shader.compiler.visitor.writer.WriteDot;
	import aerys.minko.render.shader.node.INode;
	import aerys.minko.render.shader.node.leaf.AbstractParameter;
	import aerys.minko.render.shader.node.leaf.StyleParameter;
	import aerys.minko.render.shader.node.leaf.TransformParameter;
	import aerys.minko.render.shader.node.leaf.WorldParameter;
	import aerys.minko.render.shader.node.operation.AbstractOperation;

	import flash.display.BitmapData;
	import flash.geom.Matrix;
	import flash.geom.Rectangle;
	import flash.text.TextField;

	public class DebugCompiler extends Compiler
	{
		internal static const FIELD_WIDTH	: uint = 20;
		internal static const FIELD_HEIGHT	: uint = 25;

		public function DebugCompiler()
		{
			super();
		}

		public function compileAgalVertexShader() : String
		{
			return new WriteAgal(
				_attrAllocator, _fsTmpAllocator, _varyingAllocator,
				_fsConstAllocator, _vsTmpAllocator, _vsConstAllocator
			).processVertexShader(_vertexOps);
		}

		public function compileAgalFragmentShader() : String
		{
			return new WriteAgal(
				_attrAllocator, _fsTmpAllocator, _varyingAllocator,
				_fsConstAllocator, _vsTmpAllocator, _vsConstAllocator
			).processFragmentShader(_colorNode);
		}

		public function writeDotGraph() : String
		{
			return new WriteDot().processShader(_clipspacePosNode, _colorNode);
		}

		public function writeConstantAllocationSummary(vertexShader : Boolean	= true) : String
		{
			var offsetToLetter		: Vector.<String> = Vector.<String>(['x', 'y', 'z', 'w']);
			var summary				: String = '';

			var allocationTable 	: Vector.<ParameterAllocation>	= vertexShader ? _vsParams : _fsParams;
			var constantTable		: Vector.<Number>				= vertexShader ? _vsConstData : _fsConstData;

			var occupiedRegisters	: uint = constantTable.length / 4;
			for (var registerId : uint = 0; registerId < occupiedRegisters; ++registerId)
				for (var offsetId : uint = 0; offsetId < 4; ++offsetId)
				{
					var foundInParameterTable : Boolean = false;

					for each (var allocation : ParameterAllocation in allocationTable)
					{
						if (allocation.offset == 4 * registerId + offsetId)
						{
							foundInParameterTable = true;

							summary += (vertexShader ? "vc" : "fc");
							if (allocation.size < 4)
							{
								summary += registerId + '.';
								for (var i : uint = allocation.offset % 4; i < allocation.offset % 4 + allocation.size && i < 4; ++i)
									summary += offsetToLetter[i];
							}
							else if (allocation.size == 4)
							{
								summary += registerId;
							}
							else if (allocation.size == 16)
							{
								summary += '[' + registerId + '-' + (registerId + 3) + ']';
							}

							var parameter : AbstractParameter = allocation.parameter;
							if (parameter is StyleParameter)
							{
								var styleParam : StyleParameter = parameter as StyleParameter;
								summary += "\t\tStyleParameter['" + styleParam.key + "']\n";
							}
							else if (parameter is WorldParameter)
							{
								var worldParam : WorldParameter = parameter as WorldParameter;
								summary += "\t\tWorldParameter[class='"
									+ worldParam.className + "', index='"
									+ worldParam.index + "', field='"
									+ worldParam.field + "']\n";
							}
							else if (parameter is TransformParameter)
							{
								var transformParam : TransformParameter = parameter as TransformParameter;
								summary += "\t\tTransformParameter[key='"
									+ transformParam.key + "']\n";
							}

							break;
						}
						else if (allocation.offset < 4 * registerId + offsetId
							&& allocation.offset + allocation.size > 4 * registerId + offsetId)
						{
							foundInParameterTable = true;
							break;
						}
					}

					if (!foundInParameterTable)
					{
						summary += (vertexShader ? "vc" : "fc") + registerId.toString()
							+ '.' + offsetToLetter[offsetId]
							+ "\t\tConstant[value='" + constantTable[4 * registerId + offsetId] + "']\n";
					}
				}

			return summary;
		}

		public function writeTemporaryAllocationSummary(vertexShader : Boolean = true) : BitmapData
		{
			var allocations : Vector.<Allocation>	= vertexShader ? _vsTmpAllocator.allocations : _fsTmpAllocator.allocations;
			var allocation	: Allocation;

			var maxOpId 	: uint = 0;
			var maxOffset	: uint = 0;
			for each (allocation in allocations)
			{
				if (allocation.endId > maxOpId)
					maxOpId = allocation.endId;
				if (allocation.offset + allocation.size > maxOffset)
					maxOffset = allocation.offset + allocation.size
			}
			var bitmapData	: BitmapData	= new BitmapData(FIELD_HEIGHT * maxOffset, FIELD_WIDTH * maxOpId, false, 0xFFFFFF);

			var textField	: TextField		= new TextField();
			for each (allocation in allocations)
			{
				var rect : Rectangle = new Rectangle(
					allocation.offset						* FIELD_HEIGHT,
					(allocation.beginId - 1)				* FIELD_WIDTH,
					allocation.size							* FIELD_HEIGHT,
					(allocation.endId - allocation.beginId)	* FIELD_WIDTH
				);

				bitmapData.fillRect(rect, Math.random() * 0x505050 + 0x909090);

				textField.text = AbstractOperation(allocation.node).instructionName;
				bitmapData.draw(textField, new Matrix(1, 0, 0, 1, rect.x, rect.y));
			}

			var offsetId : uint;
			for (offsetId = 1; offsetId < maxOffset; offsetId += 1)
				bitmapData.fillRect(new Rectangle(
					offsetId * FIELD_HEIGHT,
					0,
					1,
					FIELD_WIDTH * maxOpId
				), 0xBBBBBB);

			for (var operationId : uint = 1; operationId < maxOpId; ++operationId)
				bitmapData.fillRect(new Rectangle(
					0,
					operationId * FIELD_WIDTH,
					maxOffset * FIELD_HEIGHT,
					1
				), 0xBBBBBB);

			for (offsetId = 4; offsetId < maxOffset; offsetId += 4)
				bitmapData.fillRect(new Rectangle(
					offsetId * FIELD_HEIGHT,
					0,
					1,
					FIELD_WIDTH * maxOpId
				), 0);

			return bitmapData;
		}

	}
}

Fix bug in debug compiler when creating a constant allocation summary with 4 sized allocations


package aerys.minko.type
{
	public final class Signal
	{
		private var _name			: String	= null;

		private var _callbacks		: Array		= [];
		private var _numCallbacks	: uint		= 0;

		private var _executed		: Boolean	= false;
		private var _numAdded		: uint		= 0;
		private var _toAdd			: Array		= null;
		private var _numRemoved		: uint		= 0;
		private var _toRemove		: Array		= null;

		public function get numCallbacks() : uint
		{
			return _numCallbacks;
		}

		public function Signal(name : String)
		{
			_name = name;
		}

		public function add(callback : Function) : void
		{
			if (_executed)
			{
				if (_toAdd)
					_toAdd.push(callback);
				else
					_toAdd = [callback];
				++_numAdded;

				return ;
			}

			_callbacks[_numCallbacks] = callback;
			++_numCallbacks;
		}

		public function remove(callback : Function) : void
		{
			if (_executed)
			{
				if (_toRemove)
					_toRemove.push(callback);
				else
					_toRemove = [callback];
				++_numRemoved;

				return ;
			}

			var index : int = _callbacks.indexOf(callback);

			if (index < 0)
				throw new Error('This callback does not exist.');

			--_numCallbacks;
			_callbacks[index] = _callbacks[_numCallbacks];
			_callbacks.length = _numCallbacks;
		}

		public function hasCallback(callback : Function) : Boolean
		{
			return _callbacks.indexOf(callback) >= 0;
		}

		public function execute(...params) : void
		{
			_executed = true;
			for (var i : uint = 0; i < _numCallbacks; ++i)
				(_callbacks[i] as Function).apply(null, params);
			_executed = false;

			for (i = 0; i < _numAdded; ++i)
				add(_toAdd[i]);
			_numAdded = 0;
			_toAdd = null;

			for (i = 0; i < _numRemoved; ++i)
				remove(_toRemove[i]);
			_numRemoved = 0;
			_toRemove = null;
		}
	}
}

package aerys.minko.type
{
	public final class Signal
	{
		private var _name			: String	= null;

		private var _callbacks		: Array		= [];
		private var _numCallbacks	: uint		= 0;

		private var _executed		: Boolean	= false;
		private var _numAdded		: uint		= 0;
		private var _toAdd			: Array		= null;
		private var _numRemoved		: uint		= 0;
		private var _toRemove		: Array		= null;

		public function get numCallbacks() : uint
		{
			return _numCallbacks;
		}

		public function Signal(name : String)
		{
			_name = name;
		}

		public function add(callback : Function) : void
		{
			if (_executed)
			{
				if (_toAdd)
					_toAdd.push(callback);
				else
					_toAdd = [callback];
				++_numAdded;

				return ;
			}

			_callbacks[_numCallbacks] = callback;
			++_numCallbacks;
		}

		public function remove(callback : Function) : void
		{
			var index : int = _callbacks.indexOf(callback);

			if (index < 0)
				throw new Error('This callback does not exist.');

			if (_executed)
			{
				if (_toRemove)
					_toRemove.push(callback);
				else
					_toRemove = [callback];
				++_numRemoved;

				return ;
			}

			--_numCallbacks;
			_callbacks[index] = _callbacks[_numCallbacks];
			_callbacks.length = _numCallbacks;
		}

		public function hasCallback(callback : Function) : Boolean
		{
			return _callbacks.indexOf(callback) >= 0;
		}

		public function execute(...params) : void
		{
			_executed = true;
			for (var i : uint = 0; i < _numCallbacks; ++i)
				(_callbacks[i] as Function).apply(null, params);
			_executed = false;

			for (i = 0; i < _numAdded; ++i)
				add(_toAdd[i]);
			_numAdded = 0;
			_toAdd = null;

			for (i = 0; i < _numRemoved; ++i)
				remove(_toRemove[i]);
			_numRemoved = 0;
			_toRemove = null;
		}
	}
}

check the callack actually exists at the begining of Signal.removeCallback()


package logic
{
	/**
	 AGORA - an interactive and web-based argument mapping tool that stimulates reasoning,
	 reflection, critique, deliberation, and creativity in individual argument construction
	 and in collaborative or adversarial settings.
	 Copyright (C) 2011 Georgia Institute of Technology

	 This program is free software: you can redistribute it and/or modify
	 it under the terms of the GNU Affero General Public License as
	 published by the Free Software Foundation, either version 3 of the
	 License, or (at your option) any later version.

	 This program is distributed in the hope that it will be useful,
	 but WITHOUT ANY WARRANTY; without even the implied warranty of
	 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	 GNU Affero General Public License for more details.

	 You should have received a copy of the GNU Affero General Public License
	 along with this program.  If not, see <http://www.gnu.org/licenses/>.

	 */
	import classes.ArgumentPanel;

	import components.ArgSelector;

	import mx.controls.Alert;
	import mx.messaging.channels.StreamingAMFChannel;

	public class ModusPonens extends ParentArg
	{

		public function ModusPonens()
		{
			_langTypes = ["If-then","Implies","Whenever","Only if","Provided that","Sufficient condition","Necessary condition"];
			dbLangTypeNames = ["ifthen","implies","whenever","onlyif","providedthat","sufficient","necessary"];
			_expLangTypes = ["If-then","Whenever","Provided that"];
			myname = MOD_PON;
			_dbType = "MP";
		}

		override public function getLanguageType(dbString:String):String
		{
			for(var i:int=0;i<dbLangTypeNames.length;i++)
			{
				if(dbString.indexOf(dbLangTypeNames[i]) >= 0)
				{
					return _langTypes[i];
				}

			}
			return "";
		}

		override public function createLinks():void
		{
			if(inference.claim.inference != null && inference.claim.statementNegated)
			{
				Alert.show("Error: Statement cannot be negative");
			}

			//make claim and reason un-multiStatement
			if(inference.claim.multiStatement)
			{
				inference.claim.multiStatement = false;
			}

			for(var i:int=0; i < inference.reasons.length; i++)
			{
				if(inference.reasons[i].multiStatement)
				{
					inference.reasons[i].multiStatement = false;
				}
			}

			trace('claim user entered value:'+inference.claim.userEntered);
			if(inference.claim.userEntered == false && inference.claim.inference == null && inference.claim.rules.length < 2)
			{
				inference.claim.input1.text = "P";
				inference.reasons[0].input1.text = "Q";
				//make them uneditable. It automatically
				//sets the displayTxt Text control
				inference.claim.makeUnEditable();
				inference.reasons[0].makeUnEditable();
			}

			//claim and reasons should not be negated
			if(inference.claim.statementNegated)
			{
				inference.claim.statementNegated = false;
			}

			for(i=0; i < inference.reasons.length; i++)
			{
				if(inference.reasons[i].statementNegated)
				{
					inference.reasons[i].statementNegated = false;
				}
			}
			inference.implies = true;
			super.createLinks();
		}

		override public function correctUsage():String {
			var output:String = "";
			var reason:Vector.<ArgumentPanel> = inference.reasons;
			var claim:ArgumentPanel = inference.claim;
			var i:int;
			var reasonStr:String;
			switch(inference.myschemeSel.selectedType) {
				case _langTypes[0]:
					reasonStr = "";
					output += "If "
					for(i=0; i < reason.length - 1; i++)
					{
						output += reason[i].stmt + " and if ";
						reasonStr = reasonStr + reason[i].stmt + " and if ";
					}
					output += reason[i].stmt + ", then " + claim.stmt;
					reasonStr = reasonStr + reason[i].stmt;
					inference.inputs[1].text = reasonStr;
					inference.inputs[0].text = claim.stmt;
					inference.inputs[0].forwardUpdate();
					inference.inputs[1].forwardUpdate();
					break;
				case _langTypes[1]: // Implies
					output += reason[0].stmt + " implies " + claim.stmt;
					inference.inputs[1].text = reason[0].stmt;
					inference.inputs[0].text = claim.stmt;
					inference.inputs[0].forwardUpdate();
					inference.inputs[1].forwardUpdate();
					break;
				case _langTypes[2]: //Whenever
					reasonStr = "";
					output += "Whenever "
					for(i=0;i<reason.length-1;i++)
					{
						output += reason[i].stmt + " and ";
						reasonStr += reason[i].stmt + " and ";
					}
					output += reason[i].stmt + ", "+ claim.stmt;
					reasonStr = reasonStr + reason[i].stmt;
					inference.inputs[1].text = reasonStr;
					inference.inputs[0].text = claim.stmt;
					inference.inputs[0].forwardUpdate();
					inference.inputs[1].forwardUpdate();
					break;
				case _langTypes[3]: // Only if
					output += reason[0].stmt + " only if " + claim.stmt;
					inference.inputs[1].text = reason[0].stmt;
					inference.inputs[0].text = claim.stmt;
					inference.inputs[0].forwardUpdate();
					inference.inputs[1].forwardUpdate();
					break;
				case _langTypes[4]: // Provided that
					reasonStr = "";
					output += claim.stmt + " provided that ";
					for(i=0;i<reason.length-1;i++)
					{
						output += reason[i].stmt + " and ";
						reasonStr += reason[i].stmt + " and ";
					}
					output += reason[i].stmt;
					reasonStr = reasonStr + reason[i].stmt;
					inference.inputs[1].text = reasonStr;
					inference.inputs[0].text = claim.stmt;
					inference.inputs[0].forwardUpdate();
					inference.inputs[1].forwardUpdate();
					break;
				case _langTypes[5]: // Sufficient condition
					output += reason[0].stmt + " is a sufficient condition for " + claim.stmt;
					inference.inputs[1].text = reason[0].stmt;
					inference.inputs[0].text = claim.stmt;
					inference.inputs[0].forwardUpdate();
					inference.inputs[1].forwardUpdate();
					break;
				case _langTypes[6]: // Necessary condition
					output += claim.stmt + " is a necessary condition for " + reason[0].stmt;
					inference.inputs[1].text = reason[0].stmt;
					inference.inputs[0].text = claim.stmt;
					inference.inputs[0].forwardUpdate();
					inference.inputs[1].forwardUpdate();
					break;
				case _langTypes[7]: //If and only if
					output += claim.stmt + " if and only if " + reason[0].stmt; 	// IMP!! TODO: if-and-only-if2 : both claim and reason negated
					inference.inputs[1].text = reason[0].stmt;
					inference.inputs[0].text = claim.stmt;
					inference.inputs[0].forwardUpdate();
					inference.inputs[1].forwardUpdate();
					break;
				case _langTypes[8]: //Necessary and sufficient condition
					output += claim.stmt + " is a necessary and sufficient condition for " + reason[0].stmt;
					inference.inputs[1].text = reason[0].stmt;
					inference.inputs[0].text = claim.stmt;// TODO: Necessary-and-sufficient2 : both claim and reason negated
					inference.inputs[0].forwardUpdate();
					inference.inputs[1].forwardUpdate();
					break;
				case _langTypes[9]: //Equivalent
					output += claim.stmt + " and " + reason[0].stmt + " are equivalent"; 	// TODO: Equivalent2 : both claim and reason negated
					inference.inputs[1].text = reason[0].stmt;
					inference.inputs[0].text = claim.stmt;
					inference.inputs[0].forwardUpdate();
					inference.inputs[1].forwardUpdate();
			}
			return output;
		}
	}
}

package logic
{
	/**
	 AGORA - an interactive and web-based argument mapping tool that stimulates reasoning,
	 reflection, critique, deliberation, and creativity in individual argument construction
	 and in collaborative or adversarial settings.
	 Copyright (C) 2011 Georgia Institute of Technology

	 This program is free software: you can redistribute it and/or modify
	 it under the terms of the GNU Affero General Public License as
	 published by the Free Software Foundation, either version 3 of the
	 License, or (at your option) any later version.

	 This program is distributed in the hope that it will be useful,
	 but WITHOUT ANY WARRANTY; without even the implied warranty of
	 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	 GNU Affero General Public License for more details.

	 You should have received a copy of the GNU Affero General Public License
	 along with this program.  If not, see <http://www.gnu.org/licenses/>.

	 */
	import classes.ArgumentPanel;

	import components.ArgSelector;

	import mx.controls.Alert;
	import mx.messaging.channels.StreamingAMFChannel;

	public class ModusPonens extends ParentArg
	{

		public function ModusPonens()
		{
			_langTypes = ["If-then","Implies","Whenever","Only if","Provided that","Sufficient condition","Necessary condition"];
			dbLangTypeNames = ["ifthen","implies","whenever","onlyif","providedthat","sufficient","necessary"];
			_expLangTypes = ["If-then","Whenever","Provided that"];
			myname = MOD_PON;
			_dbType = "MP";
		}

		override public function getLanguageType(dbString:String):String
		{
			for(var i:int=0;i<dbLangTypeNames.length;i++)
			{
				if(dbString.indexOf(dbLangTypeNames[i]) >= 0)
				{
					return _langTypes[i];
				}

			}
			return "";
		}

		override public function createLinks():void
		{
			if(inference.claim.inference != null && inference.claim.statementNegated)
			{
				Alert.show("Error: Statement cannot be negative");
			}

			//make claim and reason un-multiStatement
			if(inference.claim.multiStatement)
			{
				inference.claim.multiStatement = false;
			}

			for(var i:int=0; i < inference.reasons.length; i++)
			{
				if(inference.reasons[i].multiStatement)
				{
					inference.reasons[i].multiStatement = false;
				}
			}

			trace('claim user entered value:'+inference.claim.userEntered);
			if(inference.claim.userEntered == false && inference.claim.inference == null && inference.claim.rules.length < 2)
			{
				inference.claim.input1.text = "P";
				inference.reasons[0].input1.text = "Q";
				//make them uneditable. It automatically
				//sets the displayTxt Text control
				inference.claim.makeUnEditable();
				inference.reasons[0].makeUnEditable();
			}

			//claim and reasons should not be negated
			if(inference.claim.statementNegated)
			{
				inference.claim.statementNegated = false;
			}

			for(i=0; i < inference.reasons.length; i++)
			{
				if(inference.reasons[i].statementNegated)
				{
					inference.reasons[i].statementNegated = false;
				}
			}
			inference.implies = true;
			super.createLinks();
		}

		override public function correctUsage():String {
			var output:String = "";
			var reason:Vector.<ArgumentPanel> = inference.reasons;
			var claim:ArgumentPanel = inference.claim;
			var i:int;
			var reasonStr:String;
			switch(inference.myschemeSel.selectedType) {
				case _langTypes[0]:
					reasonStr = "";
					output += "If ";
					for(i=0; i < reason.length - 1; i++)
					{
						output += reason[i].stmt + " and if ";
						reasonStr = reasonStr + reason[i].stmt + " and if ";
					}
					output += reason[i].stmt + ", then " + claim.stmt;
					reasonStr = reasonStr + reason[i].stmt;
					inference.inputs[1].text = reasonStr;
					inference.inputs[0].text = claim.stmt;
					inference.inputs[0].forwardUpdate();
					inference.inputs[1].forwardUpdate();
					break;
				case _langTypes[1]: // Implies
					output += reason[0].stmt + " implies " + claim.stmt;
					inference.inputs[1].text = reason[0].stmt;
					inference.inputs[0].text = claim.stmt;
					inference.inputs[0].forwardUpdate();
					inference.inputs[1].forwardUpdate();
					break;
				case _langTypes[2]: //Whenever
					reasonStr = "";
					output += "Whenever "
					for(i=0;i<reason.length-1;i++)
					{
						output += reason[i].stmt + " and ";
						reasonStr += reason[i].stmt + " and ";
					}
					output += reason[i].stmt + ", "+ claim.stmt;
					reasonStr = reasonStr + reason[i].stmt;
					inference.inputs[1].text = reasonStr;
					inference.inputs[0].text = claim.stmt;
					inference.inputs[0].forwardUpdate();
					inference.inputs[1].forwardUpdate();
					break;
				case _langTypes[3]: // Only if
					output += reason[0].stmt + " only if " + claim.stmt;
					inference.inputs[1].text = reason[0].stmt;
					inference.inputs[0].text = claim.stmt;
					inference.inputs[0].forwardUpdate();
					inference.inputs[1].forwardUpdate();
					break;
				case _langTypes[4]: // Provided that
					reasonStr = "";
					output += claim.stmt + " provided that ";
					for(i=0;i<reason.length-1;i++)
					{
						output += reason[i].stmt + " and ";
						reasonStr += reason[i].stmt + " and ";
					}
					output += reason[i].stmt;
					reasonStr = reasonStr + reason[i].stmt;
					inference.inputs[1].text = reasonStr;
					inference.inputs[0].text = claim.stmt;
					inference.inputs[0].forwardUpdate();
					inference.inputs[1].forwardUpdate();
					break;
				case _langTypes[5]: // Sufficient condition
					output += reason[0].stmt + " is a sufficient condition for " + claim.stmt;
					inference.inputs[1].text = reason[0].stmt;
					inference.inputs[0].text = claim.stmt;
					inference.inputs[0].forwardUpdate();
					inference.inputs[1].forwardUpdate();
					break;
				case _langTypes[6]: // Necessary condition
					output += claim.stmt + " is a necessary condition for " + reason[0].stmt;
					inference.inputs[1].text = reason[0].stmt;
					inference.inputs[0].text = claim.stmt;
					inference.inputs[0].forwardUpdate();
					inference.inputs[1].forwardUpdate();
					break;
				case _langTypes[7]: //If and only if
					output += claim.stmt + " if and only if " + reason[0].stmt; 	// IMP!! TODO: if-and-only-if2 : both claim and reason negated
					inference.inputs[1].text = reason[0].stmt;
					inference.inputs[0].text = claim.stmt;
					inference.inputs[0].forwardUpdate();
					inference.inputs[1].forwardUpdate();
					break;
				case _langTypes[8]: //Necessary and sufficient condition
					output += claim.stmt + " is a necessary and sufficient condition for " + reason[0].stmt;
					inference.inputs[1].text = reason[0].stmt;
					inference.inputs[0].text = claim.stmt;// TODO: Necessary-and-sufficient2 : both claim and reason negated
					inference.inputs[0].forwardUpdate();
					inference.inputs[1].forwardUpdate();
					break;
				case _langTypes[9]: //Equivalent
					output += claim.stmt + " and " + reason[0].stmt + " are equivalent"; 	// TODO: Equivalent2 : both claim and reason negated
					inference.inputs[1].text = reason[0].stmt;
					inference.inputs[0].text = claim.stmt;
					inference.inputs[0].forwardUpdate();
					inference.inputs[1].forwardUpdate();
			}
			return output;
		}
	}
}

Fix obvious semicolon error

Fix obvious semicolon error


package
{

  import flash.text.TextField;

  import org.flixel.FlxG;
  import org.flixel.FlxGame;
  import org.flixel.FlxU;

  [SWF(width=416, height=600, backgroundColor="#000000")]
  [Frame(factoryClass="Preloader")]

  // Custom FlxGame extensions.

  public class MorningStroll extends FlxGame
  {

    public function MorningStroll()
    {
      super(416, 600, MenuState, 1, 24, 24);
    }

    override protected function createFocusScreen():void
    {
      // Draw transparent black backdrop.
      // From Flixel.
      this._focus.graphics.moveTo(0, 0);
      this._focus.graphics.beginFill(0, 0.8);
      this._focus.graphics.lineTo(FlxG.width, 0);
      this._focus.graphics.lineTo(FlxG.width, FlxG.height);
      this._focus.graphics.lineTo(0, FlxG.height);
      this._focus.graphics.lineTo(0, 0);
      this._focus.graphics.endFill();

      var pauseTitle:TextField = new Text(0, 0, FlxG.width,
        "Paused", Text.H1).getTextField();
      var quitText:TextField = new Text(0, 0, FlxG.width,
        "Press Q to quit").getTextField();

      pauseTitle.y = Text.BASELINE * 6;
      quitText.y = pauseTitle.y + Text.BASELINE * 2;

      this._focus.addChild(pauseTitle);
      this._focus.addChild(quitText);

      addChild(this._focus);

    }

    public static function endGame():void
    {
      FlxG.fade(0xff000000, 1, function():void {
        FlxG.resetGame();
      });
    }

  }
}

package
{

  import flash.text.TextField;

  import org.flixel.FlxG;
  import org.flixel.FlxGame;
  import org.flixel.FlxU;

  [SWF(width=416, height=600, backgroundColor="#000000")]
  [Frame(factoryClass="Preloader")]

  // Custom FlxGame extensions.

  public class MorningStroll extends FlxGame
  {

    public function MorningStroll()
    {
      super(416, 600, MenuState, 1, 24, 24);
    }

    override protected function createFocusScreen():void
    {
      // Draw transparent black backdrop.
      // From Flixel.
      this._focus.graphics.moveTo(0, 0);
      this._focus.graphics.beginFill(0, 0.8);
      this._focus.graphics.lineTo(FlxG.width, 0);
      this._focus.graphics.lineTo(FlxG.width, FlxG.height);
      this._focus.graphics.lineTo(0, FlxG.height);
      this._focus.graphics.lineTo(0, 0);
      this._focus.graphics.endFill();

      var pauseTitle:TextField = new Text(0, 0, FlxG.width,
        "Paused", Text.H1).getTextField();
      var instructions:TextField = new Text(0, 0, FlxG.width, [
        "Arrow keys to move",
        "Press Q to quit",
        "Press 0, -, + for volume"
      ].join("\n\n")).getTextField();

      pauseTitle.y = Text.BASELINE * 6;
      instructions.y = pauseTitle.y + Text.BASELINE * 2;

      this._focus.addChild(pauseTitle);
      this._focus.addChild(instructions);

      addChild(this._focus);

    }

    public static function endGame():void
    {
      FlxG.fade(0xff000000, 1, function():void {
        FlxG.resetGame();
      });
    }

  }
}

Update instructions on pause screen.

Update instructions on pause screen.


void enter(entity_impl& out owner) {
    owner.get_animation_component().play_ani("stand");
}

void update(float delta_time, entity_impl& out owner) {

}

void leave(entity_impl& out owner) {

}

void enter(entity_impl& out owner) {
    owner.get_animation_component().play_ani("stand");
    owner.get_character_physics_component().velocity(0);
    owner.get_character_physics_component().angular_velocity(0);
}

void update(float delta_time, entity_impl& out owner) {

}

void leave(entity_impl& out owner) {

}

set velocity to zero in 'stand'-states enter function.


package Controller.logic
{
	import Model.AGORAModel;
	import Model.ArgumentTypeModel;
	import Model.InferenceModel;
	import Model.SimpleStatementModel;
	import Model.StatementModel;

	import ValueObjects.AGORAParameters;

	import components.ArgSelector;
	import components.ArgumentPanel;
	import components.MenuPanel;

	import mx.controls.Alert;
	import mx.core.FlexGlobals;

	public class NotAllSyllogism extends ParentArg
	{
		private static var instance:NotAllSyllogism;
		public function NotAllSyllogism()
		{
			label = AGORAParameters.getInstance().NOT_ALL_SYLL;
		}

		public static function getInstance():NotAllSyllogism{
			if(instance==null){
				instance = new NotAllSyllogism;
			}
			return instance;
		}

		override public function formText(argumentTypeModel:ArgumentTypeModel):void{

			var output:String = "";
			var reasonText:String = "";
			var reasonModels:Vector.<StatementModel> = argumentTypeModel.reasonModels;
			var claimModel:StatementModel = argumentTypeModel.claimModel;
			var argSelector:ArgSelector = MenuPanel(FlexGlobals.topLevelApplication.map.agoraMap.menuPanelsHash[argumentTypeModel.ID]).schemeSelector;
			var i:int;

			output = "It cannot be the case, at the same time, that ";

			for(i=0; i<reasonModels.length; i++){
				reasonText = reasonText +  reasonModels[i].statement.text + " and that ";
				argumentTypeModel.inferenceModel.statements[i+1].text = reasonModels[i].statement.text;
			}

			output = output + reasonText + claimModel.statement.positiveText;
			argumentTypeModel.inferenceModel.statements[0].text = claimModel.statement.text;
			argumentTypeModel.inferenceModel.statement.text = output;
		}

		override public function deleteLinks(argumentTypeModel:ArgumentTypeModel):void{
			var reasonModels:Vector.<StatementModel> = argumentTypeModel.reasonModels;
			var claimModel:StatementModel = argumentTypeModel.claimModel;
			var inferenceModel:StatementModel = argumentTypeModel.inferenceModel;

			//remove negativity from the inference
			inferenceModel.negated = false;

			//if first claim's argument, remove
			//negativity from the claim
			if(claimModel.firstClaim){
				claimModel.negated = false;
			}

			//remove links from claim to the inference's  statement
			var simpleStatement:SimpleStatementModel;
			var statementTobeUnLinked:SimpleStatementModel;

			simpleStatement = claimModel.statement;
			statementTobeUnLinked = inferenceModel.statements[0];
			removeDependence(simpleStatement, statementTobeUnLinked);

			if(reasonModels.length > 1){
				trace("NotAllSyllogism::deleteLinks: This should not be occuring.");
			}
			//remove links from reasons to the inference's statement
			simpleStatement = reasonModels[0].statement;
			statementTobeUnLinked = inferenceModel.statements[1];
			removeDependence(simpleStatement, statementTobeUnLinked);

			//delete the unnecessary statements in the infernece
			//but this is not required as the scheme could be changed
			//only when there is one reason. If there is only one reasons
			//the number of statements in the inference is going to be
			//only two, which is the default.

		}

		override public function link(argumentTypeModel:ArgumentTypeModel):void{
			var claimModel:StatementModel = argumentTypeModel.claimModel;
			var reasonModels:Vector.<StatementModel> = argumentTypeModel.reasonModels;
			var inferenceModel:StatementModel = argumentTypeModel.inferenceModel;

			//inference is a disjunction
			inferenceModel.connectingString = StatementModel.DISJUNCTION;

			//if first claim, change it to negative
			if(claimModel.firstClaim){
				claimModel.negated = true;
			}

			//connect the claim's statement to the inference's first statement
			//claimModel.statement.forwardList.push(inferenceModel.statements[0]);
			claimModel.statement.addDependentStatement(inferenceModel.statements[0]);

			//connect the reason's statement to the infernece's second statement
			//reasonModels[0].statement.forwardList.push(inferenceModel.statements[1]);
			for(var i:int=0; i<reasonModels.length; i++){
				reasonModels[i].statement.addDependentStatement(inferenceModel.statements[i+1]);
			}
		}

		/*
		override public function get dbType():String
		{
			return _dbType;
		}

		override public function getLanguageType(dbString:String):String{
			return _langTypes[0];
		}

		override public function createLinks():void
		{
			if(inference.claim.inference != null && !inference.claim.statementNegated)
			{
				Alert.show("Error: Statement cannot be positive");
			}

			if(inference.claim.multiStatement)
			{
				inference.claim.multiStatement = false;
			}

			for(var i:int=0; i < inference.reasons.length; i++)
			{
				if(inference.reasons[i].multiStatement)
				{
					inference.reasons[i].multiStatement = false;
				}
			}

			if(inference.claim.userEntered == false && inference.claim.inference == null && inference.claim.rules.length < 2)
			{
				inference.claim.input1.text = "P";
				inference.claim.makeUnEditable();
				inference.reasons[0].input1.text = "Q";
				inference.reasons[0].makeUnEditable();
			}

			if(!inference.claim.statementNegated)
			{
				inference.claim.statementNegated = true;
			}

			for(i=0; i < inference.reasons.length; i++)
			{
				if(inference.reasons[i].statementNegated)
				{
					inference.reasons[i].statementNegated = false;
				}
			}
			inference.implies = false;

			super.createLinks();

		}

		override public function correctUsage():String {
			var output:String = "";
			var reasonStr:String;
			var i:int;

			output += "It cannot be the case, at the same time, that ";
			for(i=0;i<inference.reasons.length;i++)
			{
					output += inference.reasons[i].stmt + " and that ";
					//inference.inputs[i+1].text = inference.reasons[i].stmt;
					//inference.inputs[i+1].forwardUpdate();
			}
			output += inference.claim.positiveStmt;
			//inference.inputs[0].text = inference.claim.positiveStmt;
			//inference.inputs[0].forwardUpdate();
			return output;
		}
		*/
	}
}

package Controller.logic
{
	import Model.AGORAModel;
	import Model.ArgumentTypeModel;
	import Model.InferenceModel;
	import Model.SimpleStatementModel;
	import Model.StatementModel;

	import ValueObjects.AGORAParameters;

	import components.ArgSelector;
	import components.ArgumentPanel;
	import components.MenuPanel;

	import mx.controls.Alert;
	import mx.core.FlexGlobals;

	public class NotAllSyllogism extends ParentArg
	{
		private static var instance:NotAllSyllogism;
		public function NotAllSyllogism()
		{
			label = AGORAParameters.getInstance().NOT_ALL_SYLL;
		}

		public static function getInstance():NotAllSyllogism{
			if(instance==null){
				instance = new NotAllSyllogism;
			}
			return instance;
		}

		override public function formText(argumentTypeModel:ArgumentTypeModel):void{

			var output:String = "";
			var reasonText:String = "";
			var reasonModels:Vector.<StatementModel> = argumentTypeModel.reasonModels;
			var claimModel:StatementModel = argumentTypeModel.claimModel;
			var argSelector:ArgSelector = MenuPanel(FlexGlobals.topLevelApplication.map.agoraMap.menuPanelsHash[argumentTypeModel.ID]).schemeSelector;
			var i:int;

			output = "It cannot be the case, at the same time, that ";

			for(i=0; i<reasonModels.length; i++){
				reasonText = reasonText +  reasonModels[i].statement.text + " and that ";
				argumentTypeModel.inferenceModel.statements[i+1].text = reasonModels[i].statement.text;
			}

			output = output + reasonText + claimModel.statement.positiveText;
			argumentTypeModel.inferenceModel.statements[0].text = claimModel.statement.text;
			argumentTypeModel.inferenceModel.statement.text = output;
		}

		override public function deleteLinks(argumentTypeModel:ArgumentTypeModel):void{
			var reasonModels:Vector.<StatementModel> = argumentTypeModel.reasonModels;
			var claimModel:StatementModel = argumentTypeModel.claimModel;
			var inferenceModel:StatementModel = argumentTypeModel.inferenceModel;

			//remove negativity from the inference
			inferenceModel.negated = false;

			//if first claim's argument, remove
			//negativity from the claim
			if(claimModel.firstClaim){
				claimModel.negated = false;
			}

			//remove links from claim to the inference's  statement
			var simpleStatement:SimpleStatementModel;
			var statementTobeUnLinked:SimpleStatementModel;

			simpleStatement = claimModel.statement;
			statementTobeUnLinked = inferenceModel.statements[0];
			removeDependence(simpleStatement, statementTobeUnLinked);

			if(reasonModels.length > 1){
				trace("NotAllSyllogism::deleteLinks: This should not be occuring.");
			}
			//remove links from reasons to the inference's statement
			simpleStatement = reasonModels[0].statement;
			statementTobeUnLinked = inferenceModel.statements[1];
			removeDependence(simpleStatement, statementTobeUnLinked);

			//delete the unnecessary statements in the infernece
			//but this is not required as the scheme could be changed
			//only when there is one reason. If there is only one reasons
			//the number of statements in the inference is going to be
			//only two, which is the default.

		}

		override public function link(argumentTypeModel:ArgumentTypeModel):void{
			var claimModel:StatementModel = argumentTypeModel.claimModel;
			var reasonModels:Vector.<StatementModel> = argumentTypeModel.reasonModels;
			var inferenceModel:StatementModel = argumentTypeModel.inferenceModel;

			//inference is a disjunction
			inferenceModel.connectingString = StatementModel.DISJUNCTION;

			//if first claim, change it to negative
			if(claimModel.firstClaim){
				claimModel.negated = true;
			}

			//connect the claim's statement to the inference's first statement
			//claimModel.statement.forwardList.push(inferenceModel.statements[0]);
			claimModel.statement.addDependentStatement(inferenceModel.statements[0]);

			//connect the reason's statement to the infernece's second statement
			//reasonModels[0].statement.forwardList.push(inferenceModel.statements[1]);
			for(var i:int=0; i<reasonModels.length; i++){
				reasonModels[i].statement.addDependentStatement(inferenceModel.statements[i+1]);
			}
		}
	}
}

clean up

clean up