diff options
Diffstat (limited to 'Source/WebInspectorUI/UserInterface/GeneralTreeElement.js')
-rw-r--r-- | Source/WebInspectorUI/UserInterface/GeneralTreeElement.js | 395 |
1 files changed, 395 insertions, 0 deletions
diff --git a/Source/WebInspectorUI/UserInterface/GeneralTreeElement.js b/Source/WebInspectorUI/UserInterface/GeneralTreeElement.js new file mode 100644 index 000000000..371891fd1 --- /dev/null +++ b/Source/WebInspectorUI/UserInterface/GeneralTreeElement.js @@ -0,0 +1,395 @@ +/* + * Copyright (C) 2013 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +WebInspector.GeneralTreeElement = function(classNames, title, subtitle, representedObject, hasChildren) +{ + TreeElement.call(this, "", representedObject, hasChildren); + + this.classNames = classNames; + + this._tooltipHandledSeparately = false; + this._mainTitle = title || ""; + this._subtitle = subtitle || ""; + this._status = ""; +} + +WebInspector.GeneralTreeElement.StyleClassName = "item"; +WebInspector.GeneralTreeElement.DisclosureButtonStyleClassName = "disclosure-button"; +WebInspector.GeneralTreeElement.IconElementStyleClassName = "icon"; +WebInspector.GeneralTreeElement.StatusElementStyleClassName = "status"; +WebInspector.GeneralTreeElement.TitlesElementStyleClassName = "titles"; +WebInspector.GeneralTreeElement.MainTitleElementStyleClassName = "title"; +WebInspector.GeneralTreeElement.SubtitleElementStyleClassName = "subtitle"; +WebInspector.GeneralTreeElement.NoSubtitleStyleClassName = "no-subtitle"; +WebInspector.GeneralTreeElement.SmallStyleClassName = "small"; +WebInspector.GeneralTreeElement.TwoLineStyleClassName = "two-line"; + +WebInspector.GeneralTreeElement.Event = { + MainTitleDidChange: "general-tree-element-main-title-did-change" +}; + +WebInspector.GeneralTreeElement.prototype = { + constructor: WebInspector.GeneralTreeElement, + + // Public + + get element() + { + return this._listItemNode; + }, + + get disclosureButton() + { + this._createElementsIfNeeded(); + return this._disclosureButton; + }, + + get iconElement() + { + this._createElementsIfNeeded(); + return this._iconElement; + }, + + get titlesElement() + { + this._createElementsIfNeeded(); + return this._titlesElement; + }, + + get mainTitleElement() + { + this._createElementsIfNeeded(); + return this._mainTitleElement; + }, + + get subtitleElement() + { + this._createElementsIfNeeded(); + this._createSubtitleElementIfNeeded(); + return this._subtitleElement; + }, + + get classNames() + { + return this._classNames; + }, + + set classNames(x) + { + if (this._listItemNode && this._classNames) { + for (var i = 0; i < this._classNames.length; ++i) + this._listItemNode.classList.remove(this._classNames[i]); + } + + if (typeof x === "string") + x = [x]; + + this._classNames = x || []; + + if (this._listItemNode) { + for (var i = 0; i < this._classNames.length; ++i) + this._listItemNode.classList.add(this._classNames[i]); + } + }, + + addClassName: function(className) + { + if (this._classNames.contains(className)) + return; + + this._classNames.push(className); + + if (this._listItemNode) + this._listItemNode.classList.add(className); + }, + + removeClassName: function(className) + { + if (!this._classNames.contains(className)) + return; + + this._classNames.remove(className); + + if (this._listItemNode) + this._listItemNode.classList.remove(className); + }, + + get small() + { + return this._small; + }, + + set small(x) + { + this._small = x; + + if (this._listItemNode) { + if (this._small) + this._listItemNode.classList.add(WebInspector.GeneralTreeElement.SmallStyleClassName); + else + this._listItemNode.classList.remove(WebInspector.GeneralTreeElement.SmallStyleClassName); + } + }, + + get twoLine() + { + return this._twoLine; + }, + + set twoLine(x) + { + this._twoLine = x; + + if (this._listItemNode) { + if (this._twoLine) + this._listItemNode.classList.add(WebInspector.GeneralTreeElement.TwoLineStyleClassName); + else + this._listItemNode.classList.remove(WebInspector.GeneralTreeElement.TwoLineStyleClassName); + } + }, + + get mainTitle() + { + return this._mainTitle; + }, + + set mainTitle(x) + { + this._mainTitle = x || ""; + this._updateTitleElements(); + this.didChange(); + this.dispatchEventToListeners(WebInspector.GeneralTreeElement.Event.MainTitleDidChange); + }, + + get subtitle() + { + return this._subtitle; + }, + + set subtitle(x) + { + this._subtitle = x || ""; + this._updateTitleElements(); + this.didChange(); + }, + + get status() + { + return this._status; + }, + + set status(x) + { + this._status = x || ""; + this._updateStatusElement(); + }, + + get filterableData() + { + return {text: [this.mainTitle, this.subtitle]}; + }, + + get tooltipHandledSeparately() + { + return this._tooltipHandledSeparately; + }, + + set tooltipHandledSeparately(x) + { + this._tooltipHandledSeparately = x || false; + }, + + // Overrides from TreeElement (Private) + + isEventWithinDisclosureTriangle: function(event) + { + return event.target === this._disclosureButton; + }, + + onattach: function() + { + this._createElementsIfNeeded(); + this._updateTitleElements(); + this._updateStatusElement(); + + this._listItemNode.classList.add(WebInspector.GeneralTreeElement.StyleClassName); + + if (this._classNames) { + for (var i = 0; i < this._classNames.length; ++i) + this._listItemNode.classList.add(this._classNames[i]); + } + + if (this._small) + this._listItemNode.classList.add(WebInspector.GeneralTreeElement.SmallStyleClassName); + + if (this._twoLine) + this._listItemNode.classList.add(WebInspector.GeneralTreeElement.TwoLineStyleClassName); + + this._listItemNode.appendChild(this._disclosureButton); + this._listItemNode.appendChild(this._iconElement); + this._listItemNode.appendChild(this._statusElement); + this._listItemNode.appendChild(this._titlesElement); + + if (this.oncontextmenu && typeof this.oncontextmenu === "function") { + this._boundContextMenuEventHandler = this.oncontextmenu.bind(this); + this._listItemNode.addEventListener("contextmenu", this._boundContextMenuEventHandler, true); + } + + if (!this._boundContextMenuEventHandler && this.treeOutline.oncontextmenu && typeof this.treeOutline.oncontextmenu === "function") { + this._boundContextMenuEventHandler = function(event) { this.treeOutline.oncontextmenu(event, this); }.bind(this); + this._listItemNode.addEventListener("contextmenu", this._boundContextMenuEventHandler, true); + } + }, + + ondetach: function() + { + if (this._boundContextMenuEventHandler) { + this._listItemNode.removeEventListener("contextmenu", this._boundContextMenuEventHandler, true); + delete this._boundContextMenuEventHandler; + } + }, + + onreveal: function() + { + if (this._listItemNode) + this._listItemNode.scrollIntoViewIfNeeded(false); + }, + + // Protected + + callFirstAncestorFunction: function(functionName, arguments) + { + // Call the first ancestor that implements a function named functionName (if any). + var currentNode = this.parent; + while (currentNode) { + if (typeof currentNode[functionName] === "function") { + currentNode[functionName].apply(currentNode, arguments); + break; + } + + currentNode = currentNode.parent; + } + }, + + // Private + + _createElementsIfNeeded: function() + { + if (this._createdElements) + return; + + this._disclosureButton = document.createElement("button"); + this._disclosureButton.className = WebInspector.GeneralTreeElement.DisclosureButtonStyleClassName; + + // Don't allow the disclosure button to be keyboard focusable. The TreeOutline is focusable and has + // its own keybindings for toggling expand and collapse. + this._disclosureButton.tabIndex = -1; + + this._iconElement = document.createElement("img"); + this._iconElement.className = WebInspector.GeneralTreeElement.IconElementStyleClassName; + + this._statusElement = document.createElement("div"); + this._statusElement.className = WebInspector.GeneralTreeElement.StatusElementStyleClassName; + + this._titlesElement = document.createElement("div"); + this._titlesElement.className = WebInspector.GeneralTreeElement.TitlesElementStyleClassName; + + this._mainTitleElement = document.createElement("span"); + this._mainTitleElement.className = WebInspector.GeneralTreeElement.MainTitleElementStyleClassName; + this._titlesElement.appendChild(this._mainTitleElement); + + this._createdElements = true; + }, + + _createSubtitleElementIfNeeded: function() + { + if (this._subtitleElement) + return; + + this._subtitleElement = document.createElement("span"); + this._subtitleElement.className = WebInspector.GeneralTreeElement.SubtitleElementStyleClassName; + this._titlesElement.appendChild(this._subtitleElement); + }, + + _updateTitleElements: function() + { + if (!this._createdElements) + return; + + if (typeof this._mainTitle === "string") { + if (this._mainTitleElement.textContent !== this._mainTitle) + this._mainTitleElement.textContent = this._mainTitle; + } else if (this._mainTitle instanceof Node) { + this._mainTitleElement.removeChildren(); + this._mainTitleElement.appendChild(this._mainTitle); + } + + if (typeof this._subtitle === "string" && this._subtitle) { + this._createSubtitleElementIfNeeded(); + if (this._subtitleElement.textContent !== this._subtitle) + this._subtitleElement.textContent = this._subtitle; + this._titlesElement.classList.remove(WebInspector.GeneralTreeElement.NoSubtitleStyleClassName); + } else if (this._subtitle instanceof Node) { + this._createSubtitleElementIfNeeded(); + this._subtitleElement.removeChildren(); + this._subtitleElement.appendChild(this._subtitle); + } else { + if (this._subtitleElement) + this._subtitleElement.textContent = ""; + this._titlesElement.classList.add(WebInspector.GeneralTreeElement.NoSubtitleStyleClassName); + } + + // Set a default tooltip if there isn't a custom one already assigned. + if (!this.tooltip && !this._tooltipHandledSeparately) { + console.assert(this._listItemNode); + + // Get the textContent for the elements since they can contain other nodes, + // and the tool tip only cares about the text. + var mainTitleText = this._mainTitleElement.textContent; + var subtitleText = this._subtitleElement ? this._subtitleElement.textContent : ""; + + if (mainTitleText && subtitleText) + this._listItemNode.title = mainTitleText + (this._small && !this._twoLine ? " \u2014 " : "\n") + subtitleText; + else if (mainTitleText) + this._listItemNode.title = mainTitleText; + else + this._listItemNode.title = subtitleText; + } + }, + + _updateStatusElement: function() + { + if (!this._createdElements) + return; + + if (this._status instanceof Node) { + this._statusElement.removeChildren(); + this._statusElement.appendChild(this._status); + } else + this._statusElement.textContent = this._status; + } +} + +WebInspector.GeneralTreeElement.prototype.__proto__ = TreeElement.prototype; |