You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@flex.apache.org by ah...@apache.org on 2014/09/03 02:17:53 UTC

[20/30] Radii8 code base as accepted by IP Clearance

http://git-wip-us.apache.org/repos/asf/flex-radii8/blob/f370bfcf/Radii8Library/src/com/flexcapacitor/model/Project.as
----------------------------------------------------------------------
diff --git a/Radii8Library/src/com/flexcapacitor/model/Project.as b/Radii8Library/src/com/flexcapacitor/model/Project.as
new file mode 100644
index 0000000..29c87a1
--- /dev/null
+++ b/Radii8Library/src/com/flexcapacitor/model/Project.as
@@ -0,0 +1,1035 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package com.flexcapacitor.model {
+	import com.flexcapacitor.controller.Radiate;
+	import com.flexcapacitor.services.IServiceEvent;
+	import com.flexcapacitor.services.IWPServiceEvent;
+	
+	import flash.events.Event;
+	import flash.events.IEventDispatcher;
+	import flash.net.URLVariables;
+	
+	import mx.utils.UIDUtil;
+	
+	/**
+	 * Dispatched when project is saved
+	 * */
+	[Event(name="saveResults", type="flash.events.Event")]
+	
+	/**
+	 * Dispatched when project is opened
+	 * */
+	[Event(name="projectOpened", type="flash.events.Event")]
+	
+	/**
+	 * Project model
+	 * */
+	public class Project extends ProjectData implements IProject, ISavable {
+		
+		/**
+		 * Constructor
+		 * */
+		public function Project() {
+			nodeName = "project";
+			nameIndex++;
+			uid = UIDUtil.createUID();
+		}
+		
+		public static var PROJECT_OPENED:String = "projectOpened";
+		
+		/**
+		 * Used when creating incremental project names
+		 * */
+		public static var nameIndex:int;
+		
+		/**
+		 * Used when creating incremental document names
+		 * */
+		public var documentNameIndex:int;
+		
+		/**
+		 * Default name for new documents
+		 * */
+		public var defaultDocumentName:String = "Document";
+		
+		/**
+		 * Set to true when saving because we need to wait until we get IDs for the documents
+		 * */
+		private var deferSave:Boolean;
+		
+		/**
+		 * Set to true when saving because we need to wait until we get IDs for the documents
+		 * */
+		private var deferSaveLocations:String;
+		
+		
+		private var _documentsMetaData:Array = [];
+
+		/**
+		 * Array of documents meta data
+		 * */
+		public function get documentsMetaData():Array {
+			return _documentsMetaData;
+		}
+
+		public function set documentsMetaData(value:Array):void {
+			_documentsMetaData = value;
+		}
+
+
+		private var _projectData:IProjectData;
+
+		/**
+		 * Defines the last restored saved project data object
+		 * */
+		public function get projectData():IProjectData {
+			return _projectData;
+		}
+
+		/**
+		 * @private
+		 */
+		public function set projectData(value:IProjectData):void {
+			_projectData = value;
+		}
+
+		/**
+		 * Create unique document name
+		 * */
+		public function createDocumentName(document:IDocument = null):String {
+			var name:String;
+			
+			if (document) {
+				name = document.name ? document.name : defaultDocumentName;
+			}
+			
+			var length:int = documents.length;
+			
+			for (var i:int;i<length;i++) {
+				if (IDocument(documents[i])!=document) {
+					if (name==IDocument(documents[i]).name) {
+						name = name + " " + ++documentNameIndex; // update name
+						i = 0; // start over checking again 
+					}
+				}
+			}
+			
+			return name;
+			
+		}
+		
+		/**
+		 * Adds a document if it hasn't been added yet
+		 * */
+		public function addDocument(document:IDocument, overwrite:Boolean = false):void {
+			var exists:Boolean = getDocumentExists(document);
+			
+			if (!exists || overwrite) {
+				
+				if (exists && overwrite) {
+					var documentToRemove:IDocumentData = getDocumentByUID(document.uid);
+					removeDocument(documentToRemove);
+				}
+				
+				documents.push(document);
+				document.name = createDocumentName(document);
+				document.project = this;
+				document.projectID = uid;
+				isChanged = true;
+			}
+			else {
+				Radiate.log.info("Document already added");
+			}
+		}
+		
+		/**
+		 * Remove a document 
+		 * */
+		public function removeDocument(document:IDocumentData):void {
+			var documentIndex:int = getDocumentIndexByUID(document.uid);
+			
+			if (documentIndex!=-1) {
+				var removedArray:Array = documents.splice(documentIndex, 1);
+				
+				if (removedArray.length!=0 && removedArray[0]==document) {
+					//Radiate.log.info("Document removed " + document.name);
+				}
+				isChanged = true;
+			}
+			else {
+				//Radiate.log.info("Document not removed " + document.name);
+			}
+		}
+		
+		/**
+		 * Imports documents 
+		 * */
+		public function importDocumentInstances(documentsToImport:Array, overwrite:Boolean = false):void {
+			var metaDataLength:int = documentsMetaData.length;
+			var iDocument:IDocument;
+			var currentDocumentData:IDocumentData;
+			var iDocumentMetaData:IDocumentMetaData;
+			var documentsDataArrayLength:int;
+
+
+			// loop through project's documents metadata
+			for (var i:int;i<metaDataLength;i++) {
+				iDocumentMetaData = IDocumentMetaData(documentsMetaData[i]);
+				documentsDataArrayLength = documentsToImport.length;
+				j = 0;
+				
+				// loop through all documents for match with project that owns document
+				for (var j:int;j<documentsDataArrayLength;j++) {
+					iDocument = IDocument(documentsToImport[j]);
+					
+					
+					if (iDocument.uid == iDocumentMetaData.uid) {
+						//iDocument = currentDocumentData;
+						// should be created already
+						/*if (!(currentDocumentData is IDocument)) {
+							iDocument = currentDocumentData.createInstance(currentDocumentData);
+						}*/
+						
+						//Radiate.instance.addDocument(iDocument, this);
+						//Radiate.instance.openDocument(iDocument);
+						
+						addDocument(iDocument);//changed to document from documentdata
+						//log.info("  document added: " + iDocumentData.name);
+					}
+					else {
+						//log.info("  document not added. " + iDocumentData.name);
+					}
+				}
+			}
+		}
+		
+		/**
+		 * Opens a document if it isn't already open
+		 * */
+		public function openDocument(document:IDocument, overwrite:Boolean = false):void {
+			//document.open();
+			//Radiate.instance.openDocument(document);
+		}
+		
+		/**
+		 * Returns true if the document data is contained in the documents array
+		 * */
+		public function getDocumentExists(data:IDocumentMetaData):Boolean {
+			var length:int = documents.length;
+			
+			for (var i:int;i<length;i++) {
+				if (IDocumentData(documents[i]).uid == data.uid) {
+					return true;
+				}
+			}
+			
+			return false;
+		}
+		
+		/**
+		 * Returns true if the document exists in the documents array
+		 * */
+		public function getDocumentExistsByID(uid:String):Boolean {
+			var length:int = documents.length;
+			
+			for (var i:int;i<length;i++) {
+				if (IDocumentData(documents[i]).uid == uid) {
+					return true;
+				}
+			}
+			
+			return false;
+		}
+		
+		/**
+		 * Returns the document if it exists or null if not
+		 * */
+		public function getDocumentByUID(uid:String):IDocumentData {
+			var length:int = documents.length;
+			
+			for (var i:int;i<length;i++) {
+				if (IDocumentData(documents[i]).uid == uid) {
+					return IDocumentData(documents[i]);
+				}
+			}
+			
+			return null;
+		}
+		
+		
+		/**
+		 * Returns the document index
+		 * */
+		public function getDocumentIndexByUID(uid:String):int {
+			var length:int = documents.length;
+			
+			for (var i:int;i<length;i++) {
+				if (IDocumentData(documents[i]).uid == uid) {
+					return i;
+				}
+			}
+			
+			return -1;
+		}
+		
+		/**
+		 * @inheritDoc
+		 * */
+		override public function toXML(representation:Boolean = false):XML {
+			return marshall(XML_TYPE, representation) as XML;
+		}
+		
+		/**
+		 * @inheritDoc
+		 * */
+		override public function toString():String {
+			
+			return marshall(STRING_TYPE, true) as String;
+			
+			/*var documentData:IDocumentData;
+			var documentXML:String;
+			var xml:XML = new XML(<project/>);
+			
+			xml.@host = host;
+			xml.@id = id;
+			xml.@name = name;
+			xml.@URI = URI;
+			xml.@uid = uid;
+			xml.documents = new XML(<documents/>);
+			xml.@dateSaved = getTimeInHistory();
+			
+			if (!representation) {
+				for (var i:int;i<documents.length;i++) {
+					documentData = documents[i];
+					documentXML = documentData.toMXMLString(true);
+					XML(xml.documents).appendChild( new XML(documentXML) );
+				}
+			}
+			else {
+				throw new Error("Representative XML is not implemented");
+			}
+			
+			return xml.toXMLString();*/
+		}
+		
+		
+		/**
+		 * Get source code for document. 
+		 * Don't really like the way I'm doing this.
+		 * I think it would be better to keep exporting and importing to external classes
+		 * */
+		/*override public function getSource(target:Object = null):String {
+			var documentData:IDocumentData;
+			var documentXML:String;
+			var xml:XML = new XML(<project/>);
+			
+			xml.@host = host;
+			xml.@id = id;
+			xml.@name = name;
+			xml.@uri = uri;
+			xml.@uid = uid;
+			xml.@dateSaved = getTimeInHistory();
+			
+			//if (!representation) {
+				xml.documents = new XML(<documents/>);
+				
+				for (var i:int;i<documents.length;i++) {
+					documentData = documents[i];
+					documentXML = documentData.marshall(METADATA_TYPE, true);
+					XML(xml.documents).appendChild( new XML(documentXML) );
+				}
+				
+				for (var m:int;m<documents.length;m++) {
+					documentData = IDocumentData(documents[m]);
+					documentXML = XML(documentData.marshall(XML_TYPE, true));
+					XML(xml.documents).appendChild( documentXML );
+				}
+			//}
+			
+			return xml.toXMLString();
+			
+		}*/
+		
+		
+		/**
+		 * Serialize project data for saving. Export.
+		 * */
+		override public function marshall(format:String = PROJECT_TYPE, representation:Boolean = false):Object {
+			var documentsCount:int = documents.length;
+			var documentsArray:Array = [];
+			var documentData:IDocumentData;
+			var projectData:ProjectData;
+			var object:Object;
+			
+			// if string type get xml object. we will translate later
+			if (format==STRING_TYPE || format==XML_TYPE ) {
+				object = super.marshall(XML_TYPE, representation);
+			}
+			
+			if (format==PROJECT_TYPE || format==METADATA_TYPE) {
+				// get default document data information
+				object = super.marshall(DOCUMENT_TYPE, representation);
+				projectData = new ProjectData();
+				projectData.unmarshall(object);
+				
+				for (var i:int;i<documentsCount;i++) {
+					documentData = IDocumentData(documents[i]);
+					documentsArray.push(documentData.marshall(METADATA_TYPE, true));
+				}
+				
+				// we're saving meta data but for readability we call it documents
+				projectData.documents = documentsArray;
+			
+				return projectData;
+			}
+			else if (format==STRING_TYPE || format==XML_TYPE ) {
+				var documentXML:XML;
+				var xml:XML = XML(object);
+				
+				xml.documents = new XML(<documents/>);
+				
+				//if (!representation) {
+					for (var m:int;m<documents.length;m++) {
+						documentData = IDocumentData(documents[m]);
+						documentXML = XML(documentData.marshall(XML_TYPE, true));
+						XML(xml.documents).appendChild( documentXML );
+					}
+				//}
+				
+				if (format==STRING_TYPE) {
+					return xml.toXMLString();
+				}
+				
+				if (format==XML_TYPE) {
+					return xml;
+				}
+			}
+			
+			
+			return object;
+		}
+		
+		/**
+		 * Deserialize project data. 
+		 * */
+		override public function unmarshall(data:Object):void {
+			super.unmarshall(data);
+			
+			
+			if (data is IDocumentMetaData || data is IDocumentData) {
+				
+				if (data is IDocumentData) {
+					source = data.source;
+				}
+				
+				if (data is IProjectData) {
+					documentsMetaData = IProjectData(data).documents;
+				}
+			}
+			else if (data is XML) {
+				var documentsMetaDataList:XMLList = data.documents.document;
+				
+				source = XML(data).toXMLString();
+				originalSource = XML(data).toXMLString();
+				
+				if (data && documentsMetaDataList.length()>0) {
+					var documentsCount:int = documentsMetaDataList.length();
+					var documentMetaData:DocumentMetaData;
+					var documentXML:XML;
+					var dateCreated:int;
+					
+					
+					for (var i:int;i<documentsCount;i++) {
+						documentXML = XML(documentsMetaDataList[i]);
+						documentMetaData = new DocumentMetaData();
+						documentMetaData.unmarshall(documentXML);
+						documentsMetaData.push(documentMetaData);
+					}
+				}
+			}
+			/*
+			var iProjectData:IProjectData = data as IProjectData;
+			
+			if (iProjectData) {
+				projectData = iProjectData;
+				documentsMetaData = iProjectData.documents;
+			}*/
+		}
+		
+		/**
+		 * Deserialize XML project data. 
+		 * NOTE: TODO. We need to keep these in sync with the object representation. 
+		 * */
+		/*public function unmarshallXML(data:XML):void {
+			super.unmarshallXML(data);
+			
+			var documentsList:XMLList = data.documents.document;
+			var documentXML:XML;
+			var documentData:DocumentData;
+			var dateCreated:int;
+			
+			if (data && documentsList.length()>0) {
+				
+				var length:int = documentsList.length();
+				for (var i:int;i<length;i++) {
+					
+					documentXML = XML(documentsList[i]);
+					documentData = new DocumentData();
+					documentData.unmarshallXML(documentXML);
+					documentsMetaData.push(documentData);
+					//dateSaved = documentData.dateSaved;
+					//Radiate.instance.createDocumentFromData(documentData);
+					//Radiate.instance.addDocument(documentData.document);
+				}
+			}
+		}*/
+		
+		/**
+		 * @inheritDoc
+		 * */
+		override public function close():void {
+			super.close();
+			isOpen = false;
+		}
+		
+		/**
+		 * @inheritDoc
+		 * */
+		override public function open(location:String = REMOTE_LOCATION):void {
+			var count:int = documents.length; //fromMetaData ? documentsMetaData.length : documents.length;
+			var documentsArray:Array = documents; //fromMetaData ? documentsMetaData : documents;
+			var documentMetaData:IDocumentMetaData;
+			var documentData:IDocumentData;
+			var iDocument:IDocument;
+			var documentCreated:Boolean;
+			var isRemote:Boolean = Radiate.getInstance().getIsRemoteLocation(location);
+			var isLocal:Boolean = Radiate.getInstance().getIsLocalLocation(location);
+			var isInternal:Boolean = Radiate.getInstance().getIsInternalLocation(location);
+			
+			// do documents have remote ID? if so we have to open from the server
+			var needToWaitForDocumentsOpenResults:Boolean;
+			
+			// should set isOpen to true
+			isOpen = true;
+			
+			//Radiate.instance.openPreviouslyOpenDocuments();
+			
+			
+			// open documents
+			//if (!fromMetaData) {
+				
+				for (var i:int;i<count;i++) {
+					iDocument = IDocument(documentsArray[i]);
+					
+					
+					if (isRemote) {
+						//documentCreated = getDocumentExists(iDocument);
+						
+						//if (!documentCreated) {
+						
+						if (iDocument && !iDocument.isOpen && iDocument.id!=null) {
+							
+							if (iDocument) {
+								DocumentData(iDocument).addEventListener(LoadResultsEvent.LOAD_RESULTS, documentRetrievedResultsHandler, false, 0, true);
+ 							}
+							
+							//Radiate.log.info("calling retrieve on document " + iDocument.name);
+							iDocument.retrieve();
+						}
+						
+						//}
+						//else {
+							//iDocument = getDocumentByID(documentMetaData.uid);
+							//iDocument.open();
+							//Radiate.instance.openDocumentByData(iDocument, true);
+						//}
+					}
+					else if (isLocal) {
+						iDocument.open(DocumentData.LOCAL_LOCATION);
+						Radiate.instance.openDocumentByData(iDocument, true);
+					}
+					else if (isInternal) {
+						iDocument.open();
+						Radiate.instance.openDocument(iDocument, location, true);
+					}
+				}
+			/*	
+			}
+			else {
+				
+				for (var j:int;j<length;j++) {
+					documentMetaData = IDocumentMetaData(documentsArray[j]);
+					
+					documentCreated = getDocumentExists(documentMetaData);
+					
+					if (!documentCreated) {
+						if (documentData is DocumentData) {
+							DocumentData(documentData).addEventListener(DocumentData.RETRIEVED_RESULTS, documentRetrievedResultsHandler, false, 0, true);
+						}
+						
+						Radiate.log.info("calling retrieve on document " + documentData.name);
+						documentData.retrieve();
+					}
+					else {
+						iDocument = getDocumentByID(documentMetaData.uid);
+						iDocument.open();
+						Radiate.instance.openDocumentByData(iDocument, true);
+					}
+				}
+			}*/
+			
+			/*
+			if (!needToWaitForDocumentsOpenResults) {
+				//super.open(local);
+			}
+			else {
+				// we need to open the project with the remote ID
+				deferOpen = true;
+			}*/
+		
+		}
+		
+		/**
+		 * @inheritDoc
+		 * */
+		public function openFromMetaData(location:String = REMOTE_LOCATION):void {
+			var count:int = documentsMetaData.length;
+			var documentsArray:Array = documentsMetaData;
+			var documentMetaData:IDocumentMetaData;
+			//var documentData:IDocumentData;
+			var iDocument:IDocument;
+			var iDocumentData:IDocumentData;
+			var documentCreated:Boolean;
+			var radiate:Radiate = Radiate.getInstance();
+			
+			// do documents have remote ID? if so we have to open from the server
+			var needToWaitForDocumentsOpenResults:Boolean;
+			
+			// should set isOpen to true
+			isOpen = true;
+			
+			//Radiate.instance.openPreviouslyOpenDocuments();
+			
+			for (var j:int;j<count;j++) {
+				documentMetaData = IDocumentMetaData(documentsArray[j]);
+				
+				documentCreated = getDocumentExists(documentMetaData);
+				
+				if (!documentCreated) {
+					iDocument = radiate.createDocumentFromMetaData(documentMetaData);
+					DocumentData(iDocument).addEventListener(LoadResultsEvent.LOAD_RESULTS, documentRetrievedResultsHandler, false, 0, true);
+					//Radiate.log.info("calling retrieve on document " + iDocument.name);
+					iDocument.retrieve();
+					documents.push(iDocument);
+					iDocument.project = this;
+					/*
+					if (documentData.id==null) {
+						needToWaitForDocumentsOpenResults = true;
+					}*/
+				}
+				else {
+					iDocumentData = getDocumentByUID(documentMetaData.uid);
+					iDocumentData.open(location);
+					Radiate.instance.openDocumentByData(iDocumentData, true);
+				}
+			}
+			
+			
+			// project is already open...?
+			/*if (!needToWaitForDocumentsOpenResults) {
+				//super.open(local);
+			}
+			else {
+				// we need to open the project with the remote ID
+				deferOpen = true;
+			}*/
+		
+		}
+		
+		/**
+		 * @inheritDoc
+		 * */
+		override public function retrieve(local:Boolean = false):void {
+			var length:int = documentsMetaData.length;
+			var documentData:IDocumentData;
+			var documentsArray:Array = documents.length ? documents : documentsMetaData;
+			
+			// do documents have remote ID? if so we have to open from the server
+			var needToWaitForDocumentsOpenResults:Boolean = false;
+			
+			// open documents
+			for (var i:int;i<length;i++) {
+				documentData = IDocumentData(documentsArray[i]);
+				
+				if (documentData is DocumentData) {
+					DocumentData(documentData).addEventListener(LoadResultsEvent.LOAD_RESULTS, documentRetrievedResultsHandler, false, 0, true);
+				}
+				
+				Radiate.log.info("calling open on document " + documentData.name);
+				documentData.retrieve(local);
+				
+				if (documentData.id==null) {
+					needToWaitForDocumentsOpenResults = true;
+				}
+			}
+			
+			if (!needToWaitForDocumentsOpenResults) {
+				//super.open(local);
+			}
+			else {
+				// we need to open the project with the remote ID
+				//deferOpen = true;
+			}
+		
+		}
+		
+		/**
+		 * @inheritDoc
+		 * */
+		override public function save(locations:String = REMOTE_LOCATION, options:Object = null):Boolean {
+			var length:int = documents.length;
+			var documentData:IDocumentData;
+			var saveRemote:Boolean = locations.indexOf(REMOTE_LOCATION)!=-1;
+			var saveLocally:Boolean = locations.indexOf(LOCAL_LOCATION)!=-1;
+			
+			// do all documents have remote ID? if not we have to save again when 
+			// we get an ID from the server
+			var needToWaitForDocumentsSaveResults:Boolean = false;
+			
+			if (id==null) {
+				firstTimeSave = true;
+			}
+			
+			// save documents
+			for (var i:int;i<length;i++) {
+				documentData = IDocumentData(documents[i]);
+				
+				if (documentData.isChanged || documentData.id==null) {
+					if (saveRemote && documentData is DocumentData) {
+						DocumentData(documentData).addEventListener(SaveResultsEvent.SAVE_RESULTS, documentSaveResultsHandler, false, 0, true);
+					}
+					
+					if (saveRemote && documentData.id==null) {
+						needToWaitForDocumentsSaveResults = true;
+					}
+					
+					documentData.save(locations);
+				}
+			}
+			
+			if (!needToWaitForDocumentsSaveResults) {
+				var savedLocally:Boolean = super.save(locations);
+			}
+			else {
+				// we need to save the project when we receive the response with the remote ID
+				deferSave = true;
+				deferSaveLocations = locations;
+			}
+		
+			return savedLocally;
+		}
+		
+		
+		/**
+		 * Creates an object to send to the server
+		 * */
+		override public function toSaveFormObject():URLVariables {
+			var object:URLVariables = super.toSaveFormObject();
+			var content:String;
+			
+			object.categories = PROJECT_CATEGORY;
+			content = String(marshall(STRING_TYPE, false));
+			object.content = content;
+			object["custom[source]"] = content;
+			source = content;
+			
+			return object;
+		}
+		
+		/**
+		 * Result from project save fault
+		 * */
+		override public function saveFaultHandler(event:IServiceEvent):void {
+			super.saveFaultHandler(event);
+			
+			//trace("Save Project Fault");
+			Radiate.log.info("Error when trying to save "+ name + ".");
+			deferSave = false;
+			dispatchEvent(event as Event);
+		}
+		
+		/**
+		 * Result from project save results 
+		 * */
+		override public function saveResultsHandler(event:IWPServiceEvent):void {
+			super.saveResultsHandler(event);
+			
+			checkProjectHasChanged();
+			
+			if (firstTimeSave) {
+				firstTimeSave = false;
+				super.save(REMOTE_LOCATION);
+			}
+			else {
+				deferSave = false;
+				dispatchEvent(event as Event);
+				//Radiate.instance.setLastSaveDate();
+			}
+			//Radiate.log.info("PROJECT - Success saving project "+ name + ".");
+		}
+		
+		/**
+		 * Result from open result
+		 * */
+		override public function openResultsHandler(event:IServiceEvent):void {
+			super.openResultsHandler(event);
+			
+			// add assets
+			if (documents.length==0) {
+				dispatchProjectOpened();
+			}
+		}
+		
+		/**
+		 * Project opened
+		 * */
+		public function dispatchProjectOpened():void {
+			//Radiate.log.info("Project open complete");
+			isOpen = true;
+			dispatchEvent(new Event(PROJECT_OPENED));
+		}
+		
+		/**
+		 * Result from retrieved results
+		 * */
+		public function documentRetrievedResultsHandler(event:LoadResultsEvent):void {
+			var currentDocumentData:IDocumentData = IDocumentData(event.currentTarget);
+			var documentsArray:Array = documents; //documentsMetaData;//documents.length ? documents : documentsMetaData;
+			var length:int = documentsArray.length;
+			var documentData:IDocumentData;
+			var iDocument:IDocument;
+			var resultsNotIn:Array = [];
+			var openNotSuccessful:Array = [];
+			var data:Object = event.data;
+			
+			//Radiate.log.info("Is document " + event.currentTarget.name + " open: "+ event.successful);
+			
+			DocumentData(currentDocumentData).removeEventListener(LoadResultsEvent.LOAD_RESULTS, documentRetrievedResultsHandler);
+			
+			// check if all documents have loaded
+			for (var i:int;i<length;i++) {
+				documentData = IDocumentData(documentsArray[i]);
+				
+				if (documentData is DocumentData) {
+					
+					// check if open is in progress
+					if (DocumentData(documentData).openInProgress) {
+						resultsNotIn.push(documentData);
+					}
+					
+					// check if open is unsuccessful
+					if (!documentData.openSuccessful) {
+						openNotSuccessful.push(documentData.name);
+					}
+				}
+			}
+			
+			if (!currentDocumentData.openSuccessful) {
+				Radiate.log.info("The document '" + currentDocumentData.name + "' could not be loaded because of the following error: " + event.message);
+				
+				if (event.faultEvent) {
+					Radiate.log.info(event.faultEvent + "");
+				}
+			}
+			
+			// ALSO NEED TO UPDATE CODE IN OPEN RESULTS HANDLER
+			// all documents opened
+			if (resultsNotIn.length==0) {
+				
+				if (openNotSuccessful.length>0) {
+					//Radiate.log.info("These documents could not be opened: " + openNotSuccessful);
+					//Radiate.log.info("Document error occurred for "+documentData.name+": " + event.message);
+				}
+				
+				dispatchProjectOpened();
+			}
+			
+			// open document now that it's loaded
+			// move this to Radiate in project open event (its a new event)
+			if (currentDocumentData.openSuccessful) {
+				if (!(currentDocumentData is IDocument)) {
+					iDocument = currentDocumentData.createInstance(currentDocumentData);
+				}
+				else {
+					iDocument = IDocument(currentDocumentData);
+				}
+				
+				// we are over writing the previous instance - 
+				// but should we unmarshall it? 
+				Radiate.instance.addDocument(iDocument, this, true);
+				Radiate.instance.openDocument(iDocument);
+			}
+			
+			/*if (deferOpen) {
+				super.open();
+				deferOpen = false;
+			} else {
+				
+			}*/
+		}
+		
+		/**
+		 * Result from save results
+		 * */
+		public function documentSaveResultsHandler(event:SaveResultsEvent):void {
+			//trace("Document save results");
+			//Radiate.log.info("Is document " + event.currentTarget.name + " saved: "+ event.successful);
+			var length:int = documents.length;
+			var document:IDocumentData;
+			var resultsNotIn:Array = [];
+			var unsuccessfulSaves:Array = [];
+			var currentDocument:IDocumentData;
+			
+			currentDocument = DocumentData(event.currentTarget);
+			
+			if (currentDocument is IEventDispatcher) {
+				IEventDispatcher(currentDocument).removeEventListener(SaveResultsEvent.SAVE_RESULTS, documentSaveResultsHandler);
+			}
+			
+			for (var i:int;i<length;i++) {
+				document = IDocumentData(documents[i]);
+				
+				if (document is DocumentData) {
+					
+					// check if saving is in progress
+					if (DocumentData(document).saveInProgress) {
+						resultsNotIn.push(document);
+					}
+					
+					// check if save is unsuccessful
+					if (!document.saveSuccessful) {
+						unsuccessfulSaves.push(document.name);
+					}
+				}
+			}
+			
+			if (!currentDocument.saveSuccessful) {
+				
+				if (!Radiate.getInstance().isUserLoggedIn) {
+					Radiate.log.info("The document, '" + currentDocument.name + "' was not saved because the user is not logged in.");
+				}
+				else {
+					Radiate.log.info("The document, '" + currentDocument.name + "' was not saved because of the following error: " + event.message);
+				}
+				
+				if (event.faultEvent) {
+					Radiate.log.info(event.faultEvent + "");
+				}
+			}
+			
+			if (resultsNotIn.length==0) {
+				//Radiate.log.info(name + " save complete");
+				
+				// if document was not saved recently saveSuccessful may be false?
+				if (unsuccessfulSaves.length>0) {
+					//Radiate.log.info("These documents could not be saved: " + unsuccessfulSaves);
+				}
+				else {
+					//isChanged = false; // hardcoding for now until checkProjectHasChanged is fixed
+				}
+			}
+			
+			if (deferSave) {
+				super.save(deferSaveLocations);
+				deferSave = false;
+			} else {
+				
+			}
+			
+			
+			//DocumentData(document).addEventListener(DocumentData.SAVE_RESULTS, documentSaveResultsHandler, false, 0, true);
+			
+		}
+		
+		/**
+		 * Check if project source has changed
+		 * */
+		public function checkProjectHasChanged():Boolean {
+			//var content:String = String(marshall(STRING_TYPE, false));
+			var contentXML:XML = XML(marshall(XML_TYPE, false));
+			var sourceXML:XML = new XML(source);
+			var pattern:RegExp = / dateSaved=\"\d+\"/g;
+			
+			//delete contentXML.@dateSaved;
+			
+			var contentXMLValue:String = contentXML.toXMLString().replace(pattern, "");
+			var sourceXMLValue:String = sourceXML.toXMLString().replace(pattern, "");
+			
+			if (contentXMLValue!=sourceXMLValue) { // will always be false because date and time is saved on each call
+				isChanged = true;
+			}
+			else {
+				isChanged = false;
+			}
+			//isChanged = false; // setting to false for now until we find a better way
+			
+			return isChanged;
+		}
+		
+		
+		/**
+		 * Get a list of documents for local storage. If open is set to true then only returns open documents.
+		 * */
+		public function getSavableDocumentsData(open:Boolean = false, metaData:Boolean = false):Array {
+			var documentsArray:Array = [];
+			var length:int = documents.length;
+			var iDocument:IDocument;
+			
+			
+			for (var i:int;i<length;i++) {
+				iDocument = IDocument(documents[i]);
+				//Radiate.log.info("Exporting document " + iDocument.name);
+				
+				if (open) {
+					if (iDocument.isOpen) {
+						if (metaData) {
+							documentsArray.push(iDocument.toMetaData());
+						}
+						else {
+							documentsArray.push(iDocument.marshall());
+							//Radiate.log.info("Exporting document " + iDocument.source);
+						}
+					}
+				}
+				else {
+					if (metaData) {
+						documentsArray.push(iDocument.toMetaData());
+					}
+					else {
+						documentsArray.push(iDocument.marshall(DOCUMENT_TYPE, false));
+					}
+				}
+			}
+			
+			
+			return documentsArray;
+		}
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-radii8/blob/f370bfcf/Radii8Library/src/com/flexcapacitor/model/ProjectData.as
----------------------------------------------------------------------
diff --git a/Radii8Library/src/com/flexcapacitor/model/ProjectData.as b/Radii8Library/src/com/flexcapacitor/model/ProjectData.as
new file mode 100644
index 0000000..5426728
--- /dev/null
+++ b/Radii8Library/src/com/flexcapacitor/model/ProjectData.as
@@ -0,0 +1,63 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package com.flexcapacitor.model {
+	
+	
+	/**
+	 * Holds project data for storage
+	 * */
+	[RemoteClass(alias="ProjectData")]
+	public class ProjectData extends DocumentData implements IProjectData {
+		
+		
+		public function ProjectData() {
+			
+		}
+
+
+		private var _documentsData:Array = [];
+
+		/**
+		 * @inheritDoc
+		 * */
+		public function get documentsData():Array {
+			return _documentsData;
+		}
+
+		public function set documentsData(value:Array):void {
+			_documentsData = value;
+		}
+
+
+		private var _documents:Array = [];
+
+		/**
+		 * @inheritDoc
+		 * */
+		public function get documents():Array {
+			return _documents;
+		}
+
+		public function set documents(value:Array):void {
+			_documents = value;
+		}
+		
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-radii8/blob/f370bfcf/Radii8Library/src/com/flexcapacitor/model/ProjectDataDescriptor.as
----------------------------------------------------------------------
diff --git a/Radii8Library/src/com/flexcapacitor/model/ProjectDataDescriptor.as b/Radii8Library/src/com/flexcapacitor/model/ProjectDataDescriptor.as
new file mode 100644
index 0000000..9079352
--- /dev/null
+++ b/Radii8Library/src/com/flexcapacitor/model/ProjectDataDescriptor.as
@@ -0,0 +1,107 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package com.flexcapacitor.model {
+	import mx.collections.ICollectionView;
+	import mx.controls.treeClasses.DefaultDataDescriptor;
+	
+	/**
+	 * Describes how project data is displayed in a tree
+	 * */
+	public class ProjectDataDescriptor extends DefaultDataDescriptor {
+		
+		
+		public function ProjectDataDescriptor() {
+			super();
+		}
+		
+		/**
+		 * Get documents for now
+		 * */
+		override public function getChildren(node:Object, model:Object = null):ICollectionView {
+			if ("documents" in node) {
+				return node.documents;
+			}
+			
+			return null;
+		}
+		
+	
+	    /**
+	     *  Tests a node for termination.
+	     *  Branches are non-terminating but are not required to have any leaf nodes.
+	     *  If the node is XML, returns <code>true</code> if the node has children
+	     *  or a <code>true isBranch</code> attribute.
+	     *  If the node is an object, returns <code>true</code> if the node has a
+	     *  (possibly empty) <code>children</code> field.
+	     *
+	     *  @param node The node object currently being evaluated.
+	     *  @param model The collection that contains the node; ignored by this class.
+	     *  
+	     *  @return <code>true</code> if this node is non-terminating.
+	     *  
+	     *  @langversion 3.0
+	     *  @playerversion Flash 9
+	     *  @playerversion AIR 1.1
+	     *  @productversion Flex 3
+	     */
+	    override public function isBranch(node:Object, model:Object = null):Boolean
+	    {
+	        if (node == null)
+	            return false;
+	            
+	        var branch:Boolean = false;
+	            
+	        if (node is XML)
+	        {
+	            var childList:XMLList = node.children();
+	            //accessing non-required e4x attributes is quirky
+	            //but we know we'll at least get an XMLList
+	            var branchFlag:XMLList = node.@isBranch;
+	            //check to see if a flag has been set
+	            if (branchFlag.length() == 1)
+	            {
+	                //check flag and return (this flag overrides termination status)
+	                if (branchFlag[0] == "true")
+	                    branch = true;
+	            }
+	            //since no flags, we'll check to see if there are children
+	            else if (childList.length() != 0)
+	            {
+	                branch = true;
+	            }
+	        }
+	        else if (node is Object)
+	        {
+	            try
+	            {
+	                if (node.documents != undefined)
+	                {
+	                    branch = true;
+	                }
+	            }
+	            catch(e:Error)
+	            {
+	            }
+	        }
+	        return branch;
+	    }
+
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-radii8/blob/f370bfcf/Radii8Library/src/com/flexcapacitor/model/ProjectMetaData.as
----------------------------------------------------------------------
diff --git a/Radii8Library/src/com/flexcapacitor/model/ProjectMetaData.as b/Radii8Library/src/com/flexcapacitor/model/ProjectMetaData.as
new file mode 100644
index 0000000..5627c9c
--- /dev/null
+++ b/Radii8Library/src/com/flexcapacitor/model/ProjectMetaData.as
@@ -0,0 +1,33 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package com.flexcapacitor.model {
+	
+	/**
+	 * Used to store basic information about a project for later retrieval.
+	 * */
+	[RemoteClass(alias="ProjectMetaData")]
+	public class ProjectMetaData extends DocumentMetaData implements IProjectMetaData {
+		
+		public function ProjectMetaData() {
+			
+		}
+		
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-radii8/blob/f370bfcf/Radii8Library/src/com/flexcapacitor/model/SaveResultsEvent.as
----------------------------------------------------------------------
diff --git a/Radii8Library/src/com/flexcapacitor/model/SaveResultsEvent.as b/Radii8Library/src/com/flexcapacitor/model/SaveResultsEvent.as
new file mode 100644
index 0000000..00d9115
--- /dev/null
+++ b/Radii8Library/src/com/flexcapacitor/model/SaveResultsEvent.as
@@ -0,0 +1,81 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package com.flexcapacitor.model {
+	import com.flexcapacitor.services.IWPServiceEvent;
+	import com.flexcapacitor.services.ServiceEvent;
+	
+	import flash.events.Event;
+	
+	/**
+	 * Indicates if save of document was successful
+	 * */
+	public class SaveResultsEvent extends ServiceEvent implements IWPServiceEvent {
+		
+		/**
+		 * Event dispatched when the save results are returned
+		 * */
+		public static const SAVE_RESULTS:String = "saveResults";
+		
+
+		private var _call:String;
+
+		/**
+		 * 
+		 * */
+		public function get call():String {
+			return _call;
+		}
+
+		public function set call(value:String):void {
+			_call = value;
+		}
+
+		private var _text:String;
+
+		private var _message:String;
+
+		/**
+		 * 
+		 * */
+		public function get message():String {
+			return _message;
+		}
+
+		public function set message(value:String):void {
+			_message = value;
+		}
+
+		
+		public function SaveResultsEvent(type:String, bubbles:Boolean=false, cancelable:Boolean=false, successful:Boolean = false)
+		{
+			super(type, bubbles, cancelable);
+			this.successful = successful;
+		}
+		
+		/**
+		 * Indicates if save was successful
+		 * */
+		public var successful:Boolean;
+		
+		override public function clone():Event {
+			return new SaveResultsEvent(type, bubbles, cancelable, successful);
+		}
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-radii8/blob/f370bfcf/Radii8Library/src/com/flexcapacitor/model/SavedData.as
----------------------------------------------------------------------
diff --git a/Radii8Library/src/com/flexcapacitor/model/SavedData.as b/Radii8Library/src/com/flexcapacitor/model/SavedData.as
new file mode 100644
index 0000000..d2e7405
--- /dev/null
+++ b/Radii8Library/src/com/flexcapacitor/model/SavedData.as
@@ -0,0 +1,76 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package com.flexcapacitor.model {
+	
+	
+	/**
+	 * Class used to store projects, documents and resources
+	 * */
+	[RemoteClass(alias="SavedData")]
+	public class SavedData implements ISavedData {
+		
+		public function SavedData() {
+			modified = created = new Date().time;
+		}
+		
+		
+		private var _version:uint = 1;
+
+		public function get version():uint {
+			return _version;
+		}
+
+		public function set version(value:uint):void {
+			_version = value;
+		}
+		
+		public var saveCount:int;
+		
+		
+		public var created:uint;
+		public var modified:uint;
+		private var _modifiedValue:uint;
+
+		public function get modifiedValue():uint {
+			return _modifiedValue;
+		}
+
+		public function set modifiedValue(value:uint):void {
+			_modifiedValue = value;
+		}
+
+		
+		public var workspaces:Array = [];
+		
+		public var projects:Array = [];
+		
+		public var documents:Array = [];
+		
+		public var resources:Array = [];
+		
+		
+		
+		public function unmarshall(data:Object):void {
+			
+			
+			
+		}
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-radii8/blob/f370bfcf/Radii8Library/src/com/flexcapacitor/model/Settings.as
----------------------------------------------------------------------
diff --git a/Radii8Library/src/com/flexcapacitor/model/Settings.as b/Radii8Library/src/com/flexcapacitor/model/Settings.as
new file mode 100644
index 0000000..1d2b0cb
--- /dev/null
+++ b/Radii8Library/src/com/flexcapacitor/model/Settings.as
@@ -0,0 +1,82 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package com.flexcapacitor.model {
+	
+	
+	/**
+	 * Class used to store settings and projects
+	 * */
+	[RemoteClass(alias="Settings")]
+	public class Settings implements ISettings {
+		
+		public function Settings() {
+			
+			lastOpened = modified = created = new Date().time;
+		}
+		
+		private var _version:uint = 1;
+
+		public function get version():uint {
+			return _version;
+		}
+
+		public function set version(value:uint):void {
+			_version = value;
+		}
+		
+		
+		public var created:uint;
+		public var modified:uint;
+		private var _modifiedValue:uint;
+
+		public function get modifiedValue():uint {
+			return new Date().time;
+		}
+
+		public function set modifiedValue(value:uint):void {
+			_modifiedValue = value;
+		}
+
+		public var lastOpened:uint; 
+		
+		public var configuration:Object;
+		
+		public var openProjects:Array = [];
+		
+		public var openDocuments:Array = [];
+		
+		public var openWorkspace:Array = [];
+		
+		public var selectedDocument:IDocumentMetaData;
+		
+		public var selectedProject:IDocumentMetaData;
+		
+		public var saveCount:int;
+		
+		
+		
+		public function unmarshall(data:Object):void {
+			
+			
+			
+		}
+		
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-radii8/blob/f370bfcf/Radii8Library/src/com/flexcapacitor/model/Size.as
----------------------------------------------------------------------
diff --git a/Radii8Library/src/com/flexcapacitor/model/Size.as b/Radii8Library/src/com/flexcapacitor/model/Size.as
new file mode 100644
index 0000000..e4edcc8
--- /dev/null
+++ b/Radii8Library/src/com/flexcapacitor/model/Size.as
@@ -0,0 +1,61 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package com.flexcapacitor.model {
+	
+	/**
+	 * Base class for document sizes
+	 * */
+	public class Size {
+		
+		
+		public function Size(width:String="0", height:String="0", ppi:int=0)
+		{
+			this.width = width;
+			this.height = height;
+			this.ppi = ppi;
+		}
+		
+		/**
+		 * 
+		 * */
+		public var name:String;
+		
+		/**
+		 * Width can be percent
+		 * */
+		public var width:String;
+		
+		/**
+		 * Height can be percent
+		 * */
+		public var height:String;
+		
+		/**
+		 * Points per inch
+		 * */
+		public var ppi:int;
+		
+		/**
+		 * Screen type
+		 * */
+		public var type:String;
+		
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-radii8/blob/f370bfcf/Radii8Library/src/com/flexcapacitor/model/StyleMetaData.as
----------------------------------------------------------------------
diff --git a/Radii8Library/src/com/flexcapacitor/model/StyleMetaData.as b/Radii8Library/src/com/flexcapacitor/model/StyleMetaData.as
new file mode 100644
index 0000000..530f9ea
--- /dev/null
+++ b/Radii8Library/src/com/flexcapacitor/model/StyleMetaData.as
@@ -0,0 +1,102 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package com.flexcapacitor.model {
+	import mx.styles.IStyleClient;
+	
+	/**
+	 * Contains information on style metadata
+	 * */
+	public class StyleMetaData extends MetaData {
+		
+		/**
+		 * Constructor
+		 * */
+		public function StyleMetaData(item:XML = null, target:* = null) {
+			if (item) unmarshall(item, target);
+		}
+		
+		/**
+		 * 
+		 * */
+		public var inherit:Boolean;
+		
+		/**
+		 * Set to true if style is defined on the target. 
+		 * In other words the user set it in MXML or AS3 and it is not inherited.
+		 * styleClient.getStyle(thisStyle)!==undefined. 
+		 * */
+		public var definedInline:Boolean;
+		
+		/**
+		 * 
+		 * */
+		public var inheritedValue:*;
+		
+		/**
+		 * 
+		 * */
+		public var nonInheritedValue:*;
+		
+		/**
+		 * Import metadata XML Style node into this instance
+		 * */
+		override public function unmarshall(item:XML, target:* = null, getValue:Boolean = true):void {
+			super.unmarshall(item, target, getValue);
+			
+			var args:XMLList = item.arg;
+			var keyName:String;
+			var keyValue:String;
+			
+			
+			for each (var arg:XML in args) {
+				keyName = arg.@key;
+				
+				if (keyName=="inherit") {
+					inherit = keyValue=="no";//bug?
+					break;
+				}
+				
+			}
+			
+			// this shows if it's defined at all 
+			definedInline = target && target is IStyleClient && target.getStyle(name)!==undefined;
+			
+			if (!definedInline) {
+				inheritedValue = target.getStyle(name);
+				nonInheritedValue = undefined;
+				value = inheritedValue;
+				textValue = "" + inheritedValue;
+			}
+			else {
+				// don't know how to get this value -
+				// UPDATE: there is CSS code in MiniInspector to check if a value is 
+				// set inline or inherited
+				// we also have the inheritedStyles and nonInherited object on IStyleClient
+				inheritedValue = undefined;
+				nonInheritedValue = target.getStyle(name);
+				value = nonInheritedValue;
+				textValue = "" + nonInheritedValue;
+			}
+			
+			
+			
+		}
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-radii8/blob/f370bfcf/Radii8Library/src/com/flexcapacitor/model/VisualElementVO.as
----------------------------------------------------------------------
diff --git a/Radii8Library/src/com/flexcapacitor/model/VisualElementVO.as b/Radii8Library/src/com/flexcapacitor/model/VisualElementVO.as
new file mode 100644
index 0000000..07e2d3b
--- /dev/null
+++ b/Radii8Library/src/com/flexcapacitor/model/VisualElementVO.as
@@ -0,0 +1,64 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+
+
+
+/**
+ * Used for display in the Outline view
+ * */
+package com.flexcapacitor.model {
+	
+	import com.flexcapacitor.utils.InspectorUtils;
+	
+	import flash.display.DisplayObjectContainer;
+	
+	import mx.collections.ArrayCollection;
+
+	public class VisualElementVO {
+
+		public var id:String;
+		public var name:String;
+		public var type:String;
+		public var superClass:String;
+		public var element:Object;
+		public var children:ArrayCollection;
+		public var parent:DisplayObjectContainer;
+		public var label:String;
+
+		public function VisualElementVO() {
+
+		}
+
+		public static function unmarshall(element:*):VisualElementVO {
+			var vo:VisualElementVO = new VisualElementVO();
+			
+			vo.id = 		InspectorUtils.getIdentifier(element);
+			vo.name = 		InspectorUtils.getName(element);
+			vo.type = 		InspectorUtils.getClassName(element);
+			vo.superClass = InspectorUtils.getSuperClassName(element);
+			vo.element = 	element;
+			vo.label =		vo.type;
+			
+			// get vo.children manually
+
+			return vo;
+		}
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-radii8/blob/f370bfcf/Radii8Library/src/com/flexcapacitor/skins/DeviceImage.mxml
----------------------------------------------------------------------
diff --git a/Radii8Library/src/com/flexcapacitor/skins/DeviceImage.mxml b/Radii8Library/src/com/flexcapacitor/skins/DeviceImage.mxml
new file mode 100644
index 0000000..c00cd81
--- /dev/null
+++ b/Radii8Library/src/com/flexcapacitor/skins/DeviceImage.mxml
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+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.
+
+-->
+
+<!--- The default skin class for a Spark SkinnableContainer container.  
+
+     @see spark.components.SkinnableContainer
+        
+      @langversion 3.0
+      @playerversion Flash 10
+      @playerversion AIR 1.5
+      @productversion Flex 4
+-->
+<s:Skin xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" 
+    xmlns:fb="http://ns.adobe.com/flashbuilder/2009" alpha.disabled="0.5">
+
+    <fx:Metadata>
+    <![CDATA[ 
+        /** 
+         * @copy spark.skins.spark.ApplicationSkin#hostComponent
+         */
+        [HostComponent("spark.components.SkinnableContainer")]
+    ]]>
+    </fx:Metadata> 
+    
+    <fx:Script fb:purpose="styling">
+        <![CDATA[         
+            /**
+             *  @private
+             */
+            override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number) : void
+            {
+                // Push backgroundColor and backgroundAlpha directly.
+                // Handle undefined backgroundColor by hiding the background object.
+                if (isNaN(getStyle("backgroundColor")))
+                {
+                    background.visible = false;
+                }
+                else
+                {
+                    background.visible = true;
+                    bgFill.color = getStyle("backgroundColor");
+                    bgFill.alpha = getStyle("backgroundAlpha");
+                }
+                
+                super.updateDisplayList(unscaledWidth, unscaledHeight);
+            }
+        ]]>        
+    </fx:Script>
+    
+    <s:states>
+        <s:State name="normal" />
+        <s:State name="disabled" />
+    </s:states>
+    
+    <!--- Defines the appearance of the SkinnableContainer class's background. -->
+    <s:Rect id="background" left="0" right="0" top="0" bottom="0">
+        <s:fill>
+            <!--- @private -->
+            <s:SolidColor id="bgFill" color="#FFFFFF"/>
+        </s:fill>
+    </s:Rect>
+    
+    <!--
+        Note: setting the minimum size to 0 here so that changes to the host component's
+        size will not be thwarted by this skin part's minimum size.   This is a compromise,
+        more about it here: http://bugs.adobe.com/jira/browse/SDK-21143
+    -->
+    <!--- @copy spark.components.SkinnableContainer#contentGroup -->
+    <s:Group id="contentGroup" left="0" right="0" top="0" bottom="0" minWidth="0" minHeight="0">
+        <s:layout>
+            <s:BasicLayout/>
+        </s:layout>
+    </s:Group>
+
+</s:Skin>

http://git-wip-us.apache.org/repos/asf/flex-radii8/blob/f370bfcf/Radii8Library/src/com/flexcapacitor/skins/DeviceSkin.mxml
----------------------------------------------------------------------
diff --git a/Radii8Library/src/com/flexcapacitor/skins/DeviceSkin.mxml b/Radii8Library/src/com/flexcapacitor/skins/DeviceSkin.mxml
new file mode 100644
index 0000000..6d65b42
--- /dev/null
+++ b/Radii8Library/src/com/flexcapacitor/skins/DeviceSkin.mxml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+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.
+
+-->
+
+
+<!--- The default skin class for a Spark SkinnableContainer container.  
+
+     @see spark.components.SkinnableContainer
+        
+      @langversion 3.0
+      @playerversion Flash 10
+      @playerversion AIR 1.5
+      @productversion Flex 4
+-->
+<s:Skin xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" 
+    xmlns:fb="http://ns.adobe.com/flashbuilder/2009" alpha.disabled="0.5">
+
+    <fx:Metadata>
+    <![CDATA[ 
+        /** 
+         * @copy spark.skins.spark.ApplicationSkin#hostComponent
+         */
+        [HostComponent("spark.components.SkinnableContainer")]
+    ]]>
+    </fx:Metadata> 
+    
+    <fx:Script fb:purpose="styling">
+        <![CDATA[         
+            /**
+             *  @private
+             */
+            override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number) : void
+            {
+				//trace("IN SKIN");
+                // Push backgroundColor and backgroundAlpha directly.
+                // Handle undefined backgroundColor by hiding the background object.
+                /*if (isNaN(getStyle("backgroundColor")))
+                {
+                    background.visible = false;
+                }
+                else
+                {
+                    background.visible = true;
+                    bgFill.color = getStyle("backgroundColor");
+                    bgFill.alpha = getStyle("backgroundAlpha");
+                }*/
+                
+                super.updateDisplayList(unscaledWidth, unscaledHeight);
+            }
+        ]]>        
+    </fx:Script>
+    
+    <s:states>
+        <s:State name="portrait" />
+        <s:State name="landscape" />
+        <s:State name="disabled" />
+        <s:State name="normal" />
+    </s:states>
+    
+    <!--- Defines the appearance of the SkinnableContainer class's background. -->
+    <s:Rect id="background" left="0" right="0" top="0" bottom="0" radiusX="10" radiusY="10">
+        <s:fill>
+            <!--- @private -->
+            <s:SolidColor id="bgFill" color="#FF0000"/>
+        </s:fill>
+    </s:Rect>
+    
+    <!--
+        Note: setting the minimum size to 0 here so that changes to the host component's
+        size will not be thwarted by this skin part's minimum size.   This is a compromise,
+        more about it here: http://bugs.adobe.com/jira/browse/SDK-21143
+    -->
+    <!--- @copy spark.components.SkinnableContainer#contentGroup -->
+    <s:Group id="contentGroup" 
+			 left.portrait="20" 
+			 right.portrait="20" 
+			 top.portrait="40" 
+			 bottom.portrait="40" 
+			 
+			 left.landscape="40" 
+			 right.landscape="40" 
+			 top.landscape="20" 
+			 bottom.landscape="20" 
+			 minWidth="0" 
+			 minHeight="0"
+			 width="100%" height="100%">
+        <s:layout>
+            <s:BasicLayout/>
+        </s:layout>
+    </s:Group>
+
+</s:Skin>

http://git-wip-us.apache.org/repos/asf/flex-radii8/blob/f370bfcf/Radii8Library/src/com/flexcapacitor/skins/MenuBarButtonSkin.mxml
----------------------------------------------------------------------
diff --git a/Radii8Library/src/com/flexcapacitor/skins/MenuBarButtonSkin.mxml b/Radii8Library/src/com/flexcapacitor/skins/MenuBarButtonSkin.mxml
new file mode 100644
index 0000000..41caa02
--- /dev/null
+++ b/Radii8Library/src/com/flexcapacitor/skins/MenuBarButtonSkin.mxml
@@ -0,0 +1,233 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+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.
+
+-->
+
+<!--- The default skin class for the Spark Button component.  
+
+       @see spark.components.Button
+        
+      @langversion 3.0
+      @playerversion Flash 10
+      @playerversion AIR 1.5
+      @productversion Flex 4
+-->
+<s:SparkButtonSkin xmlns:fx="http://ns.adobe.com/mxml/2009" 
+             xmlns:s="library://ns.adobe.com/flex/spark" 
+             xmlns:fb="http://ns.adobe.com/flashbuilder/2009"
+             minWidth="21" minHeight="21" 
+             alpha.disabled="0.5">
+     
+    <fx:Metadata>
+        <![CDATA[ 
+        /** 
+         * @copy spark.skins.spark.ApplicationSkin#hostComponent
+         */
+        [HostComponent("spark.components.Button")]
+        ]]>
+    </fx:Metadata>
+    
+    <fx:Script fb:purpose="styling">
+        <![CDATA[         
+            import spark.components.Group;
+            /* Define the skin elements that should not be colorized. 
+            For button, the graphics are colorized but the label is not. */
+            static private const exclusions:Array = ["labelDisplay"];
+            
+            /** 
+             * @private
+             */     
+            override public function get colorizeExclusions():Array {return exclusions;}
+            
+            /**
+             * @private
+             */
+            override protected function initializationComplete():void
+            {
+                useChromeColor = true;
+                super.initializationComplete();
+            }  
+            
+            /**
+             *  @private
+             */
+            override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number) : void
+            {
+                var cr:Number = getStyle("cornerRadius");
+                
+                if (cornerRadius != cr)
+                {
+                    cornerRadius = cr;
+                    /*shadow.radiusX = cornerRadius;
+                    fill.radiusX = cornerRadius;
+                    lowlight.radiusX = cornerRadius;
+                    highlight.radiusX = cornerRadius;
+                    border.radiusX = cornerRadius;*/
+                }
+                /*
+                if (highlightStroke) highlightStroke.radiusX = cornerRadius;
+                if (hldownstroke1) hldownstroke1.radiusX = cornerRadius;
+                if (hldownstroke2) hldownstroke2.radiusX = cornerRadius;*/
+                
+                super.updateDisplayList(unscaledWidth, unscaledHeight);
+				
+				if (labelDisplay) {
+					Label(labelDisplay).setStyle("color", 0xFFFFFF);
+				}
+            }
+            
+            private var cornerRadius:Number = 2;
+                                 
+        ]]>        
+    </fx:Script>
+        
+    <!-- states -->
+    <s:states>
+        <s:State name="up" />
+        <s:State name="over" />
+        <s:State name="down" />
+        <s:State name="disabled" />
+    </s:states>
+    
+    <!-- layer 1: shadow -->
+    <!--- @private -->
+    <!--<s:Rect id="shadow" left="-1" right="-1" top="-1" bottom="-1" radiusX="2">
+        <s:fill>
+            <s:LinearGradient rotation="90">
+                <s:GradientEntry color="0x000000" 
+                                 color.down="0xFFFFFF"
+                                 alpha="0.01"
+                                 alpha.down="0" />
+                <s:GradientEntry color="0x000000" 
+                                 color.down="0xFFFFFF" 
+                                 alpha="0.07"
+                                 alpha.down="0.5" />
+            </s:LinearGradient>
+        </s:fill>
+    </s:Rect>-->
+    
+    <!-- layer 2: fill -->
+    <!--- @private -->
+    <!--<s:Rect id="fill" left="1" right="1" top="1" bottom="1" radiusX="2">
+        <s:fill>
+            <s:LinearGradient rotation="90">
+                <s:GradientEntry color="0xFFFFFF" 
+                                 color.over="0xBBBDBD" 
+                                 color.down="0xAAAAAA" 
+                                 alpha="0.85" />
+                <s:GradientEntry color="0xD8D8D8" 
+                                 color.over="0x9FA0A1" 
+                                 color.down="0x929496" 
+                                 alpha="0.85" />
+            </s:LinearGradient>
+        </s:fill>
+    </s:Rect>-->
+
+    <!-- layer 3: fill lowlight -->
+    <!--- @private -->
+    <!--<s:Rect id="lowlight" left="1" right="1" top="1" bottom="1" radiusX="2">
+        <s:fill>
+            <s:LinearGradient rotation="270">
+                <s:GradientEntry color="0x000000" ratio="0.0" alpha="0.0627" />
+                <s:GradientEntry color="0x000000" ratio="0.48" alpha="0.0099" />
+                <s:GradientEntry color="0x000000" ratio="0.48001" alpha="0" />
+            </s:LinearGradient>
+        </s:fill>
+    </s:Rect>-->
+    
+    <!-- layer 4: fill highlight -->
+    <!--- @private -->
+    <!--<s:Rect id="highlight" left="1" right="1" top="1" bottom="1" radiusX="2">
+        <s:fill>
+            <s:LinearGradient rotation="90">
+                <s:GradientEntry color="0xFFFFFF"
+                                 ratio="0.0"
+                                 alpha="0.33" 
+                                 alpha.over="0.22" 
+                                 alpha.down="0.12"/>
+                <s:GradientEntry color="0xFFFFFF"
+                                 ratio="0.48"
+                                 alpha="0.33"
+                                 alpha.over="0.22"
+                                 alpha.down="0.12" />
+                <s:GradientEntry color="0xFFFFFF"
+                                 ratio="0.48001"
+                                 alpha="0" />
+            </s:LinearGradient>
+        </s:fill>
+    </s:Rect>-->
+    
+    <!-- layer 5: highlight stroke (all states except down) -->
+    <!--- @private -->
+    <!--<s:Rect id="highlightStroke" left="1" right="1" top="1" bottom="1" radiusX="2" excludeFrom="down">
+        <s:stroke>
+            <s:LinearGradientStroke rotation="90" weight="1">
+                <s:GradientEntry color="0xFFFFFF" alpha.over="0.22" />
+                <s:GradientEntry color="0xD8D8D8" alpha.over="0.22" />
+            </s:LinearGradientStroke>
+        </s:stroke>
+    </s:Rect>-->
+    
+    <!-- layer 6: highlight stroke (down state only) -->
+    <!--- @private -->
+    <!--<s:Rect id="hldownstroke1" left="1" right="1" top="1" bottom="1" radiusX="2" includeIn="down">
+        <s:stroke>
+            <s:LinearGradientStroke rotation="90" weight="1">
+                <s:GradientEntry color="0x000000" alpha="0.25" ratio="0.0" />
+                <s:GradientEntry color="0x000000" alpha="0.25" ratio="0.001" />
+                <s:GradientEntry color="0x000000" alpha="0.07" ratio="0.0011" />
+                <s:GradientEntry color="0x000000" alpha="0.07" ratio="0.965" />
+                <s:GradientEntry color="0x000000" alpha="0.00" ratio="0.9651" />
+            </s:LinearGradientStroke>
+        </s:stroke>
+    </s:Rect>-->
+    <!--- @private -->
+    <!--<s:Rect id="hldownstroke2" left="2" right="2" top="2" bottom="2" radiusX="2" includeIn="down">
+        <s:stroke>
+            <s:LinearGradientStroke rotation="90" weight="1">
+                <s:GradientEntry color="0x000000" alpha="0.09" ratio="0.0" />
+                <s:GradientEntry color="0x000000" alpha="0.00" ratio="0.0001" />
+            </s:LinearGradientStroke>
+        </s:stroke>
+    </s:Rect>-->
+
+    <!-- layer 7: border - put on top of the fill so it doesn't disappear when scale is less than 1 -->
+    <!--- @private -->
+    <!--<s:Rect id="border" left="0" right="0" top="0" bottom="0" width="69" height="20" radiusX="2">
+        <s:stroke>
+            <s:LinearGradientStroke rotation="90" weight="1">
+                <s:GradientEntry color="0x000000" 
+                                 alpha="0.5625"
+                                 alpha.down="0.6375" />
+                <s:GradientEntry color="0x000000" 
+                                 alpha="0.75" 
+                                 alpha.down="0.85" />
+            </s:LinearGradientStroke>
+        </s:stroke>
+    </s:Rect>-->
+    
+    <!-- layer 8: text -->
+    <!--- @copy spark.components.supportClasses.ButtonBase#labelDisplay  -->
+    <s:Label id="labelDisplay"
+             textAlign="center"
+             maxDisplayedLines="1"
+             horizontalCenter="0" verticalCenter="1" verticalAlign="middle"
+             left="10" right="10" top="2" bottom="2">
+    </s:Label>
+    
+</s:SparkButtonSkin>

http://git-wip-us.apache.org/repos/asf/flex-radii8/blob/f370bfcf/Radii8Library/src/com/flexcapacitor/skins/MenuItemSkin.mxml
----------------------------------------------------------------------
diff --git a/Radii8Library/src/com/flexcapacitor/skins/MenuItemSkin.mxml b/Radii8Library/src/com/flexcapacitor/skins/MenuItemSkin.mxml
new file mode 100644
index 0000000..38764e4
--- /dev/null
+++ b/Radii8Library/src/com/flexcapacitor/skins/MenuItemSkin.mxml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+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.
+
+-->
+
+<!--- The wireframe skin class for menu items in the MX Menu component. 
+
+      @see mx.controls.Menu
+      @see mx.controls.MenuItem
+        
+      @langversion 3.0
+      @playerversion Flash 10
+      @playerversion AIR 1.5
+      @productversion Flex 4
+-->
+<s:Skin xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" 
+      minWidth="21" minHeight="21"
+      alpha.disabled="0.5">
+
+    <!-- states -->
+    <s:states>
+        <s:State name="up" />
+        <s:State name="over" />
+        <s:State name="down" />
+        <s:State name="disabled" />
+    </s:states>
+    
+    <!-- layer 1: fill -->
+    <s:Rect left="0" right="0" top="1" bottom="1" excludeFrom="up,disabled" >
+        <s:fill>
+            <s:SolidColor color="#5983f7" />
+        </s:fill>
+    </s:Rect>
+    
+    <!-- layer 2: fill highlight -->
+    <!--<s:Rect left="0" right="0" top="1" height="9" excludeFrom="up" >
+        <s:fill>
+            <s:SolidColor color="0xFFFFFF" alpha="0.33" />
+        </s:fill>
+    </s:Rect>-->
+    
+</s:Skin>

http://git-wip-us.apache.org/repos/asf/flex-radii8/blob/f370bfcf/Radii8Library/src/com/flexcapacitor/skins/PopUpButtonSkin.mxml
----------------------------------------------------------------------
diff --git a/Radii8Library/src/com/flexcapacitor/skins/PopUpButtonSkin.mxml b/Radii8Library/src/com/flexcapacitor/skins/PopUpButtonSkin.mxml
new file mode 100644
index 0000000..82a2dbf
--- /dev/null
+++ b/Radii8Library/src/com/flexcapacitor/skins/PopUpButtonSkin.mxml
@@ -0,0 +1,287 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+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.
+
+-->
+
+<!--- The Spark skin class for the MX PopUpButton component. 
+
+      @see mx.controls.PopUpButton
+        
+      @langversion 3.0
+      @playerversion Flash 10
+      @playerversion AIR 1.5
+      @productversion Flex 4
+-->
+<local:SparkSkinForHalo xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" 
+      xmlns:local="mx.skins.spark.*"
+      minWidth="21" minHeight="21"
+      alpha.disabled="0.5">
+    
+    <fx:Script>
+        /* Define the skin elements that should not be colorized. 
+           For button, the graphics are colorized but the arrow is not. */
+        static private const exclusions:Array = ["arrow"];
+        /**
+         *  @private
+         */
+        override public function get colorizeExclusions():Array {return exclusions;}
+        
+        /* Define the symbol fill items that should be colored by the "symbolColor" style. */
+        static private const symbols:Array = ["arrowFill1", "arrowFill2"];
+        /**
+         *  @private
+         */
+        override public function get symbolItems():Array {return symbols};
+
+        /* Define the border items.*/
+        //static private const borderItem:Array = ["borderEntry1", "borderEntry2"];
+        static private const borderItem:Array = [];
+        /**
+         *  @private
+         */
+        override protected function get borderItems():Array {return borderItem;}
+        
+        /**
+         * @private
+         */
+        override protected function initializationComplete():void
+        {
+            useChromeColor = true;
+            super.initializationComplete();
+        }
+        
+        /**
+         *  @private
+         */
+        override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number) : void
+        {
+            var cr:Number = getStyle("cornerRadius");
+            
+            if (cornerRadius != cr)
+            {
+                cornerRadius = cr;
+                /*shadow.radiusX = cornerRadius;
+                fill.topLeftRadiusX = cornerRadius;
+                fill.bottomLeftRadiusX = cornerRadius;
+                fill2.topRightRadiusX = cornerRadius;
+                fill2.bottomRightRadiusX = cornerRadius;
+                lowlight.radiusX = cornerRadius;
+                highlight.radiusX = cornerRadius;
+                border.radiusX = cornerRadius;*/
+            }
+                
+            //if (highlightStroke) highlightStroke.radiusX = cornerRadius;
+                
+            super.updateDisplayList(unscaledWidth, unscaledHeight);
+        }
+        
+        private var cornerRadius:Number = 2;
+    </fx:Script>
+    
+    <!-- states -->
+    <local:states>
+        <s:State name="up" />
+        <s:State name="over" stateGroups="overStates" />
+        <s:State name="down" stateGroups="downStates" />
+        <s:State name="disabled" />
+        <s:State name="popUpOver" stateGroups="overStates, popUpStates" />
+        <s:State name="popUpDown" stateGroups="downStates, popUpStates" />
+    </local:states>
+    
+    <!-- layer 1: shadow -->
+    <!--- @private -->
+    <!--<s:Rect id="shadow" left="-1" right="-1" top="-1" bottom="-1" radiusX="2">
+        <s:fill>
+            <s:LinearGradient rotation="90">
+                <s:GradientEntry color="0x000000" 
+                               color.downStates="0xFFFFFF"
+                               alpha="0.01"
+                               alpha.downStates="0" />
+                <s:GradientEntry color="0x000000" 
+                               color.downStates="0xFFFFFF" 
+                               alpha="0.07"
+                               alpha.downStates="0.5" />
+            </s:LinearGradient>
+        </s:fill>
+    </s:Rect>-->
+    
+    <!-- layer 2: fill -->
+    <!--- @private -->
+    <!--<s:Rect id="fill" left="1" right="18" top="1" bottom="1" 
+            topLeftRadiusX="2" bottomLeftRadiusX="2">
+        <s:fill>
+            <s:LinearGradient rotation="90">
+                <s:GradientEntry color="0xFFFFFF" 
+                                 color.over="0xBBBDBD" 
+                                 color.down="0xAAAAAA" 
+                                 alpha="0.85" />
+                <s:GradientEntry color="0xD8D8D8" 
+                                 color.over="0x9FA0A1" 
+                                 color.down="0x929496" 
+                                 alpha="0.85" />
+            </s:LinearGradient>
+        </s:fill>
+    </s:Rect>-->
+    <!--- @private -->
+    <!--<s:Rect id="fill2" width="18" right="1" top="1" bottom="1" 
+            topRightRadiusX="2" bottomRightRadiusX="2">
+        <s:fill>
+            <s:LinearGradient rotation="90">
+                <s:GradientEntry color="0xFFFFFF" 
+                                 color.popUpOver="0xBBBDBD" 
+                                 color.popUpDown="0xAAAAAA" 
+                                 alpha="0.85" />
+                <s:GradientEntry color="0xD8D8D8" 
+                                 color.popUpOver="0x9FA0A1" 
+                                 color.popUpDown="0x929496" 
+                                 alpha="0.85" />
+            </s:LinearGradient>
+        </s:fill>
+    </s:Rect>-->
+    
+    <!-- layer 3: fill lowlight -->
+    <!--- @private -->
+    <!--<s:Rect id="lowlight" left="1" right="1" top="1" bottom="1" radiusX="2">
+        <s:fill>
+            <s:LinearGradient rotation="270">
+                <s:GradientEntry color="0x000000" ratio="0.0" alpha="0.0627" />
+                <s:GradientEntry color="0x000000" ratio="0.48" alpha="0.0099" />
+                <s:GradientEntry color="0x000000" ratio="0.48001" alpha="0" />
+            </s:LinearGradient>
+        </s:fill>
+    </s:Rect>-->
+    
+    <!-- layer 4: fill highlight -->
+    <!--- @private -->
+    <!--<s:Rect id="highlight" left="1" right="1" top="1" bottom="1" radiusX="2">
+        <s:fill>
+            <s:LinearGradient rotation="90">
+                <s:GradientEntry color="0xFFFFFF"
+                                 ratio="0.0"
+                                 alpha="0.33"
+                                 alpha.overStates="0.22" 
+                                 alpha.downStates="0.12"/>
+                <s:GradientEntry color="0xFFFFFF"
+                                 ratio="0.48"
+                                 alpha="0.33"
+                                 alpha.overStates="0.22" 
+                                 alpha.downStates="0.12"/>
+                <s:GradientEntry color="0xFFFFFF"
+                                 ratio="0.48001"
+                                 alpha="0" />
+            </s:LinearGradient>
+        </s:fill>
+    </s:Rect>-->
+    
+    <!-- layer 5: highlight stroke (all states except down) -->
+    <!--- @private -->
+    <!--<s:Rect id="highlightStroke"  left="1" right="1" top="1" bottom="1" radiusX="2" excludeFrom="downStates">
+        <s:stroke>
+            <s:LinearGradientStroke rotation="90" weight="1">
+                <s:GradientEntry color="0xFFFFFF" alpha.overStates="0.22" />
+                <s:GradientEntry color="0xD8D8D8" alpha.overStates="0.22" />
+            </s:LinearGradientStroke>
+        </s:stroke>
+    </s:Rect>-->
+    
+    <!-- layer 6: highlight stroke (down state only) -->
+    <!--- @private -->
+    <!--<s:Rect left="1" top="1" bottom="1" width="1" includeIn="down">
+        <s:fill>
+            <s:SolidColor color="0x000000" alpha="0.07" />
+        </s:fill>
+    </s:Rect>
+    <s:Rect right="19" top="1" bottom="1" width="1" includeIn="down">
+        <s:fill>
+            <s:SolidColor color="0x000000" alpha="0.07" />
+        </s:fill>
+    </s:Rect>
+    <s:Rect left="2" top="1" right="19" height="1" includeIn="down">
+        <s:fill>
+            <s:SolidColor color="0x000000" alpha="0.25" />
+        </s:fill>
+    </s:Rect>
+    <s:Rect left="1" top="2" right="19" height="1" includeIn="down">
+        <s:fill>
+            <s:SolidColor color="0x000000" alpha="0.09" />
+        </s:fill>
+    </s:Rect>
+    
+    <s:Rect right="17" top="1" bottom="1" width="1" includeIn="popUpDown">
+        <s:fill>
+            <s:SolidColor color="0x000000" alpha="0.07" />
+        </s:fill>
+    </s:Rect>
+    <s:Rect right="1" top="1" bottom="1" width="1" includeIn="popUpDown">
+        <s:fill>
+            <s:SolidColor color="0x000000" alpha="0.07" />
+        </s:fill>
+    </s:Rect>
+    <s:Rect width="16" top="1" right="2" height="1" includeIn="popUpDown">
+        <s:fill>
+            <s:SolidColor color="0x000000" alpha="0.25" />
+        </s:fill>
+    </s:Rect>
+    <s:Rect width="17" top="2" right="1" height="1" includeIn="popUpDown">
+        <s:fill>
+            <s:SolidColor color="0x000000" alpha="0.09" />
+        </s:fill>
+    </s:Rect>-->
+    
+    <!-- layer 7: border - put on top of the fill so it doesn't disappear when scale is less than 1 -->
+    <!--- @private -->
+    <!--<s:Rect id="border" left="0" right="0" top="0" bottom="0" width="69" height="20" radiusX="2">
+        <s:stroke>
+            <s:LinearGradientStroke rotation="90" weight="1">
+                <s:GradientEntry id="borderEntry1" 
+                               alpha="0.5625"
+                               alpha.downStates="0.6375" />
+                <s:GradientEntry id="borderEntry2"  
+                               alpha="0.75" 
+                               alpha.downStates="0.85" />
+            </s:LinearGradientStroke>
+        </s:stroke>
+    </s:Rect>
+    <s:Rect right="18" top="1" bottom="1" width="1">
+        <s:fill>
+             <s:LinearGradient rotation="90">
+                <s:GradientEntry color="0x000000" 
+                               alpha="0.5625"
+                               alpha.downStates="0.6375" />
+                <s:GradientEntry color="0x000000" 
+                               alpha="0.75" 
+                               alpha.downStates="0.85" />
+            </s:LinearGradient>
+        </s:fill>
+    </s:Rect>-->
+
+    <!-- layer 8: arrow -->
+    <!--- @private -->
+    <s:Path right="6" verticalCenter="0" id="arrow"
+          data="M 4.0 4.0 L 4.0 3.0 L 5.0 3.0 L 5.0 2.0 L 6.0 2.0 L 6.0 1.0 L 7.0 1.0 L 7.0 0.0 L 0.0 0.0 L 0.0 1.0 L 1.0 1.0 L 1.0 2.0 L 2.0 2.0 L 2.0 3.0 L 3.0 3.0 L 3.0 4.0 L 4.0 4.0"
+		  visible="false" includeInLayout="false">
+        <s:fill>
+            <s:RadialGradient rotation="90" focalPointRatio="1">    
+                <!--- @private -->
+                <s:GradientEntry id="arrowFill1" color="0" alpha="0.6" />
+                <!--- @private -->
+                <s:GradientEntry id="arrowFill2" color="0" alpha="0.8" />
+            </s:RadialGradient>
+        </s:fill>
+    </s:Path>
+</local:SparkSkinForHalo>