Bug 1022083 - Project Editor: Add context menu in sourceeditor. r=harth

This commit is contained in:
Brian Grinstead 2014-07-31 08:44:00 -04:00
parent 46c071d323
commit 609cdfc446
8 changed files with 118 additions and 10 deletions

View File

@ -53,6 +53,14 @@
<popupset>
<menupopup id="context-menu-popup">
</menupopup>
<menupopup id="texteditor-context-popup">
<menuitem id="cMenu_cut"/>
<menuitem id="cMenu_copy"/>
<menuitem id="cMenu_paste"/>
<menuitem id="cMenu_delete"/>
<menuseparator/>
<menuitem id="cMenu_selectAll"/>
</menupopup>
</popupset>
<deck id="main-deck" flex="1">

View File

@ -51,6 +51,7 @@ var ItchEditor = Class({
* ItchEditor.prototype.initialize.apply(this, arguments)
*/
initialize: function(host) {
this.host = host;
this.doc = host.document;
this.label = "";
this.elt = this.doc.createElement("vbox");
@ -165,7 +166,8 @@ var TextEditor = Class({
lineNumbers: true,
extraKeys: this.extraKeys,
themeSwitching: false,
autocomplete: true
autocomplete: true,
contextMenu: this.host.textEditorContextMenuPopup
});
// Trigger a few editor specific events on `this`.

View File

@ -175,6 +175,12 @@ var ProjectEditor = Class({
_buildMenubar: function() {
this.contextMenuPopup = this.document.getElementById("context-menu-popup");
this.contextMenuPopup.addEventListener("popupshowing", this._updateContextMenuItems);
this.textEditorContextMenuPopup = this.document.getElementById("texteditor-context-popup");
this.textEditorContextMenuPopup.addEventListener("popupshowing", this._updateMenuItems);
this.editMenu = this.document.getElementById("edit-menu");
this.fileMenu = this.document.getElementById("file-menu");
@ -191,6 +197,7 @@ var ProjectEditor = Class({
body.appendChild(this.editorCommandset);
body.appendChild(this.editorKeyset);
body.appendChild(this.contextMenuPopup);
body.appendChild(this.textEditorContextMenuPopup);
let index = this.menuindex || 0;
this.menubar.insertBefore(this.editMenu, this.menubar.children[index]);
@ -232,9 +239,6 @@ var ProjectEditor = Class({
this.editorCommandset = this.document.getElementById("editMenuCommands");
this.editorKeyset = this.document.getElementById("editMenuKeys");
this.contextMenuPopup = this.document.getElementById("context-menu-popup");
this.contextMenuPopup.addEventListener("popupshowing", this._updateContextMenuItems);
this.projectEditorCommandset.addEventListener("command", (evt) => {
evt.stopPropagation();
evt.preventDefault();
@ -313,6 +317,7 @@ var ProjectEditor = Class({
this.editorCommandset.remove();
this.editorKeyset.remove();
this.contextMenuPopup.remove();
this.textEditorContextMenuPopup.remove();
this.editMenu.remove();
this.fileMenu.remove();

View File

@ -7,6 +7,8 @@ support-files =
[browser_projecteditor_app_options.js]
skip-if = buildapp == 'mulet'
[browser_projecteditor_contextmenu_01.js]
[browser_projecteditor_contextmenu_02.js]
[browser_projecteditor_delete_file.js]
skip-if = buildapp == 'mulet'
[browser_projecteditor_editing_01.js]

View File

@ -0,0 +1,27 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
// Test that context menus append to the correct document.
let test = asyncTest(function*() {
let projecteditor = yield addProjectEditorTabForTempDirectory({
menubar: false
});
ok(projecteditor, "ProjectEditor has loaded");
let contextMenuPopup = projecteditor.document.querySelector("#context-menu-popup");
let textEditorContextMenuPopup = projecteditor.document.querySelector("#texteditor-context-popup");
ok (contextMenuPopup, "The menu has loaded in the projecteditor document");
ok (textEditorContextMenuPopup, "The menu has loaded in the projecteditor document");
let projecteditor2 = yield addProjectEditorTabForTempDirectory();
let contextMenuPopup = projecteditor2.document.getElementById("context-menu-popup");
let textEditorContextMenuPopup = projecteditor2.document.getElementById("texteditor-context-popup");
ok (!contextMenuPopup, "The menu has NOT loaded in the projecteditor document");
ok (!textEditorContextMenuPopup, "The menu has NOT loaded in the projecteditor document");
ok (content.document.querySelector("#context-menu-popup"), "The menu has loaded in the specified element");
ok (content.document.querySelector("#texteditor-context-popup"), "The menu has loaded in the specified element");
});

View File

@ -0,0 +1,62 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
loadHelperScript("helper_edits.js");
// Test context menu enabled / disabled state in editor
let test = asyncTest(function*() {
let projecteditor = yield addProjectEditorTabForTempDirectory();
ok (projecteditor, "ProjectEditor has loaded");
let {textEditorContextMenuPopup} = projecteditor;
let cmdDelete = textEditorContextMenuPopup.querySelector("[command=cmd_delete]");
let cmdSelectAll = textEditorContextMenuPopup.querySelector("[command=cmd_selectAll]");
let cmdCut = textEditorContextMenuPopup.querySelector("[command=cmd_cut]");
let cmdCopy = textEditorContextMenuPopup.querySelector("[command=cmd_copy]");
let cmdPaste = textEditorContextMenuPopup.querySelector("[command=cmd_paste]");
info ("Opening resource");
let resource = projecteditor.project.allResources()[2];
yield selectFile(projecteditor, resource);
let editor = projecteditor.currentEditor;
editor.editor.focus();
info ("Opening context menu on resource");
yield openContextMenuForEditor(editor, textEditorContextMenuPopup);
is (cmdDelete.getAttribute("disabled"), "true", "cmdDelete is disabled");
is (cmdSelectAll.getAttribute("disabled"), "", "cmdSelectAll is enabled");
is (cmdCut.getAttribute("disabled"), "true", "cmdCut is disabled");
is (cmdCopy.getAttribute("disabled"), "true", "cmdCopy is disabled");
is (cmdPaste.getAttribute("disabled"), "", "cmdPaste is enabled");
info ("Setting a selection and repening context menu on resource");
yield closeContextMenuForEditor(editor, textEditorContextMenuPopup);
editor.editor.setSelection({line: 0, ch: 0}, {line: 0, ch: 2});
yield openContextMenuForEditor(editor, textEditorContextMenuPopup);
is (cmdDelete.getAttribute("disabled"), "", "cmdDelete is enabled");
is (cmdSelectAll.getAttribute("disabled"), "", "cmdSelectAll is enabled");
is (cmdCut.getAttribute("disabled"), "", "cmdCut is enabled");
is (cmdCopy.getAttribute("disabled"), "", "cmdCopy is enabled");
is (cmdPaste.getAttribute("disabled"), "", "cmdPaste is enabled");
});
function openContextMenuForEditor(editor, contextMenu) {
let editorDoc = editor.editor.container.contentDocument;
let shown = onPopupShow(contextMenu);
EventUtils.synthesizeMouse(editorDoc.body, 2, 2,
{type: "contextmenu", button: 2}, editorDoc.defaultView);
yield shown;
}
function closeContextMenuForEditor(editor, contextMenu) {
let editorDoc = editor.editor.container.contentDocument;
let hidden = onPopupHidden(contextMenu);
contextMenu.hidePopup();
yield hidden;
}

View File

@ -82,7 +82,7 @@ let test = asyncTest(function*() {
let editor = projecteditor.currentEditor;
editor.editor.focus();
EventUtils.synthesizeKey("foo", { }, projecteditor.window);
EventUtils.synthesizeKey("f", { }, projecteditor.window);
yield openAndCloseMenu(fileMenu);
yield openAndCloseMenu(editMenu);
@ -99,10 +99,10 @@ let test = asyncTest(function*() {
});
function openAndCloseMenu(menu) {
let shown = onPopupShow(menu)
let shown = onPopupShow(menu);
EventUtils.synthesizeMouseAtCenter(menu, {}, menu.ownerDocument.defaultView);
yield shown;
let hidden = onPopupHidden(menu)
let hidden = onPopupHidden(menu);
EventUtils.synthesizeMouseAtCenter(menu, {}, menu.ownerDocument.defaultView);
yield hidden;
}

View File

@ -131,8 +131,8 @@ Editor.modes = {
* properties go to CodeMirror's documentation (see below).
*
* Other than that, it accepts one additional and optional
* property contextMenu. This property should be an ID of
* an element we can use as a context menu.
* property contextMenu. This property should be an element, or
* an ID of an element that we can use as a context menu.
*
* This object is also an event emitter.
*
@ -286,7 +286,9 @@ Editor.prototype = {
cm.getWrapperElement().addEventListener("contextmenu", (ev) => {
ev.preventDefault();
if (!this.config.contextMenu) return;
let popup = el.ownerDocument.getElementById(this.config.contextMenu);
let popup = this.config.contextMenu;
if (typeof popup == "string")
popup = el.ownerDocument.getElementById(this.config.contextMenu);
popup.openPopupAtScreen(ev.screenX, ev.screenY, true);
}, false);