package org.arisgames.editor.components
{
import com.ninem.controls.TreeBrowser;
import com.ninem.events.TreeBrowserEvent;

import flash.events.MouseEvent;

import mx.containers.Panel;
import mx.controls.Alert;
import mx.controls.Button;
import mx.controls.DataGrid;
import mx.core.ClassFactory;
import mx.events.DynamicEvent;
import mx.events.FlexEvent;
import mx.managers.PopUpManager;
import mx.rpc.Responder;

import org.arisgames.editor.data.arisserver.Media;
import org.arisgames.editor.data.businessobjects.ObjectPaletteItemBO;
import org.arisgames.editor.models.GameModel;
import org.arisgames.editor.services.AppServices;
import org.arisgames.editor.util.AppConstants;
import org.arisgames.editor.util.AppDynamicEventManager;
import org.arisgames.editor.util.AppUtils;

public class ItemEditorMediaPickerView extends Panel
{
    // Data Object
	public var delegate:Object;
    private var objectPaletteItem:ObjectPaletteItemBO;
    private var isIconPicker:Boolean = false;
	private var isNPC:Boolean = false;
	private var uploadFormVisable:Boolean = false;

    // Media Data
    [Bindable] public var xmlData:XML;

    // GUI
    [Bindable] public var treeBrowser:TreeBrowser;
    [Bindable] public var closeButton:Button;
	[Bindable] public var selectButton:Button;

	// Tree Icons
	[Bindable]
	[Embed(source="assets/img/separator.png")]
	public var separatorIcon:Class; //If these names are changed, make sure it is also changed in AppConstants (MEDIATREEICON_*)

	[Bindable]
	[Embed(source="assets/img/upload.png")]
	public var uploadIcon:Class; //If these names are changed, make sure it is also changed in AppConstants (MEDIATREEICON_*)

	private var mediaUploader:ItemEditorMediaPickerUploadFormMX;

    /**
     * Constructor
     */
    public function ItemEditorMediaPickerView()
    {
        super();
        this.addEventListener(FlexEvent.CREATION_COMPLETE, handleInit);
    }

    private function handleInit(event:FlexEvent):void
    {
        trace("in ItemEditorMediaPickerView's handleInit");
        var cf:ClassFactory = new ClassFactory(ItemEditorMediaPickerCustomEditorMX);
        cf.properties = {objectPaletteItem: this.objectPaletteItem};
        treeBrowser.detailRenderer = cf;
        treeBrowser.addEventListener(TreeBrowserEvent.NODE_SELECTED, onNodeSelected);
        closeButton.addEventListener(MouseEvent.CLICK, handleCloseButton);
		selectButton.addEventListener(MouseEvent.CLICK, handleSelectButton);
        // Load Game's Media Into XML
        AppServices.getInstance().getMediaForGame(GameModel.getInstance().game.gameId, new Responder(handleLoadingOfMediaIntoXML, handleFault));
    }

    private function printXMLData():void
    {
        trace("XML Data = '" + xmlData.toXMLString() + "'");
    }

    public function setObjectPaletteItem(opi:ObjectPaletteItemBO):void
    {
        trace("setting objectPaletteItem with name = '" + opi.name + "' in ItemEditorPlaqueView");
        objectPaletteItem = opi;
    }

    public function isInIconPickerMode():Boolean
    {
        return isIconPicker;
    }

    public function setIsIconPicker(isIconPickerMode:Boolean):void
    {
        trace("setting isIconPicker mode to: " + isIconPickerMode);
        this.isIconPicker = isIconPickerMode;
        this.updateTitleBasedOnMode();
    }

    private function updateTitleBasedOnMode():void
    {
        if (isIconPicker)
        {
            title = "Icon Picker";
        }
        else
        {
            title = "Media Picker";
        }
    }

    private function handleCloseButton(evt:MouseEvent):void
    {
        trace("ItemEditorMediaPickerView: handleCloseButton()");
		PopUpManager.removePopUp(this);
    }

	private function handleSelectButton(evt:MouseEvent):void
	{
		trace("Select Button clicked...");

		var m:Media = new Media();
		m.mediaId = treeBrowser.selectedItem.@mediaId;
		m.name = treeBrowser.selectedItem.@name;
		m.type = treeBrowser.selectedItem.@type;
		m.urlPath = treeBrowser.selectedItem.@urlPath;
		m.fileName = treeBrowser.selectedItem.@fileName;
		m.isDefault = treeBrowser.selectedItem.@isDefault;

		if (delegate.hasOwnProperty("didSelectMediaItem")){
			delegate.didSelectMediaItem(this, m);
		}

		PopUpManager.removePopUp(this);
	}

    private function handleLoadingOfMediaIntoXML(obj:Object):void
    {
		if(this.objectPaletteItem.objectType == AppConstants.CONTENTTYPE_CHARACTER_DATABASE){
			this.isNPC = true;
			trace("This is an NPC, so disallow Audio/Visual media");
		}

        trace("In handleLoadingOfMediaIntoXML() Result called with obj = " + obj + "; Result = " + obj.result);
        if (obj.result.returnCode != 0)
        {
            trace("Bad loading of media attempt... let's see what happened.  Error = '" + obj.result.returnCodeDescription + "'");
            var msg:String = obj.result.returnCodeDescription;
            Alert.show("Error Was: " + msg, "Error While Loading Media");
			return;
        }

        //Init the XML Data
		xmlData = new XML('<nodes label="' + AppConstants.MEDIATYPE + '"/>');

		if (!this.isIconPicker && !this.isNPC) {
			xmlData.appendChild('<node label="' + AppConstants.MEDIATYPE_IMAGE + '"/>');
			xmlData.appendChild('<node label="' + AppConstants.MEDIATYPE_AUDIO + '"/>');
			xmlData.appendChild('<node label="' + AppConstants.MEDIATYPE_VIDEO + '"/>');
		}

		this.printXMLData();

		var media:Array = obj.result.data as Array;
        trace("Number of Media Objects returned from server = '" + media.length + "'");

		//Puts media items in xml readable format
		var numImageDefaults:Number = 0;
		var numAudioDefaults:Number = 0;
		var numVideoDefaults:Number = 0;
		var numIconDefaults:Number = 0;
		for (var k:Number = 0; k <= 1; k++) //Iterates over list twice; once for uploaded items, again for default
		{
			for (var j:Number = 0; j < media.length; j++)
			{
				var o:Object = media[j];

				if((k==0 && !o.is_default) || (k==1 && o.is_default)){
					var m:Media = new Media();

					m.mediaId = o.media_id;
					m.name = o.name;
					m.type = o.type;
					m.urlPath = o.url_path;
					m.fileName = o.file_name;
					m.isDefault = o.is_default; //for both default files and uploaded files

					var node:String = "<node label='" + AppUtils.filterStringToXMLEscapeCharacters(m.name) + "' mediaId='" + m.mediaId + "' type='" + m.type + "' urlPath='" + m.urlPath + "' fileName='" + m.fileName + "' isDefault='" + m.isDefault + "'/>";

					switch (m.type)
					{
						case AppConstants.MEDIATYPE_IMAGE:
							if(!this.isNPC){
								if (!this.isIconPicker) {
									//Only add "-----------" (AppConstants.MEDIATYPE_SEPARATOR) if there are also defaults to choose from
									if(k > numImageDefaults) xmlData.node.(@label == AppConstants.MEDIATYPE_IMAGE).appendChild('<node label="' + AppConstants.MEDIATYPE_SEPARATOR + '" icon="'+ AppConstants.MEDIATREEICON_SEPARATOR +'"/>');
									xmlData.node.(@label == AppConstants.MEDIATYPE_IMAGE).appendChild(node);
									numImageDefaults+=k;
								}
							}
							else{
								if (!this.isIconPicker) {
									if(k > numIconDefaults) xmlData.appendChild('<node label="' + AppConstants.MEDIATYPE_SEPARATOR + '" icon="'+ AppConstants.MEDIATREEICON_SEPARATOR +'"/>');
									xmlData.appendChild(node);
									numIconDefaults+=k;
								}
							}
							break;
						case AppConstants.MEDIATYPE_AUDIO:
							if (!this.isIconPicker && !this.isNPC) {
								//Only add "-----------" (AppConstants.MEDIATYPE_SEPARATOR) if there are also defaults to choose from
								if(k > numAudioDefaults) xmlData.node.(@label == AppConstants.MEDIATYPE_AUDIO).appendChild('<node label="' + AppConstants.MEDIATYPE_SEPARATOR + '" icon="'+ AppConstants.MEDIATREEICON_SEPARATOR +'"/>');
								xmlData.node.(@label == AppConstants.MEDIATYPE_AUDIO).appendChild(node);
								numAudioDefaults+=k;
							}
							break;
						case AppConstants.MEDIATYPE_VIDEO:
							if (!this.isIconPicker && !this.isNPC) {
								//Only add "-----------" (AppConstants.MEDIATYPE_SEPARATOR) if there are also defaults to choose from
								if(k > numVideoDefaults) xmlData.node.(@label == AppConstants.MEDIATYPE_VIDEO).appendChild('<node label="' + AppConstants.MEDIATYPE_SEPARATOR + '" icon="'+ AppConstants.MEDIATREEICON_SEPARATOR +'"/>');
								xmlData.node.(@label == AppConstants.MEDIATYPE_VIDEO).appendChild(node);
								numVideoDefaults+=k;
							}
							break;
						case AppConstants.MEDIATYPE_ICON:
							if (this.isIconPicker) {
								trace("hello?:"+node);
								if(k > numIconDefaults) xmlData.appendChild('<node label="' + AppConstants.MEDIATYPE_SEPARATOR + '" icon="'+ AppConstants.MEDIATREEICON_SEPARATOR +'"/>');
								xmlData.appendChild(node);
								numIconDefaults+=k;
							}
							break;
						default:
							trace("Default statement reached in load media.  This SHOULD NOT HAPPEN.  The offending mediaId = '" + m.mediaId + "' and type = '" + m.type + "'");
							break;
					}
				}
			}

			//Add "Upload new" in between uploaded and default pictures
			if(k==0 && (!this.isIconPicker && !this.isNPC)){
				xmlData.node.(@label == AppConstants.MEDIATYPE_IMAGE).appendChild('<node label="' + AppConstants.MEDIATYPE_UPLOADNEW + '" icon="'+ AppConstants.MEDIATREEICON_UPLOAD +'"/>');
				xmlData.node.(@label == AppConstants.MEDIATYPE_AUDIO).appendChild('<node label="' + AppConstants.MEDIATYPE_UPLOADNEW + '" icon="'+ AppConstants.MEDIATREEICON_UPLOAD +'"/>');
				xmlData.node.(@label == AppConstants.MEDIATYPE_VIDEO).appendChild('<node label="' + AppConstants.MEDIATYPE_UPLOADNEW + '" icon="'+ AppConstants.MEDIATREEICON_UPLOAD +'"/>');
			}
			else if(k == 0){
				xmlData.appendChild('<node label="' + AppConstants.MEDIATYPE_UPLOADNEW + '" icon="'+ AppConstants.MEDIATREEICON_UPLOAD +'"/>');
			}
		}
        trace("ItemEditorMediaPickerView: handleLoadingOfMediaIntoXML: Just finished loading Media Objects into XML.  Here's what the new XML looks like:");
        this.printXMLData();

        trace("Finished with handleLoadingOfMediaIntoXML().");
    }

    public function handleFault(obj:Object):void
    {
        trace("Fault called: " + obj.message);
        Alert.show("Error occurred: " + obj.message, "Problems Loading Media");
    }

    private function onNodeSelected(event:TreeBrowserEvent):void
    {
        if (!event.isBranch)
        {
            if (event.item.@label == AppConstants.MEDIATYPE_UPLOADNEW)
            {
                if (uploadFormVisable == false) {
					trace("ItemEditorMediaPickerView: onNodeSelected label == MEDIATYPE_UPLOADNEW, display form");
					selectButton.enabled = false;
					uploadFormVisable = true;
	                this.displayMediaUploader();
					PopUpManager.removePopUp(this);
				}
				else trace("ItemEditorMediaPickerView: ignored second TreeBrowserEvent == MEDIATYPE_UPLOADNEW");

            }
			else if(event.item.@label == AppConstants.MEDIATYPE_SEPARATOR){
				//Do Nothing
				trace("Separator Selected");
				selectButton.enabled = false;
			}
            else
            {
                trace("ItemEditorMediaPickerView: onNodeSelected is a media item");
				selectButton.enabled = true;
            }
        }
		else {
			selectButton.enabled = false;
		}
    }

    private function displayMediaUploader():void
    {
        trace("itemEditorMediaPickerPickerView: displayMediaUploader");
        mediaUploader = new ItemEditorMediaPickerUploadFormMX();
		mediaUploader.isIconPicker = this.isIconPicker;
		mediaUploader.delegate = this;
        PopUpManager.addPopUp(mediaUploader, AppUtils.getInstance().getMainView(), true);
		PopUpManager.centerPopUp(mediaUploader);
    }

	public function didUploadMedia(uploader:ItemEditorMediaPickerUploadFormMX, m:Media):void{
		trace("ItemEditorMediaPicker: didUploadMedia");

		uploadFormVisable = false;

		if (delegate.hasOwnProperty("didSelectMediaItem")){
			delegate.didSelectMediaItem(this, m);
		}

		PopUpManager.removePopUp(uploader);
	}

}
}

