package unittests
{
	public class TestDisjunctiveSyllogism
	{
		import logic.DisjunctiveSyllogism;

		import mx.controls.Alert;

		import org.flexunit.Assert;
		private var djs:DisjunctiveSyllogism;
		private var djsReverse:DisjunctiveSyllogism;

		[Before]
		public function setUp():void
		{
			/*
			* reversePos apparently differentiates between Basic Claim and Reason 1.
			* ~~ Printing all reasons in NotPFalse
			* It is not the case that Reason 1
			* Reason 2
			* ~~ Printing all reasons in Reverse NotPFalse
			* It is not the case that Basic Claim
			* Reason 2
			*/
			//DisjunctiveSyllogism(claimText:String, reasonText:Array, reversePos:Boolean,inferenceText:String="", inferencePresent:Boolean=false)
			djsReverse = new DisjunctiveSyllogism("Basic Claim", ["Reason 1", "Reason 2"], true, "Either Foo or Bar, and Baz unless Quux", false);
			djs = new DisjunctiveSyllogism("Basic Claim", ["Reason 1", "Reason 2"], false, "Either Foo or Bar, and Baz unless Quux", false);
		}

		[After]
		public function tearDown():void
		{
		}

		[BeforeClass]
		public static function setUpBeforeClass():void
		{
		}

		[AfterClass]
		public static function tearDownAfterClass():void
		{
		}
		//Copied from the superclass tests
		[Test]
		public function testConstructorClaim():void{
			Assert.assertEquals("Basic Claim", djs.getClaim());
		}
		[Test]
		public function testConstructorReason():void{
			Assert.assertEquals("Reason 1", djs.getReason()[0]);
		}
		//New tests for this subclass's particular functions
		//Not asserting anything because it's currently pointless
		[Test(order=1)]
		public function testNotPTrue():void{
			djs.notP(true);
			trace("~~ Printing all reasons in NotPTrue");
			for each (var reason:String in djs.getReason()){
				trace(reason);
			}
			djsReverse.notP(true);
			trace("~~ Printing all reasons in Reverse NotPTrue");
			for each (reason in djsReverse.getReason()){
				trace(reason);
			}
		}
		[Test(order=2)]
		public function testNotPFalse():void{
			djs.notP(false);
			trace("~~ Printing all reasons in NotPFalse");
			for each (var reason:String in djs.getReason()){
				trace(reason);
			}
			djsReverse.notP(false);
			trace("~~ Printing all reasons in Reverse NotPFalse");
			for each (reason in djsReverse.getReason()){
				trace(reason);
			}
		}
		[Test(order=3)]
		public function testNotQTrue():void{
			djs.notQ(true);
			trace("~~ Printing all reasons in NotQTrue");
			for each (var reason:String in djs.getReason()){
				trace(reason);
			}
			djsReverse.notQ(true);
			trace("~~ Printing all reasons in Reverse NotQTrue");
			for each (reason in djsReverse.getReason()){
				trace(reason);
			}
		}
		[Test(order=4)]
		public function testNotQFalse():void{
			djs.notQ(false);
			trace("~~ Printing all reasons in NotQFalse");
			for each (var reason:String in djs.getReason()){
				trace(reason);
			}
			djsReverse.notQ(false);
			trace("~~ Printing all reasons in Reverse NotQFalse");
			for each (reason in djsReverse.getReason()){
				trace(reason);
			}
		}
		[Test(order=5)]
		public function testAlternatePTrue():void{
			djs.alternateP(true);
			trace("~~ Printing all reasons in AlternatePTrue");
			for each (var reason:String in djs.getReason()){
				trace(reason);
			}
			djsReverse.alternateP(true);
			trace("~~ Printing all reasons in Reverse AlternatePTrue");
			for each (reason in djsReverse.getReason()){
				trace(reason);
			}
		}
		[Test(order=6)]
		public function testAlternatePFalse():void{
			djs.alternateP(false);
			trace("~~ Printing all reasons in AlternatePFalse");
			for each (var reason:String in djs.getReason()){
				trace(reason);
			}
			djsReverse.alternateP(false);
			trace("~~ Printing all reasons in Reverse AlternatePFalse");
			for each (reason in djsReverse.getReason()){
				trace(reason);
			}
		}
		[Test(order=7)]
		public function testAlternateQTrue():void{
			djs.alternateQ(true);
			trace("~~ Printing all reasons in AlternateQTrue");
			for each (var reason:String in djs.getReason()){
				trace(reason);
			}
			djsReverse.alternateQ(true);
			trace("~~ Printing all reasons in Reverse AlternateQTrue");
			for each (reason in djsReverse.getReason()){
				trace(reason);
			}
		}
		[Test(order=8)]
		public function testAlternateQFalse():void{
			djs.alternateQ(false);
			trace("~~ Printing all reasons in AlternateQFalse");
			for each (var reason:String in djs.getReason()){
				trace(reason);
			}
			djsReverse.alternateQ(false);
			trace("~~ Printing all reasons in Reverse AlternateQFalse");
			for each (reason in djsReverse.getReason()){
				trace(reason);
			}
		}
	}
}

package unittests
{
	public class TestDisjunctiveSyllogism
	{
		import logic.DisjunctiveSyllogism;

		import org.flexunit.Assert;
		private var djs:DisjunctiveSyllogism;
		private var djsReverse:DisjunctiveSyllogism;

		[Before]
		public function setUp():void
		{
			/*
			* reversePos apparently differentiates between Basic Claim and Reason 1.
			* ~~ Printing all reasons in NotPFalse
			* It is not the case that Reason 1
			* Reason 2
			* ~~ Printing all reasons in Reverse NotPFalse
			* It is not the case that Basic Claim
			* Reason 2
			*/
			//DisjunctiveSyllogism(claimText:String, reasonText:Array, reversePos:Boolean,inferenceText:String="", inferencePresent:Boolean=false)
			djsReverse = new DisjunctiveSyllogism("Basic Claim", ["Reason 1", "Reason 2"], true, "Either Foo or Bar, and Baz unless Quux", false);
			djs = new DisjunctiveSyllogism("Basic Claim", ["Reason 1", "Reason 2"], false, "Either Foo or Bar, and Baz unless Quux", false);
		}

		[After]
		public function tearDown():void
		{
		}

		[BeforeClass]
		public static function setUpBeforeClass():void
		{
		}

		[AfterClass]
		public static function tearDownAfterClass():void
		{
		}
		//Copied from the superclass tests
		[Test]
		public function testConstructorClaim():void{
			Assert.assertEquals("Basic Claim", djs.getClaim());
		}
		[Test]
		public function testConstructorReason():void{
			Assert.assertEquals("Reason 1", djs.getReason()[0]);
		}
		//New tests for this subclass's particular functions
		//Not asserting anything because it's currently pointless
		[Test(order=1)]
		public function testNotPTrue():void{
			djs.notP(true);
			trace("~~ Printing all reasons in NotPTrue");
			for each (var reason:String in djs.getReason()){
				trace(reason);
			}
			djsReverse.notP(true);
			trace("~~ Printing all reasons in Reverse NotPTrue");
			for each (reason in djsReverse.getReason()){
				trace(reason);
			}
		}
		[Test(order=2)]
		public function testNotPFalse():void{
			djs.notP(false);
			trace("~~ Printing all reasons in NotPFalse");
			for each (var reason:String in djs.getReason()){
				trace(reason);
			}
			djsReverse.notP(false);
			trace("~~ Printing all reasons in Reverse NotPFalse");
			for each (reason in djsReverse.getReason()){
				trace(reason);
			}
		}
		[Test(order=3)]
		public function testNotQTrue():void{
			djs.notQ(true);
			trace("~~ Printing all reasons in NotQTrue");
			for each (var reason:String in djs.getReason()){
				trace(reason);
			}
			djsReverse.notQ(true);
			trace("~~ Printing all reasons in Reverse NotQTrue");
			for each (reason in djsReverse.getReason()){
				trace(reason);
			}
		}
		[Test(order=4)]
		public function testNotQFalse():void{
			djs.notQ(false);
			trace("~~ Printing all reasons in NotQFalse");
			for each (var reason:String in djs.getReason()){
				trace(reason);
			}
			djsReverse.notQ(false);
			trace("~~ Printing all reasons in Reverse NotQFalse");
			for each (reason in djsReverse.getReason()){
				trace(reason);
			}
		}
		[Test(order=5)]
		public function testAlternatePTrue():void{
			djs.alternateP(true);
			trace("~~ Printing all reasons in AlternatePTrue");
			for each (var reason:String in djs.getReason()){
				trace(reason);
			}
			djsReverse.alternateP(true);
			trace("~~ Printing all reasons in Reverse AlternatePTrue");
			for each (reason in djsReverse.getReason()){
				trace(reason);
			}
		}
		[Test(order=6)]
		public function testAlternatePFalse():void{
			djs.alternateP(false);
			trace("~~ Printing all reasons in AlternatePFalse");
			for each (var reason:String in djs.getReason()){
				trace(reason);
			}
			djsReverse.alternateP(false);
			trace("~~ Printing all reasons in Reverse AlternatePFalse");
			for each (reason in djsReverse.getReason()){
				trace(reason);
			}
		}
		[Test(order=7)]
		public function testAlternateQTrue():void{
			djs.alternateQ(true);
			trace("~~ Printing all reasons in AlternateQTrue");
			for each (var reason:String in djs.getReason()){
				trace(reason);
			}
			djsReverse.alternateQ(true);
			trace("~~ Printing all reasons in Reverse AlternateQTrue");
			for each (reason in djsReverse.getReason()){
				trace(reason);
			}
		}
		[Test(order=8)]
		public function testAlternateQFalse():void{
			djs.alternateQ(false);
			trace("~~ Printing all reasons in AlternateQFalse");
			for each (var reason:String in djs.getReason()){
				trace(reason);
			}
			djsReverse.alternateQ(false);
			trace("~~ Printing all reasons in Reverse AlternateQFalse");
			for each (reason in djsReverse.getReason()){
				trace(reason);
			}
		}
	}
}

Remove needless import.

Remove needless import.


/*
 * Copyright (c) 2009 the original author or authors
 *
 * Permission is hereby granted to use, modify, and distribute this file
 * in accordance with the terms of the license agreement accompanying it.
 */

