/*
 * Copyright 2017 FreshPlanet
 * 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.freshplanet.ane.AirCapabilities {

import com.freshplanet.ane.AirCapabilities.events.AirCapabilitiesLowMemoryEvent;
import com.freshplanet.ane.AirCapabilities.events.AirCapabilitiesOpenURLEvent;
	import flash.display.BitmapData;
	import flash.events.EventDispatcher;
	import flash.events.StatusEvent;
	import flash.external.ExtensionContext;
	import flash.system.Capabilities;

	public class AirCapabilities extends EventDispatcher {

		// --------------------------------------------------------------------------------------//
		//																						 //
		// 									   PUBLIC API										 //
		// 																						 //
		// --------------------------------------------------------------------------------------//

		/**
		 * Is the ANE supported on the current platform
		 */
        static public function get isSupported():Boolean {
            return (Capabilities.manufacturer.indexOf("iOS") > -1 && Capabilities.os.indexOf("x86_64") < 0 && Capabilities.os.indexOf("i386") < 0) || Capabilities.manufacturer.indexOf("Android") > -1;
        }

		/**
		 * If true, logs will be displayed at the ActionScript and native level.
		 */
		public function setLogging(value:Boolean):void {

			_doLogging = value;
			if (isSupported)
				_extContext.call("setLogging", value);
		}

		public function get nativeLogger():ILogger {
            return _logger;
        }

        /**
         * AirCapabilities instance
         */
        static public function get instance():AirCapabilities {
			return _instance != null ? _instance : new AirCapabilities()
		}

        /**
         * Is SMS available
         * @return
         */
		public function hasSmsEnabled():Boolean {

			if (isSupported)
				return _extContext.call("hasSMS");

			return false;
		}

        /**
         * Is Twitter available
         * @return
         */
		public function hasTwitterEnabled():Boolean {

			if (isSupported)
				return _extContext.call("hasTwitter");

			return false;
		}

        /**
         * Sends an SMS message
         * @param message to send
         * @param recipient phonenumber
         */
		public function sendMsgWithSms(message:String, recipient:String = null):void {

			if (isSupported)
				_extContext.call("sendWithSms", message, recipient);
		}

        /**
         * Sends a Twitter message
         * @param message
         */
		public function sendMsgWithTwitter(message:String):void {

			if (isSupported)
				_extContext.call("sendWithTwitter", message);
		}

        /**
         * Redirect user to Rating page
         * @param appId
         * @param appName
         */
		public function redirecToRating(appId:String, appName:String):void {

			if (isSupported)
				_extContext.call("redirectToRating", appId, appName);
		}

        /**
         * Model of the device
         * @return
         */
		public function getDeviceModel():String {

			if (isSupported)
				return _extContext.call("getDeviceModel") as String;

            return "";
		}

        /**
         * Name of the machine
         * @return
         */
		public function getMachineName():String {

			if (isSupported)
				return _extContext.call("getMachineName") as String;

            return "";
		}

        /**
         * Opens the referral link URL
         * @param url
         */
		public function processReferralLink(url:String):void {

			if (isSupported)
				_extContext.call("processReferralLink", url);
		}

        /**
         * Opens Facebook page
         * @param pageId id of the facebook page
         */
		public function redirectToPageId(pageId:String):void {

			if (isSupported)
				_extContext.call("redirectToPageId", pageId);
		}

        /**
         * Opens Twitter account
         * @param twitterAccount
         */
		public function redirectToTwitterAccount(twitterAccount:String):void {

			if (isSupported)
				_extContext.call("redirectToTwitterAccount", twitterAccount);
		}

        /**
         * Is posting pictures on Twitter enabled
         * @return
         */
		public function canPostPictureOnTwitter():Boolean {

			if (isSupported)
				return _extContext.call("canPostPictureOnTwitter");

			return false;
		}

        /**
         * Post new picture on Twitter
         * @param message
         * @param bitmapData
         */
		public function postPictureOnTwitter(message:String, bitmapData:BitmapData):void {

			if (isSupported)
				_extContext.call("postPictureOnTwitter", message, bitmapData);
		}

        /**
         * Is Instagram enabled
         * @return
         */
		public function hasInstagramEnabled():Boolean {

			if (isSupported)
				return _extContext.call("hasInstagramEnabled");

			return false;
		}

        /**
         * Post new picture on Instagram
         * @param message
         * @param bitmapData
         * @param x
         * @param y
         * @param width
         * @param height
         */
		public function postPictureOnInstagram(message:String, bitmapData:BitmapData,
                                               x:int, y:int, width:int, height:int):void {

			if (isSupported)
				_extContext.call("postPictureOnInstagram", message, bitmapData, x, y, width, height);
		}

		/**
		 * Open an application (if installed on the Device) or send the player to the appstore.  iOS Only
		 * @param schemes 		List of schemes (String) that the application accepts.  Examples : @"sms://", @"twit://".  You can find schemes in http://handleopenurl.com/
		 * @param appStoreURL 	(optional) Link to the AppStore page for the Application for the player to download. URL can be generated via Apple's linkmaker (itunes.apple.com/linkmaker?)
		 */
		public function openExternalApplication(schemes:Array, appStoreURL:String = null):void {

			if (isSupported && Capabilities.manufacturer.indexOf("Android") == -1)
				_extContext.call("openExternalApplication", schemes, appStoreURL);
		}

        /**
         * Is opening URLs available
         * @param url
         * @return
         */
		public function canOpenURL(url:String):Boolean {
			return isSupported ? _extContext.call("canOpenURL", url) as Boolean : false;
		}

        /**
         * Open URL
         * @param url
         */
		public function openURL(url:String):void {

			if (canOpenURL(url))
				_extContext.call("openURL", url);
		}

		/**
		 * Opens modal app store. Available on iOS only
		 * @param appStoreId	id of the app to open a modal view to (do not include the "id" at the beginning of the number)
		 */
		public function openModalAppStoreIOS(appStoreId:String):void {

			if (Capabilities.manufacturer.indexOf("iOS") > -1)
				_extContext.call("openModalAppStore", appStoreId);
		}

        /**
         * Version of the operating system
         * @return
         */
        public function getOSVersion():String {

            if (isSupported)
                return _extContext.call("getOSVersion") as String;

            return "";
        }

        /**
         * @return  current amount of RAM being used in bytes
         */
        public function getCurrentMem():Number {

			if (!isSupported)
				return -1;

            var ret:Object = _extContext.call("getCurrentMem");
            if (ret is Error)
                throw ret;
            else
                return ret ? ret as Number : 0;
        }

        /**
         * @return  amount of RAM used by the VM
         */
        public function getCurrentVirtualMem():Number {

			if(!isSupported)
				return -1;

            if (Capabilities.manufacturer.indexOf("iOS") == -1)
                return -1;

            var ret:Object = _extContext.call("getCurrentVirtualMem");
            if (ret is Error)
                throw ret;
            else
                return ret ? ret as Number : 0;
        }

		/**
		 * @return  is requesting review available. Available on iOS only
		 */
		public function canRequestReview():Boolean {

			if (!isSupported)
				return false;

			if (Capabilities.manufacturer.indexOf("iOS") == -1)
				return false;

			return _extContext.call("canRequestReview");
		}

		/**
		 * Request AppStore review. Available on iOS only
		 */
		public function requestReview():void {

			if (!canRequestReview())
				return;

			_extContext.call("requestReview");
		}
		/**
		 * Generate haptic feedback - iOS only
		 */
		public function generateHapticFeedback(feedbackType:AirCapabilitiesHapticFeedbackType):void {

			if (Capabilities.manufacturer.indexOf("iOS") < 0)
				return;

			if(!feedbackType)
				return

			_extContext.call("generateHapticFeedback", feedbackType.value);
		}

		public function getNativeScale():Number
		{
			if (Capabilities.manufacturer.indexOf("iOS") < 0)
				return 1;
			return _extContext.call("getNativeScale");
		}

		// --------------------------------------------------------------------------------------//
		//																						 //
		// 									 	PRIVATE API										 //
		// 																						 //
		// --------------------------------------------------------------------------------------//

		static private const EXTENSION_ID:String = "com.freshplanet.ane.AirCapabilities";

		static private var _instance:AirCapabilities = null;

		private var _extContext:ExtensionContext = null;
		private var _doLogging:Boolean = false;
		private var _logger:ILogger;

		/**
		 * "private" singleton constructor
		 */
		public function AirCapabilities() {

			super();

			if (_instance)
				throw new Error("singleton class, use .instance");

			_extContext = ExtensionContext.createExtensionContext(EXTENSION_ID, null);
			_extContext.addEventListener(StatusEvent.STATUS, _handleStatusEvent);

			if (isSupported)
				_logger = new NativeLogger(_extContext);
			else
				_logger = new DefaultLogger();

			_instance = this;
		}

        private function _handleStatusEvent(event:StatusEvent):void {

            if (event.code == "log")
	            _doLogging && trace("[AirCapabilities] " + event.level);
            else if (event.code == "OPEN_URL")
                this.dispatchEvent(new AirCapabilitiesOpenURLEvent(AirCapabilitiesOpenURLEvent.OPEN_URL_SUCCESS, event.level));
            else if (event.code == AirCapabilitiesLowMemoryEvent.LOW_MEMORY_WARNING) {
	            var memory:Number = Number(event.level);
	            this.dispatchEvent(new AirCapabilitiesLowMemoryEvent(event.code, memory));
            }
            else
                this.dispatchEvent(event);
        }
	}
}

