From b89a7ee8b956c96a1dcee995ea840feddc5d4b27 Mon Sep 17 00:00:00 2001 From: Pierre Frisch Date: Thu, 22 Dec 2011 07:25:50 -0800 Subject: First commit of Ninja to ninja-internal Signed-off-by: Valerio Virgillito --- js/io/document/base-document.js | 88 +++ js/io/document/document-controller.js | 326 +++++++++ js/io/document/html-document.js | 424 +++++++++++ js/io/document/text-document.js | 91 +++ js/io/system/config.xml | 6 + js/io/system/fileio.js | 226 ++++++ js/io/system/filesystem.js | 723 ++++++++++++++++++ js/io/system/projectio.js | 63 ++ js/io/system/shellapi.js | 806 +++++++++++++++++++++ js/io/workflow/new-project-manager.js | 136 ++++ .../new-file-location.reel/new-file-location.css | 50 ++ .../new-file-location.reel/new-file-location.html | 41 ++ .../new-file-location.reel/new-file-location.js | 28 + .../new-file-options-navigator.css | 95 +++ .../new-file-options-navigator.html | 51 ++ .../new-file-options-navigator.js | 160 ++++ .../newFileDialog/new-file-workflow-controller.js | 59 ++ .../newFileDialog/new-file-workflow-model.js | 121 ++++ js/io/workflow/newProjectNavigator.js | 75 ++ .../newProjectNavigator.css | 32 + .../newProjectNavigator.html | 32 + 21 files changed, 3633 insertions(+) create mode 100644 js/io/document/base-document.js create mode 100644 js/io/document/document-controller.js create mode 100644 js/io/document/html-document.js create mode 100644 js/io/document/text-document.js create mode 100644 js/io/system/config.xml create mode 100644 js/io/system/fileio.js create mode 100644 js/io/system/filesystem.js create mode 100644 js/io/system/projectio.js create mode 100644 js/io/system/shellapi.js create mode 100644 js/io/workflow/new-project-manager.js create mode 100644 js/io/workflow/newFileDialog/new-file-location.reel/new-file-location.css create mode 100644 js/io/workflow/newFileDialog/new-file-location.reel/new-file-location.html create mode 100644 js/io/workflow/newFileDialog/new-file-location.reel/new-file-location.js create mode 100644 js/io/workflow/newFileDialog/new-file-options-navigator.reel/new-file-options-navigator.css create mode 100644 js/io/workflow/newFileDialog/new-file-options-navigator.reel/new-file-options-navigator.html create mode 100644 js/io/workflow/newFileDialog/new-file-options-navigator.reel/new-file-options-navigator.js create mode 100644 js/io/workflow/newFileDialog/new-file-workflow-controller.js create mode 100644 js/io/workflow/newFileDialog/new-file-workflow-model.js create mode 100644 js/io/workflow/newProjectNavigator.js create mode 100644 js/io/workflow/newProjectNavigator.reel/newProjectNavigator.css create mode 100644 js/io/workflow/newProjectNavigator.reel/newProjectNavigator.html (limited to 'js/io') diff --git a/js/io/document/base-document.js b/js/io/document/base-document.js new file mode 100644 index 00000000..44f54f78 --- /dev/null +++ b/js/io/document/base-document.js @@ -0,0 +1,88 @@ +/* +This file contains proprietary software owned by Motorola Mobility, Inc.
+No rights, expressed or implied, whatsoever to this software are provided by Motorola Mobility, Inc. hereunder.
+(c) Copyright 2011 Motorola Mobility, Inc. All Rights Reserved. +
*/ + +//BaseDocument Object for all files types and base class for HTML documents. + +var Montage = require("montage/core/core").Montage; + +var BaseDocument = exports.BaseDocument = Montage.create(Montage, { + /** Private Members **/ + _name: { value: null, enumerable: false }, + _uri: { value: null, enumerable: false }, + _documentType: { value: null, enumerable: false }, + _container: {value: null, enumerable: false }, + _uuid: { value: null, enumerable: false }, + _isActive: { value: true, enumerable: false }, + _dirtyFlag: { value: false, enumerable: false }, + _callback: { value: null, enumerable: false }, + _currentView: { value: null, enumerable: false}, + + /** Getters/Setters **/ + name: { + get: function() { return this._name; }, + set: function(value) { this._name = value; } + }, + + uri: { + get: function() { return this._uri; }, + set: function(value) { this._uri = value; } + }, + + documentType: { + get: function() { return this._documentType; }, + set: function(value) { this._documentType = value; } + }, + + container: { + get: function() { return this._container; }, + set: function(value) { this._container = value; } + }, + + uuid: { + get: function() { return this._uuid; }, + set: function(value) { this._uuid = value; } + }, + + isActive: { + get: function() { return this._isActive; }, + set: function(value) { this._isActive = value; } + }, + + dirtyFlag: { + get: function() { return this._dirtyFlag; }, + set: function(value) { this._dirtyFlag = value; } + }, + + callback: { + get: function() { return this._callback; }, + set: function(value) { this._callback = value; } + }, + + currentView: { + get: function() { return this._currentView; }, + set: function(value) { this._currentView = value } + }, + + /** Base Methods **/ + init: { + value: function(name, uri, type, container, uuid, callback) { + this.name = name; + this.uri = uri; + this.documentType = type; + this.container = container; + this.uuid = uuid; + this.callback = callback; + } + }, + + loadDocument: { + value: function() { + // Have the XHR here? + } + } + + +}); \ No newline at end of file diff --git a/js/io/document/document-controller.js b/js/io/document/document-controller.js new file mode 100644 index 00000000..99177de0 --- /dev/null +++ b/js/io/document/document-controller.js @@ -0,0 +1,326 @@ +/* +This file contains proprietary software owned by Motorola Mobility, Inc.
+No rights, expressed or implied, whatsoever to this software are provided by Motorola Mobility, Inc. hereunder.
+(c) Copyright 2011 Motorola Mobility, Inc. All Rights Reserved. +
*/ + +/** +@module js/document/documentManager +@requires montage/core/core +@requires montage/ui/component +@requires js/document/html-document +@requires js/document/text-document +*/ + +// TODO : Fix deps from Montage V4 Archi + +var Montage = require("montage/core/core").Montage, + Component = require("montage/ui/component").Component, + Uuid = require("montage/core/uuid").Uuid; + +var HTMLDocument = require("js/io/document/html-document").HTMLDocument; +var TextDocument = require("js/io/document/text-document").TextDocument; + +var DocumentController = exports.DocumentController = Montage.create(Component, { + hasTemplate: { value: false }, + + _documents: { value: [] }, + _documentsHash: { value: {} }, + _activeDocument: { value: null }, + _iframeCounter: { value: 1, enumerable: false }, + _iframeHolder: { value: null, enumerable: false }, + _textHolder: { value: null, enumerable: false }, + _codeMirrorCounter: {value: 1, enumerable: false}, + + _codeEditor: { + value: { + "editor": { + value: null, + enumerable: false + }, + "hline": { + value: null, + enumerable: false + } + } + }, + + activeDocument: { + get: function() { + return this._activeDocument; + }, + set: function(doc) { + if(this._activeDocument) { + if(this.activeDocument.documentType === "htm" || this.activeDocument.documentType === "html") { + // TODO selection should use the document own selectionModel + //this._activeDocument.selectionModel = selectionManagerModule.selectionManager._selectedItems; + } + + this._activeDocument.isActive = false; + } + + if(this._documents.indexOf(doc) === -1) { + //this._documentsHash[doc.uuid] = this._documents.push(doc) - 1; + this._documents.push(doc); + } + + this._activeDocument = doc; + this._activeDocument.isActive = true; + + if(this.activeDocument.documentType === "htm" || this.activeDocument.documentType === "html") { + // TODO selection should use the document own selectionModel + //selectionManagerModule.selectionManager._selectedItems = this._activeDocument.selectionModel; + } + } + }, + + deserializedFromTemplate: { + value: function() { + this.eventManager.addEventListener("appLoaded", this, false); + } + }, + + handleAppLoaded: { + value: function() { + this.openDocument({"type": "html"}); + } + }, + + /** Open a Document **/ + openDocument: { + value: function(doc) { + var d; + + if(!doc) return false; + + try { + if (doc.type === 'html' || doc.type === 'htm') { + d = Montage.create(HTMLDocument); + d.initialize(doc, Uuid.generate(), this._createIframeElement(), this._onOpenDocument); + } else { + d = Montage.create(TextDocument); + d.initialize(doc, Uuid.generate(), this._createTextAreaElement(), this._onOpenTextDocument); + } + + } catch (err) { + console.log("Could not open Document ", err); + } + } + }, + + closeDocument: { + value: function(id) { + var doc = this._findDocumentByUUID(id); + this._removeDocumentView(doc.container); + + this._documents.splice(this._findIndexByUUID(id), 1); + + if(this.activeDocument.uuid === id && this._documents.length > 0) { + this.switchDocument(this._documents[0].uuid) + } + } + }, + + switchDocument: { + value: function(id) { + this._hideCurrentDocument(); + this.activeDocument = this._findDocumentByUUID(id); + + this.application.ninja.stage._scrollFlag = false; // TODO HACK to prevent type error on Hide/Show Iframe + this._showCurrentDocument(); + + if(this.activeDocument.documentType === "htm" || this.activeDocument.documentType === "html") { + this.application.ninja.stage._scrollFlag = true; // TODO HACK to prevent type error on Hide/Show Iframe + // TODO dispatch event here +// appDelegateModule.MyAppDelegate.onSetActiveDocument(); + } + } + }, + + switchViews: { + value: function() { + this.application.ninja.stage.saveScroll(); + this._hideCurrentDocument(); + + if(this.activeDocument.currentView === "design") { + this._textHolder.style.display = "none"; + this.activeDocument.container.style["display"] = "block"; + this.application.ninja.stage._scrollFlag = true; + //this._showCurrentDocument(); + this.application.ninja.stage.restoreScroll(); + + } else { + this.application.ninja.stage._scrollFlag = false; // TODO HACK to prevent type error on Hide/Show Iframe + var codeview = this._createTextAreaElement(); + this._textHolder.style.display = "block"; + codeview.firstChild.innerHTML = this.activeDocument.iframe.contentWindow.document.body.parentNode.innerHTML; + + this._codeEditor.editor = CodeMirror.fromTextArea(codeview.firstChild, { + lineNumbers: true, + mode: "htmlmixed", + onCursorActivity: function() { + DocumentManager._codeEditor.editor.setLineClass(DocumentManager._codeEditor.hline, null); + DocumentManager._codeEditor.hline = DocumentManager._codeEditor.editor.setLineClass(DocumentManager._codeEditor.editor.getCursor().line, "activeline"); + } + }); + this._codeEditor.hline = DocumentManager._codeEditor.editor.setLineClass(0, "activeline"); + } + } + }, + + // Document has been loaded into the Iframe. Dispatch the event. + // Event Detail: Contains the current ActiveDocument + _onOpenDocument: { + value: function(doc){ + //var data = DocumentManager.activeDocument; + //DocumentManager._hideCurrentDocument(); + + //stageManagerModule.stageManager.toggleCanvas(); + + DocumentController.activeDocument = doc; + + NJevent("onOpenDocument", doc); +// appDelegateModule.MyAppDelegate.onSetActiveDocument(); + + } + }, + + _onOpenTextDocument: { + value: function(doc) { + DocumentManager._hideCurrentDocument(); + this.application.ninja.stage._scrollFlag = false; // TODO HACK to prevent type error on Hide/Show Iframe + DocumentManager.activeDocument = doc; + + var type; + + switch(doc.documentType) { + case "css" : + type = "css"; + break; + case "js" : + type = "javascript"; + break; + } + + DocumentManager._codeEditor.editor = CodeMirror.fromTextArea(doc.textArea, { + lineNumbers: true, + mode: type, + onCursorActivity: function() { + DocumentManager._codeEditor.editor.setLineClass(DocumentManager._codeEditor.hline, null); + DocumentManager._codeEditor.hline = DocumentManager._codeEditor.editor.setLineClass(DocumentManager._codeEditor.editor.getCursor().line, "activeline"); + } + }); + DocumentManager._codeEditor.hline = DocumentManager._codeEditor.editor.setLineClass(0, "activeline"); + + } + }, + + /** + * VIEW Related Methods + */ + // PUBLIC + ShowActiveDocument: { + value: function() { + this.activeDocument.iframe.style.opacity = 1.0; + } + }, + + // PRIVATE + _findDocumentByUUID: { + value: function(uuid) { + var len = this._documents.length; + for(var i = 0; i < len; i++) { + if(this._documents[i].uuid === uuid) return this._documents[i]; + } + + return false; + } + }, + + _findIndexByUUID: { + value: function(uuid) { + var len = this._documents.length; + for(var i = 0; i < len; i++) { + if(this._documents[i].uuid === uuid) return i; + } + + return false; + } + }, + + _hideCurrentDocument: { + value: function() { + if(this.activeDocument) { + this.activeDocument.container.style["display"] = "none"; + if(this.activeDocument.documentType === "htm" || this.activeDocument.documentType === "html") this.application.ninja.stage.toggleCanvas(); + } + } + }, + + _showCurrentDocument: { + value: function() { + if(this.activeDocument) { + this.activeDocument.container.style["display"] = "block"; + if(this.activeDocument.documentType === "htm" || this.activeDocument.documentType === "html") this.application.ninja.stage.toggleCanvas(); + } + } + }, + + _removeDocumentView: { + value: function(node) { + node.parentNode.removeChild(node); + } + }, + + reloadDocumentContent: { + value: function() { + this.activeDocument._window.location.reload(); + } + }, + + /** + * Creates a new iFrame element using a new unique ID for it. Returns the iframe ID. + */ + _createIframeElement: { + value: function() { + var e = document.createElement("iframe"); + e.id = this._createIframeID(); + e.style.border = "none"; + e.style.opacity = 0; + e.height = 1000; + e.width = 2000; + e.src = ""; + + if(!this._iframeHolder) this._iframeHolder = document.getElementById("iframeContainer"); + + this._iframeHolder.appendChild(e); + + return e; + } + }, + + + _createIframeID: { + value: function() { + return "userDocument_" + (this._iframeCounter++); + } + }, + + _createTextAreaElement: { + value: function() { + var codeMirrorDiv = document.createElement("div"); + codeMirrorDiv.id = "codeMirror_" + (this._codeMirrorCounter++); + + var textArea = document.createElement("textarea"); + textArea.id = "code"; + textArea.name = "code"; + + codeMirrorDiv.appendChild(textArea); + + if(!this._textHolder) this._textHolder = document.getElementById("codeViewContainer"); + this._textHolder.appendChild(codeMirrorDiv); + + return codeMirrorDiv; + } + } +}); diff --git a/js/io/document/html-document.js b/js/io/document/html-document.js new file mode 100644 index 00000000..c44dfe75 --- /dev/null +++ b/js/io/document/html-document.js @@ -0,0 +1,424 @@ +/* +This file contains proprietary software owned by Motorola Mobility, Inc.
+No rights, expressed or implied, whatsoever to this software are provided by Motorola Mobility, Inc. hereunder.
+(c) Copyright 2011 Motorola Mobility, Inc. All Rights Reserved. +
*/ + +var Montage = require("montage/core/core").Montage, + baseDocumentModule = require("js/io/document/base-document"), + NJUtils = require("js/lib/NJUtils").NJUtils; + +var HTMLDocument = exports.HTMLDocument = Montage.create(baseDocumentModule.BaseDocument, { + // PRIVATE MEMBERS + _selectionExclude: { value: null, enumerable: false }, + _cloudTemplateUri: { value: "user-document-templates/montage-application-cloud/index.html", enumerable: false}, + _iframe: { value: null, enumerable: false }, + _server: { value: null, enumerable: false }, + _selectionModel: { value: [], enumerable: false }, + _undoModel: { value: { "queue" : [], "position" : 0 }, enumerable: false}, + + _document: { value: null, enumerable: false }, + _documentRoot: { value: null, enumerable: false }, + _stageBG: { value: null, enumerable: false }, + _window: { value: null, enumerable: false }, + _styles: { value: null, enumerable: false }, + _stylesheets: { value: null, enumerable: false }, + _stageStyleSheetId : { value: 'nj-stage-stylesheet', enumerable: false }, + _initialUserDocument: { value: null, enumerable: false }, + _htmlSource: {value: "", enumerable: false}, + _glData: {value: null, enumerable: false }, + + _elementCounter: { value: 1, enumerable: false }, + _snapping : { value: true, enumerable: false }, + _layoutMode: { value: "all", enumerable: false }, + _draw3DGrid: { value: false, writable: true }, + _swfObject: { value: false, enumerable: false }, + + _zoomFactor: { value: 100, enumerable: false }, + + // PUBLIC MEMBERS + cssLoadInterval: { value: null, enumerable: false }, + + /* + * PUBLIC API + */ + + // GETTERS / SETTERS + selectionExclude: { + get: function() { return this._selectionExclude; }, + set: function(value) { this._selectionExclude = value; } + }, + + iframe: { + get: function() { return this._iframe; }, + set: function(value) { this._iframe = value; } + }, + + server: { + get: function() { return this._server; }, + set: function(value) { this._server = value; } + }, + + selectionModel: { + get: function() { return this._selectionModel; }, + set: function(value) { this._selectionModel = value; } + }, + + undoModel: { + get: function() { return this._undoModel; }, + set: function(value) { this._undoModel.queue = value.queue; this._undoModel.position = value.position; } + }, + + documentRoot: { + get: function() { return this._documentRoot; }, + set: function(value) { this._documentRoot = value; } + }, + + stageBG: { + get: function() { return this._stageBG; }, + set: function(value) { this._stageBG = value; } + }, + + elementCounter: { + set: function(value) { this._elementCounter = value; }, + get: function() { return this._elementCounter; } + }, + + snapping: { + get: function() { return this._snapping; }, + set: function(value) { + if(this._snapping !== value) { + this._snapping = value; + } + } + }, + + // TODO SEND THE EVENT --> Redraw the desired layout + layoutMode: { + get: function() { return this._layoutMode; }, + set: function(mode) { this._layoutMode = mode; } + }, + + draw3DGrid: { + get: function() { return this._draw3DGrid; }, + set: function(value) { + if(this._draw3DGrid !== value) { + this._draw3DGrid = value; + } + } + }, + + _userComponentSet: { + value: {}, + writable: true, + enumerable:true + }, + +// userComponentSet:{ +// enumerable: true, +// get: function() { +// return this._userComponentSet; +// }, +// set: function(value) { +// this._userComponentSet = value; +// this._drawUserComponentsOnOpen(); +// } +// }, +// +// _drawUserComponentsOnOpen:{ +// value:function(){ +// for(var i in this._userComponentSet){ +// console.log(this._userComponentSet[i].control) +// this._userComponentSet[i].control.needsDraw = true; +// } +// } +// }, + + glData: { + get: function() + { + var elt = this.iframe; + var elt = this.iframe.contentWindow.document.getElementById("UserContent"); + this._glData = null; + if (elt) + { + this._glData = new Array(); + this.collectGLData( elt, this._glData ); + } + + return this._glData + }, + + set: function(value) + { + var nWorlds = value.length; + for (var i=0; i= 0) + { + var endIndex = importStr.indexOf( "\n", startIndex ); + if (endIndex > 0) + { + var id = importStr.substring( startIndex+4, endIndex ); + var canvas = this.iframe.contentWindow.document.getElementById( id ); + if (canvas) + { + if (!canvas.elementModel) + { + NJUtils.makeElementModel(canvas, "Canvas", "shape", true); + } + + if (canvas.elementModel) + { + if (canvas.elementModel.shapeModel.GLWorld) + canvas.elementModel.shapeModel.GLWorld.clearTree(); + + var world = new GLWorld( canvas ); + canvas.elementModel.shapeModel.GLWorld = world; + world.import( importStr ); + } + } + } + } + } + } + }, + + zoomFactor: { + get: function() { return this._zoomFactor; }, + set: function(value) { this._zoomFactor = value; } + }, + + //****************************************// + // PUBLIC METHODS + initialize: { + value: function(doc, uuid, iframe, callback) { + // Shell mode is not used anymore + //if(!window.IsInShellMode()) { + + this.init("index-cloud", this._cloudTemplateUri, doc.type, iframe, uuid, callback); + /* + } else { + var tmpurl = doc.uri.split('\\'); + var fileUrl = doc.server.url + "/" + tmpurl[tmpurl.length -1] + "?fileio=true&template=/user-document-templates/montage-application/index.html"; + this.init(name, fileUrl, doc.type, iframe, uuid, callback); + this.server = doc.server; + this._initialUserDocument = doc; + } + */ + this.iframe = iframe; + this.selectionExclude = ["HTML", "BODY", "Viewport", "UserContent", "stageBG"]; + this.currentView = "design"; + + this._loadDocument(this.uri); + } + }, + + collectGLData: { + value: function( elt, dataArray ) + { + if (elt.elementModel && elt.elementModel.shapeModel && elt.elementModel.shapeModel.GLWorld) + { + var data = elt.elementModel.shapeModel.GLWorld.export(); + dataArray.push( data ); + } + + if (elt.children) + { + var nKids = elt.children.length; + for (var i=0; i 1) { + clearInterval(this.cssLoadInterval); + this._styles = this._document.styleSheets[this._document.styleSheets.length - 1]; + this._stylesheets = this._document.styleSheets; // Entire stlyesheets array + + this.callback(this); + } + }.bind(this), 50); + + // TODO - Not sure where this goes + this._userComponentSet = {}; + } else { + this._styles = this._document.styleSheets[this._document.styleSheets.length - 1]; + this._stylesheets = this._document.styleSheets; // Entire stlyesheets array + + /* TODO Finish this implementation once we start caching Core Elements */ + // Assign a model to the UserContent and add the ViewPort reference to it. + NJUtils.makeElementModel(this.documentRoot, "Stage", "stage"); + //this.documentRoot.elementModel.viewPort = this.iframe.contentWindow.document.getElementById("Viewport"); + NJUtils.makeElementModel(this.stageBG, "Stage", "stage"); + NJUtils.makeElementModel(this.iframe.contentWindow.document.getElementById("Viewport"), "Stage", "stage"); + + for(i = 0; i < this._stylesheets.length; i++) { + if(this._stylesheets[i].ownerNode.id === this._stageStyleSheetId) { + this.documentRoot.elementModel.defaultRule = this._stylesheets[i]; + break; + } + } + + // Temporary create properties for each rule we need to save the index of the rule. + var len = this.documentRoot.elementModel.defaultRule.cssRules.length; + for(var j = 0; j < len; j++) { +// console.log(this.documentRoot.elementModel.defaultRule.cssRules[j].selectorText); + if(this.documentRoot.elementModel.defaultRule.cssRules[j].selectorText === "*") { + + this.documentRoot.elementModel.transitionStopRule = this.documentRoot.elementModel.defaultRule.cssRules[j]; + + } else if(this.documentRoot.elementModel.defaultRule.cssRules[j].selectorText === "body") { + + this.documentRoot.elementModel.body = this.documentRoot.elementModel.defaultRule.cssRules[j]; + + } else if(this.documentRoot.elementModel.defaultRule.cssRules[j].selectorText === "#Viewport") { + + this.documentRoot.elementModel.viewPort = this.documentRoot.elementModel.defaultRule.cssRules[j]; + + } else if(this.documentRoot.elementModel.defaultRule.cssRules[j].selectorText === ".stageDimension") { + + this.documentRoot.elementModel.stageDimension = this.documentRoot.elementModel.defaultRule.cssRules[j]; + + } else if(this.documentRoot.elementModel.defaultRule.cssRules[j].selectorText === ".stageView") { + + this.documentRoot.elementModel.stageView = this.documentRoot.elementModel.defaultRule.cssRules[j]; + + } + } + + this.callback(this); + } + } + }, + + _setSWFObjectScript: { + value: function() { + if(!this._swfObject) { + /* + var swfObj = document.createElement("script"); + swfObj.type = "text/javascript"; + swfObj.src = "../../user-document-templates/external-libs/swf-object/swfobject.js"; + swfObj.id = "swfObject"; + var head= this._document.getElementsByTagName('head')[0]; + head.appendChild(swfObj); + this._swfObject = true; + */ + } + } + } +}); \ No newline at end of file diff --git a/js/io/document/text-document.js b/js/io/document/text-document.js new file mode 100644 index 00000000..3506891a --- /dev/null +++ b/js/io/document/text-document.js @@ -0,0 +1,91 @@ +/* +This file contains proprietary software owned by Motorola Mobility, Inc.
+No rights, expressed or implied, whatsoever to this software are provided by Motorola Mobility, Inc. hereunder.
+(c) Copyright 2011 Motorola Mobility, Inc. All Rights Reserved. +
*/ + +var Montage = require("montage/core/core").Montage; +var baseDocumentModule = require("js/io/document/base-document"); + + +var TextDocument = exports.TextDocument = Montage.create(baseDocumentModule.BaseDocument, { + // PRIVATE MEMBERS + _codeEditor: { + value: { + "editor": { value: null, enumerable: false }, + "hline": { value: null, enumerable: false } + } + }, + + _textArea: { value: null, enumerable: false }, + + // Temporary Save the source + _source: { value: null, enumerable: false}, + + textArea: { + get: function() { return this._textArea;}, + set: function(value) { this._textArea = value; } + }, + + source: { + get: function() { return this._source;}, + set: function(value) { this._source = value;} + }, + + // PUBLIC MEMBERS + + //****************************************// + //PUBLIC API + + + // GETTERS / SETTERS + editor: { + get: function() { return this._codeEditor.editor; }, + set: function(value) { this._codeEditor.editor = value} + }, + + hline: { + get: function() { return this._codeEditor.hline; }, + set: function(value) {this._codeEditor.hline = value; } + }, + + + // PUBLIC METHODS + initialize: { + value: function(doc, uuid, textArea, callback) { + this.init(doc.name, doc.uri, doc.type, textArea, uuid, callback); + this.textArea = textArea.firstChild; + this.currentView = "code"; + this._loadContent(); + } + }, + + // PRIVATE METHODS + _loadContent: { + value: function() { + // Start and AJAX call to load the HTML Document as a String + var xhr = new XMLHttpRequest(); + var ref = this; + + xhr.onreadystatechange = function() { + if (xhr.readyState == 4) { + ref.source = xhr.responseText; + ref.textArea.innerHTML = xhr.responseText; + //ref.callback(xhr.responseText); + ref.callback(ref); + } + }; + + if(this.documentType === "js") { + xhr.open('GET', 'user-document-templates/montage-application-cloud/appdelegate.js'); + } else if(this.documentType === "css") { + xhr.open('GET', 'user-document-templates/montage-application-cloud/default_html.css'); + } else { + xhr.open('GET', 'user-document-templates/montage-application-cloud/index.html'); + } + + xhr.send(''); + } + } + +}); \ No newline at end of file diff --git a/js/io/system/config.xml b/js/io/system/config.xml new file mode 100644 index 00000000..4660d647 --- /dev/null +++ b/js/io/system/config.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/js/io/system/fileio.js b/js/io/system/fileio.js new file mode 100644 index 00000000..1d76a91b --- /dev/null +++ b/js/io/system/fileio.js @@ -0,0 +1,226 @@ +/* +This file contains proprietary software owned by Motorola Mobility, Inc.
+No rights, expressed or implied, whatsoever to this software are provided by Motorola Mobility, Inc. hereunder.
+(c) Copyright 2011 Motorola Mobility, Inc. All Rights Reserved. +
*/ + +//Required modules +var Serializer = require("montage/core/serializer").Serializer; +//Exporting as File I/O +exports.FileIo = (require("montage/core/core").Montage).create(Object.prototype, { + /* +create: { + enumerable: true, + value: function (type) { + // + } + }, +*/ + //////////////////////////////////////////////////////////////////// + // + open: { + enumerable: true, + value: function(doc, type, uri, server) { + // + var file = {}, head, body, h, b; + file.uri = uri; + file.server = server; + // + if (doc.content) { + if (type === 'html' || type === 'htm') { + // + h = doc.content.split(''); + h = h[0].split(''); + head = h[1]; + // + b = doc.content.split(''); + b = b[0].split(''); + body = b[1]; + // + file.type = 'html'; + file.head = head; + file.body = body; + } else { + //TODO: Add other file type routines + file.type = type; + file.content = doc.content; + } + } else { + //TODO: File is empty + if (type === 'html' || type === 'htm') { + head = ''; + body = ''; + // + file.type = 'html'; + file.head = head; + file.body = body; + } else { + //TODO: Add other file type routines + file.type = type; + file.content = doc.content; + } + } + //TODO: Load contents into App + //documentManagerModule.DocumentManager.openDocument(file); + } + }, + //////////////////////////////////////////////////////////////////// + // + save: { + enumerable: true, + value: function(type, id, components) { + + /* + + GETS HTML IN LOADED DOCUMENT + document.getElementById('userDocument').contentDocument.documentElement.outerHTML + + GETS HTML IN AND OR ANYTHING INSIDE + document.getElementById('userDocument').contentDocument.documentElement.innerHTML + + THE ABOVE METHOD SEEMS TO BE BETTER JUST IN CASE PEOPLE REMOVE THE BODY TAG SINCE NOT REQUIRED IN HTML5 + + GETS HTML IN ONLY + document.getElementById('userDocument').contentDocument.body.innerHTML + + HACK TO GET THE STYLES OF THE ELEMENTS ADDED WHILE DRAWING + document.getElementById('userDocument').contentDocument.styleSheets[document.getElementById('userDocument').contentDocument.styleSheets.length-1] + + CSS SEEMS TO BE RESERVED WHEN APPENDED, MEANING 0 IN THE ARRAY IS ACTUALLY THE LAST DEFINED STYLE IN THE CSS + + //GETS CSS RULES APPLIED TO ALL OBJECTS CREATED BY THE APP + document.getElementById('userDocument').contentDocument.styleSheets[document.getElementById('userDocument').contentDocument.styleSheets.length-1].cssRules + + document.getElementById('userDocument').contentDocument.getElementById('userHead').innerHTML + document.getElementById('userDocument').contentDocument.getElementById('UserContent').innerHTML + this.getCssFromRules(document.getElementById('userDocument').contentDocument.styleSheets[document.getElementById('userDocument').contentDocument.styleSheets.length-1].cssRules) + + */ + + // + var contents, counter = 0; + //Checking for document type to go through saving routine + switch (type.toLowerCase()) { + case 'html': + //Checking for components in components panel + if (components) { + var comps = '', comp, html, mbind, hackParams = '', compSerializer = Serializer.create(); + //TODO: Check if this is needed since compSerializer was localized + compSerializer._serializedObjects = []; + // + html = document.getElementById(id).contentDocument.getElementById('UserContent').innerHTML; + // + for(var i in components){ + // + comp = compSerializer.serializeObject(components[i]); + //TODO: Remove this HACK + if (components[i]._montage_metadata.__proto__.objectName == 'PhotoEditor') { + if (components[i].pathToJSON) { + hackParams = '"pathToJSON": "'+components[i].pathToJSON+'",\n'; + } + } else { + + } + var split = comp.split('"element":U("m-obj://undefined/'+components[i]._element.uuid); + comp = split[0]+hackParams+'\t"element":E("#'+components[i]._element.id+split[1]; + if (document.getElementById(id).contentDocument.getElementById(components[i]._originalElementId).innerHTML.length > 2) { + split = html.split(document.getElementById(id).contentDocument.getElementById(components[i]._originalElementId).innerHTML); + html = split[0]+split[1]; + } + // + if (counter > 0) { + comps += ',\n'+comp; + } else { + comps += comp; + } + counter++; + } + + for(var i in components){ + // + if (components[i]._bindingDescriptors){ + var split = comps.split('U("m-obj://undefined/'+components[i]._bindingDescriptors.uuid+'", {\n })'); + comps = split[0]+'\n'+ + '{\n'+ + '"'+components[i].binding.sourceProperty+'": {\n'+ + '"boundObject": U("m-obj://'+components[i].binding.target._montage_metadata.__proto__.objectName+'/'+components[i].binding.target.uuid+'?mId='+components[i].binding.target._montage_metadata.__proto__.moduleId+'"),\n'+ + '"boundObjectPropertyPath": "'+components[i].binding.targetProperty+'"\n'+ + '}\n'+ + '}\n'+ + split[1]; + } + } + var montage = ''; + + contents = '\n\t'+document.getElementById(id).contentDocument.getElementById('userHead').innerHTML+'\n\t\t'+montage+'\n\t\n\t\n'+html+'\n\t\n'; + } else { + //No m-js components in file, so saving plain document HTML + contents = '\n\t'+document.getElementById(id).contentDocument.getElementById('userHead').innerHTML+'\n\t\n\t\n'+document.getElementById(id).contentDocument.getElementById('UserContent').innerHTML+'\n\t\n'; + } + break; + case 'css': + contents = this.getCssFromRules(document.getElementById(id).contentDocument.styleSheets[document.getElementById(id).contentDocument.styleSheets.length-1].cssRules); + break; + case 'js': + break; + case 'text': + break; + default: + break; + } + + + return contents; + + + + } + }, + //////////////////////////////////////////////////////////////////// + // + saveAs: { + enumerable: true, + value: function(e) { + //TODO: Add functionality + console.log('FileIO: saveFileAs'); + } + }, + + + + + //////////////////////////////////////////////////////////////////// + //Method to return a string from CSS rules (to be saved to a file) + getCssFromRules: { + enumerable: false, + value: function (list) { + //Variable to store CSS definitions + var i, str, css = ''; + //Looping through list + if (list && list.length > 0) { + //Adding each list item to string and also adding breaks + for (i = 0; list[i]; i++) { + str = list[i].cssText+' '; + str = str.replace( new RegExp( "{", "gi" ), "{\n\t" ); + str = str.replace( new RegExp( "}", "gi" ), "}\n" ); + str = str.replace( new RegExp( ";", "gi" ), ";\n\t" ); + css += '\n'+str; + } + } + //Returning the CSS string + return css; + } + } + + + + + //////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////// +}); +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// \ No newline at end of file diff --git a/js/io/system/filesystem.js b/js/io/system/filesystem.js new file mode 100644 index 00000000..54c16a05 --- /dev/null +++ b/js/io/system/filesystem.js @@ -0,0 +1,723 @@ +/* +This file contains proprietary software owned by Motorola Mobility, Inc.
+No rights, expressed or implied, whatsoever to this software are provided by Motorola Mobility, Inc. hereunder.
+(c) Copyright 2011 Motorola Mobility, Inc. All Rights Reserved. +
*/ + +var FileIo = require("js/io/system/fileio").FileIo, + ProjectIo = require("js/io/system/projectio").ProjectIo, + ShellApi = require("js/io/system/shellapi").ShellApi, + ComponentsPanelBase = require("js/panels/Components/ComponentsPanelBase.reel").ComponentsPanelBase; +//////////////////////////////////////////////////////////////////////// +//Exporting as File System +exports.FileSystem = (require("montage/core/core").Montage).create(Object.prototype, { + //////////////////////////////////////////////////////////////////// + // + init: { + enumerable: false, + value: function () { + //Called by NinjaMain + + + + //Calling Shell API to initialize + ShellApi.init(); + } + }, + + shellApiHandler :{ + enumerable:true, + writable:false, + value:ShellApi + }, + + + //////////////////////////////////////////////////////////////////// + // + cloud: { + enumerable: false, + value: false + }, + //////////////////////////////////////////////////////////////////// + // + cloud: { + enumerable: false, + get: function() { + return this._cloud; + }, + set: function(value) { + this._cloud = value + } + }, + + + + + + + //////////////////////////////////////////////////////////////////// + // + _documentType: { + enumerable: false, + value: function () { + //return DocumentManagerModule.DocumentManager.activeDocument.documentType; // this._documentType() + } + }, + + + + //////////////////////////////////////////////////////////////////// + // + newFile: { + enumerable: false, + value: function (template) { + //Checking for cloud (to be added later) + if (this.cloud) { + //TODO: Add cloud integration + console.log("[CLOUD] New File"); + //documentManagerModule.DocumentManager.openDocument({"type": "html"}); + } else { + // + var file = {uri: ShellApi.openShellDialog({type: 'file', action: 'new'})}, type; + var check = ShellApi.fileExists(file); + + + + + + + + + + + + + + + //TODO: implement createFile to avoid duplicate funtionality + if (check.success) { + switch (check.status) { + case 204: + //TODO: Add logic for already existing file + window.alert('Error Code 204: File already exists.'); + break; + case 404: + //File does not exists, ready to be created + + + //TODO: The type (template) should be sent into this routine via the UI of file I/O (not by file extension as now) + if (template) { + type = template; + } else { + type = file.uri.split('.'); + type = type[type.length-1]; + } + // + + + //TODO: Improve logic + //Checking for file to exist in files template folder + var templateCheck = ShellApi.fileExists({uri: window.NativeShellApp.GetKnownFolder('appsource')+'\\document-templates\\files\\template.'+type}), content; + // + if (templateCheck.success) { + switch (check.status) { + case 204: + //Template exists, so opening and getting contents to be used when creating file + content = ShellApi.openFile({uri: 'template.'+type}); + if (content.content) { + file.content = content.content; + } else { + file.content = ""; + } + break; + case 404: + //No template + file.content = ""; + break; + case 500: + //Error + break; + default: + //Error + break; + } + } else { + + } + + + /* +switch (type.toLowerCase()) { + case 'html': + break; + case 'css': + break; + case 'js': + break; + case 'xml': + break; + case 'json': + break; + default: + break; + } +*/ + + + + + + + + var create = ShellApi.createFile(file); + if (create.success) { + switch (create.status) { + case 201: + //File was created, opening created file + this.openFile(file); + break; + case 400: + //TODO: Add error handling + //window.alert('Error Code 400: File already exists.'); + break; + case 500: + //TODO: Add error handling + //window.alert('Error Code 500: An error occurred while creating a new file.'); + break; + default: + //TODO: Add error handling + //window.alert('Unknown Error: An error occurred while creating a new file.'); + break; + } + } else { + //window.alert('Unknown Error: An error occurred while creating a new file.'); + } + + + + + + + + + + + + + break; + case 500: + //TODO: Add error handling + //window.alert('Error Code 500: An error occurred while creating a new file.'); + break; + default: + //TODO: Add error handling + //window.alert('Unknown Error: An error occurred while creating a new file.'); + break; + } + } else { + //TODO: Add error handling + //window.alert('Unknown Error: An error occurred while creating a new file.'); + } + } + + } + }, + + + + + + //////////////////////////////////////////////////////////////////// + // + newProject: { + enumerable: false, + value: function () { + //Checking for cloud (to be added later) + if (this.cloud) { + //TODO: Add cloud integration + console.log("[CLOUD] : New Project"); + //documentManagerModule.DocumentManager.openDocument({"type": "html"}); + } else { + // + var directory = {uri: ShellApi.openShellDialog({type: 'directory', action: 'new'})}; + var check = ShellApi.directoryExists(directory); + // + if (check.success) { + switch (check.status) { + case 204: + this.createProject(directory); + break; + case 404: + //Directory does not exists, ready to be created + var create = ShellApi.createDirectory(directory); + if (create.success) { + switch (create.status) { + case 201: + this.createProject(directory); + break; + case 400: + window.alert('Error Code 400: Directory already exists.'); + break; + case 500: + window.alert('Error Code 500: An error occurred while creating a new directory.'); + break; + default: + window.alert('Unknown Error: An error occurred while creating a new directory.'); + break; + } + } else { + window.alert('Unknown Error: An error occurred while creating a new directory.'); + } + break; + case 500: + //TODO: Add error handling + window.alert('Error Code 500: An error occurred while creating a new directory.'); + break; + default: + //TODO: Add error handling + window.alert('Unknown Error: An error occurred while creating a new directory.'); + break; + } + } else { + //TODO: Add error handling + window.alert('Unknown Error: An error occurred while creating a new directory.'); + } + } + } + }, + + + + //////////////////////////////////////////////////////////////////// + // + createFile: { + enumerable: false, + value: function (file) { + //Checking for file to exist + var check = ShellApi.fileExists(file), createdFile = null; + // + if (check.success) { + switch (check.status) { + case 204: + //TODO: Add logic for already existing file + break; + case 404: + //File does not exists, ready to be created + var create = ShellApi.createFile(file); + if (create.success) { + switch (create.status) { + case 201: + //File was created + createdFile = file; + break; + case 400: + //File already exists + createdFile = file; + break; + case 500: + //Error while creating + break; + default: + //TODO: Add error handling + break; + } + } else { + //Error creating file via API + } + break; + case 500: + //TODO: Add error handling + break; + default: + //TODO: Add error handling + break; + } + } else { + //TODO: Add error handling + } + // + return createdFile; + } + }, + + + + //////////////////////////////////////////////////////////////////// + // + openFile: { + enumerable: false, + value: function (file) { + var uri, i; + //Checking for file to defined (otherwise prompts for URI) + if (file && file.uri) { + uri = file.uri; + } else { + //Checking to prompt user depending on mode + if (this.cloud) { + //TODO: Add cloud integration + } else { + //Getting file URI from native prompt + uri = ShellApi.openShellDialog({type: 'file', action: 'open'}); + } + } + //Checking for a valid URI + if (uri && uri.length>0) { + //Checking for URI to be single or array of URIs + if (uri.constructor.toString().indexOf('Array') == -1) { + //Opening single URI + shellOpenFile(uri); + } else { + //Opening via loop of URIs + for (i=0; uri[i]; i++) { + shellOpenFile (uri[i]); + } + } + } else { + //No file was selected to be opened, nothing happens + } + //Opening file via shell + function shellOpenFile (f) { + //Getting string from file + var doc = ShellApi.openFile({uri: f}), type = f.split('.'); + //Splitting to get file extension + type = type[type.length-1]; + //TODO: Fix this HACK to generate string + var dir = f.split('\\'), dir_str = '', server; + for (var i=0; i < dir.length-1; i++) { + dir_str += dir[i] + '\\'; + } + //Starting an instance of the shell server on directory + server = ShellApi.startServer(dir_str); + //Opening file in app + FileIo.open(doc, type, f, server); + } + } + }, + + //////////////////////////////////////////////////////////////////// + //Creating unified method to check for success + //FOR: Move, Copy, Rename + directoryMCRCheck: { + enumerable: false, + value: function (r, code) { + //TODO: Add error handling for unsuccessful attempts + var outcome; + // + if (r.success) { + // + outcome = {}; + // + switch (r.status) { + case 204: + //Success + break; + case 400: + //Already exists + break; + case 404: + //Source does not exists + break; + case 500: + //Unknonwn + break; + default: + break; + } + } else { + //TODO: Add error handling + } + // + return outcome; + } + }, + + + //////////////////////////////////////////////////////////////////// + // + createProject: { + enumerable: false, + value: function (directory) { + var mjs_dir = {uri: directory.uri}; + mjs_dir.uri += '\\m-js'; + var mjs_check = ShellApi.directoryExists(mjs_dir); + // + if (mjs_check.success) { + switch (mjs_check.status) { + case 204: + //TODO: Add logic to check for the correct version of m-js + break; + case 404: + //m-js does not exists, ready to be created + + + + + + + //Creating m-js folder and copying contents + var mjs_folder = ShellApi.createDirectory(mjs_dir); + if (mjs_folder.success) { + switch (mjs_folder.status) { + case 201: + //TODO: Add error handling for error on copy sub directories + + + var temp_dir = window.NativeShellApp.GetKnownFolder('appsource')+'\\user-document-templates\\montage-application\\systemio\\new\\project\\montage'; + var mjs_deps = ShellApi.createDirectory({uri: mjs_dir.uri+'\\deps'}); + + //Folder created, now copying contents + var copy_lib = ShellApi.copyDirectory({sourceUri: window.NativeShellApp.GetKnownFolder('frameworksource')+'\\lib', destUri: mjs_dir.uri+'\\lib'}), + copy_deps = ShellApi.copyDirectory({sourceUri: window.NativeShellApp.GetKnownFolder('frameworksource')+'\\deps\\require', destUri: mjs_dir.uri+'\\deps\\require'}), + copy_components = ShellApi.copyDirectory({sourceUri: window.NativeShellApp.GetKnownFolder('appsource')+'\\montage-components', destUri: directory.uri+'\\montage-components'}); + + //Checking for lib operation's result + if (copy_lib.success) { + //Successful copy of directory + } else { + //Error, checking to see reason for error and this method should handling error state + var check_lib = this.directoryMCRCheck(copy_lib, true); + } + + //Checking for deps operation's result + if (copy_deps.success) { + //Successful copy of directory + } else { + //Error, checking to see reason for error and this method should handling error state + var check_deps = this.directoryMCRCheck(copy_deps, true); + } + + //Checking for components operation's result + if (copy_components.success) { + //Successful copy of directory + } else { + //Error, checking to see reason for error and this method should handling error state + var check_components = this.directoryMCRCheck(copy_components, true); + } + + var prj_tmplt = window.NativeShellApp.GetKnownFolder('appsource')+'\\document-templates\\projects\\montage'; + //TODO: Add error handling for file copying, clean up this HACK + var copy_packagemjs = ShellApi.copyFile({sourceUri: window.NativeShellApp.GetKnownFolder('frameworksource')+'\\package.json', destUri: mjs_dir.uri+'\\package.json'}), + copy_styles = ShellApi.copyFile({sourceUri: prj_tmplt+'\\styles.css', destUri: directory.uri+'\\styles.css'}), + copy_appdelegate = ShellApi.copyFile({sourceUri: prj_tmplt+'\\appdelegate.js', destUri: directory.uri+'\\appdelegate.js'}), + copy_package = ShellApi.copyFile({sourceUri: prj_tmplt+'\\package.json', destUri: directory.uri+'\\package.json'}), + copy_index = ShellApi.copyFile({sourceUri: prj_tmplt+'\\index.html', destUri: directory.uri+'\\index.html'}); + + // + this.openProject(directory); + + + + + break; + case 400: + //TODO: Add logic to handle already existing copy of m-js + break; + case 500: + //TODO: Add error handling + break; + default: + //TODO: Add error handling + break; + } + } else { + //TODO: Add error handling + } + + + + + + + + + break; + case 500: + //TODO: Add error handling + break; + default: + //TODO: Add error handling + break; + } + } else { + //TODO: Add error handling + } + } + }, + + + + //////////////////////////////////////////////////////////////////// + // + openProject: { + enumerable: false, + value: function (directory) { + //TODO: Add functionality, this is a HACK + + + + + + var uri, i; + //Checking for directory to defined (otherwise prompts for URI) + if (directory && directory.uri) { + uri = directory.uri; + } else { + //Checking to prompt user depending on mode + if (this.cloud) { + //TODO: Add cloud integration + } else { + //Getting file URI from native prompt + uri = ShellApi.openShellDialog({type: 'directory', action: 'open'}); + } + } + //Checking for a valid URI + if (uri && uri.length>0) { + + this.openFile({uri: uri+'\\index.html'}); + + + } else { + //No file was selected to be opened, nothing happens + } + + + + + + } + }, + + + + + + //////////////////////////////////////////////////////////////////// + // + saveFile: { + enumerable: false, + value: function (f) { + //console.log(f); + //TODO: Add functionality + //console.log('FileSystem: saveFile'); + //HACK + + //////////////////////////////////////////////////////////////////// + // DEBUG CODE TO TEST WebGL I/O + //var glData = DocumentManagerModule.DocumentManager.activeDocument.glData; + //DocumentManagerModule.DocumentManager.activeDocument.glData = glData; + //////////////////////////////////////////////////////////////////// + + if (f) { + var s = ShellApi.updateFile(f); + } else { + //HACK + this.saveProject(); + } + + } + }, + + + + + //////////////////////////////////////////////////////////////////// + // + saveFileAs: { + enumerable: false, + value: function () { + //TODO: Add functionality + //console.log('FileSystem: saveFileAs'); + //HACK + this.saveProject(); + } + }, + + + + +