package org.robotlegs.base
{
	import flash.events.Event;
	import flash.events.IEventDispatcher;
	import flash.utils.Dictionary;
	import flash.utils.describeType;

	import org.robotlegs.core.ICommandMap;
	import org.robotlegs.core.IInjector;
	import org.robotlegs.core.IReflector;

	/**
	 * An abstract ICommandMap implementation
	 */
	public class CommandMap implements ICommandMap
	{
		/**
		 * The IEventDispatcher to listen to
		 */
		protected var eventDispatcher:IEventDispatcher;

		/**
		 * The IInjector to inject with
		 */
		protected var injector:IInjector;

		/**
		 * The IReflector to reflect with
		 */
		protected var reflector:IReflector;

		/**
		 * Internal
		 *
		 * TODO: This needs to be documented
		 */
		protected var eventTypeMap:Dictionary;

		/**
		 * Internal
		 *
		 * Collection of command classes that have been verified to implement an execute method
		 */
		protected var verifiedCommandClasses:Dictionary;

		protected var detainedCommands:Dictionary;

		//---------------------------------------------------------------------
		//  Constructor
		//---------------------------------------------------------------------

		/**
		 * Creates a new CommandMap object
		 *
		 * @param eventDispatcher The IEventDispatcher to listen to
		 * @param injector An IInjector to use for this context
		 * @param reflector An IReflector to use for this context
		 */
		public function CommandMap(eventDispatcher:IEventDispatcher, injector:IInjector, reflector:IReflector)
		{
			this.eventDispatcher = eventDispatcher;
			this.injector = injector;
			this.reflector = reflector;
			this.eventTypeMap = new Dictionary(false);
			this.verifiedCommandClasses = new Dictionary(false);
			this.detainedCommands = new Dictionary(false);
		}

		//---------------------------------------------------------------------
		//  API
		//---------------------------------------------------------------------

		/**
		 * @inheritDoc
		 */
		public function mapEvent(eventType:String, commandClass:Class, eventClass:Class = null, oneshot:Boolean = false):void
		{
			verifyCommandClass(commandClass);
			eventClass = eventClass || Event;

			var eventClassMap:Dictionary = eventTypeMap[eventType] ||= new Dictionary(false);

			var callbacksByCommandClass:Dictionary = eventClassMap[eventClass] ||= new Dictionary(false);

			if (callbacksByCommandClass[commandClass] != null)
			{
				throw new ContextError(ContextError.E_COMMANDMAP_OVR + ' - eventType (' + eventType + ') and Command (' + commandClass + ')');
			}
			var callback:Function = function(event:Event):void
			{
				routeEventToCommand(event, commandClass, oneshot, eventClass);
			};
			eventDispatcher.addEventListener(eventType, callback, false, 0, true);
			callbacksByCommandClass[commandClass] = callback;
		}

		/**
		 * @inheritDoc
		 */
		public function unmapEvent(eventType:String, commandClass:Class, eventClass:Class = null):void
		{
			var eventClassMap:Dictionary = eventTypeMap[eventType];
			if (eventClassMap == null) return;

			var callbacksByCommandClass:Dictionary = eventClassMap[eventClass || Event];
			if (callbacksByCommandClass == null) return;

			var callback:Function = callbacksByCommandClass[commandClass];
			if (callback == null) return;

			eventDispatcher.removeEventListener(eventType, callback, false);
			delete callbacksByCommandClass[commandClass];
		}

		/**
		 * @inheritDoc
		 */
		public function unmapEvents():void
		{
			for (var eventType:String in eventTypeMap)
			{
				var eventClassMap:Dictionary = eventTypeMap[eventType];
				for each (var callbacksByCommandClass:Dictionary in eventClassMap)
				{
					for each ( var callback:Function in callbacksByCommandClass)
					{
						eventDispatcher.removeEventListener(eventType, callback, false);
					}
				}
			}
			eventTypeMap = new Dictionary(false);
		}

		/**
		 * @inheritDoc
		 */
		public function hasEventCommand(eventType:String, commandClass:Class, eventClass:Class = null):Boolean
		{
			var eventClassMap:Dictionary = eventTypeMap[eventType];
			if (eventClassMap == null) return false;

			var callbacksByCommandClass:Dictionary = eventClassMap[eventClass || Event];
			if (callbacksByCommandClass == null) return false;

			return callbacksByCommandClass[commandClass] != null;
		}

		/**
		 * @inheritDoc
		 */
		public function execute(commandClass:Class, payload:Object = null, payloadClass:Class = null, named:String = ''):void
		{
			verifyCommandClass(commandClass);

			if (payload != null || payloadClass != null)
			{
				payloadClass ||= reflector.getClass(payload);

				if (payload is Event && payloadClass != Event)
					injector.mapValue(Event, payload, named);

				injector.mapValue(payloadClass, payload, named);
			}

			var command:Object = injector.instantiate(commandClass);

			if (payload !== null || payloadClass != null)
			{
				if (payload is Event && payloadClass != Event)
					injector.unmap(Event, named);

				injector.unmap(payloadClass, named);
			}

			command.execute();
		}

		/**
		 * @inheritDoc
		 */
		public function detain(command:Object):void
		{
			detainedCommands[command] = true;
		}

		/**
		 * @inheritDoc
		 */
		public function release(command:Object):void
		{
			if (detainedCommands[command])
				delete detainedCommands[command];
		}

		//---------------------------------------------------------------------
		//  Internal
		//---------------------------------------------------------------------

		/**
		 * @throws org.robotlegs.base::ContextError
		 */
		protected function verifyCommandClass(commandClass:Class):void
		{
			if (!verifiedCommandClasses[commandClass])
			{
				verifiedCommandClasses[commandClass] = describeType(commandClass).factory.method.(@name == "execute").length();
				if (!verifiedCommandClasses[commandClass])
					throw new ContextError(ContextError.E_COMMANDMAP_NOIMPL + ' - ' + commandClass);
			}
		}

		/**
		 * Event Handler
		 *
		 * @param event The Event
		 * @param commandClass The Class to construct and execute
		 * @param oneshot Should this command mapping be removed after execution?
         * @return true if the event was routed to a Command and the Command was executed,
         *         false otherwise
		 */
		protected function routeEventToCommand(event:Event, commandClass:Class, oneshot:Boolean, originalEventClass:Class):Boolean
		{
			if (!(event is originalEventClass)) return false;

			execute(commandClass, event);

			if (oneshot) unmapEvent(event.type, commandClass, originalEventClass);

			return true;
		}

	}
}

/*
 * Copyright (c) 2009 the original author or authors
 *
 * Permission is hereby granted to use, modify, and distribute this file
 * in accordance with the terms of the license agreement accompanying it.
 */

package org.robotlegs.base
{
	import flash.events.Event;
	import flash.events.IEventDispatcher;
	import flash.utils.Dictionary;
	import flash.utils.describeType;

	import org.robotlegs.core.ICommandMap;
	import org.robotlegs.core.IInjector;
	import org.robotlegs.core.IReflector;

	/**
	 * An abstract ICommandMap implementation
	 */
	public class CommandMap implements ICommandMap
	{
		/**
		 * The IEventDispatcher to listen to
		 */
		protected var eventDispatcher:IEventDispatcher;

		/**
		 * The IInjector to inject with
		 */
		protected var injector:IInjector;

		/**
		 * The IReflector to reflect with
		 */
		protected var reflector:IReflector;

		/**
		 * Internal
		 *
		 * TODO: This needs to be documented
		 */
		protected var eventTypeMap:Dictionary;

		/**
		 * Internal
		 *
		 * Collection of command classes that have been verified to implement an execute method
		 */
		protected var verifiedCommandClasses:Dictionary;

		protected var detainedCommands:Dictionary;

		//---------------------------------------------------------------------
		//  Constructor
		//---------------------------------------------------------------------

		/**
		 * Creates a new CommandMap object
		 *
		 * @param eventDispatcher The IEventDispatcher to listen to
		 * @param injector An IInjector to use for this context
		 * @param reflector An IReflector to use for this context
		 */
		public function CommandMap(eventDispatcher:IEventDispatcher, injector:IInjector, reflector:IReflector)
		{
			this.eventDispatcher = eventDispatcher;
			this.injector = injector;
			this.reflector = reflector;
			this.eventTypeMap = new Dictionary(false);
			this.verifiedCommandClasses = new Dictionary(false);
			this.detainedCommands = new Dictionary(false);
		}

		//---------------------------------------------------------------------
		//  API
		//---------------------------------------------------------------------

		/**
		 * @inheritDoc
		 */
		public function mapEvent(eventType:String, commandClass:Class, eventClass:Class = null, oneshot:Boolean = false):void
		{
			verifyCommandClass(commandClass);
			eventClass = eventClass || Event;

			var eventClassMap:Dictionary = eventTypeMap[eventType] ||= new Dictionary(false);

			var callbacksByCommandClass:Dictionary = eventClassMap[eventClass] ||= new Dictionary(false);

			if (callbacksByCommandClass[commandClass] != null)
			{
				throw new ContextError(ContextError.E_COMMANDMAP_OVR + ' - eventType (' + eventType + ') and Command (' + commandClass + ')');
			}
			var callback:Function = function(event:Event):void
			{
				routeEventToCommand(event, commandClass, oneshot, eventClass);
			};
			eventDispatcher.addEventListener(eventType, callback, false, 0, true);
			callbacksByCommandClass[commandClass] = callback;
		}

		/**
		 * @inheritDoc
		 */
		public function unmapEvent(eventType:String, commandClass:Class, eventClass:Class = null):void
		{
			var eventClassMap:Dictionary = eventTypeMap[eventType];
			if (eventClassMap == null) return;

			var callbacksByCommandClass:Dictionary = eventClassMap[eventClass || Event];
			if (callbacksByCommandClass == null) return;

			var callback:Function = callbacksByCommandClass[commandClass];
			if (callback == null) return;

			eventDispatcher.removeEventListener(eventType, callback, false);
			delete callbacksByCommandClass[commandClass];
		}

		/**
		 * @inheritDoc
		 */
		public function unmapEvents():void
		{
			for (var eventType:String in eventTypeMap)
			{
				var eventClassMap:Dictionary = eventTypeMap[eventType];
				for each (var callbacksByCommandClass:Dictionary in eventClassMap)
				{
					for each ( var callback:Function in callbacksByCommandClass)
					{
						eventDispatcher.removeEventListener(eventType, callback, false);
					}
				}
			}
			eventTypeMap = new Dictionary(false);
		}

		/**
		 * @inheritDoc
		 */
		public function hasEventCommand(eventType:String, commandClass:Class, eventClass:Class = null):Boolean
		{
			var eventClassMap:Dictionary = eventTypeMap[eventType];
			if (eventClassMap == null) return false;

			var callbacksByCommandClass:Dictionary = eventClassMap[eventClass || Event];
			if (callbacksByCommandClass == null) return false;

			return callbacksByCommandClass[commandClass] != null;
		}

		/**
		 * @inheritDoc
		 */
		public function execute(commandClass:Class, payload:Object = null, payloadClass:Class = null, named:String = ''):void
		{
			verifyCommandClass(commandClass);

			if (payload != null || payloadClass != null)
			{
				payloadClass ||= reflector.getClass(payload);

				if (payload is Event && payloadClass != Event)
					injector.mapValue(Event, payload);

				injector.mapValue(payloadClass, payload, named);
			}

			var command:Object = injector.instantiate(commandClass);

			if (payload !== null || payloadClass != null)
			{
				if (payload is Event && payloadClass != Event)
					injector.unmap(Event);

				injector.unmap(payloadClass, named);
			}

			command.execute();
		}

		/**
		 * @inheritDoc
		 */
		public function detain(command:Object):void
		{
			detainedCommands[command] = true;
		}

		/**
		 * @inheritDoc
		 */
		public function release(command:Object):void
		{
			if (detainedCommands[command])
				delete detainedCommands[command];
		}

		//---------------------------------------------------------------------
		//  Internal
		//---------------------------------------------------------------------

		/**
		 * @throws org.robotlegs.base::ContextError
		 */
		protected function verifyCommandClass(commandClass:Class):void
		{
			if (!verifiedCommandClasses[commandClass])
			{
				verifiedCommandClasses[commandClass] = describeType(commandClass).factory.method.(@name == "execute").length();
				if (!verifiedCommandClasses[commandClass])
					throw new ContextError(ContextError.E_COMMANDMAP_NOIMPL + ' - ' + commandClass);
			}
		}

		/**
		 * Event Handler
		 *
		 * @param event The Event
		 * @param commandClass The Class to construct and execute
		 * @param oneshot Should this command mapping be removed after execution?
         * @return true if the event was routed to a Command and the Command was executed,
         *         false otherwise
		 */
		protected function routeEventToCommand(event:Event, commandClass:Class, oneshot:Boolean, originalEventClass:Class):Boolean
		{
			if (!(event is originalEventClass)) return false;

			execute(commandClass, event);

			if (oneshot) unmapEvent(event.type, commandClass, originalEventClass);

			return true;
		}

	}
}