/*
 * Copyright 2017 FreshPlanet
 * 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.freshplanet.ane.AirCapabilities {

import com.freshplanet.ane.AirCapabilities.events.AirCapabilitiesLowMemoryEvent;
import com.freshplanet.ane.AirCapabilities.events.AirCapabilitiesOpenURLEvent;
	import flash.display.BitmapData;
	import flash.events.EventDispatcher;
	import flash.events.StatusEvent;
	import flash.external.ExtensionContext;
	import flash.system.Capabilities;

	public class AirCapabilities extends EventDispatcher {

		// --------------------------------------------------------------------------------------//
		//																						 //
		// 									   PUBLIC API										 //
		// 																						 //
		// --------------------------------------------------------------------------------------//

		/**
		 * Is the ANE supported on the current platform
		 */
        static public function get isSupported():Boolean {
            return (Capabilities.manufacturer.indexOf("iOS") > -1 && Capabilities.os.indexOf("x86_64") < 0 && Capabilities.os.indexOf("i386") < 0) || Capabilities.manufacturer.indexOf("Android") > -1;
        }

		/**
		 * If true, logs will be displayed at the ActionScript and native level.
		 */
		public function setLogging(value:Boolean):void {

			_doLogging = value;
			if (isSupported)
				_extContext.call("setLogging", value);
		}

		public function get nativeLogger():ILogger {
            return _logger;
        }

        /**
         * AirCapabilities instance
         */
        static public function get instance():AirCapabilities {
			return _instance != null ? _instance : new AirCapabilities()
		}

        /**
         * Is SMS available
         * @return
         */
		public function hasSmsEnabled():Boolean {

			if (isSupported)
				return _extContext.call("hasSMS");

			return false;
		}

        /**
         * Is Twitter available
         * @return
         */
		public function hasTwitterEnabled():Boolean {

			if (isSupported)
				return _extContext.call("hasTwitter");

			return false;
		}

        /**
         * Sends an SMS message
         * @param message to send
         * @param recipient phonenumber
         */
		public function sendMsgWithSms(message:String, recipient:String = null):void {

			if (isSupported)
				_extContext.call("sendWithSms", message, recipient);
		}

        /**
         * Sends a Twitter message
         * @param message
         */
		public function sendMsgWithTwitter(message:String):void {

			if (isSupported)
				_extContext.call("sendWithTwitter", message);
		}

        /**
         * Redirect user to Rating page
         * @param appId
         * @param appName
         */
		public function redirecToRating(appId:String, appName:String):void {

			if (isSupported)
				_extContext.call("redirectToRating", appId, appName);
		}

        /**
         * Model of the device
         * @return
         */
		public function getDeviceModel():String {

			if (isSupported)
				return _extContext.call("getDeviceModel") as String;

            return "";
		}

        /**
         * Name of the machine
         * @return
         */
		public function getMachineName():String {

			if (isSupported)
				return _extContext.call("getMachineName") as String;

            return "";
		}

        /**
         * Opens the referral link URL
         * @param url
         */
		public function processReferralLink(url:String):void {

			if (isSupported)
				_extContext.call("processReferralLink", url);
		}

        /**
         * Opens Facebook page
         * @param pageId id of the facebook page
         */
		public function redirectToPageId(pageId:String):void {

			if (isSupported)
				_extContext.call("redirectToPageId", pageId);
		}

        /**
         * Opens Twitter account
         * @param twitterAccount
         */
		public function redirectToTwitterAccount(twitterAccount:String):void {

			if (isSupported)
				_extContext.call("redirectToTwitterAccount", twitterAccount);
		}

        /**
         * Is posting pictures on Twitter enabled
         * @return
         */
		public function canPostPictureOnTwitter():Boolean {

			if (isSupported)
				return _extContext.call("canPostPictureOnTwitter");

			return false;
		}

        /**
         * Post new picture on Twitter
         * @param message
         * @param bitmapData
         */
		public function postPictureOnTwitter(message:String, bitmapData:BitmapData):void {

			if (isSupported)
				_extContext.call("postPictureOnTwitter", message, bitmapData);
		}

        /**
         * Is Instagram enabled
         * @return
         */
		public function hasInstagramEnabled():Boolean {

			if (isSupported)
				return _extContext.call("hasInstagramEnabled");

			return false;
		}

        /**
         * Post new picture on Instagram
         * @param message
         * @param bitmapData
         * @param x
         * @param y
         * @param width
         * @param height
         */
		public function postPictureOnInstagram(message:String, bitmapData:BitmapData,
                                               x:int, y:int, width:int, height:int):void {

			if (isSupported)
				_extContext.call("postPictureOnInstagram", message, bitmapData, x, y, width, height);
		}

		/**
		 * Open an application (if installed on the Device) or send the player to the appstore.  iOS Only
		 * @param schemes 		List of schemes (String) that the application accepts.  Examples : @"sms://", @"twit://".  You can find schemes in http://handleopenurl.com/
		 * @param appStoreURL 	(optional) Link to the AppStore page for the Application for the player to download. URL can be generated via Apple's linkmaker (itunes.apple.com/linkmaker?)
		 */
		public function openExternalApplication(schemes:Array, appStoreURL:String = null):void {

			if (isSupported && Capabilities.manufacturer.indexOf("Android") == -1)
				_extContext.call("openExternalApplication", schemes, appStoreURL);
		}

        /**
         * Is opening URLs available
         * @param url
         * @return
         */
		public function canOpenURL(url:String):Boolean {
			return isSupported ? _extContext.call("canOpenURL", url) as Boolean : false;
		}

        /**
         * Open URL
         * @param url
         */
		public function openURL(url:String):void {

			if (canOpenURL(url))
				_extContext.call("openURL", url);
		}

		/**
		 * Opens modal app store. Available on iOS only
		 * @param appStoreId	id of the app to open a modal view to (do not include the "id" at the beginning of the number)
		 */
		public function openModalAppStoreIOS(appStoreId:String):void {

			if (Capabilities.manufacturer.indexOf("iOS") > -1)
				_extContext.call("openModalAppStore", appStoreId);
		}

        /**
         * Version of the operating system
         * @return
         */
        public function getOSVersion():String {

            if (isSupported)
                return _extContext.call("getOSVersion") as String;

            return "";
        }

        /**
         * @return  current amount of RAM being used in bytes
         */
        public function getCurrentMem():Number {

			if (!isSupported)
				return -1;

            var ret:Object = _extContext.call("getCurrentMem");
            if (ret is Error)
                throw ret;
            else
                return ret ? ret as Number : 0;
        }

        /**
         * @return  amount of RAM used by the VM
         */
        public function getCurrentVirtualMem():Number {

			if(!isSupported)
				return -1;

            if (Capabilities.manufacturer.indexOf("iOS") == -1)
                return -1;

            var ret:Object = _extContext.call("getCurrentVirtualMem");
            if (ret is Error)
                throw ret;
            else
                return ret ? ret as Number : 0;
        }

		/**
		 * @return  is requesting review available. Available on iOS only
		 */
		public function canRequestReview():Boolean {

			if (!isSupported)
				return false;

			if (Capabilities.manufacturer.indexOf("iOS") == -1)
				return false;

			return _extContext.call("canRequestReview");
		}

		/**
		 * Request AppStore review. Available on iOS only
		 */
		public function requestReview():void {

			if (!canRequestReview())
				return;

			_extContext.call("requestReview");
		}
		/**
		 * Generate haptic feedback - iOS only
		 */
		public function generateHapticFeedback(feedbackType:AirCapabilitiesHapticFeedbackType):void {

			if (Capabilities.manufacturer.indexOf("iOS") < 0)
				return;

			if(!feedbackType)
				return

			_extContext.call("generateHapticFeedback", feedbackType.value);
		}

		public function getNativeScale():Number
		{
			if (Capabilities.manufacturer.indexOf("iOS") < 0)
				return 1;
			return _extContext.call("getNativeScale") as Number;
		}

		// --------------------------------------------------------------------------------------//
		//																						 //
		// 									 	PRIVATE API										 //
		// 																						 //
		// --------------------------------------------------------------------------------------//

		static private const EXTENSION_ID:String = "com.freshplanet.ane.AirCapabilities";

		static private var _instance:AirCapabilities = null;

		private var _extContext:ExtensionContext = null;
		private var _doLogging:Boolean = false;
		private var _logger:ILogger;

		/**
		 * "private" singleton constructor
		 */
		public function AirCapabilities() {

			super();

			if (_instance)
				throw new Error("singleton class, use .instance");

			_extContext = ExtensionContext.createExtensionContext(EXTENSION_ID, null);
			_extContext.addEventListener(StatusEvent.STATUS, _handleStatusEvent);

			if (isSupported)
				_logger = new NativeLogger(_extContext);
			else
				_logger = new DefaultLogger();

			_instance = this;
		}

        private function _handleStatusEvent(event:StatusEvent):void {

            if (event.code == "log")
	            _doLogging && trace("[AirCapabilities] " + event.level);
            else if (event.code == "OPEN_URL")
                this.dispatchEvent(new AirCapabilitiesOpenURLEvent(AirCapabilitiesOpenURLEvent.OPEN_URL_SUCCESS, event.level));
            else if (event.code == AirCapabilitiesLowMemoryEvent.LOW_MEMORY_WARNING) {
	            var memory:Number = Number(event.level);
	            this.dispatchEvent(new AirCapabilitiesLowMemoryEvent(event.code, memory));
            }
            else
                this.dispatchEvent(event);
        }
	}
}

fix build issue

fix build issue


package aerys.minko.type
{
	import flash.events.IEventDispatcher;
	import flash.events.MouseEvent;
	import flash.ui.Mouse;

	public final class MouseManager
	{
		private var _x					: Number			= 0.;
		private var _y					: Number			= 0.;
		private var _deltaX				: Number			= 0.;
		private var _deltaY				: Number			= 0.;
		private var _deltaDistance		: Number			= 0.;

		private var _leftButtonDown		: Boolean			= false;
		private var _middleButtonDown	: Boolean			= false;
		private var _rightButtonDown	: Boolean			= false;

		private var _mouseDown			: Signal			= new Signal("mouseDown");
		private var _mouseUp			: Signal			= new Signal("mouseUp");

		private var _cursors			: Vector.<String>	= new <String>[];

		public function get x() : Number
		{
			return _x;
		}

		public function get y() : Number
		{
			return _y;
		}

		public function get deltaX() : Number
		{
			return _deltaX;
		}

		public function get deltaY() : Number
		{
			return _deltaY;
		}

		public function get deltaDistance() : Number
		{
			return _deltaDistance;
		}

		public function get leftButtonDown() : Boolean
		{
			return _leftButtonDown;
		}

		public function get middleButtonDown() : Boolean
		{
			return _middleButtonDown;
		}

		public function get rightButtonDown() : Boolean
		{
			return _rightButtonDown;
		}

		public function get cursor() : String
		{
			return Mouse.cursor;
		}

		public function get mouseDown() : Signal
		{
			return _mouseDown;
		}

		public function get mouseUp() : Signal
		{
			return _mouseUp;
		}

		public function bind(dispatcher : IEventDispatcher) : void
		{
			dispatcher.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
			dispatcher.addEventListener(MouseEvent.MOUSE_DOWN, mouseLeftDownHandler);
			dispatcher.addEventListener(MouseEvent.MOUSE_UP, mouseLeftUpHandler);

			if (MouseEvent.RIGHT_CLICK != null)
			{
				dispatcher.addEventListener(MouseEvent.RIGHT_MOUSE_DOWN, mouseRightDownHandler);
				dispatcher.addEventListener(MouseEvent.RIGHT_MOUSE_UP, mouseRightUpHandler);
			}

			if (MouseEvent.MIDDLE_CLICK != null)
			{
				dispatcher.addEventListener(MouseEvent.MIDDLE_MOUSE_DOWN, mouseMiddleDownHandler);
				dispatcher.addEventListener(MouseEvent.MIDDLE_MOUSE_UP, mouseMiddleUpHandler);
			}
		}

		public function unbind(dispatcher : IEventDispatcher) : void
		{
			dispatcher.removeEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
			dispatcher.removeEventListener(MouseEvent.MOUSE_DOWN, mouseLeftDownHandler);
			dispatcher.removeEventListener(MouseEvent.MOUSE_UP, mouseLeftUpHandler);

			if (MouseEvent.RIGHT_CLICK != null)
			{
				dispatcher.removeEventListener(MouseEvent.RIGHT_MOUSE_DOWN, mouseRightDownHandler);
				dispatcher.removeEventListener(MouseEvent.RIGHT_MOUSE_UP, mouseRightUpHandler);
			}

			if (MouseEvent.MIDDLE_CLICK != null)
			{
				dispatcher.removeEventListener(MouseEvent.MIDDLE_MOUSE_DOWN, mouseMiddleDownHandler);
				dispatcher.removeEventListener(MouseEvent.MIDDLE_MOUSE_UP, mouseMiddleUpHandler);
			}
		}

		private function mouseMoveHandler(event : MouseEvent) : void
		{
			var localX : Number = event.localX;
			var localY : Number = event.localY;

			_deltaX = localX - _x;
			_deltaY = localY - _y;
			_deltaDistance = Math.sqrt(_deltaX * deltaX + deltaY * deltaY);

			_x = event.localX;
			_y = event.localY;
		}

		private function mouseLeftDownHandler(event : MouseEvent) : void
		{
			_leftButtonDown = true;
			_mouseDown.execute();
		}

		private function mouseLeftUpHandler(event : MouseEvent) : void
		{
			_leftButtonDown = false;
			_mouseUp.execute();
		}

		private function mouseMiddleDownHandler(event : MouseEvent) : void
		{
			_middleButtonDown = true;
		}

		private function mouseMiddleUpHandler(event : MouseEvent) : void
		{
			_middleButtonDown = false;
		}

		private function mouseRightDownHandler(event : MouseEvent) : void
		{
			_rightButtonDown = true;
		}

		private function mouseRightUpHandler(event : MouseEvent) : void
		{
			_rightButtonDown = false;
		}

		public function pushCursor(cursor : String) : MouseManager
		{
			_cursors.push(Mouse.cursor);
			Mouse.cursor = cursor;

			return this;
		}

		public function popCursor() : MouseManager
		{
			Mouse.cursor = _cursors.pop();

			return this;
		}
	}
}

package aerys.minko.type
{
	import flash.events.IEventDispatcher;
	import flash.events.MouseEvent;
	import flash.ui.Mouse;

	public final class MouseManager
	{
		private var _x					: Number			= 0.;
		private var _y					: Number			= 0.;
		private var _deltaX				: Number			= 0.;
		private var _deltaY				: Number			= 0.;
		private var _deltaDistance		: Number			= 0.;

		private var _leftButtonDown		: Boolean			= false;
		private var _middleButtonDown	: Boolean			= false;
		private var _rightButtonDown	: Boolean			= false;

		private var _mouseDown			: Signal			= new Signal("mouseDown");
		private var _mouseUp			: Signal			= new Signal("mouseUp");

		private var _cursors			: Vector.<String>	= new <String>[];

		public function get x() : Number
		{
			return _x;
		}

		public function get y() : Number
		{
			return _y;
		}

		public function get deltaX() : Number
		{
			return _deltaX;
		}

		public function get deltaY() : Number
		{
			return _deltaY;
		}

		public function get deltaDistance() : Number
		{
			return _deltaDistance;
		}

		public function get leftButtonDown() : Boolean
		{
			return _leftButtonDown;
		}

		public function get middleButtonDown() : Boolean
		{
			return _middleButtonDown;
		}

		public function get rightButtonDown() : Boolean
		{
			return _rightButtonDown;
		}

		public function get cursor() : String
		{
			return Mouse.cursor;
		}

		public function get mouseDown() : Signal
		{
			return _mouseDown;
		}

		public function get mouseUp() : Signal
		{
			return _mouseUp;
		}

		public function bind(dispatcher : IEventDispatcher) : void
		{
			dispatcher.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
			dispatcher.addEventListener(MouseEvent.MOUSE_DOWN, mouseLeftDownHandler);
			dispatcher.addEventListener(MouseEvent.MOUSE_UP, mouseLeftUpHandler);

			if (MouseEvent.RIGHT_CLICK != null)
			{
				dispatcher.addEventListener(MouseEvent.RIGHT_MOUSE_DOWN, mouseRightDownHandler);
				dispatcher.addEventListener(MouseEvent.RIGHT_MOUSE_UP, mouseRightUpHandler);
			}

			if (MouseEvent.MIDDLE_CLICK != null)
			{
				dispatcher.addEventListener(MouseEvent.MIDDLE_MOUSE_DOWN, mouseMiddleDownHandler);
				dispatcher.addEventListener(MouseEvent.MIDDLE_MOUSE_UP, mouseMiddleUpHandler);
			}
		}

		public function unbind(dispatcher : IEventDispatcher) : void
		{
			dispatcher.removeEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
			dispatcher.removeEventListener(MouseEvent.MOUSE_DOWN, mouseLeftDownHandler);
			dispatcher.removeEventListener(MouseEvent.MOUSE_UP, mouseLeftUpHandler);

			if (MouseEvent.RIGHT_CLICK != null)
			{
				dispatcher.removeEventListener(MouseEvent.RIGHT_MOUSE_DOWN, mouseRightDownHandler);
				dispatcher.removeEventListener(MouseEvent.RIGHT_MOUSE_UP, mouseRightUpHandler);
			}

			if (MouseEvent.MIDDLE_CLICK != null)
			{
				dispatcher.removeEventListener(MouseEvent.MIDDLE_MOUSE_DOWN, mouseMiddleDownHandler);
				dispatcher.removeEventListener(MouseEvent.MIDDLE_MOUSE_UP, mouseMiddleUpHandler);
			}
		}

		private function mouseMoveHandler(event : MouseEvent) : void
		{
			var localX : Number = event.localX;
			var localY : Number = event.localY;

			_deltaX = localX - _x;
			_deltaY = localY - _y;
			_deltaDistance = Math.sqrt(_deltaX * deltaX + deltaY * deltaY);

			_x = event.localX;
			_y = event.localY;
		}

		private function mouseLeftDownHandler(event : MouseEvent) : void
		{
			_leftButtonDown = true;
			_mouseDown.execute();
		}

		private function mouseLeftUpHandler(event : MouseEvent) : void
		{
			_leftButtonDown = false;
			_mouseUp.execute();
		}

		private function mouseMiddleDownHandler(event : MouseEvent) : void
		{
			_middleButtonDown = true;
		}

		private function mouseMiddleUpHandler(event : MouseEvent) : void
		{
			_middleButtonDown = false;
		}

		private function mouseRightDownHandler(event : MouseEvent) : void
		{
			_rightButtonDown = true;
		}

		private function mouseRightUpHandler(event : MouseEvent) : void
		{
			_rightButtonDown = false;
		}

		public function pushCursor(cursor : String) : MouseManager
		{
			_cursors.push(Mouse.cursor);
			Mouse.cursor = cursor;

			return this;
		}

		public function popCursor() : MouseManager
		{
            if (_cursors.length)
    			Mouse.cursor = _cursors.pop();

			return this;
		}
	}
}

fix MouseManager.popCursor() to avoid null pointer exception when the cursor stack is empty


