/*****************************************************
*
*  Copyright 2010 Eyewonder, LLC.  All Rights Reserved.
*
*****************************************************
*  The contents of this file are subject to the Mozilla Public License
*  Version 1.1 (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.mozilla.org/MPL/
*
*  Software distributed under the License is distributed on an "AS IS"
*  basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
*  License for the specific language governing rights and limitations
*  under the License.
*
*
*  The Initial Developer of the Original Code is Eyewonder, LLC.
*  Portions created by Eyewonder, LLC. are Copyright (C) 2010
*  Eyewonder, LLC. A Limelight Networks Business. All Rights Reserved.
*
*****************************************************/

package org.osmf.vast.media
{
	import __AS3__.vec.Vector;

	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.geom.Rectangle;

	import org.osmf.elements.ProxyElement;
	import org.osmf.elements.SWFLoader;
	import org.osmf.elements.VideoElement;
	import org.osmf.elements.beaconClasses.Beacon;
	import org.osmf.events.MediaElementEvent;
	import org.osmf.media.MediaElement;
	import org.osmf.media.MediaFactory;
	import org.osmf.media.URLResource;
	import org.osmf.metadata.Metadata;
	import org.osmf.traits.DisplayObjectTrait;
	import org.osmf.traits.MediaTraitType;
	import org.osmf.utils.HTTPLoader;
	import org.osmf.vast.model.VAST2MediaFile;
	import org.osmf.vast.model.VAST2Translator;
	import org.osmf.vast.model.VASTTrackingEvent;
	import org.osmf.vast.model.VASTTrackingEventType;
	import org.osmf.vast.model.VASTUrl;
	import org.osmf.vast.parser.base.VAST2CompanionElement;
	import org.osmf.vpaid.elements.VPAIDElement;
	import org.osmf.vpaid.metadata.VPAIDMetadata;

	CONFIG::LOGGING
	{
		import org.osmf.logging.Logger;
		import org.osmf.logging.Log;
	}

	/**
	 * Utility class for creating MediaElements from a VASTDocument.
	 *
	 *  @langversion 3.0
	 *  @playerversion Flash 10
	 *  @playerversion AIR 1.5
	 *  @productversion OSMF 1.0
	 */
	public class VAST2MediaGenerator
	{
		/**
		 * Constructor.
		 *
		 * @param mediaFileResolver The resolver to use when a VASTDocument
		 * contains multiple representations of the same content (MediaFile).
		 * If null, this object will use a DefaultVASTMediaFileResolver.
		 *
		 *  @langversion 3.0
		 *  @playerversion Flash 10
		 *  @playerversion AIR 1.5
		 *  @productversion OSMF 1.0
		 */
		public function VAST2MediaGenerator(mediaFileResolver:IVAST2MediaFileResolver=null, mediaFactory:MediaFactory=null)
		{
			super();

			this.mediaFileResolver =
				 mediaFileResolver != null
				 ? mediaFileResolver
				 : new DefaultVAST2MediaFileResolver();
			this.mediaFactory = mediaFactory;

		}

		/**
		 * Creates all relevant MediaElements from the specified VAST document.
		 *
		 * @param vastDocument The VASTDocument that holds the raw VAST information.
		 *
		 * @returns A Vector of MediaElements, where each MediaElement
		 * represents a different VASTAd within the VASTDocument.
		 *
		 *  @langversion 3.0
		 *  @playerversion Flash 10
		 *  @playerversion AIR 1.5
		 *  @productversion OSMF 1.0
		 */
		public function createMediaElements(vastDocument:VAST2Translator, vastPlacement:String = null,playerSize:Rectangle = null, translatorIndex:int = 0):Vector.<MediaElement>
		{
			var mediaElements:Vector.<MediaElement> = new Vector.<MediaElement>();

			this.vastDocument = vastDocument;
			vastDocument.adPlacement = (vastPlacement == null)?vastDocument.PLACEMENT_LINEAR:vastPlacement;

			if(vastDocument.clickThruUrl != null || vastDocument.clickThruUrl != "")
			{
				clickThru = vastDocument.clickThruUrl
			}

			cacheBuster = new CacheBuster();

			var trackingEvents:Vector.<VASTTrackingEvent> = new Vector.<VASTTrackingEvent>;
			var proxyChain:Vector.<ProxyElement> = new Vector.<ProxyElement>();

			// Check for the Impressions.
			if (vastDocument.impressionArray != null && vastDocument.impressionArray.length > 0)
			{
				var impressionArray:Vector.<VASTUrl> = new Vector.<VASTUrl>;
				for each(var impressionObj:Object in vastDocument.impressionArray)
				{
					var impressionURL:VASTUrl = new VASTUrl(impressionObj.url);
					impressionArray.push(impressionURL);
				}
			}

			addTrackingEvent("trkClickThruEvent", VASTTrackingEventType.CLICK_THRU, trackingEvents);
			addTrackingEvent("errorArray", VASTTrackingEventType.ERROR, trackingEvents);
			addTrackingEvent("trkStartEvent", VASTTrackingEventType.START, trackingEvents);
			addTrackingEvent("trkMidPointEvent", VASTTrackingEventType.MIDPOINT, trackingEvents);
			addTrackingEvent("trkFirstQuartileEvent", VASTTrackingEventType.FIRST_QUARTILE, trackingEvents);
			addTrackingEvent("trkThirdQuartileEvent", VASTTrackingEventType.THIRD_QUARTILE, trackingEvents);
			addTrackingEvent("trkCompleteEvent", VASTTrackingEventType.COMPLETE, trackingEvents);
			addTrackingEvent("trkMuteEvent", VASTTrackingEventType.MUTE, trackingEvents);
			addTrackingEvent("trkCreativeViewEvent", VASTTrackingEventType.CREATIVE_VIEW, trackingEvents);
			addTrackingEvent("trkPauseEvent", VASTTrackingEventType.PAUSE,trackingEvents);
			addTrackingEvent("trkReplayEvent", VASTTrackingEventType.REPLAY, trackingEvents);
			addTrackingEvent("trkFullScreenEvent", VASTTrackingEventType.FULLSCREEN, trackingEvents);
			addTrackingEvent("trkStopEvent", VASTTrackingEventType.STOP, trackingEvents);
			addTrackingEvent("trkUnmuteEvent", VASTTrackingEventType.UNMUTE, trackingEvents);
			addTrackingEvent("trkCloseEvent", VASTTrackingEventType.CLOSE, trackingEvents);
			addTrackingEvent("trkRewindEvent", VASTTrackingEventType.REWIND, trackingEvents);
			addTrackingEvent("trkResumeEvent", VASTTrackingEventType.RESUME, trackingEvents);
			addTrackingEvent("trkExpandEvent", VASTTrackingEventType.EXPAND, trackingEvents);
			addTrackingEvent("trkCollapseEvent", VASTTrackingEventType.COLLAPSE, trackingEvents);
			addTrackingEvent("trkAcceptInvitationEvent", VASTTrackingEventType.ACCEPT_INVITATION, trackingEvents);
			addTrackingEvent("trkSkipEvent", VASTTrackingEventType.SKIP,trackingEvents );
			addTrackingEvent("trkProgressEvent", VASTTrackingEventType.PROGRESS, trackingEvents);
			addTrackingEvent("trkExitFullScreenEvent", VASTTrackingEventType.EXIT_FULLSCREEN, trackingEvents );
			addTrackingEvent("trkCloseLinearEvent", VASTTrackingEventType.CLOSE_LINEAR, trackingEvents );

			// Check for Video.
			if (vastDocument.mediafileArray != null && vastDocument.mediafileArray.length > 0 && isLinear)
			{

				for each(var mediaObj:Object in vastDocument.mediafileArray)
				{
					var mediaFileObj:VAST2MediaFile = new VAST2MediaFile();
					mediaFileObj.url = mediaObj.url;
					mediaFileObj.delivery = mediaObj.delivery;
					mediaFileObj.bitrate = mediaObj.bitrate;
					mediaFileObj.type = mediaObj.type;
					mediaFileObj.width = mediaObj.width;
					mediaFileObj.height = mediaObj.height;
					mediaFileObj.id = mediaObj.id;
					mediaFileObj.scalable = mediaObj.scalable;
					mediaFileObj.maintainAspectRatio = mediaObj.maintainAspectRatio;
					mediaFileObj.apiFramework = mediaObj.apiFramework;

					var mediaFileURL:Vector.<VAST2MediaFile> = new Vector.<VAST2MediaFile>;
					mediaFileURL.push(mediaFileObj);
				}

				// Resolve the correct one.
				var mediaFile:VAST2MediaFile = mediaFileResolver.resolveMediaFiles(mediaFileURL);
				if (mediaFile != null)
				{
					var mediaURL:String = mediaFile.url;

					// If streaming, we may need to strip off the extension.
					if (mediaFile.delivery == "streaming" && mediaFile.type != "application/x-shockwave-flash")
					{
						mediaURL = mediaURL.replace(/\.flv$|\.f4v$/i, "");

					}

					var rootElement:MediaElement;

					if(mediaFile.type == "application/x-shockwave-flash" ||mediaFile.type == "swf" )
					{
						if (mediaFile.scalable)
						{
							rootElement = new VPAIDElement(new URLResource(mediaFile.url), new SWFLoader(),playerSize.width,playerSize.height);
						}
						else
						{
							rootElement = new VPAIDElement(new URLResource(mediaFile.url), new SWFLoader(),mediaFile.width,mediaFile.height);
						}
						VPAIDMetadata(rootElement.getMetadata("org.osmf.vpaid.metadata.VPAIDMetadata")).addValue(VPAIDMetadata.NON_LINEAR_CREATIVE, false);

					}
					else
					{
						if (mediaFactory != null)
						{
							rootElement = mediaFactory.createMediaElement(new URLResource(mediaURL)) as VideoElement;
							//VideoElement(rootElement).smoothing = true;
						}
						else
						{
							rootElement = new VideoElement(new URLResource(mediaURL));
							//VideoElement(rootElement).smoothing = true;
						}

					}

					var impressions:VASTImpressionProxyElement = new VAST2ImpressionProxyElement(impressionArray, null, rootElement, cacheBuster);
					var events:VASTTrackingProxyElement = new VAST2TrackingProxyElement(trackingEvents,null, impressions, cacheBuster,clickThru);
					var vastMediaElement:MediaElement = events;

					mediaElements.push(vastMediaElement);

				}
			}
			else if(vastDocument.nonlinearArray != null && vastDocument.nonlinearArray.length > 0 && isNonLinear)
			{

				//Non-linear check goes here.  If available create VPAID Element
				for each(var element:Object in vastDocument.nonlinearArray)
				{

					if(element.creativeType == "application/x-shockwave-flash")
					{

						var vpaidElement:MediaElement = new VPAIDElement(new URLResource(element.URL), new SWFLoader());
						var vpaidMetadata:Metadata = vpaidElement.getMetadata(VPAIDMetadata.NAMESPACE);
						vpaidMetadata.addValue(VPAIDMetadata.NON_LINEAR_CREATIVE, true);

						var impressionsNonLinear:VASTImpressionProxyElement = new VAST2ImpressionProxyElement(impressionArray, null, vpaidElement, cacheBuster);
						var eventsNonLinear:VASTTrackingProxyElement = new VAST2TrackingProxyElement(trackingEvents,null, impressionsNonLinear, cacheBuster, clickThru);
						var vastMediaElementNonLinear:MediaElement = eventsNonLinear;

						mediaElements.push(vastMediaElementNonLinear);

					}
				}

			}

			if(vastDocument.companionArray != null && vastDocument.companionArray.length > 0)
			{
				for each(var companionAd:VAST2CompanionElement in vastDocument.companionArray)
				{
					CONFIG::LOGGING
					{
						logger.debug("[VAST] Companion ad detected" + companionAd.staticResource);
					}
					var companionElement:CompanionElement = new CompanionElement(companionAd);
					companionElement.scriptPath = companionAd.staticResource;
					mediaElements.push(companionElement);
				}
			}

			return mediaElements;
		}

		private function get isLinear() : Boolean
		{
			return (vastDocument.adPlacement == VAST2Translator.PLACEMENT_LINEAR);
		}
		private function get isNonLinear() : Boolean
		{
			return (vastDocument.adPlacement == VAST2Translator.PLACEMENT_NONLINEAR);
		}

		/**
		 *
		 * @param evtName property name in vastDocument
		 * @param evtType type of event
		 * @return VASTTrackingEvent with the given evtType and the suitable URLs
		 *
		 */
		private function addTrackingEvent(evtName:String, evtType:VASTTrackingEventType, trackingArray:Vector.<VASTTrackingEvent>): void
		{
			if(trackingArray && vastDocument[evtName] != null && vastDocument[evtName].length > 0)
			{
				var trkEvent:VASTTrackingEvent = new VASTTrackingEvent(evtType);
				var trkArray:Vector.<VASTUrl> = new Vector.<VASTUrl>;

				for each(var obj:Object in vastDocument[evtName])
				{
					var url:VASTUrl = new VASTUrl(obj.url);
					trkArray.push(url);
				}

				trkEvent.urls = trkArray;
				trackingArray.push(trkEvent);
			}

		}

		private var mediaFactory:MediaFactory;
		private var clickThru:String;
		private var httpLoader:HTTPLoader;
		private var vastDocument:VAST2Translator;
		private var mediaFileResolver:IVAST2MediaFileResolver;
		private var vastTranslator:VAST2Translator;
		private var cacheBuster:CacheBuster;
		private var _adPlacement:String;

		CONFIG::LOGGING
		{
			private static const logger:Logger = Log.getLogger("org.osmf.vast.media.VAST2MediaGenerator");
		}
	}
}