Fix unnecessarily name injecting during abstract Event "mapValue"


package aerys.minko.scene.visitor.data
{
	import aerys.minko.type.math.Frustum;
	import aerys.minko.type.math.Matrix4x4;
	import aerys.minko.type.math.Vector4;

	public class CameraData implements IWorldData
	{
		public static const POSITION		: String = 'position';
		public static const LOOK_AT			: String = 'lookAt';
		public static const UP				: String = 'up';

		public static const RATIO			: String = 'ratio';
		public static const FOV				: String = 'fov';
		public static const Z_NEAR			: String = 'zNear';

		public static const Z_FAR			: String = 'zFar';
		public static const Z_FAR_PARTS		: String = 'zFarParts';

		public static const VIEW			: String = 'view';
		public static const PROJECTION		: String = 'projection';
		public static const LOCAL_POSITION	: String = 'localPosition';
		public static const LOCAL_LOOK_AT	: String = 'localLookAt';

		public static const DIRECTION		: String = 'direction';
		public static const LOCAL_DIRECTION	: String = 'localDirection';

		public static const FRUSTUM			: String = 'frustum';

		// local data provider
		protected var _styleStack	: StyleStack;
		protected var _localData	: LocalData;

		// data available on initialisation
		protected var _position	: Vector4;
		protected var _lookAt	: Vector4;
		protected var _up		: Vector4;

		protected var _ratio	: Number;
		protected var _fov		: Number;
		protected var _zNear	: Number;
		protected var _zFar		: Number;

		// computed data
		protected var _zFarParts						: Vector4;
		protected var _zFarParts_invalidated			: Boolean;

		protected var _view								: Matrix4x4;
		protected var _view_positionVersion				: uint;
		protected var _view_lookAtVersion				: uint;
		protected var _view_upVersion					: uint;

		protected var _projection						: Matrix4x4;
		protected var _projection_invalidated			: Boolean;

		protected var _localPosition					: Vector4;
		protected var _localPosition_positionVersion	: uint;

		protected var _localLookAt						: Vector4;
		protected var _localLookAt_lookAtVersion		: uint;

		protected var _frustum							: Frustum;
		protected var _frustum_projectionVersion		: uint;

		public function get position() : Vector4
		{
			return _position;
		}

		public function get lookAt() : Vector4
		{
			return _lookAt;
		}

		public function get up() : Vector4
		{
			return _up;
		}

		public function get fieldOfView() : Number
		{
			return _fov;
		}

		public function get zNear() : Number
		{
			return _zNear;
		}

		public function get zFar() : Number
		{
			return _zFar;
		}

		public function get zFarParts() : Vector4
		{
			if (_zFarParts_invalidated)
			{
				_zFarParts = new Vector4(0, 0.25 * _zFar, 0.5 * _zFar, 0.75 * _zFar);
				_zFarParts_invalidated = false;
			}
			return _zFarParts;
		}

		public function get view() : Matrix4x4
		{
			if (_view_positionVersion != _position.version ||
				_view_lookAtVersion != _lookAt.version ||
				_view_upVersion != _up.version)
			{
				_view = Matrix4x4.lookAtLH(_position, _lookAt, _up, _view);

				_view_positionVersion	= _position.version;
				_view_lookAtVersion		= _lookAt.version;
				_view_upVersion			= _lookAt.version;
			}

			return _view;
		}

		public function get projection() : Matrix4x4
		{
			if (_projection_invalidated)
			{
				_projection = Matrix4x4.perspectiveFoVLH(_fov, _ratio, _zNear, _zFar, _projection);
				_projection_invalidated = false;
			}

			return _projection;
		}

		public function get frustrum() : Frustum
		{
			var projectionMatrix : Matrix4x4 = projection;

			if (_frustum_projectionVersion != projectionMatrix.version)
			{
				if (_frustum == null)
					_frustum = new Frustum();
				_frustum.update(projectionMatrix);
				_frustum_projectionVersion = projectionMatrix.version;
			}

			return _frustum;
		}

		public function get localPosition() : Vector4
		{
			if (_localPosition_positionVersion != _position.version)
			{
				_localPosition = _localData.world.multiplyVector(_position, _localPosition);
				_localPosition_positionVersion = _position.version;
			}

			return _localPosition;
		}

		public function get localLookAt() : Vector4
		{
			if (_localLookAt_lookAtVersion != _lookAt.version)
			{
				_localLookAt = _localData.world.deltaMultiplyVector(_lookAt, _localLookAt);
				_localLookAt_lookAtVersion = _lookAt.version;
			}

			return _localLookAt;
		}

		public function get localDirection() : Vector4
		{
			// FIXME: handle cache
			return Vector4.subtract(localPosition, localLookAt).normalize();
		}

		public function get direction() : Vector4
		{
			// FIXME: handle cache
			return Vector4.subtract(position, lookAt).normalize();
		}

		public function set ratio(v : Number) : void
		{
			_ratio = v;
			_projection_invalidated = true;
		}

		public function set position(v : Vector4) : void
		{
			_position = v;
		}

		public function set lookAt(v : Vector4) : void
		{
			_lookAt = v;
		}

		public function set up(v : Vector4) : void
		{
			_up = v;
		}

		public function set fov(v : Number) : void
		{
			_fov = v;
			_projection_invalidated = true;
		}

		public function set zNear(v : Number) : void
		{
			_zNear = v;
			_projection_invalidated = true;
		}

		public function set zFar(v : Number) : void
		{
			_zFar = v;
			_projection_invalidated = true;
		}

		public function CameraData()
		{
			reset()
		}

		public function setLocalDataProvider(styleStack	: StyleStack,
											 localData	: LocalData) : void
		{
			_styleStack	= styleStack;
			_localData	= localData;
		}

		public function invalidate() : void
		{
			// do nothing
		}

		public function reset() : void
		{
			_position	= null;
			_lookAt		= null;
			_up			= null;

			_ratio	= -1;
			_fov	= -1;
			_zNear	= -1;
			_zFar	= -1;

			_view_positionVersion			= uint.MAX_VALUE;
			_view_lookAtVersion				= uint.MAX_VALUE;
			_view_upVersion					= uint.MAX_VALUE;
			_localPosition_positionVersion	= uint.MAX_VALUE;
			_localLookAt_lookAtVersion		= uint.MAX_VALUE;
			_frustum_projectionVersion		= uint.MAX_VALUE;

			_zFarParts_invalidated	= true;
			_projection_invalidated = true;
		}
	}
}

