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>