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

Side by Side Diff: Source/devtools/front_end/timeline/TimelineView.js

Issue 270693003: Timeline: make frames in TimelineView selectable (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 6 years, 7 months 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 | Annotate | Revision Log
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2013 Google Inc. All rights reserved. 2 * Copyright (C) 2013 Google Inc. All rights reserved.
3 * Copyright (C) 2012 Intel Inc. All rights reserved. 3 * Copyright (C) 2012 Intel Inc. All rights reserved.
4 * 4 *
5 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are 6 * modification, are permitted provided that the following conditions are
7 * met: 7 * met:
8 * 8 *
9 * * Redistributions of source code must retain the above copyright 9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer. 10 * notice, this list of conditions and the following disclaimer.
(...skipping 28 matching lines...) Expand all
39 WebInspector.TimelineView = function(delegate, model) 39 WebInspector.TimelineView = function(delegate, model)
40 { 40 {
41 WebInspector.HBox.call(this); 41 WebInspector.HBox.call(this);
42 this.element.classList.add("timeline-view"); 42 this.element.classList.add("timeline-view");
43 43
44 this._delegate = delegate; 44 this._delegate = delegate;
45 this._model = model; 45 this._model = model;
46 this._presentationModel = new WebInspector.TimelinePresentationModel(model); 46 this._presentationModel = new WebInspector.TimelinePresentationModel(model);
47 this._calculator = new WebInspector.TimelineCalculator(model); 47 this._calculator = new WebInspector.TimelineCalculator(model);
48 this._linkifier = new WebInspector.Linkifier(); 48 this._linkifier = new WebInspector.Linkifier();
49 this._frameStripByFrame = new Map();
49 50
50 this._boundariesAreValid = true; 51 this._boundariesAreValid = true;
51 this._scrollTop = 0; 52 this._scrollTop = 0;
52 53
53 this._recordsView = this._createRecordsView(); 54 this._recordsView = this._createRecordsView();
54 this._recordsView.addEventListener(WebInspector.SplitView.Events.SidebarSize Changed, this._sidebarResized, this); 55 this._recordsView.addEventListener(WebInspector.SplitView.Events.SidebarSize Changed, this._sidebarResized, this);
55 this._recordsView.show(this.element); 56 this._recordsView.show(this.element);
56 this._headerElement = this.element.createChild("div", "fill"); 57 this._headerElement = this.element.createChild("div", "fill");
57 this._headerElement.id = "timeline-graph-records-header"; 58 this._headerElement.id = "timeline-graph-records-header";
58 59
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
135 var divider = WebInspector.TimelineUIUtils.createEventDivider(record .type(), WebInspector.TimelineUIUtils.recordTitle(record, this._model)); 136 var divider = WebInspector.TimelineUIUtils.createEventDivider(record .type(), WebInspector.TimelineUIUtils.recordTitle(record, this._model));
136 divider.style.left = dividerPosition + "px"; 137 divider.style.left = dividerPosition + "px";
137 dividers[dividerPosition] = divider; 138 dividers[dividerPosition] = divider;
138 } 139 }
139 this._timelineGrid.addEventDividers(dividers); 140 this._timelineGrid.addEventDividers(dividers);
140 }, 141 },
141 142
142 _updateFrameBars: function(frames) 143 _updateFrameBars: function(frames)
143 { 144 {
144 var clientWidth = this._graphRowsElementWidth; 145 var clientWidth = this._graphRowsElementWidth;
145 if (this._frameContainer) 146 if (this._frameContainer) {
146 this._frameContainer.removeChildren(); 147 this._frameContainer.removeChildren();
147 else { 148 } else {
148 const frameContainerBorderWidth = 1; 149 const frameContainerBorderWidth = 1;
149 this._frameContainer = document.createElement("div"); 150 this._frameContainer = document.createElement("div");
150 this._frameContainer.classList.add("fill"); 151 this._frameContainer.classList.add("fill");
151 this._frameContainer.classList.add("timeline-frame-container"); 152 this._frameContainer.classList.add("timeline-frame-container");
152 this._frameContainer.style.height = WebInspector.TimelinePanel.rowHe ight + frameContainerBorderWidth + "px"; 153 this._frameContainer.style.height = WebInspector.TimelinePanel.rowHe ight + frameContainerBorderWidth + "px";
153 this._frameContainer.addEventListener("dblclick", this._onFrameDoubl eClicked.bind(this), false); 154 this._frameContainer.addEventListener("dblclick", this._onFrameDoubl eClicked.bind(this), false);
155 this._frameContainer.addEventListener("click", this._onFrameClicked. bind(this), false);
154 } 156 }
157 this._frameStripByFrame.clear();
155 158
156 var dividers = []; 159 var dividers = [];
157 160
158 for (var i = 0; i < frames.length; ++i) { 161 for (var i = 0; i < frames.length; ++i) {
159 var frame = frames[i]; 162 var frame = frames[i];
160 var frameStart = this._calculator.computePosition(frame.startTime); 163 var frameStart = this._calculator.computePosition(frame.startTime);
161 var frameEnd = this._calculator.computePosition(frame.endTime); 164 var frameEnd = this._calculator.computePosition(frame.endTime);
162 165
163 var frameStrip = document.createElement("div"); 166 var frameStrip = document.createElement("div");
164 frameStrip.className = "timeline-frame-strip"; 167 frameStrip.className = "timeline-frame-strip";
165 var actualStart = Math.max(frameStart, 0); 168 var actualStart = Math.max(frameStart, 0);
166 var width = frameEnd - actualStart; 169 var width = frameEnd - actualStart;
167 frameStrip.style.left = actualStart + "px"; 170 frameStrip.style.left = actualStart + "px";
168 frameStrip.style.width = width + "px"; 171 frameStrip.style.width = width + "px";
169 frameStrip._frame = frame; 172 frameStrip._frame = frame;
173 this._frameStripByFrame.put(frame, frameStrip);
170 174
171 const minWidthForFrameInfo = 60; 175 const minWidthForFrameInfo = 60;
172 if (width > minWidthForFrameInfo) 176 if (width > minWidthForFrameInfo)
173 frameStrip.textContent = Number.millisToString(frame.endTime - f rame.startTime, true); 177 frameStrip.textContent = Number.millisToString(frame.endTime - f rame.startTime, true);
174 178
175 this._frameContainer.appendChild(frameStrip); 179 this._frameContainer.appendChild(frameStrip);
176 180
177 if (actualStart > 0) { 181 if (actualStart > 0) {
178 var frameMarker = WebInspector.TimelineUIUtils.createEventDivide r(WebInspector.TimelineModel.RecordType.BeginFrame); 182 var frameMarker = WebInspector.TimelineUIUtils.createEventDivide r(WebInspector.TimelineModel.RecordType.BeginFrame);
179 frameMarker.style.left = frameStart + "px"; 183 frameMarker.style.left = frameStart + "px";
180 dividers.push(frameMarker); 184 dividers.push(frameMarker);
181 } 185 }
182 } 186 }
183 this._timelineGrid.addEventDividers(dividers); 187 this._timelineGrid.addEventDividers(dividers);
184 this._headerElement.appendChild(this._frameContainer); 188 this._headerElement.appendChild(this._frameContainer);
185 }, 189 },
186 190
187 _onFrameDoubleClicked: function(event) 191 _onFrameDoubleClicked: function(event)
188 { 192 {
189 var frameBar = event.target.enclosingNodeOrSelfWithClass("timeline-frame -strip"); 193 var frameBar = event.target.enclosingNodeOrSelfWithClass("timeline-frame -strip");
190 if (!frameBar) 194 if (!frameBar)
191 return; 195 return;
192 this._delegate.requestWindowTimes(frameBar._frame.startTime, frameBar._f rame.endTime); 196 this._delegate.requestWindowTimes(frameBar._frame.startTime, frameBar._f rame.endTime);
193 }, 197 },
194 198
199 _onFrameClicked: function(event)
200 {
201 var frameBar = event.target.enclosingNodeOrSelfWithClass("timeline-frame -strip");
202 if (!frameBar)
203 return;
204 this._delegate.select(WebInspector.TimelineSelection.fromFrame(frameBar. _frame));
205 },
206
195 /** 207 /**
196 * @param {!WebInspector.TimelineModel.Record} record 208 * @param {!WebInspector.TimelineModel.Record} record
197 */ 209 */
198 addRecord: function(record) 210 addRecord: function(record)
199 { 211 {
200 this._presentationModel.addRecord(record); 212 this._presentationModel.addRecord(record);
201 this._invalidateAndScheduleRefresh(false, false); 213 this._invalidateAndScheduleRefresh(false, false);
202 }, 214 },
203 215
204 /** 216 /**
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
305 /** 317 /**
306 * @param {boolean} preserveBoundaries 318 * @param {boolean} preserveBoundaries
307 * @param {boolean} userGesture 319 * @param {boolean} userGesture
308 */ 320 */
309 _invalidateAndScheduleRefresh: function(preserveBoundaries, userGesture) 321 _invalidateAndScheduleRefresh: function(preserveBoundaries, userGesture)
310 { 322 {
311 this._presentationModel.invalidateFilteredRecords(); 323 this._presentationModel.invalidateFilteredRecords();
312 this._scheduleRefresh(preserveBoundaries, userGesture); 324 this._scheduleRefresh(preserveBoundaries, userGesture);
313 }, 325 },
314 326
327 _clearSelection: function()
328 {
329 this._delegate.select(null);
330 },
331
315 /** 332 /**
316 * @param {?WebInspector.TimelinePresentationModel.Record} presentationRecor d 333 * @param {?WebInspector.TimelinePresentationModel.Record} presentationRecor d
317 */ 334 */
318 _selectRecord: function(presentationRecord) 335 _selectRecord: function(presentationRecord)
319 { 336 {
320 if (presentationRecord && presentationRecord.coalesced()) { 337 if (presentationRecord.coalesced()) {
321 // Presentation record does not have model record to highlight. 338 // Presentation record does not have model record to highlight.
322 this._innerSetSelectedRecord(presentationRecord); 339 this._innerSetSelectedRecord(presentationRecord);
323 var aggregatedStats = {}; 340 var aggregatedStats = {};
324 var presentationChildren = presentationRecord.presentationChildren() ; 341 var presentationChildren = presentationRecord.presentationChildren() ;
325 for (var i = 0; i < presentationChildren.length; ++i) 342 for (var i = 0; i < presentationChildren.length; ++i)
326 WebInspector.TimelineUIUtils.aggregateTimeByCategory(aggregatedS tats, presentationChildren[i].record().aggregatedStats); 343 WebInspector.TimelineUIUtils.aggregateTimeByCategory(aggregatedS tats, presentationChildren[i].record().aggregatedStats);
327 var idle = presentationRecord.record().endTime() - presentationRecor d.record().startTime(); 344 var idle = presentationRecord.record().endTime() - presentationRecor d.record().startTime();
328 for (var category in aggregatedStats) 345 for (var category in aggregatedStats)
329 idle -= aggregatedStats[category]; 346 idle -= aggregatedStats[category];
330 aggregatedStats["idle"] = idle; 347 aggregatedStats["idle"] = idle;
331 var pieChart = WebInspector.TimelineUIUtils.generatePieChart(aggrega tedStats); 348 var pieChart = WebInspector.TimelineUIUtils.generatePieChart(aggrega tedStats);
332 this._delegate.showInDetails(WebInspector.TimelineUIUtils.recordStyl e(presentationRecord.record()).title, pieChart); 349 this._delegate.showInDetails(WebInspector.TimelineUIUtils.recordStyl e(presentationRecord.record()).title, pieChart);
333 return; 350 return;
334 } 351 }
335 this._delegate.selectRecord(presentationRecord ? presentationRecord.reco rd() : null); 352 this._delegate.select(WebInspector.TimelineSelection.fromRecord(presenta tionRecord.record()));
336 }, 353 },
337 354
338 /** 355 /**
339 * @param {?WebInspector.TimelineModel.Record} record 356 * @param {?WebInspector.TimelineSelection} selection
340 */ 357 */
341 setSelectedRecord: function(record) 358 setSelection: function(selection)
342 { 359 {
343 this._innerSetSelectedRecord(this._presentationModel.toPresentationRecor d(record)); 360 if (!selection) {
361 this._innerSetSelectedRecord(null);
362 this._setSelectedFrame(null);
363 return;
364 }
365 if (selection.type() === WebInspector.TimelineSelection.Type.Record) {
366 var record = /** @type {!WebInspector.TimelineModel.Record} */ (sele ction.object());
367 this._innerSetSelectedRecord(this._presentationModel.toPresentationR ecord(record));
368 this._setSelectedFrame(null);
369 } else if (selection.type() === WebInspector.TimelineSelection.Type.Fram e) {
370 var frame = /** @type {!WebInspector.TimelineFrame} */ (selection.ob ject());
371 this._innerSetSelectedRecord(null);
372 this._setSelectedFrame(frame);
373 }
344 }, 374 },
345 375
346 /** 376 /**
347 * @param {?WebInspector.TimelinePresentationModel.Record} presentationRecor d 377 * @param {?WebInspector.TimelinePresentationModel.Record} presentationRecor d
348 */ 378 */
349 _innerSetSelectedRecord: function(presentationRecord) 379 _innerSetSelectedRecord: function(presentationRecord)
350 { 380 {
351 if (presentationRecord === this._lastSelectedRecord) 381 if (presentationRecord === this._lastSelectedRecord)
352 return; 382 return;
353 383
(...skipping 10 matching lines...) Expand all
364 return; 394 return;
365 395
366 this._innerRevealRecord(presentationRecord); 396 this._innerRevealRecord(presentationRecord);
367 if (presentationRecord.listRow()) 397 if (presentationRecord.listRow())
368 presentationRecord.listRow().renderAsSelected(true); 398 presentationRecord.listRow().renderAsSelected(true);
369 if (presentationRecord.graphRow()) 399 if (presentationRecord.graphRow())
370 presentationRecord.graphRow().renderAsSelected(true); 400 presentationRecord.graphRow().renderAsSelected(true);
371 }, 401 },
372 402
373 /** 403 /**
404 * @param {?WebInspector.TimelineFrame} frame
405 */
406 _setSelectedFrame: function(frame)
407 {
408 if (this._lastSelectedFrame === frame)
409 return;
410 var oldStripElement = this._lastSelectedFrame && this._frameStripByFrame .get(this._lastSelectedFrame);
411 if (oldStripElement)
412 oldStripElement.classList.remove("selected");
413 var newStripElement = frame && this._frameStripByFrame.get(frame);
414 if (newStripElement)
415 newStripElement.classList.add("selected");
416 this._lastSelectedFrame = frame;
417 },
418
419 /**
374 * @param {number} startTime 420 * @param {number} startTime
375 * @param {number} endTime 421 * @param {number} endTime
376 */ 422 */
377 setWindowTimes: function(startTime, endTime) 423 setWindowTimes: function(startTime, endTime)
378 { 424 {
379 this._windowStartTime = startTime; 425 this._windowStartTime = startTime;
380 this._windowEndTime = endTime; 426 this._windowEndTime = endTime;
381 this._presentationModel.setWindowTimes(startTime, endTime); 427 this._presentationModel.setWindowTimes(startTime, endTime);
382 this._automaticallySizeWindow = false; 428 this._automaticallySizeWindow = false;
383 this._invalidateAndScheduleRefresh(false, true); 429 this._invalidateAndScheduleRefresh(false, true);
384 this._selectRecord(null); 430 this._clearSelection();
385 }, 431 },
386 432
387 /** 433 /**
388 * @param {boolean} preserveBoundaries 434 * @param {boolean} preserveBoundaries
389 * @param {boolean} userGesture 435 * @param {boolean} userGesture
390 */ 436 */
391 _scheduleRefresh: function(preserveBoundaries, userGesture) 437 _scheduleRefresh: function(preserveBoundaries, userGesture)
392 { 438 {
393 this._closeRecordDetails(); 439 this._closeRecordDetails();
394 this._boundariesAreValid &= preserveBoundaries; 440 this._boundariesAreValid &= preserveBoundaries;
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
480 526
481 var rowHeight = WebInspector.TimelinePanel.rowHeight; 527 var rowHeight = WebInspector.TimelinePanel.rowHeight;
482 var headerHeight = WebInspector.TimelinePanel.headerHeight; 528 var headerHeight = WebInspector.TimelinePanel.headerHeight;
483 529
484 // Convert visible area to visible indexes. Always include top-level rec ord for a visible nested record. 530 // Convert visible area to visible indexes. Always include top-level rec ord for a visible nested record.
485 var startIndex = Math.max(0, Math.min(Math.floor((visibleTop - headerHei ght) / rowHeight), recordsInWindow.length - 1)); 531 var startIndex = Math.max(0, Math.min(Math.floor((visibleTop - headerHei ght) / rowHeight), recordsInWindow.length - 1));
486 var endIndex = Math.min(recordsInWindow.length, Math.ceil(visibleBottom / rowHeight)); 532 var endIndex = Math.min(recordsInWindow.length, Math.ceil(visibleBottom / rowHeight));
487 var lastVisibleLine = Math.max(0, Math.floor((visibleBottom - headerHeig ht) / rowHeight)); 533 var lastVisibleLine = Math.max(0, Math.floor((visibleBottom - headerHeig ht) / rowHeight));
488 if (this._automaticallySizeWindow && recordsInWindow.length > lastVisibl eLine) { 534 if (this._automaticallySizeWindow && recordsInWindow.length > lastVisibl eLine) {
489 this._automaticallySizeWindow = false; 535 this._automaticallySizeWindow = false;
490 this._selectRecord(null); 536 this._clearSelection();
491 // If we're at the top, always use real timeline start as a left win dow bound so that expansion arrow padding logic works. 537 // If we're at the top, always use real timeline start as a left win dow bound so that expansion arrow padding logic works.
492 var windowStartTime = startIndex ? recordsInWindow[startIndex].recor d().startTime() : this._model.minimumRecordTime(); 538 var windowStartTime = startIndex ? recordsInWindow[startIndex].recor d().startTime() : this._model.minimumRecordTime();
493 var windowEndTime = recordsInWindow[Math.max(0, lastVisibleLine - 1) ].record().endTime(); 539 var windowEndTime = recordsInWindow[Math.max(0, lastVisibleLine - 1) ].record().endTime();
494 this._delegate.requestWindowTimes(windowStartTime, windowEndTime); 540 this._delegate.requestWindowTimes(windowStartTime, windowEndTime);
495 recordsInWindow = this._presentationModel.filteredRecords(); 541 recordsInWindow = this._presentationModel.filteredRecords();
496 endIndex = Math.min(recordsInWindow.length, lastVisibleLine); 542 endIndex = Math.min(recordsInWindow.length, lastVisibleLine);
497 } 543 }
498 544
499 // Resize gaps first. 545 // Resize gaps first.
500 this._topGapElement.style.height = (startIndex * rowHeight) + "px"; 546 this._topGapElement.style.height = (startIndex * rowHeight) + "px";
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after
663 // Prevent the container from being scrolled off the end. 709 // Prevent the container from being scrolled off the end.
664 if ((this._scrollTop + this._containerElementHeight) > totalHeight + 1) 710 if ((this._scrollTop + this._containerElementHeight) > totalHeight + 1)
665 this._containerElement.scrollTop = (totalHeight - this._containerEle ment.offsetHeight); 711 this._containerElement.scrollTop = (totalHeight - this._containerEle ment.offsetHeight);
666 }, 712 },
667 713
668 _getPopoverAnchor: function(element) 714 _getPopoverAnchor: function(element)
669 { 715 {
670 var anchor = element.enclosingNodeOrSelfWithClass("timeline-graph-bar"); 716 var anchor = element.enclosingNodeOrSelfWithClass("timeline-graph-bar");
671 if (anchor && anchor._tasksInfo) 717 if (anchor && anchor._tasksInfo)
672 return anchor; 718 return anchor;
673 return element.enclosingNodeOrSelfWithClass("timeline-frame-strip"); 719 return null;
674 }, 720 },
675 721
676 _mouseOut: function() 722 _mouseOut: function()
677 { 723 {
678 this._hideQuadHighlight(); 724 this._hideQuadHighlight();
679 }, 725 },
680 726
681 /** 727 /**
682 * @param {?Event} e 728 * @param {?Event} e
683 */ 729 */
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
795 delete this._highlightedQuadRecord; 841 delete this._highlightedQuadRecord;
796 } 842 }
797 }, 843 },
798 844
799 /** 845 /**
800 * @param {!Element} anchor 846 * @param {!Element} anchor
801 * @param {!WebInspector.Popover} popover 847 * @param {!WebInspector.Popover} popover
802 */ 848 */
803 _showPopover: function(anchor, popover) 849 _showPopover: function(anchor, popover)
804 { 850 {
805 if (anchor.classList.contains("timeline-frame-strip")) { 851 if (!anchor._tasksInfo)
806 var frame = anchor._frame; 852 return;
807 popover.show(WebInspector.TimelineUIUtils.generatePopupContentForFra me(frame), anchor); 853 popover.show(WebInspector.TimelineUIUtils.generateMainThreadBarPopupCont ent(this._model, anchor._tasksInfo), anchor, null, null, WebInspector.Popover.Or ientation.Bottom);
808 } else if (anchor._tasksInfo) {
809 popover.show(WebInspector.TimelineUIUtils.generateMainThreadBarPopup Content(this._model, anchor._tasksInfo), anchor, null, null, WebInspector.Popove r.Orientation.Bottom);
810 }
811
812 function showCallback(popupContent)
813 {
814 popover.show(popupContent, anchor);
815 }
816 }, 854 },
817 855
818 _closeRecordDetails: function() 856 _closeRecordDetails: function()
819 { 857 {
820 this._popoverHelper.hidePopover(); 858 this._popoverHelper.hidePopover();
821 }, 859 },
822 860
823 /** 861 /**
824 * @param {?WebInspector.TimelineModel.Record} record 862 * @param {?WebInspector.TimelineModel.Record} record
825 * @param {string=} regex 863 * @param {string=} regex
(...skipping 418 matching lines...) Expand 10 before | Expand all | Expand 10 after
1244 this._element.classList.remove("hidden"); 1282 this._element.classList.remove("hidden");
1245 } else 1283 } else
1246 this._element.classList.add("hidden"); 1284 this._element.classList.add("hidden");
1247 }, 1285 },
1248 1286
1249 _dispose: function() 1287 _dispose: function()
1250 { 1288 {
1251 this._element.remove(); 1289 this._element.remove();
1252 } 1290 }
1253 } 1291 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698