/*****************************************************
*
*  Copyright 2010 Eyewonder, LLC.  All Rights Reserved.
*
*****************************************************
*  The contents of this file are subject to the Mozilla Public License
*  Version 1.1 (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.mozilla.org/MPL/
*
*  Software distributed under the License is distributed on an "AS IS"
*  basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
*  License for the specific language governing rights and limitations
*  under the License.
*
*
*  The Initial Developer of the Original Code is Eyewonder, LLC.
*  Portions created by Eyewonder, LLC. are Copyright (C) 2010
*  Eyewonder, LLC. A Limelight Networks Business. All Rights Reserved.
*
*****************************************************/

package org.osmf.vast.media
{
	import __AS3__.vec.Vector;

	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.geom.Rectangle;

	import org.osmf.elements.ProxyElement;
	import org.osmf.elements.SWFLoader;
	import org.osmf.elements.VideoElement;
	import org.osmf.elements.beaconClasses.Beacon;
	import org.osmf.events.MediaElementEvent;
	import org.osmf.media.MediaElement;
	import org.osmf.media.MediaFactory;
	import org.osmf.media.URLResource;
	import org.osmf.metadata.Metadata;
	import org.osmf.traits.DisplayObjectTrait;
	import org.osmf.traits.MediaTraitType;
	import org.osmf.utils.HTTPLoader;
	import org.osmf.vast.model.VAST2MediaFile;
	import org.osmf.vast.model.VAST2Translator;
	import org.osmf.vast.model.VASTTrackingEvent;
	import org.osmf.vast.model.VASTTrackingEventType;
	import org.osmf.vast.model.VASTUrl;
	import org.osmf.vast.parser.base.VAST2CompanionElement;
	import org.osmf.vpaid.elements.VPAIDElement;
	import org.osmf.vpaid.metadata.VPAIDMetadata;

	CONFIG::LOGGING
	{
		import org.osmf.logging.Logger;
		import org.osmf.logging.Log;
	}

	/**
	 * Utility class for creating MediaElements from a VASTDocument.
	 *
	 *  @langversion 3.0
	 *  @playerversion Flash 10
	 *  @playerversion AIR 1.5
	 *  @productversion OSMF 1.0
	 */
	public class VAST2MediaGenerator
	{
		/**
		 * Constructor.
		 *
		 * @param mediaFileResolver The resolver to use when a VASTDocument
		 * contains multiple representations of the same content (MediaFile).
		 * If null, this object will use a DefaultVASTMediaFileResolver.
		 *
		 *  @langversion 3.0
		 *  @playerversion Flash 10
		 *  @playerversion AIR 1.5
		 *  @productversion OSMF 1.0
		 */
		public function VAST2MediaGenerator(mediaFileResolver:IVAST2MediaFileResolver=null, mediaFactory:MediaFactory=null)
		{
			super();

			this.mediaFileResolver =
				 mediaFileResolver != null
				 ? mediaFileResolver
				 : new DefaultVAST2MediaFileResolver();
			this.mediaFactory = mediaFactory;

		}

		/**
		 * Creates all relevant MediaElements from the specified VAST document.
		 *
		 * @param vastDocument The VASTDocument that holds the raw VAST information.
		 *
		 * @returns A Vector of MediaElements, where each MediaElement
		 * represents a different VASTAd within the VASTDocument.
		 *
		 *  @langversion 3.0
		 *  @playerversion Flash 10
		 *  @playerversion AIR 1.5
		 *  @productversion OSMF 1.0
		 */
		public function createMediaElements(vastDocument:VAST2Translator, vastPlacement:String = null,playerSize:Rectangle = null, translatorIndex:int = 0):Vector.<MediaElement>
		{
			var mediaElements:Vector.<MediaElement> = new Vector.<MediaElement>();

			this.vastDocument = vastDocument;
			vastDocument.adPlacement = (vastPlacement == null)?vastDocument.PLACEMENT_LINEAR:vastPlacement;

			if(vastDocument.clickThruUrl != null || vastDocument.clickThruUrl != "")
			{
				clickThru = vastDocument.clickThruUrl
			}

			cacheBuster = new CacheBuster();

			var trackingEvents:Vector.<VASTTrackingEvent> = new Vector.<VASTTrackingEvent>;
			var proxyChain:Vector.<ProxyElement> = new Vector.<ProxyElement>();

			// Check for the Impressions.
			if (vastDocument.impressionArray != null && vastDocument.impressionArray.length > 0)
			{
				var impressionArray:Vector.<VASTUrl> = new Vector.<VASTUrl>;
				for each(var impressionObj:Object in vastDocument.impressionArray)
				{
					var impressionURL:VASTUrl = new VASTUrl(impressionObj.url);
					impressionArray.push(impressionURL);
				}
			}

			addTrackingEvent("trkClickThruEvent", VASTTrackingEventType.CLICK_THRU, trackingEvents);
			addTrackingEvent("errorArray", VASTTrackingEventType.ERROR, trackingEvents);
			addTrackingEvent("trkStartEvent", VASTTrackingEventType.START, trackingEvents);
			addTrackingEvent("trkMidPointEvent", VASTTrackingEventType.MIDPOINT, trackingEvents);
			addTrackingEvent("trkFirstQuartileEvent", VASTTrackingEventType.FIRST_QUARTILE, trackingEvents);
			addTrackingEvent("trkThirdQuartileEvent", VASTTrackingEventType.THIRD_QUARTILE, trackingEvents);
			addTrackingEvent("trkCompleteEvent", VASTTrackingEventType.COMPLETE, trackingEvents);
			addTrackingEvent("trkMuteEvent", VASTTrackingEventType.MUTE, trackingEvents);
			addTrackingEvent("trkCreativeViewEvent", VASTTrackingEventType.CREATIVE_VIEW, trackingEvents);
			addTrackingEvent("trkPauseEvent", VASTTrackingEventType.PAUSE,trackingEvents);
			addTrackingEvent("trkReplayEvent", VASTTrackingEventType.REPLAY, trackingEvents);
			addTrackingEvent("trkFullScreenEvent", VASTTrackingEventType.FULLSCREEN, trackingEvents);
			addTrackingEvent("trkStopEvent", VASTTrackingEventType.STOP, trackingEvents);
			addTrackingEvent("trkUnmuteEvent", VASTTrackingEventType.UNMUTE, trackingEvents);
			addTrackingEvent("trkCloseEvent", VASTTrackingEventType.CLOSE, trackingEvents);
			addTrackingEvent("trkRewindEvent", VASTTrackingEventType.REWIND, trackingEvents);
			addTrackingEvent("trkResumeEvent", VASTTrackingEventType.RESUME, trackingEvents);
			addTrackingEvent("trkExpandEvent", VASTTrackingEventType.EXPAND, trackingEvents);
			addTrackingEvent("trkCollapseEvent", VASTTrackingEventType.COLLAPSE, trackingEvents);
			addTrackingEvent("trkAcceptInvitationEvent", VASTTrackingEventType.ACCEPT_INVITATION, trackingEvents);
			addTrackingEvent("trkSkipEvent", VASTTrackingEventType.SKIP,trackingEvents );
			addTrackingEvent("trkProgressEvent", VASTTrackingEventType.PROGRESS, trackingEvents);
			addTrackingEvent("trkExitFullScreenEvent", VASTTrackingEventType.EXIT_FULLSCREEN, trackingEvents );
			addTrackingEvent("trkCloseLinearEvent", VASTTrackingEventType.CLOSE_LINEAR, trackingEvents );

			// Check for Video.
			if (vastDocument.mediafileArray != null && vastDocument.mediafileArray.length > 0 && isLinear)
			{
				var mediaFileURL:Vector.<VAST2MediaFile> = new Vector.<VAST2MediaFile>;

				for each(var mediaObj:Object in vastDocument.mediafileArray)
				{
					var mediaFileObj:VAST2MediaFile = new VAST2MediaFile();
					mediaFileObj.url = mediaObj.url;
					mediaFileObj.delivery = mediaObj.delivery;
					mediaFileObj.bitrate = mediaObj.bitrate;
					mediaFileObj.type = mediaObj.type;
					mediaFileObj.width = mediaObj.width;
					mediaFileObj.height = mediaObj.height;
					mediaFileObj.id = mediaObj.id;
					mediaFileObj.scalable = mediaObj.scalable;
					mediaFileObj.maintainAspectRatio = mediaObj.maintainAspectRatio;
					mediaFileObj.apiFramework = mediaObj.apiFramework;

					mediaFileURL.push(mediaFileObj);
				}

				// Resolve the correct one.
				var mediaFile:VAST2MediaFile = mediaFileResolver.resolveMediaFiles(mediaFileURL);
				if (mediaFile != null)
				{
					var mediaURL:String = mediaFile.url;

					// If streaming, we may need to strip off the extension.
					if (mediaFile.delivery == "streaming" && mediaFile.type != "application/x-shockwave-flash")
					{
						mediaURL = mediaURL.replace(/\.flv$|\.f4v$/i, "");

					}

					var rootElement:MediaElement;

					if(mediaFile.type == "application/x-shockwave-flash" ||mediaFile.type == "swf" )
					{
						if (mediaFile.scalable)
						{
							rootElement = new VPAIDElement(new URLResource(mediaFile.url), new SWFLoader(),playerSize.width,playerSize.height);
						}
						else
						{
							rootElement = new VPAIDElement(new URLResource(mediaFile.url), new SWFLoader(),mediaFile.width,mediaFile.height);
						}
						VPAIDMetadata(rootElement.getMetadata("org.osmf.vpaid.metadata.VPAIDMetadata")).addValue(VPAIDMetadata.NON_LINEAR_CREATIVE, false);

					}
					else
					{
						if (mediaFactory != null)
						{
							rootElement = mediaFactory.createMediaElement(new URLResource(mediaURL)) as VideoElement;
							//VideoElement(rootElement).smoothing = true;
						}
						else
						{
							rootElement = new VideoElement(new URLResource(mediaURL));
							//VideoElement(rootElement).smoothing = true;
						}

					}

					var impressions:VASTImpressionProxyElement = new VAST2ImpressionProxyElement(impressionArray, null, rootElement, cacheBuster);
					var events:VASTTrackingProxyElement = new VAST2TrackingProxyElement(trackingEvents,null, impressions, cacheBuster,clickThru);
					var vastMediaElement:MediaElement = events;

					mediaElements.push(vastMediaElement);

				}
			}
			else if(vastDocument.nonlinearArray != null && vastDocument.nonlinearArray.length > 0 && isNonLinear)
			{

				//Non-linear check goes here.  If available create VPAID Element
				for each(var element:Object in vastDocument.nonlinearArray)
				{

					if(element.creativeType == "application/x-shockwave-flash")
					{

						var vpaidElement:MediaElement = new VPAIDElement(new URLResource(element.URL), new SWFLoader());
						var vpaidMetadata:Metadata = vpaidElement.getMetadata(VPAIDMetadata.NAMESPACE);
						vpaidMetadata.addValue(VPAIDMetadata.NON_LINEAR_CREATIVE, true);

						var impressionsNonLinear:VASTImpressionProxyElement = new VAST2ImpressionProxyElement(impressionArray, null, vpaidElement, cacheBuster);
						var eventsNonLinear:VASTTrackingProxyElement = new VAST2TrackingProxyElement(trackingEvents,null, impressionsNonLinear, cacheBuster, clickThru);
						var vastMediaElementNonLinear:MediaElement = eventsNonLinear;

						mediaElements.push(vastMediaElementNonLinear);

					}
				}

			}

			if(vastDocument.companionArray != null && vastDocument.companionArray.length > 0)
			{
				for each(var companionAd:VAST2CompanionElement in vastDocument.companionArray)
				{
					CONFIG::LOGGING
					{
						logger.debug("[VAST] Companion ad detected" + companionAd.staticResource);
					}
					var companionElement:CompanionElement = new CompanionElement(companionAd);
					companionElement.scriptPath = companionAd.staticResource;
					mediaElements.push(companionElement);
				}
			}

			return mediaElements;
		}

		private function get isLinear() : Boolean
		{
			return (vastDocument.adPlacement == VAST2Translator.PLACEMENT_LINEAR);
		}
		private function get isNonLinear() : Boolean
		{
			return (vastDocument.adPlacement == VAST2Translator.PLACEMENT_NONLINEAR);
		}

		/**
		 *
		 * @param evtName property name in vastDocument
		 * @param evtType type of event
		 * @return VASTTrackingEvent with the given evtType and the suitable URLs
		 *
		 */
		private function addTrackingEvent(evtName:String, evtType:VASTTrackingEventType, trackingArray:Vector.<VASTTrackingEvent>): void
		{
			if(trackingArray && vastDocument[evtName] != null && vastDocument[evtName].length > 0)
			{
				var trkEvent:VASTTrackingEvent = new VASTTrackingEvent(evtType);
				var trkArray:Vector.<VASTUrl> = new Vector.<VASTUrl>;

				for each(var obj:Object in vastDocument[evtName])
				{
					var url:VASTUrl = new VASTUrl(obj.url);
					trkArray.push(url);
				}

				trkEvent.urls = trkArray;
				trackingArray.push(trkEvent);
			}

		}

		private var mediaFactory:MediaFactory;
		private var clickThru:String;
		private var httpLoader:HTTPLoader;
		private var vastDocument:VAST2Translator;
		private var mediaFileResolver:IVAST2MediaFileResolver;
		private var vastTranslator:VAST2Translator;
		private var cacheBuster:CacheBuster;
		private var _adPlacement:String;

		CONFIG::LOGGING
		{
			private static const logger:Logger = Log.getLogger("org.osmf.vast.media.VAST2MediaGenerator");
		}
	}
}