package away3d.materials.methods
{
	import away3d.arcane;
	import away3d.core.managers.Stage3DProxy;
	import away3d.materials.compilation.ShaderRegisterCache;
	import away3d.materials.compilation.ShaderRegisterElement;
	import away3d.textures.Texture2DBase;

	use namespace arcane;

	/**
	 * AlphaMaskMethod allows the use of an additional texture to specify the alpha value of the material. When used
	 * with the secondary uv set, it allows for a tiled main texture with independently varying alpha (useful for water
	 * etc).
	 */
	public class AlphaMaskMethod extends EffectMethodBase
	{
		private var _texture:Texture2DBase;
		private var _useSecondaryUV:Boolean;

		/**
		 * Creates a new AlphaMaskMethod object
		 * @param texture The texture to use as the alpha mask.
		 * @param useSecondaryUV Indicated whether or not the secondary uv set for the mask. This allows mapping alpha independently.
		 */
		public function AlphaMaskMethod(texture:Texture2DBase, useSecondaryUV:Boolean = false)
		{
			super();
			_texture = texture;
			_useSecondaryUV = useSecondaryUV;
		}

		/**
		 * @inheritDoc
		 */
		override arcane function initVO(vo:MethodVO):void
		{
			vo.needsSecondaryUV = _useSecondaryUV;
			vo.needsUV = !_useSecondaryUV;
		}

		/**
		 * Indicated whether or not the secondary uv set for the mask. This allows mapping alpha independently, for
		 * instance to tile the main texture and normal map while providing untiled alpha, for example to define the
		 * transparency over a tiled water surface.
		 */
		public function get useSecondaryUV():Boolean
		{
			return _useSecondaryUV;
		}

		public function set useSecondaryUV(value:Boolean):void
		{
			if (_useSecondaryUV == value)
				return;
			_useSecondaryUV = value;
			invalidateShaderProgram();
		}

		/**
		 * The texture to use as the alpha mask.
		 */
		public function get texture():Texture2DBase
		{
			return _texture;
		}

		public function set texture(value:Texture2DBase):void
		{
			_texture = value;
		}

		/**
		 * @inheritDoc
		 */
		arcane override function activate(vo:MethodVO, stage3DProxy:Stage3DProxy):void
		{
			stage3DProxy._context3D.setTextureAt(vo.texturesIndex, _texture.getTextureForStage3D(stage3DProxy));
		}

		/**
		 * @inheritDoc
		 */
		arcane override function getFragmentCode(vo:MethodVO, regCache:ShaderRegisterCache, targetReg:ShaderRegisterElement):String
		{
			var textureReg:ShaderRegisterElement = regCache.getFreeTextureReg();
			var temp:ShaderRegisterElement = regCache.getFreeFragmentVectorTemp();
			var uvReg:ShaderRegisterElement = _useSecondaryUV? _sharedRegisters.secondaryUVVarying : _sharedRegisters.uvVarying;
			vo.texturesIndex = textureReg.index;

			return getTex2DSampleCode(vo, temp, textureReg, _texture, uvReg) +
				"mul " + targetReg + ", " + targetReg + ", " + temp + ".x\n";
		}
	}
}

package away3d.materials.methods
{
	import away3d.arcane;
	import away3d.core.managers.Stage3DProxy;
	import away3d.materials.compilation.ShaderRegisterCache;
	import away3d.materials.compilation.ShaderRegisterElement;
	import away3d.textures.Texture2DBase;

	use namespace arcane;

	/**
	 * AlphaMaskMethod allows the use of an additional texture to specify the alpha value of the material. When used
	 * with the secondary uv set, it allows for a tiled main texture with independently varying alpha (useful for water
	 * etc).
	 */
	public class AlphaMaskMethod extends EffectMethodBase
	{
		private var _texture:Texture2DBase;
		private var _useSecondaryUV:Boolean;

		/**
		 * Creates a new AlphaMaskMethod object
		 * @param texture The texture to use as the alpha mask.
		 * @param useSecondaryUV Indicated whether or not the secondary uv set for the mask. This allows mapping alpha independently.
		 */
		public function AlphaMaskMethod(texture:Texture2DBase, useSecondaryUV:Boolean = false)
		{
			super();
			_texture = texture;
			_useSecondaryUV = useSecondaryUV;
		}

		/**
		 * @inheritDoc
		 */
		override arcane function initVO(vo:MethodVO):void
		{
			vo.needsSecondaryUV = _useSecondaryUV;
			vo.needsUV = !_useSecondaryUV;
		}

		/**
		 * Indicated whether or not the secondary uv set for the mask. This allows mapping alpha independently, for
		 * instance to tile the main texture and normal map while providing untiled alpha, for example to define the
		 * transparency over a tiled water surface.
		 */
		public function get useSecondaryUV():Boolean
		{
			return _useSecondaryUV;
		}

		public function set useSecondaryUV(value:Boolean):void
		{
			if (_useSecondaryUV == value)
				return;
			_useSecondaryUV = value;
			invalidateShaderProgram();
		}

		/**
		 * The texture to use as the alpha mask.
		 */
		public function get texture():Texture2DBase
		{
			return _texture;
		}

		public function set texture(value:Texture2DBase):void
		{
			_texture = value;
		}

		/**
		 * @inheritDoc
		 */
		arcane override function activate(vo:MethodVO, stage3DProxy:Stage3DProxy):void
		{
			stage3DProxy._context3D.setTextureAt(vo.texturesIndex, _texture.getTextureForStage3D(stage3DProxy));
		}

		/**
		 * @inheritDoc
		 */
		arcane override function getFragmentCode(vo:MethodVO, regCache:ShaderRegisterCache, targetReg:ShaderRegisterElement):String
		{
			var textureReg:ShaderRegisterElement = regCache.getFreeTextureReg();
			var temp:ShaderRegisterElement = regCache.getFreeFragmentVectorTemp();
			var uvReg:ShaderRegisterElement = _useSecondaryUV? _sharedRegisters.secondaryUVVarying : _sharedRegisters.uvVarying;
			vo.texturesIndex = textureReg.index;

			return getTex2DSampleCode(vo, temp, textureReg, _texture, uvReg) +
				"mul " + targetReg + ".w" + ", " + targetReg + ".w" + ", " + temp + ".x\n";
		}
	}
}

fix alpha mask shader

fix alpha mask shader