package aerys.minko.scene.visitor.data
{
	import aerys.minko.type.math.Frustum;
	import aerys.minko.type.math.Matrix4x4;
	import aerys.minko.type.math.Vector4;

	public class CameraData implements IWorldData
	{
		public static const POSITION		: String = 'position';
		public static const LOOK_AT			: String = 'lookAt';
		public static const UP				: String = 'up';

		public static const RATIO			: String = 'ratio';
		public static const FOV				: String = 'fov';
		public static const Z_NEAR			: String = 'zNear';

		public static const Z_FAR			: String = 'zFar';
		public static const Z_FAR_PARTS		: String = 'zFarParts';

		public static const VIEW			: String = 'view';
		public static const PROJECTION		: String = 'projection';
		public static const LOCAL_POSITION	: String = 'localPosition';
		public static const LOCAL_LOOK_AT	: String = 'localLookAt';

		public static const DIRECTION		: String = 'direction';
		public static const LOCAL_DIRECTION	: String = 'localDirection';

		public static const FRUSTUM			: String = 'frustum';

		// local data provider
		protected var _styleStack	: StyleStack;
		protected var _localData	: LocalData;

		// data available on initialisation
		protected var _position	: Vector4;
		protected var _lookAt	: Vector4;
		protected var _up		: Vector4;

		protected var _ratio	: Number;
		protected var _fov		: Number;
		protected var _zNear	: Number;
		protected var _zFar		: Number;

		// computed data
		protected var _zFarParts						: Vector4;
		protected var _zFarParts_invalidated			: Boolean;

		protected var _view								: Matrix4x4;
		protected var _view_positionVersion				: uint;
		protected var _view_lookAtVersion				: uint;
		protected var _view_upVersion					: uint;

		protected var _projection						: Matrix4x4;
		protected var _projection_invalidated			: Boolean;

		protected var _localPosition					: Vector4;
		protected var _localPosition_positionVersion	: uint;
		protected var _localPosition_worldVersion		: uint;

		protected var _localLookAt						: Vector4;
		protected var _localLookAt_lookAtVersion		: uint;
		protected var _localLookAt_worldVersion			: uint;

		protected var _frustum							: Frustum;
		protected var _frustum_projectionVersion		: uint;

		public function get position() : Vector4
		{
			return _position;
		}

		public function get lookAt() : Vector4
		{
			return _lookAt;
		}

		public function get up() : Vector4
		{
			return _up;
		}

		public function get fieldOfView() : Number
		{
			return _fov;
		}

		public function get zNear() : Number
		{
			return _zNear;
		}

		public function get zFar() : Number
		{
			return _zFar;
		}

		public function get zFarParts() : Vector4
		{
			if (_zFarParts_invalidated)
			{
				_zFarParts = new Vector4(0, 0.25 * _zFar, 0.5 * _zFar, 0.75 * _zFar);
				_zFarParts_invalidated = false;
			}
			return _zFarParts;
		}

		public function get view() : Matrix4x4
		{
			if (_view_positionVersion != _position.version ||
				_view_lookAtVersion != _lookAt.version ||
				_view_upVersion != _up.version)
			{
				_view = Matrix4x4.lookAtLH(_position, _lookAt, _up, _view);

				_view_positionVersion	= _position.version;
				_view_lookAtVersion		= _lookAt.version;
				_view_upVersion			= _lookAt.version;
			}

			return _view;
		}

		public function get projection() : Matrix4x4
		{
			if (_projection_invalidated)
			{
				_projection = Matrix4x4.perspectiveFoVLH(_fov, _ratio, _zNear, _zFar, _projection);
				_projection_invalidated = false;
			}

			return _projection;
		}

		public function get frustrum() : Frustum
		{
			var projectionMatrix : Matrix4x4 = projection;

			if (_frustum_projectionVersion != projectionMatrix.version)
			{
				if (_frustum == null)
					_frustum = new Frustum();
				_frustum.update(projectionMatrix);
				_frustum_projectionVersion = projectionMatrix.version;
			}

			return _frustum;
		}

		public function get localPosition() : Vector4
		{
			var worldMatrix : Matrix4x4 = _localData.world;

			if (_localPosition_positionVersion != _position.version ||
				_localPosition_worldVersion != worldMatrix.version)
			{
				_localPosition = worldMatrix.multiplyVector(_position, _localPosition);
				_localPosition_positionVersion	= _position.version;
				_localPosition_worldVersion		= worldMatrix.version;
			}

			return _localPosition;
		}

		public function get localLookAt() : Vector4
		{
			var worldMatrix : Matrix4x4 = _localData.world;

			if (_localLookAt_lookAtVersion != _lookAt.version ||
				_localLookAt_worldVersion != worldMatrix.version)
			{
				_localLookAt = worldMatrix.multiplyVector(_lookAt, _localLookAt);
				_localLookAt_lookAtVersion	= _lookAt.version;
				_localLookAt_worldVersion	= worldMatrix.version;
			}

			return _localLookAt;
		}

		public function get localDirection() : Vector4
		{
			// FIXME: handle cache
			return Vector4.subtract(localPosition, localLookAt).normalize();
		}

		public function get direction() : Vector4
		{
			// FIXME: handle cache
			return Vector4.subtract(position, lookAt).normalize();
		}

		public function set ratio(v : Number) : void
		{
			_ratio = v;
			_projection_invalidated = true;
		}

		public function set position(v : Vector4) : void
		{
			_position = v;
		}

		public function set lookAt(v : Vector4) : void
		{
			_lookAt = v;
		}

		public function set up(v : Vector4) : void
		{
			_up = v;
		}

		public function set fov(v : Number) : void
		{
			_fov = v;
			_projection_invalidated = true;
		}

		public function set zNear(v : Number) : void
		{
			_zNear = v;
			_projection_invalidated = true;
		}

		public function set zFar(v : Number) : void
		{
			_zFar = v;
			_projection_invalidated = true;
		}

		public function CameraData()
		{
			reset()
		}

		public function setLocalDataProvider(styleStack	: StyleStack,
											 localData	: LocalData) : void
		{
			_styleStack	= styleStack;
			_localData	= localData;
		}

		public function invalidate() : void
		{
			// do nothing
		}

		public function reset() : void
		{
			_position	= null;
			_lookAt		= null;
			_up			= null;

			_ratio	= -1;
			_fov	= -1;
			_zNear	= -1;
			_zFar	= -1;

			_view_positionVersion			= uint.MAX_VALUE;
			_view_lookAtVersion				= uint.MAX_VALUE;
			_view_upVersion					= uint.MAX_VALUE;
			_localPosition_positionVersion	= uint.MAX_VALUE;
			_localPosition_worldVersion		= uint.MAX_VALUE;
			_localLookAt_lookAtVersion		= uint.MAX_VALUE;
			_localLookAt_worldVersion		= uint.MAX_VALUE;
			_frustum_projectionVersion		= uint.MAX_VALUE;

			_zFarParts_invalidated	= true;
			_projection_invalidated = true;
		}
	}
}

Fix versionning bug in lazy access to local data from the CameraData (cameraLocalPosition and cameraLocalLookAt)


package aerys.minko.type.loader
{
	import aerys.minko.render.resource.texture.TextureResource;
	import aerys.minko.type.Signal;

	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.DisplayObject;
	import flash.display.Loader;
	import flash.display.LoaderInfo;
	import flash.events.Event;
	import flash.events.IOErrorEvent;
	import flash.events.ProgressEvent;
	import flash.net.URLLoader;
	import flash.net.URLLoaderDataFormat;
	import flash.net.URLRequest;
	import flash.system.LoaderContext;
	import flash.utils.ByteArray;
	import flash.utils.getQualifiedClassName;

	public final class TextureLoader implements ILoader
	{
		private var _progress			: Signal;
		private var _error				: Signal;
		private var _complete			: Signal;

		private var _isComplete			: Boolean;

		private var _mipmap				: Boolean;
		private var _textureResource	: TextureResource;

		public function get progress() : Signal
		{
			return _progress;
		}

		public function get error() : Signal
		{
			return _error;
		}

		public function get complete() : Signal
		{
			return _complete;
		}

		public function get isComplete() : Boolean
		{
			return _isComplete;
		}

		public function get textureResource() : TextureResource
		{
			return _textureResource;
		}

		public function TextureLoader(enableMipmapping : Boolean = true)
		{
			_mipmap		= enableMipmapping;

			_textureResource 	= new TextureResource();
			_isComplete 		= false;
			_error				= new Signal();
			_progress			= new Signal();
			_complete			= new Signal();
		}

		public function load(request : URLRequest) : void
		{
			var loader : URLLoader = new URLLoader();

			loader.dataFormat = URLLoaderDataFormat.BINARY;
			loader.addEventListener(ProgressEvent.PROGRESS, onLoadProgressHandler);
			loader.addEventListener(Event.COMPLETE, onLoadCompleteHandler);
			loader.addEventListener(IOErrorEvent.IO_ERROR, onLoadIoErrorEvent);
			loader.load(request);
		}

		private function onLoadIoErrorEvent(e : IOErrorEvent) : void
		{
			_textureResource = null;
			_error.execute(this, e.errorID, e.text);
		}

		private function onLoadProgressHandler(e : ProgressEvent) : void
		{
			_progress.execute(this, e.bytesLoaded, e.bytesTotal);
		}

		private function onLoadCompleteHandler(e : Event) : void
		{
			loadBytes(URLLoader(e.currentTarget).data);
		}

		public function loadClass(classObject : Class) : void
		{
			var assetObject : Object		= new classObject();

			if (assetObject is Bitmap || assetObject is BitmapData)
			{
				var bitmapData : BitmapData = assetObject as BitmapData;
				if (bitmapData == null)
					bitmapData = Bitmap(assetObject).bitmapData;

//				_textureResource = new TextureResource();
				_textureResource.setContentFromBitmapData(bitmapData, _mipmap);
				_complete.execute(this, _textureResource);
				_isComplete = true;
			}
			else if (assetObject is ByteArray)
			{
				loadBytes(ByteArray(assetObject));
			}
			else
			{
				var className : String = getQualifiedClassName(classObject);
				className = className.substr(className.lastIndexOf(':') + 1);

				_isComplete = true;

				throw new Error('No texture can be created from an object of type \'' + className + '\'');
			}
		}

		public function loadBytes(bytes : ByteArray) : void
		{
			bytes.position = 0;

			if (bytes.readByte() == 'A'.charCodeAt(0) &&
				bytes.readByte() == 'T'.charCodeAt(0) &&
				bytes.readByte() == 'F'.charCodeAt(0))
			{
				bytes.position = 0;
//				_textureResource = new TextureResource();
				_textureResource.setContentFromATF(bytes);
				_complete.execute(this, _textureResource);
				_isComplete = true;
			}
			else
			{
				bytes.position = 0;

				var loader : Loader = new Loader();
				loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onLoadBytesComplete);
				loader.loadBytes(bytes);
			}
		}

		private function onLoadBytesComplete(e : Event) : void
		{
			var displayObject : DisplayObject = LoaderInfo(e.currentTarget).content;

			if (displayObject is Bitmap)
			{
				_textureResource.setContentFromBitmapData(Bitmap(displayObject).bitmapData, _mipmap);
				_complete.execute(this, _textureResource);
				_isComplete = true;
			}
			else
			{
				var className : String = getQualifiedClassName(displayObject);

				className = className.substr(className.lastIndexOf(':') + 1);
				_isComplete = true;
				throw new Error('No texture can be created from an object of type \'' + className + '\'');
			}
		}

		public static function loadClass(classObject 		: Class,
										 enableMipMapping 	: Boolean = true) : TextureResource
		{
			var textureLoader : TextureLoader = new TextureLoader(enableMipMapping);

			textureLoader.loadClass(classObject);

			return textureLoader.textureResource;
		}

		public static function load(request				: URLRequest,
									enableMipMapping 	: Boolean = true) : TextureResource
		{
			var textureLoader : TextureLoader = new TextureLoader(enableMipMapping);

			textureLoader.load(request);

			return textureLoader.textureResource;
		}

		public static function loadBytes(bytes				: ByteArray,
										 enableMipMapping 	: Boolean = true) : TextureResource
		{
			var textureLoader : TextureLoader = new TextureLoader(enableMipMapping);

			textureLoader.loadBytes(bytes);

			return textureLoader.textureResource;
		}
	}
}

package aerys.minko.type.loader
{
	import aerys.minko.render.resource.texture.TextureResource;
	import aerys.minko.type.Signal;

	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.DisplayObject;
	import flash.display.Loader;
	import flash.display.LoaderInfo;
	import flash.events.Event;
	import flash.events.IOErrorEvent;
	import flash.events.ProgressEvent;
	import flash.net.URLLoader;
	import flash.net.URLLoaderDataFormat;
	import flash.net.URLRequest;
	import flash.system.LoaderContext;
	import flash.utils.ByteArray;
	import flash.utils.getQualifiedClassName;

	public class TextureLoader implements ILoader
	{
		private var _progress			: Signal;
		private var _error				: Signal;
		private var _complete			: Signal;

		private var _isComplete			: Boolean;

		private var _mipmap				: Boolean;
		private var _textureResource	: TextureResource;

		public function get progress() : Signal
		{
			return _progress;
		}

		public function get error() : Signal
		{
			return _error;
		}

		public function get complete() : Signal
		{
			return _complete;
		}

		public function get isComplete() : Boolean
		{
			return _isComplete;
		}

		public function get textureResource() : TextureResource
		{
			return _textureResource;
		}

		public function TextureLoader(enableMipmapping : Boolean = true)
		{
			_mipmap		= enableMipmapping;

			_textureResource 	= new TextureResource();
			_isComplete 		= false;
			_error				= new Signal();
			_progress			= new Signal();
			_complete			= new Signal();
		}

		public function load(request : URLRequest) : void
		{
			var loader : URLLoader = new URLLoader();

			loader.dataFormat = URLLoaderDataFormat.BINARY;
			loader.addEventListener(ProgressEvent.PROGRESS, onLoadProgressHandler);
			loader.addEventListener(Event.COMPLETE, onLoadCompleteHandler);
			loader.addEventListener(IOErrorEvent.IO_ERROR, onLoadIoErrorEvent);
			loader.load(request);
		}

		private function onLoadIoErrorEvent(e : IOErrorEvent) : void
		{
			_textureResource = null;
			_error.execute(this, e.errorID, e.text);
		}

		private function onLoadProgressHandler(e : ProgressEvent) : void
		{
			_progress.execute(this, e.bytesLoaded, e.bytesTotal);
		}

		private function onLoadCompleteHandler(e : Event) : void
		{
			loadBytes(URLLoader(e.currentTarget).data);
		}

		public function loadClass(classObject : Class) : void
		{
			var assetObject : Object		= new classObject();

			if (assetObject is Bitmap || assetObject is BitmapData)
			{
				var bitmapData : BitmapData = assetObject as BitmapData;
				if (bitmapData == null)
					bitmapData = Bitmap(assetObject).bitmapData;

//				_textureResource = new TextureResource();
				_textureResource.setContentFromBitmapData(bitmapData, _mipmap);
				_complete.execute(this, _textureResource);
				_isComplete = true;
			}
			else if (assetObject is ByteArray)
			{
				loadBytes(ByteArray(assetObject));
			}
			else
			{
				var className : String = getQualifiedClassName(classObject);
				className = className.substr(className.lastIndexOf(':') + 1);

				_isComplete = true;

				throw new Error('No texture can be created from an object of type \'' + className + '\'');
			}
		}

		public function loadBytes(bytes : ByteArray) : void
		{
			bytes.position = 0;

			if (bytes.readByte() == 'A'.charCodeAt(0) &&
				bytes.readByte() == 'T'.charCodeAt(0) &&
				bytes.readByte() == 'F'.charCodeAt(0))
			{
				bytes.position = 0;
//				_textureResource = new TextureResource();
				_textureResource.setContentFromATF(bytes);
				_complete.execute(this, _textureResource);
				_isComplete = true;
			}
			else
			{
				bytes.position = 0;

				var loader : Loader = new Loader();
				loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onLoadBytesComplete);
				loader.loadBytes(bytes);
			}
		}

		private function onLoadBytesComplete(e : Event) : void
		{
			var displayObject : DisplayObject = LoaderInfo(e.currentTarget).content;

			if (displayObject is Bitmap)
			{
				_textureResource.setContentFromBitmapData(Bitmap(displayObject).bitmapData, _mipmap);
				_complete.execute(this, _textureResource);
				_isComplete = true;
			}
			else
			{
				var className : String = getQualifiedClassName(displayObject);

				className = className.substr(className.lastIndexOf(':') + 1);
				_isComplete = true;
				throw new Error('No texture can be created from an object of type \'' + className + '\'');
			}
		}

		public static function loadClass(classObject 		: Class,
										 enableMipMapping 	: Boolean = true) : TextureResource
		{
			var textureLoader : TextureLoader = new TextureLoader(enableMipMapping);

			textureLoader.loadClass(classObject);

			return textureLoader.textureResource;
		}

		public static function load(request				: URLRequest,
									enableMipMapping 	: Boolean = true) : TextureResource
		{
			var textureLoader : TextureLoader = new TextureLoader(enableMipMapping);

			textureLoader.load(request);

			return textureLoader.textureResource;
		}

		public static function loadBytes(bytes				: ByteArray,
										 enableMipMapping 	: Boolean = true) : TextureResource
		{
			var textureLoader : TextureLoader = new TextureLoader(enableMipMapping);

			textureLoader.loadBytes(bytes);

			return textureLoader.textureResource;
		}
	}
}

Make TextureLoader inheritable.

Make TextureLoader inheritable.


package test.request {
  import mx.rpc.events.ResultEvent;

  import flails.request.HTTPClient;
  import flails.request.JSONFilter;
  import flails.request.Record;
  import flails.request.ResourcePathBuilder;

  import net.digitalprimates.fluint.tests.TestCase;

  public class HTTPClientTest extends TestCase {
    private var r:HTTPClient;

    override protected function setUp():void {
      var cleanup:HTTPClient = new HTTPClient(null)
      cleanup.addEventListener("result", asyncHandler(pendUntilComplete, 1000))
      cleanup.doGet("/posts/reset");

      r = new HTTPClient(new ResourcePathBuilder("posts"), new JSONFilter());
    }

    public function testIndex():void {
      r.addEventListener("result", asyncHandler(function (e:ResultEvent, data:Object):void {
            var a:Array = e.result as Array;

            assertEquals(2, a.length);
            assertEquals('testFindAll #1', a[0].subject);
            assertEquals('testFindAll #1 body', a[0].body);
            assertEquals('testFindAll #2', a[1].subject);
            assertEquals('testFindAll #2 body', a[1].body);
          }, 1000));
      r.index();
    }
5
    public function testFindById():void {
      var r:HTTPClient = new HTTPClient(new ResourcePathBuilder("posts"), new JSONFilter());
      r.addEventListener("result", asyncHandler(function (e:ResultEvent, data:Object):void {
            var p:Record = e.result as Record;

            assertEquals('testFindAll #1', p.subject);
            assertEquals('testFindAll #1 body', p.body);
          }, 1500));
      r.show(1);
    }

    public function testUpdate():void {
      var r:HTTPClient = new HTTPClient(new ResourcePathBuilder("posts"), new JSONFilter());
      r.addEventListener("result", asyncHandler(verifyUpdateComplete, 1500));
      r.update(2, {post: {subject: "testFindAll #2 updated", body: "testFindAll #2 body updated"}});
    }

    private function verifyUpdateComplete(e:ResultEvent, data:Object):void {
      var r:HTTPClient = new HTTPClient(new ResourcePathBuilder("posts"), new JSONFilter());

      r.addEventListener("result", asyncHandler(function (e:ResultEvent, data:Object):void {
            var p:Record = e.result as Record;

            assertEquals('testFindAll #2 updated', p.subject);
            assertEquals('testFindAll #2 body updated', p.body);
          }, 1500));
      r.show(2);
    }
  }
}

package test.request {
  import mx.rpc.events.ResultEvent;

  import flails.request.HTTPClient;
  import flails.request.JSONFilter;
  import flails.request.Record;
  import flails.request.ResourcePathBuilder;

  import net.digitalprimates.fluint.tests.TestCase;

  public class HTTPClientTest extends TestCase {
    private var r:HTTPClient;

    override protected function setUp():void {
      var cleanup:HTTPClient = new HTTPClient(null)
      cleanup.addEventListener("result", asyncHandler(pendUntilComplete, 1000))
      cleanup.doGet("/posts/reset");

      r = new HTTPClient(new ResourcePathBuilder("posts"), new JSONFilter());
    }

    public function testIndex():void {
      r.addEventListener("result", asyncHandler(function (e:ResultEvent, data:Object):void {
            var a:Array = e.result as Array;

            assertEquals(2, a.length);
            assertEquals('testFindAll #1', a[0].subject);
            assertEquals('testFindAll #1 body', a[0].body);
            assertEquals('testFindAll #2', a[1].subject);
            assertEquals('testFindAll #2 body', a[1].body);
          }, 1000));
      r.index();
    }
5
    public function testFindById():void {
      var r:HTTPClient = new HTTPClient(new ResourcePathBuilder("posts"), new JSONFilter());
      r.addEventListener("result", asyncHandler(function (e:ResultEvent, data:Object):void {
            var p:Record = e.result as Record;

            assertEquals('testFindAll #1', p.subject);
            assertEquals('testFindAll #1 body', p.body);
          }, 1500));
      r.show(1);
    }

    public function testCreate():void {
      var r:HTTPClient = new HTTPClient(new ResourcePathBuilder("posts"), new JSONFilter());
      r.addEventListener("result", asyncHandler(verifyCreateComplete, 1500));
      r.create({post: {subject: "creating new post", body: "creating new post with body"}});
    }

    private function verifyCreateComplete(e:ResultEvent, data:Object):void {
      var r:HTTPClient = new HTTPClient(new ResourcePathBuilder("posts"), new JSONFilter());

      r.addEventListener("result", asyncHandler(function (e:ResultEvent, data:Object):void {
        var p:Record = e.result as Record;

        assertEquals('testFindAll #2 updated', p.subject);
        assertEquals('testFindAll #2 body updated', p.body);
      }, 1500));
      r.show(2);
    }

    public function testUpdate():void {
      var r:HTTPClient = new HTTPClient(new ResourcePathBuilder("posts"), new JSONFilter());
      r.addEventListener("result", asyncHandler(verifyUpdateComplete, 1500));
      r.update(2, {post: {subject: "testFindAll #2 updated", body: "testFindAll #2 body updated"}});
    }

    private function verifyUpdateComplete(e:ResultEvent, data:Object):void {
      var r:HTTPClient = new HTTPClient(new ResourcePathBuilder("posts"), new JSONFilter());

      r.addEventListener("result", asyncHandler(function (e:ResultEvent, data:Object):void {
            var p:Record = e.result as Record;

            assertEquals('testFindAll #2 updated', p.subject);
            assertEquals('testFindAll #2 body updated', p.body);
          }, 1500));
      r.show(2);
    }
  }
}

create test

create test


//
// Nenya library - tools for developing networked games
// Copyright (C) 2002-2010 Three Rings Design, Inc., All Rights Reserved
// http://www.threerings.net/code/nenya/
//
// This library is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// This library 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
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

package com.threerings.cast {

import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.DisplayObject;

import flash.geom.Point;
import flash.geom.Rectangle;

import flash.events.Event;

import flash.utils.ByteArray;

import nochump.util.zip.ZipEntry;
import nochump.util.zip.ZipError;
import nochump.util.zip.ZipFile;

import com.threerings.media.image.PngRecolorUtil;
import com.threerings.media.tile.TileDataPack;
import com.threerings.media.tile.TileSet;
import com.threerings.util.DataPack;
import com.threerings.util.Log;
import com.threerings.util.Map;
import com.threerings.util.Maps;
import com.threerings.util.MultiLoader;
import com.threerings.util.Set;
import com.threerings.util.StringUtil;

/**
 * Like a normal data pack, but we don't deal with any data, and all our filenames are a direct
 *  translation, so we need no metadata file.  We also serve as a tile ImageProvider.
 */
public class ComponentDataPack extends TileDataPack
    implements FrameProvider
{
    private static var log :Log = Log.getLog(ComponentDataPack);

    public function ComponentDataPack (source :Object, actions :Map,
        completeListener :Function = null, errorListener :Function = null)
    {
        super(source, completeListener, errorListener);
        _actions = actions;
    }

    // Documentation inherited from interface
    public function getFrames (component :CharacterComponent, action :String,
        type :String) :ActionFrames
    {
        // obtain the action sequence definition for this action
        var actseq :ActionSequence = _actions.get(action);
        if (actseq == null) {
            log.warning("Missing action sequence definition [action=" + action +
                        ", component=" + component + "].");
            return null;
        }

        // determine our image path name
        var imgpath :String = action;
        var dimgpath :String = ActionSequence.DEFAULT_SEQUENCE;
        if (type != null) {
            imgpath += "_" + type;
            dimgpath += "_" + type;
        }

        var root :String = component.componentClass.name + "/" + component.name + "/";
        var cpath :String = root + imgpath + ".png";
        var dpath :String = root + dimgpath + ".png";

        // look to see if this tileset is already cached (as the custom action or the default
        // action)
        var aset :TileSet = _setcache.get(cpath);
        if (aset == null) {
            aset = _setcache.get(dpath);
            if (aset != null) {
                // save ourselves a lookup next time
                _setcache.put(cpath, aset);
            }
        }

        try {
            // then try loading up a tileset customized for this action
            if (aset == null) {
                if (_zip.getEntry(cpath)) {
                    aset = TileSet(actseq.tileset.clone());
                    aset.setImagePath(cpath);
                } else if (_zip.getEntry(dpath)) {
                    aset = TileSet(TileSet(_actions.get(ActionSequence.DEFAULT_SEQUENCE)).clone());
                    aset.setImagePath(dpath);
                    _setcache.put(dpath, aset);
                }
            }

            // if that failed too, we're hosed
            if (aset == null) {
                // if this is a shadow or crop image, no need to freak out as they are optional
                if (!StandardActions.CROP_TYPE == type &&
                    !StandardActions.SHADOW_TYPE == type) {
                    log.warning("Unable to locate tileset for action '" + imgpath + "' " +
                                component + ".");
                }
                return null;
            }

            aset.setImageProvider(this);
            _setcache.put(cpath, aset);
            return new TileSetFrameImage(aset, actseq);

        } catch (e :Error) {
            log.warning("Error loading tset for action '" + imgpath + "' " + component + ".", e);
        }

        return null;
    }

    // Documentation inherited from interface
    public function getFramePath (
        component :CharacterComponent, action :String, type :String, existentPaths :Set) :String
    {
        var actionPath :String = makePath(component, action, type);
        if (!existentPaths.contains(actionPath)) {
            return makePath(component, ActionSequence.DEFAULT_SEQUENCE, type);
        }
        return actionPath;
    }

    protected function makePath (component :CharacterComponent, action :String,
        type :String) :String
    {
        var imgpath :String = action;
        if (type != null) {
            imgpath += "_" + type;
        }
        var root :String = component.componentClass.name + "/" + component.name + "/";
        return root + imgpath + ".png";
    }

    protected var _actions :Map;

    protected var _setcache :Map = Maps.newMapOf(String);
}
}

//
// Nenya library - tools for developing networked games
// Copyright (C) 2002-2010 Three Rings Design, Inc., All Rights Reserved
// http://www.threerings.net/code/nenya/
//
// This library is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// This library 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
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

package com.threerings.cast {

import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.DisplayObject;

import flash.geom.Point;
import flash.geom.Rectangle;

import flash.events.Event;

import flash.utils.ByteArray;

import nochump.util.zip.ZipEntry;
import nochump.util.zip.ZipError;
import nochump.util.zip.ZipFile;

import com.threerings.media.image.PngRecolorUtil;
import com.threerings.media.tile.TileDataPack;
import com.threerings.media.tile.TileSet;
import com.threerings.util.DataPack;
import com.threerings.util.Log;
import com.threerings.util.Map;
import com.threerings.util.Maps;
import com.threerings.util.MultiLoader;
import com.threerings.util.Set;
import com.threerings.util.StringUtil;

/**
 * Like a normal data pack, but we don't deal with any data, and all our filenames are a direct
 *  translation, so we need no metadata file.  We also serve as a tile ImageProvider.
 */
public class ComponentDataPack extends TileDataPack
    implements FrameProvider
{
    private static var log :Log = Log.getLog(ComponentDataPack);

    public function ComponentDataPack (source :Object, actions :Map,
        completeListener :Function = null, errorListener :Function = null)
    {
        super(source, completeListener, errorListener);
        _actions = actions;
    }

    // Documentation inherited from interface
    public function getFrames (component :CharacterComponent, action :String,
        type :String) :ActionFrames
    {
        // obtain the action sequence definition for this action
        var actseq :ActionSequence = _actions.get(action);
        if (actseq == null) {
            log.warning("Missing action sequence definition [action=" + action +
                        ", component=" + component + "].");
            return null;
        }

        // determine our image path name
        var imgpath :String = action;
        var dimgpath :String = ActionSequence.DEFAULT_SEQUENCE;
        if (type != null) {
            imgpath += "_" + type;
            dimgpath += "_" + type;
        }

        var root :String = component.componentClass.name + "/" + component.name + "/";
        var cpath :String = root + imgpath + ".png";
        var dpath :String = root + dimgpath + ".png";

        // look to see if this tileset is already cached (as the custom action or the default
        // action)
        var aset :TileSet = _setcache.get(cpath);
        if (aset == null) {
            aset = _setcache.get(dpath);
            if (aset != null) {
                // save ourselves a lookup next time
                _setcache.put(cpath, aset);
            }
        }

        try {
            // then try loading up a tileset customized for this action
            if (aset == null) {
                if (_zip.getEntry(cpath)) {
                    aset = TileSet(actseq.tileset.clone());
                    aset.setImagePath(cpath);
                } else if (_zip.getEntry(dpath)) {
                    actseq = _actions.get(ActionSequence.DEFAULT_SEQUENCE);
                    aset = TileSet(actseq.tileset.clone());
                    aset.setImagePath(dpath);
                    _setcache.put(dpath, aset);
                }
            }

            // if that failed too, we're hosed
            if (aset == null) {
                // if this is a shadow or crop image, no need to freak out as they are optional
                if (!StandardActions.CROP_TYPE == type &&
                    !StandardActions.SHADOW_TYPE == type) {
                    log.warning("Unable to locate tileset for action '" + imgpath + "' " +
                                component + ".");
                }
                return null;
            }

            aset.setImageProvider(this);
            _setcache.put(cpath, aset);
            return new TileSetFrameImage(aset, actseq);

        } catch (e :Error) {
            log.warning("Error loading tset for action '" + imgpath + "' " + component + ".", e);
        }

        return null;
    }

    // Documentation inherited from interface
    public function getFramePath (
        component :CharacterComponent, action :String, type :String, existentPaths :Set) :String
    {
        var actionPath :String = makePath(component, action, type);
        if (!existentPaths.contains(actionPath)) {
            return makePath(component, ActionSequence.DEFAULT_SEQUENCE, type);
        }
        return actionPath;
    }

    protected function makePath (component :CharacterComponent, action :String,
        type :String) :String
    {
        var imgpath :String = action;
        if (type != null) {
            imgpath += "_" + type;
        }
        var root :String = component.componentClass.name + "/" + component.name + "/";
        return root + imgpath + ".png";
    }

    protected var _actions :Map;

    protected var _setcache :Map = Maps.newMapOf(String);
}
}

Fix bug with falling back to default action.

git-svn-id: b675b909355d5cf946977f44a8ec5a6ceb3782e4@996 ed5b42cb-e716-0410-a449-f6a68f950b19