vast: allow fallback to a supported mediaFile, if mediaFiles list
contains unsupported one (such as webm).


package com.google.analytics.utils
{

    public class FakeEnvironment extends Environment
    {
        private var _appName:String;
        private var _appVersion:Version;
        private var _url:String;
        private var _referrer:String;
        private var _documentTitle:String;
        private var _domainName:String;
        private var _locationPath:String;
        private var _locationSearch:String;
        private var _flashVersion:Version;
        private var _language:String;
        private var _languageEncoding:String;
        private var _operatingSystem:String;
        private var _playerType:String;
        private var _platform:String;
        private var _protocol:String;
        private var _screenWidth:Number;
        private var _screenHeight:Number;
        private var _screenColorDepth:String;
        private var _userAgent:String;
        private var _isInHTML:Boolean;
        private var _isAIR:Boolean;

        public function FakeEnvironment( appName:String = "", appVersion:Version = null,
                                       url:String = "", referrer:String = "",
                                       documentTitle:String = "", domainName:String = "",
                                       locationPath:String = "", locationSearch:String = "",
                                       flashVersion:Version = null, language:String = "",
                                       languageEncoding:String = "", operatingSystem:String = "",
                                       playerType:String = "", platform:String = "",
                                       protocol:String = null, screenWidth:Number = NaN,
                                       screenHeight:Number = NaN, screenColorDepth:String = "",
                                       userAgent:String = null,
                                       isInHTML:Boolean = false,
                                       isAIR:Boolean = false )
        {
            super("", "", "", null);

            _appName = appName;
            _appVersion = appVersion;
            _url = url;
            _referrer = referrer;
            _documentTitle = documentTitle;
            _domainName = domainName;
            _locationPath = locationPath;
            _locationSearch = locationSearch;
            _flashVersion = flashVersion;
            _language = language;
            _languageEncoding = languageEncoding;
            _operatingSystem = operatingSystem;
            _playerType = playerType;
            _platform = platform;
            _protocol = protocol;
            _screenWidth = screenWidth;
            _screenHeight = screenHeight;
            _screenColorDepth = screenColorDepth;
            _userAgent = userAgent;
            _isInHTML = isInHTML;
            _isAIR = isAIR;
        }

        public override function get appName():String
        {
            return _appName;
        }

        public override function set appName( value:String ):void
        {
            _appName = value;
        }

        public override function get appVersion():Version
        {
            return _appVersion;
        }

        public override function set appVersion( value:Version ):void
        {
            _appVersion = value;
        }

//        ga_internal override function set url( value:String ):void
//        {
//            _url = value;
//        }

        public override function get locationSWFPath():String
        {
            return _url;
        }

        public override function get referrer():String
        {
            return _referrer;
        }

        public override function get documentTitle():String
        {
            return _documentTitle;
        }

        public override function get domainName():String
        {
            return _domainName;
        }

        public override function get locationPath():String
        {
            return _locationPath;
        }

        public override function get locationSearch():String
        {
            return _locationSearch;
        }

        public override function get flashVersion():Version
        {
            return _flashVersion;
        }

        public override function get language():String
        {
            return _language;
        }

        public override function get languageEncoding():String
        {
            return _languageEncoding;
        }

        public override function get operatingSystem():String
        {
            return _operatingSystem;
        }

        public override function get playerType():String
        {
            return _playerType;
        }

        public override function get platform():String
        {
            return _platform;
        }

        public override function get protocol():String
        {
            return _protocol;
        }

        public override function get screenWidth():Number
        {
            return _screenWidth;
        }

        public override function get screenHeight():Number
        {
            return _screenHeight;
        }

        public override function get screenColorDepth():String
        {
            return _screenColorDepth;
        }

        public override function get userAgent():String
        {
            return _userAgent;
        }

        public override function set userAgent( custom:String ):void
        {
            _userAgent = custom;
        }

        public override function isInHTML():Boolean
        {
            return _isInHTML;
        }

        public override function isAIR():Boolean
        {
            return _isAIR;
        }
    }
}

package com.google.analytics.utils
{
    import core.version;

    public class FakeEnvironment extends Environment
    {
        private var _appName:String;
        private var _appVersion:version;
        private var _url:String;
        private var _referrer:String;
        private var _documentTitle:String;
        private var _domainName:String;
        private var _locationPath:String;
        private var _locationSearch:String;
        private var _flashVersion:version;
        private var _language:String;
        private var _languageEncoding:String;
        private var _operatingSystem:String;
        private var _playerType:String;
        private var _platform:String;
        private var _protocol:String;
        private var _screenWidth:Number;
        private var _screenHeight:Number;
        private var _screenColorDepth:String;
        private var _userAgent:String;
        private var _isInHTML:Boolean;
        private var _isAIR:Boolean;

        public function FakeEnvironment( appName:String = "", appVersion:version = null,
                                       url:String = "", referrer:String = "",
                                       documentTitle:String = "", domainName:String = "",
                                       locationPath:String = "", locationSearch:String = "",
                                       flashVersion:version = null, language:String = "",
                                       languageEncoding:String = "", operatingSystem:String = "",
                                       playerType:String = "", platform:String = "",
                                       protocol:String = null, screenWidth:Number = NaN,
                                       screenHeight:Number = NaN, screenColorDepth:String = "",
                                       userAgent:String = null,
                                       isInHTML:Boolean = false,
                                       isAIR:Boolean = false )
        {
            super("", "", "", null);

            _appName = appName;
            _appVersion = appVersion;
            _url = url;
            _referrer = referrer;
            _documentTitle = documentTitle;
            _domainName = domainName;
            _locationPath = locationPath;
            _locationSearch = locationSearch;
            _flashVersion = flashVersion;
            _language = language;
            _languageEncoding = languageEncoding;
            _operatingSystem = operatingSystem;
            _playerType = playerType;
            _platform = platform;
            _protocol = protocol;
            _screenWidth = screenWidth;
            _screenHeight = screenHeight;
            _screenColorDepth = screenColorDepth;
            _userAgent = userAgent;
            _isInHTML = isInHTML;
            _isAIR = isAIR;
        }

        public override function get appName():String
        {
            return _appName;
        }

        public override function set appName( value:String ):void
        {
            _appName = value;
        }

        public override function get appVersion():version
        {
            return _appVersion;
        }

        public override function set appVersion( value:version ):void
        {
            _appVersion = value;
        }

//        ga_internal override function set url( value:String ):void
//        {
//            _url = value;
//        }

        public override function get locationSWFPath():String
        {
            return _url;
        }

        public override function get referrer():String
        {
            return _referrer;
        }

        public override function get documentTitle():String
        {
            return _documentTitle;
        }

        public override function get domainName():String
        {
            return _domainName;
        }

        public override function get locationPath():String
        {
            return _locationPath;
        }

        public override function get locationSearch():String
        {
            return _locationSearch;
        }

        public override function get flashVersion():version
        {
            return _flashVersion;
        }

        public override function get language():String
        {
            return _language;
        }

        public override function get languageEncoding():String
        {
            return _languageEncoding;
        }

        public override function get operatingSystem():String
        {
            return _operatingSystem;
        }

        public override function get playerType():String
        {
            return _playerType;
        }

        public override function get platform():String
        {
            return _platform;
        }

        public override function get protocol():String
        {
            return _protocol;
        }

        public override function get screenWidth():Number
        {
            return _screenWidth;
        }

        public override function get screenHeight():Number
        {
            return _screenHeight;
        }

        public override function get screenColorDepth():String
        {
            return _screenColorDepth;
        }

        public override function get userAgent():String
        {
            return _userAgent;
        }

        public override function set userAgent( custom:String ):void
        {
            _userAgent = custom;
        }

        public override function isInHTML():Boolean
        {
            return _isInHTML;
        }

        public override function isAIR():Boolean
        {
            return _isAIR;
        }
    }
}

replace class Version by core.version

replace class Version by core.version


