Chromium Code Reviews| Index: Source/devtools/front_end/components/FlameChart.js |
| diff --git a/Source/devtools/front_end/components/FlameChart.js b/Source/devtools/front_end/components/FlameChart.js |
| index f4a9c7366e25b9b4a234e4226e703dd6609efa24..c885d6d6c31c7464e9a6d559aaf3902d97000291 100644 |
| --- a/Source/devtools/front_end/components/FlameChart.js |
| +++ b/Source/devtools/front_end/components/FlameChart.js |
| @@ -68,6 +68,7 @@ WebInspector.FlameChart = function(dataProvider, flameChartDelegate, isTopDown) |
| this._vScrollElement.addEventListener("scroll", this.scheduleUpdate.bind(this), false); |
| this._entryInfo = this.element.createChild("div", "profile-entry-info"); |
| + this._markerHighlighElement = this.element.createChild("div", "flame-chart-marker-highlight-element"); |
| this._highlightElement = this.element.createChild("div", "flame-chart-highlight-element"); |
| this._selectedElement = this.element.createChild("div", "flame-chart-selected-element"); |
| @@ -84,6 +85,7 @@ WebInspector.FlameChart = function(dataProvider, flameChartDelegate, isTopDown) |
| this._paddingLeft = this._dataProvider.paddingLeft(); |
| this._markerPadding = 2; |
| this._markerRadius = this._barHeight / 2 - this._markerPadding; |
| + this._highlightedMarkerIndex = -1; |
| this._highlightedEntryIndex = -1; |
| this._selectedEntryIndex = -1; |
| this._textWidth = {}; |
| @@ -98,13 +100,20 @@ WebInspector.FlameChartDataProvider = function() |
| { |
| } |
| -/** @typedef {!{ |
| - entryLevels: (!Array.<number>|!Uint8Array), |
| - entryTotalTimes: (!Array.<number>|!Float32Array), |
| - entryStartTimes: (!Array.<number>|!Float64Array) |
| - }} |
| +/** |
| + * @constructor |
| + * @param {!Array.<number>|!Uint8Array} entryLevels |
| + * @param {!Array.<number>|!Float32Array} entryTotalTimes |
| + * @param {!Array.<number>|!Float64Array} entryStartTimes |
| */ |
| -WebInspector.FlameChart.TimelineData; |
| +WebInspector.FlameChart.TimelineData = function(entryLevels, entryTotalTimes, entryStartTimes) |
| +{ |
| + this.entryLevels = entryLevels; |
| + this.entryTotalTimes = entryTotalTimes; |
| + this.entryStartTimes = entryStartTimes; |
| + /** @type {!Array.<number>} */ |
| + this.markerTimestamps = []; |
| +} |
| WebInspector.FlameChartDataProvider.prototype = { |
| /** |
| @@ -120,6 +129,18 @@ WebInspector.FlameChartDataProvider.prototype = { |
| dividerOffsets: function(startTime, endTime) { }, |
| /** |
| + * @param {number} index |
| + * @return {string} |
| + */ |
| + markerColor: function(index) { }, |
| + |
| + /** |
| + * @param {number} index |
| + * @return {string} |
| + */ |
| + markerTitle: function(index) { }, |
| + |
| + /** |
| * @return {number} |
| */ |
| minimumBoundary: function() { }, |
| @@ -455,6 +476,13 @@ WebInspector.FlameChart.prototype = { |
| { |
| if (this._isDragging) |
| return; |
| + |
| + var inDividersBar = event.offsetY < WebInspector.FlameChart.DividersBarHeight; |
| + this._highlightedMarkerIndex = inDividersBar ? this._markerIndexAtPosition(event.offsetX) : -1; |
| + this._updateMarkerHighlight(); |
| + if (inDividersBar) |
| + return; |
| + |
| var entryIndex = this._coordinatesToEntryIndex(event.offsetX, event.offsetY); |
| if (this._highlightedEntryIndex === entryIndex) |
| @@ -562,6 +590,11 @@ WebInspector.FlameChart.prototype = { |
| if (!entryIndexes || !entryIndexes.length) |
| return -1; |
| + /** |
| + * @param {number} time |
| + * @param {number} entryIndex |
| + * @return {number} |
| + */ |
| function comparator(time, entryIndex) |
| { |
| return time - entryStartTimes[entryIndex]; |
| @@ -599,6 +632,44 @@ WebInspector.FlameChart.prototype = { |
| }, |
| /** |
| + * @param {number} x |
| + * @return {number} |
| + */ |
| + _markerIndexAtPosition: function(x) |
| + { |
| + var markers = this._timelineData().markerTimestamps; |
| + if (!markers) |
| + return -1; |
| + var accurracyOffsetPx = 1; |
| + var time = this._cursorTime(x); |
| + var leftTime = this._cursorTime(x - accurracyOffsetPx); |
| + var rightTime = this._cursorTime(x + accurracyOffsetPx); |
| + |
| + /** |
| + * @param {number} time |
| + * @param {number} markerTimestamp |
| + * @return {number} |
| + */ |
| + function comparator(time, markerTimestamp) |
| + { |
| + return time - markerTimestamp; |
| + } |
| + var left = markers.lowerBound(leftTime, comparator); |
| + var markerIndex = -1; |
| + var distance = Infinity; |
| + for (var i = left; i < markers.length; i++) { |
| + if (markers[i] > rightTime) |
|
alph
2014/07/21 14:21:07
nit: you can move the check into the for condition
yurys
2014/07/21 14:30:00
Done.
|
| + break; |
| + var nextDistance = Math.abs(markers[i] - time); |
| + if (nextDistance < distance) { |
| + markerIndex = i; |
| + distance = nextDistance; |
| + } |
| + } |
| + return markerIndex; |
| + }, |
| + |
| + /** |
| * @param {number} height |
| * @param {number} width |
| */ |
| @@ -746,9 +817,60 @@ WebInspector.FlameChart.prototype = { |
| var offsets = this._dataProvider.dividerOffsets(this._calculator.minimumBoundary(), this._calculator.maximumBoundary()); |
| WebInspector.TimelineGrid.drawCanvasGrid(this._canvas, this._calculator, offsets); |
| + this._drawMarkers(); |
| this._updateElementPosition(this._highlightElement, this._highlightedEntryIndex); |
| this._updateElementPosition(this._selectedElement, this._selectedEntryIndex); |
| + this._updateMarkerHighlight(); |
| + }, |
| + |
| + _drawMarkers: function() |
| + { |
| + var markerTimestamps = this._timelineData().markerTimestamps; |
| + /** |
| + * @param {number} time |
| + * @param {number} markerTimestamp |
| + * @return {number} |
| + */ |
| + function compare(time, markerTimestamp) |
| + { |
| + return time - markerTimestamp; |
| + } |
| + var left = markerTimestamps.lowerBound(this._calculator.minimumBoundary(), compare); |
| + var right = markerTimestamps.upperBound(this._calculator.maximumBoundary(), compare); |
|
alph
2014/07/21 14:21:07
nit: you don't really need to calculate it. you ca
yurys
2014/07/21 14:30:00
Done.
|
| + |
| + var context = this._canvas.getContext("2d"); |
| + context.save(); |
| + var ratio = window.devicePixelRatio; |
| + context.scale(ratio, ratio); |
| + var height = WebInspector.FlameChart.DividersBarHeight - 1; |
| + context.lineWidth = 2; |
| + for (var i = left; i < right; i++) { |
| + var timestamp = markerTimestamps[i]; |
| + var position = this._calculator.computePosition(timestamp); |
| + context.strokeStyle = this._dataProvider.markerColor(i); |
| + context.beginPath(); |
| + context.moveTo(position, 0); |
| + context.lineTo(position, height); |
| + context.stroke(); |
| + } |
| + context.restore(); |
| + }, |
| + |
| + _updateMarkerHighlight: function() |
| + { |
| + var element = this._markerHighlighElement; |
| + if (element.parentElement) |
| + element.remove(); |
| + var markerIndex = this._highlightedMarkerIndex; |
| + if (markerIndex === -1) |
| + return; |
| + var barX = this._timeToPosition(this._timelineData().markerTimestamps[markerIndex]); |
| + element.title = this._dataProvider.markerTitle(markerIndex); |
| + var style = element.style; |
| + style.left = barX + "px"; |
| + style.backgroundColor = this._dataProvider.markerColor(markerIndex); |
| + this.element.appendChild(element); |
| }, |
| /** |
| @@ -953,6 +1075,7 @@ WebInspector.FlameChart.prototype = { |
| reset: function() |
| { |
| + this._highlightedMarkerIndex = -1; |
| this._highlightedEntryIndex = -1; |
| this._selectedEntryIndex = -1; |
| this._textWidth = {}; |