<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[203114] trunk/Source/WebInspectorUI</title>
</head>
<body>
<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; }
#msg dl a { font-weight: bold}
#msg dl a:link { color:#fc3; }
#msg dl a:active { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/203114">203114</a></dd>
<dt>Author</dt> <dd>commit-queue@webkit.org</dd>
<dt>Date</dt> <dd>2016-07-12 06:05:13 -0700 (Tue, 12 Jul 2016)</dd>
</dl>
<h3>Log Message</h3>
<pre>Web Inspector: Use separate files for TreeOutline/TreeElement and DataGrid/DataGridNode
https://bugs.webkit.org/show_bug.cgi?id=159659
Patch by Joseph Pecoraro <pecoraro@apple.com> on 2016-07-12
Reviewed by Timothy Hatcher.
* UserInterface/Main.html:
* UserInterface/Views/DataGrid.js:
* UserInterface/Views/DataGridNode.js: Added.
* UserInterface/Views/TreeElement.js: Added.
* UserInterface/Views/TreeOutline.js:
Extra the component classes to their own file.</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebInspectorUIChangeLog">trunk/Source/WebInspectorUI/ChangeLog</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceMainhtml">trunk/Source/WebInspectorUI/UserInterface/Main.html</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsDataGridjs">trunk/Source/WebInspectorUI/UserInterface/Views/DataGrid.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsTreeOutlinejs">trunk/Source/WebInspectorUI/UserInterface/Views/TreeOutline.js</a></li>
</ul>
<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsDataGridNodejs">trunk/Source/WebInspectorUI/UserInterface/Views/DataGridNode.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsTreeElementjs">trunk/Source/WebInspectorUI/UserInterface/Views/TreeElement.js</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebInspectorUIChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/ChangeLog (203113 => 203114)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/ChangeLog        2016-07-12 13:04:38 UTC (rev 203113)
+++ trunk/Source/WebInspectorUI/ChangeLog        2016-07-12 13:05:13 UTC (rev 203114)
</span><span class="lines">@@ -1,3 +1,17 @@
</span><ins>+2016-07-12 Joseph Pecoraro <pecoraro@apple.com>
+
+ Web Inspector: Use separate files for TreeOutline/TreeElement and DataGrid/DataGridNode
+ https://bugs.webkit.org/show_bug.cgi?id=159659
+
+ Reviewed by Timothy Hatcher.
+
+ * UserInterface/Main.html:
+ * UserInterface/Views/DataGrid.js:
+ * UserInterface/Views/DataGridNode.js: Added.
+ * UserInterface/Views/TreeElement.js: Added.
+ * UserInterface/Views/TreeOutline.js:
+ Extra the component classes to their own file.
+
</ins><span class="cx"> 2016-07-11 Joseph Pecoraro <pecoraro@apple.com>
</span><span class="cx">
</span><span class="cx"> Web Inspector: ProfileView sometimes shows Top Functions data despite Top Functions being disabled
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceMainhtml"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Main.html (203113 => 203114)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Main.html        2016-07-12 13:04:38 UTC (rev 203113)
+++ trunk/Source/WebInspectorUI/UserInterface/Main.html        2016-07-12 13:05:13 UTC (rev 203114)
</span><span class="lines">@@ -386,13 +386,14 @@
</span><span class="cx"> <script src="Proxies/HeapSnapshotWorkerProxy.js"></script>
</span><span class="cx">
</span><span class="cx"> <script src="Views/View.js"></script>
</span><del>- <script src="Views/Dialog.js"></script>
</del><span class="cx">
</span><span class="cx"> <script src="Views/ConsoleCommandView.js"></script>
</span><span class="cx"> <script src="Views/ConsoleMessageView.js"></script>
</span><span class="cx"> <script src="Views/ContentView.js"></script>
</span><span class="cx"> <script src="Views/DataGrid.js"></script>
</span><ins>+ <script src="Views/DataGridNode.js"></script>
</ins><span class="cx"> <script src="Views/DetailsSectionRow.js"></script>
</span><ins>+ <script src="Views/Dialog.js"></script>
</ins><span class="cx"> <script src="Views/HierarchicalPathComponent.js"></script>
</span><span class="cx"> <script src="Views/NavigationItem.js"></script>
</span><span class="cx"> <script src="Views/SidebarPanel.js"></script>
</span><span class="lines">@@ -403,6 +404,7 @@
</span><span class="cx"> <script src="Views/TextEditor.js"></script>
</span><span class="cx"> <script src="Views/TimelineOverviewGraph.js"></script>
</span><span class="cx"> <script src="Views/TimelineView.js"></script>
</span><ins>+ <script src="Views/TreeElement.js"></script>
</ins><span class="cx"> <script src="Views/TreeOutline.js"></script>
</span><span class="cx">
</span><span class="cx"> <script src="Views/ButtonNavigationItem.js"></script>
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsDataGridjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/DataGrid.js (203113 => 203114)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/DataGrid.js        2016-07-12 13:04:38 UTC (rev 203113)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/DataGrid.js        2016-07-12 13:05:13 UTC (rev 203114)
</span><span class="lines">@@ -1,26 +1,26 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2008, 2013-2015 Apple Inc. All Rights Reserved.
</del><ins>+ * Copyright (C) 2008, 2013-2016 Apple Inc. All Rights Reserved.
</ins><span class="cx"> *
</span><span class="cx"> * Redistribution and use in source and binary forms, with or without
</span><span class="cx"> * modification, are permitted provided that the following conditions
</span><span class="cx"> * are met:
</span><span class="cx"> * 1. Redistributions of source code must retain the above copyright
</span><del>- * notice, this list of conditions and the following disclaimer.
</del><ins>+ * notice, this list of conditions and the following disclaimer.
</ins><span class="cx"> * 2. Redistributions in binary form must reproduce the above copyright
</span><del>- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
</del><ins>+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
</ins><span class="cx"> *
</span><del>- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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
- * 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.
</del><ins>+ * 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.
</ins><span class="cx"> */
</span><span class="cx">
</span><span class="cx"> WebInspector.DataGrid = class DataGrid extends WebInspector.View
</span><span class="lines">@@ -962,7 +962,7 @@
</span><span class="cx"> resizer = this.resizers[i] = new WebInspector.Resizer(WebInspector.Resizer.RuleOrientation.Vertical, this);
</span><span class="cx"> this.element.appendChild(resizer.element);
</span><span class="cx"> }
</span><del>-
</del><ins>+
</ins><span class="cx"> left = columnWidths[i];
</span><span class="cx">
</span><span class="cx"> if (this._isColumnVisible(this.orderedColumns[i])) {
</span><span class="lines">@@ -1916,729 +1916,3 @@
</span><span class="cx"> WebInspector.DataGrid.SortColumnAscendingStyleClassName = "sort-ascending";
</span><span class="cx"> WebInspector.DataGrid.SortColumnDescendingStyleClassName = "sort-descending";
</span><span class="cx"> WebInspector.DataGrid.SortableColumnStyleClassName = "sortable";
</span><del>-
-WebInspector.DataGridNode = class DataGridNode extends WebInspector.Object
-{
- constructor(data, hasChildren)
- {
- super();
-
- this._expanded = false;
- this._hidden = false;
- this._selected = false;
- this._copyable = true;
- this._shouldRefreshChildren = true;
- this._data = data || {};
- this.hasChildren = hasChildren || false;
- this.children = [];
- this.dataGrid = null;
- this.parent = null;
- this.previousSibling = null;
- this.nextSibling = null;
- this.disclosureToggleWidth = 10;
- }
-
- get hidden()
- {
- return this._hidden;
- }
-
- set hidden(x)
- {
- x = !!x;
-
- if (this._hidden === x)
- return;
-
- this._hidden = x;
- if (this._element)
- this._element.classList.toggle("hidden", this._hidden);
-
- if (this.dataGrid)
- this.dataGrid._noteRowsChanged();
- }
-
- get selectable()
- {
- return this._element && !this._hidden;
- }
-
- get copyable()
- {
- return this._copyable;
- }
-
- set copyable(x)
- {
- this._copyable = x;
- }
-
- get element()
- {
- if (this._element)
- return this._element;
-
- if (!this.dataGrid)
- return null;
-
- this._element = document.createElement("tr");
- this._element._dataGridNode = this;
-
- if (this.hasChildren)
- this._element.classList.add("parent");
- if (this.expanded)
- this._element.classList.add("expanded");
- if (this.selected)
- this._element.classList.add("selected");
- if (this.revealed)
- this._element.classList.add("revealed");
- if (this._hidden)
- this._element.classList.add("hidden");
-
- this.createCells();
- return this._element;
- }
-
- createCells()
- {
- for (var columnIdentifier of this.dataGrid.orderedColumns)
- this._element.appendChild(this.createCell(columnIdentifier));
- }
-
- refreshIfNeeded()
- {
- if (!this._needsRefresh)
- return;
-
- this._needsRefresh = false;
-
- this.refresh();
- }
-
- needsRefresh()
- {
- this._needsRefresh = true;
-
- if (!this._revealed)
- return;
-
- if (this._scheduledRefreshIdentifier)
- return;
-
- this._scheduledRefreshIdentifier = requestAnimationFrame(this.refresh.bind(this));
- }
-
- get data()
- {
- return this._data;
- }
-
- set data(x)
- {
- console.assert(typeof x === "object", "Data should be an object.");
-
- x = x || {};
-
- if (Object.shallowEqual(this._data, x))
- return;
-
- this._data = x;
- this.needsRefresh();
- }
-
- get filterableData()
- {
- if (this._cachedFilterableData)
- return this._cachedFilterableData;
-
- this._cachedFilterableData = [];
-
- for (let column of this.dataGrid.columns.values()) {
- if (column.hidden)
- continue;
-
- let value = this.filterableDataForColumn(column.columnIdentifier);
- if (!value)
- continue;
-
- if (!(value instanceof Array))
- value = [value];
-
- if (!value.length)
- continue;
-
- this._cachedFilterableData = this._cachedFilterableData.concat(value);
- }
-
- return this._cachedFilterableData;
- }
-
- get revealed()
- {
- if ("_revealed" in this)
- return this._revealed;
-
- var currentAncestor = this.parent;
- while (currentAncestor && !currentAncestor.root) {
- if (!currentAncestor.expanded) {
- this._revealed = false;
- return false;
- }
-
- currentAncestor = currentAncestor.parent;
- }
-
- this._revealed = true;
- return true;
- }
-
- set hasChildren(x)
- {
- if (this._hasChildren === x)
- return;
-
- this._hasChildren = x;
-
- if (!this._element)
- return;
-
- if (this._hasChildren) {
- this._element.classList.add("parent");
- if (this.expanded)
- this._element.classList.add("expanded");
- } else
- this._element.classList.remove("parent", "expanded");
- }
-
- get hasChildren()
- {
- return this._hasChildren;
- }
-
- set revealed(x)
- {
- if (this._revealed === x)
- return;
-
- this._revealed = x;
-
- if (this._element) {
- if (this._revealed)
- this._element.classList.add("revealed");
- else
- this._element.classList.remove("revealed");
- }
-
- this.refreshIfNeeded();
-
- for (var i = 0; i < this.children.length; ++i)
- this.children[i].revealed = x && this.expanded;
- }
-
- get depth()
- {
- if ("_depth" in this)
- return this._depth;
- if (this.parent && !this.parent.root)
- this._depth = this.parent.depth + 1;
- else
- this._depth = 0;
- return this._depth;
- }
-
- get leftPadding()
- {
- if (typeof(this._leftPadding) === "number")
- return this._leftPadding;
-
- this._leftPadding = this.depth * this.dataGrid.indentWidth;
- return this._leftPadding;
- }
-
- get shouldRefreshChildren()
- {
- return this._shouldRefreshChildren;
- }
-
- set shouldRefreshChildren(x)
- {
- this._shouldRefreshChildren = x;
- if (x && this.expanded)
- this.expand();
- }
-
- get selected()
- {
- return this._selected;
- }
-
- set selected(x)
- {
- if (x)
- this.select();
- else
- this.deselect();
- }
-
- get expanded()
- {
- return this._expanded;
- }
-
- set expanded(x)
- {
- if (x)
- this.expand();
- else
- this.collapse();
- }
-
- hasAncestor(ancestor)
- {
- if (!ancestor)
- return false;
-
- let currentAncestor = this.parent;
- while (currentAncestor) {
- if (ancestor === currentAncestor)
- return true;
-
- currentAncestor = currentAncestor.parent;
- }
-
- return false;
- }
-
- refresh()
- {
- if (!this._element || !this.dataGrid)
- return;
-
- if (this._scheduledRefreshIdentifier) {
- cancelAnimationFrame(this._scheduledRefreshIdentifier);
- this._scheduledRefreshIdentifier = undefined;
- }
-
- this._cachedFilterableData = null;
- this._needsRefresh = false;
-
- this._element.removeChildren();
- this.createCells();
- }
-
- refreshRecursively()
- {
- this.refresh();
- this.forEachChildInSubtree((node) => node.refresh());
- }
-
- updateLayout()
- {
- // Implemented by subclasses if needed.
- }
-
- createCell(columnIdentifier)
- {
- var cellElement = document.createElement("td");
- cellElement.className = columnIdentifier + "-column";
- cellElement.__columnIdentifier = columnIdentifier;
-
- var column = this.dataGrid.columns.get(columnIdentifier);
-
- if (column["aligned"])
- cellElement.classList.add(column["aligned"]);
-
- if (column["group"])
- cellElement.classList.add("column-group-" + column["group"]);
-
- var div = cellElement.createChild("div", "cell-content");
- var content = this.createCellContent(columnIdentifier, cellElement);
- div.append(content);
-
- if (column["icon"]) {
- let iconElement = document.createElement("div");
- iconElement.classList.add("icon");
- div.insertBefore(iconElement, div.firstChild);
- }
-
- if (columnIdentifier === this.dataGrid.disclosureColumnIdentifier) {
- cellElement.classList.add("disclosure");
- if (this.leftPadding)
- cellElement.style.setProperty("padding-left", this.leftPadding + "px");
- }
-
- return cellElement;
- }
-
- createCellContent(columnIdentifier)
- {
- return this.data[columnIdentifier] || "\u200b"; // Zero width space to keep the cell from collapsing.
- }
-
- elementWithColumnIdentifier(columnIdentifier)
- {
- if (!this.dataGrid)
- return null;
-
- let index = this.dataGrid.orderedColumns.indexOf(columnIdentifier);
- if (index === -1)
- return null;
-
- return this.element.children[index];
- }
-
- // Share these functions with DataGrid. They are written to work with a DataGridNode this object.
- appendChild() { return WebInspector.DataGrid.prototype.appendChild.apply(this, arguments); }
- insertChild() { return WebInspector.DataGrid.prototype.insertChild.apply(this, arguments); }
- removeChild() { return WebInspector.DataGrid.prototype.removeChild.apply(this, arguments); }
- removeChildren() { return WebInspector.DataGrid.prototype.removeChildren.apply(this, arguments); }
- removeChildrenRecursive() { return WebInspector.DataGrid.prototype.removeChildrenRecursive.apply(this, arguments); }
-
- _recalculateSiblings(myIndex)
- {
- if (!this.parent)
- return;
-
- var previousChild = (myIndex > 0 ? this.parent.children[myIndex - 1] : null);
-
- if (previousChild) {
- previousChild.nextSibling = this;
- this.previousSibling = previousChild;
- } else
- this.previousSibling = null;
-
- var nextChild = this.parent.children[myIndex + 1];
-
- if (nextChild) {
- nextChild.previousSibling = this;
- this.nextSibling = nextChild;
- } else
- this.nextSibling = null;
- }
-
- collapse()
- {
- if (this._element)
- this._element.classList.remove("expanded");
-
- this._expanded = false;
-
- for (var i = 0; i < this.children.length; ++i)
- this.children[i].revealed = false;
-
- this.dispatchEventToListeners("collapsed");
-
- if (this.dataGrid) {
- this.dataGrid.dispatchEventToListeners(WebInspector.DataGrid.Event.CollapsedNode, {dataGridNode: this});
- this.dataGrid._noteRowsChanged();
- }
- }
-
- collapseRecursively()
- {
- var item = this;
- while (item) {
- if (item.expanded)
- item.collapse();
- item = item.traverseNextNode(false, this, true);
- }
- }
-
- expand()
- {
- if (!this.hasChildren || this.expanded)
- return;
-
- if (this.revealed && !this._shouldRefreshChildren)
- for (var i = 0; i < this.children.length; ++i)
- this.children[i].revealed = true;
-
- if (this._shouldRefreshChildren) {
- for (var i = 0; i < this.children.length; ++i)
- this.children[i]._detach();
-
- this.dispatchEventToListeners("populate");
-
- if (this._attached) {
- for (var i = 0; i < this.children.length; ++i) {
- var child = this.children[i];
- if (this.revealed)
- child.revealed = true;
- child._attach();
- }
- }
-
- this._shouldRefreshChildren = false;
- }
-
- if (this._element)
- this._element.classList.add("expanded");
-
- this._expanded = true;
-
- this.dispatchEventToListeners("expanded");
-
- if (this.dataGrid) {
- this.dataGrid.dispatchEventToListeners(WebInspector.DataGrid.Event.ExpandedNode, {dataGridNode: this});
- this.dataGrid._noteRowsChanged();
- }
- }
-
- expandRecursively()
- {
- var item = this;
- while (item) {
- item.expand();
- item = item.traverseNextNode(false, this);
- }
- }
-
- forEachImmediateChild(callback)
- {
- for (let node of this.children)
- callback(node);
- }
-
- forEachChildInSubtree(callback)
- {
- let node = this.traverseNextNode(false, this, true);
- while (node) {
- callback(node);
- node = node.traverseNextNode(false, this, true);
- }
- }
-
- isInSubtreeOfNode(baseNode)
- {
- let node = baseNode;
- while (node) {
- if (node === this)
- return true;
- node = node.traverseNextNode(false, baseNode, true);
- }
- return false;
- }
-
- reveal()
- {
- var currentAncestor = this.parent;
- while (currentAncestor && !currentAncestor.root) {
- if (!currentAncestor.expanded)
- currentAncestor.expand();
- currentAncestor = currentAncestor.parent;
- }
-
- this.element.scrollIntoViewIfNeeded(false);
-
- this.dispatchEventToListeners("revealed");
- }
-
- select(suppressSelectedEvent)
- {
- if (!this.dataGrid || !this.selectable || this.selected)
- return;
-
- let oldSelectedNode = this.dataGrid.selectedNode;
- if (oldSelectedNode)
- oldSelectedNode.deselect(true);
-
- this._selected = true;
- this.dataGrid.selectedNode = this;
-
- if (this._element)
- this._element.classList.add("selected");
-
- if (!suppressSelectedEvent)
- this.dataGrid.dispatchEventToListeners(WebInspector.DataGrid.Event.SelectedNodeChanged, {oldSelectedNode});
- }
-
- revealAndSelect()
- {
- this.reveal();
- this.select();
- }
-
- deselect(suppressDeselectedEvent)
- {
- if (!this.dataGrid || this.dataGrid.selectedNode !== this || !this.selected)
- return;
-
- this._selected = false;
- this.dataGrid.selectedNode = null;
-
- if (this._element)
- this._element.classList.remove("selected");
-
- if (!suppressDeselectedEvent)
- this.dataGrid.dispatchEventToListeners(WebInspector.DataGrid.Event.SelectedNodeChanged, {oldSelectedNode: this});
- }
-
- traverseNextNode(skipHidden, stayWithin, dontPopulate, info)
- {
- if (!dontPopulate && this.hasChildren)
- this.dispatchEventToListeners("populate");
-
- if (info)
- info.depthChange = 0;
-
- var node = (!skipHidden || this.revealed) ? this.children[0] : null;
- if (node && (!skipHidden || this.expanded)) {
- if (info)
- info.depthChange = 1;
- return node;
- }
-
- if (this === stayWithin)
- return null;
-
- node = (!skipHidden || this.revealed) ? this.nextSibling : null;
- if (node)
- return node;
-
- node = this;
- while (node && !node.root && !((!skipHidden || node.revealed) ? node.nextSibling : null) && node.parent !== stayWithin) {
- if (info)
- info.depthChange -= 1;
- node = node.parent;
- }
-
- if (!node)
- return null;
-
- return (!skipHidden || node.revealed) ? node.nextSibling : null;
- }
-
- traversePreviousNode(skipHidden, dontPopulate)
- {
- var node = (!skipHidden || this.revealed) ? this.previousSibling : null;
- if (!dontPopulate && node && node.hasChildren)
- node.dispatchEventToListeners("populate");
-
- while (node && ((!skipHidden || (node.revealed && node.expanded)) ? node.children.lastValue : null)) {
- if (!dontPopulate && node.hasChildren)
- node.dispatchEventToListeners("populate");
- node = ((!skipHidden || (node.revealed && node.expanded)) ? node.children.lastValue : null);
- }
-
- if (node)
- return node;
-
- if (!this.parent || this.parent.root)
- return null;
-
- return this.parent;
- }
-
- isEventWithinDisclosureTriangle(event)
- {
- if (!this.hasChildren)
- return false;
- let cell = event.target.enclosingNodeOrSelfWithNodeName("td");
- if (!cell || !cell.classList.contains("disclosure"))
- return false;
-
- let computedLeftPadding = window.getComputedStyle(cell).getPropertyCSSValue("padding-left").getFloatValue(CSSPrimitiveValue.CSS_PX);
- let left = cell.totalOffsetLeft + computedLeftPadding;
- return event.pageX >= left && event.pageX <= left + this.disclosureToggleWidth;
- }
-
- _attach()
- {
- if (!this.dataGrid || this._attached)
- return;
-
- this._attached = true;
-
- let insertionIndex = -1;
-
- if (!this.isPlaceholderNode) {
- var previousGridNode = this.traversePreviousNode(true, true);
- insertionIndex = this.dataGrid._rows.indexOf(previousGridNode);
- if (insertionIndex === -1)
- insertionIndex = 0;
- else
- insertionIndex++;
- }
-
- if (insertionIndex === -1)
- this.dataGrid._rows.push(this);
- else
- this.dataGrid._rows.insertAtIndex(this, insertionIndex);
-
- this.dataGrid._noteRowsChanged();
-
- if (this.expanded) {
- for (var i = 0; i < this.children.length; ++i)
- this.children[i]._attach();
- }
- }
-
- _detach()
- {
- if (!this._attached)
- return;
-
- this._attached = false;
-
- this.dataGrid._rows.remove(this, true);
- this.dataGrid._noteRowRemoved(this);
-
- for (var i = 0; i < this.children.length; ++i)
- this.children[i]._detach();
- }
-
- savePosition()
- {
- if (this._savedPosition)
- return;
-
- console.assert(this.parent);
- if (!this.parent)
- return;
-
- this._savedPosition = {
- parent: this.parent,
- index: this.parent.children.indexOf(this)
- };
- }
-
- restorePosition()
- {
- if (!this._savedPosition)
- return;
-
- if (this.parent !== this._savedPosition.parent)
- this._savedPosition.parent.insertChild(this, this._savedPosition.index);
-
- this._savedPosition = null;
- }
-
- appendContextMenuItems(contextMenu)
- {
- // Subclasses may override
- return null;
- }
-
- // Protected
-
- filterableDataForColumn(columnIdentifier)
- {
- let value = this.data[columnIdentifier];
- return typeof value === "string" ? value : null;
- }
-};
-
-// Used to create a new table row when entering new data by editing cells.
-WebInspector.PlaceholderDataGridNode = class PlaceholderDataGridNode extends WebInspector.DataGridNode
-{
- constructor(data)
- {
- super(data, false);
- this.isPlaceholderNode = true;
- }
-
- makeNormal()
- {
- this.isPlaceholderNode = false;
- }
-};
</del></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsDataGridNodejs"></a>
<div class="addfile"><h4>Added: trunk/Source/WebInspectorUI/UserInterface/Views/DataGridNode.js (0 => 203114)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/DataGridNode.js         (rev 0)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/DataGridNode.js        2016-07-12 13:05:13 UTC (rev 203114)
</span><span class="lines">@@ -0,0 +1,750 @@
</span><ins>+/*
+ * Copyright (C) 2008, 2013-2016 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.DataGridNode = class DataGridNode extends WebInspector.Object
+{
+ constructor(data, hasChildren)
+ {
+ super();
+
+ this._expanded = false;
+ this._hidden = false;
+ this._selected = false;
+ this._copyable = true;
+ this._shouldRefreshChildren = true;
+ this._data = data || {};
+ this.hasChildren = hasChildren || false;
+ this.children = [];
+ this.dataGrid = null;
+ this.parent = null;
+ this.previousSibling = null;
+ this.nextSibling = null;
+ this.disclosureToggleWidth = 10;
+ }
+
+ get hidden()
+ {
+ return this._hidden;
+ }
+
+ set hidden(x)
+ {
+ x = !!x;
+
+ if (this._hidden === x)
+ return;
+
+ this._hidden = x;
+ if (this._element)
+ this._element.classList.toggle("hidden", this._hidden);
+
+ if (this.dataGrid)
+ this.dataGrid._noteRowsChanged();
+ }
+
+ get selectable()
+ {
+ return this._element && !this._hidden;
+ }
+
+ get copyable()
+ {
+ return this._copyable;
+ }
+
+ set copyable(x)
+ {
+ this._copyable = x;
+ }
+
+ get element()
+ {
+ if (this._element)
+ return this._element;
+
+ if (!this.dataGrid)
+ return null;
+
+ this._element = document.createElement("tr");
+ this._element._dataGridNode = this;
+
+ if (this.hasChildren)
+ this._element.classList.add("parent");
+ if (this.expanded)
+ this._element.classList.add("expanded");
+ if (this.selected)
+ this._element.classList.add("selected");
+ if (this.revealed)
+ this._element.classList.add("revealed");
+ if (this._hidden)
+ this._element.classList.add("hidden");
+
+ this.createCells();
+ return this._element;
+ }
+
+ createCells()
+ {
+ for (var columnIdentifier of this.dataGrid.orderedColumns)
+ this._element.appendChild(this.createCell(columnIdentifier));
+ }
+
+ refreshIfNeeded()
+ {
+ if (!this._needsRefresh)
+ return;
+
+ this._needsRefresh = false;
+
+ this.refresh();
+ }
+
+ needsRefresh()
+ {
+ this._needsRefresh = true;
+
+ if (!this._revealed)
+ return;
+
+ if (this._scheduledRefreshIdentifier)
+ return;
+
+ this._scheduledRefreshIdentifier = requestAnimationFrame(this.refresh.bind(this));
+ }
+
+ get data()
+ {
+ return this._data;
+ }
+
+ set data(x)
+ {
+ console.assert(typeof x === "object", "Data should be an object.");
+
+ x = x || {};
+
+ if (Object.shallowEqual(this._data, x))
+ return;
+
+ this._data = x;
+ this.needsRefresh();
+ }
+
+ get filterableData()
+ {
+ if (this._cachedFilterableData)
+ return this._cachedFilterableData;
+
+ this._cachedFilterableData = [];
+
+ for (let column of this.dataGrid.columns.values()) {
+ if (column.hidden)
+ continue;
+
+ let value = this.filterableDataForColumn(column.columnIdentifier);
+ if (!value)
+ continue;
+
+ if (!(value instanceof Array))
+ value = [value];
+
+ if (!value.length)
+ continue;
+
+ this._cachedFilterableData = this._cachedFilterableData.concat(value);
+ }
+
+ return this._cachedFilterableData;
+ }
+
+ get revealed()
+ {
+ if ("_revealed" in this)
+ return this._revealed;
+
+ var currentAncestor = this.parent;
+ while (currentAncestor && !currentAncestor.root) {
+ if (!currentAncestor.expanded) {
+ this._revealed = false;
+ return false;
+ }
+
+ currentAncestor = currentAncestor.parent;
+ }
+
+ this._revealed = true;
+ return true;
+ }
+
+ set hasChildren(x)
+ {
+ if (this._hasChildren === x)
+ return;
+
+ this._hasChildren = x;
+
+ if (!this._element)
+ return;
+
+ if (this._hasChildren) {
+ this._element.classList.add("parent");
+ if (this.expanded)
+ this._element.classList.add("expanded");
+ } else
+ this._element.classList.remove("parent", "expanded");
+ }
+
+ get hasChildren()
+ {
+ return this._hasChildren;
+ }
+
+ set revealed(x)
+ {
+ if (this._revealed === x)
+ return;
+
+ this._revealed = x;
+
+ if (this._element) {
+ if (this._revealed)
+ this._element.classList.add("revealed");
+ else
+ this._element.classList.remove("revealed");
+ }
+
+ this.refreshIfNeeded();
+
+ for (var i = 0; i < this.children.length; ++i)
+ this.children[i].revealed = x && this.expanded;
+ }
+
+ get depth()
+ {
+ if ("_depth" in this)
+ return this._depth;
+ if (this.parent && !this.parent.root)
+ this._depth = this.parent.depth + 1;
+ else
+ this._depth = 0;
+ return this._depth;
+ }
+
+ get leftPadding()
+ {
+ if (typeof(this._leftPadding) === "number")
+ return this._leftPadding;
+
+ this._leftPadding = this.depth * this.dataGrid.indentWidth;
+ return this._leftPadding;
+ }
+
+ get shouldRefreshChildren()
+ {
+ return this._shouldRefreshChildren;
+ }
+
+ set shouldRefreshChildren(x)
+ {
+ this._shouldRefreshChildren = x;
+ if (x && this.expanded)
+ this.expand();
+ }
+
+ get selected()
+ {
+ return this._selected;
+ }
+
+ set selected(x)
+ {
+ if (x)
+ this.select();
+ else
+ this.deselect();
+ }
+
+ get expanded()
+ {
+ return this._expanded;
+ }
+
+ set expanded(x)
+ {
+ if (x)
+ this.expand();
+ else
+ this.collapse();
+ }
+
+ hasAncestor(ancestor)
+ {
+ if (!ancestor)
+ return false;
+
+ let currentAncestor = this.parent;
+ while (currentAncestor) {
+ if (ancestor === currentAncestor)
+ return true;
+
+ currentAncestor = currentAncestor.parent;
+ }
+
+ return false;
+ }
+
+ refresh()
+ {
+ if (!this._element || !this.dataGrid)
+ return;
+
+ if (this._scheduledRefreshIdentifier) {
+ cancelAnimationFrame(this._scheduledRefreshIdentifier);
+ this._scheduledRefreshIdentifier = undefined;
+ }
+
+ this._cachedFilterableData = null;
+ this._needsRefresh = false;
+
+ this._element.removeChildren();
+ this.createCells();
+ }
+
+ refreshRecursively()
+ {
+ this.refresh();
+ this.forEachChildInSubtree((node) => node.refresh());
+ }
+
+ updateLayout()
+ {
+ // Implemented by subclasses if needed.
+ }
+
+ createCell(columnIdentifier)
+ {
+ var cellElement = document.createElement("td");
+ cellElement.className = columnIdentifier + "-column";
+ cellElement.__columnIdentifier = columnIdentifier;
+
+ var column = this.dataGrid.columns.get(columnIdentifier);
+
+ if (column["aligned"])
+ cellElement.classList.add(column["aligned"]);
+
+ if (column["group"])
+ cellElement.classList.add("column-group-" + column["group"]);
+
+ var div = cellElement.createChild("div", "cell-content");
+ var content = this.createCellContent(columnIdentifier, cellElement);
+ div.append(content);
+
+ if (column["icon"]) {
+ let iconElement = document.createElement("div");
+ iconElement.classList.add("icon");
+ div.insertBefore(iconElement, div.firstChild);
+ }
+
+ if (columnIdentifier === this.dataGrid.disclosureColumnIdentifier) {
+ cellElement.classList.add("disclosure");
+ if (this.leftPadding)
+ cellElement.style.setProperty("padding-left", this.leftPadding + "px");
+ }
+
+ return cellElement;
+ }
+
+ createCellContent(columnIdentifier)
+ {
+ return this.data[columnIdentifier] || "\u200b"; // Zero width space to keep the cell from collapsing.
+ }
+
+ elementWithColumnIdentifier(columnIdentifier)
+ {
+ if (!this.dataGrid)
+ return null;
+
+ let index = this.dataGrid.orderedColumns.indexOf(columnIdentifier);
+ if (index === -1)
+ return null;
+
+ return this.element.children[index];
+ }
+
+ // Share these functions with DataGrid. They are written to work with a DataGridNode this object.
+ appendChild() { return WebInspector.DataGrid.prototype.appendChild.apply(this, arguments); }
+ insertChild() { return WebInspector.DataGrid.prototype.insertChild.apply(this, arguments); }
+ removeChild() { return WebInspector.DataGrid.prototype.removeChild.apply(this, arguments); }
+ removeChildren() { return WebInspector.DataGrid.prototype.removeChildren.apply(this, arguments); }
+ removeChildrenRecursive() { return WebInspector.DataGrid.prototype.removeChildrenRecursive.apply(this, arguments); }
+
+ _recalculateSiblings(myIndex)
+ {
+ if (!this.parent)
+ return;
+
+ var previousChild = (myIndex > 0 ? this.parent.children[myIndex - 1] : null);
+
+ if (previousChild) {
+ previousChild.nextSibling = this;
+ this.previousSibling = previousChild;
+ } else
+ this.previousSibling = null;
+
+ var nextChild = this.parent.children[myIndex + 1];
+
+ if (nextChild) {
+ nextChild.previousSibling = this;
+ this.nextSibling = nextChild;
+ } else
+ this.nextSibling = null;
+ }
+
+ collapse()
+ {
+ if (this._element)
+ this._element.classList.remove("expanded");
+
+ this._expanded = false;
+
+ for (var i = 0; i < this.children.length; ++i)
+ this.children[i].revealed = false;
+
+ this.dispatchEventToListeners("collapsed");
+
+ if (this.dataGrid) {
+ this.dataGrid.dispatchEventToListeners(WebInspector.DataGrid.Event.CollapsedNode, {dataGridNode: this});
+ this.dataGrid._noteRowsChanged();
+ }
+ }
+
+ collapseRecursively()
+ {
+ var item = this;
+ while (item) {
+ if (item.expanded)
+ item.collapse();
+ item = item.traverseNextNode(false, this, true);
+ }
+ }
+
+ expand()
+ {
+ if (!this.hasChildren || this.expanded)
+ return;
+
+ if (this.revealed && !this._shouldRefreshChildren)
+ for (var i = 0; i < this.children.length; ++i)
+ this.children[i].revealed = true;
+
+ if (this._shouldRefreshChildren) {
+ for (var i = 0; i < this.children.length; ++i)
+ this.children[i]._detach();
+
+ this.dispatchEventToListeners("populate");
+
+ if (this._attached) {
+ for (var i = 0; i < this.children.length; ++i) {
+ var child = this.children[i];
+ if (this.revealed)
+ child.revealed = true;
+ child._attach();
+ }
+ }
+
+ this._shouldRefreshChildren = false;
+ }
+
+ if (this._element)
+ this._element.classList.add("expanded");
+
+ this._expanded = true;
+
+ this.dispatchEventToListeners("expanded");
+
+ if (this.dataGrid) {
+ this.dataGrid.dispatchEventToListeners(WebInspector.DataGrid.Event.ExpandedNode, {dataGridNode: this});
+ this.dataGrid._noteRowsChanged();
+ }
+ }
+
+ expandRecursively()
+ {
+ var item = this;
+ while (item) {
+ item.expand();
+ item = item.traverseNextNode(false, this);
+ }
+ }
+
+ forEachImmediateChild(callback)
+ {
+ for (let node of this.children)
+ callback(node);
+ }
+
+ forEachChildInSubtree(callback)
+ {
+ let node = this.traverseNextNode(false, this, true);
+ while (node) {
+ callback(node);
+ node = node.traverseNextNode(false, this, true);
+ }
+ }
+
+ isInSubtreeOfNode(baseNode)
+ {
+ let node = baseNode;
+ while (node) {
+ if (node === this)
+ return true;
+ node = node.traverseNextNode(false, baseNode, true);
+ }
+ return false;
+ }
+
+ reveal()
+ {
+ var currentAncestor = this.parent;
+ while (currentAncestor && !currentAncestor.root) {
+ if (!currentAncestor.expanded)
+ currentAncestor.expand();
+ currentAncestor = currentAncestor.parent;
+ }
+
+ this.element.scrollIntoViewIfNeeded(false);
+
+ this.dispatchEventToListeners("revealed");
+ }
+
+ select(suppressSelectedEvent)
+ {
+ if (!this.dataGrid || !this.selectable || this.selected)
+ return;
+
+ let oldSelectedNode = this.dataGrid.selectedNode;
+ if (oldSelectedNode)
+ oldSelectedNode.deselect(true);
+
+ this._selected = true;
+ this.dataGrid.selectedNode = this;
+
+ if (this._element)
+ this._element.classList.add("selected");
+
+ if (!suppressSelectedEvent)
+ this.dataGrid.dispatchEventToListeners(WebInspector.DataGrid.Event.SelectedNodeChanged, {oldSelectedNode});
+ }
+
+ revealAndSelect()
+ {
+ this.reveal();
+ this.select();
+ }
+
+ deselect(suppressDeselectedEvent)
+ {
+ if (!this.dataGrid || this.dataGrid.selectedNode !== this || !this.selected)
+ return;
+
+ this._selected = false;
+ this.dataGrid.selectedNode = null;
+
+ if (this._element)
+ this._element.classList.remove("selected");
+
+ if (!suppressDeselectedEvent)
+ this.dataGrid.dispatchEventToListeners(WebInspector.DataGrid.Event.SelectedNodeChanged, {oldSelectedNode: this});
+ }
+
+ traverseNextNode(skipHidden, stayWithin, dontPopulate, info)
+ {
+ if (!dontPopulate && this.hasChildren)
+ this.dispatchEventToListeners("populate");
+
+ if (info)
+ info.depthChange = 0;
+
+ var node = (!skipHidden || this.revealed) ? this.children[0] : null;
+ if (node && (!skipHidden || this.expanded)) {
+ if (info)
+ info.depthChange = 1;
+ return node;
+ }
+
+ if (this === stayWithin)
+ return null;
+
+ node = (!skipHidden || this.revealed) ? this.nextSibling : null;
+ if (node)
+ return node;
+
+ node = this;
+ while (node && !node.root && !((!skipHidden || node.revealed) ? node.nextSibling : null) && node.parent !== stayWithin) {
+ if (info)
+ info.depthChange -= 1;
+ node = node.parent;
+ }
+
+ if (!node)
+ return null;
+
+ return (!skipHidden || node.revealed) ? node.nextSibling : null;
+ }
+
+ traversePreviousNode(skipHidden, dontPopulate)
+ {
+ var node = (!skipHidden || this.revealed) ? this.previousSibling : null;
+ if (!dontPopulate && node && node.hasChildren)
+ node.dispatchEventToListeners("populate");
+
+ while (node && ((!skipHidden || (node.revealed && node.expanded)) ? node.children.lastValue : null)) {
+ if (!dontPopulate && node.hasChildren)
+ node.dispatchEventToListeners("populate");
+ node = ((!skipHidden || (node.revealed && node.expanded)) ? node.children.lastValue : null);
+ }
+
+ if (node)
+ return node;
+
+ if (!this.parent || this.parent.root)
+ return null;
+
+ return this.parent;
+ }
+
+ isEventWithinDisclosureTriangle(event)
+ {
+ if (!this.hasChildren)
+ return false;
+ let cell = event.target.enclosingNodeOrSelfWithNodeName("td");
+ if (!cell || !cell.classList.contains("disclosure"))
+ return false;
+
+ let computedLeftPadding = window.getComputedStyle(cell).getPropertyCSSValue("padding-left").getFloatValue(CSSPrimitiveValue.CSS_PX);
+ let left = cell.totalOffsetLeft + computedLeftPadding;
+ return event.pageX >= left && event.pageX <= left + this.disclosureToggleWidth;
+ }
+
+ _attach()
+ {
+ if (!this.dataGrid || this._attached)
+ return;
+
+ this._attached = true;
+
+ let insertionIndex = -1;
+
+ if (!this.isPlaceholderNode) {
+ var previousGridNode = this.traversePreviousNode(true, true);
+ insertionIndex = this.dataGrid._rows.indexOf(previousGridNode);
+ if (insertionIndex === -1)
+ insertionIndex = 0;
+ else
+ insertionIndex++;
+ }
+
+ if (insertionIndex === -1)
+ this.dataGrid._rows.push(this);
+ else
+ this.dataGrid._rows.insertAtIndex(this, insertionIndex);
+
+ this.dataGrid._noteRowsChanged();
+
+ if (this.expanded) {
+ for (var i = 0; i < this.children.length; ++i)
+ this.children[i]._attach();
+ }
+ }
+
+ _detach()
+ {
+ if (!this._attached)
+ return;
+
+ this._attached = false;
+
+ this.dataGrid._rows.remove(this, true);
+ this.dataGrid._noteRowRemoved(this);
+
+ for (var i = 0; i < this.children.length; ++i)
+ this.children[i]._detach();
+ }
+
+ savePosition()
+ {
+ if (this._savedPosition)
+ return;
+
+ console.assert(this.parent);
+ if (!this.parent)
+ return;
+
+ this._savedPosition = {
+ parent: this.parent,
+ index: this.parent.children.indexOf(this)
+ };
+ }
+
+ restorePosition()
+ {
+ if (!this._savedPosition)
+ return;
+
+ if (this.parent !== this._savedPosition.parent)
+ this._savedPosition.parent.insertChild(this, this._savedPosition.index);
+
+ this._savedPosition = null;
+ }
+
+ appendContextMenuItems(contextMenu)
+ {
+ // Subclasses may override
+ return null;
+ }
+
+ // Protected
+
+ filterableDataForColumn(columnIdentifier)
+ {
+ let value = this.data[columnIdentifier];
+ return typeof value === "string" ? value : null;
+ }
+};
+
+// Used to create a new table row when entering new data by editing cells.
+WebInspector.PlaceholderDataGridNode = class PlaceholderDataGridNode extends WebInspector.DataGridNode
+{
+ constructor(data)
+ {
+ super(data, false);
+ this.isPlaceholderNode = true;
+ }
+
+ makeNormal()
+ {
+ this.isPlaceholderNode = false;
+ }
+};
</ins></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsTreeElementjs"></a>
<div class="addfile"><h4>Added: trunk/Source/WebInspectorUI/UserInterface/Views/TreeElement.js (0 => 203114)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/TreeElement.js         (rev 0)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/TreeElement.js        2016-07-12 13:05:13 UTC (rev 203114)
</span><span class="lines">@@ -0,0 +1,612 @@
</span><ins>+/*
+ * Copyright (C) 2007, 2013, 2015 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.
+ * 3. Neither the name of Apple Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE 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 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.TreeElement = class TreeElement extends WebInspector.Object
+{
+ constructor(title, representedObject, hasChildren)
+ {
+ super();
+
+ this._title = title;
+ this.representedObject = (representedObject || {});
+
+ if (this.representedObject.__treeElementIdentifier)
+ this.identifier = this.representedObject.__treeElementIdentifier;
+ else {
+ this.identifier = WebInspector.TreeOutline._knownTreeElementNextIdentifier++;
+ this.representedObject.__treeElementIdentifier = this.identifier;
+ }
+
+ this._hidden = false;
+ this._selectable = true;
+ this.expanded = false;
+ this.selected = false;
+ this.hasChildren = hasChildren;
+ this.children = [];
+ this.treeOutline = null;
+ this.parent = null;
+ this.previousSibling = null;
+ this.nextSibling = null;
+ this._listItemNode = null;
+ }
+
+ // Methods
+
+ appendChild() { return WebInspector.TreeOutline.prototype.appendChild.apply(this, arguments); }
+ insertChild() { return WebInspector.TreeOutline.prototype.insertChild.apply(this, arguments); }
+ removeChild() { return WebInspector.TreeOutline.prototype.removeChild.apply(this, arguments); }
+ removeChildAtIndex() { return WebInspector.TreeOutline.prototype.removeChildAtIndex.apply(this, arguments); }
+ removeChildren() { return WebInspector.TreeOutline.prototype.removeChildren.apply(this, arguments); }
+ removeChildrenRecursive() { return WebInspector.TreeOutline.prototype.removeChildrenRecursive.apply(this, arguments); }
+
+ get arrowToggleWidth()
+ {
+ return 10;
+ }
+
+ get selectable()
+ {
+ if (this._hidden)
+ return false;
+ return this._selectable;
+ }
+
+ set selectable(x)
+ {
+ this._selectable = x;
+ }
+
+ get listItemElement()
+ {
+ return this._listItemNode;
+ }
+
+ get title()
+ {
+ return this._title;
+ }
+
+ set title(x)
+ {
+ this._title = x;
+ this._setListItemNodeContent();
+ this.didChange();
+ }
+
+ get titleHTML()
+ {
+ return this._titleHTML;
+ }
+
+ set titleHTML(x)
+ {
+ this._titleHTML = x;
+ this._setListItemNodeContent();
+ this.didChange();
+ }
+
+ get tooltip()
+ {
+ return this._tooltip;
+ }
+
+ set tooltip(x)
+ {
+ this._tooltip = x;
+ if (this._listItemNode)
+ this._listItemNode.title = x ? x : "";
+ }
+
+ get hasChildren()
+ {
+ return this._hasChildren;
+ }
+
+ set hasChildren(x)
+ {
+ if (this._hasChildren === x)
+ return;
+
+ this._hasChildren = x;
+
+ if (!this._listItemNode)
+ return;
+
+ if (x)
+ this._listItemNode.classList.add("parent");
+ else {
+ this._listItemNode.classList.remove("parent");
+ this.collapse();
+ }
+
+ this.didChange();
+ }
+
+ get hidden()
+ {
+ return this._hidden;
+ }
+
+ set hidden(x)
+ {
+ if (this._hidden === x)
+ return;
+
+ this._hidden = x;
+
+ if (this._listItemNode)
+ this._listItemNode.hidden = this._hidden;
+ if (this._childrenListNode)
+ this._childrenListNode.hidden = this._hidden;
+
+ if (this.treeOutline)
+ this.treeOutline.dispatchEventToListeners(WebInspector.TreeOutline.Event.ElementVisibilityDidChange, {element: this});
+ }
+
+ get shouldRefreshChildren()
+ {
+ return this._shouldRefreshChildren;
+ }
+
+ set shouldRefreshChildren(x)
+ {
+ this._shouldRefreshChildren = x;
+ if (x && this.expanded)
+ this.expand();
+ }
+
+ _fireDidChange()
+ {
+ if (this.treeOutline)
+ this.treeOutline._treeElementDidChange(this);
+ }
+
+ didChange()
+ {
+ if (!this.treeOutline)
+ return;
+
+ this.onNextFrame._fireDidChange();
+ }
+
+ _setListItemNodeContent()
+ {
+ if (!this._listItemNode)
+ return;
+
+ if (!this._titleHTML && !this._title)
+ this._listItemNode.removeChildren();
+ else if (typeof this._titleHTML === "string")
+ this._listItemNode.innerHTML = this._titleHTML;
+ else if (typeof this._title === "string")
+ this._listItemNode.textContent = this._title;
+ else {
+ this._listItemNode.removeChildren();
+ if (this._title.parentNode)
+ this._title.parentNode.removeChild(this._title);
+ this._listItemNode.appendChild(this._title);
+ }
+ }
+
+ _attach()
+ {
+ if (!this._listItemNode || this.parent._shouldRefreshChildren) {
+ if (this._listItemNode && this._listItemNode.parentNode)
+ this._listItemNode.parentNode.removeChild(this._listItemNode);
+
+ this._listItemNode = this.treeOutline._childrenListNode.ownerDocument.createElement("li");
+ this._listItemNode.treeElement = this;
+ this._setListItemNodeContent();
+ this._listItemNode.title = this._tooltip ? this._tooltip : "";
+ this._listItemNode.hidden = this.hidden;
+
+ if (this.hasChildren)
+ this._listItemNode.classList.add("parent");
+ if (this.expanded)
+ this._listItemNode.classList.add("expanded");
+ if (this.selected)
+ this._listItemNode.classList.add("selected");
+
+ this._listItemNode.addEventListener("mousedown", WebInspector.TreeElement.treeElementMouseDown);
+ this._listItemNode.addEventListener("click", WebInspector.TreeElement.treeElementToggled);
+ this._listItemNode.addEventListener("dblclick", WebInspector.TreeElement.treeElementDoubleClicked);
+
+ if (this.onattach)
+ this.onattach(this);
+ }
+
+ var nextSibling = null;
+ if (this.nextSibling && this.nextSibling._listItemNode && this.nextSibling._listItemNode.parentNode === this.parent._childrenListNode)
+ nextSibling = this.nextSibling._listItemNode;
+ this.parent._childrenListNode.insertBefore(this._listItemNode, nextSibling);
+ if (this._childrenListNode)
+ this.parent._childrenListNode.insertBefore(this._childrenListNode, this._listItemNode.nextSibling);
+ if (this.selected)
+ this.select();
+ if (this.expanded)
+ this.expand();
+ }
+
+ _detach()
+ {
+ if (this.ondetach)
+ this.ondetach(this);
+ if (this._listItemNode && this._listItemNode.parentNode)
+ this._listItemNode.parentNode.removeChild(this._listItemNode);
+ if (this._childrenListNode && this._childrenListNode.parentNode)
+ this._childrenListNode.parentNode.removeChild(this._childrenListNode);
+ }
+
+ static treeElementMouseDown(event)
+ {
+ var element = event.currentTarget;
+ if (!element || !element.treeElement || !element.treeElement.selectable)
+ return;
+
+ if (element.treeElement.isEventWithinDisclosureTriangle(event)) {
+ event.preventDefault();
+ return;
+ }
+
+ element.treeElement.selectOnMouseDown(event);
+ }
+
+ static treeElementToggled(event)
+ {
+ var element = event.currentTarget;
+ if (!element || !element.treeElement)
+ return;
+
+ var toggleOnClick = element.treeElement.toggleOnClick && !element.treeElement.selectable;
+ var isInTriangle = element.treeElement.isEventWithinDisclosureTriangle(event);
+ if (!toggleOnClick && !isInTriangle)
+ return;
+
+ if (element.treeElement.expanded) {
+ if (event.altKey)
+ element.treeElement.collapseRecursively();
+ else
+ element.treeElement.collapse();
+ } else {
+ if (event.altKey)
+ element.treeElement.expandRecursively();
+ else
+ element.treeElement.expand();
+ }
+ event.stopPropagation();
+ }
+
+ static treeElementDoubleClicked(event)
+ {
+ var element = event.currentTarget;
+ if (!element || !element.treeElement)
+ return;
+
+ if (element.treeElement.isEventWithinDisclosureTriangle(event))
+ return;
+
+ if (element.treeElement.ondblclick)
+ element.treeElement.ondblclick.call(element.treeElement, event);
+ else if (element.treeElement.hasChildren && !element.treeElement.expanded)
+ element.treeElement.expand();
+ }
+
+ collapse()
+ {
+ if (this._listItemNode)
+ this._listItemNode.classList.remove("expanded");
+ if (this._childrenListNode)
+ this._childrenListNode.classList.remove("expanded");
+
+ this.expanded = false;
+ if (this.treeOutline)
+ this.treeOutline._treeElementsExpandedState[this.identifier] = false;
+
+ if (this.oncollapse)
+ this.oncollapse(this);
+
+ if (this.treeOutline)
+ this.treeOutline.dispatchEventToListeners(WebInspector.TreeOutline.Event.ElementDisclosureDidChanged, {element: this});
+ }
+
+ collapseRecursively()
+ {
+ var item = this;
+ while (item) {
+ if (item.expanded)
+ item.collapse();
+ item = item.traverseNextTreeElement(false, this, true);
+ }
+ }
+
+ expand()
+ {
+ if (this.expanded && !this._shouldRefreshChildren && this._childrenListNode)
+ return;
+
+ // Set this before onpopulate. Since onpopulate can add elements and dispatch an ElementAdded event,
+ // this makes sure the expanded flag is true before calling those functions. This prevents the
+ // possibility of an infinite loop if onpopulate or an event handler were to call expand.
+
+ this.expanded = true;
+ if (this.treeOutline)
+ this.treeOutline._treeElementsExpandedState[this.identifier] = true;
+
+ // If there are no children, return. We will be expanded once we have children.
+ if (!this.hasChildren)
+ return;
+
+ if (this.treeOutline && (!this._childrenListNode || this._shouldRefreshChildren)) {
+ if (this._childrenListNode && this._childrenListNode.parentNode)
+ this._childrenListNode.parentNode.removeChild(this._childrenListNode);
+
+ this._childrenListNode = this.treeOutline._childrenListNode.ownerDocument.createElement("ol");
+ this._childrenListNode.parentTreeElement = this;
+ this._childrenListNode.classList.add("children");
+ this._childrenListNode.hidden = this.hidden;
+
+ this.onpopulate();
+
+ for (var i = 0; i < this.children.length; ++i)
+ this.children[i]._attach();
+
+ this._shouldRefreshChildren = false;
+ }
+
+ if (this._listItemNode) {
+ this._listItemNode.classList.add("expanded");
+ if (this._childrenListNode && this._childrenListNode.parentNode !== this._listItemNode.parentNode)
+ this.parent._childrenListNode.insertBefore(this._childrenListNode, this._listItemNode.nextSibling);
+ }
+
+ if (this._childrenListNode)
+ this._childrenListNode.classList.add("expanded");
+
+ if (this.onexpand)
+ this.onexpand(this);
+
+ if (this.treeOutline)
+ this.treeOutline.dispatchEventToListeners(WebInspector.TreeOutline.Event.ElementDisclosureDidChanged, {element: this});
+ }
+
+ expandRecursively(maxDepth)
+ {
+ var item = this;
+ var info = {};
+ var depth = 0;
+
+ // The Inspector uses TreeOutlines to represents object properties, so recursive expansion
+ // in some case can be infinite, since JavaScript objects can hold circular references.
+ // So default to a recursion cap of 3 levels, since that gives fairly good results.
+ if (maxDepth === undefined)
+ maxDepth = 3;
+
+ while (item) {
+ if (depth < maxDepth)
+ item.expand();
+ item = item.traverseNextTreeElement(false, this, (depth >= maxDepth), info);
+ depth += info.depthChange;
+ }
+ }
+
+ hasAncestor(ancestor)
+ {
+ if (!ancestor)
+ return false;
+
+ var currentNode = this.parent;
+ while (currentNode) {
+ if (ancestor === currentNode)
+ return true;
+ currentNode = currentNode.parent;
+ }
+
+ return false;
+ }
+
+ reveal()
+ {
+ var currentAncestor = this.parent;
+ while (currentAncestor && !currentAncestor.root) {
+ if (!currentAncestor.expanded)
+ currentAncestor.expand();
+ currentAncestor = currentAncestor.parent;
+ }
+
+ if (this.onreveal)
+ this.onreveal(this);
+ }
+
+ revealed(ignoreHidden)
+ {
+ if (!ignoreHidden && this.hidden)
+ return false;
+
+ var currentAncestor = this.parent;
+ while (currentAncestor && !currentAncestor.root) {
+ if (!currentAncestor.expanded)
+ return false;
+ if (!ignoreHidden && currentAncestor.hidden)
+ return false;
+ currentAncestor = currentAncestor.parent;
+ }
+
+ return true;
+ }
+
+ selectOnMouseDown(event)
+ {
+ this.select(false, true);
+ }
+
+ select(omitFocus, selectedByUser, suppressOnSelect, suppressOnDeselect)
+ {
+ if (!this.treeOutline || !this.selectable)
+ return;
+
+ if (this.selected && !this.treeOutline.allowsRepeatSelection)
+ return;
+
+ if (!omitFocus)
+ this.treeOutline._childrenListNode.focus();
+
+ // Focusing on another node may detach "this" from tree.
+ let treeOutline = this.treeOutline;
+ if (!treeOutline)
+ return;
+
+ treeOutline.processingSelectionChange = true;
+
+ // Prevent dispatching a SelectionDidChange event for the deselected element if
+ // it will be dispatched for the selected element. The event data includes both
+ // the selected and deselected elements, so one event is.
+ if (!suppressOnSelect)
+ suppressOnDeselect = true;
+
+ let deselectedElement = treeOutline.selectedTreeElement;
+ if (!this.selected) {
+ if (treeOutline.selectedTreeElement)
+ treeOutline.selectedTreeElement.deselect(suppressOnDeselect);
+
+ this.selected = true;
+ treeOutline.selectedTreeElement = this;
+
+ if (this._listItemNode)
+ this._listItemNode.classList.add("selected");
+ }
+
+ if (!suppressOnSelect) {
+ if (this.onselect)
+ this.onselect(this, selectedByUser);
+
+ treeOutline.dispatchEventToListeners(WebInspector.TreeOutline.Event.SelectionDidChange, {selectedElement: this, deselectedElement, selectedByUser});
+ }
+
+ treeOutline.processingSelectionChange = false;
+ }
+
+ revealAndSelect(omitFocus, selectedByUser, suppressOnSelect, suppressOnDeselect)
+ {
+ this.reveal();
+ this.select(omitFocus, selectedByUser, suppressOnSelect, suppressOnDeselect);
+ }
+
+ deselect(suppressOnDeselect)
+ {
+ if (!this.treeOutline || this.treeOutline.selectedTreeElement !== this || !this.selected)
+ return false;
+
+ this.selected = false;
+ this.treeOutline.selectedTreeElement = null;
+
+ if (this._listItemNode)
+ this._listItemNode.classList.remove("selected");
+
+ if (!suppressOnDeselect) {
+ if (this.ondeselect)
+ this.ondeselect(this);
+
+ this.treeOutline.dispatchEventToListeners(WebInspector.TreeOutline.Event.SelectionDidChange, {deselectedElement: this});
+ }
+
+ return true;
+ }
+
+ onpopulate()
+ {
+ // Overriden by subclasses.
+ }
+
+ traverseNextTreeElement(skipUnrevealed, stayWithin, dontPopulate, info)
+ {
+ function shouldSkip(element) {
+ return skipUnrevealed && !element.revealed(true);
+ }
+
+ var depthChange = 0;
+ var element = this;
+
+ if (!dontPopulate)
+ element.onpopulate();
+
+ do {
+ if (element.hasChildren && element.children[0] && (!skipUnrevealed || element.expanded)) {
+ element = element.children[0];
+ depthChange += 1;
+ } else {
+ while (element && !element.nextSibling && element.parent && !element.parent.root && element.parent !== stayWithin) {
+ element = element.parent;
+ depthChange -= 1;
+ }
+
+ if (element)
+ element = element.nextSibling;
+ }
+ } while (element && shouldSkip(element));
+
+ if (info)
+ info.depthChange = depthChange;
+
+ return element;
+ }
+
+ traversePreviousTreeElement(skipUnrevealed, dontPopulate)
+ {
+ function shouldSkip(element) {
+ return skipUnrevealed && !element.revealed(true);
+ }
+
+ var element = this;
+
+ do {
+ if (element.previousSibling) {
+ element = element.previousSibling;
+
+ while (element && element.hasChildren && element.expanded && !shouldSkip(element)) {
+ if (!dontPopulate)
+ element.onpopulate();
+ element = element.children.lastValue;
+ }
+ } else
+ element = element.parent && element.parent.root ? null : element.parent;
+ } while (element && shouldSkip(element));
+
+ return element;
+ }
+
+ isEventWithinDisclosureTriangle(event)
+ {
+ if (!document.contains(this._listItemNode))
+ return false;
+
+ // FIXME: We should not use getComputedStyle(). For that we need to get rid of using ::before for disclosure triangle. (http://webk.it/74446)
+ var computedLeftPadding = window.getComputedStyle(this._listItemNode).getPropertyCSSValue("padding-left").getFloatValue(CSSPrimitiveValue.CSS_PX);
+ var left = this._listItemNode.totalOffsetLeft + computedLeftPadding;
+ return event.pageX >= left && event.pageX <= left + this.arrowToggleWidth && this.hasChildren;
+ }
+};
</ins></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsTreeOutlinejs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/TreeOutline.js (203113 => 203114)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/TreeOutline.js        2016-07-12 13:04:38 UTC (rev 203113)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/TreeOutline.js        2016-07-12 13:05:13 UTC (rev 203114)
</span><span class="lines">@@ -643,588 +643,3 @@
</span><span class="cx"> };
</span><span class="cx">
</span><span class="cx"> WebInspector.TreeOutline._knownTreeElementNextIdentifier = 1;
</span><del>-
-WebInspector.TreeElement = class TreeElement extends WebInspector.Object
-{
- constructor(title, representedObject, hasChildren)
- {
- super();
-
- this._title = title;
- this.representedObject = (representedObject || {});
-
- if (this.representedObject.__treeElementIdentifier)
- this.identifier = this.representedObject.__treeElementIdentifier;
- else {
- this.identifier = WebInspector.TreeOutline._knownTreeElementNextIdentifier++;
- this.representedObject.__treeElementIdentifier = this.identifier;
- }
-
- this._hidden = false;
- this._selectable = true;
- this.expanded = false;
- this.selected = false;
- this.hasChildren = hasChildren;
- this.children = [];
- this.treeOutline = null;
- this.parent = null;
- this.previousSibling = null;
- this.nextSibling = null;
- this._listItemNode = null;
- }
-
- // Methods
-
- appendChild() { return WebInspector.TreeOutline.prototype.appendChild.apply(this, arguments); }
- insertChild() { return WebInspector.TreeOutline.prototype.insertChild.apply(this, arguments); }
- removeChild() { return WebInspector.TreeOutline.prototype.removeChild.apply(this, arguments); }
- removeChildAtIndex() { return WebInspector.TreeOutline.prototype.removeChildAtIndex.apply(this, arguments); }
- removeChildren() { return WebInspector.TreeOutline.prototype.removeChildren.apply(this, arguments); }
- removeChildrenRecursive() { return WebInspector.TreeOutline.prototype.removeChildrenRecursive.apply(this, arguments); }
-
- get arrowToggleWidth()
- {
- return 10;
- }
-
- get selectable()
- {
- if (this._hidden)
- return false;
- return this._selectable;
- }
-
- set selectable(x)
- {
- this._selectable = x;
- }
-
- get listItemElement()
- {
- return this._listItemNode;
- }
-
- get title()
- {
- return this._title;
- }
-
- set title(x)
- {
- this._title = x;
- this._setListItemNodeContent();
- this.didChange();
- }
-
- get titleHTML()
- {
- return this._titleHTML;
- }
-
- set titleHTML(x)
- {
- this._titleHTML = x;
- this._setListItemNodeContent();
- this.didChange();
- }
-
- get tooltip()
- {
- return this._tooltip;
- }
-
- set tooltip(x)
- {
- this._tooltip = x;
- if (this._listItemNode)
- this._listItemNode.title = x ? x : "";
- }
-
- get hasChildren()
- {
- return this._hasChildren;
- }
-
- set hasChildren(x)
- {
- if (this._hasChildren === x)
- return;
-
- this._hasChildren = x;
-
- if (!this._listItemNode)
- return;
-
- if (x)
- this._listItemNode.classList.add("parent");
- else {
- this._listItemNode.classList.remove("parent");
- this.collapse();
- }
-
- this.didChange();
- }
-
- get hidden()
- {
- return this._hidden;
- }
-
- set hidden(x)
- {
- if (this._hidden === x)
- return;
-
- this._hidden = x;
-
- if (this._listItemNode)
- this._listItemNode.hidden = this._hidden;
- if (this._childrenListNode)
- this._childrenListNode.hidden = this._hidden;
-
- if (this.treeOutline)
- this.treeOutline.dispatchEventToListeners(WebInspector.TreeOutline.Event.ElementVisibilityDidChange, {element: this});
- }
-
- get shouldRefreshChildren()
- {
- return this._shouldRefreshChildren;
- }
-
- set shouldRefreshChildren(x)
- {
- this._shouldRefreshChildren = x;
- if (x && this.expanded)
- this.expand();
- }
-
- _fireDidChange()
- {
- if (this.treeOutline)
- this.treeOutline._treeElementDidChange(this);
- }
-
- didChange()
- {
- if (!this.treeOutline)
- return;
-
- this.onNextFrame._fireDidChange();
- }
-
- _setListItemNodeContent()
- {
- if (!this._listItemNode)
- return;
-
- if (!this._titleHTML && !this._title)
- this._listItemNode.removeChildren();
- else if (typeof this._titleHTML === "string")
- this._listItemNode.innerHTML = this._titleHTML;
- else if (typeof this._title === "string")
- this._listItemNode.textContent = this._title;
- else {
- this._listItemNode.removeChildren();
- if (this._title.parentNode)
- this._title.parentNode.removeChild(this._title);
- this._listItemNode.appendChild(this._title);
- }
- }
-
- _attach()
- {
- if (!this._listItemNode || this.parent._shouldRefreshChildren) {
- if (this._listItemNode && this._listItemNode.parentNode)
- this._listItemNode.parentNode.removeChild(this._listItemNode);
-
- this._listItemNode = this.treeOutline._childrenListNode.ownerDocument.createElement("li");
- this._listItemNode.treeElement = this;
- this._setListItemNodeContent();
- this._listItemNode.title = this._tooltip ? this._tooltip : "";
- this._listItemNode.hidden = this.hidden;
-
- if (this.hasChildren)
- this._listItemNode.classList.add("parent");
- if (this.expanded)
- this._listItemNode.classList.add("expanded");
- if (this.selected)
- this._listItemNode.classList.add("selected");
-
- this._listItemNode.addEventListener("mousedown", WebInspector.TreeElement.treeElementMouseDown);
- this._listItemNode.addEventListener("click", WebInspector.TreeElement.treeElementToggled);
- this._listItemNode.addEventListener("dblclick", WebInspector.TreeElement.treeElementDoubleClicked);
-
- if (this.onattach)
- this.onattach(this);
- }
-
- var nextSibling = null;
- if (this.nextSibling && this.nextSibling._listItemNode && this.nextSibling._listItemNode.parentNode === this.parent._childrenListNode)
- nextSibling = this.nextSibling._listItemNode;
- this.parent._childrenListNode.insertBefore(this._listItemNode, nextSibling);
- if (this._childrenListNode)
- this.parent._childrenListNode.insertBefore(this._childrenListNode, this._listItemNode.nextSibling);
- if (this.selected)
- this.select();
- if (this.expanded)
- this.expand();
- }
-
- _detach()
- {
- if (this.ondetach)
- this.ondetach(this);
- if (this._listItemNode && this._listItemNode.parentNode)
- this._listItemNode.parentNode.removeChild(this._listItemNode);
- if (this._childrenListNode && this._childrenListNode.parentNode)
- this._childrenListNode.parentNode.removeChild(this._childrenListNode);
- }
-
- static treeElementMouseDown(event)
- {
- var element = event.currentTarget;
- if (!element || !element.treeElement || !element.treeElement.selectable)
- return;
-
- if (element.treeElement.isEventWithinDisclosureTriangle(event)) {
- event.preventDefault();
- return;
- }
-
- element.treeElement.selectOnMouseDown(event);
- }
-
- static treeElementToggled(event)
- {
- var element = event.currentTarget;
- if (!element || !element.treeElement)
- return;
-
- var toggleOnClick = element.treeElement.toggleOnClick && !element.treeElement.selectable;
- var isInTriangle = element.treeElement.isEventWithinDisclosureTriangle(event);
- if (!toggleOnClick && !isInTriangle)
- return;
-
- if (element.treeElement.expanded) {
- if (event.altKey)
- element.treeElement.collapseRecursively();
- else
- element.treeElement.collapse();
- } else {
- if (event.altKey)
- element.treeElement.expandRecursively();
- else
- element.treeElement.expand();
- }
- event.stopPropagation();
- }
-
- static treeElementDoubleClicked(event)
- {
- var element = event.currentTarget;
- if (!element || !element.treeElement)
- return;
-
- if (element.treeElement.isEventWithinDisclosureTriangle(event))
- return;
-
- if (element.treeElement.ondblclick)
- element.treeElement.ondblclick.call(element.treeElement, event);
- else if (element.treeElement.hasChildren && !element.treeElement.expanded)
- element.treeElement.expand();
- }
-
- collapse()
- {
- if (this._listItemNode)
- this._listItemNode.classList.remove("expanded");
- if (this._childrenListNode)
- this._childrenListNode.classList.remove("expanded");
-
- this.expanded = false;
- if (this.treeOutline)
- this.treeOutline._treeElementsExpandedState[this.identifier] = false;
-
- if (this.oncollapse)
- this.oncollapse(this);
-
- if (this.treeOutline)
- this.treeOutline.dispatchEventToListeners(WebInspector.TreeOutline.Event.ElementDisclosureDidChanged, {element: this});
- }
-
- collapseRecursively()
- {
- var item = this;
- while (item) {
- if (item.expanded)
- item.collapse();
- item = item.traverseNextTreeElement(false, this, true);
- }
- }
-
- expand()
- {
- if (this.expanded && !this._shouldRefreshChildren && this._childrenListNode)
- return;
-
- // Set this before onpopulate. Since onpopulate can add elements and dispatch an ElementAdded event,
- // this makes sure the expanded flag is true before calling those functions. This prevents the
- // possibility of an infinite loop if onpopulate or an event handler were to call expand.
-
- this.expanded = true;
- if (this.treeOutline)
- this.treeOutline._treeElementsExpandedState[this.identifier] = true;
-
- // If there are no children, return. We will be expanded once we have children.
- if (!this.hasChildren)
- return;
-
- if (this.treeOutline && (!this._childrenListNode || this._shouldRefreshChildren)) {
- if (this._childrenListNode && this._childrenListNode.parentNode)
- this._childrenListNode.parentNode.removeChild(this._childrenListNode);
-
- this._childrenListNode = this.treeOutline._childrenListNode.ownerDocument.createElement("ol");
- this._childrenListNode.parentTreeElement = this;
- this._childrenListNode.classList.add("children");
- this._childrenListNode.hidden = this.hidden;
-
- this.onpopulate();
-
- for (var i = 0; i < this.children.length; ++i)
- this.children[i]._attach();
-
- this._shouldRefreshChildren = false;
- }
-
- if (this._listItemNode) {
- this._listItemNode.classList.add("expanded");
- if (this._childrenListNode && this._childrenListNode.parentNode !== this._listItemNode.parentNode)
- this.parent._childrenListNode.insertBefore(this._childrenListNode, this._listItemNode.nextSibling);
- }
-
- if (this._childrenListNode)
- this._childrenListNode.classList.add("expanded");
-
- if (this.onexpand)
- this.onexpand(this);
-
- if (this.treeOutline)
- this.treeOutline.dispatchEventToListeners(WebInspector.TreeOutline.Event.ElementDisclosureDidChanged, {element: this});
- }
-
- expandRecursively(maxDepth)
- {
- var item = this;
- var info = {};
- var depth = 0;
-
- // The Inspector uses TreeOutlines to represents object properties, so recursive expansion
- // in some case can be infinite, since JavaScript objects can hold circular references.
- // So default to a recursion cap of 3 levels, since that gives fairly good results.
- if (maxDepth === undefined)
- maxDepth = 3;
-
- while (item) {
- if (depth < maxDepth)
- item.expand();
- item = item.traverseNextTreeElement(false, this, (depth >= maxDepth), info);
- depth += info.depthChange;
- }
- }
-
- hasAncestor(ancestor)
- {
- if (!ancestor)
- return false;
-
- var currentNode = this.parent;
- while (currentNode) {
- if (ancestor === currentNode)
- return true;
- currentNode = currentNode.parent;
- }
-
- return false;
- }
-
- reveal()
- {
- var currentAncestor = this.parent;
- while (currentAncestor && !currentAncestor.root) {
- if (!currentAncestor.expanded)
- currentAncestor.expand();
- currentAncestor = currentAncestor.parent;
- }
-
- if (this.onreveal)
- this.onreveal(this);
- }
-
- revealed(ignoreHidden)
- {
- if (!ignoreHidden && this.hidden)
- return false;
-
- var currentAncestor = this.parent;
- while (currentAncestor && !currentAncestor.root) {
- if (!currentAncestor.expanded)
- return false;
- if (!ignoreHidden && currentAncestor.hidden)
- return false;
- currentAncestor = currentAncestor.parent;
- }
-
- return true;
- }
-
- selectOnMouseDown(event)
- {
- this.select(false, true);
- }
-
- select(omitFocus, selectedByUser, suppressOnSelect, suppressOnDeselect)
- {
- if (!this.treeOutline || !this.selectable)
- return;
-
- if (this.selected && !this.treeOutline.allowsRepeatSelection)
- return;
-
- if (!omitFocus)
- this.treeOutline._childrenListNode.focus();
-
- // Focusing on another node may detach "this" from tree.
- let treeOutline = this.treeOutline;
- if (!treeOutline)
- return;
-
- treeOutline.processingSelectionChange = true;
-
- // Prevent dispatching a SelectionDidChange event for the deselected element if
- // it will be dispatched for the selected element. The event data includes both
- // the selected and deselected elements, so one event is.
- if (!suppressOnSelect)
- suppressOnDeselect = true;
-
- let deselectedElement = treeOutline.selectedTreeElement;
- if (!this.selected) {
- if (treeOutline.selectedTreeElement)
- treeOutline.selectedTreeElement.deselect(suppressOnDeselect);
-
- this.selected = true;
- treeOutline.selectedTreeElement = this;
-
- if (this._listItemNode)
- this._listItemNode.classList.add("selected");
- }
-
- if (!suppressOnSelect) {
- if (this.onselect)
- this.onselect(this, selectedByUser);
-
- treeOutline.dispatchEventToListeners(WebInspector.TreeOutline.Event.SelectionDidChange, {selectedElement: this, deselectedElement, selectedByUser});
- }
-
- treeOutline.processingSelectionChange = false;
- }
-
- revealAndSelect(omitFocus, selectedByUser, suppressOnSelect, suppressOnDeselect)
- {
- this.reveal();
- this.select(omitFocus, selectedByUser, suppressOnSelect, suppressOnDeselect);
- }
-
- deselect(suppressOnDeselect)
- {
- if (!this.treeOutline || this.treeOutline.selectedTreeElement !== this || !this.selected)
- return false;
-
- this.selected = false;
- this.treeOutline.selectedTreeElement = null;
-
- if (this._listItemNode)
- this._listItemNode.classList.remove("selected");
-
- if (!suppressOnDeselect) {
- if (this.ondeselect)
- this.ondeselect(this);
-
- this.treeOutline.dispatchEventToListeners(WebInspector.TreeOutline.Event.SelectionDidChange, {deselectedElement: this});
- }
-
- return true;
- }
-
- onpopulate()
- {
- // Overriden by subclasses.
- }
-
- traverseNextTreeElement(skipUnrevealed, stayWithin, dontPopulate, info)
- {
- function shouldSkip(element) {
- return skipUnrevealed && !element.revealed(true);
- }
-
- var depthChange = 0;
- var element = this;
-
- if (!dontPopulate)
- element.onpopulate();
-
- do {
- if (element.hasChildren && element.children[0] && (!skipUnrevealed || element.expanded)) {
- element = element.children[0];
- depthChange += 1;
- } else {
- while (element && !element.nextSibling && element.parent && !element.parent.root && element.parent !== stayWithin) {
- element = element.parent;
- depthChange -= 1;
- }
-
- if (element)
- element = element.nextSibling;
- }
- } while (element && shouldSkip(element));
-
- if (info)
- info.depthChange = depthChange;
-
- return element;
- }
-
- traversePreviousTreeElement(skipUnrevealed, dontPopulate)
- {
- function shouldSkip(element) {
- return skipUnrevealed && !element.revealed(true);
- }
-
- var element = this;
-
- do {
- if (element.previousSibling) {
- element = element.previousSibling;
-
- while (element && element.hasChildren && element.expanded && !shouldSkip(element)) {
- if (!dontPopulate)
- element.onpopulate();
- element = element.children.lastValue;
- }
- } else
- element = element.parent && element.parent.root ? null : element.parent;
- } while (element && shouldSkip(element));
-
- return element;
- }
-
- isEventWithinDisclosureTriangle(event)
- {
- if (!document.contains(this._listItemNode))
- return false;
-
- // FIXME: We should not use getComputedStyle(). For that we need to get rid of using ::before for disclosure triangle. (http://webk.it/74446)
- var computedLeftPadding = window.getComputedStyle(this._listItemNode).getPropertyCSSValue("padding-left").getFloatValue(CSSPrimitiveValue.CSS_PX);
- var left = this._listItemNode.totalOffsetLeft + computedLeftPadding;
- return event.pageX >= left && event.pageX <= left + this.arrowToggleWidth && this.hasChildren;
- }
-};
</del></span></pre>
</div>
</div>
</body>
</html>