123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322 |
- /*
- * Copyright (C) 2013 Google 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:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * 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.
- * * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
- * OWNER 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.
- */
- /**
- * @constructor
- * @extends {WebInspector.MemoryStatistics}
- * @param {WebInspector.TimelinePanel} timelinePanel
- * @param {WebInspector.TimelineModel} model
- * @param {number} sidebarWidth
- */
- WebInspector.DOMCountersGraph = function(timelinePanel, model, sidebarWidth)
- {
- WebInspector.MemoryStatistics.call(this, timelinePanel, model, sidebarWidth);
- }
- /**
- * @constructor
- * @extends {WebInspector.CounterUIBase}
- * @param {WebInspector.DOMCountersGraph} memoryCountersPane
- * @param {string} title
- * @param {string} currentValueLabel
- * @param {Array.<number>} rgb
- * @param {function(WebInspector.DOMCountersGraph.Counter):number} valueGetter
- */
- WebInspector.DOMCounterUI = function(memoryCountersPane, title, currentValueLabel, rgb, valueGetter)
- {
- var swatchColor = "rgb(" + rgb.join(",") + ")";
- WebInspector.CounterUIBase.call(this, memoryCountersPane, title, swatchColor, valueGetter)
- this._range = this._swatch.element.createChild("span");
- this._value = memoryCountersPane._currentValuesBar.createChild("span", "memory-counter-value");
- this._value.style.color = swatchColor;
- this._currentValueLabel = currentValueLabel;
- this.graphColor = "rgba(" + rgb.join(",") + ",0.8)";
- this.graphYValues = [];
- }
- /**
- * @constructor
- * @extends {WebInspector.MemoryStatistics.Counter}
- * @param {number} time
- * @param {number} documentCount
- * @param {number} nodeCount
- * @param {number} listenerCount
- */
- WebInspector.DOMCountersGraph.Counter = function(time, documentCount, nodeCount, listenerCount)
- {
- WebInspector.MemoryStatistics.Counter.call(this, time);
- this.documentCount = documentCount;
- this.nodeCount = nodeCount;
- this.listenerCount = listenerCount;
- }
- WebInspector.DOMCounterUI.prototype = {
- /**
- * @param {number} minValue
- * @param {number} maxValue
- */
- setRange: function(minValue, maxValue)
- {
- this._range.textContent = WebInspector.UIString("[ %d - %d ]", minValue, maxValue);
- },
- updateCurrentValue: function(countersEntry)
- {
- this._value.textContent = WebInspector.UIString(this._currentValueLabel, this.valueGetter(countersEntry));
- },
- clearCurrentValueAndMarker: function(ctx)
- {
- this._value.textContent = "";
- this.restoreImageUnderMarker(ctx);
- },
- /**
- * @param {CanvasRenderingContext2D} ctx
- * @param {number} x
- * @param {number} y
- * @param {number} radius
- */
- saveImageUnderMarker: function(ctx, x, y, radius)
- {
- const w = radius + 1;
- var imageData = ctx.getImageData(x - w, y - w, 2 * w, 2 * w);
- this._imageUnderMarker = {
- x: x - w,
- y: y - w,
- imageData: imageData
- };
- },
- /**
- * @param {CanvasRenderingContext2D} ctx
- */
- restoreImageUnderMarker: function(ctx)
- {
- if (!this.visible)
- return;
- if (this._imageUnderMarker)
- ctx.putImageData(this._imageUnderMarker.imageData, this._imageUnderMarker.x, this._imageUnderMarker.y);
- this.discardImageUnderMarker();
- },
- discardImageUnderMarker: function()
- {
- delete this._imageUnderMarker;
- },
- __proto__: WebInspector.CounterUIBase.prototype
- }
- WebInspector.DOMCountersGraph.prototype = {
- _createCurrentValuesBar: function()
- {
- this._currentValuesBar = this._canvasContainer.createChild("div");
- this._currentValuesBar.id = "counter-values-bar";
- this._canvasContainer.addStyleClass("dom-counters");
- },
- /**
- * @return {Array.<WebInspector.DOMCounterUI>}
- */
- _createCounterUIList: function()
- {
- function getDocumentCount(entry)
- {
- return entry.documentCount;
- }
- function getNodeCount(entry)
- {
- return entry.nodeCount;
- }
- function getListenerCount(entry)
- {
- return entry.listenerCount;
- }
- return [
- new WebInspector.DOMCounterUI(this, "Document Count", "Documents: %d", [100, 0, 0], getDocumentCount),
- new WebInspector.DOMCounterUI(this, "DOM Node Count", "Nodes: %d", [0, 100, 0], getNodeCount),
- new WebInspector.DOMCounterUI(this, "Event Listener Count", "Listeners: %d", [0, 0, 100], getListenerCount)
- ];
- },
- _canvasHeight: function()
- {
- return this._canvasContainer.offsetHeight - this._currentValuesBar.offsetHeight;
- },
- /**
- * @param {WebInspector.Event} event
- */
- _onRecordAdded: function(event)
- {
- function addStatistics(record)
- {
- var counters = record["counters"];
- if (!counters)
- return;
- this._counters.push(new WebInspector.DOMCountersGraph.Counter(
- record.endTime || record.startTime,
- counters["documents"],
- counters["nodes"],
- counters["jsEventListeners"]
- ));
- }
- WebInspector.TimelinePresentationModel.forAllRecords([event.data], null, addStatistics.bind(this));
- },
- _draw: function()
- {
- WebInspector.MemoryStatistics.prototype._draw.call(this);
- for (var i = 0; i < this._counterUI.length; i++)
- this._drawGraph(this._counterUI[i]);
- },
- /**
- * @param {CanvasRenderingContext2D} ctx
- */
- _restoreImageUnderMarker: function(ctx)
- {
- for (var i = 0; i < this._counterUI.length; i++) {
- var counterUI = this._counterUI[i];
- if (!counterUI.visible)
- continue;
- counterUI.restoreImageUnderMarker(ctx);
- }
- },
- /**
- * @param {CanvasRenderingContext2D} ctx
- * @param {number} x
- * @param {number} index
- */
- _saveImageUnderMarker: function(ctx, x, index)
- {
- const radius = 2;
- for (var i = 0; i < this._counterUI.length; i++) {
- var counterUI = this._counterUI[i];
- if (!counterUI.visible)
- continue;
- var y = counterUI.graphYValues[index];
- counterUI.saveImageUnderMarker(ctx, x, y, radius);
- }
- },
- /**
- * @param {CanvasRenderingContext2D} ctx
- * @param {number} x
- * @param {number} index
- */
- _drawMarker: function(ctx, x, index)
- {
- this._saveImageUnderMarker(ctx, x, index);
- const radius = 2;
- for (var i = 0; i < this._counterUI.length; i++) {
- var counterUI = this._counterUI[i];
- if (!counterUI.visible)
- continue;
- var y = counterUI.graphYValues[index];
- ctx.beginPath();
- ctx.arc(x, y, radius, 0, Math.PI * 2, true);
- ctx.lineWidth = 1;
- ctx.fillStyle = counterUI.graphColor;
- ctx.strokeStyle = counterUI.graphColor;
- ctx.fill();
- ctx.stroke();
- ctx.closePath();
- }
- },
- /**
- * @param {WebInspector.CounterUIBase} counterUI
- */
- _drawGraph: function(counterUI)
- {
- var canvas = this._canvas;
- var ctx = canvas.getContext("2d");
- var width = canvas.width;
- var height = this._clippedHeight;
- var originY = this._originY;
- var valueGetter = counterUI.valueGetter;
- if (!this._counters.length)
- return;
- var maxValue;
- var minValue;
- for (var i = this._minimumIndex; i <= this._maximumIndex; i++) {
- var value = valueGetter(this._counters[i]);
- if (minValue === undefined || value < minValue)
- minValue = value;
- if (maxValue === undefined || value > maxValue)
- maxValue = value;
- }
- counterUI.setRange(minValue, maxValue);
- if (!counterUI.visible)
- return;
- var yValues = counterUI.graphYValues;
- yValues.length = this._counters.length;
- var maxYRange = maxValue - minValue;
- var yFactor = maxYRange ? height / (maxYRange) : 1;
- ctx.beginPath();
- var currentY = originY + (height - (valueGetter(this._counters[this._minimumIndex]) - minValue) * yFactor);
- ctx.moveTo(0, currentY);
- for (var i = this._minimumIndex; i <= this._maximumIndex; i++) {
- var x = this._counters[i].x;
- ctx.lineTo(x, currentY);
- currentY = originY + (height - (valueGetter(this._counters[i]) - minValue) * yFactor);
- ctx.lineTo(x, currentY);
- yValues[i] = currentY;
- }
- ctx.lineTo(width, currentY);
- ctx.lineWidth = 1;
- ctx.strokeStyle = counterUI.graphColor;
- ctx.stroke();
- ctx.closePath();
- },
- _discardImageUnderMarker: function()
- {
- for (var i = 0; i < this._counterUI.length; i++)
- this._counterUI[i].discardImageUnderMarker();
- },
- __proto__: WebInspector.MemoryStatistics.prototype
- }
|