package org.arisgames.editor.components
{
import com.ninem.controls.TreeBrowser;
import com.ninem.events.TreeBrowserEvent;

import flash.events.MouseEvent;

import mx.containers.Panel;
import mx.controls.Alert;
import mx.controls.Button;
import mx.controls.DataGrid;
import mx.core.ClassFactory;
import mx.events.DynamicEvent;
import mx.events.FlexEvent;
import mx.managers.PopUpManager;
import mx.rpc.Responder;

import org.arisgames.editor.data.arisserver.Media;
import org.arisgames.editor.data.businessobjects.ObjectPaletteItemBO;
import org.arisgames.editor.models.GameModel;
import org.arisgames.editor.services.AppServices;
import org.arisgames.editor.util.AppConstants;
import org.arisgames.editor.util.AppDynamicEventManager;
import org.arisgames.editor.util.AppUtils;

public class ItemEditorMediaPickerView extends Panel
{
    // Data Object
	public var delegate:Object;
    private var objectPaletteItem:ObjectPaletteItemBO;
    private var isIconPicker:Boolean = false;
	private var isNPC:Boolean = false;
	private var uploadFormVisable:Boolean = false;

    // Media Data
    [Bindable] public var xmlData:XML;

    // GUI
    [Bindable] public var treeBrowser:TreeBrowser;
    [Bindable] public var closeButton:Button;
	[Bindable] public var selectButton:Button;

	// Tree Icons
	[Bindable]
	[Embed(source="assets/img/separator.png")]
	public var separatorIcon:Class; //If these names are changed, make sure it is also changed in AppConstants (MEDIATREEICON_*)

	[Bindable]
	[Embed(source="assets/img/upload.png")]
	public var uploadIcon:Class; //If these names are changed, make sure it is also changed in AppConstants (MEDIATREEICON_*)

	private var mediaUploader:ItemEditorMediaPickerUploadFormMX;

    /**
     * Constructor
     */
    public function ItemEditorMediaPickerView()
    {
        super();
        this.addEventListener(FlexEvent.CREATION_COMPLETE, handleInit);
    }

    private function handleInit(event:FlexEvent):void
    {
        trace("in ItemEditorMediaPickerView's handleInit");
        var cf:ClassFactory = new ClassFactory(ItemEditorMediaPickerCustomEditorMX);
        cf.properties = {objectPaletteItem: this.objectPaletteItem};
        treeBrowser.detailRenderer = cf;
        treeBrowser.addEventListener(TreeBrowserEvent.NODE_SELECTED, onNodeSelected);
        closeButton.addEventListener(MouseEvent.CLICK, handleCloseButton);
		selectButton.addEventListener(MouseEvent.CLICK, handleSelectButton);
        // Load Game's Media Into XML
        AppServices.getInstance().getMediaForGame(GameModel.getInstance().game.gameId, new Responder(handleLoadingOfMediaIntoXML, handleFault));
    }

    private function printXMLData():void
    {
        trace("XML Data = '" + xmlData.toXMLString() + "'");
    }

    public function setObjectPaletteItem(opi:ObjectPaletteItemBO):void
    {
        trace("setting objectPaletteItem with name = '" + opi.name + "' in ItemEditorPlaqueView");
        objectPaletteItem = opi;
    }

    public function isInIconPickerMode():Boolean
    {
        return isIconPicker;
    }

    public function setIsIconPicker(isIconPickerMode:Boolean):void
    {
        trace("setting isIconPicker mode to: " + isIconPickerMode);
        this.isIconPicker = isIconPickerMode;
        this.updateTitleBasedOnMode();
    }

    private function updateTitleBasedOnMode():void
    {
        if (isIconPicker)
        {
            title = "Icon Picker";
        }
        else
        {
            title = "Media Picker";
        }
    }

    private function handleCloseButton(evt:MouseEvent):void
    {
        trace("ItemEditorMediaPickerView: handleCloseButton()");
		PopUpManager.removePopUp(this);
    }

	private function handleSelectButton(evt:MouseEvent):void
	{
		trace("Select Button clicked...");

		var m:Media = new Media();
		m.mediaId = treeBrowser.selectedItem.@mediaId;
		m.name = treeBrowser.selectedItem.@name;
		m.type = treeBrowser.selectedItem.@type;
		m.urlPath = treeBrowser.selectedItem.@urlPath;
		m.fileName = treeBrowser.selectedItem.@fileName;
		m.isDefault = treeBrowser.selectedItem.@isDefault;

		if (delegate.hasOwnProperty("didSelectMediaItem")){
			delegate.didSelectMediaItem(this, m);
		}

		PopUpManager.removePopUp(this);
	}

    private function handleLoadingOfMediaIntoXML(obj:Object):void
    {
		if(this.objectPaletteItem.objectType == AppConstants.CONTENTTYPE_CHARACTER_DATABASE){
			this.isNPC = true;
			trace("This is an NPC, so disallow Audio/Visual media");
		}

        trace("In handleLoadingOfMediaIntoXML() Result called with obj = " + obj + "; Result = " + obj.result);
        if (obj.result.returnCode != 0)
        {
            trace("Bad loading of media attempt... let's see what happened.  Error = '" + obj.result.returnCodeDescription + "'");
            var msg:String = obj.result.returnCodeDescription;
            Alert.show("Error Was: " + msg, "Error While Loading Media");
			return;
        }

        //Init the XML Data
		xmlData = new XML('<nodes label="' + AppConstants.MEDIATYPE + '"/>');

		if (!this.isIconPicker && !this.isNPC) {
			xmlData.appendChild('<node label="' + AppConstants.MEDIATYPE_IMAGE + '"/>');
			xmlData.appendChild('<node label="' + AppConstants.MEDIATYPE_AUDIO + '"/>');
			xmlData.appendChild('<node label="' + AppConstants.MEDIATYPE_VIDEO + '"/>');
		}

		this.printXMLData();

		var media:Array = obj.result.data as Array;
        trace("Number of Media Objects returned from server = '" + media.length + "'");

		//Puts media items in xml readable format
		var numImageDefaults:Number = 0;
		var numAudioDefaults:Number = 0;
		var numVideoDefaults:Number = 0;
		var numIconDefaults:Number = 0;
		for (var k:Number = 0; k <= 1; k++) //Iterates over list twice; once for uploaded items, again for default
		{
			//Add "Upload new" in between uploaded and default pictures
			if(k==0 && (!this.isIconPicker && !this.isNPC)){
				xmlData.node.(@label == AppConstants.MEDIATYPE_IMAGE).appendChild('<node label="' + AppConstants.MEDIATYPE_UPLOADNEW + '" icon="'+ AppConstants.MEDIATREEICON_UPLOAD +'"/>');
				xmlData.node.(@label == AppConstants.MEDIATYPE_AUDIO).appendChild('<node label="' + AppConstants.MEDIATYPE_UPLOADNEW + '" icon="'+ AppConstants.MEDIATREEICON_UPLOAD +'"/>');
				xmlData.node.(@label == AppConstants.MEDIATYPE_VIDEO).appendChild('<node label="' + AppConstants.MEDIATYPE_UPLOADNEW + '" icon="'+ AppConstants.MEDIATREEICON_UPLOAD +'"/>');
			}
			else if(k == 0){
				xmlData.appendChild('<node label="' + AppConstants.MEDIATYPE_UPLOADNEW + '" icon="'+ AppConstants.MEDIATREEICON_UPLOAD +'"/>');
			}
			for (var j:Number = 0; j < media.length; j++)
			{
				var o:Object = media[j];

				if((k==0 && !o.is_default) || (k==1 && o.is_default)){
					var m:Media = new Media();

					m.mediaId = o.media_id;
					m.name = o.name;
					m.type = o.type;
					m.urlPath = o.url_path;
					m.fileName = o.file_name;
					m.isDefault = o.is_default; //for both default files and uploaded files

					var node:String = "<node label='" + AppUtils.filterStringToXMLEscapeCharacters(m.name) + "' mediaId='" + m.mediaId + "' type='" + m.type + "' urlPath='" + m.urlPath + "' fileName='" + m.fileName + "' isDefault='" + m.isDefault + "'/>";

					switch (m.type)
					{
						case AppConstants.MEDIATYPE_IMAGE:
							if(!this.isNPC){
								if (!this.isIconPicker) {
									//Only add "-----------" (AppConstants.MEDIATYPE_SEPARATOR) if there are also defaults to choose from
									if(k > numImageDefaults) xmlData.node.(@label == AppConstants.MEDIATYPE_IMAGE).appendChild('<node label="' + AppConstants.MEDIATYPE_SEPARATOR + '" icon="'+ AppConstants.MEDIATREEICON_SEPARATOR +'"/>');
									xmlData.node.(@label == AppConstants.MEDIATYPE_IMAGE).appendChild(node);
									numImageDefaults+=k;
								}
							}
							else{
								if (!this.isIconPicker) {
									if(k > numIconDefaults) xmlData.appendChild('<node label="' + AppConstants.MEDIATYPE_SEPARATOR + '" icon="'+ AppConstants.MEDIATREEICON_SEPARATOR +'"/>');
									xmlData.appendChild(node);
									numIconDefaults+=k;
								}
							}
							break;
						case AppConstants.MEDIATYPE_AUDIO:
							if (!this.isIconPicker && !this.isNPC) {
								//Only add "-----------" (AppConstants.MEDIATYPE_SEPARATOR) if there are also defaults to choose from
								if(k > numAudioDefaults) xmlData.node.(@label == AppConstants.MEDIATYPE_AUDIO).appendChild('<node label="' + AppConstants.MEDIATYPE_SEPARATOR + '" icon="'+ AppConstants.MEDIATREEICON_SEPARATOR +'"/>');
								xmlData.node.(@label == AppConstants.MEDIATYPE_AUDIO).appendChild(node);
								numAudioDefaults+=k;
							}
							break;
						case AppConstants.MEDIATYPE_VIDEO:
							if (!this.isIconPicker && !this.isNPC) {
								//Only add "-----------" (AppConstants.MEDIATYPE_SEPARATOR) if there are also defaults to choose from
								if(k > numVideoDefaults) xmlData.node.(@label == AppConstants.MEDIATYPE_VIDEO).appendChild('<node label="' + AppConstants.MEDIATYPE_SEPARATOR + '" icon="'+ AppConstants.MEDIATREEICON_SEPARATOR +'"/>');
								xmlData.node.(@label == AppConstants.MEDIATYPE_VIDEO).appendChild(node);
								numVideoDefaults+=k;
							}
							break;
						case AppConstants.MEDIATYPE_ICON:
							if (this.isIconPicker) {
								trace("hello?:"+node);
								if(k > numIconDefaults) xmlData.appendChild('<node label="' + AppConstants.MEDIATYPE_SEPARATOR + '" icon="'+ AppConstants.MEDIATREEICON_SEPARATOR +'"/>');
								xmlData.appendChild(node);
								numIconDefaults+=k;
							}
							break;
						default:
							trace("Default statement reached in load media.  This SHOULD NOT HAPPEN.  The offending mediaId = '" + m.mediaId + "' and type = '" + m.type + "'");
							break;
					}
				}
			}
		}
        trace("ItemEditorMediaPickerView: handleLoadingOfMediaIntoXML: Just finished loading Media Objects into XML.  Here's what the new XML looks like:");
        this.printXMLData();

        trace("Finished with handleLoadingOfMediaIntoXML().");
    }

    public function handleFault(obj:Object):void
    {
        trace("Fault called: " + obj.message);
        Alert.show("Error occurred: " + obj.message, "Problems Loading Media");
    }

    private function onNodeSelected(event:TreeBrowserEvent):void
    {
        if (!event.isBranch)
        {
            if (event.item.@label == AppConstants.MEDIATYPE_UPLOADNEW)
            {
                if (uploadFormVisable == false) {
					trace("ItemEditorMediaPickerView: onNodeSelected label == MEDIATYPE_UPLOADNEW, display form");
					selectButton.enabled = false;
					uploadFormVisable = true;
	                this.displayMediaUploader();
					PopUpManager.removePopUp(this);
				}
				else trace("ItemEditorMediaPickerView: ignored second TreeBrowserEvent == MEDIATYPE_UPLOADNEW");

            }
			else if(event.item.@label == AppConstants.MEDIATYPE_SEPARATOR){
				//Do Nothing
				trace("Separator Selected");
				selectButton.enabled = false;
			}
            else
            {
                trace("ItemEditorMediaPickerView: onNodeSelected is a media item");
				selectButton.enabled = true;
            }
        }
		else {
			selectButton.enabled = false;
		}
    }

    private function displayMediaUploader():void
    {
        trace("itemEditorMediaPickerPickerView: displayMediaUploader");
        mediaUploader = new ItemEditorMediaPickerUploadFormMX();
		mediaUploader.isIconPicker = this.isIconPicker;
		mediaUploader.delegate = this;
        PopUpManager.addPopUp(mediaUploader, AppUtils.getInstance().getMainView(), true);
		PopUpManager.centerPopUp(mediaUploader);
    }

	public function didUploadMedia(uploader:ItemEditorMediaPickerUploadFormMX, m:Media):void{
		trace("ItemEditorMediaPicker: didUploadMedia");

		uploadFormVisable = false;

		if (delegate.hasOwnProperty("didSelectMediaItem")){
			delegate.didSelectMediaItem(this, m);
		}

		PopUpManager.removePopUp(uploader);
	}

}
}

