Chromium Code Reviews| Index: Source/devtools/front_end/TimelineTraceView.js |
| diff --git a/Source/devtools/front_end/TimelineTraceView.js b/Source/devtools/front_end/TimelineTraceView.js |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..213bae0b910153729bc44f7bdee5dbcc1ded44c1 |
| --- /dev/null |
| +++ b/Source/devtools/front_end/TimelineTraceView.js |
| @@ -0,0 +1,438 @@ |
| +/* |
| + * 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 |
| + * @implements {WebInspector.TimelineModeView} |
| + * @implements {WebInspector.FlameChartDelegate} |
| + * @extends {WebInspector.VBox} |
| + * @param {!WebInspector.TimelineModeViewDelegate} delegate |
| + * @param {!WebInspector.TracingModel} tracingModel |
| + */ |
| +WebInspector.TimelineTraceView = function(delegate, tracingModel) |
| +{ |
| + WebInspector.VBox.call(this); |
| + this._delegate = delegate; |
| + this._tracingModel = tracingModel; |
|
pfeldman
2014/03/26 20:37:12
unused?
caseq
2014/03/28 17:13:41
used now :-)
|
| + this.element.classList.add("timeline-flamechart"); |
| + this.registerRequiredCSS("flameChart.css"); |
| + this._delegate = delegate; |
| + this._model = tracingModel; |
| + this._dataProvider = new WebInspector.TraceViewFlameChartDataProvider(tracingModel); |
| + this._mainView = new WebInspector.FlameChart.MainPane(this._dataProvider, this, true, true); |
| + this._mainView.show(this.element); |
| + this._mainView.addEventListener(WebInspector.FlameChart.Events.EntrySelected, this._onEntrySelected, this); |
| +} |
| + |
| +WebInspector.TimelineTraceView.prototype = { |
| + /** |
| + * @param {number} windowStartTime |
| + * @param {number} windowEndTime |
| + */ |
| + requestWindowTimes: function(windowStartTime, windowEndTime) |
| + { |
| + this._delegate.requestWindowTimes(windowStartTime, windowEndTime); |
| + }, |
| + |
| + wasShown: function() |
| + { |
| + this._mainView._scheduleUpdate(); |
| + }, |
| + |
| + reset: function() |
| + { |
| + this._dataProvider.reset(); |
| + this._mainView.setWindowTimes(0, Infinity); |
| + }, |
| + |
| + /** |
| + * @param {?RegExp} textFilter |
| + */ |
| + refreshRecords: function(textFilter) |
| + { |
| + this._dataProvider.reset(); |
| + this._mainView._scheduleUpdate(); |
| + }, |
| + |
| + /** |
| + * @param {!WebInspector.TimelineModel.Record} record |
| + */ |
| + addRecord: function(record) {}, |
| + |
| + /** |
| + * @param {?WebInspector.TimelineModel.Record} record |
| + * @param {string=} regex |
| + * @param {boolean=} selectRecord |
| + */ |
| + highlightSearchResult: function(record, regex, selectRecord) {}, |
| + |
| + /** |
| + * @param {number} startTime |
| + * @param {number} endTime |
| + */ |
| + setWindowTimes: function(startTime, endTime) |
| + { |
| + this._mainView.setWindowTimes(startTime, endTime); |
|
pfeldman
2014/03/26 20:10:06
This does not work when applied.
caseq
2014/03/28 17:13:41
This requires https://codereview.chromium.org/2128
|
| + }, |
| + |
| + /** |
| + * @param {number} width |
| + */ |
| + setSidebarSize: function(width) {}, |
| + |
| + /** |
| + * @param {?WebInspector.TimelineModel.Record} record |
| + */ |
| + setSelectedRecord: function(record) {}, |
| + |
| + /** |
| + * @param {!WebInspector.Event} event |
| + */ |
| + _onEntrySelected: function(event) |
| + { |
| + }, |
| + |
| + __proto__: WebInspector.VBox.prototype |
| +}; |
| + |
| +/** |
| + * @constructor |
| + * @implements {WebInspector.FlameChartDataProvider} |
| + * @param {!WebInspector.TracingModel} model |
| + */ |
| +WebInspector.TraceViewFlameChartDataProvider = function(model) |
| +{ |
| + WebInspector.FlameChartDataProvider.call(this); |
| + this._model = model; |
| + this._font = "bold 12px " + WebInspector.fontFamily(); |
| + this._palette = new WebInspector.TraceViewPalette(); |
| +} |
| + |
| +WebInspector.TraceViewFlameChartDataProvider.prototype = { |
| + /** |
| + * @return {number} |
| + */ |
| + barHeight: function() |
| + { |
| + return 20; |
| + }, |
| + |
| + /** |
| + * @return {number} |
| + */ |
| + textBaseline: function() |
| + { |
| + return 6; |
| + }, |
| + |
| + /** |
| + * @return {number} |
| + */ |
| + textPadding: function() |
| + { |
| + return 5; |
| + }, |
| + |
| + /** |
| + * @param {number} entryIndex |
| + * @return {string} |
| + */ |
| + entryFont: function(entryIndex) |
| + { |
| + return this._font; |
| + }, |
| + |
| + /** |
| + * @param {number} entryIndex |
| + * @return {?string} |
| + */ |
| + entryTitle: function(entryIndex) |
| + { |
| + return this._records[entryIndex].name; |
| + }, |
| + |
| + /** |
| + * @param {number} startTime |
| + * @param {number} endTime |
| + * @return {?Array.<number>} |
| + */ |
| + dividerOffsets: function(startTime, endTime) |
| + { |
| + return null; |
| + }, |
| + |
| + reset: function() |
| + { |
| + this._timelineData = null; |
| + /** @type {!Array.<!WebInspector.TracingModel.Event|!WebInspector.TraceViewFlameChartDataProvider.FakeEventForDelimiter>} */ |
| + this._records = []; |
| + }, |
| + |
| + /** |
| + * @return {!WebInspector.FlameChart.TimelineData} |
| + */ |
| + timelineData: function() |
| + { |
| + if (this._timelineData) |
| + return this._timelineData; |
| + |
| + /** |
| + * @type {?WebInspector.FlameChart.TimelineData} |
| + */ |
| + this._timelineData = { |
| + entryLevels: [], |
| + entryTotalTimes: [], |
| + entryOffsets: [] |
| + }; |
| + |
| + this._currentLevel = 0; |
| + this._zeroTime = this._model.minimumRecordTime() || 0; |
|
pfeldman
2014/03/26 20:37:12
This is going to be relative to the CPU clock, whi
caseq
2014/03/28 17:13:41
With https://codereview.chromium.org/212893002/, t
|
| + this._timeSpan = Math.max((this._model.maximumRecordTime() || 0) - this._zeroTime, 1000000); |
| + var processes = this._model.sortedProcesses(); |
| + for (var i = 0; i < processes.length; ++i) { |
| + this._appendDelimiterRecord(processes[i].name()); |
| + var threads = processes[i].sortedThreads(); |
| + for (var j = 0; j < threads.length; ++j) { |
| + this._appendDelimiterRecord(threads[j].name()); |
| + var events = threads[j].events(); |
| + for (var k = 0; k < events.length; ++k) { |
| + if (events[k].duration) |
| + this._appendRecord(events[k]); |
| + } |
| + this._currentLevel += threads[j].maxStackDepth(); |
| + } |
| + ++this._currentLevel; |
| + } |
| + return this._timelineData; |
| + }, |
| + |
| + /** |
| + * @return {number} |
| + */ |
| + zeroTime: function() |
| + { |
| + return this._toTimelineTime(this._zeroTime); |
| + }, |
| + |
| + /** |
| + * @return {number} |
| + */ |
| + totalTime: function() |
| + { |
| + return this._toTimelineTime(this._timeSpan); |
| + }, |
| + |
| + /** |
| + * @return {number} |
| + */ |
| + maxStackDepth: function() |
| + { |
| + return this._currentLevel; |
| + }, |
| + |
| + /** |
| + * @param {number} entryIndex |
| + * @return {?Array.<!{title: string, text: string}>} |
| + */ |
| + prepareHighlightedEntryInfo: function(entryIndex) |
| + { |
| + return null; |
| + }, |
| + |
| + /** |
| + * @param {number} entryIndex |
| + * @return {boolean} |
| + */ |
| + canJumpToEntry: function(entryIndex) |
| + { |
| + return false; |
| + }, |
| + |
| + /** |
| + * @param {number} entryIndex |
| + * @return {!string} |
| + */ |
| + entryColor: function(entryIndex) |
| + { |
| + var record = this._records[entryIndex]; |
| + if (record instanceof WebInspector.TraceViewFlameChartDataProvider.FakeEventForDelimiter) |
|
pfeldman
2014/03/26 20:10:06
instanceof is way too expensive for the case of 2M
caseq
2014/03/28 17:13:41
Fixed.
|
| + return "#555"; |
| + return this._palette.colorForString(this._records[entryIndex].name); |
| + }, |
| + |
| + |
| + /** |
| + * @param {number} entryIndex |
| + * @param {!CanvasRenderingContext2D} context |
| + * @param {?string} text |
| + * @param {number} barX |
| + * @param {number} barY |
| + * @param {number} barWidth |
| + * @param {number} barHeight |
| + * @param {function(number):number} offsetToPosition |
| + * @return {boolean} |
| + */ |
| + decorateEntry: function(entryIndex, context, text, barX, barY, barWidth, barHeight, offsetToPosition) |
| + { |
| + return false; |
| + }, |
| + |
| + /** |
| + * @param {number} entryIndex |
| + * @return {boolean} |
| + */ |
| + forceDecoration: function(entryIndex) |
| + { |
| + return false; |
| + }, |
| + |
| + /** |
| + * @param {number} entryIndex |
| + * @return {?{startTimeOffset: number, endTimeOffset: number}} |
| + */ |
| + highlightTimeRange: function(entryIndex) |
| + { |
| + return null; |
| + }, |
| + |
| + /** |
| + * @return {number} |
| + */ |
| + paddingLeft: function() |
| + { |
| + return 0; |
| + }, |
| + |
| + /** |
| + * @param {number} entryIndex |
| + * @return {!string} |
| + */ |
| + textColor: function(entryIndex) |
| + { |
| + return "white"; |
| + }, |
| + |
| + /** |
| + * @param {string} title |
| + */ |
| + _appendDelimiterRecord: function(title) |
| + { |
| + var record = new WebInspector.TraceViewFlameChartDataProvider.FakeEventForDelimiter(this._zeroTime, this._timeSpan, title, 0); |
| + this._appendRecord(record); |
| + ++this._currentLevel; |
| + }, |
| + |
| + /** |
| + * @param {!WebInspector.TracingModel.Event|!WebInspector.TraceViewFlameChartDataProvider.FakeEventForDelimiter} record |
| + */ |
| + _appendRecord: function(record) |
| + { |
| + var index = this._records.length; |
| + this._records.push(record); |
| + this._timelineData.entryLevels[index] = this._currentLevel + record.level; |
| + this._timelineData.entryTotalTimes[index] = this._toTimelineTime(record.duration); |
| + this._timelineData.entryOffsets[index] = this._toTimelineTime(record.startTime - this._zeroTime); |
| + }, |
| + |
| + /** |
| + * @param {number} time |
| + * @return {number} |
| + */ |
| + _toTimelineTime: function(time) |
| + { |
| + return time / 1000; |
| + } |
| +} |
| + |
| +/** |
| + * @constructor |
| + * @param {number} offset |
| + * @param {number} duration |
| + * @param {string} title |
| + */ |
| +WebInspector.TraceViewFlameChartDataProvider.FakeEventForDelimiter = function(offset, duration, title, level) |
| +{ |
| + this.startTime = offset; |
| + this.duration = duration; |
| + this.name = title; |
| + this.level = level; |
| +} |
| + |
| +// The below logic is shamelessly stolen from https://code.google.com/p/trace-viewer/source/browse/trunk/trace_viewer/tracing/color_scheme.js |
| + |
| +/** |
| + * @constructor |
| + */ |
| +WebInspector.TraceViewPalette = function() |
| +{ |
| + this._palette = WebInspector.TraceViewPalette._paletteBase.map(WebInspector.TraceViewPalette._rgbToString); |
| +} |
| + |
| +WebInspector.TraceViewPalette._paletteBase = [ |
| + {r: 138, g: 113, b: 152}, |
|
pfeldman
2014/03/26 20:10:06
See WebInspector.Color.Nicknames for how we define
caseq
2014/03/28 17:13:41
Changed objects to arrays, though I think we do no
|
| + {r: 175, g: 112, b: 133}, |
| + {r: 127, g: 135, b: 225}, |
| + {r: 93, g: 81, b: 137}, |
| + {r: 116, g: 143, b: 119}, |
| + {r: 178, g: 214, b: 122}, |
| + {r: 87, g: 109, b: 147}, |
| + {r: 119, g: 155, b: 95}, |
| + {r: 114, g: 180, b: 160}, |
| + {r: 132, g: 85, b: 103}, |
| + {r: 157, g: 210, b: 150}, |
| + {r: 148, g: 94, b: 86}, |
| + {r: 164, g: 108, b: 138}, |
| + {r: 139, g: 191, b: 150}, |
| + {r: 110, g: 99, b: 145}, |
| + {r: 80, g: 129, b: 109}, |
| + {r: 125, g: 140, b: 149}, |
| + {r: 93, g: 124, b: 132}, |
| + {r: 140, g: 85, b: 140}, |
| + {r: 104, g: 163, b: 162}, |
| + {r: 132, g: 141, b: 178}, |
| + {r: 131, g: 105, b: 147}, |
| + {r: 135, g: 183, b: 98}, |
| + {r: 152, g: 134, b: 177}, |
| + {r: 141, g: 188, b: 141}, |
| + {r: 133, g: 160, b: 210}, |
| + {r: 126, g: 186, b: 148}, |
| + {r: 112, g: 198, b: 205}, |
| + {r: 180, g: 122, b: 195}, |
| + {r: 203, g: 144, b: 152} |
| +]; |
| + |
| +/** |
| + * @param {string} string |
| + * @return {number} |
| + */ |
| +WebInspector.TraceViewPalette._stringHash = function(string) |
| +{ |
| + var hash = 0; |
| + for (var i = 0; i < string.length; ++i) |
| + hash = (hash + 37 * hash + 11 * string.charCodeAt(i)) % 0xFFFFFFFF; |
| + return hash; |
| +} |
| + |
| +/** |
| + * @param {!{r: number, g:number, b:number}} rgb |
| + * @return {string} |
| + */ |
| +WebInspector.TraceViewPalette._rgbToString = function(rgb) |
| +{ |
| + return "rgb(" + rgb.r + "," + rgb.g + "," + rgb.b +")"; |
| +} |
| + |
| +WebInspector.TraceViewPalette.prototype = { |
| + /** |
| + * @param {string} string |
| + * @return {string} |
| + */ |
| + colorForString: function(string) |
| + { |
| + var hash = WebInspector.TraceViewPalette._stringHash(string); |
| + return this._palette[hash % this._palette.length]; |
| + } |
| +}; |