////////////////////////////////////////////////////////////////////////////////
//
//  tandem. explore your world.
//  Copyright (c) 2007–2008 Daniel Gasienica (daniel@gasienica.ch)
//
//  tandem is free software: you can redistribute it and/or modify
//  it under the terms of the GNU Affero General Public License as published by
//  the Free Software Foundation, either version 3 of the License, or
//  (at your option) any later version.
//
//  tandem is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU Affero General Public License for more details.
//
//  You should have received a copy of the GNU Affero General Public License
//  along with tandem. If not, see <http://www.gnu.org/licenses/>.
//
////////////////////////////////////////////////////////////////////////////////
package tandem.core
{

import caurina.transitions.Tweener;
import caurina.transitions.properties.ColorShortcuts;

import com.adobe.webapis.flickr.FlickrService;
import com.adobe.webapis.flickr.PagedPhotoList;
import com.adobe.webapis.flickr.User;
import com.adobe.webapis.flickr.events.FlickrResultEvent;

import flash.display.DisplayObject;
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.events.Event;
import flash.system.Security;

import tandem.events.TandemEvent;
import tandem.model.ApplicationModel;
import tandem.ui.GlobalNavigation;
import tandem.ui.GlobalNavigationComponent;
import tandem.ui.KeyboardNavigationButton;
import tandem.ui.KeyboardNavigationButtonComponent;
import tandem.ui.MemoryIndicator;
import tandem.ui.MemoryIndicatorComponent;
import tandem.ui.NotificationOverlay;
import tandem.ui.NotificationOverlayComponent;
import tandem.ui.Timeline;
import tandem.ui.ZoomNavigator;
import tandem.ui.ZoomViewport;
import tandem.ui.views.StreamView;

public class Application extends Sprite
{
    //--------------------------------------------------------------------------
    //
    //  Constructor
    //
    //--------------------------------------------------------------------------
    /**
    * Constructor.
    */
    public function Application()
    {
        addEventListener( Event.ADDED_TO_STAGE, addedToStageHandler, false, 0, true )
    }

    //--------------------------------------------------------------------------
    //
    //  Class Constants
    //
    //--------------------------------------------------------------------------

    private const DEFAULT_USER_ADDRESS : String = "gasi"
    private const DEFAULT_USER_ID : String = "72389028@N00"
    private const DEFAULT_MINIMUM_ZOOM : Number = 0.25//0.5
    private const DEFAULT_MAXIMUM_ZOOM : Number = 180
    private const NUM_FARMS = 10

    //--------------------------------------------------------------------------
    //
    //  Children
    //
    //--------------------------------------------------------------------------

    private var globalNavigation : GlobalNavigation
    private var memoryIndicator : MemoryIndicator
    private var notificationOverlay : NotificationOverlay
    private var keyboardNavigationButton : KeyboardNavigationButton
    private var timeline : Timeline

    private var viewport : ZoomViewport
    private var navigator : ZoomNavigator

    private var view : DisplayObject
    private var initialized : Boolean = false

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

    private var model : ApplicationModel = ApplicationModel.getInstance()
    private var completed : Boolean = false

    private var numPhotos : int = 363
    private var page : int = 1
    private var pageSize : int = 500
    private var extras : String = "date_taken, original_format"

    //--------------------------------------------------------------------------
    //
    //  Event Handler: Stage
    //
    //--------------------------------------------------------------------------

    private function addedToStageHandler( event : Event ) : void
    {
        // Code in constructor is interpreted by
        // AVM, therefore move processing-intensive code
        // outside, so it can be processed by the JIT compiler
        initialize()
    }

    //--------------------------------------------------------------------------
    //
    //  Methods: Initialization
    //
    //--------------------------------------------------------------------------

    private function initialize() : void
    {
        stage.align = StageAlign.TOP_LEFT
        stage.scaleMode = StageScaleMode.NO_SCALE

        initializeLibraries()
        initializeSecurity()
        registerListeners()
        createChildren()
        updateDisplayList()

        model.service = new FlickrService( model.API_KEY )
        model.service.addEventListener( FlickrResultEvent.PEOPLE_GET_PUBLIC_PHOTOS,
                                        getPublicPhotosHandler )
    }

    private function initializeSecurity() : void
    {
        // TODO: Smells bad… =(
        Security.loadPolicyFile( "http://static.flickr.com/crossdomain.xml" )

        for (var i:int = 0; i < NUM_FARMS; i++)
        {
            Security.loadPolicyFile("http://farm" + i + ".static.flickr.com/crossdomain.xml")
        }

        Security.loadPolicyFile( "http://l.yimg.com/crossdomain.xml" )
    }

    private function initializeLibraries() : void
    {
        // Tweener
        ColorShortcuts.init()
    }

    private function registerListeners() : void
    {
        stage.addEventListener( Event.RESIZE, resizeHandler )
        addEventListener( TandemEvent.APPLICATION_COMPLETE, applicationCompleteHandler )

        SWFAddress.addEventListener( SWFAddressEvent.CHANGE, swfAddressChangeHandler )
    }

    //--------------------------------------------------------------------------
    //
    //  User Interface
    //
    //--------------------------------------------------------------------------

    private function createChildren() : void
    {
        createTimeline()
        createGlobalNavigation()
        createMemoryIndicator()
        createNotificationOverlay()
        createKeyboardNavigationButton()
    }

    private function createViewport() : void
    {
        completed = false
        model.photos = []

        if( view )
            removeChild( view )

        if( navigator )
            removeChild( navigator )

        // view
        initialized = false
        view = new StreamView()
        view.alpha = 0

        // container
        viewport = new ZoomViewport()
        viewport.minZoom = DEFAULT_MINIMUM_ZOOM
        viewport.maxZoom = DEFAULT_MAXIMUM_ZOOM
        viewport.content = view

        // navigator
        navigator = new ZoomNavigator()
        navigator.model = viewport
        navigator.alpha = 0

        // add children to display list
        addChildAt( viewport, 0 )
        addChildAt( view, 1 )
        addChildAt( navigator, 2 )

        // fade in notification overlay
        Tweener.addTween(
                            notificationOverlay,
                            {
                                alpha: 1,
                                time: 1
                            }
                        )

        // call service
        model.service.people.getPublicPhotos( model.user.nsid, extras,
                                              Math.min( pageSize, numPhotos ),
                                              page )

        // initial layout
        updateDisplayList()
    }

    private function createTimeline() : void
    {
        //timeline = new TimelineComponent()
        //addChild( timeline )
    }

    private function createGlobalNavigation() : void
    {
        globalNavigation = new GlobalNavigationComponent()
        addChild( globalNavigation )
    }

    private function createMemoryIndicator() : void
    {
        memoryIndicator = new MemoryIndicatorComponent()
        addChild( memoryIndicator )
    }

    private function createNotificationOverlay() : void
    {
        notificationOverlay = new NotificationOverlayComponent()
        notificationOverlay.alpha = 0
        addChild( notificationOverlay )

        // fade in notification overlay
        Tweener.addTween(
                            notificationOverlay,
                            {
                                alpha: 1,
                                time: 1.5,
                                delay: 2
                            }
                        )
    }

    private function createKeyboardNavigationButton() : void
    {
        keyboardNavigationButton = new KeyboardNavigationButtonComponent()
        keyboardNavigationButton.alpha = 0
        addChild( keyboardNavigationButton )

        Tweener.addTween(
                            keyboardNavigationButton,
                            {
                                alpha: 1,
                                time: 1.5,
                                delay: 1
                            }
                        )
    }

    //--------------------------------------------------------------------------
    //
    //  SWFAdress
    //
    //--------------------------------------------------------------------------

    private function swfAddressChangeHandler( event : SWFAddressEvent ) : void
    {
        var user : String
        var action : String = SWFAddress.getPathNames()[ 0 ]
        var flickrNSIDPattern : RegExp = /[0-9]*@N[0-9]*/

        if( action == "photos" )
        {
            // Long URL, e.g. http://flickr.com/photos/gasi
            // or http://flickr.com/photos/72389028@N00
            user = SWFAddress.getPathNames()[ 1 ]
        }
        else
        {
            // Short URL, e.g. http://flickr.com/gasi
            user = SWFAddress.getPathNames()[ 0 ]
        }

        if( user == null )
        {
            // Default user
            SWFAddress.setValue( "photos/" + DEFAULT_USER_ADDRESS + "/" )
        }
        else if( flickrNSIDPattern.test( user ) )
        {
            // Look up Flickr NSID, e.g. 72389028@N00
            model.service.people.getInfo( user )
            model.service.addEventListener( FlickrResultEvent.PEOPLE_GET_INFO, getInfoHandler )
        }
        else
        {
            // Look up Flickr URL
            model.service.urls.lookupUser( "http://flickr.com/photos/" + user + "/" )
            model.service.addEventListener( FlickrResultEvent.URLS_LOOKUP_USER, lookupUserHandler )
        }
    }

    //--------------------------------------------------------------------------
    //
    //  Event Handlers: Application
    //
    //--------------------------------------------------------------------------

    private function resizeHandler( event : Event ) : void
    {
        updateDisplayList()
    }

    private function applicationCompleteHandler( event : Event ) : void
    {
        // fade in view
        Tweener.addTween(
                             view,
                             {
                                alpha: 1,
                                time: 5
                             }
                        )

        // fade in navigator
        Tweener.addTween(
                           navigator,
                           {
                               alpha: 1,
                               time: 2,
                               delay: 2
                           }
                        )

        // fade out notification
        Tweener.addTween(
                           notificationOverlay,
                           {
                               alpha: 0,
                               time: 0.8,
                               delay: 1.8
                           }
                        )

       updateDisplayList()
    }

    //--------------------------------------------------------------------------
    //
    //  Event Handlers: Service
    //
    //--------------------------------------------------------------------------

    private function getPublicPhotosHandler( event : FlickrResultEvent ) : void
    {
        if( event.success )
        {
            var result : PagedPhotoList = PagedPhotoList( event.data.photos )

            // add result data to view
            if( view is StreamView )
            {
                result.photos.forEach(
                                            function( item : *,
                                                     ...ignored ) : void
                                            {
                                                model.photos.push( item )
                                                StreamView( view ).addItem( item )
                                            }
                                     )

            }

            // we're done
            if( model.photos.length >= Math.min( numPhotos, result.total ) && !completed )
            {
                completed = true
            }

            // fetch more data
            if( result.page < result.pages && !completed )
            {
                page++
                model.service.people.getPublicPhotos( model.user.nsid, extras, pageSize, page )
            }

            if( !initialized )
            {
                initialized = true
                dispatchEvent( new TandemEvent( TandemEvent.APPLICATION_COMPLETE ) )
            }
        }
    }

    private function lookupUserHandler( event : FlickrResultEvent ) : void
    {
        if( event.success )
        {
            model.user = User( event.data.user )
            createViewport()
            SWFAddress.setTitle( "tandem — " + model.user.username + " (" + model.user.nsid + ")" )
        }
        else
        {
            // Default
            SWFAddress.setValue( "photos/" + DEFAULT_USER_ADDRESS + "/" )
        }
    }

    private function getInfoHandler( event : FlickrResultEvent ) : void
    {
        if( event.success )
        {
            model.user = User( event.data.user )
            createViewport()
            SWFAddress.setTitle( "tandem — " + model.user.username + " (" + model.user.nsid + ")" )
        }
        else
        {
            // Default
            SWFAddress.setValue( "photos/" + DEFAULT_USER_ADDRESS + "/" )
        }
    }

    //--------------------------------------------------------------------------
    //
    //  Methods: Layout
    //
    //--------------------------------------------------------------------------

    private function updateDisplayList() : void
    {
        // Navigation
        if( globalNavigation )
        {
            globalNavigation.x = 0
            globalNavigation.y = 0
        }

        // Viewport
        if( viewport )
        {
            viewport.x = 0
            viewport.y = 0
            viewport.width = stage.stageWidth
            viewport.height = stage.stageHeight
        }

        // Navigator
        if( navigator )
        {
            navigator.x = stage.stageWidth - navigator.width - 12
            navigator.y = globalNavigation ? globalNavigation.height + 12 : 12
        }

        // Timeline
        if( timeline )
        {
            timeline.width = stage.stageWidth
            timeline.y = stage.stageHeight - timeline.height
        }

        // Memory Indicator
        if( memoryIndicator )
        {
            memoryIndicator.x = stage.stageWidth - memoryIndicator.width - 10
            memoryIndicator.y = stage.stageHeight - memoryIndicator.height - 10
        }

        // Notification Overlay
        if( notificationOverlay )
        {
            notificationOverlay.x = ( stage.stageWidth - notificationOverlay.width ) / 2
            notificationOverlay.y = ( stage.stageHeight - notificationOverlay.height ) / 2
        }

        // Keyboard Navigation Button
        if( keyboardNavigationButton )
        {
            keyboardNavigationButton.x = ( stage.stageWidth - keyboardNavigationButton.width ) / 2
            keyboardNavigationButton.y = stage.stageHeight - keyboardNavigationButton.height - 10
        }
    }
}

}

