123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133 |
- /* 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 component is used to build the menus for the HTML contextmenu attribute.
- Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
- const Cc = Components.classes;
- const Ci = Components.interfaces;
- // A global value that is used to identify each menu item. It is
- // incremented with each one that is found.
- var gGeneratedId = 1;
- function HTMLMenuBuilder() {
- this.currentNode = null;
- this.root = null;
- this.items = {};
- this.nestedStack = [];
- };
- // Building is done in two steps:
- // The first generates a hierarchical JS object that contains the menu structure.
- // This object is returned by toJSONString.
- //
- // The second step can take this structure and generate a XUL menu hierarchy or
- // other UI from this object. The default UI is done in PageMenu.jsm.
- //
- // When a multi-process browser is used, the first step is performed by the child
- // process and the second step is performed by the parent process.
- HTMLMenuBuilder.prototype =
- {
- classID: Components.ID("{51c65f5d-0de5-4edc-9058-60e50cef77f8}"),
- QueryInterface: XPCOMUtils.generateQI([Ci.nsIMenuBuilder]),
- currentNode: null,
- root: null,
- items: {},
- nestedStack: [],
- toJSONString: function() {
- return JSON.stringify(this.root);
- },
- openContainer: function(aLabel) {
- if (!this.currentNode) {
- this.root = {
- type: "menu",
- children: []
- };
- this.currentNode = this.root;
- }
- else {
- let parent = this.currentNode;
- this.currentNode = {
- type: "menu",
- label: aLabel,
- children: []
- };
- parent.children.push(this.currentNode);
- this.nestedStack.push(parent);
- }
- },
- addItemFor: function(aElement, aCanLoadIcon) {
- if (!("children" in this.currentNode)) {
- return;
- }
- let item = {
- type: "menuitem",
- label: aElement.label
- };
- let elementType = aElement.type;
- if (elementType == "checkbox" || elementType == "radio") {
- item.checkbox = true;
- if (aElement.checked) {
- item.checked = true;
- }
- }
- let icon = aElement.icon;
- if (icon.length > 0 && aCanLoadIcon) {
- item.icon = icon;
- }
- if (aElement.disabled) {
- item.disabled = true;
- }
- item.id = gGeneratedId++;
- this.currentNode.children.push(item);
- this.items[item.id] = aElement;
- },
- addSeparator: function() {
- if (!("children" in this.currentNode)) {
- return;
- }
- this.currentNode.children.push({ type: "separator"});
- },
- undoAddSeparator: function() {
- if (!("children" in this.currentNode)) {
- return;
- }
- let children = this.currentNode.children;
- if (children.length && children[children.length - 1].type == "separator") {
- children.pop();
- }
- },
- closeContainer: function() {
- this.currentNode = this.nestedStack.length ? this.nestedStack.pop() : this.root;
- },
- click: function(id) {
- let item = this.items[id];
- if (item) {
- item.click();
- }
- }
- };
- this.NSGetFactory = XPCOMUtils.generateNSGetFactory([HTMLMenuBuilder]);
|