Put Upload New button at top of media picker list


// vim: tabstop=4 shiftwidth=4

// Copyright (c) 2010 , 杨博 (Yang Bo) All rights reserved.
//
//         pop.atry@gmail.com
//
// Use, modification and distribution are subject to the "New BSD License"
// as listed at <url: http://www.opensource.org/licenses/bsd-license.php >.

package com.netease.protobuf {
	import flash.utils.*
	public final class VarintWriter extends ByteArray {
		private var bitsLeft:uint = 0
		public function end():void {
			if (length == 1) {
				this[0] &= 0x7F
			} else {
				for (var i:uint = length; i > 0; i--) {
					const byte:uint = this[i - 1]
					if (byte != 0x80) {
						this[i - 1] = 0x7F & byte
						length = i
						return
					}
				}
			}
		}
		public function write(number:uint, bits:uint):void {
			if (bits <= bitsLeft) {
				this[length - 1] |= number << (7 - bitsLeft)
				bitsLeft -= bits
			} else {
				if (bitsLeft != 0) {
					this[length - 1] |= number << (7 - bitsLeft)
					bits -= bitsLeft
					number >>>= bitsLeft
				}
				while (bits >= 7) {
					writeByte(0x80 | number)
					number >>>= 7
					bits -= 7
				}
				writeByte(0x80 | number)
				bitsLeft = 7 - bits
			}
		}
	}
}

// vim: tabstop=4 shiftwidth=4

// Copyright (c) 2010 , 杨博 (Yang Bo) All rights reserved.
//
//         pop.atry@gmail.com
//
// Use, modification and distribution are subject to the "New BSD License"
// as listed at <url: http://www.opensource.org/licenses/bsd-license.php >.

package com.netease.protobuf {
	import flash.utils.*;
	public final class VarintWriter extends ByteArray {
		private var bitsLeft:uint = 0
		public function end():void {
			if (length == 1) {
				this[0] &= 0x7F
			} else {
				for (var i:uint = length; i > 0;) {
					const l:uint = i - 1
					const byte:uint = this[l]
					if (byte != 0x80) {
						this[l] = byte & 0x7F
						length = i
						return
					}
					i = l
				}
				this[0] = 0
				length = 1
			}
		}
		public function write(number:uint, bits:uint):void {
			if (bits <= bitsLeft) {
				this[length - 1] |= number << (7 - bitsLeft)
				bitsLeft -= bits
			} else {
				if (bitsLeft != 0) {
					this[length - 1] |= number << (7 - bitsLeft)
					bits -= bitsLeft
					number >>>= bitsLeft
				}
				while (bits >= 7) {
					writeByte(0x80 | number)
					number >>>= 7
					bits -= 7
				}
				writeByte(0x80 | number)
				bitsLeft = 7 - bits
			}
		}
	}
}

修复 Varint 大于 127 时组包错误的问题

修复 Varint 大于 127 时组包错误的问题


package com.kaltura.hls.m2ts
{
	import com.kaltura.hls.HLSDVRTimeTrait;
	import com.kaltura.hls.HLSDVRTrait;
	import com.kaltura.hls.HLSMetadataNamespaces;

	import flash.net.NetConnection;
	import flash.net.NetStream;
	import flash.events.NetStatusEvent;

	import org.osmf.events.DVRStreamInfoEvent;
	import org.osmf.media.MediaResourceBase;
	import org.osmf.media.URLResource;
	import org.osmf.metadata.Metadata;
	import org.osmf.metadata.MetadataNamespaces;
	import org.osmf.net.NetStreamLoadTrait;
	import org.osmf.net.NetStreamCodes;
	import org.osmf.net.httpstreaming.HLSHTTPNetStream;
	import org.osmf.net.httpstreaming.HTTPStreamingFactory;
	import org.osmf.net.httpstreaming.HTTPStreamingNetLoader;
	import org.osmf.net.httpstreaming.dvr.DVRInfo;
	import org.osmf.traits.LoadState;

	/**
	 * Factory to identify and process MPEG2 TS via OSMF.
	 */
	public class M2TSNetLoader extends HTTPStreamingNetLoader
	{
		private var netStream:HLSHTTPNetStream;

		override public function canHandleResource( resource:MediaResourceBase ):Boolean
		{
			var metadata:Object = resource.getMetadataValue( HLSMetadataNamespaces.PLAYABLE_RESOURCE_METADATA );

			if ( metadata != null && metadata == true )
				return true;

			return false;
		}

		override protected function createNetStream(connection:NetConnection, resource:URLResource):NetStream
		{
			var factory:HTTPStreamingFactory = new M2TSStreamingFactory();
			var httpNetStream:HLSHTTPNetStream = new HLSHTTPNetStream(connection, factory, resource);
			return httpNetStream;
		}

		override protected function processFinishLoading(loadTrait:NetStreamLoadTrait):void
		{
			var resource:URLResource = loadTrait.resource as URLResource;

			if (!dvrMetadataPresent(resource))
			{
				updateLoadTrait(loadTrait, LoadState.READY);
				return;
			}

			netStream = loadTrait.netStream as HLSHTTPNetStream;
			netStream.addEventListener(DVRStreamInfoEvent.DVRSTREAMINFO, onDVRStreamInfo);
			netStream.DVRGetStreamInfo(null);
			function onDVRStreamInfo(event:DVRStreamInfoEvent):void
			{
				netStream.removeEventListener(DVRStreamInfoEvent.DVRSTREAMINFO, onDVRStreamInfo);

				loadTrait.setTrait(new HLSDVRTrait(loadTrait.connection, netStream, event.info as DVRInfo));
				loadTrait.setTrait(new HLSDVRTimeTrait(loadTrait.connection, netStream, event.info as DVRInfo));
				updateLoadTrait(loadTrait, LoadState.READY);
			}
		}

		private function dvrMetadataPresent(resource:URLResource):Boolean
		{
			var metadata:Metadata = resource.getMetadataValue(MetadataNamespaces.DVR_METADATA) as Metadata;

			return (metadata != null);
		}
	}
}

