From 285338d43e7404b8f95a509471cafe2951a96f94 Mon Sep 17 00:00:00 2001 From: Alexandre Poirot Date: Tue, 6 Sep 2022 18:37:10 +0000 Subject: [PATCH] Bug 1788032 - [devtools] Remove unused AbstractTreeItem.jsm. r=bomsy Differential Revision: https://phabricator.services.mozilla.com/D156180 --- .../shared/widgets/AbstractTreeItem.jsm | 668 ------------------ devtools/client/shared/widgets/moz.build | 1 - 2 files changed, 669 deletions(-) delete mode 100644 devtools/client/shared/widgets/AbstractTreeItem.jsm diff --git a/devtools/client/shared/widgets/AbstractTreeItem.jsm b/devtools/client/shared/widgets/AbstractTreeItem.jsm deleted file mode 100644 index e2554d393d30..000000000000 --- a/devtools/client/shared/widgets/AbstractTreeItem.jsm +++ /dev/null @@ -1,668 +0,0 @@ -/* 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/. */ -"use strict"; - -const { require, loader } = ChromeUtils.import( - "resource://devtools/shared/loader/Loader.jsm" -); -const { ViewHelpers } = require("devtools/client/shared/widgets/view-helpers"); -const { KeyCodes } = require("devtools/client/shared/keycodes"); - -const lazy = {}; - -loader.lazyRequireGetter(lazy, "EventEmitter", "devtools/shared/event-emitter"); - -const EXPORTED_SYMBOLS = ["AbstractTreeItem"]; - -/** - * A very generic and low-level tree view implementation. It is not intended - * to be used alone, but as a base class that you can extend to build your - * own custom implementation. - * - * Language: - * - An "item" is an instance of an AbstractTreeItem. - * - An "element" or "node" is a Node. - * - * The following events are emitted by this tree, always from the root item, - * with the first argument pointing to the affected child item: - * - "expand": when an item is expanded in the tree - * - "collapse": when an item is collapsed in the tree - * - "focus": when an item is selected in the tree - * - * For example, you can extend this abstract class like this: - * - * function MyCustomTreeItem(dataSrc, properties) { - * AbstractTreeItem.call(this, properties); - * this.itemDataSrc = dataSrc; - * } - * - * MyCustomTreeItem.prototype = extend(AbstractTreeItem.prototype, { - * _displaySelf: function(document, arrowNode) { - * let node = document.createXULElement("hbox"); - * ... - * // Append the provided arrow node wherever you want. - * node.appendChild(arrowNode); - * ... - * // Use `this.itemDataSrc` to customize the tree item and - * // `this.level` to calculate the indentation. - * node.style.marginInlineStart = (this.level * 10) + "px"; - * node.appendChild(document.createTextNode(this.itemDataSrc.label)); - * ... - * return node; - * }, - * _populateSelf: function(children) { - * ... - * // Use `this.itemDataSrc` to get the data source for the child items. - * let someChildDataSrc = this.itemDataSrc.children[0]; - * ... - * children.push(new MyCustomTreeItem(someChildDataSrc, { - * parent: this, - * level: this.level + 1 - * })); - * ... - * } - * }); - * - * And then you could use it like this: - * - * let dataSrc = { - * label: "root", - * children: [{ - * label: "foo", - * children: [] - * }, { - * label: "bar", - * children: [{ - * label: "baz", - * children: [] - * }] - * }] - * }; - * let root = new MyCustomTreeItem(dataSrc, { parent: null }); - * root.attachTo(Node); - * root.expand(); - * - * The following tree view will be generated (after expanding all nodes): - * ▼ root - * ▶ foo - * ▼ bar - * ▶ baz - * - * The way the data source is implemented is completely up to you. There's - * no assumptions made and you can use it however you like inside the - * `_displaySelf` and `populateSelf` methods. If you need to add children to a - * node at a later date, you just need to modify the data source: - * - * dataSrc[...path-to-foo...].children.push({ - * label: "lazily-added-node" - * children: [] - * }); - * - * The existing tree view will be modified like so (after expanding `foo`): - * ▼ root - * ▼ foo - * ▶ lazily-added-node - * ▼ bar - * ▶ baz - * - * Everything else is taken care of automagically! - * - * @param AbstractTreeItem parent - * The parent tree item. Should be null for root items. - * @param number level - * The indentation level in the tree. The root item is at level 0. - */ -function AbstractTreeItem({ parent, level }) { - this._rootItem = parent ? parent._rootItem : this; - this._parentItem = parent; - this._level = level || 0; - this._childTreeItems = []; - - // Events are always propagated through the root item. Decorating every - // tree item as an event emitter is a very costly operation. - if (this == this._rootItem) { - lazy.EventEmitter.decorate(this); - } -} - -AbstractTreeItem.prototype = { - _containerNode: null, - _targetNode: null, - _arrowNode: null, - _constructed: false, - _populated: false, - _expanded: false, - - /** - * Optionally, trees may be allowed to automatically expand a few levels deep - * to avoid initially displaying a completely collapsed tree. - */ - autoExpandDepth: 0, - - /** - * Creates the view for this tree item. Implement this method in the - * inheriting classes to create the child node displayed in the tree. - * Use `this.level` and the provided `arrowNode` as you see fit. - * - * @param Node document - * @param Node arrowNode - * @return Node - */ - _displaySelf(document, arrowNode) { - throw new Error( - "The `_displaySelf` method needs to be implemented by inheriting classes." - ); - }, - - /** - * Populates this tree item with child items, whenever it's expanded. - * Implement this method in the inheriting classes to fill the provided - * `children` array with AbstractTreeItem instances, which will then be - * magically handled by this tree item. - * - * @param array:AbstractTreeItem children - */ - _populateSelf(children) { - throw new Error( - "The `_populateSelf` method needs to be implemented by inheriting classes." - ); - }, - - /** - * Gets the this tree's owner document. - * @return Document - */ - get document() { - return this._containerNode.ownerDocument; - }, - - /** - * Gets the root item of this tree. - * @return AbstractTreeItem - */ - get root() { - return this._rootItem; - }, - - /** - * Gets the parent of this tree item. - * @return AbstractTreeItem - */ - get parent() { - return this._parentItem; - }, - - /** - * Gets the indentation level of this tree item. - */ - get level() { - return this._level; - }, - - /** - * Gets the element displaying this tree item. - */ - get target() { - return this._targetNode; - }, - - /** - * Gets the element containing all tree items. - * @return Node - */ - get container() { - return this._containerNode; - }, - - /** - * Returns whether or not this item is populated in the tree. - * Collapsed items can still be populated. - * @return boolean - */ - get populated() { - return this._populated; - }, - - /** - * Returns whether or not this item is expanded in the tree. - * Expanded items with no children aren't consudered `populated`. - * @return boolean - */ - get expanded() { - return this._expanded; - }, - - /** - * Gets the bounds for this tree's container without flushing. - * @return object - */ - get bounds() { - const win = this.document.defaultView; - const utils = win.windowUtils; - return utils.getBoundsWithoutFlushing(this._containerNode); - }, - - /** - * Creates and appends this tree item to the specified parent element. - * - * @param Node containerNode - * The parent element for this tree item (and every other tree item). - * @param Node fragmentNode [optional] - * An optional document fragment temporarily holding this tree item in - * the current batch. Defaults to the `containerNode`. - * @param Node beforeNode [optional] - * An optional child element which should succeed this tree item. - */ - attachTo(containerNode, fragmentNode = containerNode, beforeNode = null) { - this._containerNode = containerNode; - this._constructTargetNode(); - - if (beforeNode) { - fragmentNode.insertBefore(this._targetNode, beforeNode); - } else { - fragmentNode.appendChild(this._targetNode); - } - - if (this._level < this.autoExpandDepth) { - this.expand(); - } - }, - - /** - * Permanently removes this tree item (and all subsequent children) from the - * parent container. - */ - remove() { - this._targetNode.remove(); - this._hideChildren(); - this._childTreeItems.length = 0; - }, - - /** - * Focuses this item in the tree. - */ - focus() { - this._targetNode.focus(); - }, - - /** - * Expands this item in the tree. - */ - expand() { - if (this._expanded) { - return; - } - this._expanded = true; - this._arrowNode.setAttribute("open", ""); - this._targetNode.setAttribute("expanded", ""); - this._toggleChildren(true); - this._rootItem.emit("expand", this); - }, - - /** - * Collapses this item in the tree. - */ - collapse() { - if (!this._expanded) { - return; - } - this._expanded = false; - this._arrowNode.removeAttribute("open"); - this._targetNode.removeAttribute("expanded", ""); - this._toggleChildren(false); - this._rootItem.emit("collapse", this); - }, - - /** - * Returns the child item at the specified index. - * - * @param number index - * @return AbstractTreeItem - */ - getChild(index = 0) { - return this._childTreeItems[index]; - }, - - /** - * Calls the provided function on all the descendants of this item. - * If this item was never expanded, then no descendents exist yet. - * @param function cb - */ - traverse(cb) { - for (const child of this._childTreeItems) { - cb(child); - child.bfs(); - } - }, - - /** - * Calls the provided function on all descendants of this item until - * a truthy value is returned by the predicate. - * @param function predicate - * @return AbstractTreeItem - */ - find(predicate) { - for (const child of this._childTreeItems) { - if (predicate(child) || child.find(predicate)) { - return child; - } - } - return null; - }, - - /** - * Shows or hides all the children of this item in the tree. If neessary, - * populates this item with children. - * - * @param boolean visible - * True if the children should be visible, false otherwise. - */ - _toggleChildren(visible) { - if (visible) { - if (!this._populated) { - this._populateSelf(this._childTreeItems); - this._populated = !!this._childTreeItems.length; - } - this._showChildren(); - } else { - this._hideChildren(); - } - }, - - /** - * Shows all children of this item in the tree. - */ - _showChildren() { - // If this is the root item and we're not expanding any child nodes, - // it is safe to append everything at once. - if (this == this._rootItem && this.autoExpandDepth == 0) { - this._appendChildrenBatch(); - } else { - // Otherwise, append the child items and their descendants successively; - // if not, the tree will become garbled and nodes will intertwine, - // since all the tree items are sharing a single container node. - this._appendChildrenSuccessive(); - } - }, - - /** - * Hides all children of this item in the tree. - */ - _hideChildren() { - for (const item of this._childTreeItems) { - item._targetNode.remove(); - item._hideChildren(); - } - }, - - /** - * Appends all children in a single batch. - * This only works properly for root nodes when no child nodes will expand. - */ - _appendChildrenBatch() { - if (this._fragment === undefined) { - this._fragment = this.document.createDocumentFragment(); - } - - const childTreeItems = this._childTreeItems; - - for (let i = 0, len = childTreeItems.length; i < len; i++) { - childTreeItems[i].attachTo(this._containerNode, this._fragment); - } - - this._containerNode.appendChild(this._fragment); - }, - - /** - * Appends all children successively. - */ - _appendChildrenSuccessive() { - const childTreeItems = this._childTreeItems; - const expandedChildTreeItems = childTreeItems.filter(e => e._expanded); - const nextNode = this._getSiblingAtDelta(1); - - for (let i = 0, len = childTreeItems.length; i < len; i++) { - childTreeItems[i].attachTo(this._containerNode, undefined, nextNode); - } - for (let i = 0, len = expandedChildTreeItems.length; i < len; i++) { - expandedChildTreeItems[i]._showChildren(); - } - }, - - /** - * Constructs and stores the target node displaying this tree item. - */ - _constructTargetNode() { - if (this._constructed) { - return; - } - this._onArrowClick = this._onArrowClick.bind(this); - this._onClick = this._onClick.bind(this); - this._onDoubleClick = this._onDoubleClick.bind(this); - this._onKeyDown = this._onKeyDown.bind(this); - this._onFocus = this._onFocus.bind(this); - this._onBlur = this._onBlur.bind(this); - - const document = this.document; - - const arrowNode = (this._arrowNode = document.createXULElement("hbox")); - arrowNode.className = "arrow theme-twisty"; - arrowNode.addEventListener("mousedown", this._onArrowClick); - - const targetNode = (this._targetNode = this._displaySelf( - document, - arrowNode - )); - targetNode.style.MozUserFocus = "normal"; - - targetNode.addEventListener("mousedown", this._onClick); - targetNode.addEventListener("dblclick", this._onDoubleClick); - targetNode.addEventListener("keydown", this._onKeyDown); - targetNode.addEventListener("focus", this._onFocus); - targetNode.addEventListener("blur", this._onBlur); - - this._constructed = true; - }, - - /** - * Gets the element displaying an item in the tree at the specified offset - * relative to this item. - * - * @param number delta - * The offset from this item to the target item. - * @return Node - * The element displaying the target item at the specified offset. - */ - _getSiblingAtDelta(delta) { - const childNodes = this._containerNode.childNodes; - const indexOfSelf = Array.prototype.indexOf.call( - childNodes, - this._targetNode - ); - if (indexOfSelf + delta >= 0) { - return childNodes[indexOfSelf + delta]; - } - return undefined; - }, - - _getNodesPerPageSize() { - const childNodes = this._containerNode.childNodes; - const nodeHeight = this._getHeight(childNodes[childNodes.length - 1]); - const containerHeight = this.bounds.height; - return Math.ceil(containerHeight / nodeHeight); - }, - - _getHeight(elem) { - const win = this.document.defaultView; - const utils = win.windowUtils; - return utils.getBoundsWithoutFlushing(elem).height; - }, - - /** - * Focuses the first item in this tree. - */ - _focusFirstNode() { - const childNodes = this._containerNode.childNodes; - // The root node of the tree may be hidden in practice, so uses for-loop - // here to find the next visible node. - for (let i = 0; i < childNodes.length; i++) { - // The height will be 0 if an element is invisible. - if (this._getHeight(childNodes[i])) { - childNodes[i].focus(); - return; - } - } - }, - - /** - * Focuses the last item in this tree. - */ - _focusLastNode() { - const childNodes = this._containerNode.childNodes; - childNodes[childNodes.length - 1].focus(); - }, - - /** - * Focuses the next item in this tree. - */ - _focusNextNode() { - const nextElement = this._getSiblingAtDelta(1); - if (nextElement) { - nextElement.focus(); - } // Node - }, - - /** - * Focuses the previous item in this tree. - */ - _focusPrevNode() { - const prevElement = this._getSiblingAtDelta(-1); - if (prevElement) { - prevElement.focus(); - } // Node - }, - - /** - * Focuses the parent item in this tree. - * - * The parent item is not always the previous item, because any tree item - * may have multiple children. - */ - _focusParentNode() { - const parentItem = this._parentItem; - if (parentItem) { - parentItem.focus(); - } // AbstractTreeItem - }, - - /** - * Handler for the "click" event on the arrow node of this tree item. - */ - _onArrowClick(e) { - if (!this._expanded) { - this.expand(); - } else { - this.collapse(); - } - }, - - /** - * Handler for the "click" event on the element displaying this tree item. - */ - _onClick(e) { - e.stopPropagation(); - this.focus(); - }, - - /** - * Handler for the "dblclick" event on the element displaying this tree item. - */ - _onDoubleClick(e) { - // Ignore dblclick on the arrow as it has already recived and handled two - // click events. - if (!e.target.classList.contains("arrow")) { - this._onArrowClick(e); - } - this.focus(); - }, - - /** - * Handler for the "keydown" event on the element displaying this tree item. - */ - _onKeyDown(e) { - // Prevent scrolling when pressing navigation keys. - ViewHelpers.preventScrolling(e); - - switch (e.keyCode) { - case KeyCodes.DOM_VK_UP: - this._focusPrevNode(); - return; - - case KeyCodes.DOM_VK_DOWN: - this._focusNextNode(); - return; - - case KeyCodes.DOM_VK_LEFT: - if (this._expanded && this._populated) { - this.collapse(); - } else { - this._focusParentNode(); - } - return; - - case KeyCodes.DOM_VK_RIGHT: - if (!this._expanded) { - this.expand(); - } else { - this._focusNextNode(); - } - return; - - case KeyCodes.DOM_VK_PAGE_UP: - const pageUpElement = this._getSiblingAtDelta( - -this._getNodesPerPageSize() - ); - // There's a chance that the root node is hidden. In this case, its - // height will be 0. - if (pageUpElement && this._getHeight(pageUpElement)) { - pageUpElement.focus(); - } else { - this._focusFirstNode(); - } - return; - - case KeyCodes.DOM_VK_PAGE_DOWN: - const pageDownElement = this._getSiblingAtDelta( - this._getNodesPerPageSize() - ); - if (pageDownElement) { - pageDownElement.focus(); - } else { - this._focusLastNode(); - } - return; - - case KeyCodes.DOM_VK_HOME: - this._focusFirstNode(); - return; - - case KeyCodes.DOM_VK_END: - this._focusLastNode(); - } - }, - - /** - * Handler for the "focus" event on the element displaying this tree item. - */ - _onFocus(e) { - this._rootItem.emit("focus", this); - }, - - /** - * Handler for the "blur" event on the element displaying this tree item. - */ - _onBlur(e) { - this._rootItem.emit("blur", this); - }, -}; diff --git a/devtools/client/shared/widgets/moz.build b/devtools/client/shared/widgets/moz.build index a8c402a68cde..60b4049e0efd 100644 --- a/devtools/client/shared/widgets/moz.build +++ b/devtools/client/shared/widgets/moz.build @@ -9,7 +9,6 @@ DIRS += [ ] DevToolsModules( - "AbstractTreeItem.jsm", "Chart.js", "CubicBezierPresets.js", "CubicBezierWidget.js",