/*
    Weave (Web-based Analysis and Visualization Environment)
    Copyright (C) 2008-2011 University of Massachusetts Lowell

    This file is a part of Weave.

    Weave is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License, Version 3,
    as published by the Free Software Foundation.

    Weave 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 General Public License for more details.

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

package weave.data.KeySets
{
	import mx.utils.ObjectUtil;

	import weave.api.core.ICallbackCollection;
	import weave.api.core.ILinkableObject;
	import weave.api.data.IAttributeColumn;
	import weave.api.data.IKeySet;
	import weave.api.data.IQualifiedKey;
	import weave.api.getCallbackCollection;
	import weave.api.linkableObjectIsBusy;
	import weave.api.newDisposableChild;
	import weave.api.newLinkableChild;
	import weave.api.registerLinkableChild;
	import weave.compiler.StandardLib;
	import weave.core.CallbackCollection;
	import weave.data.QKeyManager;
	import weave.utils.AsyncSort;

	/**
	 * This provides the keys from an existing IKeySet in a sorted order.
	 * Callbacks will trigger when the sorted result changes.
	 *
	 * @author adufilie
	 */
	public class SortedKeySet implements IKeySet
	{
		public static var debug:Boolean = false;

		/**
		 * @param keySet An IKeySet to sort.
		 * @param compare A function that compares two IQualifiedKey objects and returns an integer.
		 * @param dependencies A list of ILinkableObjects that affect the result of the compare function.
		 */
		public function SortedKeySet(keySet:IKeySet, keyCompare:Function = null, dependencies:Array = null)
		{
			_keySet = keySet;
			_compare = keyCompare || QKeyManager.keyCompare;

			getCallbackCollection(_asyncSort).addImmediateCallback(this, _handleSorted);

			for each (var object:ILinkableObject in dependencies)
				registerLinkableChild(_dependencies, object);
			registerLinkableChild(_dependencies, _keySet);
			_dependencies.addImmediateCallback(this, _validate, true);

			if (debug)
				getCallbackCollection(this).addImmediateCallback(this, _firstCallback);
		}

		private function _firstCallback():void { debugTrace(this,'trigger',keys.length,'keys'); }

		/**
		 * This is the list of keys from the IKeySet, sorted.
		 */
		public function get keys():Array
		{
			if (_triggerCounter != _dependencies.triggerCounter)
				_validate();
			return _sortedKeys;
		}

		/**
		 * @inheritDoc
		 */
		public function containsKey(key:IQualifiedKey):Boolean
		{
			return _keySet.containsKey(key);
		}

		private var _triggerCounter:uint = 0;
		private var _dependencies:ICallbackCollection = newDisposableChild(this, CallbackCollection);
		private var _keySet:IKeySet;
		private var _compare:Function;
		private var _asyncSort:AsyncSort = newLinkableChild(this, AsyncSort);
		private var _sortedKeys:Array = [];
		private var _prevSortedKeys:Array = [];

		private function _validate():void
		{
			_triggerCounter = _dependencies.triggerCounter;

			// if actively sorting, don't overwrite previous keys
			if (!linkableObjectIsBusy(_asyncSort))
				_prevSortedKeys = _sortedKeys;

			// begin sorting a copy of the new keys
			_sortedKeys = _keySet.keys.concat();
			_asyncSort.beginSort(_sortedKeys, _compare);
		}

		private function _handleSorted():void
		{
			// only trigger callbacks if sorting changes order
			if (StandardLib.arrayCompare(_prevSortedKeys, _sortedKeys) != 0)
				getCallbackCollection(this).triggerCallbacks();
		}

		/**
		 * This funciton generates a compare function that will compare IQualifiedKeys based on the corresponding values in the specified columns.
		 * @param columns An Array of IAttributeColumns to use for comparing IQualifiedKeys.
		 * @param sortDirections Array of sort directions corresponding to the columns and given as integers (1=ascending, -1=descending, 0=none).
		 * @return A new Function that will compare two IQualifiedKeys using numeric values from the specified columns.
		 */
		public static function generateCompareFunction(columns:Array, sortDirections:Array = null):Function
		{
			return new KeyComparator(columns, sortDirections).compare;
		}
	}
}

import mx.utils.ObjectUtil;

import weave.api.core.ILinkableObject;
import weave.api.data.IAttributeColumn;
import weave.api.data.IQualifiedKey;
import weave.api.getCallbackCollection;
import weave.data.QKeyManager;

internal class KeyComparator
{
	public function KeyComparator(columns:Array, sortDirections:Array)
	{
		this.columns = columns.concat();
		this.n = columns.length;
		if (sortDirections)
		{
			this.sortDirections = sortDirections.concat();
			this.sortDirections.length = columns.length;
		}

		// when any of the columns are disposed, disable the compare function
		for each (var obj:ILinkableObject in columns)
			getCallbackCollection(obj).addDisposeCallback(null, dispose);
	}

	private var columns:Array;
	private var sortDirections:Array;
	private var n:int;

	public function compare(key1:IQualifiedKey, key2:IQualifiedKey):int
	{
		for (var i:int = 0; i < n; i++)
		{
			var column:IAttributeColumn = columns[i] as IAttributeColumn;
			if (!column || (sortDirections && !sortDirections[i]))
				continue;
			var value1:* = column.getValueFromKey(key1, Number);
			var value2:* = column.getValueFromKey(key2, Number);
			var result:int = ObjectUtil.numericCompare(value1, value2);
			if (result != 0)
			{
				if (sortDirections && sortDirections[i] < 0)
					return -result;
				return result;
			}
		}
		return QKeyManager.keyCompare(key1, key2);
	}

	public function dispose():void
	{
		columns = null;
		sortDirections = null;
		n = 0;
	}
}

/*
    Weave (Web-based Analysis and Visualization Environment)
    Copyright (C) 2008-2011 University of Massachusetts Lowell

    This file is a part of Weave.

    Weave is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License, Version 3,
    as published by the Free Software Foundation.

    Weave 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 General Public License for more details.

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

package weave.data.KeySets
{
	import mx.utils.ObjectUtil;

	import weave.api.core.ICallbackCollection;
	import weave.api.core.ILinkableObject;
	import weave.api.data.IAttributeColumn;
	import weave.api.data.IKeySet;
	import weave.api.data.IQualifiedKey;
	import weave.api.getCallbackCollection;
	import weave.api.linkableObjectIsBusy;
	import weave.api.newDisposableChild;
	import weave.api.registerLinkableChild;
	import weave.compiler.StandardLib;
	import weave.core.CallbackCollection;
	import weave.data.QKeyManager;
	import weave.utils.AsyncSort;

	/**
	 * This provides the keys from an existing IKeySet in a sorted order.
	 * Callbacks will trigger when the sorted result changes.
	 *
	 * @author adufilie
	 */
	public class SortedKeySet implements IKeySet
	{
		public static var debug:Boolean = false;

		/**
		 * @param keySet An IKeySet to sort.
		 * @param compare A function that compares two IQualifiedKey objects and returns an integer.
		 * @param dependencies A list of ILinkableObjects that affect the result of the compare function.
		 */
		public function SortedKeySet(keySet:IKeySet, keyCompare:Function = null, dependencies:Array = null)
		{
			_keySet = keySet;
			_compare = keyCompare || QKeyManager.keyCompare;

			getCallbackCollection(_asyncSort).addImmediateCallback(this, _handleSorted);

			for each (var object:ILinkableObject in dependencies)
				registerLinkableChild(_dependencies, object);
			registerLinkableChild(_dependencies, _keySet);
			_dependencies.addImmediateCallback(this, _validate, true);

			if (debug)
				getCallbackCollection(this).addImmediateCallback(this, _firstCallback);
		}

		private function _firstCallback():void { debugTrace(this,'trigger',keys.length,'keys'); }

		/**
		 * This is the list of keys from the IKeySet, sorted.
		 */
		public function get keys():Array
		{
			if (_triggerCounter != _dependencies.triggerCounter)
				_validate();
			return _sortedKeys;
		}

		/**
		 * @inheritDoc
		 */
		public function containsKey(key:IQualifiedKey):Boolean
		{
			return _keySet.containsKey(key);
		}

		private var _triggerCounter:uint = 0;
		private var _dependencies:ICallbackCollection = newDisposableChild(this, CallbackCollection);
		private var _keySet:IKeySet;
		private var _compare:Function;
		// Note: not using newLinkableChild for _asyncSort because we do not trigger if sorting does not affect order
		private var _asyncSort:AsyncSort = newDisposableChild(this, AsyncSort);
		private var _sortedKeys:Array = [];
		private var _prevSortedKeys:Array = [];

		private function _validate():void
		{
			_triggerCounter = _dependencies.triggerCounter;

			// if actively sorting, don't overwrite previous keys
			if (!linkableObjectIsBusy(_asyncSort))
				_prevSortedKeys = _sortedKeys;

			// begin sorting a copy of the new keys
			_sortedKeys = _keySet.keys.concat();
			_asyncSort.beginSort(_sortedKeys, _compare);
		}

		private function _handleSorted():void
		{
			// only trigger callbacks if sorting changes order
			if (StandardLib.arrayCompare(_prevSortedKeys, _sortedKeys) != 0)
				getCallbackCollection(this).triggerCallbacks();
		}

		/**
		 * This funciton generates a compare function that will compare IQualifiedKeys based on the corresponding values in the specified columns.
		 * @param columns An Array of IAttributeColumns to use for comparing IQualifiedKeys.
		 * @param sortDirections Array of sort directions corresponding to the columns and given as integers (1=ascending, -1=descending, 0=none).
		 * @return A new Function that will compare two IQualifiedKeys using numeric values from the specified columns.
		 */
		public static function generateCompareFunction(columns:Array, sortDirections:Array = null):Function
		{
			return new KeyComparator(columns, sortDirections).compare;
		}
	}
}

import mx.utils.ObjectUtil;

import weave.api.core.ILinkableObject;
import weave.api.data.IAttributeColumn;
import weave.api.data.IQualifiedKey;
import weave.api.getCallbackCollection;
import weave.data.QKeyManager;

internal class KeyComparator
{
	public function KeyComparator(columns:Array, sortDirections:Array)
	{
		this.columns = columns.concat();
		this.n = columns.length;
		if (sortDirections)
		{
			this.sortDirections = sortDirections.concat();
			this.sortDirections.length = columns.length;
		}

		// when any of the columns are disposed, disable the compare function
		for each (var obj:ILinkableObject in columns)
			getCallbackCollection(obj).addDisposeCallback(null, dispose);
	}

	private var columns:Array;
	private var sortDirections:Array;
	private var n:int;

	public function compare(key1:IQualifiedKey, key2:IQualifiedKey):int
	{
		for (var i:int = 0; i < n; i++)
		{
			var column:IAttributeColumn = columns[i] as IAttributeColumn;
			if (!column || (sortDirections && !sortDirections[i]))
				continue;
			var value1:* = column.getValueFromKey(key1, Number);
			var value2:* = column.getValueFromKey(key2, Number);
			var result:int = ObjectUtil.numericCompare(value1, value2);
			if (result != 0)
			{
				if (sortDirections && sortDirections[i] < 0)
					return -result;
				return result;
			}
		}
		return QKeyManager.keyCompare(key1, key2);
	}

	public function dispose():void
	{
		columns = null;
		sortDirections = null;
		n = 0;
	}
}

