mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-07 20:17:37 +00:00
244 lines
6.4 KiB
JavaScript
244 lines
6.4 KiB
JavaScript
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
|
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
const { Cu } = require("chrome");
|
|
const { Class } = require("sdk/core/heritage");
|
|
const { EventTarget } = require("sdk/event/target");
|
|
const { emit } = require("sdk/event/core");
|
|
const { EditorTypeForResource } = require("projecteditor/editors");
|
|
const NetworkHelper = require("devtools/toolkit/webconsole/network-helper");
|
|
const promise = require("promise");
|
|
|
|
/**
|
|
* The Shell is the object that manages the editor for a single resource.
|
|
* It is in charge of selecting the proper Editor (text/image/plugin-defined)
|
|
* and instantiating / appending the editor.
|
|
* This object is not exported, it is just used internally by the ShellDeck.
|
|
*
|
|
* This object has a promise `editorAppended`, that will resolve once the editor
|
|
* is ready to be used.
|
|
*/
|
|
var Shell = Class({
|
|
extends: EventTarget,
|
|
|
|
/**
|
|
* @param ProjectEditor host
|
|
* @param Resource resource
|
|
*/
|
|
initialize: function(host, resource) {
|
|
this.host = host;
|
|
this.doc = host.document;
|
|
this.resource = resource;
|
|
this.elt = this.doc.createElement("vbox");
|
|
this.elt.classList.add("view-project-detail");
|
|
this.elt.shell = this;
|
|
|
|
let constructor = this._editorTypeForResource();
|
|
|
|
this.editor = constructor(this.host);
|
|
this.editor.shell = this;
|
|
this.editorAppended = this.editor.appended;
|
|
|
|
this.editor.on("load", () => {
|
|
this.editorDeferred.resolve();
|
|
});
|
|
this.elt.appendChild(this.editor.elt);
|
|
},
|
|
|
|
/**
|
|
* Start loading the resource. The 'load' event happens as
|
|
* a result of this function, so any listeners to 'editorAppended'
|
|
* need to be added before calling this.
|
|
*/
|
|
load: function() {
|
|
this.editorDeferred = promise.defer();
|
|
this.editorLoaded = this.editorDeferred.promise;
|
|
this.editor.load(this.resource);
|
|
},
|
|
|
|
/**
|
|
* Destroy the shell and its associated editor
|
|
*/
|
|
destroy: function() {
|
|
this.editor.destroy();
|
|
this.resource.destroy();
|
|
},
|
|
|
|
/**
|
|
* Make sure the correct editor is selected for the resource.
|
|
* @returns Type:Editor
|
|
*/
|
|
_editorTypeForResource: function() {
|
|
let resource = this.resource;
|
|
let constructor = EditorTypeForResource(resource);
|
|
|
|
if (this.host.plugins) {
|
|
this.host.plugins.forEach(plugin => {
|
|
if (plugin.editorForResource) {
|
|
let pluginEditor = plugin.editorForResource(resource);
|
|
if (pluginEditor) {
|
|
constructor = pluginEditor;
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
return constructor;
|
|
}
|
|
});
|
|
|
|
/**
|
|
* The ShellDeck is in charge of managing the list of active Shells for
|
|
* the current ProjectEditor instance (aka host).
|
|
*
|
|
* This object emits the following events:
|
|
* - "editor-created": When an editor is initially created
|
|
* - "editor-activated": When an editor is ready to use
|
|
* - "editor-deactivated": When an editor is ready to use
|
|
*/
|
|
var ShellDeck = Class({
|
|
extends: EventTarget,
|
|
|
|
/**
|
|
* @param ProjectEditor host
|
|
* @param Document document
|
|
*/
|
|
initialize: function(host, document) {
|
|
this.doc = document;
|
|
this.host = host;
|
|
this.deck = this.doc.createElement("deck");
|
|
this.deck.setAttribute("flex", "1");
|
|
this.elt = this.deck;
|
|
|
|
this.shells = new Map();
|
|
|
|
this._activeShell = null;
|
|
},
|
|
|
|
/**
|
|
* Open a resource in a Shell. Will create the Shell
|
|
* if it doesn't exist yet.
|
|
*
|
|
* @param Resource resource
|
|
* The file to be opened
|
|
* @returns Shell
|
|
*/
|
|
open: function(defaultResource) {
|
|
let shell = this.shellFor(defaultResource);
|
|
if (!shell) {
|
|
shell = this._createShell(defaultResource);
|
|
this.shells.set(defaultResource, shell);
|
|
}
|
|
this.selectShell(shell);
|
|
return shell;
|
|
},
|
|
|
|
/**
|
|
* Create a new Shell for a resource. Called by `open`.
|
|
*
|
|
* @returns Shell
|
|
*/
|
|
_createShell: function(defaultResource) {
|
|
let shell = Shell(this.host, defaultResource);
|
|
|
|
shell.editorAppended.then(() => {
|
|
this.shells.set(shell.resource, shell);
|
|
emit(this, "editor-created", shell.editor);
|
|
if (this.currentShell === shell) {
|
|
this.selectShell(shell);
|
|
}
|
|
|
|
});
|
|
|
|
shell.load();
|
|
this.deck.appendChild(shell.elt);
|
|
return shell;
|
|
},
|
|
|
|
/**
|
|
* Remove the shell for a given resource.
|
|
*
|
|
* @param Resource resource
|
|
*/
|
|
removeResource: function(resource) {
|
|
let shell = this.shellFor(resource);
|
|
if (shell) {
|
|
this.shells.delete(resource);
|
|
shell.destroy();
|
|
}
|
|
},
|
|
|
|
destroy: function() {
|
|
for (let [resource, shell] of this.shells.entries()) {
|
|
this.shells.delete(resource);
|
|
shell.destroy();
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Select a given shell and open its editor.
|
|
* Will fire editor-deactivated on the old selected Shell (if any),
|
|
* and editor-activated on the new one once it is ready
|
|
*
|
|
* @param Shell shell
|
|
*/
|
|
selectShell: function(shell) {
|
|
// Don't fire another activate if this is already the active shell
|
|
if (this._activeShell != shell) {
|
|
if (this._activeShell) {
|
|
emit(this, "editor-deactivated", this._activeShell.editor, this._activeShell.resource);
|
|
}
|
|
this.deck.selectedPanel = shell.elt;
|
|
this._activeShell = shell;
|
|
|
|
// Only reload the shell if the editor doesn't have local changes.
|
|
if (shell.editor.isClean()) {
|
|
shell.load();
|
|
}
|
|
shell.editorLoaded.then(() => {
|
|
// Handle case where another shell has been requested before this
|
|
// one is finished loading.
|
|
if (this._activeShell === shell) {
|
|
emit(this, "editor-activated", shell.editor, shell.resource);
|
|
}
|
|
});
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Find a Shell for a Resource.
|
|
*
|
|
* @param Resource resource
|
|
* @returns Shell
|
|
*/
|
|
shellFor: function(resource) {
|
|
return this.shells.get(resource);
|
|
},
|
|
|
|
/**
|
|
* The currently active Shell. Note: the editor may not yet be available
|
|
* on the current shell. Best to wait for the 'editor-activated' event
|
|
* instead.
|
|
*
|
|
* @returns Shell
|
|
*/
|
|
get currentShell() {
|
|
return this._activeShell;
|
|
},
|
|
|
|
/**
|
|
* The currently active Editor, or null if it is not ready.
|
|
*
|
|
* @returns Editor
|
|
*/
|
|
get currentEditor() {
|
|
let shell = this.currentShell;
|
|
return shell ? shell.editor : null;
|
|
},
|
|
|
|
});
|
|
exports.ShellDeck = ShellDeck;
|