////////////////////////////////////////////////////////////////////////////////
//
//  tandem. explore your world.
//  Copyright (c) 2007–2008 Daniel Gasienica (daniel@gasienica.ch)
//
//  tandem is free software: you can redistribute it and/or modify
//  it under the terms of the GNU Affero General Public License as published by
//  the Free Software Foundation, either version 3 of the License, or
//  (at your option) any later version.
//
//  tandem is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU Affero General Public License for more details.
//
//  You should have received a copy of the GNU Affero General Public License
//  along with tandem. If not, see <http://www.gnu.org/licenses/>.
//
////////////////////////////////////////////////////////////////////////////////
package tandem.core
{

import caurina.transitions.Tweener;
import caurina.transitions.properties.ColorShortcuts;

import com.adobe.webapis.flickr.FlickrService;
import com.adobe.webapis.flickr.PagedPhotoList;
import com.adobe.webapis.flickr.User;
import com.adobe.webapis.flickr.events.FlickrResultEvent;

import flash.display.DisplayObject;
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.events.Event;
import flash.system.Security;

import tandem.events.TandemEvent;
import tandem.model.ApplicationModel;
import tandem.ui.GlobalNavigation;
import tandem.ui.GlobalNavigationComponent;
import tandem.ui.KeyboardNavigationButton;
import tandem.ui.KeyboardNavigationButtonComponent;
import tandem.ui.MemoryIndicator;
import tandem.ui.MemoryIndicatorComponent;
import tandem.ui.NotificationOverlay;
import tandem.ui.NotificationOverlayComponent;
import tandem.ui.Timeline;
import tandem.ui.ZoomNavigator;
import tandem.ui.ZoomViewport;
import tandem.ui.views.StreamView;

public class Application extends Sprite
{
    //--------------------------------------------------------------------------
    //
    //  Constructor
    //
    //--------------------------------------------------------------------------
    /**
    * Constructor.
    */
    public function Application()
    {
        addEventListener( Event.ADDED_TO_STAGE, addedToStageHandler, false, 0, true )
    }

    //--------------------------------------------------------------------------
    //
    //  Class Constants
    //
    //--------------------------------------------------------------------------

    private const DEFAULT_USER_ADDRESS : String = "gasi"
    private const DEFAULT_USER_ID : String = "72389028@N00"
    private const DEFAULT_MINIMUM_ZOOM : Number = 0.25//0.5
    private const DEFAULT_MAXIMUM_ZOOM : Number = 180
    private const NUM_FARMS:int = 10

    //--------------------------------------------------------------------------
    //
    //  Children
    //
    //--------------------------------------------------------------------------

    private var globalNavigation : GlobalNavigation
    private var memoryIndicator : MemoryIndicator
    private var notificationOverlay : NotificationOverlay
    private var keyboardNavigationButton : KeyboardNavigationButton
    private var timeline : Timeline

    private var viewport : ZoomViewport
    private var navigator : ZoomNavigator

    private var view : DisplayObject
    private var initialized : Boolean = false

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

    private var model : ApplicationModel = ApplicationModel.getInstance()
    private var completed : Boolean = false

    private var numPhotos : int = 363
    private var page : int = 1
    private var pageSize : int = 500
    private var extras : String = "date_taken, original_format"

    //--------------------------------------------------------------------------
    //
    //  Event Handler: Stage
    //
    //--------------------------------------------------------------------------

    private function addedToStageHandler( event : Event ) : void
    {
        // Code in constructor is interpreted by
        // AVM, therefore move processing-intensive code
        // outside, so it can be processed by the JIT compiler
        initialize()
    }

    //--------------------------------------------------------------------------
    //
    //  Methods: Initialization
    //
    //--------------------------------------------------------------------------

    private function initialize() : void
    {
        stage.align = StageAlign.TOP_LEFT
        stage.scaleMode = StageScaleMode.NO_SCALE

        initializeLibraries()
        initializeSecurity()
        registerListeners()
        createChildren()
        updateDisplayList()

        model.service = new FlickrService( model.API_KEY )
        model.service.addEventListener( FlickrResultEvent.PEOPLE_GET_PUBLIC_PHOTOS,
                                        getPublicPhotosHandler )
    }

    private function initializeSecurity() : void
    {
        // TODO: Smells bad… =(
        Security.loadPolicyFile( "http://static.flickr.com/crossdomain.xml" )

        for (var i:int = 0; i < NUM_FARMS; i++)
        {
            Security.loadPolicyFile("http://farm" + i + ".static.flickr.com/crossdomain.xml")
        }

        Security.loadPolicyFile( "http://l.yimg.com/crossdomain.xml" )
    }

    private function initializeLibraries() : void
    {
        // Tweener
        ColorShortcuts.init()
    }

    private function registerListeners() : void
    {
        stage.addEventListener( Event.RESIZE, resizeHandler )
        addEventListener( TandemEvent.APPLICATION_COMPLETE, applicationCompleteHandler )

        SWFAddress.addEventListener( SWFAddressEvent.CHANGE, swfAddressChangeHandler )
    }

    //--------------------------------------------------------------------------
    //
    //  User Interface
    //
    //--------------------------------------------------------------------------

    private function createChildren() : void
    {
        createTimeline()
        createGlobalNavigation()
        createMemoryIndicator()
        createNotificationOverlay()
        createKeyboardNavigationButton()
    }

    private function createViewport() : void
    {
        completed = false
        model.photos = []

        if( view )
            removeChild( view )

        if( navigator )
            removeChild( navigator )

        // view
        initialized = false
        view = new StreamView()
        view.alpha = 0

        // container
        viewport = new ZoomViewport()
        viewport.minZoom = DEFAULT_MINIMUM_ZOOM
        viewport.maxZoom = DEFAULT_MAXIMUM_ZOOM
        viewport.content = view

        // navigator
        navigator = new ZoomNavigator()
        navigator.model = viewport
        navigator.alpha = 0

        // add children to display list
        addChildAt( viewport, 0 )
        addChildAt( view, 1 )
        addChildAt( navigator, 2 )

        // fade in notification overlay
        Tweener.addTween(
                            notificationOverlay,
                            {
                                alpha: 1,
                                time: 1
                            }
                        )

        // call service
        model.service.people.getPublicPhotos( model.user.nsid, extras,
                                              Math.min( pageSize, numPhotos ),
                                              page )

        // initial layout
        updateDisplayList()
    }

    private function createTimeline() : void
    {
        //timeline = new TimelineComponent()
        //addChild( timeline )
    }

    private function createGlobalNavigation() : void
    {
        globalNavigation = new GlobalNavigationComponent()
        addChild( globalNavigation )
    }

    private function createMemoryIndicator() : void
    {
        memoryIndicator = new MemoryIndicatorComponent()
        addChild( memoryIndicator )
    }

    private function createNotificationOverlay() : void
    {
        notificationOverlay = new NotificationOverlayComponent()
        notificationOverlay.alpha = 0
        addChild( notificationOverlay )

        // fade in notification overlay
        Tweener.addTween(
                            notificationOverlay,
                            {
                                alpha: 1,
                                time: 1.5,
                                delay: 2
                            }
                        )
    }

    private function createKeyboardNavigationButton() : void
    {
        keyboardNavigationButton = new KeyboardNavigationButtonComponent()
        keyboardNavigationButton.alpha = 0
        addChild( keyboardNavigationButton )

        Tweener.addTween(
                            keyboardNavigationButton,
                            {
                                alpha: 1,
                                time: 1.5,
                                delay: 1
                            }
                        )
    }

    //--------------------------------------------------------------------------
    //
    //  SWFAdress
    //
    //--------------------------------------------------------------------------

    private function swfAddressChangeHandler( event : SWFAddressEvent ) : void
    {
        var user : String
        var action : String = SWFAddress.getPathNames()[ 0 ]
        var flickrNSIDPattern : RegExp = /[0-9]*@N[0-9]*/

        if( action == "photos" )
        {
            // Long URL, e.g. http://flickr.com/photos/gasi
            // or http://flickr.com/photos/72389028@N00
            user = SWFAddress.getPathNames()[ 1 ]
        }
        else
        {
            // Short URL, e.g. http://flickr.com/gasi
            user = SWFAddress.getPathNames()[ 0 ]
        }

        if( user == null )
        {
            // Default user
            SWFAddress.setValue( "photos/" + DEFAULT_USER_ADDRESS + "/" )
        }
        else if( flickrNSIDPattern.test( user ) )
        {
            // Look up Flickr NSID, e.g. 72389028@N00
            model.service.people.getInfo( user )
            model.service.addEventListener( FlickrResultEvent.PEOPLE_GET_INFO, getInfoHandler )
        }
        else
        {
            // Look up Flickr URL
            model.service.urls.lookupUser( "http://flickr.com/photos/" + user + "/" )
            model.service.addEventListener( FlickrResultEvent.URLS_LOOKUP_USER, lookupUserHandler )
        }
    }

    //--------------------------------------------------------------------------
    //
    //  Event Handlers: Application
    //
    //--------------------------------------------------------------------------

    private function resizeHandler( event : Event ) : void
    {
        updateDisplayList()
    }

    private function applicationCompleteHandler( event : Event ) : void
    {
        // fade in view
        Tweener.addTween(
                             view,
                             {
                                alpha: 1,
                                time: 5
                             }
                        )

        // fade in navigator
        Tweener.addTween(
                           navigator,
                           {
                               alpha: 1,
                               time: 2,
                               delay: 2
                           }
                        )

        // fade out notification
        Tweener.addTween(
                           notificationOverlay,
                           {
                               alpha: 0,
                               time: 0.8,
                               delay: 1.8
                           }
                        )

       updateDisplayList()
    }

    //--------------------------------------------------------------------------
    //
    //  Event Handlers: Service
    //
    //--------------------------------------------------------------------------

    private function getPublicPhotosHandler( event : FlickrResultEvent ) : void
    {
        if( event.success )
        {
            var result : PagedPhotoList = PagedPhotoList( event.data.photos )

            // add result data to view
            if( view is StreamView )
            {
                result.photos.forEach(
                                            function( item : *,
                                                     ...ignored ) : void
                                            {
                                                model.photos.push( item )
                                                StreamView( view ).addItem( item )
                                            }
                                     )

            }

            // we're done
            if( model.photos.length >= Math.min( numPhotos, result.total ) && !completed )
            {
                completed = true
            }

            // fetch more data
            if( result.page < result.pages && !completed )
            {
                page++
                model.service.people.getPublicPhotos( model.user.nsid, extras, pageSize, page )
            }

            if( !initialized )
            {
                initialized = true
                dispatchEvent( new TandemEvent( TandemEvent.APPLICATION_COMPLETE ) )
            }
        }
    }

    private function lookupUserHandler( event : FlickrResultEvent ) : void
    {
        if( event.success )
        {
            model.user = User( event.data.user )
            createViewport()
            SWFAddress.setTitle( "tandem — " + model.user.username + " (" + model.user.nsid + ")" )
        }
        else
        {
            // Default
            SWFAddress.setValue( "photos/" + DEFAULT_USER_ADDRESS + "/" )
        }
    }

    private function getInfoHandler( event : FlickrResultEvent ) : void
    {
        if( event.success )
        {
            model.user = User( event.data.user )
            createViewport()
            SWFAddress.setTitle( "tandem — " + model.user.username + " (" + model.user.nsid + ")" )
        }
        else
        {
            // Default
            SWFAddress.setValue( "photos/" + DEFAULT_USER_ADDRESS + "/" )
        }
    }

    //--------------------------------------------------------------------------
    //
    //  Methods: Layout
    //
    //--------------------------------------------------------------------------

    private function updateDisplayList() : void
    {
        // Navigation
        if( globalNavigation )
        {
            globalNavigation.x = 0
            globalNavigation.y = 0
        }

        // Viewport
        if( viewport )
        {
            viewport.x = 0
            viewport.y = 0
            viewport.width = stage.stageWidth
            viewport.height = stage.stageHeight
        }

        // Navigator
        if( navigator )
        {
            navigator.x = stage.stageWidth - navigator.width - 12
            navigator.y = globalNavigation ? globalNavigation.height + 12 : 12
        }

        // Timeline
        if( timeline )
        {
            timeline.width = stage.stageWidth
            timeline.y = stage.stageHeight - timeline.height
        }

        // Memory Indicator
        if( memoryIndicator )
        {
            memoryIndicator.x = stage.stageWidth - memoryIndicator.width - 10
            memoryIndicator.y = stage.stageHeight - memoryIndicator.height - 10
        }

        // Notification Overlay
        if( notificationOverlay )
        {
            notificationOverlay.x = ( stage.stageWidth - notificationOverlay.width ) / 2
            notificationOverlay.y = ( stage.stageHeight - notificationOverlay.height ) / 2
        }

        // Keyboard Navigation Button
        if( keyboardNavigationButton )
        {
            keyboardNavigationButton.x = ( stage.stageWidth - keyboardNavigationButton.width ) / 2
            keyboardNavigationButton.y = stage.stageHeight - keyboardNavigationButton.height - 10
        }
    }
}

}

