Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1735)

Side by Side Diff: third_party/WebKit/Source/devtools/front_end/timeline/TimelineTreeView.js

Issue 2466123002: DevTools: reformat front-end code to match chromium style. (Closed)
Patch Set: all done Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4
5 /** 4 /**
6 * @constructor 5 * @unrestricted
7 * @extends {WebInspector.VBox}
8 */ 6 */
9 WebInspector.TimelineTreeView = function() 7 WebInspector.TimelineTreeView = class extends WebInspector.VBox {
10 { 8 constructor() {
11 WebInspector.VBox.call(this); 9 super();
12 this.element.classList.add("timeline-tree-view"); 10 this.element.classList.add('timeline-tree-view');
11 }
12
13 /**
14 * @param {!WebInspector.TracingModel.Event} event
15 * @return {string}
16 */
17 static eventNameForSorting(event) {
18 if (event.name === WebInspector.TimelineModel.RecordType.JSFrame) {
19 var data = event.args['data'];
20 return data['functionName'] + '@' + (data['scriptId'] || data['url'] || '' );
21 }
22 return event.name + ':@' + WebInspector.TimelineProfileTree.eventURL(event);
23 }
24
25 /**
26 * @param {!WebInspector.TimelineModel} model
27 * @param {!Array<!WebInspector.TimelineModel.Filter>} filters
28 */
29 _init(model, filters) {
30 this._model = model;
31 this._linkifier = new WebInspector.Linkifier();
32
33 this._filters = filters.slice();
34
35 var columns = /** @type {!Array<!WebInspector.DataGrid.ColumnDescriptor>} */ ([]);
36 this._populateColumns(columns);
37
38 var mainView = new WebInspector.VBox();
39 this._populateToolbar(mainView.element);
40 this._dataGrid = new WebInspector.SortableDataGrid(columns);
41 this._dataGrid.addEventListener(WebInspector.DataGrid.Events.SortingChanged, this._sortingChanged, this);
42 this._dataGrid.element.addEventListener('mousemove', this._onMouseMove.bind( this), true);
43 this._dataGrid.setResizeMethod(WebInspector.DataGrid.ResizeMethod.Last);
44 this._dataGrid.asWidget().show(mainView.element);
45
46 this._splitWidget = new WebInspector.SplitWidget(true, true, 'timelineTreeVi ewDetailsSplitWidget');
47 this._splitWidget.show(this.element);
48 this._splitWidget.setMainWidget(mainView);
49
50 this._detailsView = new WebInspector.VBox();
51 this._detailsView.element.classList.add('timeline-details-view', 'timeline-d etails-view-body');
52 this._splitWidget.setSidebarWidget(this._detailsView);
53 this._dataGrid.addEventListener(WebInspector.DataGrid.Events.SelectedNode, t his._updateDetailsForSelection, this);
54
55 /** @type {?WebInspector.TimelineProfileTree.Node|undefined} */
56 this._lastSelectedNode;
57 }
58
59 /**
60 * @param {!WebInspector.TimelineSelection} selection
61 */
62 updateContents(selection) {
63 this.setRange(selection.startTime(), selection.endTime());
64 }
65
66 /**
67 * @param {number} startTime
68 * @param {number} endTime
69 */
70 setRange(startTime, endTime) {
71 this._startTime = startTime;
72 this._endTime = endTime;
73 this._refreshTree();
74 }
75
76 /**
77 * @return {boolean}
78 */
79 _exposePercentages() {
80 return false;
81 }
82
83 /**
84 * @param {!Element} parent
85 */
86 _populateToolbar(parent) {
87 }
88
89 /**
90 * @param {?WebInspector.TimelineProfileTree.Node} node
91 */
92 _onHover(node) {
93 }
94
95 /**
96 * @param {!WebInspector.TracingModel.Event} event
97 * @return {?Element}
98 */
99 _linkifyLocation(event) {
100 var target = this._model.targetByEvent(event);
101 if (!target)
102 return null;
103 var frame = WebInspector.TimelineProfileTree.eventStackFrame(event);
104 if (!frame)
105 return null;
106 return this._linkifier.maybeLinkifyConsoleCallFrame(target, frame);
107 }
108
109 /**
110 * @param {!WebInspector.TimelineProfileTree.Node} treeNode
111 * @param {boolean} suppressSelectedEvent
112 */
113 selectProfileNode(treeNode, suppressSelectedEvent) {
114 var pathToRoot = [];
115 for (var node = treeNode; node; node = node.parent)
116 pathToRoot.push(node);
117 for (var i = pathToRoot.length - 1; i > 0; --i) {
118 var gridNode = this._dataGridNodeForTreeNode(pathToRoot[i]);
119 if (gridNode && gridNode.dataGrid)
120 gridNode.expand();
121 }
122 var gridNode = this._dataGridNodeForTreeNode(treeNode);
123 if (gridNode.dataGrid) {
124 gridNode.reveal();
125 gridNode.select(suppressSelectedEvent);
126 }
127 }
128
129 _refreshTree() {
130 this._linkifier.reset();
131 this._dataGrid.rootNode().removeChildren();
132 var tree = this._buildTree();
133 if (!tree.children)
134 return;
135 var maxSelfTime = 0;
136 var maxTotalTime = 0;
137 for (var child of tree.children.values()) {
138 maxSelfTime = Math.max(maxSelfTime, child.selfTime);
139 maxTotalTime = Math.max(maxTotalTime, child.totalTime);
140 }
141 for (var child of tree.children.values()) {
142 // Exclude the idle time off the total calculation.
143 var gridNode =
144 new WebInspector.TimelineTreeView.TreeGridNode(child, tree.totalTime, maxSelfTime, maxTotalTime, this);
145 this._dataGrid.insertChild(gridNode);
146 }
147 this._sortingChanged();
148 this._updateDetailsForSelection();
149 }
150
151 /**
152 * @return {!WebInspector.TimelineProfileTree.Node}
153 */
154 _buildTree() {
155 throw new Error('Not Implemented');
156 }
157
158 /**
159 * @param {function(!WebInspector.TracingModel.Event):(string|symbol)=} eventI dCallback
160 * @return {!WebInspector.TimelineProfileTree.Node}
161 */
162 _buildTopDownTree(eventIdCallback) {
163 return WebInspector.TimelineProfileTree.buildTopDown(
164 this._model.mainThreadEvents(), this._filters, this._startTime, this._en dTime, eventIdCallback);
165 }
166
167 /**
168 * @param {!Array<!WebInspector.DataGrid.ColumnDescriptor>} columns
169 */
170 _populateColumns(columns) {
171 columns.push(
172 {id: 'self', title: WebInspector.UIString('Self Time'), width: '110px', fixedWidth: true, sortable: true});
173 columns.push(
174 {id: 'total', title: WebInspector.UIString('Total Time'), width: '110px' , fixedWidth: true, sortable: true});
175 columns.push({id: 'activity', title: WebInspector.UIString('Activity'), disc losure: true, sortable: true});
176 }
177
178 _sortingChanged() {
179 var columnId = this._dataGrid.sortColumnId();
180 if (!columnId)
181 return;
182 var sortFunction;
183 switch (columnId) {
184 case 'startTime':
185 sortFunction = compareStartTime;
186 break;
187 case 'self':
188 sortFunction = compareNumericField.bind(null, 'selfTime');
189 break;
190 case 'total':
191 sortFunction = compareNumericField.bind(null, 'totalTime');
192 break;
193 case 'activity':
194 sortFunction = compareName;
195 break;
196 default:
197 console.assert(false, 'Unknown sort field: ' + columnId);
198 return;
199 }
200 this._dataGrid.sortNodes(sortFunction, !this._dataGrid.isSortOrderAscending( ));
201
202 /**
203 * @param {string} field
204 * @param {!WebInspector.DataGridNode} a
205 * @param {!WebInspector.DataGridNode} b
206 * @return {number}
207 */
208 function compareNumericField(field, a, b) {
209 var nodeA = /** @type {!WebInspector.TimelineTreeView.TreeGridNode} */ (a) ;
210 var nodeB = /** @type {!WebInspector.TimelineTreeView.TreeGridNode} */ (b) ;
211 return nodeA._profileNode[field] - nodeB._profileNode[field];
212 }
213
214 /**
215 * @param {!WebInspector.DataGridNode} a
216 * @param {!WebInspector.DataGridNode} b
217 * @return {number}
218 */
219 function compareStartTime(a, b) {
220 var nodeA = /** @type {!WebInspector.TimelineTreeView.TreeGridNode} */ (a) ;
221 var nodeB = /** @type {!WebInspector.TimelineTreeView.TreeGridNode} */ (b) ;
222 return nodeA._profileNode.event.startTime - nodeB._profileNode.event.start Time;
223 }
224
225 /**
226 * @param {!WebInspector.DataGridNode} a
227 * @param {!WebInspector.DataGridNode} b
228 * @return {number}
229 */
230 function compareName(a, b) {
231 var nodeA = /** @type {!WebInspector.TimelineTreeView.TreeGridNode} */ (a) ;
232 var nodeB = /** @type {!WebInspector.TimelineTreeView.TreeGridNode} */ (b) ;
233 var nameA = WebInspector.TimelineTreeView.eventNameForSorting(nodeA._profi leNode.event);
234 var nameB = WebInspector.TimelineTreeView.eventNameForSorting(nodeB._profi leNode.event);
235 return nameA.localeCompare(nameB);
236 }
237 }
238
239 _updateDetailsForSelection() {
240 var selectedNode = this._dataGrid.selectedNode ?
241 /** @type {!WebInspector.TimelineTreeView.TreeGridNode} */ (this._dataGr id.selectedNode)._profileNode :
242 null;
243 if (selectedNode === this._lastSelectedNode)
244 return;
245 this._lastSelectedNode = selectedNode;
246 this._detailsView.detachChildWidgets();
247 this._detailsView.element.removeChildren();
248 if (!selectedNode || !this._showDetailsForNode(selectedNode)) {
249 var banner = this._detailsView.element.createChild('div', 'full-widget-dim med-banner');
250 banner.createTextChild(WebInspector.UIString('Select item for details.'));
251 }
252 }
253
254 /**
255 * @param {!WebInspector.TimelineProfileTree.Node} node
256 * @return {boolean}
257 */
258 _showDetailsForNode(node) {
259 return false;
260 }
261
262 /**
263 * @param {!Event} event
264 */
265 _onMouseMove(event) {
266 var gridNode = event.target && (event.target instanceof Node) ?
267 /** @type {?WebInspector.TimelineTreeView.TreeGridNode} */ (
268 this._dataGrid.dataGridNodeFromNode(/** @type {!Node} */ (event.targ et))) :
269 null;
270 var profileNode = gridNode && gridNode._profileNode;
271 if (profileNode === this._lastHoveredProfileNode)
272 return;
273 this._lastHoveredProfileNode = profileNode;
274 this._onHover(profileNode);
275 }
276
277 /**
278 * @param {!WebInspector.TimelineProfileTree.Node} treeNode
279 * @return {?WebInspector.TimelineTreeView.GridNode}
280 */
281 _dataGridNodeForTreeNode(treeNode) {
282 return treeNode[WebInspector.TimelineTreeView.TreeGridNode._gridNodeSymbol] || null;
283 }
13 }; 284 };
14 285
15 WebInspector.TimelineTreeView.prototype = {
16 /**
17 * @param {!WebInspector.TimelineModel} model
18 * @param {!Array<!WebInspector.TimelineModel.Filter>} filters
19 */
20 _init: function(model, filters)
21 {
22 this._model = model;
23 this._linkifier = new WebInspector.Linkifier();
24
25 this._filters = filters.slice();
26
27 var columns = /** @type {!Array<!WebInspector.DataGrid.ColumnDescriptor> } */ ([]);
28 this._populateColumns(columns);
29
30 var mainView = new WebInspector.VBox();
31 this._populateToolbar(mainView.element);
32 this._dataGrid = new WebInspector.SortableDataGrid(columns);
33 this._dataGrid.addEventListener(WebInspector.DataGrid.Events.SortingChan ged, this._sortingChanged, this);
34 this._dataGrid.element.addEventListener("mousemove", this._onMouseMove.b ind(this), true);
35 this._dataGrid.setResizeMethod(WebInspector.DataGrid.ResizeMethod.Last);
36 this._dataGrid.asWidget().show(mainView.element);
37
38 this._splitWidget = new WebInspector.SplitWidget(true, true, "timelineTr eeViewDetailsSplitWidget");
39 this._splitWidget.show(this.element);
40 this._splitWidget.setMainWidget(mainView);
41
42 this._detailsView = new WebInspector.VBox();
43 this._detailsView.element.classList.add("timeline-details-view", "timeli ne-details-view-body");
44 this._splitWidget.setSidebarWidget(this._detailsView);
45 this._dataGrid.addEventListener(WebInspector.DataGrid.Events.SelectedNod e, this._updateDetailsForSelection, this);
46
47 /** @type {?WebInspector.TimelineProfileTree.Node|undefined} */
48 this._lastSelectedNode;
49 },
50
51 /**
52 * @param {!WebInspector.TimelineSelection} selection
53 */
54 updateContents: function(selection)
55 {
56 this.setRange(selection.startTime(), selection.endTime());
57 },
58
59 /**
60 * @param {number} startTime
61 * @param {number} endTime
62 */
63 setRange: function(startTime, endTime)
64 {
65 this._startTime = startTime;
66 this._endTime = endTime;
67 this._refreshTree();
68 },
69
70 /**
71 * @return {boolean}
72 */
73 _exposePercentages: function()
74 {
75 return false;
76 },
77
78 /**
79 * @param {!Element} parent
80 */
81 _populateToolbar: function(parent) { },
82
83 /**
84 * @param {?WebInspector.TimelineProfileTree.Node} node
85 */
86 _onHover: function(node) { },
87
88 /**
89 * @param {!WebInspector.TracingModel.Event} event
90 * @return {?Element}
91 */
92 _linkifyLocation: function(event)
93 {
94 var target = this._model.targetByEvent(event);
95 if (!target)
96 return null;
97 var frame = WebInspector.TimelineProfileTree.eventStackFrame(event);
98 if (!frame)
99 return null;
100 return this._linkifier.maybeLinkifyConsoleCallFrame(target, frame);
101 },
102
103 /**
104 * @param {!WebInspector.TimelineProfileTree.Node} treeNode
105 * @param {boolean} suppressSelectedEvent
106 */
107 selectProfileNode: function(treeNode, suppressSelectedEvent)
108 {
109 var pathToRoot = [];
110 for (var node = treeNode; node; node = node.parent)
111 pathToRoot.push(node);
112 for (var i = pathToRoot.length - 1; i > 0; --i) {
113 var gridNode = this._dataGridNodeForTreeNode(pathToRoot[i]);
114 if (gridNode && gridNode.dataGrid)
115 gridNode.expand();
116 }
117 var gridNode = this._dataGridNodeForTreeNode(treeNode);
118 if (gridNode.dataGrid) {
119 gridNode.reveal();
120 gridNode.select(suppressSelectedEvent);
121 }
122 },
123
124 _refreshTree: function()
125 {
126 this._linkifier.reset();
127 this._dataGrid.rootNode().removeChildren();
128 var tree = this._buildTree();
129 if (!tree.children)
130 return;
131 var maxSelfTime = 0;
132 var maxTotalTime = 0;
133 for (var child of tree.children.values()) {
134 maxSelfTime = Math.max(maxSelfTime, child.selfTime);
135 maxTotalTime = Math.max(maxTotalTime, child.totalTime);
136 }
137 for (var child of tree.children.values()) {
138 // Exclude the idle time off the total calculation.
139 var gridNode = new WebInspector.TimelineTreeView.TreeGridNode(child, tree.totalTime, maxSelfTime, maxTotalTime, this);
140 this._dataGrid.insertChild(gridNode);
141 }
142 this._sortingChanged();
143 this._updateDetailsForSelection();
144 },
145
146 /**
147 * @return {!WebInspector.TimelineProfileTree.Node}
148 */
149 _buildTree: function()
150 {
151 throw new Error("Not Implemented");
152 },
153
154 /**
155 * @param {function(!WebInspector.TracingModel.Event):(string|symbol)=} even tIdCallback
156 * @return {!WebInspector.TimelineProfileTree.Node}
157 */
158 _buildTopDownTree: function(eventIdCallback)
159 {
160 return WebInspector.TimelineProfileTree.buildTopDown(this._model.mainThr eadEvents(), this._filters, this._startTime, this._endTime, eventIdCallback);
161 },
162
163 /**
164 * @param {!Array<!WebInspector.DataGrid.ColumnDescriptor>} columns
165 */
166 _populateColumns: function(columns)
167 {
168 columns.push({id: "self", title: WebInspector.UIString("Self Time"), wid th: "110px", fixedWidth: true, sortable: true});
169 columns.push({id: "total", title: WebInspector.UIString("Total Time"), w idth: "110px", fixedWidth: true, sortable: true});
170 columns.push({id: "activity", title: WebInspector.UIString("Activity"), disclosure: true, sortable: true});
171 },
172
173 _sortingChanged: function()
174 {
175 var columnId = this._dataGrid.sortColumnId();
176 if (!columnId)
177 return;
178 var sortFunction;
179 switch (columnId) {
180 case "startTime":
181 sortFunction = compareStartTime;
182 break;
183 case "self":
184 sortFunction = compareNumericField.bind(null, "selfTime");
185 break;
186 case "total":
187 sortFunction = compareNumericField.bind(null, "totalTime");
188 break;
189 case "activity":
190 sortFunction = compareName;
191 break;
192 default:
193 console.assert(false, "Unknown sort field: " + columnId);
194 return;
195 }
196 this._dataGrid.sortNodes(sortFunction, !this._dataGrid.isSortOrderAscend ing());
197
198 /**
199 * @param {string} field
200 * @param {!WebInspector.DataGridNode} a
201 * @param {!WebInspector.DataGridNode} b
202 * @return {number}
203 */
204 function compareNumericField(field, a, b)
205 {
206 var nodeA = /** @type {!WebInspector.TimelineTreeView.TreeGridNode} */ (a);
207 var nodeB = /** @type {!WebInspector.TimelineTreeView.TreeGridNode} */ (b);
208 return nodeA._profileNode[field] - nodeB._profileNode[field];
209 }
210
211 /**
212 * @param {!WebInspector.DataGridNode} a
213 * @param {!WebInspector.DataGridNode} b
214 * @return {number}
215 */
216 function compareStartTime(a, b)
217 {
218 var nodeA = /** @type {!WebInspector.TimelineTreeView.TreeGridNode} */ (a);
219 var nodeB = /** @type {!WebInspector.TimelineTreeView.TreeGridNode} */ (b);
220 return nodeA._profileNode.event.startTime - nodeB._profileNode.event .startTime;
221 }
222
223 /**
224 * @param {!WebInspector.DataGridNode} a
225 * @param {!WebInspector.DataGridNode} b
226 * @return {number}
227 */
228 function compareName(a, b)
229 {
230 var nodeA = /** @type {!WebInspector.TimelineTreeView.TreeGridNode} */ (a);
231 var nodeB = /** @type {!WebInspector.TimelineTreeView.TreeGridNode} */ (b);
232 var nameA = WebInspector.TimelineTreeView.eventNameForSorting(nodeA. _profileNode.event);
233 var nameB = WebInspector.TimelineTreeView.eventNameForSorting(nodeB. _profileNode.event);
234 return nameA.localeCompare(nameB);
235 }
236 },
237
238 _updateDetailsForSelection: function()
239 {
240 var selectedNode = this._dataGrid.selectedNode ? /** @type {!WebInspecto r.TimelineTreeView.TreeGridNode} */ (this._dataGrid.selectedNode)._profileNode : null;
241 if (selectedNode === this._lastSelectedNode)
242 return;
243 this._lastSelectedNode = selectedNode;
244 this._detailsView.detachChildWidgets();
245 this._detailsView.element.removeChildren();
246 if (!selectedNode || !this._showDetailsForNode(selectedNode)) {
247 var banner = this._detailsView.element.createChild("div", "full-widg et-dimmed-banner");
248 banner.createTextChild(WebInspector.UIString("Select item for detail s."));
249 }
250 },
251
252 /**
253 * @param {!WebInspector.TimelineProfileTree.Node} node
254 * @return {boolean}
255 */
256 _showDetailsForNode: function(node)
257 {
258 return false;
259 },
260
261 /**
262 * @param {!Event} event
263 */
264 _onMouseMove: function(event)
265 {
266 var gridNode = event.target && (event.target instanceof Node)
267 ? /** @type {?WebInspector.TimelineTreeView.TreeGridNode} */ (this._ dataGrid.dataGridNodeFromNode(/** @type {!Node} */ (event.target)))
268 : null;
269 var profileNode = gridNode && gridNode._profileNode;
270 if (profileNode === this._lastHoveredProfileNode)
271 return;
272 this._lastHoveredProfileNode = profileNode;
273 this._onHover(profileNode);
274 },
275
276 /**
277 * @param {!WebInspector.TimelineProfileTree.Node} treeNode
278 * @return {?WebInspector.TimelineTreeView.GridNode}
279 */
280 _dataGridNodeForTreeNode: function(treeNode)
281 {
282 return treeNode[WebInspector.TimelineTreeView.TreeGridNode._gridNodeSymb ol] || null;
283 },
284
285 __proto__: WebInspector.VBox.prototype
286 };
287 286
288 /** 287 /**
289 * @param {!WebInspector.TracingModel.Event} event 288 * @unrestricted
290 * @return {string}
291 */ 289 */
292 WebInspector.TimelineTreeView.eventNameForSorting = function(event) 290 WebInspector.TimelineTreeView.GridNode = class extends WebInspector.SortableData GridNode {
293 { 291 /**
294 if (event.name === WebInspector.TimelineModel.RecordType.JSFrame) { 292 * @param {!WebInspector.TimelineProfileTree.Node} profileNode
295 var data = event.args["data"]; 293 * @param {number} grandTotalTime
296 return data["functionName"] + "@" + (data["scriptId"] || data["url"] || ""); 294 * @param {number} maxSelfTime
297 } 295 * @param {number} maxTotalTime
298 return event.name + ":@" + WebInspector.TimelineProfileTree.eventURL(event); 296 * @param {!WebInspector.TimelineTreeView} treeView
299 }; 297 */
300 298 constructor(profileNode, grandTotalTime, maxSelfTime, maxTotalTime, treeView) {
301 /** 299 super(null, false);
302 * @constructor
303 * @extends {WebInspector.SortableDataGridNode}
304 * @param {!WebInspector.TimelineProfileTree.Node} profileNode
305 * @param {number} grandTotalTime
306 * @param {number} maxSelfTime
307 * @param {number} maxTotalTime
308 * @param {!WebInspector.TimelineTreeView} treeView
309 */
310 WebInspector.TimelineTreeView.GridNode = function(profileNode, grandTotalTime, m axSelfTime, maxTotalTime, treeView)
311 {
312 WebInspector.SortableDataGridNode.call(this, null, false);
313 300
314 this._populated = false; 301 this._populated = false;
315 this._profileNode = profileNode; 302 this._profileNode = profileNode;
316 this._treeView = treeView; 303 this._treeView = treeView;
317 this._grandTotalTime = grandTotalTime; 304 this._grandTotalTime = grandTotalTime;
318 this._maxSelfTime = maxSelfTime; 305 this._maxSelfTime = maxSelfTime;
319 this._maxTotalTime = maxTotalTime; 306 this._maxTotalTime = maxTotalTime;
320 }; 307 }
321 308
322 WebInspector.TimelineTreeView.GridNode.prototype = { 309 /**
323 /** 310 * @override
324 * @override 311 * @param {string} columnId
325 * @param {string} columnId 312 * @return {!Element}
326 * @return {!Element} 313 */
327 */ 314 createCell(columnId) {
328 createCell: function(columnId) 315 if (columnId === 'activity')
329 { 316 return this._createNameCell(columnId);
330 if (columnId === "activity") 317 return this._createValueCell(columnId) || super.createCell(columnId);
331 return this._createNameCell(columnId); 318 }
332 return this._createValueCell(columnId) || WebInspector.DataGridNode.prot otype.createCell.call(this, columnId); 319
333 }, 320 /**
334 321 * @param {string} columnId
335 /** 322 * @return {!Element}
336 * @param {string} columnId 323 */
337 * @return {!Element} 324 _createNameCell(columnId) {
338 */ 325 var cell = this.createTD(columnId);
339 _createNameCell: function(columnId) 326 var container = cell.createChild('div', 'name-container');
340 { 327 var icon = container.createChild('div', 'activity-icon');
341 var cell = this.createTD(columnId); 328 var name = container.createChild('div', 'activity-name');
342 var container = cell.createChild("div", "name-container"); 329 var event = this._profileNode.event;
343 var icon = container.createChild("div", "activity-icon"); 330 if (this._profileNode.isGroupNode()) {
344 var name = container.createChild("div", "activity-name"); 331 var treeView = /** @type {!WebInspector.AggregatedTimelineTreeView} */ (th is._treeView);
345 var event = this._profileNode.event; 332 var info = treeView._displayInfoForGroupNode(this._profileNode);
346 if (this._profileNode.isGroupNode()) { 333 name.textContent = info.name;
347 var treeView = /** @type {!WebInspector.AggregatedTimelineTreeView} */ (this._treeView); 334 icon.style.backgroundColor = info.color;
348 var info = treeView._displayInfoForGroupNode(this._profileNode); 335 } else if (event) {
349 name.textContent = info.name; 336 var data = event.args['data'];
350 icon.style.backgroundColor = info.color; 337 var deoptReason = data && data['deoptReason'];
351 } else if (event) { 338 if (deoptReason)
352 var data = event.args["data"]; 339 container.createChild('div', 'activity-warning').title =
353 var deoptReason = data && data["deoptReason"]; 340 WebInspector.UIString('Not optimized: %s', deoptReason);
354 if (deoptReason) 341 name.textContent = event.name === WebInspector.TimelineModel.RecordType.JS Frame ?
355 container.createChild("div", "activity-warning").title = WebInsp ector.UIString("Not optimized: %s", deoptReason); 342 WebInspector.beautifyFunctionName(event.args['data']['functionName']) :
356 name.textContent = event.name === WebInspector.TimelineModel.RecordT ype.JSFrame 343 WebInspector.TimelineUIUtils.eventTitle(event);
357 ? WebInspector.beautifyFunctionName(event.args["data"]["function Name"]) 344 var link = this._treeView._linkifyLocation(event);
358 : WebInspector.TimelineUIUtils.eventTitle(event); 345 if (link)
359 var link = this._treeView._linkifyLocation(event); 346 container.createChild('div', 'activity-link').appendChild(link);
360 if (link) 347 icon.style.backgroundColor = WebInspector.TimelineUIUtils.eventColor(event );
361 container.createChild("div", "activity-link").appendChild(link); 348 }
362 icon.style.backgroundColor = WebInspector.TimelineUIUtils.eventColor (event); 349 return cell;
363 } 350 }
364 return cell; 351
365 }, 352 /**
366 353 * @param {string} columnId
367 /** 354 * @return {?Element}
368 * @param {string} columnId 355 */
369 * @return {?Element} 356 _createValueCell(columnId) {
370 */ 357 if (columnId !== 'self' && columnId !== 'total' && columnId !== 'startTime')
371 _createValueCell: function(columnId) 358 return null;
372 { 359
373 if (columnId !== "self" && columnId !== "total" && columnId !== "startTi me") 360 var showPercents = false;
374 return null; 361 var value;
375 362 var maxTime;
376 var showPercents = false; 363 switch (columnId) {
377 var value; 364 case 'startTime':
378 var maxTime; 365 value = this._profileNode.event.startTime - this._treeView._model.minimu mRecordTime();
379 switch (columnId) { 366 break;
380 case "startTime": 367 case 'self':
381 value = this._profileNode.event.startTime - this._treeView._model.mi nimumRecordTime(); 368 value = this._profileNode.selfTime;
382 break; 369 maxTime = this._maxSelfTime;
383 case "self": 370 showPercents = true;
384 value = this._profileNode.selfTime; 371 break;
385 maxTime = this._maxSelfTime; 372 case 'total':
386 showPercents = true; 373 value = this._profileNode.totalTime;
387 break; 374 maxTime = this._maxTotalTime;
388 case "total": 375 showPercents = true;
389 value = this._profileNode.totalTime; 376 break;
390 maxTime = this._maxTotalTime; 377 default:
391 showPercents = true; 378 return null;
392 break; 379 }
393 default: 380 var cell = this.createTD(columnId);
394 return null; 381 cell.className = 'numeric-column';
395 } 382 var textDiv = cell.createChild('div');
396 var cell = this.createTD(columnId); 383 textDiv.createChild('span').textContent = WebInspector.UIString('%.1f\u2009m s', value);
397 cell.className = "numeric-column"; 384
398 var textDiv = cell.createChild("div"); 385 if (showPercents && this._treeView._exposePercentages())
399 textDiv.createChild("span").textContent = WebInspector.UIString("%.1f\u2 009ms", value); 386 textDiv.createChild('span', 'percent-column').textContent =
400 387 WebInspector.UIString('%.1f\u2009%%', value / this._grandTotalTime * 1 00);
401 if (showPercents && this._treeView._exposePercentages()) 388 if (maxTime) {
402 textDiv.createChild("span", "percent-column").textContent = WebInspe ctor.UIString("%.1f\u2009%%", value / this._grandTotalTime * 100); 389 textDiv.classList.add('background-percent-bar');
403 if (maxTime) { 390 cell.createChild('div', 'background-bar-container').createChild('div', 'ba ckground-bar').style.width =
404 textDiv.classList.add("background-percent-bar"); 391 (value * 100 / maxTime).toFixed(1) + '%';
405 cell.createChild("div", "background-bar-container").createChild("div ", "background-bar").style.width = (value * 100 / maxTime).toFixed(1) + "%"; 392 }
406 } 393 return cell;
407 return cell; 394 }
408 },
409
410 __proto__: WebInspector.SortableDataGridNode.prototype
411 }; 395 };
412 396
413 /** 397 /**
414 * @constructor 398 * @unrestricted
415 * @extends {WebInspector.TimelineTreeView.GridNode}
416 * @param {!WebInspector.TimelineProfileTree.Node} profileNode
417 * @param {number} grandTotalTime
418 * @param {number} maxSelfTime
419 * @param {number} maxTotalTime
420 * @param {!WebInspector.TimelineTreeView} treeView
421 */ 399 */
422 WebInspector.TimelineTreeView.TreeGridNode = function(profileNode, grandTotalTim e, maxSelfTime, maxTotalTime, treeView) 400 WebInspector.TimelineTreeView.TreeGridNode = class extends WebInspector.Timeline TreeView.GridNode {
423 { 401 /**
424 WebInspector.TimelineTreeView.GridNode.call(this, profileNode, grandTotalTim e, maxSelfTime, maxTotalTime, treeView); 402 * @param {!WebInspector.TimelineProfileTree.Node} profileNode
403 * @param {number} grandTotalTime
404 * @param {number} maxSelfTime
405 * @param {number} maxTotalTime
406 * @param {!WebInspector.TimelineTreeView} treeView
407 */
408 constructor(profileNode, grandTotalTime, maxSelfTime, maxTotalTime, treeView) {
409 super(profileNode, grandTotalTime, maxSelfTime, maxTotalTime, treeView);
425 this.hasChildren = this._profileNode.children ? this._profileNode.children.s ize > 0 : false; 410 this.hasChildren = this._profileNode.children ? this._profileNode.children.s ize > 0 : false;
426 profileNode[WebInspector.TimelineTreeView.TreeGridNode._gridNodeSymbol] = th is; 411 profileNode[WebInspector.TimelineTreeView.TreeGridNode._gridNodeSymbol] = th is;
427 }; 412 }
428 413
429 WebInspector.TimelineTreeView.TreeGridNode._gridNodeSymbol = Symbol("treeGridNod e"); 414 /**
430 415 * @override
431 WebInspector.TimelineTreeView.TreeGridNode.prototype = { 416 */
432 /** 417 populate() {
433 * @override 418 if (this._populated)
434 */ 419 return;
435 populate: function() 420 this._populated = true;
436 { 421 if (!this._profileNode.children)
437 if (this._populated) 422 return;
438 return; 423 for (var node of this._profileNode.children.values()) {
439 this._populated = true; 424 var gridNode = new WebInspector.TimelineTreeView.TreeGridNode(
440 if (!this._profileNode.children) 425 node, this._grandTotalTime, this._maxSelfTime, this._maxTotalTime, thi s._treeView);
441 return; 426 this.insertChildOrdered(gridNode);
442 for (var node of this._profileNode.children.values()) { 427 }
443 var gridNode = new WebInspector.TimelineTreeView.TreeGridNode(node, this._grandTotalTime, this._maxSelfTime, this._maxTotalTime, this._treeView); 428 }
444 this.insertChildOrdered(gridNode); 429 };
445 } 430
446 }, 431 WebInspector.TimelineTreeView.TreeGridNode._gridNodeSymbol = Symbol('treeGridNod e');
447
448 __proto__: WebInspector.TimelineTreeView.GridNode.prototype
449 };
450
451 432
452 /** 433 /**
453 * @constructor 434 * @unrestricted
454 * @extends {WebInspector.TimelineTreeView}
455 * @param {!WebInspector.TimelineModel} model
456 * @param {!Array<!WebInspector.TimelineModel.Filter>} filters
457 */ 435 */
458 WebInspector.AggregatedTimelineTreeView = function(model, filters) 436 WebInspector.AggregatedTimelineTreeView = class extends WebInspector.TimelineTre eView {
459 { 437 /**
460 WebInspector.TimelineTreeView.call(this); 438 * @param {!WebInspector.TimelineModel} model
461 this._groupBySetting = WebInspector.settings.createSetting("timelineTreeGrou pBy", WebInspector.TimelineAggregator.GroupBy.Category); 439 * @param {!Array<!WebInspector.TimelineModel.Filter>} filters
440 */
441 constructor(model, filters) {
442 super();
443 this._groupBySetting =
444 WebInspector.settings.createSetting('timelineTreeGroupBy', WebInspector. TimelineAggregator.GroupBy.Category);
462 this._init(model, filters); 445 this._init(model, filters);
463 var nonessentialEvents = [ 446 var nonessentialEvents = [
464 WebInspector.TimelineModel.RecordType.EventDispatch, 447 WebInspector.TimelineModel.RecordType.EventDispatch, WebInspector.Timeline Model.RecordType.FunctionCall,
465 WebInspector.TimelineModel.RecordType.FunctionCall, 448 WebInspector.TimelineModel.RecordType.TimerFire
466 WebInspector.TimelineModel.RecordType.TimerFire
467 ]; 449 ];
468 this._filters.push(new WebInspector.ExclusiveNameFilter(nonessentialEvents)) ; 450 this._filters.push(new WebInspector.ExclusiveNameFilter(nonessentialEvents)) ;
469 this._stackView = new WebInspector.TimelineStackView(this); 451 this._stackView = new WebInspector.TimelineStackView(this);
470 this._stackView.addEventListener(WebInspector.TimelineStackView.Events.Selec tionChanged, this._onStackViewSelectionChanged, this); 452 this._stackView.addEventListener(
471 }; 453 WebInspector.TimelineStackView.Events.SelectionChanged, this._onStackVie wSelectionChanged, this);
472 454 }
473 WebInspector.AggregatedTimelineTreeView.prototype = { 455
456 /**
457 * @override
458 * @param {!WebInspector.TimelineSelection} selection
459 */
460 updateContents(selection) {
461 this._updateExtensionResolver();
462 super.updateContents(selection);
463 var rootNode = this._dataGrid.rootNode();
464 if (rootNode.children.length)
465 rootNode.children[0].revealAndSelect();
466 }
467
468 _updateExtensionResolver() {
469 this._executionContextNamesByOrigin = new Map();
470 for (var target of WebInspector.targetManager.targets()) {
471 for (var context of target.runtimeModel.executionContexts())
472 this._executionContextNamesByOrigin.set(context.origin, context.name);
473 }
474 }
475
476 /**
477 * @param {!WebInspector.TimelineProfileTree.Node} node
478 * @return {!{name: string, color: string}}
479 */
480 _displayInfoForGroupNode(node) {
481 var categories = WebInspector.TimelineUIUtils.categories();
482 var color = node.id ? WebInspector.TimelineUIUtils.eventColor(node.event) : categories['other'].color;
483
484 switch (this._groupBySetting.get()) {
485 case WebInspector.TimelineAggregator.GroupBy.Category:
486 var category = categories[node.id] || categories['other'];
487 return {name: category.title, color: category.color};
488
489 case WebInspector.TimelineAggregator.GroupBy.Domain:
490 case WebInspector.TimelineAggregator.GroupBy.Subdomain:
491 var name = node.id;
492 if (WebInspector.TimelineAggregator.isExtensionInternalURL(name))
493 name = WebInspector.UIString('[Chrome extensions overhead]');
494 else if (name.startsWith('chrome-extension'))
495 name = this._executionContextNamesByOrigin.get(name) || name;
496 return {name: name || WebInspector.UIString('unattributed'), color: colo r};
497
498 case WebInspector.TimelineAggregator.GroupBy.EventName:
499 var name = node.event.name === WebInspector.TimelineModel.RecordType.JSF rame ?
500 WebInspector.UIString('JavaScript') :
501 WebInspector.TimelineUIUtils.eventTitle(node.event);
502 return {
503 name: name,
504 color: node.event.name === WebInspector.TimelineModel.RecordType.JSFra me ?
505 WebInspector.TimelineUIUtils.eventStyle(node.event).category.color :
506 color
507 };
508
509 case WebInspector.TimelineAggregator.GroupBy.URL:
510 break;
511
512 default:
513 console.assert(false, 'Unexpected aggregation type');
514 }
515 return {name: node.id || WebInspector.UIString('unattributed'), color: color };
516 }
517
518 /**
519 * @override
520 * @param {!Element} parent
521 */
522 _populateToolbar(parent) {
523 var panelToolbar = new WebInspector.Toolbar('', parent);
524 this._groupByCombobox = new WebInspector.ToolbarComboBox(this._onGroupByChan ged.bind(this));
474 /** 525 /**
475 * @override 526 * @param {string} name
476 * @param {!WebInspector.TimelineSelection} selection 527 * @param {string} id
528 * @this {WebInspector.TimelineTreeView}
477 */ 529 */
478 updateContents: function(selection) 530 function addGroupingOption(name, id) {
479 { 531 var option = this._groupByCombobox.createOption(name, '', id);
480 this._updateExtensionResolver(); 532 this._groupByCombobox.addOption(option);
481 WebInspector.TimelineTreeView.prototype.updateContents.call(this, select ion); 533 if (id === this._groupBySetting.get())
482 var rootNode = this._dataGrid.rootNode(); 534 this._groupByCombobox.select(option);
483 if (rootNode.children.length) 535 }
484 rootNode.children[0].revealAndSelect(); 536 addGroupingOption.call(this, WebInspector.UIString('No Grouping'), WebInspec tor.TimelineAggregator.GroupBy.None);
485 }, 537 addGroupingOption.call(
486 538 this, WebInspector.UIString('Group by Activity'), WebInspector.TimelineA ggregator.GroupBy.EventName);
487 _updateExtensionResolver: function() 539 addGroupingOption.call(
488 { 540 this, WebInspector.UIString('Group by Category'), WebInspector.TimelineA ggregator.GroupBy.Category);
489 this._executionContextNamesByOrigin = new Map(); 541 addGroupingOption.call(
490 for (var target of WebInspector.targetManager.targets()) { 542 this, WebInspector.UIString('Group by Domain'), WebInspector.TimelineAgg regator.GroupBy.Domain);
491 for (var context of target.runtimeModel.executionContexts()) 543 addGroupingOption.call(
492 this._executionContextNamesByOrigin.set(context.origin, context. name); 544 this, WebInspector.UIString('Group by Subdomain'), WebInspector.Timeline Aggregator.GroupBy.Subdomain);
493 } 545 addGroupingOption.call(this, WebInspector.UIString('Group by URL'), WebInspe ctor.TimelineAggregator.GroupBy.URL);
494 }, 546 panelToolbar.appendToolbarItem(this._groupByCombobox);
495 547 }
496 /** 548
497 * @param {!WebInspector.TimelineProfileTree.Node} node 549 /**
498 * @return {!{name: string, color: string}} 550 * @param {!WebInspector.TimelineProfileTree.Node} treeNode
499 */ 551 * @return {!Array<!WebInspector.TimelineProfileTree.Node>}
500 _displayInfoForGroupNode: function(node) 552 */
501 { 553 _buildHeaviestStack(treeNode) {
502 var categories = WebInspector.TimelineUIUtils.categories(); 554 console.assert(!!treeNode.parent, 'Attempt to build stack for tree root');
503 var color = node.id ? WebInspector.TimelineUIUtils.eventColor(node.event ) : categories["other"].color; 555 var result = [];
504 556 // Do not add root to the stack, as it's the tree itself.
505 switch (this._groupBySetting.get()) { 557 for (var node = treeNode; node && node.parent; node = node.parent)
506 case WebInspector.TimelineAggregator.GroupBy.Category: 558 result.push(node);
507 var category = categories[node.id] || categories["other"]; 559 result = result.reverse();
508 return {name: category.title, color: category.color}; 560 for (node = treeNode; node && node.children && node.children.size;) {
509 561 var children = Array.from(node.children.values());
510 case WebInspector.TimelineAggregator.GroupBy.Domain: 562 node = children.reduce((a, b) => a.totalTime > b.totalTime ? a : b);
511 case WebInspector.TimelineAggregator.GroupBy.Subdomain: 563 result.push(node);
512 var name = node.id; 564 }
513 if (WebInspector.TimelineAggregator.isExtensionInternalURL(name)) 565 return result;
514 name = WebInspector.UIString("[Chrome extensions overhead]"); 566 }
515 else if (name.startsWith("chrome-extension")) 567
516 name = this._executionContextNamesByOrigin.get(name) || name; 568 /**
517 return { 569 * @override
518 name: name || WebInspector.UIString("unattributed"), 570 * @return {boolean}
519 color: color 571 */
520 }; 572 _exposePercentages() {
521 573 return true;
522 case WebInspector.TimelineAggregator.GroupBy.EventName: 574 }
523 var name = node.event.name === WebInspector.TimelineModel.RecordType .JSFrame ? 575
524 WebInspector.UIString("JavaScript") : WebInspector.TimelineUIUti ls.eventTitle(node.event); 576 _onGroupByChanged() {
525 return { 577 this._groupBySetting.set(this._groupByCombobox.selectedOption().value);
526 name: name, 578 this._refreshTree();
527 color: node.event.name === WebInspector.TimelineModel.RecordType .JSFrame ? 579 }
528 WebInspector.TimelineUIUtils.eventStyle(node.event).category .color : color 580
529 }; 581 _onStackViewSelectionChanged() {
530 582 var treeNode = this._stackView.selectedTreeNode();
531 case WebInspector.TimelineAggregator.GroupBy.URL: 583 if (treeNode)
532 break; 584 this.selectProfileNode(treeNode, true);
533 585 }
534 default: 586
535 console.assert(false, "Unexpected aggregation type"); 587 /**
536 } 588 * @override
537 return { 589 * @param {!WebInspector.TimelineProfileTree.Node} node
538 name: node.id || WebInspector.UIString("unattributed"), 590 * @return {boolean}
539 color: color 591 */
540 }; 592 _showDetailsForNode(node) {
541 }, 593 var stack = this._buildHeaviestStack(node);
542 594 this._stackView.setStack(stack, node);
543 /** 595 this._stackView.show(this._detailsView.element);
544 * @override 596 return true;
545 * @param {!Element} parent 597 }
546 */ 598
547 _populateToolbar: function(parent) 599 /**
548 { 600 * @return {!WebInspector.TimelineAggregator}
549 var panelToolbar = new WebInspector.Toolbar("", parent); 601 */
550 this._groupByCombobox = new WebInspector.ToolbarComboBox(this._onGroupBy Changed.bind(this)); 602 _createAggregator() {
551 /** 603 return new WebInspector.TimelineAggregator(
552 * @param {string} name 604 event => WebInspector.TimelineUIUtils.eventStyle(event).title,
553 * @param {string} id 605 event => WebInspector.TimelineUIUtils.eventStyle(event).category.name);
554 * @this {WebInspector.TimelineTreeView} 606 }
555 */
556 function addGroupingOption(name, id)
557 {
558 var option = this._groupByCombobox.createOption(name, "", id);
559 this._groupByCombobox.addOption(option);
560 if (id === this._groupBySetting.get())
561 this._groupByCombobox.select(option);
562 }
563 addGroupingOption.call(this, WebInspector.UIString("No Grouping"), WebIn spector.TimelineAggregator.GroupBy.None);
564 addGroupingOption.call(this, WebInspector.UIString("Group by Activity"), WebInspector.TimelineAggregator.GroupBy.EventName);
565 addGroupingOption.call(this, WebInspector.UIString("Group by Category"), WebInspector.TimelineAggregator.GroupBy.Category);
566 addGroupingOption.call(this, WebInspector.UIString("Group by Domain"), W ebInspector.TimelineAggregator.GroupBy.Domain);
567 addGroupingOption.call(this, WebInspector.UIString("Group by Subdomain") , WebInspector.TimelineAggregator.GroupBy.Subdomain);
568 addGroupingOption.call(this, WebInspector.UIString("Group by URL"), WebI nspector.TimelineAggregator.GroupBy.URL);
569 panelToolbar.appendToolbarItem(this._groupByCombobox);
570 },
571
572 /**
573 * @param {!WebInspector.TimelineProfileTree.Node} treeNode
574 * @return {!Array<!WebInspector.TimelineProfileTree.Node>}
575 */
576 _buildHeaviestStack: function(treeNode)
577 {
578 console.assert(!!treeNode.parent, "Attempt to build stack for tree root" );
579 var result = [];
580 // Do not add root to the stack, as it's the tree itself.
581 for (var node = treeNode; node && node.parent; node = node.parent)
582 result.push(node);
583 result = result.reverse();
584 for (node = treeNode; node && node.children && node.children.size;) {
585 var children = Array.from(node.children.values());
586 node = children.reduce((a, b) => a.totalTime > b.totalTime ? a : b);
587 result.push(node);
588 }
589 return result;
590 },
591
592 /**
593 * @override
594 * @return {boolean}
595 */
596 _exposePercentages: function()
597 {
598 return true;
599 },
600
601 _onGroupByChanged: function()
602 {
603 this._groupBySetting.set(this._groupByCombobox.selectedOption().value);
604 this._refreshTree();
605 },
606
607 _onStackViewSelectionChanged: function()
608 {
609 var treeNode = this._stackView.selectedTreeNode();
610 if (treeNode)
611 this.selectProfileNode(treeNode, true);
612 },
613
614 /**
615 * @override
616 * @param {!WebInspector.TimelineProfileTree.Node} node
617 * @return {boolean}
618 */
619 _showDetailsForNode: function(node)
620 {
621 var stack = this._buildHeaviestStack(node);
622 this._stackView.setStack(stack, node);
623 this._stackView.show(this._detailsView.element);
624 return true;
625 },
626
627 /**
628 * @return {!WebInspector.TimelineAggregator}
629 */
630 _createAggregator: function()
631 {
632 return new WebInspector.TimelineAggregator(
633 event => WebInspector.TimelineUIUtils.eventStyle(event).title,
634 event => WebInspector.TimelineUIUtils.eventStyle(event).category.nam e
635 );
636 },
637
638 __proto__: WebInspector.TimelineTreeView.prototype,
639 }; 607 };
640 608
641 /** 609 /**
642 * @constructor 610 * @unrestricted
643 * @extends {WebInspector.AggregatedTimelineTreeView}
644 * @param {!WebInspector.TimelineModel} model
645 * @param {!Array<!WebInspector.TimelineModel.Filter>} filters
646 */ 611 */
647 WebInspector.CallTreeTimelineTreeView = function(model, filters) 612 WebInspector.CallTreeTimelineTreeView = class extends WebInspector.AggregatedTim elineTreeView {
648 { 613 /**
649 WebInspector.AggregatedTimelineTreeView.call(this, model, filters); 614 * @param {!WebInspector.TimelineModel} model
650 this._dataGrid.markColumnAsSortedBy("total", WebInspector.DataGrid.Order.Des cending); 615 * @param {!Array<!WebInspector.TimelineModel.Filter>} filters
651 }; 616 */
652 617 constructor(model, filters) {
653 WebInspector.CallTreeTimelineTreeView.prototype = { 618 super(model, filters);
654 /** 619 this._dataGrid.markColumnAsSortedBy('total', WebInspector.DataGrid.Order.Des cending);
655 * @override 620 }
656 * @return {!WebInspector.TimelineProfileTree.Node} 621
657 */ 622 /**
658 _buildTree: function() 623 * @override
659 { 624 * @return {!WebInspector.TimelineProfileTree.Node}
660 var topDown = this._buildTopDownTree(WebInspector.TimelineAggregator.eve ntId); 625 */
661 return this._createAggregator().performGrouping(topDown, this._groupBySe tting.get()); 626 _buildTree() {
662 }, 627 var topDown = this._buildTopDownTree(WebInspector.TimelineAggregator.eventId );
663 628 return this._createAggregator().performGrouping(topDown, this._groupBySettin g.get());
664 __proto__: WebInspector.AggregatedTimelineTreeView.prototype, 629 }
665 }; 630 };
666 631
667 /** 632 /**
668 * @constructor 633 * @unrestricted
669 * @extends {WebInspector.AggregatedTimelineTreeView}
670 * @param {!WebInspector.TimelineModel} model
671 * @param {!Array<!WebInspector.TimelineModel.Filter>} filters
672 */ 634 */
673 WebInspector.BottomUpTimelineTreeView = function(model, filters) 635 WebInspector.BottomUpTimelineTreeView = class extends WebInspector.AggregatedTim elineTreeView {
674 { 636 /**
675 WebInspector.AggregatedTimelineTreeView.call(this, model, filters); 637 * @param {!WebInspector.TimelineModel} model
676 this._dataGrid.markColumnAsSortedBy("self", WebInspector.DataGrid.Order.Desc ending); 638 * @param {!Array<!WebInspector.TimelineModel.Filter>} filters
677 }; 639 */
678 640 constructor(model, filters) {
679 WebInspector.BottomUpTimelineTreeView.prototype = { 641 super(model, filters);
680 /** 642 this._dataGrid.markColumnAsSortedBy('self', WebInspector.DataGrid.Order.Desc ending);
681 * @override 643 }
682 * @return {!WebInspector.TimelineProfileTree.Node} 644
683 */ 645 /**
684 _buildTree: function() 646 * @override
685 { 647 * @return {!WebInspector.TimelineProfileTree.Node}
686 var topDown = this._buildTopDownTree(WebInspector.TimelineAggregator.eve ntId); 648 */
687 return WebInspector.TimelineProfileTree.buildBottomUp(topDown, this._cre ateAggregator().groupFunction(this._groupBySetting.get())); 649 _buildTree() {
688 }, 650 var topDown = this._buildTopDownTree(WebInspector.TimelineAggregator.eventId );
689 651 return WebInspector.TimelineProfileTree.buildBottomUp(
690 __proto__: WebInspector.AggregatedTimelineTreeView.prototype 652 topDown, this._createAggregator().groupFunction(this._groupBySetting.get ()));
653 }
691 }; 654 };
692 655
693 /** 656 /**
694 * @constructor 657 * @unrestricted
695 * @extends {WebInspector.TimelineTreeView}
696 * @param {!WebInspector.TimelineModel} model
697 * @param {!Array<!WebInspector.TimelineModel.Filter>} filters
698 * @param {!WebInspector.TimelineModeViewDelegate} delegate
699 */ 658 */
700 WebInspector.EventsTimelineTreeView = function(model, filters, delegate) 659 WebInspector.EventsTimelineTreeView = class extends WebInspector.TimelineTreeVie w {
701 { 660 /**
702 WebInspector.TimelineTreeView.call(this); 661 * @param {!WebInspector.TimelineModel} model
662 * @param {!Array<!WebInspector.TimelineModel.Filter>} filters
663 * @param {!WebInspector.TimelineModeViewDelegate} delegate
664 */
665 constructor(model, filters, delegate) {
666 super();
703 this._filtersControl = new WebInspector.TimelineFilters(); 667 this._filtersControl = new WebInspector.TimelineFilters();
704 this._filtersControl.addEventListener(WebInspector.TimelineFilters.Events.Fi lterChanged, this._onFilterChanged, this); 668 this._filtersControl.addEventListener(
669 WebInspector.TimelineFilters.Events.FilterChanged, this._onFilterChanged , this);
705 this._init(model, filters); 670 this._init(model, filters);
706 this._delegate = delegate; 671 this._delegate = delegate;
707 this._filters.push.apply(this._filters, this._filtersControl.filters()); 672 this._filters.push.apply(this._filters, this._filtersControl.filters());
708 this._dataGrid.markColumnAsSortedBy("startTime", WebInspector.DataGrid.Order .Ascending); 673 this._dataGrid.markColumnAsSortedBy('startTime', WebInspector.DataGrid.Order .Ascending);
709 }; 674 }
710 675
711 WebInspector.EventsTimelineTreeView.prototype = { 676 /**
677 * @override
678 * @param {!WebInspector.TimelineSelection} selection
679 */
680 updateContents(selection) {
681 super.updateContents(selection);
682 if (selection.type() === WebInspector.TimelineSelection.Type.TraceEvent) {
683 var event = /** @type {!WebInspector.TracingModel.Event} */ (selection.obj ect());
684 this._selectEvent(event, true);
685 }
686 }
687
688 /**
689 * @override
690 * @return {!WebInspector.TimelineProfileTree.Node}
691 */
692 _buildTree() {
693 this._currentTree = this._buildTopDownTree();
694 return this._currentTree;
695 }
696
697 _onFilterChanged() {
698 var selectedEvent = this._lastSelectedNode && this._lastSelectedNode.event;
699 this._refreshTree();
700 if (selectedEvent)
701 this._selectEvent(selectedEvent, false);
702 }
703
704 /**
705 * @param {!WebInspector.TracingModel.Event} event
706 * @return {?WebInspector.TimelineProfileTree.Node}
707 */
708 _findNodeWithEvent(event) {
709 var iterators = [this._currentTree.children.values()];
710
711 while (iterators.length) {
712 var iterator = iterators.peekLast().next();
713 if (iterator.done) {
714 iterators.pop();
715 continue;
716 }
717 var child = /** @type {!WebInspector.TimelineProfileTree.Node} */ (iterato r.value);
718 if (child.event === event)
719 return child;
720 if (child.children)
721 iterators.push(child.children.values());
722 }
723 return null;
724 }
725
726 /**
727 * @param {!WebInspector.TracingModel.Event} event
728 * @param {boolean=} expand
729 */
730 _selectEvent(event, expand) {
731 var node = this._findNodeWithEvent(event);
732 if (!node)
733 return;
734 this.selectProfileNode(node, false);
735 if (expand)
736 this._dataGridNodeForTreeNode(node).expand();
737 }
738
739 /**
740 * @override
741 * @param {!Array<!WebInspector.DataGrid.ColumnDescriptor>} columns
742 */
743 _populateColumns(columns) {
744 columns.push({
745 id: 'startTime',
746 title: WebInspector.UIString('Start Time'),
747 width: '110px',
748 fixedWidth: true,
749 sortable: true
750 });
751 super._populateColumns(columns);
752 }
753
754 /**
755 * @override
756 * @param {!Element} parent
757 */
758 _populateToolbar(parent) {
759 var filtersWidget = this._filtersControl.filtersWidget();
760 filtersWidget.forceShowFilterBar();
761 filtersWidget.show(parent);
762 }
763
764 /**
765 * @override
766 * @param {!WebInspector.TimelineProfileTree.Node} node
767 * @return {boolean}
768 */
769 _showDetailsForNode(node) {
770 var traceEvent = node.event;
771 if (!traceEvent)
772 return false;
773 WebInspector.TimelineUIUtils.buildTraceEventDetails(
774 traceEvent, this._model, this._linkifier, false, showDetails.bind(this)) ;
775 return true;
776
712 /** 777 /**
713 * @override 778 * @param {!DocumentFragment} fragment
714 * @param {!WebInspector.TimelineSelection} selection 779 * @this {WebInspector.EventsTimelineTreeView}
715 */ 780 */
716 updateContents: function(selection) 781 function showDetails(fragment) {
717 { 782 this._detailsView.element.appendChild(fragment);
718 WebInspector.TimelineTreeView.prototype.updateContents.call(this, select ion); 783 }
719 if (selection.type() === WebInspector.TimelineSelection.Type.TraceEvent) { 784 }
720 var event = /** @type {!WebInspector.TracingModel.Event} */ (selecti on.object()); 785
721 this._selectEvent(event, true); 786 /**
722 } 787 * @override
723 }, 788 * @param {?WebInspector.TimelineProfileTree.Node} node
724 789 */
725 /** 790 _onHover(node) {
726 * @override 791 this._delegate.highlightEvent(node && node.event);
727 * @return {!WebInspector.TimelineProfileTree.Node} 792 }
728 */
729 _buildTree: function()
730 {
731 this._currentTree = this._buildTopDownTree();
732 return this._currentTree;
733 },
734
735 _onFilterChanged: function()
736 {
737 var selectedEvent = this._lastSelectedNode && this._lastSelectedNode.eve nt;
738 this._refreshTree();
739 if (selectedEvent)
740 this._selectEvent(selectedEvent, false);
741 },
742
743 /**
744 * @param {!WebInspector.TracingModel.Event} event
745 * @return {?WebInspector.TimelineProfileTree.Node}
746 */
747 _findNodeWithEvent: function(event)
748 {
749 var iterators = [this._currentTree.children.values()];
750
751 while (iterators.length) {
752 var iterator = iterators.peekLast().next();
753 if (iterator.done) {
754 iterators.pop();
755 continue;
756 }
757 var child = /** @type {!WebInspector.TimelineProfileTree.Node} */ (i terator.value);
758 if (child.event === event)
759 return child;
760 if (child.children)
761 iterators.push(child.children.values());
762 }
763 return null;
764 },
765
766 /**
767 * @param {!WebInspector.TracingModel.Event} event
768 * @param {boolean=} expand
769 */
770 _selectEvent: function(event, expand)
771 {
772 var node = this._findNodeWithEvent(event);
773 if (!node)
774 return;
775 this.selectProfileNode(node, false);
776 if (expand)
777 this._dataGridNodeForTreeNode(node).expand();
778 },
779
780 /**
781 * @override
782 * @param {!Array<!WebInspector.DataGrid.ColumnDescriptor>} columns
783 */
784 _populateColumns: function(columns)
785 {
786 columns.push({id: "startTime", title: WebInspector.UIString("Start Time" ), width: "110px", fixedWidth: true, sortable: true});
787 WebInspector.TimelineTreeView.prototype._populateColumns.call(this, colu mns);
788 },
789
790 /**
791 * @override
792 * @param {!Element} parent
793 */
794 _populateToolbar: function(parent)
795 {
796 var filtersWidget = this._filtersControl.filtersWidget();
797 filtersWidget.forceShowFilterBar();
798 filtersWidget.show(parent);
799 },
800
801 /**
802 * @override
803 * @param {!WebInspector.TimelineProfileTree.Node} node
804 * @return {boolean}
805 */
806 _showDetailsForNode: function(node)
807 {
808 var traceEvent = node.event;
809 if (!traceEvent)
810 return false;
811 WebInspector.TimelineUIUtils.buildTraceEventDetails(traceEvent, this._mo del, this._linkifier, false, showDetails.bind(this));
812 return true;
813
814 /**
815 * @param {!DocumentFragment} fragment
816 * @this {WebInspector.EventsTimelineTreeView}
817 */
818 function showDetails(fragment)
819 {
820 this._detailsView.element.appendChild(fragment);
821 }
822 },
823
824 /**
825 * @override
826 * @param {?WebInspector.TimelineProfileTree.Node} node
827 */
828 _onHover: function(node)
829 {
830 this._delegate.highlightEvent(node && node.event);
831 },
832
833 __proto__: WebInspector.TimelineTreeView.prototype
834 }; 793 };
835 794
836 /** 795 /**
837 * @constructor 796 * @unrestricted
838 * @extends {WebInspector.VBox}
839 */ 797 */
840 WebInspector.TimelineStackView = function(treeView) 798 WebInspector.TimelineStackView = class extends WebInspector.VBox {
841 { 799 constructor(treeView) {
842 WebInspector.VBox.call(this); 800 super();
843 var header = this.element.createChild("div", "timeline-stack-view-header"); 801 var header = this.element.createChild('div', 'timeline-stack-view-header');
844 header.textContent = WebInspector.UIString("Heaviest stack"); 802 header.textContent = WebInspector.UIString('Heaviest stack');
845 this._treeView = treeView; 803 this._treeView = treeView;
846 var columns = /** @type {!Array<!WebInspector.DataGrid.ColumnDescriptor>} */ ([ 804 var columns = /** @type {!Array<!WebInspector.DataGrid.ColumnDescriptor>} */ ([
847 {id: "total", title: WebInspector.UIString("Total Time"), fixedWidth: tr ue, width: "110px"}, 805 {id: 'total', title: WebInspector.UIString('Total Time'), fixedWidth: true , width: '110px'},
848 {id: "activity", title: WebInspector.UIString("Activity")} 806 {id: 'activity', title: WebInspector.UIString('Activity')}
849 ]); 807 ]);
850 this._dataGrid = new WebInspector.ViewportDataGrid(columns); 808 this._dataGrid = new WebInspector.ViewportDataGrid(columns);
851 this._dataGrid.setResizeMethod(WebInspector.DataGrid.ResizeMethod.Last); 809 this._dataGrid.setResizeMethod(WebInspector.DataGrid.ResizeMethod.Last);
852 this._dataGrid.addEventListener(WebInspector.DataGrid.Events.SelectedNode, t his._onSelectionChanged, this); 810 this._dataGrid.addEventListener(WebInspector.DataGrid.Events.SelectedNode, t his._onSelectionChanged, this);
853 this._dataGrid.asWidget().show(this.element); 811 this._dataGrid.asWidget().show(this.element);
812 }
813
814 /**
815 * @param {!Array<!WebInspector.TimelineProfileTree.Node>} stack
816 * @param {!WebInspector.TimelineProfileTree.Node} selectedNode
817 */
818 setStack(stack, selectedNode) {
819 var rootNode = this._dataGrid.rootNode();
820 rootNode.removeChildren();
821 var nodeToReveal = null;
822 var totalTime = Math.max.apply(Math, stack.map(node => node.totalTime));
823 for (var node of stack) {
824 var gridNode = new WebInspector.TimelineTreeView.GridNode(node, totalTime, totalTime, totalTime, this._treeView);
825 rootNode.appendChild(gridNode);
826 if (node === selectedNode)
827 nodeToReveal = gridNode;
828 }
829 nodeToReveal.revealAndSelect();
830 }
831
832 /**
833 * @return {?WebInspector.TimelineProfileTree.Node}
834 */
835 selectedTreeNode() {
836 var selectedNode = this._dataGrid.selectedNode;
837 return selectedNode && /** @type {!WebInspector.TimelineTreeView.GridNode} * / (selectedNode)._profileNode;
838 }
839
840 _onSelectionChanged() {
841 this.dispatchEventToListeners(WebInspector.TimelineStackView.Events.Selectio nChanged);
842 }
854 }; 843 };
855 844
856 /** @enum {symbol} */ 845 /** @enum {symbol} */
857 WebInspector.TimelineStackView.Events = { 846 WebInspector.TimelineStackView.Events = {
858 SelectionChanged: Symbol("SelectionChanged") 847 SelectionChanged: Symbol('SelectionChanged')
859 }; 848 };
860
861 WebInspector.TimelineStackView.prototype = {
862 /**
863 * @param {!Array<!WebInspector.TimelineProfileTree.Node>} stack
864 * @param {!WebInspector.TimelineProfileTree.Node} selectedNode
865 */
866 setStack: function(stack, selectedNode)
867 {
868 var rootNode = this._dataGrid.rootNode();
869 rootNode.removeChildren();
870 var nodeToReveal = null;
871 var totalTime = Math.max.apply(Math, stack.map(node => node.totalTime));
872 for (var node of stack) {
873 var gridNode = new WebInspector.TimelineTreeView.GridNode(node, tota lTime, totalTime, totalTime, this._treeView);
874 rootNode.appendChild(gridNode);
875 if (node === selectedNode)
876 nodeToReveal = gridNode;
877 }
878 nodeToReveal.revealAndSelect();
879 },
880
881 /**
882 * @return {?WebInspector.TimelineProfileTree.Node}
883 */
884 selectedTreeNode: function()
885 {
886 var selectedNode = this._dataGrid.selectedNode;
887 return selectedNode && /** @type {!WebInspector.TimelineTreeView.GridNod e} */ (selectedNode)._profileNode;
888 },
889
890 _onSelectionChanged: function()
891 {
892 this.dispatchEventToListeners(WebInspector.TimelineStackView.Events.Sele ctionChanged);
893 },
894
895 __proto__: WebInspector.VBox.prototype
896 };
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698