package com.mangui.HLS.streaming {

    import com.mangui.HLS.*;
    import com.mangui.HLS.parsing.*;
    import com.mangui.HLS.utils.*;
    import flash.events.*;
    import flash.net.*;
    import flash.utils.*;

    /** Loader for hls streaming manifests. **/
    public class Getter {

        /** Reference to the hls framework controller. **/
        private var _hls:HLS;
        /** Array with levels. **/
        private var _levels:Array = [];
        /** Object that fetches the manifest. **/
        private var _urlloader:URLLoader;
        /** Link to the M3U8 file. **/
        private var _url:String;
        /** Amount of playlists still need loading. **/
        private var _toLoad:Number;
        /** are all playlists filled ? **/
        private var _canStart:Boolean;
        /** initial reload timer **/
        private var _fragmentDuration:Number = 5000;
        /** Timeout ID for reloading live playlists. **/
        private var _timeoutID:Number;
        /** Streaming type (live, ondemand). **/
        private var _type:String;
        /** last reload manifest time **/
        private var _reload_playlists_timer:uint;

        /** Setup the loader. **/
        public function Getter(hls:HLS) {
            _hls = hls;
            _hls.addEventListener(HLSEvent.STATE,_stateHandler);
            _levels = [];
            _urlloader = new URLLoader();
            _urlloader.addEventListener(Event.COMPLETE,_loaderHandler);
            _urlloader.addEventListener(IOErrorEvent.IO_ERROR,_errorHandler);
            _urlloader.addEventListener(SecurityErrorEvent.SECURITY_ERROR,_errorHandler);
        };

        /** Loading failed; return errors. **/
        private function _errorHandler(event:ErrorEvent):void {
            var txt:String = "Cannot load M3U8: "+event.text;
            if(event is SecurityErrorEvent) {
                txt = "Cannot load M3U8: crossdomain access denied";
            } else if (event is IOErrorEvent) {
                txt = "Cannot load M3U8: 404 not found";
            }
            _hls.dispatchEvent(new HLSEvent(HLSEvent.ERROR,txt));
        };

        /** return true if first two levels contain at least 2 fragments **/
        private function _areFirstLevelsFilled():Boolean {
           for(var i:Number = 0; (i < _levels.length) && (i < 2); i++) {
            if(_levels[i].fragments.length < 2) {
               return false;
            }
         }
         return true;
        };

        /** Return the current manifest. **/
        public function getLevels():Array {
            return _levels;
        };

        /** Return the stream type. **/
        public function getType():String {
            return _type;
        };

        /** Load the manifest file. **/
        public function load(url:String):void {
            _url = url;
            _levels = [];
            _canStart = false;
            _reload_playlists_timer = getTimer();
            _urlloader.load(new URLRequest(_url));
        };

        /** Manifest loaded; check and parse it **/
        private function _loaderHandler(event:Event):void {
            _loadManifest(String(event.target.data));
        };

        /** load a playlist **/
        private function _loadPlaylist(string:String,url:String,index:Number):void {
            if(string != null && string.length != 0) {
               var frags:Array = Manifest.getFragments(string,url);
               // set fragment and update sequence number range
               _levels[index].setFragments(frags);
               _levels[index].targetduration = Manifest.getTargetDuration(string);
               _levels[index].start_seqnum = frags[0].seqnum;
               _levels[index].end_seqnum = frags[frags.length-1].seqnum;
               _levels[index].duration = frags[frags.length-1].start + frags[frags.length-1].duration;
            }
            if(--_toLoad == 0) {
            // Check whether the stream is live or not finished yet
            if(Manifest.hasEndlist(string)) {
                _type = HLSTypes.VOD;
            } else {
                _type = HLSTypes.LIVE;
                var timeout:Number = Math.max(100,_reload_playlists_timer + _fragmentDuration - getTimer());
                Log.txt("Live Playlist parsing finished: reload in " + timeout + " ms");
                _timeoutID = setTimeout(_loadPlaylists,timeout);
            }
               if (!_canStart && (_canStart =_areFirstLevelsFilled())) {
                  Log.txt("first 2 levels are filled with at least 2 fragments, notify event");
                  _fragmentDuration = frags[0].duration*1000;
                  _hls.dispatchEvent(new HLSEvent(HLSEvent.MANIFEST,_levels));
              }
            }
        };

        /** load First Level Playlist **/
        private function _loadManifest(string:String):void {
            // Check for M3U8 playlist or manifest.
            if(string.indexOf(Manifest.HEADER) == 0) {
               //1 level playlist, create unique level and parse playlist
                if(string.indexOf(Manifest.FRAGMENT) > 0) {
                    var level:Level = new Level();
                    level.url = _url;
                    _levels.push(level);
                    _toLoad = 1;
                    Log.txt("1 Level Playlist, load it");
                    _loadPlaylist(string,_url,0);
                } else if(string.indexOf(Manifest.LEVEL) > 0) {
                  //adaptative playlist, extract levels from playlist, get them and parse them
                  _levels = Manifest.extractLevels(string,_url);
                  _loadPlaylists();
                }
            } else {
                var message:String = "Manifest is not a valid M3U8 file" + _url;
                _hls.dispatchEvent(new HLSEvent(HLSEvent.ERROR,message));
            }
        };

        /** load/reload all M3U8 playlists **/
        private function _loadPlaylists():void {
            _reload_playlists_timer = getTimer();
            _toLoad = _levels.length;
            //Log.txt("HLS Playlist, with " + _toLoad + " levels");
            for(var i:Number = 0; i < _levels.length; i++) {
                new Manifest().loadPlaylist(_levels[i].url,_loadPlaylist,_errorHandler,i);
            }
        };

        /** When the framework idles out, reloading is cancelled. **/
        public function _stateHandler(event:HLSEvent):void {
            if(event.state == HLSStates.IDLE) {
                clearTimeout(_timeoutID);
            }
        };
    }
}

package com.mangui.HLS.streaming {

    import com.mangui.HLS.*;
    import com.mangui.HLS.parsing.*;
    import com.mangui.HLS.utils.*;
    import flash.events.*;
    import flash.net.*;
    import flash.utils.*;

    /** Loader for hls streaming manifests. **/
    public class Getter {

        /** Reference to the hls framework controller. **/
        private var _hls:HLS;
        /** Array with levels. **/
        private var _levels:Array = [];
        /** Object that fetches the manifest. **/
        private var _urlloader:URLLoader;
        /** Link to the M3U8 file. **/
        private var _url:String;
        /** Amount of playlists still need loading. **/
        private var _toLoad:Number;
        /** are all playlists filled ? **/
        private var _canStart:Boolean;
        /** initial reload timer **/
        private var _fragmentDuration:Number = 5000;
        /** Timeout ID for reloading live playlists. **/
        private var _timeoutID:Number;
        /** Streaming type (live, ondemand). **/
        private var _type:String;
        /** last reload manifest time **/
        private var _reload_playlists_timer:uint;

        /** Setup the loader. **/
        public function Getter(hls:HLS) {
            _hls = hls;
            _hls.addEventListener(HLSEvent.STATE,_stateHandler);
            _levels = [];
            _urlloader = new URLLoader();
            _urlloader.addEventListener(Event.COMPLETE,_loaderHandler);
            _urlloader.addEventListener(IOErrorEvent.IO_ERROR,_errorHandler);
            _urlloader.addEventListener(SecurityErrorEvent.SECURITY_ERROR,_errorHandler);
        };

        /** Loading failed; return errors. **/
        private function _errorHandler(event:ErrorEvent):void {
            var txt:String = "Cannot load M3U8: "+event.text;
            if(event is SecurityErrorEvent) {
                txt = "Cannot load M3U8: crossdomain access denied";
            } else if (event is IOErrorEvent) {
                txt = "Cannot load M3U8: 404 not found";
            }
            _hls.dispatchEvent(new HLSEvent(HLSEvent.ERROR,txt));
        };

        /** return true if first two levels contain at least 2 fragments **/
        private function _areFirstLevelsFilled():Boolean {
           for(var i:Number = 0; (i < _levels.length) && (i < 2); i++) {
            if(_levels[i].fragments.length < 2) {
               return false;
            }
         }
         return true;
        };

        /** Return the current manifest. **/
        public function getLevels():Array {
            return _levels;
        };

        /** Return the stream type. **/
        public function getType():String {
            return _type;
        };

        /** Load the manifest file. **/
        public function load(url:String):void {
            _url = url;
            _levels = [];
            _canStart = false;
            _reload_playlists_timer = getTimer();
            _urlloader.load(new URLRequest(_url));
        };

        /** Manifest loaded; check and parse it **/
        private function _loaderHandler(event:Event):void {
            _loadManifest(String(event.target.data));
        };

        /** load a playlist **/
        private function _loadPlaylist(string:String,url:String,index:Number):void {
            if(string != null && string.length != 0) {
               var frags:Array = Manifest.getFragments(string,url);
               // set fragment and update sequence number range
               _levels[index].setFragments(frags);
               _levels[index].targetduration = Manifest.getTargetDuration(string);
               _levels[index].start_seqnum = frags[0].seqnum;
               _levels[index].end_seqnum = frags[frags.length-1].seqnum;
               _levels[index].duration = frags[frags.length-1].start + frags[frags.length-1].duration;
               _fragmentDuration = _levels[index].targetduration;
            }
            if(--_toLoad == 0) {
            // Check whether the stream is live or not finished yet
            if(Manifest.hasEndlist(string)) {
                _type = HLSTypes.VOD;
            } else {
                _type = HLSTypes.LIVE;
                var timeout:Number = Math.max(100,_reload_playlists_timer + _fragmentDuration - getTimer());
                Log.txt("Live Playlist parsing finished: reload in " + timeout + " ms");
                _timeoutID = setTimeout(_loadPlaylists,timeout);
            }
               if (!_canStart && (_canStart =_areFirstLevelsFilled())) {
                  Log.txt("first 2 levels are filled with at least 2 fragments, notify event");
                  _hls.dispatchEvent(new HLSEvent(HLSEvent.MANIFEST,_levels));
              }
            }
        };

        /** load First Level Playlist **/
        private function _loadManifest(string:String):void {
            // Check for M3U8 playlist or manifest.
            if(string.indexOf(Manifest.HEADER) == 0) {
               //1 level playlist, create unique level and parse playlist
                if(string.indexOf(Manifest.FRAGMENT) > 0) {
                    var level:Level = new Level();
                    level.url = _url;
                    _levels.push(level);
                    _toLoad = 1;
                    Log.txt("1 Level Playlist, load it");
                    _loadPlaylist(string,_url,0);
                } else if(string.indexOf(Manifest.LEVEL) > 0) {
                  //adaptative playlist, extract levels from playlist, get them and parse them
                  _levels = Manifest.extractLevels(string,_url);
                  _loadPlaylists();
                }
            } else {
                var message:String = "Manifest is not a valid M3U8 file" + _url;
                _hls.dispatchEvent(new HLSEvent(HLSEvent.ERROR,message));
            }
        };

        /** load/reload all M3U8 playlists **/
        private function _loadPlaylists():void {
            _reload_playlists_timer = getTimer();
            _toLoad = _levels.length;
            //Log.txt("HLS Playlist, with " + _toLoad + " levels");
            for(var i:Number = 0; i < _levels.length; i++) {
                new Manifest().loadPlaylist(_levels[i].url,_loadPlaylist,_errorHandler,i);
            }
        };

        /** When the framework idles out, reloading is cancelled. **/
        public function _stateHandler(event:HLSEvent):void {
            if(event.state == HLSStates.IDLE) {
                clearTimeout(_timeoutID);
            }
        };
    }
}

use #EXT-X-TARGETDURATION for live playlist timer


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

    This file is a part of Weave.

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

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

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