package com.kaltura.hls.m2ts
{
	import com.kaltura.hls.HLSDVRTimeTrait;
	import com.kaltura.hls.HLSDVRTrait;
	import com.kaltura.hls.HLSMetadataNamespaces;

	import flash.net.NetConnection;
	import flash.net.NetStream;
	import flash.events.NetStatusEvent;

	import org.osmf.events.DVRStreamInfoEvent;
	import org.osmf.media.MediaResourceBase;
	import org.osmf.media.URLResource;
	import org.osmf.metadata.Metadata;
	import org.osmf.metadata.MetadataNamespaces;
	import org.osmf.net.NetStreamLoadTrait;
	import org.osmf.net.NetStreamCodes;
	import org.osmf.net.httpstreaming.HLSHTTPNetStream;
	import org.osmf.net.httpstreaming.HTTPStreamingFactory;
	import org.osmf.net.httpstreaming.HTTPStreamingNetLoader;
	import org.osmf.net.httpstreaming.dvr.DVRInfo;
	import org.osmf.traits.LoadState;

	import org.osmf.net.NetStreamSwitchManagerBase
	import org.osmf.net.metrics.BandwidthMetric;
	import org.osmf.net.DynamicStreamingResource;
	import org.osmf.net.httpstreaming.DefaultHTTPStreamingSwitchManager;

	import org.osmf.net.metrics.MetricType;
	import org.osmf.net.rules.BandwidthRule;

	/**
	 * Factory to identify and process MPEG2 TS via OSMF.
	 */
	public class M2TSNetLoader extends HTTPStreamingNetLoader
	{
		private var netStream:HLSHTTPNetStream;

		override public function canHandleResource( resource:MediaResourceBase ):Boolean
		{
			var metadata:Object = resource.getMetadataValue( HLSMetadataNamespaces.PLAYABLE_RESOURCE_METADATA );

			if ( metadata != null && metadata == true )
				return true;

			return false;
		}

		override protected function createNetStream(connection:NetConnection, resource:URLResource):NetStream
		{
			var factory:HTTPStreamingFactory = new M2TSStreamingFactory();
			var httpNetStream:HLSHTTPNetStream = new HLSHTTPNetStream(connection, factory, resource);
			return httpNetStream;
		}

		override protected function createNetStreamSwitchManager(connection:NetConnection, netStream:NetStream, dsResource:DynamicStreamingResource):NetStreamSwitchManagerBase
		{
			var switcher:DefaultHTTPStreamingSwitchManager = super.createNetStreamSwitchManager(connection, netStream, dsResource) as DefaultHTTPStreamingSwitchManager;

			// Since our segments are large, switch rapidly.

			// First, try to bias the bandwidth metric itself.
			var weights:Vector.<Number> = new Vector.<Number>;
			weights.push(1.0);
			weights.push(0.0);
			weights.push(0.0);
			var bw:BandwidthMetric = switcher.metricRepository.getMetric(MetricType.BANDWIDTH, weights) as BandwidthMetric;
			trace("Tried to override BandwidthMetric to N=1, and N=" + bw.weights.length);

			// Second, bias the bandwidthrule.
			for(var i:int=0; i<switcher.normalRules.length; i++)
			{
				var bwr:BandwidthRule = switcher.normalRules[i] as BandwidthRule;
				if(!bwr)
					continue;

				bwr.weights.length = 3;
				bwr.weights[0] = 1.0;
				bwr.weights[1] = 0.0;
				bwr.weights[2] = 0.0;

				trace("Adjusted BandwidthRule");
			}

			return switcher;
		}

		override protected function processFinishLoading(loadTrait:NetStreamLoadTrait):void
		{
			// Set up DVR state updating.
			var resource:URLResource = loadTrait.resource as URLResource;

			if (!dvrMetadataPresent(resource))
			{
				updateLoadTrait(loadTrait, LoadState.READY);
				return;
			}

			netStream = loadTrait.netStream as HLSHTTPNetStream;
			netStream.addEventListener(DVRStreamInfoEvent.DVRSTREAMINFO, onDVRStreamInfo);
			netStream.DVRGetStreamInfo(null);
			function onDVRStreamInfo(event:DVRStreamInfoEvent):void
			{
				netStream.removeEventListener(DVRStreamInfoEvent.DVRSTREAMINFO, onDVRStreamInfo);

				loadTrait.setTrait(new HLSDVRTrait(loadTrait.connection, netStream, event.info as DVRInfo));
				loadTrait.setTrait(new HLSDVRTimeTrait(loadTrait.connection, netStream, event.info as DVRInfo));
				updateLoadTrait(loadTrait, LoadState.READY);
			}
		}

		private function dvrMetadataPresent(resource:URLResource):Boolean
		{
			var metadata:Metadata = resource.getMetadataValue(MetadataNamespaces.DVR_METADATA) as Metadata;

			return (metadata != null);
		}
	}
}

Adjust weighting to react to latest segment speed exclusively.


package io.github.jwhile.impetus
{
    import flash.media.Sound;
    import flash.media.SoundChannel;
    import flash.net.URLRequest;

    public class ImpetusSound
    {
        private var sound:Sound;

        private var channels:Vector.<SoundChannel>;

        public function ImpetusSound(url:String):void
        {
            this.sound = new Sound();

            this.channels = new Vector.<SoundChannel>;

            this.sound.load(new URLRequest(url));
        }

        public function playNew():SoundChannel
        {
            var c:SoundChannel = this.sound.play(0);

            channels.push(c);

            return c;
        }
    }
}

package io.github.jwhile.impetus
{
    import flash.media.Sound;
    import flash.net.URLRequest;

    public class ImpetusSound
    {
        private var sound:Sound;

        private var channels:Vector.<ImpetusChannel>;

        public function ImpetusSound(url:String):void
        {
            this.sound = new Sound();

            this.channels = new Vector.<ImpetusChannel>;

            this.sound.load(new URLRequest(url));
        }

        public function playNew():ImpetusChannel
        {
            var c:ImpetusChannel = new ImpetusChannel(this.sound.play(0));

            channels.push(c);

            return c;
        }
    }
}

Use ImpetusChannel instead SoundChannel

Use ImpetusChannel instead SoundChannel


package aerys.minko.scene.node.camera
{
	import flash.geom.Point;

	import aerys.minko.ns.minko_camera;
	import aerys.minko.scene.controller.camera.CameraController;
	import aerys.minko.scene.data.CameraDataProvider;
	import aerys.minko.scene.node.AbstractSceneNode;
	import aerys.minko.type.Signal;
	import aerys.minko.type.math.Frustum;
	import aerys.minko.type.math.Matrix4x4;
	import aerys.minko.type.math.Ray;
	import aerys.minko.type.math.Vector4;

	public class AbstractCamera extends AbstractSceneNode
	{
		use namespace minko_camera;

		public static const DEFAULT_ZNEAR	: Number	= .1;
		public static const DEFAULT_ZFAR	: Number	= 500.;

		minko_camera var _cameraCtrl	: CameraController;
		minko_camera var _cameraData	: CameraDataProvider;

		protected var _enabled		: Boolean;

		protected var _activated	: Signal;
		protected var _deactivated	: Signal;

		public function get zNear() : Number
		{
			return _cameraData.zNear;
		}
		public function set zNear(value : Number) : void
		{
			_cameraData.zNear = value;
		}

		public function get zFar() : Number
		{
			return _cameraData.zFar;
		}
		public function set zFar(value : Number) : void
		{
			_cameraData.zFar = value;
		}

		public function get enabled() : Boolean
		{
			return _enabled;
		}
		public function set enabled(value : Boolean) : void
		{
			if (value != _enabled)
			{
				_enabled = value;

				if (_enabled)
					_activated.execute(this);
				else
					_deactivated.execute(this);
			}
		}

		public function get activated() : Signal
		{
			return _activated;
		}
		public function get deactivated() : Signal
		{
			return _deactivated;
		}

		public function get frustum() : Frustum
		{
			return _cameraData.frustum;
		}

		protected function get cameraController() : CameraController
		{
			return _cameraCtrl;
		}

		protected function get cameraData() : CameraDataProvider
		{
			return _cameraData;
		}

		public function AbstractCamera(zNear	: Number = DEFAULT_ZNEAR,
									   zFar		: Number = DEFAULT_ZFAR)
		{
			super();

			initializeCameraData(zNear, zFar);
		}

		override protected function initialize() : void
		{
			_enabled = true;

			super.initialize();
		}

		override protected function initializeSignals():void
		{
			super.initializeSignals();

			_activated = new Signal('Camera.activated');
			_deactivated = new Signal('Camera.deactivated');
		}

		override protected function initializeContollers():void
		{
			super.initializeContollers();

			_cameraCtrl = new CameraController();
			addController(_cameraCtrl);
		}

		override protected function initializeDataProviders():void
		{
			super.initializeDataProviders();

			_cameraData = _cameraCtrl.cameraData;
		}

		protected function initializeCameraData(zNear : Number, zFar : Number) : void
		{
			_cameraData.zNear = zNear;
			_cameraData.zFar = zFar;
		}

		public function unproject(x : Number, y : Number, out : Ray = null) : Ray
		{
			throw new Error('Must be overriden.');
		}

		public function project(worldPosition : Vector4, output : Point = null) : Point
		{
			throw new Error('Must be overriden.');
		}

		/**
		 * Return a copy of the world to view matrix. This method is an alias on the
		 * getWorldToLocalTransform() method.
		 *
		 * @param output
		 * @return
		 *
		 */
		public function getWorldToViewTransform(forceUpdate	: Boolean	= false,
												output 		: Matrix4x4 = null) : Matrix4x4
		{
			return getWorldToLocalTransform(forceUpdate, output);
		}

		/**
		 * Return a copy of the view to world matrix. This method is an alias on the
		 * getLocalToWorldTransform() method.
		 *
		 * @param output
		 * @return
		 *
		 */
		public function getViewToWorldTransform(forceUpdate : Boolean	= false,
												output 		: Matrix4x4 = null) : Matrix4x4
		{
			return getLocalToWorldTransform(forceUpdate, output);
		}

		/**
		 * Return a copy of the projection matrix.
		 *
		 * @param output
		 * @return
		 *
		 */
		public function getProjection(output : Matrix4x4) : Matrix4x4
		{
			output ||= new Matrix4x4();

			return output.copyFrom(_cameraData.projection);
		}
	}
}

