Index: Source/devtools/front_end/ui/ViewportDataGrid.js |
diff --git a/Source/devtools/front_end/ui/ViewportDataGrid.js b/Source/devtools/front_end/ui/ViewportDataGrid.js |
new file mode 100644 |
index 0000000000000000000000000000000000000000..593ac15693060187624526837a90ab4270f285d6 |
--- /dev/null |
+++ b/Source/devtools/front_end/ui/ViewportDataGrid.js |
@@ -0,0 +1,222 @@ |
+// Copyright 2014 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+/** |
+ * @constructor |
+ * @extends {WebInspector.DataGrid} |
+ * @param {!Array.<!WebInspector.DataGrid.ColumnDescriptor>} columnsArray |
+ * @param {function(!WebInspector.DataGridNode, string, string, string)=} editCallback |
+ * @param {function(!WebInspector.DataGridNode)=} deleteCallback |
+ * @param {function()=} refreshCallback |
+ * @param {function(!WebInspector.ContextMenu, !WebInspector.DataGridNode)=} contextMenuCallback |
+ */ |
+WebInspector.ViewportDataGrid = function(columnsArray, editCallback, deleteCallback, refreshCallback, contextMenuCallback) |
+{ |
+ WebInspector.DataGrid.call(this, columnsArray, editCallback, deleteCallback, refreshCallback, contextMenuCallback); |
+ this._scrollContainer.addEventListener("scroll", this._onScroll.bind(this), true); |
+ /** @type {!Array.<!WebInspector.ViewportDataGridNode>} */ |
+ this._visibleNodes = []; |
+ /** @type {boolean} */ |
+ this._updateScheduled = false; |
+ /** @type {boolean} */ |
+ this._inline = false; |
+ this.setRootNode(new WebInspector.ViewportDataGridNode()); |
+} |
+ |
+WebInspector.ViewportDataGrid.prototype = { |
+ /** |
+ * @override |
+ */ |
+ onResize: function() |
+ { |
+ this.scheduleUpdate(); |
+ }, |
+ |
+ /** |
+ * @param {?Event} event |
+ */ |
+ _onScroll: function(event) |
+ { |
+ this.scheduleUpdate(); |
+ }, |
+ |
+ /** |
+ * @protected |
+ */ |
+ scheduleUpdate: function() { |
+ if (this._updateScheduled) |
+ return; |
+ this._updateScheduled = true; |
+ window.requestAnimationFrame(this._update.bind(this)); |
+ }, |
+ |
+ /** |
+ * @override |
+ */ |
+ renderInline: function() |
+ { |
+ this._inline = true; |
+ WebInspector.DataGrid.prototype.renderInline.call(this); |
+ this._update(); |
+ }, |
+ |
+ /** |
+ * @param {number} scrollHeight |
+ * @param {number} scrollTop |
+ * @return {{topPadding: number, bottomPadding: number, visibleNodes: !Array.<!WebInspector.ViewportDataGridNode>}} |
+ */ |
+ _calculateVisibleNodes: function(scrollHeight, scrollTop) |
+ { |
+ var nodes = this._rootNode.children; |
+ if (this._inline) |
+ return {topPadding: 0, bottomPadding: 0, visibleNodes: nodes}; |
+ |
+ var size = nodes.length; |
+ var i = 0; |
+ var y = 0; |
+ |
+ for (; i < size && y + nodes[i].nodeSelfHeight() < scrollTop; ++i) |
+ y += nodes[i].nodeSelfHeight(); |
+ var start = i; |
+ var topPadding = y; |
+ |
+ for (; i < size && y < scrollTop + scrollHeight; ++i) |
+ y += nodes[i].nodeSelfHeight(); |
+ var end = i; |
+ |
+ var bottomPadding = 0; |
+ for (; i < size; ++i) |
+ bottomPadding += nodes[i].nodeSelfHeight(); |
+ |
+ return {topPadding: topPadding, bottomPadding: bottomPadding, visibleNodes: nodes.slice(start, end)}; |
+ }, |
+ |
+ _update: function() |
+ { |
+ this._updateScheduled = false; |
+ |
+ var viewportState = this._calculateVisibleNodes(this._scrollContainer.offsetHeight, this._scrollContainer.scrollTop); |
+ var visibleNodes = viewportState.visibleNodes; |
+ var visibleNodesSet = Set.fromArray(visibleNodes); |
+ |
+ for (var i = 0; i < this._visibleNodes.length; ++i) { |
+ var oldNode = this._visibleNodes[i]; |
+ if (!visibleNodesSet.contains(oldNode)) { |
+ oldNode.element().remove(); |
+ oldNode.wasDetached(); |
+ } |
+ } |
+ |
+ var previousElement = this._topFillerRow; |
+ var tBody = this.dataTableBody; |
+ for (var i = 0; i < visibleNodes.length; ++i) { |
+ var element = visibleNodes[i].element(); |
+ tBody.insertBefore(element, previousElement.nextSibling); |
+ previousElement = element; |
+ } |
+ |
+ this.setVerticalPadding(viewportState.topPadding, viewportState.bottomPadding); |
+ this._visibleNodes = visibleNodes; |
+ }, |
+ |
+ __proto__: WebInspector.DataGrid.prototype |
+} |
+ |
+/** |
+ * @constructor |
+ * @extends {WebInspector.DataGridNode} |
+ * @param {?Object.<string, *>=} data |
+ */ |
+WebInspector.ViewportDataGridNode = function(data) |
+{ |
+ WebInspector.DataGridNode.call(this, data, false); |
+ /** @type {boolean} */ |
+ this._stale = false; |
+} |
+ |
+WebInspector.ViewportDataGridNode.prototype = { |
+ /** |
+ * @override |
+ * @return {!Element} |
+ */ |
+ element: function() |
+ { |
+ if (!this._element) { |
+ this.createElement(); |
+ this.createCells(); |
+ this._stale = false; |
+ } |
+ |
+ if (this._stale) { |
+ this.createCells(); |
+ this._stale = false; |
+ } |
+ |
+ return /** @type {!Element} */ (this._element); |
+ }, |
+ |
+ /** |
+ * @override |
+ * @param {!WebInspector.DataGridNode} child |
+ * @param {number} index |
+ */ |
+ insertChild: function(child, index) |
+ { |
+ child.dataGrid = this.dataGrid; |
+ this.children.splice(index, 0, child); |
+ child.recalculateSiblings(index); |
+ this.dataGrid.scheduleUpdate(); |
+ }, |
+ |
+ /** |
+ * @override |
+ * @param {!WebInspector.DataGridNode} child |
+ */ |
+ removeChild: function(child) |
+ { |
+ child.deselect(); |
+ this.children.remove(child, true); |
+ |
+ if (child.previousSibling) |
+ child.previousSibling.nextSibling = child.nextSibling; |
+ if (child.nextSibling) |
+ child.nextSibling.previousSibling = child.previousSibling; |
+ |
+ this.dataGrid.scheduleUpdate(); |
+ }, |
+ |
+ /** |
+ * @override |
+ */ |
+ removeChildren: function() |
+ { |
+ for (var i = 0; i < this.children.length; ++i) |
+ this.children[i].deselect(); |
+ this.children = []; |
+ |
+ this.dataGrid.scheduleUpdate(); |
+ }, |
+ |
+ /** |
+ * @override |
+ */ |
+ expand: function() |
+ { |
+ }, |
+ |
+ /** |
+ * @override |
+ */ |
+ refresh: function() |
+ { |
+ if (this._element && this._element.parentElement) { |
+ this._stale = true; |
+ this.dataGrid.scheduleUpdate(); |
+ } else { |
+ this._element = null; |
+ } |
+ }, |
+ |
+ __proto__: WebInspector.DataGridNode.prototype |
+} |