package weave.utils
{
	import flash.display.Stage;

	import mx.controls.ToolTip;
	import mx.core.Application;
	import mx.core.IToolTip;
	import mx.managers.ToolTipManager;
	import mx.utils.ObjectUtil;

	import weave.Weave;
	import weave.api.data.IAttributeColumn;
	import weave.api.data.IKeySet;
	import weave.api.data.IQualifiedKey;
	import weave.api.primitives.IBounds2D;
	import weave.compiler.StringLib;
	import weave.core.LinkableHashMap;
	import weave.primitives.Bounds2D;
	import weave.visualization.layers.InteractiveVisualization;
	import weave.visualization.layers.SimpleInteractiveVisualization;

	/**
	 * ProbeTextManager
	 * A static class containing functions to manage a list of probed attribute columns
	 *
	 * @author adufilie
	 */
	public class ProbeTextUtils
	{
		public static function get probedColumns():LinkableHashMap
		{
			// this initializes the probed columns object map if not created yet, otherwise just returns the existing one
			return Weave.root.requestObject("Probed Columns", LinkableHashMap, true);
		}

		public static function get probeHeaderColumns():LinkableHashMap
		{
			return Weave.root.requestObject("Probe Header Columns", LinkableHashMap, true);
		}

		/**
		 * getProbeText
		 * @param keySet The key set you are interested in.
		 * @param additionalColumns An array of additional columns (other than global probed columns) to be displayed in the probe tooltip
		 * @param maxRecordsShown Maximum no. of records shown in one probe tooltip
		 * @return A string to be displayed on a tooltip while probing
		 */
		public static function getProbeText(keySet:IKeySet, additionalColumns:Array = null):String
		{
			var result:String = '';
			var columns:Array = probedColumns.getObjects(IAttributeColumn);
			if (additionalColumns != null)
				columns = columns.concat(additionalColumns);
			var headers:Array = probeHeaderColumns.getObjects(IAttributeColumn);
			var keys:Array = keySet.keys.concat().sort(ObjectUtil.compare);
			var key:IQualifiedKey;
			var recordCount:int = 0;
			var maxRecordsShown:Number = Weave.properties.maxTooltipRecordsShown.value;
			for (var iKey:int = 0; iKey < keys.length && iKey < maxRecordsShown; iKey++)
			{
				key = keys[iKey] as IQualifiedKey;

				var record:String = '';
				for (var iHeader:int = 0; iHeader < headers.length; iHeader++)
				{
					var header:IAttributeColumn = headers[iHeader] as IAttributeColumn;
					var headerValue:String = StringLib.toString(header.getValueFromKey(key, String));
					if (headerValue == '')
						continue;
					if (record != '')
						record += ', ';
					record += headerValue;
				}

				if (record != '')
					record += '\n';
				var lookup:Object = new Object() ;
				for (var iColumn:int = 0; iColumn < columns.length; iColumn++)
				{
					var column:IAttributeColumn = columns[iColumn] as IAttributeColumn;
					var value:String = String(column.getValueFromKey(key, String));
					if (value == '' || value == 'NaN')
						continue;
					var title:String = ColumnUtils.getTitle(column);
					var line:String = StringLib.lpad(value, 8) + ' (' + title + ')\n';
					if(lookup[line]  == undefined )
					{
						record += line;
						lookup[line] = true;
					}
				}
				if (record != '')
				{
					result += record + '\n';
					recordCount++;
				}
			}
			// remove ending '\n'
			while (result.substr(result.length - 1) == '\n')
				result = result.substr(0, result.length - 1);

			if (result == '')
			{
				result = 'Record Identifier' + (keys.length > 1 ? 's' : '') + ':\n';
				for (var i:int = 0; i < keys.length && i < maxRecordsShown; i++)
				{
					key = keys[i] as IQualifiedKey;
					result += '    ' + key.keyType + '#' + key.localName + '\n';
					recordCount++;
				}
			}

			if (recordCount >= maxRecordsShown && keys.length > maxRecordsShown)
			{
				result += '\n... (' + keys.length + ' records total, ' + recordCount + ' shown)';
			}

			return result;
		}

		private static function setProbeToolTipAppearance():void
		{
			(probeToolTip as ToolTip).setStyle("backgroundAlpha", Weave.properties.probeToolTipBackgroundAlpha.value);
			if (isFinite(Weave.properties.probeToolTipBackgroundColor.value))
				(probeToolTip as ToolTip).setStyle("backgroundColor", Weave.properties.probeToolTipBackgroundColor.value);
		}

		public static function showProbeToolTip(probeText:String, stageX:Number, stageY:Number, bounds:IBounds2D = null, margin:int = 5):void
		{
			if (bounds == null)
			{
				var stage:Stage = Application.application.stage;
				tempBounds.setBounds(stage.x, stage.y, stage.stageWidth, stage.stageHeight);
				bounds = tempBounds;
			}
			destroyProbeToolTip();

			// create new tooltip
			probeToolTip = ToolTipManager.createToolTip(probeText, 0, 0);

			// make tooltip completely opaque because text + graphics on same sprite is slow
			setProbeToolTipAppearance() ;
			var xMin:Number = bounds.getXNumericMin();
			var yMin:Number = bounds.getYNumericMin();
			var xMax:Number = bounds.getXNumericMax() - probeToolTip.width;
			var yMax:Number = bounds.getYNumericMax() - probeToolTip.height;
			var b:Boolean = false;
			var yAxisToolTip:IToolTip = SimpleInteractiveVisualization.yAxisTooltipPtr ;
			var xAxisToolTip:IToolTip = SimpleInteractiveVisualization.xAxisTooltipPtr ;

			// calculate y coordinate
			var y:int;
			// calculate y pos depending on toolTipAbove setting
			if (toolTipAbove)
			{
				y = stageY - (probeToolTip.height + 2 * margin);
				if(yAxisToolTip != null)
					y = yAxisToolTip.y - margin - probeToolTip.height ;
			}
			else // below
			{
				y = stageY + margin * 2;
				if(yAxisToolTip != null)
					y = yAxisToolTip.y+yAxisToolTip.height+margin;
			}

			// flip y position if out of bounds
			if ((y < yMin && toolTipAbove) || (y > yMax && !toolTipAbove))
				toolTipAbove = !toolTipAbove;

			// calculate x coordinate
			var x:int;
			if (cornerToolTip)
			{
				// want toolTip corner to be near probe point
				if (toolTipToTheLeft)
				{
					x = stageX - margin - probeToolTip.width;
					if(xAxisToolTip != null)
						x = xAxisToolTip.x - margin - probeToolTip.width;
				}
				else // to the right
				{
					x = stageX + margin;
					if(xAxisToolTip != null)
						x = xAxisToolTip.x+xAxisToolTip.width+margin;
				}

				// flip x position if out of bounds
				if ((x < xMin && toolTipToTheLeft) || (x > xMax && !toolTipToTheLeft))
					toolTipToTheLeft = !toolTipToTheLeft;
			}
			else // center x coordinate
			{
				x = stageX - probeToolTip.width / 2;
			}

			// if at lower-right corner of mouse, shift to the right 10 pixels to get away from the mouse pointer
			if (x > stageX && y > stageY)
				x += 10;

			// enforce min/max values and position tooltip
			x = Math.max(xMin, Math.min(x, xMax));
			y = Math.max(yMin, Math.min(y, yMax));

			probeToolTip.move(x, y);
		}

		/**
		 * cornerToolTip:
		 * false = center of tooltip will be aligned with x probe coordinate
		 * true = corner of tooltip will be aligned with x probe coordinate
		 */
		private static var cornerToolTip:Boolean = true;
		private static var toolTipAbove:Boolean = true;
		private static var toolTipToTheLeft:Boolean = false;
		private static var probeToolTip:IToolTip = null;
		private static const tempBounds:IBounds2D = new Bounds2D();

		public static function destroyProbeToolTip():void
		{
			if (probeToolTip != null)
			{
				ToolTipManager.destroyToolTip(probeToolTip);
				probeToolTip = null;
			}
		}
	}
}

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

    This file is a part of Weave.

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

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

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

package weave.utils
{
	import flash.display.Stage;

	import mx.controls.ToolTip;
	import mx.core.Application;
	import mx.core.IToolTip;
	import mx.managers.ToolTipManager;
	import mx.utils.ObjectUtil;

	import weave.Weave;
	import weave.api.data.IAttributeColumn;
	import weave.api.data.IKeySet;
	import weave.api.data.IQualifiedKey;
	import weave.api.primitives.IBounds2D;
	import weave.compiler.StringLib;
	import weave.core.LinkableHashMap;
	import weave.primitives.Bounds2D;
	import weave.visualization.layers.InteractiveVisualization;
	import weave.visualization.layers.SimpleInteractiveVisualization;

	/**
	 * ProbeTextManager
	 * A static class containing functions to manage a list of probed attribute columns
	 *
	 * @author adufilie
	 */
	public class ProbeTextUtils
	{
		public static function get probedColumns():LinkableHashMap
		{
			// this initializes the probed columns object map if not created yet, otherwise just returns the existing one
			return Weave.root.requestObject("Probed Columns", LinkableHashMap, true);
		}

		public static function get probeHeaderColumns():LinkableHashMap
		{
			return Weave.root.requestObject("Probe Header Columns", LinkableHashMap, true);
		}

		/**
		 * getProbeText
		 * @param keySet The key set you are interested in.
		 * @param additionalColumns An array of additional columns (other than global probed columns) to be displayed in the probe tooltip
		 * @param maxRecordsShown Maximum no. of records shown in one probe tooltip
		 * @return A string to be displayed on a tooltip while probing
		 */
		public static function getProbeText(keySet:IKeySet, additionalColumns:Array = null):String
		{
			var result:String = '';
			var columns:Array = probedColumns.getObjects(IAttributeColumn);
			if (additionalColumns != null)
				columns = columns.concat(additionalColumns);
			var headers:Array = probeHeaderColumns.getObjects(IAttributeColumn);
			var keys:Array = keySet.keys.concat().sort(ObjectUtil.compare);
			var key:IQualifiedKey;
			var recordCount:int = 0;
			var maxRecordsShown:Number = Weave.properties.maxTooltipRecordsShown.value;
			for (var iKey:int = 0; iKey < keys.length && iKey < maxRecordsShown; iKey++)
			{
				key = keys[iKey] as IQualifiedKey;

				var record:String = '';
				for (var iHeader:int = 0; iHeader < headers.length; iHeader++)
				{
					var header:IAttributeColumn = headers[iHeader] as IAttributeColumn;
					var headerValue:String = StringLib.toString(header.getValueFromKey(key, String));
					if (headerValue == '')
						continue;
					if (record != '')
						record += ', ';
					record += headerValue;
				}

				if (record != '')
					record += '\n';
				var lookup:Object = new Object() ;
				for (var iColumn:int = 0; iColumn < columns.length; iColumn++)
				{
					var column:IAttributeColumn = columns[iColumn] as IAttributeColumn;
					var value:String = String(column.getValueFromKey(key, String));
					if (value == '' || value == 'NaN')
						continue;
					var title:String = ColumnUtils.getTitle(column);
					var line:String = StringLib.lpad(value, 8) + ' (' + title + ')\n';
					if(lookup[line]  == undefined )
					{
						if (!(value.toLowerCase() == 'undefined' || title.toLowerCase() == 'undefined'))
						{
							record += line;
							lookup[line] = true;
						}
					}
				}
				if (record != '')
				{
					result += record + '\n';
					recordCount++;
				}
			}
			// remove ending '\n'
			while (result.substr(result.length - 1) == '\n')
				result = result.substr(0, result.length - 1);

			if (result == '')
			{
				result = 'Record Identifier' + (keys.length > 1 ? 's' : '') + ':\n';
				for (var i:int = 0; i < keys.length && i < maxRecordsShown; i++)
				{
					key = keys[i] as IQualifiedKey;
					result += '    ' + key.keyType + '#' + key.localName + '\n';
					recordCount++;
				}
			}

			if (recordCount >= maxRecordsShown && keys.length > maxRecordsShown)
			{
				result += '\n... (' + keys.length + ' records total, ' + recordCount + ' shown)';
			}

			return result;
		}

		private static function setProbeToolTipAppearance():void
		{
			(probeToolTip as ToolTip).setStyle("backgroundAlpha", Weave.properties.probeToolTipBackgroundAlpha.value);
			if (isFinite(Weave.properties.probeToolTipBackgroundColor.value))
				(probeToolTip as ToolTip).setStyle("backgroundColor", Weave.properties.probeToolTipBackgroundColor.value);
		}

		public static function showProbeToolTip(probeText:String, stageX:Number, stageY:Number, bounds:IBounds2D = null, margin:int = 5):void
		{
			if (bounds == null)
			{
				var stage:Stage = Application.application.stage;
				tempBounds.setBounds(stage.x, stage.y, stage.stageWidth, stage.stageHeight);
				bounds = tempBounds;
			}
			destroyProbeToolTip();

			// create new tooltip
			probeToolTip = ToolTipManager.createToolTip(probeText, 0, 0);

			// make tooltip completely opaque because text + graphics on same sprite is slow
			setProbeToolTipAppearance() ;
			var xMin:Number = bounds.getXNumericMin();
			var yMin:Number = bounds.getYNumericMin();
			var xMax:Number = bounds.getXNumericMax() - probeToolTip.width;
			var yMax:Number = bounds.getYNumericMax() - probeToolTip.height;
			var b:Boolean = false;
			var yAxisToolTip:IToolTip = SimpleInteractiveVisualization.yAxisTooltipPtr ;
			var xAxisToolTip:IToolTip = SimpleInteractiveVisualization.xAxisTooltipPtr ;

			// calculate y coordinate
			var y:int;
			// calculate y pos depending on toolTipAbove setting
			if (toolTipAbove)
			{
				y = stageY - (probeToolTip.height + 2 * margin);
				if(yAxisToolTip != null)
					y = yAxisToolTip.y - margin - probeToolTip.height ;
			}
			else // below
			{
				y = stageY + margin * 2;
				if(yAxisToolTip != null)
					y = yAxisToolTip.y+yAxisToolTip.height+margin;
			}

			// flip y position if out of bounds
			if ((y < yMin && toolTipAbove) || (y > yMax && !toolTipAbove))
				toolTipAbove = !toolTipAbove;

			// calculate x coordinate
			var x:int;
			if (cornerToolTip)
			{
				// want toolTip corner to be near probe point
				if (toolTipToTheLeft)
				{
					x = stageX - margin - probeToolTip.width;
					if(xAxisToolTip != null)
						x = xAxisToolTip.x - margin - probeToolTip.width;
				}
				else // to the right
				{
					x = stageX + margin;
					if(xAxisToolTip != null)
						x = xAxisToolTip.x+xAxisToolTip.width+margin;
				}

				// flip x position if out of bounds
				if ((x < xMin && toolTipToTheLeft) || (x > xMax && !toolTipToTheLeft))
					toolTipToTheLeft = !toolTipToTheLeft;
			}
			else // center x coordinate
			{
				x = stageX - probeToolTip.width / 2;
			}

			// if at lower-right corner of mouse, shift to the right 10 pixels to get away from the mouse pointer
			if (x > stageX && y > stageY)
				x += 10;

			// enforce min/max values and position tooltip
			x = Math.max(xMin, Math.min(x, xMax));
			y = Math.max(yMin, Math.min(y, yMax));

			probeToolTip.move(x, y);
		}

		/**
		 * cornerToolTip:
		 * false = center of tooltip will be aligned with x probe coordinate
		 * true = corner of tooltip will be aligned with x probe coordinate
		 */
		private static var cornerToolTip:Boolean = true;
		private static var toolTipAbove:Boolean = true;
		private static var toolTipToTheLeft:Boolean = false;
		private static var probeToolTip:IToolTip = null;
		private static const tempBounds:IBounds2D = new Bounds2D();

		public static function destroyProbeToolTip():void
		{
			if (probeToolTip != null)
			{
				ToolTipManager.destroyToolTip(probeToolTip);
				probeToolTip = null;
			}
		}
	}
}