package aerys.minko.scene.node.camera
{
	import flash.geom.Point;

	import aerys.minko.ns.minko_camera;
	import aerys.minko.scene.controller.camera.CameraController;
	import aerys.minko.scene.data.CameraDataProvider;
	import aerys.minko.scene.node.AbstractSceneNode;
	import aerys.minko.type.Signal;
	import aerys.minko.type.math.Frustum;
	import aerys.minko.type.math.Matrix4x4;
	import aerys.minko.type.math.Ray;
	import aerys.minko.type.math.Vector4;

	public class AbstractCamera extends AbstractSceneNode
	{
		use namespace minko_camera;

		public static const DEFAULT_ZNEAR	: Number	= .1;
		public static const DEFAULT_ZFAR	: Number	= 500.;

		minko_camera var _cameraCtrl	: CameraController;
		minko_camera var _cameraData	: CameraDataProvider;

		protected var _enabled		: Boolean;

		protected var _activated	: Signal;
		protected var _deactivated	: Signal;

		public function get zNear() : Number
		{
			return _cameraData.zNear;
		}
		public function set zNear(value : Number) : void
		{
			_cameraData.zNear = value;
		}

		public function get zFar() : Number
		{
			return _cameraData.zFar;
		}
		public function set zFar(value : Number) : void
		{
			_cameraData.zFar = value;
		}

		public function get enabled() : Boolean
		{
			return _enabled;
		}
		public function set enabled(value : Boolean) : void
		{
			if (value != _enabled)
			{
				_enabled = value;

				if (_enabled)
					_activated.execute(this);
				else
					_deactivated.execute(this);
			}
		}

		public function get activated() : Signal
		{
			return _activated;
		}
		public function get deactivated() : Signal
		{
			return _deactivated;
		}

		public function get frustum() : Frustum
		{
			return _cameraData.frustum;
		}

		protected function get cameraController() : CameraController
		{
			return _cameraCtrl;
		}

		protected function get cameraData() : CameraDataProvider
		{
			return _cameraData;
		}

		public function AbstractCamera(zNear	: Number = DEFAULT_ZNEAR,
									   zFar		: Number = DEFAULT_ZFAR)
		{
			super();

			initializeCameraData(zNear, zFar);
		}

		override protected function initialize() : void
		{
			_enabled = true;

			super.initialize();
		}

		override protected function initializeSignals():void
		{
			super.initializeSignals();

			_activated = new Signal('Camera.activated');
			_deactivated = new Signal('Camera.deactivated');
		}

		override protected function initializeContollers():void
		{
			super.initializeContollers();

			_cameraCtrl = new CameraController();
			addController(_cameraCtrl);
		}

		override protected function initializeDataProviders():void
		{
			super.initializeDataProviders();

			_cameraData = _cameraCtrl.cameraData;
		}

		protected function initializeCameraData(zNear : Number, zFar : Number) : void
		{
			_cameraData.zNear = zNear;
			_cameraData.zFar = zFar;
		}

		public function unproject(x : Number, y : Number, out : Ray = null) : Ray
		{
			throw new Error('Must be overriden.');
		}

		public function project(worldPosition : Vector4, output : Point = null) : Point
		{
			throw new Error('Must be overriden.');
		}

		/**
		 * Return a copy of the world to view matrix. This method is an alias on the
		 * getWorldToLocalTransform() method.
		 *
		 * @param output
		 * @return
		 *
		 */
		public function getWorldToViewTransform(forceUpdate	: Boolean	= false,
												output 		: Matrix4x4 = null) : Matrix4x4
		{
			return getWorldToLocalTransform(forceUpdate, output);
		}

		/**
		 * Return a copy of the view to world matrix. This method is an alias on the
		 * getLocalToWorldTransform() method.
		 *
		 * @param output
		 * @return
		 *
		 */
		public function getViewToWorldTransform(forceUpdate : Boolean	= false,
												output 		: Matrix4x4 = null) : Matrix4x4
		{
			return getLocalToWorldTransform(forceUpdate, output);
		}

		/**
		 * Return a copy of the projection matrix.
		 *
		 * @param output
		 * @return
		 *
		 */
		public function getProjection(output : Matrix4x4 = null) : Matrix4x4
		{
			output ||= new Matrix4x4();

			return output.copyFrom(_cameraData.projection);
		}
	}
}

Fix missing default argument.

Fix missing default argument.


//
// $Id$
//
// Narya library - tools for developing networked games
// Copyright (C) 2002-2009 Three Rings Design, Inc., All Rights Reserved
// http://www.threerings.net/code/narya/
//
// This library is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

package com.threerings.util {

import com.threerings.io.ObjectInputStream;
import com.threerings.io.ObjectOutputStream;
import com.threerings.io.Streamable;

import com.threerings.util.Log;
import com.threerings.util.Maps;
import com.threerings.util.maps.ForwardingMap;

/**
 * A {@link HashMap} that can be sent over the wire, bearing in mind that all keys and values must
 * be primitives or implement {@link Streamable}.
 */
public class StreamableHashMap extends ForwardingMap
    implements Streamable
{
    public function StreamableHashMap (keyClazz :Class = null)
    {
        if (keyClazz != null) {
            super(Maps.newMapOf(keyClazz));
        }
    }

    // documentation inherited from interface Streamable
    public function writeObject (out :ObjectOutputStream) :void
    {
        out.writeInt(size());
        forEach(function (key :Object, value :Object) :void {
            out.writeObject(key);
            out.writeObject(value);
        });
    }

    // documentation inherited from interface Streamable
    public function readObject (ins :ObjectInputStream) :void
    {
        var ecount :int = ins.readInt();
        if (ecount > 0) {
            // guess the type of map based on the first key
            var key :Object = ins.readObject();
            _source = Maps.newMapOf(ClassUtil.getClass(key));
            put(key, ins.readObject());
            // now read the rest
            for (var ii :int = 1; ii < ecount; ii++) {
                put(ins.readObject(), ins.readObject());
            }

        } else {
            // shit!
            Log.getLog(this).warning("Empty StreamableHashMap read, guessing DictionaryMap.");
            _source = Maps.newMapOf(Object);
        }
    }
}
}

//
// $Id$
//
// Narya library - tools for developing networked games
// Copyright (C) 2002-2009 Three Rings Design, Inc., All Rights Reserved
// http://www.threerings.net/code/narya/
//
// This library is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

package com.threerings.util {

import com.threerings.io.ObjectInputStream;
import com.threerings.io.ObjectOutputStream;
import com.threerings.io.Streamable;

import com.threerings.util.Log;
import com.threerings.util.Maps;
import com.threerings.util.maps.ForwardingMap;

/**
 * A @see com.threerings.util.Map that can be sent over the wire,
 * bearing in mind that all keys and values must
 * be primitives or implement @see com.threerings.io.Streamable
 */
public class StreamableHashMap extends ForwardingMap
    implements Streamable
{
    public function StreamableHashMap (keyClazz :Class = null)
    {
        if (keyClazz != null) {
            super(Maps.newMapOf(keyClazz));
        }
    }

    // documentation inherited from interface Streamable
    public function writeObject (out :ObjectOutputStream) :void
    {
        out.writeInt(size());
        forEach(function (key :Object, value :Object) :void {
            out.writeObject(key);
            out.writeObject(value);
        });
    }

    // documentation inherited from interface Streamable
    public function readObject (ins :ObjectInputStream) :void
    {
        var ecount :int = ins.readInt();
        if (ecount > 0) {
            // guess the type of map based on the first key
            var key :Object = ins.readObject();
            _source = Maps.newMapOf(ClassUtil.getClass(key));
            put(key, ins.readObject());
            // now read the rest
            for (var ii :int = 1; ii < ecount; ii++) {
                put(ins.readObject(), ins.readObject());
            }

        } else {
            // shit!
            Log.getLog(this).warning("Empty StreamableHashMap read, guessing DictionaryMap.");
            _source = Maps.newMapOf(Object);
        }
    }
}
}

Fix the asdocs here. But wait, why is this even showing up in the SDK docs?

git-svn-id: a1a4b28b82a3276cc491891159dd9963a0a72fae@5930 542714f4-19e9-0310-aa3c-eee0fc999fb1


/**
 * Generated by Gas3 v2.3.0 (Granite Data Services).
 *
 * NOTE: this file is only generated if it does not exist. You may safely put
 * your custom code here.
 */

package org.openforis.collect.metamodel.proxy {
	import mx.collections.IList;

	import org.openforis.collect.util.CollectionUtil;

    [Bindable]
    [RemoteClass(alias="org.openforis.collect.metamodel.proxy.UITabSetProxy")]
    public class UITabSetProxy extends UITabSetProxyBase {

		public function getTab(name:String):UITabProxy {
			var stack:Array = new Array();
			stack.push(tabs);
			while (stack.length > 0) {
				var tabs:IList = stack.pop();
				for each(var tab:UITabProxy in tabs) {
					if(tab.name == name) {
						return tab;
					}
					if ( CollectionUtil.isNotEmpty(tab.tabs) ) {
						stack.push(tab.tabs);
					}
				}
			}
			return null;
		}
    }
}

/**
 * Generated by Gas3 v2.3.0 (Granite Data Services).
 *
 * NOTE: this file is only generated if it does not exist. You may safely put
 * your custom code here.
 */

package org.openforis.collect.metamodel.proxy {
	import mx.collections.IList;

	import org.openforis.collect.util.CollectionUtil;

    [Bindable]
    [RemoteClass(alias="org.openforis.collect.metamodel.proxy.UITabSetProxy")]
    public class UITabSetProxy extends UITabSetProxyBase {

		public function getTab(name:String):UITabProxy {
			var stack:Array = new Array();
			stack.push(this.tabs);
			while (stack.length > 0) {
				var currentTabs:IList = stack.pop();
				for each(var tab:UITabProxy in currentTabs) {
					if(tab.name == name) {
						return tab;
					}
					if ( CollectionUtil.isNotEmpty(tab.tabs) ) {
						stack.push(tab.tabs);
					}
				}
			}
			return null;
		}
    }
}

Fix unexpected behavior with nested tabs


/**
 * BossClick.as
 * @author Christopher Long at The Banner Boss - @clong
 * @description Creates and adds an invisible hitArea over the entirety
 *				of the banner.  It also filters a basic clickTAG request
 *				sent from a web browser into the banner swf file.
 *				Finally, there is a method to add a border
 *				around the edge of the banner which is required by
 *				most websites that host ads.
 */
