UNPKG

ares-ide

Version:

A browser-based code editor and UI designer for Enyo 2 projects

444 lines (412 loc) 13.8 kB
/*global Ares, ServiceRegistry, enyo, async, ares, alert, ComponentsRegistry, $L */ enyo.path.addPaths({ "assets" : "$enyo/../assets", // deprecated aliases "utilities" : "$enyo/../utilities", "services" : "$enyo/../services", "phobos" : "$enyo/../phobos", "deimos" : "$enyo/../deimos", "harmonia" : "$enyo/../harmonia", "project-view" : "$enyo/../project-view" }); enyo.kind({ name: "Ares", kind: "Control", classes: "onyx", fit: true, debug: false, //noDefer: true, //FIXME: does not work with statics:{} components: [ { name:"aresLayoutPanels", kind: "Panels", draggable: false, arrangerKind: "CollapsingArranger", fit: true, classes:"ares-main-panels enyo-border-box", onTransitionFinish:"changeGrabberDirection", components:[ { name: "projectView", kind: "ProjectView", classes: "ares-panel-min-width " }, { kind: "Harmonia", name: "harmonia", classes: "ares-panel-min-width enyo-fit", onFileOpenRequest: "openDocument", onFileRemoved: "closeDocument", onFolderChanged: "closeSomeDocuments" }, {kind: "Ares.EnyoEditor", name: "enyoEditor"} ] }, { name: "waitPopup", kind: "onyx.Popup", centered: true, floating: true, autoDismiss: false, modal: true, style: "text-align: center; padding: 20px; width: 200px;", components: [ {kind: "Image", src: "$phobos/assets/images/save-spinner.gif", style: "width: 54px; height: 55px;"}, {name: "waitPopupMessage", content: "Ongoing...", style: "padding-top: 10px;"}, {kind: "onyx.Button", name:"canceBuildButton", content: "Cancel", ontap: "cancelService", style: "margin-top: 10px;", showing: false} ] }, {name: "errorPopup", kind: "Ares.ErrorPopup", msg: "unknown error", details: ""}, {name: "signInErrorPopup", kind: "Ares.SignInErrorPopup", msg: "unknown error", details: ""}, {kind: "ServiceRegistry"}, {kind: "Ares.PackageMunger", name: "packageMunger"} ], handlers: { onReloadServices: "handleReloadServices", onUpdateAuth: "handleUpdateAuth", onShowWaitPopup: "showWaitPopup", onHideWaitPopup: "hideWaitPopup", onError: "showError", onDesignerBroken: "showDesignerError", onSignInError: "showAccountConfiguration", onTreeChanged: "_treeChanged", onFsEvent: "_fsEventAction", onChangingNode: "_nodeChanging", onAllDocumentsAreClosed: "showProjectView", onRegisterMe : "_registerComponent", onMovePanel : "_movePanel", //handlers for editorSettings kind (utilities/EditorSettings.js) onChangeSettings:"applyPreviewSettings", onChangeRightPane: "changeRightPane", onApplySettings: "applySettings" }, projectListIndex: 0, hermesFileTreeIndex: 1, enyoEditorIndex: 2, projectListWidth: 300, isProjectView: true, create: function() { ares.setupTraceLogger(this); // Setup this.trace() function according to this.debug value this.inherited(arguments); this._registerComponent(null,{name: "ares", reference: this}); ComponentsRegistry.getComponent("enyoEditor").showPhobosPanel(); ServiceRegistry.instance.setOwner(this); // plumb services events all the way up window.onbeforeunload = enyo.bind(this, "handleBeforeUnload"); if (Ares.TestController) { Ares.Workspace.loadProjects("com.enyojs.ares.tests", true); this.createComponent({kind: "Ares.TestController", aresObj: this}); } else { Ares.Workspace.loadProjects(); } Ares.instance = this; }, rendered: function() { this.inherited(arguments); this.showProjectView(); }, /** * @private */ handleReloadServices: function(inSender, inEvent) { this.trace("sender:", inSender, ", event:", inEvent); this.$.serviceRegistry.reloadServices(); }, /** * @private */ handleUpdateAuth: function(inSender, inEvent) { this.trace("sender:", inSender, ", event:", inEvent); this.$.serviceRegistry.setConfig(inEvent.serviceId, {auth: inEvent.auth}, inEvent.next); }, openDocument: function(inSender, inEvent) { this._openDocument(inEvent.projectData, inEvent.file, ares.noNext ); }, /** @private */ _openDocument: function(projectData, file, next) { ares.assertCb(next); var fileDataId = Ares.Workspace.files.computeId(file); var editor = ComponentsRegistry.getComponent("enyoEditor"); if (! fileDataId ) { throw new Error ('Undefined fileId for file ' + file.name + ' service ' + file.service); } var fileData = Ares.Workspace.files.get(fileDataId); // hide projectView only the first time a file is opened in a project // otherwise, let the user handle this var mayHideProjectView = Ares.Workspace.files.length ? function() { next();} : function(next) { this.hideProjectView(); next();} ; this.trace("open document with project ", projectData.getName(), " file ", file.name, " using cache ", fileData); if (fileData) { // switch triggered by double-clicking an already opened // file in HermesFileTree editor.switchToDocument(fileData, $L("Switching files..."), next) ; } else { this.showWaitPopup(this, {msg: $L("Fetching file...")}); async.waterfall( [ this._fetchDocument.bind(this,projectData, file), editor.switchToNewTabAndDoc.bind(editor,projectData,file), mayHideProjectView.bind(this) ], (function(err) { this.hideWaitPopup(); next(err); }).bind(this) ); } }, /** @private */ _fetchDocument: function(projectData, file, next) { this.trace("project name:", projectData.getName(), ", file name:", file.name); var service = projectData.getService(); service.getFile(file.id) .response(this, function(inEvent, inData) { next(null, inData && inData.content || ""); }) .error(this, function(inEvent, inErr) { next(inErr); }); }, /** * close documents contained in a folder after a folder rename. * @param {Object} inSender * @param {Object} inEvent */ // One might say that these documents are canon folder... closeSomeDocuments: function(inSender, inEvent) { this.trace("sender:", inSender, ", event:", inEvent); var files = Ares.Workspace.files, model, i; for( i = 0; i < files.models.length; i++ ) { model = files.models[i]; var path = model.getFile().path, serviceId = model.getProjectData().getServiceId(); if ( serviceId == inEvent.projectData.getServiceId() && path.indexOf( inEvent.file.path, 0 ) >= 0 ) { this._closeDocument(model.id); i--; } } }, /** @private */ closeDocument: function(inSender,inEvent) { this._closeDocument(inEvent.id); }, _closeDocument: function(docId) { ComponentsRegistry.getComponent("enyoEditor").closeDoc(docId, ares.noNext); }, /** @private */ _fsEventAction: function(inSender, inEvent) { var harmonia = ComponentsRegistry.getComponent("harmonia"); harmonia.refreshFileTree(inEvent.nodeId); }, handleBeforeUnload: function() { if (window.location.search.indexOf("debug") == -1) { return 'You may have some unsaved data'; } }, /** * The width of the panel needs to be calculated en function of width of the previous panel * if the panel is not the last panel of arranger * and we want that this panel take place of all remaining screen after display of all previous panels * @private * @param {Object} panel */ _calcPanelWidth:function(panel) { var cn = this.$.aresLayoutPanels.hasNode(); this.aresContainerBounds = cn ? {width: cn.clientWidth, height: cn.clientHeight} : {}; panel.applyStyle("width", (this.aresContainerBounds.width - this.projectListWidth) + "px"); }, hideProjectView: function(inSender, inEvent) { this.isProjectView = false; this.$.aresLayoutPanels.getPanels()[this.hermesFileTreeIndex].applyStyle("width", null); var harmonia = ComponentsRegistry.getComponent("harmonia"); harmonia.addClass("ares-small-screen"); this.$.aresLayoutPanels.reflow(); this.$.aresLayoutPanels.setIndexDirect(this.hermesFileTreeIndex); harmonia.showGrabber(); harmonia.hideLogo(); }, showProjectView: function(inSender, inEvent) { this.isProjectView = true; var harmonia = ComponentsRegistry.getComponent("harmonia"); harmonia.removeClass("ares-small-screen"); this.$.aresLayoutPanels.setIndex(this.projectListIndex); this.$.aresLayoutPanels.getPanels()[this.enyoEditorIndex].switchGrabberDirection(false); this._calcPanelWidth(this.$.aresLayoutPanels.getPanels()[this.hermesFileTreeIndex]); this.$.aresLayoutPanels.reflow(); harmonia.hideGrabber(); harmonia.showLogo(); }, changeGrabberDirection:function(inSender, inEvent){ if(inEvent.toIndex > 0 && inEvent.fromIndex < inEvent.toIndex){ for(var i = 1; i<=inEvent.toIndex; i++){ this.$.aresLayoutPanels.getPanels()[i].switchGrabberDirection(true); } } if(inEvent.fromIndex>inEvent.toIndex){ this.$.aresLayoutPanels.getPanels()[inEvent.fromIndex].switchGrabberDirection(false); } }, /** @private */ _movePanel: function(inSender, inEvent){ if(inEvent.panelIndex === this.$.aresLayoutPanels.getIndex()){ this.$.aresLayoutPanels.previous(); }else{ this.$.aresLayoutPanels.setIndex(inEvent.panelIndex); } }, resizeHandler: function(inSender, inEvent) { this.inherited(arguments); if(this.$.aresLayoutPanels.getIndex() === this.projectListIndex && this.isProjectView){ this._calcPanelWidth(this.$.aresLayoutPanels.getPanels()[this.hermesFileTreeIndex]); } }, showWaitPopup: function(inSender, inEvent) { if(inEvent.service === 'build' ) { this.$.canceBuildButton.show(); } this.$.waitPopupMessage.setContent(inEvent.msg); this.$.waitPopup.show(); }, cancelService: function(inSender, inEvent) { enyo.Signals.send("plugin.phonegap.buildCanceled"); this.hideWaitPopup(); }, hideWaitPopup: function(inSender, inEvent) { this.$.canceBuildButton.hide(); this.$.waitPopup.hide(); }, showError: function(inSender, inEvent) { this.trace("event:", inEvent, "from sender:", inSender); this.hideWaitPopup(); if (inEvent && inEvent.err && inEvent.err.status === 401) { this.showSignInErrorPopup(inEvent); } else { this.showErrorPopup(inEvent); } return true; //Stop event propagation }, showErrorPopup : function(inEvent) { this.$.errorPopup.raise(inEvent); }, showDesignerError: function(){ this.showError("",ComponentsRegistry.getComponent("enyoEditor").getErrorFromDesignerBroken()); }, showSignInErrorPopup : function(inEvent) { this.$.signInErrorPopup.raise(inEvent); }, showAccountConfiguration: function() { ComponentsRegistry.getComponent("accountsConfigurator").show(); this.$.signInErrorPopup.hide(); }, /** * Event handler for user-initiated file or folder changes * * @private * @param {Object} inSender * @param {Object} inEvent as defined by calls to HermesFileTree#doTreeChanged */ _treeChanged: function(inSender, inEvent) { this.trace("sender:", inSender, ", event:", inEvent); this.$.packageMunger.changeNodes(inEvent, (function(err) { if (err) { this.warn(err); } }).bind(this)); }, /** * Event handler for system-initiated file or folder changes * * @private * @param {Object} inSender * @param {Object} inEvent as defined by calls to Ares.PackageMunger#doChangingNode */ _nodeChanging: function(inSender, inEvent) { this.trace("sender:", inSender, ", event:", inEvent); var docId = Ares.Workspace.files.computeId(inEvent.node); this._closeDocument(docId); }, /** * Event handler for ace's settings called when settings from localStorage have to be applied (cancel/open) * * @private * @param {Object} inSender * @param {Object} inEvent */ applySettings: function(inSender, inEvent){ ComponentsRegistry.getComponent("enyoEditor").applySettings(inEvent.originator.getSettingFromLS()); }, /** * Event handler for ace's settings called when a setting is changing (change theme, font size on ui for example) * * @private * @param {Object} inSender * @param {Object} inEvent */ applyPreviewSettings: function(inSender, inEvent){ ComponentsRegistry.getComponent("enyoEditor").applySettings(inEvent.originator.getPreviewSettings()); }, /** * Event handler for ace's settings called when a right panel is changed * * @private * @param {Object} inSender * @param {Object} inEvent */ changeRightPane: function(inSender, inEvent){ ComponentsRegistry.getComponent("enyoEditor").changeRightPane(inEvent.originator.getPreviewSettings()); }, /** * Event handler for ares components registry * * @private * @param {Object} inSender * @param {Object} inEvent => inEvent.name in [phobos, deimos, projectView, documentToolbar, harmonia, enyoEditor, accountsConfigurator, ...] */ _registerComponent: function(inSender, inEvent) { ComponentsRegistry.registerComponent(inEvent); return true; }, stopEvent: function(){ return true; }, statics: { isBrowserSupported: function() { if (enyo.platform.ie && enyo.platform.ie <= 8) { return false; } else { return true; } }, instance: null } }); if ( ! Ares.isBrowserSupported()) { alert($L("Ares is designed for the latest version of IE. We recommend that you upgrade your browser or use Chrome")); } /** * Manages registered components * * @class ComponentRegistry * @augments enyo.Object */ enyo.kind({ name: "ComponentsRegistry", debug: false, kind: "enyo.Object", statics: { components: {}, /** @public */ registerComponent: function(inEvent) { var ref = ComponentsRegistry.components[inEvent.name]; if (ref === undefined || ref === inEvent.reference){ ComponentsRegistry.components[inEvent.name] = inEvent.reference; } else { throw new Error("Component is already registred: '" + inEvent.name + "'"); } }, getComponent: function(name) { return ComponentsRegistry.components[name]; } } });