package org.denivip.osmf.elements.m3u8Classes
{
	import flash.events.EventDispatcher;

	import org.denivip.osmf.net.HLSDynamicStreamingResource;
	import org.osmf.events.ParseEvent;
	import org.osmf.logging.Log;
	import org.osmf.logging.Logger;
	import org.osmf.media.MediaResourceBase;
	import org.osmf.media.MediaType;
	import org.osmf.media.URLResource;
	import org.osmf.metadata.Metadata;
	import org.osmf.metadata.MetadataNamespaces;
	import org.osmf.net.DynamicStreamingItem;
	import org.osmf.net.DynamicStreamingResource;
	import org.osmf.net.StreamType;
	import org.osmf.net.StreamingItem;
	import org.osmf.net.StreamingURLResource;

	[Event(name="parseComplete", type="org.osmf.events.ParseEvent")]
	[Event(name="parseError", type="org.osmf.events.ParseEvent")]

	/**
	 * You will not belive, but this class parses *.m3u8 playlist
	 */
	public class M3U8PlaylistParser extends EventDispatcher
	{
		public function M3U8PlaylistParser(){
			// nothing todo here...
		}

		public function parse(value:String, baseResource:URLResource):void{

			if(!value || value == ''){
				throw new ArgumentError("Parsed value is missing =(");
			}

			var lines:Array = value.split(/\r?\n/);

			if(lines[0] != '#EXTM3U'){
				;
				CONFIG::LOGGING
				{
					logger.warn('Incorrect header! {0}', lines[0]);
				}
			}

			var result:MediaResourceBase;
			var isLive:Boolean = true;
			var streamItems:Vector.<DynamicStreamingItem>;
			var tempStreamingRes:StreamingURLResource = null;
			var tempDynamicRes:DynamicStreamingResource = null;
			var alternateStreams:Vector.<StreamingItem> = null;
			var initialStreamName:String = '';
			for(var i:int = 1; i < lines.length; i++){
				var line:String = String(lines[i]).replace(/^([\s|\t|\n]+)?(.*)([\s|\t|\n]+)?$/gm, "$2");

				if(line.indexOf("#EXTINF:") == 0){
					result = baseResource;
					tempStreamingRes = result as StreamingURLResource;

					if(tempStreamingRes && tempStreamingRes.streamType == StreamType.LIVE_OR_RECORDED){
						for(var j:int = i+1; j < lines.length; j++){
							if(String(lines[j]).indexOf('#EXT-X-ENDLIST') == 0){
								isLive = false;
								break;
							}
						}
						if(isLive)
							tempStreamingRes.streamType = StreamType.LIVE;
					}
					break;
				}

				if(line.indexOf("#EXT-X-STREAM-INF:") == 0){
					if(!result){
						result = new HLSDynamicStreamingResource(baseResource.url);
						tempDynamicRes = result as DynamicStreamingResource;
						tempStreamingRes = baseResource as StreamingURLResource;
						if(tempStreamingRes){
							tempDynamicRes.streamType = tempStreamingRes.streamType;
							tempDynamicRes.clipStartTime = tempStreamingRes.clipStartTime;
							tempDynamicRes.clipEndTime = tempStreamingRes.clipEndTime;
						}
						streamItems = new Vector.<DynamicStreamingItem>();
					}

					var bw:Number;
					if(line.search(/BANDWIDTH=(\d+)/) > 0)
						bw = parseFloat(line.match(/BANDWIDTH=(\d+)/)[1])/1000;

					var width:int = -1;
					var height:int = -1;
					if(line.search(/RESOLUTION=(\d+)x(\d+)/) > 0){
						width = parseInt(line.match(/RESOLUTION=(\d+)x(\d+)/)[1]);
						height = parseInt(line.match(/RESOLUTION=(\d+)x(\d+)/)[2]);
					}

					var name:String = lines[i+1];
					streamItems.push(new DynamicStreamingItem(name, bw, width, height));
					// store stream name of first stream encountered
					if(initialStreamName == ''){
						initialStreamName = name;
					}
					DynamicStreamingResource(result).streamItems = streamItems;
				}

				if(line.indexOf("#EXT-X-MEDIA:") == 0){
					if(line.search(/TYPE=(.*?)\W/) > 0 && line.match(/TYPE=(.*?)\W/)[1] == 'AUDIO'){
						var stUrl:String;
						var lang:String;
						var stName:String;
						if(line.search(/URI="(.*?)"/) > 0){
							stUrl = line.match(/URI="(.*?)"/)[1];
							if(stUrl.search(/(file|https?):\/\//) != 0){
								stUrl = baseResource.url.substr(0, baseResource.url.lastIndexOf('/')+1) + stUrl;
							}
						}
						if(line.search(/LANGUAGE="(.*?)"/) > 0){
							lang = line.match(/LANGUAGE="(.*?)"/)[1]
						}
						if(line.search(/NAME="(.*?)"/) > 0){
							stName = line.match(/NAME="(.*?)"/)[1];
						}
						if(!alternateStreams)
							alternateStreams = new Vector.<StreamingItem>();

						alternateStreams.push(
							new StreamingItem(MediaType.AUDIO, stUrl, 0, {label:stName, language:lang})
						);
					}
				}
			}

			if(tempDynamicRes && tempDynamicRes.streamItems){
				if(tempDynamicRes.streamItems.length == 1){
					tempStreamingRes = baseResource as StreamingURLResource;
					if(tempStreamingRes){
						// var url:String = (lines[i].search(/(ftp|file|https?):\/\//) == 0) ?  lines[i] : rateItem.url.substr(0, rateItem.url.lastIndexOf('/')+1) + lines[i];
						var url:String = (tempDynamicRes.streamItems[0].streamName.search(/(ftp|file|https?):\/\//) == 0)
							? tempDynamicRes.streamItems[0].streamName
							: tempDynamicRes.host.substr(0, tempDynamicRes.host.lastIndexOf('/')+1) + tempDynamicRes.streamItems[0].streamName;
						result = new StreamingURLResource(
							url,
							tempStreamingRes.streamType,
							tempStreamingRes.clipStartTime,
							tempStreamingRes.clipEndTime,
							tempStreamingRes.connectionArguments,
							tempStreamingRes.urlIncludesFMSApplicationInstance,
							tempStreamingRes.drmContentData
						);
					}
				}else{
					if(baseResource.getMetadataValue(MetadataNamespaces.RESOURCE_INITIAL_INDEX) != null){
						var initialIndex:int = baseResource.getMetadataValue(MetadataNamespaces.RESOURCE_INITIAL_INDEX) as int;
						tempDynamicRes.initialIndex = initialIndex < 0 ? 0 : (initialIndex >= tempDynamicRes.streamItems.length) ? (tempDynamicRes.streamItems.length-1) : initialIndex;
					}else{
						// set initialIndex to index of first stream name encountered
						tempDynamicRes.initialIndex = tempDynamicRes.indexFromName(initialStreamName);
					}
				}
			}

			baseResource.addMetadataValue("HLS_METADATA", new Metadata()); // fix for multistreaming resources
			result.addMetadataValue("HLS_METADATA", new Metadata());

			var httpMetadata:Metadata = new Metadata();
			result.addMetadataValue(MetadataNamespaces.HTTP_STREAMING_METADATA, httpMetadata);

			if(alternateStreams && result is StreamingURLResource){
				(result as StreamingURLResource).alternativeAudioStreamItems = alternateStreams;
			}

			if(result is StreamingURLResource && StreamingURLResource(result).streamType == StreamType.DVR){
				var dvrMetadata:Metadata = new Metadata();
				result.addMetadataValue(MetadataNamespaces.DVR_METADATA, dvrMetadata);
			}

			dispatchEvent(new ParseEvent(ParseEvent.PARSE_COMPLETE, false, false, result));
		}
		/*
		private function addDVRInfo():void{

			CONFIG::LOGGING
			{
				logger.info('DVR!!! \\o/'); // we happy!
			}

			// black magic...
			var dvrInfo:DVRInfo = new DVRInfo();
			dvrInfo.id = dvrInfo.url = '';
			dvrInfo.isRecording = true; // if live then in process
			//dvrInfo.startTime = 0.0;
			// attach info into playlist
		}
		*/
		CONFIG::LOGGING
		{
			private var logger:Logger = Log.getLogger("org.denivip.osmf.elements.m3u8Classes.M3U8PlaylistParser");
		}
	}
}

package org.denivip.osmf.elements.m3u8Classes
{
	import flash.events.EventDispatcher;

	import org.denivip.osmf.net.HLSDynamicStreamingResource;
	import org.denivip.osmf.utility.Url;
	import org.osmf.events.ParseEvent;
	import org.osmf.logging.Log;
	import org.osmf.logging.Logger;
	import org.osmf.media.MediaResourceBase;
	import org.osmf.media.MediaType;
	import org.osmf.media.URLResource;
	import org.osmf.metadata.Metadata;
	import org.osmf.metadata.MetadataNamespaces;
	import org.osmf.net.DynamicStreamingItem;
	import org.osmf.net.DynamicStreamingResource;
	import org.osmf.net.StreamType;
	import org.osmf.net.StreamingItem;
	import org.osmf.net.StreamingURLResource;

	[Event(name="parseComplete", type="org.osmf.events.ParseEvent")]
	[Event(name="parseError", type="org.osmf.events.ParseEvent")]

	/**
	 * You will not belive, but this class parses *.m3u8 playlist
	 */
	public class M3U8PlaylistParser extends EventDispatcher
	{
		public function M3U8PlaylistParser(){
			// nothing todo here...
		}

		public function parse(value:String, baseResource:URLResource):void{

			if(!value || value == ''){
				throw new ArgumentError("Parsed value is missing =(");
			}

			var lines:Array = value.split(/\r?\n/);

			if(lines[0] != '#EXTM3U'){
				;
				CONFIG::LOGGING
				{
					logger.warn('Incorrect header! {0}', lines[0]);
				}
			}

			var result:MediaResourceBase;
			var isLive:Boolean = true;
			var streamItems:Vector.<DynamicStreamingItem>;
			var tempStreamingRes:StreamingURLResource = null;
			var tempDynamicRes:DynamicStreamingResource = null;
			var alternateStreams:Vector.<StreamingItem> = null;
			var initialStreamName:String = '';
			for(var i:int = 1; i < lines.length; i++){
				var line:String = String(lines[i]).replace(/^([\s|\t|\n]+)?(.*)([\s|\t|\n]+)?$/gm, "$2");

				if(line.indexOf("#EXTINF:") == 0){
					result = baseResource;
					tempStreamingRes = result as StreamingURLResource;

					if(tempStreamingRes && tempStreamingRes.streamType == StreamType.LIVE_OR_RECORDED){
						for(var j:int = i+1; j < lines.length; j++){
							if(String(lines[j]).indexOf('#EXT-X-ENDLIST') == 0){
								isLive = false;
								break;
							}
						}
						if(isLive)
							tempStreamingRes.streamType = StreamType.LIVE;
					}
					break;
				}

				if(line.indexOf("#EXT-X-STREAM-INF:") == 0){
					if(!result){
						result = new HLSDynamicStreamingResource(baseResource.url);
						tempDynamicRes = result as DynamicStreamingResource;
						tempStreamingRes = baseResource as StreamingURLResource;
						if(tempStreamingRes){
							tempDynamicRes.streamType = tempStreamingRes.streamType;
							tempDynamicRes.clipStartTime = tempStreamingRes.clipStartTime;
							tempDynamicRes.clipEndTime = tempStreamingRes.clipEndTime;
						}
						streamItems = new Vector.<DynamicStreamingItem>();
					}

					var bw:Number;
					if(line.search(/BANDWIDTH=(\d+)/) > 0)
						bw = parseFloat(line.match(/BANDWIDTH=(\d+)/)[1])/1000;

					var width:int = -1;
					var height:int = -1;
					if(line.search(/RESOLUTION=(\d+)x(\d+)/) > 0){
						width = parseInt(line.match(/RESOLUTION=(\d+)x(\d+)/)[1]);
						height = parseInt(line.match(/RESOLUTION=(\d+)x(\d+)/)[2]);
					}

					var name:String = lines[i+1];
					streamItems.push(new DynamicStreamingItem(name, bw, width, height));
					// store stream name of first stream encountered
					if(initialStreamName == ''){
						initialStreamName = name;
					}
					DynamicStreamingResource(result).streamItems = streamItems;
				}

				if(line.indexOf("#EXT-X-MEDIA:") == 0){
					if(line.search(/TYPE=(.*?)\W/) > 0 && line.match(/TYPE=(.*?)\W/)[1] == 'AUDIO'){
						var stUrl:String;
						var lang:String;
						var stName:String;
						if(line.search(/URI="(.*?)"/) > 0){
							stUrl = line.match(/URI="(.*?)"/)[1];
							if(stUrl.search(/(file|https?):\/\//) != 0){
								stUrl = baseResource.url.substr(0, baseResource.url.lastIndexOf('/')+1) + stUrl;
							}
						}
						if(line.search(/LANGUAGE="(.*?)"/) > 0){
							lang = line.match(/LANGUAGE="(.*?)"/)[1]
						}
						if(line.search(/NAME="(.*?)"/) > 0){
							stName = line.match(/NAME="(.*?)"/)[1];
						}
						if(!alternateStreams)
							alternateStreams = new Vector.<StreamingItem>();

						alternateStreams.push(
							new StreamingItem(MediaType.AUDIO, stUrl, 0, {label:stName, language:lang})
						);
					}
				}
			}

			if(tempDynamicRes && tempDynamicRes.streamItems){
				if(tempDynamicRes.streamItems.length == 1){
					tempStreamingRes = baseResource as StreamingURLResource;
					if(tempStreamingRes){
						// var url:String = (lines[i].search(/(ftp|file|https?):\/\//) == 0) ?  lines[i] : rateItem.url.substr(0, rateItem.url.lastIndexOf('/')+1) + lines[i];
						/*
						var url:String = (tempDynamicRes.streamItems[0].streamName.search(/(ftp|file|https?):\/\//) == 0)
							? tempDynamicRes.streamItems[0].streamName
							: tempDynamicRes.host.substr(0, tempDynamicRes.host.lastIndexOf('/')+1) + tempDynamicRes.streamItems[0].streamName;
						*/
						var url:String = Url.absolute(tempDynamicRes.host, tempDynamicRes.streamItems[0].streamName);
						result = new StreamingURLResource(
							url,
							tempStreamingRes.streamType,
							tempStreamingRes.clipStartTime,
							tempStreamingRes.clipEndTime,
							tempStreamingRes.connectionArguments,
							tempStreamingRes.urlIncludesFMSApplicationInstance,
							tempStreamingRes.drmContentData
						);
					}
				}else{
					if(baseResource.getMetadataValue(MetadataNamespaces.RESOURCE_INITIAL_INDEX) != null){
						var initialIndex:int = baseResource.getMetadataValue(MetadataNamespaces.RESOURCE_INITIAL_INDEX) as int;
						tempDynamicRes.initialIndex = initialIndex < 0 ? 0 : (initialIndex >= tempDynamicRes.streamItems.length) ? (tempDynamicRes.streamItems.length-1) : initialIndex;
					}else{
						// set initialIndex to index of first stream name encountered
						tempDynamicRes.initialIndex = tempDynamicRes.indexFromName(initialStreamName);
					}
				}
			}

			baseResource.addMetadataValue("HLS_METADATA", new Metadata()); // fix for multistreaming resources
			result.addMetadataValue("HLS_METADATA", new Metadata());

			var httpMetadata:Metadata = new Metadata();
			result.addMetadataValue(MetadataNamespaces.HTTP_STREAMING_METADATA, httpMetadata);

			if(alternateStreams && result is StreamingURLResource){
				(result as StreamingURLResource).alternativeAudioStreamItems = alternateStreams;
			}

			if(result is StreamingURLResource && StreamingURLResource(result).streamType == StreamType.DVR){
				var dvrMetadata:Metadata = new Metadata();
				result.addMetadataValue(MetadataNamespaces.DVR_METADATA, dvrMetadata);
			}

			dispatchEvent(new ParseEvent(ParseEvent.PARSE_COMPLETE, false, false, result));
		}
		/*
		private function addDVRInfo():void{

			CONFIG::LOGGING
			{
				logger.info('DVR!!! \\o/'); // we happy!
			}

			// black magic...
			var dvrInfo:DVRInfo = new DVRInfo();
			dvrInfo.id = dvrInfo.url = '';
			dvrInfo.isRecording = true; // if live then in process
			//dvrInfo.startTime = 0.0;
			// attach info into playlist
		}
		*/
		CONFIG::LOGGING
		{
			private var logger:Logger = Log.getLogger("org.denivip.osmf.elements.m3u8Classes.M3U8PlaylistParser");
		}
	}
}

Update M3U8PlaylistParser.as

Update M3U8PlaylistParser.as

Relative to absolute path - moved to org.denivip.osmf.utility.Url


package aerys.minko.type.loader
{
	import flash.events.Event;
	import flash.events.ProgressEvent;
	import flash.net.URLLoader;
	import flash.net.URLLoaderDataFormat;
	import flash.net.URLRequest;
	import flash.utils.ByteArray;
	import flash.utils.setTimeout;

	import aerys.minko.scene.node.ISceneNode;
	import aerys.minko.type.Signal;
	import aerys.minko.type.loader.parser.IParser;
	import aerys.minko.type.loader.parser.ParserOptions;

	public class SceneLoader implements ILoader
	{
		private static const REGISTERED_PARSERS : Vector.<Class> = new <Class>[];

		private static const STATE_IDLE		: uint = 0;
		private static const STATE_LOADING	: uint = 1;
		private static const STATE_PARSING	: uint = 2;
		private static const STATE_COMPLETE	: uint = 3;

		private var _currentState			: int;

		private var _progress				: Signal;
		private var _complete				: Signal;
		private var _error					: Signal;

		private var _data					: ISceneNode;
		private var _parser					: IParser;
		private var _numDependencies		: uint;
		private var _dependencies			: Vector.<ILoader>;
		private var _parserOptions			: ParserOptions;

		private var _currentProgress		: Number;
		private var _currentProgressChanged : Boolean;
		private var _isComplete				: Boolean;

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

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

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

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

		public function get data() : ISceneNode
		{
			return _data;
		}

		public static function registerParser(parserClass : Class) : void
		{
			if (REGISTERED_PARSERS.indexOf(parserClass) != -1)
				return;

			if (!(new parserClass(new ParserOptions()) is IParser))
				throw new Error('Parsers must implement the IParser interface.');

			REGISTERED_PARSERS.push(parserClass);
		}

		public function SceneLoader(parserOptions : ParserOptions = null)
		{
			_currentState	= STATE_IDLE;

			_error			= new Signal('SceneLoader.error');
			_progress		= new Signal('SceneLoader.progress');
			_complete		= new Signal('SceneLoader.complete');
			_data			= null;
			_isComplete		= false;

			_parserOptions	= parserOptions || new ParserOptions();
		}

		public function load(urlRequest : URLRequest) : void
		{
			if (_currentState != STATE_IDLE)
				throw new Error('This controller is already loading an asset.');

			_currentState = STATE_LOADING;

			var urlLoader : URLLoader = new URLLoader();
			urlLoader.dataFormat = URLLoaderDataFormat.BINARY;
			urlLoader.addEventListener(ProgressEvent.PROGRESS, loadProgressHandler);
			urlLoader.addEventListener(Event.COMPLETE, loadCompleteHandler);
			urlLoader.load(urlRequest);
		}

		private function loadProgressHandler(e : ProgressEvent) : void
		{
			_progress.execute(this, 0.5 * e.bytesLoaded / e.bytesTotal);
		}

		private function loadCompleteHandler(e : Event) : void
		{
			_currentState = STATE_IDLE;

			loadBytes(URLLoader(e.currentTarget).data);
		}

		public function loadClass(classObject : Class) : void
		{
			loadBytes(new classObject());
		}

		public function loadBytes(byteArray : ByteArray) : void
		{
			var startPosition : uint = byteArray.position;

			if (_currentState != STATE_IDLE)
				throw new Error('This loader is already loading an asset.');

			_currentState = STATE_PARSING;
			_progress.execute(this, 0.5);

			if (_parserOptions != null && _parserOptions.parser != null)
			{
				_parser = new (_parserOptions.parser)(_parserOptions);

				if (!_parser.isParsable(byteArray))
					throw new Error('Invalid datatype for this parser.');
			}
			else
			{
				// search a parser by testing registered parsers.
				var numRegisteredParser : uint = REGISTERED_PARSERS.length;
				for (var parserId : uint = 0; parserId < numRegisteredParser; ++parserId)
				{
					_parser = new REGISTERED_PARSERS[parserId](_parserOptions);
					byteArray.position = startPosition;
					if (_parser.isParsable(byteArray))
						break;
				}

				if (parserId == numRegisteredParser)
					throw new Error('No parser could be found for this datatype.');
			}

			byteArray.position = startPosition;

			_dependencies	 = _parser.getDependencies(byteArray);
			_numDependencies = 0;

			if (_dependencies != null)
				for each (var dependency : ILoader in _dependencies)
					if (!dependency.isComplete)
					{
						dependency.error.add(decrementDependencyCounter);
						dependency.complete.add(decrementDependencyCounter);

						_numDependencies++;
					}

			if (_numDependencies == 0)
				parse();
		}

		private function decrementDependencyCounter(...args) : void
		{
			--_numDependencies;

			if (_numDependencies == 0)
				parse();
		}

		private function parse() : void
		{
			_parser.error.add(parseErrorHandler);
			_parser.progress.add(parseProgressHandler);
			_parser.complete.add(parseCompleteHandler);
			_parser.parse();
		}

		private function parseErrorHandler(parser : IParser) : void
		{
			_isComplete = true;

            _parser = null;
		}

		private function parseProgressHandler(parser : IParser, progress : Number) : void
		{
			_progress.execute(this, 0.5 * (1 + progress));
		}

		private function parseCompleteHandler(parser : IParser, loadedData : ISceneNode) : void
		{
			_isComplete = true;
			_data = loadedData;

            _parser = null;

			// call later to make sure the loading is always seen as asynchronous
			setTimeout(callLaterComplete, 0, loadedData);
		}

		private function callLaterComplete(loadedData : ISceneNode) : void
		{
			_complete.execute(this, loadedData);
		}
	}
}

package aerys.minko.type.loader
{
	import flash.events.Event;
	import flash.events.IOErrorEvent;
	import flash.events.ProgressEvent;
	import flash.events.SecurityErrorEvent;
	import flash.net.URLLoader;
	import flash.net.URLLoaderDataFormat;
	import flash.net.URLRequest;
	import flash.utils.ByteArray;
	import flash.utils.setTimeout;

	import aerys.minko.scene.node.ISceneNode;
	import aerys.minko.type.Signal;
	import aerys.minko.type.loader.parser.IParser;
	import aerys.minko.type.loader.parser.ParserOptions;

	public class SceneLoader implements ILoader
	{
		private static const REGISTERED_PARSERS : Vector.<Class> = new <Class>[];

		private static const STATE_IDLE		: uint = 0;
		private static const STATE_LOADING	: uint = 1;
		private static const STATE_PARSING	: uint = 2;
		private static const STATE_COMPLETE	: uint = 3;

		private var _currentState			: int;

		private var _progress				: Signal;
		private var _complete				: Signal;
		private var _error					: Signal;

		private var _data					: ISceneNode;
		private var _parser					: IParser;
		private var _numDependencies		: uint;
		private var _dependencies			: Vector.<ILoader>;
		private var _parserOptions			: ParserOptions;

		private var _currentProgress		: Number;
		private var _currentProgressChanged : Boolean;
		private var _isComplete				: Boolean;

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

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

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

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

		public function get data() : ISceneNode
		{
			return _data;
		}

		public static function registerParser(parserClass : Class) : void
		{
			if (REGISTERED_PARSERS.indexOf(parserClass) != -1)
				return;

			if (!(new parserClass(new ParserOptions()) is IParser))
				throw new Error('Parsers must implement the IParser interface.');

			REGISTERED_PARSERS.push(parserClass);
		}

		public function SceneLoader(parserOptions : ParserOptions = null)
		{
			_currentState	= STATE_IDLE;

			_error			= new Signal('SceneLoader.error');
			_progress		= new Signal('SceneLoader.progress');
			_complete		= new Signal('SceneLoader.complete');
			_data			= null;
			_isComplete		= false;

			_parserOptions	= parserOptions || new ParserOptions();
		}

		public function load(urlRequest : URLRequest) : void
		{
			if (_currentState != STATE_IDLE)
				throw new Error('This controller is already loading an asset.');

			_currentState = STATE_LOADING;

			var urlLoader : URLLoader = new URLLoader();
			urlLoader.dataFormat = URLLoaderDataFormat.BINARY;
			urlLoader.addEventListener(ProgressEvent.PROGRESS, loadProgressHandler);
			urlLoader.addEventListener(Event.COMPLETE, loadCompleteHandler);
			urlLoader.addEventListener(IOErrorEvent.IO_ERROR, loadErrorHandler);
			urlLoader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, loadSecurityErrorHandler);

			try
			{
				urlLoader.load(urlRequest);
			}
			catch (e : Error)
			{
				_error.execute(this, e.errorID, e.message);
			}
		}

		private function loadErrorHandler(e : IOErrorEvent) : void
		{
			_error.execute(this, e.errorID, e.text);
		}

		private function loadSecurityErrorHandler(e : SecurityErrorEvent) : void
		{
			_error.execute(this, e.errorID, e.text);
		}

		private function loadProgressHandler(e : ProgressEvent) : void
		{
			_progress.execute(this, 0.5 * e.bytesLoaded / e.bytesTotal);
		}

		private function loadCompleteHandler(e : Event) : void
		{
			_currentState = STATE_IDLE;

			loadBytes(URLLoader(e.currentTarget).data);
		}

		public function loadClass(classObject : Class) : void
		{
			loadBytes(new classObject());
		}

		public function loadBytes(byteArray : ByteArray) : void
		{
			var startPosition : uint = byteArray.position;

			if (_currentState != STATE_IDLE)
				throw new Error('This loader is already loading an asset.');

			_currentState = STATE_PARSING;
			_progress.execute(this, 0.5);

			if (_parserOptions != null && _parserOptions.parser != null)
			{
				_parser = new (_parserOptions.parser)(_parserOptions);

				if (!_parser.isParsable(byteArray))
					throw new Error('Invalid datatype for this parser.');
			}
			else
			{
				// search a parser by testing registered parsers.
				var numRegisteredParser : uint = REGISTERED_PARSERS.length;
				for (var parserId : uint = 0; parserId < numRegisteredParser; ++parserId)
				{
					_parser = new REGISTERED_PARSERS[parserId](_parserOptions);
					byteArray.position = startPosition;
					if (_parser.isParsable(byteArray))
						break;
				}

				if (parserId == numRegisteredParser)
					throw new Error('No parser could be found for this datatype.');
			}

			byteArray.position = startPosition;

			_dependencies	 = _parser.getDependencies(byteArray);
			_numDependencies = 0;

			if (_dependencies != null)
				for each (var dependency : ILoader in _dependencies)
					if (!dependency.isComplete)
					{
						dependency.error.add(decrementDependencyCounter);
						dependency.complete.add(decrementDependencyCounter);

						_numDependencies++;
					}

			if (_numDependencies == 0)
				parse();
		}

		private function decrementDependencyCounter(...args) : void
		{
			--_numDependencies;

			if (_numDependencies == 0)
				parse();
		}

		private function parse() : void
		{
			_parser.error.add(parseErrorHandler);
			_parser.progress.add(parseProgressHandler);
			_parser.complete.add(parseCompleteHandler);
			_parser.parse();
		}

		private function parseErrorHandler(parser : IParser) : void
		{
			_isComplete = true;

            _parser = null;
		}

		private function parseProgressHandler(parser : IParser, progress : Number) : void
		{
			_progress.execute(this, 0.5 * (1 + progress));
		}

		private function parseCompleteHandler(parser : IParser, loadedData : ISceneNode) : void
		{
			_isComplete = true;
			_data = loadedData;

            _parser = null;

			// call later to make sure the loading is always seen as asynchronous
			setTimeout(callLaterComplete, 0, loadedData);
		}

		private function callLaterComplete(loadedData : ISceneNode) : void
		{
			_complete.execute(this, loadedData);
		}
	}
}

Fix error handling in SceneLoader.

Fix error handling in SceneLoader.


# detached brackets
--style=allman

# 4 spaces, no tabs
--indent=spaces=4

# for C++ files only
--indent-classes

# Indent 'switch' blocks so that the 'case X:' statements are indented in the switch block.
# The entire case block is indented.
--indent-switches

# Add extra indentation to namespace blocks. This option has no effect on Java files.
--indent-namespaces

# Converts tabs into spaces in the non-indentation part of the line.
--convert-tabs

# requires --convert-tabs to work properly
--indent-preprocessor

--indent-col1-comments

--min-conditional-indent=2

--max-instatement-indent=40

# Pad empty lines around header blocks (e.g. 'if', 'for', 'while'...).
--break-blocks

# Insert space padding around operators.
--pad-oper

# Insert space padding after paren headers only (e.g. 'if', 'for', 'while'...).
--pad-header

# Add brackets to unbracketed one line conditional statements (e.g. 'if', 'for', 'while'...).
--add-brackets

--align-pointer=name

# Do not retain a backup of the original file. The original file is purged after it is formatted.
--suffix=none

# For each directory in the command line, process all subdirectories recursively.
--recursive

# Preserve the original file's date and time modified.
--preserve-date

# Formatted files display mode. Display only the files that have been formatted.
# Do not display files that are unchanged.
--formatted

--lineend=linux

# detached brackets
--style=allman

# 4 spaces, no tabs
--indent=spaces=4

# for C++ files only
--indent-classes

# Indent 'switch' blocks so that the 'case X:' statements are indented in the switch block.
# The entire case block is indented.
--indent-switches

# Add extra indentation to namespace blocks. This option has no effect on Java files.
--indent-namespaces

# Converts tabs into spaces in the non-indentation part of the line.
--convert-tabs

# requires --convert-tabs to work properly
--indent-preprocessor

--indent-col1-comments

--min-conditional-indent=2

--max-instatement-indent=40

# Insert space padding around operators.
--pad-oper

# Insert space padding after paren headers only (e.g. 'if', 'for', 'while'...).
--pad-header

# Add brackets to unbracketed one line conditional statements (e.g. 'if', 'for', 'while'...).
--add-brackets

--align-pointer=name

# Do not retain a backup of the original file. The original file is purged after it is formatted.
--suffix=none

# For each directory in the command line, process all subdirectories recursively.
--recursive

# Preserve the original file's date and time modified.
--preserve-date

# Formatted files display mode. Display only the files that have been formatted.
# Do not display files that are unchanged.
--formatted

--lineend=linux

Remove --break-blocks option, it doesn't match the existing code style

Strip trailing newlines.


package aerys.minko.scene.visitor.rendering
{
	import aerys.minko.ns.minko;
	import aerys.minko.render.effect.IEffect;
	import aerys.minko.render.effect.IEffectPass;
	import aerys.minko.render.effect.IEffectTarget;
	import aerys.minko.render.renderer.IRenderer;
	import aerys.minko.render.ressource.IRessource;
	import aerys.minko.render.renderer.state.RenderState;
	import aerys.minko.scene.node.*;
	import aerys.minko.scene.node.group.*;
	import aerys.minko.scene.node.mesh.*;
	import aerys.minko.scene.node.texture.*;
	import aerys.minko.scene.visitor.*;
	import aerys.minko.scene.action.IAction;
	import aerys.minko.scene.action.IActionTarget;
	import aerys.minko.scene.visitor.data.*;
	import aerys.minko.type.stream.IndexStream;
	import aerys.minko.type.stream.VertexStreamList;

	import flash.display.ActionScriptVersion;
	import flash.utils.Dictionary;

	public class RenderingVisitor implements ISceneVisitor
	{
		use namespace minko;

		protected var _renderer			: IRenderer;
		protected var _numNodes			: uint;

		protected var _localData		: LocalData;
		protected var _worldData		: Dictionary;
		protected var _renderingData	: RenderingData;

		public function get localData()		: LocalData			{ return _localData; }
		public function get worldData()		: Dictionary		{ return _worldData; }
		public function get renderingData()	: RenderingData		{ return _renderingData; }

		public function get numNodes() : uint
		{
			return _numNodes;
		}

		public function RenderingVisitor(renderer : IRenderer)
		{
			_renderer		= renderer;

			_localData		= new LocalData();
			_worldData		= new Dictionary();
			_renderingData	= new RenderingData();
		}

		public function reset(defaultEffect : IEffect, color : int = 0) : void
		{
			_renderer.clear(((color >> 16) & 0xff) / 255.,
							((color >> 8) & 0xff) / 255.,
							(color & 0xff) / 255.);

			_worldData		= null;
			_numNodes		= 0;

			_renderingData.clear(defaultEffect);
		}

		public function updateWorldData(worldData : Dictionary) : void
		{
			_worldData = worldData;

			for each (var worldObject : IWorldData in worldData)
				worldObject.setLocalDataProvider(_renderingData.styleStack, _localData);

			// update our transformManager if there is a camera, or
			// set it to null to render to screenspace otherwise
			var cameraData : CameraData = worldData[CameraData] as CameraData;

			if (cameraData)
			{
				_localData.view			= cameraData.view;
				_localData.projection	= cameraData.projection;
			}
		}

		public function visit(scene : IScene) : void
		{
			var actions 	: Vector.<IAction> 	= scene.actions;
			var numActions	: int				= actions.length;
			var	i			: int				= 0;

			for (i = 0; i < numActions; ++i)
				if (!actions[i].prefix(scene, this, _renderer))
					break ;

			for (i = 0; i < numActions; ++i)
				if (!actions[i].infix(scene, this, _renderer))
					break ;

			for (i = 0; i < numActions; ++i)
				if (!actions[i].postfix(scene, this, _renderer))
					break ;

			// update statistical data
			++_numNodes;
		}
	}
}

package aerys.minko.scene.visitor.rendering
{
	import aerys.minko.render.effect.IEffect;
	import aerys.minko.render.renderer.IRenderer;
	import aerys.minko.scene.action.IAction;
	import aerys.minko.scene.node.IScene;
	import aerys.minko.scene.visitor.ISceneVisitor;
	import aerys.minko.scene.visitor.data.CameraData;
	import aerys.minko.scene.visitor.data.IWorldData;
	import aerys.minko.scene.visitor.data.LocalData;
	import aerys.minko.scene.visitor.data.RenderingData;

	import flash.utils.Dictionary;

	public class RenderingVisitor implements ISceneVisitor
	{
		protected var _renderer			: IRenderer;
		protected var _numNodes			: uint;

		protected var _localData		: LocalData;
		protected var _worldData		: Dictionary;
		protected var _renderingData	: RenderingData;

		public function get localData()		: LocalData			{ return _localData; }
		public function get worldData()		: Dictionary		{ return _worldData; }
		public function get renderingData()	: RenderingData		{ return _renderingData; }

		public function get numNodes() : uint
		{
			return _numNodes;
		}

		public function RenderingVisitor(renderer : IRenderer)
		{
			_renderer		= renderer;

			_localData		= new LocalData();
			_worldData		= new Dictionary();
			_renderingData	= new RenderingData();
		}

		public function reset(defaultEffect : IEffect, color : int = 0) : void
		{
			_renderer.clear(((color >> 16) & 0xff) / 255.,
							((color >> 8) & 0xff) / 255.,
							(color & 0xff) / 255.);

			_worldData		= null;
			_numNodes		= 0;

			_renderingData.clear(defaultEffect);
		}

		public function updateWorldData(worldData : Dictionary) : void
		{
			_worldData = worldData;

			for each (var worldObject : IWorldData in worldData)
				worldObject.setLocalDataProvider(_renderingData.styleStack, _localData);

			// update our transformManager if there is a camera, or
			// set it to null to render to screenspace otherwise
			var cameraData : CameraData = worldData[CameraData] as CameraData;

			if (cameraData)
			{
				_localData.view			= cameraData.view;
				_localData.projection	= cameraData.projection;
			}
		}

		public function visit(scene : IScene) : void
		{
			var actions 	: Vector.<IAction> 	= scene.actions;
			var numActions	: int				= actions.length;
			var	i			: int				= 0;

			for (i = 0; i < numActions; ++i)
				if (!actions[i].prefix(scene, this, _renderer))
					break ;

			for (i = 0; i < numActions; ++i)
				if (!actions[i].infix(scene, this, _renderer))
					break ;

			for (i = 0; i < numActions; ++i)
				if (!actions[i].postfix(scene, this, _renderer))
					break ;

			// update statistical data
			++_numNodes;
		}
	}
}

Reorganize imports

Reorganize imports


package org.openforis.collect.presenter {
	/**
	 *
	 * @author S. Ricci
	 * */
	import flash.events.Event;
	import flash.events.KeyboardEvent;
	import flash.events.MouseEvent;
	import flash.ui.Keyboard;

	import mx.binding.utils.ChangeWatcher;
	import mx.collections.IList;
	import mx.managers.PopUpManager;
	import mx.rpc.AsyncResponder;
	import mx.rpc.events.ResultEvent;

	import org.openforis.collect.Application;
	import org.openforis.collect.client.ClientFactory;
	import org.openforis.collect.client.DataClient;
	import org.openforis.collect.event.ApplicationEvent;
	import org.openforis.collect.event.UIEvent;
	import org.openforis.collect.i18n.Message;
	import org.openforis.collect.metamodel.proxy.EntityDefinitionProxy;
	import org.openforis.collect.metamodel.proxy.ModelVersionProxy;
	import org.openforis.collect.model.CollectRecord$Step;
	import org.openforis.collect.model.proxy.EntityProxy;
	import org.openforis.collect.model.proxy.RecordProxy;
	import org.openforis.collect.model.proxy.UserProxy;
	import org.openforis.collect.remoting.service.UpdateResponse;
	import org.openforis.collect.ui.UIBuilder;
	import org.openforis.collect.ui.component.ErrorListPopUp;
	import org.openforis.collect.ui.component.detail.FormContainer;
	import org.openforis.collect.ui.view.DetailView;
	import org.openforis.collect.util.AlertUtil;
	import org.openforis.collect.util.PopUpUtil;
	import org.openforis.collect.util.StringUtil;

	public class DetailPresenter extends AbstractPresenter {

		private var _dataClient:DataClient;
		private var _view:DetailView;
		private var _errorsListPopUp:ErrorListPopUp;
		private var _rootEntityKeyTextChangeWatcher:ChangeWatcher;

		public function DetailPresenter(view:DetailView) {
			this._view = view;
			this._dataClient = ClientFactory.dataClient;
			super();
		}

		override internal function initEventListeners():void {
			_view.backToListButton.addEventListener(MouseEvent.CLICK, backToListButtonClickHandler);
			_view.saveButton.addEventListener(MouseEvent.CLICK, saveButtonClickHandler);
			_view.autoSaveCheckBox.addEventListener(MouseEvent.CLICK, autoSaveCheckBoxClickHandler);
			_view.submitButton.addEventListener(MouseEvent.CLICK, submitButtonClickHandler);
			_view.rejectButton.addEventListener(MouseEvent.CLICK, rejectButtonClickHandler);
			eventDispatcher.addEventListener(ApplicationEvent.UPDATE_RESPONSE_RECEIVED, updateResponseReceivedHandler);
			eventDispatcher.addEventListener(ApplicationEvent.RECORD_SAVED, recordSavedHandler);
			eventDispatcher.addEventListener(UIEvent.ACTIVE_RECORD_CHANGED, activeRecordChangedListener);

			_view.stage.addEventListener(KeyboardEvent.KEY_DOWN, stageKeyDownHandler);
		}

		/**
		 * Active record changed
		 * */
		internal function activeRecordChangedListener(event:UIEvent):void {
			var preview:Boolean = Application.preview;
			var activeRecord:RecordProxy = Application.activeRecord;
			var version:ModelVersionProxy = activeRecord.version;
			var rootEntity:EntityProxy = activeRecord.rootEntity;
			rootEntity.updateKeyText();
			updateRecordKeyLabel();
			if ( _rootEntityKeyTextChangeWatcher == null ) {
				_rootEntityKeyTextChangeWatcher = ChangeWatcher.watch(rootEntity, "keyText", updateRecordKeyLabel);
			} else {
				_rootEntityKeyTextChangeWatcher.reset(rootEntity);
			}
			_view.formVersionContainer.visible = version != null;
			if ( version != null ) {
				_view.formVersionText.text = version.getLabelText();
			}
			var step:CollectRecord$Step = activeRecord.step;
			_view.currentPhaseText.text = getStepLabel(step);

			var user:UserProxy = Application.user;
			var canSubmit:Boolean = !preview && user.canSubmit(activeRecord);
			var canReject:Boolean = !preview && user.canReject(activeRecord);
			var canSave:Boolean = !preview && Application.activeRecordEditable;

			_view.header.visible = _view.header.includeInLayout = !preview;
			_view.submitButton.visible = _view.submitButton.includeInLayout = canSubmit;
			_view.rejectButton.visible = _view.rejectButton.includeInLayout = canReject;
			if ( canReject ) {
				_view.rejectButton.label = step == CollectRecord$Step.ANALYSIS ? Message.get("edit.unlock"): Message.get("edit.reject");
			}
			_view.saveButton.visible = canSave;
			_view.updateStatusLabel.text = null;
			_view.autoSaveCheckBox.visible = canSave;
			_view.updateStatusLabel.visible = canSave;

			var rootEntityDefn:EntityDefinitionProxy = Application.activeRootEntity;
			var form:FormContainer = null;
			if (_view.formsContainer.contatinsForm(version,rootEntityDefn)){
				_view.currentState = DetailView.EDIT_STATE;
				form = _view.formsContainer.getForm(version, rootEntityDefn);
			} else {
				//build form
				_view.currentState = DetailView.LOADING_STATE;
				form = UIBuilder.buildForm(rootEntityDefn, version);
				_view.formsContainer.addForm(form, version, rootEntityDefn);
				_view.currentState = DetailView.EDIT_STATE;
			}
			form = _view.formsContainer.setActiveForm(version, rootEntityDefn);
			form.record = activeRecord;
		}

		protected function recordSavedHandler(event:ApplicationEvent):void {
			var rootEntityLabel:String = Application.activeRootEntity.getInstanceOrHeadingLabelText();
			_view.messageDisplay.show(Message.get("edit.recordSaved", [rootEntityLabel]));
		}

		protected function autoSaveCheckBoxClickHandler(event:MouseEvent):void {
			Application.autoSave = _view.autoSaveCheckBox.selected;
		}

		protected function updateRecordKeyLabel(event:Event = null):void {
			var result:String;
			var rootEntityLabel:String = Application.activeRootEntity.getInstanceOrHeadingLabelText();
			var keyText:String = Application.activeRecord.rootEntity.keyText;
			if(StringUtil.isBlank(keyText) && isNaN(Application.activeRecord.id)) {
				result = Message.get('edit.newRecordKeyLabel', [rootEntityLabel]);
			} else {
				result = StringUtil.concat("  ", rootEntityLabel, keyText);
			}
			_view.recordKeyLabel.text = result;
		}

		/**
		 * Back to list
		 * */
		protected function backToListButtonClickHandler(event:Event):void {
			if(Application.activeRecord.updated) {
				AlertUtil.showConfirm("edit.confirmBackToList", null, null, performClearActiveRecord);
			} else {
				performClearActiveRecord();
			}
		}

		protected function performClearActiveRecord():void {
			//reset immediately activeRecord to avoid concurrency problems
			//when keepAlive message is sent and record is being unlocked
			ClientFactory.sessionClient.cancelLastKeepAliveOperation();
			Application.activeRecord = null;
			_dataClient.clearActiveRecord(new AsyncResponder(clearActiveRecordHandler, faultHandler));
		}

		protected function saveButtonClickHandler(event:MouseEvent):void {
			performSaveActiveRecord();
		}

		protected function performSaveActiveRecord():void {
			_dataClient.saveActiveRecord(saveActiveRecordResultHandler, faultHandler, Application.autoSave);
		}

		protected function submitButtonClickHandler(event:MouseEvent):void {
			var r:RecordProxy = Application.activeRecord;
			r.showErrors();
			var applicationEvent:ApplicationEvent = new ApplicationEvent(ApplicationEvent.ASK_FOR_SUBMIT);
			eventDispatcher.dispatchEvent(applicationEvent);
			var totalErrors:int = r.errors + r.missingErrors + r.skipped;
			if ( totalErrors > 0 ) {
				openErrorsListPopUp();
			} else {
				var messageResource:String;
				if(r.step == CollectRecord$Step.ENTRY) {
					messageResource = "edit.confirmSubmitDataCleansing";
					AlertUtil.showConfirm(messageResource, null, null, performSubmitToClenasing);
				} else if(r.step == CollectRecord$Step.CLEANSING) {
					messageResource = "edit.confirmSubmitDataAnalysis";
					AlertUtil.showConfirm(messageResource, null, null, performSubmitToAnalysis);
				}
			}
		}

		protected function openErrorsListPopUp():void {
			if ( _errorsListPopUp != null ) {
				PopUpManager.removePopUp(_errorsListPopUp);
				_errorsListPopUp = null;
			}
			_errorsListPopUp = ErrorListPopUp(PopUpUtil.createPopUp(ErrorListPopUp, false));
		}

		protected function rejectButtonClickHandler(event:MouseEvent):void {
			var messageResource:String;
			var r:RecordProxy = Application.activeRecord;
			if(r.step == CollectRecord$Step.CLEANSING) {
				messageResource = "edit.confirmRejectDataCleansing";
				AlertUtil.showConfirm(messageResource, null, null, performRejectToEntry);
			} else if(r.step == CollectRecord$Step.ANALYSIS) {
				messageResource = "edit.confirmRejectDataAnalysis";
				AlertUtil.showConfirm(messageResource, null, null, performRejectToCleansing);
			}
		}

		protected function performSubmitToClenasing():void {
			var responder:AsyncResponder = new AsyncResponder(promoteRecordResultHandler, faultHandler);
			_dataClient.promoteToCleansing(responder);
		}

		protected function performSubmitToAnalysis():void {
			var responder:AsyncResponder = new AsyncResponder(promoteRecordResultHandler, faultHandler);
			_dataClient.promoteToAnalysis(responder);
		}

		protected function performRejectToCleansing():void {
			var responder:AsyncResponder = new AsyncResponder(rejectRecordResultHandler, faultHandler);
			_dataClient.demoteToCleansing(responder);
		}

		protected function performRejectToEntry():void {
			var responder:AsyncResponder = new AsyncResponder(rejectRecordResultHandler, faultHandler);
			_dataClient.demoteToEntry(responder);
		}

		internal function clearActiveRecordHandler(event:ResultEvent, token:Object = null):void {
			var uiEvent:UIEvent = new UIEvent(UIEvent.BACK_TO_LIST);
			eventDispatcher.dispatchEvent(uiEvent);
		}

		internal function saveActiveRecordResultHandler(event:ResultEvent, token:Object = null):void {
			Application.activeRecord.showErrors();
			Application.activeRecord.updated = false;
			var applicationEvent:ApplicationEvent = new ApplicationEvent(ApplicationEvent.RECORD_SAVED);
			eventDispatcher.dispatchEvent(applicationEvent);
		}

		internal function promoteRecordResultHandler(event:ResultEvent, token:Object = null):void {
			var rootEntity:EntityDefinitionProxy = Application.activeRootEntity;
			var rootEntityLabel:String = rootEntity.getInstanceOrHeadingLabelText();
			var r:RecordProxy = Application.activeRecord;
			var keyLabel:String = r.rootEntity.keyText;
			var actualStep:CollectRecord$Step = getNextStep(r.step);
			var stepLabel:String = getStepLabel(actualStep).toLowerCase();
			AlertUtil.showMessage("edit.recordSubmitted", [rootEntityLabel, keyLabel, stepLabel], "edit.recordSubmittedTitle", [rootEntityLabel]);
			Application.activeRecord = null;
			var uiEvent:UIEvent = new UIEvent(UIEvent.BACK_TO_LIST);
			eventDispatcher.dispatchEvent(uiEvent);
		}

		internal function rejectRecordResultHandler(event:ResultEvent, token:Object = null):void {
			var rootEntity:EntityDefinitionProxy = Application.activeRootEntity;
			var rootEntityLabel:String = rootEntity.getInstanceOrHeadingLabelText();
			var r:RecordProxy = Application.activeRecord;
			var keyLabel:String = r.rootEntity.keyText;
			var actualStep:CollectRecord$Step = getPreviousStep(r.step);
			var stepLabel:String = getStepLabel(actualStep).toLowerCase();
			AlertUtil.showMessage("edit.recordRejected", [rootEntityLabel, keyLabel, stepLabel], "edit.recordRejectedTitle", [rootEntityLabel]);
			Application.activeRecord = null;
			var uiEvent:UIEvent = new UIEvent(UIEvent.BACK_TO_LIST);
			eventDispatcher.dispatchEvent(uiEvent);
		}

		protected function updateResponseReceivedHandler(event:ApplicationEvent):void {
			var updateMessageKey:String;
			if ( Application.activeRecord.updated ) {
				updateMessageKey = "edit.changes_not_saved";
			} else {
				updateMessageKey = "edit.all_changes_saved";
			}
			_view.updateStatusLabel.text = Message.get(updateMessageKey);
		}

		protected function stageKeyDownHandler(event:KeyboardEvent):void {
			//save record pressing CTRL + s
			if ( !Application.preview && Application.activeRecordEditable &&
					event.ctrlKey && event.keyCode == Keyboard.S ) {
				performSaveActiveRecord();
			}
		}

		public static function getNextStep(step:CollectRecord$Step):CollectRecord$Step {
			switch ( step ) {
				case CollectRecord$Step.ENTRY:
					return CollectRecord$Step.CLEANSING;
				case CollectRecord$Step.CLEANSING:
					return CollectRecord$Step.ANALYSIS;
				default:
					return null;
			}
		}

		public static function getPreviousStep(step:CollectRecord$Step):CollectRecord$Step {
			switch ( step ) {
				case CollectRecord$Step.CLEANSING:
					return CollectRecord$Step.ENTRY;
				case CollectRecord$Step.ANALYSIS:
					return CollectRecord$Step.CLEANSING;
				default:
					return null;

			}
		}

		public static function getStepLabel(step:CollectRecord$Step):String {
			switch ( step ) {
				case CollectRecord$Step.ENTRY:
					return Message.get("edit.dataEntry");
				case CollectRecord$Step.CLEANSING:
					return Message.get("edit.dataCleansing");
				case CollectRecord$Step.ANALYSIS:
					return Message.get("edit.dataAnalysis");
				default:
					return null;
			}
		}
	}
}

package org.openforis.collect.presenter {
	/**
	 *
	 * @author S. Ricci
	 * */
	import flash.events.Event;
	import flash.events.KeyboardEvent;
	import flash.events.MouseEvent;
	import flash.ui.Keyboard;

	import mx.binding.utils.ChangeWatcher;
	import mx.collections.IList;
	import mx.managers.PopUpManager;
	import mx.rpc.AsyncResponder;
	import mx.rpc.events.ResultEvent;

	import org.openforis.collect.Application;
	import org.openforis.collect.client.ClientFactory;
	import org.openforis.collect.client.DataClient;
	import org.openforis.collect.event.ApplicationEvent;
	import org.openforis.collect.event.UIEvent;
	import org.openforis.collect.i18n.Message;
	import org.openforis.collect.metamodel.proxy.EntityDefinitionProxy;
	import org.openforis.collect.metamodel.proxy.ModelVersionProxy;
	import org.openforis.collect.model.CollectRecord$Step;
	import org.openforis.collect.model.proxy.EntityProxy;
	import org.openforis.collect.model.proxy.RecordProxy;
	import org.openforis.collect.model.proxy.UserProxy;
	import org.openforis.collect.remoting.service.UpdateResponse;
	import org.openforis.collect.ui.UIBuilder;
	import org.openforis.collect.ui.component.ErrorListPopUp;
	import org.openforis.collect.ui.component.detail.FormContainer;
	import org.openforis.collect.ui.view.DetailView;
	import org.openforis.collect.util.AlertUtil;
	import org.openforis.collect.util.PopUpUtil;
	import org.openforis.collect.util.StringUtil;

	public class DetailPresenter extends AbstractPresenter {

		private var _dataClient:DataClient;
		private var _view:DetailView;
		private var _errorsListPopUp:ErrorListPopUp;
		private var _rootEntityKeyTextChangeWatcher:ChangeWatcher;

		public function DetailPresenter(view:DetailView) {
			this._view = view;
			this._dataClient = ClientFactory.dataClient;
			super();
		}

		override internal function initEventListeners():void {
			_view.backToListButton.addEventListener(MouseEvent.CLICK, backToListButtonClickHandler);
			_view.saveButton.addEventListener(MouseEvent.CLICK, saveButtonClickHandler);
			_view.autoSaveCheckBox.addEventListener(MouseEvent.CLICK, autoSaveCheckBoxClickHandler);
			_view.submitButton.addEventListener(MouseEvent.CLICK, submitButtonClickHandler);
			_view.rejectButton.addEventListener(MouseEvent.CLICK, rejectButtonClickHandler);
			eventDispatcher.addEventListener(ApplicationEvent.UPDATE_RESPONSE_RECEIVED, updateResponseReceivedHandler);
			eventDispatcher.addEventListener(ApplicationEvent.RECORD_SAVED, recordSavedHandler);
			eventDispatcher.addEventListener(UIEvent.ACTIVE_RECORD_CHANGED, activeRecordChangedListener);

			_view.stage.addEventListener(KeyboardEvent.KEY_DOWN, stageKeyDownHandler);
		}

		/**
		 * Active record changed
		 * */
		internal function activeRecordChangedListener(event:UIEvent):void {
			var preview:Boolean = Application.preview;
			var activeRecord:RecordProxy = Application.activeRecord;
			var version:ModelVersionProxy = activeRecord.version;
			var rootEntity:EntityProxy = activeRecord.rootEntity;
			rootEntity.updateKeyText();
			updateRecordKeyLabel();
			if ( _rootEntityKeyTextChangeWatcher == null ) {
				_rootEntityKeyTextChangeWatcher = ChangeWatcher.watch(rootEntity, "keyText", updateRecordKeyLabel);
			} else {
				_rootEntityKeyTextChangeWatcher.reset(rootEntity);
			}
			_view.formVersionContainer.visible = version != null;
			if ( version != null ) {
				_view.formVersionText.text = version.getLabelText();
			}
			var step:CollectRecord$Step = activeRecord.step;
			_view.currentPhaseText.text = getStepLabel(step);

			var user:UserProxy = Application.user;
			var canSubmit:Boolean = !preview && user.canSubmit(activeRecord);
			var canReject:Boolean = !preview && user.canReject(activeRecord);
			var canSave:Boolean = !preview && Application.activeRecordEditable;

			_view.header.visible = _view.header.includeInLayout = !preview;
			_view.submitButton.visible = _view.submitButton.includeInLayout = canSubmit;
			_view.rejectButton.visible = _view.rejectButton.includeInLayout = canReject;
			if ( canReject ) {
				_view.rejectButton.label = step == CollectRecord$Step.ANALYSIS ? Message.get("edit.unlock"): Message.get("edit.reject");
			}
			_view.saveButton.visible = canSave;
			_view.updateStatusLabel.text = null;
			_view.autoSaveCheckBox.visible = canSave;
			_view.updateStatusLabel.visible = canSave;

			var rootEntityDefn:EntityDefinitionProxy = Application.activeRootEntity;
			var form:FormContainer = null;
			if (_view.formsContainer.contatinsForm(version,rootEntityDefn)){
				_view.currentState = DetailView.EDIT_STATE;
				form = _view.formsContainer.getForm(version, rootEntityDefn);
			} else {
				//build form
				_view.currentState = DetailView.LOADING_STATE;
				form = UIBuilder.buildForm(rootEntityDefn, version);
				_view.formsContainer.addForm(form, version, rootEntityDefn);
				_view.currentState = DetailView.EDIT_STATE;
			}
			form = _view.formsContainer.setActiveForm(version, rootEntityDefn);
			form.record = activeRecord;
		}

		protected function recordSavedHandler(event:ApplicationEvent):void {
			var rootEntityLabel:String = Application.activeRootEntity.getInstanceOrHeadingLabelText();
			_view.messageDisplay.show(Message.get("edit.recordSaved", [rootEntityLabel]));
		}

		protected function autoSaveCheckBoxClickHandler(event:MouseEvent):void {
			Application.autoSave = _view.autoSaveCheckBox.selected;
		}

		protected function updateRecordKeyLabel(event:Event = null):void {
			var result:String;
			var rootEntityLabel:String = Application.activeRootEntity.getInstanceOrHeadingLabelText();
			var keyText:String = Application.activeRecord.rootEntity.keyText;
			if(StringUtil.isBlank(keyText) && isNaN(Application.activeRecord.id)) {
				result = Message.get('edit.newRecordKeyLabel', [rootEntityLabel]);
			} else {
				result = StringUtil.concat("  ", rootEntityLabel, keyText);
			}
			_view.recordKeyLabel.text = result;
		}

		/**
		 * Back to list
		 * */
		protected function backToListButtonClickHandler(event:Event):void {
			if(Application.activeRecord.updated) {
				AlertUtil.showConfirm("edit.confirmBackToList", null, null, performClearActiveRecord);
			} else {
				performClearActiveRecord();
			}
		}

		protected function performClearActiveRecord():void {
			//reset immediately activeRecord to avoid concurrency problems
			//when keepAlive message is sent and record is being unlocked
			ClientFactory.sessionClient.cancelLastKeepAliveOperation();
			Application.activeRecord = null;
			_dataClient.clearActiveRecord(new AsyncResponder(clearActiveRecordHandler, faultHandler));
		}

		protected function saveButtonClickHandler(event:MouseEvent):void {
			performSaveActiveRecord();
		}

		protected function performSaveActiveRecord():void {
			_dataClient.saveActiveRecord(saveActiveRecordResultHandler, faultHandler, Application.autoSave);
		}

		protected function submitButtonClickHandler(event:MouseEvent):void {
			var r:RecordProxy = Application.activeRecord;
			r.showErrors();
			var applicationEvent:ApplicationEvent = new ApplicationEvent(ApplicationEvent.ASK_FOR_SUBMIT);
			eventDispatcher.dispatchEvent(applicationEvent);
			var totalErrors:int = r.errors + r.missingErrors + r.skipped;
			if ( totalErrors > 0 ) {
				openErrorsListPopUp();
			} else {
				var messageResource:String;
				if(r.step == CollectRecord$Step.ENTRY) {
					messageResource = "edit.confirmSubmitDataCleansing";
					AlertUtil.showConfirm(messageResource, null, null, performSubmitToClenasing);
				} else if(r.step == CollectRecord$Step.CLEANSING) {
					messageResource = "edit.confirmSubmitDataAnalysis";
					AlertUtil.showConfirm(messageResource, null, null, performSubmitToAnalysis);
				}
			}
		}

		protected function openErrorsListPopUp():void {
			if ( _errorsListPopUp != null ) {
				PopUpManager.removePopUp(_errorsListPopUp);
				_errorsListPopUp = null;
			}
			_errorsListPopUp = ErrorListPopUp(PopUpUtil.createPopUp(ErrorListPopUp, false));
		}

		protected function rejectButtonClickHandler(event:MouseEvent):void {
			var messageResource:String;
			var r:RecordProxy = Application.activeRecord;
			if(r.step == CollectRecord$Step.CLEANSING) {
				messageResource = "edit.confirmRejectDataCleansing";
				AlertUtil.showConfirm(messageResource, null, null, performRejectToEntry);
			} else if(r.step == CollectRecord$Step.ANALYSIS) {
				messageResource = "edit.confirmRejectDataAnalysis";
				AlertUtil.showConfirm(messageResource, null, null, performRejectToCleansing);
			}
		}

		protected function performSubmitToClenasing():void {
			var responder:AsyncResponder = new AsyncResponder(promoteRecordResultHandler, faultHandler);
			_dataClient.promoteToCleansing(responder);
		}

		protected function performSubmitToAnalysis():void {
			var responder:AsyncResponder = new AsyncResponder(promoteRecordResultHandler, faultHandler);
			_dataClient.promoteToAnalysis(responder);
		}

		protected function performRejectToCleansing():void {
			var responder:AsyncResponder = new AsyncResponder(rejectRecordResultHandler, faultHandler);
			_dataClient.demoteToCleansing(responder);
		}

		protected function performRejectToEntry():void {
			var responder:AsyncResponder = new AsyncResponder(rejectRecordResultHandler, faultHandler);
			_dataClient.demoteToEntry(responder);
		}

		internal function clearActiveRecordHandler(event:ResultEvent, token:Object = null):void {
			var uiEvent:UIEvent = new UIEvent(UIEvent.BACK_TO_LIST);
			eventDispatcher.dispatchEvent(uiEvent);
		}

		internal function saveActiveRecordResultHandler(event:ResultEvent, token:Object = null):void {
			Application.activeRecord.showErrors();
			Application.activeRecord.updated = false;
			updateStatusLabel();
			var applicationEvent:ApplicationEvent = new ApplicationEvent(ApplicationEvent.RECORD_SAVED);
			eventDispatcher.dispatchEvent(applicationEvent);
		}

		internal function promoteRecordResultHandler(event:ResultEvent, token:Object = null):void {
			var rootEntity:EntityDefinitionProxy = Application.activeRootEntity;
			var rootEntityLabel:String = rootEntity.getInstanceOrHeadingLabelText();
			var r:RecordProxy = Application.activeRecord;
			var keyLabel:String = r.rootEntity.keyText;
			var actualStep:CollectRecord$Step = getNextStep(r.step);
			var stepLabel:String = getStepLabel(actualStep).toLowerCase();
			AlertUtil.showMessage("edit.recordSubmitted", [rootEntityLabel, keyLabel, stepLabel], "edit.recordSubmittedTitle", [rootEntityLabel]);
			Application.activeRecord = null;
			var uiEvent:UIEvent = new UIEvent(UIEvent.BACK_TO_LIST);
			eventDispatcher.dispatchEvent(uiEvent);
		}

		internal function rejectRecordResultHandler(event:ResultEvent, token:Object = null):void {
			var rootEntity:EntityDefinitionProxy = Application.activeRootEntity;
			var rootEntityLabel:String = rootEntity.getInstanceOrHeadingLabelText();
			var r:RecordProxy = Application.activeRecord;
			var keyLabel:String = r.rootEntity.keyText;
			var actualStep:CollectRecord$Step = getPreviousStep(r.step);
			var stepLabel:String = getStepLabel(actualStep).toLowerCase();
			AlertUtil.showMessage("edit.recordRejected", [rootEntityLabel, keyLabel, stepLabel], "edit.recordRejectedTitle", [rootEntityLabel]);
			Application.activeRecord = null;
			var uiEvent:UIEvent = new UIEvent(UIEvent.BACK_TO_LIST);
			eventDispatcher.dispatchEvent(uiEvent);
		}

		protected function updateResponseReceivedHandler(event:ApplicationEvent):void {
			updateStatusLabel();
		}

		protected function updateStatusLabel():void {
			var updateMessageKey:String;
			if ( Application.activeRecord.updated ) {
				updateMessageKey = "edit.changes_not_saved";
			} else {
				updateMessageKey = "edit.all_changes_saved";
			}
			_view.updateStatusLabel.text = Message.get(updateMessageKey);
		}

		protected function stageKeyDownHandler(event:KeyboardEvent):void {
			//save record pressing CTRL + s
			if ( !Application.preview && Application.activeRecordEditable &&
					event.ctrlKey && event.keyCode == Keyboard.S ) {
				performSaveActiveRecord();
			}
		}

		public static function getNextStep(step:CollectRecord$Step):CollectRecord$Step {
			switch ( step ) {
				case CollectRecord$Step.ENTRY:
					return CollectRecord$Step.CLEANSING;
				case CollectRecord$Step.CLEANSING:
					return CollectRecord$Step.ANALYSIS;
				default:
					return null;
			}
		}

		public static function getPreviousStep(step:CollectRecord$Step):CollectRecord$Step {
			switch ( step ) {
				case CollectRecord$Step.CLEANSING:
					return CollectRecord$Step.ENTRY;
				case CollectRecord$Step.ANALYSIS:
					return CollectRecord$Step.CLEANSING;
				default:
					return null;

			}
		}

		public static function getStepLabel(step:CollectRecord$Step):String {
			switch ( step ) {
				case CollectRecord$Step.ENTRY:
					return Message.get("edit.dataEntry");
				case CollectRecord$Step.CLEANSING:
					return Message.get("edit.dataCleansing");
				case CollectRecord$Step.ANALYSIS:
					return Message.get("edit.dataAnalysis");
				default:
					return null;
			}
		}
	}
}

Update record status label when record is saved


package gov.nih.nci.cbiit.casas.components
{
	import flash.display.MovieClip;

	import learnmath.windows.apps.EditorApp;

	import mx.controls.Alert;
	public class FormulaPanel extends EditorApp
	{
		public function FormulaPanel(arg0:MovieClip, arg1:int, arg2:int, arg3:int, arg4:int, arg5:Function)
		{
			super(arg0, arg1, arg2, arg3, arg4, arg5);
			name= "NCI Center for Bioinformatics & Information Technology - Scientific Algorithm Service";
			return;
		}

		override public function openAction()
		{
//			var _loc_1:* = String(ExternalInterface.call("getMathMLFromJavascript"));
//			if (_loc_1 != null)
//			{
//			}
//			if (_loc_1.length != 0)
//			{
//			}
//			if (_loc_1 == "null")
//			{
//				return;
//			}
//			this.editor.newFormula();
//			this.editor.insert(_loc_1, this.lastStyle);
			Alert.show("open is cliked...","Scientific Algorithm Service:openAction()");
			super.openAction();
			return;
		}// end function

		override public function saveAction()
		{
//			var _loc_1:* = this.convToMathML(this.editor.getMathMLString());
//			ExternalInterface.call("saveMathMLToJavascript", _loc_1);
//			this.isSaved = true;
			Alert.show("save is cliked...","Scientific Algorithm Service:saveAction()");
			super.saveAction();
			return;
		}// end function
	}
}

package gov.nih.nci.cbiit.casas.components
{
	import flash.display.MovieClip;
	import flash.net.FileReference;

	import learnmath.windows.apps.EditorApp;

	import mx.controls.Alert;
	public class FormulaPanel extends EditorApp
	{
		public function FormulaPanel(arg0:MovieClip, arg1:int, arg2:int, arg3:int, arg4:int, arg5:Function)
		{
			super(arg0, arg1, arg2, arg3, arg4, arg5);
			name= "NCI Center for Bioinformatics & Information Technology - Scientific Algorithm Service";
			return;
		}

		override  public function openAction():*
		{
//			var _loc_1:* = String(ExternalInterface.call("getMathMLFromJavascript"));
//			if (_loc_1 != null)
//			{
//			}
//			if (_loc_1.length != 0)
//			{
//			}
//			if (_loc_1 == "null")
//			{
//				return;
//			}
//			this.editor.newFormula();
//			this.editor.insert(_loc_1, this.lastStyle);

			var myFileReference:FileReference = new FileReference();
			myFileReference.browse();
			super.openAction();
			return;
		}// end function

		override public function saveAction():*
		{
//			var _loc_1:* = this.convToMathML(this.editor.getMathMLString());
//			ExternalInterface.call("saveMathMLToJavascript", _loc_1);
//			this.isSaved = true;
			Alert.show("save is cliked...","Scientific Algorithm Service:saveAction()");
			super.saveAction();
			return;
		}// end function
	}
}

set return type for functions

set return type for functions

SVN-Revision: 3134


package com.freshplanet.nativeExtensions
{
	import flash.display.BitmapData;
	import flash.events.EventDispatcher;
	import flash.events.StatusEvent;
	import flash.external.ExtensionContext;
	import flash.system.Capabilities;

	import mx.graphics.shaderClasses.ExclusionShader;

    public class PushNotification extends EventDispatcher
	{

		public static const RECURRENCE_NONE:int   = 0;
		public static const RECURRENCE_DAILY:int  = 1;
		public static const RECURRENCE_WEEK:int   = 2;
		public static const RECURRENCE_MONTH:int  = 3;
		public static const RECURRENCE_YEAR:int   = 4;

		private static var extCtx:ExtensionContext = null;

        private static var _instance:PushNotification;

        public function PushNotification()
		{
			if (!_instance)
			{
				if (this.isPushNotificationSupported)
				{

					extCtx = ExtensionContext.createExtensionContext("com.freshplanet.AirPushNotification", null);

					if (extCtx != null)
					{
						extCtx.addEventListener(StatusEvent.STATUS, onStatus);
					} else
					{
						trace('extCtx is null.');
					}
				}
				_instance = this;
			}
			else
			{
				throw Error( 'This is a singleton, use getInstance, do not call the constructor directly');
			}
		}

		public function get isPushNotificationSupported():Boolean
		{
			var result:Boolean = (Capabilities.manufacturer.search('iOS') > -1 || Capabilities.manufacturer.search('Android') > -1);
			return result;
		}

		public static function getInstance() : PushNotification
		{
			return _instance ? _instance : new PushNotification();
		}

        /**
		 * Needs Project id for Android Notifications.
		 * The project id is the one the developer used to register to gcm.
		 * @param projectId: project id to use
		 */
		public function registerForPushNotification(projectId:String = null) : void
		{
			if (this.isPushNotificationSupported)
			{
				extCtx.call("registerPush", projectId);
			}
		}

		public function setBadgeNumberValue(value:int):void
		{
			if (this.isPushNotificationSupported)
			{
				extCtx.call("setBadgeNb", value);
			}
		}

		/**
		 * Sends a local notification to the device.
		 * @param message the local notification text displayed
		 * @param timestamp when the local notification should appear (in sec)
		 * @param title (Android Only) Title of the local notification
		 * @param recurrenceType
		 *
		 */
		public function sendLocalNotification(message:String, timestamp:int, title:String, recurrenceType:int = RECURRENCE_NONE):void
		{
			trace("[Push Notification]","sendLocalNotification");
			if (this.isPushNotificationSupported)
			{
				extCtx.call("sendLocalNotification", message, timestamp, title, recurrenceType);
			}
		}

		public function setIsAppInForeground(value:Boolean):void
		{
			if (this.isPushNotificationSupported)
			{
				extCtx.call("setIsAppInForeground", value);
			}
		}

		public function addListenerForStarterNotifications(listener:Function):void
		{
			if (this.isPushNotificationSupported)
			{
				this.addEventListener(PushNotificationEvent.APP_STARTING_FROM_NOTIFICATION_EVENT, listener);
				extCtx.call("fetchStarterNotification");
			}
		}

        // onStatus()
        // Event handler for the event that the native implementation dispatches.
        //
        private function onStatus(e:StatusEvent):void
		{
			if (this.isPushNotificationSupported)
			{
				var event : PushNotificationEvent;
				var data:String = e.level;
				switch (e.code)
				{
					case "TOKEN_SUCCESS":
						event = new PushNotificationEvent( PushNotificationEvent.PERMISSION_GIVEN_WITH_TOKEN_EVENT );
						event.token = e.level;
						break;
					case "TOKEN_FAIL":
						event = new PushNotificationEvent( PushNotificationEvent.PERMISSION_REFUSED_EVENT );
						event.errorCode = "NativeCodeError";
						event.errorMessage = e.level;
						break;
					case "COMING_FROM_NOTIFICATION":
						event = new PushNotificationEvent( PushNotificationEvent.COMING_FROM_NOTIFICATION_EVENT );
						if (data != null)
						{
							try
							{
								event.parameters = JSON.parse(data);
							} catch (error:Error)
							{
								trace("[PushNotification Error]", "cannot parse the params string", data);
							}
						}
						break;
					case "APP_STARTING_FROM_NOTIFICATION":
						event = new PushNotificationEvent( PushNotificationEvent.APP_STARTING_FROM_NOTIFICATION_EVENT );
						if (data != null)
						{
							try
							{
								event.parameters = JSON.parse(data);
							} catch (error:Error)
							{
								trace("[PushNotification Error]", "cannot parse the params string", data);
							}
						}
						break;
					case "APP_BROUGHT_TO_FOREGROUND_FROM_NOTIFICATION":
						event = new PushNotificationEvent( PushNotificationEvent.APP_BROUGHT_TO_FOREGROUND_FROM_NOTIFICATION_EVENT );
						if (data != null)
						{
							try
							{
								event.parameters = JSON.parse(data);
							} catch (error:Error)
							{
								trace("[PushNotification Error]", "cannot parse the params string", data);
							}
						}
						break;
					case "NOTIFICATION_RECEIVED_WHEN_IN_FOREGROUND":
						event = new PushNotificationEvent( PushNotificationEvent.NOTIFICATION_RECEIVED_WHEN_IN_FOREGROUND_EVENT );
						if (data != null)
						{
							try
							{
								event.parameters = JSON.parse(data);
							} catch (error:Error)
							{
								trace("[PushNotification Error]", "cannot parse the params string", data);
							}
						}
						break;
					case "LOGGING":
						trace(e, e.level);
						break;
				}

				if (event != null)
				{
					this.dispatchEvent( event );
				}
			}
		}

	}
}

package com.freshplanet.nativeExtensions
{
	import flash.display.BitmapData;
	import flash.events.EventDispatcher;
	import flash.events.StatusEvent;
	import flash.external.ExtensionContext;
	import flash.system.Capabilities;

    public class PushNotification extends EventDispatcher
	{

		public static const RECURRENCE_NONE:int   = 0;
		public static const RECURRENCE_DAILY:int  = 1;
		public static const RECURRENCE_WEEK:int   = 2;
		public static const RECURRENCE_MONTH:int  = 3;
		public static const RECURRENCE_YEAR:int   = 4;

		private static var extCtx:ExtensionContext = null;

        private static var _instance:PushNotification;

        public function PushNotification()
		{
			if (!_instance)
			{
				if (this.isPushNotificationSupported)
				{

					extCtx = ExtensionContext.createExtensionContext("com.freshplanet.AirPushNotification", null);

					if (extCtx != null)
					{
						extCtx.addEventListener(StatusEvent.STATUS, onStatus);
					} else
					{
						trace('extCtx is null.');
					}
				}
				_instance = this;
			}
			else
			{
				throw Error( 'This is a singleton, use getInstance, do not call the constructor directly');
			}
		}

		public function get isPushNotificationSupported():Boolean
		{
			var result:Boolean = (Capabilities.manufacturer.search('iOS') > -1 || Capabilities.manufacturer.search('Android') > -1);
			return result;
		}

		public static function getInstance() : PushNotification
		{
			return _instance ? _instance : new PushNotification();
		}

        /**
		 * Needs Project id for Android Notifications.
		 * The project id is the one the developer used to register to gcm.
		 * @param projectId: project id to use
		 */
		public function registerForPushNotification(projectId:String = null) : void
		{
			if (this.isPushNotificationSupported)
			{
				extCtx.call("registerPush", projectId);
			}
		}

		public function setBadgeNumberValue(value:int):void
		{
			if (this.isPushNotificationSupported)
			{
				extCtx.call("setBadgeNb", value);
			}
		}

		/**
		 * Sends a local notification to the device.
		 * @param message the local notification text displayed
		 * @param timestamp when the local notification should appear (in sec)
		 * @param title (Android Only) Title of the local notification
		 * @param recurrenceType
		 *
		 */
		public function sendLocalNotification(message:String, timestamp:int, title:String, recurrenceType:int = RECURRENCE_NONE):void
		{
			trace("[Push Notification]","sendLocalNotification");
			if (this.isPushNotificationSupported)
			{
				extCtx.call("sendLocalNotification", message, timestamp, title, recurrenceType);
			}
		}

		public function setIsAppInForeground(value:Boolean):void
		{
			if (this.isPushNotificationSupported)
			{
				extCtx.call("setIsAppInForeground", value);
			}
		}

		public function addListenerForStarterNotifications(listener:Function):void
		{
			if (this.isPushNotificationSupported)
			{
				this.addEventListener(PushNotificationEvent.APP_STARTING_FROM_NOTIFICATION_EVENT, listener);
				extCtx.call("fetchStarterNotification");
			}
		}

        // onStatus()
        // Event handler for the event that the native implementation dispatches.
        //
        private function onStatus(e:StatusEvent):void
		{
			if (this.isPushNotificationSupported)
			{
				var event : PushNotificationEvent;
				var data:String = e.level;
				switch (e.code)
				{
					case "TOKEN_SUCCESS":
						event = new PushNotificationEvent( PushNotificationEvent.PERMISSION_GIVEN_WITH_TOKEN_EVENT );
						event.token = e.level;
						break;
					case "TOKEN_FAIL":
						event = new PushNotificationEvent( PushNotificationEvent.PERMISSION_REFUSED_EVENT );
						event.errorCode = "NativeCodeError";
						event.errorMessage = e.level;
						break;
					case "COMING_FROM_NOTIFICATION":
						event = new PushNotificationEvent( PushNotificationEvent.COMING_FROM_NOTIFICATION_EVENT );
						if (data != null)
						{
							try
							{
								event.parameters = JSON.parse(data);
							} catch (error:Error)
							{
								trace("[PushNotification Error]", "cannot parse the params string", data);
							}
						}
						break;
					case "APP_STARTING_FROM_NOTIFICATION":
						event = new PushNotificationEvent( PushNotificationEvent.APP_STARTING_FROM_NOTIFICATION_EVENT );
						if (data != null)
						{
							try
							{
								event.parameters = JSON.parse(data);
							} catch (error:Error)
							{
								trace("[PushNotification Error]", "cannot parse the params string", data);
							}
						}
						break;
					case "APP_BROUGHT_TO_FOREGROUND_FROM_NOTIFICATION":
						event = new PushNotificationEvent( PushNotificationEvent.APP_BROUGHT_TO_FOREGROUND_FROM_NOTIFICATION_EVENT );
						if (data != null)
						{
							try
							{
								event.parameters = JSON.parse(data);
							} catch (error:Error)
							{
								trace("[PushNotification Error]", "cannot parse the params string", data);
							}
						}
						break;
					case "NOTIFICATION_RECEIVED_WHEN_IN_FOREGROUND":
						event = new PushNotificationEvent( PushNotificationEvent.NOTIFICATION_RECEIVED_WHEN_IN_FOREGROUND_EVENT );
						if (data != null)
						{
							try
							{
								event.parameters = JSON.parse(data);
							} catch (error:Error)
							{
								trace("[PushNotification Error]", "cannot parse the params string", data);
							}
						}
						break;
					case "LOGGING":
						trace(e, e.level);
						break;
				}

				if (event != null)
				{
					this.dispatchEvent( event );
				}
			}
		}

	}
}

Remove useless import.

Remove useless import.


package flump {

import flash.display.MovieClip;
import flash.filesystem.FileMode;
import flash.filesystem.File;
import flash.filesystem.FileStream;
import flash.utils.ByteArray;
import com.adobe.images.PNGEncoder;
import flash.display.BitmapData;
import flash.display.Bitmap;
import flash.geom.Rectangle;
import com.threerings.flashbang.resource.SwfResource;
import com.threerings.flashbang.resource.ResourceManager;
import com.threerings.util.F;
import flash.display.LoaderInfo;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.sampler.Sample;
import flash.sampler.StackFrame;
import flash.sampler.getSamples;
import flash.sampler.pauseSampling;
import flash.sampler.clearSamples;
import flash.sampler.startSampling;
import flash.sampler.stopSampling;
import flash.utils.Timer;
import flash.events.TimerEvent;
import flash.ui.Keyboard;

public class Flump extends Sprite
{
    public function Flump ()
    {
        _rsrc.registerDefaultResourceTypes();
        addEventListener(Event.ADDED_TO_STAGE, F.callbackOnce(addedToStage));
    }

    protected function addedToStage () :void
    {
        _rsrc.queueResourceLoad("swf", "pant", { embeddedClass: PANT});
        _rsrc.queueResourceLoad("swf", "hat", { embeddedClass: HAT});
        _rsrc.queueResourceLoad("swf", "top", { embeddedClass: TOP});
        _rsrc.queueResourceLoad("swf", "hed", { embeddedClass: HED});
        _rsrc.queueResourceLoad("swf", "sho", { embeddedClass: SHO});
        _rsrc.queueResourceLoad("swf", "base", { embeddedClass: BASE});
        _rsrc.loadQueuedResources(resourcesLoaded);
    }

    protected function resourcesLoaded () :void
    {
        F.forEach(layers, export);
        trace("{\n    " + _offsets.join(",\n    ") + "\n}");
    }

    protected function export (layer :String) :void
    {
        var theClass :Class;
        for each (var resource :String in resources) {
            theClass= SwfResource.getSwf(_rsrc, resource).getClass(layer + "_class");
            if (theClass != null) break;
        }
        if (theClass == null) { trace("skipping " + layer); return; }

        const holder :Sprite = new Sprite();
        const child :Sprite = Sprite(new theClass());
        holder.addChild(child);
        const bounds :Rectangle = child.getBounds(holder);
        if (bounds.width == 0 || bounds.height == 0) { trace("invisible " + layer); return; }
        if (_renames.hasOwnProperty(layer)) layer = _renames[layer];
        child.x = -bounds.x;
        child.y = -bounds.y;
        _offsets.push(layer + ": [" + bounds.x + ', ' + bounds.y + "]");

        const bd :BitmapData = new BitmapData(bounds.width, bounds.height, true);
        // Clear bitmapdata's default white background with a transparent one
        bd.fillRect(new Rectangle(0, 0, bounds.width, bounds.height), 0);
        bd.draw(holder);
        var fs :FileStream = new FileStream();
        fs.open(new File("/Users/charlie/dev/flump/" + layer + ".png"), FileMode.WRITE);
        fs.writeBytes(PNGEncoder.encode(bd));
        fs.close();
    }

    protected const _offsets :Array = [];

    protected const _rsrc :ResourceManager = new ResourceManager();
    protected const _renames :Object = {"container_device_a": "device", "container_head_a": "head"};

    protected const layers :Array = ["forearmL", "handL", "head", "neck", "bicepL", "scarfB",
        "chest", "belly", "skirtL", "skirtM", "skirtR", "thighL", "pelvis", "calfL", "footL",
        "thighR", "calfR", "footR", "forearmR", "handR", "device", "bicepR", "tails", "hairB",
        "container_head_a", "container_device_a", "shadow"];

    protected const resources :Array = ["pant", "hat", "top", "hed", "sho", "base"];

    [Embed(source="/../swfresources/avatar/HAT_001.swf", mimeType="application/octet-stream")]
    protected const HAT :Class;
    [Embed(source="/../swfresources/avatar/PNT_001.swf", mimeType="application/octet-stream")]
    protected const PANT :Class;
    [Embed(source="/../swfresources/avatar/TOP_001.swf", mimeType="application/octet-stream")]
    protected const TOP :Class;
    [Embed(source="/../swfresources/avatar/HED_001.swf", mimeType="application/octet-stream")]
    protected const HED :Class;
    [Embed(source="/../swfresources/avatar/SHO_001.swf", mimeType="application/octet-stream")]
    protected const SHO :Class;
    [Embed(source="/../swfresources/avatar/male_player_base.swf", mimeType="application/octet-stream")]
    protected const BASE :Class;
}
}

//
// Flump - Copyright 2012 Three Rings Design

package flump {

import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Sprite;
import flash.filesystem.File;
import flash.filesystem.FileMode;
import flash.filesystem.FileStream;
import flash.geom.Point;
import flash.geom.Rectangle;

import com.adobe.images.PNGEncoder;

import com.threerings.util.F;

public class Flump extends Sprite
{
    protected function exportToPng (dest :String, toExport :Sprite) :Point {
        const holder :Sprite = new Sprite();
        holder.addChild(toExport);
        const bounds :Rectangle = toExport.getBounds(holder);
        toExport.x = -bounds.x;
        toExport.y = -bounds.y;

        const bd :BitmapData = new BitmapData(bounds.width, bounds.height, true);
        // Clear bitmapdata's default white background with a transparent one
        bd.fillRect(new Rectangle(0, 0, bounds.width, bounds.height), 0);
        bd.draw(holder);
        var fs :FileStream = new FileStream();
        fs.open(new File(dest), FileMode.WRITE);
        fs.writeBytes(PNGEncoder.encode(bd));
        fs.close();
        return new Point(bounds.x, bounds.y);
    }
}}

Clean out testing code, leave png export


package dolly {

import dolly.core.dolly_internal;
import dolly.data.CopyableCloneableClass;

import org.as3commons.reflect.Field;
import org.as3commons.reflect.Type;
import org.flexunit.asserts.assertEquals;
import org.flexunit.asserts.assertNotNull;

use namespace dolly_internal;

public class CopyingOfCopyableCloneableClassTest {

	private var copyableCloneableClass:CopyableCloneableClass;
	private var copyableCloneableClassType:Type;

	[Before]
	public function before():void {
		copyableCloneableClass = new CopyableCloneableClass();
		copyableCloneableClass.property1 = "property1 value";
		copyableCloneableClass.writableField1 = "writableField1 value";
		copyableCloneableClassType = Type.forInstance(copyableCloneableClass);
	}

	[After]
	public function after():void {
		copyableCloneableClass = null;
		copyableCloneableClassType = null;
	}

	[Test]
	public function findingAllWritableFieldsForType():void {
		const writableFields:Vector.<Field> = Copier.findCopyableFieldsForType(copyableCloneableClassType);
		assertNotNull(writableFields);
		assertEquals(2, writableFields.length);
	}

	[Test]
	public function cloningByCloner():void {
		const clone:CopyableCloneableClass = Copier.copy(copyableCloneableClass);

		assertNotNull(clone);
		assertNotNull(clone.property1);
		assertEquals(clone.property1, copyableCloneableClass.property1);
		assertNotNull(clone.writableField1);
		assertEquals(clone.writableField1, copyableCloneableClass.writableField1);
	}

	[Test]
	public function cloningByCloneFunction():void {
		const cloneInstance:CopyableCloneableClass = copy(copyableCloneableClass);

		assertNotNull(cloneInstance);
		assertNotNull(cloneInstance.property1);
		assertEquals(cloneInstance.property1, copyableCloneableClass.property1);
		assertNotNull(cloneInstance.writableField1);
		assertEquals(cloneInstance.writableField1, copyableCloneableClass.writableField1);
	}
}
}

package dolly {

import dolly.core.dolly_internal;
import dolly.data.CopyableCloneableClass;

import org.as3commons.reflect.Field;
import org.as3commons.reflect.Type;
import org.flexunit.asserts.assertEquals;
import org.flexunit.asserts.assertNotNull;

use namespace dolly_internal;

public class CopyingOfCopyableCloneableClassTest {

	private var copyableCloneableClass:CopyableCloneableClass;
	private var copyableCloneableClassType:Type;

	[Before]
	public function before():void {
		copyableCloneableClass = new CopyableCloneableClass();
		copyableCloneableClass.property1 = "property1 value";
		copyableCloneableClass.writableField1 = "writableField1 value";
		copyableCloneableClassType = Type.forInstance(copyableCloneableClass);
	}

	[After]
	public function after():void {
		copyableCloneableClass = null;
		copyableCloneableClassType = null;
	}

	[Test]
	public function findingAllCopyableFieldsForType():void {
		const copyableFields:Vector.<Field> = Copier.findCopyableFieldsForType(copyableCloneableClassType);
		assertNotNull(copyableFields);
		assertEquals(2, copyableFields.length);
		assertNotNull(copyableFields[0]);
		assertNotNull(copyableFields[1]);
	}

	[Test]
	public function cloningByCloner():void {
		const clone:CopyableCloneableClass = Copier.copy(copyableCloneableClass);

		assertNotNull(clone);
		assertNotNull(clone.property1);
		assertEquals(clone.property1, copyableCloneableClass.property1);
		assertNotNull(clone.writableField1);
		assertEquals(clone.writableField1, copyableCloneableClass.writableField1);
	}

	[Test]
	public function cloningByCloneFunction():void {
		const cloneInstance:CopyableCloneableClass = copy(copyableCloneableClass);

		assertNotNull(cloneInstance);
		assertNotNull(cloneInstance.property1);
		assertEquals(cloneInstance.property1, copyableCloneableClass.property1);
		assertNotNull(cloneInstance.writableField1);
		assertEquals(cloneInstance.writableField1, copyableCloneableClass.writableField1);
	}
}
}

Fix variable and methods names.

Fix variable and methods names.


////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2008-2013 Esri. All Rights Reserved.
//
// Licensed 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 com.esri.builder.controllers
{

import com.esri.builder.controllers.supportClasses.processes.CleanUpProcess;
import com.esri.builder.controllers.supportClasses.processes.ProcessArbiter;
import com.esri.builder.controllers.supportClasses.processes.ProcessArbiterEvent;
import com.esri.builder.controllers.supportClasses.WellKnownDirectories;
import com.esri.builder.eventbus.AppEvent;
import com.esri.builder.model.WidgetType;
import com.esri.builder.model.WidgetTypeRegistryModel;
import com.esri.builder.views.BuilderAlert;

import flash.filesystem.File;

import mx.resources.ResourceManager;

public class RemoveCustomWidgetController
{
    private var removeWidgetArbiter:ProcessArbiter;

    private var widgetTypeToRemove:WidgetType;

    public function RemoveCustomWidgetController()
    {
        AppEvent.addListener(AppEvent.REMOVE_CUSTOM_WIDGET, removeCustomWidgetHandler);
    }

    private function removeCustomWidgetHandler(importCustomWidget:AppEvent):void
    {
        widgetTypeToRemove = importCustomWidget.data as WidgetType;
        removeWidget(widgetTypeToRemove);
    }

    private function removeWidget(widgetType:WidgetType):void
    {
        removeWidgetArbiter = new ProcessArbiter();
        removeWidgetArbiter.addEventListener(ProcessArbiterEvent.COMPLETE, importArbiter_completeHandler);
        removeWidgetArbiter.addEventListener(ProcessArbiterEvent.FAILURE, importArbiter_failureHandler);

        var customWidgetConfig:File = WellKnownDirectories.getInstance().customModules.resolvePath(widgetTypeToRemove.name + "Module.xml");
        var customWidgetFolder:File = WellKnownDirectories.getInstance().customFlexViewer.resolvePath("widgets/" + widgetType.name);

        removeWidgetArbiter.addProcess(new CleanUpProcess(customWidgetConfig));
        removeWidgetArbiter.addProcess(new CleanUpProcess(customWidgetFolder));

        removeWidgetArbiter.executeProcs();
    }

    protected function importArbiter_completeHandler(event:ProcessArbiterEvent):void
    {
        removeWidgetArbiter.removeEventListener(ProcessArbiterEvent.COMPLETE, importArbiter_completeHandler);
        removeWidgetArbiter.removeEventListener(ProcessArbiterEvent.FAILURE, importArbiter_failureHandler);

        WidgetTypeRegistryModel.getInstance().widgetTypeRegistry.removeWidgetType(widgetTypeToRemove);
        AppEvent.dispatch(AppEvent.REMOVE_CUSTOM_WIDGET_SUCCESS);
    }

    protected function importArbiter_failureHandler(event:ProcessArbiterEvent):void
    {
        removeWidgetArbiter.removeEventListener(ProcessArbiterEvent.COMPLETE, importArbiter_completeHandler);
        removeWidgetArbiter.removeEventListener(ProcessArbiterEvent.FAILURE, importArbiter_failureHandler);

        var removeCustomWidgetFailureMessage:String = ResourceManager.getInstance().getString("BuilderStrings",
                                                                                "removeCustomWidgetProcess.failure",
                                                                                [ event.message ]);
        var removeCustomWidgetFailureTitle:String = ResourceManager.getInstance().getString("BuilderStrings",
                                                                                "widgetManager.removeCustomWidget");
        BuilderAlert.show(removeCustomWidgetFailureMessage, removeCustomWidgetFailureTitle);

        AppEvent.dispatch(AppEvent.REMOVE_CUSTOM_WIDGET_FAILURE);
    }
}
}

////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2008-2013 Esri. All Rights Reserved.
//
// Licensed 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 com.esri.builder.controllers
{

import com.esri.builder.controllers.supportClasses.processes.CleanUpProcess;
import com.esri.builder.controllers.supportClasses.processes.ProcessArbiter;
import com.esri.builder.controllers.supportClasses.processes.ProcessArbiterEvent;
import com.esri.builder.controllers.supportClasses.WellKnownDirectories;
import com.esri.builder.eventbus.AppEvent;
import com.esri.builder.model.WidgetType;
import com.esri.builder.model.WidgetTypeRegistryModel;
import com.esri.builder.views.BuilderAlert;

import flash.filesystem.File;

import mx.resources.ResourceManager;

public class RemoveCustomWidgetController
{
    private var removeWidgetArbiter:ProcessArbiter;

    private var widgetTypeToRemove:WidgetType;

    public function RemoveCustomWidgetController()
    {
        AppEvent.addListener(AppEvent.REMOVE_CUSTOM_WIDGET, removeCustomWidgetHandler);
    }

    private function removeCustomWidgetHandler(importCustomWidget:AppEvent):void
    {
        widgetTypeToRemove = importCustomWidget.data as WidgetType;
        removeWidget(widgetTypeToRemove);
    }

    private function removeWidget(widgetType:WidgetType):void
    {
        removeWidgetArbiter = new ProcessArbiter();
        removeWidgetArbiter.addEventListener(ProcessArbiterEvent.COMPLETE, importArbiter_completeHandler);
        removeWidgetArbiter.addEventListener(ProcessArbiterEvent.FAILURE, importArbiter_failureHandler);

        var customWidgetModule:File = WellKnownDirectories.getInstance().customModules.resolvePath(widgetTypeToRemove.name + "Module.swf");
        var customWidgetConfig:File = WellKnownDirectories.getInstance().customModules.resolvePath(widgetTypeToRemove.name + "Module.xml");
        var customWidgetFolder:File = WellKnownDirectories.getInstance().customFlexViewer.resolvePath("widgets/" + widgetType.name);

        removeWidgetArbiter.addProcess(new CleanUpProcess(customWidgetModule));
        removeWidgetArbiter.addProcess(new CleanUpProcess(customWidgetConfig));
        removeWidgetArbiter.addProcess(new CleanUpProcess(customWidgetFolder));

        removeWidgetArbiter.executeProcs();
    }

    protected function importArbiter_completeHandler(event:ProcessArbiterEvent):void
    {
        removeWidgetArbiter.removeEventListener(ProcessArbiterEvent.COMPLETE, importArbiter_completeHandler);
        removeWidgetArbiter.removeEventListener(ProcessArbiterEvent.FAILURE, importArbiter_failureHandler);

        WidgetTypeRegistryModel.getInstance().widgetTypeRegistry.removeWidgetType(widgetTypeToRemove);
        AppEvent.dispatch(AppEvent.REMOVE_CUSTOM_WIDGET_SUCCESS);
    }

    protected function importArbiter_failureHandler(event:ProcessArbiterEvent):void
    {
        removeWidgetArbiter.removeEventListener(ProcessArbiterEvent.COMPLETE, importArbiter_completeHandler);
        removeWidgetArbiter.removeEventListener(ProcessArbiterEvent.FAILURE, importArbiter_failureHandler);

        var removeCustomWidgetFailureMessage:String = ResourceManager.getInstance().getString("BuilderStrings",
                                                                                "removeCustomWidgetProcess.failure",
                                                                                [ event.message ]);
        var removeCustomWidgetFailureTitle:String = ResourceManager.getInstance().getString("BuilderStrings",
                                                                                "widgetManager.removeCustomWidget");
        BuilderAlert.show(removeCustomWidgetFailureMessage, removeCustomWidgetFailureTitle);

        AppEvent.dispatch(AppEvent.REMOVE_CUSTOM_WIDGET_FAILURE);
    }
}
}

Update RemoveCustomWidgetController to remove imported modules.


////////////////////////////////////////////////////////////////////////////////
//
//  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 org.apache.flex.core
{
    /**
     *  The ILayoutParent interface is the basic interface for the
     *  container that have an IBeadLayout.  The layout implementation
     *  often needs to know certain things about other objects in
     *  the component.
     *
     *  @langversion 3.0
     *  @playerversion Flash 10.2
     *  @playerversion AIR 2.6
     *  @productversion FlexJS 0.0
     */
	public interface ILayoutParent
	{
        /**
         *  The container that parents all of the content.
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
		function get contentView():IParentIUIBase;

        /**
         *  The container whose size changes
         *  imply the need for another layout pass.  This
         *  is normally the host component.
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
		function get resizableView():IUIBase;
	}
}

////////////////////////////////////////////////////////////////////////////////
//
//  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 org.apache.flex.core
{
    /**
     *  The ILayoutParent interface is the basic interface for the
     *  container views that have an IBeadLayout.  The layout implementation
     *  often needs to know certain things about other objects in
     *  the view.
     *
     *  @langversion 3.0
     *  @playerversion Flash 10.2
     *  @playerversion AIR 2.6
     *  @productversion FlexJS 0.0
     */
	public interface ILayoutParent
	{
        /**
         *  The container that parents all of the content.
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
		function get contentView():IParentIUIBase;

        /**
         *  The container whose size changes
         *  imply the need for another layout pass.  This
         *  is normally the host component.
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
		function get resizableView():IUIBase;
	}
}

clean up a comment

clean up a comment