Add missing type.

Add missing type.


/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.hola {
    import flash.events.*;
    import flash.external.ExternalInterface;
    import org.hola.ZExternalInterface;
    import flash.net.URLRequest;
    import flash.net.URLStream;
    import flash.net.URLRequestHeader;
    import flash.net.URLRequestMethod;
    import flash.utils.ByteArray;
    import flash.utils.getTimer;
    import flash.utils.Timer;
    import org.hola.ZErr;
    import org.hola.Base64;
    import org.hola.WorkerUtils;
    import org.hola.HEvent;
    import org.hola.HSettings;

    public dynamic class JSURLStream extends URLStream {
        private static var js_api_inited : Boolean = false;
        private static var req_count : Number = 0;
        private static var reqs : Object = {};
        private var _connected : Boolean;
        private var _resource : ByteArray = new ByteArray();
        private var _curr_data : Object;
        private var _hola_managed : Boolean = false;
        private var _req_id : String;
        private var _self_load : Boolean = false;
        private var _events : Object;
        private var _size : Number;

        public function JSURLStream(){
            _hola_managed = HSettings.enabled && ZExternalInterface.avail();
            addEventListener(Event.OPEN, onopen);
            super();
            if (!_hola_managed || js_api_inited)
                return;
            // Connect calls to JS.
            ZErr.log('JSURLStream init api');
            ExternalInterface.marshallExceptions = true;
            ExternalInterface.addCallback('hola_onFragmentData',
                hola_onFragmentData);
            js_api_inited = true;
        }

        protected function _trigger(cb : String, data : Object) : void {
            if (!_hola_managed && !_self_load)
            {
                // XXX arik: need ZErr.throw
                ZErr.log('invalid trigger');
                throw new Error('invalid trigger');
            }
            ExternalInterface.call('window.hola_'+cb,
                {objectID: ExternalInterface.objectID, data: data});
        }

        override public function get connected() : Boolean {
            if (!_hola_managed)
                return super.connected;
            return _connected;
        }

        override public function get bytesAvailable() : uint {
            if (!_hola_managed)
                return super.bytesAvailable;
            return _resource.bytesAvailable;
        }

        override public function readByte() : int {
            if (!_hola_managed)
                return super.readByte();
            return _resource.readByte();
        }

        override public function readUnsignedShort() : uint {
            if (!_hola_managed)
                return super.readUnsignedShort();
            return _resource.readUnsignedShort();
        }

        override public function readBytes(bytes : ByteArray,
            offset : uint = 0, length : uint = 0) : void
        {
            if (!_hola_managed)
                return super.readBytes(bytes, offset, length);
            _resource.readBytes(bytes, offset, length);
        }

        override public function close() : void {
            if (_hola_managed || _self_load)
            {
                if (reqs[_req_id])
                    _trigger('abortFragment', {req_id: _req_id});
                WorkerUtils.removeEventListener(HEvent.WORKER_MESSAGE, onmsg);
            }
            if (super.connected)
                super.close();
            _connected = false;
        }

        override public function load(request : URLRequest) : void {
            // XXX arik: cleanup previous if hola mode changed
            _hola_managed = HSettings.enabled && ZExternalInterface.avail();
            req_count++;
            _req_id = 'req'+req_count;
            if (!_hola_managed)
                return super.load(request);
            WorkerUtils.addEventListener(HEvent.WORKER_MESSAGE, onmsg);
            reqs[_req_id] = this;
            _resource = new ByteArray();
            _trigger('requestFragment', {url: request.url, req_id: _req_id});
            this.dispatchEvent(new Event(Event.OPEN));
        }

        private function onopen(e : Event) : void { _connected = true; }

        private function onerror(e : ErrorEvent) : void {
            _delete();
            if (!_events.error)
                return;
            _trigger('onRequestEvent', {req_id: _req_id, event: 'error',
                error: e.text, text: e.toString()});
        }

        private function onprogress(e : ProgressEvent) : void {
            _size = e.bytesTotal;
            if (!_events.progress)
                return;
            _trigger('onRequestEvent', {req_id: _req_id, event: 'progress',
                loaded: e.bytesLoaded, total: e.bytesTotal,
                text: e.toString()});
        }

        private function onstatus(e : HTTPStatusEvent) : void {
            if (!_events.status)
                return;
            // XXX bahaa: get redirected/responseURL/responseHeaders
            _trigger('onRequestEvent', {req_id: _req_id, event: 'status',
                status: e.status, text: e.toString()});
        }

        private function oncomplete(e : Event) : void {
            _delete();
            if (!_events.complete)
                return;
            _trigger('onRequestEvent', {req_id: _req_id, event: 'complete',
                size: _size, text: e.toString()});
        }

        private function decode(str : String) : void {
            if (!str)
                return on_decoded_data(null);
            if (!HSettings.use_worker)
                return on_decoded_data(Base64.decode_str(str));
            var data : ByteArray = new ByteArray();
            data.shareable = true;
            data.writeUTFBytes(str);
            WorkerUtils.send({cmd: "b64.decode", id: _req_id});
            WorkerUtils.send(data);
        }

        private function onmsg(e : HEvent) : void {
            var msg : Object = e.data;
            if (!_req_id || _req_id!=msg.id || msg.cmd!="b64.decode")
                return;
            on_decoded_data(WorkerUtils.recv());
        }

        private function on_decoded_data(data : ByteArray) : void {
            if (data)
            {
                data.position = 0;
                if (_resource)
                {
                    var prev : uint = _resource.position;
                    data.readBytes(_resource, _resource.length);
                    _resource.position = prev;
                }
                else
                    _resource = data;
                // XXX arik: get finalLength from js
                var finalLength : uint = _resource.length;
                dispatchEvent(new ProgressEvent( ProgressEvent.PROGRESS, false,
                    false, _resource.length, finalLength));
            }
            // XXX arik: dispatch httpStatus/httpResponseStatus
            if (_curr_data.status)
                resourceLoadingSuccess();
        }

        private function self_load(o : Object) : void {
            _self_load = true;
            _hola_managed = false;
            _events = o.events||{};
            addEventListener(IOErrorEvent.IO_ERROR, onerror);
            addEventListener(SecurityErrorEvent.SECURITY_ERROR, onerror);
            addEventListener(ProgressEvent.PROGRESS, onprogress);
            addEventListener(HTTPStatusEvent.HTTP_STATUS, onstatus);
            addEventListener(Event.COMPLETE, oncomplete);
            var req : URLRequest = new URLRequest(o.url);
            req.method = o.method=="POST" ? URLRequestMethod.POST :
                URLRequestMethod.GET;
            // this doesn't seem to work. simply ignored
            var headers : Object = o.headers||{};
            for (var k : String in headers)
                req.requestHeaders.push(new URLRequestHeader(k, headers[k]));
            super.load(req);
        }

        private function on_fragment_data(o : Object) : void {
            _curr_data = o;
            if (o.self_load)
                return self_load(o);
            if (o.error)
                return resourceLoadingError();
            decode(o.data);
        }

        protected static function hola_onFragmentData(o : Object) : void{
            var stream : JSURLStream;
            try {
                if (!(stream = reqs[o.req_id]))
                    throw new Error('req_id not found '+o.req_id);
                stream.on_fragment_data(o);
            } catch(err : Error){
                ZErr.log('Error in hola_onFragmentData', ''+err,
                    ''+err.getStackTrace());
                if (stream)
                    stream.resourceLoadingError();
                throw err;
            }
        }

        private function _delete() : void {
            delete reqs[_req_id];
        }

        protected function resourceLoadingError() : void {
            _delete();
            dispatchEvent(new IOErrorEvent(IOErrorEvent.IO_ERROR));
        }

        protected function resourceLoadingSuccess() : void {
            _delete();
            dispatchEvent(new Event(Event.COMPLETE));
        }
    }
}

