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]; |
+ } |
+}; |