revert accidental change to SortedKeySet


/**
  * LzInputTextSprite.as
  *
  * @copyright Copyright 2001-2009 Laszlo Systems, Inc.  All Rights Reserved.
  *            Use is subject to license terms.
  *
  * @topic Kernel
  * @subtopic swf9
  */

/**
  * @shortdesc Used for input text.
  *
  */
public class LzInputTextSprite extends LzTextSprite {

    #passthrough (toplevel:true) {
        import flash.display.InteractiveObject;
        import flash.events.Event;
        import flash.events.FocusEvent;
        import flash.text.TextField;
        import flash.text.TextFieldType;
    }#

    #passthrough  {

    function LzInputTextSprite (newowner:LzView = null, args:Object = null) {
        super(newowner);
    }

    var enabled :Boolean = true;
    var focusable :Boolean = true;
    var hasFocus :Boolean = false;

    override public function __initTextProperties (args:Object) :void {
        super.__initTextProperties(args);
        // We do not support html in input fields.
        if (this.enabled) {
            textfield.type = TextFieldType.INPUT;
        } else {
            textfield.type = TextFieldType.DYNAMIC;
        }

        /*
          TODO [hqm 2008-01]
          these handlers need to be implemented via Flash native event listenters:

          focusIn , focusOut

          change -- dispatched after text input is modified

          textInput  -- dispatched before the content is modified
                        Do we need to use this for intercepting when we have
                        a pattern restriction on input?

        */

        textfield.addEventListener(Event.CHANGE        , __onChanged);
        //textfield.addEventListener(TextEvent.TEXT_INPUT, __onTextInput);
        textfield.addEventListener(FocusEvent.FOCUS_IN , __gotFocus);
        textfield.addEventListener(FocusEvent.FOCUS_OUT, __lostFocus);

        this.hasFocus = false;
    }

    /**
     * Called from LzInputText#_gotFocusEvent() after focus was set by lz.Focus
     * @access private
     */
    public function gotFocus () :void {
        if ( this.hasFocus ) { return; }
        // assign keyboard control
        LFCApplication.stage.focus = this.textfield;
        this.select();
        this.hasFocus = true;
    }

    /**
     * Called from LzInputText#_gotBlurEvent() after focus was cleared by lz.Focus
     * @access private
     */
    function gotBlur () :void {
        this.hasFocus = false;
        this.deselect();
        if (LFCApplication.stage.focus === this.textfield) {
            // remove keyboard control
            LFCApplication.stage.focus = LFCApplication.stage;
        }
    }

    function select () :void {
        textfield.setSelection(0, textfield.text.length);
    }

    function deselect () :void {
        textfield.setSelection(0, 0);
    }

    /**
     * TODO [hqm 2008-01] I have no idea whether this comment
     * still applies:
     * Register for update on every frame when the text field gets the focus.
     * Set the behavior of the enter key depending on whether the field is
     * multiline or not.
     *
     * @access private
     */
    function __gotFocus (event:FocusEvent) :void {
        // scroll text fields horizontally back to start
        if (owner) owner.inputtextevent('onfocus');
    }

    /**
     * @access private
     * TODO [hqm 2008-01] Does we still need this workaround???
     */
    function __lostFocus (event:FocusEvent) :void {
        // defer execution, see swf8 kernel
        LzTimeKernel.setTimeout(this.__handlelostFocus, 1, event);
    }

    /**
     * TODO [hqm 2008-01] Does this comment still apply? Do we still need this workaround???
     *
     * must be called after an idle event to prevent the selection from being
     * cleared prematurely, e.g. before a button click.  If the selection is
     * cleared, the button doesn't send mouse events.
     * @access private
     */
    function __handlelostFocus (event:Event) :void {
        if (owner) owner.inputtextevent('onblur');
    }

    /**
     * Register to be called when the text field is modified. Convert this
     * into a LFC ontext event.
     * @access private
     */
    function __onChanged (event:Event) :void {
        this.text = this.getText();
        if (owner) owner.inputtextevent('onchange', this.text);
    }

    /**
     * Get the current text for this inputtext-sprite.
     * @protected
     */
    override public function getText() :String {
        // We normalize swf's \r to \n
        return this.textfield.text.replace(/\r/g, '\n');
    }

    /**
     * Sets whether user can modify input text field
     * @param Boolean enabled: true if the text field can be edited
     */
    function setEnabled (enabled:Boolean) :void {
        this.enabled = enabled;
        if (enabled) {
            textfield.type = 'input';
        } else {
            textfield.type = 'dynamic';
        }
    }

    /**
     * If a mouse event occurs in an input text field, find the focused view
     */
    static function findSelection() :LzInputText {
        var f:InteractiveObject = LFCApplication.stage.focus;
        if (f is TextField && f.parent is LzInputTextSprite) {
            return (f.parent as LzInputTextSprite).owner;
        }
        return null;
    }

    }#  // #passthrough

} // End of LzInputTextSprite

/**
  * LzInputTextSprite.as
  *
  * @copyright Copyright 2001-2009 Laszlo Systems, Inc.  All Rights Reserved.
  *            Use is subject to license terms.
  *
  * @topic Kernel
  * @subtopic swf9
  */

/**
  * @shortdesc Used for input text.
  *
  */
public class LzInputTextSprite extends LzTextSprite {

    #passthrough (toplevel:true) {
        import flash.display.InteractiveObject;
        import flash.events.Event;
        import flash.events.FocusEvent;
        import flash.text.TextField;
        import flash.text.TextFieldType;
    }#

    #passthrough  {

    function LzInputTextSprite (newowner:LzView = null, args:Object = null) {
        super(newowner);
    }

    var enabled :Boolean = true;
    var focusable :Boolean = true;
    var hasFocus :Boolean = false;

    override public function __initTextProperties (args:Object) :void {
        super.__initTextProperties(args);
        // We do not support html in input fields.
        this.html = false;

        if (this.enabled) {
            textfield.type = TextFieldType.INPUT;
        } else {
            textfield.type = TextFieldType.DYNAMIC;
        }

        /*
          TODO [hqm 2008-01]
          these handlers need to be implemented via Flash native event listenters:

          focusIn , focusOut

          change -- dispatched after text input is modified

          textInput  -- dispatched before the content is modified
                        Do we need to use this for intercepting when we have
                        a pattern restriction on input?

        */

        textfield.addEventListener(Event.CHANGE        , __onChanged);
        //textfield.addEventListener(TextEvent.TEXT_INPUT, __onTextInput);
        textfield.addEventListener(FocusEvent.FOCUS_IN , __gotFocus);
        textfield.addEventListener(FocusEvent.FOCUS_OUT, __lostFocus);

        this.hasFocus = false;
    }

    /**
     * Called from LzInputText#_gotFocusEvent() after focus was set by lz.Focus
     * @access private
     */
    public function gotFocus () :void {
        if ( this.hasFocus ) { return; }
        // assign keyboard control
        LFCApplication.stage.focus = this.textfield;
        this.select();
        this.hasFocus = true;
    }

    /**
     * Called from LzInputText#_gotBlurEvent() after focus was cleared by lz.Focus
     * @access private
     */
    function gotBlur () :void {
        this.hasFocus = false;
        this.deselect();
        if (LFCApplication.stage.focus === this.textfield) {
            // remove keyboard control
            LFCApplication.stage.focus = LFCApplication.stage;
        }
    }

    function select () :void {
        textfield.setSelection(0, textfield.text.length);
    }

    function deselect () :void {
        textfield.setSelection(0, 0);
    }

    /**
     * TODO [hqm 2008-01] I have no idea whether this comment
     * still applies:
     * Register for update on every frame when the text field gets the focus.
     * Set the behavior of the enter key depending on whether the field is
     * multiline or not.
     *
     * @access private
     */
    function __gotFocus (event:FocusEvent) :void {
        // scroll text fields horizontally back to start
        if (owner) owner.inputtextevent('onfocus');
    }

    /**
     * @access private
     * TODO [hqm 2008-01] Does we still need this workaround???
     */
    function __lostFocus (event:FocusEvent) :void {
        // defer execution, see swf8 kernel
        LzTimeKernel.setTimeout(this.__handlelostFocus, 1, event);
    }

    /**
     * TODO [hqm 2008-01] Does this comment still apply? Do we still need this workaround???
     *
     * must be called after an idle event to prevent the selection from being
     * cleared prematurely, e.g. before a button click.  If the selection is
     * cleared, the button doesn't send mouse events.
     * @access private
     */
    function __handlelostFocus (event:Event) :void {
        if (owner) owner.inputtextevent('onblur');
    }

    /**
     * Register to be called when the text field is modified. Convert this
     * into a LFC ontext event.
     * @access private
     */
    function __onChanged (event:Event) :void {
        this.text = this.getText();
        if (owner) owner.inputtextevent('onchange', this.text);
    }

    /**
     * Get the current text for this inputtext-sprite.
     * @protected
     */
    override public function getText() :String {
        // We normalize swf's \r to \n
        return this.textfield.text.replace(/\r/g, '\n');
    }

    /**
     * Sets whether user can modify input text field
     * @param Boolean enabled: true if the text field can be edited
     */
    function setEnabled (enabled:Boolean) :void {
        this.enabled = enabled;
        if (enabled) {
            textfield.type = 'input';
        } else {
            textfield.type = 'dynamic';
        }
    }

    /**
     * If a mouse event occurs in an input text field, find the focused view
     */
    static function findSelection() :LzInputText {
        var f:InteractiveObject = LFCApplication.stage.focus;
        if (f is TextField && f.parent is LzInputTextSprite) {
            return (f.parent as LzInputTextSprite).owner;
        }
        return null;
    }

    }#  // #passthrough

} // End of LzInputTextSprite

Change 20090406-bargull-ybS by bargull@dell--p4--2-53 on 2009-04-06 00:42:09
    in /home/Admin/src/svn/openlaszlo/trunk
    for http://svn.openlaszlo.org/openlaszlo/trunk

Summary: inputtext shouldn't be in html-mode by default

New Features:

Bugs Fixed: LPP-8026 (SWF9: edittext/inputtext is in html-mode)

Technical Reviewer: max
QA Reviewer: (pending)
Doc Reviewer: (pending)

Documentation:

Release Notes:

Details:
Set html-flag to false for compatibility with swf8 and dhtml.

Tests:
testcase from bugreport

git-svn-id: d62bde4b5aa582fdf07c8d403e53e0399a7ed285@13609 fa20e4f9-1d0a-0410-b5f3-dc9c16b8b17c