package com.thebannerboss.utils{

	import flash.events.MouseEvent;
	import flash.display.Stage;
	import flash.display.Sprite;
	import flash.display.Shape;
	import flash.net.URLRequest;
	import flash.net.navigateToURL;
	import flash.external.ExternalInterface;

	public class BossClick extends Sprite{

		private var url:String;
		private var hitAreaWidth:uint;
		private var hitAreaHeight:uint;

		public function BossClick(loaderInfo:Object,stage:Stage) {
			//
			trace('BossClick : Add clickTag button?  Add a border?');
			//
		}

		public function addClickTagBtn():void{
			//Invisible hit area
			hitAreaWidth = stage.stageWidth;
			hitAreaHeight = stage.stageHeight;
			this.graphics.beginFill(0xFF0000, 0);
			this.graphics.drawRect( 0, 0, hitAreaWidth, hitAreaHeight );
			this.graphics.endFill();

			//Check for various iterations of clickTAG
			if(loaderInfo.parameters.clicktag != null) {
				url = loaderInfo.parameters.clicktag;
			} else if(loaderInfo.parameters.clickTag != null) {
				url = loaderInfo.parameters.clickTag;
			}else if(loaderInfo.parameters.clickTag1 != null) {
				url = loaderInfo.parameters.clickTag1;
			}else if(loaderInfo.parameters.clickTAG != null) {
				url = loaderInfo.parameters.clickTAG;
			}

			//Add Click event listener to trigger actions when the banner is clicked on
			addEventListener(MouseEvent.CLICK, clickHandler);
			buttonMode = true;
			//
			trace('BossClick : clickTag button added.');
		}

		//CLICKTAG MANNIPULATION BEGIN ---!!!!!!
		private function clickHandler(e:MouseEvent):void {
			if (! url) {
				trace("BossClick : clickTag button pressed.");
			}else{
				openWindow( url );
			}
		}

		private function getBrowserName():String {
			var browser:String;
			//Uses external interface to reach out to browser and grab browser useragent info.
			var browserAgent:String = ExternalInterface.call("function getBrowser(){return navigator.userAgent;}");
			//Determines brand of browser using a find index. If not found indexOf returns (-1).
			if (browserAgent != null && browserAgent.indexOf("Firefox")>= 0) {
				browser = "Firefox";
			} else if (browserAgent != null && browserAgent.indexOf("Safari")>= 0) {
				browser = "Safari";
			} else if (browserAgent != null && browserAgent.indexOf("MSIE")>= 0) {
				browser = "IE";
			} else if (browserAgent != null && browserAgent.indexOf("Opera")>= 0) {
				browser = "Opera";
			} else {
				browser = "Undefined";
			}
			return (browser);
		}

		//Try to avoid pop-blockers by using ExternalInterface call to load url
		private function openWindow(url:String, target:String = '_blank', features:String=""):void {
			var WINDOW_OPEN_FUNCTION:String = "window.open";
			var myURL:URLRequest = new URLRequest(url);
			var browserName:String = getBrowserName();
			switch (browserName) {
					//If browser is Firefox, use ExternalInterface to call out to browser
					//and launch window via browser's window.open method.
				case "Firefox" :
					ExternalInterface.call(WINDOW_OPEN_FUNCTION, url, target, features);
					break;
					//If IE,
				case "IE" :
					ExternalInterface.call("function setWMWindow() {window.open('" + url + "', '"+target+"', '"+features+"');}");
					break;
					// If Safari or Opera or any other;
				case "Safari" :
					navigateToURL(myURL, target);
					break;
				case "Opera" :
					navigateToURL(myURL, target);
					break;
				default :
					navigateToURL(myURL, target);
					break;
			}
		}
		//CLICKTAG MANNIPULATION END ---!!!!!!

		//BORDER BEGIN ---!!!!!!
		//addBorder - if no properties are set on method call, give the banner a black border that is 2 pxls thick
		public function addBorder(borderThickness:uint=2,borderColor:uint=0x000000):void{

			//rect visual properties
			var borderRectHeight:uint = hitAreaHeight;
			var borderRectWidth:uint = hitAreaWidth;
			var borderRect:Shape = new Shape();
			borderRect.graphics.lineStyle(borderThickness, borderColor, 1);

			// rect starting at point 0, 0
			borderRect.graphics.moveTo(0, 0);
			borderRect.graphics.lineTo(borderRectWidth - 1, 0);
			borderRect.graphics.lineTo(borderRectWidth - 1, borderRectHeight - 1);
			borderRect.graphics.lineTo(0, borderRectHeight - 1);
			borderRect.graphics.lineTo(0, 0);
			addChild(borderRect);

			//
			trace('BossClick : border added.');
		}
		//BORDER END ---!!!!!!

	}

}

/**
 * BossClick.as
 * @author Christopher Long at The Banner Boss - @clong
 * @description Creates and adds an invisible hitArea over the entirety
 *				of the banner.  It also filters a basic clickTAG request
 *				sent from a web browser into the banner swf file.
 *				Finally, there is a method to add a border
 *				around the edge of the banner which is required by
 *				most websites that host ads.
 */
package com.thebannerboss.utils{

	import flash.events.MouseEvent;
	import flash.display.Stage;
	import flash.display.Sprite;
	import flash.display.Shape;
	import flash.net.URLRequest;
	import flash.net.navigateToURL;
	import flash.external.ExternalInterface;
	import flash.system.Capabilities;

	public class BossClick extends Sprite{

		private var url:String;
		private var hitAreaWidth:uint;
		private var hitAreaHeight:uint;

		public function BossClick(loaderInfo:Object,stage:Stage) {
			//
			trace('BossClick : Add clickTag button?  Add a border?');
			//
		}

		public function addClickTagBtn():void{
			//Invisible hit area
			hitAreaWidth = stage.stageWidth;
			hitAreaHeight = stage.stageHeight;
			this.graphics.beginFill(0xFF0000, 0);
			this.graphics.drawRect( 0, 0, hitAreaWidth, hitAreaHeight );
			this.graphics.endFill();

			//Check for various iterations of clickTAG
			if(loaderInfo.parameters.clicktag != null) {
				url = loaderInfo.parameters.clicktag;
			} else if(loaderInfo.parameters.clickTag != null) {
				url = loaderInfo.parameters.clickTag;
			}else if(loaderInfo.parameters.clickTag1 != null) {
				url = loaderInfo.parameters.clickTag1;
			}else if(loaderInfo.parameters.clickTAG != null) {
				url = loaderInfo.parameters.clickTAG;
			}

			//Add Click event listener to trigger actions when the banner is clicked on
			addEventListener(MouseEvent.CLICK, clickHandler);
			buttonMode = true;
			//
			trace('BossClick : clickTag button added.');
		}

		//CLICKTAG MANNIPULATION BEGIN ---!!!!!!
		private function clickHandler(e:MouseEvent):void {
			if (! url) {
				trace("BossClick : clickTag button pressed.");
			}else{
				//Try to avoid pop-blockers by using ExternalInterface call to load url
				if(Capabilities.playerType == "ActiveX" && Capabilities.os != "Mac" && ExternalInterface.available)
				{
					ExternalInterface.call("window.open", url, "_blank", "");
				}
				else
				{
					navigateToURL(new URLRequest(url), "_blank");
				}
			}
		}

		//Try to avoid pop-blockers by using ExternalInterface call to load url

		//CLICKTAG MANNIPULATION END ---!!!!!!

		//BORDER BEGIN ---!!!!!!
		//addBorder - if no properties are set on method call, give the banner a black border that is 2 pxls thick
		public function addBorder(borderThickness:uint=2,borderColor:uint=0x000000):void{

			//rect visual properties
			var borderRectHeight:uint = hitAreaHeight;
			var borderRectWidth:uint = hitAreaWidth;
			var borderRect:Shape = new Shape();
			borderRect.graphics.lineStyle(borderThickness, borderColor, 1);

			// rect starting at point 0, 0
			borderRect.graphics.moveTo(0, 0);
			borderRect.graphics.lineTo(borderRectWidth - 1, 0);
			borderRect.graphics.lineTo(borderRectWidth - 1, borderRectHeight - 1);
			borderRect.graphics.lineTo(0, borderRectHeight - 1);
			borderRect.graphics.lineTo(0, 0);
			addChild(borderRect);

			//
			trace('BossClick : border added.');
		}
		//BORDER END ---!!!!!!

	}

}

Update BossClick.as

Update BossClick.as

I updated how BossClick attempts to avoid pop-up blockers.  Instead of looking for various browsers by name, BossClick now looks for the Flash "player type" to see if it is ActiveX or Mac.  If the "player type" is ActiveX, BossClick opens the clickThrough link in a window by making a Javascript call from the browser instead of using the inherit Flash method of opening a browser window.


package aerys.minko.render.effect.basic
{
	import aerys.minko.render.RenderTarget;
	import aerys.minko.render.effect.IEffect;
	import aerys.minko.render.effect.IEffectPass;
	import aerys.minko.render.effect.fog.FogStyle;
	import aerys.minko.render.renderer.state.Blending;
	import aerys.minko.render.renderer.state.CompareMode;
	import aerys.minko.render.renderer.state.RendererState;
	import aerys.minko.render.renderer.state.TriangleCulling;
	import aerys.minko.render.shader.ActionScriptShader;
	import aerys.minko.render.shader.SValue;
	import aerys.minko.render.shader.node.Components;
	import aerys.minko.render.shader.node.INode;
	import aerys.minko.scene.visitor.data.CameraData;
	import aerys.minko.scene.visitor.data.LocalData;
	import aerys.minko.scene.visitor.data.StyleStack;
	import aerys.minko.scene.visitor.data.ViewportData;
	import aerys.minko.type.math.ConstVector4;

	import flash.utils.Dictionary;

	[StyleParameter(name="basic diffuse map",type="texture")]

	[StyleParameter(name="fog enabled",type="boolean")]
	[StyleParameter(name="fog color",type="color")]
	[StyleParameter(name="fog start",type="number")]
	[StyleParameter(name="fog distance",type="number")]

	public class BasicEffect extends ActionScriptShader implements IEffect, IEffectPass
	{
		protected var _priority			: Number;
		protected var _renderTarget		: RenderTarget;

		protected var _passes			: Vector.<IEffectPass>	= Vector.<IEffectPass>([this]);

		public function BasicEffect(priority		: Number		= 0,
								  	renderTarget	: RenderTarget	= null)
		{
			_priority		= priority;
			_renderTarget	= renderTarget;
		}

		public function getPasses(styleStack	: StyleStack,
								  local			: LocalData,
								  world			: Dictionary) : Vector.<IEffectPass>
		{
			return _passes;
		}

		override public function fillRenderState(state	: RendererState,
												 style	: StyleStack,
												 local	: LocalData,
												 world	: Dictionary) : Boolean
		{
			super.fillRenderState(state, style, local, world);

			var blending : uint = style.get(BasicStyle.BLENDING, Blending.NORMAL) as uint;

			state.depthTest			= CompareMode.LESS;
			state.blending			= blending;
			state.triangleCulling	= style.get(BasicStyle.TRIANGLE_CULLING, TriangleCulling.BACK) as uint;
			state.priority			= _priority + .5;
			state.rectangle			= null;
			state.renderTarget		= _renderTarget || world[ViewportData].renderTarget;

			if (state.blending != Blending.NORMAL)
				state.priority -= .5;

			return true;
		}

		override protected function getOutputPosition() : SValue
		{
			return vertexClipspacePosition;
		}

		override protected function getOutputColor() : SValue
		{
			var diffuse	: SValue		= null;

			if (styleIsSet(BasicStyle.DIFFUSE_MAP))
				diffuse = sampleTexture(BasicStyle.DIFFUSE_MAP, interpolate(vertexUV));
			else
				diffuse = combine(interpolate(vertexRGBColor).rgb, 1.);

			// fog
			if (getStyleConstant(FogStyle.FOG_ENABLED, false))
			{
				var zFar		: SValue = styleIsSet(FogStyle.DISTANCE)
										  ? getStyleParameter(1, FogStyle.DISTANCE)
										  : getWorldParameter(1, CameraData, CameraData.Z_FAR);
				var fogColor 	: *		= styleIsSet(FogStyle.COLOR)
										  ? getStyleParameter(3, FogStyle.COLOR)
										  : vector3(0., 0., 0.);
				var fogStart	: *		= styleIsSet(FogStyle.START)
										  ? getStyleParameter(1, FogStyle.START)
										  : 0.;

				fogColor = getFogColor(fogStart, zFar, fogColor);
				diffuse = blend(fogColor, diffuse, Blending.ALPHA);
			}

			return diffuse;
		}

		override protected function getDataHash(style	: StyleStack,
												local	: LocalData,
												world	: Dictionary) : String
		{
			var hash : String	= "basic";

			hash += style.get(BasicStyle.DIFFUSE_MAP, false) ? "_diffuse" : "_color";

			if (style.get(FogStyle.FOG_ENABLED, false))
			{
				hash += "_fog(";
				hash += "start=" + style.get(FogStyle.START, 0.);
				hash += ",distance=" + style.get(FogStyle.DISTANCE, 0.);
				hash += ",color=" + style.get(FogStyle.COLOR, 0);
				hash += ");"
			}

			return hash;
		}
	}
}