Fix Bug#283 Stop bar chart from showing "Undefined" column in probe


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

/**
  * @access private
  */
var LzMakeLoadSprite = {};

/**
  * Makes the given view able to load a remote resource
  */
LzMakeLoadSprite.transform = function (v, src, cache, headers, filetype) {
    for (var k in this) {
        if (k != "transform") {
            if (typeof v[k] == 'function') {
                // replace old method with _methodname to support super
                v[ '___' + k ] = v[k];
            }
            v[k] = this[k];
        }
    }

    if (v.__LZmovieClipRef == null || ! v.__LZhaser) {
        //the view doesn't have the empty resource. We need to try and replace it
        v.makeContainerResource();
    }

    v.createLoader(src, cache, headers, filetype);
}

/**
  * @access private
  */
LzMakeLoadSprite.createLoader = function (src, cache, headers, filetype) {
    this.loader = new LzMediaLoader(this, {});

    this.updateDel = new LzDelegate(this, "updateAfterLoad", this.loader, "onloaddone");
    this.errorDel = new LzDelegate(this, "__LZsendError", this.loader, "onerror");
    this.timeoutDel = new LzDelegate(this, "__LZsendTimeout", this.loader, "ontimeout");

    if (src != null) {
        this.setSource(src, cache, headers, filetype);
    }
}

/**
  * @access private
  * @param String src: The url from which to load the resource for this view.
  * @param String cache: If set, controls caching behavior. Choices are
  * "none" , "clientonly" , "serveronly" , "both" -- where both is the default.
  * @param String headers: Headers to send with the request (if any.)
  * @param String filetype: Filetype, e.g. 'mp3' or 'jpg'.  If not specified, it will be derived from the URL.
  */
LzMakeLoadSprite.setSource = function (src, cache, headers, filetype) {
    // unload anything currently loading...
    if (this.loader.mc.loading == true) {
        LzLoadQueue.unloadRequest(this.loader.mc);
    }

    if (src == '' || src == ' ' || src == null) {
        if ($debug) Debug.error('setSource called with an empty url');
        return;
    }

    this.stopTrackPlay();
    this.isloaded = false;
    if (this.queuedplayaction == null) {
        this.queuePlayAction("checkPlayStatus");
    }

    this.resource = src;
    //this.owner.resource = src;
    //if (this.owner.onresource) this.owner.onresource.sendEvent( src );

    this.owner.__LZvizLoad = false;
    this.owner.__LZupdateShown();
    this.loader.request(src, cache, headers, filetype);
}

/**
  * This method keeps the behavior of setResource consistent between
  * load-transformed views and those that aren't
  * @access private
  */
LzMakeLoadSprite.setResource = function (nresc) {
    // unload anything currently loading...
    if (this.loader.mc.loading == true) {
        LzLoadQueue.unloadRequest(this.loader.mc);
    }
    if (nresc == "empty") {
        // call shadowed setResource()
        this.___setResource(nresc);
    } else if (nresc.indexOf('http:') == 0 || nresc.indexOf('https:') == 0) {
        this.setSource(nresc);
    } else {
        this.loader.attachLoadMovie(nresc);
        if (this.queuedplayaction == null) {
            this.queuePlayAction("checkPlayStatus");
        }
        // make sure resource is updated, but no "onload"-event is sent
        this.updateAfterLoad(null);
        // need to call manually because no "onload"-event was sent
        this.doQueuedPlayAction();
    }
}

/**
  * Updates movieclip properties after the resource has loaded
  * @access private
  */
LzMakeLoadSprite.updateAfterLoad = function (mloader) {
    this.isloaded = true;

    var mc = this.getMCRef();
    this.resourcewidth = mc._width;
    this.resourceheight = mc._height;
    this.currentframe = mc._currentframe;

    var tfchg = this.totalframes != mc._totalframes;
    if (tfchg) {
        this.totalframes = mc._totalframes;
        this.owner.resourceevent('totalframes', this.totalframes);
    }

    if (this.totalframes > 1) {
        this.checkPlayStatus();
    }

    this.setHeight(this.hassetheight ? this.height : null);
    this.setWidth(this.hassetwidth ? this.width : null);

    // Install right-click context menu if there is one
    if (this.__contextmenu) mc.menu = this.__contextmenu.kernel.__LZcontextMenu();

    this.owner.__LZvizLoad = true;
    this.owner.__LZupdateShown();
    // skip event when called by setResource()
    var skip = (mloader == null);
    this.owner.resourceload({width: this.resourcewidth, height: this.resourceheight,
                                resource: this.resource, skiponload: skip});
    this.owner.reevaluateSize();
}

/**
  * Unloads the media
  * @access private
  */
LzMakeLoadSprite.unload = function () {
    this.loader.unload(this.loader.mc);
}

/**
  * Get a reference to the control mc
  * @access private
  */
LzMakeLoadSprite.getMCRef = function () {
    //return null if not loaded
    if (this.loader.isaudio) return this.loader.mc;
    return this.isloaded ? this.loader.getLoadMC() : null;
}

/**
  * Get the number of bytes loaded so far
  * @return: A number that is the maximum offset for this resource
  */
LzMakeLoadSprite.getLoadBytes = function () {
    return this.getMCRef().getBytesLoaded();
}

/**
  * Get the total number of bytes for the attached resource
  * @return: A number that is the maximum offset for this resource
  */
LzMakeLoadSprite.getMaxBytes = function () {
    return this.getMCRef().getBytesTotal();
}

/**
  * @access private
  */
LzMakeLoadSprite.__LZsendError = function (e) {
    this.resourcewidth = 0;
    this.resourceheight = 0;
    if (this.owner) this.owner.resourceloaderror(e)
}

/**
  * @access private
  */
LzMakeLoadSprite.__LZsendTimeout = function (e) {
    this.resourcewidth = 0;
    this.resourceheight = 0;
    if (this.owner) this.owner.resourceloadtimeout(e)
}

/**
  * @access private
  */
LzMakeLoadSprite.destroy = function () {
    if ('updateDel' in this)
         this.updateDel.unregisterAll();
    if ('errorDel' in this)
         this.errorDel.unregisterAll();
    if ('timeoutDel' in this)
         this.timeoutDel.unregisterAll();

    this.loader.unload(this.loader.mc);

    // call shadowed destroy()
    this.___destroy();
}

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

/**
  * @access private
  */
var LzMakeLoadSprite = {};

/**
  * Makes the given view able to load a remote resource
  */
LzMakeLoadSprite.transform = function (v, src, cache, headers, filetype) {
    for (var k in this) {
        if (k != "transform") {
            if (typeof v[k] == 'function') {
                // replace old method with _methodname to support super
                v[ '___' + k ] = v[k];
            }
            v[k] = this[k];
        }
    }

    if (v.__LZmovieClipRef == null || ! v.__LZhaser) {
        //the view doesn't have the empty resource. We need to try and replace it
        v.makeContainerResource();
    }

    v.createLoader(src, cache, headers, filetype);
}

/**
  * @access private
  */
LzMakeLoadSprite.createLoader = function (src, cache, headers, filetype) {
    this.loader = new LzMediaLoader(this, {});

    this.updateDel = new LzDelegate(this, "updateAfterLoad", this.loader, "onloaddone");
    this.errorDel = new LzDelegate(this, "__LZsendError", this.loader, "onerror");
    this.timeoutDel = new LzDelegate(this, "__LZsendTimeout", this.loader, "ontimeout");

    if (src != null) {
        this.setSource(src, cache, headers, filetype);
    }
}

/**
  * @access private
  * @param String src: The url from which to load the resource for this view.
  * @param String cache: If set, controls caching behavior. Choices are
  * "none" , "clientonly" , "serveronly" , "both" -- where both is the default.
  * @param String headers: Headers to send with the request (if any.)
  * @param String filetype: Filetype, e.g. 'mp3' or 'jpg'.  If not specified, it will be derived from the URL.
  */
LzMakeLoadSprite.setSource = function (src, cache, headers, filetype) {
    // unload anything currently loading...
    if (this.loader.mc.loading == true) {
        LzLoadQueue.unloadRequest(this.loader.mc);
    }

    if (src == '' || src == ' ' || src == null) {
        if ($debug) Debug.error('setSource called with an empty url');
        return;
    }

    this.stopTrackPlay();
    this.isloaded = false;
    if (this.queuedplayaction == null) {
        this.queuePlayAction("checkPlayStatus");
    }

    this.resource = src;
    //this.owner.resource = src;
    //if (this.owner.onresource) this.owner.onresource.sendEvent( src );

    if (! this.__LZbuttonRef) {
        // only hide if we're not clickable - see LPP-4957
        this.owner.__LZvizLoad = false;
        this.owner.__LZupdateShown();
    }
    this.loader.request(src, cache, headers, filetype);
}

/**
  * This method keeps the behavior of setResource consistent between
  * load-transformed views and those that aren't
  * @access private
  */
LzMakeLoadSprite.setResource = function (nresc) {
    // unload anything currently loading...
    if (this.loader.mc.loading == true) {
        LzLoadQueue.unloadRequest(this.loader.mc);
    }
    if (nresc == "empty") {
        // call shadowed setResource()
        this.___setResource(nresc);
    } else if (nresc.indexOf('http:') == 0 || nresc.indexOf('https:') == 0) {
        this.setSource(nresc);
    } else {
        this.loader.attachLoadMovie(nresc);
        if (this.queuedplayaction == null) {
            this.queuePlayAction("checkPlayStatus");
        }
        // make sure resource is updated, but no "onload"-event is sent
        this.updateAfterLoad(null);
        // need to call manually because no "onload"-event was sent
        this.doQueuedPlayAction();
    }
}

/**
  * Updates movieclip properties after the resource has loaded
  * @access private
  */
LzMakeLoadSprite.updateAfterLoad = function (mloader) {
    this.isloaded = true;

    var mc = this.getMCRef();
    this.resourcewidth = mc._width;
    this.resourceheight = mc._height;
    this.currentframe = mc._currentframe;

    var tfchg = this.totalframes != mc._totalframes;
    if (tfchg) {
        this.totalframes = mc._totalframes;
        this.owner.resourceevent('totalframes', this.totalframes);
    }

    if (this.totalframes > 1) {
        this.checkPlayStatus();
    }

    this.setHeight(this.hassetheight ? this.height : null);
    this.setWidth(this.hassetwidth ? this.width : null);

    // Install right-click context menu if there is one
    if (this.__contextmenu) mc.menu = this.__contextmenu.kernel.__LZcontextMenu();

    this.owner.__LZvizLoad = true;
    this.owner.__LZupdateShown();
    // skip event when called by setResource()
    var skip = (mloader == null);
    this.owner.resourceload({width: this.resourcewidth, height: this.resourceheight,
                                resource: this.resource, skiponload: skip});
    this.owner.reevaluateSize();
}

