diff options
author | Matt A. Tobin <mattatobin@localhost.localdomain> | 2018-02-02 04:16:08 -0500 |
---|---|---|
committer | Matt A. Tobin <mattatobin@localhost.localdomain> | 2018-02-02 04:16:08 -0500 |
commit | 5f8de423f190bbb79a62f804151bc24824fa32d8 (patch) | |
tree | 10027f336435511475e392454359edea8e25895d /devtools/client/projecteditor/lib/plugins | |
parent | 49ee0794b5d912db1f95dce6eb52d781dc210db5 (diff) | |
download | UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.gz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.lz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.xz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.zip |
Add m-esr52 at 52.6.0
Diffstat (limited to 'devtools/client/projecteditor/lib/plugins')
22 files changed, 893 insertions, 0 deletions
diff --git a/devtools/client/projecteditor/lib/plugins/app-manager/app-project-editor.js b/devtools/client/projecteditor/lib/plugins/app-manager/app-project-editor.js new file mode 100644 index 000000000..9a66770b0 --- /dev/null +++ b/devtools/client/projecteditor/lib/plugins/app-manager/app-project-editor.js @@ -0,0 +1,56 @@ +/* -*- 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 promise = require("promise"); +const { ItchEditor } = require("devtools/client/projecteditor/lib/editors"); + +var AppProjectEditor = Class({ + extends: ItchEditor, + + hidesToolbar: true, + + initialize: function (host) { + ItchEditor.prototype.initialize.apply(this, arguments); + this.appended = promise.resolve(); + this.host = host; + this.label = "app-manager"; + }, + + destroy: function () { + this.elt.remove(); + this.elt = null; + }, + + load: function (resource) { + let {appManagerOpts} = this.host.project; + + // Only load the frame the first time it is selected + if (!this.iframe || this.iframe.getAttribute("src") !== appManagerOpts.projectOverviewURL) { + + this.elt.textContent = ""; + let iframe = this.iframe = this.elt.ownerDocument.createElement("iframe"); + let iframeLoaded = this.iframeLoaded = promise.defer(); + + iframe.addEventListener("load", function onLoad() { + iframe.removeEventListener("load", onLoad); + iframeLoaded.resolve(); + }); + + iframe.setAttribute("flex", "1"); + iframe.setAttribute("src", appManagerOpts.projectOverviewURL); + this.elt.appendChild(iframe); + + } + + promise.all([this.iframeLoaded.promise, this.appended]).then(() => { + this.emit("load"); + }); + } +}); + +exports.AppProjectEditor = AppProjectEditor; diff --git a/devtools/client/projecteditor/lib/plugins/app-manager/moz.build b/devtools/client/projecteditor/lib/plugins/app-manager/moz.build new file mode 100644 index 000000000..8aae52725 --- /dev/null +++ b/devtools/client/projecteditor/lib/plugins/app-manager/moz.build @@ -0,0 +1,10 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# 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/. + +DevToolsModules( + 'app-project-editor.js', + 'plugin.js', +) diff --git a/devtools/client/projecteditor/lib/plugins/app-manager/plugin.js b/devtools/client/projecteditor/lib/plugins/app-manager/plugin.js new file mode 100644 index 000000000..82bbab34b --- /dev/null +++ b/devtools/client/projecteditor/lib/plugins/app-manager/plugin.js @@ -0,0 +1,77 @@ +const { Cu } = require("chrome"); +const { Class } = require("sdk/core/heritage"); +const { EventTarget } = require("sdk/event/target"); +const { emit } = require("sdk/event/core"); +const promise = require("promise"); +var { registerPlugin, Plugin } = require("devtools/client/projecteditor/lib/plugins/core"); +const { AppProjectEditor } = require("./app-project-editor"); +const OPTION_URL = "chrome://devtools/skin/images/tool-options.svg"; +const Services = require("Services"); +const Strings = Services.strings.createBundle("chrome://devtools/locale/webide.properties"); + +var AppManagerRenderer = Class({ + extends: Plugin, + + isAppManagerProject: function () { + return !!this.host.project.appManagerOpts; + }, + editorForResource: function (resource) { + if (!resource.parent && this.isAppManagerProject()) { + return AppProjectEditor; + } + }, + getUI: function (parent) { + let doc = parent.ownerDocument; + if (parent.childElementCount == 0) { + let image = doc.createElement("image"); + let optionImage = doc.createElement("image"); + let flexElement = doc.createElement("div"); + let nameLabel = doc.createElement("span"); + let statusElement = doc.createElement("div"); + + image.className = "project-image"; + optionImage.className = "project-options"; + optionImage.setAttribute("src", OPTION_URL); + nameLabel.className = "project-name-label"; + statusElement.className = "project-status"; + flexElement.className = "project-flex"; + + parent.appendChild(image); + parent.appendChild(nameLabel); + parent.appendChild(flexElement); + parent.appendChild(statusElement); + parent.appendChild(optionImage); + } + + return { + image: parent.querySelector(".project-image"), + nameLabel: parent.querySelector(".project-name-label"), + statusElement: parent.querySelector(".project-status") + }; + }, + onAnnotate: function (resource, editor, elt) { + if (resource.parent || !this.isAppManagerProject()) { + return; + } + + let {appManagerOpts} = this.host.project; + let doc = elt.ownerDocument; + + let {image, nameLabel, statusElement} = this.getUI(elt); + let name = appManagerOpts.name || resource.basename; + let url = appManagerOpts.iconUrl || "icon-sample.png"; + let status = appManagerOpts.validationStatus || "unknown"; + let tooltip = Strings.formatStringFromName("status_tooltip", + [Strings.GetStringFromName("status_" + status)], 1); + + nameLabel.textContent = name; + image.setAttribute("src", url); + statusElement.setAttribute("status", status); + statusElement.setAttribute("tooltiptext", tooltip); + + return true; + } +}); + +exports.AppManagerRenderer = AppManagerRenderer; +registerPlugin(AppManagerRenderer); diff --git a/devtools/client/projecteditor/lib/plugins/core.js b/devtools/client/projecteditor/lib/plugins/core.js new file mode 100644 index 000000000..933eda043 --- /dev/null +++ b/devtools/client/projecteditor/lib/plugins/core.js @@ -0,0 +1,83 @@ +/* -*- 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/. */ + +// This is the core plugin API. + +const { Class } = require("sdk/core/heritage"); + +var Plugin = Class({ + initialize: function (host) { + this.host = host; + this.init(host); + }, + + destroy: function (host) { }, + + init: function (host) {}, + + showForCategories: function (elt, categories) { + this._showFor = this._showFor || []; + let set = new Set(categories); + this._showFor.push({ + elt: elt, + categories: new Set(categories) + }); + if (this.host.currentEditor) { + this.onEditorActivated(this.host.currentEditor); + } else { + elt.classList.add("plugin-hidden"); + } + }, + + priv: function (item) { + if (!this._privData) { + this._privData = new WeakMap(); + } + if (!this._privData.has(item)) { + this._privData.set(item, {}); + } + return this._privData.get(item); + }, + onTreeSelected: function (resource) {}, + + + // Editor state lifetime... + onEditorCreated: function (editor) {}, + onEditorDestroyed: function (editor) {}, + + onEditorActivated: function (editor) { + if (this._showFor) { + let category = editor.category; + for (let item of this._showFor) { + if (item.categories.has(category)) { + item.elt.classList.remove("plugin-hidden"); + } else { + item.elt.classList.add("plugin-hidden"); + } + } + } + }, + onEditorDeactivated: function (editor) { + if (this._showFor) { + for (let item of this._showFor) { + item.elt.classList.add("plugin-hidden"); + } + } + }, + + onEditorLoad: function (editor) {}, + onEditorSave: function (editor) {}, + onEditorChange: function (editor) {}, + onEditorCursorActivity: function (editor) {}, +}); +exports.Plugin = Plugin; + +function registerPlugin(constr) { + exports.registeredPlugins.push(constr); +} +exports.registerPlugin = registerPlugin; + +exports.registeredPlugins = []; diff --git a/devtools/client/projecteditor/lib/plugins/delete/delete.js b/devtools/client/projecteditor/lib/plugins/delete/delete.js new file mode 100644 index 000000000..b28d6a0ef --- /dev/null +++ b/devtools/client/projecteditor/lib/plugins/delete/delete.js @@ -0,0 +1,67 @@ +/* -*- 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 { Class } = require("sdk/core/heritage"); +const { registerPlugin, Plugin } = require("devtools/client/projecteditor/lib/plugins/core"); +const { confirm } = require("devtools/client/projecteditor/lib/helpers/prompts"); +const { getLocalizedString } = require("devtools/client/projecteditor/lib/helpers/l10n"); + +var DeletePlugin = Class({ + extends: Plugin, + shouldConfirm: true, + + init: function (host) { + this.host.addCommand(this, { + id: "cmd-delete" + }); + this.contextMenuItem = this.host.createMenuItem({ + parent: this.host.contextMenuPopup, + label: getLocalizedString("projecteditor.deleteLabel"), + command: "cmd-delete" + }); + }, + + confirmDelete: function (resource) { + let deletePromptMessage = resource.isDir ? + getLocalizedString("projecteditor.deleteFolderPromptMessage") : + getLocalizedString("projecteditor.deleteFilePromptMessage"); + return !this.shouldConfirm || confirm( + getLocalizedString("projecteditor.deletePromptTitle"), + deletePromptMessage + ); + }, + + onContextMenuOpen: function (resource) { + // Do not allow deletion of the top level items in the tree. In the + // case of the Web IDE in particular this can leave the UI in a weird + // state. If we'd like to add ability to delete the project folder from + // the tree in the future, then the UI could be cleaned up by listening + // to the ProjectTree's "resource-removed" event. + if (!resource.parent) { + this.contextMenuItem.setAttribute("hidden", "true"); + } else { + this.contextMenuItem.removeAttribute("hidden"); + } + }, + + onCommand: function (cmd) { + if (cmd === "cmd-delete") { + let tree = this.host.projectTree; + let resource = tree.getSelectedResource(); + + if (!this.confirmDelete(resource)) { + return; + } + + resource.delete().then(() => { + this.host.project.refresh(); + }); + } + } +}); + +exports.DeletePlugin = DeletePlugin; +registerPlugin(DeletePlugin); diff --git a/devtools/client/projecteditor/lib/plugins/delete/moz.build b/devtools/client/projecteditor/lib/plugins/delete/moz.build new file mode 100644 index 000000000..4b1d00466 --- /dev/null +++ b/devtools/client/projecteditor/lib/plugins/delete/moz.build @@ -0,0 +1,9 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# 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/. + +DevToolsModules( + 'delete.js', +) diff --git a/devtools/client/projecteditor/lib/plugins/dirty/dirty.js b/devtools/client/projecteditor/lib/plugins/dirty/dirty.js new file mode 100644 index 000000000..f976c626f --- /dev/null +++ b/devtools/client/projecteditor/lib/plugins/dirty/dirty.js @@ -0,0 +1,47 @@ +/* -*- 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 { Class } = require("sdk/core/heritage"); +const { registerPlugin, Plugin } = require("devtools/client/projecteditor/lib/plugins/core"); +const { emit } = require("sdk/event/core"); + +var DirtyPlugin = Class({ + extends: Plugin, + + onEditorSave: function (editor) { this.onEditorChange(editor); }, + onEditorLoad: function (editor) { this.onEditorChange(editor); }, + + onEditorChange: function (editor) { + // Only run on a TextEditor + if (!editor || !editor.editor) { + return; + } + + // Dont' force a refresh unless the dirty state has changed... + let priv = this.priv(editor); + let clean = editor.isClean(); + if (priv.isClean !== clean) { + let resource = editor.shell.resource; + emit(resource, "label-change", resource); + priv.isClean = clean; + } + }, + + onAnnotate: function (resource, editor, elt) { + // Only run on a TextEditor + if (!editor || !editor.editor) { + return; + } + + if (!editor.isClean()) { + elt.textContent = "*" + resource.displayName; + return true; + } + } +}); +exports.DirtyPlugin = DirtyPlugin; + +registerPlugin(DirtyPlugin); diff --git a/devtools/client/projecteditor/lib/plugins/dirty/moz.build b/devtools/client/projecteditor/lib/plugins/dirty/moz.build new file mode 100644 index 000000000..b86c5a9af --- /dev/null +++ b/devtools/client/projecteditor/lib/plugins/dirty/moz.build @@ -0,0 +1,9 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# 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/. + +DevToolsModules( + 'dirty.js', +) diff --git a/devtools/client/projecteditor/lib/plugins/image-view/image-editor.js b/devtools/client/projecteditor/lib/plugins/image-view/image-editor.js new file mode 100644 index 000000000..668fcbeb2 --- /dev/null +++ b/devtools/client/projecteditor/lib/plugins/image-view/image-editor.js @@ -0,0 +1,50 @@ +/* -*- 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 promise = require("promise"); +const { ItchEditor } = require("devtools/client/projecteditor/lib/editors"); + +var ImageEditor = Class({ + extends: ItchEditor, + + initialize: function () { + ItchEditor.prototype.initialize.apply(this, arguments); + this.label = "image"; + this.appended = promise.resolve(); + }, + + load: function (resource) { + this.elt.innerHTML = ""; + let image = this.image = this.doc.createElement("image"); + image.className = "editor-image"; + image.setAttribute("src", resource.uri); + + let box1 = this.doc.createElement("box"); + box1.appendChild(image); + + let box2 = this.doc.createElement("box"); + box2.setAttribute("flex", 1); + + this.elt.appendChild(box1); + this.elt.appendChild(box2); + + this.appended.then(() => { + this.emit("load"); + }); + }, + + destroy: function () { + if (this.image) { + this.image.remove(); + this.image = null; + } + } + +}); + +exports.ImageEditor = ImageEditor; diff --git a/devtools/client/projecteditor/lib/plugins/image-view/moz.build b/devtools/client/projecteditor/lib/plugins/image-view/moz.build new file mode 100644 index 000000000..d67370e5b --- /dev/null +++ b/devtools/client/projecteditor/lib/plugins/image-view/moz.build @@ -0,0 +1,10 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# 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/. + +DevToolsModules( + 'image-editor.js', + 'plugin.js', +) diff --git a/devtools/client/projecteditor/lib/plugins/image-view/plugin.js b/devtools/client/projecteditor/lib/plugins/image-view/plugin.js new file mode 100644 index 000000000..626ea3c9a --- /dev/null +++ b/devtools/client/projecteditor/lib/plugins/image-view/plugin.js @@ -0,0 +1,28 @@ +/* -*- 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 promise = require("promise"); +const { ImageEditor } = require("./image-editor"); +const { registerPlugin, Plugin } = require("devtools/client/projecteditor/lib/plugins/core"); + +var ImageEditorPlugin = Class({ + extends: Plugin, + + editorForResource: function (node) { + if (node.contentCategory === "image") { + return ImageEditor; + } + }, + + init: function (host) { + + } +}); + +exports.ImageEditorPlugin = ImageEditorPlugin; +registerPlugin(ImageEditorPlugin); diff --git a/devtools/client/projecteditor/lib/plugins/logging/logging.js b/devtools/client/projecteditor/lib/plugins/logging/logging.js new file mode 100644 index 000000000..cd5757b72 --- /dev/null +++ b/devtools/client/projecteditor/lib/plugins/logging/logging.js @@ -0,0 +1,29 @@ +/* -*- 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/. */ + +var { Class } = require("sdk/core/heritage"); +var { registerPlugin, Plugin } = require("devtools/client/projecteditor/lib/plugins/core"); + +var LoggingPlugin = Class({ + extends: Plugin, + + // Editor state lifetime... + onEditorCreated: function (editor) { console.log("editor created: " + editor); }, + onEditorDestroyed: function (editor) { console.log("editor destroyed: " + editor);}, + + onEditorSave: function (editor) { console.log("editor saved: " + editor); }, + onEditorLoad: function (editor) { console.log("editor loaded: " + editor); }, + + onEditorActivated: function (editor) { console.log("editor activated: " + editor);}, + onEditorDeactivated: function (editor) { console.log("editor deactivated: " + editor);}, + + onEditorChange: function (editor) { console.log("editor changed: " + editor);}, + + onCommand: function (cmd) { console.log("Command: " + cmd); } +}); +exports.LoggingPlugin = LoggingPlugin; + +registerPlugin(LoggingPlugin); diff --git a/devtools/client/projecteditor/lib/plugins/logging/moz.build b/devtools/client/projecteditor/lib/plugins/logging/moz.build new file mode 100644 index 000000000..5d8d98fbe --- /dev/null +++ b/devtools/client/projecteditor/lib/plugins/logging/moz.build @@ -0,0 +1,9 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# 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/. + +DevToolsModules( + 'logging.js', +) diff --git a/devtools/client/projecteditor/lib/plugins/moz.build b/devtools/client/projecteditor/lib/plugins/moz.build new file mode 100644 index 000000000..17bff7ce0 --- /dev/null +++ b/devtools/client/projecteditor/lib/plugins/moz.build @@ -0,0 +1,21 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# 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/. + +DIRS += [ + 'app-manager', + 'delete', + 'dirty', + 'image-view', + 'logging', + 'new', + 'rename', + 'save', + 'status-bar', +] + +DevToolsModules( + 'core.js', +) diff --git a/devtools/client/projecteditor/lib/plugins/new/moz.build b/devtools/client/projecteditor/lib/plugins/new/moz.build new file mode 100644 index 000000000..3caacefb1 --- /dev/null +++ b/devtools/client/projecteditor/lib/plugins/new/moz.build @@ -0,0 +1,9 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# 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/. + +DevToolsModules( + 'new.js', +) diff --git a/devtools/client/projecteditor/lib/plugins/new/new.js b/devtools/client/projecteditor/lib/plugins/new/new.js new file mode 100644 index 000000000..220cb4977 --- /dev/null +++ b/devtools/client/projecteditor/lib/plugins/new/new.js @@ -0,0 +1,80 @@ +/* -*- 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 { Class } = require("sdk/core/heritage"); +const { registerPlugin, Plugin } = require("devtools/client/projecteditor/lib/plugins/core"); +const { getLocalizedString } = require("devtools/client/projecteditor/lib/helpers/l10n"); + +// Handles the new command. +var NewFile = Class({ + extends: Plugin, + + init: function () { + this.command = this.host.addCommand(this, { + id: "cmd-new", + key: getLocalizedString("projecteditor.new.commandkey"), + modifiers: "accel" + }); + this.host.createMenuItem({ + parent: this.host.fileMenuPopup, + label: getLocalizedString("projecteditor.newLabel"), + command: "cmd-new", + key: "key_cmd-new" + }); + this.host.createMenuItem({ + parent: this.host.contextMenuPopup, + label: getLocalizedString("projecteditor.newLabel"), + command: "cmd-new" + }); + }, + + onCommand: function (cmd) { + if (cmd === "cmd-new") { + let tree = this.host.projectTree; + let resource = tree.getSelectedResource(); + parent = resource.isDir ? resource : resource.parent; + sibling = resource.isDir ? null : resource; + + if (!("createChild" in parent)) { + return; + } + + let extension = sibling ? sibling.contentCategory : parent.store.defaultCategory; + let template = "untitled{1}." + extension; + let name = this.suggestName(parent, template); + + tree.promptNew(name, parent, sibling).then(name => { + + // XXX: sanitize bad file names. + + // If the name is already taken, just add/increment a number. + if (parent.hasChild(name)) { + let matches = name.match(/([^\d.]*)(\d*)([^.]*)(.*)/); + template = matches[1] + "{1}" + matches[3] + matches[4]; + name = this.suggestName(parent, template, parseInt(matches[2]) || 2); + } + + return parent.createChild(name); + }).then(resource => { + tree.selectResource(resource); + this.host.currentEditor.focus(); + }).then(null, console.error); + } + }, + + suggestName: function (parent, template, start = 1) { + let i = start; + let name; + do { + name = template.replace("\{1\}", i === 1 ? "" : i); + i++; + } while (parent.hasChild(name)); + + return name; + } +}); +exports.NewFile = NewFile; +registerPlugin(NewFile); diff --git a/devtools/client/projecteditor/lib/plugins/rename/moz.build b/devtools/client/projecteditor/lib/plugins/rename/moz.build new file mode 100644 index 000000000..2b1612452 --- /dev/null +++ b/devtools/client/projecteditor/lib/plugins/rename/moz.build @@ -0,0 +1,9 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# 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/. + +DevToolsModules( + 'rename.js', +) diff --git a/devtools/client/projecteditor/lib/plugins/rename/rename.js b/devtools/client/projecteditor/lib/plugins/rename/rename.js new file mode 100644 index 000000000..850401869 --- /dev/null +++ b/devtools/client/projecteditor/lib/plugins/rename/rename.js @@ -0,0 +1,74 @@ +/* -*- 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 { Class } = require("sdk/core/heritage"); +const { registerPlugin, Plugin } = require("devtools/client/projecteditor/lib/plugins/core"); +const { getLocalizedString } = require("devtools/client/projecteditor/lib/helpers/l10n"); + +var RenamePlugin = Class({ + extends: Plugin, + + init: function (host) { + this.host.addCommand(this, { + id: "cmd-rename" + }); + this.contextMenuItem = this.host.createMenuItem({ + parent: this.host.contextMenuPopup, + label: getLocalizedString("projecteditor.renameLabel"), + command: "cmd-rename" + }); + }, + + onContextMenuOpen: function (resource) { + if (resource.isRoot) { + this.contextMenuItem.setAttribute("hidden", "true"); + } else { + this.contextMenuItem.removeAttribute("hidden"); + } + }, + + onCommand: function (cmd) { + if (cmd === "cmd-rename") { + let tree = this.host.projectTree; + let resource = tree.getSelectedResource(); + let parent = resource.parent; + let oldName = resource.basename; + + tree.promptEdit(oldName, resource).then(name => { + if (name === oldName) { + return resource; + } + if (parent.hasChild(name)) { + let matches = name.match(/([^\d.]*)(\d*)([^.]*)(.*)/); + let template = matches[1] + "{1}" + matches[3] + matches[4]; + name = this.suggestName(resource, template, parseInt(matches[2]) || 2); + } + return parent.rename(oldName, name); + }).then(resource => { + this.host.project.refresh(); + tree.selectResource(resource); + if (!resource.isDir) { + this.host.currentEditor.focus(); + } + }).then(null, console.error); + } + }, + + suggestName: function (resource, template, start = 1) { + let i = start; + let name; + let parent = resource.parent; + do { + name = template.replace("\{1\}", i === 1 ? "" : i); + i++; + } while (parent.hasChild(name)); + + return name; + } +}); + +exports.RenamePlugin = RenamePlugin; +registerPlugin(RenamePlugin); diff --git a/devtools/client/projecteditor/lib/plugins/save/moz.build b/devtools/client/projecteditor/lib/plugins/save/moz.build new file mode 100644 index 000000000..66df054eb --- /dev/null +++ b/devtools/client/projecteditor/lib/plugins/save/moz.build @@ -0,0 +1,9 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# 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/. + +DevToolsModules( + 'save.js', +) diff --git a/devtools/client/projecteditor/lib/plugins/save/save.js b/devtools/client/projecteditor/lib/plugins/save/save.js new file mode 100644 index 000000000..43b2185d2 --- /dev/null +++ b/devtools/client/projecteditor/lib/plugins/save/save.js @@ -0,0 +1,93 @@ +/* -*- 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 { Class } = require("sdk/core/heritage"); +const { registerPlugin, Plugin } = require("devtools/client/projecteditor/lib/plugins/core"); +const picker = require("devtools/client/projecteditor/lib/helpers/file-picker"); +const { getLocalizedString } = require("devtools/client/projecteditor/lib/helpers/l10n"); + +// Handles the save command. +var SavePlugin = Class({ + extends: Plugin, + + init: function (host) { + + this.host.addCommand(this, { + id: "cmd-save", + key: getLocalizedString("projecteditor.save.commandkey"), + modifiers: "accel" + }); + this.host.addCommand(this, { + id: "cmd-saveas", + key: getLocalizedString("projecteditor.save.commandkey"), + modifiers: "accel shift" + }); + this.host.createMenuItem({ + parent: this.host.fileMenuPopup, + label: getLocalizedString("projecteditor.saveLabel"), + command: "cmd-save", + key: "key_cmd-save" + }); + this.host.createMenuItem({ + parent: this.host.fileMenuPopup, + label: getLocalizedString("projecteditor.saveAsLabel"), + command: "cmd-saveas", + key: "key_cmd-saveas" + }); + }, + + isCommandEnabled: function (cmd) { + let currentEditor = this.host.currentEditor; + return currentEditor.isEditable; + }, + + onCommand: function (cmd) { + if (cmd === "cmd-save") { + this.onEditorSaveRequested(); + } else if (cmd === "cmd-saveas") { + this.saveAs(); + } + }, + + saveAs: function () { + let editor = this.host.currentEditor; + let project = this.host.resourceFor(editor); + + let resource; + picker.showSave({ + window: this.host.window, + directory: project && project.parent ? project.parent.path : null, + defaultName: project ? project.basename : null, + }).then(path => { + return this.createResource(path); + }).then(res => { + resource = res; + return this.saveResource(editor, resource); + }).then(() => { + this.host.openResource(resource); + }).then(null, console.error); + }, + + onEditorSaveRequested: function () { + let editor = this.host.currentEditor; + let resource = this.host.resourceFor(editor); + if (!resource) { + return this.saveAs(); + } + + return this.saveResource(editor, resource); + }, + + createResource: function (path) { + return this.host.project.resourceFor(path, { create: true }); + }, + + saveResource: function (editor, resource) { + return editor.save(resource); + } +}); +exports.SavePlugin = SavePlugin; +registerPlugin(SavePlugin); diff --git a/devtools/client/projecteditor/lib/plugins/status-bar/moz.build b/devtools/client/projecteditor/lib/plugins/status-bar/moz.build new file mode 100644 index 000000000..87ce21584 --- /dev/null +++ b/devtools/client/projecteditor/lib/plugins/status-bar/moz.build @@ -0,0 +1,9 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# 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/. + +DevToolsModules( + 'plugin.js', +) diff --git a/devtools/client/projecteditor/lib/plugins/status-bar/plugin.js b/devtools/client/projecteditor/lib/plugins/status-bar/plugin.js new file mode 100644 index 000000000..9450baef3 --- /dev/null +++ b/devtools/client/projecteditor/lib/plugins/status-bar/plugin.js @@ -0,0 +1,105 @@ +/* -*- 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 promise = require("promise"); +const { registerPlugin, Plugin } = require("devtools/client/projecteditor/lib/plugins/core"); + +/** + * Print information about the currently opened file + * and the state of the current editor + */ +var StatusBarPlugin = Class({ + extends: Plugin, + + init: function () { + this.box = this.host.createElement("hbox", { + parent: "#projecteditor-toolbar-bottom" + }); + + this.activeMode = this.host.createElement("label", { + parent: this.box, + class: "projecteditor-basic-display" + }); + + this.cursorPosition = this.host.createElement("label", { + parent: this.box, + class: "projecteditor-basic-display" + }); + + this.fileLabel = this.host.createElement("label", { + parent: "#plugin-toolbar-left", + class: "projecteditor-file-label" + }); + }, + + destroy: function () { + }, + + /** + * Print information about the current state of the editor + * + * @param Editor editor + */ + render: function (editor, resource) { + if (!resource || resource.isDir) { + this.fileLabel.textContent = ""; + this.cursorPosition.value = ""; + return; + } + + this.fileLabel.textContent = resource.basename; + this.activeMode.value = editor.toString(); + if (editor.editor) { + let cursorStart = editor.editor.getCursor("start"); + let cursorEnd = editor.editor.getCursor("end"); + if (cursorStart.line === cursorEnd.line && cursorStart.ch === cursorEnd.ch) { + this.cursorPosition.value = cursorStart.line + " " + cursorStart.ch; + } else { + this.cursorPosition.value = cursorStart.line + " " + cursorStart.ch + " | " + + cursorEnd.line + " " + cursorEnd.ch; + } + } else { + this.cursorPosition.value = ""; + } + }, + + + /** + * Print the current file name + * + * @param Resource resource + */ + onTreeSelected: function (resource) { + if (!resource || resource.isDir) { + this.fileLabel.textContent = ""; + return; + } + this.fileLabel.textContent = resource.basename; + }, + + onEditorDeactivated: function (editor) { + this.fileLabel.textContent = ""; + this.cursorPosition.value = ""; + }, + + onEditorChange: function (editor, resource) { + this.render(editor, resource); + }, + + onEditorCursorActivity: function (editor, resource) { + this.render(editor, resource); + }, + + onEditorActivated: function (editor, resource) { + this.render(editor, resource); + }, + +}); + +exports.StatusBarPlugin = StatusBarPlugin; +registerPlugin(StatusBarPlugin); |