package aerys.minko.render.effect.basic
{
	import aerys.minko.render.RenderTarget;
	import aerys.minko.render.effect.IEffect;
	import aerys.minko.render.effect.IEffectPass;
	import aerys.minko.render.effect.fog.FogStyle;
	import aerys.minko.render.renderer.state.Blending;
	import aerys.minko.render.renderer.state.CompareMode;
	import aerys.minko.render.renderer.state.RendererState;
	import aerys.minko.render.renderer.state.TriangleCulling;
	import aerys.minko.render.shader.ActionScriptShader;
	import aerys.minko.render.shader.SValue;
	import aerys.minko.render.shader.node.Components;
	import aerys.minko.render.shader.node.INode;
	import aerys.minko.scene.visitor.data.CameraData;
	import aerys.minko.scene.visitor.data.LocalData;
	import aerys.minko.scene.visitor.data.StyleStack;
	import aerys.minko.scene.visitor.data.ViewportData;
	import aerys.minko.type.math.ConstVector4;

	import flash.utils.Dictionary;

	[StyleParameter(name="basic diffuse map",type="texture")]

	[StyleParameter(name="fog enabled",type="boolean")]
	[StyleParameter(name="fog color",type="color")]
	[StyleParameter(name="fog start",type="number")]
	[StyleParameter(name="fog distance",type="number")]

	public class BasicEffect extends ActionScriptShader implements IEffect, IEffectPass
	{
		protected var _priority			: Number;
		protected var _renderTarget		: RenderTarget;

		protected var _passes			: Vector.<IEffectPass>	= Vector.<IEffectPass>([this]);

		public function BasicEffect(priority		: Number		= 0,
								  	renderTarget	: RenderTarget	= null)
		{
			_priority		= priority;
			_renderTarget	= renderTarget;
		}

		public function getPasses(styleStack	: StyleStack,
								  local			: LocalData,
								  world			: Dictionary) : Vector.<IEffectPass>
		{
			return _passes;
		}

		override public function fillRenderState(state	: RendererState,
												 style	: StyleStack,
												 local	: LocalData,
												 world	: Dictionary) : Boolean
		{
			super.fillRenderState(state, style, local, world);

			var blending : uint = style.get(BasicStyle.BLENDING, Blending.NORMAL) as uint;

			state.depthTest			= CompareMode.LESS;
			state.blending			= blending;
			state.triangleCulling	= style.get(BasicStyle.TRIANGLE_CULLING, TriangleCulling.BACK) as uint;
			state.priority			= _priority + .5;
			state.rectangle			= null;
			state.renderTarget		= _renderTarget || world[ViewportData].renderTarget;

			if (state.blending != Blending.NORMAL)
				state.priority -= .5;

			return true;
		}

		override protected function getOutputPosition() : SValue
		{
			return vertexClipspacePosition;
		}

		override protected function getOutputColor() : SValue
		{
			var diffuse	: SValue		= null;

			if (styleIsSet(BasicStyle.DIFFUSE_MAP))
				diffuse = sampleTexture(BasicStyle.DIFFUSE_MAP, interpolate(vertexUV));
			else if (styleIsSet(BasicStyle.DIFFUSE_COLOR))
				diffuse = getStyleParameter(4, BasicStyle.DIFFUSE_COLOR);
			else
				diffuse = combine(interpolate(vertexRGBColor).rgb, 1.);

			// fog
			if (getStyleConstant(FogStyle.FOG_ENABLED, false))
			{
				var zFar		: SValue = styleIsSet(FogStyle.DISTANCE)
										  ? getStyleParameter(1, FogStyle.DISTANCE)
										  : getWorldParameter(1, CameraData, CameraData.Z_FAR);
				var fogColor 	: *		= styleIsSet(FogStyle.COLOR)
										  ? getStyleParameter(3, FogStyle.COLOR)
										  : vector3(0., 0., 0.);
				var fogStart	: *		= styleIsSet(FogStyle.START)
										  ? getStyleParameter(1, FogStyle.START)
										  : 0.;

				fogColor = getFogColor(fogStart, zFar, fogColor);
				diffuse = blend(fogColor, diffuse, Blending.ALPHA);
			}

			return diffuse;
		}

		override protected function getDataHash(style	: StyleStack,
												local	: LocalData,
												world	: Dictionary) : String
		{
			var hash : String	= "basic";

			hash += style.get(BasicStyle.DIFFUSE_MAP, false) ? "_diffuse" : "_color";

			if (style.get(FogStyle.FOG_ENABLED, false))
			{
				hash += "_fog(";
				hash += "start=" + style.get(FogStyle.START, 0.);
				hash += ",distance=" + style.get(FogStyle.DISTANCE, 0.);
				hash += ",color=" + style.get(FogStyle.COLOR, 0);
				hash += ");"
			}

			return hash;
		}
	}
}

Add the possibility to set the diffuse color from BasicStyle.DIFFUSE_COLOR before searching for them into vertex attributes


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

// shim the mx classes for states
package mx.states
{
    /**
     *  The State class is one of the classes in the
     *  view states subsystem.  It is used to declare a
     *  view state in an MXML document.  This is one of the
     *  few classes in FlexJS that use the same name as
     *  a Flex SDK class because some of the IDEs and
     *  compilers are hard-coded to assume this name.
     *
     *  @langversion 3.0
     *  @playerversion Flash 10.2
     *  @playerversion AIR 2.6
     *  @productversion FlexJS 0.0
     */
	public class State
	{
        /**
         *  Constructor.
         *
         *  @param properties This parameter is not used in FlexJS and exists to make legacy compilers happy.
         *  @langversion 3.0
         *  @playerversion Flash 9
         *  @playerversion AIR 1.1
         *  @productversion Flex 3
         */
		public function State(properties:Object = null)
		{
			super();
		}

        /**
         *  The name of the state.
         *
         *  @langversion 3.0
         *  @playerversion Flash 9
         *  @playerversion AIR 1.1
         *  @productversion Flex 3
         */
		public var name:String;

        /**
         *  The array of overrides.  This is normally set by the compiler.
         *
         *  @langversion 3.0
         *  @playerversion Flash 9
         *  @playerversion AIR 1.1
         *  @productversion Flex 3
         */
        public var overrides:Array;
	}
}

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

// shim the mx classes for states
package mx.states
{
    /**
     *  The State class is one of the classes in the
     *  view states subsystem.  It is used to declare a
     *  view state in an MXML document.  This is one of the
     *  few classes in FlexJS that use the same name as
     *  a Flex SDK class because some of the IDEs and
     *  compilers are hard-coded to assume this name.
     *
     *  @langversion 3.0
     *  @playerversion Flash 10.2
     *  @playerversion AIR 2.6
     *  @productversion FlexJS 0.0
     */
	public class State
	{
        /**
         *  Constructor.
         *
         *  @param properties This parameter is not used in FlexJS and exists to make legacy compilers happy.
         *  @langversion 3.0
         *  @playerversion Flash 9
         *  @playerversion AIR 1.1
         *  @productversion Flex 3
         */
		public function State(properties:Object = null)
		{
			super();
		}

        /**
         *  The name of the state.
         *
         *  @langversion 3.0
         *  @playerversion Flash 9
         *  @playerversion AIR 1.1
         *  @productversion Flex 3
         */
		public var name:String;

        /**
         *  Comma-delimited list of state groups of the state.
         *  It is not an array so don't use square brackets [].
         *
         *  @langversion 3.0
         *  @playerversion Flash 9
         *  @playerversion AIR 1.1
         *  @productversion Flex 3
         */
        public var stateGroups:String;

        /**
         *  The array of overrides.  This is normally set by the compiler.
         *
         *  @langversion 3.0
         *  @playerversion Flash 9
         *  @playerversion AIR 1.1
         *  @productversion Flex 3
         */
        public var overrides:Array;
	}
}

handle stateGroups

handle stateGroups


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

// Receives mouse events from the runtime
class LzMouseKernel  {
    #passthrough (toplevel:true) {
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.ui.Mouse;
    }#

    // sends mouse events to the callback
    static function __sendEvent(view:*, eventname:String) :void {
        if (__callback) __scope[__callback](eventname, view);
        //Debug.write('LzMouseKernel event', eventname);
    }
    static var __callback:String = null;
    static var __scope:* = null;
    static var __lastMouseDown:LzSprite = null;
    static var __mouseLeft:Boolean = false;
    static var __listeneradded:Boolean = false;

    /**
     * Shows or hides the hand cursor for all clickable views.
     */
    static var showhandcursor:Boolean = true;

    static function setCallback (scope:*, funcname:String) :void {
        __scope = scope;
        __callback = funcname;
        if (__listeneradded == false) {
            /* TODO [hqm 2008-01] Do we want to do anything with other
            * events, like click?
            stage.addEventListener(MouseEvent.CLICK, reportClick);
            */

            LFCApplication.stage.addEventListener(MouseEvent.MOUSE_MOVE, __mouseHandler);
            LFCApplication.stage.addEventListener(MouseEvent.MOUSE_UP,   __mouseHandler);
            LFCApplication.stage.addEventListener(MouseEvent.MOUSE_DOWN, __mouseHandler);
            LFCApplication.stage.addEventListener(MouseEvent.MOUSE_WHEEL, __mouseWheelHandler);
            LFCApplication.stage.addEventListener(Event.MOUSE_LEAVE, __mouseLeaveHandler);
            __listeneradded = true;
        }
    }

    // Handles global mouse events
    static function __mouseHandler(event:MouseEvent):void {
        var eventname:String = 'on' + event.type.toLowerCase();
        if (eventname == 'onmouseup' && __lastMouseDown != null) {
            // call mouseup on the sprite that got the last mouse down
            __lastMouseDown.__globalmouseup(event);
            __lastMouseDown = null;
        } else {
            if (__mouseLeft) {
                __mouseLeft = false;
                if (event.buttonDown) __mouseUpOutsideHandler();
            }
            __sendEvent(null, eventname);
        }
    }

    // sends mouseup and calls __globalmouseup when the mouse goes up outside the app - see LPP-7724
    static function __mouseUpOutsideHandler():void {
        if (__lastMouseDown != null) {
            var ev:MouseEvent = new MouseEvent('mouseup');
            __lastMouseDown.__globalmouseup(ev);
            __lastMouseDown = null;
        }
    }

    // handles MOUSE_LEAVE event
    static function __mouseLeaveHandler(event:Event = null):void {
        __mouseLeft = true;
        __sendEvent(null, 'onmouseleave');
    }

    static function __mouseWheelHandler(event:MouseEvent):void {
        lz.Keys.__mousewheelEvent(event.delta);
    }

    /**
    * Shows or hides the hand cursor for all clickable views.
    * @param Boolean show: true shows the hand cursor for buttons, false hides it
    */
    static function showHandCursor (show:Boolean) :void {
        showhandcursor = show;
    }

    static var __amLocked:Boolean = false;
    static var cursorSprite:Sprite = null;
    static var globalCursorResource:String = null;
    static var lastCursorResource:String = null;

    /**
    * Sets the cursor to a resource
    * @param String what: The resource to use as the cursor.
    */
    static function setCursorGlobal (what:String) :void {
        globalCursorResource = what;
        setCursorLocal(what);
    }

    static function setCursorLocal (what:String) :void {
        if ( __amLocked ) { return; }
        Mouse.hide();
        cursorSprite.x = LFCApplication.stage.mouseX;
        cursorSprite.y = LFCApplication.stage.mouseY;
        LFCApplication.setChildIndex(cursorSprite, LFCApplication._sprite.numChildren-1);
        if (lastCursorResource != what) {
            if (cursorSprite.numChildren > 0) {
                cursorSprite.removeChildAt(0);
            }
            var resourceSprite:Sprite = getCursorResource(what);
            cursorSprite.addChild( resourceSprite );
            lastCursorResource = what;
        }
        // respond to mouse move events
        cursorSprite.startDrag();
        LFCApplication.stage.addEventListener(Event.MOUSE_LEAVE, mouseLeaveHandler);
        cursorSprite.visible = true;
    }

    static function mouseLeaveHandler(evt:Event):void {
        cursorSprite.visible = false;
    }

    static function getCursorResource (resource:String):Sprite {
          var resinfo:Object = LzResourceLibrary[resource];
          var assetclass:Class;
          var frames:Array = resinfo.frames;
          var asset:Sprite;
          // single frame resources get an entry in LzResourceLibrary which has
          // 'assetclass' pointing to the resource Class object.
          if (resinfo.assetclass is Class) {
              assetclass = resinfo.assetclass;
          } else {
              // Multiframe resources have an array of Class objects in frames[]
              assetclass = frames[0];
          }

          if (! assetclass) return null;
          asset = new assetclass();
          asset.scaleX = 1.0;
          asset.scaleY = 1.0;
          //Debug.write('cursor asset', asset);
          return asset;
    }

    /**
    * This function restores the default cursor if there is no locked cursor on
    * the screen.
    *
    * @access private
    */
    static function restoreCursor () :void {
        if ( __amLocked ) { return; }
        cursorSprite.stopDrag();
        cursorSprite.visible = false;
        globalCursorResource = null;
        Mouse.show();
    }

    /** Called by LzSprite to restore cursor to global value.
     */
    static function restoreCursorLocal () :void {
        if ( __amLocked ) { return; }
        if (globalCursorResource == null) {
            // Restore to system default pointer
            restoreCursor();
        } else {
            // Restore to the last value set by setCursorGlobal
            setCursorLocal(globalCursorResource);
        }
    }

    /**
    * Prevents the cursor from being changed until unlock is called.
    *
    */
    static function lock () :void {
        __amLocked = true;
    }

    /**
    * Restores the default cursor.
    *
    */
    static function unlock () :void {
        __amLocked = false;
        restoreCursor();
    }

    static function initCursor () :void {
        cursorSprite = new Sprite();
        cursorSprite.mouseChildren = false;
        cursorSprite.mouseEnabled = false;
        // Add the cursor DisplayObject to the root sprite
        LFCApplication.addChild(cursorSprite);
        cursorSprite.x = -10000;
        cursorSprite.y = -10000;
    }
}

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