/**
  * Unloads the media
  * @access private
  */
LzMakeLoadSprite.unload = function () {
    this.loader.unload(this.loader.mc);
}

/**
  * Get a reference to the control mc
  * @access private
  */
LzMakeLoadSprite.getMCRef = function () {
    //return null if not loaded
    if (this.loader.isaudio) return this.loader.mc;
    return this.isloaded ? this.loader.getLoadMC() : null;
}

/**
  * Get the number of bytes loaded so far
  * @return: A number that is the maximum offset for this resource
  */
LzMakeLoadSprite.getLoadBytes = function () {
    return this.getMCRef().getBytesLoaded();
}

/**
  * Get the total number of bytes for the attached resource
  * @return: A number that is the maximum offset for this resource
  */
LzMakeLoadSprite.getMaxBytes = function () {
    return this.getMCRef().getBytesTotal();
}

/**
  * @access private
  */
LzMakeLoadSprite.__LZsendError = function (e) {
    this.resourcewidth = 0;
    this.resourceheight = 0;
    if (this.owner) this.owner.resourceloaderror(e)
}

/**
  * @access private
  */
LzMakeLoadSprite.__LZsendTimeout = function (e) {
    this.resourcewidth = 0;
    this.resourceheight = 0;
    if (this.owner) this.owner.resourceloadtimeout(e)
}

/**
  * @access private
  */
LzMakeLoadSprite.destroy = function () {
    if ('updateDel' in this)
         this.updateDel.unregisterAll();
    if ('errorDel' in this)
         this.errorDel.unregisterAll();
    if ('timeoutDel' in this)
         this.timeoutDel.unregisterAll();

    this.loader.unload(this.loader.mc);

    // call shadowed destroy()
    this.___destroy();
}

Change 20081211-maxcarlson-I by maxcarlson@Bank.lan on 2008-12-11 01:08:07 PST
    in /Users/maxcarlson/openlaszlo/trunk-clean
    for http://svn.openlaszlo.org/openlaszlo/trunk

Summary: Avoid hiding suring setSource for clickable sprites

Bugs Fixed: LPP-4957 - onclick event lost after doing setSource onmouseover

Technical Reviewer: andre.bargull@udo.edu
QA Reviewer: hminsky

Details: Only hide sprite during setSource() if the sprite is not clickable - behavior now consistent across swf8, 9 and dhtml.

Tests: See updated testcase for LPP-4957

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


package aerys.minko.render.shader.node.leaf
{
	import aerys.minko.render.shader.compiler.visitor.IShaderNodeVisitor;
	import aerys.minko.render.shader.node.IFragmentNode;
	import aerys.minko.render.shader.node.INode;

	public class Sampler extends AbstractLeaf implements IFragmentNode
	{
		public static const _SAMPLER_FILTER_STRINGS:Vector.<String> =
			Vector.<String>(['nearest', 'linear']);

		public static const _SAMPLER_MIPMAP_STRINGS:Vector.<String> =
			Vector.<String>(['mipnone', 'mipnearest', 'miplinear']);

		public static const _SAMPLER_WRAPPING_STRINGS:Vector.<String> =
			Vector.<String>(['clamp', 'repeat']);

		public static const _SAMPLER_DIMENSION_STRINGS:Vector.<String> =
			Vector.<String>(['2d', 'cube', '3d']);

		public static const FILTER_NEAREST	: uint = 0;
		public static const FILTER_LINEAR	: uint = 1;

		public static const MIPMAP_DISABLE	: uint = 0;
		public static const MIPMAP_NEAREST	: uint = 1;
		public static const MIPMAP_LINEAR	: uint = 2;

		public static const WRAPPING_CLAMP	: uint = 0;
		public static const WRAPPING_REPEAT	: uint = 1;

		public static const DIMENSION_2D	: uint = 0;
		public static const DIMENSION_CUBE	: uint = 1;

		protected var _id			: uint;
		protected var _styleId		: int;
		protected var _filter		: uint;
		protected var _mipmap		: uint;
		protected var _wrapping		: uint;
		protected var _dimension	: uint;

		override public function get size() : uint
		{
			return 0;
		}

		public function get styleId() : int
		{
			return _styleId;
		}

		public function get filter() : uint
		{
			return _filter;
		}

		public function get mipmap() : uint
		{
			return _mipmap;
		}

		public function get wrapping() : uint
		{
			return _wrapping;
		}

		public function get dimension() : uint
		{
			return _dimension;
		}

		public function get samplerId() : uint
		{
			return _id;
		}

		public function set samplerId(value : uint) : void
		{
			_id = value;
		}

		public function Sampler(styleId		: int,
								filter		: uint	= FILTER_LINEAR,
								mipmap		: uint	= MIPMAP_DISABLE,
								wrapping	: uint	= WRAPPING_REPEAT,
								dimension	: uint	= DIMENSION_2D)
		{
			super();

			_styleId	= styleId;
			_filter		= filter;
			_mipmap		= mipmap;
			_wrapping	= wrapping;
			_dimension	= dimension;
		}

		override public function isSame(otherNode : INode) : Boolean
		{
			var samplerOtherNode : Sampler = otherNode as Sampler;
			if (samplerOtherNode == null)
				return false;

			return _styleId	== samplerOtherNode._styleId
				&& _filter		== samplerOtherNode._filter
				&& _mipmap		== samplerOtherNode._mipmap
				&& _wrapping	== samplerOtherNode._wrapping
				&& _dimension	== samplerOtherNode._dimension
		}

		override public function toString() : String
		{
			return "Sampler\\nname=" + styleId;
		}
	}
}

package aerys.minko.render.shader.node.leaf
{
	import aerys.minko.render.shader.node.IFragmentNode;
	import aerys.minko.render.shader.node.INode;

	public class Sampler extends AbstractLeaf implements IFragmentNode
	{
		public static const _SAMPLER_FILTER_STRINGS:Vector.<String> =
			Vector.<String>(['nearest', 'linear']);

		public static const _SAMPLER_MIPMAP_STRINGS:Vector.<String> =
			Vector.<String>(['mipnone', 'mipnearest', 'miplinear']);

		public static const _SAMPLER_WRAPPING_STRINGS:Vector.<String> =
			Vector.<String>(['clamp', 'repeat']);

		public static const _SAMPLER_DIMENSION_STRINGS:Vector.<String> =
			Vector.<String>(['2d', 'cube', '3d']);

		public static const FILTER_NEAREST	: uint = 0;
		public static const FILTER_LINEAR	: uint = 1;

		public static const MIPMAP_DISABLE	: uint = 0;
		public static const MIPMAP_NEAREST	: uint = 1;
		public static const MIPMAP_LINEAR	: uint = 2;

		public static const WRAPPING_CLAMP	: uint = 0;
		public static const WRAPPING_REPEAT	: uint = 1;

		public static const DIMENSION_2D	: uint = 0;
		public static const DIMENSION_CUBE	: uint = 1;

		protected var _id			: uint;
		protected var _styleId		: int;
		protected var _filter		: uint;
		protected var _mipmap		: uint;
		protected var _wrapping		: uint;
		protected var _dimension	: uint;

		override public function get size() : uint
		{
			return 0;
		}

		public function get styleId() : int
		{
			return _styleId;
		}

		public function get filter() : uint
		{
			return _filter;
		}

		public function get mipmap() : uint
		{
			return _mipmap;
		}

		public function get wrapping() : uint
		{
			return _wrapping;
		}

		public function get dimension() : uint
		{
			return _dimension;
		}

		public function get samplerId() : uint
		{
			return _id;
		}

		public function set samplerId(value : uint) : void
		{
			_id = value;
		}

		public function Sampler(styleId		: int,
								filter		: uint	= FILTER_LINEAR,
								mipmap		: uint	= MIPMAP_DISABLE,
								wrapping	: uint	= WRAPPING_REPEAT,
								dimension	: uint	= DIMENSION_2D)
		{
			super();

			_styleId	= styleId;
			_filter		= filter;
			_mipmap		= mipmap;
			_wrapping	= wrapping;
			_dimension	= dimension;
		}

		override public function isSame(otherNode : INode) : Boolean
		{
			var samplerOtherNode : Sampler = otherNode as Sampler;
			if (samplerOtherNode == null)
				return false;

			return _styleId	== samplerOtherNode._styleId
				&& _filter		== samplerOtherNode._filter
				&& _mipmap		== samplerOtherNode._mipmap
				&& _wrapping	== samplerOtherNode._wrapping
				&& _dimension	== samplerOtherNode._dimension
		}

		override public function toString() : String
		{
			return "Sampler\\nname=" + styleId;
		}
	}
}

Remove unused import

Remove unused import


##                                                         -*- shell-script -*-
## base.as: This file is part of build-aux.
## Copyright (C) Gostai S.A.S., 2006-2008.
##
## This software is provided "as is" without warranty of any kind,
## either expressed or implied, including but not limited to the
## implied warranties of fitness for a particular purpose.
##
## See the LICENSE file for more information.
## For comments, bug reports and feedback: http://www.urbiforge.com
##

m4_pattern_forbid([^_?URBI_])dnl

# m4_define([_m4_divert(M4SH-INIT)],   5)
m4_define([_m4_divert(URBI-INIT)],    10)

m4_defun([_URBI_ABSOLUTE_PREPARE],
[
# is_absolute PATH
# ----------------
is_absolute ()
{
  case $[1] in
    ([[\\/]]* | ?:[[\\/]]*) return 0;;
    (                    *) return 1;;
  esac
}

# absolute NAME -> ABS-NAME
# -------------------------
# Return an absolute path to NAME.
absolute ()
{
  local res
  AS_IF([is_absolute "$[1]"],
  [# Absolute paths do not need to be expanded.
   res=$[1]],
  [local dir=$(pwd)/$(dirname "$[1]")
   if test -d "$dir"; then
     res=$(cd "$dir" 2>/dev/null && pwd)/$(basename "$[1]")
   else
     fatal "absolute: not a directory: $dir"
   fi])

  # On Windows, we must make sure we have a Windows-like UNIX-friendly path (of
  # the form C:/cygwin/path/to/somewhere instead of /path/to/somewhere, notice
  # the use of forward slashes in the Windows path.  Windows *does* understand
  # paths with forward slashes).
  case $(uname -s) in
    (CYGWIN*) res=$(cygpath "$res")
  esac
  echo "$res"
}
])

m4_defun([_URBI_FIND_PROG_PREPARE],
[# find_prog PROG PATH
# -------------------
# Return full path to PROG in PATH ($PATH_SEPARATOR separated),
# nothing if not found.
find_prog ()
{
  _AS_PATH_WALK([$[2]],
                [AS_IF([AS_TEST_X([$as_dir/$[1]])],
                       [echo "$as_dir/$[1]"; break])])
}
])