/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.hola {
    import flash.events.*;
    import flash.external.ExternalInterface;
    import org.hola.ZExternalInterface;
    import flash.net.URLRequest;
    import flash.net.URLStream;
    import flash.net.URLRequestHeader;
    import flash.net.URLRequestMethod;
    import flash.utils.ByteArray;
    import flash.utils.getTimer;
    import flash.utils.Timer;
    import org.hola.ZErr;
    import org.hola.Base64;
    import org.hola.WorkerUtils;
    import org.hola.HEvent;
    import org.hola.HSettings;

    public dynamic class JSURLStream extends URLStream {
        private static var js_api_inited : Boolean = false;
        private static var req_count : Number = 0;
        private static var reqs : Object = {};
        private var _connected : Boolean;
        private var _resource : ByteArray = new ByteArray();
        private var _curr_data : Object;
        private var _hola_managed : Boolean = false;
        private var _req_id : String;
        private var _self_load : Boolean = false;
        private var _events : Object;
        private var _size : Number;

        public function JSURLStream(){
            _hola_managed = HSettings.enabled && ZExternalInterface.avail();
            addEventListener(Event.OPEN, onopen);
            super();
            if (!_hola_managed || js_api_inited)
                return;
            // Connect calls to JS.
            ZErr.log('JSURLStream init api');
            ExternalInterface.marshallExceptions = true;
            ExternalInterface.addCallback('hola_onFragmentData',
                hola_onFragmentData);
            js_api_inited = true;
        }

        protected function _trigger(cb : String, data : Object) : void {
            if (!_hola_managed && !_self_load)
            {
                // XXX arik: need ZErr.throw
                ZErr.log('invalid trigger');
                throw new Error('invalid trigger');
            }
            ExternalInterface.call('window.hola_'+cb,
                {objectID: ExternalInterface.objectID, data: data});
        }

        override public function get connected() : Boolean {
            if (!_hola_managed)
                return super.connected;
            return _connected;
        }

        override public function get bytesAvailable() : uint {
            if (!_hola_managed)
                return super.bytesAvailable;
            return _resource.bytesAvailable;
        }

        override public function readByte() : int {
            if (!_hola_managed)
                return super.readByte();
            return _resource.readByte();
        }

        override public function readUnsignedShort() : uint {
            if (!_hola_managed)
                return super.readUnsignedShort();
            return _resource.readUnsignedShort();
        }

        override public function readBytes(bytes : ByteArray,
            offset : uint = 0, length : uint = 0) : void
        {
            if (!_hola_managed)
                return super.readBytes(bytes, offset, length);
            _resource.readBytes(bytes, offset, length);
        }

        override public function close() : void {
            if (_hola_managed || _self_load)
            {
                if (reqs[_req_id])
                {
                    delete reqs[_req_id];
                    _trigger('abortFragment', {req_id: _req_id});
                }
                WorkerUtils.removeEventListener(HEvent.WORKER_MESSAGE, onmsg);
            }
            if (super.connected)
                super.close();
            _connected = false;
        }

        override public function load(request : URLRequest) : void {
            if (_hola_managed || _self_load)
            {
                if (reqs[_req_id])
                {
                    delete reqs[_req_id];
                    _trigger('abortFragment', {req_id: _req_id});
                }
                WorkerUtils.removeEventListener(HEvent.WORKER_MESSAGE, onmsg);
            }
            _hola_managed = HSettings.enabled && ZExternalInterface.avail();
            req_count++;
            _req_id = 'req'+req_count;
            if (!_hola_managed)
                return super.load(request);
            WorkerUtils.addEventListener(HEvent.WORKER_MESSAGE, onmsg);
            reqs[_req_id] = this;
            _resource = new ByteArray();
            _trigger('requestFragment', {url: request.url, req_id: _req_id});
            this.dispatchEvent(new Event(Event.OPEN));
        }

        private function onopen(e : Event) : void { _connected = true; }

        private function onerror(e : ErrorEvent) : void {
            _delete();
            if (!_events.error)
                return;
            _trigger('onRequestEvent', {req_id: _req_id, event: 'error',
                error: e.text, text: e.toString()});
        }

        private function onprogress(e : ProgressEvent) : void {
            _size = e.bytesTotal;
            if (!_events.progress)
                return;
            _trigger('onRequestEvent', {req_id: _req_id, event: 'progress',
                loaded: e.bytesLoaded, total: e.bytesTotal,
                text: e.toString()});
        }

        private function onstatus(e : HTTPStatusEvent) : void {
            if (!_events.status)
                return;
            // XXX bahaa: get redirected/responseURL/responseHeaders
            _trigger('onRequestEvent', {req_id: _req_id, event: 'status',
                status: e.status, text: e.toString()});
        }

        private function oncomplete(e : Event) : void {
            _delete();
            if (!_events.complete)
                return;
            _trigger('onRequestEvent', {req_id: _req_id, event: 'complete',
                size: _size, text: e.toString()});
        }

        private function decode(str : String) : void {
            if (!str)
                return on_decoded_data(null);
            if (!HSettings.use_worker)
                return on_decoded_data(Base64.decode_str(str));
            var data : ByteArray = new ByteArray();
            data.shareable = true;
            data.writeUTFBytes(str);
            WorkerUtils.send({cmd: "b64.decode", id: _req_id});
            WorkerUtils.send(data);
        }

        private function onmsg(e : HEvent) : void {
            var msg : Object = e.data;
            if (!_req_id || _req_id!=msg.id || msg.cmd!="b64.decode")
                return;
            on_decoded_data(WorkerUtils.recv());
        }

        private function on_decoded_data(data : ByteArray) : void {
            if (data)
            {
                data.position = 0;
                if (_resource)
                {
                    var prev : uint = _resource.position;
                    data.readBytes(_resource, _resource.length);
                    _resource.position = prev;
                }
                else
                    _resource = data;
                // XXX arik: get finalLength from js
                var finalLength : uint = _resource.length;
                dispatchEvent(new ProgressEvent( ProgressEvent.PROGRESS, false,
                    false, _resource.length, finalLength));
            }
            // XXX arik: dispatch httpStatus/httpResponseStatus
            if (_curr_data.status)
                resourceLoadingSuccess();
        }

        private function self_load(o : Object) : void {
            _self_load = true;
            _hola_managed = false;
            _events = o.events||{};
            addEventListener(IOErrorEvent.IO_ERROR, onerror);
            addEventListener(SecurityErrorEvent.SECURITY_ERROR, onerror);
            addEventListener(ProgressEvent.PROGRESS, onprogress);
            addEventListener(HTTPStatusEvent.HTTP_STATUS, onstatus);
            addEventListener(Event.COMPLETE, oncomplete);
            var req : URLRequest = new URLRequest(o.url);
            req.method = o.method=="POST" ? URLRequestMethod.POST :
                URLRequestMethod.GET;
            // this doesn't seem to work. simply ignored
            var headers : Object = o.headers||{};
            for (var k : String in headers)
                req.requestHeaders.push(new URLRequestHeader(k, headers[k]));
            super.load(req);
        }

        private function on_fragment_data(o : Object) : void {
            _curr_data = o;
            if (o.self_load)
                return self_load(o);
            if (o.error)
                return resourceLoadingError();
            decode(o.data);
        }

        protected static function hola_onFragmentData(o : Object) : void{
            var stream : JSURLStream;
            try {
                if (!(stream = reqs[o.req_id]))
                    throw new Error('req_id not found '+o.req_id);
                stream.on_fragment_data(o);
            } catch(err : Error){
                ZErr.log('Error in hola_onFragmentData', ''+err,
                    ''+err.getStackTrace());
                if (stream)
                    stream.resourceLoadingError();
                throw err;
            }
        }

        private function _delete() : void {
            delete reqs[_req_id];
        }

        protected function resourceLoadingError() : void {
            _delete();
            dispatchEvent(new IOErrorEvent(IOErrorEvent.IO_ERROR));
        }

        protected function resourceLoadingSuccess() : void {
            _delete();
            dispatchEvent(new Event(Event.COMPLETE));
        }
    }
}

abort requet on load

abort requet on load


/*
 * Copyright 2008 Adobe Systems Inc., 2008 Google Inc.
 *
 * 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.
 *
 * Contributor(s):
 *   Zwetan Kjukov <zwetan@gmail.com>.
 */

package
{
    import library.ASTUce.Runner;

    import com.google.analytics.AllTests;
    import flash.display.Sprite;

    /* note:
       Run the Google Analytics unit tests
    */
    [SWF(width="400", height="400", backgroundColor='0xffffff', frameRate='24', pageTitle='testrunner', scriptRecursionLimit='1000', scriptTimeLimit='60')]
    [ExcludeClass]
    public class TestRunner extends Sprite
    {
        public function TestRunner()
        {
            Runner.main( com.google.analytics.AllTests.suite( ) );
        }

    }
}

update comment

update comment