// Receives mouse events from the runtime
class LzMouseKernel  {
    #passthrough (toplevel:true) {
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.ui.Mouse;
    import flash.ui.MouseCursor;
    }#

    // sends mouse events to the callback
    static function __sendEvent(view:*, eventname:String) :void {
        if (__callback) __scope[__callback](eventname, view);
        //Debug.write('LzMouseKernel event', eventname);
    }
    static var __callback:String = null;
    static var __scope:* = null;
    static var __lastMouseDown:LzSprite = null;
    static var __mouseLeft:Boolean = false;
    static var __listeneradded:Boolean = false;

    /**
     * Shows or hides the hand cursor for all clickable views.
     */
    static var showhandcursor:Boolean = true;

    static function setCallback (scope:*, funcname:String) :void {
        __scope = scope;
        __callback = funcname;
        if (__listeneradded == false) {
            /* TODO [hqm 2008-01] Do we want to do anything with other
            * events, like click?
            stage.addEventListener(MouseEvent.CLICK, reportClick);
            */

            LFCApplication.stage.addEventListener(MouseEvent.MOUSE_MOVE, __mouseHandler);
            LFCApplication.stage.addEventListener(MouseEvent.MOUSE_UP,   __mouseHandler);
            LFCApplication.stage.addEventListener(MouseEvent.MOUSE_DOWN, __mouseHandler);
            LFCApplication.stage.addEventListener(MouseEvent.MOUSE_WHEEL, __mouseWheelHandler);
            LFCApplication.stage.addEventListener(Event.MOUSE_LEAVE, __mouseLeaveHandler);
            __listeneradded = true;
        }
    }

    // Handles global mouse events
    static function __mouseHandler(event:MouseEvent):void {
        var eventname:String = 'on' + event.type.toLowerCase();
        if (eventname == 'onmouseup' && __lastMouseDown != null) {
            // call mouseup on the sprite that got the last mouse down
            __lastMouseDown.__globalmouseup(event);
            __lastMouseDown = null;
        } else {
            if (__mouseLeft) {
                __mouseLeft = false;
                if (event.buttonDown) __mouseUpOutsideHandler();
            }
            __sendEvent(null, eventname);
        }
    }

    // sends mouseup and calls __globalmouseup when the mouse goes up outside the app - see LPP-7724
    static function __mouseUpOutsideHandler():void {
        if (__lastMouseDown != null) {
            var ev:MouseEvent = new MouseEvent('mouseup');
            __lastMouseDown.__globalmouseup(ev);
            __lastMouseDown = null;
        }
    }

    // handles MOUSE_LEAVE event
    static function __mouseLeaveHandler(event:Event = null):void {
        __mouseLeft = true;
        __sendEvent(null, 'onmouseleave');
    }

    static function __mouseWheelHandler(event:MouseEvent):void {
        lz.Keys.__mousewheelEvent(event.delta);
    }

    /**
    * Shows or hides the hand cursor for all clickable views.
    * @param Boolean show: true shows the hand cursor for buttons, false hides it
    */
    static function showHandCursor (show:Boolean) :void {
        showhandcursor = show;
    }

    static var __amLocked:Boolean = false;
    static var useBuiltinCursor:Boolean = false;
    static var cursorSprite:Sprite = null;
    static var globalCursorResource:String = null;
    static var lastCursorResource:String = null;

    #passthrough {
        private static var __builtinCursors:Object = null;
        static function get builtinCursors () :Object {
            if (__builtinCursors == null) {
                var cursors:Object = {};
                cursors[MouseCursor.ARROW] = true;
                cursors[MouseCursor.AUTO] = true;
                cursors[MouseCursor.BUTTON] = true;
                cursors[MouseCursor.HAND] = true;
                cursors[MouseCursor.IBEAM] = true;
                __builtinCursors = cursors;
            }
            return __builtinCursors;
        }
    }#

    /**
    * Sets the cursor to a resource
    * @param String what: The resource to use as the cursor.
    */
    static function setCursorGlobal (what:String) :void {
        globalCursorResource = what;
        setCursorLocal(what);
    }

    static function setCursorLocal (what:String) :void {
        if ( __amLocked ) { return; }
        if (what == null) {
            // null is invalid, maybe call restoreCursor()?
            return;
        } else if (lastCursorResource != what) {
            var resourceSprite:Sprite = getCursorResource(what);
            if (resourceSprite != null) {
                if (cursorSprite.numChildren > 0) {
                    cursorSprite.removeChildAt(0);
                }
                cursorSprite.addChild( resourceSprite );
                useBuiltinCursor = false;
            } else if (builtinCursors[what] != null) {
                useBuiltinCursor = true;
            } else {
                // invalid cursor?
                return;
            }
            lastCursorResource = what;
        }
        if (useBuiltinCursor) {
            Mouse.cursor = what;
            cursorSprite.stopDrag();
            cursorSprite.visible = false;
            LFCApplication.stage.removeEventListener(Event.MOUSE_LEAVE, mouseLeaveHandler);
            Mouse.show();
        } else {
            Mouse.hide();
            cursorSprite.x = LFCApplication.stage.mouseX;
            cursorSprite.y = LFCApplication.stage.mouseY;
            LFCApplication.setChildIndex(cursorSprite, LFCApplication._sprite.numChildren-1);
            // respond to mouse move events
            cursorSprite.startDrag();
            LFCApplication.stage.addEventListener(Event.MOUSE_LEAVE, mouseLeaveHandler);
            cursorSprite.visible = true;
        }
    }

    static function mouseLeaveHandler(evt:Event):void {
        cursorSprite.visible = false;
    }

    static function getCursorResource (resource:String):Sprite {
          if (! (LzAsset.isMovieClipAsset(resource) || LzAsset.isMovieClipLoaderAsset(resource))) {
              // only swf cursors are supported
              return null;
          }

          var resinfo:Object = LzResourceLibrary[resource];
          var assetclass:Class;
          // single frame resources get an entry in LzResourceLibrary which has
          // 'assetclass' pointing to the resource Class object.
          if (resinfo.assetclass is Class) {
              assetclass = resinfo.assetclass;
          } else {
              // Multiframe resources have an array of Class objects in frames[]
              var frames:Array = resinfo.frames;
              assetclass = frames[0];
          }

          var asset:Sprite = new assetclass();
          asset.scaleX = 1.0;
          asset.scaleY = 1.0;
          //Debug.write('cursor asset', asset);
          return asset;
    }

    /**
    * This function restores the default cursor if there is no locked cursor on
    * the screen.
    *
    * @access private
    */
    static function restoreCursor () :void {
        if ( __amLocked ) { return; }
        cursorSprite.stopDrag();
        cursorSprite.visible = false;
        LFCApplication.stage.removeEventListener(Event.MOUSE_LEAVE, mouseLeaveHandler);
        globalCursorResource = null;
        Mouse.cursor = MouseCursor.AUTO;
        Mouse.show();
    }

    /** Called by LzSprite to restore cursor to global value.
     */
    static function restoreCursorLocal () :void {
        if ( __amLocked ) { return; }
        if (globalCursorResource == null) {
            // Restore to system default pointer
            restoreCursor();
        } else {
            // Restore to the last value set by setCursorGlobal
            setCursorLocal(globalCursorResource);
        }
    }

    /**
    * Prevents the cursor from being changed until unlock is called.
    *
    */
    static function lock () :void {
        __amLocked = true;
    }

    /**
    * Restores the default cursor.
    *
    */
    static function unlock () :void {
        __amLocked = false;
        restoreCursor();
    }

    static function initCursor () :void {
        cursorSprite = new Sprite();
        cursorSprite.mouseChildren = false;
        cursorSprite.mouseEnabled = false;
        // Add the cursor DisplayObject to the root sprite
        LFCApplication.addChild(cursorSprite);
        cursorSprite.x = -10000;
        cursorSprite.y = -10000;
    }
}

Change 20090314-bargull-GHI by bargull@dell--p4--2-53 on 2009-03-14 19:31:57
    in /home/Admin/src/svn/openlaszlo/trunk
    for http://svn.openlaszlo.org/openlaszlo/trunk

Summary: add support for 'native' swf9 cursors

New Features: LPP-7912 (SWF9: support for default cursors)

Bugs Fixed:

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

Documentation:

Release Notes:

Details:
With this change the 'native' swf9 cursors (eg. hand- and ibeam-cursor) can be used for lz.Cursor.setCursorGlobal() and lz.view#cursor.

Tests:
testcase at bugreport

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