m4_defun([_URBI_STDERR_PREPARE],
[
# stderr LINES
# ------------
stderr ()
{
  local i
  for i
  do
    echo >&2 "$as_me: $i"
  done
  echo >&2
}

# error EXIT MESSAGES
# -------------------
error ()
{
  local exit=$[1]
  shift
  stderr "$[@]"
  ex_exit $exit
}

# fatal MESSAGES
# --------------
fatal ()
{
  # To help the user, just make sure that she is not confused between
  # the prototypes of fatal and error: the first argument is unlikely
  # to be integer.
  case $[1] in
    ([!0-9]) ;;
    (*)  stderr "warning: possible confusion between fatal and error";;
  esac

  error 1 "$[@]"
}

# ex_to_string EXIT
# -----------------
# Return a decoding of EXIT status if available, nothing otherwise.
ex_to_string ()
{
  case $[1] in
     (  0) echo ' (EX_OK: successful termination)';;
     ( 64) echo ' (EX_USAGE: command line usage error)';;
     ( 65) echo ' (EX_DATAERR: data format error)';;
     ( 66) echo ' (EX_NOINPUT: cannot open input)';;
     ( 67) echo ' (EX_NOUSER: addressee unknown)';;
     ( 68) echo ' (EX_NOHOST: host name unknown)';;
     ( 69) echo ' (EX_UNAVAILABLE: service unavailable)';;
     ( 70) echo ' (EX_SOFTWARE: internal software error)';;
     ( 71) echo ' (EX_OSERR: system error (e.g., cannot fork))';;
     ( 72) echo ' (EX_OSFILE: critical OS file missing)';;
     ( 73) echo ' (EX_CANTCREAT: cannot create (user) output file)';;
     ( 74) echo ' (EX_IOERR: input/output error)';;
     ( 75) echo ' (EX_TEMPFAIL: temp failure; user is invited to retry)';;
     ( 76) echo ' (EX_PROTOCOL: remote error in protocol)';;
     ( 77) echo ' (EX_NOPERM: permission denied)';;
     ( 78) echo ' (EX_CONFIG: configuration error)';;
     (176) echo ' (EX_SKIP: skip this test with unmet dependencies)';;
     (177) echo ' (EX_HARD: hard error that cannot be saved)';;
     (242) echo ' (killed by Valgrind)';;
     (  *) if test 127 -lt $[1]; then
            echo " (SIG$(kill -l $[1] || true))"
          fi;;
  esac
}

# ex_to_int CODE
# --------------
# Decode the CODE and return the corresponding int.
ex_to_int ()
{
  case $[1] in
    (OK         |EX_OK)          echo 0;;
    (USAGE      |EX_USAGE)       echo 64;;
    (DATAERR    |EX_DATAERR)     echo 65;;
    (NOINPUT    |EX_NOINPUT)     echo 66;;
    (NOUSER     |EX_NOUSER)      echo 67;;
    (NOHOST     |EX_NOHOST)      echo 68;;
    (UNAVAILABLE|EX_UNAVAILABLE) echo 69;;
    (SOFTWARE   |EX_SOFTWARE)    echo 70;;
    (OSERR      |EX_OSERR)       echo 71;;
    (OSFILE     |EX_OSFILE)      echo 72;;
    (CANTCREAT  |EX_CANTCREAT)   echo 73;;
    (IOERR      |EX_IOERR)       echo 74;;
    (TEMPFAIL   |EX_TEMPFAIL)    echo 75;;
    (PROTOCOL   |EX_PROTOCOL)    echo 76;;
    (NOPERM     |EX_NOPERM)      echo 77;;
    (CONFIG     |EX_CONFIG)      echo 78;;

    (SKIP       |EX_SKIP)        echo 176;;
    (HARD       |EX_HARD)        echo 177;;

    (*)                          echo $[1];;
  esac
}

ex_exit ()
{
  exit $(ex_to_int $[1])
}
])

# URBI_GET_OPTIONS
# ----------------
# Generate get_options().
m4_define([URBI_GET_OPTIONS],
[# Parse command line options
get_options ()
{
  while test $[#] -ne 0; do
    case $[1] in
        (--*=*)
            opt=$(echo "$[1]" | sed -e 's/=.*//')
            val=$(echo "$[1]" | sed -e ['s/[^=]*=//'])
            shift
            set dummy "$opt" "$val" ${1+"$[@]"};
            shift
            ;;
    esac

    case $[1] in
      $@
    esac
    shift
  done
}
])

m4_defun([_URBI_PREPARE],
[
# truth TEST-ARGUMENTS...
# -----------------------
# Run "test TEST-ARGUMENTS" and echo true/false depending on the result.
truth ()
{
  if test "$[@]"; then
    echo true
  else
    echo false
  fi
}

_URBI_ABSOLUTE_PREPARE
_URBI_FIND_PROG_PREPARE
_URBI_STDERR_PREPARE

])

# URBI_PREPARE
# ------------
# Output all the M4sh possible initialization into the initialization
# diversion.
m4_defun([URBI_PREPARE],
[m4_divert_text([M4SH-INIT], [_URBI_PREPARE])dnl
URBI_RST_PREPARE()dnl
URBI_INSTRUMENT_PREPARE()dnl
URBI_CHILDREN_PREPARE()dnl
])

# URBI_INIT
# ---------
# Replaces the AS_INIT invocation.
# Must be defined via "m4_define", not "m4_defun" since it is AS_INIT
# which will set up the diversions used for "m4_defun".
m4_define([URBI_INIT],
[AS_INIT()dnl
URBI_PREPARE()
set -e
case $VERBOSE in
  (x) set -x;;
esac

: ${abs_builddir='@abs_builddir@'}
: ${abs_top_builddir='@abs_top_builddir@'}
: ${abs_top_srcdir='@abs_top_srcdir@'}
])

##                                                         -*- shell-script -*-
## base.as: This file is part of build-aux.
## Copyright (C) Gostai S.A.S., 2006-2008.
##
## This software is provided "as is" without warranty of any kind,
## either expressed or implied, including but not limited to the
## implied warranties of fitness for a particular purpose.
##
## See the LICENSE file for more information.
## For comments, bug reports and feedback: http://www.urbiforge.com
##

m4_pattern_forbid([^_?URBI_])dnl

# m4_define([_m4_divert(M4SH-INIT)],   5)
m4_define([_m4_divert(URBI-INIT)],    10)

m4_defun([_URBI_ABSOLUTE_PREPARE],
[
# is_absolute PATH
# ----------------
is_absolute ()
{
  case $[1] in
    ([[\\/]]* | ?:[[\\/]]*) return 0;;
    (                    *) return 1;;
  esac
}

# absolute NAME -> ABS-NAME
# -------------------------
# Return an absolute path to NAME.
absolute ()
{
  local res
  AS_IF([is_absolute "$[1]"],
  [# Absolute paths do not need to be expanded.
   res=$[1]],
  [local dir=$(pwd)/$(dirname "$[1]")
   if test -d "$dir"; then
     res=$(cd "$dir" 2>/dev/null && pwd)/$(basename "$[1]")
   else
     fatal "absolute: not a directory: $dir"
   fi])

  # On Windows, we must make sure we have a Windows-like UNIX-friendly path (of
  # the form C:/cygwin/path/to/somewhere instead of /path/to/somewhere, notice
  # the use of forward slashes in the Windows path.  Windows *does* understand
  # paths with forward slashes).
  case $(uname -s) in
    (CYGWIN*) res=$(cygpath "$res")
  esac
  echo "$res"
}
])

m4_defun([_URBI_FIND_PROG_PREPARE],
[# find_prog PROG PATH
# -------------------
# Return full path to PROG in PATH ($PATH_SEPARATOR separated),
# nothing if not found.
find_prog ()
{
  _AS_PATH_WALK([$[2]],
                [AS_IF([AS_TEST_X([$as_dir/$[1]])],
                       [echo "$as_dir/$[1]"; break])])
}
])

m4_defun([_URBI_STDERR_PREPARE],
[
# stderr LINES
# ------------
stderr ()
{
  local i
  for i
  do
    echo >&2 "$as_me: $i"
  done
  echo >&2
}

# error EXIT MESSAGES
# -------------------
error ()
{
  local exit=$[1]
  shift
  stderr "$[@]"
  ex_exit $exit
}

# fatal MESSAGES
# --------------
fatal ()
{
  # To help the user, just make sure that she is not confused between
  # the prototypes of fatal and error: the first argument is unlikely
  # to be integer.
  case $[1] in
    (*[[!0-9]]*|'') ;;
    (*)  stderr "warning: possible confusion between fatal and error" \
                "fatal $[*]";;
  esac

  error 1 "$[@]"
}

# ex_to_string EXIT
# -----------------
# Return a decoding of EXIT status if available, nothing otherwise.
ex_to_string ()
{
  case $[1] in
     (  0) echo ' (EX_OK: successful termination)';;
     ( 64) echo ' (EX_USAGE: command line usage error)';;
     ( 65) echo ' (EX_DATAERR: data format error)';;
     ( 66) echo ' (EX_NOINPUT: cannot open input)';;
     ( 67) echo ' (EX_NOUSER: addressee unknown)';;
     ( 68) echo ' (EX_NOHOST: host name unknown)';;
     ( 69) echo ' (EX_UNAVAILABLE: service unavailable)';;
     ( 70) echo ' (EX_SOFTWARE: internal software error)';;
     ( 71) echo ' (EX_OSERR: system error (e.g., cannot fork))';;
     ( 72) echo ' (EX_OSFILE: critical OS file missing)';;
     ( 73) echo ' (EX_CANTCREAT: cannot create (user) output file)';;
     ( 74) echo ' (EX_IOERR: input/output error)';;
     ( 75) echo ' (EX_TEMPFAIL: temp failure; user is invited to retry)';;
     ( 76) echo ' (EX_PROTOCOL: remote error in protocol)';;
     ( 77) echo ' (EX_NOPERM: permission denied)';;
     ( 78) echo ' (EX_CONFIG: configuration error)';;
     (176) echo ' (EX_SKIP: skip this test with unmet dependencies)';;
     (177) echo ' (EX_HARD: hard error that cannot be saved)';;
     (242) echo ' (killed by Valgrind)';;
     (  *) if test 127 -lt $[1]; then
            echo " (SIG$(kill -l $[1] || true))"
          fi;;
  esac
}

# ex_to_int CODE
# --------------
# Decode the CODE and return the corresponding int.
ex_to_int ()
{
  case $[1] in
    (OK         |EX_OK)          echo 0;;
    (USAGE      |EX_USAGE)       echo 64;;
    (DATAERR    |EX_DATAERR)     echo 65;;
    (NOINPUT    |EX_NOINPUT)     echo 66;;
    (NOUSER     |EX_NOUSER)      echo 67;;
    (NOHOST     |EX_NOHOST)      echo 68;;
    (UNAVAILABLE|EX_UNAVAILABLE) echo 69;;
    (SOFTWARE   |EX_SOFTWARE)    echo 70;;
    (OSERR      |EX_OSERR)       echo 71;;
    (OSFILE     |EX_OSFILE)      echo 72;;
    (CANTCREAT  |EX_CANTCREAT)   echo 73;;
    (IOERR      |EX_IOERR)       echo 74;;
    (TEMPFAIL   |EX_TEMPFAIL)    echo 75;;
    (PROTOCOL   |EX_PROTOCOL)    echo 76;;
    (NOPERM     |EX_NOPERM)      echo 77;;
    (CONFIG     |EX_CONFIG)      echo 78;;

    (SKIP       |EX_SKIP)        echo 176;;
    (HARD       |EX_HARD)        echo 177;;

    (*)                          echo $[1];;
  esac
}

ex_exit ()
{
  exit $(ex_to_int $[1])
}
])

# URBI_GET_OPTIONS
# ----------------
# Generate get_options().
m4_define([URBI_GET_OPTIONS],
[# Parse command line options
get_options ()
{
  while test $[#] -ne 0; do
    case $[1] in
        (--*=*)
            opt=$(echo "$[1]" | sed -e 's/=.*//')
            val=$(echo "$[1]" | sed -e ['s/[^=]*=//'])
            shift
            set dummy "$opt" "$val" ${1+"$[@]"};
            shift
            ;;
    esac

    case $[1] in
      $@
    esac
    shift
  done
}
])

m4_defun([_URBI_PREPARE],
[
# truth TEST-ARGUMENTS...
# -----------------------
# Run "test TEST-ARGUMENTS" and echo true/false depending on the result.
truth ()
{
  if test "$[@]"; then
    echo true
  else
    echo false
  fi
}

_URBI_ABSOLUTE_PREPARE
_URBI_FIND_PROG_PREPARE
_URBI_STDERR_PREPARE

])

# URBI_PREPARE
# ------------
# Output all the M4sh possible initialization into the initialization
# diversion.
m4_defun([URBI_PREPARE],
[m4_divert_text([M4SH-INIT], [_URBI_PREPARE])dnl
URBI_RST_PREPARE()dnl
URBI_INSTRUMENT_PREPARE()dnl
URBI_CHILDREN_PREPARE()dnl
])

# URBI_INIT
# ---------
# Replaces the AS_INIT invocation.
# Must be defined via "m4_define", not "m4_defun" since it is AS_INIT
# which will set up the diversions used for "m4_defun".
m4_define([URBI_INIT],
[AS_INIT()dnl
URBI_PREPARE()
set -e
case $VERBOSE in
  (x) set -x;;
esac

: ${abs_builddir='@abs_builddir@'}
: ${abs_top_builddir='@abs_top_builddir@'}
: ${abs_top_srcdir='@abs_top_srcdir@'}
])

Fix fatal (not the converse).

Fix fatal (not the converse).

	* build-aux/base.as (fatal): Beware of M4 quotation.