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>