зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1033855 - Do not show delete context menu item for project root. r=harth
This commit is contained in:
Родитель
c0cb00234a
Коммит
e14da131f5
|
@ -17,7 +17,7 @@ var DeletePlugin = Class({
|
|||
this.host.addCommand(this, {
|
||||
id: "cmd-delete"
|
||||
});
|
||||
this.host.createMenuItem({
|
||||
this.contextMenuItem = this.host.createMenuItem({
|
||||
parent: this.host.contextMenuPopup,
|
||||
label: getLocalizedString("projecteditor.deleteLabel"),
|
||||
command: "cmd-delete"
|
||||
|
@ -34,6 +34,19 @@ var DeletePlugin = Class({
|
|||
);
|
||||
},
|
||||
|
||||
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;
|
||||
|
|
|
@ -62,6 +62,7 @@ require("projecteditor/plugins/status-bar/plugin");
|
|||
* - "onEditorCursorActivity": When there is cursor activity in a text editor
|
||||
* - "onCommand": When a command happens
|
||||
* - "onEditorDestroyed": When editor is destroyed
|
||||
* - "onContextMenuOpen": When the context menu is opened on the project tree
|
||||
*
|
||||
* The events can be bound like so:
|
||||
* projecteditor.on("onEditorCreated", (editor) => { });
|
||||
|
@ -87,6 +88,7 @@ var ProjectEditor = Class({
|
|||
this._onEditorActivated = this._onEditorActivated.bind(this);
|
||||
this._onEditorDeactivated = this._onEditorDeactivated.bind(this);
|
||||
this._updateMenuItems = this._updateMenuItems.bind(this);
|
||||
this._updateContextMenuItems = this._updateContextMenuItems.bind(this);
|
||||
this.destroy = this.destroy.bind(this);
|
||||
this.menubar = options.menubar || null;
|
||||
this.menuindex = options.menuindex || null;
|
||||
|
@ -231,6 +233,7 @@ var ProjectEditor = Class({
|
|||
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();
|
||||
|
@ -269,6 +272,15 @@ var ProjectEditor = Class({
|
|||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Enable / disable necessary context menu items by passing an event
|
||||
* onto plugins.
|
||||
*/
|
||||
_updateContextMenuItems: function() {
|
||||
let resource = this.projectTree.getSelectedResource();
|
||||
this.pluginDispatch("onContextMenuOpen", resource);
|
||||
},
|
||||
|
||||
/**
|
||||
* Destroy all objects on the iframe unload event.
|
||||
*/
|
||||
|
|
|
@ -13,68 +13,73 @@ let test = asyncTest(function*() {
|
|||
let root = [...projecteditor.project.allStores()][0].root;
|
||||
is(root.path, TEMP_PATH, "The root store is set to the correct temp path.");
|
||||
for (let child of root.children) {
|
||||
yield deleteWithContextMenu(projecteditor.projectTree.getViewContainer(child));
|
||||
yield deleteWithContextMenu(projecteditor, projecteditor.projectTree.getViewContainer(child));
|
||||
}
|
||||
|
||||
function onPopupShow(contextMenu) {
|
||||
let defer = promise.defer();
|
||||
contextMenu.addEventListener("popupshown", function onpopupshown() {
|
||||
contextMenu.removeEventListener("popupshown", onpopupshown);
|
||||
defer.resolve();
|
||||
});
|
||||
return defer.promise;
|
||||
}
|
||||
yield testDeleteOnRoot(projecteditor, projecteditor.projectTree.getViewContainer(root));
|
||||
});
|
||||
|
||||
function openContextMenuOn(node) {
|
||||
EventUtils.synthesizeMouseAtCenter(
|
||||
node,
|
||||
{button: 2, type: "contextmenu"},
|
||||
node.ownerDocument.defaultView
|
||||
);
|
||||
}
|
||||
|
||||
function deleteWithContextMenu(container) {
|
||||
let defer = promise.defer();
|
||||
function openContextMenuOn(node) {
|
||||
EventUtils.synthesizeMouseAtCenter(
|
||||
node,
|
||||
{button: 2, type: "contextmenu"},
|
||||
node.ownerDocument.defaultView
|
||||
);
|
||||
}
|
||||
|
||||
let resource = container.resource;
|
||||
let popup = projecteditor.contextMenuPopup;
|
||||
info ("Going to attempt deletion for: " + resource.path)
|
||||
function testDeleteOnRoot(projecteditor, container) {
|
||||
let popup = projecteditor.contextMenuPopup;
|
||||
let oncePopupShown = onPopupShow(popup);
|
||||
openContextMenuOn(container.label);
|
||||
yield oncePopupShown;
|
||||
|
||||
onPopupShow(popup).then(function () {
|
||||
let deleteCommand = popup.querySelector("[command=cmd-delete]");
|
||||
ok (deleteCommand, "Delete command exists in popup");
|
||||
is (deleteCommand.getAttribute("hidden"), "", "Delete command is visible");
|
||||
is (deleteCommand.getAttribute("disabled"), "", "Delete command is enabled");
|
||||
let deleteCommand = popup.querySelector("[command=cmd-delete]");
|
||||
ok (deleteCommand, "Delete command exists in popup");
|
||||
is (deleteCommand.getAttribute("hidden"), "true", "Delete command is hidden");
|
||||
}
|
||||
|
||||
function onConfirmShown(aSubject) {
|
||||
info("confirm dialog observed as expected");
|
||||
Services.obs.removeObserver(onConfirmShown, "common-dialog-loaded");
|
||||
Services.obs.removeObserver(onConfirmShown, "tabmodal-dialog-loaded");
|
||||
function deleteWithContextMenu(projecteditor, container) {
|
||||
let defer = promise.defer();
|
||||
|
||||
projecteditor.project.on("refresh-complete", function refreshComplete() {
|
||||
projecteditor.project.off("refresh-complete", refreshComplete);
|
||||
OS.File.stat(resource.path).then(() => {
|
||||
ok (false, "The file was not deleted");
|
||||
defer.resolve();
|
||||
}, (ex) => {
|
||||
ok (ex instanceof OS.File.Error && ex.becauseNoSuchFile, "OS.File.stat promise was rejected because the file is gone");
|
||||
defer.resolve();
|
||||
});
|
||||
let popup = projecteditor.contextMenuPopup;
|
||||
let resource = container.resource;
|
||||
info ("Going to attempt deletion for: " + resource.path);
|
||||
|
||||
onPopupShow(popup).then(function () {
|
||||
let deleteCommand = popup.querySelector("[command=cmd-delete]");
|
||||
ok (deleteCommand, "Delete command exists in popup");
|
||||
is (deleteCommand.getAttribute("hidden"), "", "Delete command is visible");
|
||||
is (deleteCommand.getAttribute("disabled"), "", "Delete command is enabled");
|
||||
|
||||
function onConfirmShown(aSubject) {
|
||||
info("confirm dialog observed as expected");
|
||||
Services.obs.removeObserver(onConfirmShown, "common-dialog-loaded");
|
||||
Services.obs.removeObserver(onConfirmShown, "tabmodal-dialog-loaded");
|
||||
|
||||
projecteditor.project.on("refresh-complete", function refreshComplete() {
|
||||
projecteditor.project.off("refresh-complete", refreshComplete);
|
||||
OS.File.stat(resource.path).then(() => {
|
||||
ok (false, "The file was not deleted");
|
||||
defer.resolve();
|
||||
}, (ex) => {
|
||||
ok (ex instanceof OS.File.Error && ex.becauseNoSuchFile, "OS.File.stat promise was rejected because the file is gone");
|
||||
defer.resolve();
|
||||
});
|
||||
});
|
||||
|
||||
// Click the 'OK' button
|
||||
aSubject.Dialog.ui.button0.click();
|
||||
}
|
||||
// Click the 'OK' button
|
||||
aSubject.Dialog.ui.button0.click();
|
||||
}
|
||||
|
||||
Services.obs.addObserver(onConfirmShown, "common-dialog-loaded", false);
|
||||
Services.obs.addObserver(onConfirmShown, "tabmodal-dialog-loaded", false);
|
||||
Services.obs.addObserver(onConfirmShown, "common-dialog-loaded", false);
|
||||
Services.obs.addObserver(onConfirmShown, "tabmodal-dialog-loaded", false);
|
||||
|
||||
deleteCommand.click();
|
||||
popup.hidePopup();
|
||||
});
|
||||
deleteCommand.click();
|
||||
popup.hidePopup();
|
||||
});
|
||||
|
||||
openContextMenuOn(container.label);
|
||||
openContextMenuOn(container.label);
|
||||
|
||||
return defer.promise;
|
||||
}
|
||||
});
|
||||
return defer.promise;
|
||||
}
|
||||
|
|
|
@ -106,21 +106,3 @@ function openAndCloseMenu(menu) {
|
|||
EventUtils.synthesizeMouseAtCenter(menu, {}, menu.ownerDocument.defaultView);
|
||||
yield hidden;
|
||||
}
|
||||
|
||||
function onPopupShow(menu) {
|
||||
let defer = promise.defer();
|
||||
menu.addEventListener("popupshown", function onpopupshown() {
|
||||
menu.removeEventListener("popupshown", onpopupshown);
|
||||
defer.resolve();
|
||||
});
|
||||
return defer.promise;
|
||||
}
|
||||
|
||||
function onPopupHidden(menu) {
|
||||
let defer = promise.defer();
|
||||
menu.addEventListener("popuphidden", function onpopupshown() {
|
||||
menu.removeEventListener("popuphidden", onpopupshown);
|
||||
defer.resolve();
|
||||
});
|
||||
return defer.promise;
|
||||
}
|
||||
|
|
|
@ -303,3 +303,22 @@ function onceEditorSave(projecteditor) {
|
|||
});
|
||||
return def.promise;
|
||||
}
|
||||
|
||||
function onPopupShow(menu) {
|
||||
let defer = promise.defer();
|
||||
menu.addEventListener("popupshown", function onpopupshown() {
|
||||
menu.removeEventListener("popupshown", onpopupshown);
|
||||
defer.resolve();
|
||||
});
|
||||
return defer.promise;
|
||||
}
|
||||
|
||||
function onPopupHidden(menu) {
|
||||
let defer = promise.defer();
|
||||
menu.addEventListener("popuphidden", function onpopuphidden() {
|
||||
menu.removeEventListener("popuphidden", onpopuphidden);
|
||||
defer.resolve();
|
||||
});
|
||||
return defer.promise;
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче